Skip to content

Commit cc2185b

Browse files
authored
Merge pull request Pyomo#3475 from shermanjasonaf/fix-docs-and-logging
Fix/Tweak PyROS Documentation and Solver Output Logging
2 parents bb5f993 + 0f955d0 commit cc2185b

File tree

5 files changed

+56
-30
lines changed

5 files changed

+56
-30
lines changed

doc/OnlineDocs/explanation/solvers/pyros.rst

+19-22
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,8 @@ where:
6666
PyROS accepts models in which there are:
6767

6868
1. Bounds declared on the ``Var`` objects representing
69-
components of the variable vectors :math:`z` and :math:`y`.
70-
These bounds are reformulated to inequality constraints.
71-
2. Ranged inequality constraints. These are easily reformulated to
72-
single inequality constraints.
69+
components of the variable vectors
70+
2. Ranged inequality constraints
7371

7472
In order to cast the robust optimization counterpart of the
7573
:ref:`deterministic model <deterministic-model>`,
@@ -186,9 +184,9 @@ The PyROS solver is invoked through the
186184
Upon successful convergence of PyROS, the solution returned is
187185
certified to be robust optimal only if:
188186

189-
1. master problems are solved to global optimality
187+
1. Master problems are solved to global optimality
190188
(by specifying ``solve_master_globally=True``)
191-
2. a worst-case objective focus is chosen
189+
2. A worst-case objective focus is chosen
192190
(by specifying ``objective_focus=ObjectiveType.worst_case``)
193191

194192
Otherwise, the solution returned is certified to only be robust feasible.
@@ -998,7 +996,7 @@ Observe that the log contains the following information:
998996
p_robustness={}
999997
------------------------------------------------------------------------------
1000998
Preprocessing...
1001-
Done preprocessing; required wall time of 0.018s.
999+
Done preprocessing; required wall time of 0.009s.
10021000
------------------------------------------------------------------------------
10031001
Model Statistics:
10041002
Number of variables : 62
@@ -1020,34 +1018,33 @@ Observe that the log contains the following information:
10201018
------------------------------------------------------------------------------
10211019
Itn Objective 1-Stg Shift 2-Stg Shift #CViol Max Viol Wall Time (s)
10221020
------------------------------------------------------------------------------
1023-
0 3.5838e+07 - - 1 2.7000e+02 0.657
1024-
1 3.6087e+07 8.0199e-01 1.2807e-01 5 4.1852e+04 1.460
1025-
2 3.6125e+07 8.7068e-01 2.7098e-01 8 2.7711e+01 3.041
1026-
3 3.6174e+07 7.6526e-01 2.2357e-01 4 1.3893e+02 4.186
1027-
4 3.6285e+07 2.8923e-01 3.4064e-01 0 1.2670e-09g 7.162
1021+
0 3.5838e+07 - - 5 1.8832e+04 0.412
1022+
1 3.5838e+07 1.2289e-09 1.5886e-12 5 2.8919e+02 0.992
1023+
2 3.6269e+07 3.1647e-01 1.0432e-01 4 2.9020e+02 1.865
1024+
3 3.6285e+07 7.6526e-01 2.2258e-01 0 2.3874e-12g 3.508
10281025
------------------------------------------------------------------------------
10291026
Robust optimal solution identified.
10301027
------------------------------------------------------------------------------
10311028
Timing breakdown:
10321029
10331030
Identifier ncalls cumtime percall %
10341031
-----------------------------------------------------------
1035-
main 1 7.163 7.163 100.0
1032+
main 1 3.509 3.509 100.0
10361033
------------------------------------------------------
1037-
dr_polishing 4 0.293 0.073 4.1
1038-
global_separation 27 1.106 0.041 15.4
1039-
local_separation 135 3.385 0.025 47.3
1040-
master 5 1.396 0.279 19.5
1041-
master_feasibility 4 0.155 0.039 2.2
1042-
preprocessing 1 0.018 0.018 0.2
1043-
other n/a 0.811 n/a 11.3
1034+
dr_polishing 3 0.209 0.070 6.0
1035+
global_separation 27 0.590 0.022 16.8
1036+
local_separation 108 1.569 0.015 44.7
1037+
master 4 0.654 0.163 18.6
1038+
master_feasibility 3 0.083 0.028 2.4
1039+
preprocessing 1 0.009 0.009 0.3
1040+
other n/a 0.394 n/a 11.2
10441041
======================================================
10451042
===========================================================
10461043
10471044
------------------------------------------------------------------------------
10481045
Termination stats:
1049-
Iterations : 5
1050-
Solve time (wall s) : 7.163
1046+
Iterations : 4
1047+
Solve time (wall s) : 3.509
10511048
Final objective value : 3.6285e+07
10521049
Termination condition : pyrosTerminationCondition.robust_optimal
10531050
------------------------------------------------------------------------------

