B
    '\                 @   s   d Z ddlmZmZmZmZ ddlmZ ddlmZm	Z	 ddl
mZmZ ddlmZmZ dd	lmZ eeZG d
d deZG dd deZG dd deZG dd deZG dd deZG dd deZejfddZG dd deZdd Zdd ZdS )au  
The basic idea to nest logical expressions is instead of trying to denest
things via distribution, we add new variables. So if we have some logical
expression expr, we replace it with x and add expr <-> x to the clauses,
where x is a new variable, and expr <-> x is recursively evaluated in the
same way, so that the final clauses are ORs of atoms.

To use this, create a new Clauses object with the max var, for instance, if you
already have [[1, 2, -3]], you would use C = Clause(3).  All functions return
a new literal, which represents that function, or True or False if the expression
can be resolved fully. They may also add new clauses to C.clauses, which
will then be delivered to the SAT solver.

All functions take atoms as arguments (an atom is an integer, representing a
literal or a negated literal, or boolean constants True or False; that is,
it is the callers' responsibility to do the conversion of expressions
recursively. This is done because we do not have data structures
representing the various logical classes, only atoms.

The polarity argument can be set to True or False if you know that the literal
being used will only be used in the positive or the negative, respectively
(e.g., you will only use x, not -x).  This will generate fewer clauses. It
is probably best if you do not take advantage of this directly, but rather
through the Require and Prevent functions.

    )absolute_importdivisionprint_functionunicode_literals)array)chaincombinations)DEBUG	getLogger   )	iteritemsodict   )SatSolverChoicec               @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )
ClauseListzEStorage for the CNF clauses, represented as a list of tuples of ints.c             C   s   g | _ | j j| _| j j| _d S )N)_clause_listappendextend)self r   1lib/python3.7/site-packages/conda/common/logic.py__init__,   s    
zClauseList.__init__c             C   s
   t | jS )z2
        Return number of stored clauses.
        )lenr   )r   r   r   r   get_clause_count3   s    zClauseList.get_clause_countc             C   s
   t | jS )z
        Get state information to be able to revert temporary additions of
        supplementary clauses.  ClauseList: state is simply the number of clauses.
        )r   r   )r   r   r   r   
save_state9   s    zClauseList.save_statec             C   s   |}g | j |d< dS )z~
        Restore state saved via `save_state`.
        Removes clauses that were added after the sate has been saved.
        N)r   )r   saved_stateZlen_clausesr   r   r   restore_state@   s    zClauseList.restore_statec             C   s   | j S )z+Return clauses as a list of tuples of ints.)r   )r   r   r   r   as_listH   s    zClauseList.as_listc             C   s0   t d}x"| jD ]}|| |d qW |S )zX
        Return clauses as a flat int array, each clause being terminated by 0.
        ir   )r   r   r   r   )r   Zclause_arraycr   r   r   as_arrayL   s
    
zClauseList.as_arrayN)
__name__
__module____qualname____doc__r   r   r   r   r   r    r   r   r   r   r   *   s   r   c               @   sP   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd ZdS )ClauseArrayzp
    Storage for the CNF clauses, represented as a flat int array.
    Each clause is terminated by int(0).
    c             C   s"   t d| _| jj| _| jj| _d S )Nr   )r   _clause_arrayr   _array_appendr   _array_extend)r   r   r   r   r   \   s    

zClauseArray.__init__c             C   s   x|D ]}|  | qW d S )N)r   )r   clausesclauser   r   r   r   c   s    
zClauseArray.extendc             C   s   |  | | d d S )Nr   )r(   r'   )r   r*   r   r   r   r   g   s    
zClauseArray.appendc             C   s   | j dS )z
        Return number of stored clauses.
        This is an O(n) operation since we don't store the number of clauses
        explicitly due to performance reasons (Python interpreter overhead in
        self.append).
        r   )r&   count)r   r   r   r   r   k   s    zClauseArray.get_clause_countc             C   s
   t | jS )z
        Get state information to be able to revert temporary additions of
        supplementary clauses. ClauseArray: state is the length of the int
        array, NOT number of clauses.
        )r   r&   )r   r   r   r   r   t   s    zClauseArray.save_statec             C   s   |}t d| j|d< dS )z~
        Restore state saved via `save_state`.
        Removes clauses that were added after the sate has been saved.
        r   N)r   r&   )r   r   Zlen_clause_arrayr   r   r   r   |   s    zClauseArray.restore_statec             c   s>   g }x4| j D ]*}|dkr,t|V  |  q|| qW dS )z+Return clauses as a list of tuples of ints.r   N)r&   tupleclearr   )r   r*   vr   r   r   r      s    

