Skip to content

pyomo.doe adding more verbose output for sensitivity analysis #3525

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 30 commits into
base: main
Choose a base branch
from

Conversation

smondal13
Copy link

@smondal13 smondal13 commented Mar 19, 2025

Fixes # .

Summary/Motivation:

  • Adding more verbose is helpful to analyze the problem
  • Adding a new method to check the FIM can help in the general usage of the method.
  • Adding a new standalone function to calculate different metrics of the FIM is helpful in case the user does not want to build the get_labeled_model().

Changes proposed in this PR:

  • added eigenvalues, determinant of FIM, and trace of FIM for sensitivity output in compute_FIM_full_factorial()
  • added_check_FIM() by separating it from check_model_FIM()
  • added _compute_FIM_metrics()
  • added get_FIM_metrics()

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.

@smondal13 smondal13 marked this pull request as draft March 19, 2025 14:13
@smondal13
Copy link
Author

@adowling2 @djlaky ready for early feedback

@adowling2
Copy link
Member

Next step:

  • Also add solver status

Comment on lines 1534 to 1536
if abs(E_vals.imag[E_ind]) > 1e-8:
self.logger.warning(
"Eigenvalue has imaginary component greater than 1e-6, contact developers if this issue persists."
"Eigenvalue has imaginary component greater than 1e-8, contact developers if this issue persists."
Copy link
Member

Choose a reason for hiding this comment

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

nit: this is why "embedded constants are evil". An improved solution would be to declare a module-level constant (maybe IMAG_THRESHOLD) and then use that both in the test and in the message.

@adowling2
Copy link
Member

@smondal13 See #3532 for an example of what @jsiirola is suggesting

… doe object that uses the "reactor_experiment" example in doe directory. Also added the png files to gitignore that are stored when "reactor_example.py" is run.
@smondal13 smondal13 force-pushed the adding_eigen_values branch from 6e68c2b to e9e83b6 Compare April 30, 2025 01:17
@adowling2 adowling2 moved this from Todo to Development in ParmEst & Pyomo.DoE Development Apr 30, 2025
@smondal13
Copy link
Author

@adowling2 Ready for review.

Copy link
Member

@adowling2 adowling2 left a comment

Choose a reason for hiding this comment

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

@smondal13 This looks really close. I left a few minor comments.

@blnicho @jsiirola @mrmundt This is ready for a design review from the Pyomo team. I am moving it on the project board.

"FIM provided matches expected dimensions from model and is approximately positive (semi) definite."
)

# TODO: Make this a static method
Copy link
Member

Choose a reason for hiding this comment

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

You can remove this TODO.

_compute_FIM_metrics(FIM)
)
"""
Since we are using the `_compute_FIM_metrics()` to compute the metrics in this chunk of code., This chunk of code is ready to be deleted.
Copy link
Member

Choose a reason for hiding this comment

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

Please delete if you feel it is no longer needed. It is in the Git history in case we need to find it.

E_vals, E_vecs = np.linalg.eig(FIM)
E_ind = np.argmin(E_vals.real) # index of smallest eigenvalue

# Warn the user if there is a ``large`` imaginary component (should not be)
Copy link
Member

Choose a reason for hiding this comment

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

Will you ever get to this warning? Or will _check_FIM throw an error first?

Copy link
Author

@smondal13 smondal13 May 2, 2025

Choose a reason for hiding this comment

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

@adowling2 _check_FIM() will not trigger this warning. _check_FIM() only checks whether the FIM is square, symmetric, and positive definite. Although this method checks for the symmetry of the FIM with a tolerance, and it is unlikely that the FIM will have large imaginary eigenvalues, we have kept the warning there just in case there is a large imaginary eigenvalue.

Copy link
Member

Choose a reason for hiding this comment

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

@smondal13 Thank you.

@blnicho @mrmundt Is there a best practice for testing this warning message is properly thrown?

@adowling2
Copy link
Member

Also, @smondal13, please remove the draft status.

@adowling2 adowling2 moved this from Development to Ready for design review in ParmEst & Pyomo.DoE Development May 1, 2025
smondal13 added 2 commits May 2, 2025 07:56
…_FIM_full_factorial()` which was replaced by function call `_compute_FIM_metrics()`
…ght that will be helpful for the user to understand the method.
@smondal13 smondal13 marked this pull request as ready for review May 2, 2025 13:06
@smondal13
Copy link
Author

@adowling2 I have implemented your suggestions. I have also added Returns in the compute_FIM_full_factorial() docstring. I thought it would be helpful for the user to know what the method is returning.

@blnicho blnicho self-requested a review May 6, 2025 19:30
Copy link
Member

@adowling2 adowling2 left a comment

Choose a reason for hiding this comment

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

Pending input from the Pyomo team, I think this PR is ready to merge.

E_vals, E_vecs = np.linalg.eig(FIM)
E_ind = np.argmin(E_vals.real) # index of smallest eigenvalue

# Warn the user if there is a ``large`` imaginary component (should not be)
Copy link
Member

Choose a reason for hiding this comment

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

@smondal13 Thank you.

@blnicho @mrmundt Is there a best practice for testing this warning message is properly thrown?



class TestFIMWarning(unittest.TestCase):
def test_FIM_eigenvalue_warning(self):
Copy link
Member

Choose a reason for hiding this comment

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

@blnicho @mrmundt I have not tested warning messages before, so your input here is appreciated.

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

Successfully merging this pull request may close these issues.

4 participants