Skip to content

Instantly share code, notes, and snippets.

@asmeurer
Last active July 12, 2025 23:50
Show Gist options
  • Save asmeurer/d4a53cec804cf2d75fd8bb7cce9f5126 to your computer and use it in GitHub Desktop.
Save asmeurer/d4a53cec804cf2d75fd8bb7cce9f5126 to your computer and use it in GitHub Desktop.
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) ======================================
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 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
<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