B _>6@sdZddlZddlTddlmZddlmmZddl m Z ddl m Z ddlmZddl mmZddlZdddZd d ZGd d d Zd dZddZdS)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)*)ScenarioTreeInstanceFactory)ExtensiveFormAlgorithm)CreateAbstractScenarioTreeModelcCsJ|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-d4p3hk07/pyomo/pysp/util/rapper.py_optiondict_2_lists   r csrifdd}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)kwargsrr 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)rrr )rrr _kwfromphopts s  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&|dkrpt|}td}||}t||}yt|||_Wn,tdt ddt ddYnXnt |r~|} 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)r phinitconstruct_ph_options_parser parse_argsrZGenerateScenarioTreeForPH scenario_treeprintinspectstack RuntimeErrorcallablereplace __import__splitgetattrrZgenerate_scenario_treeZ%construct_instances_for_scenario_treeZlinkInInstances)selfZfsfileZfsfctZ tree_modelrrparseroptionsZscenario_instance_factoryZ scen_functionmnZ treecbnameZ tree_makertreerZ instancesr r r __init__^s<         zStochSolver.__init__Fc Cstj|j||||||dS)a0 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)pyspefZcreate_ef_instancer)r%verboser-r.r/r0r1r r r make_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.r/r0r1NF)teeZload_solutionsr)r5) r4Z ef_instanceZ SolverFactoryr'solvelenZsolutionZgapZ solutionsZ load_fromrZ"pullScenarioSolutionsFromInstancesZsnapshotSolutionFromScenarios)r% subsolversoptsr5Zneed_gapr3r-r.r/r0r1Zsolverr Z solve_resultZabsgapr r r solve_efs,%    zStochSolver.solve_efc Csd}td}dt|g}|d|t|t||d}|dk rd}x(|D] } || dt|| d7}qPW|d||||} yt| |j}Wn&td |dk r| YnX| } | dk rt d t| | |S) afSolve 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=) rrstrrr rZPHAlgorithmBuilderrrZrelease_componentsr6rZ save_solution) r%r8Z default_rhorr9phr&Z phargslistZ soptstringr Z phoptionsretvalr r r solve_phs2         zStochSolver.solve_phccs`|j}xPt|jD]B}|j|\}}|}|dk rH|dt|d7}||j|fVqWdS)zqGenerator to loop over x-bar Yields: name, value pair for root node solution values N[])r findRootNodesortedZ _variable_idsr=Z _solution)r% root_nodeZ variable_idvar_nameindexnamer r r root_Var_solution0s 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) )rrCZcomputeExpectedNodeCost)r%rEr r r root_E_obj?s zStochSolver.root_E_obj)NNN)FFNNNr,) NFFFFNNNr,)NN) __name__ __module__ __qualname____doc__r+r4r:r@rIrJr r r r rFs( 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_phIs rQccs8x2|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)rPnodenamevarnameZvarvaluer r r xhat_walkerYs rU)N)rNrZ pyomo.environZ(pyomo.pysp.scenariotree.instance_factoryrZ pyomo.pysp.efZpyspZefr2Zpyomo.pysp.ef_writer_scriptrZ,pyomo.pysp.scenariotree.tree_structure_modelrZpyomo.pysp.phinitrosr rrrQrUr r r r s      &