zClauseArray.as_listc             C   s   | j S )zX
        Return clauses as a flat int array, each clause being terminated by 0.
        )r&   )r   r   r   r   r       s    zClauseArray.as_arrayN)r!   r"   r#   r$   r   r   r   r   r   r   r   r    r   r   r   r   r%   W   s   	
r%   c               @   sX   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd ZdS )	SatSolverzV
    Simple wrapper to call a SAT solver given a ClauseList/ClauseArray instance.
    c             K   s*   |pi | _ t | _| jj| _| jj| _d S )N)_run_kwargsr   _clausesr   
add_clauser   add_clauses)r   
run_kwargsr   r   r   r      s    

zSatSolver.__init__c             C   s
   | j  S )N)r1   r   )r   r   r   r   r      s    zSatSolver.get_clause_countc             C   s
   | j  S )N)r1   r   )r   r   r   r   r      s    zSatSolver.as_listc             C   s
   | j  S )N)r1   r   )r   r   r   r   r      s    zSatSolver.save_statec             C   s   | j |S )N)r1   r   )r   r   r   r   r   r      s    zSatSolver.restore_statec             K   s:   | j  }|| | j|f|}| |}| |}|S )N)r0   copyupdatesetupinvokeprocess_solution)r   mkwargsr4   solversat_solutionsolutionr   r   r   run   s    



zSatSolver.runc             K   s
   t  dS )z?Create a solver instance, add the clauses to it, and return it.N)NotImplementedError)r   r:   r;   r   r   r   r7      s    zSatSolver.setupc             C   s
   t  dS )z@Start the actual SAT solving and return the calculated solution.N)r@   )r   r<   r   r   r   r8      s    zSatSolver.invokec             C   s
   t  dS )z
        Process the solution returned by self.invoke.
        Returns a list of satisfied variables or None if no solution is found.
        N)r@   )r   r=   r   r   r   r9      s    zSatSolver.process_solutionN)r!   r"   r#   r$   r   r   r   r   r   r?   r7   r8   r9   r   r   r   r   r/      s   r/   c               @   s&   e Zd Zd	ddZdd Zdd ZdS )
PycoSatSolverr   c             K   s    ddl m} || j ||dS )Nr   )	itersolve)varsZ
prop_limit)ZpycosatrB   r1   r   )r   r:   limitr;   rB   r   r   r   r7      s    zPycoSatSolver.setupc             C   s,   yt |}W n tk
r$   d}Y nX ~|S )NUNSAT)nextStopIteration)r   Ziter_solr=   r   r   r   r8      s    
zPycoSatSolver.invokec             C   s   |dkrd S |S )N)rE   ZUNKNOWNr   )r   r=   r   r   r   r9      s    zPycoSatSolver.process_solutionN)r   )r!   r"   r#   r7   r8   r9   r   r   r   r   rA      s   

rA   c               @   s&   e Zd Zd	ddZdd Zdd ZdS )
CryptoMiniSatSolverr   c             K   s*   ddl m} ||d}|| j  |S )Nr   )Solver)threads)ZpycryptosatrI   r3   r1   r   )r   r:   rJ   r;   rI   r<   r   r   r   r7      s    
zCryptoMiniSatSolver.setupc             C   s   |  \}}|sd }|S )N)solve)r   r<   satr=   r   r   r   r8      s    zCryptoMiniSatSolver.invokec             C   s   |sd S dd t |D }|S )Nc             S   s   g | ]\}}|r|qS r   r   ).0r   br   r   r   
<listcomp>   s    z8CryptoMiniSatSolver.process_solution.<locals>.<listcomp>)	enumerate)r   r>   r   r   r   r9      s    z$CryptoMiniSatSolver.process_solutionN)r   )r!   r"   r#   r7   r8   r9   r   r   r   r   rH      s   
rH   c               @   s$   e Zd Zdd Zdd Zdd ZdS )PySatSolverc             K   s&   ddl m} | }|| j  |S )Nr   )Glucose4)Zpysat.solversrR   Zappend_formular1   r   )r   r:   r;   rR   r<   r   r   r   r7      s    zPySatSolver.setupc             C   s"   |  sd }n| }|  |S )N)rK   Z	get_modeldelete)r   r<   r=   r   r   r   r8      s
    zPySatSolver.invokec             C   s   |d krd }n|}|S )Nr   )r   r=   r>   r   r   r   r9     s    zPySatSolver.process_solutionN)r!   r"   r#   r7   r8   r9   r   r   r   r   rQ      s   rQ   c             C   s  t tjtftjtftjtfg}||  }y| d W n> t	k
