U
    b*                     @   sl   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mZ eZeZdZdZdZG d	d
 d
e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)chain   )ClausesFALSETRUEZpycosatZpycryptosatZpysatc                   @   sX  e Zd ZdefddZedd Zedd Zdd	 Zd
d Z	dd Z
dd Zdd Zdd Zdd ZdKddZdd Zdd ZdLddZdd  Zd!d" Zd#d$ Zd%d& ZdMd'd(ZdNd)d*ZdOd+d,ZdPd-d.ZdQd/d0ZdRd1d2ZdSd3d4ZdTd5d6ZdUd7d8ZdVd9d:Z dWd;d<Z!dXd=d>Z"dYd?d@Z#dZdBdCZ$d[dEdFZ%d\dGdHZ&d]dIdJZ'dS )^r   r   c                 C   s   i | _ i | _t||d| _d S )N)mZsat_solver_str)namesindices_Clauses_clauses)selfr   Z
sat_solver r   1lib/python3.8/site-packages/conda/common/logic.py__init__3   s    zClauses.__init__c                 C   s   | j jS N)r   r   r   r   r   r   r   8   s    z	Clauses.mc                 C   s   | j jS r   )r   unsatr   r   r   r   r   <   s    zClauses.unsatc                 C   s
   | j  S r   )r   get_clause_countr   r   r   r   r   @   s    zClauses.get_clause_countc                 C   s
   | j  S r   )r   as_listr   r   r   r   r   C   s    zClauses.as_listc                 C   s8   dt |  k r| jkr"n n|S td|| jd S )Nr   z,SAT variable out of bounds: {} (max_var: {}))absr   
ValueErrorformat)r   Zvariabler   r   r   _check_variableF   s    zClauses._check_variablec                 C   s   |t thkr|S | |S r   )r
   r	   r   )r   literalr   r   r   _check_literalK   s    zClauses._check_literalc                 C   s   | j t| j| | d S r   )r   
add_clausemapr   _convert)r   clauser   r   r   r   P   s    zClauses.add_clausec                 C   s   |D ]}|  | qd S r   )r   )r   clausesr"   r   r   r   add_clausesS   s    zClauses.add_clausesc                 C   sX   |  | d| }|| j|< | | j|< |tthkrT|| jkrT|| j|< || j| < |S )N!)r   r   r
   r	   r   )r   r   nameZnnamer   r   r   name_varW   s    


zClauses.name_varNc                 C   s   | j  }|r| || |S r   )r   new_varr'   )r   r&   r   r   r   r   r(   a   s    
zClauses.new_varc                 C   s   | j |S r   r   get)r   r&   r   r   r   	from_nameg   s    zClauses.from_namec                 C   s   | j |S r   r   r*   )r   r   r   r   r   
from_indexj   s    zClauses.from_indexc                 C   sP   | j |}|s|S |tthkrD| j  }| j |r:|fn| f | ||S r   )r   Zassignr
   r	   r(   r   r'   )r   valsr&   xr   r   r   _assignm   s    
zClauses._assignc                 C   sn   t |ttfr"t|t| j|S t |tr6| |S |}z| j| W S  t	k
rh   t
d|Y nX d S )Nz"Unregistered SAT variable name: {})
isinstancetuplelisttyper    r!   intr   r   KeyErrorr   r   )r   r/   r&   r   r   r   r!   v   s    

