+
    iS                         R t ^ RIHt ^ RIHtHt ^ RIHt ^ RIH	t	 ^ RI
Ht RR ltR t ! R R	4      t ! R
 R4      tR# )zImplementation of DPLL algorithm

Features:
  - Clause learning
  - Watch literal scheme
  - VSIDS heuristic

References:
  - https://en.wikipedia.org/wiki/DPLL_algorithm
)defaultdict)heappushheappop)ordered)
EncodedCNF)	LRASolverc                   \        V \        4      '       g   \        4       pVP                  V 4       Tp ^ 0V P                  9   d   V'       d
   R R 4       # R# V'       d   \        P
                  ! V 4      w  rEMRp. p\        V P                  V,           V P                  \        4       V P                  VR7      pVP                  4       pV'       d   \        V4      #  \        V4      #   \         d     R# i ; i)ah  
Check satisfiability of a propositional sentence.
It returns a model rather than True when it succeeds.
Returns a generator of all models if all_models is True.

Examples
========

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

c              3   $   "   T F  qx  K  	  R # 5iN ).0fs   & Z/var/www/html/photoedit/myenv/lib/python3.14/site-packages/sympy/logic/algorithms/dpll2.py	<genexpr>#dpll_satisfiable.<locals>.<genexpr>.   s     'w!Aws   FN)
lra_theoryF)
isinstancer   add_propdatar   from_encoded_cnf	SATSolver	variablessetsymbols_find_model_all_modelsnextStopIteration)expr
all_modelsuse_lra_theoryexprslraimmediate_conflictssolvermodelss   &&&     r   dpll_satisfiabler'      s    " dJ''t 	
sdii'w''#,#=#=d#C   tyy#66t||hklF!F6""F| s   
C* *C98C9c              #   v   "   R p  \        V 4      x  RpK    \         d    T'       g   R x   R#  R# i ; i5i)FTN)r   r   )r&   satisfiables   & r   r   r   G   s<     Kv,K K s   9 66969c                      a  ] tR t^Rt o RtRR ltR tR tR t]	R 4       t
R tR	 tR
 tR t R tR tR tR tR tR tR tR tR tR tR tR tRtV tR# )r   zr
Class for representing a SAT solver capable of
 finding a model to a boolean theory in conjunctive
 normal form.
Nc	                   W0n         WPn        R V n        . V n        . V n        Wpn        Vf   \        \        V4      4      V n        MW@n        V P                  V4       V P                  V4       RV8X  dV   V P                  4        V P                  V n        V P                  V n        V P                   V n        V P$                  V n        M\(        hRV8X  dI   V P*                  V n        V P.                  V n        V P                  P3                  V P4                  4       MRV8X  d   R V n        R V n        M\(        h\7        ^ 4      .V n        W0P:                  n        ^ V n        ^ V n         \C        V PD                  4      V n#        Wn$        R# )FNvsidssimplenonec                     R # r
   r   )xs   &r   <lambda>$SATSolver.__init__.<locals>.<lambda>~   s        c                      R # r
   r   r   r3   r   r1   r2      s    Dr3   )%var_settings	heuristicis_unsatisfied_unit_prop_queueupdate_functionsINTERVALlistr   r   _initialize_variables_initialize_clauses_vsids_init_vsids_calculateheur_calculate_vsids_lit_assignedheur_lit_assigned_vsids_lit_unsetheur_lit_unset_vsids_clause_addedheur_clause_addedNotImplementedError_simple_add_learned_clauseadd_learned_clause_simple_compute_conflictcompute_conflictappend_simple_clean_clausesLevellevels_current_levelvarsettingsnum_decisionsnum_learned_clauseslenclausesoriginal_num_clausesr#   )	selfrU   r   r5   r   r6   clause_learningr:   r   s	   &&&&&&&&&r   __init__SATSolver.__init__Y   sV    )"# " " ?	 23DL"L""9-  )i"&"7"7D%)%=%=D""&"7"7D%)%=%=D" &%&&*&E&ED#$($A$AD!!!(()C)CD&&4D#$0D!%% Qxj*6' #$ $'$5!r3   c                    \        \        4      V n        \        \        4      V n        R.\        V4      ^,           ,          V n        R# )z+Set up the variable data structures needed.FN)r   r   	sentinelsintoccurrence_countrT   variable_set)rW   r   s   &&r   r<   SATSolver._initialize_variables   s3    $S) +C 0"Gs9~'9:r3   c                   V Uu. uF  p\        V4      NK  	  upV n        \        V P                  4       F  w  r2^\        V4      8X  d%   V P                  P                  V^ ,          4       K9  V P                  V^ ,          ,          P                  V4       V P                  VR,          ,          P                  V4       V F"  pV P                  V;;,          ^,          uu&   K$  	  K  	  R# u upi )a  Set up the clause data structures needed.

