B u `C@sjddlmmmZddlmZmZddlm Z m Z ddl m Z ddl mZmZddlmZmZddlmZddlmZddlZed ZeejejejgZeej ej!gZ"Gd d d e#Z$Gd d d e#Z%Gddde#Z&ddZ'd0ddZ(ddZ)d1ddZ*ddZ+ddZ,ddZ-ddZ.d d!Z/d"d#Z0d$d%Z1d&d'Z2d(d)Z3d*d+Z4d,d-Z5d.d/Z6dS)2N) GDP_Error Disjunction) _DisjunctDataDisjunct)_ComponentBase)BlockTraversalStrategy)TerminationCondition SolverStatus)iterkeys)refz pyomo.gdpc@s eZdZdS)NORMALN)__name__ __module__ __qualname__rr2/tmp/pip-unpacked-wheel-n62dbgi3/pyomo/gdp/util.pyr $sr c@s eZdZdS) INFEASIBLEN)rrrrrrrr%src@s eZdZdS) NONOPTIMALN)rrrrrrrr&srcCs:|jj}|jj}|tjkr&|tkr&tS|tkr2tSt SdS)N) ZsolverstatusZtermination_conditionr ok"_acceptable_termination_conditionsr "_infeasible_termination_conditionsrr)resultsrZtermrrrverify_successful_solve(srcCs$|dkr i}tj|dd}||S)aA function that is used to clone an expression. Cloning is roughly equivalent to calling ``copy.deepcopy``. However, the :attr:`clone_leaves` argument can be used to clone only interior (i.e. non-leaf) nodes in the expression tree. Note that named expression objects are treated as leaves when :attr:`clone_leaves` is :const:`True`, and hence those subexpressions are not cloned. This function uses a non-recursive logic, which makes it more scalable than the logic in ``copy.deepcopy``. Args: expr: The expression that will be cloned. substitute (dict): A dictionary mapping object ids to objects. This dictionary has the same semantics as the memo object used with ``copy.deepcopy``. Defaults to None, which indicates that no user-defined dictionary is used. Returns: The cloned expression. NT) substituteZremove_named_expressions)EXPRZExpressionReplacementVisitorZdfs_postorder_stack)exprrZvisitorrrr#clone_without_expression_components4s rcCsnt|tr|gSt|drXg}x4|D],}t|tr>||q$tdt|fq$W|Stdt|fdS)N__iter__z6Expected Component or list of Components. Recieved %s) isinstancerhasattrappend ValueErrortype)xZansirrr target_listVs     r'cCs|dkr i}t}|}x||}|r>|dd|DdS|dk rb|sb|dd|DdS||kr|dd|DdS|dkr|dd|DdS|||}||kr|}q|}qWdS)NcSsi|] }d|qS)Tr).0crrr yszis_child_of..TcSsi|] }d|qS)Fr)r(r)rrrr*|sFcSsi|] }d|qS)Tr)r(r)rrrr*scSsi|] }d|qS)Fr)r(r)rrrr*s)setgetupdateaddZparent_component parent_block)parentchildZ knownBlockstmpnodeZknown containerrrr is_child_ofns.    r5cCsL|}x0|jtttfdD]}|jr||kr|SqWtd|jdS)aReturn the Disjunction corresponding to xor_constraint Parameters ---------- xor_constraint: Constraint, which must be the logical constraint (located on the transformation block) of some Disjunction ) descend_intoz^It appears that '%s' is not an XOR or OR constraint resulting from transforming a Disjunction.N)modelcomponent_data_objectsrrrZ_algebraic_constraintrname)Zxor_constraintm disjunctionrrrget_src_disjunctions r<cCs.t|drt|jtk r&td|j|S)zReturn the Disjunct object whose transformed components are on transBlock. Parameters ---------- transBlock: _BlockData which is in the relaxedDisjuncts IndexedBlock on a transformation block. _srcDisjunctz`Block '%s' doesn't appear to be a transformation block for a disjunct. No source disjunct found.)r!r$r= weakref_refrr9) transBlockrrrget_src_disjuncts  r@cCs.|}t|ds td|j|jd|S)aReturn the original Constraint whose transformed counterpart is transformedConstraint Parameters ---------- transformedConstraint: Constraint, which must be a component on one of the BlockDatas in the relaxedDisjuncts Block of a transformation block _constraintMapz/Constraint '%s' is not a transformed constraintZsrcConstraints)r/r!rr9rA)ZtransformedConstraintr?rrrget_src_constraints   rBcCs:|}x,t|ts4|dkr*td|j|}q W|S)Nz?Constraint '%s' is not on a disjunct and so was not transformed)r/r rrr9) constraintparent_disjunctrrr_find_parent_disjuncts   rEcCs.t|}|j}|dkr$td|j|}|S)Nz?Constraint '%s' is on a disjunct which has not been transformed)rEZ_transformation_blockrr9)rCrDr?rrr_get_constraint_transBlocks rFcCsJ|rtdt|}y|jd|Std|jYnXdS)zReturn the transformed version of srcConstraint Parameters ---------- srcConstraint: SimpleConstraint or _ConstraintData, which must be in the subtree of a transformed Disjunct aArgument to get_transformed_constraint should be a SimpleConstraint or _ConstraintData. (If you want the container for all transformed constraints from an IndexedDisjunction, this is the parent component of a transformed constraint originating from any of its _ComponentDatas.)ZtransformedConstraintsz)Constraint '%s' has not been transformed.N) is_indexedrrFrAloggererrorr9)Z srcConstraintr?rrrget_transformed_constraintss rJcCs|js t|}|r@x(tt|D]}||jr$||}Pq$W|}|jdksVt|jd|d}|jd|d}td||fdS)NT)fully_qualified name_bufferzFound untransformed disjunction '%s' in disjunct '%s'! The disjunction must be transformed before the disjunct. If you are using targets, put the disjunction before the disjunct in the list.) activeAssertionErrorrGsortedr r/Zalgebraic_constraintgetnamer)r;disjunct NAME_BUFFER problemdisjr&Z parentblockZ _probDisjNameZ _disjNamerrr_warn_for_active_disjunctions   rTcCsh|js t|}|r@x(tt|D]}||jr$||}Pq$Wtd|jd|d|jd|ddS)NzFound active disjunct '{0}' in disjunct '{1}'! Either {0} is not in a disjunction or the disjunction it is in has not been transformed. {0} needs to be deactivated or its disjunction transformed before {1} can be transformed.T)rKrL)rMrNrGrOr rformatrP)Z innerdisjunctZ outerdisjunctrRrSr&rrr_warn_for_active_disjuncts  rVcCsh|js t|}|rDx,|D]}||jr||}PqW|dS|jd|d}td||jfdS)NT)rKrLzFound untransformed logical constraint %s in disjunct %s! The logical constraint must be transformed before the disjunct. Use the logical_to_linear transformation.)rMrNrGZ deactivaterPrr9)Zlogical_statementrQrRZproblem_statementr&Z_probStatementNamerrr#_warn_for_active_logical_constraint(s    rWcCsdd|jtttfddD}dd|jtttfddD}t}x|D]}||jqHWt}x|D]}||jqhWx|jttftjdD]|}|j dk rqq|j rt |rt |r||krt d|jfd S||krt d |jfd St d |jfd SqWdS) aGChecks if there are any active Disjuncts or Disjunctions reachable via active Blocks. If there are not, it returns True. If there are, it issues a warning detailing where in the model there are remaining non-algebraic components, and returns False. Parameters ---------- instance: a Model or Block cSsh|]}|qSrr)r(r&rrr Ksz(check_model_algebraic..N)r6rMcSsh|]}|qSrr)r(r&rrrrXMsT)r6Z descent_orderzDisjunct "%s" is currently active, but was not found in any Disjunctions. This is generally an error as the model has not been fully relaxed to a pure algebraic form.Fa"Disjunct "%s" is currently active. While it participates in a Disjunction, that Disjunction is currently deactivated. This is generally an error as the model has not been fully relaxed to a pure algebraic form. Did you deactivate the Disjunction without addressing the individual Disjuncts?zbDisjunct "%s" is currently active. It must be transformed or deactivated before solving the model.)r8rrrr+r-Z disjunctsrZ PostfixDFSZtransformation_blockrM_disjunct_not_fixed_true_disjunct_on_active_blockrHwarningr9)instanceZdisjunction_setZactive_disjunction_setZdisjuncts_in_disjunctionsr&Z disjuncts_in_active_disjunctionsrQrrrcheck_model_algebraicAs:         r]cCs|jjo|jjdk S)N) indicator_varfixedvalue)rQrrrrY{srYcCs`|}xR|dk rZ|jtkr&|js&dS|jtkrN|jsN|jjdkrN|jjrNdS|}q q WdS)NFrT)r/ctyperrMrr_rar`)rQr/rrrrZs  rZ)N)N)7Zpyomo.core.expr.currentcorercurrentrZ pyomo.gdprrZpyomo.gdp.disjunctrrZpyomo.core.base.componentrZ pyomo.corerrZ pyomo.optr r sixr weakrefr r>logging getLoggerrHr+ZoptimalZgloballyOptimalZlocallyOptimalrZ infeasibleZinvalidProblemrobjectr rrrrr'r5r<r@rBrErFrJrTrVrWr]rYrZrrrr sF       "   :