-
Notifications
You must be signed in to change notification settings - Fork 579
Add core symbolic gradient support to Pyomo.DoE #3928
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
Open
snarasi2
wants to merge
49
commits into
Pyomo:main
Choose a base branch
from
snarasi2:clean_symbolic
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
50cbc4a
Add symbolic gradient support to Pyomo.DoE
85116d5
Add symbolic DoE regression tests
12e5e95
Allow writeable in typos config
b35253a
Port polynomial and reactor symbolic tests
431b28e
Document symbolic gradient methods in DoE
f55a294
Refactor ExperimentGradients setup
ca66ac6
Add polynomial DoE regression coverage
8d8b8bd
Add broader gradient consistency tests
5c373fb
Add factorial results dataframe tests
103a121
Add reactor regression and CI fixes
76f53c4
Add plotting guard coverage tests
f28d86d
Clarify cyipopt HSL skip reason
80552f2
Reuse polynomial example in DoE tests
d708d55
Drop unused data arg from polynomial example
f53fe17
Clarify symbolic sensitivity math comments
11d475e
Remove no-op polynomial finalization
e704f68
Simplify polynomial test imports
0d0a14f
Remove redundant polynomial FIM smoke test
401c03a
Strengthen polynomial DoE regression test
0dd08eb
Use symbolic path for dataframe tests
65571da
Align symbolic DoE test coverage
9eb4959
Guard DoE utils tests on ipopt
702dc89
Strengthen symbolic Jacobian tests
d652cea
Remove out-of-scope FIM metric test
b5ea7f1
Tighten Jacobian regression assertions
9a78180
Drop workflow changes from symbolic PR
c593f0b
Checkpoint reactor test conversions to RB/polynomial
36d5694
Checkpoint remaining reactor test cleanup
dae72f4
Replace remaining reactor DoE tests
0545dcf
Clarify GreyBox MA57 skip reason
270bf8c
Add symbolic DoE PR notes
33d0b98
Refactor Jacobian rule setup
4209df5
Tighten FD scenario validation
653e3be
Format DoE module with black
2b8ba66
Merge branch 'Pyomo:main' into clean_symbolic
snarasi2 734fd58
Cleanup: remove trailing whitespace in DOE tests and utils
snarasi2 06dda52
Format DOE files with Black
snarasi2 67f23c8
Guard DOE test requiring pandas (optional dependency)
snarasi2 5ad99f0
Remove disabled Rooney-Biegler Cholesky test
snarasi2 ab2f729
Standardize GreyBox MA57 skip reason
snarasi2 f1c9a8f
Remove redundant NumPy skips in DoE utils tests
snarasi2 dcbfee6
Remove redundant SciPy skip in DoE utils tests
snarasi2 1096e52
Clarify k_aug gradient method scope
snarasi2 1e46960
Merge remote-tracking branch 'upstream/main' into clean_symbolic
snarasi2 cbb1582
Defer DoE optional dependency imports
snarasi2 53c80be
Apply black formatting to DoE imports
snarasi2 15c0677
Remove redundant GreyBox dependency skips
snarasi2 ba6d769
Remove redundant DoE dependency skips
snarasi2 512451e
Address symbolic DoE test review comments
snarasi2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| # Symbolic DoE PR Notes | ||
|
|
||
| This note is intended to help reviewers understand the scope of the symbolic | ||
| Pyomo.DoE pull request, the mathematical background for the main changes, and | ||
| how those ideas map onto the implementation. | ||
|
|
||
| ## Overview | ||
|
|
||
| This PR adds symbolic-gradient support to `pyomo.contrib.doe` on top of the | ||
| current DoE implementation while preserving the newer objective and GreyBox | ||
| structure already present on `main`. | ||
|
|
||
| At a high level, the PR: | ||
|
|
||
| - adds symbolic / `pynumero` gradient support alongside the existing | ||
| finite-difference workflow | ||
| - adds `ExperimentGradients` to organize the derivative information used by DoE | ||
| - keeps the newer DoE objective and GreyBox structure from current `main` | ||
| - adds a lightweight public `PolynomialExperiment` example for symbolic testing | ||
| - broadens test coverage for symbolic/automatic derivative consistency and DoE | ||
| regression behavior | ||
|
|
||
| The PR does **not** change the underlying Fisher information matrix mathematics. | ||
| The main change is how the derivative information needed for those calculations | ||
| can be assembled. | ||
|
|
||
| ## Mathematical Background | ||
|
|
||
| For a model with outputs `y` and unknown parameters `theta`, DoE needs the | ||
| output sensitivity matrix | ||
|
|
||
| ```math | ||
| Q = \frac{\partial y}{\partial \theta} | ||
| ``` | ||
|
|
||
| to build the Fisher information matrix | ||
|
|
||
| ```math | ||
| \mathrm{FIM} = Q^T \Sigma^{-1} Q | ||
| ``` | ||
|
|
||
| where `Sigma` is the measurement-error covariance matrix. | ||
|
|
||
| For models defined implicitly by equations | ||
|
|
||
| ```math | ||
| F(x, u, \theta) = 0 | ||
| ``` | ||
|
|
||
| the state sensitivities follow from differentiating the implicit system: | ||
|
|
||
| ```math | ||
| \frac{\partial F}{\partial x}\frac{\partial x}{\partial \theta} | ||
| + | ||
| \frac{\partial F}{\partial \theta} | ||
| = 0 | ||
| ``` | ||
|
|
||
| so | ||
|
|
||
| ```math | ||
| \frac{\partial x}{\partial \theta} | ||
| = | ||
| -\left(\frac{\partial F}{\partial x}\right)^{-1} | ||
| \frac{\partial F}{\partial \theta} | ||
| ``` | ||
|
|
||
| Those state sensitivities are then propagated to the experiment outputs to form | ||
| `Q`, and then to the FIM. | ||
|
|
||
| The symbolic path in this PR changes how those Jacobian terms are assembled; it | ||
| does not change the equations above. | ||
|
|
||
| ## Implementation Mapping | ||
|
|
||
| ### `gradient_method` | ||
|
|
||
| The symbolic behavior in this PR is selected through `gradient_method`. | ||
|
|
||
| - finite-difference setup still uses `fd_formula` | ||
| - symbolic / `pynumero` behavior is selected by `gradient_method` | ||
| - `fd_formula="central"` remains the shared setup convention in many tests even | ||
| when `gradient_method="pynumero"` is used | ||
|
|
||
| This means the symbolic path is not activated by changing the finite-difference | ||
| formula. Instead, the finite-difference configuration stays available while the | ||
| derivative backend is chosen independently. | ||
|
|
||
| ### `ExperimentGradients` | ||
|
|
||
| `ExperimentGradients` is responsible for organizing the derivative information | ||
| used to build sensitivity matrices for DoE. | ||
|
|
||
| The important implementation detail in this PR is that the symbolic and | ||
| automatic derivative structures are prepared through a unified setup path. This | ||
| lets tests compare symbolic and automatic Jacobian entries directly while still | ||
| using the same overall experiment structure. | ||
|
|
||
| In other words, the PR moves the code toward: | ||
|
|
||
| - one shared setup path for Jacobian bookkeeping | ||
| - backend-specific derivative population within that structure | ||
|
|
||
| rather than maintaining more separate symbolic and automatic setup logic. | ||
|
|
||
| ## Test Strategy | ||
|
|
||
| The test updates in this PR were aimed at checking both the mathematical path | ||
| and the practical DoE integration path. | ||
|
|
||
| ### Polynomial | ||
|
|
||
| The polynomial example is the lightweight symbolic reference problem. | ||
|
|
||
| It is used for: | ||
|
|
||
| - exact gradient checks against hand-derived values | ||
| - symbolic vs automatic Jacobian consistency checks | ||
| - public example coverage | ||
| - generic 2D factorial / plotting coverage where a small two-design-variable | ||
| example is helpful | ||
|
|
||
| Because the polynomial example has one output and four parameters, some FIM | ||
| regression tests use an identity prior to avoid rank-deficient raw FIMs when the | ||
| test purpose is metric regression rather than singular-matrix behavior. | ||
|
|
||
| ### Rooney-Biegler | ||
|
|
||
| Rooney-Biegler is used for most of the general-purpose solve and regression | ||
| coverage because it is lightweight and still exercises the full DoE flow. | ||
|
|
||
| It is used for: | ||
|
|
||
| - symbolic `run_doe()` regression tests | ||
| - symbolic objective-matrix consistency checks | ||
| - bad-model / error-path coverage | ||
| - perturbed-point Jacobian agreement checks in the non-reactor replacements | ||
| - GreyBox helper and solve-path coverage | ||
|
|
||
| Several Rooney-Biegler determinant tests use a prior FIM. This is not meant to | ||
| change the underlying mathematics; it is there to keep the determinant-based | ||
| solve path well-conditioned for the small Rooney-Biegler problem. | ||
|
|
||
| ### GreyBox | ||
|
|
||
| The non-solve GreyBox helper tests now use the Rooney-Biegler path as well. | ||
|
|
||
| Those tests were updated to match a two-parameter FIM instead of the older | ||
| reactor-specific four-parameter setup. In particular: | ||
|
|
||
| - the test FIM used for GreyBox helper checks is now `2 x 2` | ||
| - the reduced-Hessian finite-difference helper was generalized to use the | ||
| current FIM dimension instead of assuming four parameters | ||
| - the build checks compare against the actual FIM carried by the GreyBox object | ||
| rather than a hard-coded reactor-specific reconstruction | ||
|
|
||
| The solve-path checks still use the `cyipopt` GreyBox route and therefore remain | ||
| subject to the MA57/HSL runtime availability for that path. | ||
|
|
||
| ## Notes And Caveats | ||
|
|
||
| ### Reactor initialization nuance | ||
|
|
||
| One important nuance that came up during review is that the reactor model | ||
| required more care for generalized symbolic/automatic correctness checks. | ||
|
|
||
| In particular: | ||
|
|
||
| - the raw reactor labeled model is not always the cleanest reduced test vehicle | ||
| for output-sensitivity checks | ||
| - some reactor-oriented checks were therefore replaced with lighter | ||
| Rooney-Biegler or polynomial coverage where the test purpose was generic | ||
|
|
||
| ### MA57 / HSL on the GreyBox `cyipopt` path | ||
|
|
||
| The GreyBox `cyipopt` path is distinct from simply having a working standalone | ||
| IPOPT executable. In local debugging, the relevant failure mode was that | ||
| `cyipopt` could be present while the MA57/HSL runtime needed on that path was | ||
| not available. The test skip message and code comment call that out explicitly | ||
| so it is not confused with generic IPOPT availability. | ||
|
|
||
| ## Validation Snapshot | ||
|
|
||
| The final focused DoE test bundle used during this review pass was: | ||
|
|
||
| ```bash | ||
| python -m pytest -q \ | ||
| pyomo/contrib/doe/tests/test_utils.py \ | ||
| pyomo/contrib/doe/tests/test_doe_solve.py \ | ||
| pyomo/contrib/doe/tests/test_doe_build.py \ | ||
| pyomo/contrib/doe/tests/test_doe_errors.py \ | ||
| pyomo/contrib/doe/tests/test_greybox.py | ||
| ``` | ||
|
|
||
| with local result: | ||
|
|
||
| ```text | ||
| 130 passed, 4 skipped, 5 warnings in 35.67s | ||
| ``` | ||
|
|
||
| The remaining warnings are the expected non-interactive matplotlib `Agg` | ||
| warnings from tests that call `draw_factorial_figure()`. |
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
Oops, something went wrong.
Oops, something went wrong.
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.
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.
This file needs to be removed before this PR can be approved.