B
    lz]E                 @   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 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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   )	iteritemsc               @   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_count2   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_state8   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_listG   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_arrayK   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   b   s    
zClauseArray.extendc             C   s   |  | | d d S )Nr   )r%   r$   )r   r'   r   r   r   r   f   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   j   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   s   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"   V   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)r.   r   )r   r   r   r   r      s    zSatSolver.get_clause_countc             C   s
   | j  S )N)r.   r   )r   r   r   r   r      s    zSatSolver.as_listc             C   s
   | j  S )N)r.   r   )r   r   r   r   r      s    zSatSolver.save_statec             C   s   | j |S )N)r.   r   )r   r   r   r   r   r      s    zSatSolver.restore_statec             K   s:   | j  }|| | j|f|}| |}| |}|S )N)r-   copyupdatesetupinvokeprocess_solution)r   mkwargsr1   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   r7   r8   r   r   r   r4      s    zSatSolver.setupc             C   s
   t  dS )z@Start the actual SAT solving and return the calculated solution.N)r=   )r   r9   r   r   r   r5      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   r6      s    zSatSolver.process_solutionN)r   r   r    r!   r   r   r   r   r   r<   r4   r5   r6   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pycosatr?   r.   r   )r   r7   limitr8   r?   r   r   r   r4      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   r5      s    
zPycoSatSolver.invokec             C   s   |dkrd S |S )N)rB   ZUNKNOWNr   )r   r:   r   r   r   r6      s    zPycoSatSolver.process_solutionN)r   )r   r   r    r4   r5   r6   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 )
CryptoMiniSatSolverr   c             K   s*   ddl m} ||d}|| j  |S )Nr   )Solver)threads)ZpycryptosatrF   r0   r.   r   )r   r7   rG   r8   rF   r9   r   r   r   r4      s    
zCryptoMiniSatSolver.setupc             C   s   |  \}}|sd }|S )N)solve)r   r9   satr:   r   r   r   r5      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   r6      s    z$CryptoMiniSatSolver.process_solutionN)r   )r   r   r    r4   r5   r6   r   r   r   r   rE      s   
rE   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.solversrO   Zappend_formular.   r   )r   r7   r8   rO   r9   r   r   r   r4      s    zPySatSolver.setupc             C   s"   |  sd }n| }|  |S )N)rH   Z	get_modeldelete)r   r9   r:   r   r   r   r5      s
    zPySatSolver.invokec             C   s   |d krd }n|}|S )Nr   )r   r:   r;   r   r   r   r6     s    zPySatSolver.process_solutionN)r   r   r    r4   r5   r6   r   r   r   r   rN      s   rN   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unsatr7   _sat_solverr/   r0   )r   r7   Zsat_solver_clsr   r   r   r     s    
zClauses.__init__c             C   s
   | j  S )N)rU   r   )r   r   r   r   r     s    zClauses.get_clause_countc             C   s
   | j  S )N)rU   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!)rR   typeboolrS   )r   r7   nameZnnamer   r   r   name_var   s    

