Skip to content

Add grey box objectives to Pyomo.DoE #3606

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
wants to merge 158 commits into
base: main
Choose a base branch
from
Open

Conversation

djlaky
Copy link
Contributor

@djlaky djlaky commented May 20, 2025

Summary/Motivation:

Pyomo.DoE currently can only compute trace-optimal and D-optimal experimental designs. We are expanding the suite to be able to compute E-optimal and ME-optimal (or condition number optimal) designs. Given that these formulations require computing eigenvalues on the fly, we have updated Pyomo.DoE to make use of the ExternalGreyBox modules.

This PR adds grey box capabilities to Pyomo.DoE.

Changes proposed in this PR:

  • Added grey box capabilities within Pyomo.DoE
  • Ability to compute E-optimal and ME-optimal designs using these grey box capabilities

Legal Acknowledgement

By contributing to this software project, I have read the contribution guide and agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the BSD license.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

djlaky and others added 30 commits December 4, 2024 07:37
Issue on windows, uploading file to test on mac
Windows-specific issue with the code; will report issue in due time.
Used all phrases for ExternalGreyBoxModel.

Need to make more robust the naming and bookkeeping for input names and subsequently the coo matrices.
Added a single version of grey box. Currently cannot solve due to the model not being a Pyomo Block. Will revisit next week.
Added greybox solver separate from regular solver (will call normal ipopt to solve subproblems without grey box model). Fixed bugs with grey box utilities to now update the input values correctly.

Having determinism issue.
Trying to explore hessian option to make these things converge better. Need to explore more tensor calculus.
Need to try some other numerical things to encourage convergence before attacking Hessian problem...
Added option for condition number optimality. Last step will be to potentially change to triangular definition of inputs in grey-box function, then add Hessian computation.
Should improve computational performance. Seemed to help E and ME but D still has issues. Next steps would be to add the Hessian calculation.
Trying to get D-optimality to work without hessian first.
Adding functions for testing grey box derivative accuracy using numerical counterparts. Functions are working properly, just need to implement the derivatives/hessians in the grey box file.
@blnicho blnicho moved this from Todo to Review In Progress in July 2025 Release Jun 23, 2025
@adowling2
Copy link
Member

@blnicho @mrmundt @michaelbynum @jsiirola I think this is ready for another review

Copy link
Contributor

@mrmundt mrmundt left a comment

Choose a reason for hiding this comment

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

This overall looks good! Just a few comments / minor changes


if self.objective_option == ObjectiveLib.trace:
Minv = np.linalg.pinv(M)
# Derivative formula of A-optimality
Copy link
Contributor

Choose a reason for hiding this comment

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

I really appreciate all of these inline comments - very helpful.

Copy link
Contributor

@mrmundt mrmundt left a comment

Choose a reason for hiding this comment

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

A few questions and a stray typo!

@@ -826,7 +928,9 @@ def initialize_jac(m, i, j):
# Otherwise initialize to 0.1 (which is an arbitrary non-zero value)
else:
raise AttributeError(
Copy link
Contributor

Choose a reason for hiding this comment

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

You may want to have this be a DeveloperError or MouseTrap error instead of an AttributeError.

@@ -1062,13 +1171,10 @@ def _generate_scenario_blocks(self, model=None):
model.scenarios = range(len(model.base_model.unknown_parameters) + 1)
else:
raise AttributeError(
Copy link
Contributor

Choose a reason for hiding this comment

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

You may want to have this be a DeveloperError or MouseTrap error instead of an AttributeError.

@@ -1183,12 +1291,14 @@ def create_objective_function(self, model=None):
ObjectiveLib.zero,
]:
raise AttributeError(
Copy link
Contributor

Choose a reason for hiding this comment

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

You may want to have this be a DeveloperError or MouseTrap error instead of an AttributeError.


# Test whether or not cyipopt
# is appropriately calling the
# lienar solvers.
Copy link
Contributor

Choose a reason for hiding this comment

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

Ooo, typo. Reported upstream to crate-ci/typos

Suggested change
# lienar solvers.
# linear solvers.

Comment on lines +345 to +347
# Change linear solvers to mumps
# doe_object.solver.options["linear_solver"] = "mumps"
# doe_object.grey_box_solver.config.options["linear_solver"] = "mumps"
Copy link
Contributor

Choose a reason for hiding this comment

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

Leftover?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Review In Progress
Status: Ready for final review
Development

Successfully merging this pull request may close these issues.

5 participants