B u `@sddlZddlmmZddlmZddlmZm Z ddl m Z ddl m Z ddlmZddlmmmZddlmZmZmZddlmZmZmZmZmZmZm 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-m.Z.m/Z/dd l0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:dd l;mZ>m?Z?dd l@mAZBeCdZDiZEejFdddGdddeZGejFdddGdddeGZHdS)N) deprecated) ComponentMap ComponentSet)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)r1r2r3assume_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. csZtt|t|jtdtdtdtdt dt dt dt dt dt|jt|jt|jt|ji|_dS)NF)superr/__init__r_transform_constraintrr r rrrrrrrr(rr)r _transform_block_on_disjunctr"_warn_for_active_logical_statementhandlers)self) __class__:/tmp/pip-unpacked-wheel-n62dbgi3/pyomo/gdp/plugins/hull.pyr:szHull_Reformulation.__init__cCsZ|d}t|tkrVx>t|D]2\}}||dkrDt|||<q |||q WdS)N LocalVars) componenttyperr+getrupdate)r?blocklocal_var_dict localVarsZdisjZvar_listrArArB_add_local_varss   z"Hull_Reformulation._add_local_varscCsPx(|jttdtjdD]}|||qWx |dk rJ||||}q,W|S)NT) descend_intoactivesort)component_data_objectsr r deterministicrK parent_block)r?rHrIbrArArB_get_local_var_suffixess    z*Hull_Reformulation._get_local_var_suffixescKs*trtz|j|f|WdtXdS)N) NAME_BUFFERAssertionError_apply_to_implclear)r?instancekwdsrArArB _apply_toszHull_Reformulation._apply_tocKs||di|_|j||jj}|dkr6|f}i}x|D]}t|||dshtd|j|jfq@|jt kr| r| |q| || q@|jttfkr| r||q||q@td|jt|fq@WdS)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_valuer0r#rnamectyper is_indexed_transform_disjunction_transform_disjunctionDataindexr r_transform_block_transform_blockDatarE)r?rXrYr0r^trArArBrVs.      z!Hull_Reformulation._apply_to_implcCsPt|d}t}|||tt|_tdddgd|_ttt|_ t |_ |S)NZ_pyomo_gdp_hull_reformulationlbubeq) initialize) rr add_componentrrelaxedDisjunctsrlbubrrdisaggregationConstraintsr_disaggregationConstraintMap)r?rXZtransBlockName transBlockrArArB_add_transformation_blocks  z,Hull_Reformulation._add_transformation_blockcCs(x"tt|D]}|||qWdS)N)sortedr,rj)r?objirArArBrisz#Hull_Reformulation._transform_blockcCs4x.|jtdtjttftjdD]}||qWdS)NT)rMrNrLZ descent_order) component_objectsrrrPr rrZ PostfixDFSrf)r?rx disjunctionrArArBrj sz'Hull_Reformulation._transform_blockDatacCsZt|tst|jdk r |St|}|t||jdt dd|t ||_|S)NT)fully_qualified name_bufferZ_xor) isinstancerrU_algebraic_constraintr index_setrprgetnamerT weakref_ref)r?r{ruZorCrArArB_add_xor_constraint*s    z&Hull_Reformulation._add_xor_constraintcCsp|js dS|jdk r"|}n||}|||}x&tt|D]}|||||qJW|dS)N) rMrrQrvrrwr,rg deactivate)r?rxruZ xorConstraintryrArArBrfCs  z)Hull_Reformulation._transform_disjunctionc s8|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 krtt j!rt"d j dtd|nx| #|ddk r| |dkr |#|d}|dk r||dng||d<n |n |qPWd}x2|j D](} || j$7}|%| |||#| gq2W|||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)r|r})rMrNrL)Z include_fixedcsg|]}|kr|qSrArA).0d)varvarsByDisjunctrArB szAHull_Reformulation._transform_disjunctionData..zGAssuming '%s' is not a local var since it isused in multiple disjuncts.disaggregatedVar)+rMxorrrcparent_componentrrQrvrrsrtlen disjunctsrrTrrrar8rOrrrPr EXPRidentify_variablesbodyaddappendrSlogger isEnabledForloggingDEBUGdebugrF indicator_var_transform_disjunctr enumerate_transformation_block_disaggregatedVarMapr)r?rxrhrurZ orConstraintZdisaggregationConstraintZdisaggregationConstraintMapZ varOrder_setZvarOrderZlocalVarsByDisjunctZinclude_fixed_varsdisjunctZ disjunctVarsZconsvarSetrJrZlocalVars_thisDisjunctZor_exprryZdisaggregatedExprrZthismaprA)rrrBrg\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.)ZwithinZboundsroF)r|r}rrZ_boundsrlrmcss|]\}}t||fVqdS)N)id)rvnewVrArArB sz9Hull_Reformulation._transform_disjunct..css|]\}}t|tfVqdS)N)rr)rrrrArArBrscss|]}t|tfVqdS)N)rr)rrrArArBrs)-rMrZis_fixedrrrcrrqrr localVarReferencesZdisaggregatedVarsr_constraintMapr_bigMConstraintMaprZ _srcDisjunctrQrdr_add_local_var_suffixrCrFrlrmrrminmaxrrrTrprrrrrZsetlbZsetubdictr+rG_transform_block_componentsZ$_deactivate_without_fixing_indicator)r?rxrurrJrqrelaxationBlockZ local_var_setZparent_disjunctrrlrmrZdisaggregatedVarNameZbigmConstraintZconNamevar_substitute_mapzero_substitute_maprArArBrs                                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)rLrMT)r|r})rNrLF)rMrLzNo 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.)rrrzrr rprrrTr rQrOrrrPZalgebraic_constraint_transfer_var_referencesr>rFrdr) r?rHrrr disjunctBlockZ varRefBlockrZdestinationBlockrxruhandlerrArArBrs0     z.Hull_Reformulation._transform_block_componentscCsD|j}x8t|jD]*\}}|t|}t|_|j|jqWdS)N)rqr+rr rZtransfer_attributes_from)r?Z fromBlockZtoBlockZ disjunctListidxrZnewblockrArArBrs  z+Hull_Reformulation._transfer_var_referencescCst||tdS)N)r(rT)r?r{rrrrArArBr(sz/Hull_Reformulation._warn_for_active_disjunctioncCst||tdS)N)r)rT)r?Z innerdisjunctZ outerdisjunctrrrArArBr)sz,Hull_Reformulation._warn_for_active_disjunctcCst||tdS)N)r rT)r?Zlogical_statmentrrrrArArBr=sz5Hull_Reformulation._warn_for_active_logical_statementcCs.x(tt|D]}||||||qWdS)N)rwr,r)r?rHrrrryrArArBr<s z/Hull_Reformulation._transform_block_on_disjunctcs|}|}|jd}|j}t||jdtd} |rNt| |j } n t|j } | | | |rx| |d|<||d| <xTt t |D]B} || } | 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 rt!"t#j$r | jdtd}t!%d|| r || jk}n|d|| jk}|r| | df|| | dfg|d| <| |d| | df<n.| d|| dg|d| <| |d| d<| j&dk rt!"t#j$r| jdtd}t!%d|| r|| j&k}n|d|| j&k}|r| | df||d'| }|dk rV|(| | dfn| | dfg|d| <| |d| | df<q| d||d'| }|dk r|(| dn| dg|d| <| |d| d<qW|)dS)NrT)r|r}rr)rrr4) substituter5c3s|]\}}||fVqdS)NrA)rrsubs)yrArBr)sz;Hull_Reformulation._transform_constraint..r6c3s"|]\}}||fVqdS)NrA)rrr)r7rrArBr1sc3s*|]"\}}||dfVqdS)rNrA)rrr)r7rrArBr9srzUnknown NL Hull moderrnz'GDP(Hull): Transforming constraint '%s'rlrm)*rrQrrrrrTrerrrrrprwr,rMrZpolynomial_degreerar7Zperspective_functionr!rrr+ RuntimeErrorZequalitylowerlistrrrZfixrrrrrrupperrFrr)r?rxrrrrruZvarMapZ constraintMaprcZ newConstraintrycNLmodeZh_0Zsub_exprexprZ newConsExprr_nameZ transformedrA)r7rrBr;s               &              z(Hull_Reformulation._transform_constraintcCsP|d}|dkr"ttjd|_n*|jtkr0dStd|jdtd|jfdS)NrC) directionz\A component called 'LocalVars' is declared on Disjunct %s, but it is of type %s, not Suffix.T)r|r})rDrZLOCALrCrdrrrT)r?rZ localSuffixrArArBrs  z(Hull_Reformulation._add_local_var_suffixcCst|S)N)r')r?rurArArBr'sz#Hull_Reformulation.get_src_disjunctcCst|S)N)r$)r?Zxor_constraintrArArBr$sz&Hull_Reformulation.get_src_disjunctioncCst|S)N)r%)r?ZtransformedConstraintrArArBr%sz%Hull_Reformulation.get_src_constraintcCst|S)N)r&)r?Z srcConstraintrArArBr&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')rrrcrrerror)r?rrrurArArBget_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)rQrrrrc)r?Zdisaggregated_varrurArArB 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')rrrrcrQrtrr)r?Z original_varr{rrurArArBget_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)rQrrrrc)r?rrurArArBget_var_bounds_constraints   z,Hull_Reformulation.get_var_bounds_constraint)N)+__name__ __module__ __qualname____doc__cfgZ ConfigBlockr_ZdeclareZ ConfigValuer"ZInZ PositiveFloatboolr:rKrSrZrVrvrirjrrfrgrrrr(r)r=r<r;rr*r'r$r%r&rrrr __classcell__rArA)r@rBr/)sh6    *         06  3r/z 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)rversioncstt|dS)N)r9rr:)r?)r@rArBr:5sz_Deprecated_Name_Hull.__init__)rrrrr:rrArA)r@rBr1sr)IrZpyomo.common.configcommonconfigrZ pyomo.commonrZpyomo.common.collectionsrrZpyomo.common.modelingrZpyomo.core.expr.numvaluerZpyomo.core.base.componentrZpyomo.core.expr.currentcorercurrentrZpyomo.core.baserr r Z pyomo.corer r r rrrrrrrrrrrrrrrZ pyomo.gdprrrZpyomo.gdp.utilr r!r"r#r$r%r&r'r(r) functoolsr*sixr+r,weakrefr-r getLoggerrrTregisterr/rrArArArB s@    P0