Skip to content

Commit 14a1c10

Browse files
authored
Merge pull request #3646 from shermanjasonaf/pyros-adjust-sep-eval-errors
Adjust PyROS handling of separation objective evaluation errors
2 parents 31b08b8 + 580beaf commit 14a1c10

File tree

2 files changed

+39
-25
lines changed

2 files changed

+39
-25
lines changed

pyomo/contrib/pyros/separation_problem_methods.py

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -193,27 +193,23 @@ def get_sep_objective_values(separation_data, ss_ineq_cons):
193193
con_to_obj_map = separation_data.separation_model.second_stage_ineq_con_to_obj_map
194194
violations = ComponentMap()
195195

196-
user_var_partitioning = separation_data.separation_model.user_var_partitioning
197-
first_stage_variables = user_var_partitioning.first_stage_variables
198-
second_stage_variables = user_var_partitioning.second_stage_variables
199-
200196
for ss_ineq_con in ss_ineq_cons:
201197
obj = con_to_obj_map[ss_ineq_con]
202198
try:
203199
violations[ss_ineq_con] = value(obj.expr)
204-
except ValueError:
205-
for v in first_stage_variables:
206-
config.progress_logger.info(v.name + " " + str(v.value))
207-
for v in second_stage_variables:
208-
config.progress_logger.info(v.name + " " + str(v.value))
209-
raise ArithmeticError(
210-
f"Evaluation of second-stage inequality constraint {ss_ineq_con.name} "
211-
f"(separation objective {obj.name}) "
212-
"led to a math domain error. "
213-
"Does the constraint expression "
214-
"contain log(x) or 1/x functions "
200+
except (ValueError, ArithmeticError):
201+
vars_in_expr_str = ",\n ".join(
202+
f"{var.name}={var.value}" for var in identify_variables(obj.expr)
203+
)
204+
config.progress_logger.error(
205+
"PyROS encountered an exception evaluating "
206+
"expression of second-stage inequality constraint with name "
207+
f"{ss_ineq_con.name!r} (separation objective {obj.name!r}) "
208+
f"at variable values:\n {vars_in_expr_str}\n"
209+
"Does the expression contain log(x) or 1/x functions "
215210
"or others with tricky domains?"
216211
)
212+
raise
217213

218214
return violations
219215

pyomo/contrib/pyros/tests/test_grcs.py

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,9 +1242,8 @@ def test_pyros_nl_and_ampl_writer_tol(self):
12421242
)
12431243
def test_pyros_math_domain_error(self):
12441244
"""
1245-
Test PyROS on a two-stage problem, discrete
1246-
set type with a math domain error evaluating
1247-
second-stage inequality constraint expressions in separation.
1245+
Test PyROS behavior is as expected when there are errors
1246+
encountered while evaluating separation problem objectives.
12481247
"""
12491248
m = ConcreteModel()
12501249
m.q = Param(initialize=1, mutable=True)
@@ -1259,16 +1258,35 @@ def test_pyros_math_domain_error(self):
12591258
pyros_solver = SolverFactory("pyros")
12601259

12611260
with self.assertRaisesRegex(
1262-
expected_exception=ArithmeticError,
1263-
expected_regex=(
1264-
"Evaluation of second-stage inequality constraint.*math domain error.*"
1265-
),
1266-
msg="ValueError arising from math domain error not raised",
1261+
expected_exception=ValueError,
1262+
expected_regex="math domain error",
1263+
msg="Exception arising from math domain error not raised",
12671264
):
12681265
# should raise math domain error:
12691266
# (1) lower bounding constraint on x2 solved first
1270-
# in separation, q = 0 in worst case
1271-
# (2) now tries to evaluate log(q), but q = 0
1267+
# in separation. Solution has q = 0
1268+
# (2) upon solution of the first separation problem,
1269+
# evaluation of x2 - log(q) at q = 0
1270+
# results in exception
1271+
pyros_solver.solve(
1272+
model=m,
1273+
first_stage_variables=[m.x1],
1274+
second_stage_variables=[m.x2],
1275+
uncertain_params=[m.q],
1276+
uncertainty_set=box_set,
1277+
local_solver=local_solver,
1278+
global_solver=global_solver,
1279+
decision_rule_order=1,
1280+
tee=True,
1281+
)
1282+
1283+
# this should result in error stemming from division by zero
1284+
m.x2.setub(1 / m.q)
1285+
with self.assertRaisesRegex(
1286+
expected_exception=ZeroDivisionError,
1287+
expected_regex="float division by zero",
1288+
msg="Exception arising from math domain error not raised",
1289+
):
12721290
pyros_solver.solve(
12731291
model=m,
12741292
first_stage_variables=[m.x1],

0 commit comments

Comments
 (0)