rv } z t
d|  t
jd|dd W d d }~X Y nX t
d|  |S xf| D ]Z\}}y| d W n0 t	k
r } zt
d| | W d d }~X Y qX t
d|  |S qW d	d
lm} |dd S )Nr   z0Could not run SAT solver through interface '%s'.zSAT interface error due to: %sT)exc_infoz Using SAT solver interface '%s'.z7Attempted SAT interface '%s' but unavailable due to: %sz*Falling back to SAT solver interface '%s'.r   )CondaDependencyErrorz@Cannot run solver. No functioning SAT implementations available.)r   r   PYCOSATrA   ZPYCRYPTOSATrH   ZPYSATrQ   r?   	ExceptionlogZwarningdebugitems
exceptionsrU   )Zsat_solver_choiceZsolversclseZsolver_choicerU   r   r   r   get_sat_solver_cls  s,    "r^   c               @   s  e Zd ZdefddZdd Zdd Zdd	 Zd
d ZdcddZ	dd Z
dd ZddddZdd Zdd ZdeddZdd Zdd Zd d! Zdfd#d$Zdgd%d&Zdhd'd(Zdid)d*Zdjd+d,Zdkd-d.Zdld/d0Zdmd1d2Zdnd3d4Zdod5d6Zdpd7d8Zdqd9d:Zd;d< Zdrd=d>Z d?d@ Z!dsdAdBZ"dtdCdDZ#dudEdFZ$dvdGdHZ%dIdJ Z&dwdKdLZ'dMdN Z(dxdOdPZ)dydQdRZ*dSdT Z+dUdV Z,dWdX Z-dzdYdZZ.d{d[d\Z/d|d]d^Z0d}d_d`Z1d~dadbZ2dS )Clausesr   c             C   s8   i | _ i | _d| _|| _| | _| jj| _| jj| _d S )NF)namesindicesunsatr:   _sat_solverr2   r3   )r   r:   Zsat_solver_clsr   r   r   r   -  s    
zClauses.__init__c             C   s
   | j  S )N)rc   r   )r   r   r   r   r   7  s    zClauses.get_clause_countc             C   s
   | j  S )N)rc   r   )r   r   r   r   r   :  s    zClauses.as_listc             C   sN   d| }|| j |< | | j |< t|tk	rJ|| jkrJ|| j|< || j| < |S )N!)r`   typeboolra   )r   r:   nameZnnamer   r   r   name_var=  s    

zClauses.name_varc             C   s   | j d }|| _ |S )Nr   )r:   )r   r:   r   r   r   _new_varF  s    
zClauses._new_varNc             C   s   |   }|r| || |S )N)ri   rh   )r   rg   r:   r   r   r   new_varK  s    zClauses.new_varc             C   s   | j |S )N)r`   get)r   rg   r   r   r   	from_nameQ  s    zClauses.from_namec             C   s   | j |S )N)ra   rk   )r   r:   r   r   r   
from_indexT  s    zClauses.from_indexc             C   sH   |  |}|s|S t|tr<|  }| |r2|fn| f | ||S )N)_assign_no_name
isinstancerf   ri   r2   rh   )r   valsrg   xr   r   r   Assign_W  s    

