Skip to content

Commit fe49756

Browse files
committed
Separate graph building and validation
1 parent 4159ed1 commit fe49756

2 files changed

Lines changed: 31 additions & 23 deletions

File tree

src/graph.rs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ use std::fmt::Display;
1515
use strum::IntoEnumIterator;
1616

1717
/// A graph of commodity flows for a given region and year
18-
type CommoditiesGraph = Graph<GraphNode, GraphEdge, Directed>;
18+
pub type CommoditiesGraph = Graph<GraphNode, GraphEdge, Directed>;
1919

2020
#[derive(Eq, PartialEq, Clone, Hash)]
2121
/// A node in the commodity graph
22-
enum GraphNode {
22+
pub enum GraphNode {
2323
/// A node representing a commodity
2424
Commodity(CommodityID),
2525
/// A source node for processes that have no inputs
@@ -43,7 +43,7 @@ impl Display for GraphNode {
4343

4444
#[derive(Eq, PartialEq, Clone, Hash)]
4545
/// An edge in the commodity graph
46-
enum GraphEdge {
46+
pub enum GraphEdge {
4747
/// An edge representing a process
4848
Process(ProcessID),
4949
/// An edge representing a service demand
@@ -196,7 +196,7 @@ fn prepare_commodities_graph_for_validation(
196196
/// The validation is only performed for commodities with the specified time slice level. For full
197197
/// validation of all commodities in the model, we therefore need to run this function for all time
198198
/// slice selections at all time slice levels. This is handled by
199-
/// `build_and_validate_commodity_graphs_for_model`.
199+
/// `validate_commodity_graphs_for_model`.
200200
fn validate_commodities_graph(
201201
graph: &CommoditiesGraph,
202202
commodities: &CommodityMap,
@@ -307,7 +307,26 @@ fn topo_sort_commodities(
307307
Ok(order)
308308
}
309309

310-
/// Builds and validates commodity graphs for the entire model.
310+
/// Builds base commodity graphs for each region and year
311+
///
312+
/// These do not take into account demand and process availability
313+
pub fn build_commodity_graphs_for_model(
314+
processes: &ProcessMap,
315+
region_ids: &IndexSet<RegionID>,
316+
years: &[u32],
317+
) -> Result<HashMap<(RegionID, u32), CommoditiesGraph>> {
318+
let commodity_graphs: HashMap<(RegionID, u32), CommoditiesGraph> =
319+
iproduct!(region_ids, years.iter())
320+
.map(|(region_id, year)| {
321+
let graph = create_commodities_graph_for_region_year(processes, region_id, *year);
322+
((region_id.clone(), *year), graph)
323+
})
324+
.collect();
325+
326+
Ok(commodity_graphs)
327+
}
328+
329+
/// Validates commodity graphs for the entire model.
311330
///
312331
/// This function creates commodity flow graphs for each region/year combination in the model,
313332
/// validates the graph structure against commodity type rules, and determines the optimal
@@ -337,23 +356,12 @@ fn topo_sort_commodities(
337356
/// - Any commodity graph contains cycles
338357
/// - Commodity type rules are violated (e.g., SVD commodities being consumed)
339358
/// - Demand cannot be satisfied
340-
pub fn build_and_validate_commodity_graphs_for_model(
359+
pub fn validate_commodity_graphs_for_model(
360+
commodity_graphs: &HashMap<(RegionID, u32), CommoditiesGraph>,
341361
processes: &ProcessMap,
342362
commodities: &CommodityMap,
343-
region_ids: &IndexSet<RegionID>,
344-
years: &[u32],
345363
time_slice_info: &TimeSliceInfo,
346364
) -> Result<HashMap<(RegionID, u32), Vec<CommodityID>>> {
347-
// Build base commodity graphs for each region and year
348-
// These do not take into account demand and process availability
349-
let commodity_graphs: HashMap<(RegionID, u32), CommoditiesGraph> =
350-
iproduct!(region_ids, years.iter())
351-
.map(|(region_id, year)| {
352-
let graph = create_commodities_graph_for_region_year(processes, region_id, *year);
353-
((region_id.clone(), *year), graph)
354-
})
355-
.collect();
356-
357365
// Determine commodity ordering for each region and year
358366
let commodity_order: HashMap<(RegionID, u32), Vec<CommodityID>> = commodity_graphs
359367
.iter()
@@ -366,7 +374,7 @@ pub fn build_and_validate_commodity_graphs_for_model(
366374
.try_collect()?;
367375

368376
// Validate graphs at all time slice levels (taking into account process availability and demand)
369-
for ((region_id, year), base_graph) in &commodity_graphs {
377+
for ((region_id, year), base_graph) in commodity_graphs {
370378
for ts_level in TimeSliceLevel::iter() {
371379
for ts_selection in time_slice_info.iter_selections_at_level(ts_level) {
372380
let graph = prepare_commodities_graph_for_validation(

src/input.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Common routines for handling input data.
22
use crate::asset::AssetPool;
3-
use crate::graph::build_and_validate_commodity_graphs_for_model;
3+
use crate::graph::{build_commodity_graphs_for_model, validate_commodity_graphs_for_model};
44
use crate::id::{HasID, IDLike};
55
use crate::model::{Model, ModelParameters};
66
use crate::units::UnitType;
@@ -213,11 +213,11 @@ pub fn load_model<P: AsRef<Path>>(model_dir: P) -> Result<(Model, AssetPool)> {
213213

214214
// Build and validate commodity graphs for all regions and years
215215
// This gives us the commodity order for each region/year which is passed to the model
216-
let commodity_order = build_and_validate_commodity_graphs_for_model(
216+
let commodity_graphs = build_commodity_graphs_for_model(&processes, &region_ids, years)?;
217+
let commodity_order = validate_commodity_graphs_for_model(
218+
&commodity_graphs,
217219
&processes,
218220
&commodities,
219-
&region_ids,
220-
years,
221221
&time_slice_info,
222222
)?;
223223

0 commit comments

Comments
 (0)