§
    OŠtjä#  ã                   ó–   — 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„ Zd„ Zd„ Zi fd	„Zd
„ Zd„ Zd„ Zd„ Zd„ Z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                 óÈ  — t          | t          ¦  «        st          t          | ¦  «        ¦  «        }n| j        }d|v rdS t          t          | ¦  «        t          ¬¦  «        }t          t          dt          |¦  «        dz   ¦  «        ¦  «        }t          ||¦  «        }t          ||i ¦  «        }|s|S i }|D ](}|                     ||dz
           ||         i¦  «         Œ)|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   s           úY/var/www/html/CA-Chatbot/venv/lib/python3.11/site-packages/sympy/logic/algorithms/dpll.pyÚdpll_satisfiabler       sñ   € õ �d�CÑ Ô ð Ý�F 4™LœLÑ)Ô)ˆˆà”,ˆØ�ÐÐØˆuÝÕ% dÑ+Ô+Õ1AÐBÑBÔB€GÝ�5 ¥C¨¡L¤L°1Ñ$4Ñ5Ô5Ñ6Ô6ÐÝ" 7¨GÑ4Ô4ÐÝÐ+Ð-=¸rÑBÔB€FØð ØˆØ€FØð 7ð 7ˆØ�Š�w˜s Q™wÔ'¨°¬Ð5Ñ6Ô6Ð6Ð6Ø€Mó    c                 ó‚  — t          | |¦  «        \  }}|rV|                     ||i¦  «         |                     |¦  «         |s| }t          | |¦  «        } t          | |¦  «        \  }}|°Vt	          || ¦  «        \  }}|rV|                     ||i¦  «         |                     |¦  «         |s| }t          | |¦  «        } t	          || ¦  «        \  }}|°Vg }| D ]2}t          ||¦  «        }|du r dS |dur|                     |¦  «         Œ3|s|S | s|S |                     ¦   «         }|                     ¦   «         }|                     |di¦  «         |                     |di¦  «         |dd…         }	t          t          ||¦  «        ||¦  «        p+t          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_copys
             r   r*   r*   1   s  € õ   ¨Ñ/Ô/�H€A€uØ
ð 4Ø�Š�a˜�ZÑ Ô Ð Ø�Š�qÑÔÐØð 	Ø�ˆAÝ  ¨!Ñ,Ô,ˆÝ# G¨UÑ3Ô3‰ˆˆ5ð ð 4õ   ¨Ñ1Ô1�H€A€uØ
ð 6Ø�Š�a˜�ZÑ Ô Ð Ø�Š�qÑÔÐØð 	Ø�ˆAÝ  ¨!Ñ,Ô,ˆÝ# G¨WÑ5Ô5‰ˆˆ5ð ð 6ð €OØð &ð &ˆÝ�a˜ÑÔˆØ�%ˆ<ˆ<Ø�5�5Ø�dˆ?ˆ?Ø×"Ò" 1Ñ%Ô%Ð%øØð ØˆØð ØˆØ�Š‰Œ€AØ—’‘”€JØ	‡L‚L�!�T�ÑÔÐØ×Ò�q˜%�jÑ!Ô!Ð!Ø˜1˜1˜1”:€LÝ• °Ñ3Ô3°W¸eÑDÔDð TÝ• µ°Q±´Ñ8Ô8¸,È
ÑSÔSðUr!   c                 óv  — t          | |¦  «        \  }}|rV|                     ||i¦  «         |                     |¦  «         |s| }t          | |¦  «        } t          | |¦  «        \  }}|°Vt	          || ¦  «        \  }}|rV|                     ||i¦  «         |                     |¦  «         |s| }t          | |¦  «        } t	          || ¦  «        \  }}|°Vg }| D ]2}t          ||¦  «        }|du r dS |dur|                     |¦  «         Œ3|s|S |                     ¦   «         }|                     ¦   «         }|                     |di¦  «         |                     |di¦  «         |                     ¦   «         }	t          t          ||¦  «        ||¦  «        pt          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+   s
             r   r   r   b   sû  € õ )¨°%Ñ8Ô8�H€A€uØ