zClauses.Assign_c                sR   t |trN|   |  fdd|d D  |  fdd|d D   S |S )Nc             3   s   | ]}  f| V  qd S )Nr   )rM   y)rq   r   r   	<genexpr>c  s    z*Clauses._assign_no_name.<locals>.<genexpr>r   c             3   s   | ]} f| V  qd S )Nr   )rM   rs   )rq   r   r   rt   d  s    r   )ro   r,   ri   r3   )r   rp   r   )rq   r   rn   `  s    
zClauses._assign_no_namec             C   s2   t |}|ttfkr$|t| j|S | j||S )N)re   r,   listmapConvert_r`   rk   )r   rq   Ztxr   r   r   rw   h  s    zClauses.Convert_Tc       	      C   s   |r|  |}| j }||d|i}|d kr8| |S |dk	rL| ||S t|}|tkrz| |d  | |d  n<|tk	r| 	|r|n| f n| j
| | jp||k| _d S )NpolarityFr   r   )rw   rc   r   rn   rr   re   r,   r3   rf   r2   r   rb   )	r   funcargsrx   rg   convr   rp   Ztvalsr   r   r   Eval_n  s"    


zClauses.Eval_c             C   s   t dd |D rdS dd |D }t|}|dkr8dS |dkrH|d S td	d |D rtd
d |D g tdd |D g fS | t| j||S d S )Nc             s   s   | ]}|d kV  qdS )FNr   )rM   r.   r   r   r   rt     s    z#Clauses.Combine_.<locals>.<genexpr>Fc             S   s   g | ]}|d k	r|qS )Tr   )rM   r.   r   r   r   rO     s    z$Clauses.Combine_.<locals>.<listcomp>r   Tr   c             s   s   | ]}t |tkV  qd S )N)re   r,   )rM   r.   r   r   r   rt     s    c             s   s   | ]}|d  V  qdS )r   Nr   )rM   r.   r   r   r   rt     s    c             s   s   | ]}|d  V  qdS )r   Nr   )rM   r.   r   r   r   rt     s    )anyr   allsumAll_rv   rr   )r   rz   rx   nvr   r   r   Combine_  s    (zClauses.Combine_c             G   s   | | t|dddS )NF)rx   rg   )__get__r_   )r   whatrz   r   r   r   Prevent  s    zClauses.Preventc             G   s   | | t|dddS )NTF)rx   rg   )r   r_   )r   r   rz   r   r   r   Require  s    zClauses.RequireFc             C   s   t |tkr| S | S )N)re   rf   )r   rq   rx   add_new_clausesr   r   r   Not_  s    zClauses.Not_c             C   s   |  | j|f||S )N)r|   r   )r   rq   rx   rg   r   r   r   Not  s    zClauses.Notc             C   s   |dks|dkrdS |dkr |S |dkr,|S ||kr8|S || krFdS ||k rX|| }}|r|   }|dkr| | |f| |fg |dkr| || | fg |S |dkr|f|fgng }|dkr| | fgng }||fS )NFT)TN)FN)rj   r3   )r   fgrx   r   rq   pvalnvalr   r   r   And_  s,    

zClauses.And_c             C   s   |  | j||f||S )N)r|   r   )r   r   r   rx   rg   r   r   r   And  s    zClauses.Andc             C   s   |dks|dkrdS |dkr |S |dkr,|S ||kr8|S || krFdS ||k rX|| }}|r|   }|dkr| | ||fg |dkr| || f|| fg |S |dkr||fgng }|dkr| f| fgng }||fS )NTF)TN)FN)rj   r3   )r   r   r   rx   r   rq   r   r   r   r   r   Or_  s,    

zClauses.Or_c             C   s   |  | j||f||S )N)r|   r   )r   r   r   rx   rg   r   r   r   Or  s    z
Clauses.Orc             C   s  |dkr|S |dkr$| j |||dS |dkr0|S |dkr>| S ||krJdS || krXdS ||k rj|| }}|r|  }|dkr| | ||f| | | fg |dkr| || |f||| fg |S |dkr||f| | fgng }|dkr| |f|| fgng }||fS )NFT)r   )TN)FN)r   rj   r3   )r   r   r   rx   r   rq   r   r   r   r   r   Xor_  s0    

" "zClauses.Xor_c             C   s   |  | j||f||S )N)r|   r   )r   r   r   rx   rg   r   r   r   Xor  s    zClauses.Xorc       	      C   s  |dkr|S |dkr|S |dkr2| j ||||dS |dkrN| j| |||dS |dkrh| j||||dS |dkr| j || ||dS ||kr| j ||||dS || kr| j| |||dS ||kr| j||||dS || kr| j || ||dS ||kr|S || kr | j||||dS ||k r<|||   }}}|r|  }|dkr~| | | |f| ||f| ||fg |dkr| || | f||| f|| | fg |S |dkr| |f||f||fgng }|dkr| | f|| f| | fgng }||fS )NTF)r   )TN)FN)r   r   r   rj   r3   )	r   r   tr   rx   r   rq   r   r   r   r   r   ITE_  sH    




