Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
84de166
Move ScalarObjective to use AbstractScalar pattern
jsiirola Jun 9, 2025
dbd2fa0
Rework/simplify constraint & var bound evaluation
jsiirola Jun 9, 2025
a944c8b
Support templatization of scalar constraint/objective components
jsiirola Jun 9, 2025
72450b9
Disable __call__ on AbstractScalarConstraint components
jsiirola Jun 9, 2025
c59ef84
Catch exceptions when attempting to evaluate a unary function with an…
jsiirola Jun 9, 2025
9c12dbe
Promote inv2str to util as val2str
jsiirola Jun 9, 2025
049909a
Promote FIXED processing to the main linear/quadratic walkers
jsiirola Jun 9, 2025
aade470
Route checks for 0 and 1 mult coefficients through constant_flag and …
jsiirola Jun 9, 2025
3194125
overhaul, simplify, and combine parameterized linear and quadratic re…
jsiirola Jun 9, 2025
c2d028e
NFC: minor cleanup, improve comments
jsiirola Jun 9, 2025
e78870b
Silence NumPy deprecation warning
jsiirola Jun 9, 2025
52dfe87
Update linear template repn visitor
jsiirola Jun 9, 2025
df72496
Update TemplateVarRecorder to not accept var_order; correctly initial…
jsiirola Jun 9, 2025
54c88a2
Fix logging namespace in pyomo.repn.util
jsiirola Jun 9, 2025
82586ca
Catch additional errors applying operations to InvalidNumber
jsiirola Jun 9, 2025
ffca68a
Update tests to reflect changes in repn compilers
jsiirola Jun 9, 2025
a18e936
Update BigM test: int argument is now preserved
jsiirola Jun 9, 2025
6d0ca6b
Test standard form compiler for both regular and templated expressions
jsiirola Jun 9, 2025
104a8cb
Provide special-case handling for LINEAR**2
jsiirola Jun 14, 2025
874fbee
Improve use of mutable_expression context manager
jsiirola Jun 15, 2025
6045edc
Merge branch 'main' into repn-refactor
jsiirola Jun 16, 2025
6ffce1e
Merge branch 'main' into repn-refactor
jsiirola Jun 18, 2025
190d09b
NFC: apply black
jsiirola Jun 18, 2025
cac10c7
Fix copy/paste typo
jsiirola Jun 18, 2025
0bcbaa6
NFC: fix typo
jsiirola Jun 18, 2025
8eb7a10
Fix detection of TemplateRepn
jsiirola Jun 26, 2025
5d2923c
Merge branch 'main' into repn-refactor
jsiirola Jun 29, 2025
44c20d8
Allow creating parameterized vectors from iterators
jsiirola Jun 30, 2025
ef8ea2d
Catch edge case: trivial constraints with non-numeric linear constants
jsiirola Jun 30, 2025
0e4ff92
Standardize construction of CSC matricies (empty and nonempty)
jsiirola Jun 30, 2025
7ef0db4
NFC: fix typo
jsiirola Jun 30, 2025
a2ea1c3
Merge branch 'main' into repn-refactor
jsiirola Jun 30, 2025
3cadc0a
Explicitly check for InvalidNumber in linear,quadratic walkers
jsiirola Jul 1, 2025
d212669
Improve robustness of QuadraticRepn to str
jsiirola Jul 1, 2025
627e0b5
Improve linear,quadratic repn coverage
jsiirola Jul 1, 2025
41fc0d5
Apply black
mrmundt Jul 2, 2025
065448d
Merge branch 'main' into repn-refactor
jsiirola Jul 30, 2025
0bc65e1
Make Templatized objective and constraint classes more consistent
jsiirola Aug 4, 2025
4e2d87a
NFC: add/update comments
jsiirola Aug 4, 2025
67c9ef3
Merge branch 'main' into repn-refactor
jsiirola Aug 4, 2025
f8562a0
Apply black - newlines are the worst
mrmundt Aug 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyomo/contrib/pyros/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
from pyomo.core.util import prod
from pyomo.opt import SolverFactory
import pyomo.repn.ampl as pyomo_ampl_repn
from pyomo.repn.parameterized_quadratic import ParameterizedQuadraticRepnVisitor
from pyomo.repn.parameterized import ParameterizedQuadraticRepnVisitor
import pyomo.repn.plugins.nl_writer as pyomo_nl_writer
from pyomo.repn.util import OrderedVarRecorder
from pyomo.util.vars_from_expressions import get_vars_from_components
Expand Down
84 changes: 56 additions & 28 deletions pyomo/core/base/constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@
TEMPLATIZE_CONSTRAINTS = False

