Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
47 changes: 25 additions & 22 deletions doc/OnlineDocs/explanation/solvers/pyros/solver_log.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,29 @@ your console output will, by default, look like this:
:linenos:

==============================================================================
PyROS: The Pyomo Robust Optimization Solver, v1.3.11.
Pyomo version: 6.9.5
PyROS: The Pyomo Robust Optimization Solver, v1.3.15.
Pyomo version: 6.10.2.dev0
Commit hash: unknown
Invoked at UTC 2025-10-18T00:00:00.000000+00:00
Invoked at UTC 2026-06-05T00:00:00.000000+00:00

Developed by: Natalie M. Isenberg (1), Jason A. F. Sherman (1),
John D. Siirola (2), Chrysanthos E. Gounaris (1)
(1) Carnegie Mellon University, Department of Chemical Engineering
(2) Sandia National Laboratories, Center for Computing Research

The developers gratefully acknowledge support from the U.S. Department
of Energy's Institute for the Design of Advanced Energy Systems (IDAES).
of Energy's Institute for the Design of Advanced Energy Systems (IDAES)
and Carbon Capture Simulation for Industry Impact (CCSI2) projects.
==============================================================================
================================= DISCLAIMER =================================
PyROS is currently under active development.
Please provide feedback and/or report any issues by creating a ticket at
https://github.com/Pyomo/pyomo/issues/new/choose
==============================================================================
User-provided solver options:
tee=False
objective_focus=<ObjectiveType.worst_case: 1>
decision_rule_order=1
solve_master_globally=True
bypass_local_separation=False
------------------------------------------------------------------------------
Model Statistics (before preprocessing):
Number of variables : 4
Expand All @@ -60,21 +61,23 @@ your console output will, by default, look like this:
Inequality constraints : 2
------------------------------------------------------------------------------
Preprocessing...
Done preprocessing; required wall time of 0.004s.
Done preprocessing; required wall time of 0.003s.
------------------------------------------------------------------------------
Itn Objective 1-Stg Shift 2-Stg Shift #CViol Max Viol Wall Time (s)
------------------------------------------------------------------------------
0 5.4079e+03 - - 3 7.9226e+00 0.209
1 5.4079e+03 6.0451e-10 1.0717e-10 2 1.0250e-01 0.476
2 6.5403e+03 1.0018e-01 7.4564e-03 1 1.0249e-02 0.786
3 6.5403e+03 1.9372e-16 2.0321e-05 2 8.7074e-03 1.132
4 6.5403e+03 0.0000e+00 2.0311e-05 0 1.2310e-06g 1.956
0 5.4079e+03 - - 3 4.6876e+02 0.185
1 5.4079e+03 6.0451e-10 1.0717e-10 2 6.1500e+01 0.496
2 6.5403e+03 1.0018e-01 7.4564e-03 1 1.7142e-03 0.804
3 6.5403e+03 1.9372e-16 3.6832e-06 2 2.7964e-01 1.136
4 6.5403e+03 0.0000e+00 3.8115e-06 1 1.7141e-03 1.465
5 6.5403e+03 0.0000e+00 8.4872e-03 1 4.7920e-01 1.855
6 6.5403e+03 0.0000e+00 2.0736e-04 0 1.3594e-06g 2.756
------------------------------------------------------------------------------
Robust optimal solution identified.
------------------------------------------------------------------------------
Termination stats:
Iterations : 5
Solve time (wall s) : 1.956
Iterations : 7
Solve time (wall s) : 2.756
Final objective value : 6.5403e+03
Termination condition : pyrosTerminationCondition.robust_optimal
------------------------------------------------------------------------------
Expand All @@ -87,32 +90,32 @@ Observe that the log contains the following information
(listed in order of appearance):


* **Introductory information and disclaimer** (lines 1--19):
* **Introductory information** (lines 1--18):
Includes the version number, author
information, (UTC) time at which the solver was invoked,
and, if available, information on the local Git branch and
commit hash.
* **Summary of solver options** (lines 20--24): Enumeration of
* **Summary of solver options** (lines 19--25): Enumeration of
specifications for optional arguments to the solver.
* **Model component statistics** (lines 25--34):
* **Model component statistics** (lines 26--35):
Breakdown of component statistics for the user-provided model
and variable selection (before preprocessing).
* **Preprocessing information** (lines 35--37):
* **Preprocessing information** (lines 36--38):
Wall time required for preprocessing
the deterministic model and associated components,
i.e., standardizing model components and adding the decision rule
variables and equations.
* **Iteration log table** (lines 38--45):
* **Iteration log table** (lines 39--48):
Summary information on the problem iterates and subproblem outcomes.
The constituent columns are defined in detail in
:ref:`the table that follows <table-iteration-log-columns>`.
* **Termination message** (lines 46--47): One-line message briefly summarizing
* **Termination message** (lines 49--50): One-line message briefly summarizing
the reason the solver has terminated.
* **Final result** (lines 48--53):
* **Final result** (lines 51--56):
A printout of the
:class:`~pyomo.contrib.pyros.solve_data.ROSolveResults`
object that is finally returned.
* **Exit message** (lines 54--55): Confirmation that the
* **Exit message** (lines 57--58): Confirmation that the
solver has been exited properly.

The iteration log table is designed to provide, in a concise manner,
Expand Down
3 changes: 2 additions & 1 deletion pyomo/contrib/pyros/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ PyROS CHANGELOG


-------------------------------------------------------------------------------
PyROS 1.3.15 12 May 2026
PyROS 1.3.15 04 Jun 2026
-------------------------------------------------------------------------------
- Extend `CardinalitySet` to allow for negative deviations
- Update PyROS solver output log introductory information


-------------------------------------------------------------------------------
Expand Down
16 changes: 8 additions & 8 deletions pyomo/contrib/pyros/pyros.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,19 @@ def _log_intro(self, logger, **log_kwargs):
logger.log(
msg=(
"of Energy's "
"Institute for the Design of Advanced Energy Systems (IDAES)."
"Institute for the Design of Advanced Energy Systems (IDAES)"
),
**log_kwargs,
)
logger.log(
msg="and Carbon Capture Simulation for Industry Impact (CCSI2) projects.",
**log_kwargs,
)
logger.log(msg="=" * self._LOG_LINE_LENGTH, **log_kwargs)

def _log_disclaimer(self, logger, **log_kwargs):
def _log_feedback_guidance(self, logger, **log_kwargs):
"""
Log PyROS solver disclaimer messages.
Log PyROS solver guidance on providing user feedback.

Parameters
----------
Expand All @@ -212,10 +216,6 @@ def _log_disclaimer(self, logger, **log_kwargs):
Keyword arguments to ``logger.log()`` callable.
Should not include `msg`.
"""
disclaimer_header = " DISCLAIMER ".center(self._LOG_LINE_LENGTH, "=")

logger.log(msg=disclaimer_header, **log_kwargs)
logger.log(msg="PyROS is currently under active development. ", **log_kwargs)
logger.log(
msg=(
"Please provide feedback and/or report any issues by creating "
Expand Down Expand Up @@ -419,7 +419,7 @@ def solve(
)
)
self._log_intro(logger=progress_logger, level=logging.INFO)
self._log_disclaimer(logger=progress_logger, level=logging.INFO)
self._log_feedback_guidance(logger=progress_logger, level=logging.INFO)

config, user_var_partitioning = self._resolve_and_validate_pyros_args(
model, **kwds
Expand Down
23 changes: 11 additions & 12 deletions pyomo/contrib/pyros/tests/test_grcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3979,7 +3979,7 @@ def test_log_intro(self):
# check number of lines is as expected
self.assertEqual(
len(intro_msg_lines),
14,
15,
msg=(
"PyROS solver introductory message does not contain"
"the expected number of lines."
Expand All @@ -3993,16 +3993,17 @@ def test_log_intro(self):
# check regex main text
self.assertRegex(
" ".join(intro_msg_lines[1:-1]),
r"PyROS: The Pyomo Robust Optimization Solver, v.* \(IDAES\)\.",
r"PyROS: The Pyomo Robust Optimization Solver, v.* \(CCSI2\) "
r"projects\.",
)

def test_log_disclaimer(self):
def test_log_feedback_ref(self):
"""
Test logging of PyROS solver disclaimer messages.
Test logging of PyROS solver guidance on providing feedback.
"""
pyros_solver = SolverFactory("pyros")
with LoggingIntercept(level=logging.INFO) as LOG:
pyros_solver._log_disclaimer(logger=logger, level=logging.INFO)
pyros_solver._log_feedback_guidance(logger=logger, level=logging.INFO)

disclaimer_msgs = LOG.getvalue()

Expand All @@ -4012,23 +4013,21 @@ def test_log_disclaimer(self):
# check number of lines is as expected
self.assertEqual(
len(disclaimer_msg_lines),
5,
3,
msg=(
"PyROS solver disclaimer message does not contain"
"PyROS solver disclaimer message does not contain "
"the expected number of lines."
),
)

# regex first line of disclaimer section
self.assertRegex(disclaimer_msg_lines[0], r"=.* DISCLAIMER .*=")
# check last line of disclaimer section
self.assertEqual(disclaimer_msg_lines[-1], "=" * 78)

# check regex main text
self.assertRegex(
" ".join(disclaimer_msg_lines[1:-1]),
r"PyROS is currently under active development.*ticket at.*",
" ".join(disclaimer_msg_lines[0:-1]),
r"Please provide feedback.*ticket at.*",
)
self.assertEqual(disclaimer_msg_lines[-1], "=" * 78)


class UnavailableSolver:
Expand Down
11 changes: 6 additions & 5 deletions pyomo/contrib/pyros/uncertainty_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1475,16 +1475,16 @@ class CardinalitySet(UncertaintySet):
origin : (N,) array_like
Origin of the set (e.g., nominal uncertain parameter values).
positive_deviation : (N,) array_like
Upper bounds for absolute values of the positive coordinate
deviations from the origin.
Maximal absolute deviation from the origin in the
positive coordinate direction.
gamma : numeric type
Upper bound for the number of coordinates that can
simultaneously realize their maximal deviations from
the origin. Must be a numerical value ranging from 0
to the set dimension `N`.
negative_deviation : (N,) array_like, optional
Upper bounds for absolute values of the negative coordinate
deviations from the origin.
Maximal absolute deviation from the origin in the
negative coordinate direction.
If `None` is passed, then this argument is set to
an (`N`,) shaped array of zeros.

Expand Down Expand Up @@ -1538,7 +1538,8 @@ class CardinalitySet(UncertaintySet):
\\right\\},

the cardinality-constrained set implicitly defined
in the popular robust optimization work [BS04]_.
in the popular robust optimization work by Bertsimas and Sim
[BS04]_.

Examples
--------
Expand Down
Loading