*
,&.zClauses.ITE_c             C   s   |  | j|||f||S )z
        if c then t else f

        In this function, if any of c, t, or f are True and False the resulting
        expression is resolved.
        )r|   r   )r   r   r   r   rx   rg   r   r   r   ITE  s    zClauses.ITEc             C   s   t  }x6|D ].}|dkrq|dks,| |kr0dS || qW t|}|dkrRdS |dkrltdd |D S |dkrdd	 |D ng }|d
krtdd |D gng }||fS )NTFr   r   c             s   s   | ]
}|V  qd S )Nr   )rM   r.   r   r   r   rt   2  s    zClauses.All_.<locals>.<genexpr>)TNc             S   s   g | ]
}|fqS r   r   )rM   r.   r   r   r   rO   3  s    z Clauses.All_.<locals>.<listcomp>)FNc             s   s   | ]}| V  qd S )Nr   )rM   r.   r   r   r   rt   4  s    )setaddr   rF   r,   )r   iterrx   rp   r.   r   r   r   r   r   r   r   &  s    
 zClauses.All_c             C   s   |  | j|f||S )N)r|   r   )r   r   rx   rg   r   r   r   All7  s    zClauses.Allc             C   s   t  }x8|D ]0}|dkrqn|dks.| |kr2dS || qW t|}|dkrTdS |dkrntdd |D S |dkrt|gng }|dkrd	d
 |D ng }||fS )NFTr   r   c             s   s   | ]
}|V  qd S )Nr   )rM   r.   r   r   r   rt   F  s    zClauses.Any_.<locals>.<genexpr>)TN)FNc             S   s   g | ]}| fqS r   r   )rM   r.   r   r   r   rO   H  s    z Clauses.Any_.<locals>.<listcomp>)r   r   r   rF   r,   )r   r   rx   rp   r.   r   r   r   r   r   r   Any_:  s    
zClauses.Any_c             C   s   |  | jt|f||S )N)r|   r   ru   )r   rp   rx   rg   r   r   r   AnyK  s    zClauses.Anyc             C   sD   g }x2t t| j|dD ]\}}|| ||| qW | ||S )Nr   )r   rv   r   r   r   r   )r   rp   rx   Zcombosv1v2r   r   r   AtMostOne_NSQ_N  s    zClauses.AtMostOne_NSQ_c             C   s   |  | jt|f||S )N)r|   r   ru   )r   rp   rx   rg   r   r   r   AtMostOne_NSQT  s    zClauses.AtMostOne_NSQc             C   s    dd |D }|  |ddd|S )Nc             S   s   g | ]}d |fqS )r   r   )rM   r.   r   r   r   rO   X  s    z*Clauses.AtMostOne_BDD_.<locals>.<listcomp>r   r   T)LinearBound_)r   rp   rx   rg   r   r   r   AtMostOne_BDD_W  s    zClauses.AtMostOne_BDD_c             C   s   |  | jt|f||S )N)r|   r   ru   )r   rp   rx   rg   r   r   r   AtMostOne_BDD[  s    zClauses.AtMostOne_BDDc             C   s@   t |}t|}|d|dk	 k r(| j}n| j}| ||f||S )N   T)ru   r   r   r   r|   )r   rp   rx   rg   r   r   r   r   r   	AtMostOne^  s    zClauses.AtMostOnec             C   s0   t |}| ||}| ||}| ||f|S )N)ru   r   r   r   )r   rp   rx   r   r   r   r   r   ExactlyOne_NSQ_g  s    zClauses.ExactlyOne_NSQ_c             C   s   |  | jt|f||S )N)r|   r   ru   )r   rp   rx   rg   r   r   r   ExactlyOne_NSQm  s    zClauses.ExactlyOne_NSQc             C   s    dd |D }|  |ddd|S )Nc             S   s   g | ]}d |fqS )r   r   )rM   r.   r   r   r   rO   q  s    z+Clauses.ExactlyOne_BDD_.<locals>.<listcomp>r   T)r   )r   rp   rx   r   r   r   ExactlyOne_BDD_p  s    zClauses.ExactlyOne_BDD_c             C   s   |  | jt|f||S )N)r|   r   ru   )r   rp   rx   rg   r   r   r   ExactlyOne_BDDt  s    zClauses.ExactlyOne_BDDc             C   s8   t |}t|}|dk r | j}n| j}| ||f||S )Nr   )ru   r   r   r   r|   )r   rp   rx   rg   r   r   r   r   r   
ExactlyOnew  s    zClauses.ExactlyOnec                sj   t |tkr" fddt|D }tdd |D rVtdd |D }dd |D }nd}t|}||fS )Nc                s"   g | ]\}}| j ||fqS r   )r`   rk   )rM   ar   )r   r   r   rO     s    z*Clauses.LB_Preprocess_.<locals>.<listcomp>c             s   s&   | ]\}}|d kpt |tkV  qdS )r   N)re   rf   )rM   r   r   r   r   r   rt     s    z)Clauses.LB_Preprocess_.<locals>.<genexpr>c             s   s.   | ]&\}}|d ks"|dk	r|dkr|V  qdS )TFr   Nr   )rM   r   r   r   r   r   rt     s    c             S   s<   g | ]4\}}t |tk	r|r|d kr,||fn
| | fqS )r   )re   rf   )rM   r   r   r   r   r   rO     s    r   )re   dictr   r}   r   sorted)r   equationoffsetr   )r   r   LB_Preprocess_  s    zClauses.LB_Preprocess_c             C   s^  t dd |d | D }|d d|f}|g}i }	|j}
|j}|	j}| j}d}x|rT|d \}}}|| }|| }|dkr||krd|	| < qR||ks|dk rd|	| < qR|| \}}|d8 }||8 }||dk r|n|| |f}||}|d kr|
| qR||dk r|| n||f}||}|d kr6|
| qR|t||||dd|	| < qRW |	| S )	Nc             s   s   | ]\}}|V  qd S )Nr   )rM   r   _r   r   r   rt     s    zClauses.BDD_.<locals>.<genexpr>r   r   TF)r   )r   r   poprk   r   abs)r   r   ntermslohirx   totaltargetZ
call_stackretZcall_stack_appendZcall_stack_popZret_getr   ZcsumZndxZlower_limitZupper_limitZLCZLAZhi_keyZthiZlo_keyZtlor   r   r   BDD_  sD    



 zClauses.BDD_c                s  |r"|  |\}}||8 } |8  t|}|rp|d d  krpt fdd|D }td||f  ||8 }nd}tdd |d | D }	|rt|dg}t |	g | krdS |dkr|dk}
n| ||| |}
|r| dd	 ||d  D |}| 	|
|f|}
|
S )
Nr   r   c             3   s   | ]\}}| kV  qd S )Nr   )rM   r   r   )r   r   r   rt     s    z'Clauses.LinearBound_.<locals>.<genexpr>z+Eliminating %d/%d terms for bound violationc             s   s   | ]\}}|V  qd S )Nr   )rM   r   r   r   r   r   rt     s    Fc             S   s   g | ]\}}| qS r   r   )rM   r   r   r   r   r   rO     s    z(Clauses.LinearBound_.<locals>.<listcomp>)
r   r   r   rX   tracemaxminr   r   r   )r   r   r   r   
preprocessrx   r   r   Znpruner   ZresZpruner   )r   r   r     s.    

zClauses.LinearBound_c             C   s   | j | j||||f||ddS )NF)r{   )r|   r   )r   r   r   r   r   rx   rg   r   r   r   LinearBound  s    zClauses.LinearBoundc             C   s.   t trt d|   | jj||d}|S )Nz"Invoking SAT with clause count: %s)rD   )rX   isEnabledForr	   rY   r   rc   r?   )r   r:   rD   r>   r   r   r   _run_sat  s    
zClauses._run_satc                s    j r
dS  js|rt S g S  j }|r^ fdd}t||}|r^|d sTdS  |  j j|d}|r|dks~|s j| |dkrdS |rtdd  fdd|D D S |S )	z
        Calculate a SAT solution for the current clause set.

        Returned is the list of those solutions.  When the clauses are
        unsatisfiable, an empty list is returned.

        Nc             3   sH    fdd}x6| D ].}t ||}|s.|V  P |d dk	r|V  qW d S )Nc             3   s:   x4| D ],} j ||}|dkr"q|V  |dkrP qW d S )NFT)r`   rk   )ccr   )r   r   r   preproc_  s    