zClauses.name_varc             C   s   | j d }|| _ |S )Nr   )r7   )r   r7   r   r   r   _new_var)  s    
zClauses._new_varNc             C   s   |   }|r| || |S )N)r[   rZ   )r   rY   r7   r   r   r   new_var.  s    zClauses.new_varc             C   s   | j |S )N)rR   get)r   rY   r   r   r   	from_name4  s    zClauses.from_namec             C   s   | j |S )N)rS   r]   )r   r7   r   r   r   
from_index7  s    zClauses.from_indexc             C   sH   |  |}|s|S t|tr<|  }| |r2|fn| f | ||S )N)_assign_no_name
isinstancerX   r[   r/   rZ   )r   valsrY   xr   r   r   Assign_:  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   )rJ   y)rc   r   r   	<genexpr>F  s    z*Clauses._assign_no_name.<locals>.<genexpr>r   c             3   s   | ]} f| V  qd S )Nr   )rJ   re   )rc   r   r   rf   G  s    r   )ra   r)   r[   r0   )r   rb   r   )rc   r   r`   C  s    
zClauses._assign_no_namec             C   sV   t |}|}|ttfkr(|t| j|S |ttfkrH|| jkrH| |}| j	||S )N)
rW   r)   listmapConvert_rX   intrR   r\   r]   )r   rc   ZtxrY   r   r   r   ri   K  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   )ri   rU   r   r`   rd   rW   r)   r0   rX   r/   r   rT   )	r   funcargsrk   rY   convr   rb   Ztvalsr   r   r   Eval_]  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   )rJ   r+   r   r   r   rf   s  s    z#Clauses.Combine_.<locals>.<genexpr>Fc             S   s   g | ]}|d k	r|qS )Tr   )rJ   r+   r   r   r   rL   u  s    z$Clauses.Combine_.<locals>.<listcomp>r   Tr   c             s   s   | ]}t |tkV  qd S )N)rW   r)   )rJ   r+   r   r   r   rf   {  s    c             s   s   | ]}|d  V  qdS )r   Nr   )rJ   r+   r   r   r   rf   |  s    c             s   s   | ]}|d  V  qdS )r   Nr   )rJ   r+   r   r   r   rf   |  s    )anyr   allsumAll_rh   rd   )r   rm   rk   nvr   r   r   Combine_r  s    (zClauses.Combine_c             G   s   | | t|dddS )NF)rk   rY   )__get__rQ   )r   whatrm   r   r   r   Prevent  s    zClauses.Preventc             G   s   | | t|dddS )NTF)rk   rY   )rv   rQ   )r   rw   rm   r   r   r   Require  s    zClauses.RequireFc             C   s   t |tkr| S | S )N)rW   rX   )r   rc   rk   add_new_clausesr   r   r   Not_  s    zClauses.Not_c             C   s   |  | j|f||S )N)ro   r{   )r   rc   rk   rY   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)r\   r0   )r   fgrk   rz   rc   pvalnvalr   r   r   And_  s,    

zClauses.And_c             C   s   |  | j||f||S )N)ro   r   )r   r}   r~   rk   rY   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)r\   r0   )r   r}   r~   rk   rz   rc   r   r   r   r   r   Or_  s,    

zClauses.Or_c             C   s   |  | j||f||S )N)ro   r   )r   r}   r~   rk   rY   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)rz   )TN)FN)r{   r\   r0   )r   r}   r~   rk   rz   rc   r   r   r   r   r   Xor_  s0    

" "zClauses.Xor_c             C   s   |  | j||f||S )N)ro   r   )r   r}   r~   rk   rY   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)rz   )TN)FN)r   r   r   r\   r0   )	r   r   tr}   rk   rz   rc   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.
        )ro   r   )r   r   r   r}   rk   rY   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   )rJ   r+   r   r   r   rf   !  s    zClauses.All_.<locals>.<genexpr>)TNc             S   s   g | ]
}|fqS r   r   )rJ   r+   r   r   r   rL   "  s    z Clauses.All_.<locals>.<listcomp>)FNc             s   s   | ]}| V  qd S )Nr   )rJ   r+   r   r   r   rf   #  s    )setaddr   rC   r)   )r   iterrk   rb   r+   rt   r   r   r   r   r   rs     s    
 zClauses.All_c             C   s   |  | j|f||S )N)ro   rs   )r   r   rk   rY   r   r   r   All&  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   )rJ   r+   r   r   r   rf   5  s    zClauses.Any_.<locals>.<genexpr>)TN)FNc             S   s   g | ]}| fqS r   r   )rJ   r+   r   r   r   rL   7  s    z Clauses.Any_.<locals>.<listcomp>)r   r   r   rC   r)   )r   r   rk   rb   r+   rt   r   r   r   r   r   Any_)  s    