For each clause, the following changes are made:
- Unit clauses are queued for propagation right away.
- Non-unit clauses have their first and last literals set as sentinels.
- The number of clauses a literal appears in is computed.
N)	r;   rU   	enumeraterT   r8   rL   r\   addr^   )rW   rU   clauseilits   &&   r   r=   SATSolver._initialize_clauses   s     4;;7V7;"4<<0IA CK%%,,VAY7NN6!9%))!,NN6":&**1-%%c*a/*  1 <s   C/c              #    a"   RpV P                  4        V P                  '       d   R#  V P                  V P                  ,          ^ 8X  d   V P                   F
  pV! 4        K  	  V'       d   RpV P
                  P                  pEMWV P                  4       pV ;P                  ^,          un        ^ V8X  Ed   V P                  '       dj   V P                   F$  pV P                  P                  V4      oSf   K$   M	  V P                  P                  4       oV P                  P                  4        MRoSe   S^ ,          '       dE   V P                   Uu/ uF*  pV P                  \        V4      ^,
          ,          V^ 8  bK,  	  upx  MV P                  S^,          4       \         ;QJ d3    V3R lV P
                  P                   4       F  '       g   K   RM(	  RM$! V3R lV P
                  P                   4       4      '       g   V P#                  4        Kz  V P
                  P$                  '       d   V P#                  4        K.  \'        V P(                  4      ^8X  d   R# V P
                  P                  ) pV P#                  4        V P(                  P+                  \-        VRR7      4       RpEK  V P(                  P+                  \-        V4      4       V P/                  V4       V P                  4        V P                  '       g   EK  RV n        V P
                  P$                  '       d/   V P#                  4        ^\'        V P(                  4      8X  g   KH  R# V P1                  V P3                  4       4       V P
                  P                  ) pV P#                  4        V P(                  P+                  \-        VRR7      4       RpEK  u upi 5i)a  
Main DPLL loop. Returns a generator of models.

Variables are chosen successively, and assigned to be either
True or False. If a solution is not found with this setting,
the opposite is chosen and the search continues. The solver
halts when every variable has a setting.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())
>>> list(l._find_model())
[{1: True, 2: False, 3: False}, {1: True, 2: True, 3: True}]

>>> from sympy.abc import A, B, C
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set(), [A, B, C])
>>> list(l._find_model())
[{A: True, B: False, C: False}, {A: True, B: True, C: True}]

FNTc              3   <   <"   T F  q) S^,          9   x  K  	  R# 5i)   Nr   )r   rg   ress   & r   r   (SATSolver._find_model.<locals>.<genexpr>   s     %a@`dc!fn@`s   )flipped)	_simplifyr7   rR   r:   r9   rP   decisionr@   r#   r5   
assert_litcheckreset_boundsr   absrH   any_undorn   rT   rO   rL   rN   _assign_literalrI   rK   )rW   flip_varfuncrg   enc_varflip_litrl   s   &     @r   r   SATSolver._find_model   s    8  	 !!DMM1Q6 11DF 2  ))22 ))+""a'" 8 xxx'+'8'8G"&(("5"5g">C" % (9 #hhnn.--/"{c!ff7;7H7HJ7H  $||CHqL9$'!G ,7HJ J 77A? #&#%a@S@S@`@`%a###%a@S@S@`@`%a"a"a JJL--555

4;;'1, $ 3 3 < <<HJJLKK&&uXt'DE#H ""5:.   % NN """&+# ))111JJL C,, ''(=(=(?@ !//888

""54#@AaJsX   A+O/AO+O<AO
O0O(O1(O1O-O<CO"O9'O%A8Oc                (    V P                   R,          # )a<  The current decision level data structure

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{1}, {2}], {1, 2}, set())
>>> next(l._find_model())
{1: True, 2: True}
>>> l._current_level.decision
0
>>> l._current_level.flipped
False
>>> l._current_level.var_settings
{1, 2}

rb   )rO   rW   s   &r   rP   SATSolver._current_level"  s    & {{2r3   c                `    V P                   V,           F  pW P                  9   g   K   R# 	  R# )a:  Check if a clause is satisfied by the current variable setting.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{1}, {-1}], {1}, set())
>>> try:
...     next(l._find_model())
... except StopIteration:
...     pass
>>> l._clause_sat(0)
False
>>> l._clause_sat(1)
True

TF)rU   r5   rW   clsrg   s   && r   _clause_satSATSolver._clause_sat7  s.    $ <<$$C''' % r3   c                ,    W P                   V,          9   # )aI  Check if a literal is a sentinel of a given clause.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())
>>> next(l._find_model())
{1: True, 2: False, 3: False}
>>> l._is_sentinel(2, 3)
True
>>> l._is_sentinel(-3, 1)
False

)r\   )rW   rg   r   s   &&&r   _is_sentinelSATSolver._is_sentinelN  s    " nnS)))r3   c                   V P                   P                  V4       V P                  P                   P                  V4       RV P                  \	        V4      &   V P                  V4       \        V P                  V) ,          4      pV F  pV P                  V4      '       d   K  RpV P                  V,           F  pWQ) 8w  g   K  V P                  WS4      '       d   TpK'  V P                  \	        V4      ,          '       d   KK  V P                  V) ,          P                  V4       V P                  V,          P                  V4       Rp M	  V'       g   K  V P                  P                  V4       K  	  R# )a  Make a literal assignment.

The literal assignment must be recorded as part of the current
decision level. Additionally, if the literal is marked as a
sentinel of any clause, then a new sentinel must be chosen. If
this is not possible, then unit propagation is triggered and
another literal is added to the queue to be set in the future.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())
>>> next(l._find_model())
{1: True, 2: False, 3: False}
>>> l.var_settings
{-3, -2, 1}

>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())
>>> l._assign_literal(-1)
>>> try:
...     next(l._find_model())
... except StopIteration:
...     pass
>>> l.var_settings
{-1}

TN)r5   rd   rP   r_   rt   rB   r;   r\   r   rU   r   remover8   rL   )rW   rg   sentinel_listr   other_sentinelnewlits   &&    r   rw   SATSolver._assign_literala  s$   > 	c"((,,S1&*#c(#s#T^^SD12 C##C((!%"ll3//F~,,V99-3N!%!2!23v;!?!? NNC4077< NN6266s;-1N! 0 ">))00@ !r3   c                    V P                   P                   FG  pV P                  P                  V4       V P                  V4       RV P                  \        V4      &   KI  	  V P                  P                  4        R# )a  
_undo the changes of the most recent decision level.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())
>>> next(l._find_model())
{1: True, 2: False, 3: False}
>>> level = l._current_level
>>> level.decision, level.var_settings, level.flipped
(-3, {-3, -2}, False)
>>> l._undo()
>>> level = l._current_level
>>> level.decision, level.var_settings, level.flipped
(0, {1}, False)

FN)rP   r5   r   rD   r_   rt   rO   poprW   rg   s   & r   rv   SATSolver._undo  s`    , &&33C$$S)$*/Dc#h' 4 	r3   c                z    RpV'       d1   RpWP                  4       ,          pWP                  4       ,          pK8  R# )a  Iterate over the various forms of propagation to simplify the theory.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())
>>> l.variable_set
[False, False, False, False]
>>> l.sentinels
{-3: {0, 2}, -2: {3, 4}, 2: {0, 3}, 3: {2, 4}}

