feat(study): reject parameter dependency extension at load time, with actionable errors - #276
Open
aoustry wants to merge 7 commits into
Open
feat(study): reject parameter dependency extension at load time, with actionable errors#276aoustry wants to merge 7 commits into
aoustry wants to merge 7 commits into
Conversation
…he system A component parameter's time/scenario dependency must be less than or equal to the one its model declares, axis by axis: the component may narrow what the model declares (true -> false) but never extend it. Narrowing already worked correctly at solve time — parameter arrays keep the dimensions the model declares and narrower data is broadcast over the remaining axes — but nothing tested it, and extending was caught only later, inside build_problem(), by a "Data inconsistency ... Requirement not met" message that named neither the flags nor the file. Move the check into resolve_system(), so load_study() and the CLI fail immediately with an error naming the component, the parameter, and both declarations. Keep Study.check_consistency() as the safety net for studies built programmatically, and report the data's and the model's axes there too. Data-shape errors now name the offending component and parameter, report the shape read, and point at the flag to change. check_requirement() is now derived from a new structure() on each data container rather than reimplemented per subclass; the accept/reject behaviour is unchanged. Solver output is unchanged: an end-to-end test covers every allowed model/component combination and asserts the data is constant along each axis the component declared independent, and that narrowing leaves the problem's variables, constraints, and array dimensions untouched. Closes #258 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013uUKXBbXCvH9ZECvbx4nC6
Removed section on parameter time and scenario dependency from the user guide.
Updated CHANGELOG to reflect fixed issues and clearer error messages.
Clarified error handling for parameter time/scenario dependency validation and improved data-shape error messages.
Removed unnecessary lines from the inputs documentation.
…_structure() Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013uUKXBbXCvH9ZECvbx4nC6
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.
Process ID
Process: GP-02 (refs #258 — see Scope vs #258 below; this PR does not close it)
Description
A component parameter's time/scenario dependency must be ≤ the one its model declares, axis by axis: a component may narrow what the model declares (
true→false) but never extend it.Narrowing already worked, end to end — this PR adds the missing test coverage for it, it does not fix it. Extension already failed too; what was wrong is when and how. It surfaced only inside
build_problem()asData inconsistency for component: G, parameter: cost. Requirement not met., which named neither the flags, nor the model, nor the file — soload_study()succeeded and nothing failed until you tried to solve.resolve_system(), soload_study()and the CLI fail immediately with an error naming the component, the parameter, and both declarations.Study.check_consistency()stays as the safety net for programmatically built studies, now reporting the data's and the model's axes.T×1,1×S,T×S, inline float).check_requirement()is now derived from a newindexing_structure()per data container instead of being reimplemented four times; accept/reject behaviour is identical, and four deadisinstance(self, X)guards (tautologically true insideX.check_requirement) are gone.So the user-visible delta is error timing and wording only — no study that used to work stops working, and no study that used to fail starts working.
Scope vs #258
#258 reports three things. This PR addresses one and takes a position on a second; the third is untouched. It therefore refs the issue rather than closing it.
true→falsefrom the system file) should workRationale for rejecting extension:
_build_param_arrays_for_modelbuilds one array per model, shaped fromparam.structure(the model's declaration). A component varying along an axis its model does not declare has nowhere to live without per-component dims, which would ripple into the indexing-structure analysis used for constraint shapes. Making it a clear, early error is the cheap and coherent option.Impact Analysis
Affected modules:
study/only (resolve_components.py,data.py,study.py). No changes toexpression/,simulation/, oroptim_config/.Solver output values are not expected to change. Parameter arrays keep the dimensions the model declares, and narrower data is broadcast over the remaining axes exactly as before; the
check_requirementtruth table is unchanged for all four data containers.test_narrowing_does_not_change_the_problem_shapeasserts narrowing leaves array dimensions, variables, and constraints untouched, and the 8 parametrized end-to-end cases pin the objective values. Backward compatible; the only wording change to an existing message is scenario-series "exactly one row" instead of "exactly one line".One caveat worth a reviewer's eye: moving the check into
resolve_system()means a study whose system file extends a model declaration now fails at load, not at solve. That is the intent, but it is a behaviour change forgems_craft-only consumers that load without solving.gems_craft_hybridis unaffected (it parses and writes, it never callsresolve_system).AbstractDataStructuregains a new abstractindexing_structure(), so any out-of-tree subclass must implement it.Checklist
pytest) — 632 passed, 6 skipped, 2 xfailedmypy) — 68 source filesblack,isort)pyproject.tomlversion bumped if applicable — not bumped: this repo bumps in dedicatedrelease:commits, so the entry went under[Unreleased]indocs/CHANGELOG.mdAGENTS.mdreviewed for impact and updated if needed — reviewed, no change needed (the rule is user-facing and documented indocs/user-guide/inputs.md)