Skip to content

Feature/add funnel globalization mechanism to trf#3832

Open
gulhameed361 wants to merge 12 commits intoPyomo:mainfrom
gulhameed361:feature/add-funnel-globalization-mechanism-to-trf
Open

Feature/add funnel globalization mechanism to trf#3832
gulhameed361 wants to merge 12 commits intoPyomo:mainfrom
gulhameed361:feature/add-funnel-globalization-mechanism-to-trf

Conversation

@gulhameed361
Copy link

Fixes # .

Summary/Motivation:

This PR introduces the Funnel globalization strategy to the Trust Region Framework (TRF) solver in Pyomo. The Funnel method is an alternative to the existing Filter globalization mechanism.
The solver functionality remains unchanged by default and will continue to work as it has in previous versions unless the user explicitly selects the Funnel strategy in solver's options (globalization_strategy=1). This ensures backward compatibility.
The Funnel strategy is based on the methodology introduced in the paper "A Trust-region Funnel Algorithm for Grey-Box Optimisation" (https://arxiv.org/abs/2511.18998), which is accepted in AIChE Journal and will be live in the upcoming days.

Changes proposed in this PR:

  1. Added funnel.py to implement the Funnel globalization strategy.
  2. Updated TRF.py to integrate the Funnel strategy into the Trust Region Framework solver.
  3. Added unit tests:
    • test_funnel.py: Tests for the Funnel class.
    • test_TRF_w_Funnel.py: Tests for the integration of Funnel with TRF.
    • 'test_TRFw_Filter.py': Tests for the integration of Filter with TRF (it works even after adding funnel method as it used to in current/previous versions)
  4. Ensured backward compatibility:
    • The solver defaults to the existing Filter globalization strategy unless the Funnel strategy is explicitly selected by the user by using "globalization_strategy=1" in options of the solver.

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.

@gulhameed361
Copy link
Author

Thank you for reviewing this PR! Please let me know if there are any changes or clarifications needed. I have tested the feature locally, and all tests passed successfully.

@mrmundt mrmundt self-requested a review February 3, 2026 18:12
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.

Some initial requests for changes that will be stoppers on this PR.

@mrmundt
Copy link
Contributor

mrmundt commented Feb 3, 2026

Also, please install the most recent version of black and run it on your changes. I can already tell that at least one file is going to cause our CI check for formatting to fail.

Copy link
Author

@gulhameed361 gulhameed361 left a comment

Choose a reason for hiding this comment

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

Many thanks for the quick feedback. I have addressed the requested changes:

  • Added copyright headers to funnel.py and test_funnel.py.
  • Consolidated Funnel and Filter tests into test_TRF.py and removed duplicate test files (test_TRF_w_Funnel.py and test_TRF_w_Filter.py).
  • Formatted the updated files using black.
  • Verified functionality with pytest, and all tests passed successfully.
    Please let me know if further changes are required. Thank you!

Copy link
Author

@gulhameed361 gulhameed361 left a comment

Choose a reason for hiding this comment

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

All the requested changes have been addressed. Made a few additional changes as well to the code to make it concise/efficient.

@gulhameed361 gulhameed361 requested a review from mrmundt February 4, 2026 16:28
@codecov
Copy link

codecov bot commented Feb 9, 2026

Codecov Report

❌ Patch coverage is 97.72727% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.68%. Comparing base (200746e) to head (52b7fbe).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
pyomo/contrib/trustregion/TRF.py 98.14% 1 Missing ⚠️
pyomo/contrib/trustregion/funnel.py 97.05% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3832   +/-   ##
=======================================
  Coverage   89.68%   89.68%           
=======================================
  Files         908      909    +1     
  Lines      106753   106822   +69     
=======================================
+ Hits        95740    95807   +67     
- Misses      11013    11015    +2     
Flag Coverage Δ
builders 29.08% <21.59%> (+<0.01%) ⬆️
default 85.97% <97.72%> (?)
expensive 35.50% <21.59%> (?)
linux 87.15% <97.72%> (-2.03%) ⬇️
linux_other 87.15% <97.72%> (+<0.01%) ⬆️
oldsolvers 28.00% <21.59%> (+<0.01%) ⬆️
osx 82.48% <97.72%> (+<0.01%) ⬆️
win 85.57% <97.72%> (+<0.01%) ⬆️
win_other 85.57% <97.72%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

@gulhameed361
Copy link
Author

gulhameed361 commented Feb 11, 2026

I have added a test for lines which were not tested as per the codecov report, and updated both the main and feature branches.

@gulhameed361
Copy link
Author

I haven't updated the branch, because it may require the PR to go through all checks again! I can do it whenever required.

@gulhameed361 gulhameed361 force-pushed the feature/add-funnel-globalization-mechanism-to-trf branch from e70f720 to 56ae690 Compare March 17, 2026 17:29
@gulhameed361
Copy link
Author

Rebased onto the latest main, this should fix the CI failures.

@blnicho blnicho self-requested a review March 17, 2026 19:23
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.

Thanks for doing the updates! Sorry, we messed with you a bit here on the copyright. We updated them everywhere while this PR was open.

Additionally, there is existing online documentation for TRF: https://pyomo.readthedocs.io/en/stable/explanation/solvers/trustregion.html

It would be good for you to go edit those files with updates about your changes: https://github.com/Pyomo/pyomo/blob/main/doc/OnlineDocs/explanation/solvers/trustregion.rst

@gulhameed361 gulhameed361 force-pushed the feature/add-funnel-globalization-mechanism-to-trf branch from 5b5bdae to 109f802 Compare March 17, 2026 22:05
…added tests for both funnel and filter methods
…py, made small theoretical changes to TRF.py as per the funnel mechanism published in AIChE, added a comment in example2.py showing how funnel mechanism can imprive solver's performance.
…y as per reviewers' suggestion, updated test_TRF.py as per the changes made in TRF.py
@gulhameed361 gulhameed361 force-pushed the feature/add-funnel-globalization-mechanism-to-trf branch from 109f802 to a314a55 Compare March 17, 2026 22:08
@gulhameed361 gulhameed361 requested a review from mrmundt March 17, 2026 22:39
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.

Sorry sorry, little bit of a nitpick here.

gulhameed361 and others added 2 commits March 18, 2026 13:38
Co-authored-by: Miranda Mundt <55767766+mrmundt@users.noreply.github.com>
Co-authored-by: Miranda Mundt <55767766+mrmundt@users.noreply.github.com>
@gulhameed361
Copy link
Author

Sorry sorry, little bit of a nitpick here.

I think it was a great catch as it wasn't step 4, it was just an alternative.

@gulhameed361
Copy link
Author

I just noticed it was at pre-test inspected status. Apologies for re-requesting review!

Comment on lines +8 to +14
#
# Development of this module was conducted as part of the Institute for
# the Design of Advanced Energy Systems (IDAES) with support through the
# Simulation-Based Engineering, Crosscutting Research Program within the
# U.S. Department of Energy’s Office of Fossil Energy and Carbon Management.
#
# This software is distributed under the 3-clause BSD License.
Copy link
Member

Choose a reason for hiding this comment

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

@gulhameed361 I'm assuming the development of the funnel approach was not funded under the IDAES program in which case the IDAES copyright assertion can be removed from any new files in this PR.

Comment on lines +8 to +14
#
# Development of this module was conducted as part of the Institute for
# the Design of Advanced Energy Systems (IDAES) with support through the
# Simulation-Based Engineering, Crosscutting Research Program within the
# U.S. Department of Energy’s Office of Fossil Energy and Carbon Management.
#
# This software is distributed under the 3-clause BSD License.
Copy link
Member

Choose a reason for hiding this comment

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

Same comment about the IDAES copyright. I suspect this can be removed but confirm with your paper coauthors.

"``0`` = Filter (default), ``1`` = Funnel. "
"Default = 0.",
),
)
Copy link
Member

Choose a reason for hiding this comment

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

Why did you set this up to be an integer instead of something more verbose/explicit like a string enum where the options are "filter" and "funnel"? Using an enum would prevent users having to remember which integer is mapped to which variant.

If you decide to change this implementation you can find a couple examples here:
https://github.com/Pyomo/pyomo/blob/main/pyomo/contrib/pyros/config.py#L628
https://github.com/Pyomo/pyomo/blob/main/pyomo/contrib/incidence_analysis/config.py#L67

) -> bool:
# Δf ≥ μ_s · Δθ
return (f_old - f_new) >= self.mu_s * ((theta_old) ** 2)
# return (f_old - f_new) >= self.mu_s * (theta_old - theta_new)
Copy link
Member

Choose a reason for hiding this comment

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

Can this commented line be removed? Also, do you still need to pass theta_new to this function if it's not being used?

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.

4 participants