
    g-                         d Z ddlmZ ddlmZ ddlmZmZ ddlm	Z	m
Z
 ddlmZmZ ddlmZ ddlmZ dd	lmZ dd
lmZmZ ddlmZ dedefdZd ZddZd ZddZdefdZdS )zJ
Module to evaluate the proposition with assumptions using SAT algorithm.
    )S)Symbol)
NumberKindUndefinedKind)get_all_known_matrix_factsget_all_known_number_facts)global_assumptionsAppliedPredicate)class_fact_registry)oo)satisfiable)CNF
EncodedCNF)
MatrixKindTc                 h   t          j        |           }t          j        |            }t          j        |          }t                      }|r|                    |          }t          |||||          }|                    |           |r|                    |           t          |||          S )a  
    Function to evaluate the proposition with assumptions using SAT algorithm.

    This function extracts every fact relevant to the expressions composing
    proposition and assumptions. For example, if a predicate containing
    ``Abs(x)`` is proposed, then ``Q.zero(Abs(x)) | Q.positive(Abs(x))``
    will be found and passed to SAT solver because ``Q.nonnegative`` is
    registered as a fact for ``Abs``.

    Proposition is evaluated to ``True`` or ``False`` if the truth value can be
    determined. If not, ``None`` is returned.

    Parameters
    ==========

    proposition : Any boolean expression.
        Proposition which will be evaluated to boolean value.

    assumptions : Any boolean expression, optional.
        Local assumptions to evaluate the *proposition*.

    context : AssumptionsContext, optional.
        Default assumptions to evaluate the *proposition*. By default,
        this is ``sympy.assumptions.global_assumptions`` variable.

    use_known_facts : bool, optional.
        If ``True``, facts from ``sympy.assumptions.ask_generated``
        module are passed to SAT solver as well.

    iterations : int, optional.
        Number of times that relevant facts are recursively extracted.
        Default is infinite times until no new fact is found.

    Returns
    =======

    ``True``, ``False``, or ``None``

    Examples
    ========

    >>> from sympy import Abs, Q
    >>> from sympy.assumptions.satask import satask
    >>> from sympy.abc import x
    >>> satask(Q.zero(Abs(x)), Q.zero(x))
    True

    )use_known_facts
iterations)r   	from_propextendget_all_relevant_factsadd_from_cnfcheck_satisfiability)	propositionassumptionscontextr   r   props_propscontext_cnfsats	            T/var/www/html/ai-engine/env/lib/python3.11/site-packages/sympy/assumptions/satask.pysataskr!      s    d M+&&E]K<((F-,,K%%K 2!((11
 ['J@ @ @C[!!! &%%%vs333    c                 4   |                                 }|                                 }|                    |            |                    |           t          |          }t          |          }|r|rd S |r|sdS |s|rdS |s|st          d          d S d S )NTFzInconsistent assumptions)copyr   r   
ValueError)prop_propfactbasesat_true	sat_falsecan_be_truecan_be_falses          r    r   r   U   s    }}HI$5!!!h''Ky))L | t < t < u 5| 5 3444	5 5 5 5r"   Nc                    t          |           |                                 }t                      }|r||                                z  }|r||                                z  }|t          j        t          j        hz
  }d}|t                      k    rXt                      }|D ]+}t          |          }|z  t                      k    r||z  },|z
  }|z  |t                      k    X|fd|D             z  }t                      }	|D ]D}
t          |
t                    r|	t          |
j                  z  }	/|		                    |
           E|	S )a  
    Extract every expression in the argument of predicates from *proposition*,
    *assumptions* and *context*.

    Parameters
    ==========

    proposition : sympy.assumptions.cnf.CNF

    assumptions : sympy.assumptions.cnf.CNF, optional.

    context : sympy.assumptions.cnf.CNF, optional.
        CNF generated from assumptions context.

    Examples
    ========

    >>> from sympy import Q, Abs
    >>> from sympy.assumptions.cnf import CNF
    >>> from sympy.assumptions.satask import extract_predargs
    >>> from sympy.abc import x, y
    >>> props = CNF.from_prop(Q.zero(Abs(x*y)))
    >>> assump = CNF.from_prop(Q.zero(x) & Q.zero(y))
    >>> extract_predargs(props, assump)
    {x, y, Abs(x*y)}

    Nc                 X    h | ]&}t          |          z  t                      k    $|'S  )find_symbolsset).0lreq_keyss     r    	<setcomp>z#extract_predargs.<locals>.<setcomp>   s2    EEE1a8!;suu!D!DQ!D!D!Dr"   )
