B _C@sddlmZddlmmmZddlmZm Z ddl m Z m Z ddl mZmZddlmZddlmZmZddlmZmZdd lmZmZdd lmZddlZdd lmZddl Z e !d Z"e#ej$ej%ej&gZ'e#ej(ej)gZ*Gd dde+Z,Gddde+Z-Gddde+Z.ddZ/d3ddZ0ddZ1d4ddZ2ddZ3ddZ4dd Z5d!d"Z6d#d$Z7d%d&Z8d'd(Z9d)d*Z:d+d,Z;d-d.ZdS)5) string_typesN)nonpyomo_leaf_typesnative_numeric_types) GDP_Error Disjunction) _DisjunctDataDisjunct)deepcopy)_ComponentBase ComponentUID)BlockTraversalStrategy)TerminationCondition SolverStatus)iterkeys)refz pyomo.gdpc@s eZdZdS)NORMALN)__name__ __module__ __qualname__rr2/tmp/pip-unpacked-wheel-d4p3hk07/pyomo/gdp/util.pyr(src@s eZdZdS) INFEASIBLEN)rrrrrrrr)src@s eZdZdS) NONOPTIMALN)rrrrrrrr*srcCs:|jj}|jj}|tjkr&|tkr&tS|tkr2tSt SdS)N) ZsolverstatusZtermination_conditionrok"_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)exprr Zvisitorrrr#clone_without_expression_components8s r#cCsnt|tr|gSt|drXg}x4|D],}t|tr>||q$tdt|fq$W|Stdt|fdS)N__iter__z6Expected Component or list of Components. Recieved %s) isinstancer hasattrappend ValueErrortype)xZansirrr target_listZs     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 }szis_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_ofrs.    r:cCsL|}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_objectsrr rZ_algebraic_constraintrname)Zxor_constraintm disjunctionrrrget_src_disjunctions rAcCs.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)rB weakref_refrr>) transBlockrrrget_src_disjuncts  rEcCs.|}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)r4r&rr>rF)ZtransformedConstraintrDrrrget_src_constraints   rGcCs:|}x,t|ts4|dkr*td|j|}q W|S)Nz?Constraint '%s' is not on a disjunct and so was not transformed)r4r%rrr>) constraintparent_disjunctrrr_find_parent_disjuncts   rJcCs.t|}|j}|dkr$td|j|}|S)Nz?Constraint '%s' is on a disjunct which has not been transformed)rJZ_transformation_blockrr>)rHrIrDrrr_get_constraint_transBlocks rKcCsJ|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_indexedrrKrFloggererrorr>)Z srcConstraintrDrrrget_transformed_constraintss rOcCs|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.) activeAssertionErrorrLsortedrr4Zalgebraic_constraintgetnamer)r@disjunct NAME_BUFFER problemdisjr+Z parentblockZ _probDisjNameZ _disjNamerrr_warn_for_active_disjunctions   rYcCsh|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)rPrQ)rRrSrLrTrrformatrU)Z innerdisjunctZ outerdisjunctrWrXr+rrr_warn_for_active_disjuncts  r[cCsh|js t|}|rDx,|D]}||jr||}PqW|dS|jd|d}td||jfdS)NT)rPrQzFound untransformed logical constraint %s in disjunct %s! The logical constraint must be transformed before the disjunct. Use the logical_to_linear transformation.)rRrSrLZ deactivaterUrr>)Zlogical_statementrVrWZproblem_statementr+Z_probStatementNamerrr#_warn_for_active_logical_constraint,s    r\cCsdd|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 Osz(check_model_algebraic..N)r;rRcSsh|]}|qSrr)r-r+rrrr]QsT)r;Z 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.)r=rr rr0r2Z disjunctsr Z PostfixDFSZtransformation_blockrR_disjunct_not_fixed_true_disjunct_on_active_blockrMwarningr>)instanceZdisjunction_setZactive_disjunction_setZdisjuncts_in_disjunctionsr+Z disjuncts_in_active_disjunctionsrVrrrcheck_model_algebraicEs:         rbcCs|jjo|jjdk S)N) indicator_varfixedvalue)rVrrrr^sr^cCs`|}xR|dk rZ|jtkr&|js&dS|jtkrN|jsN|jjdkrN|jjrNdS|}q q WdS)NFrT)r4ctyper rRrrdrfre)rVr4rrrr_s  r_)N)N)?sixrZpyomo.core.expr.currentcorer"currentr!Zpyomo.core.expr.numvaluerrZ pyomo.gdprrZpyomo.gdp.disjunctrrcopyr Zpyomo.core.base.componentr r Z pyomo.corer r Z pyomo.optrrrsysweakrefrrClogging getLoggerrMr0ZoptimalZgloballyOptimalZlocallyOptimalrZ infeasibleZinvalidProblemrobjectrrrrr#r,r:rArErGrJrKrOrYr[r\rbr^r_rrrr sN        "   :