zClauses.Any_c             C   s   |  | jt|f||S )N)ro   r   rg   )r   rb   rk   rY   r   r   r   Any:  s    zClauses.Anyc             C   sD   g }x2t t| j|dD ]\}}|| ||| qW | ||S )N   )r   rh   r{   r   r   ru   )r   rb   rk   Zcombosv1v2r   r   r   AtMostOne_NSQ_=  s    zClauses.AtMostOne_NSQ_c             C   s   |  | jt|f||S )N)ro   r   rg   )r   rb   rk   rY   r   r   r   AtMostOne_NSQC  s    zClauses.AtMostOne_NSQc             C   s    dd |D }|  |ddd|S )Nc             S   s   g | ]}d |fqS )r   r   )rJ   r+   r   r   r   rL   G  s    z*Clauses.AtMostOne_BDD_.<locals>.<listcomp>r   r   T)LinearBound_)r   rb   rk   rY   r   r   r   AtMostOne_BDD_F  s    zClauses.AtMostOne_BDD_c             C   s   |  | jt|f||S )N)ro   r   rg   )r   rb   rk   rY   r   r   r   AtMostOne_BDDJ  s    zClauses.AtMostOne_BDDc             C   s@   t |}t|}|d|dk	 k r(| j}n| j}| ||f||S )N   T)rg   r   r   r   ro   )r   rb   rk   rY   rt   rw   r   r   r   	AtMostOneM  s    zClauses.AtMostOnec             C   s0   t |}| ||}| ||}| ||f|S )N)rg   r   r   ru   )r   rb   rk   r   r   r   r   r   ExactlyOne_NSQ_V  s    zClauses.ExactlyOne_NSQ_c             C   s   |  | jt|f||S )N)ro   r   rg   )r   rb   rk   rY   r   r   r   ExactlyOne_NSQ\  s    zClauses.ExactlyOne_NSQc             C   s    dd |D }|  |ddd|S )Nc             S   s   g | ]}d |fqS )r   r   )rJ   r+   r   r   r   rL   `  s    z+Clauses.ExactlyOne_BDD_.<locals>.<listcomp>r   T)r   )r   rb   rk   r   r   r   ExactlyOne_BDD__  s    zClauses.ExactlyOne_BDD_c             C   s   |  | jt|f||S )N)ro   r   rg   )r   rb   rk   rY   r   r   r   ExactlyOne_BDDc  s    zClauses.ExactlyOne_BDDc             C   s8   t |}t|}|dk r | j}n| j}| ||f||S )Nr   )rg   r   r   r   ro   )r   rb   rk   rY   rt   rw   r   r   r   
ExactlyOnef  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   )rR   r]   )rJ   ar   )r   r   r   rL   q  s    z*Clauses.LB_Preprocess_.<locals>.<listcomp>c             s   s&   | ]\}}|d kpt |tkV  qdS )r   N)rW   rX   )rJ   r   r   r   r   r   rf   r  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   )rJ   r   r   r   r   r   rf   s  s    c             S   s<   g | ]4\}}t |tk	r|r|d kr,||fn
| | fqS )r   )rW   rX   )rJ   r   r   r   r   r   rL   t  s    r   )rW   dictr   rp   rr   sorted)r   equationoffsetr   )r   r   LB_Preprocess_o  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   )rJ   r   _r   r   r   rf     s    zClauses.BDD_.<locals>.<genexpr>r   r   TF)rz   )rr   r   popr]   r   abs)r   r   ntermslohirk   totaltargetZ
call_stackZ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   )rJ   r   r   )r   r   r   rf     s    z'Clauses.LinearBound_.<locals>.<genexpr>z+Eliminating %d/%d terms for bound violationc             s   s   | ]\}}|V  qd S )Nr   )rJ   r   r   r   r   r   rf     s    Fc             S   s   g | ]\}}| qS r   r   )rJ   r   r   r   r   r   rL     s    z(Clauses.LinearBound_.<locals>.<listcomp>)
r   r   rr   logtracemaxminr   rs   ru   )r   r   r   r   
preprocessrk   r   r   Znpruner   ZresZpruner   )r   r   r     s.    

zClauses.LinearBound_c             C   s   | j | j||||f||ddS )NF)rn   )ro   r   )r   r   r   r   r   rk   rY   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)rA   )r   isEnabledForr	   debugr   rU   r<   )r   r7   rA   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)rR   r]   )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   )rA   c             s   s"   | ]}|r|d  dkr|V  qdS )r   rV   Nr   )rJ   Znmr   r   r   rf     s    zClauses.sat.<locals>.<genexpr>c             3   s   | ]} j |V  qd S )N)rS   r]   )rJ   s)r   r   r   rf     s    )	rT   r7   r   rU   r   rg   r0   r   r   )r   Z
additionalZ	includeIfrR   rA   r   r   r;   r   )r   r   rI     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   )rJ   k)r7   r   r   rL   
  s    z%Clauses.itersolve.<locals>.<listcomp>)r7   rI   r   r   )r   Zconstraintsr7   Zexcludesolr   )r7   r   r?     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}x\|dkrdndD ]F}	|	rtd |}
ntd |}
dd |D }|
||  }j}ttrF }j }|rd|	sd|d }td|f  xN|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rbd td|f  |krP 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   )rJ   r   r   r   r   r   rf     s    z#Clauses.minimize.<locals>.<genexpr>r   z!Empty objective, trivial solutionr   c                s"   g | ]\}}| j ||fqS r   )rR   r]   )rJ   r   r+   )r   r   r   rL     s    z$Clauses.minimize.<locals>.<listcomp>c             s   s   | ]\}}|V  qd S )Nr   )rJ   r   r   r   r   r   rf   !  s    c                s   t  fdd| D S )Nc             3   s   | ]}  |d V  qdS )r   N)r]   )rJ   r   )odictr   r   rf   $  s    z5Clauses.minimize.<locals>.peak_val.<locals>.<genexpr>)r   )r   r   r   )r   r   peak_val#  s    z"Clauses.minimize.<locals>.peak_valc                s   t  fdd| D S )Nc             3   s   | ]}  |d V  qdS )r   N)r]   )rJ   r   )r   r   r   rf   '  s    z4Clauses.minimize.<locals>.sum_val.<locals>.<genexpr>)rr   )r   r   r   )r   r   sum_val&  s    z!Clauses.minimize.<locals>.sum_val)TF)FzBeginning peak minimizationzBeginning sum minimizationc             S   s   i | ]\}}||qS r   r   )rJ   r   r   r   r   r   
<dictcomp>3  s    z$Clauses.minimize.<locals>.<dictcomp>zInitial range (%d,%d)r   c             3   s   | ]\}}| kr|V  qd S )Nr   )rJ   r   r   )midr   r   rf   H  s    c             3   s.   | ]&\}} |  krkrn q|V  qd S )Nr   )rJ   r   r   )r   r   r   r   rf   I  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peakrr   c                s    g | ]\}}| kr||fqS r   r   )rJ   r   r   )bestvalr   r   rL   r  s    zNew peak objective: %d)r   r7   r   r   rI   rT   rr   rW   r   r   r   r   r   r   r	   r   rU   r   rx   r   r)   ry   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    r>   r   r   r   rZ   r[   r\   r^   r_   rd   r`   ri   ro   ru   rx   ry   r{   r|   r   r   r   r   r   r   r   r   rs   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rI   r?   r   r   r   r   r   rQ     s^   
	

	









)
	






	


	0


,
rQ   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   )rW   rX   )rJ   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)rW   rX   r]   )rJ   r   )eqr   r   rf   ~  s    zevaluate_eq.<locals>.<genexpr>)rW   r   rr   )r   r   r   )r   r   evaluate_eq{  s    r   c             C   sp   t  }t  }||ddkr$t |}nt |}x>t | | D ].}|||hB ddkr^|| q:|| q:W |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).

    TN)r   r   )r&   rI   Zexplicit_specsZworking_setZfound_conflictsspecr   r   r   minimal_unsatisfiable_subset  s    
r   N)r!   Z
__future__r   r   r   r   r   	itertoolsr   r   Zloggingr	   r
   compatr   r   r   objectr   r"   r,   r>   rE   rN   rQ   r   r   r   r   r   r   <module>   s&   ->0    p