r0   all_predicatesr1   r   truefalse
isinstancer
   	argumentsadd)r   r   r   keyslkeystmp_keystmpr3   symsexprskeyr4   s              @r    extract_predargsrC   m   sk   8 K((H%%''DEEE .++--- *'')))QVQW%%EH
cee

ee 	 	A??DxCEE))t>H cee

 	EEEEEEEEDEEE  c+,, 	S'''EEIIcNNNNLr"   c                     t          | t                    r9t                      }|                                 D ]}|t	          |          z  }|S |                     t                    S )z
    Find every :obj:`~.Symbol` in *pred*.

    Parameters
    ==========

    pred : sympy.assumptions.cnf.CNF, or any Expr.

    )r9   r   r1   r6   r0   atomsr   )predsymbolsas      r    r0   r0      sc     $ %%$$&& 	' 	'A|A&GG::fr"   c                 R   |st                      }t                      }| D ]}t          |          D ]n}t          j        |          }|                    |          }|                                D ].}t          |t                    r|t          |j                  z  }/o|| z
  |fS )a2	  
    Extract relevant facts from the items in *exprs*. Facts are defined in
    ``assumptions.sathandlers`` module.

    This function is recursively called by ``get_all_relevant_facts()``.

    Parameters
    ==========

    exprs : set
        Expressions whose relevant facts are searched.

    relevant_facts : sympy.assumptions.cnf.CNF, optional.
        Pre-discovered relevant facts.

    Returns
    =======

    exprs : set
        Candidates for next relevant fact searching.

    relevant_facts : sympy.assumptions.cnf.CNF
        Updated relevant facts.

    Examples
    ========

    Here, we will see how facts relevant to ``Abs(x*y)`` are recursively
    extracted. On the first run, set containing the expression is passed
    without pre-discovered relevant facts. The result is a set containing
    candidates for next run, and ``CNF()`` instance containing facts
    which are relevant to ``Abs`` and its argument.

    >>> from sympy import Abs
    >>> from sympy.assumptions.satask import get_relevant_clsfacts
    >>> from sympy.abc import x, y
    >>> exprs = {Abs(x*y)}
    >>> exprs, facts = get_relevant_clsfacts(exprs)
    >>> exprs
    {x*y}
    >>> facts.clauses #doctest: +SKIP
    {frozenset({Literal(Q.odd(Abs(x*y)), False), Literal(Q.odd(x*y), True)}),
    frozenset({Literal(Q.zero(Abs(x*y)), False), Literal(Q.zero(x*y), True)}),
    frozenset({Literal(Q.even(Abs(x*y)), False), Literal(Q.even(x*y), True)}),
    frozenset({Literal(Q.zero(Abs(x*y)), True), Literal(Q.zero(x*y), False)}),
    frozenset({Literal(Q.even(Abs(x*y)), False),
                Literal(Q.odd(Abs(x*y)), False),
                Literal(Q.odd(x*y), True)}),
    frozenset({Literal(Q.even(Abs(x*y)), False),
                Literal(Q.even(x*y), True),
                Literal(Q.odd(Abs(x*y)), False)}),
    frozenset({Literal(Q.positive(Abs(x*y)), False),
                Literal(Q.zero(Abs(x*y)), False)})}

    We pass the first run's results to the second run, and get the expressions
    for next run and updated facts.

    >>> exprs, facts = get_relevant_clsfacts(exprs, relevant_facts=facts)
    >>> exprs
    {x, y}

    On final run, no more candidate is returned thus we know that all
    relevant facts are successfully retrieved.

    >>> exprs, facts = get_relevant_clsfacts(exprs, relevant_facts=facts)
    >>> exprs
    set()

    )	r   r1   r   to_CNF_andr6   r9   r
   r:   )rA   relevant_factsnewexprsexprfactnewfactrB   s          r    get_relevant_clsfactsrQ      s    L  uuH 3 3'-- 	3 	3Dj&&G+0099N--// 3 3c#344 3CM 2 22H3	3 e^++r"   c                    d}t                      }t                      }	 |dk    rt          | ||          }||z  }t          ||          \  }}|dz  }||k    rn|sn?|r`t                      }	t	          d |D                       r!|	                    t                                 t	          d |D                       r!|	                    t                                 t                      }
|
	                    |	           d fd}g }g }t          |
j                  }t          |          D ]2\  }|fd|
j        D             z  }| ||
j        ||z            z  }3t          t          t!          |t#          dt          |          dz                                           }t          ||          }nt                      }|                    |           |S )	al  
    Extract all relevant facts from *proposition* and *assumptions*.

    This function extracts the facts by recursively calling
    ``get_relevant_clsfacts()``. Extracted facts are converted to
    ``EncodedCNF`` and returned.

    Parameters
    ==========

    proposition : sympy.assumptions.cnf.CNF
        CNF generated from proposition expression.

    assumptions : sympy.assumptions.cnf.CNF
        CNF generated from assumption expression.

    context : sympy.assumptions.cnf.CNF
        CNF generated from assumptions context.

    use_known_facts : bool, optional.
        If ``True``, facts from ``sympy.assumptions.ask_generated``
        module are encoded as well.

    iterations : int, optional.
        Number of times that relevant facts are recursively extracted.
        Default is infinite times until no new fact is found.

    Returns
    =======

    sympy.assumptions.cnf.EncodedCNF

    Examples
    ========

    >>> from sympy import Q
    >>> from sympy.assumptions.cnf import CNF
    >>> from sympy.assumptions.satask import get_all_relevant_facts
    >>> from sympy.abc import x, y
    >>> props = CNF.from_prop(Q.nonzero(x*y))
    >>> assump = CNF.from_prop(Q.nonzero(x))
    >>> context = CNF.from_prop(Q.nonzero(y))
    >>> get_all_relevant_facts(props, assump, context) #doctest: +SKIP
    <sympy.assumptions.cnf.EncodedCNF at 0x7f09faa6ccd0>

    r   T   c              3   P   K   | ]!}|j         t          t                    k    V  "d S N)kindr   r   r2   rN   s     r    	<genexpr>z)get_all_relevant_facts.<locals>.<genexpr>R  s1      IIttyJz222IIIIIIr"   c              3   V   K   | ]$}|j         t          k    p|j         t          k    V  %d S rU   )rV   r   r   rW   s     r    rX   z)get_all_relevant_facts.<locals>.<genexpr>U  s5      aatj(Idi=.Haaaaaar"   c                 "    | dk    r| |z   S | |z
  S )Nr   r/   )litdeltas     r    translate_literalz1get_all_relevant_facts.<locals>.translate_literal[  s    QwwU{"U{"r"   c                 $    fd| D             S )Nc                 .    g | ]}fd |D             S )c                 (    h | ]} |          S r/   r/   )r2   ir\   r]   s     r    r5   zLget_all_relevant_facts.<locals>.translate_data.<locals>.<listcomp>.<setcomp>b  s'    AAAQ&&q%00AAAr"   r/   )r2   clauser\   r]   s     r    
<listcomp>zBget_all_relevant_facts.<locals>.translate_data.<locals>.<listcomp>b  s1    UUUfAAAAA&AAAUUUr"   r/   )datar\   r]   s    `r    translate_dataz.get_all_relevant_facts.<locals>.translate_dataa  s"    UUUUUPTUUUUr"   c                 &    g | ]} |          S r/   r/   )r2   rF   rN   s     r    rc   z*get_all_relevant_facts.<locals>.<listcomp>g  s!    BBBtT

BBBr"   )r   r1   rC   rQ   anyadd_clausesr   r   r   from_cnflenrG   	enumeraterd   dictlistzipranger   )r   r   r   r   r   ra   rL   	all_exprsrA   known_facts_CNF
kf_encodedre   rd   rG   n_litencodingctxrN   r]   s                    @@r    r   r     s/   h 	
AUUNI	66$[+wGGEU	 5e^ L L~	Q
?? 		  %%IIyIIIII 	F''(B(D(DEEEaaW`aaaaa 	F''(B(D(DEEE\\
O,,,	# 	# 	#	V 	V 	V 	V 	VJ&'' ++ 	? 	?GAtBBBBz/ABBBBGNN:?AI>>>DDS%3w<<>*B*BCCDDEEx((ll^$$$Jr"   )NNrU   )__doc__sympy.core.singletonr   sympy.core.symbolr   sympy.core.kindr   r   sympy.assumptions.ask_generatedr   r   sympy.assumptions.assumer	   r
   sympy.assumptions.sathandlersr   
sympy.corer   sympy.logic.inferencer   sympy.assumptions.cnfr   r   sympy.matrices.kindr   r!   r   rC   r0   rQ   r   r/   r"   r    <module>r      sz    # " " " " " $ $ $ $ $ $ 5 5 5 5 5 5 5 5 b b b b b b b b I I I I I I I I = = = = = =       - - - - - - 1 1 1 1 1 1 1 1 * * * * * * %)2DA4 A4 A4 A4H5 5 507 7 7 7r  $R, R, R, R,l d d d d d dr"   