B u `25@sdZddlZddlmZddlmZddlmZddlm Z ddl m Z m Z m Z ddd Zd d ZGd d d ZddZddZdS)z A class and some utilities to wrap PySP. In particular to enable programmatic access to some of the functionality in runef and runph for ConcreteModels Author: David L. Woodruff, started February 2017 N)_name_index_generator) SolverFactory)ScenarioTreeInstanceFactory)create_ef_instance)construct_ph_options_parserGenerateScenarioTreeForPHPHAlgorithmBuildercCsJ|dkr g}|dk rFx0|D](}||||dk r|||qW|S)z1 A little utility to change the format of optionsN)append)phopts args_listkeyr :/tmp/pip-unpacked-wheel-n62dbgi3/pyomo/pysp/util/rapper.py_optiondict_2_lists   rcsrifdd}dk rn|dd|dddkrHtdd <ndd <d krfd d <ndd <S) a This is really local to the StochSolver __init__ but I moved it way out to make the init more readable. The function takes the phopts dictionary and returns a kwargs dictionary suitable for a call to generate_scenario_tree. Note that only some options (i.e., bundle options) are needed when the tree is created. The rest can be passed in when the ph object is created. inputs: phopts: a ph options dictionary. return: kwargs: a dictionary suitable for a call to generate_scenario_tree. cs2|kr&|dk r&t||<nd|<dS)N)int)Zphofo)kwargsr r r dointpair+sz _kwfromphopts..dointpairNz--create-random-bundlesZrandom_bundlesz--scenario-tree-seedZ random_seedz#--scenario-tree-downsample-fractionZdownsample_fractionz--scenario-bundle-specificationz$--scenario-tree-bundle-specificationZbundles)float)r rr )rr r _kwfromphoptss  rc @sHeZdZdZdddZdddZdd d Zdd d Zd dZddZ dS) StochSolveraA class for solving stochastic versions of concrete models and abstract models. Inspired by the IDAES use case and by daps ability to create tree models. Author: David L. Woodruff, February 2017 Args: fsfile (str): is a path to the file that contains the scenario callback for concrete or the reference model for abstract. fsfct (str, or fct, or None): | str: callback function name in the file | fct: callback function (fsfile is ignored) | None: it is a AbstractModel tree_model (concrete model, or networkx tree, or path): gives the tree as a concrete model (which could be a fct) or a valid networkx scenario tree or path to AMPL data file. phopts: dictionary of ph options; needed during construction if there is bundling. Attributes: scenario_tree: scenario tree object (that includes data) NcCs"|dkrlt|}td}||}t||}yt|||_Wn,tdtddt ddYnXnt |rz|} nD| dd}t |} x$| d ddD]} t| | } qWt| |} |dkrd } t| | } | }t| |}n t| |}t|}|jf||_||j}|j|dS) z)Initialize a StochSolver object. Nz ERROR in StochSolver called fromzfsfct is None, so assumingz1AbstractModel but could not find all ingredients.z.py.Z!pysp_scenario_tree_model_callback)rr parse_argsrr scenario_treeprintinspectstack RuntimeErrorcallablereplace __import__splitgetattrrZgenerate_scenario_treeZ%construct_instances_for_scenario_treeZlinkInInstances)selfZfsfileZfsfctZ tree_modelr r parseroptionsZscenario_instance_factoryZ scen_functionmnZ treecbnameZ tree_makertreerZ instancesr r r__init__Zs<        zStochSolver.__init__Fc Cst|j||||||dS)a( Make an ef object (used by solve_ef); all Args are optional. Args: verbose (boolean): indicates verbosity to PySP for construction generate_weighted_cvar (boolean): indicates we want weighted CVar cvar_weight (float): weight for the cvar term risk_alpha (float): alpha value for cvar cc_indicator_var_name (string): name of the Var used for chance constraint cc_alpha (float): alpha for chance constraint Returns: ef_instance: the ef object )Zverbose_outputgenerate_weighted_cvar cvar_weight risk_alphacc_indicator_var_namecc_alpha)rr)r&verboser.r/r0r1r2r r rmake_efszStochSolver.make_efc Cs|j||||| | d|_t|} |dk rDx|D]} || | j| <q.W|r| j|j|dd} t| jdkrv| dj}nd}|jj | n| j|j|d} |j |j |r| |fS| SdS)aSolve the stochastic program directly using the extensive form. All Args other than subsolver are optional. Args: subsolver (str): the solver to call (e.g., 'ipopt') sopts (dict): solver options tee (bool): indicates dynamic solver output to terminal. need_gap (bool): indicates the need for the optimality gap verbose (boolean): indicates verbosity to PySP for construction generate_weighted_cvar (boolean): indicates we want weighted CVar cvar_weight (float): weight for the cvar term risk_alpha (float): alpha value for cvar cc_indicator_var_name (string): name of the Var used for chance constraint cc_alpha (float): alpha for chance constraint Returns: (`Pyomo solver result`, `float`) solve_result is the solver return value. absgap is the absolute optimality gap (might not be valid); only if requested Note: Also update the scenario tree, populated with the solution. Also attach the full ef instance to the object. So you might want obj = pyo.value(stsolver.ef_instance.MASTER) This needs more work to deal with solver failure (dlw, March, 2018) )r3r.r/r0r1r2NF)teeZload_solutionsr)r5) r4Z ef_instancerr(solvelenZsolutionZgapZ solutionsZ load_fromrZ"pullScenarioSolutionsFromInstancesZsnapshotSolutionFromScenarios)r& subsolversoptsr5Zneed_gapr3r.r/r0r1r2Zsolverr Z solve_resultZabsgapr r rsolve_efs,%    zStochSolver.solve_efc Csd}td}dt|g}|d|t|t||d}|dk rd}x(|D] } || dt|| d7}qNW|d||||} yt| |j}Wn&td |dk r|YnX| } | dk rt d t| | |S) aeSolve the stochastic program given by this.scenario_tree using ph Args: subsolver (str): the solver to call (e.g., 'ipopt') default_rho (float): the rho value to use by default phopts: dictionary of ph options (optional) sopts: dictionary of subsolver options (optional) Returns: the ph object Note: Updates the scenario tree, populated with the xbar values; however, you probably want to do obj, xhat = ph.compute_and_report_inner_bound_using_xhat() where ph is the return value. Nrz --default-rhoz--solver)r = z--scenario-solver-optionsz'Internal error: ph construction failed.zph Failure Encountered=) rstrr rrrrrZrelease_componentsr6r Z save_solution) r&r8Z default_rhor r9phr'Z phargslistZ soptstringr Z phoptionsretvalr r rsolve_phs2        zStochSolver.solve_phccsX|j}xHt|jD]:}|j|\}}|}|dk r@|t|7}||j|fVqWdS)zqGenerator to loop over x-bar Yields: name, value pair for root node solution values N)r findRootNodesortedZ _variable_idsrZ _solution)r& root_nodeZ variable_idvar_nameindexnamer r rroot_Var_solution,s  zStochSolver.root_Var_solutioncCs|j}|S)zpost solve Expected cost of the solution in the scenario tree (xbar) Returns: float: the expected costs of the solution in the tree (xbar) )rrAZcomputeExpectedNodeCost)r&rCr r r root_E_obj;s zStochSolver.root_E_obj)NNN)FFNNNr-) NFFFFNNNr-)NN) __name__ __module__ __qualname____doc__r,r4r:r@rGrHr r r rrBs( 8  ? 7rcCs|\}}||fS)za service fuction to wrap a call to get xhat Args: ph: a post-solve ph object Returns: (float, object) float: the expected cost of the xhat solution for the scenarios xhat: an object with the solution tree )Z)compute_and_report_inner_bound_using_xhat)r>objxhatr r r xhat_from_phEs rOccs8x2|D]*}x$||D]\}}|||fVqWqWdS)zA service generator to walk over a given xhat Args: xhat (dict): an xhat solution (probably from xhat_from_ph) Yields: (nodename, varname, varvalue) N)items)rNnodenamevarnameZvarvaluer r r xhat_walkerUs rS)N)rLrZpyomo.core.base.componentrZ pyomo.environrZ(pyomo.pysp.scenariotree.instance_factoryrZ pyomo.pysp.efrZpyomo.pysp.phinitrrrrrrrOrSr r r rs     &