Ë
    täiá-  ã                   óÈ   — 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	            úg/Volumes/fast/ai/experiments/MLX_z-image/.venv/lib/python3.12/site-packages/sympy/assumptions/satask.pyÚsataskr!      s�   € ôd �M‰M˜+Ó&€EÜ�]‰]˜K˜<Ó(€Fä—-‘- Ó,€Kä“%€KÙØ!×(Ñ(¨Ó1ˆä
  ¨°[Ø'°Jô@€Cà×Ñ�[Ô!ÙØ×Ñ˜Ô%ä  v¨sÓ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ä‹E€EÙØ�×+Ñ+Ó-Ñ-ˆÙØ�×'Ñ'Ó)Ñ)ˆà”Q—V‘VœQŸW™WÐ%Ñ%€EØ€HØ
”c“eÒ
Ü‹eˆÛˆAÜ “?ˆDØ�x‘¤C£EÓ)Ø�t‘‘ð ð ˜‘>ˆØ�HÑˆð ”c“eÓ
ð 	™ÓE™�1¤¨a£°8Ñ!;¼s»uÓ!DŠQ˜ÑEÑE€Dä‹E€EÛˆÜ�cÔ+Ô,Ø”S˜Ÿ™Ó'Ñ'‰Eà�I‰I�c�Nð	 ð
 €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 Ü›ˆä‹u€HÛˆÜ'¨Ö-ˆDÜ—j‘j Ó&ˆGØ+×0Ñ0°Ó9ˆNØ×-Ñ-Ö/�Ü˜cÔ#3Õ4Ø¤ C§M¡MÓ 2Ñ2‘Hñ 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   è ø€ ÐI¹y°tˆt�y‰yœJ¤zÓ2Õ2¹yùs   ‚&(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-   è ø€ ÐaÑW`Èt�—‘œjÑ(ÒI¨d¯i©i¼=Ñ.HÓIÑW`ùs   ‚24c                 ó    — | dkD  r| |z   S | |z
  S )Nr   © )ÚlitÚdeltas     r    Útranslate_literalz1get_all_relevant_facts.<locals>.translate_literal[  s   € Ø�QŠwØ˜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ÔUÑPTÀf¹&ÓA¹&°QÑ& q¨%Õ0¸&ÓAÐPTÒ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Ü“U€NÜ“€IØ
Ø�Š6Ü$ [°+¸wÓGˆEØ�UÑˆ	Ü 5°e¸^Ó LÑˆˆ~Ø	ˆQ‰ˆØ�
Š?ØÙØð ò Ü›%ˆäÑI¹yÓIÔIØ×'Ñ'Ô(BÓ(DÔEäÑaÑW`ÓaÔaØ×'Ñ'Ô(BÓ(DÔEä“\ˆ
Ø×Ñ˜OÔ,ò	#ô	VàˆØˆÜ�J×&Ñ&Ó'ˆÜ  Ö+‰GˆAˆtØ¨z×/AÒ/AÓBÑ/A t™˜T�
Ð/AÑBÑBˆGØ‘N :§?¡?°A¸±IÓ>Ñ>‰Dð ,ô œœS ¬%°´3°w³<À±>Ó*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4òH5ó07òró$R,ðl ¨ôdr"   