Skip to content

Commit 8a555ae

Browse files
authored
Merge pull request #544 from DLWoodruff/moderner_Bauer
Moderner bauer
2 parents 8cc8085 + 16cdef6 commit 8a555ae

33 files changed

+735
-248
lines changed

doc/src/amalgamator.rst

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
Amalgamator
44
===========
55

6-
For simple problems that do not need extra specification, ``amalgamator.py``
6+
.. Note::
7+
This is an advanced topic, probably of interest only to maintainers of
8+
confidence interfal and related code.
9+
10+
The file ``amalgamator.py``
711
provides several drivers to solve a problem without writing a program
812
that creates the cylinders one by one. ``amalgamator.from_module`` enables
913
a high-level user to create a hub-and-spoke architecture using the command
@@ -49,7 +53,9 @@ It must contains the following attributes for use with cylinders:
4953

5054

5155
Create Amalgamator from a module and command line
52-
------------------------------------------------- Given an options
56+
-------------------------------------------------
57+
58+
Given an options
5359
``Config`` object (typically called `cfg`) as above,
5460
``amalgamator.Amalgamator_parser`` creates calls the appropriate
5561
functions to add the necessary information for different modules.
@@ -88,7 +94,7 @@ Examples
8894
--------
8995

9096
As intended, the examples of use of Amalgamator are quite short. The first
91-
example, ``farmer_ama.py``, solves directly the EF. The model can be specified,
97+
example, ``examples.farmer.archive.farmer_ama.py``, solves directly the EF. The model can be specified,
9298
e.g. by taking an integer version of it. This specification can be made via
9399
the command line, thanks to the ``inparser_adder`` method of ``farmer.py``.
94100

doc/src/confidence_intervals.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ This object has a ``run`` method that returns a gap estimator and a confidence i
5757
Examples
5858
--------
5959

60-
There are example scripts for sequential sampling in both ``farmer`` and ``aircond``.
60+
There are example scripts for sequential sampling in both ``farmer/CI`` and ``aircond``.
6161

6262
Using stand-alone ``mmw_conf.py``
6363
---------------------------------
@@ -79,7 +79,7 @@ to be able to pass problem-specific args down without knowing what they are.
7979

8080
Once a model satisfies the requirement for amalgamator, next a ``.npy`` file should be constructed from the given model. This can be accomplished, for example, by adding the line
8181
``sputils.ef_ROOT_nonants_npy_serializer(instance, 'xhat.npy')`` after solving the ef ``instance``. When using ``Amalgamator`` to solve the program, this can be done by adding the line
82-
``sputils.ef_ROOT_nonants_npy_serializer(ama_object.ef, "xhat.npy")`` to your existing program (see the example in ``farmer.py`` for an example of this).
82+
``sputils.ef_ROOT_nonants_npy_serializer(ama_object.ef, "xhat.npy")`` to your existing program (see the example in ``examples/farmer/archive/farmer.py`` for an example of this).
8383

8484
Once this is accomplished, on the command line, run
8585
``python -m mpisppy.confidence_intervals.mmw_conf my_model.py xhat.npy gurobi --num-scens n --alpha 0.95``. Note that ``xhat.npy`` is assumed to be in the same directory as ``my_model.py`` in this case. If the file is saved elsewhere then the corresponding path should be called on the command line.

doc/src/examples.rst

Lines changed: 21 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ constraints are the number of tons per acre that each crop will yield (2.5 for
4747
wheat, 3 for corn, and 20 for sugar beets).
4848

4949

50-
The following code creates an instance of the farmer's model:
50+
The following code in ``examples/farmer/archive/farmer.py`` (with similar code in ``examples/farmer/farmer.py``) creates an instance of the farmer's model:
5151

5252
.. testcode::
5353

@@ -109,7 +109,8 @@ yields for each crop. We can solve the model:
109109
The optimal objective value is:
110110

111111
.. testoutput::
112-
112+
:options: +SKIP
113+
113114
-118600.0
114115

115116
In practice, the farmer does not know the number of tons that each crop will
@@ -206,136 +207,39 @@ farmer's stochastic program.
206207
Solving the Extensive Form
207208
^^^^^^^^^^^^^^^^^^^^^^^^^^
208209