>>> l._simplify()

>>> l.variable_set
[False, True, False, False]
>>> l.sentinels
{-3: {0, 2}, -2: {3, 4}, -1: set(), 2: {0, 3},
...3: {2, 4}}

TFN)
_unit_prop_pure_literal)rW   changeds   & r   ro   SATSolver._simplify  s6    . G((G))++G r3   c                    \        V P                  4      ^ 8  pV P                  '       dP   V P                  P                  4       pV) V P                  9   d   RV n        . V n        R# V P                  V4       Ka  V# )z/Perform unit propagation on the current theory.TF)rT   r8   r   r5   r7   rw   )rW   resultnext_lits   &  r   r   SATSolver._unit_prop  sm    T**+a/###,,002HyD---&*#(*%$$X.r3   c                    R# )z2Look for pure literals and assign them when found.Fr   r~   s   &r   r   SATSolver._pure_literal  s    r3   c                   . V n         / V n        \        ^\        V P                  4      4       F  p\        V P                  V,          ) 4      V P                  V&   \        V P                  V) ,          ) 4      V P                  V) &   \        V P                   V P                  V,          V34       \        V P                   V P                  V) ,          V) 34       K  	  R# )z>Initialize the data structures needed for the VSIDS heuristic.N)lit_heap
lit_scoresrangerT   r_   floatr^   r   )rW   vars   & r   r>   SATSolver._vsids_init  s    C 1 123C#($*?*?*D)D#EDOOC $)4+@+@#+F*F$GDOOSD!T]]T__S%93$?@T]]T__cT%:SD$AB	 4r3   c                    V P                   P                  4        F"  pV P                   V;;,          R,          uu&   K$  	  R# )as  Decay the VSIDS scores for every literal.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())

>>> l.lit_scores
{-3: -2.0, -2: -2.0, -1: 0.0, 1: 0.0, 2: -2.0, 3: -2.0}

>>> l._vsids_decay()

>>> l.lit_scores
{-3: -1.0, -2: -1.0, -1: 0.0, 1: 0.0, 2: -1.0, 3: -1.0}

g       @N)r   keysr   s   & r   _vsids_decaySATSolver._vsids_decay  s/    * ??'')COOC C'  *r3   c                L   \        V P                  4      ^ 8X  d   ^ # V P                  \        V P                  ^ ,          ^,          4      ,          '       d4   \	        V P                  4       \        V P                  4      ^ 8X  g   Kk  ^ # \	        V P                  4      ^,          # )ay  
    VSIDS Heuristic Calculation

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())

>>> l.lit_heap
[(-2.0, -3), (-2.0, 2), (-2.0, -2), (0.0, 1), (-2.0, 3), (0.0, -1)]

>>> l._vsids_calculate()
-3

>>> l.lit_heap
[(-2.0, -2), (-2.0, 2), (0.0, -1), (0.0, 1), (-2.0, 3)]

)rT   r   r_   rt   r   r~   s   &r   r?   SATSolver._vsids_calculate  sr    * t}}" DMM!$4Q$7 899DMM"4==!Q&t}}%a((r3   c                    R# )z;Handle the assignment of a literal for the VSIDS heuristic.Nr   r   s   &&r   rA   SATSolver._vsids_lit_assigned3      r3   c                    \        V4      p\        V P                  V P                  V,          V34       \        V P                  V P                  V) ,          V) 34       R# )a  Handle the unsetting of a literal for the VSIDS heuristic.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())
>>> l.lit_heap
[(-2.0, -3), (-2.0, 2), (-2.0, -2), (0.0, 1), (-2.0, 3), (0.0, -1)]

>>> l._vsids_lit_unset(2)

>>> l.lit_heap
[(-2.0, -3), (-2.0, -2), (-2.0, -2), (-2.0, 2), (-2.0, 3), (0.0, -1),
...(-2.0, 2), (0.0, 1)]

N)rt   r   r   r   )rW   rg   r   s   && r   rC   SATSolver._vsids_lit_unset7  sI    & #h!5s ;<#!6 =>r3   c                    V ;P                   ^,          un         V F"  pV P                  V;;,          ^,          uu&   K$  	  R# )a  Handle the addition of a new clause for the VSIDS heuristic.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())

>>> l.num_learned_clauses
0
>>> l.lit_scores
{-3: -2.0, -2: -2.0, -1: 0.0, 1: 0.0, 2: -2.0, 3: -2.0}

>>> l._vsids_clause_added({2, -3})

>>> l.num_learned_clauses
1
>>> l.lit_scores
{-3: -1.0, -2: -2.0, -1: 0.0, 1: 0.0, 2: -1.0, 3: -2.0}

N)rS   r   r   s   && r   rE   SATSolver._vsids_clause_addedN  s3    . 	  A% COOC A%  r3   c                |   \        V P                  4      pV P                  P                  V4       V F"  pV P                  V;;,          ^,          uu&   K$  	  V P                  V^ ,          ,          P                  V4       V P                  VR,          ,          P                  V4       V P                  V4       R# )a  Add a new clause to the theory.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())

>>> l.num_learned_clauses
0
>>> l.clauses
[[2, -3], [1], [3, -3], [2, -2], [3, -2]]
>>> l.sentinels
{-3: {0, 2}, -2: {3, 4}, 2: {0, 3}, 3: {2, 4}}

>>> l._simple_add_learned_clause([3])

>>> l.clauses
[[2, -3], [1], [3, -3], [2, -2], [3, -2], [3]]
>>> l.sentinels
{-3: {0, 2}, -2: {3, 4}, 2: {0, 3}, 3: {2, 4, 5}}

Nrb   )rT   rU   rL   r^   r\   rd   rF   )rW   r   cls_numrg   s   &&  r   rH   $SATSolver._simple_add_learned_clausel  s    2 dll#C C!!#&!+&  	s1v""7+s2w##G,s#r3   c                f    V P                   R,           Uu. uF  qP                  ) NK  	  up# u upi )aR  Build a clause representing the fact that at least one decision made
so far is wrong.

Examples
========

>>> from sympy.logic.algorithms.dpll2 import SATSolver
>>> l = SATSolver([{2, -3}, {1}, {3, -3}, {2, -2},
... {3, -2}], {1, 2, 3}, set())
>>> next(l._find_model())
{1: True, 2: False, 3: False}
>>> l._simple_compute_conflict()
[3]

:rk   NN)rO   rp   )rW   levels   & r   rJ   "SATSolver._simple_compute_conflict  s)      04{{2?e..!???s   .c                    R# )zClean up learned clauses.Nr   r~   s   &r   rM   SATSolver._simple_clean_clauses  r   r3   )r:   r8   rI   rU   rK   r@   rF   rB   rD   r6   r7   rO   r   r   r#   rR   rS   r^   rV   r\   r   r9   r5   r_   )Nr,   r.   i  N)__name__
__module____qualname____firstlineno____doc__rY   r<   r=   r   propertyrP   r   r   rw   rv   ro   r   r   r>   r   r?   rA   rC   rE   rH   rJ   rM   __static_attributes____classdictcell____classdict__s   @r   r   r   R   s     3j;0.r n  (.*&5AnB
,:	C(0)@?.&<"$H@$ r3   r   c                   .   a  ] tR tRt o RtRR ltRtV tR# )rN   i  zv
Represents a single level in the DPLL algorithm, and contains
enough information for a sound backtracking procedure.
c                <    Wn         \        4       V n        W n        R # r
   )rp   r   r5   rn   )rW   rp   rn   s   &&&r   rY   Level.__init__  s     Er3   )rp   rn   r5   Nr   )r   r   r   r   r   rY   r   r   r   s   @r   rN   rN     s     
 r3   rN   N)FF)r   collectionsr   heapqr   r   sympy.core.sortingr   sympy.assumptions.cnfr   !sympy.logic.algorithms.lra_theoryr   r'   r   r   rN   r   r3   r   <module>r      s=   	 $ # & , 7*dR	 R	j	 	r3   