o
    oh#                     @   s   d Z ddlmZ ddlmZmZmZmZmZm	Z	m
Z
 ddlmZ ddlmZmZ dd Zdd	 Zd
d Zi fddZdd Zdd Zdd Zdd Zdd Zdd ZdS )a&  Implementation of DPLL algorithm

Further improvements: eliminate calls to pl_true, implement branching rules,
efficient unit propagation.

References:
  - https://en.wikipedia.org/wiki/DPLL_algorithm
  - https://www.researchgate.net/publication/242384772_Implementations_of_the_DPLL_Algorithm
    )default_sort_key)OrNot	conjuncts	disjunctsto_cnfto_int_repr_find_predicates)CNF)pl_trueliteral_symbolc                 C   s   t | tstt| }n| j}d|v rdS tt| td}tt	dt
|d }t||}t||i }|s7|S i }|D ]}|||d  || i q;|S )a>  
    Check satisfiability of a propositional sentence.
    It returns a model rather than True when it succeeds

    >>> from sympy.abc import A, B
    >>> from sympy.logic.algorithms.dpll import dpll_satisfiable
    >>> dpll_satisfiable(A & ~B)
    {A: True, B: False}
    >>> dpll_satisfiable(A & ~A)
    False

    F)key   )
isinstancer
   r   r   clausessortedr	   r   setrangelenr   dpll_int_reprupdate)exprr   symbolssymbols_int_reprclauses_int_reprresultoutputr    r   o/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/logic/algorithms/dpll.pydpll_satisfiable   s   

r   c           
      C   sH  t | |\}}|r(|||i || |s| }t| |} t | |\}}|s	t|| \}}|rP|||i || |sB| }t| |} t|| \}}|s1g }| D ]}t||}|du rb dS |durk|| qT|sp|S | st|S | }| }||di ||di |dd }	t	t||||pt	t|t
||	|S )z
    Compute satisfiability in a partial model.
    Clauses is an array of conjuncts.

    >>> from sympy.abc import A, B, D
    >>> from sympy.logic.algorithms.dpll import dpll
    >>> dpll([A, B, D], [A, B], {D: False})
    False

    FTN)find_unit_clauser   removeunit_propagatefind_pure_symbolr   appendpopcopydpllr   
r   r   modelPvalueunknown_clausescval
model_copysymbols_copyr   r   r   r'   1   sL   





r'   c           
      C   s:  t | |\}}|r(|||i || |s| }t| |} t | |\}}|s	t|| \}}|rP|||i || |sB| }t| |} t|| \}}|s1g }| D ]}t||}|du rb dS |durk|| qT|sp|S | }| }||di ||di | }	t	t||||pt	t|| |	|S )z
    Compute satisfiability in a partial model.
    Arguments are expected to be in integer representation

    >>> from sympy.logic.algorithms.dpll import dpll_int_repr
    >>> dpll_int_repr([{1}, {2}, {3}], {1, 2}, {3: False})
    False

    FT)
find_unit_clause_int_reprr   r!   unit_propagate_int_reprfind_pure_symbol_int_reprpl_true_int_reprr$   r%   r&   r   r(   r   r   r   r   b   sH   





r   c                 C   sZ   d}| D ]&}|dk r| | }|dur| }n| |}|du r$ dS |du r*d}q|S )af  
    Lightweight version of pl_true.
    Argument clause represents the set of args of an Or clause. This is used
    inside dpll_int_repr, it is not meant to be used directly.

    >>> from sympy.logic.algorithms.dpll import pl_true_int_repr
    >>> pl_true_int_repr({1, 2}, {1: False})
    >>> pl_true_int_repr({1, 2}, {1: False, 2: False})
    False

    Fr   NT)get)clauser)   r   litpr   r   r   r4      s   
r4   c                    sv   g }| D ]4}|j tkr|| q|jD ]}|  kr,|t fdd|jD    n| kr2 nq|| q|S )a  
    Returns an equivalent set of clauses
    If a set of clauses contains the unit clause l, the other clauses are
    simplified by the application of the two following rules:

      1. every clause containing l is removed
      2. in every clause that contains ~l this literal is deleted

    Arguments are expected to be in CNF.

    >>> from sympy.abc import A, B, D
    >>> from sympy.logic.algorithms.dpll import unit_propagate
    >>> unit_propagate([A | B, D | ~B, B], B)
    [D, B]

    c                    s   g | ]	}|  kr|qS r   r   ).0xsymbolr   r   
<listcomp>   s    z"unit_propagate.<locals>.<listcomp>)funcr   r$   args)r   r<   r   r-   argr   r;   r   r"      s   




r"   c                    s    h  fdd| D S )z
    Same as unit_propagate, but arguments are expected to be in integer
    representation

    >>> from sympy.logic.algorithms.dpll import unit_propagate_int_repr
    >>> unit_propagate_int_repr([{1, 2}, {3, -2}, {2}], 2)
    [{3}]

    c                    s   g | ]
}|vr|  qS r   r   )r9   r6   negatedsr   r   r=      s    z+unit_propagate_int_repr.<locals>.<listcomp>r   )r   rC   r   rA   r   r2      s   
r2   c                 C   s`   | D ]+}d\}}|D ]}|s|t |v rd}|s"t|t |v r"d}q
||kr-||f  S qdS )a#  
    Find a symbol and its value if it appears only as a positive literal
    (or only as a negative) in clauses.

    >>> from sympy.abc import A, B, D
    >>> from sympy.logic.algorithms.dpll import find_pure_symbol
    >>> find_pure_symbol([A, B, D], [A|~B,~B|~D,D|A])
    (A, True)

    )FFTNN)r   r   )r   r,   sym	found_pos	found_negr-   r   r   r   r#      s   r#   c                 C   sp   t  j| }|| }|dd | D }|D ]}| |vr$|df  S q|D ]}| |vr5| df  S q'dS )a  
    Same as find_pure_symbol, but arguments are expected
    to be in integer representation

    >>> from sympy.logic.algorithms.dpll import find_pure_symbol_int_repr
    >>> find_pure_symbol_int_repr({1,2,3},
    ...     [{1, -2}, {-2, -3}, {3, 1}])
    (1, True)

    c                 S   s   g | ]}| qS r   r   )r9   rC   r   r   r   r=          z-find_pure_symbol_int_repr.<locals>.<listcomp>TFrD   )r   unionintersection)r   r,   all_symbolsrF   rG   r8   r   r   r   r3      s   


r3   c                 C   s^   | D ]*}d}t |D ]}t|}||vr!|d7 }|t|t }}q
|dkr,||f  S qdS )a  
    A unit clause has only 1 variable that is not bound in the model.

    >>> from sympy.abc import A, B, D
    >>> from sympy.logic.algorithms.dpll import find_unit_clause
    >>> find_unit_clause([A | B | D, B | ~D, A | ~B], {A:True})
    (B, False)

    r   r   rD   )r   r   r   r   )r   r)   r6   num_not_in_modelliteralrE   r*   r+   r   r   r   r    
  s   
r    c                 C   sb   t |dd |D B }| D ]!}|| }t|dkr.| }|dk r(| df  S |df  S qdS )a  
    Same as find_unit_clause, but arguments are expected to be in
    integer representation.

    >>> from sympy.logic.algorithms.dpll import find_unit_clause_int_repr
    >>> find_unit_clause_int_repr([{1, 2, 3},
    ...     {2, -3}, {1, -2}], {1: True})
    (2, False)

    c                 S   s   h | ]}| qS r   r   )r9   rE   r   r   r   	<setcomp>+  rH   z,find_unit_clause_int_repr.<locals>.<setcomp>r   r   FTrD   )r   r   r%   )r   r)   boundr6   unboundr8   r   r   r   r1      s   r1   N)__doc__sympy.core.sortingr   sympy.logic.boolalgr   r   r   r   r   r   r	   sympy.assumptions.cnfr
   sympy.logic.inferencer   r   r   r'   r   r4   r"   r2   r#   r3   r    r1   r   r   r   r   <module>   s    
$10!