Skip to content
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

Correct calculation of Constraint.equality for RangedExpression with constant bounds #2097

Closed
wants to merge 1 commit into from

Conversation

jsiirola
Copy link
Member

Fixes #2093

Summary/Motivation:

As was documented in #2093, the new implementation of ConstraintData.equality would occasionally fail to identify equality constraints for RangedExpression objects where the bounds were constants. This resolves that issue by using == instead of is when both bounds are constants (native types or constant expressions).

Changes proposed in this PR:

  • Use == instead of is to compare constraint bounds and determine equality when both bounds are constants.

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.

@jsiirola jsiirola requested a review from blnicho August 19, 2021 23:21
@ghackebeil
Copy link
Member

This feels like a move in the wrong direction. The use of two inequalities to express a constraint may be intentional, for reasons outside of Pyomo.

@codecov
Copy link

codecov bot commented Aug 20, 2021

Codecov Report

Merging #2097 (01878cf) into main (828c551) will increase coverage by 0.00%.
The diff coverage is 83.33%.

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #2097   +/-   ##
=======================================
  Coverage   82.87%   82.88%           
=======================================
  Files         619      619           
  Lines       76848    76852    +4     
=======================================
+ Hits        63689    63696    +7     
+ Misses      13159    13156    -3     
Impacted Files Coverage Δ
pyomo/core/base/constraint.py 92.23% <83.33%> (-0.17%) ⬇️
pyomo/contrib/mindtpy/iterate.py 76.73% <0.00%> (+1.98%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 828c551...01878cf. Read the comment docs.

@jsiirola
Copy link
Member Author

@ghackebeil I spent some time thinking about exactly this. Some discussion points included should we relax this more (that is, allow an 'equality tolerance'), or leave it more strict (leaning toward a very narrow relaxation of the is test, e.g., just to cover the originally reported issue with 0. is 0. occasionally not being True and comparison of 0 with 0.). The final argument for this approach centered on:

  • this removes a regression and restores behavior seen pre-6.1
  • this is restricted to structural equality: it will only return True if the lower bound and upper bound are constants and equal
  • if a user really wants to express this as two inequalities, they still can.

@ghackebeil
Copy link
Member

ghackebeil commented Aug 20, 2021

I'm simply saying that ranged inequality expressions may be important in whatever form the Pyomo model is translated into, whether or not the upper and lower bounds are constant, equal, parameters, or whatever. A user may want that structure retained (in, say, the LP or NL file). It seems inconsistent to turn a constraint into equality form, simply because the bound types or mutability changes.

My vote is for the entire elif self._expr.__class__ is logical_expr.RangedExpression: block to just be removed, but it's just a suggestion. ¯\_(ツ)_/¯

@michaelbynum
Copy link
Contributor

Should we have an explicit mechanism for users to have control over this behavior? This could be done a few different ways. We could have special constraint types or we could have functions that construct "the right thing" based on user input. I think it is best to make the default behavior something reasonable (probably what is implemented in this PR) but also allow users to have greater control if necessary.

@jsiirola
Copy link
Member Author

@blnicho and I were talking about this, too. I think there are three possible interpretations of ConstraintData.equality:

  1. Was the Constraint initialized with an EqualityExpression object (as opposed to an InequalityExpression or RangedExpression)?
  2. Does the ConstraintData represent a "structural equality"; that is (1) plus RangedExpression where the upper and lower bounds are symbolically equal?
  3. Does the ConstraintData represent a "numerical equality"; that is (1) plus RangedExpression where the upper and lower bounds are have equal value()?

Looking through the code base, there is not real consistency ... some places assume equality means case (1) (primarily transformations), and others (primarily writers) assume something closer to (3). @ghackebeil makes a good point that users may have had a good reason for expressing an equality as a ranged expression. Similarly, some solvers (like PyROS) would be much more interested in (3) (that is, the algorithm treats equality constraints very differently from inequalities).

We should probably document which one equality refers to (the property has never been documented), as well as how clients that care can get the other two versions if they care. One possible path forward is to deprecate equality and replace it with 1 or more new methods / properties that have more explicit names.

@jsiirola
Copy link
Member Author

Closing this PR and replacing it with PEP #2105

@jsiirola jsiirola closed this Aug 24, 2021
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
4 participants