B
    [                 @   s   d Z ddlmZmZ ddlmZmZmZmZ ddl	m
Z
 ddlmZ dd Zdd
dZdd Zi d	fddZi fddZG dd deZG dd deZdS )z Inference in propositional logic    )print_functiondivision)AndNot	conjunctsto_cnf)ordered)sympifyc          	   C   s`   | dks| dkr| S y&| j r | S | jr4t| jd S tW n  ttfk
rZ   tdY nX dS )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.N)Z	is_SymbolZis_Notliteral_symbolargs
ValueErrorAttributeError)literal r   4lib/python3.7/site-packages/sympy/logic/inference.pyr
   	   s    r
   dpll2Fc             C   sJ   t | } |dkr$ddlm} || S |dkrBddlm} || |S tdS )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

    Zdpllr   )dpll_satisfiabler   N)r   Zsympy.logic.algorithms.dpllr   Zsympy.logic.algorithms.dpll2NotImplementedError)expr	algorithmZ
all_modelsr   r   r   r   satisfiable&   s    *
r   c             C   s   t t|  S )aw  
    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] http://en.wikipedia.org/wiki/Validity

    )r   r   )r   r   r   r   validZ   s    r   c                s   ddl m ddlm  d fdd| kr:| S t| } | sVtd|  tfdd	| D }| |}|krt	|S |rtd
d	 |
 D }t||rt|rdS nt|sdS dS )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, C
    >>> 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)BooleanFunction)TFc                s<   t | s| krdS t |  s$dS tfdd| jD S )NTFc             3   s   | ]} |V  qd S )Nr   ).0arg)	_validater   r   	<genexpr>   s    z-pl_true.<locals>._validate.<locals>.<genexpr>)
isinstanceallr   )r   )r   r   r   booleanr   r   r      s
    
zpl_true.<locals>._validatez$%s is not a valid boolean expressionc             3   s"   | ]\}}| kr||fV  qd S )Nr   )r   kv)r    r   r   r      s    zpl_true.<locals>.<genexpr>c             s   s   | ]}|d fV  qdS )TNr   )r   r!   r   r   r   r      s    TFN)Zsympy.core.symbolr   sympy.logic.boolalgr   r	   r   dictitemsZsubsboolZatomspl_truer   r   )r   ZmodelZdeepresultr   )r   r   r   r    r   r'   r   s*    '

r'   c             C   s$   t |}|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] http://en.wikipedia.org/wiki/Logical_consequence

    )listappendr   r   r   )r   Zformula_setr   r   r   entails   s    r+   c               @   s>   e Zd ZdZdddZdd Zdd Zd	d
 Zedd Z	dS )KBz"Base class for all knowledge basesNc             C   s   t  | _|r| | d S )N)setclauses_tell)selfsentencer   r   r   __init__   s    zKB.__init__c             C   s   t d S )N)r   )r0   r1   r   r   r   r/      s    zKB.tellc             C   s   t d S )N)r   )r0   queryr   r   r   ask   s    zKB.askc             C   s   t d S )N)r   )r0   r1   r   r   r   retract   s    z
KB.retractc             C   s   t t| jS )N)r)   r   r.   )r0   r   r   r   clauses   s    z
KB.clauses)N)
__name__
__module____qualname____doc__r2   r/   r4   r5   propertyr6   r   r   r   r   r,      s   
r,   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	PropKBz=A KB for Propositional Logic.  Inefficient, with no indexing.c             C   s&   x t t|D ]}| j| qW dS )ah  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   r.   add)r0   r1   cr   r   r   r/      s    zPropKB.tellc             C   s   t || jS )a7  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
        )r+   r.   )r0   r3   r   r   r   r4     s    z
PropKB.askc             C   s&   x t t|D ]}| j| qW dS )al  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   r.   discard)r0   r1   r>   r   r   r   r5     s    zPropKB.retractN)r7   r8   r9   r:   r/   r4   r5   r   r   r   r   r<      s   r<   N)r   F)r:   Z
__future__r   r   r#   r   r   r   r   Zsympy.core.compatibilityr   Zsympy.core.sympifyr	   r
   r   r   r'   r+   objectr,   r<   r   r   r   r   <module>   s   
4F