zClauses._convertc                 C   sH   |  |}|dkr*| j||| | d S ||| d|i}| ||S )NFpolarity)r!   r   ZEvalr0   )r   funcargsZno_literal_argsr7   r&   r.   r   r   r   _eval   s    
zClauses._evalc                 G   s   | | t|dddS )NFr7   r&   __get__r   r   whatr9   r   r   r   Prevent   s    zClauses.Preventc                 G   s   | | t|dddS )NTFr;   r<   r>   r   r   r   Require   s    zClauses.Requirec                 C   s   |  | jj|fd||S Nr   )r:   r   Not)r   r/   r7   r&   r   r   r   rC      s    zClauses.Notc                 C   s   |  | jj||fd||S rB   )r:   r   Andr   fgr7   r&   r   r   r   rD      s    zClauses.Andc                 C   s   |  | jj||fd||S rB   )r:   r   OrrE   r   r   r   rH      s    z
Clauses.Orc                 C   s   |  | jj||fd||S rB   )r:   r   XorrE   r   r   r   rI      s    zClauses.Xorc                 C   s   |  | jj|||fd||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   ITE)r   ctrF   r7   r&   r   r   r   rJ      s    zClauses.ITEc                 C   s   |  | jj|fd||S rB   )r:   r   All)r   iterr7   r&   r   r   r   rM      s    zClauses.Allc                 C   s   |  | jjt|fd||S rB   )r:   r   Anyr3   r   r.   r7   r&   r   r   r   rO      s    zClauses.Anyc                 C   s   |  | jjt|fd||S rB   )r:   r   AtMostOne_NSQr3   rP   r   r   r   rQ      s    zClauses.AtMostOne_NSQc                 C   s   |  | jjt|fd||S rB   )r:   r   AtMostOne_BDDr3   rP   r   r   r   rR      s    zClauses.AtMostOne_BDDc                 C   sB   t |}t|}|d|dk	 k r(| j}n| j}| ||fd||S )N   Tr   )r3   lenrQ   rR   r:   r   r.   r7   r&   Znvr?   r   r   r   	AtMostOne   s    zClauses.AtMostOnec                 C   s   |  | jjt|fd||S rB   )r:   r   ExactlyOne_NSQr3   rP   r   r   r   rW      s    zClauses.ExactlyOne_NSQc                 C   s   |  | jjt|fd||S rB   )r:   r   ExactlyOne_BDDr3   rP   r   r   r   rX      s    zClauses.ExactlyOne_BDDc                 C   s:   t |}t|}|dk r | j}n| j}| ||fd||S )N   r   )r3   rT   rW   rX   r:   rU   r   r   r   
ExactlyOne   s    zClauses.ExactlyOneTc           	      C   sP   t |tsdd |D }t| }t| }| | jj|f||||f||S )Nc                 S   s   i | ]\}}||qS r   r   .0ZcoeffZ	named_litr   r   r   
<dictcomp>   s      z'Clauses.LinearBound.<locals>.<dictcomp>)r1   dictr3   keysvaluesr:   r   LinearBound)	r   ZequationlohiZ
preprocessr7   r&   Znamed_literalsZcoefficientsr   r   r   ra      s    
 
  zClauses.LinearBoundFc                    sz    j r
dS  js|rt S g S |r4 fdd|D } jj|||d}|dkrRdS |rvt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   s$   | ]}t  fd d|D V  qdS )c                 3   s   | ]} j ||V  qd S r   r)   )r\   rK   r   r   r   	<genexpr>   s     z(Clauses.sat.<locals>.<genexpr>.<genexpr>N)r2   )r\   Zccr   r   r   rd      s     zClauses.sat.<locals>.<genexpr>)
additional	includeIflimitc                 s   s"   | ]}|r|d  dkr|V  qdS )r   r%   Nr   )r\   Znmr   r   r   rd      s       c                 3   s   | ]} j |V  qd S r   r,   )r\   sr   r   r   rd      s     )r   r   setr   sat)r   re   rf   r   rg   Zsolutionr   r   r   rj      s     zClauses.satc                 #   sR   g } d kr| j  | t||}|d kr.d S |V  | fdd|D  qd S )Nc                    s,   g | ]$}  |  kr krn q| qS r   r   )r\   kr   r   r   
<listcomp>   s
      
  z%Clauses.itersolve.<locals>.<listcomp>)r   rj   r   append)r   Zconstraintsr   ZexcludeZsolr   rl   r   	itersolve   s    zClauses.itersolvec                 C   sJ   t |tsdd |D }| t| }t| }| jj||||dS )Nc                 S   s   i | ]\}}||qS r   r   r[   r   r   r   r]      s      z$Clauses.minimize.<locals>.<dictcomp>)bestsoltrymax)r1   r^   r!   r3   r_   r`   r   minimize)r   Z	objectiverp   rq   literalsZcoeffsr   r   r   rr      s
    
zClauses.minimize)N)N)NN)NN)NN)NN)NN)NN)NN)NN)NN)NN)NN)NN)NN)TNN)NFFr   )NN)NF)(__name__
__module____qualname__PycoSatSolverr   propertyr   r   r   r   r   r   r   r$   r'   r(   r+   r-   r0   r!   r:   r@   rA   rC   rD   rH   rI   rJ   rM   rO   rQ   rR   rV   rW   rX   rZ   ra   rj   ro   rr   r   r   r   r   r   2   sJ   




	




	




	


	


r   c                 C   sl   t  }t  }||ddkr$t |}nt |}t | | D ].}|||hB ddkr\|| q8|| q8|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)ri   add)r#   rj   Zexplicit_specsZworking_setZfound_conflictsspecr   r   r   minimal_unsatisfiable_subset  s    
r{   N)__doc__Z
__future__r   r   r   r   	itertoolsr   Z_logicr   r   r	   r
   rw   ZPyCryptoSatSolverZPySatSolverobjectr{   r   r   r   r   <module>   s    P