_inf = float('inf')
_nonfinite_values = {_inf, -_inf}
_ninf = -_inf
_nonfinite_values = {_inf, _ninf}
_known_relational_expression_types = {
EqualityExpression,
InequalityExpression,
Expand Down Expand Up @@ -246,21 +247,31 @@

if evaluate_bounds:
lb, body, ub = ans
return self._evaluate_bound(lb, True), body, self._evaluate_bound(ub, False)
return self._evaluate_bound(lb, _ninf), body, self._evaluate_bound(ub, _inf)
return ans

def _evaluate_bound(self, bound, is_lb):
def _evaluate_bound(self, bound, unbounded):
if bound is None:
return None
if bound.__class__ not in native_numeric_types:
bound = float(value(bound))
bound = value(bound)
if bound.__class__ not in native_numeric_types:
# Starting in numpy 1.25, casting 1-element ndarray to
# float is deprecated. We still want to support
# that... but without enforcing a hard numpy dependence
for cls in bound.__class__.__mro__:
if cls.__name__ == 'ndarray' and cls.__module__ == 'numpy':
if len(bound) == 1:
bound = bound[0]
break
bound = float(bound)
# Note that "bound != bound" catches float('nan')
if bound in _nonfinite_values or bound != bound:
if bound == (-_inf if is_lb else _inf):
if bound == unbounded:
return None
raise ValueError(
f"Constraint '{self.name}' created with an invalid non-finite "
f"{'lower' if is_lb else 'upper'} bound ({bound})."
f"{'upper' if unbounded==_inf else 'lower'} bound ({bound})."
)
return bound

Expand Down Expand Up @@ -333,12 +344,12 @@
@property
def lb(self):
"""float : the value of the lower bound of a constraint expression."""
return self._evaluate_bound(self.to_bounded_expression()[0], True)
return self._evaluate_bound(self.to_bounded_expression()[0], _ninf)

@property
def ub(self):
"""float : the value of the upper bound of a constraint expression."""
return self._evaluate_bound(self.to_bounded_expression()[2], False)
return self._evaluate_bound(self.to_bounded_expression()[2], _inf)

@property
def equality(self):
Expand Down Expand Up @@ -527,20 +538,9 @@
__renamed__version__ = '6.7.2'


class TemplateConstraintData(ConstraintData):
class TemplateDataMixin(object):
__slots__ = ()

def __init__(self, template_info, component, index):
# These lines represent in-lining of the
# following constructors:
# - ConstraintData,
# - ActiveComponentData
# - ComponentData
self._component = component
self._active = True
self._index = index
self._expr = template_info

@property
def expr(self):
# Note that it is faster to just generate the expression from
Expand All @@ -552,17 +552,34 @@
return self._expr

def set_value(self, expr):
self.__class__ = ConstraintData
self.__class__ = self.__class__.__mro__[

Check warning on line 555 in pyomo/core/base/constraint.py

View check run for this annotation

Codecov / codecov/patch

pyomo/core/base/constraint.py#L555

Added line #L555 was not covered by tests
self.__class__.__mro__.index(TemplateDataMixin) + 1
]
Comment thread
jsiirola marked this conversation as resolved.
return self.set_value(expr)

def to_bounded_expression(self):
def to_bounded_expression(self, evaluate_bounds=False):
tmp, self._expr = self._expr, self._expr[0]
try:
return super().to_bounded_expression()
return super().to_bounded_expression(evaluate_bounds)
finally:
self._expr = tmp


class TemplateConstraintData(TemplateDataMixin, ConstraintData):
__slots__ = ()

def __init__(self, template_info, component, index):
# These lines represent in-lining of the
# following constructors:
# - ConstraintData,
# - ActiveComponentData
# - ComponentData
self._component = component
self._active = True
self._index = index
self._expr = template_info

Check warning on line 580 in pyomo/core/base/constraint.py

View check run for this annotation

Codecov / codecov/patch

pyomo/core/base/constraint.py#L577-L580

Added lines #L577 - L580 were not covered by tests


@ModelComponentFactory.register("General constraint expressions.")
class Constraint(ActiveIndexedComponent):
"""
Expand Down Expand Up @@ -695,11 +712,17 @@
if TEMPLATIZE_CONSTRAINTS:
try:
template_info = templatize_constraint(self)
comp = weakref_ref(self)
self._data = {
idx: TemplateConstraintData(template_info, comp, idx)
for idx in self.index_set()
}
if self.is_indexed():
comp = weakref_ref(self)
self._data = {

Check warning on line 717 in pyomo/core/base/constraint.py

View check run for this annotation

Codecov / codecov/patch

pyomo/core/base/constraint.py#L716-L717

Added lines #L716 - L717 were not covered by tests
idx: TemplateConstraintData(template_info, comp, idx)
for idx in self.index_set()
}
else:
assert self.__class__ is ScalarConstraint
self.__class__ = TemplateScalarConstraint
self._expr = template_info
self._data = {None: self}
return
except TemplateExpressionError:
pass
Expand Down Expand Up @@ -912,6 +935,7 @@

@disable_methods(
{
'__call__',
'add',
'set_value',
'to_bounded_expression',
Expand All @@ -933,6 +957,10 @@
__renamed__version__ = '6.0'


class TemplateScalarConstraint(TemplateDataMixin, ScalarConstraint):
pass


class IndexedConstraint(Constraint):
#
# Leaving this method for backward compatibility reasons
Expand Down
Loading
Loading