Skip to content

Improved ConstraintData.equality, relational expression generation#3893

Open
jsiirola wants to merge 25 commits intoPyomo:mainfrom
jsiirola:constraint-equality
Open

Improved ConstraintData.equality, relational expression generation#3893
jsiirola wants to merge 25 commits intoPyomo:mainfrom
jsiirola:constraint-equality

Conversation

@jsiirola
Copy link
Copy Markdown
Member

@jsiirola jsiirola commented Mar 26, 2026

Fixes #2093 .

Summary/Motivation:

The original motivation of this PR was to resolve #2093. The Issue stemmed from the ConstraintData.equality property sometimes returning False for things that are obviously equality constraints due to the use of is for comparing the lower and upper bounds. This PR makes a modification of the property so that native_types in the lower/upper bounds are compared using == and everything else is compared with is. This is related to the (abandoned) PR #2097), where we used is_constant() to determine if we should use == or is. The difference here is the switch to native_types - both for efficiency and clarity of the intent.

As part of working through this, we came across inconsistencies in when constant expressions were resolved: the move of the relational expression generation logic to a multiple dispatch model caused constant relational expressions generated from operator overloading to be resolved to bool. This behavior was not promulgated to the inequality() function, or to the specification of constraints using "tuple notation". This PR overhauls inequality() and the tuple processing to be consistent with the relational expression logic. It also removed redundant logic, and funnels all expression generation through the relational expression dispatchers.

Update [13 Apr]

Resolved a number of additional edge cases, mostly related to resolving trivial portions of ranged constraints, including

  • inequality(0, 0, None) should be True (and not 0), and
  • Ranged constraints should check that trivial bounds are feasible (e.g., inequality(1, m.x, 0) should be False).

As part of this update, I added about 2000 lines of relational expression tests. Unfortunately, GitHub gets confused when trying to render the diff. The actual changes are adding 3 arguments (native2 (a larger native constant) and le2 / lt2 which are the same as le / lt, but with the argument order reversed). This meant adding 3 tests to the end of each test method, plus adding 3 new test methods (test_XX_native2, test_XX_le2, and test_XX_lt2) for each of the 3 test classes.

Buried in this are a handful of baseline changes, all due to the expression system being more thorough and consistent with resolving constant portions of expressions when generating expressions.

Changes proposed in this PR:

  • use == for comparing constraint bounds for native_types in ConstraintData.equality
  • rework inequality() to build on relational expression dispatcher
  • improve implementation of tuple_to_relational_expr to make it consistent with constraint behavior (and build on inequality())
  • simplify ConstraintData.set_value() to call tuple_to_relational_expr
  • add workarounds for unbounded constraints in the nonnegative_transform and Complementarity
  • update tests

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.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.93%. Comparing base (e55e4a2) to head (ae23c61).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3893   +/-   ##
=======================================
  Coverage   89.93%   89.93%           
=======================================
  Files         902      902           
  Lines      106415   106457   +42     
=======================================
+ Hits        95705    95745   +40     
- Misses      10710    10712    +2     
Flag Coverage Δ
builders 29.18% <21.42%> (+<0.01%) ⬆️
default 86.24% <100.00%> (?)
expensive 35.64% <40.47%> (?)
linux 87.39% <100.00%> (-2.03%) ⬇️
linux_other 87.39% <100.00%> (+<0.01%) ⬆️
oldsolvers 28.11% <41.66%> (+0.01%) ⬆️
osx 82.72% <100.00%> (+<0.01%) ⬆️
win 85.81% <100.00%> (-0.01%) ⬇️
win_other 85.81% <100.00%> (-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.

@blnicho blnicho requested a review from emma58 April 8, 2026 06:09
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.

Constraint's equality attribute sometimes fails to properly identify equality constraints

3 participants