pyomo/contrib/pyros/CHANGELOG.txt

+13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@ PyROS CHANGELOG
33
===============
44

55

6+
-------------------------------------------------------------------------------
7+
PyROS 1.3.5 13 Feb 2025
8+
-------------------------------------------------------------------------------
9+
- Tweak online documentation, including solver logging output example
10+
- Adjust UTC invocation time retrieval in PyROS logging to
11+
deprecation of `datetime.datetime.now()` in Python 3.12
12+
- Suppress error message emitted to console when PyROS
13+
attempts to retrieve git commit hash of Pyomo installation that
14+
is not a git repository
15+
- Add more information to solver output logging message emitted upon
16+
failure to solve deterministic (i.e., initial master) problem
17+
18+
619
-------------------------------------------------------------------------------
720
PyROS 1.3.4 22 Jan 2025
821
-------------------------------------------------------------------------------

pyomo/contrib/pyros/master_problem_methods.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,9 @@ def solver_call_master(master_data):
845845
)
846846
deterministic_msg = (
847847
(
848-
" Please ensure your deterministic model "
848+
" Please ensure that your deterministic model, "
849+
"subject to the nominal uncertain parameter realization "
850+
"you have provided, "
849851
f"is solvable by at least one of the subordinate {solve_mode} "
850852
"optimizers provided."
851853
)

pyomo/contrib/pyros/pyros.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# ___________________________________________________________________________
1111

1212
# pyros.py: Generalized Robust Cutting-Set Algorithm for Pyomo
13-
from datetime import datetime
13+
from datetime import datetime, timezone
1414
import logging
1515

1616
from pyomo.common.config import document_kwargs_from_configdict
@@ -33,7 +33,7 @@
3333
)
3434

3535

36-
__version__ = "1.3.4"
36+
__version__ = "1.3.5"
3737

3838

3939
default_pyros_solver_logger = setup_pyros_logger()
@@ -61,7 +61,14 @@ def _get_pyomo_version_info():
6161
]
6262
try:
6363
commit_hash = (
64-
subprocess.check_output(commit_hash_command_args).decode("ascii").strip()
64+
subprocess.check_output(
65+
commit_hash_command_args,
66+
# suppress git error if Pyomo installation
67+
# is not a git repo
68+
stderr=subprocess.DEVNULL,
69+
)
70+
.decode("ascii")
71+
.strip()
6572
)
6673
except subprocess.CalledProcessError:
6774
commit_hash = "unknown"
@@ -133,7 +140,8 @@ def _log_intro(self, logger, **log_kwargs):
133140
logger.log(
134141
msg=(
135142
f"{' ' * len('PyROS:')} "
136-
f"Invoked at UTC {datetime.utcnow().isoformat()}"
143+
"Invoked at UTC "
144+
f"{datetime.now(timezone.utc).isoformat()}"
137145
),
138146
**log_kwargs,
139147
)

pyomo/contrib/pyros/tests/test_grcs.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919

2020
from parameterized import parameterized
2121
import pyomo.common.unittest as unittest
22-
from pyomo.common.log import LoggingIntercept
2322
from pyomo.common.collections import Bunch
2423
from pyomo.common.errors import InvalidValueError
24+
from pyomo.common.log import LoggingIntercept
25+
from pyomo.common.tee import capture_output
2526
from pyomo.core.base.set_types import NonNegativeIntegers
2627
from pyomo.repn.plugins import nl_writer as pyomo_nl_writer
2728
import pyomo.repn.ampl as pyomo_ampl_repn
@@ -2740,8 +2741,13 @@ def test_log_intro(self):
27402741
Test logging of PyROS solver introductory messages.
27412742
"""
27422743
pyros_solver = SolverFactory("pyros")
2743-
with LoggingIntercept(level=logging.INFO) as LOG:
2744-
pyros_solver._log_intro(logger=logger, level=logging.INFO)
2744+
with capture_output(capture_fd=True) as OUT:
2745+
with LoggingIntercept(level=logging.INFO) as LOG:
2746+
pyros_solver._log_intro(logger=logger, level=logging.INFO)
2747+
2748+
# ensure git repo commit check error messages suppressed
2749+
err_msgs = OUT.getvalue()
2750+
self.assertEqual(err_msgs, "")
27452751

27462752
intro_msgs = LOG.getvalue()
27472753

0 commit comments

Comments
 (0)