-
Notifications
You must be signed in to change notification settings - Fork 541
Map Constraint.Feasible/Infeasible to concrete constraints #3546
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
base: main
Are you sure you want to change the base?
Conversation
This permits assigning logical expressions based on IntervalVar objects, restoring previous behavior. We should revisit template expressions in the future to permit better expression type validation.
A note from the dev call on 4/8 - we don't think we need to especially rush to get this in by the patch release next week, but it would be nice if we could. |
I feel like I am missing some context for this PR. Other than the example in #2918, I can't think of a use case for In short, I'm not really a user of |
@@ -622,7 +623,9 @@ class Constraint(ActiveIndexedComponent): | |||
class Infeasible(object): | |||
pass | |||
|
|||
Feasible = ActiveIndexedComponent.Skip | |||
class Feasible(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class Feasible(object): | |
class Feasible: |
@@ -188,118 +221,94 @@ class LogicalConstraint(ActiveIndexedComponent): | |||
class Infeasible(object): | |||
pass | |||
|
|||
Feasible = ActiveIndexedComponent.Skip | |||
class Feasible(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class Feasible(object): | |
class Feasible: |
self.add(expr) | ||
if self.rule is not None: | ||
_rule = self.rule(self.parent_block(), ()) | ||
for cc in iter(_rule): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does cc
stand for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not entirely sure - it is just a temporary, and was copied from the implementation in ConstraintList (and preserved for consistency)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really nice! I'm very happy about the implications for GDP. :) I have a few questions and a couple comments, but mostly just so I understand things.
_known_relational_expressions = { | ||
_known_relational_expression_types = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this name change a lot--it's much clearer!
# Note that an inequality is sufficient to induce | ||
# infeasibility and is simpler to relax (in the Big-M | ||
# sense) than an equality. | ||
self._expr = InequalityExpression((1, 0), False) | ||
return | ||
elif expr is Constraint.Feasible: | ||
# Note that we do not want to provide a trivial equality | ||
# constraint as that can confuse solvers like Ipopt into | ||
# believing that the model has fewer degrees of freedom | ||
# than it actually has. | ||
self._expr = InequalityExpression((0, 0), False) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just so that I understand: Why do we have to put trivial expressions at all? Could we not consider Constraint.Feasible
and Constraint.Infeasible
to be (weird) relational expression nodes in the expression tree, themselves?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We certainly could. That is, we could make Constraint.Feasible
and Constraint.Infeasible
be singleton expression objects (and not types). I think I would still make them special cases of InequalityExpression
, mostly so that all the walkers, writers, and whatnot don't have to be updated to handle them as special cases. This just seemed simpler?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it is simpler, but it's a bit confusing to me why, because it feels like we lose information in this step rather than carrying it through. Because if they were singleton expression objects, then wouldn't we would know after set_value
that the Constraint is either non-trivial or it's Constraint.Infeasible
or Constraint.Feasible
? With this implementation, it could be trivial, and that has to be checked later (by transformations, writers, whatever). Otherwise downstream things would know they either have these special nodes or a non-trivial constraint. Which might be nice...?
def body(self): | ||
def expr(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this PR deprecate body
? I agree with the change, but missed the magic somewhere, I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. .body
is still implemented in the LogicalConstraintData
base class and is an alias to .expr
Fixes #2918 .
Summary/Motivation:
We have historically mapped
Constraint.Feasible
toConstraint.Skip
and hadConstraint.Infeasible
immediately raise aValueError
. This causes some undesirable behavior:Constraint
that was set byConstraint.Feasible
because theConstraintData
was not created (see this question on SO)This updates
Constraint
andLogicalConstraint
to mapConstraint.Feasible
to a trivial inequality, andConstraint.Infeasible
to a trivial infeasible Inequality.Changes proposed in this PR:
Constraint.Feasible
andConstraint.Infeasible
to actual trivial constraintslogical_to_linear
andlogical_to_disjunctive
to support constant expressionsLegal Acknowledgement
By contributing to this software project, I have read the contribution guide and agree to the following terms and conditions for my contribution: