Skip to content

Commit b524a24

Browse files
authored
Merge pull request #3541 from jsiirola/calc-var-overflow
`calc_variable_from_constraint`: guard against expression overflow
2 parents adb0ab1 + b7b0842 commit b524a24

File tree

2 files changed

+33
-13
lines changed

2 files changed

+33
-13
lines changed

pyomo/util/calc_var_value.py

+23-13
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,10 @@ def calculate_variable_from_constraint(
176176
intercept = (residual_1 - upper) - slope * x1
177177
if slope:
178178
variable.set_value(-intercept / slope, skip_validation=True)
179-
body_val = value(body, exception=False)
179+
try:
180+
body_val = value(body, exception=False)
181+
except OverflowError:
182+
body_val = None
180183
if body_val.__class__ not in _invalid_types and abs(body_val - upper) < eps:
181184
# Re-set the variable value to trigger any warnings WRT
182185
# the final variable state
@@ -277,18 +280,25 @@ def calculate_variable_from_constraint(
277280
while alpha > alpha_min:
278281
# check if the value at xkp1 has sufficient reduction in
279282
# the residual
280-
fkp1 = value(expr, exception=False)
281-
# HACK for Python3 support, pending resolution of #879
282-
# Issue #879 also pertains to other checks for "complex"
283-
# in this method.
284-
if fkp1.__class__ in _invalid_types:
285-
# We cannot perform computations on complex numbers
286-
fkp1 = None
287-
if fkp1 is not None and fkp1**2 < c1 * fk**2:
288-
# found an alpha value with sufficient reduction
289-
# continue to the next step
290-
fk = fkp1
291-
break
283+
try:
284+
fkp1 = value(expr, exception=False)
285+
# HACK for Python3 support, pending resolution of #879
286+
# Issue #879 also pertains to other checks for "complex"
287+
# in this method.
288+
if fkp1.__class__ in _invalid_types:
289+
# We cannot perform computations on complex numbers
290+
fkp1 = None
291+
if fkp1 is not None and fkp1**2 < c1 * fk**2:
292+
# found an alpha value with sufficient reduction
293+
# continue to the next step
294+
fk = fkp1
295+
break
296+
except OverflowError:
297+
# Encountered an overflow, either from evaluating
298+
# this point in the line search (to get fkp1) or
299+
# from squaring fkp1. (The example from #3540
300+
# actually triggers both). Reject this alpha value.
301+
pass
292302
alpha /= 2.0
293303
xkp1 = xk + alpha * pk
294304
variable.set_value(xkp1, skip_validation=True)

pyomo/util/tests/test_calc_var_value.py

+10
Original file line numberDiff line numberDiff line change
@@ -459,3 +459,13 @@ def test_external_function_explicit_sympy(self):
459459
calculate_variable_from_constraint(
460460
m.x, m.c, diff_mode=differentiate.Modes.sympy
461461
)
462+
463+
def test_linea_search_overflow(self):
464+
# This tests the example from #3540
465+
m = ConcreteModel()
466+
m.x = Var(initialize=5)
467+
m.y = Var(initialize=1)
468+
m.con = Constraint(expr=m.y == 10 ** (-m.x))
469+
470+
calculate_variable_from_constraint(m.x, m.con)
471+
self.assertAlmostEqual(value(m.x), 0)

0 commit comments

Comments
 (0)