209-
The simplest approach is to solve the extensive form of the model directly.
210-
MPI-SPPy makes this quite simple:
211-
212-
.. testcode::
210+
The simplest approach is to solve the extensive form of the model directly. Assuming you are in the directory
211+
``examples/farmer`` the following unix command will work.
213212

214-
from mpisppy.opt.ef import ExtensiveForm
213+
.. code-block:: bash
215214
216-
options = {"solver": "cplex_direct"}
217-
all_scenario_names = ["good", "average", "bad"]
218-
ef = ExtensiveForm(options, all_scenario_names, scenario_creator)
219-
results = ef.solve_extensive_form()
215+
python ../../mpisppy/generic_cylinders.py --module-name farmer --num-scens 3 --EF --EF-solver-name gurobi
220216
221-
objval = ef.get_objective_value()
222-
print(f"{objval:.1f}")
217+
We can extract the optimal solution itself using the ``--solution-base-name`` option:
223218

219+
.. code-block:: bash
224220
225-
.. testoutput::
226-
227-
...
228-
-108390.0
221+
python ../../mpisppy/generic_cylinders.py --module-name farmer --num-scens 3 --EF --EF-solver-name gurobi --solution-base-name farmersol
229222
230-
We can extract the optimal solution itself using the ``get_root_solution``
231-
method of the ``ExtensiveForm`` object:
232-
233-
.. testcode::
234-
235-
soln = ef.get_root_solution()
236-
for (var_name, var_val) in soln.items():
237-
print(var_name, var_val)
238-
239-
.. testoutput::
240-
241-
X[BEETS] 250.0
242-
X[CORN] 80.0
243-
X[WHEAT] 170.0
223+
This command writes solution data for nonanticipative variables to two files with the base name farmersol and full scenario solutions to a directory named farmersol_soldir.
244224

225+
.. note::
226+
Most command line options relevant to the EF start with --EF. Most other command line options will be silently ignored
227+
if ``--EF`` is specified (one exception is ``--solution-base-name``).
228+
245229

246230
Solving Using Progressive Hedging (PH)
247231
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
248232

249-
We can also solve the model using the progressive hedging (PH) algorithm.
250-
First, we must construct a PH object:
251-
252-
.. testcode::
253-
254-
from mpisppy.opt.ph import PH
255-
256-
options = {
257-
"solver_name": "cplex_persistent",
258-
"PHIterLimit": 5,
259-
"defaultPHrho": 10,
260-
"convthresh": 1e-7,
261-
"verbose": False,
262-
"display_progress": False,
263-
"display_timing": False,
264-
"iter0_solver_options": dict(),
265-
"iterk_solver_options": dict(),
266-
}
267-
all_scenario_names = ["good", "average", "bad"]
268-
ph = PH(
269-
options,
270-
all_scenario_names,
271-
scenario_creator,
272-
)
273-
274-
275-
.. testoutput::
276-
:hide:
277-
278-
...
279-
280-
Note that all of the options in the ``options`` dict must be specified in order
281-
to construct the PH object. Once the PH object is constructed, we can execute
282-
the algorithm with a call to the ``ph_main`` method:
283-
284-
.. testcode::
285-
286-
ph.ph_main()
287-
288-
.. testoutput::
289-
:hide:
290-
291-
...
292-
293-
294-
.. testoutput::
295-
:options: +SKIP
296-
297-
298-
[ 0.00] Start SPBase.__init__
299-
[ 0.01] Start PHBase.__init__
300-
[ 0.01] Creating solvers
301-
[ 0.01] Entering solve loop in PHBase.Iter0
302-
[ 2.80] Reached user-specified limit=5 on number of PH iterations
233+
Here is a simple command that uses PH as the hub algorithm and
234+
computes lower bounds using a Lagrangian spoke (``--lagrangian``) with
235+
upper bounds computed by randomly trying scenario solutions to fix the nonanticipative variables (``--xhatshuffle``).
303236

304-
Note that precise timing results may differ. In this toy example, we only
305-
execute 5 iterations of the algorithm. Although the algorithm does not converge
306-
completely, we can see that the first-stage variables already exhibit
307-
relatively good agreement:
308237

309-
.. testcode::
238+
.. code-block:: bash
239+
240+
mpiexec -np 3 python -m mpi4py ../../mpisppy/generic_cylinders.py --module-name farmer --num-scens 3 --solver-name gurobi_persistent --max-iterations 10 --max-solver-threads 4 --default-rho 1 --lagrangian --xhatshuffle --rel-gap 0.01
310241
311-
variables = ph.gather_var_values_to_rank0()
312-
for (scenario_name, variable_name) in variables:
313-
variable_value = variables[scenario_name, variable_name]
314-
print(scenario_name, variable_name, variable_value)
315-
316-
.. testoutput::
317-
:hide:
318-
319-
...
320-
average X[BEETS]
321-
...
322-
323-
.. testoutput::
324-
:options: +SKIP
325242
326-
good X[BEETS] 280.6489711937925
327-
good X[CORN] 85.26131687116064
328-
good X[WHEAT] 134.0897119350402
329-
average X[BEETS] 283.2796296293019
330-
average X[CORN] 80.00000000014425
331-
average X[WHEAT] 136.72037037055298
332-
bad X[BEETS] 280.64897119379475
333-
bad X[CORN] 85.26131687116226
334-
bad X[WHEAT] 134.08971193504266
335-
336-
The function ``gather_var_values_to_rank0`` can be used in parallel to collect
337-
the values of all non-anticipative variables at the root. In this (serial)
338-
example, it simply returns the values of the first-stage variables.
339243
340244
Solving Using Benders' Decomposition
341245
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

doc/src/quick_start.rst

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ If you installed from github, install from source using pip in editable mode fro
77
88
pip install -e .
99

10-
This step is not needed if you installed using pip.
11-
You can also include the extras flags ``mpi`` to install a compliant version
12-
of mpi4py or ``docs`` to install documentation dependencies from pip.
10+
This step is not needed if you installed using pip, but we recommend against installing using pip because
11+
the software is under active development and the pip version is almost always out of date.
12+
You can also include the extras flag ``docs`` to install documentation dependencies from pip.
1313

1414

1515
Verify installation
@@ -25,13 +25,8 @@ terminal commands:
2525

2626
cd examples
2727
cd farmer
28-
python farmer_ef 1 3 solver_name
28+
python ../../mpisppy/generic_cylinders.py --module-name farmer --help
2929

30-
but replace `solver_name` with the name of the solver you have installed, e.g., if you have installed glpk, use
31-
32-
::
33-
34-
python farmer_ef 1 3 glpk
3530

3631
If you intend to use any parallel features, you should verify that you
3732
have a *proper* installation of MPI and ``mpi4py``; see the section
@@ -50,15 +45,10 @@ first thing is to code a scenario creation function. See
5045
If you create a few more helper functions
5146
(see :ref:`helper_functions`),
5247
you can make use of the ``generic_cylinders`` program (see :ref:`generic_cylinders`) to use the hub and spoke system or to solve the the EF directly.
53-
54-
Alternatively, once you have the scenario creation function,
55-
you can mimic the code in ``examples.farmer.farmer_ef`` to
56-
solve the extensive form directly. If you want to use the hub
57-
and spoke system to solve your problem via decomposition, you
58-
should proceed to the section on writing :ref:`Drivers`, or to
59-
the :ref:`Examples` section, or to the :ref:`generic_cylinders` section.
60-
6148

49+
You might want to start with the farmer example. See the `farmer` directory in the `examples` directory for the
50+
files `farmer.py` and `farmer_generic.bash`. For more information see :ref:`Examples`.
51+
6252
PySP Users
6353
----------
6454

@@ -74,12 +64,6 @@ Here are the general steps:
7464

7565
# Construct a ``PySPModel`` object giving its constructor information about your PySP model.
7666

