Skip to content

Commit 3d5cb6c

Browse files
Fix PyROS discrete separation iteration log
1 parent 26e4970 commit 3d5cb6c

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

pyomo/contrib/pyros/pyros_algorithm_methods.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ def ROSolver_iterative_solve(model_data, config):
805805
len(scaled_violations) == len(separation_model.util.performance_constraints)
806806
and not separation_results.subsolver_error
807807
and not separation_results.time_out
808-
)
808+
) or separation_results.all_discrete_scenarios_exhausted
809809

810810
iter_log_record = IterationLogRecord(
811811
iteration=k,

pyomo/contrib/pyros/separation_problem_methods.py

+1
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ def perform_separation_loop(model_data, config, solve_globally):
649649
solver_call_results=ComponentMap(),
650650
solved_globally=solve_globally,
651651
worst_case_perf_con=None,
652+
all_discrete_scenarios_exhausted=True,
652653
)
653654

654655
perf_con_to_maximize = sorted_priority_groups[

pyomo/contrib/pyros/solve_data.py

+27-2
Original file line numberDiff line numberDiff line change
@@ -347,16 +347,23 @@ class SeparationLoopResults:
347347
solver_call_results : ComponentMap
348348
Mapping from performance constraints to corresponding
349349
``SeparationSolveCallResults`` objects.
350-
worst_case_perf_con : None or int, optional
350+
worst_case_perf_con : None or Constraint
351351
Performance constraint mapped to ``SeparationSolveCallResults``
352352
object in `self` corresponding to maximally violating
353353
separation problem solution.
354+
all_discrete_scenarios_exhausted : bool, optional
355+
For problems with discrete uncertainty sets,
356+
True if all scenarios were explicitly accounted for in master
357+
(which occurs if there have been
358+
as many PyROS iterations as there are scenarios in the set)
359+
False otherwise.
354360
355361
Attributes
356362
----------
357363
solver_call_results
358364
solved_globally
359365
worst_case_perf_con
366+
all_discrete_scenarios_exhausted
360367
found_violation
361368
violating_param_realization
362369
scaled_violations
@@ -365,11 +372,18 @@ class SeparationLoopResults:
365372
time_out
366373
"""
367374

368-
def __init__(self, solved_globally, solver_call_results, worst_case_perf_con):
375+
def __init__(
376+
self,
377+
solved_globally,
378+
solver_call_results,
379+
worst_case_perf_con,
380+
all_discrete_scenarios_exhausted=False,
381+
):
369382
"""Initialize self (see class docstring)."""
370383
self.solver_call_results = solver_call_results
371384
self.solved_globally = solved_globally
372385
self.worst_case_perf_con = worst_case_perf_con
386+
self.all_discrete_scenarios_exhausted = all_discrete_scenarios_exhausted
373387

374388
@property
375389
def found_violation(self):
@@ -599,6 +613,17 @@ def get_violating_attr(self, attr_name):
599613
"""
600614
return getattr(self.main_loop_results, attr_name, None)
601615

616+
@property
617+
def all_discrete_scenarios_exhausted(self):
618+
"""
619+
bool : For problems where the uncertainty set is of type
620+
DiscreteScenarioSet,
621+
True if last master problem solved explicitly
622+
accounts for all scenarios in the uncertainty set,
623+
False otherwise.
624+
"""
625+
return self.get_violating_attr("all_discrete_scenarios_exhausted")
626+
602627
@property
603628
def worst_case_perf_con(self):
604629
"""

0 commit comments

Comments
 (0)