-
Notifications
You must be signed in to change notification settings - Fork 1
Use integer variables in appraisal for divisible assets #1075
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
192d999
ce77870
9ff532c
1d3ba5d
f820ab9
6998cef
acb993c
43d3b50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ use crate::asset::{AssetRef, AssetState}; | |
| use crate::commodity::Commodity; | ||
| use crate::time_slice::{TimeSliceID, TimeSliceInfo}; | ||
| use crate::units::{Capacity, Flow}; | ||
| use float_cmp::approx_eq; | ||
| use highs::RowProblem as Problem; | ||
| use indexmap::IndexMap; | ||
|
|
||
|
|
@@ -19,15 +20,26 @@ pub fn add_capacity_constraint( | |
| max_capacity: Option<Capacity>, | ||
| capacity_var: Variable, | ||
| ) { | ||
| let capacity = max_capacity.unwrap_or(asset.capacity()); | ||
| let mut capacity_limit = max_capacity.unwrap_or(asset.capacity()).value(); | ||
|
|
||
| // If asset is divisible, capacity_var represents number of units, so we must divide the | ||
| // capacity bounds by the unit size. | ||
| if let Some(unit_size) = asset.unit_size() { | ||
| capacity_limit /= unit_size.value(); | ||
|
|
||
| // Sanity check: capacity_limit should be a whole number of units (i.e pre-adjusted | ||
| // capacity limit was a multiple of unit size) | ||
| assert!(approx_eq!(f64, capacity_limit, capacity_limit.round())); | ||
|
Comment on lines
+30
to
+32
|
||
| } | ||
|
|
||
| let bounds = match asset.state() { | ||
| AssetState::Commissioned { .. } => { | ||
| // Fixed capacity for commissioned assets | ||
| capacity.value()..=capacity.value() | ||
| capacity_limit..=capacity_limit | ||
| } | ||
| AssetState::Candidate => { | ||
| // Variable capacity between 0 and max for candidate assets | ||
| 0.0..=capacity.value() | ||
| 0.0..=capacity_limit | ||
| } | ||
| _ => panic!( | ||
| "add_capacity_constraint should only be called with Commissioned or Candidate assets" | ||
|
|
@@ -100,8 +112,15 @@ fn add_activity_constraints_for_candidate( | |
| time_slice_info: &TimeSliceInfo, | ||
| ) { | ||
| for (ts_selection, limits) in asset.iter_activity_per_capacity_limits() { | ||
| let upper_limit = limits.end().value(); | ||
| let lower_limit = limits.start().value(); | ||
| let mut upper_limit = limits.end().value(); | ||
| let mut lower_limit = limits.start().value(); | ||
|
|
||
| // If the asset is divisible, the capacity variable represents number of units, | ||
| // so we need to multiply the per-capacity limits by the unit size. | ||
| if let Some(unit_size) = asset.unit_size() { | ||
| upper_limit *= unit_size.value(); | ||
| lower_limit *= unit_size.value(); | ||
| } | ||
|
|
||
| // Collect capacity and activity terms | ||
| // We have a single capacity term, and activity terms for all time slices in the selection | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,15 @@ | ||
| asset_id,process_id,region_id,agent_id,group_id,commission_year,decommission_year,capacity | ||
| 0,GASDRV,GBR,A0_GEX,,2020,,4002.26 | ||
| 1,GASPRC,GBR,A0_GPR,,2020,,3782.13 | ||
| 2,WNDFRM,GBR,A0_ELC,,2020,2040,3.964844 | ||
| 3,GASCGT,GBR,A0_ELC,,2020,2040,2.43 | ||
| 2,WNDFRM,GBR,A0_ELC,,2020,,3.964844 | ||
| 3,GASCGT,GBR,A0_ELC,,2020,,2.43 | ||
| 4,RGASBR,GBR,A0_RES,,2020,2035,1000.0 | ||
| 5,RGASBR,GBR,A0_RES,,2020,2035,1000.0 | ||
| 6,RGASBR,GBR,A0_RES,,2020,2035,1000.0 | ||
| 7,RELCHP,GBR,A0_RES,,2020,2035,399.98 | ||
| 8,RGASBR,GBR,A0_RES,1,2030,,1000.0 | ||
| 9,GASCGT,GBR,A0_ELC,,2030,2040,0.44245235762867363 | ||
| 10,RGASBR,GBR,A0_RES,2,2040,,1000.0 | ||
| 11,RGASBR,GBR,A0_RES,2,2040,,1000.0 | ||
| 12,RGASBR,GBR,A0_RES,2,2040,,1000.0 | ||
| 13,RGASBR,GBR,A0_RES,2,2040,,1000.0 | ||
| 8,RELCHP,GBR,A0_RES,,2030,,255.83840587648046 | ||
| 9,GASCGT,GBR,A0_ELC,,2030,2040,3.1192651014219064 | ||
| 10,RGASBR,GBR,A0_RES,1,2040,,1000.0 | ||
| 11,RGASBR,GBR,A0_RES,1,2040,,1000.0 | ||
| 12,RGASBR,GBR,A0_RES,1,2040,,1000.0 | ||
| 13,RGASBR,GBR,A0_RES,1,2040,,1000.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cast to u32 in capacity_to_units could overflow if the number of units exceeds u32::MAX (approximately 4.3 billion). Consider using u64 instead of u32 for the return type to handle larger capacities safely, or add validation to ensure the result fits within u32 bounds before casting.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is really unlikely unless someone does something stupid (not impossible though...)