Add subannual generic relation constraints#1020
Open
Wegatriespython wants to merge 2 commits into
Open
Conversation
Extend the generic relation mechanism to subannual time-slice resolution. The annual relation sums activity over all time slices, so on a time-sliced scenario it can only bound the annual total; the new variant bounds each slice independently. - New parameters relation_upper_time, relation_lower_time and relation_activity_time, and flag sets is_relation_upper_time and is_relation_lower_time, mirroring the annual trio with a trailing time index. - New GAMS equations RELATION_EQUIVALENCE_TIME, RELATION_CONSTRAINT_UP_TIME and RELATION_CONSTRAINT_LO_TIME, plus auxiliary variable REL_TIME(r, n, y, h). REL_TIME carries only the activity term; capacity factors stay annual because CAP has no subannual dimension. - Register the new parameters, flag sets and variable in MESSAGE.items so they initialize automatically; Scenarios from earlier versions get them added empty. - MESSAGE.enforce composes the is_*_time flag sets from parent-parameter keys, so a zero-valued bound is preserved as a valid constraint.
The subannual relation items (relation_upper_time, relation_lower_time, relation_activity_time, is_relation_*_time, REL_TIME) are registered in MESSAGE.items and initialized on every scenario, so Reporter.from_scenario auto-derives keys for them. Add the resulting 306 keys to the test_from_scenario golden set.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1020 +/- ##
=======================================
- Coverage 92.3% 92.0% -0.3%
=======================================
Files 60 61 +1
Lines 5260 5392 +132
=======================================
+ Hits 4856 4966 +110
- Misses 404 426 +22
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR addresses part of #191 (the
RELATION_EQUIVALENCEitem) and slots under the umbrella #979 by adding subannual generic relation constraints to MESSAGE, so a generic relation can express a per-time-slice bound on a subannual scenario instead of only an annual one.Today the GAMS core consumes annual
relation_activity/relation_upper/relation_loweronly. On a timesliced (h1..h4) scenario there is no way to carry a signal that varies by slice through the generic-relation mechanism — it stays annual even where the demand and activity are subannual. This blocks any workflow that needs a season- or slice-specific relation cap.Rather than add a time dimension to the existing parameters (which would break stored scenarios and is the backwards-compatibility blocker noted on #191), this adds parallel
_timevariants. New parametersrelation_upper_time,relation_lower_time,relation_activity_time, flag setsis_relation_upper_time/is_relation_lower_time, and an auxiliary variableREL_TIME(r, n, y, h), plus three equationsRELATION_EQUIVALENCE_TIME,RELATION_CONSTRAINT_UP_TIME,RELATION_CONSTRAINT_LO_TIMEinmodel_core.gms. Annual scenarios are unaffected; a relation may use the annual parameters, the_timeparameters, or both.The
is_*_timeflag sets are composed in the Python layer (MESSAGE.enforce) from the parent parameter keys — dropping the value and unit columns — rather than derived from parameter values in GAMS. This is key-based, so a zero-valued bound (relation_upper_time = 0, a validREL_TIME <= 0constraint) survives instead of being silently dropped, and it mirrors the existingcapacity_factorhandling. MatchingHelperTableInfoentries are added inscenario_data.pyfor the ixmp4 backend.Out of scope, and following the annual
RELATION_*siblings: the_timeconstraints carry no%SLACK_RELATION_BOUND_*%hooks, there is norelation_cost_timeterm in the objective, andRELATION_EQUIVALENCE_TIMEis unconditioned over the full time set (which multiplies its equation count by|time|on large scenarios).How to review
Read the diff in the four GAMS files (
parameter_def.gms,sets_maps_def.gms,data_load.gms,model_core.gms) and the Python registration/composition inmessage.pyandscenario_data.py.The behaviour is exercised by
message_ix/tests/test_feature_relation_time.py: a baseline subannual solve, upper- and lower-bound binding viaRELATION_CONSTRAINT_UP_TIME/RELATION_CONSTRAINT_LO_TIME, flag composition without an explicitis_*_timeset, a zero-bound binding case, an annual-vs-_timeequivalence check (annualrelation_upper = Cagainstrelation_upper_time = C/2on two equal slices gives equal OBJ and total activity), and a coexistence case where an annual cap and a tighter per-slice cap both bind on the same relation.PR checklist