
    \h#                         S r SSKJr  SSKJrJrJrJrJrJ	r	J
r
  SSKJr  SSKJrJr  S rS rS r0 4S	 jrS
 rS rS rS rS rS rg)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                 z   [        U [        5      (       d  [        [        U 5      5      nOU R                  nSU;   a  g[        [        U 5      [        S9n[        [        S[        U5      S-   5      5      n[        X5      n[        XC0 5      nU(       d  U$ 0 nU H  nUR                  X'S-
     XW   05        M     U$ )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   s           S/var/www/auris/envauris/lib/python3.13/site-packages/sympy/logic/algorithms/dpll.pydpll_satisfiabler       s     dC  F4L),,%d+1ABG5CL1$456"74+rBFFwQw'56 M    c                 $   [        X5      u  p4U(       aN  UR                  X405        UR                  U5        U(       d  U) n[        X5      n [        X5      u  p4U(       a  MN  [	        X5      u  p4U(       aN  UR                  X405        UR                  U5        U(       d  U) n[        X5      n [	        X5      u  p4U(       a  MN  / nU  H-  n[        Xb5      nUSL a    gUSLd  M  UR                  U5        M/     U(       d  U$ U (       d  U$ UR                  5       nUR                  5       nUR                  US05        UR                  US05        USS n	[        [        XS5      X5      =(       d    [        [        U[        U5      5      X5      $ )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_copys
             r   r*   r*   1   sc     /HA
aZ qA ,#G3 !  1HA
aZ qA ,#G5 ! Oa%<d?""1%  AJ	LL!Tq%j!1:L3WD TQ8,SUr!   c                    [        X5      u  p4U(       aN  UR                  X405        UR                  U5        U(       d  U* n[        X5      n [        X5      u  p4U(       a  MN  [	        X5      u  p4U(       aN  UR                  X405        UR                  U5        U(       d  U* n[        X5      n [	        X5      u  p4U(       a  MN  / nU  H-  n[        Xb5      nUSL a    gUSLd  M  UR                  U5        M/     U(       d  U$ UR                  5       nUR                  5       nUR                  US05        UR                  US05        UR                  5       n	[        [        XS5      X5      =(       d    [        [        XS* 5      X5      $ )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+   s
             r   r   r   b   s[    )8HA
aZ qA)'5,W< ! ):HA
aZ qA)'5,W> ! Oq(%<d?""1%  AJ	LL!Tq%j!<<>L1/EwV b1/2Facr!   c                     SnU  HE  nUS:  a  UR                  U* 5      nUb  U(       + nOUR                  U5      nUSL a    gUb  MC  SnMG     U$ )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ps        r   r8   r8      s^     F7		3$A}E		#A9YF  Mr!   c                 R   / nU  H  nUR                   [        :w  a  UR                  U5        M*  UR                   HN  nXA) :X  a=  UR                  [        UR                   Vs/ s H  oUU) :w  d  M  UPM     sn6 5          M|  XA:X  d  MM    M     UR                  U5        M     U$ s  snf )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]

)funcr   r'   args)r   symbolr   r0   argxs         r   r%   r%      s    " F66R<MM!66Cg~baff"EffW1f"EFG}  MM!  M #Fs   "
B$0B$c                 L    U* 1nU  Vs/ s H  o1U;  d  M
  X2-
  PM     sn$ s  snf )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}]

 )r   snegatedr;   s       r   r6   r6      s/     rdG+2F7voF7FFFs   	!!c                     U  HW  nSu  p4U H@  nU(       d  U[        U5      ;   a  SnU(       a  M$  [        U5      [        U5      ;   d  M>  SnMB     X4:w  d  MT  X#4s  $    g)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_negr0   s         r   r&   r&      sa     +	 A	!!4 	9SYq\!9 		 !
 !>!  r!   c                     [        5       R                  " U6 nUR                  U 5      nUR                  U  Vs/ s H  oD* PM     sn5      nU H  nU* U;  d  M  US4s  $    U H  nU* U;  d  M  U* S4s  $    gs  snf )z
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)

TFrI   )r   unionintersection)r   r/   all_symbolsrK   rF   rL   r=   s          r   r7   r7      s     %++/K((1I((g)>g"g)>?I2Yd7N  2Y2u9   *?s   A9c                     U  HP  nSn[        U5       H0  n[        U5      nXQ;  d  M  US-  nU[        U[        5      (       + pvM2     US:X  d  ML  WW4s  $    g)z
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   rI   )r   r   r   r   )r   r,   r;   num_not_in_modelliteralrJ   r-   r.   s           r   r#   r#   
  sg      (G )C A% Jw$< <5	 )
 q e8O  r!   c                     [        U5      U Vs1 s H  o"* iM     sn-  nU  H9  nXC-
  n[        U5      S:X  d  M  UR                  5       nUS:  a  U* S4s  $ US4s  $    gs  snf )z
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)

r   r   FTrI   )r   r   r(   )r   r,   rJ   boundr;   unboundr=   s          r   r5   r5      so     J%0%3$%00E.w<1A1ur5y $w   1s   A N)__doc__sympy.core.sortingr   sympy.logic.boolalgr   r   r   r   r   r	   r
   sympy.assumptions.cnfr   sympy.logic.inferencer   r   r    r*   r   r8   r%   r6   r&   r7   r#   r5   rE   r!   r   <module>r\      sa    0" " " % 9>.Ub+c` $& 6BG..,r!   