z.Clauses.sat.<locals>.preproc.<locals>.preproc_r   T)r,   )Zeqsr   r   )r   r   r   preproc  s    
zClauses.sat.<locals>.preprocr   )rD   c             s   s"   | ]}|r|d  dkr|V  qdS )r   rd   Nr   )rM   Znmr   r   r   rt     s    zClauses.sat.<locals>.<genexpr>c             3   s   | ]} j |V  qd S )N)ra   rk   )rM   s)r   r   r   rt     s    )	rb   r:   r   rc   r   ru   r3   r   r   )r   Z
additionalZ	includeIfr`   rD   r   r   r>   r   )r   r   rL     s(    

 zClauses.satc             #   sV   g } d kr| j  x>| t||}|d kr0d S |V  | fdd|D  qW d S )Nc                s,   g | ]$}  |  kr krn q| qS r   r   )rM   k)r:   r   r   rO     s    z%Clauses.itersolve.<locals>.<listcomp>)r:   rL   r   r   )r   Zconstraintsr:   Zexcludesolr   )r:   r   rB     s    zClauses.itersolvec          	      s.  |dkst |jk r(td  }|dks6jrbtd ||r\tdd |D d ndfS |sxtd |dfS t|tkrfd	d
t	|D }
|\}}tdd |D }dd }dd }dd}xP|dkrdndD ]:}	|	rtd |}
ntd |}
dd |D }|
||  }j}ttrF }j }|rd|	sd|d }td|f  xB|dkr| d n||	rjtfdd|D  tfdd|D }|rj| nj|d ttr(td| | f   }|dkrVd td|f  n4k}|}|
||  }td|f  |rP |_j |krj| d_d}qzW td|	rdnd  f   dkrP q|	r fd!d
|D }|||} qtd"|||  qW | fS )#a  
        Minimize the objective function given either by (coeff, integer)
        tuple pairs, or a dictionary of varname: coeff values. The actual
        minimization is multiobjective: first, we minimize the largest
        active coefficient value, then we minimize the sum.
        Nz#Clauses added, recomputing solutionzConstraints are unsatisfiablec             s   s   | ]\}}t |V  qd S )N)r   )rM   r   r   r   r   r   rt   )  s    z#Clauses.minimize.<locals>.<genexpr>r   z!Empty objective, trivial solutionr   c                s"   g | ]\}}| j ||fqS r   )r`   rk   )rM   r   r.   )r   r   r   rO   /  s    z$Clauses.minimize.<locals>.<listcomp>c             s   s   | ]\}}|V  qd S )Nr   )rM   r   r   r   r   r   rt   2  s    c                s   t  fdd| D S )Nc             3   s   | ]}  |d V  qdS )r   N)rk   )rM   r   )r   r   r   rt   5  s    z5Clauses.minimize.<locals>.peak_val.<locals>.<genexpr>)r   )r   r   r   )r   r   peak_val4  s    z"Clauses.minimize.<locals>.peak_valc                s   t  fdd| D S )Nc             3   s   | ]}  |d V  qdS )r   N)rk   )rM   r   )r   r   r   rt   8  s    z4Clauses.minimize.<locals>.sum_val.<locals>.<genexpr>)r   )r   r   r   )r   r   sum_val7  s    z!Clauses.minimize.<locals>.sum_val)TF)FzBeginning peak minimizationzBeginning sum minimizationc             S   s   i | ]\}}||qS r   r   )rM   r   r   r   r   r   
