Last active
July 12, 2025 23:50
-
-
Save asmeurer/d4a53cec804cf2d75fd8bb7cce9f5126 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Using CPython 3.14.0a6 | |
Creating virtual environment at: .venv | |
Activate with: source .venv/bin/activate | |
Resolved 10 packages in 1ms | |
Installed 10 packages in 11ms | |
+ attrs==25.3.0 | |
+ hypothesis==6.135.29 | |
+ iniconfig==2.1.0 | |
+ mpmath==1.3.0 | |
+ packaging==25.0 | |
+ pluggy==1.6.0 | |
+ pygments==2.19.2 | |
+ pytest==8.4.1 | |
+ pytest-run-parallel==0.4.4 | |
+ sortedcontainers==2.4.0 | |
=========================================================================== test session starts =========================================================================== | |
platform darwin -- Python 3.14.0a6, pytest-8.4.1, pluggy-1.6.0 | |
architecture: 64-bit | |
cache: yes | |
ground types: python | |
rootdir: /Users/aaronmeurer/Documents/Python/sympy/sympy | |
configfile: pyproject.toml | |
testpaths: sympy, doc/src | |
plugins: hypothesis-6.135.29, run-parallel-0.4.4 | |
collected 13875 items / 199 deselected / 13676 selected | |
Collected 13528 items to run in parallel | |
sympy/algebras/tests/test_quaternion.py ·················· [ 0%] | |
sympy/assumptions/tests/test_assumptions_2.py ··e [ 0%] | |
sympy/assumptions/tests/test_context.py eeee [ 0%] | |
sympy/assumptions/tests/test_matrices.py ···x··········x······ [ 0%] | |
sympy/assumptions/tests/test_query.py ·················ee·exxeeex·eeeeee··ex·eeeeeee·eee··e··.····e····ex···ee··e· [ 0%] | |
sympy/assumptions/tests/test_refine.py eee···ee········ [ 1%] | |
sympy/assumptions/tests/test_rel_queries.py eee·eexex [ 1%] | |
sympy/assumptions/tests/test_satask.py e···x··eee·ee······ [ 1%] | |
sympy/assumptions/tests/test_sathandlers.py ···· [ 1%] | |
sympy/assumptions/tests/test_wrapper.py ···· [ 1%] | |
sympy/calculus/tests/test_accumulationbounds.py ·····x······ [ 1%] | |
sympy/calculus/tests/test_euler.py ······ [ 1%] | |
sympy/calculus/tests/test_finite_diff.py ···e [ 1%] | |
sympy/calculus/tests/test_singularities.py ······e [ 1%] | |
sympy/calculus/tests/test_util.py ··xxx············ [ 1%] | |
sympy/categories/tests/test_baseclasses.py ··· [ 1%] | |
sympy/categories/tests/test_drawing.py ········· [ 1%] | |
sympy/codegen/tests/test_abstract_nodes.py · [ 1%] | |
sympy/codegen/tests/test_algorithms.py ·ss·s· [ 1%] | |
sympy/codegen/tests/test_applications.py s [ 1%] | |
sympy/codegen/tests/test_approximations.py ··· [ 1%] | |
sympy/codegen/tests/test_ast.py ······························· [ 2%] | |
sympy/codegen/tests/test_cfunctions.py ·········· [ 2%] | |
sympy/codegen/tests/test_cnodes.py ·········· [ 2%] | |
sympy/codegen/tests/test_cxxnodes.py · [ 2%] | |
sympy/codegen/tests/test_fnodes.py ············s [ 2%] | |
sympy/codegen/tests/test_matrix_nodes.py ··s [ 2%] | |
sympy/codegen/tests/test_numpy_nodes.py ···· [ 2%] | |
sympy/codegen/tests/test_pynodes.py · [ 2%] | |
sympy/codegen/tests/test_pyutils.py · [ 2%] | |
sympy/codegen/tests/test_rewriting.py ·················xs [ 2%] | |
sympy/codegen/tests/test_scipy_nodes.py ·· [ 2%] | |
sympy/combinatorics/tests/test_coset_table.py ··· [ 2%] | |
sympy/combinatorics/tests/test_fp_groups.py ······· [ 2%] | |
sympy/combinatorics/tests/test_free_groups.py ·····e················ [ 2%] | |
sympy/combinatorics/tests/test_galois.py ··· [ 2%] | |
sympy/combinatorics/tests/test_generators.py · [ 2%] | |
sympy/combinatorics/tests/test_graycode.py ·· [ 2%] | |
sympy/combinatorics/tests/test_group_constructs.py · [ 2%] | |
sympy/combinatorics/tests/test_group_numbers.py ····· [ 2%] | |
sympy/combinatorics/tests/test_homomorphisms.py ··· [ 2%] | |
sympy/combinatorics/tests/test_named_groups.py ······ [ 2%] | |
sympy/combinatorics/tests/test_partitions.py ····· [ 2%] | |
sympy/combinatorics/tests/test_pc_groups.py ··· [ 2%] | |
sympy/combinatorics/tests/test_perm_groups.py ···············s···············s····························· [ 3%] | |
sympy/combinatorics/tests/test_permutations.py ·e·········e···· [ 3%] | |
sympy/combinatorics/tests/test_polyhedron.py ·· [ 3%] | |
sympy/combinatorics/tests/test_prufer.py ·· [ 3%] | |
sympy/combinatorics/tests/test_rewriting.py · [ 3%] | |
sympy/combinatorics/tests/test_schur_number.py ·· [ 3%] | |
sympy/combinatorics/tests/test_subsets.py ·· [ 3%] | |
sympy/combinatorics/tests/test_tensor_can.py ·········s·· [ 3%] | |
sympy/combinatorics/tests/test_testutil.py ····· [ 3%] | |
sympy/combinatorics/tests/test_util.py ········ [ 3%] | |
sympy/concrete/tests/test_delta.py ··························· [ 3%] | |
sympy/concrete/tests/test_gosper.py ··········· [ 4%] | |
sympy/concrete/tests/test_guess.py ··e··· [ 4%] | |
sympy/concrete/tests/test_products.py ······················ [ 4%] | |
sympy/concrete/tests/test_sums_products.py ············^C | |
================================================================================= ERRORS ================================================================================== | |
______________________________________________________________________ ERROR at call of test_global _______________________________________________________________________ | |
def test_global(): | |
"""Test for global assumptions""" | |
global_assumptions.add(x > 0) | |
assert (x > 0) in global_assumptions | |
> global_assumptions.remove(x > 0) | |
E KeyError: x > 0 | |
sympy/assumptions/tests/test_assumptions_2.py:27: KeyError | |
_____________________________________________________________________ ERROR at call of test_assuming ______________________________________________________________________ | |
def test_assuming(): | |
with assuming(Q.integer(x)): | |
assert ask(Q.integer(x)) | |
> assert not ask(Q.integer(x)) | |
E assert not True | |
E + where True = ask(Q.integer(x)) | |
E + where Q.integer(x) = Q.integer(x) | |
E + where Q.integer = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.integer | |
sympy/assumptions/tests/test_context.py:8: AssertionError | |
__________________________________________________________________ ERROR at call of test_assuming_nested __________________________________________________________________ | |
def test_assuming_nested(): | |
> assert not ask(Q.integer(x)) | |
E assert not True | |
E + where True = ask(Q.integer(x)) | |
E + where Q.integer(x) = Q.integer(x) | |
E + where Q.integer = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.integer | |
sympy/assumptions/tests/test_context.py:11: AssertionError | |
______________________________________________________________________ ERROR at call of test_finally ______________________________________________________________________ | |
def test_finally(): | |
try: | |
with assuming(Q.integer(x)): | |
1/0 | |
except ZeroDivisionError: | |
pass | |
> assert not ask(Q.integer(x)) | |
E assert not True | |
E + where True = ask(Q.integer(x)) | |
E + where Q.integer(x) = Q.integer(x) | |
E + where Q.integer = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.integer | |
sympy/assumptions/tests/test_context.py:30: AssertionError | |
____________________________________________________________________ ERROR at call of test_remove_safe ____________________________________________________________________ | |
def test_remove_safe(): | |
global_assumptions.add(Q.integer(x)) | |
with assuming(): | |
assert ask(Q.integer(x)) | |
> global_assumptions.remove(Q.integer(x)) | |
E KeyError: Q.integer(x) | |
sympy/assumptions/tests/test_context.py:36: KeyError | |
______________________________________________________________________ ERROR at call of test_bounded ______________________________________________________________________ | |
def test_bounded(): | |
x, y, z = symbols('x,y,z') | |
a = x + y | |
x, y = a.args | |
> assert ask(Q.finite(a), Q.positive_infinite(y)) is None | |
E assert False is None | |
E + where False = ask(Q.finite(x + y), Q.positive_infinite(y)) | |
E + where Q.finite(x + y) = Q.finite(x + y) | |
E + where Q.finite = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.finite | |
E + and Q.positive_infinite(y) = Q.positive_infinite(y) | |
E + where Q.positive_infinite = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.positive_infinite | |
sympy/assumptions/tests/test_query.py:636: AssertionError | |
_____________________________________________________________________ ERROR at call of test_unbounded _____________________________________________________________________ | |
def test_unbounded(): | |
assert ask(Q.infinite(I * oo)) is True | |
assert ask(Q.infinite(1 + I*oo)) is True | |
assert ask(Q.infinite(3 * (I * oo))) is True | |
assert ask(Q.infinite(-I * oo)) is True | |
assert ask(Q.infinite(1 + zoo)) is True | |
assert ask(Q.infinite(I * zoo)) is True | |
> assert ask(Q.infinite(x / y), Q.infinite(x) & Q.finite(y) & ~Q.zero(y)) is True | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1150: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/ask.py:501: in ask | |
res = key(*args)._eval_ask(assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:156: in _eval_ask | |
return self.function.eval(self.arguments, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:348: in eval | |
result = self.handler(*args, assumptions=assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/multipledispatch/dispatcher.py:243: in __call__ | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/handlers/calculus.py:244: in _ | |
is_finite = Q.finite(expr)._eval_ask(assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:156: in _eval_ask | |
return self.function.eval(self.arguments, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:348: in eval | |
result = self.handler(*args, assumptions=assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/multipledispatch/dispatcher.py:243: in __call__ | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/handlers/calculus.py:156: in _ | |
_bounded = ask(Q.finite(arg), assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.finite(x), assumptions = Q.finite(y) & Q.infinite(x) & ~Q.zero(y), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.finite(y) & Q.infinite(x) & ~Q.zero(y) | |
sympy/assumptions/ask.py:493: ValueError | |
____________________________________________________________________ ERROR at call of test_issue_27447 ____________________________________________________________________ | |
def test_issue_27447(): | |
x,y,z = symbols('x y z') | |
a = x*y | |
assert ask(Q.finite(a), Q.finite(x) & ~Q.finite(y)) is None | |
> assert ask(Q.finite(a), ~Q.finite(x) & Q.finite(y)) is None | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1166: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/ask.py:501: in ask | |
res = key(*args)._eval_ask(assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:156: in _eval_ask | |
return self.function.eval(self.arguments, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:348: in eval | |
result = self.handler(*args, assumptions=assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/multipledispatch/dispatcher.py:243: in __call__ | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/handlers/calculus.py:156: in _ | |
_bounded = ask(Q.finite(arg), assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.finite(x), assumptions = Q.finite(y) & ~Q.finite(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.finite(y) & ~Q.finite(x) | |
sympy/assumptions/ask.py:493: ValueError | |
____________________________________________________________________ ERROR at call of test_commutative ____________________________________________________________________ | |
def test_commutative(): | |
"""By default objects are Q.commutative that is why it returns True | |
for both key=True and key=False""" | |
assert ask(Q.commutative(x)) is True | |
> assert ask(Q.commutative(x), ~Q.commutative(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1200: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.commutative(x), assumptions = ~Q.commutative(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions ~Q.commutative(x) | |
sympy/assumptions/ask.py:493: ValueError | |
______________________________________________________________________ ERROR at call of test_complex ______________________________________________________________________ | |
@_both_exp_pow | |
def test_complex(): | |
> assert ask(Q.complex(x)) is None | |
E assert True is None | |
E + where True = ask(Q.complex(x)) | |
E + where Q.complex(x) = Q.complex(x) | |
E + where Q.complex = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.complex | |
sympy/assumptions/tests/test_query.py:1221: AssertionError | |
____________________________________________________________________ ERROR at call of test_even_query _____________________________________________________________________ | |
def test_even_query(): | |
assert ask(Q.even(x)) is None | |
assert ask(Q.even(x), Q.integer(x)) is None | |
> assert ask(Q.even(x), ~Q.integer(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1298: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.even(x), assumptions = ~Q.integer(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions ~Q.integer(x) | |
sympy/assumptions/ask.py:493: ValueError | |
___________________________________________________________________ ERROR at call of test_extended_real ___________________________________________________________________ | |
def test_extended_real(): | |
> assert ask(Q.extended_real(x), Q.positive_infinite(x)) is True | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1379: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.extended_real(x), assumptions = Q.positive_infinite(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.positive_infinite(x) | |
sympy/assumptions/ask.py:493: ValueError | |
_____________________________________________________________________ ERROR at call of test_rational ______________________________________________________________________ | |
@_both_exp_pow | |
def test_rational(): | |
assert ask(Q.rational(x), Q.integer(x)) is True | |
> assert ask(Q.rational(x), Q.irrational(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1396: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.rational(x), assumptions = Q.irrational(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.irrational(x) | |
sympy/assumptions/ask.py:493: ValueError | |
_____________________________________________________________________ ERROR at call of test_hermitian _____________________________________________________________________ | |
def test_hermitian(): | |
> assert ask(Q.hermitian(x)) is None | |
E assert True is None | |
E + where True = ask(Q.hermitian(x)) | |
E + where Q.hermitian(x) = Q.hermitian(x) | |
E + where Q.hermitian = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.hermitian | |
sympy/assumptions/tests/test_query.py:1473: AssertionError | |
_____________________________________________________________________ ERROR at call of test_imaginary _____________________________________________________________________ | |
@_both_exp_pow | |
def test_imaginary(): | |
> assert ask(Q.imaginary(x)) is None | |
E assert False is None | |
E + where False = ask(Q.imaginary(x)) | |
E + where Q.imaginary(x) = Q.imaginary(x) | |
E + where Q.imaginary = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.imaginary | |
sympy/assumptions/tests/test_query.py:1579: AssertionError | |
______________________________________________________________________ ERROR at call of test_integer ______________________________________________________________________ | |
def test_integer(): | |
> assert ask(Q.integer(x)) is None | |
E assert True is None | |
E + where True = ask(Q.integer(x)) | |
E + where Q.integer(x) = Q.integer(x) | |
E + where Q.integer = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.integer | |
sympy/assumptions/tests/test_query.py:1658: AssertionError | |
_____________________________________________________________________ ERROR at call of test_negative ______________________________________________________________________ | |
def test_negative(): | |
assert ask(Q.negative(x), Q.negative(x)) is True | |
assert ask(Q.negative(x), Q.positive(x)) is False | |
> assert ask(Q.negative(x), ~Q.real(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1702: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.negative(x), assumptions = ~Q.real(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions ~Q.real(x) | |
sympy/assumptions/ask.py:493: ValueError | |
_____________________________________________________________________ ERROR at call of test_odd_query _____________________________________________________________________ | |
def test_odd_query(): | |
assert ask(Q.odd(x)) is None | |
assert ask(Q.odd(x), Q.odd(x)) is True | |
assert ask(Q.odd(x), Q.integer(x)) is None | |
> assert ask(Q.odd(x), ~Q.integer(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1804: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.odd(x), assumptions = ~Q.integer(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions ~Q.integer(x) | |
sympy/assumptions/ask.py:493: ValueError | |
_______________________________________________________________________ ERROR at call of test_prime _______________________________________________________________________ | |
def test_prime(): | |
assert ask(Q.prime(x), Q.prime(x)) is True | |
assert ask(Q.prime(x), ~Q.prime(x)) is False | |
assert ask(Q.prime(x), Q.integer(x)) is None | |
> assert ask(Q.prime(x), ~Q.integer(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1891: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.prime(x), assumptions = ~Q.integer(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions ~Q.integer(x) | |
sympy/assumptions/ask.py:493: ValueError | |
_____________________________________________________________________ ERROR at call of test_positive ______________________________________________________________________ | |
@_both_exp_pow | |
def test_positive(): | |
assert ask(Q.positive(cos(I) ** 2 + sin(I) ** 2 - 1)) is None | |
assert ask(Q.positive(x), Q.positive(x)) is True | |
assert ask(Q.positive(x), Q.negative(x)) is False | |
assert ask(Q.positive(x), Q.nonzero(x)) is None | |
assert ask(Q.positive(-x), Q.positive(x)) is False | |
assert ask(Q.positive(-x), Q.negative(x)) is True | |
assert ask(Q.positive(x + y), Q.positive(x) & Q.positive(y)) is True | |
assert ask(Q.positive(x + y), Q.positive(x) & Q.nonnegative(y)) is True | |
assert ask(Q.positive(x + y), Q.positive(x) & Q.negative(y)) is None | |
assert ask(Q.positive(x + y), Q.positive(x) & Q.imaginary(y)) is False | |
assert ask(Q.positive(2*x), Q.positive(x)) is True | |
assumptions = Q.positive(x) & Q.negative(y) & Q.negative(z) & Q.positive(w) | |
assert ask(Q.positive(x*y*z)) is None | |
assert ask(Q.positive(x*y*z), assumptions) is True | |
assert ask(Q.positive(-x*y*z), assumptions) is False | |
assert ask(Q.positive(x**I), Q.positive(x)) is None | |
assert ask(Q.positive(x**2), Q.positive(x)) is True | |
assert ask(Q.positive(x**2), Q.negative(x)) is True | |
assert ask(Q.positive(x**3), Q.negative(x)) is False | |
assert ask(Q.positive(1/(1 + x**2)), Q.real(x)) is True | |
assert ask(Q.positive(2**I)) is False | |
assert ask(Q.positive(2 + I)) is False | |
# although this could be False, it is representative of expressions | |
# that don't evaluate to a zero with precision | |
assert ask(Q.positive(cos(I)**2 + sin(I)**2 - 1)) is None | |
assert ask(Q.positive(-I + I*(cos(2)**2 + sin(2)**2))) is None | |
#exponential | |
assert ask(Q.positive(exp(x)), Q.real(x)) is True | |
assert ask(~Q.negative(exp(x)), Q.real(x)) is True | |
assert ask(Q.positive(x + exp(x)), Q.real(x)) is None | |
> assert ask(Q.positive(exp(x)), Q.imaginary(x)) is None | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1957: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/ask.py:501: in ask | |
res = key(*args)._eval_ask(assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:156: in _eval_ask | |
return self.function.eval(self.arguments, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:348: in eval | |
result = self.handler(*args, assumptions=assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/multipledispatch/dispatcher.py:243: in __call__ | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/handlers/order.py:311: in _ | |
if ask(Q.real(expr.exp), assumptions): | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.real(x), assumptions = Q.imaginary(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.imaginary(x) | |
sympy/assumptions/ask.py:493: ValueError | |
____________________________________________________________________ ERROR at call of test_nonpositive ____________________________________________________________________ | |
def test_nonpositive(): | |
assert ask(Q.nonpositive(-1)) | |
assert ask(Q.nonpositive(0)) | |
assert ask(Q.nonpositive(1)) is False | |
assert ask(~Q.positive(x), Q.nonpositive(x)) | |
assert ask(Q.nonpositive(x), Q.positive(x)) is False | |
assert ask(Q.nonpositive(sqrt(-1))) is False | |
> assert ask(Q.nonpositive(x), Q.imaginary(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1986: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.nonpositive(x), assumptions = Q.imaginary(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.imaginary(x) | |
sympy/assumptions/ask.py:493: ValueError | |
____________________________________________________________________ ERROR at call of test_nonnegative ____________________________________________________________________ | |
def test_nonnegative(): | |
assert ask(Q.nonnegative(-1)) is False | |
assert ask(Q.nonnegative(0)) | |
assert ask(Q.nonnegative(1)) | |
assert ask(~Q.negative(x), Q.nonnegative(x)) | |
assert ask(Q.nonnegative(x), Q.negative(x)) is False | |
assert ask(Q.nonnegative(sqrt(-1))) is False | |
> assert ask(Q.nonnegative(x), Q.imaginary(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:1996: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.nonnegative(x), assumptions = Q.imaginary(x), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.imaginary(x) | |
sympy/assumptions/ask.py:493: ValueError | |
____________________________________________________________________ ERROR at call of test_real_basic _____________________________________________________________________ | |
def test_real_basic(): | |
> assert ask(Q.real(x)) is None | |
E assert True is None | |
E + where True = ask(Q.real(x)) | |
E + where Q.real(x) = Q.real(x) | |
E + where Q.real = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.real | |
sympy/assumptions/tests/test_query.py:1999: AssertionError | |
_____________________________________________________________________ ERROR at call of test_real_pow ______________________________________________________________________ | |
def test_real_pow(): | |
assert ask(Q.real(x**2), Q.real(x)) is True | |
assert ask(Q.real(sqrt(x)), Q.negative(x)) is False | |
assert ask(Q.real(x**y), Q.real(x) & Q.integer(y)) is None | |
assert ask(Q.real(x**y), Q.real(x) & Q.real(y)) is None | |
assert ask(Q.real(x**y), Q.positive(x) & Q.real(y)) is True | |
> assert ask(Q.real(x**y), Q.imaginary(x) & Q.imaginary(y)) is None # I**I or (2*I)**I | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:2027: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/ask.py:501: in ask | |
res = key(*args)._eval_ask(assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:156: in _eval_ask | |
return self.function.eval(self.arguments, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:348: in eval | |
result = self.handler(*args, assumptions=assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/multipledispatch/dispatcher.py:243: in __call__ | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/handlers/sets.py:326: in _ | |
if ask(Q.imaginary(expr.base), assumptions): | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.imaginary(x), assumptions = Q.imaginary(x) & Q.imaginary(y), context = AssumptionsContext({Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.imaginary(x) & Q.imaginary(y) | |
sympy/assumptions/ask.py:493: ValueError | |
__________________________________________________________________ ERROR at call of test_real_functions ___________________________________________________________________ | |
@_both_exp_pow | |
def test_real_functions(): | |
# trigonometric functions | |
> assert ask(Q.real(sin(x))) is None | |
E assert True is None | |
E + where True = ask(Q.real(sin(x))) | |
E + where Q.real(sin(x)) = Q.real(sin(x)) | |
E + where Q.real = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.real | |
E + and sin(x) = sin(x) | |
sympy/assumptions/tests/test_query.py:2059: AssertionError | |
_____________________________________________________________________ ERROR at call of test_algebraic _____________________________________________________________________ | |
@_both_exp_pow | |
def test_algebraic(): | |
> assert ask(Q.algebraic(x)) is None | |
E assert True is None | |
E + where True = ask(Q.algebraic(x)) | |
E + where Q.algebraic(x) = Q.algebraic(x) | |
E + where Q.algebraic = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.algebraic | |
sympy/assumptions/tests/test_query.py:2116: AssertionError | |
______________________________________________________________________ ERROR at call of test_global _______________________________________________________________________ | |
def test_global(): | |
"""Test ask with global assumptions""" | |
> assert ask(Q.integer(x)) is None | |
E assert True is None | |
E + where True = ask(Q.integer(x)) | |
E + where Q.integer(x) = Q.integer(x) | |
E + where Q.integer = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.integer | |
sympy/assumptions/tests/test_query.py:2173: AssertionError | |
__________________________________________________________________ ERROR at call of test_custom_context ___________________________________________________________________ | |
def test_custom_context(): | |
"""Test ask with custom assumptions context""" | |
> assert ask(Q.integer(x)) is None | |
E assert True is None | |
E + where True = ask(Q.integer(x)) | |
E + where Q.integer(x) = Q.integer(x) | |
E + where Q.integer = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.integer | |
sympy/assumptions/tests/test_query.py:2182: AssertionError | |
_______________________________________________________________ ERROR at call of test_composite_proposition _______________________________________________________________ | |
def test_composite_proposition(): | |
assert ask(True) is True | |
assert ask(False) is False | |
assert ask(~Q.negative(x), Q.positive(x)) is True | |
> assert ask(~Q.real(x), Q.commutative(x)) is None | |
E assert False is None | |
E + where False = ask(~Q.real(x), Q.commutative(x)) | |
E + where Q.real(x) = Q.real(x) | |
E + where Q.real = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.real | |
E + and Q.commutative(x) = Q.commutative(x) | |
E + where Q.commutative = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.commutative | |
sympy/assumptions/tests/test_query.py:2204: AssertionError | |
_________________________________________________________________ ERROR at call of test_positive_assuming _________________________________________________________________ | |
def test_positive_assuming(): | |
with assuming(Q.positive(x + 1)): | |
> assert not ask(Q.positive(x)) | |
^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:2333: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/ask.py:511: in ask | |
res = lra_satask(proposition, assumptions=assumptions, context=context) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/lra_satask.py:31: in lra_satask | |
context_cnf = context_cnf.extend(context) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <sympy.assumptions.cnf.CNF object at 0x25fe7600150>, props = AssumptionsContext({Q.positive(x + 1), Q.integer(x)}) | |
def extend(self, props): | |
> for p in props: | |
^^^^^ | |
E RuntimeError: Set changed size during iteration | |
sympy/assumptions/cnf.py:305: RuntimeError | |
____________________________________________________________________ ERROR at call of test_issue_7246 _____________________________________________________________________ | |
def test_issue_7246(): | |
assert ask(Q.positive(atan(p)), Q.positive(p)) is True | |
assert ask(Q.positive(atan(p)), Q.negative(p)) is False | |
assert ask(Q.positive(atan(p)), Q.zero(p)) is False | |
assert ask(Q.positive(atan(x))) is None | |
assert ask(Q.positive(asin(p)), Q.positive(p)) is None | |
assert ask(Q.positive(asin(p)), Q.zero(p)) is None | |
assert ask(Q.positive(asin(Rational(1, 7)))) is True | |
assert ask(Q.positive(asin(x)), Q.positive(x) & Q.nonpositive(x - 1)) is True | |
assert ask(Q.positive(asin(x)), Q.negative(x) & Q.nonnegative(x + 1)) is False | |
assert ask(Q.positive(acos(p)), Q.positive(p)) is None | |
assert ask(Q.positive(acos(Rational(1, 7)))) is True | |
assert ask(Q.positive(acos(x)), Q.nonnegative(x + 1) & Q.nonpositive(x - 1)) is True | |
assert ask(Q.positive(acos(x)), Q.nonnegative(x - 1)) is None | |
assert ask(Q.positive(acot(x)), Q.positive(x)) is True | |
assert ask(Q.positive(acot(x)), Q.real(x)) is True | |
> assert ask(Q.positive(acot(x)), Q.imaginary(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:2373: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/ask.py:501: in ask | |
res = key(*args)._eval_ask(assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:156: in _eval_ask | |
return self.function.eval(self.arguments, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/assume.py:348: in eval | |
result = self.handler(*args, assumptions=assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/multipledispatch/dispatcher.py:243: in __call__ | |
return func(*args, **kwargs) | |
^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/handlers/order.py:395: in _ | |
return ask(Q.real(expr.args[0]), assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.real(x), assumptions = Q.imaginary(x), context = AssumptionsContext({Q.positive(x + 1), Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.imaginary(x) | |
sympy/assumptions/ask.py:493: ValueError | |
_________________________________________________________________ ERROR at call of test_custom_AskHandler _________________________________________________________________ | |
def test_custom_AskHandler(): | |
from sympy.logic.boolalg import conjuncts | |
# Old handler system | |
class MersenneHandler(AskHandler): | |
@staticmethod | |
def Integer(expr, assumptions): | |
if ask(Q.integer(log(expr + 1, 2))): | |
return True | |
@staticmethod | |
def Symbol(expr, assumptions): | |
if expr in conjuncts(assumptions): | |
return True | |
try: | |
> with warns_deprecated_sympy(): | |
^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_query.py:2487: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
../../../../.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/contextlib.py:148: in __exit__ | |
next(self.gen) | |
sympy/testing/pytest.py:408: in warns_deprecated_sympy | |
with warns(SymPyDeprecationWarning): | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
../../../../.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/contextlib.py:148: in __exit__ | |
next(self.gen) | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
warningcls = <class 'sympy.utilities.exceptions.SymPyDeprecationWarning'> | |
@contextlib.contextmanager | |
def warns(warningcls, *, match='', test_stacklevel=True): | |
''' | |
Like raises but tests that warnings are emitted. | |
>>> from sympy.testing.pytest import warns | |
>>> import warnings | |
>>> with warns(UserWarning): | |
... warnings.warn('deprecated', UserWarning, stacklevel=2) | |
>>> with warns(UserWarning): | |
... pass | |
Traceback (most recent call last): | |
... | |
Failed: DID NOT WARN. No warnings of type UserWarning\ | |
was emitted. The list of emitted warnings is: []. | |
``test_stacklevel`` makes it check that the ``stacklevel`` parameter to | |
``warn()`` is set so that the warning shows the user line of code (the | |
code under the warns() context manager). Set this to False if this is | |
ambiguous or if the context manager does not test the direct user code | |
that emits the warning. | |
If the warning is a ``SymPyDeprecationWarning``, this additionally tests | |
that the ``active_deprecations_target`` is a real target in the | |
``active-deprecations.md`` file. | |
''' | |
# Absorbs all warnings in warnrec | |
with warnings.catch_warnings(record=True) as warnrec: | |
# Any warning other than the one we are looking for is an error | |
warnings.simplefilter("error") | |
warnings.filterwarnings("always", category=warningcls) | |
# Now run the test | |
yield warnrec | |
# Raise if expected warning not found | |
if not any(issubclass(w.category, warningcls) for w in warnrec): | |
msg = ('Failed: DID NOT WARN.' | |
' No warnings of type %s was emitted.' | |
' The list of emitted warnings is: %s.' | |
) % (warningcls, [w.message for w in warnrec]) | |
> raise Failed(msg) | |
E Failed: Failed: DID NOT WARN. No warnings of type <class 'sympy.utilities.exceptions.SymPyDeprecationWarning'> was emitted. The list of emitted warnings is: []. | |
sympy/testing/pytest.py:285: Failed | |
________________________________________________________________ ERROR at call of test_polyadic_predicate _________________________________________________________________ | |
def test_polyadic_predicate(): | |
class SexyPredicate(Predicate): | |
pass | |
try: | |
Q.sexyprime = SexyPredicate() | |
@Q.sexyprime.register(Integer, Integer) | |
def _(int1, int2, assumptions): | |
args = sorted([int1, int2]) | |
if not all(ask(Q.prime(a), assumptions) for a in args): | |
return False | |
return args[1] - args[0] == 6 | |
@Q.sexyprime.register(Integer, Integer, Integer) | |
def _(int1, int2, int3, assumptions): | |
args = sorted([int1, int2, int3]) | |
if not all(ask(Q.prime(a), assumptions) for a in args): | |
return False | |
return args[2] - args[1] == 6 and args[1] - args[0] == 6 | |
assert ask(Q.sexyprime(5, 11)) | |
assert ask(Q.sexyprime(7, 13, 19)) | |
finally: | |
> del Q.sexyprime | |
^^^^^^^^^^^ | |
E AttributeError: 'AssumptionKeys' object has no attribute 'sexyprime' | |
sympy/assumptions/tests/test_query.py:2540: AttributeError | |
____________________________________________________________________ ERROR at call of test_issue_25221 ____________________________________________________________________ | |
def test_issue_25221(): | |
> assert ask(Q.transcendental(x), Q.algebraic(x) | Q.positive(y,y)) is None | |
E assert False is None | |
E + where False = ask(Q.transcendental(x), (Q.algebraic(x) | Q.positive(y, y))) | |
E + where Q.transcendental(x) = Q.transcendental(x) | |
E + where Q.transcendental = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.transcendental | |
E + and Q.algebraic(x) = Q.algebraic(x) | |
E + where Q.algebraic = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.algebraic | |
E + and Q.positive(y, y) = Q.positive(y, y) | |
E + where Q.positive = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.positive | |
sympy/assumptions/tests/test_query.py:2564: AssertionError | |
________________________________________________________________________ ERROR at call of test_Abs ________________________________________________________________________ | |
def test_Abs(): | |
assert refine(Abs(x), Q.positive(x)) == x | |
assert refine(1 + Abs(x), Q.positive(x)) == 1 + x | |
assert refine(Abs(x), Q.negative(x)) == -x | |
assert refine(1 + Abs(x), Q.negative(x)) == 1 - x | |
> assert refine(Abs(x**2)) != x**2 | |
E assert x**2 != (x ** 2) | |
E + where x**2 = refine(Abs(x**2)) | |
E + where Abs(x**2) = Abs((x ** 2)) | |
sympy/assumptions/tests/test_refine.py:23: AssertionError | |
_______________________________________________________________________ ERROR at call of test_pow1 ________________________________________________________________________ | |
def test_pow1(): | |
assert refine((-1)**x, Q.even(x)) == 1 | |
assert refine((-1)**x, Q.odd(x)) == -1 | |
assert refine((-2)**x, Q.even(x)) == 2**x | |
# nested powers | |
> assert refine(sqrt(x**2)) != Abs(x) | |
E assert Abs(x) != Abs(x) | |
E + where Abs(x) = refine(sqrt(x**2)) | |
E + where sqrt(x**2) = sqrt((x ** 2)) | |
E + and Abs(x) = Abs(x) | |
sympy/assumptions/tests/test_refine.py:33: AssertionError | |
_______________________________________________________________________ ERROR at call of test_pow2 ________________________________________________________________________ | |
def test_pow2(): | |
assert refine((-1)**((-1)**x/2 - 7*S.Half), Q.integer(x)) == (-1)**(x + 1) | |
assert refine((-1)**((-1)**x/2 - 9*S.Half), Q.integer(x)) == (-1)**x | |
# powers of Abs | |
assert refine(Abs(x)**2, Q.real(x)) == x**2 | |
assert refine(Abs(x)**3, Q.real(x)) == Abs(x)**3 | |
> assert refine(Abs(x)**2) == Abs(x)**2 | |
E assert x**2 == (Abs(x) ** 2) | |
E + where x**2 = refine((Abs(x) ** 2)) | |
E + where Abs(x) = Abs(x) | |
E + and Abs(x) = Abs(x) | |
sympy/assumptions/tests/test_refine.py:65: AssertionError | |
________________________________________________________________________ ERROR at call of test_re _________________________________________________________________________ | |
def test_re(): | |
assert refine(re(x), Q.real(x)) == x | |
> assert refine(re(x), Q.imaginary(x)) is S.Zero | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_refine.py:124: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/refine.py:63: in refine | |
new_expr = handler(expr, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/refine.py:270: in refine_re | |
if ask(Q.real(arg), assumptions): | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.real(x), assumptions = Q.imaginary(x), context = AssumptionsContext({Q.positive(x + 1), Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.imaginary(x) | |
sympy/assumptions/ask.py:493: ValueError | |
________________________________________________________________________ ERROR at call of test_im _________________________________________________________________________ | |
def test_im(): | |
> assert refine(im(x), Q.imaginary(x)) == -I*x | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_refine.py:133: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/refine.py:63: in refine | |
new_expr = handler(expr, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/refine.py:293: in refine_im | |
if ask(Q.real(arg), assumptions): | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
proposition = Q.real(x), assumptions = Q.imaginary(x), context = AssumptionsContext({Q.positive(x + 1), Q.integer(x)}) | |
def ask(proposition, assumptions=True, context=global_assumptions): | |
""" | |
Function to evaluate the proposition with assumptions. | |
Explanation | |
=========== | |
This function evaluates the proposition to ``True`` or ``False`` if | |
the truth value can be determined. If not, it returns ``None``. | |
It should be discerned from :func:`~.refine` which, when applied to a | |
proposition, simplifies the argument to symbolic ``Boolean`` instead of | |
Python built-in ``True``, ``False`` or ``None``. | |
**Syntax** | |
* ask(proposition) | |
Evaluate the *proposition* in global assumption context. | |
* ask(proposition, assumptions) | |
Evaluate the *proposition* with respect to *assumptions* in | |
global assumption context. | |
Parameters | |
========== | |
proposition : Boolean | |
Proposition which will be evaluated to boolean value. If this is | |
not ``AppliedPredicate``, it will be wrapped by ``Q.is_true``. | |
assumptions : Boolean, 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. | |
Returns | |
======= | |
``True``, ``False``, or ``None`` | |
Raises | |
====== | |
TypeError : *proposition* or *assumptions* is not valid logical expression. | |
ValueError : assumptions are inconsistent. | |
Examples | |
======== | |
>>> from sympy import ask, Q, pi | |
>>> from sympy.abc import x, y | |
>>> ask(Q.rational(pi)) | |
False | |
>>> ask(Q.even(x*y), Q.even(x) & Q.integer(y)) | |
True | |
>>> ask(Q.prime(4*x), Q.integer(x)) | |
False | |
If the truth value cannot be determined, ``None`` will be returned. | |
>>> print(ask(Q.odd(3*x))) # cannot determine unless we know x | |
None | |
``ValueError`` is raised if assumptions are inconsistent. | |
>>> ask(Q.integer(x), Q.even(x) & Q.odd(x)) | |
Traceback (most recent call last): | |
... | |
ValueError: inconsistent assumptions Q.even(x) & Q.odd(x) | |
Notes | |
===== | |
Relations in assumptions are not implemented (yet), so the following | |
will not give a meaningful result. | |
>>> ask(Q.positive(x), x > 0) | |
It is however a work in progress. | |
See Also | |
======== | |
sympy.assumptions.refine.refine : Simplification using assumptions. | |
Proposition is not reduced to ``None`` if the truth value cannot | |
be determined. | |
""" | |
from sympy.assumptions.satask import satask | |
from sympy.assumptions.lra_satask import lra_satask | |
from sympy.logic.algorithms.lra_theory import UnhandledInput | |
proposition = sympify(proposition) | |
assumptions = sympify(assumptions) | |
if isinstance(proposition, Predicate) or proposition.kind is not BooleanKind: | |
raise TypeError("proposition must be a valid logical expression") | |
if isinstance(assumptions, Predicate) or assumptions.kind is not BooleanKind: | |
raise TypeError("assumptions must be a valid logical expression") | |
binrelpreds = {Eq: Q.eq, Ne: Q.ne, Gt: Q.gt, Lt: Q.lt, Ge: Q.ge, Le: Q.le} | |
if isinstance(proposition, AppliedPredicate): | |
key, args = proposition.function, proposition.arguments | |
elif proposition.func in binrelpreds: | |
key, args = binrelpreds[type(proposition)], proposition.args | |
else: | |
key, args = Q.is_true, (proposition,) | |
# convert local and global assumptions to CNF | |
assump_cnf = CNF.from_prop(assumptions) | |
assump_cnf.extend(context) | |
# extract the relevant facts from assumptions with respect to args | |
local_facts = _extract_all_facts(assump_cnf, args) | |
# convert default facts and assumed facts to encoded CNF | |
known_facts_cnf = get_all_known_facts() | |
enc_cnf = EncodedCNF() | |
enc_cnf.from_cnf(CNF(known_facts_cnf)) | |
enc_cnf.add_from_cnf(local_facts) | |
# check the satisfiability of given assumptions | |
if local_facts.clauses and satisfiable(enc_cnf) is False: | |
> raise ValueError(f"inconsistent assumptions {assumptions}") | |
E ValueError: inconsistent assumptions Q.imaginary(x) | |
sympy/assumptions/ask.py:493: ValueError | |
____________________________________________________________________ ERROR at call of test_lra_satask _____________________________________________________________________ | |
def test_lra_satask(): | |
im = Symbol('im', imaginary=True) | |
# test preprocessing of unequalities is working correctly | |
> assert lra_satask(Q.eq(x, 1), ~Q.ne(x, 0)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_rel_queries.py:16: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/lra_satask.py:35: in lra_satask | |
return check_satisfiability(props, _props, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
prop = <sympy.assumptions.cnf.CNF object at 0x25ff5f80c90>, _prop = <sympy.assumptions.cnf.CNF object at 0x25ff5f809c0> | |
factbase = <sympy.assumptions.cnf.EncodedCNF object at 0x25ff42d0df0> | |
def check_satisfiability(prop, _prop, factbase): | |
sat_true = factbase.copy() | |
sat_false = factbase.copy() | |
sat_true.add_from_cnf(prop) | |
sat_false.add_from_cnf(_prop) | |
all_pred, all_exprs = get_all_pred_and_expr_from_enc_cnf(sat_true) | |
for pred in all_pred: | |
if pred.function not in WHITE_LIST and pred.function != Q.ne: | |
> raise UnhandledInput(f"LRASolver: {pred} is an unhandled predicate") | |
E sympy.logic.algorithms.lra_theory.UnhandledInput: LRASolver: Q.odd(x) is an unhandled predicate | |
sympy/assumptions/lra_satask.py:56: UnhandledInput | |
__________________________________________________________________ ERROR at call of test_old_assumptions __________________________________________________________________ | |
def test_old_assumptions(): | |
# test unhandled old assumptions | |
w = symbols("w") | |
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3))) | |
w = symbols("w", rational=False, real=True) | |
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3))) | |
w = symbols("w", odd=True, real=True) | |
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3))) | |
w = symbols("w", even=True, real=True) | |
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3))) | |
w = symbols("w", prime=True, real=True) | |
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3))) | |
w = symbols("w", composite=True, real=True) | |
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3))) | |
w = symbols("w", integer=True, real=True) | |
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3))) | |
w = symbols("w", integer=False, real=True) | |
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3))) | |
# test handled | |
w = symbols("w", positive=True, real=True) | |
> assert lra_satask(Q.le(w, 0)) is False | |
^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_rel_queries.py:61: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/lra_satask.py:35: in lra_satask | |
return check_satisfiability(props, _props, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
prop = <sympy.assumptions.cnf.CNF object at 0x25fefdb0920>, _prop = <sympy.assumptions.cnf.CNF object at 0x25fefdb1000> | |
factbase = <sympy.assumptions.cnf.EncodedCNF object at 0x25fef981630> | |
def check_satisfiability(prop, _prop, factbase): | |
sat_true = factbase.copy() | |
sat_false = factbase.copy() | |
sat_true.add_from_cnf(prop) | |
sat_false.add_from_cnf(_prop) | |
all_pred, all_exprs = get_all_pred_and_expr_from_enc_cnf(sat_true) | |
for pred in all_pred: | |
if pred.function not in WHITE_LIST and pred.function != Q.ne: | |
> raise UnhandledInput(f"LRASolver: {pred} is an unhandled predicate") | |
E sympy.logic.algorithms.lra_theory.UnhandledInput: LRASolver: Q.odd(x) is an unhandled predicate | |
sympy/assumptions/lra_satask.py:56: UnhandledInput | |
____________________________________________________________________ ERROR at call of test_rel_queries ____________________________________________________________________ | |
def test_rel_queries(): | |
> assert ask(Q.lt(x, 2) & Q.gt(x, 3)) is False | |
E assert None is False | |
E + where None = ask((Q.lt(x, 2) & Q.gt(x, 3))) | |
E + where Q.lt(x, 2) = Q.lt(x, 2) | |
E + where Q.lt = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.lt | |
E + and Q.gt(x, 3) = Q.gt(x, 3) | |
E + where Q.gt = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.gt | |
sympy/assumptions/tests/test_rel_queries.py:81: AssertionError | |
_____________________________________________________________________ ERROR at call of test_all_pred ______________________________________________________________________ | |
def test_all_pred(): | |
# test usable pred | |
> assert lra_satask(Q.extended_positive(x), (x > 2)) is True | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_rel_queries.py:94: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/lra_satask.py:35: in lra_satask | |
return check_satisfiability(props, _props, assumptions) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
prop = <sympy.assumptions.cnf.CNF object at 0x25ff5f80dd0>, _prop = <sympy.assumptions.cnf.CNF object at 0x25ff5f80100> | |
factbase = <sympy.assumptions.cnf.EncodedCNF object at 0x25ff42d2410> | |
def check_satisfiability(prop, _prop, factbase): | |
sat_true = factbase.copy() | |
sat_false = factbase.copy() | |
sat_true.add_from_cnf(prop) | |
sat_false.add_from_cnf(_prop) | |
all_pred, all_exprs = get_all_pred_and_expr_from_enc_cnf(sat_true) | |
for pred in all_pred: | |
if pred.function not in WHITE_LIST and pred.function != Q.ne: | |
> raise UnhandledInput(f"LRASolver: {pred} is an unhandled predicate") | |
E sympy.logic.algorithms.lra_theory.UnhandledInput: LRASolver: Q.odd(x) is an unhandled predicate | |
sympy/assumptions/lra_satask.py:56: UnhandledInput | |
______________________________________________________________ ERROR at call of test_number_line_properties _______________________________________________________________ | |
def test_number_line_properties(): | |
# From: | |
# https://en.wikipedia.org/wiki/Inequality_(mathematics)#Properties_on_the_number_line | |
a, b, c = symbols("a b c", real=True) | |
# Transitivity | |
# If a <= b and b <= c, then a <= c. | |
> assert ask(a <= c, (a <= b) & (b <= c)) is True | |
E assert None is True | |
E + where None = ask(a <= c, (a <= b & b <= c)) | |
sympy/assumptions/tests/test_rel_queries.py:114: AssertionError | |
_____________________________________________________________________ ERROR at call of test_equality ______________________________________________________________________ | |
def test_equality(): | |
# test symmetry and reflexivity | |
assert ask(Q.eq(x, x)) is True | |
assert ask(Q.eq(y, x), Q.eq(x, y)) is True | |
> assert ask(Q.eq(y, x), ~Q.eq(z, z) | Q.eq(x, y)) is True | |
E assert None is True | |
E + where None = ask(Q.eq(y, x), (~Q.eq(z, z) | Q.eq(x, y))) | |
E + where Q.eq(y, x) = Q.eq(y, x) | |
E + where Q.eq = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.eq | |
E + and Q.eq(z, z) = Q.eq(z, z) | |
E + where Q.eq = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.eq | |
E + and Q.eq(x, y) = Q.eq(x, y) | |
E + where Q.eq = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.eq | |
sympy/assumptions/tests/test_rel_queries.py:156: AssertionError | |
______________________________________________________________________ ERROR at call of test_satask _______________________________________________________________________ | |
def test_satask(): | |
# No relevant facts | |
assert satask(Q.real(x), Q.real(x)) is True | |
> assert satask(Q.real(x), ~Q.real(x)) is False | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_satask.py:23: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/satask.py:82: in satask | |
return check_satisfiability(props, _props, sat) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
prop = <sympy.assumptions.cnf.CNF object at 0x260000606a0>, _prop = <sympy.assumptions.cnf.CNF object at 0x26000060f60> | |
factbase = <sympy.assumptions.cnf.EncodedCNF object at 0x260006b0d90> | |
def check_satisfiability(prop, _prop, factbase): | |
sat_true = factbase.copy() | |
sat_false = factbase.copy() | |
sat_true.add_from_cnf(prop) | |
sat_false.add_from_cnf(_prop) | |
can_be_true = satisfiable(sat_true) | |
can_be_false = satisfiable(sat_false) | |
if can_be_true and can_be_false: | |
return None | |
if can_be_true and not can_be_false: | |
return True | |
if not can_be_true and can_be_false: | |
return False | |
if not can_be_true and not can_be_false: | |
# TODO: Run additional checks to see which combination of the | |
# assumptions, global_assumptions, and relevant_facts are | |
# inconsistent. | |
> raise ValueError("Inconsistent assumptions") | |
E ValueError: Inconsistent assumptions | |
sympy/assumptions/satask.py:106: ValueError | |
________________________________________________________________ ERROR at call of test_rational_irrational ________________________________________________________________ | |
def test_rational_irrational(): | |
assert satask(Q.irrational(2)) is False | |
assert satask(Q.rational(2)) is True | |
assert satask(Q.irrational(pi)) is True | |
assert satask(Q.rational(pi)) is False | |
assert satask(Q.irrational(I)) is False | |
assert satask(Q.rational(I)) is False | |
> assert satask(Q.irrational(x*y*z), Q.irrational(x) & Q.irrational(y) & | |
Q.rational(z)) is None | |
sympy/assumptions/tests/test_satask.py:153: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/satask.py:82: in satask | |
return check_satisfiability(props, _props, sat) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
prop = <sympy.assumptions.cnf.CNF object at 0x25fedd00b50>, _prop = <sympy.assumptions.cnf.CNF object at 0x25fedd00560> | |
factbase = <sympy.assumptions.cnf.EncodedCNF object at 0x25fedd66d30> | |
def check_satisfiability(prop, _prop, factbase): | |
sat_true = factbase.copy() | |
sat_false = factbase.copy() | |
sat_true.add_from_cnf(prop) | |
sat_false.add_from_cnf(_prop) | |
can_be_true = satisfiable(sat_true) | |
can_be_false = satisfiable(sat_false) | |
if can_be_true and can_be_false: | |
return None | |
if can_be_true and not can_be_false: | |
return True | |
if not can_be_true and can_be_false: | |
return False | |
if not can_be_true and not can_be_false: | |
# TODO: Run additional checks to see which combination of the | |
# assumptions, global_assumptions, and relevant_facts are | |
# inconsistent. | |
> raise ValueError("Inconsistent assumptions") | |
E ValueError: Inconsistent assumptions | |
sympy/assumptions/satask.py:106: ValueError | |
____________________________________________________________________ ERROR at call of test_even_satask ____________________________________________________________________ | |
def test_even_satask(): | |
assert satask(Q.even(2)) is True | |
assert satask(Q.even(3)) is False | |
assert satask(Q.even(x*y), Q.even(x) & Q.odd(y)) is True | |
assert satask(Q.even(x*y), Q.even(x) & Q.integer(y)) is True | |
assert satask(Q.even(x*y), Q.even(x) & Q.even(y)) is True | |
assert satask(Q.even(x*y), Q.odd(x) & Q.odd(y)) is False | |
assert satask(Q.even(x*y), Q.even(x)) is None | |
assert satask(Q.even(x*y), Q.odd(x) & Q.integer(y)) is None | |
assert satask(Q.even(x*y), Q.odd(x) & Q.odd(y)) is False | |
assert satask(Q.even(abs(x)), Q.even(x)) is True | |
assert satask(Q.even(abs(x)), Q.odd(x)) is False | |
> assert satask(Q.even(x), Q.even(abs(x))) is None # x could be complex | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
E assert True is None | |
E + where True = satask(Q.even(x), Q.even(Abs(x))) | |
E + where Q.even(x) = Q.even(x) | |
E + where Q.even = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.even | |
E + and Q.even(Abs(x)) = Q.even(Abs(x)) | |
E + where Q.even = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.even | |
E + and Abs(x) = abs(x) | |
sympy/assumptions/tests/test_satask.py:190: AssertionError | |
____________________________________________________________________ ERROR at call of test_odd_satask _____________________________________________________________________ | |
def test_odd_satask(): | |
assert satask(Q.odd(2)) is False | |
assert satask(Q.odd(3)) is True | |
assert satask(Q.odd(x*y), Q.even(x) & Q.odd(y)) is False | |
assert satask(Q.odd(x*y), Q.even(x) & Q.integer(y)) is False | |
assert satask(Q.odd(x*y), Q.even(x) & Q.even(y)) is False | |
assert satask(Q.odd(x*y), Q.odd(x) & Q.odd(y)) is True | |
assert satask(Q.odd(x*y), Q.even(x)) is None | |
assert satask(Q.odd(x*y), Q.odd(x) & Q.integer(y)) is None | |
assert satask(Q.odd(x*y), Q.odd(x) & Q.odd(y)) is True | |
assert satask(Q.odd(abs(x)), Q.even(x)) is False | |
assert satask(Q.odd(abs(x)), Q.odd(x)) is True | |
> assert satask(Q.odd(x), Q.odd(abs(x))) is None # x could be complex | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
E assert True is None | |
E + where True = satask(Q.odd(x), Q.odd(Abs(x))) | |
E + where Q.odd(x) = Q.odd(x) | |
E + where Q.odd = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.odd | |
E + and Q.odd(Abs(x)) = Q.odd(Abs(x)) | |
E + where Q.odd = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.odd | |
E + and Abs(x) = abs(x) | |
sympy/assumptions/tests/test_satask.py:207: AssertionError | |
________________________________________________________________________ ERROR at call of test_abs ________________________________________________________________________ | |
def test_abs(): | |
assert satask(Q.nonnegative(abs(x))) is True | |
assert satask(Q.positive(abs(x)), ~Q.zero(x)) is True | |
assert satask(Q.zero(x), ~Q.zero(abs(x))) is False | |
assert satask(Q.zero(x), Q.zero(abs(x))) is True | |
> assert satask(Q.nonzero(x), ~Q.zero(abs(x))) is None # x could be complex | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
E assert True is None | |
E + where True = satask(Q.nonzero(x), ~Q.zero(Abs(x))) | |
E + where Q.nonzero(x) = Q.nonzero(x) | |
E + where Q.nonzero = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.nonzero | |
E + and Q.zero(Abs(x)) = Q.zero(Abs(x)) | |
E + where Q.zero = <sympy.assumptions.ask.AssumptionKeys object at 0x25fc1ce3910>.zero | |
E + and Abs(x) = abs(x) | |
sympy/assumptions/tests/test_satask.py:243: AssertionError | |
_____________________________________________________________________ ERROR at call of test_imaginary _____________________________________________________________________ | |
def test_imaginary(): | |
assert satask(Q.imaginary(2*I)) is True | |
> assert satask(Q.imaginary(x*y), Q.imaginary(x)) is None | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/assumptions/tests/test_satask.py:249: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/assumptions/satask.py:82: in satask | |
return check_satisfiability(props, _props, sat) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
prop = <sympy.assumptions.cnf.CNF object at 0x25fedd00740>, _prop = <sympy.assumptions.cnf.CNF object at 0x25fedd00c90> | |
factbase = <sympy.assumptions.cnf.EncodedCNF object at 0x25fedd68bf0> | |
def check_satisfiability(prop, _prop, factbase): | |
sat_true = factbase.copy() | |
sat_false = factbase.copy() | |
sat_true.add_from_cnf(prop) | |
sat_false.add_from_cnf(_prop) | |
can_be_true = satisfiable(sat_true) | |
can_be_false = satisfiable(sat_false) | |
if can_be_true and can_be_false: | |
return None | |
if can_be_true and not can_be_false: | |
return True | |
if not can_be_true and can_be_false: | |
return False | |
if not can_be_true and not can_be_false: | |
# TODO: Run additional checks to see which combination of the | |
# assumptions, global_assumptions, and relevant_facts are | |
# inconsistent. | |
> raise ValueError("Inconsistent assumptions") | |
E ValueError: Inconsistent assumptions | |
sympy/assumptions/satask.py:106: ValueError | |
_______________________________________________________________ ERROR at call of test_differentiate_finite ________________________________________________________________ | |
def test_differentiate_finite(): | |
x, y, h = symbols('x y h') | |
f = Function('f') | |
> with warns_deprecated_sympy(): | |
^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/calculus/tests/test_finite_diff.py:131: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
../../../../.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/contextlib.py:148: in __exit__ | |
next(self.gen) | |
sympy/testing/pytest.py:408: in warns_deprecated_sympy | |
with warns(SymPyDeprecationWarning): | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
../../../../.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/contextlib.py:148: in __exit__ | |
next(self.gen) | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
warningcls = <class 'sympy.utilities.exceptions.SymPyDeprecationWarning'> | |
@contextlib.contextmanager | |
def warns(warningcls, *, match='', test_stacklevel=True): | |
''' | |
Like raises but tests that warnings are emitted. | |
>>> from sympy.testing.pytest import warns | |
>>> import warnings | |
>>> with warns(UserWarning): | |
... warnings.warn('deprecated', UserWarning, stacklevel=2) | |
>>> with warns(UserWarning): | |
... pass | |
Traceback (most recent call last): | |
... | |
Failed: DID NOT WARN. No warnings of type UserWarning\ | |
was emitted. The list of emitted warnings is: []. | |
``test_stacklevel`` makes it check that the ``stacklevel`` parameter to | |
``warn()`` is set so that the warning shows the user line of code (the | |
code under the warns() context manager). Set this to False if this is | |
ambiguous or if the context manager does not test the direct user code | |
that emits the warning. | |
If the warning is a ``SymPyDeprecationWarning``, this additionally tests | |
that the ``active_deprecations_target`` is a real target in the | |
``active-deprecations.md`` file. | |
''' | |
# Absorbs all warnings in warnrec | |
with warnings.catch_warnings(record=True) as warnrec: | |
# Any warning other than the one we are looking for is an error | |
warnings.simplefilter("error") | |
warnings.filterwarnings("always", category=warningcls) | |
# Now run the test | |
yield warnrec | |
# Raise if expected warning not found | |
if not any(issubclass(w.category, warningcls) for w in warnrec): | |
msg = ('Failed: DID NOT WARN.' | |
' No warnings of type %s was emitted.' | |
' The list of emitted warnings is: %s.' | |
) % (warningcls, [w.message for w in warnrec]) | |
> raise Failed(msg) | |
E Failed: Failed: DID NOT WARN. No warnings of type <class 'sympy.utilities.exceptions.SymPyDeprecationWarning'> was emitted. The list of emitted warnings is: []. | |
sympy/testing/pytest.py:285: Failed | |
____________________________________________________________________ ERROR at call of test_issue_23401 ____________________________________________________________________ | |
f = Poly(1.0e-6*_x0**4 - 0.0002*_x0**3 + 0.0098*_x0**2 + 0.02*_x0 + 0.01, _x0, domain='RR'), n = 15, maxsteps = 50, cleanup = True | |
def nroots(f, n=15, maxsteps=50, cleanup=True): | |
""" | |
Compute numerical approximations of roots of ``f``. | |
Parameters | |
========== | |
n ... the number of digits to calculate | |
maxsteps ... the maximum number of iterations to do | |
If the accuracy `n` cannot be reached in `maxsteps`, it will raise an | |
exception. You need to rerun with higher maxsteps. | |
Examples | |
======== | |
>>> from sympy import Poly | |
>>> from sympy.abc import x | |
>>> Poly(x**2 - 3).nroots(n=15) | |
[-1.73205080756888, 1.73205080756888] | |
>>> Poly(x**2 - 3).nroots(n=30) | |
[-1.73205080756887729352744634151, 1.73205080756887729352744634151] | |
""" | |
if f.is_multivariate: | |
raise MultivariatePolynomialError( | |
"Cannot compute numerical roots of %s" % f) | |
if f.degree() <= 0: | |
return [] | |
# For integer and rational coefficients, convert them to integers only | |
# (for accuracy). Otherwise just try to convert the coefficients to | |
# mpmath.mpc and raise an exception if the conversion fails. | |
if f.rep.dom is ZZ: | |
coeffs = [int(coeff) for coeff in f.all_coeffs()] | |
elif f.rep.dom is QQ: | |
denoms = [coeff.q for coeff in f.all_coeffs()] | |
fac = ilcm(*denoms) | |
coeffs = [int(coeff*fac) for coeff in f.all_coeffs()] | |
else: | |
coeffs = [coeff.evalf(n=n).as_real_imag() | |
for coeff in f.all_coeffs()] | |
with mpmath.workdps(n): | |
try: | |
coeffs = [mpmath.mpc(*coeff) for coeff in coeffs] | |
except TypeError: | |
raise DomainError("Numerical domain expected, got %s" % \ | |
f.rep.dom) | |
dps = mpmath.mp.dps | |
mpmath.mp.dps = n | |
from sympy.functions.elementary.complexes import sign | |
try: | |
# We need to add extra precision to guard against losing accuracy. | |
# 10 times the degree of the polynomial seems to work well. | |
> roots = mpmath.polyroots(coeffs, maxsteps=maxsteps, | |
cleanup=cleanup, error=False, extraprec=f.degree()*10) | |
sympy/polys/polytools.py:3730: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
ctx = <mpmath.ctx_mp.MPContext object at 0x25fc1ce0d90> | |
coeffs = [mpc(real='1.0', imag='0.0'), mpc(real='-200.000000000000018634724839595', imag='0.0'), mpc(real='9800.000000000001861....0'), mpc(real='20000.0000000000047908183496703', imag='0.0'), mpc(real='10000.0000000000023954091748352', imag='0.0')] | |
maxsteps = 50, cleanup = True, extraprec = 40, error = False, roots_init = None | |
@defun | |
def polyroots(ctx, coeffs, maxsteps=50, cleanup=True, extraprec=10, | |
error=False, roots_init=None): | |
""" | |
Computes all roots (real or complex) of a given polynomial. | |
The roots are returned as a sorted list, where real roots appear first | |
followed by complex conjugate roots as adjacent elements. The polynomial | |
should be given as a list of coefficients, in the format used by | |
:func:`~mpmath.polyval`. The leading coefficient must be nonzero. | |
With *error=True*, :func:`~mpmath.polyroots` returns a tuple *(roots, err)* | |
where *err* is an estimate of the maximum error among the computed roots. | |
**Examples** | |
Finding the three real roots of `x^3 - x^2 - 14x + 24`:: | |
>>> from mpmath import * | |
>>> mp.dps = 15; mp.pretty = True | |
>>> nprint(polyroots([1,-1,-14,24]), 4) | |
[-4.0, 2.0, 3.0] | |
Finding the two complex conjugate roots of `4x^2 + 3x + 2`, with an | |
error estimate:: | |
>>> roots, err = polyroots([4,3,2], error=True) | |
>>> for r in roots: | |
... print(r) | |
... | |
(-0.375 + 0.59947894041409j) | |
(-0.375 - 0.59947894041409j) | |
>>> | |
>>> err | |
2.22044604925031e-16 | |
>>> | |
>>> polyval([4,3,2], roots[0]) | |
(2.22044604925031e-16 + 0.0j) | |
>>> polyval([4,3,2], roots[1]) | |
(2.22044604925031e-16 + 0.0j) | |
The following example computes all the 5th roots of unity; that is, | |
the roots of `x^5 - 1`:: | |
>>> mp.dps = 20 | |
>>> for r in polyroots([1, 0, 0, 0, 0, -1]): | |
... print(r) | |
... | |
1.0 | |
(-0.8090169943749474241 + 0.58778525229247312917j) | |
(-0.8090169943749474241 - 0.58778525229247312917j) | |
(0.3090169943749474241 + 0.95105651629515357212j) | |
(0.3090169943749474241 - 0.95105651629515357212j) | |
**Precision and conditioning** | |
The roots are computed to the current working precision accuracy. If this | |
accuracy cannot be achieved in ``maxsteps`` steps, then a | |
``NoConvergence`` exception is raised. The algorithm internally is using | |
the current working precision extended by ``extraprec``. If | |
``NoConvergence`` was raised, that is caused either by not having enough | |
extra precision to achieve convergence (in which case increasing | |
``extraprec`` should fix the problem) or too low ``maxsteps`` (in which | |
case increasing ``maxsteps`` should fix the problem), or a combination of | |
both. | |
The user should always do a convergence study with regards to | |
``extraprec`` to ensure accurate results. It is possible to get | |
convergence to a wrong answer with too low ``extraprec``. | |
Provided there are no repeated roots, :func:`~mpmath.polyroots` can | |
typically compute all roots of an arbitrary polynomial to high precision:: | |
>>> mp.dps = 60 | |
>>> for r in polyroots([1, 0, -10, 0, 1]): | |
... print(r) | |
... | |
-3.14626436994197234232913506571557044551247712918732870123249 | |
-0.317837245195782244725757617296174288373133378433432554879127 | |
0.317837245195782244725757617296174288373133378433432554879127 | |
3.14626436994197234232913506571557044551247712918732870123249 | |
>>> | |
>>> sqrt(3) + sqrt(2) | |
3.14626436994197234232913506571557044551247712918732870123249 | |
>>> sqrt(3) - sqrt(2) | |
0.317837245195782244725757617296174288373133378433432554879127 | |
**Algorithm** | |
:func:`~mpmath.polyroots` implements the Durand-Kerner method [1], which | |
uses complex arithmetic to locate all roots simultaneously. | |
The Durand-Kerner method can be viewed as approximately performing | |
simultaneous Newton iteration for all the roots. In particular, | |
the convergence to simple roots is quadratic, just like Newton's | |
method. | |
Although all roots are internally calculated using complex arithmetic, any | |
root found to have an imaginary part smaller than the estimated numerical | |
error is truncated to a real number (small real parts are also chopped). | |
Real roots are placed first in the returned list, sorted by value. The | |
remaining complex roots are sorted by their real parts so that conjugate | |
roots end up next to each other. | |
**References** | |
1. http://en.wikipedia.org/wiki/Durand-Kerner_method | |
""" | |
if len(coeffs) <= 1: | |
if not coeffs or not coeffs[0]: | |
raise ValueError("Input to polyroots must not be the zero polynomial") | |
# Constant polynomial with no roots | |
return [] | |
orig = ctx.prec | |
tol = +ctx.eps | |
with ctx.extraprec(extraprec): | |
deg = len(coeffs) - 1 | |
# Must be monic | |
lead = ctx.convert(coeffs[0]) | |
if lead == 1: | |
coeffs = [ctx.convert(c) for c in coeffs] | |
else: | |
coeffs = [c/lead for c in coeffs] | |
f = lambda x: ctx.polyval(coeffs, x) | |
if roots_init is None: | |
roots = [ctx.mpc((0.4+0.9j)**n) for n in xrange(deg)] | |
else: | |
roots = [None]*deg; | |
deg_init = min(deg, len(roots_init)) | |
roots[:deg_init] = list(roots_init[:deg_init]) | |
roots[deg_init:] = [ctx.mpc((0.4+0.9j)**n) for n | |
in xrange(deg_init,deg)] | |
err = [ctx.one for n in xrange(deg)] | |
# Durand-Kerner iteration until convergence | |
for step in xrange(maxsteps): | |
if abs(max(err)) < tol: | |
break | |
for i in xrange(deg): | |
p = roots[i] | |
x = f(p) | |
for j in range(deg): | |
if i != j: | |
try: | |
x /= (p-roots[j]) | |
except ZeroDivisionError: | |
continue | |
roots[i] = p - x | |
err[i] = abs(x) | |
if abs(max(err)) >= tol: | |
> raise ctx.NoConvergence("Didn't converge in maxsteps=%d steps." \ | |
% maxsteps) | |
E mpmath.libmp.libhyper.NoConvergence: Didn't converge in maxsteps=50 steps. | |
.venv/lib/python3.14t/site-packages/mpmath/calculus/polynomials.py:196: NoConvergence | |
During handling of the above exception, another exception occurred: | |
f = Poly(1.0e-6*_x0**4 - 0.0002*_x0**3 + 0.0098*_x0**2 + 0.02*_x0 + 0.01, _x0, domain='RR'), n = 15, maxsteps = 50, cleanup = True | |
def nroots(f, n=15, maxsteps=50, cleanup=True): | |
""" | |
Compute numerical approximations of roots of ``f``. | |
Parameters | |
========== | |
n ... the number of digits to calculate | |
maxsteps ... the maximum number of iterations to do | |
If the accuracy `n` cannot be reached in `maxsteps`, it will raise an | |
exception. You need to rerun with higher maxsteps. | |
Examples | |
======== | |
>>> from sympy import Poly | |
>>> from sympy.abc import x | |
>>> Poly(x**2 - 3).nroots(n=15) | |
[-1.73205080756888, 1.73205080756888] | |
>>> Poly(x**2 - 3).nroots(n=30) | |
[-1.73205080756887729352744634151, 1.73205080756887729352744634151] | |
""" | |
if f.is_multivariate: | |
raise MultivariatePolynomialError( | |
"Cannot compute numerical roots of %s" % f) | |
if f.degree() <= 0: | |
return [] | |
# For integer and rational coefficients, convert them to integers only | |
# (for accuracy). Otherwise just try to convert the coefficients to | |
# mpmath.mpc and raise an exception if the conversion fails. | |
if f.rep.dom is ZZ: | |
coeffs = [int(coeff) for coeff in f.all_coeffs()] | |
elif f.rep.dom is QQ: | |
denoms = [coeff.q for coeff in f.all_coeffs()] | |
fac = ilcm(*denoms) | |
coeffs = [int(coeff*fac) for coeff in f.all_coeffs()] | |
else: | |
coeffs = [coeff.evalf(n=n).as_real_imag() | |
for coeff in f.all_coeffs()] | |
with mpmath.workdps(n): | |
try: | |
coeffs = [mpmath.mpc(*coeff) for coeff in coeffs] | |
except TypeError: | |
raise DomainError("Numerical domain expected, got %s" % \ | |
f.rep.dom) | |
dps = mpmath.mp.dps | |
mpmath.mp.dps = n | |
from sympy.functions.elementary.complexes import sign | |
try: | |
# We need to add extra precision to guard against losing accuracy. | |
# 10 times the degree of the polynomial seems to work well. | |
roots = mpmath.polyroots(coeffs, maxsteps=maxsteps, | |
cleanup=cleanup, error=False, extraprec=f.degree()*10) | |
# Mpmath puts real roots first, then complex ones (as does all_roots) | |
# so we make sure this convention holds here, too. | |
roots = list(map(sympify, | |
sorted(roots, key=lambda r: (1 if r.imag else 0, r.real, abs(r.imag), sign(r.imag))))) | |
except NoConvergence: | |
try: | |
# If roots did not converge try again with more extra precision. | |
> roots = mpmath.polyroots(coeffs, maxsteps=maxsteps, | |
cleanup=cleanup, error=False, extraprec=f.degree()*15) | |
sympy/polys/polytools.py:3740: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
ctx = <mpmath.ctx_mp.MPContext object at 0x25fc1ce0d90> | |
coeffs = [mpc(real='1.0', imag='0.0'), mpc(real='-200.000000000000018634724839595', imag='0.0'), mpc(real='9800.000000000001861....0'), mpc(real='20000.0000000000047908183496703', imag='0.0'), mpc(real='10000.0000000000023954091748352', imag='0.0')] | |
maxsteps = 50, cleanup = True, extraprec = 60, error = False, roots_init = None | |
@defun | |
def polyroots(ctx, coeffs, maxsteps=50, cleanup=True, extraprec=10, | |
error=False, roots_init=None): | |
""" | |
Computes all roots (real or complex) of a given polynomial. | |
The roots are returned as a sorted list, where real roots appear first | |
followed by complex conjugate roots as adjacent elements. The polynomial | |
should be given as a list of coefficients, in the format used by | |
:func:`~mpmath.polyval`. The leading coefficient must be nonzero. | |
With *error=True*, :func:`~mpmath.polyroots` returns a tuple *(roots, err)* | |
where *err* is an estimate of the maximum error among the computed roots. | |
**Examples** | |
Finding the three real roots of `x^3 - x^2 - 14x + 24`:: | |
>>> from mpmath import * | |
>>> mp.dps = 15; mp.pretty = True | |
>>> nprint(polyroots([1,-1,-14,24]), 4) | |
[-4.0, 2.0, 3.0] | |
Finding the two complex conjugate roots of `4x^2 + 3x + 2`, with an | |
error estimate:: | |
>>> roots, err = polyroots([4,3,2], error=True) | |
>>> for r in roots: | |
... print(r) | |
... | |
(-0.375 + 0.59947894041409j) | |
(-0.375 - 0.59947894041409j) | |
>>> | |
>>> err | |
2.22044604925031e-16 | |
>>> | |
>>> polyval([4,3,2], roots[0]) | |
(2.22044604925031e-16 + 0.0j) | |
>>> polyval([4,3,2], roots[1]) | |
(2.22044604925031e-16 + 0.0j) | |
The following example computes all the 5th roots of unity; that is, | |
the roots of `x^5 - 1`:: | |
>>> mp.dps = 20 | |
>>> for r in polyroots([1, 0, 0, 0, 0, -1]): | |
... print(r) | |
... | |
1.0 | |
(-0.8090169943749474241 + 0.58778525229247312917j) | |
(-0.8090169943749474241 - 0.58778525229247312917j) | |
(0.3090169943749474241 + 0.95105651629515357212j) | |
(0.3090169943749474241 - 0.95105651629515357212j) | |
**Precision and conditioning** | |
The roots are computed to the current working precision accuracy. If this | |
accuracy cannot be achieved in ``maxsteps`` steps, then a | |
``NoConvergence`` exception is raised. The algorithm internally is using | |
the current working precision extended by ``extraprec``. If | |
``NoConvergence`` was raised, that is caused either by not having enough | |
extra precision to achieve convergence (in which case increasing | |
``extraprec`` should fix the problem) or too low ``maxsteps`` (in which | |
case increasing ``maxsteps`` should fix the problem), or a combination of | |
both. | |
The user should always do a convergence study with regards to | |
``extraprec`` to ensure accurate results. It is possible to get | |
convergence to a wrong answer with too low ``extraprec``. | |
Provided there are no repeated roots, :func:`~mpmath.polyroots` can | |
typically compute all roots of an arbitrary polynomial to high precision:: | |
>>> mp.dps = 60 | |
>>> for r in polyroots([1, 0, -10, 0, 1]): | |
... print(r) | |
... | |
-3.14626436994197234232913506571557044551247712918732870123249 | |
-0.317837245195782244725757617296174288373133378433432554879127 | |
0.317837245195782244725757617296174288373133378433432554879127 | |
3.14626436994197234232913506571557044551247712918732870123249 | |
>>> | |
>>> sqrt(3) + sqrt(2) | |
3.14626436994197234232913506571557044551247712918732870123249 | |
>>> sqrt(3) - sqrt(2) | |
0.317837245195782244725757617296174288373133378433432554879127 | |
**Algorithm** | |
:func:`~mpmath.polyroots` implements the Durand-Kerner method [1], which | |
uses complex arithmetic to locate all roots simultaneously. | |
The Durand-Kerner method can be viewed as approximately performing | |
simultaneous Newton iteration for all the roots. In particular, | |
the convergence to simple roots is quadratic, just like Newton's | |
method. | |
Although all roots are internally calculated using complex arithmetic, any | |
root found to have an imaginary part smaller than the estimated numerical | |
error is truncated to a real number (small real parts are also chopped). | |
Real roots are placed first in the returned list, sorted by value. The | |
remaining complex roots are sorted by their real parts so that conjugate | |
roots end up next to each other. | |
**References** | |
1. http://en.wikipedia.org/wiki/Durand-Kerner_method | |
""" | |
if len(coeffs) <= 1: | |
if not coeffs or not coeffs[0]: | |
raise ValueError("Input to polyroots must not be the zero polynomial") | |
# Constant polynomial with no roots | |
return [] | |
orig = ctx.prec | |
tol = +ctx.eps | |
with ctx.extraprec(extraprec): | |
deg = len(coeffs) - 1 | |
# Must be monic | |
lead = ctx.convert(coeffs[0]) | |
if lead == 1: | |
coeffs = [ctx.convert(c) for c in coeffs] | |
else: | |
coeffs = [c/lead for c in coeffs] | |
f = lambda x: ctx.polyval(coeffs, x) | |
if roots_init is None: | |
roots = [ctx.mpc((0.4+0.9j)**n) for n in xrange(deg)] | |
else: | |
roots = [None]*deg; | |
deg_init = min(deg, len(roots_init)) | |
roots[:deg_init] = list(roots_init[:deg_init]) | |
roots[deg_init:] = [ctx.mpc((0.4+0.9j)**n) for n | |
in xrange(deg_init,deg)] | |
err = [ctx.one for n in xrange(deg)] | |
# Durand-Kerner iteration until convergence | |
for step in xrange(maxsteps): | |
if abs(max(err)) < tol: | |
break | |
for i in xrange(deg): | |
p = roots[i] | |
x = f(p) | |
for j in range(deg): | |
if i != j: | |
try: | |
x /= (p-roots[j]) | |
except ZeroDivisionError: | |
continue | |
roots[i] = p - x | |
err[i] = abs(x) | |
if abs(max(err)) >= tol: | |
> raise ctx.NoConvergence("Didn't converge in maxsteps=%d steps." \ | |
% maxsteps) | |
E mpmath.libmp.libhyper.NoConvergence: Didn't converge in maxsteps=50 steps. | |
.venv/lib/python3.14t/site-packages/mpmath/calculus/polynomials.py:196: NoConvergence | |
During handling of the above exception, another exception occurred: | |
def test_issue_23401(): | |
x = Symbol('x') | |
expr = (x + 1)/(-1.0e-3*x**2 + 0.1*x + 0.1) | |
> assert is_increasing(expr, Interval(1,2), x) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/calculus/tests/test_singularities.py:122: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
sympy/calculus/singularities.py:209: in is_increasing | |
return monotonicity_helper(expression, lambda x: x >= 0, interval, symbol) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/calculus/singularities.py:165: in monotonicity_helper | |
predicate_interval = solveset(predicate(derivative), variable, S.Reals) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:2493: in solveset | |
rv = solveset(f.xreplace({symbol: newsym}), newsym, domain) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:2517: in solveset | |
return _solveset(f, symbol, domain, _check=True) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:1305: in _solveset | |
result = solve_univariate_inequality( | |
sympy/solvers/inequalities.py:520: in solve_univariate_inequality | |
solns = solvify(e, gen, domain) | |
^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:2625: in solvify | |
solution_set = solveset(f, symbol, domain) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:2517: in solveset | |
return _solveset(f, symbol, domain, _check=True) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:1339: in _solveset | |
result_rational = _solve_as_rational(equation, symbol, domain) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:790: in _solve_as_rational | |
invalid_solns = _solveset(h, symbol, domain) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:1284: in _solveset | |
result = Union(*[solver(m, symbol) for m in f.args]) | |
^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:1267: in <lambda> | |
solver = lambda f, x, domain=domain: _solveset(f, x, domain) | |
^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:1339: in _solveset | |
result_rational = _solve_as_rational(equation, symbol, domain) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:779: in _solve_as_rational | |
return _solve_as_poly(g, symbol, domain) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/solvers/solveset.py:1028: in _solve_as_poly | |
solns = roots(f, symbol, cubics=True, quartics=True, | |
sympy/polys/polyroots.py:1084: in roots | |
for r in f.nroots(): | |
^^^^^^^^^^ | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
f = Poly(1.0e-6*_x0**4 - 0.0002*_x0**3 + 0.0098*_x0**2 + 0.02*_x0 + 0.01, _x0, domain='RR'), n = 15, maxsteps = 50, cleanup = True | |
def nroots(f, n=15, maxsteps=50, cleanup=True): | |
""" | |
Compute numerical approximations of roots of ``f``. | |
Parameters | |
========== | |
n ... the number of digits to calculate | |
maxsteps ... the maximum number of iterations to do | |
If the accuracy `n` cannot be reached in `maxsteps`, it will raise an | |
exception. You need to rerun with higher maxsteps. | |
Examples | |
======== | |
>>> from sympy import Poly | |
>>> from sympy.abc import x | |
>>> Poly(x**2 - 3).nroots(n=15) | |
[-1.73205080756888, 1.73205080756888] | |
>>> Poly(x**2 - 3).nroots(n=30) | |
[-1.73205080756887729352744634151, 1.73205080756887729352744634151] | |
""" | |
if f.is_multivariate: | |
raise MultivariatePolynomialError( | |
"Cannot compute numerical roots of %s" % f) | |
if f.degree() <= 0: | |
return [] | |
# For integer and rational coefficients, convert them to integers only | |
# (for accuracy). Otherwise just try to convert the coefficients to | |
# mpmath.mpc and raise an exception if the conversion fails. | |
if f.rep.dom is ZZ: | |
coeffs = [int(coeff) for coeff in f.all_coeffs()] | |
elif f.rep.dom is QQ: | |
denoms = [coeff.q for coeff in f.all_coeffs()] | |
fac = ilcm(*denoms) | |
coeffs = [int(coeff*fac) for coeff in f.all_coeffs()] | |
else: | |
coeffs = [coeff.evalf(n=n).as_real_imag() | |
for coeff in f.all_coeffs()] | |
with mpmath.workdps(n): | |
try: | |
coeffs = [mpmath.mpc(*coeff) for coeff in coeffs] | |
except TypeError: | |
raise DomainError("Numerical domain expected, got %s" % \ | |
f.rep.dom) | |
dps = mpmath.mp.dps | |
mpmath.mp.dps = n | |
from sympy.functions.elementary.complexes import sign | |
try: | |
# We need to add extra precision to guard against losing accuracy. | |
# 10 times the degree of the polynomial seems to work well. | |
roots = mpmath.polyroots(coeffs, maxsteps=maxsteps, | |
cleanup=cleanup, error=False, extraprec=f.degree()*10) | |
# Mpmath puts real roots first, then complex ones (as does all_roots) | |
# so we make sure this convention holds here, too. | |
roots = list(map(sympify, | |
sorted(roots, key=lambda r: (1 if r.imag else 0, r.real, abs(r.imag), sign(r.imag))))) | |
except NoConvergence: | |
try: | |
# If roots did not converge try again with more extra precision. | |
roots = mpmath.polyroots(coeffs, maxsteps=maxsteps, | |
cleanup=cleanup, error=False, extraprec=f.degree()*15) | |
roots = list(map(sympify, | |
sorted(roots, key=lambda r: (1 if r.imag else 0, r.real, abs(r.imag), sign(r.imag))))) | |
except NoConvergence: | |
> raise NoConvergence( | |
'convergence to root failed; try n < %s or maxsteps > %s' % ( | |
n, maxsteps)) | |
E mpmath.libmp.libhyper.NoConvergence: convergence to root failed; try n < 15 or maxsteps > 50 | |
sympy/polys/polytools.py:3745: NoConvergence | |
_______________________________________________________________ ERROR at call of test_FreeGroup__getitem__ ________________________________________________________________ | |
def test_FreeGroup__getitem__(): | |
assert F[0:] == FreeGroup("x, y, z") | |
> assert F[1:] == FreeGroup("y, z") | |
E assert <free group o...rators (y, z)> == <free group o...rators (y, z)> | |
E | |
E Use -v to get more diff | |
sympy/combinatorics/tests/test_free_groups.py:66: AssertionError | |
______________________________________________________________ ERROR at call of test_Permutation_subclassing ______________________________________________________________ | |
def test_Permutation_subclassing(): | |
# Subclass that adds permutation application on iterables | |
class CustomPermutation(Permutation): | |
def __call__(self, *i): | |
try: | |
return super().__call__(*i) | |
except TypeError: | |
pass | |
try: | |
perm_obj = i[0] | |
return [self._array_form[j] for j in perm_obj] | |
except TypeError: | |
raise TypeError('unrecognized argument') | |
def __eq__(self, other): | |
if isinstance(other, Permutation): | |
return self._hashable_content() == other._hashable_content() | |
else: | |
return super().__eq__(other) | |
def __hash__(self): | |
return super().__hash__() | |
p = CustomPermutation([1, 2, 3, 0]) | |
q = Permutation([1, 2, 3, 0]) | |
assert p == q | |
> raises(TypeError, lambda: q([1, 2])) | |
E Failed: DID NOT RAISE <class 'TypeError'> | |
sympy/combinatorics/tests/test_permutations.py:260: Failed | |
______________________________________________________________ ERROR at call of test_deprecated_print_cyclic ______________________________________________________________ | |
def test_deprecated_print_cyclic(): | |
p = Permutation(0, 1, 2) | |
try: | |
Permutation.print_cyclic = True | |
with warns_deprecated_sympy(): | |
assert sstr(p) == '(0 1 2)' | |
> with warns_deprecated_sympy(): | |
^^^^^^^^^^^^^^^^^^^^^^^^ | |
sympy/combinatorics/tests/test_permutations.py:498: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
../../../../.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/contextlib.py:148: in __exit__ | |
next(self.gen) | |
sympy/testing/pytest.py:408: in warns_deprecated_sympy | |
with warns(SymPyDeprecationWarning): | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
../../../../.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/contextlib.py:148: in __exit__ | |
next(self.gen) | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
warningcls = <class 'sympy.utilities.exceptions.SymPyDeprecationWarning'> | |
@contextlib.contextmanager | |
def warns(warningcls, *, match='', test_stacklevel=True): | |
''' | |
Like raises but tests that warnings are emitted. | |
>>> from sympy.testing.pytest import warns | |
>>> import warnings | |
>>> with warns(UserWarning): | |
... warnings.warn('deprecated', UserWarning, stacklevel=2) | |
>>> with warns(UserWarning): | |
... pass | |
Traceback (most recent call last): | |
... | |
Failed: DID NOT WARN. No warnings of type UserWarning\ | |
was emitted. The list of emitted warnings is: []. | |
``test_stacklevel`` makes it check that the ``stacklevel`` parameter to | |
``warn()`` is set so that the warning shows the user line of code (the | |
code under the warns() context manager). Set this to False if this is | |
ambiguous or if the context manager does not test the direct user code | |
that emits the warning. | |
If the warning is a ``SymPyDeprecationWarning``, this additionally tests | |
that the ``active_deprecations_target`` is a real target in the | |
``active-deprecations.md`` file. | |
''' | |
# Absorbs all warnings in warnrec | |
with warnings.catch_warnings(record=True) as warnrec: | |
# Any warning other than the one we are looking for is an error | |
warnings.simplefilter("error") | |
warnings.filterwarnings("always", category=warningcls) | |
# Now run the test | |
yield warnrec | |
# Raise if expected warning not found | |
if not any(issubclass(w.category, warningcls) for w in warnrec): | |
msg = ('Failed: DID NOT WARN.' | |
' No warnings of type %s was emitted.' | |
' The list of emitted warnings is: %s.' | |
) % (warningcls, [w.message for w in warnrec]) | |
> raise Failed(msg) | |
E Failed: Failed: DID NOT WARN. No warnings of type <class 'sympy.utilities.exceptions.SymPyDeprecationWarning'> was emitted. The list of emitted warnings is: []. | |
sympy/testing/pytest.py:285: Failed | |
____________________________________________________________________ ERROR at call of test_rationalize ____________________________________________________________________ | |
def test_rationalize(): | |
from mpmath import cos, pi, mpf | |
assert rationalize(cos(pi/3)) == S.Half | |
assert rationalize(mpf("0.333333333333333")) == Rational(1, 3) | |
> assert rationalize(mpf("-0.333333333333333")) == Rational(-1, 3) | |
E AssertionError: assert -1/2 == -1/3 | |
E + where -1/2 = rationalize(mpf('-0.375')) | |
E + where mpf('-0.375') = <class 'mpmath.ctx_mp_python.mpf'>('-0.333333333333333') | |
E + and -1/3 = Rational(-1, 3) | |
sympy/concrete/tests/test_guess.py:45: AssertionError | |
============================================================================ warnings summary ============================================================================= | |
.venv/lib/python3.14t/site-packages/_hypothesis_pytestplugin.py:461 | |
/Users/aaronmeurer/Documents/Python/sympy/sympy/.venv/lib/python3.14t/site-packages/_hypothesis_pytestplugin.py:461: UserWarning: Skipping collection of '.hypothesis' directory - this usually means you've explicitly set the `norecursedirs` pytest config option, replacing rather than extending the default ignores. | |
warnings.warn( | |
sympy/assumptions/tests/test_query.py::test_custom_AskHandler | |
/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/assumptions/ask.py:622: SymPyDeprecationWarning: | |
The AskHandler system is deprecated. Predicate.add_handler() | |
should be replaced with the multipledispatch handler of Predicate. | |
See https://docs.sympy.org/latest/explanation/active-deprecations.html#deprecated-askhandler | |
for details. | |
This has been deprecated since SymPy version 1.8. It | |
will be removed in a future version of SymPy. | |
Qkey.add_handler(handler) | |
sympy/codegen/tests/test_algorithms.py::test_newtons_method_function__ccode_parameters | |
/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/utilities/_compilation/runners.py:93: UserWarning: failed to determine what kind of compiler arm64-apple-darwin20.0.0-clang is, assuming gcc | |
warnings.warn("failed to determine what kind of compiler %s is, assuming %s" % | |
sympy/codegen/tests/test_fnodes.py::test_size_assumed_shape | |
sympy/codegen/tests/test_fnodes.py::test_ImpliedDoLoop | |
sympy/codegen/tests/test_fnodes.py::test_Program | |
sympy/codegen/tests/test_fnodes.py::test_Module | |
sympy/codegen/tests/test_fnodes.py::test_Subroutine | |
/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/utilities/_compilation/runners.py:93: UserWarning: failed to determine what kind of compiler /Users/aaronmeurer/miniconda3/bin/arm64-apple-darwin20.0.0-gfortran is, assuming gfortran | |
warnings.warn("failed to determine what kind of compiler %s is, assuming %s" % | |
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html | |
DO *NOT* COMMIT! | |
*********************************************************************** pytest-run-parallel report ************************************************************************ | |
1 tests were not run in parallel because of use of thread-unsafe functionality, to list the tests that were skipped, re-run while setting PYTEST_RUN_PARALLEL_VERBOSE=1 in your shell environment | |
========================================================================= short test summary info ========================================================================= | |
PARALLEL FAILED sympy/assumptions/tests/test_assumptions_2.py::test_global - KeyError: x > 0 | |
PARALLEL FAILED sympy/assumptions/tests/test_context.py::test_assuming - assert not True | |
PARALLEL FAILED sympy/assumptions/tests/test_context.py::test_assuming_nested - assert not True | |
PARALLEL FAILED sympy/assumptions/tests/test_context.py::test_finally - assert not True | |
PARALLEL FAILED sympy/assumptions/tests/test_context.py::test_remove_safe - KeyError: Q.integer(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_bounded - assert False is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_unbounded - ValueError: inconsistent assumptions Q.finite(y) & Q.infinite(x) & ~Q.zero(y) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_issue_27447 - ValueError: inconsistent assumptions Q.finite(y) & ~Q.finite(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_commutative - ValueError: inconsistent assumptions ~Q.commutative(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_complex - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_even_query - ValueError: inconsistent assumptions ~Q.integer(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_extended_real - ValueError: inconsistent assumptions Q.positive_infinite(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_rational - ValueError: inconsistent assumptions Q.irrational(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_hermitian - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_imaginary - assert False is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_integer - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_negative - ValueError: inconsistent assumptions ~Q.real(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_odd_query - ValueError: inconsistent assumptions ~Q.integer(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_prime - ValueError: inconsistent assumptions ~Q.integer(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_positive - ValueError: inconsistent assumptions Q.imaginary(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_nonpositive - ValueError: inconsistent assumptions Q.imaginary(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_nonnegative - ValueError: inconsistent assumptions Q.imaginary(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_real_basic - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_real_pow - ValueError: inconsistent assumptions Q.imaginary(x) & Q.imaginary(y) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_real_functions - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_algebraic - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_global - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_custom_context - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_composite_proposition - assert False is None | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_positive_assuming - RuntimeError: Set changed size during iteration | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_issue_7246 - ValueError: inconsistent assumptions Q.imaginary(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_custom_AskHandler - Failed: Failed: DID NOT WARN. No warnings of type <class 'sympy.utilities.exceptions.SymPyDeprecationWarning'> was emitted. The list of emitted warnings is: []. | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_polyadic_predicate - AttributeError: 'AssumptionKeys' object has no attribute 'sexyprime' | |
PARALLEL FAILED sympy/assumptions/tests/test_query.py::test_issue_25221 - assert False is None | |
PARALLEL FAILED sympy/assumptions/tests/test_refine.py::test_Abs - assert x**2 != (x ** 2) | |
PARALLEL FAILED sympy/assumptions/tests/test_refine.py::test_pow1 - assert Abs(x) != Abs(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_refine.py::test_pow2 - assert x**2 == (Abs(x) ** 2) | |
PARALLEL FAILED sympy/assumptions/tests/test_refine.py::test_re - ValueError: inconsistent assumptions Q.imaginary(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_refine.py::test_im - ValueError: inconsistent assumptions Q.imaginary(x) | |
PARALLEL FAILED sympy/assumptions/tests/test_rel_queries.py::test_lra_satask - sympy.logic.algorithms.lra_theory.UnhandledInput: LRASolver: Q.odd(x) is an unhandled predicate | |
PARALLEL FAILED sympy/assumptions/tests/test_rel_queries.py::test_old_assumptions - sympy.logic.algorithms.lra_theory.UnhandledInput: LRASolver: Q.odd(x) is an unhandled predicate | |
PARALLEL FAILED sympy/assumptions/tests/test_rel_queries.py::test_rel_queries - assert None is False | |
PARALLEL FAILED sympy/assumptions/tests/test_rel_queries.py::test_all_pred - sympy.logic.algorithms.lra_theory.UnhandledInput: LRASolver: Q.odd(x) is an unhandled predicate | |
PARALLEL FAILED sympy/assumptions/tests/test_rel_queries.py::test_number_line_properties - assert None is True | |
PARALLEL FAILED sympy/assumptions/tests/test_rel_queries.py::test_equality - assert None is True | |
PARALLEL FAILED sympy/assumptions/tests/test_satask.py::test_satask - ValueError: Inconsistent assumptions | |
PARALLEL FAILED sympy/assumptions/tests/test_satask.py::test_rational_irrational - ValueError: Inconsistent assumptions | |
PARALLEL FAILED sympy/assumptions/tests/test_satask.py::test_even_satask - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_satask.py::test_odd_satask - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_satask.py::test_abs - assert True is None | |
PARALLEL FAILED sympy/assumptions/tests/test_satask.py::test_imaginary - ValueError: Inconsistent assumptions | |
PARALLEL FAILED sympy/calculus/tests/test_finite_diff.py::test_differentiate_finite - Failed: Failed: DID NOT WARN. No warnings of type <class 'sympy.utilities.exceptions.SymPyDeprecationWarning'> was emitted. The list of emitted warnings is: []. | |
PARALLEL FAILED sympy/calculus/tests/test_singularities.py::test_issue_23401 - mpmath.libmp.libhyper.NoConvergence: convergence to root failed; try n < 15 or maxsteps > 50 | |
PARALLEL FAILED sympy/combinatorics/tests/test_free_groups.py::test_FreeGroup__getitem__ - assert <free group o...rators (y, z)> == <free group o...rators (y, z)> | |
PARALLEL FAILED sympy/combinatorics/tests/test_permutations.py::test_Permutation_subclassing - Failed: DID NOT RAISE <class 'TypeError'> | |
PARALLEL FAILED sympy/combinatorics/tests/test_permutations.py::test_deprecated_print_cyclic - Failed: Failed: DID NOT WARN. No warnings of type <class 'sympy.utilities.exceptions.SymPyDeprecationWarning'> was emitted. The list of emitted warnings is: []. | |
PARALLEL FAILED sympy/concrete/tests/test_guess.py::test_rationalize - AssertionError: assert -1/2 == -1/3 | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! KeyboardInterrupt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
/Users/aaronmeurer/.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/threading.py:1105: KeyboardInterrupt | |
(to show a full traceback on KeyboardInterrupt use --full-trace) | |
===================================== 506 passed, 10 skipped, 199 deselected, 15 xfailed, 8 warnings, 57 errors in 484.82s (0:08:04) ====================================== |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! KeyboardInterrupt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
config = <_pytest.config.Config object at 0x3a852579310>, doit = <function _main at 0x3a85336e580> | |
def wrap_session( | |
config: Config, doit: Callable[[Config, Session], int | ExitCode | None] | |
) -> int | ExitCode: | |
"""Skeleton command line program.""" | |
session = Session.from_config(config) | |
session.exitstatus = ExitCode.OK | |
initstate = 0 | |
try: | |
try: | |
config._do_configure() | |
initstate = 1 | |
config.hook.pytest_sessionstart(session=session) | |
initstate = 2 | |
> session.exitstatus = doit(config, session) or 0 | |
^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/main.py:289: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
config = <_pytest.config.Config object at 0x3a852579310>, session = <Session exitstatus=<ExitCode.OK: 0> testsfailed=28 testscollected=13722> | |
def _main(config: Config, session: Session) -> int | ExitCode | None: | |
"""Default command line protocol for initialization, session, | |
running tests and reporting.""" | |
config.hook.pytest_collection(session=session) | |
> config.hook.pytest_runtestloop(session=session) | |
.venv/lib/python3.14t/site-packages/_pytest/main.py:343: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <HookCaller 'pytest_runtestloop'>, kwargs = {'session': <Session exitstatus=<ExitCode.OK: 0> testsfailed=28 testscollected=13722>}, firstresult = True | |
def __call__(self, **kwargs: object) -> Any: | |
"""Call the hook. | |
Only accepts keyword arguments, which should match the hook | |
specification. | |
Returns the result(s) of calling all registered plugins, see | |
:ref:`calling`. | |
""" | |
assert not self.is_historic(), ( | |
"Cannot directly call a historic hook - use call_historic instead." | |
) | |
self._verify_all_args_are_provided(kwargs) | |
firstresult = self.spec.opts.get("firstresult", False) if self.spec else False | |
# Copy because plugins may register other plugins during iteration (#438). | |
> return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_hooks.py:512: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <_pytest.config.PytestPluginManager object at 0x3a852578a10>, hook_name = 'pytest_runtestloop' | |
methods = [<HookImpl plugin_name='main', plugin=<module '_pytest.main' from '/Users/aaronmeurer/Documents/Python/sympy/sympy/.ve...3a853dca510>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x3a853dca810>>] | |
kwargs = {'session': <Session exitstatus=<ExitCode.OK: 0> testsfailed=28 testscollected=13722>}, firstresult = True | |
def _hookexec( | |
self, | |
hook_name: str, | |
methods: Sequence[HookImpl], | |
kwargs: Mapping[str, object], | |
firstresult: bool, | |
) -> object | list[object]: | |
# called from all hookcaller instances. | |
# enable_tracing will set its own wrapping function at self._inner_hookexec | |
> return self._inner_hookexec(hook_name, methods, kwargs, firstresult) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_manager.py:120: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <_pytest.logging.LoggingPlugin object at 0x3a853dca810>, session = <Session exitstatus=<ExitCode.OK: 0> testsfailed=28 testscollected=13722> | |
@hookimpl(wrapper=True) | |
def pytest_runtestloop(self, session: Session) -> Generator[None, object, object]: | |
if session.config.option.collectonly: | |
return (yield) | |
if self._log_cli_enabled() and self._config.get_verbosity() < 1: | |
# The verbose flag is needed to avoid messy test progress output. | |
self._config.option.verbose = 1 | |
with catching_logs(self.log_cli_handler, level=self.log_cli_level): | |
with catching_logs(self.log_file_handler, level=self.log_file_level): | |
> return (yield) # Run all the tests. | |
^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/logging.py:801: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <_pytest.terminal.TerminalReporter object at 0x3a853dca510> | |
@hookimpl(wrapper=True) | |
def pytest_runtestloop(self) -> Generator[None, object, object]: | |
> result = yield | |
^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/terminal.py:688: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
session = <Session exitstatus=<ExitCode.OK: 0> testsfailed=28 testscollected=13722> | |
def pytest_runtestloop(session: Session) -> bool: | |
if session.testsfailed and not session.config.option.continue_on_collection_errors: | |
raise session.Interrupted( | |
f"{session.testsfailed} error{'s' if session.testsfailed != 1 else ''} during collection" | |
) | |
if session.config.option.collectonly: | |
return True | |
for i, item in enumerate(session.items): | |
nextitem = session.items[i + 1] if i + 1 < len(session.items) else None | |
> item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem) | |
.venv/lib/python3.14t/site-packages/_pytest/main.py:367: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <HookCaller 'pytest_runtest_protocol'>, kwargs = {'item': <Function test_evalf_slow_series>, 'nextitem': <Function test_evalf_oo_to_oo>}, firstresult = True | |
def __call__(self, **kwargs: object) -> Any: | |
"""Call the hook. | |
Only accepts keyword arguments, which should match the hook | |
specification. | |
Returns the result(s) of calling all registered plugins, see | |
:ref:`calling`. | |
""" | |
assert not self.is_historic(), ( | |
"Cannot directly call a historic hook - use call_historic instead." | |
) | |
self._verify_all_args_are_provided(kwargs) | |
firstresult = self.spec.opts.get("firstresult", False) if self.spec else False | |
# Copy because plugins may register other plugins during iteration (#438). | |
> return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_hooks.py:512: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <_pytest.config.PytestPluginManager object at 0x3a852578a10>, hook_name = 'pytest_runtest_protocol' | |
methods = [<HookImpl plugin_name='runner', plugin=<module '_pytest.runner' from '/Users/aaronmeurer/Documents/Python/sympy/sympy...ings' from '/Users/aaronmeurer/Documents/Python/sympy/sympy/.venv/lib/python3.14t/site-packages/_pytest/warnings.py'>>] | |
kwargs = {'item': <Function test_evalf_slow_series>, 'nextitem': <Function test_evalf_oo_to_oo>}, firstresult = True | |
def _hookexec( | |
self, | |
hook_name: str, | |
methods: Sequence[HookImpl], | |
kwargs: Mapping[str, object], | |
firstresult: bool, | |
) -> object | list[object]: | |
# called from all hookcaller instances. | |
# enable_tracing will set its own wrapping function at self._inner_hookexec | |
> return self._inner_hookexec(hook_name, methods, kwargs, firstresult) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_manager.py:120: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
item = <Function test_evalf_slow_series> | |
@pytest.hookimpl(wrapper=True, tryfirst=True) | |
def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: | |
with catch_warnings_for_item( | |
config=item.config, ihook=item.ihook, when="runtest", item=item | |
): | |
> return (yield) | |
^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/warnings.py:90: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
item = <Function test_evalf_slow_series> | |
@hookimpl(wrapper=True, tryfirst=True) | |
def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: | |
"""Setup the pytest_assertrepr_compare and pytest_assertion_pass hooks. | |
The rewrite module will use util._reprcompare if it exists to use custom | |
reporting via the pytest_assertrepr_compare hook. This sets up this custom | |
comparison for the test. | |
""" | |
ihook = item.ihook | |
def callbinrepr(op, left: object, right: object) -> str | None: | |
"""Call the pytest_assertrepr_compare hook and prepare the result. | |
This uses the first result from the hook and then ensures the | |
following: | |
* Overly verbose explanations are truncated unless configured otherwise | |
(eg. if running in verbose mode). | |
* Embedded newlines are escaped to help util.format_explanation() | |
later. | |
* If the rewrite mode is used embedded %-characters are replaced | |
to protect later % formatting. | |
The result can be formatted by util.format_explanation() for | |
pretty printing. | |
""" | |
hook_result = ihook.pytest_assertrepr_compare( | |
config=item.config, op=op, left=left, right=right | |
) | |
for new_expl in hook_result: | |
if new_expl: | |
new_expl = truncate.truncate_if_required(new_expl, item) | |
new_expl = [line.replace("\n", "\\n") for line in new_expl] | |
res = "\n~".join(new_expl) | |
if item.config.getvalue("assertmode") == "rewrite": | |
res = res.replace("%", "%%") | |
return res | |
return None | |
saved_assert_hooks = util._reprcompare, util._assertion_pass | |
util._reprcompare = callbinrepr | |
util._config = item.config | |
if ihook.pytest_assertion_pass.get_hookimpls(): | |
def call_assertion_pass_hook(lineno: int, orig: str, expl: str) -> None: | |
ihook.pytest_assertion_pass(item=item, lineno=lineno, orig=orig, expl=expl) | |
util._assertion_pass = call_assertion_pass_hook | |
try: | |
> return (yield) | |
^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/assertion/__init__.py:192: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
item = <Function test_evalf_slow_series> | |
@hookimpl(wrapper=True) | |
def pytest_runtest_protocol(item: Item) -> Iterator[None]: | |
if _get_twisted_version() is TwistedVersion.Version24: | |
import twisted.python.failure as ut | |
# Monkeypatch `Failure.__init__` to store the raw exception info. | |
original__init__ = ut.Failure.__init__ | |
def store_raw_exception_info( | |
self, exc_value=None, exc_type=None, exc_tb=None, captureVars=None | |
): # pragma: no cover | |
if exc_value is None: | |
raw_exc_info = sys.exc_info() | |
else: | |
if exc_type is None: | |
exc_type = type(exc_value) | |
if exc_tb is None: | |
exc_tb = sys.exc_info()[2] | |
raw_exc_info = (exc_type, exc_value, exc_tb) | |
setattr(self, TWISTED_RAW_EXCINFO_ATTR, tuple(raw_exc_info)) | |
try: | |
original__init__( | |
self, exc_value, exc_type, exc_tb, captureVars=captureVars | |
) | |
except TypeError: # pragma: no cover | |
original__init__(self, exc_value, exc_type, exc_tb) | |
with MonkeyPatch.context() as patcher: | |
patcher.setattr(ut.Failure, "__init__", store_raw_exception_info) | |
return (yield) | |
else: | |
> return (yield) | |
^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/unittest.py:475: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
item = <Function test_evalf_slow_series> | |
@pytest.hookimpl(wrapper=True, trylast=True) | |
def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: | |
timeout = get_timeout_config_value(item.config) | |
if timeout > 0: | |
import faulthandler | |
stderr = item.config.stash[fault_handler_stderr_fd_key] | |
faulthandler.dump_traceback_later(timeout, file=stderr) | |
try: | |
return (yield) | |
finally: | |
faulthandler.cancel_dump_traceback_later() | |
else: | |
> return (yield) | |
^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/faulthandler.py:88: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
item = <Function test_evalf_slow_series>, nextitem = <Function test_evalf_oo_to_oo> | |
def pytest_runtest_protocol(item: Item, nextitem: Item | None) -> bool: | |
ihook = item.ihook | |
ihook.pytest_runtest_logstart(nodeid=item.nodeid, location=item.location) | |
> runtestprotocol(item, nextitem=nextitem) | |
.venv/lib/python3.14t/site-packages/_pytest/runner.py:117: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
item = <Function test_evalf_slow_series>, log = True, nextitem = <Function test_evalf_oo_to_oo> | |
def runtestprotocol( | |
item: Item, log: bool = True, nextitem: Item | None = None | |
) -> list[TestReport]: | |
hasrequest = hasattr(item, "_request") | |
if hasrequest and not item._request: # type: ignore[attr-defined] | |
# This only happens if the item is re-run, as is done by | |
# pytest-rerunfailures. | |
item._initrequest() # type: ignore[attr-defined] | |
rep = call_and_report(item, "setup", log) | |
reports = [rep] | |
if rep.passed: | |
if item.config.getoption("setupshow", False): | |
show_test_item(item) | |
if not item.config.getoption("setuponly", False): | |
> reports.append(call_and_report(item, "call", log)) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/runner.py:136: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
item = <Function test_evalf_slow_series>, when = 'call', log = True, kwds = {}, ihook = <_pytest.config.compat.PathAwareHookProxy object at 0x3a852579910> | |
reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>) | |
def call_and_report( | |
item: Item, when: Literal["setup", "call", "teardown"], log: bool = True, **kwds | |
) -> TestReport: | |
ihook = item.ihook | |
if when == "setup": | |
runtest_hook: Callable[..., None] = ihook.pytest_runtest_setup | |
elif when == "call": | |
runtest_hook = ihook.pytest_runtest_call | |
elif when == "teardown": | |
runtest_hook = ihook.pytest_runtest_teardown | |
else: | |
assert False, f"Unhandled runtest hook case: {when}" | |
reraise: tuple[type[BaseException], ...] = (Exit,) | |
if not item.config.getoption("usepdb", False): | |
reraise += (KeyboardInterrupt,) | |
> call = CallInfo.from_call( | |
lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise | |
) | |
.venv/lib/python3.14t/site-packages/_pytest/runner.py:245: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
cls = <class '_pytest.runner.CallInfo'>, func = <function call_and_report.<locals>.<lambda> at 0x3a86f90e340>, when = 'call' | |
reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>) | |
@classmethod | |
def from_call( | |
cls, | |
func: Callable[[], TResult], | |
when: Literal["collect", "setup", "call", "teardown"], | |
reraise: type[BaseException] | tuple[type[BaseException], ...] | None = None, | |
) -> CallInfo[TResult]: | |
"""Call func, wrapping the result in a CallInfo. | |
:param func: | |
The function to call. Called without arguments. | |
:type func: Callable[[], _pytest.runner.TResult] | |
:param when: | |
The phase in which the function is called. | |
:param reraise: | |
Exception or exceptions that shall propagate if raised by the | |
function, instead of being wrapped in the CallInfo. | |
""" | |
excinfo = None | |
instant = timing.Instant() | |
try: | |
> result: TResult | None = func() | |
^^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/runner.py:344: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
> lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
) | |
.venv/lib/python3.14t/site-packages/_pytest/runner.py:246: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <HookCaller 'pytest_runtest_call'>, kwargs = {'item': <Function test_evalf_slow_series>}, firstresult = False | |
def __call__(self, **kwargs: object) -> Any: | |
"""Call the hook. | |
Only accepts keyword arguments, which should match the hook | |
specification. | |
Returns the result(s) of calling all registered plugins, see | |
:ref:`calling`. | |
""" | |
assert not self.is_historic(), ( | |
"Cannot directly call a historic hook - use call_historic instead." | |
) | |
self._verify_all_args_are_provided(kwargs) | |
firstresult = self.spec.opts.get("firstresult", False) if self.spec else False | |
# Copy because plugins may register other plugins during iteration (#438). | |
> return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_hooks.py:512: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <_pytest.config.PytestPluginManager object at 0x3a852578a10>, hook_name = 'pytest_runtest_call' | |
methods = [<HookImpl plugin_name='threadexception', plugin=<module '_pytest.threadexception' from '/Users/aaronmeurer/Documents/... plugin_name='capturemanager', plugin=<CaptureManager _method='fd' _global_capturing=None _capture_fixture=None>>, ...] | |
kwargs = {'item': <Function test_evalf_slow_series>}, firstresult = False | |
def _hookexec( | |
self, | |
hook_name: str, | |
methods: Sequence[HookImpl], | |
kwargs: Mapping[str, object], | |
firstresult: bool, | |
) -> object | list[object]: | |
# called from all hookcaller instances. | |
# enable_tracing will set its own wrapping function at self._inner_hookexec | |
> return self._inner_hookexec(hook_name, methods, kwargs, firstresult) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_manager.py:120: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <_pytest.logging.LoggingPlugin object at 0x3a853dca810>, item = <Function test_evalf_slow_series> | |
@hookimpl(wrapper=True) | |
def pytest_runtest_call(self, item: nodes.Item) -> Generator[None]: | |
self.log_cli_handler.set_when("call") | |
with self._runtest_for(item, "call"): | |
> yield | |
.venv/lib/python3.14t/site-packages/_pytest/logging.py:850: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <CaptureManager _method='fd' _global_capturing=None _capture_fixture=None>, item = <Function test_evalf_slow_series> | |
@hookimpl(wrapper=True) | |
def pytest_runtest_call(self, item: Item) -> Generator[None]: | |
with self.item_capture("call", item): | |
> return (yield) | |
^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/capture.py:900: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
hook_impl = <HookImpl plugin_name='hypothesispytest', plugin=<module '_hypothesis_pytestplugin' from '/Users/aaronmeurer/Documents/Python/sympy/sympy/.venv/lib/python3.14t/site-packages/_hypothesis_pytestplugin.py'>> | |
hook_name = 'pytest_runtest_call', args = [<Function test_evalf_slow_series>] | |
def run_old_style_hookwrapper( | |
hook_impl: HookImpl, hook_name: str, args: Sequence[object] | |
) -> Teardown: | |
""" | |
backward compatibility wrapper to run a old style hookwrapper as a wrapper | |
""" | |
teardown: Teardown = cast(Teardown, hook_impl.function(*args)) | |
try: | |
next(teardown) | |
except StopIteration: | |
_raise_wrapfail(teardown, "did not yield") | |
try: | |
res = yield | |
result = Result(res, None) | |
except BaseException as exc: | |
result = Result(None, exc) | |
try: | |
teardown.send(result) | |
except StopIteration: | |
pass | |
except BaseException as e: | |
_warn_teardown_exception(hook_name, hook_impl, e) | |
raise | |
else: | |
_raise_wrapfail(teardown, "has second yield") | |
finally: | |
teardown.close() | |
> return result.get_result() | |
^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_callers.py:53: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
hook_impl = <HookImpl plugin_name='hypothesispytest', plugin=<module '_hypothesis_pytestplugin' from '/Users/aaronmeurer/Documents/Python/sympy/sympy/.venv/lib/python3.14t/site-packages/_hypothesis_pytestplugin.py'>> | |
hook_name = 'pytest_runtest_call', args = [<Function test_evalf_slow_series>] | |
def run_old_style_hookwrapper( | |
hook_impl: HookImpl, hook_name: str, args: Sequence[object] | |
) -> Teardown: | |
""" | |
backward compatibility wrapper to run a old style hookwrapper as a wrapper | |
""" | |
teardown: Teardown = cast(Teardown, hook_impl.function(*args)) | |
try: | |
next(teardown) | |
except StopIteration: | |
_raise_wrapfail(teardown, "did not yield") | |
try: | |
> res = yield | |
^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_callers.py:38: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
item = <Function test_evalf_slow_series> | |
@hookimpl(wrapper=True) | |
def pytest_runtest_call(item: Item) -> Generator[None]: | |
xfailed = item.stash.get(xfailed_key, None) | |
if xfailed is None: | |
item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) | |
if xfailed and not item.config.option.runxfail and not xfailed.run: | |
xfail("[NOTRUN] " + xfailed.reason) | |
try: | |
> return (yield) | |
^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/skipping.py:263: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
item = <Function test_evalf_slow_series> | |
def pytest_runtest_call(item: Item) -> None: | |
_update_current_test_var(item, "call") | |
try: | |
del sys.last_type | |
del sys.last_value | |
del sys.last_traceback | |
if sys.version_info >= (3, 12, 0): | |
del sys.last_exc # type:ignore[attr-defined] | |
except AttributeError: | |
pass | |
try: | |
> item.runtest() | |
.venv/lib/python3.14t/site-packages/_pytest/runner.py:178: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <Function test_evalf_slow_series> | |
def runtest(self) -> None: | |
"""Execute the underlying test function.""" | |
> self.ihook.pytest_pyfunc_call(pyfuncitem=self) | |
.venv/lib/python3.14t/site-packages/_pytest/python.py:1671: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <HookCaller 'pytest_pyfunc_call'>, kwargs = {'pyfuncitem': <Function test_evalf_slow_series>}, firstresult = True | |
def __call__(self, **kwargs: object) -> Any: | |
"""Call the hook. | |
Only accepts keyword arguments, which should match the hook | |
specification. | |
Returns the result(s) of calling all registered plugins, see | |
:ref:`calling`. | |
""" | |
assert not self.is_historic(), ( | |
"Cannot directly call a historic hook - use call_historic instead." | |
) | |
self._verify_all_args_are_provided(kwargs) | |
firstresult = self.spec.opts.get("firstresult", False) if self.spec else False | |
# Copy because plugins may register other plugins during iteration (#438). | |
> return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_hooks.py:512: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <_pytest.config.PytestPluginManager object at 0x3a852578a10>, hook_name = 'pytest_pyfunc_call' | |
methods = [<HookImpl plugin_name='python', plugin=<module '_pytest.python' from '/Users/aaronmeurer/Documents/Python/sympy/sympy/.venv/lib/python3.14t/site-packages/_pytest/python.py'>>] | |
kwargs = {'pyfuncitem': <Function test_evalf_slow_series>}, firstresult = True | |
def _hookexec( | |
self, | |
hook_name: str, | |
methods: Sequence[HookImpl], | |
kwargs: Mapping[str, object], | |
firstresult: bool, | |
) -> object | list[object]: | |
# called from all hookcaller instances. | |
# enable_tracing will set its own wrapping function at self._inner_hookexec | |
> return self._inner_hookexec(hook_name, methods, kwargs, firstresult) | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/pluggy/_manager.py:120: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
pyfuncitem = <Function test_evalf_slow_series> | |
@hookimpl(trylast=True) | |
def pytest_pyfunc_call(pyfuncitem: Function) -> object | None: | |
testfunction = pyfuncitem.obj | |
if is_async_function(testfunction): | |
async_fail(pyfuncitem.nodeid) | |
funcargs = pyfuncitem.funcargs | |
testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames} | |
> result = testfunction(**testargs) | |
^^^^^^^^^^^^^^^^^^^^^^^^ | |
.venv/lib/python3.14t/site-packages/_pytest/python.py:157: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
args = (), kwargs = {}, original_switch = 0.005, new_switch = 1e-06, _ = 3, closure = <function wrap_function_parallel.<locals>.inner.<locals>.closure at 0x3a86f9090c0> | |
workers = [<Thread(Thread-2349 (closure), started 6118486016)>, <Thread(Thread-2350 (closure), started 6135312384)>, <Thread(Thread-2351 (closure), started 6152138752)>, <Thread(Thread-2352 (closure), stopped 6168965120)>] | |
worker_kwargs = {}, num_completed = 4, worker = <Thread(Thread-2349 (closure), started 6118486016)> | |
@functools.wraps(fn) | |
def inner(*args, **kwargs): | |
errors = [] | |
skip = None | |
failed = None | |
barrier = threading.Barrier(n_workers) | |
original_switch = sys.getswitchinterval() | |
new_switch = 1e-6 | |
for _ in range(3): | |
try: | |
sys.setswitchinterval(new_switch) | |
break | |
except ValueError: | |
new_switch *= 10 | |
else: | |
sys.setswitchinterval(original_switch) | |
try: | |
def closure(*args, **kwargs): | |
for _ in range(n_iterations): | |
barrier.wait() | |
try: | |
fn(*args, **kwargs) | |
except Warning: | |
pass | |
except Exception as e: | |
errors.append(e) | |
except _pytest.outcomes.Skipped as s: | |
nonlocal skip | |
skip = s.msg | |
except _pytest.outcomes.Failed as f: | |
nonlocal failed | |
failed = f | |
workers = [] | |
for _ in range(0, n_workers): | |
worker_kwargs = kwargs | |
workers.append( | |
threading.Thread(target=closure, args=args, kwargs=worker_kwargs) | |
) | |
num_completed = 0 | |
try: | |
for worker in workers: | |
worker.start() | |
num_completed += 1 | |
finally: | |
if num_completed < len(workers): | |
barrier.abort() | |
for worker in workers: | |
> worker.join() | |
.venv/lib/python3.14t/site-packages/pytest_run_parallel/plugin.py:128: | |
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
self = <Thread(Thread-2349 (closure), started 6118486016)>, timeout = None | |
def join(self, timeout=None): | |
"""Wait until the thread terminates. | |
This blocks the calling thread until the thread whose join() method is | |
called terminates -- either normally or through an unhandled exception | |
or until the optional timeout occurs. | |
When the timeout argument is present and not None, it should be a | |
floating-point number specifying a timeout for the operation in seconds | |
(or fractions thereof). As join() always returns None, you must call | |
is_alive() after join() to decide whether a timeout happened -- if the | |
thread is still alive, the join() call timed out. | |
When the timeout argument is not present or None, the operation will | |
block until the thread terminates. | |
A thread can be join()ed many times. | |
join() raises a RuntimeError if an attempt is made to join the current | |
thread as that would cause a deadlock. It is also an error to join() a | |
thread before it has been started and attempts to do so raises the same | |
exception. | |
""" | |
if not self._initialized: | |
raise RuntimeError("Thread.__init__() not called") | |
if not self._started.is_set(): | |
raise RuntimeError("cannot join thread before it is started") | |
if self is current_thread(): | |
raise RuntimeError("cannot join current thread") | |
# the behavior of a negative timeout isn't documented, but | |
# historically .join(timeout=x) for x<0 has acted as if timeout=0 | |
if timeout is not None: | |
timeout = max(timeout, 0) | |
> self._handle.join(timeout) | |
E KeyboardInterrupt | |
../../../../.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/threading.py:1105: KeyboardInterrupt |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Cannot show all threads while the GIL is disabled> | |
Stack (most recent call first): | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/cache.py", line 72 in wrapper | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 1497 in evalf | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 290 in get_complex_part | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 310 in evalf_im | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 1485 in evalf | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 776 in evalf_pow | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 1485 in evalf | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 696 in evalf_mul | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 1485 in evalf | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 600 in evalf_add | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 1485 in evalf | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 855 in evalf_pow | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 1485 in evalf | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 696 in evalf_mul | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 1485 in evalf | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 600 in evalf_add | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 1485 in evalf | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/evalf.py", line 1650 in evalf | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/expr.py", line 934 in _eval_is_extended_positive_negative | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/expr.py", line 955 in _eval_is_extended_positive | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/add.py", line 768 in _eval_is_extended_positive | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/assumptions.py", line 552 in _ask | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/assumptions.py", line 496 in getit | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/functions/elementary/exponential.py", line 938 in _eval_is_zero | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/assumptions.py", line 552 in _ask | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/assumptions.py", line 496 in getit | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/simplify/powsimp.py", line 188 in powsimp | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/simplify/simplify.py", line 661 in simplify | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/expr.py", line 805 in equals | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/expr.py", line 3895 in round | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/expr.py", line 3896 in round | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/tests/test_arit.py", line 2433 in test_issue_21034 | |
File "/Users/aaronmeurer/Documents/Python/sympy/sympy/.venv/lib/python3.14t/site-packages/pytest_run_parallel/plugin.py", line 99 in closure | |
File "/Users/aaronmeurer/.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/threading.py", line 996 in run | |
File "/Users/aaronmeurer/.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/threading.py", line 1054 in _bootstrap_inner | |
File "/Users/aaronmeurer/.local/share/uv/python/cpython-3.14.0a6+freethreaded-macos-aarch64-none/lib/python3.14t/threading.py", line 1016 in _bootstrap | |
Segmentation fault: 11 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment