B @`@s.ddlZddlZddlZddlZddlZddlmZddlmZm Z m Z ddl m Z m Z mZmZmZmZmZmZmZmZmZmZddlmZddlmZddlmZddlmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*dd l+m,Z,m-Z-dd l.m/Z/m0Z0m1Z1dd l2m3Z3dd l4m5Z5dd l6m7Z7ddl8m9Z9m:Z:m;Z;ddl?e@ZAeABddBddeCdZDdZEddZFddZGddZHddZIddZJdd ZKd!d"ZLd#d$ZMGd%d&d&eNZOGd'd(d(eZPGd)d*d*e9eZQd3d+d,ZRd-d.ZSd4d/d0ZTe;Ud1eQeVd2kr*ddlWZXeYeTdS)5N) OrderedDict) SolverFactoryTerminationCondition undefined) valueminimizeSet Objective SOSConstraint ConstraintVarRangeSet ExpressionSuffixRealsParam)_GeneralConstraintData)XConstraintList)PySPConfiguredObject) PySPConfigValuePySPConfigBlocksafe_register_common_optionsafe_declare_common_optionsafe_declare_unique_option_domain_percent_domain_nonnegative_domain_positive_integer_domain_must_be_str_domain_unit_interval_domain_tuple_of_str_domain_tuple_of_str_or_dict)parse_command_linelaunch_command)InvocationTypeScenarioTreeManagerScenarioTreeManagerFactory) ScenarioTreeManagerSolverFactory)find_active_objective)create_ef_instance)SPSolverSPSolverResultsSPSolverFactory)xrangez.pycz.pyz pyomo.pyspzBenders OptionscCsbt|jjdkst||jjks$t|j}|jd|j d|j dk r^d|j j |j<dS)NPYSP_BENDERS_NODE_COST_TERM_gT) len scenario_treestagesAssertionError scenarios findRootNode _instancefind_componentname set_value preprocessorobjective_updated)managerscenariorootnoder?>/tmp/pip-unpacked-wheel-bi3529v6/pyomo/pysp/solvers/benders.py"EXTERNAL_deactivate_rootnode_costsMs  rAcCs~t|jjdkst||jjks$t|j}|j|jd|jd}|jd|j  ||j dk rzd|j j |j <dS)Nr.rr/T) r0r1r2r3r4r5r6r7_cost_variabler8r9r:r;)r<r=r>Z nodecost_varr?r?r@ EXTERNAL_activate_rootnode_costsWs  rDcCspt|jjdkst||jjks$t|jd}||jdk rl|jj |j }x| D]}| |qZWdS)Nr. PYSP_BENDERS_FIX_XHAT_CONSTRAINT) r0r1r2r3r4r6r7activater:Zconstraints_added_listr8valuesappend)r<r=fix_constraintpreprocess_constraints_listconstraint_datar?r?r@!EXTERNAL_activate_fix_constraintscs rLcCspt|jjdkst||jjks$t|jd}||jdk rl|jj |j }x| D]}| |qZWdS)Nr.rE) r0r1r2r3r4r6r7 deactivater:Zconstraints_removed_listr8rGrH)r<r=rIrJrKr?r?r@#EXTERNAL_deactivate_fix_constraintsps rNcCs|j}x0|jD]&}d|j}t||s*t||qWt|dsFt|j|j|`t|dr|j slt|` |j rd}x:|j j D].}|j|j kr|d7}|j|j}|dqW|dkstn |d|jj}t|dst|j} x<| D]4\} } } || } | | _| | d| | dqW|`d}t||sDt||d }t||sbt||d }t||st|||jdk rd |jj|j<dS) Nr/_instance_cost_expression_old_remove_dual_at_benders_cleanuprrBdualPYSP_BENDERS_CACHED_DOMAINSPYSP_BENDERS_FIX_XHAT_INDEXPYSP_BENDERS_FIX_XHAT_VALUErET)r6 node_listr8hasattrr3Z del_component_instance_cost_expressionr9rOrPr1contains_bundlesbundlesscenario_names_bundle_binding_instance_map_ScenarioTreeSymbolMapbySymbolrRdomainsetlbsetubr:r;)r<r=instancenodecost_term_namefoundscenario_bundlebundle_instancescenario_bySymbolcached_domains variable_idr^ varboundsvardatanodal_index_set_namefix_param_namefix_constraint_namer?r?r@EXTERNAL_cleanup_from_benders~sR            rocst|jjdkst||jjks$t|j}|jj}|j}d}x`|j D]V}| |j d|j d}d|j }t ||r~t||t|d|| |7}qHWt |drt|jj|_|j||jrtd} x|jjD]} |j | jkr| d7} |j| j } t | ds&d |_ttjd | _qt| jtrX| js`td | jtj qt!d qW| dkstn\t |dsd |_ttjd |_n:t|jtr|jstd |jtj nt!d |j"j#t |d rtg} |_$xf|j%D]\} | }|&s|j'}|j(}t)|_(|j'}| *| ||f|+|d|,|dqWd}t ||rntt-|d t.|j/d}|||d}t ||rt||t0|d dd| |d}t ||rtfdd}||t1||d| |2t3||t4||dS)Nr.grrBr/) initializerOrQT) directionzDModifying existing dual component to import suffix data from solver.zObject with name 'dual' was found on model that is not of type 'Suffix'. The object must be renamed in order to use the benders algorithm.rRrS)r8ZorderedrprT)ZmutablerprEcs||dkS)Ngr?)mri) fix_paramrgr?r@fix_rule0sz1EXTERNAL_initialize_for_benders..fix_rule)Zrule)5r0r1r2r3r4r5Z _leaf_nodestager6rUr7rCr8rV add_componentrrWexprrOr9rXrYrZr[rPrZIMPORTrQ isinstanceZimport_enabledprintZ set_directionZ IMPORT_EXPORT TypeErrorr\r]rR _variable_idsZis_expression_typeZboundsr^rrHr_r`rsorted_standard_variable_idsrr rMrArL)r<r=r>Z leafstageraZ cost_termsrbZ stagecost_varrcrdrerfrhrirkZ tight_boundsr^rjrlZnodal_index_setrmrnrtr?)rsrgr@EXTERNAL_initialize_for_benderss                  r~c Cst|jjdkst||jjks$t|j}d}||}|||jd}|jdk r|jj |j }x| D]}| |qpWdS)Nr.rTrE) r0r1r2r3r4r6r7Z store_valuesr:Zconstraints_updated_listr8rGrH) r<r= fix_valuesrarmrsrIrJrKr?r?r@EXTERNAL_update_fix_constraints=s   rc Cst|jjdkst||jjks$td}d}|jrd}x8|jjD],}|j|jkrD|d7}|j |jj }|j }qDW|dkstn|j j }|j }|j }i}|j|jjj|d<i}|d<|j d} t|dkrtd|jx(|jD]} || | ||j || <qW|S)Nr.rrBSSCdualsrEzNo duals were returned with the solution for scenario %s. This might indicate a solve failure or that there are discrete variables in the second-stage problem.)r0r1r2r3r4rXrYr8rZr[rQ probabilityr6r5Z _stage_costsZ leaf_noderur7 RuntimeErrorr}) r<r=Z dual_suffixZsum_probability_bundlerdrer>Zscenario_resultsrZbenders_fix_constraintrir?r?r@EXTERNAL_collect_cut_dataOs4        rc@seZdZdZddZdS)BendersOptimalityCut)xhatsscrcCs||_||_||_dS)N)rrr)selfrrrr?r?r@__init__vszBendersOptimalityCut.__init__N)__name__ __module__ __qualname__ __slots__rr?r?r?r@rtsrcseZdZed*ddZddZddZdd Zfd d Zd d Z ddZ ddZ ddZ ddZ d+ddZddZddZd,ddZd d!Zd-d"d#Zd$d%Zd&d'Zd(d)ZZS).BendersAlgorithmNc Cs|dkrt}t|dt|dtdtddddtdt|dtd td dddtdt|d td td dddtdt|dtdtddddtdt|dtdt dddddditdt|dtdt ddddtdt|dtdt ddddtdt|dtdt ddddtdt|dtdt d dddtdt|d!tdt d"ddddditdt|d#tdt d$dddtdt|d%tdt d&dddtdt|d'tdt d(dddtdtj|d)dd*|S)+Nverbosemax_iterationsdz1The maximum number of iterations. Default is 100.r)r^ descriptiondocZ visibility)ap_group percent_gapg-C6?zEPercent optimality gap required for convergence. Default is 0.0001%%.multicut_levelrBzThe number of cut groups added to the master benders problem each iteration. Default is 1. A number less than 1 indicates that the maximum value should be used, which is one cut group for each scenario not included in the master problem.optimality_gap_epsilong|=z^The epsilon value used in the denominator of the optimality gap calculation. Default is 1e-10.master_include_scenariosr?zA list of names of scenarios that should be included in the master problem. This option can be used multiple times from the command line to specify more than one scenario name.actionrH)Zap_kwdsrmaster_disable_warmstartFzJDisable warm-start of the benders master problem solves. Default is False. master_solverZcplexzTSpecify the solver with which to solve the master benders problem. Default is cplex.master_solver_ioaThe type of IO used to execute the master solver. Different solvers support different types of IO, but the following are common options: lp - generate LP files, nl - generate NL files, mps - generate MPS files, python - direct Python interface, os - generate OSiL XML files. master_mipgapz3Specifies the mipgap for the master benders solves.master_solver_optionszPersistent solver options used when solving the master benders problem. This option can be used multiple times from the command line to specify more than one solver option.master_output_solver_logz6Output solver log during solves of the master problem.master_keep_solver_fileszBRetain temporary input and output files for master benders solves.master_symbolic_solver_labelsahWhen interfacing with the solver, use symbol names derived from the model. For example, "my_special_variable[1_2_3]" instead of "v1". Useful for debugging. When using the ASL interface (--solver-io=nl), generates corresponding .row (constraints) and .col (variables) files. The ordering in these files provides a mapping from ASL index to symbolic model names. subproblem_)options_prefixZsetup_argparse)rrrrr_benders_group_labelrintrrboolrrr r&register_options)clsoptionsr?r?r@_declare_options}s z!BendersAlgorithm._declare_optionscCs|S)Nr?)rr?r?r@ __enter__FszBendersAlgorithm.__enter__cGs |dS)N)close)rargsr?r?r@__exit__IszBendersAlgorithm.__exit__cCs<|jdk r||jdk r&|jd|_d|_d|_dS)N)_managercleanup_subproblems_manager_solverr_master_solver)rr?r?r@rLs   zBendersAlgorithm.closecsdddlm}d|_d|_d|_t|_t|_d|_d|_ d|_ d|_ d|_ g|_ d|_tt|j||t|ts|td|jstdt|jjdkrtd||_t|j|jdd|_d|_t|d |d d |_t|j|rtd t|d r@t|d tkr.|j d!|d n|j |d |ddk r`|d|jj"_#dS)Nr)PersistentSolverz`BendersAlgorithm requires an instance of the ScenarioTreeManager interface as the first argumentzQBendersAlgorithm requires a scenario tree manager that has been fully initializedr.z3BendersAlgorithm requires a two-stage scenario treer)rrr)Z solver_iozSBendersAlgorithm does not yet support PersistentSolver types for the master problemrr-r)$Z/pyomo.solvers.plugins.solvers.persistent_solverrrrrrmaster_bound_historyobjective_historyincumbent_objectiveroptimality_gap iterationsmastercut_pool_num_first_stage_constraintssuperrrrxr$rzZ initialized ValueErrorr0r1r2r&_optionsr get_optiontypetupleZ set_optionsjoinrZmipgap)rr<rkwdsr) __class__r?r@rUsN     zBendersAlgorithm.__init__cCs|jjdttjdddS)NrAT)invocation_type oneway_call)rinvoke_functionthisfiler# PerScenario)rr?r?r@deactivate_rootnode_costss z*BendersAlgorithm.deactivate_rootnode_costscCs|jjdttjdddS)NrDT)rr)rrrr#r)rr?r?r@activate_rootnode_costss z(BendersAlgorithm.activate_rootnode_costscCs|jjdttjdddS)NrLT)rr)rrrr#r)rr?r?r@activate_fix_constraintss z)BendersAlgorithm.activate_fix_constraintscCs|jjdttjdddS)NrNT)rr)rrrr#r)rr?r?r@deactivate_fix_constraintss z+BendersAlgorithm.deactivate_fix_constraintscCs|jjdttj|fdddS)NrT)rZ function_argsr)rrrr#r)rrr?r?r@update_fix_constraintss z'BendersAlgorithm.update_fix_constraintsFcCs|jjdttj|dS)Nr)r async_call)rrrr#r)rrr?r?r@collect_cut_datas z!BendersAlgorithm.collect_cut_datacCs,|drtd|jjdttjdddS)Nrz$Initializing subproblems for bendersr~T)rr)rryrrrr#r)rr?r?r@initialize_subproblemss z'BendersAlgorithm.initialize_subproblemscCs,|drtd|jjdttjdddS)Nrz#Cleaning up subproblems for bendersroT)rr)rryrrrr#r)rr?r?r@rs z$BendersAlgorithm.cleanup_subproblemsr?cs`|||j}|t|tfddDtfddD}|rX||fS|SdS)a Generate a cut for the first-stage solution xhat by solving the subproblems. By default, only the stage costs and objective values are updated on the local scenario tree. Setting update_stages to a list of stage names or None (indicating all stages) can be used to control how much solution information is loaded for the variables on the scenario tree. c3s|]}||dfVqdS)rNr?).0r8)cut_datar?r@ sz0BendersAlgorithm.generate_cut..c3s|]}||dfVqdS)rNr?)rr8)rr?r@rsN)rrZsolve_subproblemsrrdict)rrZ update_stagesreturn_solve_results solve_results benders_cutr?)rr@ generate_cuts  zBendersAlgorithm.generate_cutc( sd|kr|d}n |d}t|dks.t|jj}|}|j}|jj}|dks`t|dkrz|j |j dj gdd}nt dt||j |dd}|}|j d} | |jkst|j d} t|j d kst|j|} |j| d d t|} |dkst|dkrt| _d } nt|| _d} ttt| jtd dd | jtd dd }x|j D]}|j}xt|jtd d d |jtd d d D]n}y|j||d }Wn tk r|jd}YnX|j| k r|j| kst| r|n|d7}qWq^W||_t | d d|ddkrFt ddd|j D}nddt!|dD}d}t|}|dksxtx:|j D]0}|j | jkr|||"|j |d7}qWg}x&|D]}t|dkr|"|qWt|t|kr|ddkrt dt|t|fd}t#| |r.t| $|t%| &|}d}t#| |rZt| $|t'dt|d| &|}d}t#| |rt| $|t%|| &|d}t#| |rtt(| ||d}t#| |rt|t)kr| $|t|t*fdd|Dkdn(| $|t|t*fdd|Dkd|dksTt|dkrt|j dksht| &|j dj &|j+d|j+d}nd}t*d d|j D} x|j D]v}|jd}!|!|kst|j&|!j+d|!j+d}"|jd}#|j&|#j+d|#j+d}$||j,|"| |$7}qWd!}%t#| |%r@t| $|%t-|||d"| &|%}&d#}'t#| |'rvt| $|'t.| |_/g|_0dS)$ak Build a master problem to add cuts to. This method must called prior to calling methods like solve(). When the optional keyword include_scenarios is used, it overrides the list of names of scenarios (if any) to include on the master that were specified on the options object used to initialize this class. include_scenariosrrNF) normalizez:Number of scenarios included in Benders master problem: %srBr.T)Zcreate_variable_ids)activeZ descend_into)ra)Z safety_checksrz"Using maximum number of cut groupscSsg|]}gqSr?r?)rr=r?r?r@ msz9BendersAlgorithm.build_master_problem..cSsg|]}gqSr?r?)rir?r?r@roszfThe number of cut groups indicated by the multicut_level option was too large. Reducing from %s to %s.PYSP_BENDERS_ALPHA_SSCZ#PYSP_BENDERS_BUNDLE_ALPHA_SSC_INDEXPYSP_BENDERS_BUNDLE_ALPHA_SSCPYSP_BENDERS_CUT_BUNDLES_SSCZ!PYSP_BUNDLE_AVERAGE_ALPHA_CUT_SSCc3s|]}|VqdS)Nr?)rr) bundle_alphar?r@rsz8BendersAlgorithm.build_master_problem..)rwc3s|]}|VqdS)Nr?)rr)rr?r@rsgcss|] }|jVqdS)N)r)rr=r?r?r@rsPYSP_BENDERS_OBJECTIVE)rwZsensePYSP_BENDERS_CUTS_SSC)1rpopr0r3rr1r5ruobjective_senseZmake_compressedr4r8ryr2Z_scenario_instance_factoryZ%construct_instances_for_scenario_treeZlinkInInstancesr(set_scenarios_includedlist itertoolschainZcomponent_data_objectsr r r6ZconstraintNoderrUrMrr'r,rHrVrvr r7r setattrrsumrCrr rrr)(rrrr1r>Z firststagerZmaster_scenario_treeZmaster_rootnodeZmaster_firststageZmaster_secondstageZmaster_scenario_instancesrZ remove_sscZnum_first_stage_constraintsr=rarKrbZ cut_bundlesZcntZlen_cut_bundlesZnonempty_cut_bundlesZbundleZ alpha_varname master_alphaZalpha_bundles_index_nameZbundle_alpha_indexZalpha_bundles_nameZcut_bundles_list_nameZalpha_cut_constraint_nameZmaster_cost_exprZ normalizationZscenario_rootnodeZrootnode_cost_exprZscenario_leafnodeZleafnode_cost_exprZbenders_objective_namemaster_objectiveZcutlist_constraint_namer?)rr@build_master_problems$                                  z%BendersAlgorithm.build_master_problemc s|jdkrtd|jtks t|j||jj}|jj }|j}| }| dt |j | d}| d}| d} |jd} |sxtt|dD]v\} } x`| D]X} | |jkst|j| |j| }|| }| |j|tfd d D7} qW| | | 8} qWnxxn|jD]d}|j |jkr6q |j } |j| |j| }|| }| |j|tfd d D7} q W| |8} |tkr|td| dfn|td| dfdS) a Add the cut defined by the benders_cut object to the master problem. The optional keyword ignore_cut_bundles can be used generate the cut using the single master alpha cut variable rather than over the possibly many bundle cut groups. NzcThe master problem has not been constructed.Call the build_master_problem() method to construct it.MASTER_BLEND_VAR_rrrgrc3s&|]}|||VqdS)Nr?)rri)master_variablescenario_dualsrr?r@rsz+BendersAlgorithm.add_cut..c3s&|]}|||VqdS)Nr?)rri)rrrr?r@rs)rrrrr3rrHrr1rr5r7strr8r enumerategetattrrrrZ get_scenariorrr4rr)rrZignore_cut_bundlesr1rrr>Z benders_cutsrrZcut_expressionrZ cut_scenariosZ scenario_nameZ scenario_sscr=r?)rrrr@add_cutsd           zBendersAlgorithm.add_cutcsP|jdkrtd|j}|jj}|dt|jtfdd|j DS)NzcThe master problem has not been constructed.Call the build_master_problem() method to construct it.rc3s&|]}|js||jfVqdS)N)staler)rri)rr?r@r-sz7BendersAlgorithm.extract_master_xhat..) rrrr1r5r7rr8rr})rrr>r?)rr@extract_master_xhat#s   z$BendersAlgorithm.extract_master_xhatcCsx|jdkrtdd|d|d|dd}|dsb|jrb|jj|jfdd i|}n|jj|jf|}|S) NzcThe master problem has not been constructed.Call the build_master_problem() method to construct it.Frrr)Zload_solutionsteeZ keepfilesZsymbolic_solver_labelsrZ warmstartT)rrrrZwarm_start_capablesolve)rZ common_kwdsresultsr?r?r@ solve_master1s     zBendersAlgorithm.solve_masterc sd|krd}nt|d}d|kr6d}nt|d}|dd}t|dks`tt}j}j}jdkrt dj j }j j } dd } | tfd d jD} g} d } |rtd td| tddtddtd| |d}|d}|d}t_t_|tkrDtdntd_d_td_d_d}x,td|dD]}|dkrtjdkr|d|dt}}t|jdkrt d|jj t!j"krt#$dt%|jj&t%|jj t%|dj&f|j'(|t}|j)r||dks@t|j*dksPt|tkrbtdntd}|+|+njt*|}|d}t,|dr|j-dk r|j-t.k r|tkr||j-8}n ||j-7}n|rd}td|j|</}j0|dd\}t*|t*|t1fd d!| j2Dj|<j}|tkrXt3j4n t5j4}|tkr~t5j4n t3j4_|tkrj|kr|_nj|kr|_t6|jd"t6j_|r4t5|j74}t3|j74}td#||jjd ||||t|f8jd7_jd |krz|rvtd| td$PqzW|rtd| td%|tkrtdntd_9tjr|tkrt3j4_9nt5j4_9jS)&a Run the algorithm. If one or both of the keywords max_iterations and percent_gap are used, they will override the values on the options object used to initialize this class. Returns the objective value for the incumbent solution. rroutput_solver_logFrNzcThe master problem has not been constructed.Call the build_master_problem() method to construct it.cSsdtdd|D}tdd|D}x:|D]2\}}tdt|dt|d|d|q*WdS)Ncss|]}tt|dVqdS)rN)r0r)rxr?r?r@rqszCBendersAlgorithm.solve..print_dictionary..css|]}tt|dVqdS)rBN)r0r)rrr?r?r@rtsz{0:.print_dictionarycsg|]}|r|qSr?)Zis_variable_discrete)rri)r>r?r@rsz*BendersAlgorithm.solve..rr--z%6s %16s %16s %11s %30s)ZIterz Master BoundzBest IncumbentZGapzSolution Times [s]z'%6s %16s %16s %11s %10s %10s %10s %10s)r-r-r-r-ZMasterzSub MinzSub MaxZCummrrrinfz-infTrBgz/Solve failed for master; no solutions generatedzzMaster solve did not generate an optimal solution: Solver Status: %s Solver Termination Condition: %s Solution Status: %s gapzYWARNING: Solver interface does not report an optimality gap. Master bound may be invalid.)rc3s.|]&}|jjjkr|jj|jVqdS)N)r8rrrr)rr=) new_cut_inforr?r@rsz)BendersAlgorithm.solve..rz6%6d %16.4f %16.4f %11.3f%% %10.2f %10.2f %10.2f %10.2fz!Optimality gap threshold reached.z%Maximum number of iterations reached.):rrrrr0r3timerrrrrr1r5r{ryr7rrrrfloatrrrrr,rZfixrZsolutionZsolverZtermination_conditionrZoptimalloggerwarningrstatusZ solutionsZ load_fromZfixedrfreerVr rrrrr4rrGminabsZpyomo_solve_timerbound)rrrrr start_timerrrr1rZnum_discrete_firststageZproblem_statisticsZwidth_log_tablerZmaster_bundles_alpharZoutput_no_gap_warningrZstart_time_masterZresults_masterZstop_time_masterZcurrent_master_boundZ solution0Znew_xhatrZincumbent_objective_prevZbest_master_boundZ min_time_subZ max_time_subr?)r r>rr@rIs                                      zBendersAlgorithm.solve)N)F)r?F)F)rrr classmethodrrrrrrrrrrrrrrrrrrr __classcell__r?r?)rr@r{s. I K    Z LrcsTeZdZedddZfddZddZedd Zed d Z dd dZ Z S) BendersSolverNcCs|dkrt}t|S)N)rrr)rrr?r?r@r&szBendersSolver._declare_optionscs tt|||dS)N)rrrrset_options_to_default)r)rr?r@r,szBendersSolver.__init__cCs||_dS)N)rr)rr?r?r@r0sz$BendersSolver.set_options_to_defaultcCs|jS)N)r)rr?r?r@r3szBendersSolver.optionscCsdS)Nbendersr?)rr?r?r@r87szBendersSolver.nameFc Csbt||j"}|||j|d}WdQRXt}|j|_|j|_|j j |j i|_ |S)N)r) rrrrrr*r objectiverr1r5r8r)rsprrrrr?r?r@ _solve_impl;szBendersSolver._solve_impl)N)F) rrrrrrrpropertyrr8rrr?r?)rr@r$s    rcCsb|dkrt}t|t|t|dt|dt|dt|dt|dt|d|S)Nr disable_gcprofile tracebackroutput_scenario_tree_solution)rrrr%r)rr?r?r@runbenders_register_optionsJs"  r$c Cst}t|}|tdtdt}|j|dd}|j|||jd}|j}|`tdt||j rtd|j |j |j WdQRXtdtdt|dS) zT Construct a senario tree manager and solve it with the Benders solver. r-zcRunning Generalized Benders solver for stochastic programming problems (i.e., the L-shaped method).T)sparse)rrNz!Total execution time=%.2f secondsr)r r%rpryrZextract_user_options_to_dictrrrr#r1ZsnapshotSolutionFromScenariosZpprintSolutionZ pprintCosts)rrrrZbenders_optionsrrr?r?r@ runbendersbs4    r&c Cs\ddl}yt|tddd}Wn$tk r@}z|jSd}~XYnXtt|d|j|j|j dS)Nrr&zSOptimize a stochastic program using Generalized Benders (i.e., the L-shaped method))progrz runbenders: )Z error_labelr Z profile_countr") Z pyomo.environr!r$ SystemExitcoder"r&r r!r")rpyomorZ_excr?r?r@mains r+r__main__)N)N)Zossysloggingr rZpyomo.common.collectionsrZ pyomo.optrrrZ pyomo.corerrrr r r r r rrrrZpyomo.core.base.constraintrZpyomo.core.beta.list_objectsrZ!pyomo.pysp.util.configured_objectrZpyomo.pysp.util.configrrrrrrrrrrrr Zpyomo.pysp.util.miscr!r"Zpyomo.pysp.scenariotree.managerr#r$r%Z&pyomo.pysp.scenariotree.manager_solverr&Zpyomo.pysp.phutilsr'Z pyomo.pysp.efr(Zpyomo.pysp.solvers.spsolverr)r*r+Z six.movesr,pathabspath__file__rreplace getLoggerrrrArDrLrNror~rrobjectrrrr$r&r+Zregister_solverrZ pyomo.pyspr*exitr?r?r?r@s` 8   8          <%0& ) #