<dictcomp>D  s    z$Clauses.minimize.<locals>.<dictcomp>zInitial range (%d,%d)r   c             3   s   | ]\}}| kr|V  qd S )Nr   )rM   r   r   )midr   r   rt   Y  s    c             3   s.   | ]&\}} |  krkrn q|V  qd S )Nr   )rM   r   r   )r   r   r   r   rt   Z  s    Fz+Bisection attempt: (%d,%d), (%d+%d) clausesz$Bisection failure, new range=(%d,%d)z$Bisection success, new range=(%d,%d)zFinal %s objective: %dpeakr   c                s    g | ]\}}| kr||fqS r   r   )rM   r   r   )bestvalr   r   rO     s    zNew peak objective: %d)r   r:   rX   rY   rL   rb   r   re   r   r   r   r   r   r   r	   r   rc   r   r   r   r,   r   r   r   )r   Z	objectiveZbestsolZtrymaxr   Zmaxvalr   r   Ztry0r   Zobjvalr   r   Zm_origZnzr   ZtempZnewsolZdoner   )r   r   r   r   r   minimize  s    

"





 




zClauses.minimize)N)N)T)NF)NN)F)NN)F)NN)F)NN)F)NN)N)NN)NN)NN)NN)NN)NN)NN)NN)NN)TNN)r   )NFFr   )NN)NF)3r!   r"   r#   rA   r   r   r   rh   ri   rj   rl   rm   rr   rn   rw   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rL   rB   r   r   r   r   r   r_   ,  s^   
	

	









)
	






	


	0


