B _~@sXddlZddlZddlZddlZddlZyddlmZWn ek rXddlmZYnXddl m Z m Z m Z ddl mZmZmZmZmZmZmZmZmZmZmZmZddlmZddlmZddlmZddl m!Z!m"Z"m#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/m0Z0dd l1m2Z2m3Z3m4Z4dd l5m6Z6dd l7m8Z8dd l9m:Z:ddl;mZ>ddl?m@Z@ejABeCZDeDEddEddeFdZGdZHddZIddZJddZKddZLddZMdd ZNd!d"ZOd#d$ZPGd%d&d&eQZRGd'd(d(eZSGd)d*d*eXd1eTeYd2krTddlZZ[e\eWdS)5N) OrderedDict) SolverFactoryTerminationCondition undefined) valueminimizeSet Objective SOSConstraint ConstraintVarRangeSet ExpressionSuffixRealsParam)_GeneralConstraintData)XConstraintList)PySPConfiguredObject) PySPConfigValuePySPConfigBlocksafe_register_common_optionsafe_register_unique_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-d4p3hk07/pyomo/pysp/solvers/benders.py"EXTERNAL_deactivate_rootnode_costsRs  rBcCs|t|jjdkst||jjks$t|j}t|jd|jd}|j d|j  ||j dk rxd|j j |j <dS)Nr/rr0T)r1r2r3r4r5r6instancer8_cost_variabler7r9r:r;r<)r=r>r?Z nodecost_varr@r@rA EXTERNAL_activate_rootnode_costs\s  rFcCspt|jjdkst||jjks$t|jd}||jdk rl|jj |j }x| D]}| |qZWdS)Nr/ PYSP_BENDERS_FIX_XHAT_CONSTRAINT) r1r2r3r4r5r7r8activater;Zconstraints_added_listr9valuesappend)r=r>fix_constraintpreprocess_constraints_listconstraint_datar@r@rA!EXTERNAL_activate_fix_constraintshs rNcCspt|jjdkst||jjks$t|jd}||jdk rl|jj |j }x| D]}| |qZWdS)Nr/rG) r1r2r3r4r5r7r8 deactivater;Zconstraints_removed_listr9rIrJ)r=r>rKrLrMr@r@rA#EXTERNAL_deactivate_fix_constraintsus rPcCs|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) Nr0_instance_cost_expression_old_remove_dual_at_benders_cleanuprrCdualPYSP_BENDERS_CACHED_DOMAINSPYSP_BENDERS_FIX_XHAT_INDEXPYSP_BENDERS_FIX_XHAT_VALUErGT)r7 node_listr9hasattrr4Z del_component_instance_cost_expressionr:rQrRr2contains_bundlesbundlesscenario_names_bundle_binding_instance_map_ScenarioTreeSymbolMapbySymbolrTdomainsetlbsetubr;r<)r=r>rDnodecost_term_namefoundscenario_bundlebundle_instancescenario_bySymbolcached_domains variable_idr` varboundsvardatanodal_index_set_namefix_param_namefix_constraint_namer@r@rAEXTERNAL_cleanup_from_benderssR            rpcst|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/grrCr0) initializerQrST) 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.rTrU)r9ZorderedrqrV)ZmutablerqrGcs||dkS)Ngr@)mrj) fix_paramrhr@rAfix_rule5sz1EXTERNAL_initialize_for_benders..fix_rule)Zrule)5r1r2r3r4r5r6Z _leaf_nodestager7rWr8rEr9rX add_componentrrYexprrQr:rZr[r\r]rRrZIMPORTrS isinstanceZimport_enabledprintZ set_directionZ IMPORT_EXPORT TypeErrorr^r_rT _variable_idsZis_expression_typeZboundsr`rrJrarbrsorted_standard_variable_idsrr rOrBrN)r=r>r?Z leafstagerDZ cost_termsrcZ stagecost_varrdrerfrgrirjrlZ tight_boundsr`rkrmZnodal_index_setrnrorur@)rtrhrAEXTERNAL_initialize_for_benderss                  rc Cst|jjdkst||jjks$t|j}d}||}|||jd}|jdk r|jj |j }x| D]}| |qpWdS)Nr/rVrG) r1r2r3r4r5r7r8Z store_valuesr;Zconstraints_updated_listr9rIrJ) r=r> fix_valuesrDrnrtrKrLrMr@r@rAEXTERNAL_update_fix_constraintsBs   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/rrCSSCdualsrGzNo 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.)r1r2r3r4r5rZr[r9r\r]rS probabilityr7r6Z _stage_costsZ leaf_nodervr8 RuntimeErrorr~) r=r>Z dual_suffixZsum_probability_bundlererfr?Zscenario_resultsrZbenders_fix_constraintrjr@r@rAEXTERNAL_collect_cut_dataTs4        rc@seZdZdZddZdS)BendersOptimalityCut)xhatsscrcCs||_||_||_dS)N)rrr)selfrrrr@r@rA__init__{szBendersOptimalityCut.__init__N)__name__ __module__ __qualname__ __slots__rr@r@r@rArysrcseZdZed*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_levelrCzThe 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.actionrJ)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_labelrintrr boolrrr!r'register_options)clsoptionsr@r@rA_declare_optionss z!BendersAlgorithm._declare_optionscCs|S)Nr@)rr@r@rA __enter__KszBendersAlgorithm.__enter__cGs |dS)N)close)rargsr@r@rA__exit__NszBendersAlgorithm.__exit__cCs<|jdk r||jdk r&|jd|_d|_d|_dS)N)_managercleanup_subproblems_manager_solverr_master_solver)rr@r@rArQs   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_constraintssuperrrryr%r{Z initialized ValueErrorr1r2r3r'_optionsr get_optiontypetupleZ set_optionsjoinrZmipgap)rr=rkwdsr) __class__r@rArZsN     zBendersAlgorithm.__init__cCs|jjdttjdddS)NrBT)invocation_type oneway_call)rinvoke_functionthisfiler$ PerScenario)rr@r@rAdeactivate_rootnode_costss z*BendersAlgorithm.deactivate_rootnode_costscCs|jjdttjdddS)NrFT)rr)rrrr$r)rr@r@rAactivate_rootnode_costss z(BendersAlgorithm.activate_rootnode_costscCs|jjdttjdddS)NrNT)rr)rrrr$r)rr@r@rAactivate_fix_constraintss z)BendersAlgorithm.activate_fix_constraintscCs|jjdttjdddS)NrPT)rr)rrrr$r)rr@r@rAdeactivate_fix_constraintss z+BendersAlgorithm.deactivate_fix_constraintscCs|jjdttj|fdddS)NrT)rZ function_argsr)rrrr$r)rrr@r@rAupdate_fix_constraintss z'BendersAlgorithm.update_fix_constraintsFcCs|jjdttj|dS)Nr)r async_call)rrrr$r)rrr@r@rAcollect_cut_datas z!BendersAlgorithm.collect_cut_datacCs,|drtd|jjdttjdddS)Nrz$Initializing subproblems for bendersrT)rr)rrzrrrr$r)rr@r@rAinitialize_subproblemss z'BendersAlgorithm.initialize_subproblemscCs,|drtd|jjdttjdddS)Nrz#Cleaning up subproblems for bendersrpT)rr)rrzrrrr$r)rr@r@rArs 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@).0r9)cut_datar@rA sz0BendersAlgorithm.generate_cut..c3s|]}||dfVqdS)rNr@)rr9)rr@rArsN)rrZsolve_subproblemsrrdict)rrZ update_stagesreturn_solve_results solve_results benders_cutr@)rrA 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: %srCr/T)Zcreate_variable_ids)activeZ descend_into)rD)Z safety_checksrz"Using maximum number of cut groupscSsg|]}gqSr@r@)rr>r@r@rA rsz9BendersAlgorithm.build_master_problem..cSsg|]}gqSr@r@)rir@r@rArtszfThe 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@rArsz8BendersAlgorithm.build_master_problem..)rxc3s|]}|VqdS)Nr@)rr)rr@rArsgcss|] }|jVqdS)N)r)rr>r@r@rArsPYSP_BENDERS_OBJECTIVE)rxZsensePYSP_BENDERS_CUTS_SSC)1rpopr1r4rr2r6rvobjective_senseZmake_compressedr5r9rzr3Z_scenario_instance_factoryZ%construct_instances_for_scenario_treeZlinkInInstancesr)set_scenarios_includedlist itertoolschainZcomponent_data_objectsr r r7ZconstraintNoderrWrOrr(r-rJrXrwr r8r setattrrsumrErr rrr)(rrrr2r?Z firststagerZmaster_scenario_treeZmaster_rootnodeZmaster_firststageZmaster_secondstageZmaster_scenario_instancesrZ remove_sscZnum_first_stage_constraintsr>rDrMrcZ 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@)rrAbuild_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@)rrj)master_variablescenario_dualsrr@rAr sz+BendersAlgorithm.add_cut..c3s&|]}|||VqdS)Nr@)rrj)rrrr@rArs)rrrrr4rrJrr2rr6r8strr9r enumerategetattrrrrZ get_scenariorrr5rr)rrZignore_cut_bundlesr2rrr?Z benders_cutsrrZcut_expressionrZ cut_scenariosZ scenario_nameZ scenario_sscr>r@)rrrrAadd_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)rrj)rr@rAr2sz7BendersAlgorithm.extract_master_xhat..) rrrr2r6r8rr9rr~)rrr?r@)rrAextract_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@rA solve_master6s     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)r1r)rxr@r@rArvszCBendersAlgorithm.solve..print_dictionary..css|]}tt|dVqdS)rCN)r1r)rrr@r@rArysz{0:.print_dictionarycsg|]}|r|qSr@)Zis_variable_discrete)rrj)r?r@rArsz*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-infTrCgz/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)r9rrrr)rr>) new_cut_inforr@rArsz)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.):rrrrr1r4timerrrrrr2r6r|rzr8rrrrfloatrrrrr-rZfixrZsolutionZsolverZtermination_conditionrZoptimalloggerwarningrstatusZ solutionsZ load_fromZfixedrfreerXr rrrrr5rrIminabsZpyomo_solve_timerbound)rrrrr start_timerrrr2r Znum_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?rrArNs                                      zBendersAlgorithm.solve)N)F)r@F)F)rrr classmethodrrrrrrrrrrrrrrrrrrr __classcell__r@r@)rrArs. I K    Z LrcsTeZdZedddZfddZddZedd Zed d Z dd dZ Z S) BendersSolverNcCs|dkrt}t|S)N)rrr)rrr@r@rAr+szBendersSolver._declare_optionscs tt|||dS)N)rrrrset_options_to_default)r)rr@rAr1szBendersSolver.__init__cCs||_dS)N)rr)rr@r@rAr5sz$BendersSolver.set_options_to_defaultcCs|jS)N)r)rr@r@rAr8szBendersSolver.optionscCsdS)Nbendersr@)rr@r@rAr9<szBendersSolver.nameFc Csbt||j"}|||j|d}WdQRXt}|j|_|j|_|j j |j i|_ |S)N)r) rrrrrr+r objectiverr2r6r9r)rsprrrrr@r@rA _solve_impl@szBendersSolver._solve_impl)N)F) rrrrrrrpropertyrr9rrr@r@)rrAr)s    rcCsb|dkrt}t|t|t|dt|dt|dt|dt|dt|d|S)Nr disable_gcprofile tracebackroutput_scenario_tree_solution)rrrr&r)rr@r@rArunbenders_register_optionsOs"  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)rr&rqrzrZextract_user_options_to_dictrrrr$r2ZsnapshotSolutionFromScenariosZpprintSolutionZ pprintCosts)rrrrZbenders_optionsrrr@r@rA runbendersgs4    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@rAmains r,r__main__)N)N)]ossysloggingrr collectionsr ImportErrorZ ordereddictZ pyomo.optrrrZ pyomo.corerrrr r r r r rrrrZpyomo.core.base.constraintrZpyomo.core.beta.list_objectsrZ!pyomo.pysp.util.configured_objectrZpyomo.pysp.util.configrrrrrrrrrrrr r!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 getLoggerrrrBrFrNrPrprrrobjectrrrr%r'r,Zregister_solverrZ pyomo.pyspr+exitr@r@r@rAsf8   <          <%0& ) #