K i-dZddlmZddlmZddlmZmZddlm Z m Z ddl m Z m Z ddlmZddlmZdd lmZdd lmZmZdd lmZd e d efd ZdZddZdZddZd efdZy)zJ Module to evaluate the proposition with assumptions using SAT algorithm. )S)Symbol) NumberKind UndefinedKind)get_all_known_matrix_factsget_all_known_number_facts)global_assumptionsAppliedPredicate)class_fact_registry)oo) satisfiable)CNF EncodedCNF) MatrixKindTc>tj|}tj|}tj|}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_propextendget_all_relevant_facts add_from_cnfcheck_satisfiability) proposition assumptionscontextrrprops_props context_cnfsats ^/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/assumptions/satask.pysataskr!sd MM+ &E ]]K< (F-- ,K%K!((1  ['J @C[! % vs 33c|j}|j}|j||j|t|}t|}|r|ry|r|sy|s|ry|s|s tdyy)NTFzInconsistent assumptions)copyrr ValueError)prop_propfactbasesat_true sat_false can_be_true can_be_falses r rrUsz}}H I $ 5!h'Ky)L|< < |344 ,;r"Nct|}|j}t}|r||jz}|r||jz}|tjtj hz }d}|tk7rJt}|D]#}t|} | |ztk7s|| z}%||z }||z}|tk7rJ||Dchc]}t||ztk7s| c}z}t} |D]<} t | tr| t| jz} ,| j| >| Scc}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_symbolsall_predicatessetrtruefalse isinstancer argumentsadd) rrrreq_keyskeyslkeystmp_keystmplsymsexprskeys r extract_predargsr?msA8K(H  % % 'D EE ++-- '')) QVVQWW% %EH ce e A?DxCE)t  >H ce   E1a8!;su!DQ EED EE c+ , S' 'E IIcN  L Fs E0Ect|tr/t}|jD]}|t |z}|S|j t S)z Find every :obj:`~.Symbol` in *pred*. Parameters ========== pred : sympy.assumptions.cnf.CNF, or any Expr. )r3rr0r/r.atomsr)predsymbolsas r r.r.sO$%$$& 'A |A &G ' ::f r"c2|s t}t}|D]v}t|D]f}tj|}|j |}|j D]+}t |ts|t|jz}-hx||z |fS)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() ) rr0r to_CNF_andr/r3r r4)r=relevant_factsnewexprsexprfactnewfactr>s r get_relevant_clsfactsrMsL uH3'- 3Djj&G+009N--/ 3c#34CMM 22H 3 33 e ^ ++r"c >d}t}t} |dk(r t|||}|z}t||\}}|dz }||k\rn|sn5|r,t} t d|Dr| j t t d|Dr| j tt} | j| dfd} g} g} t| j}t|D]A\}}| | jDcgc] }|| c}z } | | | j||zz } Cttt!| t#dt| dz}t| |}n t}|j%||Scc}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 rc3TK|] }|jttk("ywN)kindrr.0rJs r z)get_all_relevant_facts..RsIttyyJz22Is&(c3lK|],}|jtk(xs|jtk(.ywrQ)rRrrrSs r rUz)get_all_relevant_facts..Us*atj(Idii=.HIas24c |dkDr||zS||z S)Nr)litdeltas r translate_literalz1get_all_relevant_facts..translate_literal[sQwU{"U{"r"c h|Dcgc]}|Dchc] }|| c}c}}Scc}wcc}}wrQrX)datarZclauseir[s r translate_dataz.get_all_relevant_facts..translate_dataas-PTUf&AQ&q%0AU UAUs .) ..)rr0r?rMany add_clausesrrrfrom_cnflenrC enumerater]dictlistzipranger)rrrrrr_rH all_exprsr=known_facts_CNF kf_encodedr`r]rCn_litrJrBencodingctxr[s @r rr sh AUNI  6$[+wGEU 5e^ L~ Q ?   % IyI I  ' '(B(D E aW`a a  ' '(B(D E\ O, #  VJ&&' + ?GAt z/A/ABtT B BG N:??AI> >D ?S%3w<>*BCDEx(l^$ JCs F)NNrQ)__doc__sympy.core.singletonrsympy.core.symbolrsympy.core.kindrrsympy.assumptions.ask_generatedrrsympy.assumptions.assumer r sympy.assumptions.sathandlersr sympy.corer sympy.logic.inferencer sympy.assumptions.cnfrrsympy.matrices.kindrr!rr?r.rMrrXr"r r{sb#$5bI=-1*%)2DA4H507r$R,ldr"