
    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y)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                 >   t        j                  |       }t        j                  |        }t        j                  |      }t               }|r|j                  |      }t        |||||      }|j	                  |       |r|j	                  |       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	            M/var/www/openai/venv/lib/python3.12/site-packages/sympy/assumptions/satask.pysataskr!      s    d MM+&E]]K<(F--,K%K!((1
 ['J@C[!%vs33    c                     |j                         }|j                         }|j                  |        |j                  |       t        |      }t        |      }|r|ry |r|sy|s|ry|s|st        d      y y )NTFzInconsistent assumptions)copyr   r   
ValueError)prop_propfactbasesat_true	sat_falsecan_be_truecan_be_falses          r    r   r   U   sz    }}HI$5!h'Ky)L|<<| 344	  ,;r"   Nc                    t        |       }| j                         }t               }|r||j                         z  }|r||j                         z  }|t        j                  t        j
                  hz
  }d}|t               k7  rJt               }|D ]#  }t        |      }	|	|z  t               k7  s||	z  }% ||z
  }||z  }|t               k7  rJ||D ch c]  }t        |      |z  t               k7  s|  c}z  }t               }
|D ]<  }t        |t              r|
t        |j                        z  }
,|
j                  |       > |
S c c}w )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)}

    N)
find_symbolsall_predicatessetr   truefalse
isinstancer
   	argumentsadd)r   r   r   req_keyskeyslkeystmp_keystmplsymsexprskeys               r    extract_predargsr?   m   s;   8 K(H%%'DEE++--''))QVVQWW%%EH
ce
eA?DxCE)t  >H ce
 	E1a8!;su!DQEEDEEc+,S''EIIcN	 
 L Fs   E0Ec                     t        | t              r/t               }| j                         D ]  }|t	        |      z  } |S | j                  t              S )z
    Find every :obj:`~.Symbol` in *pred*.

    Parameters
    ==========

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

    )r3   r   r0   r/   r.   atomsr   )predsymbolsas      r    r.   r.      sJ     $%$$&A|A&G '::fr"   c                 2   |s
t               }t               }| D ]v  }t        |      D ]f  }t        j                  |      }|j	                  |      }|j                         D ]+  }t        |t              s|t        |j                        z  }- h x || 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   r0   r   to_CNF_andr/   r3   r
   r4   )r=   relevant_factsnewexprsexprfactnewfactr>   s          r    get_relevant_clsfactsrM      s    L uH'-Djj&G+009N--/c#34CMM 22H 0 .  e^++r"   c                 >   d}t               }t               }	 |dk(  rt        | ||      }|z  }t        ||      \  }}|dz  }||k\  rn|sn5|r,t               }	t	        d |D              r|	j                  t                      t	        d |D              r|	j                  t                      t               }
|
j                  |	       d fd}g }g }t        |
j                        }t        |      D ]A  \  }}||
j                  D cg c]
  } ||       c}z  }| ||
j                  ||z        z  }C t        t        t!        |t#        dt        |      dz                           }t        ||      }n
t               }|j%                  |       |S c c}w )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      c              3   T   K   | ]   }|j                   t        t              k(   " y wN)kindr   r   .0rJ   s     r    	<genexpr>z)get_all_relevant_facts.<locals>.<genexpr>R  s     IyttyyJz22ys   &(c              3   l   K   | ],  }|j                   t        k(  xs |j                   t        k(   . y wrQ   )rR   r   r   rS   s     r    rU   z)get_all_relevant_facts.<locals>.<genexpr>U  s-     aW`tj(Idii=.HIW`s   24c                      | dkD  r| |z   S | |z
  S )Nr    )litdeltas     r    translate_literalz1get_all_relevant_facts.<locals>.translate_literal[  s    QwU{"U{"r"   c                 h    | D cg c]  }|D ch c]  } ||       c} c}}S c c}w c c}}w rQ   rX   )datarZ   clauseir[   s       r    translate_dataz.get_all_relevant_facts.<locals>.translate_dataa  s7    PTUPTf&A&Q&q%0&APTUUAUs   	.)..)r   r0   r?   rM   anyadd_clausesr   r   r   from_cnflenrC   	enumerater]   dictlistzipranger   )r   r   r   r   r   r_   rH   	all_exprsr=   known_facts_CNF
kf_encodedr`   r]   rC   n_litrJ   rB   encodingctxr[   s                      @r    r   r     s   h 	
AUNI
6$[+wGEU	 5e^ L~	Q
?  %IyII''(B(DEaW`aa''(B(DE\
O,	#	VJ&&' +GAtz/A/AB/AtT
/ABBGN:??AI>>D , S%3w<>*BCDEx(l^$J Cs   F)NNrQ   )__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   r?   r.   rM   r   rX   r"   r    <module>r{      sb    # $ 5 b I =  - 1 * %)2DA4H507r$R,l dr"   