Skip to content

Commit

Permalink
Diagnostics tool for ill-posed constraints (#1454)
Browse files Browse the repository at this point in the history
* Working on cancellation detection

* Fixing typo

* Improving efficiency

* More efficiency and testing

* Reducing duplicated code in tests

* Finishing testing

* Adding additioanl tests and clean up

* Running pylint

* Adding constraint walker to diagnostics toolbox

* Addressing simple review comments

* Accumulate node rather than str(node)

* Clean up some tests

* Supporting ranged expressions

* Apply suggestions from code review

* Regorganising and fixing pylint issues

* Fixing false positives for linking constraints

* Fixing unused variable warning

* Fixing bug related to external functions with string arguments

* Addressing comments

* removing debugging prints

* Addressing more comments

* Debugging issue with nested external functions

* Adding todo

* Relax test tolerance due to Windows failures

* Adding catches for string arguments/values

* Test for nested external functions

* Fixing bug in walker logic for string arguments to external funcitons

* Address double counting of constraints

* Fixing typo

* Bumping Pyomo version

* Adding zero tolerance

* Adding test for zero tolerance

* Fixing typo

* Logic to skip scaled equality constraints

* Handling mole fraction type constraints

* Catching negations

* Fixing typos

* Limit of cancelling combinations

* Fixing typos

* Displaying cancelling terms to user

* More detail of mismatches

* Adding hooks and warnings about new config arguments

* Expression aware to string method

* Moving expression writer to util/misc

* Typos and comments

* Using StrEnum
  • Loading branch information
andrewlee94 authored Nov 5, 2024
1 parent 2e5a9a4 commit 3e403b7
Show file tree
Hide file tree
Showing 6 changed files with 2,256 additions and 40 deletions.
4 changes: 2 additions & 2 deletions idaes/core/scaling/custom_scaler_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
Author: Andrew Lee
"""
from copy import copy
from enum import Enum

from pyomo.environ import ComponentMap, units, value
from pyomo.core.base.units_container import UnitsError
Expand All @@ -26,6 +25,7 @@
from idaes.core.scaling.scaling_base import CONFIG, ScalerBase
from idaes.core.scaling.util import get_scaling_factor, NominalValueExtractionVisitor
import idaes.logger as idaeslog
from idaes.core.util.misc import StrEnum

# Set up logger
_log = idaeslog.getLogger(__name__)
Expand All @@ -41,7 +41,7 @@
}


class ConstraintScalingScheme(str, Enum):
class ConstraintScalingScheme(StrEnum):
"""
Schemes available for calculating constraint scaling factors.
Expand Down
66 changes: 66 additions & 0 deletions idaes/core/util/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
This module contains miscellaneous utility functions for use in IDAES models.
"""
from enum import Enum
import sys

import pyomo.environ as pyo
from pyomo.common.config import ConfigBlock
from pyomo.core.expr.visitor import _ToStringVisitor
from pyomo.core.base.expression import ExpressionData

import idaes.logger as idaeslog

Expand Down Expand Up @@ -177,3 +180,66 @@ class StrEnum(str, Enum):

def __str__(self):
return str(self.value)


class _ToExprStringVisitor(_ToStringVisitor):
"""
Derived version of the Pyomo _ToStringVisitor class
which checks for named Expressions in the expression tree
and prints their name instead of expanding the expression tree.
"""

def visiting_potential_leaf(self, node):
# Check if node is a named Expression
if isinstance(node, ExpressionData):
# If it is, return the name of the Expression
return True, node.name

# Otherwise, continue descending as normal
return super().visiting_potential_leaf(node)


def compact_expression_to_string(expr):
"""Return a compact string representation of an expression.
Unlike the normal Pyomo string representations, this function will
identify any Expressions that appear within the expression tree and
print the name of these rather than expanding the expression tree.
Args:
expr: ExpressionBase. The root node of an expression tree.
Returns:
A string representation for the expression.
"""
# Create and execute the visitor pattern
#
visitor = _ToExprStringVisitor(verbose=False, smap=None)
return visitor.dfs_postorder_stack(expr)


def print_compact_form(expr, stream=None):
"""
Writes a compact string representation of the given component or
expression to the specified stream.
Unlike the normal Pyomo string representations, this function will
identify any Expressions that appear within the expression tree and
print the name of these rather than expanding the expression tree.
Args:
expr: component or expression to print
stream: StringIO object to write to. Default is stdout.
Returns:
None
"""
if stream is None:
stream = sys.stdout

if hasattr(expr, "expr"):
# We have a Constraint or Expression
# We want to print the expression, not the object name
expr = expr.expr

stream.write(compact_expression_to_string(expr))
Loading

0 comments on commit 3e403b7

Please sign in to comment.