Skip to content

Add commodity constraints input and validation - #1487

Draft
dc2917 wants to merge 2 commits into
mainfrom
add-commodity-constraints-input-and-validation
Draft

Add commodity constraints input and validation#1487
dc2917 wants to merge 2 commits into
mainfrom
add-commodity-constraints-input-and-validation

Conversation

@dc2917

@dc2917 dc2917 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds a new module for reading and validating an input csv file for commodity constraints.

Commodity constraints are stored in a new CommodityConstraint struct, and the set of constraints provided are read and stored in a CommodityConstraintsMap type, which maps CommodityConstraints by region ID and year.

CommodityConstraints have a single field, limits, which stores the range of values to which the commodity is constrained.

An example commodity_constraints.csv file has been added to the "simple" setup for demonstration, and a corresponding schema has been added.

Fixes #1448

Type of change

  • Bug fix (non-breaking change to fix an issue)
  • New feature (non-breaking change to add functionality)
  • Refactoring (non-breaking, non-functional change to improve maintainability)
  • Optimization (non-breaking change to speed up the code)
  • Breaking change (whatever its nature)
  • Documentation (improve or add documentation)

Key checklist

  • All tests pass: $ cargo test
  • The documentation builds and looks OK: $ cargo doc
  • Update release notes for the latest release if this PR adds a new feature or fixes a bug
    present in the previous release

Further checks

  • Code is commented, particularly in hard-to-understand areas
  • Tests added that prove fix is effective or that feature works

@dc2917

dc2917 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

@tsmbland I've taken a stab at this but some feedback would be helpful before I add tests

@tsmbland tsmbland left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good start, but a few comments

// Extract fields from record
let commodity_id = commodity_ids.get_id(&record.commodity_id)?;
// Validation ensures single region_id, so take that at index 0
let region_id = parse_region_str(&record.region_id, region_ids)?[0].clone();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let region_id = parse_region_str(&record.region_id, region_ids)?[0].clone();
let region_id = region_ids.get_id(&record.region_id)?

Comment on lines +38 to +41
ensure!(
self.region_id != "all" && !self.region_id.contains(";"),
"Only single regions are permitted"
);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be validated by get_id (see comment below)

let region_id = parse_region_str(&record.region_id, region_ids)?[0].clone();
let years = parse_year_str(&record.years, milestone_years)?;
let ts_selection = time_slice_info.get_selection(&record.time_slice)?;
let limits = parse_range(&record.limits, Money(0.0)..=Money(f64::INFINITY))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let limits = parse_range(&record.limits, Money(0.0)..=Money(f64::INFINITY))
let limits = parse_range(&record.limits, Flow(0.0)..=Flow(f64::INFINITY))

Limits are on amount of commodity consumed/produced (i.e. Flow), rather than a monetary amount

Comment thread src/commodity.rs
#[derive(PartialEq, Debug, Clone)]
pub struct CommodityConstraint {
/// The range of values the commodity is constrained to lie between
pub limits: RangeInclusive<Money>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs to store the TimeSliceSelection that the constraint applies to, and the BalanceType

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I wasn't sure what to do with those.

Comment thread src/commodity.rs
pub type CommodityLevyMap = HashMap<(RegionID, u32, TimeSliceID), MoneyPerFlow>;

/// A map of [`CommodityConstraint`]s, keyed by region ID and year
pub type CommodityConstraintsMap = HashMap<(RegionID, u32), Rc<CommodityConstraint>>;

@tsmbland tsmbland Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can have multiple constraints for each (region, year), so this should be

HashMap<(RegionID, u32), Vec<CommodityConstraint>>

Not sure you necessarily need the Rc, but may be wrong (probably). If required, it should probably be Arc to keep things parallel-compatible

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah OK yeah, I understand what you were referring to in your comment on the issue now.

///
/// A `HashMap<CommodityID, CommodityConstraintsMap>` mapping commodity IDs to their
/// commodity-constraints maps, or an error.
pub fn read_commodity_constraints(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also want to disallow SVD commodities from having commodity constraints, so you'll need to pass in the map of the commodities rather than just the IDs (i.e. &IndexMap<CommodityID, Commodity>)

Another slightly tricky thing is that, since OTH commodities can either be consumed or produced (but not both), we don't want users to supply production constraints for OTH commodities that are consumed, and vice-versa. Probably worth opening an issue about this rather than attempting this here, as we may have to do this in the graph validation stage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add file reading and validation code for commodity constraints

2 participants