ð =Ø�Š�a˜�ZÑ Ô Ð Ø�Š�qÑÔÐØð 	Ø�ˆAÝ)¨'°1Ñ5Ô5ˆÝ,¨W°eÑ<Ô<‰ˆˆ5ð ð =õ )¨°'Ñ:Ô:�H€A€uØ
ð ?Ø�Š�a˜�ZÑ Ô Ð Ø�Š�qÑÔÐØð 	Ø�ˆAÝ)¨'°1Ñ5Ô5ˆÝ,¨W°gÑ>Ô>‰ˆˆ5ð ð ?ð €OØð &ð &ˆÝ˜q %Ñ(Ô(ˆØ�%ˆ<ˆ<Ø�5�5Ø�dˆ?ˆ?Ø×"Ò" 1Ñ%Ô%Ð%øØð ØˆØ�Š‰Œ€AØ—’‘”€JØ	‡L‚L�!�T�ÑÔÐØ×Ò�q˜%�jÑ!Ô!Ð!Ø—<’<‘>”>€LÝÕ1°/À1ÑEÔEÀwÐPUÑVÔVð bÝÕ1°/ÀAÀ2ÑFÔFÈÐV`ÑaÔaðcr!   c                 ó˜   — d}| D ]D}|dk     r|                      | ¦  «        }|�| }n|                      |¦  «        }|du r dS |€d}ŒE|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Úps        r   r8   r8   ’   sn   € ð €FØð 
ð 
ˆØ�Š7ˆ7Ø—	’	˜3˜$‘”ˆAØˆ}Ø�E�øà—	’	˜#‘”ˆAØ�ˆ9ˆ9Ø�4�4ØˆYØˆFøØ€Mr!   c                 ó  ‡— g }| D ]…}|j         t          k    r|                     |¦  «         Œ(|j        D ]@}|‰ k    r/|                     t          ˆfd„|j        D ¦   «         Ž ¦  «          n|‰k    r nŒA|                     |¦  «         Œ†|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                 ó"   •— g | ]}|‰ k    ¯	|‘ŒS © r@   )Ú.0ÚxÚsymbols     €r   ú
<listcomp>z"unit_propagate.<locals>.<listcomp>Å   s    ø€ Ð"EÐ"EÐ"E¨¸¸f¸Wº¸ 1¸¸¸r!   )Úfuncr   r'   Úargs)r   rC   r   r0   Úargs    `   r   r%   r%   ­   sµ   ø€ ð" €FØð ð ˆØŒ6•RŠ<ˆ<Ø�MŠM˜!ÑÔÐØØ”6ð 	ð 	ˆCØ�v�gŠ~ˆ~Ø—’�bÐ"EÐ"EÐ"EÐ"E¨a¬fÐ"EÑ"EÔ"EÐFÑGÔGÐGØ�Ø�fŠ}ˆ}Ø�ð ð �MŠM˜!ÑÔÐøØ€Mr!   c                 ó,   ‡‡— ‰ hŠˆˆf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                 ó"   •— g | ]}‰|v¯|‰z
  ‘ŒS r@   r@   )rA   r;   ÚnegatedÚss     €€r   rD   z+unit_propagate_int_repr.<locals>.<listcomp>Ù   s#   ø€ ÐFÐFÐF °a¸v°o°oˆF�WÑ°o°o°or!   r@   )r   rK   rJ   s    `@r   r6   r6   Î   s,   øø€ ð ˆrˆd€GØFÐFÐFÐFÐF¨7ÐFÑFÔFÐFr!   c                 óª   — | D ]O}d\  }}|D ]9}|s|t          |¦  «        v rd}|s t          |¦  «        t          |¦  «        v rd}Œ:||k    r||fc S ŒPd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_negr0   s         r   r&   r&   Ü   s’   € ð ð "ð "ˆØ+Ñˆ	�9Ø ð 	!ð 	!ˆAØð ! ­	°!©¬Ð!4Ð!4Ø �	Øð !¥ S¡¤­Y°q©\¬\Ð!9Ð!9Ø �	øØ˜	Ò!Ð!Ø˜	�>Ð!Ð!Ð!ð "àˆ:r!   c                 óÜ   —  t          ¦   «         j        |Ž }|                     | ¦  «        }|                     d„ | D ¦   «         ¦  «        }|D ]}| |vr|dfc S Œ|D ]}| |vr| dfc S Œ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                 ó   — g | ]}| ‘ŒS r@   r@   )rA   rK   s     r   rD   z-find_pure_symbol_int_repr.<locals>.<listcomp>   s   € Ð)>Ð)>Ð)>°¨1¨"Ð)>Ð)>Ð)>r!   TFrM   )r   ÚunionÚintersection)r   r/   Úall_symbolsrO   rP   r=   s         r   r7   r7   ó   s±   € ð •#‘%”%”+˜Ð/€KØ×(Ò(¨Ñ1Ô1€IØ×(Ò(Ð)>Ð)>°gÐ)>Ñ)>Ô)>Ñ?Ô?€IØð ð ˆØˆ2�YÐÐØ�d�7ˆNˆNˆNð àð ð ˆØˆ2�YÐÐØ�2�u�9ÐÐÐð àˆ:r!   c                 ó°   — | D ]R}d}t          |¦  «        D ]2}t          |¦  «        }||vr|dz  }|t          |t          ¦  «         }}Œ3|dk    r||fc S ŒSd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   rM   )r   r   r   r   )r   r,   r;   Únum_not_in_modelÚliteralrN   r-   r.   s           r   r#   r#   
  sŒ   € ð ð ð ˆØÐÝ  Ñ(Ô(ð 	=ð 	=ˆGÝ  Ñ)Ô)ˆCØ˜%ÐÐØ  AÑ%Ð Ø¥J¨w½Ñ$<Ô$<Ð <�5�øØ˜qÒ Ð Ø�e�8ˆOˆOˆOð !àˆ:r!   c                 óÆ   — t          |¦  «        d„ |D ¦   «         z  }| D ]A}||z
  }t          |¦  «        dk    r'|                     ¦   «         }|dk     r| dfc S |dfc S ŒBd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                 ó   — h | ]}| ’ŒS r@   r@   )rA   rN   s     r   ú	<setcomp>z,find_unit_clause_int_repr.<locals>.<setcomp>+  s   € Ð0Ð0Ð0 3˜3˜$Ð0Ð0Ð0r!   r   r   FTrM   )r   r   r(   )r   r,   Úboundr;   Úunboundr=   s         r   r5   r5      s�   € õ �‰JŒJÐ0Ð0¨%Ð0Ñ0Ô0Ñ0€EØð ð ˆØ˜5‘.ˆÝˆw‰<Œ<˜1ÒÐØ—’‘”ˆAØ�1ŠuˆuØ�r˜5�yÐ Ð Ð à˜$�w���ð ð ˆ:r!   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   r@   r!   r   ú<module>rc      s]  ððð ð 0Ð /Ð /Ð /Ð /Ð /ð"ð "ð "ð "ð "ð "ð "ð "ð "ð "ð "ð "ð "ð "ð "ð "ð "ð "à %Ð %Ð %Ð %Ð %Ð %Ø 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9Ð 9ðð ð ð>.Uð .Uð .Uðb+cð +cð +cð` $&ð ð ð ð ð6ð ð ðBGð Gð Gðð ð ð.ð ð ð.ð ð ð,ð ð ð ð r!   