Solving the Extensive Form

When we refer to “solving the EF” we mean passing the extensive form in its entirety directly to a general-purpose solver (as opposed to decomposition).

The simplest way to solve the EF is via generic_cylinders.py with the --EF flag:

python -m mpisppy.generic_cylinders --module-name farmer --num-scens 3 \
    --EF --EF-solver-name gurobi

See generic_cylinders.py for full details on EF-related command-line options.

mpisppy.opt.ef.ExtensiveForm Class

For developers who need programmatic access, there is a class for the EF that roughly matches the “look and feel” of a hub class, but does not function as a hub.

class mpisppy.opt.ef.ExtensiveForm(options, all_scenario_names, scenario_creator, scenario_creator_kwargs=None, all_nodenames=None, model_name=None, suppress_warnings=False, extensions=None, extension_kwargs=None)[source]

Bases: SPBase

Create and solve an extensive form.

ef

Pyomo model of the extensive form.

Type:

pyomo.environ.ConcreteModel

solver

Solver produced by the Pyomo solver factory.

Parameters:
  • options (dict) – Dictionary of options. May include a solver key to specify which solver name to use on the EF.

  • all_scenario_names (list) – List of the names of each scenario in the EF (strings).

  • scenario_creator (callable) – Scenario creator function, which takes as input a scenario name, and returns a Pyomo model of that scenario.

  • scenario_creator_kwargs (dict, optional) – Keyword arguments passed to scenario_creator.

  • all_nodenames (list, optional) – List of all node names, incl. leaves. Can be None for two-stage problem.

  • model_name (str, optional) – Name of the resulting EF model object.

  • suppress_warnings (bool, optional) – Boolean to suppress warnings when building the EF. Default is False.

Note: allowing use of the “solver” option key is for backward compatibility

get_objective_value()[source]

Retrieve the objective value.

Returns:

Objective value.

Return type:

float

Raises:

ValueError – If optimal objective value could not be retrieved.

get_root_solution()[source]

Get the value of the variables at the root node.

Returns:

Dictionary mapping variable name (str) to variable value (float) for all variables at the root node.

Return type:

dict

nonants()[source]

An iterator to give representative Vars subject to non-anticipitivity Args: None

Yields:

tree node name, full EF Var name, Var value

nonants_to_csv(filename)[source]

Dump the nonant vars from an ef to a csv file; truly a dump… :param filename: the full name of the csv output file :type filename: str

scenarios()[source]

An iterator to give the scenario sub-models in an ef Args: None

Yields:

scenario name, scenario instance (str, ConcreteModel)

solve_extensive_form(solver_options=None, tee=False)[source]

Solve the extensive form.

Parameters:
  • solver_options (dict, optional) – Dictionary of solver-specific options (e.g. Gurobi options, CPLEX options, etc.).

  • tee (bool, optional) – If True, displays solver output. Default False.

Returns:

Result returned by the Pyomo solve method.

Return type:

pyomo.opt.results.results_.SolverResults

EF Extensions

The ExtensiveForm class supports extensions via the extensions and extension_kwargs constructor arguments. EF extensions inherit from mpisppy.extensions.extension.EFExtension and can override two hooks:

  • pre_solve(): called after EF creation, before passing the model to the solver.

  • post_solve(results): called after the solver returns; must return results.

When using generic_cylinders.py, extensions are injected by defining an ef_dict_callback(ef_dict, cfg) function in the model module. This callback can modify ef_dict to add extensions before the EF is solved. Use cfg_vanilla.ef_extension_adder(ef_dict, ext_class) to add extension classes (multiple extensions are handled automatically via EFMultiExtension).

See examples/farmer/farmer_ef_ext.py for a complete example that adds a minimum expected wheat production constraint to the EF.

Other method: mpisppy.utils.sputils.create_EF

The use of this function does not require the installation of mpi4py. Its use is illustrated in examples.farmer.CI.farmer_ef.py. Here are the arguments to the function:

mpisppy.utils.sputils.create_EF(scenario_names, scenario_creator, scenario_creator_kwargs=None, EF_name=None, suppress_warnings=False, nonant_for_fixed_vars=True, total_number_of_scenarios=None)[source]

Create a ConcreteModel of the extensive form.

Parameters:
  • scenario_names (list of str) – Names for each scenario to be passed to the scenario_creator function.

  • scenario_creator (callable) – Function which takes a scenario name as its first argument and returns a concrete model corresponding to that scenario.

  • scenario_creator_kwargs (dict, optional) – Options to pass to scenario_creator.

  • EF_name (str, optional) – Name of the ConcreteModel of the EF.

  • suppress_warnings (boolean, optional) – If true, do not display warnings. Default False.

  • nonant_for_fixed_vars (bool--optional) – If True, enforces non-anticipativity constraints for all variables, including those which have been fixed. Default is True.

  • total_number_of_scenarios (int, optional) – For calculating uniform probabilities, the total number of scenarios.

Returns:

ConcreteModel of extensive form with explicit non-anticipativity constraints.

Return type:

EF_instance (ConcreteModel)

Note

If any of the scenarios produced by scenario_creator do not have a ._mpisppy_probability attribute, this function displays a warning, and assumes that all scenarios are equally likely.