Skip to content

Conversation

@kanekosh
Copy link
Contributor

@kanekosh kanekosh commented Oct 2, 2025

Purpose

  • Modified IPOPT wrapper to get information like optimality, feasibility, barrier parameters, etc. at each iteration using cyipopt's intermediate callback
  • Introduced a major iteration flag to IPOPT (previously it was always set to True even for line search iterations). Note that I think the "major iteration" is the SNOPT terminology so not sure if it is appropriate to use the same for IPOPT. In the current IPOPT wrapper, I set major=True for the top-level iterations that compute new search iterations, and the line search iterations are not flagged as major.
  • Added an example to plot SNOPT and IPOPT's optimality and feasibility history on the hs015 problem.

Expected time until merged

No rush

Type of change

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (non-backwards-compatible fix or feature)
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no API changes)
  • Documentation update
  • Maintenance update
  • Other (please describe)

Testing

Checklist

  • I have run ruff check and ruff format to make sure the Python code adheres to PEP-8 and is consistently formatted
  • I have formatted the Fortran code with fprettify or C/C++ code with clang-format as applicable
  • I have run unit and regression tests which pass locally with my changes
  • I have added new tests that prove my fix is effective or that my feature works
  • I have added necessary documentation

@kanekosh kanekosh requested a review from a team as a code owner October 2, 2025 20:40
@kanekosh kanekosh requested review from ArshSaja and sanjan98 October 2, 2025 20:40
@codecov
Copy link

codecov bot commented Oct 2, 2025

Codecov Report

❌ Patch coverage is 90.90909% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.70%. Comparing base (19ad2c8) to head (c8e03d2).

Files with missing lines Patch % Lines
pyoptsparse/pyIPOPT/pyIPOPT.py 88.88% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #459      +/-   ##
==========================================
- Coverage   86.72%   86.70%   -0.02%     
==========================================
  Files          24       24              
  Lines        3435     3460      +25     
==========================================
+ Hits         2979     3000      +21     
- Misses        456      460       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@marcomangano
Copy link
Collaborator

@kanekosh looks like the tests are failing on stable because the Ipopt version we pin does not support one of the wrapper calls:

RuntimeError: get_current_violations only supports Ipopt version >=3.14.0 CyIpopt is compiled with version 3.13.4

I will take a look at the PR in the next few days, but this sounds like a welcome improvement!

@kanekosh
Copy link
Contributor Author

kanekosh commented Oct 3, 2025

@kanekosh looks like the tests are failing on stable because the Ipopt version we pin does not support one of the wrapper calls:

RuntimeError: get_current_violations only supports Ipopt version >=3.14.0 CyIpopt is compiled with version 3.13.4

I will take a look at the PR in the next few days, but this sounds like a welcome improvement!

Thanks, I added a check on the IPOPT version so this is fixed now.

optOptions = self.optOptions.pop(self.optName, None)
store_vars = ["alg_mod", "d_norm", "regularization_size", "ls_trials"]
# check IPOPT version and add more variables to save_major_iteration_variables if IPOPT>=3.14
ipopt_314 = False
Copy link
Collaborator

Choose a reason for hiding this comment

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

IMO we do not need to support IPOPT<3.14 in tests, because 3.14.0 came out in 2021. We can just make sure we're installing sufficiently new versions of IPOPT in tests (I guess in Docker which we already do, and maybe we can pin in conda-forge)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree, but our stable Docker image still uses IPOPT 3.13.4, so we'll need to update that on the Docker side for the tests here to pass. I'll bring this up in the Docker repo.

from parameterized import parameterized

try:
# External modules
Copy link
Collaborator

Choose a reason for hiding this comment

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

Similarly we can get rid of this import

@ewu63
Copy link
Collaborator

ewu63 commented Oct 11, 2025

Also feel free to bump the patch version

Copy link
Collaborator

@marcomangano marcomangano left a comment

Choose a reason for hiding this comment

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

I think it's fair to drop support for IPOPT 3.13 at this point, although that might count as a downstream breaking change?

if self.name == "SNOPT":
hist["isMajor"] = False # this will be updated in _snstop if it is major
# Save information about major iteration counting (only matters for SNOPT and IPOPT).
if self.name in ["SNOPT", "IPOPT"]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just a curiosity for the moment.. do you think intermediate could be used in the same way _snstop is used? #420 is stalled now but I wonder if we could extend similar features to IPOPT.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I think so

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yep, eventually we can reorganize and refactor that part of the logic, it's a fairly common feature for optimizers to provide a per-iteration callback functionality.

@kanekosh
Copy link
Contributor Author

I opened a PR to update the IPOPT version in our stable docker image (https://github.com/mdolab/docker/pull/298), so once that's merged I'll remove the IPOPT 3.13 support from this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants