
    MZd^!                         d Z ddlmZmZmZmZmZ ddlmZ ddl	m
Z
 ddlmZ d ZddZd	 Zdd
ZddZ G d d      Z G d de      Zy)z Inference in propositional logic    )AndNot	conjunctsto_cnfBooleanFunction)ordered)sympify)import_modulec                     | du s| du r| S 	 | j                   r| S | j                  rt        | j                  d         S t        # t
        t        f$ r t	        d      w xY w)z
    The symbol in this literal (without the negation).

    Examples
    ========

    >>> from sympy.abc import A
    >>> from sympy.logic.inference import literal_symbol
    >>> literal_symbol(A)
    A
    >>> literal_symbol(~A)
    A

    TFr   z#Argument must be a boolean literal.)	is_Symbolis_Notliteral_symbolargs
ValueErrorAttributeError)literals    7/usr/lib/python3/dist-packages/sympy/logic/inference.pyr   r   	   sm      $'U*@N>>!',,q/22J' @>??@s   A #A A ANc                 (   ||dk(  r"t        d      }|d}n|dk(  rt        d      d}|dk(  rt        d      }|d}|dk(  rddlm}  ||       S |dk(  rddlm}  || |      S |dk(  rdd	lm}  || |      S |dk(  rdd
lm}  || ||      S t        )a  
    Check satisfiability of a propositional sentence.
    Returns a model when it succeeds.
    Returns {true: true} for trivially true expressions.

    On setting all_models to True, if given expr is satisfiable then
    returns a generator of models. However, if expr is unsatisfiable
    then returns a generator containing the single element False.

    Examples
    ========

    >>> from sympy.abc import A, B
    >>> from sympy.logic.inference import satisfiable
    >>> satisfiable(A & ~B)
    {A: True, B: False}
    >>> satisfiable(A & ~A)
    False
    >>> satisfiable(True)
    {True: True}
    >>> next(satisfiable(A & ~A, all_models=True))
    False
    >>> models = satisfiable((A >> B) & B, all_models=True)
    >>> next(models)
    {A: False, B: True}
    >>> next(models)
    {A: True, B: True}
    >>> def use_models(models):
    ...     for model in models:
    ...         if model:
    ...             # Do something with the model.
    ...             print(model)
    ...         else:
    ...             # Given expr is unsatisfiable.
    ...             print("UNSAT")
    >>> use_models(satisfiable(A >> ~A, all_models=True))
    {A: False}
    >>> use_models(satisfiable(A ^ A, all_models=True))
    UNSAT

    pycosatzpycosat module is not presentdpll2	minisat22pysatdpllr   )dpll_satisfiable)pycosat_satisfiable)minisat22_satisfiable)
r
   ImportErrorsympy.logic.algorithms.dpllr   sympy.logic.algorithms.dpll2&sympy.logic.algorithms.pycosat_wrapperr   (sympy.logic.algorithms.minisat22_wrapperr   NotImplementedError)	expr	algorithm
all_modelsminimalr   r   r   r   r   s	            r   satisfiabler'   &   s    T I2	*!II%!"ABB  I+g&=IF@%%	g	Aj11	i	N"444	k	!R$T:w??
    c                 ,    t        t        |              S )ax  
    Check validity of a propositional sentence.
    A valid propositional sentence is True under every assignment.

    Examples
    ========

    >>> from sympy.abc import A, B
    >>> from sympy.logic.inference import valid
    >>> valid(A | ~A)
    True
    >>> valid(A | B)
    False

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Validity

    )r'   r   )r#   s    r   validr*   o   s    * 3t9%%%r(   c                    ddl m dfd| v r| S t        |       }  |       st        d| z        |si }|j	                         D ci c]  \  }}|v s|| }}}| j                  |      }|v rt        |      S |rC|j                         D ci c]  }|d }}t        ||      rt        |      ryyt        |      syyc c}}w c c}w )	a+  
    Returns whether the given assignment is a model or not.

    If the assignment does not specify the value for every proposition,
    this may return None to indicate 'not obvious'.

    Parameters
    ==========

    model : dict, optional, default: {}
        Mapping of symbols to boolean values to indicate assignment.
    deep: boolean, optional, default: False
        Gives the value of the expression under partial assignments
        correctly. May still return None to indicate 'not obvious'.


    Examples
    ========

    >>> from sympy.abc import A, B
    >>> from sympy.logic.inference import pl_true
    >>> pl_true( A & B, {A: True, B: True})
    True
    >>> pl_true(A & B, {A: False})
    False
    >>> pl_true(A & B, {A: True})
    >>> pl_true(A & B, {A: True}, deep=True)
    >>> pl_true(A >> (B >> A))
    >>> pl_true(A >> (B >> A), deep=True)
    True
    >>> pl_true(A & ~A)
    >>> pl_true(A & ~A, deep=True)
    False
    >>> pl_true(A & B & (~A | ~B), {A: True})
    >>> pl_true(A & B & (~A | ~B), {A: True}, deep=True)
    False

    r   )Symbol)TFc                     t        |       s| v ryt        | t              syt        fd| j                  D              S )NTFc              3   .   K   | ]  } |        y wN ).0arg	_validates     r   	<genexpr>z-pl_true.<locals>._validate.<locals>.<genexpr>   s     7c9S>7s   )
isinstancer   allr   )r#   r,   r3   booleans    r   r3   zpl_true.<locals>._validate   s8    dF#tw$07TYY777r(   z$%s is not a valid boolean expressionTFN)sympy.core.symbolr,   r	   r   itemssubsboolatomspl_truer*   r'   )	r#   modeldeepkvresultr,   r3   r7   s	         @@@r   r=   r=      s    P )G8 w4=DT??$FGG#kkm<daqG|QT<E<YYuFF|"(,,.1QD1165!V}  v& =
 2s   CC
Cc                 z    |rt        |      }ng }|j                  t        |              t        t	        |        S )a  
    Check whether the given expr_set entail an expr.
    If formula_set is empty then it returns the validity of expr.

    Examples
    ========

    >>> from sympy.abc import A, B, C
    >>> from sympy.logic.inference import entails
    >>> entails(A, [A >> B, B >> C])
    False
    >>> entails(C, [A >> B, B >> C, A])
    True
    >>> entails(A >> B)
    False
    >>> entails(A >> (B >> A))
    True

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Logical_consequence

    )listappendr   r'   r   )r#   formula_sets     r   entailsrG      s;    2 ;'s4y!3,---r(   c                   :    e Zd ZdZddZd Zd Zd Zed        Z	y)	KBz"Base class for all knowledge basesNc                 J    t               | _        |r| j                  |       y y r/   )setclauses_tellselfsentences     r   __init__zKB.__init__   s    IIh r(   c                     t         r/   r"   rN   s     r   rM   zKB.tell       !!r(   c                     t         r/   rS   rO   querys     r   askzKB.ask   rT   r(   c                     t         r/   rS   rN   s     r   retractz
KB.retract   rT   r(   c                 >    t        t        | j                              S r/   )rD   r   rL   )rO   s    r   clausesz
KB.clauses  s    GDMM*++r(   r/   )
__name__
__module____qualname____doc__rQ   rM   rX   rZ   propertyr\   r0   r(   r   rI   rI      s-    , 
""" , ,r(   rI   c                   "    e Zd ZdZd Zd Zd Zy)PropKBz=A KB for Propositional Logic.  Inefficient, with no indexing.c                 l    t        t        |            D ]  }| j                  j                  |        y)ai  Add the sentence's clauses to the KB

        Examples
        ========

        >>> from sympy.logic.inference import PropKB
        >>> from sympy.abc import x, y
        >>> l = PropKB()
        >>> l.clauses
        []

        >>> l.tell(x | y)
        >>> l.clauses
        [x | y]

        >>> l.tell(y)
        >>> l.clauses
        [y, x | y]

        N)r   r   rL   addrO   rP   cs      r   rM   zPropKB.tell	  s/    * 6(+, 	!AMMa 	!r(   c                 .    t        || j                        S )a8  Checks if the query is true given the set of clauses.

        Examples
        ========

        >>> from sympy.logic.inference import PropKB
        >>> from sympy.abc import x, y
        >>> l = PropKB()
        >>> l.tell(x & ~y)
        >>> l.ask(x)
        True
        >>> l.ask(y)
        False

        )rG   rL   rV   s     r   rX   z
PropKB.ask!  s      udmm,,r(   c                 l    t        t        |            D ]  }| j                  j                  |        y)am  Remove the sentence's clauses from the KB

        Examples
        ========

        >>> from sympy.logic.inference import PropKB
        >>> from sympy.abc import x, y
        >>> l = PropKB()
        >>> l.clauses
        []

        >>> l.tell(x | y)
        >>> l.clauses
        [x | y]

        >>> l.retract(x | y)
        >>> l.clauses
        []

        N)r   r   rL   discardrf   s      r   rZ   zPropKB.retract3  s/    * 6(+, 	%AMM!!!$	%r(   N)r]   r^   r_   r`   rM   rX   rZ   r0   r(   r   rc   rc     s    G!0-$%r(   rc   )NFF)NFr/   )r`   sympy.logic.boolalgr   r   r   r   r   sympy.core.sortingr   sympy.core.sympifyr	   sympy.external.importtoolsr
   r   r'   r*   r=   rG   rI   rc   r0   r(   r   <module>ro      sN    & L L & & 4@:FR&0FR.B, ,*C%R C%r(   