77-
# Create an options dictionary.
78-
79-
# Create a PH or EF ``mpi-sppy`` object.
80-
81-
# Call its main function.
82-
8367
These steps alone will not result in use of the hub-spoke features of
8468
`mpi-sppy`, but they will get your PySP model running in
8569
``mpi-sppy``. See ``examples/farmer/from_pysp`` for some
@@ -95,4 +79,4 @@ The quickest thing to do is to run one of the canned examples that
9579
comes with ``mpi-sppy``. They are in subdirectories of
9680
``examples`` and sample commands can be obtained by looking at
9781
the code in ``examples.runall.py``. There is a table in the
98-
mpi-sppy paper that gives references for some of the examples.
82+
mpi-sppy paper in MPC that gives references for some of the examples.

doc/src/seqsamp.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ For multi-stage, use `multi_seqsampling.py`.
2727
Examples
2828
--------
2929

30-
There is sample code for two-stage, sequential sampling in ``examples.farmer.farmer_seqsampling.py`` and
31-
a bash scrip to test drive it is ``examples.farmer.farmer_sequential.bash``.
30+
There is sample code for two-stage, sequential sampling in ``examples.farmer.CI.farmer_seqsampling.py`` and
31+
a bash scrip to test drive it is ``examples.farmer.CI.farmer_sequential.bash``.
3232

3333
There is sample code for multi-stage, sequential sampling in ``examples.aircond.aircond_seqsampling.py`` and
3434
a bash scrip to test drive it is ``examples.aircond.aircond_sequential.bash``.

doc/src/spokes.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ so as to obtain better outer (lower when minimizing) bounds. It can also provide
6868
a Lagrangian bound even if the hub does not provide lagrangian multipliers.
6969

7070
The easiest way to use ``ph_ob`` is via the vanilla ``ph_ob_spoke`` method
71-
as illustrated in ``examples.farmer_cylinders.py``. This method takes values
71+
as illustrated in ``examples.farmer.archive.farmer_cylinders.py``. This method takes values
7272
from the config object (assuming the config object's ``ph_ob`` method
73-
was called as shown in the function ``examples.farmer_cylinders._parse_args``)
73+
was called as shown in the function ``examples.farmer.archive.farmer_cylinders._parse_args``)
7474
and sets up the options for the spoke.
7575

7676
The option ``ph-ob-initial-rho-rescale-factor`` defaults to 0.1, so if nothing

doc/src/zhat.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ Unless you are directly using mid-level functionality, your
1313
code may need to write the root node nonanticipative variable values
1414
(called `xhat` or `xhat_one`) to a file for later processing. This is
1515
typically done using ``sputils.ef_ROOT_nonants_npy_serializer``, which
16-
is shown in various examples, e.g., ``examples.farmer.farmer.py``
16+
is shown in various examples, e.g., ``examples.farmer.archive.farmer.py``
1717

1818
zhat4xhat
1919
---------
2020

2121
The program ``zhat4xhat`` estimates approximate confidence intervals
2222
for the objective function value, zhat, given an xhat. See
23-
``examples.farmer.farmer_zhat.bash`` for a bash script that first
23+
``examples.farmer.CI.farmer_zhat.bash`` for a bash script that first
2424
creates the xhat file, then computes an out-of-sample confidence
2525
interval for it. Note: this program does not compute a confidence
2626
interval for zstar, which is done using software documented in

examples/afew.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,14 @@ def do_one(dirname, progname, np, argstring):
4141
badguys[dirname] = [runstring]
4242
else:
4343
badguys[dirname].append(runstring)
44-
os.chdir("..")
44+
if '/' not in dirname:
45+
os.chdir("..")
46+
else:
47+
os.chdir("../..") # hack for one level of subdirectories
4548

4649

4750
# for farmer, the first arg is num_scens and is required
48-
do_one("farmer", "farmer_cylinders.py", 3,
51+
do_one("farmer/archive", "farmer_cylinders.py", 3,
4952
"--num-scens=3 --bundles-per-rank=0 --max-iterations=50 "
5053
"--default-rho=1 --sep-rho --display-convergence-detail "
5154
"--solver-name={} --xhatshuffle --lagrangian --use-norm-rho-updater".format(solver_name))

examples/farmer/CI/Readme.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CI
2+
--
3+
4+
This directory contains code related to getting confidence intervals for the farmer example.

0 commit comments

Comments
 (0)