B @`s@sddlZddlmmZddlmZddlmZm Z ddl m Z ddl m Z ddlmZddlmZddlmmmZddlmZmZmZdd lmZmZmZmZm 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,m-Z-dd l.m/Z/m0Z0m1Z1dd l2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;mZ>dd l?m@Z@mAZAddlBmCZDeEdZFiZGejHdddGdddeZIejHdddGdddeIZJdS)N) deprecated) ComponentMap ComponentSet) is_debug_set)unique_component_name) ZeroConstant)ActiveComponent)TransformationTransformationFactory Reference)Block BooleanVar Connector ConstraintParamSetSetOfSuffixVar ExpressionSortComponentsTraversalStrategyAnyRangeSetRealsvalueNonNegativeIntegersLogicalConstraint)Disjunct Disjunction GDP_Error) #_warn_for_active_logical_constraint#clone_without_expression_components target_list is_child_ofget_src_disjunctionget_src_constraintget_transformed_constraintsget_src_disjunct_warn_for_active_disjunction_warn_for_active_disjunct)wraps) iteritemsiterkeys)refzpyomo.gdp.hullzgdp.hullz:Relax disjunctive model by forming the hull reformulation.)docc seZdZdZedZedejde dddedejd e d d d gd d dedejdej ddedejde dddfddZ ddZddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)ZdNd*d+Zd,d-Zd.d/Zd0d1Zd2d3Zd4d5Zd6d7Zd8d9Zd:d;Zdd?Z"e!e#d@dAZ#e!e$dBdCZ$e!e%dDdEZ%dFdGZ&dHdIZ'dJdKZ(dLdMZ)Z*S)OHull_ReformulationaRelax disjunctive model by forming the hull reformulation. Relaxes a disjunctive model into an algebraic model by forming the hull reformulation of each disjunction. This transformation accepts the following keyword arguments: Parameters ---------- perspective_function : str The perspective function used for the disaggregated variables. Must be one of 'FurmanSawayaGrossmann' (default), 'LeeGrossmann', or 'GrossmannLee' EPS : float The value to use for epsilon [default: 1e-4] targets : (block, disjunction, or list of those types) The targets to transform. This can be a block, disjunction, or a list of blocks and Disjunctions [default: the instance] The transformation will create a new Block with a unique name beginning "_pyomo_gdp_hull_reformulation". That Block will contain an indexed Block named "relaxedDisjuncts", which will hold the relaxed disjuncts. This block is indexed by an integer indicating the order in which the disjuncts were relaxed. Each block has a dictionary "_constraintMap": 'srcConstraints': ComponentMap(: ), 'transformedConstraints':ComponentMap(: , : [] ) It will have a dictionary "_disaggregatedVarMap: 'srcVar': ComponentMap(:), 'disaggregatedVar': ComponentMap(:) And, last, it will have a ComponentMap "_bigMConstraintMap": : All transformed Disjuncts will have a pointer to the block their transformed constraints are on, and all transformed Disjunctions will have a pointer to the corresponding OR or XOR constraint. The _pyomo_gdp_hull_reformulation block will have a ComponentMap "_disaggregationConstraintMap": :ComponentMap(: ) zgdp.hulltargetsNz.target or list of targets that will be relaxeda This specifies the target or list of targets to relax as either a component or a list of components. If None (default), the entire model is transformed. Note that if the transformation is done out of place, the list of targets should be attached to the model before it is cloned, and the list will specify the targets on the cloned instance.)defaultdomain descriptionr/zperspective functionFurmanSawayaGrossmann LeeGrossmann GrossmannLeez5perspective function used for variable disaggregationan The perspective function used for variable disaggregation "LeeGrossmann" is the original NL convex hull from Lee & Grossmann (2000) [1]_, which substitutes nonlinear constraints h_ik(x) <= 0 with x_k = sum( nu_ik ) y_ik * h_ik( nu_ik/y_ik ) <= 0 "GrossmannLee" is an updated formulation from Grossmann & Lee (2003) [2]_, which avoids divide-by-0 errors by using: x_k = sum( nu_ik ) (y_ik + eps) * h_ik( nu_ik/(y_ik + eps) ) <= 0 "FurmanSawayaGrossmann" (default) is an improved relaxation [3]_ that is exact at 0 and 1 while avoiding numerical issues from the Lee & Grossmann formulation by using: x_k = sum( nu_ik ) ((1-eps)*y_ik + eps) * h_ik( nu_ik/((1-eps)*y_ik + eps) ) - eps * h_ki(0) * ( 1-y_ik ) <= 0 References ---------- .. [1] Lee, S., & Grossmann, I. E. (2000). New algorithms for nonlinear generalized disjunctive programming. Computers and Chemical Engineering, 24, 2125-2141 .. [2] Grossmann, I. E., & Lee, S. (2003). Generalized disjunctive programming: Nonlinear convex hull relaxation and algorithms. Computational Optimization and Applications, 26, 83-100. .. [3] Furman, K., Sawaya, N., and Grossmann, I. A computationally useful algebraic representation of nonlinear disjunctive convex sets using the perspective function. Optimization Online (2016). http://www.optimization-online.org/DB_HTML/2016/07/5544.html. EPSg-C6?z,Epsilon value to use in perspective function)r2r3r4assume_fixed_vars_permanentFzBoolean indicating whether or not to transform so that the the transformed model will still be valid when fixed Vars are unfixed.aq If True, the transformation will not disaggregate fixed variables. This means that if a fixed variable is unfixed after transformation, the transformed model is no longer valid. By default, the transformation will disagregate fixed variables so that any later fixing and unfixing will be valid in the transformed model. cs`tt|t|jtdtdtdtdt dt dt dt dt dt|jt|jt|jt|ji|_d|_dS)NF)superr0__init__r_transform_constraintrr rrrrrrrrr)rr*r _transform_block_on_disjunctr"_warn_for_active_logical_statementhandlers_generate_debug_messages)self) __class__:/tmp/pip-unpacked-wheel-bi3529v6/pyomo/gdp/plugins/hull.pyr;s  zHull_Reformulation.__init__cCsZ|d}t|tkrVx>t|D]2\}}||dkrDt|||<q |||q WdS)N LocalVars) componenttyperr,getrupdate)rAblocklocal_var_dict localVarsZdisjZvar_listrCrCrD_add_local_varss   z"Hull_Reformulation._add_local_varscCsPx(|jttdtjdD]}|||qWx |dk rJ||||}q,W|S)NT) descend_intoactivesort)component_data_objectsr r deterministicrM parent_block)rArJrKbrCrCrD_get_local_var_suffixess    z*Hull_Reformulation._get_local_var_suffixescKs*trtz|j|f|WdtXdS)N) NAME_BUFFERAssertionError_apply_to_implclear)rAinstancekwdsrCrCrD _apply_toszHull_Reformulation._apply_tocKs||di|_|j|tt|_|jj}|dkr@|f}i}x|D]}t|||dsrt d|j |j fqJ|j t kr| r||q|||qJ|j ttfkr| r||q||qJt d|j t|fqJWdS)Noptions)parentchild knownBlocksz0Target '%s' is not a component on instance '%s'!zbTarget '%s' was not a Block, Disjunct, or Disjunction. It was of type %s and can't be transformed.)CONFIGpop_config set_valuerloggerr@r1r$r namectyper is_indexed_transform_disjunction_transform_disjunctionDataindexr r_transform_block_transform_blockDatarG)rArZr[r1r`trCrCrDrXs0       z!Hull_Reformulation._apply_to_implcCsPt|d}t}|||tt|_tdddgd|_ttt|_ t |_ |S)NZ_pyomo_gdp_hull_reformulationlbubeq) initialize) rr add_componentrrelaxedDisjunctsrlbubrrdisaggregationConstraintsr_disaggregationConstraintMap)rArZZtransBlockName transBlockrCrCrD_add_transformation_block s  z,Hull_Reformulation._add_transformation_blockcCs(x"tt|D]}|||qWdS)N)sortedr-rm)rAobjirCrCrDrlsz#Hull_Reformulation._transform_blockcCs4x.|jtdtjttftjdD]}||qWdS)NT)rOrPrNZ descent_order) component_objectsrrrRr rrZ PostfixDFSri)rAr{ disjunctionrCrCrDrm#sz'Hull_Reformulation._transform_blockDatacCsZt|tst|jdk r |St|}|t||jdt dd|t ||_|S)NT)fully_qualified name_bufferZ_xor) isinstancerrW_algebraic_constraintr index_setrsrgetnamerV weakref_ref)rAr~rxZorCrCrCrD_add_xor_constraint-s    z&Hull_Reformulation._add_xor_constraintcCsp|js dS|jdk r"|}n||}|||}x&tt|D]}|||||qJW|dS)N) rOrrSryrrzr-rj deactivate)rAr{rxZ xorConstraintr|rCrCrDriFs  z)Hull_Reformulation._transform_disjunctionc s2|js dS|jstd|j|dkrT|jdk rF|}n||}|}|||}|j }|j }t |j dkrtd|j dtdt}g} tt} |jj } x|j D]|} t} | <x\| jtdtjtdD]D}x>tj|j| dD]*| |kr| |qWqW|| | } qWg}t}x| D]̉fdd D}t |d kr|jrt d j dtd|nx| !|ddk r| |dkr|!|d}|dk r||dng||d<n |n |qPWd}x2|j D](} || j"7}|#| |||!| gq,W|||d ft$|||_xt%|D]\}d}x:|j D]0} | j&dkrq| &j'd }||7}qW|||f|k|!dk r|||f||<nt}|<|||f||<qW|(dS) NzVCannot do hull reformulation for Disjunction '%s' with OR constraint. Must be an XOR!rzIDisjunction '%s' is empty. This is likely indicative of a modeling error.T)rr)rOrPrN)Z include_fixedcsg|]}|kr|qSrCrC).0d)varvarsByDisjunctrCrD szAHull_Reformulation._transform_disjunctionData..zGAssuming '%s' is not a local var since it isused in multiple disjuncts.disaggregatedVar))rOxorr rfparent_componentrrSryrrvrwlen disjunctsrrVrrrcr9rQrrrRr EXPRidentify_variablesbodyaddappendrUr@redebugrH indicator_var_transform_disjunctr enumerate_transformation_block_disaggregatedVarMapr)rAr{rkrxrZ orConstraintZdisaggregationConstraintZdisaggregationConstraintMapZ varOrder_setZvarOrderZlocalVarsByDisjunctZinclude_fixed_varsdisjunctZ disjunctVarsZconsvarSetrLrZlocalVars_thisDisjunctZor_exprr|ZdisaggregatedExprrZthismaprC)rrrDrj_s                    z-Hull_Reformulation._transform_disjunctionDatacCs|jsT|jr:t|jdkr"dStd|jt|jf|jdkrTtd|jf|jdk rltd|j|j}|t|}t |_ t |_ t t d|_ t t d|_t |_t||_t||_d}|}x |dk r|jtkrP|}qW|dk r2|||j|dkr(g|j|<|j|}x|D]} | j} | j} | dks`| dkrntd| jtttd| td| f| jd} t|j | jd t d } |j !| | |dk r|"| | |jd | <| |jd | <t#|j$}|!| d || r|%d|j| | k| r4|%d| |j| k||j| <q:Wx|D]} | j} | j} | dksn| dkr|td| jt| dkr| &dt| dkr| 'd| |jd | <| |jd | <t|| jd t d d }t#|j$}|!||| r|%d|j| | k| r.|%d| |j| k||j| <qJWt(ddt)|jd D}t(ddt)|jd D}|*dd|D|+|||||,dS)Nrz\The disjunct '%s' is deactivated, but the indicator_var is fixed to %s. This makes no sense.zThe disjunct '%s' is deactivated, but the indicator_var is not fixed and the disjunct does not appear to have been relaxed. This makes no sense. (If the intent is to deactivate the disjunct, fix its indicator_var to 0.)zThe disjunct '%s' has been transformed, but a disjunction it appears in has not. Putting the same disjunct in multiple disjunctions is not supported.)srcConstraintstransformedConstraints)srcVarrzqVariables that appear in disjuncts must be bounded in order to use the hull transformation! Missing bound for %s.)ZwithinZboundsrrF)rrrrZ_boundsrorpcss|]\}}t||fVqdS)N)id)rvnewVrCrCrD sz9Hull_Reformulation._transform_disjunct..css|]\}}t|tfVqdS)N)rr)rrrrCrCrDrscss|]}t|tfVqdS)N)rr)rrrCrCrDrs)-rOrZis_fixedrr rfrrtrr localVarReferencesZdisaggregatedVarsr_constraintMapr_bigMConstraintMaprZ _srcDisjunctrSrgr_add_local_var_suffixrErHrorprrminmaxrrrVrsrrrurZsetlbZsetubdictr,rI_transform_block_componentsZ$_deactivate_without_fixing_indicator)rAr{rxrrLrtrelaxationBlockZ local_var_setZparent_disjunctrrorprZdisaggregatedVarNameZbigmConstraintZconNamevar_substitute_mapzero_substitute_maprCrCrDrs                                z&Hull_Reformulation._transform_disjunctc Cs|}|j}x8|jttddD]$}|t||jdtdt |q W| }x>|j t t jtdD](} | jdkrtqd|  } || |qdWxP|jdddD]>} |j| jd} | s| dkrtd| jq| | |||qWdS)N)rNrOT)rr)rPrNF)rOrNzNo hull transformation handler registered for modeling components of type %s. If your disjuncts contain non-GDP Pyomo components that require transformation, please transform them first.)rrr}rr rsrrrVr rSrQrrrRZalgebraic_constraint_transfer_var_referencesr?rHrgr ) rArJrrr disjunctBlockZ varRefBlockrZdestinationBlockr{rxhandlerrCrCrDrs0     z.Hull_Reformulation._transform_block_componentscCsD|j}x8t|jD]*\}}|t|}t|_|j|jqWdS)N)rtr,rr rZtransfer_attributes_from)rAZ fromBlockZtoBlockZ disjunctListidxrZnewblockrCrCrDrs  z+Hull_Reformulation._transfer_var_referencescCst||tdS)N)r)rV)rAr~rrrrCrCrDr)sz/Hull_Reformulation._warn_for_active_disjunctioncCst||tdS)N)r*rV)rAZ innerdisjunctZ outerdisjunctrrrCrCrDr*sz,Hull_Reformulation._warn_for_active_disjunctcCst||tdS)N)r!rV)rAZlogical_statmentrrrrCrCrDr>sz5Hull_Reformulation._warn_for_active_logical_statementcCs.x(tt|D]}||||||qWdS)N)rzr-r)rArJrrrr|rCrCrDr=s z/Hull_Reformulation._transform_block_on_disjunctcs|}|}|jd}|j}t||jdtd} |rNt| |j } n t|j } | | | |rx| |d|<||d| <xHt t |D]6} || } | jsq| jdk} |jj|jj}| r|dkrt| j|d}|j| r|d kr&t| jtfd d t|Dd}|}n|d krdt| jtfd d t|Dd}|}n^|dkrt| jtfdd t|Dd}d||d}ntdnt| j|d}| jr| r|| jk}nptt|}t|dkrF| jsF|dd|dg|d| <| |d|d<q|d|| jk}|r| | df|| | dfg|d| <| |d| | df<q| d|| dg|d| <| |d| d<q| jdk r|j!r| jdtd}t"#d|| r|| jk}n|d|| jk}|rz| | df|| | dfg|d| <| |d| | df<n.| d|| dg|d| <| |d| d<| j$dk r|j!r| jdtd}t"#d|| r|| j$k}n|d|| j$k}|rv| | df||d%| }|dk rJ|&| | dfn| | dfg|d| <| |d| | df<q| d||d%| }|dk r|&| dn| dg|d| <| |d| d<qW|'dS)NrT)rrrr)rrr5) substituter6c3s|]\}}||fVqdS)NrC)rrsubs)yrCrDr,sz;Hull_Reformulation._transform_constraint..r7c3s"|]\}}||fVqdS)NrC)rrr)r8rrCrDr4sc3s*|]"\}}||dfVqdS)rNrC)rrr)r8rrCrDr<srzUnknown NL Hull moderrqz'GDP(Hull): Transforming constraint '%s'rorp)(rrSrrrrrVrhrrrursrzr-rOrZpolynomial_degreercr8Zperspective_functionr"rrr, RuntimeErrorZequalitylowerlistrrrZfixrr@rerupperrHrr)rAr{rrrrrxZvarMapZ constraintMaprfZ newConstraintr|cNLmodeZh_0Zsub_exprexprZ newConsExprr_nameZ transformedrC)r8rrDr<s               &              z(Hull_Reformulation._transform_constraintcCsP|d}|dkr"ttjd|_n*|jtkr0dStd|jdtd|jfdS)NrE) directionz\A component called 'LocalVars' is declared on Disjunct %s, but it is of type %s, not Suffix.T)rr)rFrZLOCALrErgr rrV)rArZ localSuffixrCrCrDrs  z(Hull_Reformulation._add_local_var_suffixcCst|S)N)r()rArxrCrCrDr(sz#Hull_Reformulation.get_src_disjunctcCst|S)N)r%)rAZxor_constraintrCrCrDr%sz&Hull_Reformulation.get_src_disjunctioncCst|S)N)r&)rAZtransformedConstraintrCrCrDr&sz%Hull_Reformulation.get_src_constraintcCst|S)N)r')rAZ srcConstraintrCrCrDr'sz.Hull_Reformulation.get_transformed_constraintscCsX|jdkrtd|j|}y|jd|Std|j|jfYnXdS)a\ Returns the disaggregated variable corresponding to the Var v and the Disjunct disjunct. If v is a local variable, this method will return v. Parameters ---------- v: a Var which appears in a constraint in a transformed Disjunct disjunct: a transformed Disjunct in which v appears Nz&Disjunct '%s' has not been transformedrzDIt does not appear '%s' is a variable which appears in disjunct '%s')rr rfrreerror)rArrrxrCrCrDget_disaggregated_vars  z(Hull_Reformulation.get_disaggregated_varcCs>|}y|jd|Std|jYnXdS)a Returns the original model variable to which disaggregated_var corresponds. Parameters ---------- disaggregated_var: a Var which was created by the hull transformation as a disaggregated variable (and so appears on a transformation block of some Disjunct) rz3'%s' does not appear to be a disaggregated variableN)rSrrerrf)rAZdisaggregated_varrxrCrCrD get_src_vars   zHull_Reformulation.get_src_varcCstx|jD]}|j}|dk rPqW|dkr6td|jy|j||Std|j|jfYnXdS)a Returns the disaggregation (re-aggregation?) constraint (which links the disaggregated variables to their original) corresponding to original_var and the transformation of disjunction. Parameters ---------- original_var: a Var which was disaggregated in the transformation of Disjunction disjunction disjunction: a transformed Disjunction containing original_var NzZDisjunction '%s' has not been properly transformed: None of its disjuncts are transformed.zTIt doesn't appear that '%s' is a variable that was disaggregated by Disjunction '%s')rrr rfrSrwrer)rAZ original_varr~rrxrCrCrDget_disaggregation_constraints    z0Hull_Reformulation.get_disaggregation_constraintcCs:|}y |j|Std|jYnXdS)a Returns the IndexedConstraint which sets a disaggregated variable to be within its bounds when its Disjunct is active and to be 0 otherwise. (It is always an IndexedConstraint because each bound becomes a separate constraint.) Parameters ---------- v: a Var which was created by the hull transformation as a disaggregated variable (and so appears on a transformation block of some Disjunct) zxEither '%s' is not a disaggregated variable, or the disjunction that disaggregates it has not been properly transformed.N)rSrrerrf)rArrxrCrCrDget_var_bounds_constraints   z,Hull_Reformulation.get_var_bounds_constraint)N)+__name__ __module__ __qualname____doc__cfgZ ConfigBlockraZdeclareZ ConfigValuer#ZInZ PositiveFloatboolr;rMrUr\rXryrlrmrrirjrrrr)r*r>r=r<rr+r(r%r&r'rrrr __classcell__rCrC)rBrDr0*sh6    *          06  3r0z gdp.chullzBDeprecated name for the hull reformulation. Please use 'gdp.hull'.cs*eZdZeddddfddZZS)_Deprecated_Name_HullzOThe 'gdp.chull' name is deprecated. Please use the more apt 'gdp.hull' instead.z pyomo.gdpz5.7)reversioncstt|dS)N)r:rr;)rA)rBrCrDr;8sz_Deprecated_Name_Hull.__init__)rrrrr;rrCrC)rBrDr4sr)KloggingZpyomo.common.configcommonconfigrZ pyomo.commonrZpyomo.common.collectionsrrZpyomo.common.logrZpyomo.common.modelingrZpyomo.core.expr.numvaluerZpyomo.core.base.componentrZpyomo.core.expr.currentcorercurrentrZpyomo.core.baser r r Z pyomo.corer r rrrrrrrrrrrrrrrrZ pyomo.gdprrr Zpyomo.gdp.utilr!r"r#r$r%r&r'r(r)r* functoolsr+sixr,r-weakrefr.r getLoggerrerVregisterr0rrCrCrCrD sB     P0