,
r_   c                s0   t  tk	rdd  D  t fdd|D S )Nc             S   s"   i | ]\}}t |tk	r||qS r   )re   rf   )rM   r.   r   r   r   r   r     s    zevaluate_eq.<locals>.<dictcomp>c             3   s&   | ]}t |tk	r |d V  qdS )r   N)re   rf   rk   )rM   r   )eqr   r   rt     s    zevaluate_eq.<locals>.<genexpr>)re   r   r   )r   r   r   )r   r   evaluate_eq  s    r   c                s>   t | } | rtddd d fdd	  | }|S )a  
    Given a set of clauses, find a minimal unsatisfiable subset (an
    unsatisfiable core)

    A set is a minimal unsatisfiable subset if no proper subset is
    unsatisfiable.  A set of clauses may have many minimal unsatisfiable
    subsets of different sizes.

    sat should be a function that takes a tuple of clauses and returns True if
    the clauses are satisfiable and False if they are not.  The algorithm will
    work with any order-reversing function (reversing the order of subset and
    the order False < True), that is, any function where (A <= B) iff (sat(B)
    <= sat(A)), where A <= B means A is a subset of B and False < True).

    Algorithm
    =========

    Algorithm suggested from
    http://www.slideshare.net/pvcpvc9/lecture17-31382688. We do a binary
    search on the clauses by splitting them in halves A and B. If A or B is
    UNSAT, we use that and repeat. Otherwise, we recursively check A, but each
    time we do a sat query, we include B, until we have a minimal subset A* of
    A such that A* U B is UNSAT. Then we find a minimal subset B* of B such
    that A* U B* is UNSAT. Then A* U B* will be a minimal unsatisfiable subset
    of the original set of clauses.

    Proof: If some proper subset C of A* U B* is UNSAT, then there is some
    clause c in A* U B* not in C. If c is in A*, then that means (A* - {c}) U
    B* is UNSAT, and hence (A* - {c}) U B is UNSAT, since it is a superset,
    which contradicts A* being the minimal subset of A with such
    property. Similarly, if c is in B, then A* U (B* - {c}) is UNSAT, but B* -
    {c} is a strict subset of B*, contradicting B* being the minimal subset of
    B with this property.

    zClauses are not unsatisfiablec             S   s,   t | } t| d }| d| | |d fS )z.
        Split S into two equal parts
        r   N)r,   r   )SLr   r   r   split  s    z+minimal_unsatisfiable_subset.<locals>.splitr   c                sl   t | dkr| S | \}}|| s2 ||S || sH ||S  ||| } ||| }|| S )z
        Return a minimal subset A of clauses such that A + include is
        unsatisfiable.

        Implicitly assumes that clauses + include is unsatisfiable.
        r   )r   )r)   ZincludeABZAstarZBstar)minimal_unsatrL   r   r   r   r     s    

z3minimal_unsatisfiable_subset.<locals>.minimal_unsat)r   )r,   
ValueError)r)   rL   r   r   )r   rL   r   r   minimal_unsatisfiable_subset  s    $r   N) r$   Z
__future__r   r   r   r   r   	itertoolsr   r   Zloggingr	   r
   compatr   r   Zbase.constantsr   r!   rX   objectr   r%   r/   rA   rH   rQ   rV   r^   r_   r   r   r   r   r   r   <module>   s*   ->0     b