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

Extend fbbt.ExpressionBoundsVisitor to handle relational expressions and Expr_if #3129

Merged
merged 9 commits into from
Feb 13, 2024

Conversation

jsiirola
Copy link
Member

@jsiirola jsiirola commented Feb 8, 2024

Fixes #3083 .

Summary/Motivation:

This is an extended implementation of #3086 that switches the handling of unrecognized types from generating exceptions to emitting warnings. It also fixes #3083 by adding support for relational expressions and Expr_if.

I think it would be worth a future PR to revisit the design of the BeforeChildDispatcher to simplify the amount of custom code required between the LinearRepnVisitor / AMPLRepnVisitor and the ExpressionBoundsVisitor.

Changes proposed in this PR:

  • Extend ExpressionBoundsVisitor to support relational and Expr_if expression s
  • ExpressionBoundsVisitor should not raise exceptions for unrecognized numeric / logical expressions (instead just emit a warning)
  • Clean up some error messages (and make them a little more user friendly)
  • Cover additional edge cases where Var / Param can inject invalid values into the bounds processing

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.

def __init__(self, val):
self._val = val

def __bool__(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we actually want to implement __bool__? I feel like a value property or method would be safer. Maybe I'm being paranoid.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think so? - it made some of the logic in the walker easier, and the object will never be released anywhere the user would see it.

ans = Bool(False), Bool(True)
else:
super().unexpected_expression_type(visitor, node, *args)
logger.warning(
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this issue a warning for external functions? If so, I think that needs changed.

Copy link
Member Author

Choose a reason for hiding this comment

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

It will not: ExternalFunctions are a) caught in the beforeChild callback (so exitNode should never be called, and b) there is an explicit registration for ExternalFunctionExpression, so it will never hit the unexpected_xpression_type method.

Copy link
Contributor

@emma58 emma58 left a comment

Choose a reason for hiding this comment

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

I like this a lot. Just a couple questions and a plea for docstrings. :)

Comment on lines 56 to 57
def Bool(val):
return _true if val else _false
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this (and maybe the bool_ class too) be private?

Copy link
Member Author

Choose a reason for hiding this comment

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

Bool (now BoolFlag) should probably not be private, as it is used outside of this module (however, it should definitely not be added to __init__.py). bool_ has been renamed _bool_flag)

pyomo/contrib/fbbt/interval.py Show resolved Hide resolved
self.assertEqual(len(end), 8)
self.assertEqual(len(end), 9)
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this testing? Why did it change?

Copy link
Member Author

Choose a reason for hiding this comment

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

This changed because the ExitNodeDispatcher changed a bit: by getting rid of the extra registration function (and implementing it's logic in __missing__, we changed how we handle unknown types: they are now registered witht he dispatcher using the unexpected_expression_type handler (so that handler can be overwritten). The test now reflects that the number of dispatchers registered in the END will increase.

@blnicho blnicho merged commit 7c429b1 into Pyomo:main Feb 13, 2024
33 checks passed
@jsiirola jsiirola deleted the fbbt_fix_updated branch February 20, 2024 23:58
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.

FBBT handling of Expr_if expressions
4 participants