diff --git a/.gitattributes b/.gitattributes index 36f069f53f906c6a627f0df413b33636be714433..e70fcea9db8be1f9adf1c29526e6a6d78c75fcc6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -439,3 +439,6 @@ tuning-competition-baseline/.venv/lib/python3.11/site-packages/nvidia/cudnn/lib/ .venv/lib/python3.11/site-packages/transformers/models/whisper/__pycache__/modeling_whisper.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text .venv/lib/python3.11/site-packages/transformers/utils/__pycache__/dummy_tf_objects.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text .venv/lib/python3.11/site-packages/transformers/utils/__pycache__/dummy_pt_objects.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/sympy/simplify/__pycache__/hyperexpand.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/sympy/crypto/__pycache__/crypto.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text +.venv/lib/python3.11/site-packages/sympy/simplify/tests/__pycache__/test_simplify.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d85afd5ed75d74eb5a65f7596f7275da8d7f120 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/__init__.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/_print_helpers.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/_print_helpers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..463b0ee42ed9dec6068704d349df00f1d269bf23 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/_print_helpers.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/add.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/add.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..90b9e67a7fdeb5badd2759d2d52534185c76e3ae Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/add.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/assumptions.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/assumptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2796a3272537a5375631e9b8903a1b12112d9a86 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/assumptions.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/backend.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/backend.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec52a5386e21fba616dece2aaa9e29c1562dacab Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/backend.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/cache.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/cache.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ecf11cb1c96c8fcbfcd9572ec69684e93bef4b4 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/cache.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/compatibility.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/compatibility.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..924adbfea8dd2ec82c438072c94038efdd299576 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/compatibility.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/containers.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/containers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a3f239234e9e7555aece57645fb2b5ed123c03c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/containers.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/core.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/core.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0c576e30a71cd5e44b2afb3fc4bf539d376f12b Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/core.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/evalf.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/evalf.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7dbc769a2e1d9a7560865f99699a332f70d38bf Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/evalf.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/exprtools.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/exprtools.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e9235d8b0cf4b5bb7c54b1fe86dd7adf3145a351 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/exprtools.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/facts.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/facts.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1de92912d037fcb5637f03775f6a3ca7de4187c3 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/facts.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/intfunc.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/intfunc.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..157e21c5bc756e1286551cb68b88bf2dbe5495df Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/intfunc.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/mul.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/mul.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55ccd6eb28e74c8b1cf1c7cb344a980423b037ce Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/mul.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/multidimensional.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/multidimensional.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6918f7a249ce0b6de1c23b9f006b00de42439b92 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/multidimensional.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/parameters.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/parameters.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fec3a0ab0906e7795cb6f2d9197d7a7ef772f0fc Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/parameters.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/power.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/power.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..571677db06e2497b80c5f3685bed434ec9c51bd6 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/power.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/random.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/random.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..613b9fe84239f4fe72a784569ffaccda6ca3969c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/random.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/relational.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/relational.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0598ad1e4ddfa1269deb8549635fa99d12b138c3 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/relational.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/rules.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/rules.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aee13473b6eaeae4c5d822da30b5115541976a3c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/rules.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/singleton.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/singleton.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..033b2ec667399ba995af441111df67ecf60cf892 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/singleton.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/symbol.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/symbol.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2fefc838e101695582e1c6bc1a8d0c32b581bb16 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/symbol.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/sympify.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/sympify.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3223e1ad6798b5d8075504effcb51fd911e9452 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/__pycache__/sympify.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_assumptions.py b/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_assumptions.py new file mode 100644 index 0000000000000000000000000000000000000000..1a8e47928b76034dd1d7ba8b8f87bd527bb1cdeb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_assumptions.py @@ -0,0 +1,12 @@ +from sympy.core import Symbol, Integer + +x = Symbol('x') +i3 = Integer(3) + + +def timeit_x_is_integer(): + x.is_integer + + +def timeit_Integer_is_irrational(): + i3.is_irrational diff --git a/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_basic.py b/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..df2a382ecbd3cf6eb1f8555577dabb5e07c6643b --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_basic.py @@ -0,0 +1,15 @@ +from sympy.core import symbols, S + +x, y = symbols('x,y') + + +def timeit_Symbol_meth_lookup(): + x.diff # no call, just method lookup + + +def timeit_S_lookup(): + S.Exp1 + + +def timeit_Symbol_eq_xy(): + x == y diff --git a/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_expand.py b/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_expand.py new file mode 100644 index 0000000000000000000000000000000000000000..4f5ac513e368cb7e9b542926bc25a5695de6d914 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_expand.py @@ -0,0 +1,23 @@ +from sympy.core import symbols, I + +x, y, z = symbols('x,y,z') + +p = 3*x**2*y*z**7 + 7*x*y*z**2 + 4*x + x*y**4 +e = (x + y + z + 1)**32 + + +def timeit_expand_nothing_todo(): + p.expand() + + +def bench_expand_32(): + """(x+y+z+1)**32 -> expand""" + e.expand() + + +def timeit_expand_complex_number_1(): + ((2 + 3*I)**1000).expand(complex=True) + + +def timeit_expand_complex_number_2(): + ((2 + 3*I/4)**1000).expand(complex=True) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_numbers.py b/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_numbers.py new file mode 100644 index 0000000000000000000000000000000000000000..5c7484c389232b3622fb4b6724e4ab8534dde382 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/benchmarks/bench_numbers.py @@ -0,0 +1,92 @@ +from sympy.core.numbers import Integer, Rational, pi, oo +from sympy.core.intfunc import integer_nthroot, igcd +from sympy.core.singleton import S + +i3 = Integer(3) +i4 = Integer(4) +r34 = Rational(3, 4) +q45 = Rational(4, 5) + + +def timeit_Integer_create(): + Integer(2) + + +def timeit_Integer_int(): + int(i3) + + +def timeit_neg_one(): + -S.One + + +def timeit_Integer_neg(): + -i3 + + +def timeit_Integer_abs(): + abs(i3) + + +def timeit_Integer_sub(): + i3 - i3 + + +def timeit_abs_pi(): + abs(pi) + + +def timeit_neg_oo(): + -oo + + +def timeit_Integer_add_i1(): + i3 + 1 + + +def timeit_Integer_add_ij(): + i3 + i4 + + +def timeit_Integer_add_Rational(): + i3 + r34 + + +def timeit_Integer_mul_i4(): + i3*4 + + +def timeit_Integer_mul_ij(): + i3*i4 + + +def timeit_Integer_mul_Rational(): + i3*r34 + + +def timeit_Integer_eq_i3(): + i3 == 3 + + +def timeit_Integer_ed_Rational(): + i3 == r34 + + +def timeit_integer_nthroot(): + integer_nthroot(100, 2) + + +def timeit_number_igcd_23_17(): + igcd(23, 17) + + +def timeit_number_igcd_60_3600(): + igcd(60, 3600) + + +def timeit_Rational_add_r1(): + r34 + 1 + + +def timeit_Rational_add_rq(): + r34 + q45 diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/__init__.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_assumptions.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_assumptions.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dcd2912f412104e7160e9512f01c9357b19e6da7 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_assumptions.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_containers.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_containers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce90b478ec077fc13b91beacf8df9f28e97bef8f Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_containers.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_facts.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_facts.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bf7db40aadad9ed41ac3a36a01bcc9d5292100a Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_facts.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_kind.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_kind.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1067a239ef1138d0866882ea22d9a1dae0be895c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_kind.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_power.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_power.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d854d4250a8858334bce359c4295ffcc12391088 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_power.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_random.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_random.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fdf2c9500a22795475c8a488b1bce5cf4924543c Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_random.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_subs.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_subs.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ed35814832b0426f11d20e1e1dc148ef6e85896 Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_subs.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_traversal.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_traversal.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..109766312bec2b8fcc85bc6d09a0cb3be17bb7bc Binary files /dev/null and b/.venv/lib/python3.11/site-packages/sympy/core/tests/__pycache__/test_traversal.cpython-311.pyc differ diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_arit.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_arit.py new file mode 100644 index 0000000000000000000000000000000000000000..d9848c39eb8c57580ee925f9d40e5e0a149c3174 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_arit.py @@ -0,0 +1,2472 @@ +from sympy.core.add import Add +from sympy.core.basic import Basic +from sympy.core.mod import Mod +from sympy.core.mul import Mul +from sympy.core.numbers import (Float, I, Integer, Rational, comp, nan, + oo, pi, zoo) +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, symbols) +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.complexes import (im, re, sign) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.integers import floor +from sympy.functions.elementary.miscellaneous import (Max, sqrt) +from sympy.functions.elementary.trigonometric import (atan, cos, sin) +from sympy.polys.polytools import Poly +from sympy.sets.sets import FiniteSet + +from sympy.core.parameters import distribute, evaluate +from sympy.core.expr import unchanged +from sympy.utilities.iterables import permutations +from sympy.testing.pytest import XFAIL, raises, warns +from sympy.utilities.exceptions import SymPyDeprecationWarning +from sympy.core.random import verify_numerically +from sympy.functions.elementary.trigonometric import asin + +from itertools import product + +a, c, x, y, z = symbols('a,c,x,y,z') +b = Symbol("b", positive=True) + + +def same_and_same_prec(a, b): + # stricter matching for Floats + return a == b and a._prec == b._prec + + +def test_bug1(): + assert re(x) != x + x.series(x, 0, 1) + assert re(x) != x + + +def test_Symbol(): + e = a*b + assert e == a*b + assert a*b*b == a*b**2 + assert a*b*b + c == c + a*b**2 + assert a*b*b - c == -c + a*b**2 + + x = Symbol('x', complex=True, real=False) + assert x.is_imaginary is None # could be I or 1 + I + x = Symbol('x', complex=True, imaginary=False) + assert x.is_real is None # could be 1 or 1 + I + x = Symbol('x', real=True) + assert x.is_complex + x = Symbol('x', imaginary=True) + assert x.is_complex + x = Symbol('x', real=False, imaginary=False) + assert x.is_complex is None # might be a non-number + + +def test_arit0(): + p = Rational(5) + e = a*b + assert e == a*b + e = a*b + b*a + assert e == 2*a*b + e = a*b + b*a + a*b + p*b*a + assert e == 8*a*b + e = a*b + b*a + a*b + p*b*a + a + assert e == a + 8*a*b + e = a + a + assert e == 2*a + e = a + b + a + assert e == b + 2*a + e = a + b*b + a + b*b + assert e == 2*a + 2*b**2 + e = a + Rational(2) + b*b + a + b*b + p + assert e == 7 + 2*a + 2*b**2 + e = (a + b*b + a + b*b)*p + assert e == 5*(2*a + 2*b**2) + e = (a*b*c + c*b*a + b*a*c)*p + assert e == 15*a*b*c + e = (a*b*c + c*b*a + b*a*c)*p - Rational(15)*a*b*c + assert e == Rational(0) + e = Rational(50)*(a - a) + assert e == Rational(0) + e = b*a - b - a*b + b + assert e == Rational(0) + e = a*b + c**p + assert e == a*b + c**5 + e = a/b + assert e == a*b**(-1) + e = a*2*2 + assert e == 4*a + e = 2 + a*2/2 + assert e == 2 + a + e = 2 - a - 2 + assert e == -a + e = 2*a*2 + assert e == 4*a + e = 2/a/2 + assert e == a**(-1) + e = 2**a**2 + assert e == 2**(a**2) + e = -(1 + a) + assert e == -1 - a + e = S.Half*(1 + a) + assert e == S.Half + a/2 + + +def test_div(): + e = a/b + assert e == a*b**(-1) + e = a/b + c/2 + assert e == a*b**(-1) + Rational(1)/2*c + e = (1 - b)/(b - 1) + assert e == (1 + -b)*((-1) + b)**(-1) + + +def test_pow_arit(): + n1 = Rational(1) + n2 = Rational(2) + n5 = Rational(5) + e = a*a + assert e == a**2 + e = a*a*a + assert e == a**3 + e = a*a*a*a**Rational(6) + assert e == a**9 + e = a*a*a*a**Rational(6) - a**Rational(9) + assert e == Rational(0) + e = a**(b - b) + assert e == Rational(1) + e = (a + Rational(1) - a)**b + assert e == Rational(1) + + e = (a + b + c)**n2 + assert e == (a + b + c)**2 + assert e.expand() == 2*b*c + 2*a*c + 2*a*b + a**2 + c**2 + b**2 + + e = (a + b)**n2 + assert e == (a + b)**2 + assert e.expand() == 2*a*b + a**2 + b**2 + + e = (a + b)**(n1/n2) + assert e == sqrt(a + b) + assert e.expand() == sqrt(a + b) + + n = n5**(n1/n2) + assert n == sqrt(5) + e = n*a*b - n*b*a + assert e == Rational(0) + e = n*a*b + n*b*a + assert e == 2*a*b*sqrt(5) + assert e.diff(a) == 2*b*sqrt(5) + assert e.diff(a) == 2*b*sqrt(5) + e = a/b**2 + assert e == a*b**(-2) + + assert sqrt(2*(1 + sqrt(2))) == (2*(1 + 2**S.Half))**S.Half + + x = Symbol('x') + y = Symbol('y') + + assert ((x*y)**3).expand() == y**3 * x**3 + assert ((x*y)**-3).expand() == y**-3 * x**-3 + + assert (x**5*(3*x)**(3)).expand() == 27 * x**8 + assert (x**5*(-3*x)**(3)).expand() == -27 * x**8 + assert (x**5*(3*x)**(-3)).expand() == x**2 * Rational(1, 27) + assert (x**5*(-3*x)**(-3)).expand() == x**2 * Rational(-1, 27) + + # expand_power_exp + _x = Symbol('x', zero=False) + _y = Symbol('y', zero=False) + assert (_x**(y**(x + exp(x + y)) + z)).expand(deep=False) == \ + _x**z*_x**(y**(x + exp(x + y))) + assert (_x**(_y**(x + exp(x + y)) + z)).expand() == \ + _x**z*_x**(_y**x*_y**(exp(x)*exp(y))) + + n = Symbol('n', even=False) + k = Symbol('k', even=True) + o = Symbol('o', odd=True) + + assert unchanged(Pow, -1, x) + assert unchanged(Pow, -1, n) + assert (-2)**k == 2**k + assert (-1)**k == 1 + assert (-1)**o == -1 + + +def test_pow2(): + # x**(2*y) is always (x**y)**2 but is only (x**2)**y if + # x.is_positive or y.is_integer + # let x = 1 to see why the following are not true. + assert (-x)**Rational(2, 3) != x**Rational(2, 3) + assert (-x)**Rational(5, 7) != -x**Rational(5, 7) + assert ((-x)**2)**Rational(1, 3) != ((-x)**Rational(1, 3))**2 + assert sqrt(x**2) != x + + +def test_pow3(): + assert sqrt(2)**3 == 2 * sqrt(2) + assert sqrt(2)**3 == sqrt(8) + + +def test_mod_pow(): + for s, t, u, v in [(4, 13, 497, 445), (4, -3, 497, 365), + (3.2, 2.1, 1.9, 0.1031015682350942), (S(3)/2, 5, S(5)/6, S(3)/32)]: + assert pow(S(s), t, u) == v + assert pow(S(s), S(t), u) == v + assert pow(S(s), t, S(u)) == v + assert pow(S(s), S(t), S(u)) == v + assert pow(S(2), S(10000000000), S(3)) == 1 + assert pow(x, y, z) == x**y%z + raises(TypeError, lambda: pow(S(4), "13", 497)) + raises(TypeError, lambda: pow(S(4), 13, "497")) + + +def test_pow_E(): + assert 2**(y/log(2)) == S.Exp1**y + assert 2**(y/log(2)/3) == S.Exp1**(y/3) + assert 3**(1/log(-3)) != S.Exp1 + assert (3 + 2*I)**(1/(log(-3 - 2*I) + I*pi)) == S.Exp1 + assert (4 + 2*I)**(1/(log(-4 - 2*I) + I*pi)) == S.Exp1 + assert (3 + 2*I)**(1/(log(-3 - 2*I, 3)/2 + I*pi/log(3)/2)) == 9 + assert (3 + 2*I)**(1/(log(3 + 2*I, 3)/2)) == 9 + # every time tests are run they will affirm with a different random + # value that this identity holds + while 1: + b = x._random() + r, i = b.as_real_imag() + if i: + break + assert verify_numerically(b**(1/(log(-b) + sign(i)*I*pi).n()), S.Exp1) + + +def test_pow_issue_3516(): + assert 4**Rational(1, 4) == sqrt(2) + + +def test_pow_im(): + for m in (-2, -1, 2): + for d in (3, 4, 5): + b = m*I + for i in range(1, 4*d + 1): + e = Rational(i, d) + assert (b**e - b.n()**e.n()).n(2, chop=1e-10) == 0 + + e = Rational(7, 3) + assert (2*x*I)**e == 4*2**Rational(1, 3)*(I*x)**e # same as Wolfram Alpha + im = symbols('im', imaginary=True) + assert (2*im*I)**e == 4*2**Rational(1, 3)*(I*im)**e + + args = [I, I, I, I, 2] + e = Rational(1, 3) + ans = 2**e + assert Mul(*args, evaluate=False)**e == ans + assert Mul(*args)**e == ans + args = [I, I, I, 2] + e = Rational(1, 3) + ans = 2**e*(-I)**e + assert Mul(*args, evaluate=False)**e == ans + assert Mul(*args)**e == ans + args.append(-3) + ans = (6*I)**e + assert Mul(*args, evaluate=False)**e == ans + assert Mul(*args)**e == ans + args.append(-1) + ans = (-6*I)**e + assert Mul(*args, evaluate=False)**e == ans + assert Mul(*args)**e == ans + + args = [I, I, 2] + e = Rational(1, 3) + ans = (-2)**e + assert Mul(*args, evaluate=False)**e == ans + assert Mul(*args)**e == ans + args.append(-3) + ans = (6)**e + assert Mul(*args, evaluate=False)**e == ans + assert Mul(*args)**e == ans + args.append(-1) + ans = (-6)**e + assert Mul(*args, evaluate=False)**e == ans + assert Mul(*args)**e == ans + assert Mul(Pow(-1, Rational(3, 2), evaluate=False), I, I) == I + assert Mul(I*Pow(I, S.Half, evaluate=False)) == sqrt(I)*I + + +def test_real_mul(): + assert Float(0) * pi * x == 0 + assert set((Float(1) * pi * x).args) == {Float(1), pi, x} + + +def test_ncmul(): + A = Symbol("A", commutative=False) + B = Symbol("B", commutative=False) + C = Symbol("C", commutative=False) + assert A*B != B*A + assert A*B*C != C*B*A + assert A*b*B*3*C == 3*b*A*B*C + assert A*b*B*3*C != 3*b*B*A*C + assert A*b*B*3*C == 3*A*B*C*b + + assert A + B == B + A + assert (A + B)*C != C*(A + B) + + assert C*(A + B)*C != C*C*(A + B) + + assert A*A == A**2 + assert (A + B)*(A + B) == (A + B)**2 + + assert A**-1 * A == 1 + assert A/A == 1 + assert A/(A**2) == 1/A + + assert A/(1 + A) == A/(1 + A) + + assert set((A + B + 2*(A + B)).args) == \ + {A, B, 2*(A + B)} + + +def test_mul_add_identity(): + m = Mul(1, 2) + assert isinstance(m, Rational) and m.p == 2 and m.q == 1 + m = Mul(1, 2, evaluate=False) + assert isinstance(m, Mul) and m.args == (1, 2) + m = Mul(0, 1) + assert m is S.Zero + m = Mul(0, 1, evaluate=False) + assert isinstance(m, Mul) and m.args == (0, 1) + m = Add(0, 1) + assert m is S.One + m = Add(0, 1, evaluate=False) + assert isinstance(m, Add) and m.args == (0, 1) + + +def test_ncpow(): + x = Symbol('x', commutative=False) + y = Symbol('y', commutative=False) + z = Symbol('z', commutative=False) + a = Symbol('a') + b = Symbol('b') + c = Symbol('c') + + assert (x**2)*(y**2) != (y**2)*(x**2) + assert (x**-2)*y != y*(x**2) + assert 2**x*2**y != 2**(x + y) + assert 2**x*2**y*2**z != 2**(x + y + z) + assert 2**x*2**(2*x) == 2**(3*x) + assert 2**x*2**(2*x)*2**x == 2**(4*x) + assert exp(x)*exp(y) != exp(y)*exp(x) + assert exp(x)*exp(y)*exp(z) != exp(y)*exp(x)*exp(z) + assert exp(x)*exp(y)*exp(z) != exp(x + y + z) + assert x**a*x**b != x**(a + b) + assert x**a*x**b*x**c != x**(a + b + c) + assert x**3*x**4 == x**7 + assert x**3*x**4*x**2 == x**9 + assert x**a*x**(4*a) == x**(5*a) + assert x**a*x**(4*a)*x**a == x**(6*a) + + +def test_powerbug(): + x = Symbol("x") + assert x**1 != (-x)**1 + assert x**2 == (-x)**2 + assert x**3 != (-x)**3 + assert x**4 == (-x)**4 + assert x**5 != (-x)**5 + assert x**6 == (-x)**6 + + assert x**128 == (-x)**128 + assert x**129 != (-x)**129 + + assert (2*x)**2 == (-2*x)**2 + + +def test_Mul_doesnt_expand_exp(): + x = Symbol('x') + y = Symbol('y') + assert unchanged(Mul, exp(x), exp(y)) + assert unchanged(Mul, 2**x, 2**y) + assert x**2*x**3 == x**5 + assert 2**x*3**x == 6**x + assert x**(y)*x**(2*y) == x**(3*y) + assert sqrt(2)*sqrt(2) == 2 + assert 2**x*2**(2*x) == 2**(3*x) + assert sqrt(2)*2**Rational(1, 4)*5**Rational(3, 4) == 10**Rational(3, 4) + assert (x**(-log(5)/log(3))*x)/(x*x**( - log(5)/log(3))) == sympify(1) + + +def test_Mul_is_integer(): + k = Symbol('k', integer=True) + n = Symbol('n', integer=True) + nr = Symbol('nr', rational=False) + ir = Symbol('ir', irrational=True) + nz = Symbol('nz', integer=True, zero=False) + e = Symbol('e', even=True) + o = Symbol('o', odd=True) + i2 = Symbol('2', prime=True, even=True) + + assert (k/3).is_integer is None + assert (nz/3).is_integer is None + assert (nr/3).is_integer is False + assert (ir/3).is_integer is False + assert (x*k*n).is_integer is None + assert (e/2).is_integer is True + assert (e**2/2).is_integer is True + assert (2/k).is_integer is None + assert (2/k**2).is_integer is None + assert ((-1)**k*n).is_integer is True + assert (3*k*e/2).is_integer is True + assert (2*k*e/3).is_integer is None + assert (e/o).is_integer is None + assert (o/e).is_integer is False + assert (o/i2).is_integer is False + assert Mul(k, 1/k, evaluate=False).is_integer is None + assert Mul(2., S.Half, evaluate=False).is_integer is None + assert (2*sqrt(k)).is_integer is None + assert (2*k**n).is_integer is None + + s = 2**2**2**Pow(2, 1000, evaluate=False) + m = Mul(s, s, evaluate=False) + assert m.is_integer + + # broken in 1.6 and before, see #20161 + xq = Symbol('xq', rational=True) + yq = Symbol('yq', rational=True) + assert (xq*yq).is_integer is None + e_20161 = Mul(-1,Mul(1,Pow(2,-1,evaluate=False),evaluate=False),evaluate=False) + assert e_20161.is_integer is not True # expand(e_20161) -> -1/2, but no need to see that in the assumption without evaluation + + +def test_Add_Mul_is_integer(): + x = Symbol('x') + + k = Symbol('k', integer=True) + n = Symbol('n', integer=True) + nk = Symbol('nk', integer=False) + nr = Symbol('nr', rational=False) + nz = Symbol('nz', integer=True, zero=False) + + assert (-nk).is_integer is None + assert (-nr).is_integer is False + assert (2*k).is_integer is True + assert (-k).is_integer is True + + assert (k + nk).is_integer is False + assert (k + n).is_integer is True + assert (k + x).is_integer is None + assert (k + n*x).is_integer is None + assert (k + n/3).is_integer is None + assert (k + nz/3).is_integer is None + assert (k + nr/3).is_integer is False + + assert ((1 + sqrt(3))*(-sqrt(3) + 1)).is_integer is not False + assert (1 + (1 + sqrt(3))*(-sqrt(3) + 1)).is_integer is not False + + +def test_Add_Mul_is_finite(): + x = Symbol('x', extended_real=True, finite=False) + + assert sin(x).is_finite is True + assert (x*sin(x)).is_finite is None + assert (x*atan(x)).is_finite is False + assert (1024*sin(x)).is_finite is True + assert (sin(x)*exp(x)).is_finite is None + assert (sin(x)*cos(x)).is_finite is True + assert (x*sin(x)*exp(x)).is_finite is None + + assert (sin(x) - 67).is_finite is True + assert (sin(x) + exp(x)).is_finite is not True + assert (1 + x).is_finite is False + assert (1 + x**2 + (1 + x)*(1 - x)).is_finite is None + assert (sqrt(2)*(1 + x)).is_finite is False + assert (sqrt(2)*(1 + x)*(1 - x)).is_finite is False + + +def test_Mul_is_even_odd(): + x = Symbol('x', integer=True) + y = Symbol('y', integer=True) + + k = Symbol('k', odd=True) + n = Symbol('n', odd=True) + m = Symbol('m', even=True) + + assert (2*x).is_even is True + assert (2*x).is_odd is False + + assert (3*x).is_even is None + assert (3*x).is_odd is None + + assert (k/3).is_integer is None + assert (k/3).is_even is None + assert (k/3).is_odd is None + + assert (2*n).is_even is True + assert (2*n).is_odd is False + + assert (2*m).is_even is True + assert (2*m).is_odd is False + + assert (-n).is_even is False + assert (-n).is_odd is True + + assert (k*n).is_even is False + assert (k*n).is_odd is True + + assert (k*m).is_even is True + assert (k*m).is_odd is False + + assert (k*n*m).is_even is True + assert (k*n*m).is_odd is False + + assert (k*m*x).is_even is True + assert (k*m*x).is_odd is False + + # issue 6791: + assert (x/2).is_integer is None + assert (k/2).is_integer is False + assert (m/2).is_integer is True + + assert (x*y).is_even is None + assert (x*x).is_even is None + assert (x*(x + k)).is_even is True + assert (x*(x + m)).is_even is None + + assert (x*y).is_odd is None + assert (x*x).is_odd is None + assert (x*(x + k)).is_odd is False + assert (x*(x + m)).is_odd is None + + # issue 8648 + assert (m**2/2).is_even + assert (m**2/3).is_even is False + assert (2/m**2).is_odd is False + assert (2/m).is_odd is None + + +@XFAIL +def test_evenness_in_ternary_integer_product_with_odd(): + # Tests that oddness inference is independent of term ordering. + # Term ordering at the point of testing depends on SymPy's symbol order, so + # we try to force a different order by modifying symbol names. + x = Symbol('x', integer=True) + y = Symbol('y', integer=True) + k = Symbol('k', odd=True) + assert (x*y*(y + k)).is_even is True + assert (y*x*(x + k)).is_even is True + + +def test_evenness_in_ternary_integer_product_with_even(): + x = Symbol('x', integer=True) + y = Symbol('y', integer=True) + m = Symbol('m', even=True) + assert (x*y*(y + m)).is_even is None + + +@XFAIL +def test_oddness_in_ternary_integer_product_with_odd(): + # Tests that oddness inference is independent of term ordering. + # Term ordering at the point of testing depends on SymPy's symbol order, so + # we try to force a different order by modifying symbol names. + x = Symbol('x', integer=True) + y = Symbol('y', integer=True) + k = Symbol('k', odd=True) + assert (x*y*(y + k)).is_odd is False + assert (y*x*(x + k)).is_odd is False + + +def test_oddness_in_ternary_integer_product_with_even(): + x = Symbol('x', integer=True) + y = Symbol('y', integer=True) + m = Symbol('m', even=True) + assert (x*y*(y + m)).is_odd is None + + +def test_Mul_is_rational(): + x = Symbol('x') + n = Symbol('n', integer=True) + m = Symbol('m', integer=True, nonzero=True) + + assert (n/m).is_rational is True + assert (x/pi).is_rational is None + assert (x/n).is_rational is None + assert (m/pi).is_rational is False + + r = Symbol('r', rational=True) + assert (pi*r).is_rational is None + + # issue 8008 + z = Symbol('z', zero=True) + i = Symbol('i', imaginary=True) + assert (z*i).is_rational is True + bi = Symbol('i', imaginary=True, finite=True) + assert (z*bi).is_zero is True + + +def test_Add_is_rational(): + x = Symbol('x') + n = Symbol('n', rational=True) + m = Symbol('m', rational=True) + + assert (n + m).is_rational is True + assert (x + pi).is_rational is None + assert (x + n).is_rational is None + assert (n + pi).is_rational is False + + +def test_Add_is_even_odd(): + x = Symbol('x', integer=True) + + k = Symbol('k', odd=True) + n = Symbol('n', odd=True) + m = Symbol('m', even=True) + + assert (k + 7).is_even is True + assert (k + 7).is_odd is False + + assert (-k + 7).is_even is True + assert (-k + 7).is_odd is False + + assert (k - 12).is_even is False + assert (k - 12).is_odd is True + + assert (-k - 12).is_even is False + assert (-k - 12).is_odd is True + + assert (k + n).is_even is True + assert (k + n).is_odd is False + + assert (k + m).is_even is False + assert (k + m).is_odd is True + + assert (k + n + m).is_even is True + assert (k + n + m).is_odd is False + + assert (k + n + x + m).is_even is None + assert (k + n + x + m).is_odd is None + + +def test_Mul_is_negative_positive(): + x = Symbol('x', real=True) + y = Symbol('y', extended_real=False, complex=True) + z = Symbol('z', zero=True) + + e = 2*z + assert e.is_Mul and e.is_positive is False and e.is_negative is False + + neg = Symbol('neg', negative=True) + pos = Symbol('pos', positive=True) + nneg = Symbol('nneg', nonnegative=True) + npos = Symbol('npos', nonpositive=True) + + assert neg.is_negative is True + assert (-neg).is_negative is False + assert (2*neg).is_negative is True + + assert (2*pos)._eval_is_extended_negative() is False + assert (2*pos).is_negative is False + + assert pos.is_negative is False + assert (-pos).is_negative is True + assert (2*pos).is_negative is False + + assert (pos*neg).is_negative is True + assert (2*pos*neg).is_negative is True + assert (-pos*neg).is_negative is False + assert (pos*neg*y).is_negative is False # y.is_real=F; !real -> !neg + + assert nneg.is_negative is False + assert (-nneg).is_negative is None + assert (2*nneg).is_negative is False + + assert npos.is_negative is None + assert (-npos).is_negative is False + assert (2*npos).is_negative is None + + assert (nneg*npos).is_negative is None + + assert (neg*nneg).is_negative is None + assert (neg*npos).is_negative is False + + assert (pos*nneg).is_negative is False + assert (pos*npos).is_negative is None + + assert (npos*neg*nneg).is_negative is False + assert (npos*pos*nneg).is_negative is None + + assert (-npos*neg*nneg).is_negative is None + assert (-npos*pos*nneg).is_negative is False + + assert (17*npos*neg*nneg).is_negative is False + assert (17*npos*pos*nneg).is_negative is None + + assert (neg*npos*pos*nneg).is_negative is False + + assert (x*neg).is_negative is None + assert (nneg*npos*pos*x*neg).is_negative is None + + assert neg.is_positive is False + assert (-neg).is_positive is True + assert (2*neg).is_positive is False + + assert pos.is_positive is True + assert (-pos).is_positive is False + assert (2*pos).is_positive is True + + assert (pos*neg).is_positive is False + assert (2*pos*neg).is_positive is False + assert (-pos*neg).is_positive is True + assert (-pos*neg*y).is_positive is False # y.is_real=F; !real -> !neg + + assert nneg.is_positive is None + assert (-nneg).is_positive is False + assert (2*nneg).is_positive is None + + assert npos.is_positive is False + assert (-npos).is_positive is None + assert (2*npos).is_positive is False + + assert (nneg*npos).is_positive is False + + assert (neg*nneg).is_positive is False + assert (neg*npos).is_positive is None + + assert (pos*nneg).is_positive is None + assert (pos*npos).is_positive is False + + assert (npos*neg*nneg).is_positive is None + assert (npos*pos*nneg).is_positive is False + + assert (-npos*neg*nneg).is_positive is False + assert (-npos*pos*nneg).is_positive is None + + assert (17*npos*neg*nneg).is_positive is None + assert (17*npos*pos*nneg).is_positive is False + + assert (neg*npos*pos*nneg).is_positive is None + + assert (x*neg).is_positive is None + assert (nneg*npos*pos*x*neg).is_positive is None + + +def test_Mul_is_negative_positive_2(): + a = Symbol('a', nonnegative=True) + b = Symbol('b', nonnegative=True) + c = Symbol('c', nonpositive=True) + d = Symbol('d', nonpositive=True) + + assert (a*b).is_nonnegative is True + assert (a*b).is_negative is False + assert (a*b).is_zero is None + assert (a*b).is_positive is None + + assert (c*d).is_nonnegative is True + assert (c*d).is_negative is False + assert (c*d).is_zero is None + assert (c*d).is_positive is None + + assert (a*c).is_nonpositive is True + assert (a*c).is_positive is False + assert (a*c).is_zero is None + assert (a*c).is_negative is None + + +def test_Mul_is_nonpositive_nonnegative(): + x = Symbol('x', real=True) + + k = Symbol('k', negative=True) + n = Symbol('n', positive=True) + u = Symbol('u', nonnegative=True) + v = Symbol('v', nonpositive=True) + + assert k.is_nonpositive is True + assert (-k).is_nonpositive is False + assert (2*k).is_nonpositive is True + + assert n.is_nonpositive is False + assert (-n).is_nonpositive is True + assert (2*n).is_nonpositive is False + + assert (n*k).is_nonpositive is True + assert (2*n*k).is_nonpositive is True + assert (-n*k).is_nonpositive is False + + assert u.is_nonpositive is None + assert (-u).is_nonpositive is True + assert (2*u).is_nonpositive is None + + assert v.is_nonpositive is True + assert (-v).is_nonpositive is None + assert (2*v).is_nonpositive is True + + assert (u*v).is_nonpositive is True + + assert (k*u).is_nonpositive is True + assert (k*v).is_nonpositive is None + + assert (n*u).is_nonpositive is None + assert (n*v).is_nonpositive is True + + assert (v*k*u).is_nonpositive is None + assert (v*n*u).is_nonpositive is True + + assert (-v*k*u).is_nonpositive is True + assert (-v*n*u).is_nonpositive is None + + assert (17*v*k*u).is_nonpositive is None + assert (17*v*n*u).is_nonpositive is True + + assert (k*v*n*u).is_nonpositive is None + + assert (x*k).is_nonpositive is None + assert (u*v*n*x*k).is_nonpositive is None + + assert k.is_nonnegative is False + assert (-k).is_nonnegative is True + assert (2*k).is_nonnegative is False + + assert n.is_nonnegative is True + assert (-n).is_nonnegative is False + assert (2*n).is_nonnegative is True + + assert (n*k).is_nonnegative is False + assert (2*n*k).is_nonnegative is False + assert (-n*k).is_nonnegative is True + + assert u.is_nonnegative is True + assert (-u).is_nonnegative is None + assert (2*u).is_nonnegative is True + + assert v.is_nonnegative is None + assert (-v).is_nonnegative is True + assert (2*v).is_nonnegative is None + + assert (u*v).is_nonnegative is None + + assert (k*u).is_nonnegative is None + assert (k*v).is_nonnegative is True + + assert (n*u).is_nonnegative is True + assert (n*v).is_nonnegative is None + + assert (v*k*u).is_nonnegative is True + assert (v*n*u).is_nonnegative is None + + assert (-v*k*u).is_nonnegative is None + assert (-v*n*u).is_nonnegative is True + + assert (17*v*k*u).is_nonnegative is True + assert (17*v*n*u).is_nonnegative is None + + assert (k*v*n*u).is_nonnegative is True + + assert (x*k).is_nonnegative is None + assert (u*v*n*x*k).is_nonnegative is None + + +def test_Add_is_negative_positive(): + x = Symbol('x', real=True) + + k = Symbol('k', negative=True) + n = Symbol('n', positive=True) + u = Symbol('u', nonnegative=True) + v = Symbol('v', nonpositive=True) + + assert (k - 2).is_negative is True + assert (k + 17).is_negative is None + assert (-k - 5).is_negative is None + assert (-k + 123).is_negative is False + + assert (k - n).is_negative is True + assert (k + n).is_negative is None + assert (-k - n).is_negative is None + assert (-k + n).is_negative is False + + assert (k - n - 2).is_negative is True + assert (k + n + 17).is_negative is None + assert (-k - n - 5).is_negative is None + assert (-k + n + 123).is_negative is False + + assert (-2*k + 123*n + 17).is_negative is False + + assert (k + u).is_negative is None + assert (k + v).is_negative is True + assert (n + u).is_negative is False + assert (n + v).is_negative is None + + assert (u - v).is_negative is False + assert (u + v).is_negative is None + assert (-u - v).is_negative is None + assert (-u + v).is_negative is None + + assert (u - v + n + 2).is_negative is False + assert (u + v + n + 2).is_negative is None + assert (-u - v + n + 2).is_negative is None + assert (-u + v + n + 2).is_negative is None + + assert (k + x).is_negative is None + assert (k + x - n).is_negative is None + + assert (k - 2).is_positive is False + assert (k + 17).is_positive is None + assert (-k - 5).is_positive is None + assert (-k + 123).is_positive is True + + assert (k - n).is_positive is False + assert (k + n).is_positive is None + assert (-k - n).is_positive is None + assert (-k + n).is_positive is True + + assert (k - n - 2).is_positive is False + assert (k + n + 17).is_positive is None + assert (-k - n - 5).is_positive is None + assert (-k + n + 123).is_positive is True + + assert (-2*k + 123*n + 17).is_positive is True + + assert (k + u).is_positive is None + assert (k + v).is_positive is False + assert (n + u).is_positive is True + assert (n + v).is_positive is None + + assert (u - v).is_positive is None + assert (u + v).is_positive is None + assert (-u - v).is_positive is None + assert (-u + v).is_positive is False + + assert (u - v - n - 2).is_positive is None + assert (u + v - n - 2).is_positive is None + assert (-u - v - n - 2).is_positive is None + assert (-u + v - n - 2).is_positive is False + + assert (n + x).is_positive is None + assert (n + x - k).is_positive is None + + z = (-3 - sqrt(5) + (-sqrt(10)/2 - sqrt(2)/2)**2) + assert z.is_zero + z = sqrt(1 + sqrt(3)) + sqrt(3 + 3*sqrt(3)) - sqrt(10 + 6*sqrt(3)) + assert z.is_zero + + +def test_Add_is_nonpositive_nonnegative(): + x = Symbol('x', real=True) + + k = Symbol('k', negative=True) + n = Symbol('n', positive=True) + u = Symbol('u', nonnegative=True) + v = Symbol('v', nonpositive=True) + + assert (u - 2).is_nonpositive is None + assert (u + 17).is_nonpositive is False + assert (-u - 5).is_nonpositive is True + assert (-u + 123).is_nonpositive is None + + assert (u - v).is_nonpositive is None + assert (u + v).is_nonpositive is None + assert (-u - v).is_nonpositive is None + assert (-u + v).is_nonpositive is True + + assert (u - v - 2).is_nonpositive is None + assert (u + v + 17).is_nonpositive is None + assert (-u - v - 5).is_nonpositive is None + assert (-u + v - 123).is_nonpositive is True + + assert (-2*u + 123*v - 17).is_nonpositive is True + + assert (k + u).is_nonpositive is None + assert (k + v).is_nonpositive is True + assert (n + u).is_nonpositive is False + assert (n + v).is_nonpositive is None + + assert (k - n).is_nonpositive is True + assert (k + n).is_nonpositive is None + assert (-k - n).is_nonpositive is None + assert (-k + n).is_nonpositive is False + + assert (k - n + u + 2).is_nonpositive is None + assert (k + n + u + 2).is_nonpositive is None + assert (-k - n + u + 2).is_nonpositive is None + assert (-k + n + u + 2).is_nonpositive is False + + assert (u + x).is_nonpositive is None + assert (v - x - n).is_nonpositive is None + + assert (u - 2).is_nonnegative is None + assert (u + 17).is_nonnegative is True + assert (-u - 5).is_nonnegative is False + assert (-u + 123).is_nonnegative is None + + assert (u - v).is_nonnegative is True + assert (u + v).is_nonnegative is None + assert (-u - v).is_nonnegative is None + assert (-u + v).is_nonnegative is None + + assert (u - v + 2).is_nonnegative is True + assert (u + v + 17).is_nonnegative is None + assert (-u - v - 5).is_nonnegative is None + assert (-u + v - 123).is_nonnegative is False + + assert (2*u - 123*v + 17).is_nonnegative is True + + assert (k + u).is_nonnegative is None + assert (k + v).is_nonnegative is False + assert (n + u).is_nonnegative is True + assert (n + v).is_nonnegative is None + + assert (k - n).is_nonnegative is False + assert (k + n).is_nonnegative is None + assert (-k - n).is_nonnegative is None + assert (-k + n).is_nonnegative is True + + assert (k - n - u - 2).is_nonnegative is False + assert (k + n - u - 2).is_nonnegative is None + assert (-k - n - u - 2).is_nonnegative is None + assert (-k + n - u - 2).is_nonnegative is None + + assert (u - x).is_nonnegative is None + assert (v + x + n).is_nonnegative is None + + +def test_Pow_is_integer(): + x = Symbol('x') + + k = Symbol('k', integer=True) + n = Symbol('n', integer=True, nonnegative=True) + m = Symbol('m', integer=True, positive=True) + + assert (k**2).is_integer is True + assert (k**(-2)).is_integer is None + assert ((m + 1)**(-2)).is_integer is False + assert (m**(-1)).is_integer is None # issue 8580 + + assert (2**k).is_integer is None + assert (2**(-k)).is_integer is None + + assert (2**n).is_integer is True + assert (2**(-n)).is_integer is None + + assert (2**m).is_integer is True + assert (2**(-m)).is_integer is False + + assert (x**2).is_integer is None + assert (2**x).is_integer is None + + assert (k**n).is_integer is True + assert (k**(-n)).is_integer is None + + assert (k**x).is_integer is None + assert (x**k).is_integer is None + + assert (k**(n*m)).is_integer is True + assert (k**(-n*m)).is_integer is None + + assert sqrt(3).is_integer is False + assert sqrt(.3).is_integer is False + assert Pow(3, 2, evaluate=False).is_integer is True + assert Pow(3, 0, evaluate=False).is_integer is True + assert Pow(3, -2, evaluate=False).is_integer is False + assert Pow(S.Half, 3, evaluate=False).is_integer is False + # decided by re-evaluating + assert Pow(3, S.Half, evaluate=False).is_integer is False + assert Pow(3, S.Half, evaluate=False).is_integer is False + assert Pow(4, S.Half, evaluate=False).is_integer is True + assert Pow(S.Half, -2, evaluate=False).is_integer is True + + assert ((-1)**k).is_integer + + # issue 8641 + x = Symbol('x', real=True, integer=False) + assert (x**2).is_integer is None + + # issue 10458 + x = Symbol('x', positive=True) + assert (1/(x + 1)).is_integer is False + assert (1/(-x - 1)).is_integer is False + assert (-1/(x + 1)).is_integer is False + # issue 23287 + assert (x**2/2).is_integer is None + + # issue 8648-like + k = Symbol('k', even=True) + assert (k**3/2).is_integer + assert (k**3/8).is_integer + assert (k**3/16).is_integer is None + assert (2/k).is_integer is None + assert (2/k**2).is_integer is False + o = Symbol('o', odd=True) + assert (k/o).is_integer is None + o = Symbol('o', odd=True, prime=True) + assert (k/o).is_integer is False + + +def test_Pow_is_real(): + x = Symbol('x', real=True) + y = Symbol('y', positive=True) + + assert (x**2).is_real is True + assert (x**3).is_real is True + assert (x**x).is_real is None + assert (y**x).is_real is True + + assert (x**Rational(1, 3)).is_real is None + assert (y**Rational(1, 3)).is_real is True + + assert sqrt(-1 - sqrt(2)).is_real is False + + i = Symbol('i', imaginary=True) + assert (i**i).is_real is None + assert (I**i).is_extended_real is True + assert ((-I)**i).is_extended_real is True + assert (2**i).is_real is None # (2**(pi/log(2) * I)) is real, 2**I is not + assert (2**I).is_real is False + assert (2**-I).is_real is False + assert (i**2).is_extended_real is True + assert (i**3).is_extended_real is False + assert (i**x).is_real is None # could be (-I)**(2/3) + e = Symbol('e', even=True) + o = Symbol('o', odd=True) + k = Symbol('k', integer=True) + assert (i**e).is_extended_real is True + assert (i**o).is_extended_real is False + assert (i**k).is_real is None + assert (i**(4*k)).is_extended_real is True + + x = Symbol("x", nonnegative=True) + y = Symbol("y", nonnegative=True) + assert im(x**y).expand(complex=True) is S.Zero + assert (x**y).is_real is True + i = Symbol('i', imaginary=True) + assert (exp(i)**I).is_extended_real is True + assert log(exp(i)).is_imaginary is None # i could be 2*pi*I + c = Symbol('c', complex=True) + assert log(c).is_real is None # c could be 0 or 2, too + assert log(exp(c)).is_real is None # log(0), log(E), ... + n = Symbol('n', negative=False) + assert log(n).is_real is None + n = Symbol('n', nonnegative=True) + assert log(n).is_real is None + + assert sqrt(-I).is_real is False # issue 7843 + + i = Symbol('i', integer=True) + assert (1/(i-1)).is_real is None + assert (1/(i-1)).is_extended_real is None + + # test issue 20715 + from sympy.core.parameters import evaluate + x = S(-1) + with evaluate(False): + assert x.is_negative is True + + f = Pow(x, -1) + with evaluate(False): + assert f.is_imaginary is False + + +def test_real_Pow(): + k = Symbol('k', integer=True, nonzero=True) + assert (k**(I*pi/log(k))).is_real + + +def test_Pow_is_finite(): + xe = Symbol('xe', extended_real=True) + xr = Symbol('xr', real=True) + p = Symbol('p', positive=True) + n = Symbol('n', negative=True) + i = Symbol('i', integer=True) + + assert (xe**2).is_finite is None # xe could be oo + assert (xr**2).is_finite is True + + assert (xe**xe).is_finite is None + assert (xr**xe).is_finite is None + assert (xe**xr).is_finite is None + # FIXME: The line below should be True rather than None + # assert (xr**xr).is_finite is True + assert (xr**xr).is_finite is None + + assert (p**xe).is_finite is None + assert (p**xr).is_finite is True + + assert (n**xe).is_finite is None + assert (n**xr).is_finite is True + + assert (sin(xe)**2).is_finite is True + assert (sin(xr)**2).is_finite is True + + assert (sin(xe)**xe).is_finite is None # xe, xr could be -pi + assert (sin(xr)**xr).is_finite is None + + # FIXME: Should the line below be True rather than None? + assert (sin(xe)**exp(xe)).is_finite is None + assert (sin(xr)**exp(xr)).is_finite is True + + assert (1/sin(xe)).is_finite is None # if zero, no, otherwise yes + assert (1/sin(xr)).is_finite is None + + assert (1/exp(xe)).is_finite is None # xe could be -oo + assert (1/exp(xr)).is_finite is True + + assert (1/S.Pi).is_finite is True + + assert (1/(i-1)).is_finite is None + + +def test_Pow_is_even_odd(): + x = Symbol('x') + + k = Symbol('k', even=True) + n = Symbol('n', odd=True) + m = Symbol('m', integer=True, nonnegative=True) + p = Symbol('p', integer=True, positive=True) + + assert ((-1)**n).is_odd + assert ((-1)**k).is_odd + assert ((-1)**(m - p)).is_odd + + assert (k**2).is_even is True + assert (n**2).is_even is False + assert (2**k).is_even is None + assert (x**2).is_even is None + + assert (k**m).is_even is None + assert (n**m).is_even is False + + assert (k**p).is_even is True + assert (n**p).is_even is False + + assert (m**k).is_even is None + assert (p**k).is_even is None + + assert (m**n).is_even is None + assert (p**n).is_even is None + + assert (k**x).is_even is None + assert (n**x).is_even is None + + assert (k**2).is_odd is False + assert (n**2).is_odd is True + assert (3**k).is_odd is None + + assert (k**m).is_odd is None + assert (n**m).is_odd is True + + assert (k**p).is_odd is False + assert (n**p).is_odd is True + + assert (m**k).is_odd is None + assert (p**k).is_odd is None + + assert (m**n).is_odd is None + assert (p**n).is_odd is None + + assert (k**x).is_odd is None + assert (n**x).is_odd is None + + +def test_Pow_is_negative_positive(): + r = Symbol('r', real=True) + + k = Symbol('k', integer=True, positive=True) + n = Symbol('n', even=True) + m = Symbol('m', odd=True) + + x = Symbol('x') + + assert (2**r).is_positive is True + assert ((-2)**r).is_positive is None + assert ((-2)**n).is_positive is True + assert ((-2)**m).is_positive is False + + assert (k**2).is_positive is True + assert (k**(-2)).is_positive is True + + assert (k**r).is_positive is True + assert ((-k)**r).is_positive is None + assert ((-k)**n).is_positive is True + assert ((-k)**m).is_positive is False + + assert (2**r).is_negative is False + assert ((-2)**r).is_negative is None + assert ((-2)**n).is_negative is False + assert ((-2)**m).is_negative is True + + assert (k**2).is_negative is False + assert (k**(-2)).is_negative is False + + assert (k**r).is_negative is False + assert ((-k)**r).is_negative is None + assert ((-k)**n).is_negative is False + assert ((-k)**m).is_negative is True + + assert (2**x).is_positive is None + assert (2**x).is_negative is None + + +def test_Pow_is_zero(): + z = Symbol('z', zero=True) + e = z**2 + assert e.is_zero + assert e.is_positive is False + assert e.is_negative is False + + assert Pow(0, 0, evaluate=False).is_zero is False + assert Pow(0, 3, evaluate=False).is_zero + assert Pow(0, oo, evaluate=False).is_zero + assert Pow(0, -3, evaluate=False).is_zero is False + assert Pow(0, -oo, evaluate=False).is_zero is False + assert Pow(2, 2, evaluate=False).is_zero is False + + a = Symbol('a', zero=False) + assert Pow(a, 3).is_zero is False # issue 7965 + + assert Pow(2, oo, evaluate=False).is_zero is False + assert Pow(2, -oo, evaluate=False).is_zero + assert Pow(S.Half, oo, evaluate=False).is_zero + assert Pow(S.Half, -oo, evaluate=False).is_zero is False + + # All combinations of real/complex base/exponent + h = S.Half + T = True + F = False + N = None + + pow_iszero = [ + ['**', 0, h, 1, 2, -h, -1,-2,-2*I,-I/2,I/2,1+I,oo,-oo,zoo], + [ 0, F, T, T, T, F, F, F, F, F, F, N, T, F, N], + [ h, F, F, F, F, F, F, F, F, F, F, F, T, F, N], + [ 1, F, F, F, F, F, F, F, F, F, F, F, F, F, N], + [ 2, F, F, F, F, F, F, F, F, F, F, F, F, T, N], + [ -h, F, F, F, F, F, F, F, F, F, F, F, T, F, N], + [ -1, F, F, F, F, F, F, F, F, F, F, F, F, F, N], + [ -2, F, F, F, F, F, F, F, F, F, F, F, F, T, N], + [-2*I, F, F, F, F, F, F, F, F, F, F, F, F, T, N], + [-I/2, F, F, F, F, F, F, F, F, F, F, F, T, F, N], + [ I/2, F, F, F, F, F, F, F, F, F, F, F, T, F, N], + [ 1+I, F, F, F, F, F, F, F, F, F, F, F, F, T, N], + [ oo, F, F, F, F, T, T, T, F, F, F, F, F, T, N], + [ -oo, F, F, F, F, T, T, T, F, F, F, F, F, T, N], + [ zoo, F, F, F, F, T, T, T, N, N, N, N, F, T, N] + ] + + def test_table(table): + n = len(table[0]) + for row in range(1, n): + base = table[row][0] + for col in range(1, n): + exp = table[0][col] + is_zero = table[row][col] + # The actual test here: + assert Pow(base, exp, evaluate=False).is_zero is is_zero + + test_table(pow_iszero) + + # A zero symbol... + zo, zo2 = symbols('zo, zo2', zero=True) + + # All combinations of finite symbols + zf, zf2 = symbols('zf, zf2', finite=True) + wf, wf2 = symbols('wf, wf2', nonzero=True) + xf, xf2 = symbols('xf, xf2', real=True) + yf, yf2 = symbols('yf, yf2', nonzero=True) + af, af2 = symbols('af, af2', positive=True) + bf, bf2 = symbols('bf, bf2', nonnegative=True) + cf, cf2 = symbols('cf, cf2', negative=True) + df, df2 = symbols('df, df2', nonpositive=True) + + # Without finiteness: + zi, zi2 = symbols('zi, zi2') + wi, wi2 = symbols('wi, wi2', zero=False) + xi, xi2 = symbols('xi, xi2', extended_real=True) + yi, yi2 = symbols('yi, yi2', zero=False, extended_real=True) + ai, ai2 = symbols('ai, ai2', extended_positive=True) + bi, bi2 = symbols('bi, bi2', extended_nonnegative=True) + ci, ci2 = symbols('ci, ci2', extended_negative=True) + di, di2 = symbols('di, di2', extended_nonpositive=True) + + pow_iszero_sym = [ + ['**',zo,wf,yf,af,cf,zf,xf,bf,df,zi,wi,xi,yi,ai,bi,ci,di], + [ zo2, F, N, N, T, F, N, N, N, F, N, N, N, N, T, N, F, F], + [ wf2, F, F, F, F, F, F, F, F, F, N, N, N, N, N, N, N, N], + [ yf2, F, F, F, F, F, F, F, F, F, N, N, N, N, N, N, N, N], + [ af2, F, F, F, F, F, F, F, F, F, N, N, N, N, N, N, N, N], + [ cf2, F, F, F, F, F, F, F, F, F, N, N, N, N, N, N, N, N], + [ zf2, N, N, N, N, F, N, N, N, N, N, N, N, N, N, N, N, N], + [ xf2, N, N, N, N, F, N, N, N, N, N, N, N, N, N, N, N, N], + [ bf2, N, N, N, N, F, N, N, N, N, N, N, N, N, N, N, N, N], + [ df2, N, N, N, N, F, N, N, N, N, N, N, N, N, N, N, N, N], + [ zi2, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N], + [ wi2, F, N, N, F, N, N, N, F, N, N, N, N, N, N, N, N, N], + [ xi2, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N], + [ yi2, F, N, N, F, N, N, N, F, N, N, N, N, N, N, N, N, N], + [ ai2, F, N, N, F, N, N, N, F, N, N, N, N, N, N, N, N, N], + [ bi2, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N], + [ ci2, F, N, N, F, N, N, N, F, N, N, N, N, N, N, N, N, N], + [ di2, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N] + ] + + test_table(pow_iszero_sym) + + # In some cases (x**x).is_zero is different from (x**y).is_zero even if y + # has the same assumptions as x. + assert (zo ** zo).is_zero is False + assert (wf ** wf).is_zero is False + assert (yf ** yf).is_zero is False + assert (af ** af).is_zero is False + assert (cf ** cf).is_zero is False + assert (zf ** zf).is_zero is None + assert (xf ** xf).is_zero is None + assert (bf ** bf).is_zero is False # None in table + assert (df ** df).is_zero is None + assert (zi ** zi).is_zero is None + assert (wi ** wi).is_zero is None + assert (xi ** xi).is_zero is None + assert (yi ** yi).is_zero is None + assert (ai ** ai).is_zero is False # None in table + assert (bi ** bi).is_zero is False # None in table + assert (ci ** ci).is_zero is None + assert (di ** di).is_zero is None + + +def test_Pow_is_nonpositive_nonnegative(): + x = Symbol('x', real=True) + + k = Symbol('k', integer=True, nonnegative=True) + l = Symbol('l', integer=True, positive=True) + n = Symbol('n', even=True) + m = Symbol('m', odd=True) + + assert (x**(4*k)).is_nonnegative is True + assert (2**x).is_nonnegative is True + assert ((-2)**x).is_nonnegative is None + assert ((-2)**n).is_nonnegative is True + assert ((-2)**m).is_nonnegative is False + + assert (k**2).is_nonnegative is True + assert (k**(-2)).is_nonnegative is None + assert (k**k).is_nonnegative is True + + assert (k**x).is_nonnegative is None # NOTE (0**x).is_real = U + assert (l**x).is_nonnegative is True + assert (l**x).is_positive is True + assert ((-k)**x).is_nonnegative is None + + assert ((-k)**m).is_nonnegative is None + + assert (2**x).is_nonpositive is False + assert ((-2)**x).is_nonpositive is None + assert ((-2)**n).is_nonpositive is False + assert ((-2)**m).is_nonpositive is True + + assert (k**2).is_nonpositive is None + assert (k**(-2)).is_nonpositive is None + + assert (k**x).is_nonpositive is None + assert ((-k)**x).is_nonpositive is None + assert ((-k)**n).is_nonpositive is None + + + assert (x**2).is_nonnegative is True + i = symbols('i', imaginary=True) + assert (i**2).is_nonpositive is True + assert (i**4).is_nonpositive is False + assert (i**3).is_nonpositive is False + assert (I**i).is_nonnegative is True + assert (exp(I)**i).is_nonnegative is True + + assert ((-l)**n).is_nonnegative is True + assert ((-l)**m).is_nonpositive is True + assert ((-k)**n).is_nonnegative is None + assert ((-k)**m).is_nonpositive is None + + +def test_Mul_is_imaginary_real(): + r = Symbol('r', real=True) + p = Symbol('p', positive=True) + i1 = Symbol('i1', imaginary=True) + i2 = Symbol('i2', imaginary=True) + x = Symbol('x') + + assert I.is_imaginary is True + assert I.is_real is False + assert (-I).is_imaginary is True + assert (-I).is_real is False + assert (3*I).is_imaginary is True + assert (3*I).is_real is False + assert (I*I).is_imaginary is False + assert (I*I).is_real is True + + e = (p + p*I) + j = Symbol('j', integer=True, zero=False) + assert (e**j).is_real is None + assert (e**(2*j)).is_real is None + assert (e**j).is_imaginary is None + assert (e**(2*j)).is_imaginary is None + + assert (e**-1).is_imaginary is False + assert (e**2).is_imaginary + assert (e**3).is_imaginary is False + assert (e**4).is_imaginary is False + assert (e**5).is_imaginary is False + assert (e**-1).is_real is False + assert (e**2).is_real is False + assert (e**3).is_real is False + assert (e**4).is_real is True + assert (e**5).is_real is False + assert (e**3).is_complex + + assert (r*i1).is_imaginary is None + assert (r*i1).is_real is None + + assert (x*i1).is_imaginary is None + assert (x*i1).is_real is None + + assert (i1*i2).is_imaginary is False + assert (i1*i2).is_real is True + + assert (r*i1*i2).is_imaginary is False + assert (r*i1*i2).is_real is True + + # Github's issue 5874: + nr = Symbol('nr', real=False, complex=True) # e.g. I or 1 + I + a = Symbol('a', real=True, nonzero=True) + b = Symbol('b', real=True) + assert (i1*nr).is_real is None + assert (a*nr).is_real is False + assert (b*nr).is_real is None + + ni = Symbol('ni', imaginary=False, complex=True) # e.g. 2 or 1 + I + a = Symbol('a', real=True, nonzero=True) + b = Symbol('b', real=True) + assert (i1*ni).is_real is False + assert (a*ni).is_real is None + assert (b*ni).is_real is None + + +def test_Mul_hermitian_antihermitian(): + xz, yz = symbols('xz, yz', zero=True, antihermitian=True) + xf, yf = symbols('xf, yf', hermitian=False, antihermitian=False, finite=True) + xh, yh = symbols('xh, yh', hermitian=True, antihermitian=False, nonzero=True) + xa, ya = symbols('xa, ya', hermitian=False, antihermitian=True, zero=False, finite=True) + assert (xz*xh).is_hermitian is True + assert (xz*xh).is_antihermitian is True + assert (xz*xa).is_hermitian is True + assert (xz*xa).is_antihermitian is True + assert (xf*yf).is_hermitian is None + assert (xf*yf).is_antihermitian is None + assert (xh*yh).is_hermitian is True + assert (xh*yh).is_antihermitian is False + assert (xh*ya).is_hermitian is False + assert (xh*ya).is_antihermitian is True + assert (xa*ya).is_hermitian is True + assert (xa*ya).is_antihermitian is False + + a = Symbol('a', hermitian=True, zero=False) + b = Symbol('b', hermitian=True) + c = Symbol('c', hermitian=False) + d = Symbol('d', antihermitian=True) + e1 = Mul(a, b, c, evaluate=False) + e2 = Mul(b, a, c, evaluate=False) + e3 = Mul(a, b, c, d, evaluate=False) + e4 = Mul(b, a, c, d, evaluate=False) + e5 = Mul(a, c, evaluate=False) + e6 = Mul(a, c, d, evaluate=False) + assert e1.is_hermitian is None + assert e2.is_hermitian is None + assert e1.is_antihermitian is None + assert e2.is_antihermitian is None + assert e3.is_antihermitian is None + assert e4.is_antihermitian is None + assert e5.is_antihermitian is None + assert e6.is_antihermitian is None + + +def test_Add_is_comparable(): + assert (x + y).is_comparable is False + assert (x + 1).is_comparable is False + assert (Rational(1, 3) - sqrt(8)).is_comparable is True + + +def test_Mul_is_comparable(): + assert (x*y).is_comparable is False + assert (x*2).is_comparable is False + assert (sqrt(2)*Rational(1, 3)).is_comparable is True + + +def test_Pow_is_comparable(): + assert (x**y).is_comparable is False + assert (x**2).is_comparable is False + assert (sqrt(Rational(1, 3))).is_comparable is True + + +def test_Add_is_positive_2(): + e = Rational(1, 3) - sqrt(8) + assert e.is_positive is False + assert e.is_negative is True + + e = pi - 1 + assert e.is_positive is True + assert e.is_negative is False + + +def test_Add_is_irrational(): + i = Symbol('i', irrational=True) + + assert i.is_irrational is True + assert i.is_rational is False + + assert (i + 1).is_irrational is True + assert (i + 1).is_rational is False + + +def test_Mul_is_irrational(): + expr = Mul(1, 2, 3, evaluate=False) + assert expr.is_irrational is False + expr = Mul(1, I, I, evaluate=False) + assert expr.is_rational is None # I * I = -1 but *no evaluation allowed* + # sqrt(2) * I * I = -sqrt(2) is irrational but + # this can't be determined without evaluating the + # expression and the eval_is routines shouldn't do that + expr = Mul(sqrt(2), I, I, evaluate=False) + assert expr.is_irrational is None + + +def test_issue_3531(): + # https://github.com/sympy/sympy/issues/3531 + # https://github.com/sympy/sympy/pull/18116 + class MightyNumeric(tuple): + def __rtruediv__(self, other): + return "something" + + assert sympify(1)/MightyNumeric((1, 2)) == "something" + + +def test_issue_3531b(): + class Foo: + def __init__(self): + self.field = 1.0 + + def __mul__(self, other): + self.field = self.field * other + + def __rmul__(self, other): + self.field = other * self.field + f = Foo() + x = Symbol("x") + assert f*x == x*f + + +def test_bug3(): + a = Symbol("a") + b = Symbol("b", positive=True) + e = 2*a + b + f = b + 2*a + assert e == f + + +def test_suppressed_evaluation(): + a = Add(0, 3, 2, evaluate=False) + b = Mul(1, 3, 2, evaluate=False) + c = Pow(3, 2, evaluate=False) + assert a != 6 + assert a.func is Add + assert a.args == (0, 3, 2) + assert b != 6 + assert b.func is Mul + assert b.args == (1, 3, 2) + assert c != 9 + assert c.func is Pow + assert c.args == (3, 2) + + +def test_AssocOp_doit(): + a = Add(x,x, evaluate=False) + b = Mul(y,y, evaluate=False) + c = Add(b,b, evaluate=False) + d = Mul(a,a, evaluate=False) + assert c.doit(deep=False).func == Mul + assert c.doit(deep=False).args == (2,y,y) + assert c.doit().func == Mul + assert c.doit().args == (2, Pow(y,2)) + assert d.doit(deep=False).func == Pow + assert d.doit(deep=False).args == (a, 2*S.One) + assert d.doit().func == Mul + assert d.doit().args == (4*S.One, Pow(x,2)) + + +def test_Add_Mul_Expr_args(): + nonexpr = [Basic(), Poly(x, x), FiniteSet(x)] + for typ in [Add, Mul]: + for obj in nonexpr: + # The cache can mess with the stacklevel check + with warns(SymPyDeprecationWarning, test_stacklevel=False): + typ(obj, 1) + + +def test_Add_as_coeff_mul(): + # issue 5524. These should all be (1, self) + assert (x + 1).as_coeff_mul() == (1, (x + 1,)) + assert (x + 2).as_coeff_mul() == (1, (x + 2,)) + assert (x + 3).as_coeff_mul() == (1, (x + 3,)) + + assert (x - 1).as_coeff_mul() == (1, (x - 1,)) + assert (x - 2).as_coeff_mul() == (1, (x - 2,)) + assert (x - 3).as_coeff_mul() == (1, (x - 3,)) + + n = Symbol('n', integer=True) + assert (n + 1).as_coeff_mul() == (1, (n + 1,)) + assert (n + 2).as_coeff_mul() == (1, (n + 2,)) + assert (n + 3).as_coeff_mul() == (1, (n + 3,)) + + assert (n - 1).as_coeff_mul() == (1, (n - 1,)) + assert (n - 2).as_coeff_mul() == (1, (n - 2,)) + assert (n - 3).as_coeff_mul() == (1, (n - 3,)) + + +def test_Pow_as_coeff_mul_doesnt_expand(): + assert exp(x + y).as_coeff_mul() == (1, (exp(x + y),)) + assert exp(x + exp(x + y)) != exp(x + exp(x)*exp(y)) + +def test_issue_24751(): + expr = Add(-2, -3, evaluate=False) + expr1 = Add(-1, expr, evaluate=False) + assert int(expr1) == int((-3 - 2) - 1) + + +def test_issue_3514_18626(): + assert sqrt(S.Half) * sqrt(6) == 2 * sqrt(3)/2 + assert S.Half*sqrt(6)*sqrt(2) == sqrt(3) + assert sqrt(6)/2*sqrt(2) == sqrt(3) + assert sqrt(6)*sqrt(2)/2 == sqrt(3) + assert sqrt(8)**Rational(2, 3) == 2 + + +def test_make_args(): + assert Add.make_args(x) == (x,) + assert Mul.make_args(x) == (x,) + + assert Add.make_args(x*y*z) == (x*y*z,) + assert Mul.make_args(x*y*z) == (x*y*z).args + + assert Add.make_args(x + y + z) == (x + y + z).args + assert Mul.make_args(x + y + z) == (x + y + z,) + + assert Add.make_args((x + y)**z) == ((x + y)**z,) + assert Mul.make_args((x + y)**z) == ((x + y)**z,) + + +def test_issue_5126(): + assert (-2)**x*(-3)**x != 6**x + i = Symbol('i', integer=1) + assert (-2)**i*(-3)**i == 6**i + + +def test_Rational_as_content_primitive(): + c, p = S.One, S.Zero + assert (c*p).as_content_primitive() == (c, p) + c, p = S.Half, S.One + assert (c*p).as_content_primitive() == (c, p) + + +def test_Add_as_content_primitive(): + assert (x + 2).as_content_primitive() == (1, x + 2) + + assert (3*x + 2).as_content_primitive() == (1, 3*x + 2) + assert (3*x + 3).as_content_primitive() == (3, x + 1) + assert (3*x + 6).as_content_primitive() == (3, x + 2) + + assert (3*x + 2*y).as_content_primitive() == (1, 3*x + 2*y) + assert (3*x + 3*y).as_content_primitive() == (3, x + y) + assert (3*x + 6*y).as_content_primitive() == (3, x + 2*y) + + assert (3/x + 2*x*y*z**2).as_content_primitive() == (1, 3/x + 2*x*y*z**2) + assert (3/x + 3*x*y*z**2).as_content_primitive() == (3, 1/x + x*y*z**2) + assert (3/x + 6*x*y*z**2).as_content_primitive() == (3, 1/x + 2*x*y*z**2) + + assert (2*x/3 + 4*y/9).as_content_primitive() == \ + (Rational(2, 9), 3*x + 2*y) + assert (2*x/3 + 2.5*y).as_content_primitive() == \ + (Rational(1, 3), 2*x + 7.5*y) + + # the coefficient may sort to a position other than 0 + p = 3 + x + y + assert (2*p).expand().as_content_primitive() == (2, p) + assert (2.0*p).expand().as_content_primitive() == (1, 2.*p) + p *= -1 + assert (2*p).expand().as_content_primitive() == (2, p) + + +def test_Mul_as_content_primitive(): + assert (2*x).as_content_primitive() == (2, x) + assert (x*(2 + 2*x)).as_content_primitive() == (2, x*(1 + x)) + assert (x*(2 + 2*y)*(3*x + 3)**2).as_content_primitive() == \ + (18, x*(1 + y)*(x + 1)**2) + assert ((2 + 2*x)**2*(3 + 6*x) + S.Half).as_content_primitive() == \ + (S.Half, 24*(x + 1)**2*(2*x + 1) + 1) + + +def test_Pow_as_content_primitive(): + assert (x**y).as_content_primitive() == (1, x**y) + assert ((2*x + 2)**y).as_content_primitive() == \ + (1, (Mul(2, (x + 1), evaluate=False))**y) + assert ((2*x + 2)**3).as_content_primitive() == (8, (x + 1)**3) + + +def test_issue_5460(): + u = Mul(2, (1 + x), evaluate=False) + assert (2 + u).args == (2, u) + + +def test_product_irrational(): + assert (I*pi).is_irrational is False + # The following used to be deduced from the above bug: + assert (I*pi).is_positive is False + + +def test_issue_5919(): + assert (x/(y*(1 + y))).expand() == x/(y**2 + y) + + +def test_Mod(): + assert Mod(x, 1).func is Mod + assert pi % pi is S.Zero + assert Mod(5, 3) == 2 + assert Mod(-5, 3) == 1 + assert Mod(5, -3) == -1 + assert Mod(-5, -3) == -2 + assert type(Mod(3.2, 2, evaluate=False)) == Mod + assert 5 % x == Mod(5, x) + assert x % 5 == Mod(x, 5) + assert x % y == Mod(x, y) + assert (x % y).subs({x: 5, y: 3}) == 2 + assert Mod(nan, 1) is nan + assert Mod(1, nan) is nan + assert Mod(nan, nan) is nan + + assert Mod(0, x) == 0 + with raises(ZeroDivisionError): + Mod(x, 0) + + k = Symbol('k', integer=True) + m = Symbol('m', integer=True, positive=True) + assert (x**m % x).func is Mod + assert (k**(-m) % k).func is Mod + assert k**m % k == 0 + assert (-2*k)**m % k == 0 + + # Float handling + point3 = Float(3.3) % 1 + assert (x - 3.3) % 1 == Mod(1.*x + 1 - point3, 1) + assert Mod(-3.3, 1) == 1 - point3 + assert Mod(0.7, 1) == Float(0.7) + e = Mod(1.3, 1) + assert comp(e, .3) and e.is_Float + e = Mod(1.3, .7) + assert comp(e, .6) and e.is_Float + e = Mod(1.3, Rational(7, 10)) + assert comp(e, .6) and e.is_Float + e = Mod(Rational(13, 10), 0.7) + assert comp(e, .6) and e.is_Float + e = Mod(Rational(13, 10), Rational(7, 10)) + assert comp(e, .6) and e.is_Rational + + # check that sign is right + r2 = sqrt(2) + r3 = sqrt(3) + for i in [-r3, -r2, r2, r3]: + for j in [-r3, -r2, r2, r3]: + assert verify_numerically(i % j, i.n() % j.n()) + for _x in range(4): + for _y in range(9): + reps = [(x, _x), (y, _y)] + assert Mod(3*x + y, 9).subs(reps) == (3*_x + _y) % 9 + + # denesting + t = Symbol('t', real=True) + assert Mod(Mod(x, t), t) == Mod(x, t) + assert Mod(-Mod(x, t), t) == Mod(-x, t) + assert Mod(Mod(x, 2*t), t) == Mod(x, t) + assert Mod(-Mod(x, 2*t), t) == Mod(-x, t) + assert Mod(Mod(x, t), 2*t) == Mod(x, t) + assert Mod(-Mod(x, t), -2*t) == -Mod(x, t) + for i in [-4, -2, 2, 4]: + for j in [-4, -2, 2, 4]: + for k in range(4): + assert Mod(Mod(x, i), j).subs({x: k}) == (k % i) % j + assert Mod(-Mod(x, i), j).subs({x: k}) == -(k % i) % j + + # known difference + assert Mod(5*sqrt(2), sqrt(5)) == 5*sqrt(2) - 3*sqrt(5) + p = symbols('p', positive=True) + assert Mod(2, p + 3) == 2 + assert Mod(-2, p + 3) == p + 1 + assert Mod(2, -p - 3) == -p - 1 + assert Mod(-2, -p - 3) == -2 + assert Mod(p + 5, p + 3) == 2 + assert Mod(-p - 5, p + 3) == p + 1 + assert Mod(p + 5, -p - 3) == -p - 1 + assert Mod(-p - 5, -p - 3) == -2 + assert Mod(p + 1, p - 1).func is Mod + + # handling sums + assert (x + 3) % 1 == Mod(x, 1) + assert (x + 3.0) % 1 == Mod(1.*x, 1) + assert (x - S(33)/10) % 1 == Mod(x + S(7)/10, 1) + + a = Mod(.6*x + y, .3*y) + b = Mod(0.1*y + 0.6*x, 0.3*y) + # Test that a, b are equal, with 1e-14 accuracy in coefficients + eps = 1e-14 + assert abs((a.args[0] - b.args[0]).subs({x: 1, y: 1})) < eps + assert abs((a.args[1] - b.args[1]).subs({x: 1, y: 1})) < eps + + assert (x + 1) % x == 1 % x + assert (x + y) % x == y % x + assert (x + y + 2) % x == (y + 2) % x + assert (a + 3*x + 1) % (2*x) == Mod(a + x + 1, 2*x) + assert (12*x + 18*y) % (3*x) == 3*Mod(6*y, x) + + # gcd extraction + assert (-3*x) % (-2*y) == -Mod(3*x, 2*y) + assert (.6*pi) % (.3*x*pi) == 0.3*pi*Mod(2, x) + assert (.6*pi) % (.31*x*pi) == pi*Mod(0.6, 0.31*x) + assert (6*pi) % (.3*x*pi) == 0.3*pi*Mod(20, x) + assert (6*pi) % (.31*x*pi) == pi*Mod(6, 0.31*x) + assert (6*pi) % (.42*x*pi) == pi*Mod(6, 0.42*x) + assert (12*x) % (2*y) == 2*Mod(6*x, y) + assert (12*x) % (3*5*y) == 3*Mod(4*x, 5*y) + assert (12*x) % (15*x*y) == 3*x*Mod(4, 5*y) + assert (-2*pi) % (3*pi) == pi + assert (2*x + 2) % (x + 1) == 0 + assert (x*(x + 1)) % (x + 1) == (x + 1)*Mod(x, 1) + assert Mod(5.0*x, 0.1*y) == 0.1*Mod(50*x, y) + i = Symbol('i', integer=True) + assert (3*i*x) % (2*i*y) == i*Mod(3*x, 2*y) + assert Mod(4*i, 4) == 0 + + # issue 8677 + n = Symbol('n', integer=True, positive=True) + assert factorial(n) % n == 0 + assert factorial(n + 2) % n == 0 + assert (factorial(n + 4) % (n + 5)).func is Mod + + # Wilson's theorem + assert factorial(18042, evaluate=False) % 18043 == 18042 + p = Symbol('n', prime=True) + assert factorial(p - 1) % p == p - 1 + assert factorial(p - 1) % -p == -1 + assert (factorial(3, evaluate=False) % 4).doit() == 2 + n = Symbol('n', composite=True, odd=True) + assert factorial(n - 1) % n == 0 + + # symbolic with known parity + n = Symbol('n', even=True) + assert Mod(n, 2) == 0 + n = Symbol('n', odd=True) + assert Mod(n, 2) == 1 + + # issue 10963 + assert (x**6000%400).args[1] == 400 + + #issue 13543 + assert Mod(Mod(x + 1, 2) + 1, 2) == Mod(x, 2) + + x1 = Symbol('x1', integer=True) + assert Mod(Mod(x1 + 2, 4)*(x1 + 4), 4) == Mod(x1*(x1 + 2), 4) + assert Mod(Mod(x1 + 2, 4)*4, 4) == 0 + + # issue 15493 + i, j = symbols('i j', integer=True, positive=True) + assert Mod(3*i, 2) == Mod(i, 2) + assert Mod(8*i/j, 4) == 4*Mod(2*i/j, 1) + assert Mod(8*i, 4) == 0 + + # rewrite + assert Mod(x, y).rewrite(floor) == x - y*floor(x/y) + assert ((x - Mod(x, y))/y).rewrite(floor) == floor(x/y) + + # issue 21373 + from sympy.functions.elementary.hyperbolic import sinh + from sympy.functions.elementary.piecewise import Piecewise + + x_r, y_r = symbols('x_r y_r', real=True) + assert (Piecewise((x_r, y_r > x_r), (y_r, True)) / z) % 1 + expr = exp(sinh(Piecewise((x_r, y_r > x_r), (y_r, True)) / z)) + expr.subs({1: 1.0}) + sinh(Piecewise((x_r, y_r > x_r), (y_r, True)) * z ** -1.0).is_zero + + # issue 24215 + from sympy.abc import phi + assert Mod(4.0*Mod(phi, 1) , 2) == 2.0*(Mod(2*(Mod(phi, 1)), 1)) + + xi = symbols('x', integer=True) + assert unchanged(Mod, xi, 2) + assert Mod(3*xi, 2) == Mod(xi, 2) + assert unchanged(Mod, 3*x, 2) + + +def test_Mod_Pow(): + # modular exponentiation + assert isinstance(Mod(Pow(2, 2, evaluate=False), 3), Integer) + + assert Mod(Pow(4, 13, evaluate=False), 497) == Mod(Pow(4, 13), 497) + assert Mod(Pow(2, 10000000000, evaluate=False), 3) == 1 + assert Mod(Pow(32131231232, 9**10**6, evaluate=False),10**12) == \ + pow(32131231232,9**10**6,10**12) + assert Mod(Pow(33284959323, 123**999, evaluate=False),11**13) == \ + pow(33284959323,123**999,11**13) + assert Mod(Pow(78789849597, 333**555, evaluate=False),12**9) == \ + pow(78789849597,333**555,12**9) + + # modular nested exponentiation + expr = Pow(2, 2, evaluate=False) + expr = Pow(2, expr, evaluate=False) + assert Mod(expr, 3**10) == 16 + expr = Pow(2, expr, evaluate=False) + assert Mod(expr, 3**10) == 6487 + expr = Pow(2, expr, evaluate=False) + assert Mod(expr, 3**10) == 32191 + expr = Pow(2, expr, evaluate=False) + assert Mod(expr, 3**10) == 18016 + expr = Pow(2, expr, evaluate=False) + assert Mod(expr, 3**10) == 5137 + + expr = Pow(2, 2, evaluate=False) + expr = Pow(expr, 2, evaluate=False) + assert Mod(expr, 3**10) == 16 + expr = Pow(expr, 2, evaluate=False) + assert Mod(expr, 3**10) == 256 + expr = Pow(expr, 2, evaluate=False) + assert Mod(expr, 3**10) == 6487 + expr = Pow(expr, 2, evaluate=False) + assert Mod(expr, 3**10) == 38281 + expr = Pow(expr, 2, evaluate=False) + assert Mod(expr, 3**10) == 15928 + + expr = Pow(2, 2, evaluate=False) + expr = Pow(expr, expr, evaluate=False) + assert Mod(expr, 3**10) == 256 + expr = Pow(expr, expr, evaluate=False) + assert Mod(expr, 3**10) == 9229 + expr = Pow(expr, expr, evaluate=False) + assert Mod(expr, 3**10) == 25708 + expr = Pow(expr, expr, evaluate=False) + assert Mod(expr, 3**10) == 26608 + expr = Pow(expr, expr, evaluate=False) + # XXX This used to fail in a nondeterministic way because of overflow + # error. + assert Mod(expr, 3**10) == 1966 + + +def test_Mod_is_integer(): + p = Symbol('p', integer=True) + q1 = Symbol('q1', integer=True) + q2 = Symbol('q2', integer=True, nonzero=True) + assert Mod(x, y).is_integer is None + assert Mod(p, q1).is_integer is None + assert Mod(x, q2).is_integer is None + assert Mod(p, q2).is_integer + + +def test_Mod_is_nonposneg(): + n = Symbol('n', integer=True) + k = Symbol('k', integer=True, positive=True) + assert (n%3).is_nonnegative + assert Mod(n, -3).is_nonpositive + assert Mod(n, k).is_nonnegative + assert Mod(n, -k).is_nonpositive + assert Mod(k, n).is_nonnegative is None + + +def test_issue_6001(): + A = Symbol("A", commutative=False) + eq = A + A**2 + # it doesn't matter whether it's True or False; they should + # just all be the same + assert ( + eq.is_commutative == + (eq + 1).is_commutative == + (A + 1).is_commutative) + + B = Symbol("B", commutative=False) + # Although commutative terms could cancel we return True + # meaning "there are non-commutative symbols; aftersubstitution + # that definition can change, e.g. (A*B).subs(B,A**-1) -> 1 + assert (sqrt(2)*A).is_commutative is False + assert (sqrt(2)*A*B).is_commutative is False + + +def test_polar(): + from sympy.functions.elementary.complexes import polar_lift + p = Symbol('p', polar=True) + x = Symbol('x') + assert p.is_polar + assert x.is_polar is None + assert S.One.is_polar is None + assert (p**x).is_polar is True + assert (x**p).is_polar is None + assert ((2*p)**x).is_polar is True + assert (2*p).is_polar is True + assert (-2*p).is_polar is not True + assert (polar_lift(-2)*p).is_polar is True + + q = Symbol('q', polar=True) + assert (p*q)**2 == p**2 * q**2 + assert (2*q)**2 == 4 * q**2 + assert ((p*q)**x).expand() == p**x * q**x + + +def test_issue_6040(): + a, b = Pow(1, 2, evaluate=False), S.One + assert a != b + assert b != a + assert not (a == b) + assert not (b == a) + + +def test_issue_6082(): + # Comparison is symmetric + assert Basic.compare(Max(x, 1), Max(x, 2)) == \ + - Basic.compare(Max(x, 2), Max(x, 1)) + # Equal expressions compare equal + assert Basic.compare(Max(x, 1), Max(x, 1)) == 0 + # Basic subtypes (such as Max) compare different than standard types + assert Basic.compare(Max(1, x), frozenset((1, x))) != 0 + + +def test_issue_6077(): + assert x**2.0/x == x**1.0 + assert x/x**2.0 == x**-1.0 + assert x*x**2.0 == x**3.0 + assert x**1.5*x**2.5 == x**4.0 + + assert 2**(2.0*x)/2**x == 2**(1.0*x) + assert 2**x/2**(2.0*x) == 2**(-1.0*x) + assert 2**x*2**(2.0*x) == 2**(3.0*x) + assert 2**(1.5*x)*2**(2.5*x) == 2**(4.0*x) + + +def test_mul_flatten_oo(): + p = symbols('p', positive=True) + n, m = symbols('n,m', negative=True) + x_im = symbols('x_im', imaginary=True) + assert n*oo is -oo + assert n*m*oo is oo + assert p*oo is oo + assert x_im*oo != I*oo # i could be +/- 3*I -> +/-oo + + +def test_add_flatten(): + # see https://github.com/sympy/sympy/issues/2633#issuecomment-29545524 + a = oo + I*oo + b = oo - I*oo + assert a + b is nan + assert a - b is nan + # FIXME: This evaluates as: + # >>> 1/a + # 0*(oo + oo*I) + # which should not simplify to 0. Should be fixed in Pow.eval + #assert (1/a).simplify() == (1/b).simplify() == 0 + + a = Pow(2, 3, evaluate=False) + assert a + a == 16 + + +def test_issue_5160_6087_6089_6090(): + # issue 6087 + assert ((-2*x*y**y)**3.2).n(2) == (2**3.2*(-x*y**y)**3.2).n(2) + # issue 6089 + A, B, C = symbols('A,B,C', commutative=False) + assert (2.*B*C)**3 == 8.0*(B*C)**3 + assert (-2.*B*C)**3 == -8.0*(B*C)**3 + assert (-2*B*C)**2 == 4*(B*C)**2 + # issue 5160 + assert sqrt(-1.0*x) == 1.0*sqrt(-x) + assert sqrt(1.0*x) == 1.0*sqrt(x) + # issue 6090 + assert (-2*x*y*A*B)**2 == 4*x**2*y**2*(A*B)**2 + + +def test_float_int_round(): + assert int(float(sqrt(10))) == int(sqrt(10)) + assert int(pi**1000) % 10 == 2 + assert int(Float('1.123456789012345678901234567890e20', '')) == \ + int(112345678901234567890) + assert int(Float('1.123456789012345678901234567890e25', '')) == \ + int(11234567890123456789012345) + # decimal forces float so it's not an exact integer ending in 000000 + assert int(Float('1.123456789012345678901234567890e35', '')) == \ + 112345678901234567890123456789000192 + assert int(Float('123456789012345678901234567890e5', '')) == \ + 12345678901234567890123456789000000 + assert Integer(Float('1.123456789012345678901234567890e20', '')) == \ + 112345678901234567890 + assert Integer(Float('1.123456789012345678901234567890e25', '')) == \ + 11234567890123456789012345 + # decimal forces float so it's not an exact integer ending in 000000 + assert Integer(Float('1.123456789012345678901234567890e35', '')) == \ + 112345678901234567890123456789000192 + assert Integer(Float('123456789012345678901234567890e5', '')) == \ + 12345678901234567890123456789000000 + assert same_and_same_prec(Float('123000e-2',''), Float('1230.00', '')) + assert same_and_same_prec(Float('123000e2',''), Float('12300000', '')) + + assert int(1 + Rational('.9999999999999999999999999')) == 1 + assert int(pi/1e20) == 0 + assert int(1 + pi/1e20) == 1 + assert int(Add(1.2, -2, evaluate=False)) == int(1.2 - 2) + assert int(Add(1.2, +2, evaluate=False)) == int(1.2 + 2) + assert int(Add(1 + Float('.99999999999999999', ''), evaluate=False)) == 1 + raises(TypeError, lambda: float(x)) + raises(TypeError, lambda: float(sqrt(-1))) + + assert int(12345678901234567890 + cos(1)**2 + sin(1)**2) == \ + 12345678901234567891 + + +def test_issue_6611a(): + assert Mul.flatten([3**Rational(1, 3), + Pow(-Rational(1, 9), Rational(2, 3), evaluate=False)]) == \ + ([Rational(1, 3), (-1)**Rational(2, 3)], [], None) + + +def test_denest_add_mul(): + # when working with evaluated expressions make sure they denest + eq = x + 1 + eq = Add(eq, 2, evaluate=False) + eq = Add(eq, 2, evaluate=False) + assert Add(*eq.args) == x + 5 + eq = x*2 + eq = Mul(eq, 2, evaluate=False) + eq = Mul(eq, 2, evaluate=False) + assert Mul(*eq.args) == 8*x + # but don't let them denest unnecessarily + eq = Mul(-2, x - 2, evaluate=False) + assert 2*eq == Mul(-4, x - 2, evaluate=False) + assert -eq == Mul(2, x - 2, evaluate=False) + + +def test_mul_coeff(): + # It is important that all Numbers be removed from the seq; + # This can be tricky when powers combine to produce those numbers + p = exp(I*pi/3) + assert p**2*x*p*y*p*x*p**2 == x**2*y + + +def test_mul_zero_detection(): + nz = Dummy(real=True, zero=False) + r = Dummy(extended_real=True) + c = Dummy(real=False, complex=True) + c2 = Dummy(real=False, complex=True) + i = Dummy(imaginary=True) + e = nz*r*c + assert e.is_imaginary is None + assert e.is_extended_real is None + e = nz*c + assert e.is_imaginary is None + assert e.is_extended_real is False + e = nz*i*c + assert e.is_imaginary is False + assert e.is_extended_real is None + # check for more than one complex; it is important to use + # uniquely named Symbols to ensure that two factors appear + # e.g. if the symbols have the same name they just become + # a single factor, a power. + e = nz*i*c*c2 + assert e.is_imaginary is None + assert e.is_extended_real is None + + # _eval_is_extended_real and _eval_is_zero both employ trapping of the + # zero value so args should be tested in both directions and + # TO AVOID GETTING THE CACHED RESULT, Dummy MUST BE USED + + # real is unknown + def test(z, b, e): + if z.is_zero and b.is_finite: + assert e.is_extended_real and e.is_zero + else: + assert e.is_extended_real is None + if b.is_finite: + if z.is_zero: + assert e.is_zero + else: + assert e.is_zero is None + elif b.is_finite is False: + if z.is_zero is None: + assert e.is_zero is None + else: + assert e.is_zero is False + + + for iz, ib in product(*[[True, False, None]]*2): + z = Dummy('z', nonzero=iz) + b = Dummy('f', finite=ib) + e = Mul(z, b, evaluate=False) + test(z, b, e) + z = Dummy('nz', nonzero=iz) + b = Dummy('f', finite=ib) + e = Mul(b, z, evaluate=False) + test(z, b, e) + + # real is True + def test(z, b, e): + if z.is_zero and not b.is_finite: + assert e.is_extended_real is None + else: + assert e.is_extended_real is True + + for iz, ib in product(*[[True, False, None]]*2): + z = Dummy('z', nonzero=iz, extended_real=True) + b = Dummy('b', finite=ib, extended_real=True) + e = Mul(z, b, evaluate=False) + test(z, b, e) + z = Dummy('z', nonzero=iz, extended_real=True) + b = Dummy('b', finite=ib, extended_real=True) + e = Mul(b, z, evaluate=False) + test(z, b, e) + + +def test_Mul_with_zero_infinite(): + zer = Dummy(zero=True) + inf = Dummy(finite=False) + + e = Mul(zer, inf, evaluate=False) + assert e.is_extended_positive is None + assert e.is_hermitian is None + + e = Mul(inf, zer, evaluate=False) + assert e.is_extended_positive is None + assert e.is_hermitian is None + + +def test_Mul_does_not_cancel_infinities(): + a, b = symbols('a b') + assert ((zoo + 3*a)/(3*a + zoo)) is nan + assert ((b - oo)/(b - oo)) is nan + # issue 13904 + expr = (1/(a+b) + 1/(a-b))/(1/(a+b) - 1/(a-b)) + assert expr.subs(b, a) is nan + + +def test_Mul_does_not_distribute_infinity(): + a, b = symbols('a b') + assert ((1 + I)*oo).is_Mul + assert ((a + b)*(-oo)).is_Mul + assert ((a + 1)*zoo).is_Mul + assert ((1 + I)*oo).is_finite is False + z = (1 + I)*oo + assert ((1 - I)*z).expand() is oo + + +def test_issue_8247_8354(): + from sympy.functions.elementary.trigonometric import tan + z = sqrt(1 + sqrt(3)) + sqrt(3 + 3*sqrt(3)) - sqrt(10 + 6*sqrt(3)) + assert z.is_positive is False # it's 0 + z = S('''-2**(1/3)*(3*sqrt(93) + 29)**2 - 4*(3*sqrt(93) + 29)**(4/3) + + 12*sqrt(93)*(3*sqrt(93) + 29)**(1/3) + 116*(3*sqrt(93) + 29)**(1/3) + + 174*2**(1/3)*sqrt(93) + 1678*2**(1/3)''') + assert z.is_positive is False # it's 0 + z = 2*(-3*tan(19*pi/90) + sqrt(3))*cos(11*pi/90)*cos(19*pi/90) - \ + sqrt(3)*(-3 + 4*cos(19*pi/90)**2) + assert z.is_positive is not True # it's zero and it shouldn't hang + z = S('''9*(3*sqrt(93) + 29)**(2/3)*((3*sqrt(93) + + 29)**(1/3)*(-2**(2/3)*(3*sqrt(93) + 29)**(1/3) - 2) - 2*2**(1/3))**3 + + 72*(3*sqrt(93) + 29)**(2/3)*(81*sqrt(93) + 783) + (162*sqrt(93) + + 1566)*((3*sqrt(93) + 29)**(1/3)*(-2**(2/3)*(3*sqrt(93) + 29)**(1/3) - + 2) - 2*2**(1/3))**2''') + assert z.is_positive is False # it's 0 (and a single _mexpand isn't enough) + + +def test_Add_is_zero(): + x, y = symbols('x y', zero=True) + assert (x + y).is_zero + + # Issue 15873 + e = -2*I + (1 + I)**2 + assert e.is_zero is None + + +def test_issue_14392(): + assert (sin(zoo)**2).as_real_imag() == (nan, nan) + + +def test_divmod(): + assert divmod(x, y) == (x//y, x % y) + assert divmod(x, 3) == (x//3, x % 3) + assert divmod(3, x) == (3//x, 3 % x) + + +def test__neg__(): + assert -(x*y) == -x*y + assert -(-x*y) == x*y + assert -(1.*x) == -1.*x + assert -(-1.*x) == 1.*x + assert -(2.*x) == -2.*x + assert -(-2.*x) == 2.*x + with distribute(False): + eq = -(x + y) + assert eq.is_Mul and eq.args == (-1, x + y) + with evaluate(False): + eq = -(x + y) + assert eq.is_Mul and eq.args == (-1, x + y) + + +def test_issue_18507(): + assert Mul(zoo, zoo, 0) is nan + + +def test_issue_17130(): + e = Add(b, -b, I, -I, evaluate=False) + assert e.is_zero is None # ideally this would be True + + +def test_issue_21034(): + e = -I*log((re(asin(5)) + I*im(asin(5)))/sqrt(re(asin(5))**2 + im(asin(5))**2))/pi + assert e.round(2) + + +def test_issue_22021(): + from sympy.calculus.accumulationbounds import AccumBounds + # these objects are special cases in Mul + from sympy.tensor.tensor import TensorIndexType, tensor_indices, tensor_heads + L = TensorIndexType("L") + i = tensor_indices("i", L) + A, B = tensor_heads("A B", [L]) + e = A(i) + B(i) + assert -e == -1*e + e = zoo + x + assert -e == -1*e + a = AccumBounds(1, 2) + e = a + x + assert -e == -1*e + for args in permutations((zoo, a, x)): + e = Add(*args, evaluate=False) + assert -e == -1*e + assert 2*Add(1, x, x, evaluate=False) == 4*x + 2 + + +def test_issue_22244(): + assert -(zoo*x) == zoo*x + + +def test_issue_22453(): + from sympy.utilities.iterables import cartes + e = Symbol('e', extended_positive=True) + for a, b in cartes(*[[oo, -oo, 3]]*2): + if a == b == 3: + continue + i = a + I*b + assert i**(1 + e) is S.ComplexInfinity + assert i**-e is S.Zero + assert unchanged(Pow, i, e) + assert 1/(oo + I*oo) is S.Zero + r, i = [Dummy(infinite=True, extended_real=True) for _ in range(2)] + assert 1/(r + I*i) is S.Zero + assert 1/(3 + I*i) is S.Zero + assert 1/(r + I*3) is S.Zero + + +def test_issue_22613(): + assert (0**(x - 2)).as_content_primitive() == (1, 0**(x - 2)) + assert (0**(x + 2)).as_content_primitive() == (1, 0**(x + 2)) + + +def test_issue_25176(): + assert sqrt(-4*3**(S(3)/4)*I/3) == 2*3**(S(7)/8)*sqrt(-I)/3 diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_assumptions.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_assumptions.py new file mode 100644 index 0000000000000000000000000000000000000000..574e90178fb489fe99c99ea0c72df57ceec4b249 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_assumptions.py @@ -0,0 +1,1335 @@ +from sympy.core.mod import Mod +from sympy.core.numbers import (I, oo, pi) +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (asin, sin) +from sympy.simplify.simplify import simplify +from sympy.core import Symbol, S, Rational, Integer, Dummy, Wild, Pow +from sympy.core.assumptions import (assumptions, check_assumptions, + failing_assumptions, common_assumptions, _generate_assumption_rules, + _load_pre_generated_assumption_rules) +from sympy.core.facts import InconsistentAssumptions +from sympy.core.random import seed +from sympy.combinatorics import Permutation +from sympy.combinatorics.perm_groups import PermutationGroup + +from sympy.testing.pytest import raises, XFAIL + + +def test_symbol_unset(): + x = Symbol('x', real=True, integer=True) + assert x.is_real is True + assert x.is_integer is True + assert x.is_imaginary is False + assert x.is_noninteger is False + assert x.is_number is False + + +def test_zero(): + z = Integer(0) + assert z.is_commutative is True + assert z.is_integer is True + assert z.is_rational is True + assert z.is_algebraic is True + assert z.is_transcendental is False + assert z.is_real is True + assert z.is_complex is True + assert z.is_noninteger is False + assert z.is_irrational is False + assert z.is_imaginary is False + assert z.is_positive is False + assert z.is_negative is False + assert z.is_nonpositive is True + assert z.is_nonnegative is True + assert z.is_even is True + assert z.is_odd is False + assert z.is_finite is True + assert z.is_infinite is False + assert z.is_comparable is True + assert z.is_prime is False + assert z.is_composite is False + assert z.is_number is True + + +def test_one(): + z = Integer(1) + assert z.is_commutative is True + assert z.is_integer is True + assert z.is_rational is True + assert z.is_algebraic is True + assert z.is_transcendental is False + assert z.is_real is True + assert z.is_complex is True + assert z.is_noninteger is False + assert z.is_irrational is False + assert z.is_imaginary is False + assert z.is_positive is True + assert z.is_negative is False + assert z.is_nonpositive is False + assert z.is_nonnegative is True + assert z.is_even is False + assert z.is_odd is True + assert z.is_finite is True + assert z.is_infinite is False + assert z.is_comparable is True + assert z.is_prime is False + assert z.is_number is True + assert z.is_composite is False # issue 8807 + + +def test_negativeone(): + z = Integer(-1) + assert z.is_commutative is True + assert z.is_integer is True + assert z.is_rational is True + assert z.is_algebraic is True + assert z.is_transcendental is False + assert z.is_real is True + assert z.is_complex is True + assert z.is_noninteger is False + assert z.is_irrational is False + assert z.is_imaginary is False + assert z.is_positive is False + assert z.is_negative is True + assert z.is_nonpositive is True + assert z.is_nonnegative is False + assert z.is_even is False + assert z.is_odd is True + assert z.is_finite is True + assert z.is_infinite is False + assert z.is_comparable is True + assert z.is_prime is False + assert z.is_composite is False + assert z.is_number is True + + +def test_infinity(): + oo = S.Infinity + + assert oo.is_commutative is True + assert oo.is_integer is False + assert oo.is_rational is False + assert oo.is_algebraic is False + assert oo.is_transcendental is False + assert oo.is_extended_real is True + assert oo.is_real is False + assert oo.is_complex is False + assert oo.is_noninteger is True + assert oo.is_irrational is False + assert oo.is_imaginary is False + assert oo.is_nonzero is False + assert oo.is_positive is False + assert oo.is_negative is False + assert oo.is_nonpositive is False + assert oo.is_nonnegative is False + assert oo.is_extended_nonzero is True + assert oo.is_extended_positive is True + assert oo.is_extended_negative is False + assert oo.is_extended_nonpositive is False + assert oo.is_extended_nonnegative is True + assert oo.is_even is False + assert oo.is_odd is False + assert oo.is_finite is False + assert oo.is_infinite is True + assert oo.is_comparable is True + assert oo.is_prime is False + assert oo.is_composite is False + assert oo.is_number is True + + +def test_neg_infinity(): + mm = S.NegativeInfinity + + assert mm.is_commutative is True + assert mm.is_integer is False + assert mm.is_rational is False + assert mm.is_algebraic is False + assert mm.is_transcendental is False + assert mm.is_extended_real is True + assert mm.is_real is False + assert mm.is_complex is False + assert mm.is_noninteger is True + assert mm.is_irrational is False + assert mm.is_imaginary is False + assert mm.is_nonzero is False + assert mm.is_positive is False + assert mm.is_negative is False + assert mm.is_nonpositive is False + assert mm.is_nonnegative is False + assert mm.is_extended_nonzero is True + assert mm.is_extended_positive is False + assert mm.is_extended_negative is True + assert mm.is_extended_nonpositive is True + assert mm.is_extended_nonnegative is False + assert mm.is_even is False + assert mm.is_odd is False + assert mm.is_finite is False + assert mm.is_infinite is True + assert mm.is_comparable is True + assert mm.is_prime is False + assert mm.is_composite is False + assert mm.is_number is True + + +def test_zoo(): + zoo = S.ComplexInfinity + assert zoo.is_complex is False + assert zoo.is_real is False + assert zoo.is_prime is False + + +def test_nan(): + nan = S.NaN + + assert nan.is_commutative is True + assert nan.is_integer is None + assert nan.is_rational is None + assert nan.is_algebraic is None + assert nan.is_transcendental is None + assert nan.is_real is None + assert nan.is_complex is None + assert nan.is_noninteger is None + assert nan.is_irrational is None + assert nan.is_imaginary is None + assert nan.is_positive is None + assert nan.is_negative is None + assert nan.is_nonpositive is None + assert nan.is_nonnegative is None + assert nan.is_even is None + assert nan.is_odd is None + assert nan.is_finite is None + assert nan.is_infinite is None + assert nan.is_comparable is False + assert nan.is_prime is None + assert nan.is_composite is None + assert nan.is_number is True + + +def test_pos_rational(): + r = Rational(3, 4) + assert r.is_commutative is True + assert r.is_integer is False + assert r.is_rational is True + assert r.is_algebraic is True + assert r.is_transcendental is False + assert r.is_real is True + assert r.is_complex is True + assert r.is_noninteger is True + assert r.is_irrational is False + assert r.is_imaginary is False + assert r.is_positive is True + assert r.is_negative is False + assert r.is_nonpositive is False + assert r.is_nonnegative is True + assert r.is_even is False + assert r.is_odd is False + assert r.is_finite is True + assert r.is_infinite is False + assert r.is_comparable is True + assert r.is_prime is False + assert r.is_composite is False + + r = Rational(1, 4) + assert r.is_nonpositive is False + assert r.is_positive is True + assert r.is_negative is False + assert r.is_nonnegative is True + r = Rational(5, 4) + assert r.is_negative is False + assert r.is_positive is True + assert r.is_nonpositive is False + assert r.is_nonnegative is True + r = Rational(5, 3) + assert r.is_nonnegative is True + assert r.is_positive is True + assert r.is_negative is False + assert r.is_nonpositive is False + + +def test_neg_rational(): + r = Rational(-3, 4) + assert r.is_positive is False + assert r.is_nonpositive is True + assert r.is_negative is True + assert r.is_nonnegative is False + r = Rational(-1, 4) + assert r.is_nonpositive is True + assert r.is_positive is False + assert r.is_negative is True + assert r.is_nonnegative is False + r = Rational(-5, 4) + assert r.is_negative is True + assert r.is_positive is False + assert r.is_nonpositive is True + assert r.is_nonnegative is False + r = Rational(-5, 3) + assert r.is_nonnegative is False + assert r.is_positive is False + assert r.is_negative is True + assert r.is_nonpositive is True + + +def test_pi(): + z = S.Pi + assert z.is_commutative is True + assert z.is_integer is False + assert z.is_rational is False + assert z.is_algebraic is False + assert z.is_transcendental is True + assert z.is_real is True + assert z.is_complex is True + assert z.is_noninteger is True + assert z.is_irrational is True + assert z.is_imaginary is False + assert z.is_positive is True + assert z.is_negative is False + assert z.is_nonpositive is False + assert z.is_nonnegative is True + assert z.is_even is False + assert z.is_odd is False + assert z.is_finite is True + assert z.is_infinite is False + assert z.is_comparable is True + assert z.is_prime is False + assert z.is_composite is False + + +def test_E(): + z = S.Exp1 + assert z.is_commutative is True + assert z.is_integer is False + assert z.is_rational is False + assert z.is_algebraic is False + assert z.is_transcendental is True + assert z.is_real is True + assert z.is_complex is True + assert z.is_noninteger is True + assert z.is_irrational is True + assert z.is_imaginary is False + assert z.is_positive is True + assert z.is_negative is False + assert z.is_nonpositive is False + assert z.is_nonnegative is True + assert z.is_even is False + assert z.is_odd is False + assert z.is_finite is True + assert z.is_infinite is False + assert z.is_comparable is True + assert z.is_prime is False + assert z.is_composite is False + + +def test_I(): + z = S.ImaginaryUnit + assert z.is_commutative is True + assert z.is_integer is False + assert z.is_rational is False + assert z.is_algebraic is True + assert z.is_transcendental is False + assert z.is_real is False + assert z.is_complex is True + assert z.is_noninteger is False + assert z.is_irrational is False + assert z.is_imaginary is True + assert z.is_positive is False + assert z.is_negative is False + assert z.is_nonpositive is False + assert z.is_nonnegative is False + assert z.is_even is False + assert z.is_odd is False + assert z.is_finite is True + assert z.is_infinite is False + assert z.is_comparable is False + assert z.is_prime is False + assert z.is_composite is False + + +def test_symbol_real_false(): + # issue 3848 + a = Symbol('a', real=False) + + assert a.is_real is False + assert a.is_integer is False + assert a.is_zero is False + + assert a.is_negative is False + assert a.is_positive is False + assert a.is_nonnegative is False + assert a.is_nonpositive is False + assert a.is_nonzero is False + + assert a.is_extended_negative is None + assert a.is_extended_positive is None + assert a.is_extended_nonnegative is None + assert a.is_extended_nonpositive is None + assert a.is_extended_nonzero is None + + +def test_symbol_extended_real_false(): + # issue 3848 + a = Symbol('a', extended_real=False) + + assert a.is_real is False + assert a.is_integer is False + assert a.is_zero is False + + assert a.is_negative is False + assert a.is_positive is False + assert a.is_nonnegative is False + assert a.is_nonpositive is False + assert a.is_nonzero is False + + assert a.is_extended_negative is False + assert a.is_extended_positive is False + assert a.is_extended_nonnegative is False + assert a.is_extended_nonpositive is False + assert a.is_extended_nonzero is False + + +def test_symbol_imaginary(): + a = Symbol('a', imaginary=True) + + assert a.is_real is False + assert a.is_integer is False + assert a.is_negative is False + assert a.is_positive is False + assert a.is_nonnegative is False + assert a.is_nonpositive is False + assert a.is_zero is False + assert a.is_nonzero is False # since nonzero -> real + + +def test_symbol_zero(): + x = Symbol('x', zero=True) + assert x.is_positive is False + assert x.is_nonpositive + assert x.is_negative is False + assert x.is_nonnegative + assert x.is_zero is True + # TODO Change to x.is_nonzero is None + # See https://github.com/sympy/sympy/pull/9583 + assert x.is_nonzero is False + assert x.is_finite is True + + +def test_symbol_positive(): + x = Symbol('x', positive=True) + assert x.is_positive is True + assert x.is_nonpositive is False + assert x.is_negative is False + assert x.is_nonnegative is True + assert x.is_zero is False + assert x.is_nonzero is True + + +def test_neg_symbol_positive(): + x = -Symbol('x', positive=True) + assert x.is_positive is False + assert x.is_nonpositive is True + assert x.is_negative is True + assert x.is_nonnegative is False + assert x.is_zero is False + assert x.is_nonzero is True + + +def test_symbol_nonpositive(): + x = Symbol('x', nonpositive=True) + assert x.is_positive is False + assert x.is_nonpositive is True + assert x.is_negative is None + assert x.is_nonnegative is None + assert x.is_zero is None + assert x.is_nonzero is None + + +def test_neg_symbol_nonpositive(): + x = -Symbol('x', nonpositive=True) + assert x.is_positive is None + assert x.is_nonpositive is None + assert x.is_negative is False + assert x.is_nonnegative is True + assert x.is_zero is None + assert x.is_nonzero is None + + +def test_symbol_falsepositive(): + x = Symbol('x', positive=False) + assert x.is_positive is False + assert x.is_nonpositive is None + assert x.is_negative is None + assert x.is_nonnegative is None + assert x.is_zero is None + assert x.is_nonzero is None + + +def test_symbol_falsepositive_mul(): + # To test pull request 9379 + # Explicit handling of arg.is_positive=False was added to Mul._eval_is_positive + x = 2*Symbol('x', positive=False) + assert x.is_positive is False # This was None before + assert x.is_nonpositive is None + assert x.is_negative is None + assert x.is_nonnegative is None + assert x.is_zero is None + assert x.is_nonzero is None + + +@XFAIL +def test_symbol_infinitereal_mul(): + ix = Symbol('ix', infinite=True, extended_real=True) + assert (-ix).is_extended_positive is None + + +def test_neg_symbol_falsepositive(): + x = -Symbol('x', positive=False) + assert x.is_positive is None + assert x.is_nonpositive is None + assert x.is_negative is False + assert x.is_nonnegative is None + assert x.is_zero is None + assert x.is_nonzero is None + + +def test_neg_symbol_falsenegative(): + # To test pull request 9379 + # Explicit handling of arg.is_negative=False was added to Mul._eval_is_positive + x = -Symbol('x', negative=False) + assert x.is_positive is False # This was None before + assert x.is_nonpositive is None + assert x.is_negative is None + assert x.is_nonnegative is None + assert x.is_zero is None + assert x.is_nonzero is None + + +def test_symbol_falsepositive_real(): + x = Symbol('x', positive=False, real=True) + assert x.is_positive is False + assert x.is_nonpositive is True + assert x.is_negative is None + assert x.is_nonnegative is None + assert x.is_zero is None + assert x.is_nonzero is None + + +def test_neg_symbol_falsepositive_real(): + x = -Symbol('x', positive=False, real=True) + assert x.is_positive is None + assert x.is_nonpositive is None + assert x.is_negative is False + assert x.is_nonnegative is True + assert x.is_zero is None + assert x.is_nonzero is None + + +def test_symbol_falsenonnegative(): + x = Symbol('x', nonnegative=False) + assert x.is_positive is False + assert x.is_nonpositive is None + assert x.is_negative is None + assert x.is_nonnegative is False + assert x.is_zero is False + assert x.is_nonzero is None + + +@XFAIL +def test_neg_symbol_falsenonnegative(): + x = -Symbol('x', nonnegative=False) + assert x.is_positive is None + assert x.is_nonpositive is False # this currently returns None + assert x.is_negative is False # this currently returns None + assert x.is_nonnegative is None + assert x.is_zero is False # this currently returns None + assert x.is_nonzero is True # this currently returns None + + +def test_symbol_falsenonnegative_real(): + x = Symbol('x', nonnegative=False, real=True) + assert x.is_positive is False + assert x.is_nonpositive is True + assert x.is_negative is True + assert x.is_nonnegative is False + assert x.is_zero is False + assert x.is_nonzero is True + + +def test_neg_symbol_falsenonnegative_real(): + x = -Symbol('x', nonnegative=False, real=True) + assert x.is_positive is True + assert x.is_nonpositive is False + assert x.is_negative is False + assert x.is_nonnegative is True + assert x.is_zero is False + assert x.is_nonzero is True + + +def test_prime(): + assert S.NegativeOne.is_prime is False + assert S(-2).is_prime is False + assert S(-4).is_prime is False + assert S.Zero.is_prime is False + assert S.One.is_prime is False + assert S(2).is_prime is True + assert S(17).is_prime is True + assert S(4).is_prime is False + + +def test_composite(): + assert S.NegativeOne.is_composite is False + assert S(-2).is_composite is False + assert S(-4).is_composite is False + assert S.Zero.is_composite is False + assert S(2).is_composite is False + assert S(17).is_composite is False + assert S(4).is_composite is True + x = Dummy(integer=True, positive=True, prime=False) + assert x.is_composite is None # x could be 1 + assert (x + 1).is_composite is None + x = Dummy(positive=True, even=True, prime=False) + assert x.is_integer is True + assert x.is_composite is True + + +def test_prime_symbol(): + x = Symbol('x', prime=True) + assert x.is_prime is True + assert x.is_integer is True + assert x.is_positive is True + assert x.is_negative is False + assert x.is_nonpositive is False + assert x.is_nonnegative is True + + x = Symbol('x', prime=False) + assert x.is_prime is False + assert x.is_integer is None + assert x.is_positive is None + assert x.is_negative is None + assert x.is_nonpositive is None + assert x.is_nonnegative is None + + +def test_symbol_noncommutative(): + x = Symbol('x', commutative=True) + assert x.is_complex is None + + x = Symbol('x', commutative=False) + assert x.is_integer is False + assert x.is_rational is False + assert x.is_algebraic is False + assert x.is_irrational is False + assert x.is_real is False + assert x.is_complex is False + + +def test_other_symbol(): + x = Symbol('x', integer=True) + assert x.is_integer is True + assert x.is_real is True + assert x.is_finite is True + + x = Symbol('x', integer=True, nonnegative=True) + assert x.is_integer is True + assert x.is_nonnegative is True + assert x.is_negative is False + assert x.is_positive is None + assert x.is_finite is True + + x = Symbol('x', integer=True, nonpositive=True) + assert x.is_integer is True + assert x.is_nonpositive is True + assert x.is_positive is False + assert x.is_negative is None + assert x.is_finite is True + + x = Symbol('x', odd=True) + assert x.is_odd is True + assert x.is_even is False + assert x.is_integer is True + assert x.is_finite is True + + x = Symbol('x', odd=False) + assert x.is_odd is False + assert x.is_even is None + assert x.is_integer is None + assert x.is_finite is None + + x = Symbol('x', even=True) + assert x.is_even is True + assert x.is_odd is False + assert x.is_integer is True + assert x.is_finite is True + + x = Symbol('x', even=False) + assert x.is_even is False + assert x.is_odd is None + assert x.is_integer is None + assert x.is_finite is None + + x = Symbol('x', integer=True, nonnegative=True) + assert x.is_integer is True + assert x.is_nonnegative is True + assert x.is_finite is True + + x = Symbol('x', integer=True, nonpositive=True) + assert x.is_integer is True + assert x.is_nonpositive is True + assert x.is_finite is True + + x = Symbol('x', rational=True) + assert x.is_real is True + assert x.is_finite is True + + x = Symbol('x', rational=False) + assert x.is_real is None + assert x.is_finite is None + + x = Symbol('x', irrational=True) + assert x.is_real is True + assert x.is_finite is True + + x = Symbol('x', irrational=False) + assert x.is_real is None + assert x.is_finite is None + + with raises(AttributeError): + x.is_real = False + + x = Symbol('x', algebraic=True) + assert x.is_transcendental is False + x = Symbol('x', transcendental=True) + assert x.is_algebraic is False + assert x.is_rational is False + assert x.is_integer is False + + +def test_evaluate_false(): + # Previously this failed because the assumptions query would make new + # expressions and some of the evaluation logic would fail under + # evaluate(False). + from sympy.core.parameters import evaluate + from sympy.abc import x, h + f = 2**x**7 + with evaluate(False): + fh = f.xreplace({x: x+h}) + assert fh.exp.is_rational is None + + +def test_issue_3825(): + """catch: hash instability""" + x = Symbol("x") + y = Symbol("y") + a1 = x + y + a2 = y + x + a2.is_comparable + + h1 = hash(a1) + h2 = hash(a2) + assert h1 == h2 + + +def test_issue_4822(): + z = (-1)**Rational(1, 3)*(1 - I*sqrt(3)) + assert z.is_real in [True, None] + + +def test_hash_vs_typeinfo(): + """seemingly different typeinfo, but in fact equal""" + + # the following two are semantically equal + x1 = Symbol('x', even=True) + x2 = Symbol('x', integer=True, odd=False) + + assert hash(x1) == hash(x2) + assert x1 == x2 + + +def test_hash_vs_typeinfo_2(): + """different typeinfo should mean !eq""" + # the following two are semantically different + x = Symbol('x') + x1 = Symbol('x', even=True) + + assert x != x1 + assert hash(x) != hash(x1) # This might fail with very low probability + + +def test_hash_vs_eq(): + """catch: different hash for equal objects""" + a = 1 + S.Pi # important: do not fold it into a Number instance + ha = hash(a) # it should be Add/Mul/... to trigger the bug + + a.is_positive # this uses .evalf() and deduces it is positive + assert a.is_positive is True + + # be sure that hash stayed the same + assert ha == hash(a) + + # now b should be the same expression + b = a.expand(trig=True) + hb = hash(b) + + assert a == b + assert ha == hb + + +def test_Add_is_pos_neg(): + # these cover lines not covered by the rest of tests in core + n = Symbol('n', extended_negative=True, infinite=True) + nn = Symbol('n', extended_nonnegative=True, infinite=True) + np = Symbol('n', extended_nonpositive=True, infinite=True) + p = Symbol('p', extended_positive=True, infinite=True) + r = Dummy(extended_real=True, finite=False) + x = Symbol('x') + xf = Symbol('xf', finite=True) + assert (n + p).is_extended_positive is None + assert (n + x).is_extended_positive is None + assert (p + x).is_extended_positive is None + assert (n + p).is_extended_negative is None + assert (n + x).is_extended_negative is None + assert (p + x).is_extended_negative is None + + assert (n + xf).is_extended_positive is False + assert (p + xf).is_extended_positive is True + assert (n + xf).is_extended_negative is True + assert (p + xf).is_extended_negative is False + + assert (x - S.Infinity).is_extended_negative is None # issue 7798 + # issue 8046, 16.2 + assert (p + nn).is_extended_positive + assert (n + np).is_extended_negative + assert (p + r).is_extended_positive is None + + +def test_Add_is_imaginary(): + nn = Dummy(nonnegative=True) + assert (I*nn + I).is_imaginary # issue 8046, 17 + + +def test_Add_is_algebraic(): + a = Symbol('a', algebraic=True) + b = Symbol('a', algebraic=True) + na = Symbol('na', algebraic=False) + nb = Symbol('nb', algebraic=False) + x = Symbol('x') + assert (a + b).is_algebraic + assert (na + nb).is_algebraic is None + assert (a + na).is_algebraic is False + assert (a + x).is_algebraic is None + assert (na + x).is_algebraic is None + + +def test_Mul_is_algebraic(): + a = Symbol('a', algebraic=True) + b = Symbol('b', algebraic=True) + na = Symbol('na', algebraic=False) + an = Symbol('an', algebraic=True, nonzero=True) + nb = Symbol('nb', algebraic=False) + x = Symbol('x') + assert (a*b).is_algebraic is True + assert (na*nb).is_algebraic is None + assert (a*na).is_algebraic is None + assert (an*na).is_algebraic is False + assert (a*x).is_algebraic is None + assert (na*x).is_algebraic is None + + +def test_Pow_is_algebraic(): + e = Symbol('e', algebraic=True) + + assert Pow(1, e, evaluate=False).is_algebraic + assert Pow(0, e, evaluate=False).is_algebraic + + a = Symbol('a', algebraic=True) + azf = Symbol('azf', algebraic=True, zero=False) + na = Symbol('na', algebraic=False) + ia = Symbol('ia', algebraic=True, irrational=True) + ib = Symbol('ib', algebraic=True, irrational=True) + r = Symbol('r', rational=True) + x = Symbol('x') + assert (a**2).is_algebraic is True + assert (a**r).is_algebraic is None + assert (azf**r).is_algebraic is True + assert (a**x).is_algebraic is None + assert (na**r).is_algebraic is None + assert (ia**r).is_algebraic is True + assert (ia**ib).is_algebraic is False + + assert (a**e).is_algebraic is None + + # Gelfond-Schneider constant: + assert Pow(2, sqrt(2), evaluate=False).is_algebraic is False + + assert Pow(S.GoldenRatio, sqrt(3), evaluate=False).is_algebraic is False + + # issue 8649 + t = Symbol('t', real=True, transcendental=True) + n = Symbol('n', integer=True) + assert (t**n).is_algebraic is None + assert (t**n).is_integer is None + + assert (pi**3).is_algebraic is False + r = Symbol('r', zero=True) + assert (pi**r).is_algebraic is True + + +def test_Mul_is_prime_composite(): + x = Symbol('x', positive=True, integer=True) + y = Symbol('y', positive=True, integer=True) + assert (x*y).is_prime is None + assert ( (x+1)*(y+1) ).is_prime is False + assert ( (x+1)*(y+1) ).is_composite is True + + x = Symbol('x', positive=True) + assert ( (x+1)*(y+1) ).is_prime is None + assert ( (x+1)*(y+1) ).is_composite is None + + +def test_Pow_is_pos_neg(): + z = Symbol('z', real=True) + w = Symbol('w', nonpositive=True) + + assert (S.NegativeOne**S(2)).is_positive is True + assert (S.One**z).is_positive is True + assert (S.NegativeOne**S(3)).is_positive is False + assert (S.Zero**S.Zero).is_positive is True # 0**0 is 1 + assert (w**S(3)).is_positive is False + assert (w**S(2)).is_positive is None + assert (I**2).is_positive is False + assert (I**4).is_positive is True + + # tests emerging from #16332 issue + p = Symbol('p', zero=True) + q = Symbol('q', zero=False, real=True) + j = Symbol('j', zero=False, even=True) + x = Symbol('x', zero=True) + y = Symbol('y', zero=True) + assert (p**q).is_positive is False + assert (p**q).is_negative is False + assert (p**j).is_positive is False + assert (x**y).is_positive is True # 0**0 + assert (x**y).is_negative is False + + +def test_Pow_is_prime_composite(): + x = Symbol('x', positive=True, integer=True) + y = Symbol('y', positive=True, integer=True) + assert (x**y).is_prime is None + assert ( x**(y+1) ).is_prime is False + assert ( x**(y+1) ).is_composite is None + assert ( (x+1)**(y+1) ).is_composite is True + assert ( (-x-1)**(2*y) ).is_composite is True + + x = Symbol('x', positive=True) + assert (x**y).is_prime is None + + +def test_Mul_is_infinite(): + x = Symbol('x') + f = Symbol('f', finite=True) + i = Symbol('i', infinite=True) + z = Dummy(zero=True) + nzf = Dummy(finite=True, zero=False) + from sympy.core.mul import Mul + assert (x*f).is_finite is None + assert (x*i).is_finite is None + assert (f*i).is_finite is None + assert (x*f*i).is_finite is None + assert (z*i).is_finite is None + assert (nzf*i).is_finite is False + assert (z*f).is_finite is True + assert Mul(0, f, evaluate=False).is_finite is True + assert Mul(0, i, evaluate=False).is_finite is None + + assert (x*f).is_infinite is None + assert (x*i).is_infinite is None + assert (f*i).is_infinite is None + assert (x*f*i).is_infinite is None + assert (z*i).is_infinite is S.NaN.is_infinite + assert (nzf*i).is_infinite is True + assert (z*f).is_infinite is False + assert Mul(0, f, evaluate=False).is_infinite is False + assert Mul(0, i, evaluate=False).is_infinite is S.NaN.is_infinite + + +def test_Add_is_infinite(): + x = Symbol('x') + f = Symbol('f', finite=True) + i = Symbol('i', infinite=True) + i2 = Symbol('i2', infinite=True) + z = Dummy(zero=True) + nzf = Dummy(finite=True, zero=False) + from sympy.core.add import Add + assert (x+f).is_finite is None + assert (x+i).is_finite is None + assert (f+i).is_finite is False + assert (x+f+i).is_finite is None + assert (z+i).is_finite is False + assert (nzf+i).is_finite is False + assert (z+f).is_finite is True + assert (i+i2).is_finite is None + assert Add(0, f, evaluate=False).is_finite is True + assert Add(0, i, evaluate=False).is_finite is False + + assert (x+f).is_infinite is None + assert (x+i).is_infinite is None + assert (f+i).is_infinite is True + assert (x+f+i).is_infinite is None + assert (z+i).is_infinite is True + assert (nzf+i).is_infinite is True + assert (z+f).is_infinite is False + assert (i+i2).is_infinite is None + assert Add(0, f, evaluate=False).is_infinite is False + assert Add(0, i, evaluate=False).is_infinite is True + + +def test_special_is_rational(): + i = Symbol('i', integer=True) + i2 = Symbol('i2', integer=True) + ni = Symbol('ni', integer=True, nonzero=True) + r = Symbol('r', rational=True) + rn = Symbol('r', rational=True, nonzero=True) + nr = Symbol('nr', irrational=True) + x = Symbol('x') + assert sqrt(3).is_rational is False + assert (3 + sqrt(3)).is_rational is False + assert (3*sqrt(3)).is_rational is False + assert exp(3).is_rational is False + assert exp(ni).is_rational is False + assert exp(rn).is_rational is False + assert exp(x).is_rational is None + assert exp(log(3), evaluate=False).is_rational is True + assert log(exp(3), evaluate=False).is_rational is True + assert log(3).is_rational is False + assert log(ni + 1).is_rational is False + assert log(rn + 1).is_rational is False + assert log(x).is_rational is None + assert (sqrt(3) + sqrt(5)).is_rational is None + assert (sqrt(3) + S.Pi).is_rational is False + assert (x**i).is_rational is None + assert (i**i).is_rational is True + assert (i**i2).is_rational is None + assert (r**i).is_rational is None + assert (r**r).is_rational is None + assert (r**x).is_rational is None + assert (nr**i).is_rational is None # issue 8598 + assert (nr**Symbol('z', zero=True)).is_rational + assert sin(1).is_rational is False + assert sin(ni).is_rational is False + assert sin(rn).is_rational is False + assert sin(x).is_rational is None + assert asin(r).is_rational is False + assert sin(asin(3), evaluate=False).is_rational is True + + +@XFAIL +def test_issue_6275(): + x = Symbol('x') + # both zero or both Muls...but neither "change would be very appreciated. + # This is similar to x/x => 1 even though if x = 0, it is really nan. + assert isinstance(x*0, type(0*S.Infinity)) + if 0*S.Infinity is S.NaN: + b = Symbol('b', finite=None) + assert (b*0).is_zero is None + + +def test_sanitize_assumptions(): + # issue 6666 + for cls in (Symbol, Dummy, Wild): + x = cls('x', real=1, positive=0) + assert x.is_real is True + assert x.is_positive is False + assert cls('', real=True, positive=None).is_positive is None + raises(ValueError, lambda: cls('', commutative=None)) + raises(ValueError, lambda: Symbol._sanitize({"commutative": None})) + + +def test_special_assumptions(): + e = -3 - sqrt(5) + (-sqrt(10)/2 - sqrt(2)/2)**2 + assert simplify(e < 0) is S.false + assert simplify(e > 0) is S.false + assert (e == 0) is False # it's not a literal 0 + assert e.equals(0) is True + + +def test_inconsistent(): + # cf. issues 5795 and 5545 + raises(InconsistentAssumptions, lambda: Symbol('x', real=True, + commutative=False)) + + +def test_issue_6631(): + assert ((-1)**(I)).is_real is True + assert ((-1)**(I*2)).is_real is True + assert ((-1)**(I/2)).is_real is True + assert ((-1)**(I*S.Pi)).is_real is True + assert (I**(I + 2)).is_real is True + + +def test_issue_2730(): + assert (1/(1 + I)).is_real is False + + +def test_issue_4149(): + assert (3 + I).is_complex + assert (3 + I).is_imaginary is False + assert (3*I + S.Pi*I).is_imaginary + # as Zero.is_imaginary is False, see issue 7649 + y = Symbol('y', real=True) + assert (3*I + S.Pi*I + y*I).is_imaginary is None + p = Symbol('p', positive=True) + assert (3*I + S.Pi*I + p*I).is_imaginary + n = Symbol('n', negative=True) + assert (-3*I - S.Pi*I + n*I).is_imaginary + + i = Symbol('i', imaginary=True) + assert ([(i**a).is_imaginary for a in range(4)] == + [False, True, False, True]) + + # tests from the PR #7887: + e = S("-sqrt(3)*I/2 + 0.866025403784439*I") + assert e.is_real is False + assert e.is_imaginary + + +def test_issue_2920(): + n = Symbol('n', negative=True) + assert sqrt(n).is_imaginary + + +def test_issue_7899(): + x = Symbol('x', real=True) + assert (I*x).is_real is None + assert ((x - I)*(x - 1)).is_zero is None + assert ((x - I)*(x - 1)).is_real is None + + +@XFAIL +def test_issue_7993(): + x = Dummy(integer=True) + y = Dummy(noninteger=True) + assert (x - y).is_zero is False + + +def test_issue_8075(): + raises(InconsistentAssumptions, lambda: Dummy(zero=True, finite=False)) + raises(InconsistentAssumptions, lambda: Dummy(zero=True, infinite=True)) + + +def test_issue_8642(): + x = Symbol('x', real=True, integer=False) + assert (x*2).is_integer is None, (x*2).is_integer + + +def test_issues_8632_8633_8638_8675_8992(): + p = Dummy(integer=True, positive=True) + nn = Dummy(integer=True, nonnegative=True) + assert (p - S.Half).is_positive + assert (p - 1).is_nonnegative + assert (nn + 1).is_positive + assert (-p + 1).is_nonpositive + assert (-nn - 1).is_negative + prime = Dummy(prime=True) + assert (prime - 2).is_nonnegative + assert (prime - 3).is_nonnegative is None + even = Dummy(positive=True, even=True) + assert (even - 2).is_nonnegative + + p = Dummy(positive=True) + assert (p/(p + 1) - 1).is_negative + assert ((p + 2)**3 - S.Half).is_positive + n = Dummy(negative=True) + assert (n - 3).is_nonpositive + + +def test_issue_9115_9150(): + n = Dummy('n', integer=True, nonnegative=True) + assert (factorial(n) >= 1) == True + assert (factorial(n) < 1) == False + + assert factorial(n + 1).is_even is None + assert factorial(n + 2).is_even is True + assert factorial(n + 2) >= 2 + + +def test_issue_9165(): + z = Symbol('z', zero=True) + f = Symbol('f', finite=False) + assert 0/z is S.NaN + assert 0*(1/z) is S.NaN + assert 0*f is S.NaN + + +def test_issue_10024(): + x = Dummy('x') + assert Mod(x, 2*pi).is_zero is None + + +def test_issue_10302(): + x = Symbol('x') + r = Symbol('r', real=True) + u = -(3*2**pi)**(1/pi) + 2*3**(1/pi) + i = u + u*I + + assert i.is_real is None # w/o simplification this should fail + assert (u + i).is_zero is None + assert (1 + i).is_zero is False + + a = Dummy('a', zero=True) + assert (a + I).is_zero is False + assert (a + r*I).is_zero is None + assert (a + I).is_imaginary + assert (a + x + I).is_imaginary is None + assert (a + r*I + I).is_imaginary is None + + +def test_complex_reciprocal_imaginary(): + assert (1 / (4 + 3*I)).is_imaginary is False + + +def test_issue_16313(): + x = Symbol('x', extended_real=False) + k = Symbol('k', real=True) + l = Symbol('l', real=True, zero=False) + assert (-x).is_real is False + assert (k*x).is_real is None # k can be zero also + assert (l*x).is_real is False + assert (l*x*x).is_real is None # since x*x can be a real number + assert (-x).is_positive is False + + +def test_issue_16579(): + # extended_real -> finite | infinite + x = Symbol('x', extended_real=True, infinite=False) + y = Symbol('y', extended_real=True, finite=False) + assert x.is_finite is True + assert y.is_infinite is True + + # With PR 16978, complex now implies finite + c = Symbol('c', complex=True) + assert c.is_finite is True + raises(InconsistentAssumptions, lambda: Dummy(complex=True, finite=False)) + + # Now infinite == !finite + nf = Symbol('nf', finite=False) + assert nf.is_infinite is True + + +def test_issue_17556(): + z = I*oo + assert z.is_imaginary is False + assert z.is_finite is False + + +def test_issue_21651(): + k = Symbol('k', positive=True, integer=True) + exp = 2*2**(-k) + assert exp.is_integer is None + + +def test_assumptions_copy(): + assert assumptions(Symbol('x'), {"commutative": True} + ) == {'commutative': True} + assert assumptions(Symbol('x'), ['integer']) == {} + assert assumptions(Symbol('x'), ['commutative'] + ) == {'commutative': True} + assert assumptions(Symbol('x')) == {'commutative': True} + assert assumptions(1)['positive'] + assert assumptions(3 + I) == { + 'algebraic': True, + 'commutative': True, + 'complex': True, + 'composite': False, + 'even': False, + 'extended_negative': False, + 'extended_nonnegative': False, + 'extended_nonpositive': False, + 'extended_nonzero': False, + 'extended_positive': False, + 'extended_real': False, + 'finite': True, + 'imaginary': False, + 'infinite': False, + 'integer': False, + 'irrational': False, + 'negative': False, + 'noninteger': False, + 'nonnegative': False, + 'nonpositive': False, + 'nonzero': False, + 'odd': False, + 'positive': False, + 'prime': False, + 'rational': False, + 'real': False, + 'transcendental': False, + 'zero': False} + + +def test_check_assumptions(): + assert check_assumptions(1, 0) is False + x = Symbol('x', positive=True) + assert check_assumptions(1, x) is True + assert check_assumptions(1, 1) is True + assert check_assumptions(-1, 1) is False + i = Symbol('i', integer=True) + # don't know if i is positive (or prime, etc...) + assert check_assumptions(i, 1) is None + assert check_assumptions(Dummy(integer=None), integer=True) is None + assert check_assumptions(Dummy(integer=None), integer=False) is None + assert check_assumptions(Dummy(integer=False), integer=True) is False + assert check_assumptions(Dummy(integer=True), integer=False) is False + # no T/F assumptions to check + assert check_assumptions(Dummy(integer=False), integer=None) is True + raises(ValueError, lambda: check_assumptions(2*x, x, positive=True)) + + +def test_failing_assumptions(): + x = Symbol('x', positive=True) + y = Symbol('y') + assert failing_assumptions(6*x + y, **x.assumptions0) == \ + {'real': None, 'imaginary': None, 'complex': None, 'hermitian': None, + 'positive': None, 'nonpositive': None, 'nonnegative': None, 'nonzero': None, + 'negative': None, 'zero': None, 'extended_real': None, 'finite': None, + 'infinite': None, 'extended_negative': None, 'extended_nonnegative': None, + 'extended_nonpositive': None, 'extended_nonzero': None, + 'extended_positive': None } + + +def test_common_assumptions(): + assert common_assumptions([0, 1, 2] + ) == {'algebraic': True, 'irrational': False, 'hermitian': + True, 'extended_real': True, 'real': True, 'extended_negative': + False, 'extended_nonnegative': True, 'integer': True, + 'rational': True, 'imaginary': False, 'complex': True, + 'commutative': True,'noninteger': False, 'composite': False, + 'infinite': False, 'nonnegative': True, 'finite': True, + 'transcendental': False,'negative': False} + assert common_assumptions([0, 1, 2], 'positive integer'.split() + ) == {'integer': True} + assert common_assumptions([0, 1, 2], []) == {} + assert common_assumptions([], ['integer']) == {} + assert common_assumptions([0], ['integer']) == {'integer': True} + +def test_pre_generated_assumption_rules_are_valid(): + # check the pre-generated assumptions match freshly generated assumptions + # if this check fails, consider updating the assumptions + # see sympy.core.assumptions._generate_assumption_rules + pre_generated_assumptions =_load_pre_generated_assumption_rules() + generated_assumptions =_generate_assumption_rules() + assert pre_generated_assumptions._to_python() == generated_assumptions._to_python(), "pre-generated assumptions are invalid, see sympy.core.assumptions._generate_assumption_rules" + + +def test_ask_shuffle(): + grp = PermutationGroup(Permutation(1, 0, 2), Permutation(2, 1, 3)) + + seed(123) + first = grp.random() + seed(123) + simplify(I) + second = grp.random() + seed(123) + simplify(-I) + third = grp.random() + + assert first == second == third diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_basic.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..44faf93162f0df8bd7d749d99f21c98d79a1ef41 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_basic.py @@ -0,0 +1,333 @@ +"""This tests sympy/core/basic.py with (ideally) no reference to subclasses +of Basic or Atom.""" +import collections +from typing import TypeVar, Generic + +from sympy.assumptions.ask import Q +from sympy.core.basic import (Basic, Atom, as_Basic, + _atomic, _aresame) +from sympy.core.containers import Tuple +from sympy.core.function import Function, Lambda +from sympy.core.numbers import I, pi, Float +from sympy.core.singleton import S +from sympy.core.symbol import symbols, Symbol, Dummy +from sympy.concrete.summations import Sum +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.gamma_functions import gamma +from sympy.integrals.integrals import Integral +from sympy.functions.elementary.exponential import exp +from sympy.testing.pytest import raises, warns_deprecated_sympy + +b1 = Basic() +b2 = Basic(b1) +b3 = Basic(b2) +b21 = Basic(b2, b1) +T = TypeVar('T') + + +def test__aresame(): + assert not _aresame(Basic(Tuple()), Basic()) + for i, j in [(S(2), S(2.)), (1., Float(1))]: + for do in range(2): + assert not _aresame(Basic(i), Basic(j)) + assert not _aresame(i, j) + i, j = j, i + + +def test_structure(): + assert b21.args == (b2, b1) + assert b21.func(*b21.args) == b21 + assert bool(b1) + + +def test_immutable(): + assert not hasattr(b1, '__dict__') + with raises(AttributeError): + b1.x = 1 + + +def test_equality(): + instances = [b1, b2, b3, b21, Basic(b1, b1, b1), Basic] + for i, b_i in enumerate(instances): + for j, b_j in enumerate(instances): + assert (b_i == b_j) == (i == j) + assert (b_i != b_j) == (i != j) + + assert Basic() != [] + assert not(Basic() == []) + assert Basic() != 0 + assert not(Basic() == 0) + + class Foo: + """ + Class that is unaware of Basic, and relies on both classes returning + the NotImplemented singleton for equivalence to evaluate to False. + + """ + + b = Basic() + foo = Foo() + + assert b != foo + assert foo != b + assert not b == foo + assert not foo == b + + class Bar: + """ + Class that considers itself equal to any instance of Basic, and relies + on Basic returning the NotImplemented singleton in order to achieve + a symmetric equivalence relation. + + """ + def __eq__(self, other): + if isinstance(other, Basic): + return True + return NotImplemented + + def __ne__(self, other): + return not self == other + + bar = Bar() + + assert b == bar + assert bar == b + assert not b != bar + assert not bar != b + + +def test_matches_basic(): + instances = [Basic(b1, b1, b2), Basic(b1, b2, b1), Basic(b2, b1, b1), + Basic(b1, b2), Basic(b2, b1), b2, b1] + for i, b_i in enumerate(instances): + for j, b_j in enumerate(instances): + if i == j: + assert b_i.matches(b_j) == {} + else: + assert b_i.matches(b_j) is None + assert b1.match(b1) == {} + + +def test_has(): + assert b21.has(b1) + assert b21.has(b3, b1) + assert b21.has(Basic) + assert not b1.has(b21, b3) + assert not b21.has() + assert not b21.has(str) + assert not Symbol("x").has("x") + + +def test_subs(): + assert b21.subs(b2, b1) == Basic(b1, b1) + assert b21.subs(b2, b21) == Basic(b21, b1) + assert b3.subs(b2, b1) == b2 + + assert b21.subs([(b2, b1), (b1, b2)]) == Basic(b2, b2) + + assert b21.subs({b1: b2, b2: b1}) == Basic(b2, b2) + assert b21.subs(collections.ChainMap({b1: b2}, {b2: b1})) == Basic(b2, b2) + assert b21.subs(collections.OrderedDict([(b2, b1), (b1, b2)])) == Basic(b2, b2) + + raises(ValueError, lambda: b21.subs('bad arg')) + raises(ValueError, lambda: b21.subs(b1, b2, b3)) + # dict(b1=foo) creates a string 'b1' but leaves foo unchanged; subs + # will convert the first to a symbol but will raise an error if foo + # cannot be sympified; sympification is strict if foo is not string + raises(ValueError, lambda: b21.subs(b1='bad arg')) + + assert Symbol("text").subs({"text": b1}) == b1 + assert Symbol("s").subs({"s": 1}) == 1 + + +def test_subs_with_unicode_symbols(): + expr = Symbol('var1') + replaced = expr.subs('var1', 'x') + assert replaced.name == 'x' + + replaced = expr.subs('var1', 'x') + assert replaced.name == 'x' + + +def test_atoms(): + assert b21.atoms() == {Basic()} + + +def test_free_symbols_empty(): + assert b21.free_symbols == set() + + +def test_doit(): + assert b21.doit() == b21 + assert b21.doit(deep=False) == b21 + + +def test_S(): + assert repr(S) == 'S' + + +def test_xreplace(): + assert b21.xreplace({b2: b1}) == Basic(b1, b1) + assert b21.xreplace({b2: b21}) == Basic(b21, b1) + assert b3.xreplace({b2: b1}) == b2 + assert Basic(b1, b2).xreplace({b1: b2, b2: b1}) == Basic(b2, b1) + assert Atom(b1).xreplace({b1: b2}) == Atom(b1) + assert Atom(b1).xreplace({Atom(b1): b2}) == b2 + raises(TypeError, lambda: b1.xreplace()) + raises(TypeError, lambda: b1.xreplace([b1, b2])) + for f in (exp, Function('f')): + assert f.xreplace({}) == f + assert f.xreplace({}, hack2=True) == f + assert f.xreplace({f: b1}) == b1 + assert f.xreplace({f: b1}, hack2=True) == b1 + + +def test_sorted_args(): + x = symbols('x') + assert b21._sorted_args == b21.args + raises(AttributeError, lambda: x._sorted_args) + +def test_call(): + x, y = symbols('x y') + # See the long history of this in issues 5026 and 5105. + + raises(TypeError, lambda: sin(x)({ x : 1, sin(x) : 2})) + raises(TypeError, lambda: sin(x)(1)) + + # No effect as there are no callables + assert sin(x).rcall(1) == sin(x) + assert (1 + sin(x)).rcall(1) == 1 + sin(x) + + # Effect in the pressence of callables + l = Lambda(x, 2*x) + assert (l + x).rcall(y) == 2*y + x + assert (x**l).rcall(2) == x**4 + # TODO UndefinedFunction does not subclass Expr + #f = Function('f') + #assert (2*f)(x) == 2*f(x) + + assert (Q.real & Q.positive).rcall(x) == Q.real(x) & Q.positive(x) + + +def test_rewrite(): + x, y, z = symbols('x y z') + a, b = symbols('a b') + f1 = sin(x) + cos(x) + assert f1.rewrite(cos,exp) == exp(I*x)/2 + sin(x) + exp(-I*x)/2 + assert f1.rewrite([cos],sin) == sin(x) + sin(x + pi/2, evaluate=False) + f2 = sin(x) + cos(y)/gamma(z) + assert f2.rewrite(sin,exp) == -I*(exp(I*x) - exp(-I*x))/2 + cos(y)/gamma(z) + + assert f1.rewrite() == f1 + +def test_literal_evalf_is_number_is_zero_is_comparable(): + x = symbols('x') + f = Function('f') + + # issue 5033 + assert f.is_number is False + # issue 6646 + assert f(1).is_number is False + i = Integral(0, (x, x, x)) + # expressions that are symbolically 0 can be difficult to prove + # so in case there is some easy way to know if something is 0 + # it should appear in the is_zero property for that object; + # if is_zero is true evalf should always be able to compute that + # zero + assert i.n() == 0 + assert i.is_zero + assert i.is_number is False + assert i.evalf(2, strict=False) == 0 + + # issue 10268 + n = sin(1)**2 + cos(1)**2 - 1 + assert n.is_comparable is False + assert n.n(2).is_comparable is False + assert n.n(2).n(2).is_comparable + + +def test_as_Basic(): + assert as_Basic(1) is S.One + assert as_Basic(()) == Tuple() + raises(TypeError, lambda: as_Basic([])) + + +def test_atomic(): + g, h = map(Function, 'gh') + x = symbols('x') + assert _atomic(g(x + h(x))) == {g(x + h(x))} + assert _atomic(g(x + h(x)), recursive=True) == {h(x), x, g(x + h(x))} + assert _atomic(1) == set() + assert _atomic(Basic(S(1), S(2))) == set() + + +def test_as_dummy(): + u, v, x, y, z, _0, _1 = symbols('u v x y z _0 _1') + assert Lambda(x, x + 1).as_dummy() == Lambda(_0, _0 + 1) + assert Lambda(x, x + _0).as_dummy() == Lambda(_1, _0 + _1) + eq = (1 + Sum(x, (x, 1, x))) + ans = 1 + Sum(_0, (_0, 1, x)) + once = eq.as_dummy() + assert once == ans + twice = once.as_dummy() + assert twice == ans + assert Integral(x + _0, (x, x + 1), (_0, 1, 2) + ).as_dummy() == Integral(_0 + _1, (_0, x + 1), (_1, 1, 2)) + for T in (Symbol, Dummy): + d = T('x', real=True) + D = d.as_dummy() + assert D != d and D.func == Dummy and D.is_real is None + assert Dummy().as_dummy().is_commutative + assert Dummy(commutative=False).as_dummy().is_commutative is False + + +def test_canonical_variables(): + x, i0, i1 = symbols('x _:2') + assert Integral(x, (x, x + 1)).canonical_variables == {x: i0} + assert Integral(x, (x, x + 1), (i0, 1, 2)).canonical_variables == { + x: i0, i0: i1} + assert Integral(x, (x, x + i0)).canonical_variables == {x: i1} + + +def test_replace_exceptions(): + from sympy.core.symbol import Wild + x, y = symbols('x y') + e = (x**2 + x*y) + raises(TypeError, lambda: e.replace(sin, 2)) + b = Wild('b') + c = Wild('c') + raises(TypeError, lambda: e.replace(b*c, c.is_real)) + raises(TypeError, lambda: e.replace(b.is_real, 1)) + raises(TypeError, lambda: e.replace(lambda d: d.is_Number, 1)) + + +def test_ManagedProperties(): + # ManagedProperties is now deprecated. Here we do our best to check that if + # someone is using it then it does work in the way that it previously did + # but gives a deprecation warning. + from sympy.core.assumptions import ManagedProperties + + myclasses = [] + + class MyMeta(ManagedProperties): + def __init__(cls, *args, **kwargs): + myclasses.append('executed') + super().__init__(*args, **kwargs) + + code = """ +class MySubclass(Basic, metaclass=MyMeta): + pass +""" + with warns_deprecated_sympy(): + exec(code) + + assert myclasses == ['executed'] + + +def test_generic(): + # https://github.com/sympy/sympy/issues/25399 + class A(Symbol, Generic[T]): + pass + + class B(A[T]): + pass diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_cache.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_cache.py new file mode 100644 index 0000000000000000000000000000000000000000..9124fca70718299252929a9923f335dde25256eb --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_cache.py @@ -0,0 +1,91 @@ +import sys +from sympy.core.cache import cacheit, cached_property, lazy_function +from sympy.testing.pytest import raises + +def test_cacheit_doc(): + @cacheit + def testfn(): + "test docstring" + pass + + assert testfn.__doc__ == "test docstring" + assert testfn.__name__ == "testfn" + +def test_cacheit_unhashable(): + @cacheit + def testit(x): + return x + + assert testit(1) == 1 + assert testit(1) == 1 + a = {} + assert testit(a) == {} + a[1] = 2 + assert testit(a) == {1: 2} + +def test_cachit_exception(): + # Make sure the cache doesn't call functions multiple times when they + # raise TypeError + + a = [] + + @cacheit + def testf(x): + a.append(0) + raise TypeError + + raises(TypeError, lambda: testf(1)) + assert len(a) == 1 + + a.clear() + # Unhashable type + raises(TypeError, lambda: testf([])) + assert len(a) == 1 + + @cacheit + def testf2(x): + a.append(0) + raise TypeError("Error") + + a.clear() + raises(TypeError, lambda: testf2(1)) + assert len(a) == 1 + + a.clear() + # Unhashable type + raises(TypeError, lambda: testf2([])) + assert len(a) == 1 + +def test_cached_property(): + class A: + def __init__(self, value): + self.value = value + self.calls = 0 + + @cached_property + def prop(self): + self.calls = self.calls + 1 + return self.value + + a = A(2) + assert a.calls == 0 + assert a.prop == 2 + assert a.calls == 1 + assert a.prop == 2 + assert a.calls == 1 + b = A(None) + assert b.prop == None + + +def test_lazy_function(): + module_name='xmlrpc.client' + function_name = 'gzip_decode' + lazy = lazy_function(module_name, function_name) + assert lazy(b'') == b'' + assert module_name in sys.modules + assert function_name in str(lazy) + repr_lazy = repr(lazy) + assert 'LazyFunction' in repr_lazy + assert function_name in repr_lazy + + lazy = lazy_function('sympy.core.cache', 'cheap') diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_compatibility.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_compatibility.py new file mode 100644 index 0000000000000000000000000000000000000000..31d2bed07b21aa2fa489273dca9edfc9993cfd86 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_compatibility.py @@ -0,0 +1,6 @@ +from sympy.testing.pytest import warns_deprecated_sympy + +def test_compatibility_submodule(): + # Test the sympy.core.compatibility deprecation warning + with warns_deprecated_sympy(): + import sympy.core.compatibility # noqa:F401 diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_complex.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_complex.py new file mode 100644 index 0000000000000000000000000000000000000000..a607e0bdb4db859336aa30aa61f43bfb57d5df88 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_complex.py @@ -0,0 +1,226 @@ +from sympy.core.function import expand_complex +from sympy.core.numbers import (I, Integer, Rational, pi) +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import (Abs, conjugate, im, re, sign) +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.hyperbolic import (cosh, coth, sinh, tanh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, cot, sin, tan) + +def test_complex(): + a = Symbol("a", real=True) + b = Symbol("b", real=True) + e = (a + I*b)*(a - I*b) + assert e.expand() == a**2 + b**2 + assert sqrt(I) == Pow(I, S.Half) + + +def test_conjugate(): + a = Symbol("a", real=True) + b = Symbol("b", real=True) + c = Symbol("c", imaginary=True) + d = Symbol("d", imaginary=True) + x = Symbol('x') + z = a + I*b + c + I*d + zc = a - I*b - c + I*d + assert conjugate(z) == zc + assert conjugate(exp(z)) == exp(zc) + assert conjugate(exp(I*x)) == exp(-I*conjugate(x)) + assert conjugate(z**5) == zc**5 + assert conjugate(abs(x)) == abs(x) + assert conjugate(sign(z)) == sign(zc) + assert conjugate(sin(z)) == sin(zc) + assert conjugate(cos(z)) == cos(zc) + assert conjugate(tan(z)) == tan(zc) + assert conjugate(cot(z)) == cot(zc) + assert conjugate(sinh(z)) == sinh(zc) + assert conjugate(cosh(z)) == cosh(zc) + assert conjugate(tanh(z)) == tanh(zc) + assert conjugate(coth(z)) == coth(zc) + + +def test_abs1(): + a = Symbol("a", real=True) + b = Symbol("b", real=True) + assert abs(a) == Abs(a) + assert abs(-a) == abs(a) + assert abs(a + I*b) == sqrt(a**2 + b**2) + + +def test_abs2(): + a = Symbol("a", real=False) + b = Symbol("b", real=False) + assert abs(a) != a + assert abs(-a) != a + assert abs(a + I*b) != sqrt(a**2 + b**2) + + +def test_evalc(): + x = Symbol("x", real=True) + y = Symbol("y", real=True) + z = Symbol("z") + assert ((x + I*y)**2).expand(complex=True) == x**2 + 2*I*x*y - y**2 + assert expand_complex(z**(2*I)) == (re((re(z) + I*im(z))**(2*I)) + + I*im((re(z) + I*im(z))**(2*I))) + assert expand_complex( + z**(2*I), deep=False) == I*im(z**(2*I)) + re(z**(2*I)) + + assert exp(I*x) != cos(x) + I*sin(x) + assert exp(I*x).expand(complex=True) == cos(x) + I*sin(x) + assert exp(I*x + y).expand(complex=True) == exp(y)*cos(x) + I*sin(x)*exp(y) + + assert sin(I*x).expand(complex=True) == I * sinh(x) + assert sin(x + I*y).expand(complex=True) == sin(x)*cosh(y) + \ + I * sinh(y) * cos(x) + + assert cos(I*x).expand(complex=True) == cosh(x) + assert cos(x + I*y).expand(complex=True) == cos(x)*cosh(y) - \ + I * sinh(y) * sin(x) + + assert tan(I*x).expand(complex=True) == tanh(x) * I + assert tan(x + I*y).expand(complex=True) == ( + sin(2*x)/(cos(2*x) + cosh(2*y)) + + I*sinh(2*y)/(cos(2*x) + cosh(2*y))) + + assert sinh(I*x).expand(complex=True) == I * sin(x) + assert sinh(x + I*y).expand(complex=True) == sinh(x)*cos(y) + \ + I * sin(y) * cosh(x) + + assert cosh(I*x).expand(complex=True) == cos(x) + assert cosh(x + I*y).expand(complex=True) == cosh(x)*cos(y) + \ + I * sin(y) * sinh(x) + + assert tanh(I*x).expand(complex=True) == tan(x) * I + assert tanh(x + I*y).expand(complex=True) == ( + (sinh(x)*cosh(x) + I*cos(y)*sin(y)) / + (sinh(x)**2 + cos(y)**2)).expand() + + +def test_pythoncomplex(): + x = Symbol("x") + assert 4j*x != 4*x*I + assert 4j*x == 4.0*x*I + assert 4.1j*x != 4*x*I + + +def test_rootcomplex(): + R = Rational + assert ((+1 + I)**R(1, 2)).expand( + complex=True) == 2**R(1, 4)*cos( pi/8) + 2**R(1, 4)*sin( pi/8)*I + assert ((-1 - I)**R(1, 2)).expand( + complex=True) == 2**R(1, 4)*cos(3*pi/8) - 2**R(1, 4)*sin(3*pi/8)*I + assert (sqrt(-10)*I).as_real_imag() == (-sqrt(10), 0) + + +def test_expand_inverse(): + assert (1/(1 + I)).expand(complex=True) == (1 - I)/2 + assert ((1 + 2*I)**(-2)).expand(complex=True) == (-3 - 4*I)/25 + assert ((1 + I)**(-8)).expand(complex=True) == Rational(1, 16) + + +def test_expand_complex(): + assert ((2 + 3*I)**10).expand(complex=True) == -341525 - 145668*I + # the following two tests are to ensure the SymPy uses an efficient + # algorithm for calculating powers of complex numbers. They should execute + # in something like 0.01s. + assert ((2 + 3*I)**1000).expand(complex=True) == \ + -81079464736246615951519029367296227340216902563389546989376269312984127074385455204551402940331021387412262494620336565547972162814110386834027871072723273110439771695255662375718498785908345629702081336606863762777939617745464755635193139022811989314881997210583159045854968310911252660312523907616129080027594310008539817935736331124833163907518549408018652090650537035647520296539436440394920287688149200763245475036722326561143851304795139005599209239350981457301460233967137708519975586996623552182807311159141501424576682074392689622074945519232029999 + \ + 46938745946789557590804551905243206242164799136976022474337918748798900569942573265747576032611189047943842446167719177749107138603040963603119861476016947257034472364028585381714774667326478071264878108114128915685688115488744955550920239128462489496563930809677159214598114273887061533057125164518549173898349061972857446844052995037423459472376202251620778517659247970283904820245958198842631651569984310559418135975795868314764489884749573052997832686979294085577689571149679540256349988338406458116270429842222666345146926395233040564229555893248370000*I + assert ((2 + 3*I/4)**1000).expand(complex=True) == \ + Integer(1)*37079892761199059751745775382463070250205990218394308874593455293485167797989691280095867197640410033222367257278387021789651672598831503296531725827158233077451476545928116965316544607115843772405184272449644892857783761260737279675075819921259597776770965829089907990486964515784097181964312256560561065607846661496055417619388874421218472707497847700629822858068783288579581649321248495739224020822198695759609598745114438265083593711851665996586461937988748911532242908776883696631067311443171682974330675406616373422505939887984366289623091300746049101284856530270685577940283077888955692921951247230006346681086274961362500646889925803654263491848309446197554307105991537357310209426736453173441104334496173618419659521888945605315751089087820455852582920963561495787655250624781448951403353654348109893478206364632640344111022531861683064175862889459084900614967785405977231549003280842218501570429860550379522498497412180001/114813069527425452423283320117768198402231770208869520047764273682576626139237031385665948631650626991844596463898746277344711896086305533142593135616665318539129989145312280000688779148240044871428926990063486244781615463646388363947317026040466353970904996558162398808944629605623311649536164221970332681344168908984458505602379484807914058900934776500429002716706625830522008132236281291761267883317206598995396418127021779858404042159853183251540889433902091920554957783589672039160081957216630582755380425583726015528348786419432054508915275783882625175435528800822842770817965453762184851149029376 + \ + I*421638390580169706973991429333213477486930178424989246669892530737775352519112934278994501272111385966211392610029433824534634841747911783746811994443436271013377059560245191441549885048056920190833693041257216263519792201852046825443439142932464031501882145407459174948712992271510309541474392303461939389368955986650538525895866713074543004916049550090364398070215427272240155060576252568700906004691224321432509053286859100920489253598392100207663785243368195857086816912514025693453058403158416856847185079684216151337200057494966741268925263085619240941610301610538225414050394612058339070756009433535451561664522479191267503989904464718368605684297071150902631208673621618217106272361061676184840810762902463998065947687814692402219182668782278472952758690939877465065070481351343206840649517150634973307937551168752642148704904383991876969408056379195860410677814566225456558230131911142229028179902418223009651437985670625/1793954211366022694113801876840128100034871409513586250746316776290259783425578615401030447369541046747571819748417910583511123376348523955353017744010395602173906080395504375010762174191250701116076984219741972574712741619474818186676828531882286780795390571221287481389759837587864244524002565968286448146002639202882164150037179450123657170327105882819203167448541028601906377066191895183769810676831353109303069033234715310287563158747705988305326397404720186258671215368588625611876280581509852855552819149745718992630449787803625851701801184123166018366180137512856918294030710215034138299203584 + assert ((2 + 3*I)**-1000).expand(complex=True) == \ + Integer(1)*-81079464736246615951519029367296227340216902563389546989376269312984127074385455204551402940331021387412262494620336565547972162814110386834027871072723273110439771695255662375718498785908345629702081336606863762777939617745464755635193139022811989314881997210583159045854968310911252660312523907616129080027594310008539817935736331124833163907518549408018652090650537035647520296539436440394920287688149200763245475036722326561143851304795139005599209239350981457301460233967137708519975586996623552182807311159141501424576682074392689622074945519232029999/8777125472973511649630750050295188683351430110097915876250894978429797369155961290321829625004920141758416719066805645579710744290541337680113772670040386863849283653078324415471816788604945889094925784900885812724984087843737442111926413818245854362613018058774368703971604921858023116665586358870612944209398056562604561248859926344335598822815885851096698226775053153403320782439987679978321289537645645163767251396759519805603090332694449553371530571613352311006350058217982509738362083094920649452123351717366337410243853659113315547584871655479914439219520157174729130746351059075207407866012574386726064196992865627149566238044625779078186624347183905913357718850537058578084932880569701242598663149911276357125355850792073635533676541250531086757377369962506979378337216411188347761901006460813413505861461267545723590468627854202034450569581626648934062198718362303420281555886394558137408159453103395918783625713213314350531051312551733021627153081075080140680608080529736975658786227362251632725009435866547613598753584705455955419696609282059191031962604169242974038517575645939316377801594539335940001 - Integer(1)*46938745946789557590804551905243206242164799136976022474337918748798900569942573265747576032611189047943842446167719177749107138603040963603119861476016947257034472364028585381714774667326478071264878108114128915685688115488744955550920239128462489496563930809677159214598114273887061533057125164518549173898349061972857446844052995037423459472376202251620778517659247970283904820245958198842631651569984310559418135975795868314764489884749573052997832686979294085577689571149679540256349988338406458116270429842222666345146926395233040564229555893248370000*I/8777125472973511649630750050295188683351430110097915876250894978429797369155961290321829625004920141758416719066805645579710744290541337680113772670040386863849283653078324415471816788604945889094925784900885812724984087843737442111926413818245854362613018058774368703971604921858023116665586358870612944209398056562604561248859926344335598822815885851096698226775053153403320782439987679978321289537645645163767251396759519805603090332694449553371530571613352311006350058217982509738362083094920649452123351717366337410243853659113315547584871655479914439219520157174729130746351059075207407866012574386726064196992865627149566238044625779078186624347183905913357718850537058578084932880569701242598663149911276357125355850792073635533676541250531086757377369962506979378337216411188347761901006460813413505861461267545723590468627854202034450569581626648934062198718362303420281555886394558137408159453103395918783625713213314350531051312551733021627153081075080140680608080529736975658786227362251632725009435866547613598753584705455955419696609282059191031962604169242974038517575645939316377801594539335940001 + assert ((2 + 3*I/4)**-1000).expand(complex=True) == \ + Integer(1)*4257256305661027385394552848555894604806501409793288342610746813288539790051927148781268212212078237301273165351052934681382567968787279534591114913777456610214738290619922068269909423637926549603264174216950025398244509039145410016404821694746262142525173737175066432954496592560621330313807235750500564940782099283410261748370262433487444897446779072067625787246390824312580440138770014838135245148574339248259670887549732495841810961088930810608893772914812838358159009303794863047635845688453859317690488124382253918725010358589723156019888846606295866740117645571396817375322724096486161308083462637370825829567578309445855481578518239186117686659177284332344643124760453112513611749309168470605289172320376911472635805822082051716625171429727162039621902266619821870482519063133136820085579315127038372190224739238686708451840610064871885616258831386810233957438253532027049148030157164346719204500373766157143311767338973363806106967439378604898250533766359989107510507493549529158818602327525235240510049484816090584478644771183158342479140194633579061295740839490629457435283873180259847394582069479062820225159699506175855369539201399183443253793905149785994830358114153241481884290274629611529758663543080724574566578220908907477622643689220814376054314972190402285121776593824615083669045183404206291739005554569305329760211752815718335731118664756831942466773261465213581616104242113894521054475516019456867271362053692785300826523328020796670205463390909136593859765912483565093461468865534470710132881677639651348709376/2103100954337624833663208713697737151593634525061637972297915388685604042449504336765884978184588688426595940401280828953096857809292320006227881797146858511436638446932833617514351442216409828605662238790280753075176269765767010004889778647709740770757817960711900340755635772183674511158570690702969774966791073165467918123298694584729211212414462628433370481195120564586361368504153395406845170075275051749019600057116719726628746724489572189061061036426955163696859127711110719502594479795200686212257570291758725259007379710596548777812659422174199194837355646482046783616494013289495563083118517507178847555801163089723056310287760875135196081975602765511153122381201303871673391366630940702817360340900568748719988954847590748960761446218262344767250783946365392689256634180417145926390656439421745644011831124277463643383712803287985472471755648426749842410972650924240795946699346613614779460399530274263580007672855851663196114585312432954432654691485867618908420370875753749297487803461900447407917655296784879220450937110470920633595689721819488638484547259978337741496090602390463594556401615298457456112485536498177883358587125449801777718900375736758266215245325999241624148841915093787519330809347240990363802360596034171167818310322276373120180985148650099673289383722502488957717848531612020897298448601714154586319660314294591620415272119454982220034319689607295960162971300417552364254983071768070124456169427638371140064235083443242844616326538396503937972586505546495649094344512270582463639152160238137952390380581401171977159154009407415523525096743009110916334144716516647041176989758534635251844947906038080852185583742296318878233394998111078843229681030277039104786225656992262073797524057992347971177720807155842376332851559276430280477639539393920006008737472164850104411971830120295750221200029811143140323763349636629725073624360001 - Integer(1)*3098214262599218784594285246258841485430681674561917573155883806818465520660668045042109232930382494608383663464454841313154390741655282039877410154577448327874989496074260116195788919037407420625081798124301494353693248757853222257918294662198297114746822817460991242508743651430439120439020484502408313310689912381846149597061657483084652685283853595100434135149479564507015504022249330340259111426799121454516345905101620532787348293877485702600390665276070250119465888154331218827342488849948540687659846652377277250614246402784754153678374932540789808703029043827352976139228402417432199779415751301480406673762521987999573209628597459357964214510139892316208670927074795773830798600837815329291912002136924506221066071242281626618211060464126372574400100990746934953437169840312584285942093951405864225230033279614235191326102697164613004299868695519642598882914862568516635347204441042798206770888274175592401790040170576311989738272102077819127459014286741435419468254146418098278519775722104890854275995510700298782146199325790002255362719776098816136732897323406228294203133323296591166026338391813696715894870956511298793595675308998014158717167429941371979636895553724830981754579086664608880698350866487717403917070872269853194118364230971216854931998642990452908852258008095741042117326241406479532880476938937997238098399302185675832474590293188864060116934035867037219176916416481757918864533515526389079998129329045569609325290897577497835388451456680707076072624629697883854217331728051953671643278797380171857920000*I/2103100954337624833663208713697737151593634525061637972297915388685604042449504336765884978184588688426595940401280828953096857809292320006227881797146858511436638446932833617514351442216409828605662238790280753075176269765767010004889778647709740770757817960711900340755635772183674511158570690702969774966791073165467918123298694584729211212414462628433370481195120564586361368504153395406845170075275051749019600057116719726628746724489572189061061036426955163696859127711110719502594479795200686212257570291758725259007379710596548777812659422174199194837355646482046783616494013289495563083118517507178847555801163089723056310287760875135196081975602765511153122381201303871673391366630940702817360340900568748719988954847590748960761446218262344767250783946365392689256634180417145926390656439421745644011831124277463643383712803287985472471755648426749842410972650924240795946699346613614779460399530274263580007672855851663196114585312432954432654691485867618908420370875753749297487803461900447407917655296784879220450937110470920633595689721819488638484547259978337741496090602390463594556401615298457456112485536498177883358587125449801777718900375736758266215245325999241624148841915093787519330809347240990363802360596034171167818310322276373120180985148650099673289383722502488957717848531612020897298448601714154586319660314294591620415272119454982220034319689607295960162971300417552364254983071768070124456169427638371140064235083443242844616326538396503937972586505546495649094344512270582463639152160238137952390380581401171977159154009407415523525096743009110916334144716516647041176989758534635251844947906038080852185583742296318878233394998111078843229681030277039104786225656992262073797524057992347971177720807155842376332851559276430280477639539393920006008737472164850104411971830120295750221200029811143140323763349636629725073624360001 + + a = Symbol('a', real=True) + b = Symbol('b', real=True) + assert exp(a*(2 + I*b)).expand(complex=True) == \ + I*exp(2*a)*sin(a*b) + exp(2*a)*cos(a*b) + + +def test_expand(): + f = (16 - 2*sqrt(29))**2 + assert f.expand() == 372 - 64*sqrt(29) + f = (Integer(1)/2 + I/2)**10 + assert f.expand() == I/32 + f = (Integer(1)/2 + I)**10 + assert f.expand() == Integer(237)/1024 - 779*I/256 + + +def test_re_im1652(): + x = Symbol('x') + assert re(x) == re(conjugate(x)) + assert im(x) == - im(conjugate(x)) + assert im(x)*re(conjugate(x)) + im(conjugate(x)) * re(x) == 0 + + +def test_issue_5084(): + x = Symbol('x') + assert ((x + x*I)/(1 + I)).as_real_imag() == (re((x + I*x)/(1 + I) + ), im((x + I*x)/(1 + I))) + + +def test_issue_5236(): + assert (cos(1 + I)**3).as_real_imag() == (-3*sin(1)**2*sinh(1)**2*cos(1)*cosh(1) + + cos(1)**3*cosh(1)**3, -3*cos(1)**2*cosh(1)**2*sin(1)*sinh(1) + sin(1)**3*sinh(1)**3) + + +def test_real_imag(): + x, y, z = symbols('x, y, z') + X, Y, Z = symbols('X, Y, Z', commutative=False) + a = Symbol('a', real=True) + assert (2*a*x).as_real_imag() == (2*a*re(x), 2*a*im(x)) + + # issue 5395: + assert (x*x.conjugate()).as_real_imag() == (Abs(x)**2, 0) + assert im(x*x.conjugate()) == 0 + assert im(x*y.conjugate()*z*y) == im(x*z)*Abs(y)**2 + assert im(x*y.conjugate()*x*y) == im(x**2)*Abs(y)**2 + assert im(Z*y.conjugate()*X*y) == im(Z*X)*Abs(y)**2 + assert im(X*X.conjugate()) == im(X*X.conjugate(), evaluate=False) + assert (sin(x)*sin(x).conjugate()).as_real_imag() == \ + (Abs(sin(x))**2, 0) + + # issue 6573: + assert (x**2).as_real_imag() == (re(x)**2 - im(x)**2, 2*re(x)*im(x)) + + # issue 6428: + r = Symbol('r', real=True) + i = Symbol('i', imaginary=True) + assert (i*r*x).as_real_imag() == (I*i*r*im(x), -I*i*r*re(x)) + assert (i*r*x*(y + 2)).as_real_imag() == ( + I*i*r*(re(y) + 2)*im(x) + I*i*r*re(x)*im(y), + -I*i*r*(re(y) + 2)*re(x) + I*i*r*im(x)*im(y)) + + # issue 7106: + assert ((1 + I)/(1 - I)).as_real_imag() == (0, 1) + assert ((1 + 2*I)*(1 + 3*I)).as_real_imag() == (-5, 5) + + +def test_pow_issue_1724(): + e = ((S.NegativeOne)**(S.One/3)) + assert e.conjugate().n() == e.n().conjugate() + e = S('-2/3 - (-29/54 + sqrt(93)/18)**(1/3) - 1/(9*(-29/54 + sqrt(93)/18)**(1/3))') + assert e.conjugate().n() == e.n().conjugate() + e = 2**I + assert e.conjugate().n() == e.n().conjugate() + + +def test_issue_5429(): + assert sqrt(I).conjugate() != sqrt(I) + +def test_issue_4124(): + from sympy.core.numbers import oo + assert expand_complex(I*oo) == oo*I + +def test_issue_11518(): + x = Symbol("x", real=True) + y = Symbol("y", real=True) + r = sqrt(x**2 + y**2) + assert conjugate(r) == r + s = abs(x + I * y) + assert conjugate(s) == r diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_constructor_postprocessor.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_constructor_postprocessor.py new file mode 100644 index 0000000000000000000000000000000000000000..c199e24eddf8ef7c2a14e38d1ad2dc95e4acc0cc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_constructor_postprocessor.py @@ -0,0 +1,87 @@ +from sympy.core.basic import Basic +from sympy.core.mul import Mul +from sympy.core.symbol import (Symbol, symbols) + +from sympy.testing.pytest import XFAIL + +class SymbolInMulOnce(Symbol): + # Test class for a symbol that can only appear once in a `Mul` expression. + pass + + +Basic._constructor_postprocessor_mapping[SymbolInMulOnce] = { + "Mul": [lambda x: x], + "Pow": [lambda x: x.base if isinstance(x.base, SymbolInMulOnce) else x], + "Add": [lambda x: x], +} + + +def _postprocess_SymbolRemovesOtherSymbols(expr): + args = tuple(i for i in expr.args if not isinstance(i, Symbol) or isinstance(i, SymbolRemovesOtherSymbols)) + if args == expr.args: + return expr + return Mul.fromiter(args) + + +class SymbolRemovesOtherSymbols(Symbol): + # Test class for a symbol that removes other symbols in `Mul`. + pass + +Basic._constructor_postprocessor_mapping[SymbolRemovesOtherSymbols] = { + "Mul": [_postprocess_SymbolRemovesOtherSymbols], +} + +class SubclassSymbolInMulOnce(SymbolInMulOnce): + pass + +class SubclassSymbolRemovesOtherSymbols(SymbolRemovesOtherSymbols): + pass + + +def test_constructor_postprocessors1(): + x = SymbolInMulOnce("x") + y = SymbolInMulOnce("y") + assert isinstance(3*x, Mul) + assert (3*x).args == (3, x) + assert x*x == x + assert 3*x*x == 3*x + assert 2*x*x + x == 3*x + assert x**3*y*y == x*y + assert x**5 + y*x**3 == x + x*y + + w = SymbolRemovesOtherSymbols("w") + assert x*w == w + assert (3*w).args == (3, w) + assert set((w + x).args) == {x, w} + +def test_constructor_postprocessors2(): + x = SubclassSymbolInMulOnce("x") + y = SubclassSymbolInMulOnce("y") + assert isinstance(3*x, Mul) + assert (3*x).args == (3, x) + assert x*x == x + assert 3*x*x == 3*x + assert 2*x*x + x == 3*x + assert x**3*y*y == x*y + assert x**5 + y*x**3 == x + x*y + + w = SubclassSymbolRemovesOtherSymbols("w") + assert x*w == w + assert (3*w).args == (3, w) + assert set((w + x).args) == {x, w} + + +@XFAIL +def test_subexpression_postprocessors(): + # The postprocessors used to work with subexpressions, but the + # functionality was removed. See #15948. + a = symbols("a") + x = SymbolInMulOnce("x") + w = SymbolRemovesOtherSymbols("w") + assert 3*a*w**2 == 3*w**2 + assert 3*a*x**3*w**2 == 3*w**2 + + x = SubclassSymbolInMulOnce("x") + w = SubclassSymbolRemovesOtherSymbols("w") + assert 3*a*w**2 == 3*w**2 + assert 3*a*x**3*w**2 == 3*w**2 diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_containers.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_containers.py new file mode 100644 index 0000000000000000000000000000000000000000..23357b9f667fffc82d93b2b1adb42b495114c67e --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_containers.py @@ -0,0 +1,217 @@ +from collections import defaultdict + +from sympy.core.basic import Basic +from sympy.core.containers import (Dict, Tuple) +from sympy.core.numbers import Integer +from sympy.core.kind import NumberKind +from sympy.matrices.kind import MatrixKind +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.core.sympify import sympify +from sympy.matrices.dense import Matrix +from sympy.sets.sets import FiniteSet +from sympy.core.containers import tuple_wrapper, TupleKind +from sympy.core.expr import unchanged +from sympy.core.function import Function, Lambda +from sympy.core.relational import Eq +from sympy.testing.pytest import raises +from sympy.utilities.iterables import is_sequence, iterable + +from sympy.abc import x, y + + +def test_Tuple(): + t = (1, 2, 3, 4) + st = Tuple(*t) + assert set(sympify(t)) == set(st) + assert len(t) == len(st) + assert set(sympify(t[:2])) == set(st[:2]) + assert isinstance(st[:], Tuple) + assert st == Tuple(1, 2, 3, 4) + assert st.func(*st.args) == st + p, q, r, s = symbols('p q r s') + t2 = (p, q, r, s) + st2 = Tuple(*t2) + assert st2.atoms() == set(t2) + assert st == st2.subs({p: 1, q: 2, r: 3, s: 4}) + # issue 5505 + assert all(isinstance(arg, Basic) for arg in st.args) + assert Tuple(p, 1).subs(p, 0) == Tuple(0, 1) + assert Tuple(p, Tuple(p, 1)).subs(p, 0) == Tuple(0, Tuple(0, 1)) + + assert Tuple(t2) == Tuple(Tuple(*t2)) + assert Tuple.fromiter(t2) == Tuple(*t2) + assert Tuple.fromiter(x for x in range(4)) == Tuple(0, 1, 2, 3) + assert st2.fromiter(st2.args) == st2 + + +def test_Tuple_contains(): + t1, t2 = Tuple(1), Tuple(2) + assert t1 in Tuple(1, 2, 3, t1, Tuple(t2)) + assert t2 not in Tuple(1, 2, 3, t1, Tuple(t2)) + + +def test_Tuple_concatenation(): + assert Tuple(1, 2) + Tuple(3, 4) == Tuple(1, 2, 3, 4) + assert (1, 2) + Tuple(3, 4) == Tuple(1, 2, 3, 4) + assert Tuple(1, 2) + (3, 4) == Tuple(1, 2, 3, 4) + raises(TypeError, lambda: Tuple(1, 2) + 3) + raises(TypeError, lambda: 1 + Tuple(2, 3)) + + #the Tuple case in __radd__ is only reached when a subclass is involved + class Tuple2(Tuple): + def __radd__(self, other): + return Tuple.__radd__(self, other + other) + assert Tuple(1, 2) + Tuple2(3, 4) == Tuple(1, 2, 1, 2, 3, 4) + assert Tuple2(1, 2) + Tuple(3, 4) == Tuple(1, 2, 3, 4) + + +def test_Tuple_equality(): + assert not isinstance(Tuple(1, 2), tuple) + assert (Tuple(1, 2) == (1, 2)) is True + assert (Tuple(1, 2) != (1, 2)) is False + assert (Tuple(1, 2) == (1, 3)) is False + assert (Tuple(1, 2) != (1, 3)) is True + assert (Tuple(1, 2) == Tuple(1, 2)) is True + assert (Tuple(1, 2) != Tuple(1, 2)) is False + assert (Tuple(1, 2) == Tuple(1, 3)) is False + assert (Tuple(1, 2) != Tuple(1, 3)) is True + + +def test_Tuple_Eq(): + assert Eq(Tuple(), Tuple()) is S.true + assert Eq(Tuple(1), 1) is S.false + assert Eq(Tuple(1, 2), Tuple(1)) is S.false + assert Eq(Tuple(1), Tuple(1)) is S.true + assert Eq(Tuple(1, 2), Tuple(1, 3)) is S.false + assert Eq(Tuple(1, 2), Tuple(1, 2)) is S.true + assert unchanged(Eq, Tuple(1, x), Tuple(1, 2)) + assert Eq(Tuple(1, x), Tuple(1, 2)).subs(x, 2) is S.true + assert unchanged(Eq, Tuple(1, 2), x) + f = Function('f') + assert unchanged(Eq, Tuple(1), f(x)) + assert Eq(Tuple(1), f(x)).subs(x, 1).subs(f, Lambda(y, (y,))) is S.true + + +def test_Tuple_comparision(): + assert (Tuple(1, 3) >= Tuple(-10, 30)) is S.true + assert (Tuple(1, 3) <= Tuple(-10, 30)) is S.false + assert (Tuple(1, 3) >= Tuple(1, 3)) is S.true + assert (Tuple(1, 3) <= Tuple(1, 3)) is S.true + + +def test_Tuple_tuple_count(): + assert Tuple(0, 1, 2, 3).tuple_count(4) == 0 + assert Tuple(0, 4, 1, 2, 3).tuple_count(4) == 1 + assert Tuple(0, 4, 1, 4, 2, 3).tuple_count(4) == 2 + assert Tuple(0, 4, 1, 4, 2, 4, 3).tuple_count(4) == 3 + + +def test_Tuple_index(): + assert Tuple(4, 0, 1, 2, 3).index(4) == 0 + assert Tuple(0, 4, 1, 2, 3).index(4) == 1 + assert Tuple(0, 1, 4, 2, 3).index(4) == 2 + assert Tuple(0, 1, 2, 4, 3).index(4) == 3 + assert Tuple(0, 1, 2, 3, 4).index(4) == 4 + + raises(ValueError, lambda: Tuple(0, 1, 2, 3).index(4)) + raises(ValueError, lambda: Tuple(4, 0, 1, 2, 3).index(4, 1)) + raises(ValueError, lambda: Tuple(0, 1, 2, 3, 4).index(4, 1, 4)) + + +def test_Tuple_mul(): + assert Tuple(1, 2, 3)*2 == Tuple(1, 2, 3, 1, 2, 3) + assert 2*Tuple(1, 2, 3) == Tuple(1, 2, 3, 1, 2, 3) + assert Tuple(1, 2, 3)*Integer(2) == Tuple(1, 2, 3, 1, 2, 3) + assert Integer(2)*Tuple(1, 2, 3) == Tuple(1, 2, 3, 1, 2, 3) + + raises(TypeError, lambda: Tuple(1, 2, 3)*S.Half) + raises(TypeError, lambda: S.Half*Tuple(1, 2, 3)) + + +def test_tuple_wrapper(): + + @tuple_wrapper + def wrap_tuples_and_return(*t): + return t + + p = symbols('p') + assert wrap_tuples_and_return(p, 1) == (p, 1) + assert wrap_tuples_and_return((p, 1)) == (Tuple(p, 1),) + assert wrap_tuples_and_return(1, (p, 2), 3) == (1, Tuple(p, 2), 3) + + +def test_iterable_is_sequence(): + ordered = [[], (), Tuple(), Matrix([[]])] + unordered = [set()] + not_sympy_iterable = [{}, '', ''] + assert all(is_sequence(i) for i in ordered) + assert all(not is_sequence(i) for i in unordered) + assert all(iterable(i) for i in ordered + unordered) + assert all(not iterable(i) for i in not_sympy_iterable) + assert all(iterable(i, exclude=None) for i in not_sympy_iterable) + + +def test_TupleKind(): + kind = TupleKind(NumberKind, MatrixKind(NumberKind)) + assert Tuple(1, Matrix([1, 2])).kind is kind + assert Tuple(1, 2).kind is TupleKind(NumberKind, NumberKind) + assert Tuple(1, 2).kind.element_kind == (NumberKind, NumberKind) + + +def test_Dict(): + x, y, z = symbols('x y z') + d = Dict({x: 1, y: 2, z: 3}) + assert d[x] == 1 + assert d[y] == 2 + raises(KeyError, lambda: d[2]) + raises(KeyError, lambda: d['2']) + assert len(d) == 3 + assert set(d.keys()) == {x, y, z} + assert set(d.values()) == {S.One, S(2), S(3)} + assert d.get(5, 'default') == 'default' + assert d.get('5', 'default') == 'default' + assert x in d and z in d and 5 not in d and '5' not in d + assert d.has(x) and d.has(1) # SymPy Basic .has method + + # Test input types + # input - a Python dict + # input - items as args - SymPy style + assert (Dict({x: 1, y: 2, z: 3}) == + Dict((x, 1), (y, 2), (z, 3))) + + raises(TypeError, lambda: Dict(((x, 1), (y, 2), (z, 3)))) + with raises(NotImplementedError): + d[5] = 6 # assert immutability + + assert set( + d.items()) == {Tuple(x, S.One), Tuple(y, S(2)), Tuple(z, S(3))} + assert set(d) == {x, y, z} + assert str(d) == '{x: 1, y: 2, z: 3}' + assert d.__repr__() == '{x: 1, y: 2, z: 3}' + + # Test creating a Dict from a Dict. + d = Dict({x: 1, y: 2, z: 3}) + assert d == Dict(d) + + # Test for supporting defaultdict + d = defaultdict(int) + assert d[x] == 0 + assert d[y] == 0 + assert d[z] == 0 + assert Dict(d) + d = Dict(d) + assert len(d) == 3 + assert set(d.keys()) == {x, y, z} + assert set(d.values()) == {S.Zero, S.Zero, S.Zero} + + +def test_issue_5788(): + args = [(1, 2), (2, 1)] + for o in [Dict, Tuple, FiniteSet]: + # __eq__ and arg handling + if o != Tuple: + assert o(*args) == o(*reversed(args)) + pair = [o(*args), o(*reversed(args))] + assert sorted(pair) == sorted(pair) + assert set(o(*args)) # doesn't fail diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_count_ops.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_count_ops.py new file mode 100644 index 0000000000000000000000000000000000000000..bc95004ef5ba4421927289a049a9197d208c30d0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_count_ops.py @@ -0,0 +1,155 @@ +from sympy.concrete.summations import Sum +from sympy.core.basic import Basic +from sympy.core.function import (Derivative, Function, count_ops) +from sympy.core.numbers import (I, Rational, pi) +from sympy.core.relational import (Eq, Rel) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.integrals.integrals import Integral +from sympy.logic.boolalg import (And, Equivalent, ITE, Implies, Nand, + Nor, Not, Or, Xor) +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.core.containers import Tuple + +x, y, z = symbols('x,y,z') +a, b, c = symbols('a,b,c') + +def test_count_ops_non_visual(): + def count(val): + return count_ops(val, visual=False) + assert count(x) == 0 + assert count(x) is not S.Zero + assert count(x + y) == 1 + assert count(x + y) is not S.One + assert count(x + y*x + 2*y) == 4 + assert count({x + y: x}) == 1 + assert count({x + y: S(2) + x}) is not S.One + assert count(x < y) == 1 + assert count(Or(x,y)) == 1 + assert count(And(x,y)) == 1 + assert count(Not(x)) == 1 + assert count(Nor(x,y)) == 2 + assert count(Nand(x,y)) == 2 + assert count(Xor(x,y)) == 1 + assert count(Implies(x,y)) == 1 + assert count(Equivalent(x,y)) == 1 + assert count(ITE(x,y,z)) == 1 + assert count(ITE(True,x,y)) == 0 + + +def test_count_ops_visual(): + ADD, MUL, POW, SIN, COS, EXP, AND, D, G, M = symbols( + 'Add Mul Pow sin cos exp And Derivative Integral Sum'.upper()) + DIV, SUB, NEG = symbols('DIV SUB NEG') + LT, LE, GT, GE, EQ, NE = symbols('LT LE GT GE EQ NE') + NOT, OR, AND, XOR, IMPLIES, EQUIVALENT, _ITE, BASIC, TUPLE = symbols( + 'Not Or And Xor Implies Equivalent ITE Basic Tuple'.upper()) + + def count(val): + return count_ops(val, visual=True) + + assert count(7) is S.Zero + assert count(S(7)) is S.Zero + assert count(-1) == NEG + assert count(-2) == NEG + assert count(S(2)/3) == DIV + assert count(Rational(2, 3)) == DIV + assert count(pi/3) == DIV + assert count(-pi/3) == DIV + NEG + assert count(I - 1) == SUB + assert count(1 - I) == SUB + assert count(1 - 2*I) == SUB + MUL + + assert count(x) is S.Zero + assert count(-x) == NEG + assert count(-2*x/3) == NEG + DIV + MUL + assert count(Rational(-2, 3)*x) == NEG + DIV + MUL + assert count(1/x) == DIV + assert count(1/(x*y)) == DIV + MUL + assert count(-1/x) == NEG + DIV + assert count(-2/x) == NEG + DIV + assert count(x/y) == DIV + assert count(-x/y) == NEG + DIV + + assert count(x**2) == POW + assert count(-x**2) == POW + NEG + assert count(-2*x**2) == POW + MUL + NEG + + assert count(x + pi/3) == ADD + DIV + assert count(x + S.One/3) == ADD + DIV + assert count(x + Rational(1, 3)) == ADD + DIV + assert count(x + y) == ADD + assert count(x - y) == SUB + assert count(y - x) == SUB + assert count(-1/(x - y)) == DIV + NEG + SUB + assert count(-1/(y - x)) == DIV + NEG + SUB + assert count(1 + x**y) == ADD + POW + assert count(1 + x + y) == 2*ADD + assert count(1 + x + y + z) == 3*ADD + assert count(1 + x**y + 2*x*y + y**2) == 3*ADD + 2*POW + 2*MUL + assert count(2*z + y + x + 1) == 3*ADD + MUL + assert count(2*z + y**17 + x + 1) == 3*ADD + MUL + POW + assert count(2*z + y**17 + x + sin(x)) == 3*ADD + POW + MUL + SIN + assert count(2*z + y**17 + x + sin(x**2)) == 3*ADD + MUL + 2*POW + SIN + assert count(2*z + y**17 + x + sin( + x**2) + exp(cos(x))) == 4*ADD + MUL + 2*POW + EXP + COS + SIN + + assert count(Derivative(x, x)) == D + assert count(Integral(x, x) + 2*x/(1 + x)) == G + DIV + MUL + 2*ADD + assert count(Sum(x, (x, 1, x + 1)) + 2*x/(1 + x)) == M + DIV + MUL + 3*ADD + assert count(Basic()) is S.Zero + + assert count({x + 1: sin(x)}) == ADD + SIN + assert count([x + 1, sin(x) + y, None]) == ADD + SIN + ADD + assert count({x + 1: sin(x), y: cos(x) + 1}) == SIN + COS + 2*ADD + assert count({}) is S.Zero + assert count([x + 1, sin(x)*y, None]) == SIN + ADD + MUL + assert count([]) is S.Zero + + assert count(Basic()) == 0 + assert count(Basic(Basic(),Basic(x,x+y))) == ADD + 2*BASIC + assert count(Basic(x, x + y)) == ADD + BASIC + assert [count(Rel(x, y, op)) for op in '< <= > >= == <> !='.split() + ] == [LT, LE, GT, GE, EQ, NE, NE] + assert count(Or(x, y)) == OR + assert count(And(x, y)) == AND + assert count(Or(x, Or(y, And(z, a)))) == AND + OR + assert count(Nor(x, y)) == NOT + OR + assert count(Nand(x, y)) == NOT + AND + assert count(Xor(x, y)) == XOR + assert count(Implies(x, y)) == IMPLIES + assert count(Equivalent(x, y)) == EQUIVALENT + assert count(ITE(x, y, z)) == _ITE + assert count([Or(x, y), And(x, y), Basic(x + y)] + ) == ADD + AND + BASIC + OR + + assert count(Basic(Tuple(x))) == BASIC + TUPLE + #It checks that TUPLE is counted as an operation. + + assert count(Eq(x + y, S(2))) == ADD + EQ + + +def test_issue_9324(): + def count(val): + return count_ops(val, visual=False) + + M = MatrixSymbol('M', 10, 10) + assert count(M[0, 0]) == 0 + assert count(2 * M[0, 0] + M[5, 7]) == 2 + P = MatrixSymbol('P', 3, 3) + Q = MatrixSymbol('Q', 3, 3) + assert count(P + Q) == 1 + m = Symbol('m', integer=True) + n = Symbol('n', integer=True) + M = MatrixSymbol('M', m + n, m * m) + assert count(M[0, 1]) == 2 + + +def test_issue_21532(): + f = Function('f') + g = Function('g') + FUNC_F, FUNC_G = symbols('FUNC_F, FUNC_G') + assert f(x).count_ops(visual=True) == FUNC_F + assert g(x).count_ops(visual=True) == FUNC_G diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_diff.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_diff.py new file mode 100644 index 0000000000000000000000000000000000000000..effc9cd91d2e7b6f8f8e5fd04bb667ed71c0ffaf --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_diff.py @@ -0,0 +1,160 @@ +from sympy.concrete.summations import Sum +from sympy.core.expr import Expr +from sympy.core.function import (Derivative, Function, diff, Subs) +from sympy.core.numbers import (I, Rational, pi) +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.complexes import (im, re) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import Max +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (cos, cot, sin, tan) +from sympy.tensor.array.ndim_array import NDimArray +from sympy.testing.pytest import raises +from sympy.abc import a, b, c, x, y, z + +def test_diff(): + assert Rational(1, 3).diff(x) is S.Zero + assert I.diff(x) is S.Zero + assert pi.diff(x) is S.Zero + assert x.diff(x, 0) == x + assert (x**2).diff(x, 2, x) == 0 + assert (x**2).diff((x, 2), x) == 0 + assert (x**2).diff((x, 1), x) == 2 + assert (x**2).diff((x, 1), (x, 1)) == 2 + assert (x**2).diff((x, 2)) == 2 + assert (x**2).diff(x, y, 0) == 2*x + assert (x**2).diff(x, (y, 0)) == 2*x + assert (x**2).diff(x, y) == 0 + raises(ValueError, lambda: x.diff(1, x)) + + p = Rational(5) + e = a*b + b**p + assert e.diff(a) == b + assert e.diff(b) == a + 5*b**4 + assert e.diff(b).diff(a) == Rational(1) + e = a*(b + c) + assert e.diff(a) == b + c + assert e.diff(b) == a + assert e.diff(b).diff(a) == Rational(1) + e = c**p + assert e.diff(c, 6) == Rational(0) + assert e.diff(c, 5) == Rational(120) + e = c**Rational(2) + assert e.diff(c) == 2*c + e = a*b*c + assert e.diff(c) == a*b + + +def test_diff2(): + n3 = Rational(3) + n2 = Rational(2) + n6 = Rational(6) + + e = n3*(-n2 + x**n2)*cos(x) + x*(-n6 + x**n2)*sin(x) + assert e == 3*(-2 + x**2)*cos(x) + x*(-6 + x**2)*sin(x) + assert e.diff(x).expand() == x**3*cos(x) + + e = (x + 1)**3 + assert e.diff(x) == 3*(x + 1)**2 + e = x*(x + 1)**3 + assert e.diff(x) == (x + 1)**3 + 3*x*(x + 1)**2 + e = 2*exp(x*x)*x + assert e.diff(x) == 2*exp(x**2) + 4*x**2*exp(x**2) + + +def test_diff3(): + p = Rational(5) + e = a*b + sin(b**p) + assert e == a*b + sin(b**5) + assert e.diff(a) == b + assert e.diff(b) == a + 5*b**4*cos(b**5) + e = tan(c) + assert e == tan(c) + assert e.diff(c) in [cos(c)**(-2), 1 + sin(c)**2/cos(c)**2, 1 + tan(c)**2] + e = c*log(c) - c + assert e == -c + c*log(c) + assert e.diff(c) == log(c) + e = log(sin(c)) + assert e == log(sin(c)) + assert e.diff(c) in [sin(c)**(-1)*cos(c), cot(c)] + e = (Rational(2)**a/log(Rational(2))) + assert e == 2**a*log(Rational(2))**(-1) + assert e.diff(a) == 2**a + + +def test_diff_no_eval_derivative(): + class My(Expr): + def __new__(cls, x): + return Expr.__new__(cls, x) + + # My doesn't have its own _eval_derivative method + assert My(x).diff(x).func is Derivative + assert My(x).diff(x, 3).func is Derivative + assert re(x).diff(x, 2) == Derivative(re(x), (x, 2)) # issue 15518 + assert diff(NDimArray([re(x), im(x)]), (x, 2)) == NDimArray( + [Derivative(re(x), (x, 2)), Derivative(im(x), (x, 2))]) + # it doesn't have y so it shouldn't need a method for this case + assert My(x).diff(y) == 0 + + +def test_speed(): + # this should return in 0.0s. If it takes forever, it's wrong. + assert x.diff(x, 10**8) == 0 + + +def test_deriv_noncommutative(): + A = Symbol("A", commutative=False) + f = Function("f") + assert A*f(x)*A == f(x)*A**2 + assert A*f(x).diff(x)*A == f(x).diff(x) * A**2 + + +def test_diff_nth_derivative(): + f = Function("f") + n = Symbol("n", integer=True) + + expr = diff(sin(x), (x, n)) + expr2 = diff(f(x), (x, 2)) + expr3 = diff(f(x), (x, n)) + + assert expr.subs(sin(x), cos(-x)) == Derivative(cos(-x), (x, n)) + assert expr.subs(n, 1).doit() == cos(x) + assert expr.subs(n, 2).doit() == -sin(x) + + assert expr2.subs(Derivative(f(x), x), y) == Derivative(y, x) + # Currently not supported (cannot determine if `n > 1`): + #assert expr3.subs(Derivative(f(x), x), y) == Derivative(y, (x, n-1)) + assert expr3 == Derivative(f(x), (x, n)) + + assert diff(x, (x, n)) == Piecewise((x, Eq(n, 0)), (1, Eq(n, 1)), (0, True)) + assert diff(2*x, (x, n)).dummy_eq( + Sum(Piecewise((2*x*factorial(n)/(factorial(y)*factorial(-y + n)), + Eq(y, 0) & Eq(Max(0, -y + n), 0)), + (2*factorial(n)/(factorial(y)*factorial(-y + n)), Eq(y, 0) & Eq(Max(0, + -y + n), 1)), (0, True)), (y, 0, n))) + # TODO: assert diff(x**2, (x, n)) == x**(2-n)*ff(2, n) + exprm = x*sin(x) + mul_diff = diff(exprm, (x, n)) + assert isinstance(mul_diff, Sum) + for i in range(5): + assert mul_diff.subs(n, i).doit() == exprm.diff((x, i)).expand() + + exprm2 = 2*y*x*sin(x)*cos(x)*log(x)*exp(x) + dex = exprm2.diff((x, n)) + assert isinstance(dex, Sum) + for i in range(7): + assert dex.subs(n, i).doit().expand() == \ + exprm2.diff((x, i)).expand() + + assert (cos(x)*sin(y)).diff([[x, y, z]]) == NDimArray([ + -sin(x)*sin(y), cos(x)*cos(y), 0]) + + +def test_issue_16160(): + assert Derivative(x**3, (x, x)).subs(x, 2) == Subs( + Derivative(x**3, (x, 2)), x, 2) + assert Derivative(1 + x**3, (x, x)).subs(x, 0 + ) == Derivative(1 + y**3, (y, 0)).subs(y, 0) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_equal.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_equal.py new file mode 100644 index 0000000000000000000000000000000000000000..82213b757cda5fbd80310e387bdf00cc1c9c25fe --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_equal.py @@ -0,0 +1,89 @@ +from sympy.core.numbers import Rational +from sympy.core.symbol import (Dummy, Symbol) +from sympy.functions.elementary.exponential import exp + + +def test_equal(): + b = Symbol("b") + a = Symbol("a") + e1 = a + b + e2 = 2*a*b + e3 = a**3*b**2 + e4 = a*b + b*a + assert not e1 == e2 + assert not e1 == e2 + assert e1 != e2 + assert e2 == e4 + assert e2 != e3 + assert not e2 == e3 + + x = Symbol("x") + e1 = exp(x + 1/x) + y = Symbol("x") + e2 = exp(y + 1/y) + assert e1 == e2 + assert not e1 != e2 + y = Symbol("y") + e2 = exp(y + 1/y) + assert not e1 == e2 + assert e1 != e2 + + e5 = Rational(3) + 2*x - x - x + assert e5 == 3 + assert 3 == e5 + assert e5 != 4 + assert 4 != e5 + assert e5 != 3 + x + assert 3 + x != e5 + + +def test_expevalbug(): + x = Symbol("x") + e1 = exp(1*x) + e3 = exp(x) + assert e1 == e3 + + +def test_cmp_bug1(): + class T: + pass + + t = T() + x = Symbol("x") + + assert not (x == t) + assert (x != t) + + +def test_cmp_bug2(): + class T: + pass + + t = T() + + assert not (Symbol == t) + assert (Symbol != t) + + +def test_cmp_issue_4357(): + """ Check that Basic subclasses can be compared with sympifiable objects. + + https://github.com/sympy/sympy/issues/4357 + """ + assert not (Symbol == 1) + assert (Symbol != 1) + assert not (Symbol == 'x') + assert (Symbol != 'x') + + +def test_dummy_eq(): + x = Symbol('x') + y = Symbol('y') + + u = Dummy('u') + + assert (u**2 + 1).dummy_eq(x**2 + 1) is True + assert ((u**2 + 1) == (x**2 + 1)) is False + + assert (u**2 + y).dummy_eq(x**2 + y, x) is True + assert (u**2 + y).dummy_eq(x**2 + y, y) is False diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_eval.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_eval.py new file mode 100644 index 0000000000000000000000000000000000000000..9c1633f77b50483afee21c6d9fca232b1279d2b9 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_eval.py @@ -0,0 +1,95 @@ +from sympy.core.function import Function +from sympy.core.numbers import (I, Rational) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, tan) +from sympy.testing.pytest import XFAIL + + +def test_add_eval(): + a = Symbol("a") + b = Symbol("b") + c = Rational(1) + p = Rational(5) + assert a*b + c + p == a*b + 6 + assert c + a + p == a + 6 + assert c + a - p == a + (-4) + assert a + a == 2*a + assert a + p + a == 2*a + 5 + assert c + p == Rational(6) + assert b + a - b == a + + +def test_addmul_eval(): + a = Symbol("a") + b = Symbol("b") + c = Rational(1) + p = Rational(5) + assert c + a + b*c + a - p == 2*a + b + (-4) + assert a*2 + p + a == a*2 + 5 + a + assert a*2 + p + a == 3*a + 5 + assert a*2 + a == 3*a + + +def test_pow_eval(): + # XXX Pow does not fully support conversion of negative numbers + # to their complex equivalent + + assert sqrt(-1) == I + + assert sqrt(-4) == 2*I + assert sqrt( 4) == 2 + assert (8)**Rational(1, 3) == 2 + assert (-8)**Rational(1, 3) == 2*((-1)**Rational(1, 3)) + + assert sqrt(-2) == I*sqrt(2) + assert (-1)**Rational(1, 3) != I + assert (-10)**Rational(1, 3) != I*((10)**Rational(1, 3)) + assert (-2)**Rational(1, 4) != (2)**Rational(1, 4) + + assert 64**Rational(1, 3) == 4 + assert 64**Rational(2, 3) == 16 + assert 24/sqrt(64) == 3 + assert (-27)**Rational(1, 3) == 3*(-1)**Rational(1, 3) + + assert (cos(2) / tan(2))**2 == (cos(2) / tan(2))**2 + + +@XFAIL +def test_pow_eval_X1(): + assert (-1)**Rational(1, 3) == S.Half + S.Half*I*sqrt(3) + + +def test_mulpow_eval(): + x = Symbol('x') + assert sqrt(50)/(sqrt(2)*x) == 5/x + assert sqrt(27)/sqrt(3) == 3 + + +def test_evalpow_bug(): + x = Symbol("x") + assert 1/(1/x) == x + assert 1/(-1/x) == -x + + +def test_symbol_expand(): + x = Symbol('x') + y = Symbol('y') + + f = x**4*y**4 + assert f == x**4*y**4 + assert f == f.expand() + + g = (x*y)**4 + assert g == f + assert g.expand() == f + assert g.expand() == g.expand().expand() + + +def test_function(): + f, l = map(Function, 'fl') + x = Symbol('x') + assert exp(l(x))*l(x)/exp(l(x)) == l(x) + assert exp(f(x))*f(x)/exp(f(x)) == f(x) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_evalf.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_evalf.py new file mode 100644 index 0000000000000000000000000000000000000000..05d0fd0b58b756570c954d7d7e35e0c2cb589746 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_evalf.py @@ -0,0 +1,734 @@ +import math + +from sympy.concrete.products import (Product, product) +from sympy.concrete.summations import Sum +from sympy.core.add import Add +from sympy.core.evalf import N +from sympy.core.function import (Function, nfloat) +from sympy.core.mul import Mul +from sympy.core import (GoldenRatio) +from sympy.core.numbers import (AlgebraicNumber, E, Float, I, Rational, + oo, zoo, nan, pi) +from sympy.core.power import Pow +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.combinatorial.numbers import fibonacci +from sympy.functions.elementary.complexes import (Abs, re, im) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.hyperbolic import (acosh, cosh) +from sympy.functions.elementary.integers import (ceiling, floor) +from sympy.functions.elementary.miscellaneous import (Max, sqrt) +from sympy.functions.elementary.trigonometric import (acos, atan, cos, sin, tan) +from sympy.integrals.integrals import (Integral, integrate) +from sympy.polys.polytools import factor +from sympy.polys.rootoftools import CRootOf +from sympy.polys.specialpolys import cyclotomic_poly +from sympy.printing import srepr +from sympy.printing.str import sstr +from sympy.simplify.simplify import simplify +from sympy.core.numbers import comp +from sympy.core.evalf import (complex_accuracy, PrecisionExhausted, + scaled_zero, get_integer_part, as_mpmath, evalf, _evalf_with_bounded_error) +from mpmath import inf, ninf, make_mpc +from mpmath.libmp.libmpf import from_float, fzero +from sympy.core.expr import unchanged +from sympy.testing.pytest import raises, XFAIL +from sympy.abc import n, x, y + + +def NS(e, n=15, **options): + return sstr(sympify(e).evalf(n, **options), full_prec=True) + + +def test_evalf_helpers(): + from mpmath.libmp import finf + assert complex_accuracy((from_float(2.0), None, 35, None)) == 35 + assert complex_accuracy((from_float(2.0), from_float(10.0), 35, 100)) == 37 + assert complex_accuracy( + (from_float(2.0), from_float(1000.0), 35, 100)) == 43 + assert complex_accuracy((from_float(2.0), from_float(10.0), 100, 35)) == 35 + assert complex_accuracy( + (from_float(2.0), from_float(1000.0), 100, 35)) == 35 + assert complex_accuracy(finf) == math.inf + assert complex_accuracy(zoo) == math.inf + raises(ValueError, lambda: get_integer_part(zoo, 1, {})) + + +def test_evalf_basic(): + assert NS('pi', 15) == '3.14159265358979' + assert NS('2/3', 10) == '0.6666666667' + assert NS('355/113-pi', 6) == '2.66764e-7' + assert NS('16*atan(1/5)-4*atan(1/239)', 15) == '3.14159265358979' + + +def test_cancellation(): + assert NS(Add(pi, Rational(1, 10**1000), -pi, evaluate=False), 15, + maxn=1200) == '1.00000000000000e-1000' + + +def test_evalf_powers(): + assert NS('pi**(10**20)', 10) == '1.339148777e+49714987269413385435' + assert NS(pi**(10**100), 10) == ('4.946362032e+4971498726941338543512682882' + '9089887365167832438044244613405349992494711208' + '95526746555473864642912223') + assert NS('2**(1/10**50)', 15) == '1.00000000000000' + assert NS('2**(1/10**50)-1', 15) == '6.93147180559945e-51' + +# Evaluation of Rump's ill-conditioned polynomial + + +def test_evalf_rump(): + a = 1335*y**6/4 + x**2*(11*x**2*y**2 - y**6 - 121*y**4 - 2) + 11*y**8/2 + x/(2*y) + assert NS(a, 15, subs={x: 77617, y: 33096}) == '-0.827396059946821' + + +def test_evalf_complex(): + assert NS('2*sqrt(pi)*I', 10) == '3.544907702*I' + assert NS('3+3*I', 15) == '3.00000000000000 + 3.00000000000000*I' + assert NS('E+pi*I', 15) == '2.71828182845905 + 3.14159265358979*I' + assert NS('pi * (3+4*I)', 15) == '9.42477796076938 + 12.5663706143592*I' + assert NS('I*(2+I)', 15) == '-1.00000000000000 + 2.00000000000000*I' + + +@XFAIL +def test_evalf_complex_bug(): + assert NS('(pi+E*I)*(E+pi*I)', 15) in ('0.e-15 + 17.25866050002*I', + '0.e-17 + 17.25866050002*I', '-0.e-17 + 17.25866050002*I') + + +def test_evalf_complex_powers(): + assert NS('(E+pi*I)**100000000000000000') == \ + '-3.58896782867793e+61850354284995199 + 4.58581754997159e+61850354284995199*I' + # XXX: rewrite if a+a*I simplification introduced in SymPy + #assert NS('(pi + pi*I)**2') in ('0.e-15 + 19.7392088021787*I', '0.e-16 + 19.7392088021787*I') + assert NS('(pi + pi*I)**2', chop=True) == '19.7392088021787*I' + assert NS( + '(pi + 1/10**8 + pi*I)**2') == '6.2831853e-8 + 19.7392088650106*I' + assert NS('(pi + 1/10**12 + pi*I)**2') == '6.283e-12 + 19.7392088021850*I' + assert NS('(pi + pi*I)**4', chop=True) == '-389.636364136010' + assert NS( + '(pi + 1/10**8 + pi*I)**4') == '-389.636366616512 + 2.4805021e-6*I' + assert NS('(pi + 1/10**12 + pi*I)**4') == '-389.636364136258 + 2.481e-10*I' + assert NS( + '(10000*pi + 10000*pi*I)**4', chop=True) == '-3.89636364136010e+18' + + +@XFAIL +def test_evalf_complex_powers_bug(): + assert NS('(pi + pi*I)**4') == '-389.63636413601 + 0.e-14*I' + + +def test_evalf_exponentiation(): + assert NS(sqrt(-pi)) == '1.77245385090552*I' + assert NS(Pow(pi*I, Rational( + 1, 2), evaluate=False)) == '1.25331413731550 + 1.25331413731550*I' + assert NS(pi**I) == '0.413292116101594 + 0.910598499212615*I' + assert NS(pi**(E + I/3)) == '20.8438653991931 + 8.36343473930031*I' + assert NS((pi + I/3)**(E + I/3)) == '17.2442906093590 + 13.6839376767037*I' + assert NS(exp(pi)) == '23.1406926327793' + assert NS(exp(pi + E*I)) == '-21.0981542849657 + 9.50576358282422*I' + assert NS(pi**pi) == '36.4621596072079' + assert NS((-pi)**pi) == '-32.9138577418939 - 15.6897116534332*I' + assert NS((-pi)**(-pi)) == '-0.0247567717232697 + 0.0118013091280262*I' + +# An example from Smith, "Multiple Precision Complex Arithmetic and Functions" + + +def test_evalf_complex_cancellation(): + A = Rational('63287/100000') + B = Rational('52498/100000') + C = Rational('69301/100000') + D = Rational('83542/100000') + F = Rational('2231321613/2500000000') + # XXX: the number of returned mantissa digits in the real part could + # change with the implementation. What matters is that the returned digits are + # correct; those that are showing now are correct. + # >>> ((A+B*I)*(C+D*I)).expand() + # 64471/10000000000 + 2231321613*I/2500000000 + # >>> 2231321613*4 + # 8925286452L + assert NS((A + B*I)*(C + D*I), 6) == '6.44710e-6 + 0.892529*I' + assert NS((A + B*I)*(C + D*I), 10) == '6.447100000e-6 + 0.8925286452*I' + assert NS((A + B*I)*( + C + D*I) - F*I, 5) in ('6.4471e-6 + 0.e-14*I', '6.4471e-6 - 0.e-14*I') + + +def test_evalf_logs(): + assert NS("log(3+pi*I)", 15) == '1.46877619736226 + 0.808448792630022*I' + assert NS("log(pi*I)", 15) == '1.14472988584940 + 1.57079632679490*I' + assert NS('log(-1 + 0.00001)', 2) == '-1.0e-5 + 3.1*I' + assert NS('log(100, 10, evaluate=False)', 15) == '2.00000000000000' + assert NS('-2*I*log(-(-1)**(S(1)/9))', 15) == '-5.58505360638185' + + +def test_evalf_trig(): + assert NS('sin(1)', 15) == '0.841470984807897' + assert NS('cos(1)', 15) == '0.540302305868140' + assert NS('sin(10**-6)', 15) == '9.99999999999833e-7' + assert NS('cos(10**-6)', 15) == '0.999999999999500' + assert NS('sin(E*10**100)', 15) == '0.409160531722613' + # Some input near roots + assert NS(sin(exp(pi*sqrt(163))*pi), 15) == '-2.35596641936785e-12' + assert NS(sin(pi*10**100 + Rational(7, 10**5), evaluate=False), 15, maxn=120) == \ + '6.99999999428333e-5' + assert NS(sin(Rational(7, 10**5), evaluate=False), 15) == \ + '6.99999999428333e-5' + +# Check detection of various false identities + + +def test_evalf_near_integers(): + # Binet's formula + f = lambda n: ((1 + sqrt(5))**n)/(2**n * sqrt(5)) + assert NS(f(5000) - fibonacci(5000), 10, maxn=1500) == '5.156009964e-1046' + # Some near-integer identities from + # http://mathworld.wolfram.com/AlmostInteger.html + assert NS('sin(2017*2**(1/5))', 15) == '-1.00000000000000' + assert NS('sin(2017*2**(1/5))', 20) == '-0.99999999999999997857' + assert NS('1+sin(2017*2**(1/5))', 15) == '2.14322287389390e-17' + assert NS('45 - 613*E/37 + 35/991', 15) == '6.03764498766326e-11' + + +def test_evalf_ramanujan(): + assert NS(exp(pi*sqrt(163)) - 640320**3 - 744, 10) == '-7.499274028e-13' + # A related identity + A = 262537412640768744*exp(-pi*sqrt(163)) + B = 196884*exp(-2*pi*sqrt(163)) + C = 103378831900730205293632*exp(-3*pi*sqrt(163)) + assert NS(1 - A - B + C, 10) == '1.613679005e-59' + +# Input that for various reasons have failed at some point + + +def test_evalf_bugs(): + assert NS(sin(1) + exp(-10**10), 10) == NS(sin(1), 10) + assert NS(exp(10**10) + sin(1), 10) == NS(exp(10**10), 10) + assert NS('expand_log(log(1+1/10**50))', 20) == '1.0000000000000000000e-50' + assert NS('log(10**100,10)', 10) == '100.0000000' + assert NS('log(2)', 10) == '0.6931471806' + assert NS( + '(sin(x)-x)/x**3', 15, subs={x: '1/10**50'}) == '-0.166666666666667' + assert NS(sin(1) + Rational( + 1, 10**100)*I, 15) == '0.841470984807897 + 1.00000000000000e-100*I' + assert x.evalf() == x + assert NS((1 + I)**2*I, 6) == '-2.00000' + d = {n: ( + -1)**Rational(6, 7), y: (-1)**Rational(4, 7), x: (-1)**Rational(2, 7)} + assert NS((x*(1 + y*(1 + n))).subs(d).evalf(), 6) == '0.346011 + 0.433884*I' + assert NS(((-I - sqrt(2)*I)**2).evalf()) == '-5.82842712474619' + assert NS((1 + I)**2*I, 15) == '-2.00000000000000' + # issue 4758 (1/2): + assert NS(pi.evalf(69) - pi) == '-4.43863937855894e-71' + # issue 4758 (2/2): With the bug present, this still only fails if the + # terms are in the order given here. This is not generally the case, + # because the order depends on the hashes of the terms. + assert NS(20 - 5008329267844*n**25 - 477638700*n**37 - 19*n, + subs={n: .01}) == '19.8100000000000' + assert NS(((x - 1)*(1 - x)**1000).n() + ) == '(1.00000000000000 - x)**1000*(x - 1.00000000000000)' + assert NS((-x).n()) == '-x' + assert NS((-2*x).n()) == '-2.00000000000000*x' + assert NS((-2*x*y).n()) == '-2.00000000000000*x*y' + assert cos(x).n(subs={x: 1+I}) == cos(x).subs(x, 1+I).n() + # issue 6660. Also NaN != mpmath.nan + # In this order: + # 0*nan, 0/nan, 0*inf, 0/inf + # 0+nan, 0-nan, 0+inf, 0-inf + # >>> n = Some Number + # n*nan, n/nan, n*inf, n/inf + # n+nan, n-nan, n+inf, n-inf + assert (0*E**(oo)).n() is S.NaN + assert (0/E**(oo)).n() is S.Zero + + assert (0+E**(oo)).n() is S.Infinity + assert (0-E**(oo)).n() is S.NegativeInfinity + + assert (5*E**(oo)).n() is S.Infinity + assert (5/E**(oo)).n() is S.Zero + + assert (5+E**(oo)).n() is S.Infinity + assert (5-E**(oo)).n() is S.NegativeInfinity + + #issue 7416 + assert as_mpmath(0.0, 10, {'chop': True}) == 0 + + #issue 5412 + assert ((oo*I).n() == S.Infinity*I) + assert ((oo+oo*I).n() == S.Infinity + S.Infinity*I) + + #issue 11518 + assert NS(2*x**2.5, 5) == '2.0000*x**2.5000' + + #issue 13076 + assert NS(Mul(Max(0, y), x, evaluate=False).evalf()) == 'x*Max(0, y)' + + #issue 18516 + assert NS(log(S(3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376)/36360291795869936842385267079543319118023385026001623040346035832580600191583895484198508262979388783308179702534403855752855931517013066142992430916562025780021771247847643450125342836565813209972590371590152578728008385990139795377610001).evalf(15, chop=True)) == '-oo' + + +def test_evalf_integer_parts(): + a = floor(log(8)/log(2) - exp(-1000), evaluate=False) + b = floor(log(8)/log(2), evaluate=False) + assert a.evalf() == 3.0 + assert b.evalf() == 3.0 + # equals, as a fallback, can still fail but it might succeed as here + assert ceiling(10*(sin(1)**2 + cos(1)**2)) == 10 + + assert int(floor(factorial(50)/E, evaluate=False).evalf(70)) == \ + int(11188719610782480504630258070757734324011354208865721592720336800) + assert int(ceiling(factorial(50)/E, evaluate=False).evalf(70)) == \ + int(11188719610782480504630258070757734324011354208865721592720336801) + assert int(floor(GoldenRatio**999 / sqrt(5) + S.Half) + .evalf(1000)) == fibonacci(999) + assert int(floor(GoldenRatio**1000 / sqrt(5) + S.Half) + .evalf(1000)) == fibonacci(1000) + + assert ceiling(x).evalf(subs={x: 3}) == 3.0 + assert ceiling(x).evalf(subs={x: 3*I}) == 3.0*I + assert ceiling(x).evalf(subs={x: 2 + 3*I}) == 2.0 + 3.0*I + assert ceiling(x).evalf(subs={x: 3.}) == 3.0 + assert ceiling(x).evalf(subs={x: 3.*I}) == 3.0*I + assert ceiling(x).evalf(subs={x: 2. + 3*I}) == 2.0 + 3.0*I + + assert float((floor(1.5, evaluate=False)+1/9).evalf()) == 1 + 1/9 + assert float((floor(0.5, evaluate=False)+20).evalf()) == 20 + + # issue 19991 + n = 1169809367327212570704813632106852886389036911 + r = 744723773141314414542111064094745678855643068 + + assert floor(n / (pi / 2)) == r + assert floor(80782 * sqrt(2)) == 114242 + + # issue 20076 + assert 260515 - floor(260515/pi + 1/2) * pi == atan(tan(260515)) + + assert floor(x).evalf(subs={x: sqrt(2)}) == 1.0 + + +def test_evalf_trig_zero_detection(): + a = sin(160*pi, evaluate=False) + t = a.evalf(maxn=100) + assert abs(t) < 1e-100 + assert t._prec < 2 + assert a.evalf(chop=True) == 0 + raises(PrecisionExhausted, lambda: a.evalf(strict=True)) + + +def test_evalf_sum(): + assert Sum(n,(n,1,2)).evalf() == 3. + assert Sum(n,(n,1,2)).doit().evalf() == 3. + # the next test should return instantly + assert Sum(1/n,(n,1,2)).evalf() == 1.5 + + # issue 8219 + assert Sum(E/factorial(n), (n, 0, oo)).evalf() == (E*E).evalf() + # issue 8254 + assert Sum(2**n*n/factorial(n), (n, 0, oo)).evalf() == (2*E*E).evalf() + # issue 8411 + s = Sum(1/x**2, (x, 100, oo)) + assert s.n() == s.doit().n() + + +def test_evalf_divergent_series(): + raises(ValueError, lambda: Sum(1/n, (n, 1, oo)).evalf()) + raises(ValueError, lambda: Sum(n/(n**2 + 1), (n, 1, oo)).evalf()) + raises(ValueError, lambda: Sum((-1)**n, (n, 1, oo)).evalf()) + raises(ValueError, lambda: Sum((-1)**n, (n, 1, oo)).evalf()) + raises(ValueError, lambda: Sum(n**2, (n, 1, oo)).evalf()) + raises(ValueError, lambda: Sum(2**n, (n, 1, oo)).evalf()) + raises(ValueError, lambda: Sum((-2)**n, (n, 1, oo)).evalf()) + raises(ValueError, lambda: Sum((2*n + 3)/(3*n**2 + 4), (n, 0, oo)).evalf()) + raises(ValueError, lambda: Sum((0.5*n**3)/(n**4 + 1), (n, 0, oo)).evalf()) + + +def test_evalf_product(): + assert Product(n, (n, 1, 10)).evalf() == 3628800. + assert comp(Product(1 - S.Half**2/n**2, (n, 1, oo)).n(5), 0.63662) + assert Product(n, (n, -1, 3)).evalf() == 0 + + +def test_evalf_py_methods(): + assert abs(float(pi + 1) - 4.1415926535897932) < 1e-10 + assert abs(complex(pi + 1) - 4.1415926535897932) < 1e-10 + assert abs( + complex(pi + E*I) - (3.1415926535897931 + 2.7182818284590451j)) < 1e-10 + raises(TypeError, lambda: float(pi + x)) + + +def test_evalf_power_subs_bugs(): + assert (x**2).evalf(subs={x: 0}) == 0 + assert sqrt(x).evalf(subs={x: 0}) == 0 + assert (x**Rational(2, 3)).evalf(subs={x: 0}) == 0 + assert (x**x).evalf(subs={x: 0}) == 1.0 + assert (3**x).evalf(subs={x: 0}) == 1.0 + assert exp(x).evalf(subs={x: 0}) == 1.0 + assert ((2 + I)**x).evalf(subs={x: 0}) == 1.0 + assert (0**x).evalf(subs={x: 0}) == 1.0 + + +def test_evalf_arguments(): + raises(TypeError, lambda: pi.evalf(method="garbage")) + + +def test_implemented_function_evalf(): + from sympy.utilities.lambdify import implemented_function + f = Function('f') + f = implemented_function(f, lambda x: x + 1) + assert str(f(x)) == "f(x)" + assert str(f(2)) == "f(2)" + assert f(2).evalf() == 3.0 + assert f(x).evalf() == f(x) + f = implemented_function(Function('sin'), lambda x: x + 1) + assert f(2).evalf() != sin(2) + del f._imp_ # XXX: due to caching _imp_ would influence all other tests + + +def test_evaluate_false(): + for no in [0, False]: + assert Add(3, 2, evaluate=no).is_Add + assert Mul(3, 2, evaluate=no).is_Mul + assert Pow(3, 2, evaluate=no).is_Pow + assert Pow(y, 2, evaluate=True) - Pow(y, 2, evaluate=True) == 0 + + +def test_evalf_relational(): + assert Eq(x/5, y/10).evalf() == Eq(0.2*x, 0.1*y) + # if this first assertion fails it should be replaced with + # one that doesn't + assert unchanged(Eq, (3 - I)**2/2 + I, 0) + assert Eq((3 - I)**2/2 + I, 0).n() is S.false + assert nfloat(Eq((3 - I)**2 + I, 0)) == S.false + + +def test_issue_5486(): + assert not cos(sqrt(0.5 + I)).n().is_Function + + +def test_issue_5486_bug(): + from sympy.core.expr import Expr + from sympy.core.numbers import I + assert abs(Expr._from_mpmath(I._to_mpmath(15), 15) - I) < 1.0e-15 + + +def test_bugs(): + from sympy.functions.elementary.complexes import (polar_lift, re) + + assert abs(re((1 + I)**2)) < 1e-15 + + # anything that evalf's to 0 will do in place of polar_lift + assert abs(polar_lift(0)).n() == 0 + + +def test_subs(): + assert NS('besseli(-x, y) - besseli(x, y)', subs={x: 3.5, y: 20.0}) == \ + '-4.92535585957223e-10' + assert NS('Piecewise((x, x>0)) + Piecewise((1-x, x>0))', subs={x: 0.1}) == \ + '1.00000000000000' + raises(TypeError, lambda: x.evalf(subs=(x, 1))) + + +def test_issue_4956_5204(): + # issue 4956 + v = S('''(-27*12**(1/3)*sqrt(31)*I + + 27*2**(2/3)*3**(1/3)*sqrt(31)*I)/(-2511*2**(2/3)*3**(1/3) + + (29*18**(1/3) + 9*2**(1/3)*3**(2/3)*sqrt(31)*I + + 87*2**(1/3)*3**(1/6)*I)**2)''') + assert NS(v, 1) == '0.e-118 - 0.e-118*I' + + # issue 5204 + v = S('''-(357587765856 + 18873261792*249**(1/2) + 56619785376*I*83**(1/2) + + 108755765856*I*3**(1/2) + 41281887168*6**(1/3)*(1422 + + 54*249**(1/2))**(1/3) - 1239810624*6**(1/3)*249**(1/2)*(1422 + + 54*249**(1/2))**(1/3) - 3110400000*I*6**(1/3)*83**(1/2)*(1422 + + 54*249**(1/2))**(1/3) + 13478400000*I*3**(1/2)*6**(1/3)*(1422 + + 54*249**(1/2))**(1/3) + 1274950152*6**(2/3)*(1422 + + 54*249**(1/2))**(2/3) + 32347944*6**(2/3)*249**(1/2)*(1422 + + 54*249**(1/2))**(2/3) - 1758790152*I*3**(1/2)*6**(2/3)*(1422 + + 54*249**(1/2))**(2/3) - 304403832*I*6**(2/3)*83**(1/2)*(1422 + + 4*249**(1/2))**(2/3))/(175732658352 + (1106028 + 25596*249**(1/2) + + 76788*I*83**(1/2))**2)''') + assert NS(v, 5) == '0.077284 + 1.1104*I' + assert NS(v, 1) == '0.08 + 1.*I' + + +def test_old_docstring(): + a = (E + pi*I)*(E - pi*I) + assert NS(a) == '17.2586605000200' + assert a.n() == 17.25866050002001 + + +def test_issue_4806(): + assert integrate(atan(x)**2, (x, -1, 1)).evalf().round(1) == Float(0.5, 1) + assert atan(0, evaluate=False).n() == 0 + + +def test_evalf_mul(): + # SymPy should not try to expand this; it should be handled term-wise + # in evalf through mpmath + assert NS(product(1 + sqrt(n)*I, (n, 1, 500)), 1) == '5.e+567 + 2.e+568*I' + + +def test_scaled_zero(): + a, b = (([0], 1, 100, 1), -1) + assert scaled_zero(100) == (a, b) + assert scaled_zero(a) == (0, 1, 100, 1) + a, b = (([1], 1, 100, 1), -1) + assert scaled_zero(100, -1) == (a, b) + assert scaled_zero(a) == (1, 1, 100, 1) + raises(ValueError, lambda: scaled_zero(scaled_zero(100))) + raises(ValueError, lambda: scaled_zero(100, 2)) + raises(ValueError, lambda: scaled_zero(100, 0)) + raises(ValueError, lambda: scaled_zero((1, 5, 1, 3))) + + +def test_chop_value(): + for i in range(-27, 28): + assert (Pow(10, i)*2).n(chop=10**i) and not (Pow(10, i)).n(chop=10**i) + + +def test_infinities(): + assert oo.evalf(chop=True) == inf + assert (-oo).evalf(chop=True) == ninf + + +def test_to_mpmath(): + assert sqrt(3)._to_mpmath(20)._mpf_ == (0, int(908093), -19, 20) + assert S(3.2)._to_mpmath(20)._mpf_ == (0, int(838861), -18, 20) + + +def test_issue_6632_evalf(): + add = (-100000*sqrt(2500000001) + 5000000001) + assert add.n() == 9.999999998e-11 + assert (add*add).n() == 9.999999996e-21 + + +def test_issue_4945(): + from sympy.abc import H + assert (H/0).evalf(subs={H:1}) == zoo + + +def test_evalf_integral(): + # test that workprec has to increase in order to get a result other than 0 + eps = Rational(1, 1000000) + assert Integral(sin(x), (x, -pi, pi + eps)).n(2)._prec == 10 + + +def test_issue_8821_highprec_from_str(): + s = str(pi.evalf(128)) + p = N(s) + assert Abs(sin(p)) < 1e-15 + p = N(s, 64) + assert Abs(sin(p)) < 1e-64 + + +def test_issue_8853(): + p = Symbol('x', even=True, positive=True) + assert floor(-p - S.Half).is_even == False + assert floor(-p + S.Half).is_even == True + assert ceiling(p - S.Half).is_even == True + assert ceiling(p + S.Half).is_even == False + + assert get_integer_part(S.Half, -1, {}, True) == (0, 0) + assert get_integer_part(S.Half, 1, {}, True) == (1, 0) + assert get_integer_part(Rational(-1, 2), -1, {}, True) == (-1, 0) + assert get_integer_part(Rational(-1, 2), 1, {}, True) == (0, 0) + + +def test_issue_17681(): + class identity_func(Function): + + def _eval_evalf(self, *args, **kwargs): + return self.args[0].evalf(*args, **kwargs) + + assert floor(identity_func(S(0))) == 0 + assert get_integer_part(S(0), 1, {}, True) == (0, 0) + + +def test_issue_9326(): + from sympy.core.symbol import Dummy + d1 = Dummy('d') + d2 = Dummy('d') + e = d1 + d2 + assert e.evalf(subs = {d1: 1, d2: 2}) == 3.0 + + +def test_issue_10323(): + assert ceiling(sqrt(2**30 + 1)) == 2**15 + 1 + + +def test_AssocOp_Function(): + # the first arg of Min is not comparable in the imaginary part + raises(ValueError, lambda: S(''' + Min(-sqrt(3)*cos(pi/18)/6 + re(1/((-1/2 - sqrt(3)*I/2)*(1/6 + + sqrt(3)*I/18)**(1/3)))/3 + sin(pi/18)/2 + 2 + I*(-cos(pi/18)/2 - + sqrt(3)*sin(pi/18)/6 + im(1/((-1/2 - sqrt(3)*I/2)*(1/6 + + sqrt(3)*I/18)**(1/3)))/3), re(1/((-1/2 + sqrt(3)*I/2)*(1/6 + + sqrt(3)*I/18)**(1/3)))/3 - sqrt(3)*cos(pi/18)/6 - sin(pi/18)/2 + 2 + + I*(im(1/((-1/2 + sqrt(3)*I/2)*(1/6 + sqrt(3)*I/18)**(1/3)))/3 - + sqrt(3)*sin(pi/18)/6 + cos(pi/18)/2))''')) + # if that is changed so a non-comparable number remains as + # an arg, then the Min/Max instantiation needs to be changed + # to watch out for non-comparable args when making simplifications + # and the following test should be added instead (with e being + # the sympified expression above): + # raises(ValueError, lambda: e._eval_evalf(2)) + + +def test_issue_10395(): + eq = x*Max(0, y) + assert nfloat(eq) == eq + eq = x*Max(y, -1.1) + assert nfloat(eq) == eq + assert Max(y, 4).n() == Max(4.0, y) + + +def test_issue_13098(): + assert floor(log(S('9.'+'9'*20), 10)) == 0 + assert ceiling(log(S('9.'+'9'*20), 10)) == 1 + assert floor(log(20 - S('9.'+'9'*20), 10)) == 1 + assert ceiling(log(20 - S('9.'+'9'*20), 10)) == 2 + + +def test_issue_14601(): + e = 5*x*y/2 - y*(35*(x**3)/2 - 15*x/2) + subst = {x:0.0, y:0.0} + e2 = e.evalf(subs=subst) + assert float(e2) == 0.0 + assert float((x + x*(x**2 + x)).evalf(subs={x: 0.0})) == 0.0 + + +def test_issue_11151(): + z = S.Zero + e = Sum(z, (x, 1, 2)) + assert e != z # it shouldn't evaluate + # when it does evaluate, this is what it should give + assert evalf(e, 15, {}) == \ + evalf(z, 15, {}) == (None, None, 15, None) + # so this shouldn't fail + assert (e/2).n() == 0 + # this was where the issue appeared + expr0 = Sum(x**2 + x, (x, 1, 2)) + expr1 = Sum(0, (x, 1, 2)) + expr2 = expr1/expr0 + assert simplify(factor(expr2) - expr2) == 0 + + +def test_issue_13425(): + assert N('2**.5', 30) == N('sqrt(2)', 30) + assert N('x - x', 30) == 0 + assert abs((N('pi*.1', 22)*10 - pi).n()) < 1e-22 + + +def test_issue_17421(): + assert N(acos(-I + acosh(cosh(cosh(1) + I)))) == 1.0*I + + +def test_issue_20291(): + from sympy.sets import EmptySet, Reals + from sympy.sets.sets import (Complement, FiniteSet, Intersection) + a = Symbol('a') + b = Symbol('b') + A = FiniteSet(a, b) + assert A.evalf(subs={a: 1, b: 2}) == FiniteSet(1.0, 2.0) + B = FiniteSet(a-b, 1) + assert B.evalf(subs={a: 1, b: 2}) == FiniteSet(-1.0, 1.0) + + sol = Complement(Intersection(FiniteSet(-b/2 - sqrt(b**2-4*pi)/2), Reals), FiniteSet(0)) + assert sol.evalf(subs={b: 1}) == EmptySet + + +def test_evalf_with_zoo(): + assert (1/x).evalf(subs={x: 0}) == zoo # issue 8242 + assert (-1/x).evalf(subs={x: 0}) == zoo # PR 16150 + assert (0 ** x).evalf(subs={x: -1}) == zoo # PR 16150 + assert (0 ** x).evalf(subs={x: -1 + I}) == nan + assert Mul(2, Pow(0, -1, evaluate=False), evaluate=False).evalf() == zoo # issue 21147 + assert Mul(x, 1/x, evaluate=False).evalf(subs={x: 0}) == Mul(x, 1/x, evaluate=False).subs(x, 0) == nan + assert Mul(1/x, 1/x, evaluate=False).evalf(subs={x: 0}) == zoo + assert Mul(1/x, Abs(1/x), evaluate=False).evalf(subs={x: 0}) == zoo + assert Abs(zoo, evaluate=False).evalf() == oo + assert re(zoo, evaluate=False).evalf() == nan + assert im(zoo, evaluate=False).evalf() == nan + assert Add(zoo, zoo, evaluate=False).evalf() == nan + assert Add(oo, zoo, evaluate=False).evalf() == nan + assert Pow(zoo, -1, evaluate=False).evalf() == 0 + assert Pow(zoo, Rational(-1, 3), evaluate=False).evalf() == 0 + assert Pow(zoo, Rational(1, 3), evaluate=False).evalf() == zoo + assert Pow(zoo, S.Half, evaluate=False).evalf() == zoo + assert Pow(zoo, 2, evaluate=False).evalf() == zoo + assert Pow(0, zoo, evaluate=False).evalf() == nan + assert log(zoo, evaluate=False).evalf() == zoo + assert zoo.evalf(chop=True) == zoo + assert x.evalf(subs={x: zoo}) == zoo + + +def test_evalf_with_bounded_error(): + cases = [ + # zero + (Rational(0), None, 1), + # zero im part + (pi, None, 10), + # zero real part + (pi*I, None, 10), + # re and im nonzero + (2-3*I, None, 5), + # similar tests again, but using eps instead of m + (Rational(0), Rational(1, 2), None), + (pi, Rational(1, 1000), None), + (pi * I, Rational(1, 1000), None), + (2 - 3 * I, Rational(1, 1000), None), + # very large eps + (2 - 3 * I, Rational(1000), None), + # case where x already small, hence some cancellation in p = m + n - 1 + (Rational(1234, 10**8), Rational(1, 10**12), None), + ] + for x0, eps, m in cases: + a, b, _, _ = evalf(x0, 53, {}) + c, d, _, _ = _evalf_with_bounded_error(x0, eps, m) + if eps is None: + eps = 2**(-m) + z = make_mpc((a or fzero, b or fzero)) + w = make_mpc((c or fzero, d or fzero)) + assert abs(w - z) < eps + + # eps must be positive + raises(ValueError, lambda: _evalf_with_bounded_error(pi, Rational(0))) + raises(ValueError, lambda: _evalf_with_bounded_error(pi, -pi)) + raises(ValueError, lambda: _evalf_with_bounded_error(pi, I)) + + +def test_issue_22849(): + a = -8 + 3 * sqrt(3) + x = AlgebraicNumber(a) + assert evalf(a, 1, {}) == evalf(x, 1, {}) + + +def test_evalf_real_alg_num(): + # This test demonstrates why the entry for `AlgebraicNumber` in + # `sympy.core.evalf._create_evalf_table()` has to use `x.to_root()`, + # instead of `x.as_expr()`. If the latter is used, then `z` will be + # a complex number with `0.e-20` for imaginary part, even though `a5` + # is a real number. + zeta = Symbol('zeta') + a5 = AlgebraicNumber(CRootOf(cyclotomic_poly(5), -1), [-1, -1, 0, 0], alias=zeta) + z = a5.evalf() + assert isinstance(z, Float) + assert not hasattr(z, '_mpc_') + assert hasattr(z, '_mpf_') + + +def test_issue_20733(): + expr = 1/((x - 9)*(x - 8)*(x - 7)*(x - 4)**2*(x - 3)**3*(x - 2)) + assert str(expr.evalf(1, subs={x:1})) == '-4.e-5' + assert str(expr.evalf(2, subs={x:1})) == '-4.1e-5' + assert str(expr.evalf(11, subs={x:1})) == '-4.1335978836e-5' + assert str(expr.evalf(20, subs={x:1})) == '-0.000041335978835978835979' + + expr = Mul(*((x - i) for i in range(2, 1000))) + assert srepr(expr.evalf(2, subs={x: 1})) == "Float('4.0271e+2561', precision=10)" + assert srepr(expr.evalf(10, subs={x: 1})) == "Float('4.02790050126e+2561', precision=37)" + assert srepr(expr.evalf(53, subs={x: 1})) == "Float('4.0279005012722099453824067459760158730668154575647110393e+2561', precision=179)" diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_expand.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_expand.py new file mode 100644 index 0000000000000000000000000000000000000000..e7abb5daacebbe81664b3de3a7ac35a490ab31bc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_expand.py @@ -0,0 +1,364 @@ +from sympy.core.expr import unchanged +from sympy.core.mul import Mul +from sympy.core.numbers import (I, Rational as R, pi) +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.series.order import O +from sympy.simplify.radsimp import expand_numer +from sympy.core.function import (expand, expand_multinomial, + expand_power_base, expand_log) + +from sympy.testing.pytest import raises +from sympy.core.random import verify_numerically + +from sympy.abc import x, y, z + + +def test_expand_no_log(): + assert ( + (1 + log(x**4))**2).expand(log=False) == 1 + 2*log(x**4) + log(x**4)**2 + assert ((1 + log(x**4))*(1 + log(x**3))).expand( + log=False) == 1 + log(x**4) + log(x**3) + log(x**4)*log(x**3) + + +def test_expand_no_multinomial(): + assert ((1 + x)*(1 + (1 + x)**4)).expand(multinomial=False) == \ + 1 + x + (1 + x)**4 + x*(1 + x)**4 + + +def test_expand_negative_integer_powers(): + expr = (x + y)**(-2) + assert expr.expand() == 1 / (2*x*y + x**2 + y**2) + assert expr.expand(multinomial=False) == (x + y)**(-2) + expr = (x + y)**(-3) + assert expr.expand() == 1 / (3*x*x*y + 3*x*y*y + x**3 + y**3) + assert expr.expand(multinomial=False) == (x + y)**(-3) + expr = (x + y)**(2) * (x + y)**(-4) + assert expr.expand() == 1 / (2*x*y + x**2 + y**2) + assert expr.expand(multinomial=False) == (x + y)**(-2) + + +def test_expand_non_commutative(): + A = Symbol('A', commutative=False) + B = Symbol('B', commutative=False) + C = Symbol('C', commutative=False) + a = Symbol('a') + b = Symbol('b') + i = Symbol('i', integer=True) + n = Symbol('n', negative=True) + m = Symbol('m', negative=True) + p = Symbol('p', polar=True) + np = Symbol('p', polar=False) + + assert (C*(A + B)).expand() == C*A + C*B + assert (C*(A + B)).expand() != A*C + B*C + assert ((A + B)**2).expand() == A**2 + A*B + B*A + B**2 + assert ((A + B)**3).expand() == (A**2*B + B**2*A + A*B**2 + B*A**2 + + A**3 + B**3 + A*B*A + B*A*B) + # issue 6219 + assert ((a*A*B*A**-1)**2).expand() == a**2*A*B**2/A + # Note that (a*A*B*A**-1)**2 is automatically converted to a**2*(A*B*A**-1)**2 + assert ((a*A*B*A**-1)**2).expand(deep=False) == a**2*(A*B*A**-1)**2 + assert ((a*A*B*A**-1)**2).expand() == a**2*(A*B**2*A**-1) + assert ((a*A*B*A**-1)**2).expand(force=True) == a**2*A*B**2*A**(-1) + assert ((a*A*B)**2).expand() == a**2*A*B*A*B + assert ((a*A)**2).expand() == a**2*A**2 + assert ((a*A*B)**i).expand() == a**i*(A*B)**i + assert ((a*A*(B*(A*B/A)**2))**i).expand() == a**i*(A*B*A*B**2/A)**i + # issue 6558 + assert (A*B*(A*B)**-1).expand() == 1 + assert ((a*A)**i).expand() == a**i*A**i + assert ((a*A*B*A**-1)**3).expand() == a**3*A*B**3/A + assert ((a*A*B*A*B/A)**3).expand() == \ + a**3*A*B*(A*B**2)*(A*B**2)*A*B*A**(-1) + assert ((a*A*B*A*B/A)**-2).expand() == \ + A*B**-1*A**-1*B**-2*A**-1*B**-1*A**-1/a**2 + assert ((a*b*A*B*A**-1)**i).expand() == a**i*b**i*(A*B/A)**i + assert ((a*(a*b)**i)**i).expand() == a**i*a**(i**2)*b**(i**2) + e = Pow(Mul(a, 1/a, A, B, evaluate=False), S(2), evaluate=False) + assert e.expand() == A*B*A*B + assert sqrt(a*(A*b)**i).expand() == sqrt(a*b**i*A**i) + assert (sqrt(-a)**a).expand() == sqrt(-a)**a + assert expand((-2*n)**(i/3)) == 2**(i/3)*(-n)**(i/3) + assert expand((-2*n*m)**(i/a)) == (-2)**(i/a)*(-n)**(i/a)*(-m)**(i/a) + assert expand((-2*a*p)**b) == 2**b*p**b*(-a)**b + assert expand((-2*a*np)**b) == 2**b*(-a*np)**b + assert expand(sqrt(A*B)) == sqrt(A*B) + assert expand(sqrt(-2*a*b)) == sqrt(2)*sqrt(-a*b) + + +def test_expand_radicals(): + a = (x + y)**R(1, 2) + + assert (a**1).expand() == a + assert (a**3).expand() == x*a + y*a + assert (a**5).expand() == x**2*a + 2*x*y*a + y**2*a + + assert (1/a**1).expand() == 1/a + assert (1/a**3).expand() == 1/(x*a + y*a) + assert (1/a**5).expand() == 1/(x**2*a + 2*x*y*a + y**2*a) + + a = (x + y)**R(1, 3) + + assert (a**1).expand() == a + assert (a**2).expand() == a**2 + assert (a**4).expand() == x*a + y*a + assert (a**5).expand() == x*a**2 + y*a**2 + assert (a**7).expand() == x**2*a + 2*x*y*a + y**2*a + + +def test_expand_modulus(): + assert ((x + y)**11).expand(modulus=11) == x**11 + y**11 + assert ((x + sqrt(2)*y)**11).expand(modulus=11) == x**11 + 10*sqrt(2)*y**11 + assert (x + y/2).expand(modulus=1) == y/2 + + raises(ValueError, lambda: ((x + y)**11).expand(modulus=0)) + raises(ValueError, lambda: ((x + y)**11).expand(modulus=x)) + + +def test_issue_5743(): + assert (x*sqrt( + x + y)*(1 + sqrt(x + y))).expand() == x**2 + x*y + x*sqrt(x + y) + assert (x*sqrt( + x + y)*(1 + x*sqrt(x + y))).expand() == x**3 + x**2*y + x*sqrt(x + y) + + +def test_expand_frac(): + assert expand((x + y)*y/x/(x + 1), frac=True) == \ + (x*y + y**2)/(x**2 + x) + assert expand((x + y)*y/x/(x + 1), numer=True) == \ + (x*y + y**2)/(x*(x + 1)) + assert expand((x + y)*y/x/(x + 1), denom=True) == \ + y*(x + y)/(x**2 + x) + eq = (x + 1)**2/y + assert expand_numer(eq, multinomial=False) == eq + # issue 26329 + eq = (exp(x*z) - exp(y*z))/exp(z*(x + y)) + ans = exp(-y*z) - exp(-x*z) + assert eq.expand(numer=True) != ans + assert eq.expand(numer=True, exact=True) == ans + assert expand_numer(eq) != ans + assert expand_numer(eq, exact=True) == ans + + +def test_issue_6121(): + eq = -I*exp(-3*I*pi/4)/(4*pi**(S(3)/2)*sqrt(x)) + assert eq.expand(complex=True) # does not give oo recursion + eq = -I*exp(-3*I*pi/4)/(4*pi**(R(3, 2))*sqrt(x)) + assert eq.expand(complex=True) # does not give oo recursion + + +def test_expand_power_base(): + assert expand_power_base((x*y*z)**4) == x**4*y**4*z**4 + assert expand_power_base((x*y*z)**x).is_Pow + assert expand_power_base((x*y*z)**x, force=True) == x**x*y**x*z**x + assert expand_power_base((x*(y*z)**2)**3) == x**3*y**6*z**6 + + assert expand_power_base((sin((x*y)**2)*y)**z).is_Pow + assert expand_power_base( + (sin((x*y)**2)*y)**z, force=True) == sin((x*y)**2)**z*y**z + assert expand_power_base( + (sin((x*y)**2)*y)**z, deep=True) == (sin(x**2*y**2)*y)**z + + assert expand_power_base(exp(x)**2) == exp(2*x) + assert expand_power_base((exp(x)*exp(y))**2) == exp(2*x)*exp(2*y) + + assert expand_power_base( + (exp((x*y)**z)*exp(y))**2) == exp(2*(x*y)**z)*exp(2*y) + assert expand_power_base((exp((x*y)**z)*exp( + y))**2, deep=True, force=True) == exp(2*x**z*y**z)*exp(2*y) + + assert expand_power_base((exp(x)*exp(y))**z).is_Pow + assert expand_power_base( + (exp(x)*exp(y))**z, force=True) == exp(x)**z*exp(y)**z + + +def test_expand_arit(): + a = Symbol("a") + b = Symbol("b", positive=True) + c = Symbol("c") + + p = R(5) + e = (a + b)*c + assert e == c*(a + b) + assert (e.expand() - a*c - b*c) == R(0) + e = (a + b)*(a + b) + assert e == (a + b)**2 + assert e.expand() == 2*a*b + a**2 + b**2 + e = (a + b)*(a + b)**R(2) + assert e == (a + b)**3 + assert e.expand() == 3*b*a**2 + 3*a*b**2 + a**3 + b**3 + assert e.expand() == 3*b*a**2 + 3*a*b**2 + a**3 + b**3 + e = (a + b)*(a + c)*(b + c) + assert e == (a + c)*(a + b)*(b + c) + assert e.expand() == 2*a*b*c + b*a**2 + c*a**2 + b*c**2 + a*c**2 + c*b**2 + a*b**2 + e = (a + R(1))**p + assert e == (1 + a)**5 + assert e.expand() == 1 + 5*a + 10*a**2 + 10*a**3 + 5*a**4 + a**5 + e = (a + b + c)*(a + c + p) + assert e == (5 + a + c)*(a + b + c) + assert e.expand() == 5*a + 5*b + 5*c + 2*a*c + b*c + a*b + a**2 + c**2 + x = Symbol("x") + s = exp(x*x) - 1 + e = s.nseries(x, 0, 6)/x**2 + assert e.expand() == 1 + x**2/2 + O(x**4) + + e = (x*(y + z))**(x*(y + z))*(x + y) + assert e.expand(power_exp=False, power_base=False) == x*(x*y + x* + z)**(x*y + x*z) + y*(x*y + x*z)**(x*y + x*z) + assert e.expand(power_exp=False, power_base=False, deep=False) == x* \ + (x*(y + z))**(x*(y + z)) + y*(x*(y + z))**(x*(y + z)) + e = x * (x + (y + 1)**2) + assert e.expand(deep=False) == x**2 + x*(y + 1)**2 + e = (x*(y + z))**z + assert e.expand(power_base=True, mul=True, deep=True) in [x**z*(y + + z)**z, (x*y + x*z)**z] + assert ((2*y)**z).expand() == 2**z*y**z + p = Symbol('p', positive=True) + assert sqrt(-x).expand().is_Pow + assert sqrt(-x).expand(force=True) == I*sqrt(x) + assert ((2*y*p)**z).expand() == 2**z*p**z*y**z + assert ((2*y*p*x)**z).expand() == 2**z*p**z*(x*y)**z + assert ((2*y*p*x)**z).expand(force=True) == 2**z*p**z*x**z*y**z + assert ((2*y*p*-pi)**z).expand() == 2**z*pi**z*p**z*(-y)**z + assert ((2*y*p*-pi*x)**z).expand() == 2**z*pi**z*p**z*(-x*y)**z + n = Symbol('n', negative=True) + m = Symbol('m', negative=True) + assert ((-2*x*y*n)**z).expand() == 2**z*(-n)**z*(x*y)**z + assert ((-2*x*y*n*m)**z).expand() == 2**z*(-m)**z*(-n)**z*(-x*y)**z + # issue 5482 + assert sqrt(-2*x*n) == sqrt(2)*sqrt(-n)*sqrt(x) + # issue 5605 (2) + assert (cos(x + y)**2).expand(trig=True) in [ + (-sin(x)*sin(y) + cos(x)*cos(y))**2, + sin(x)**2*sin(y)**2 - 2*sin(x)*sin(y)*cos(x)*cos(y) + cos(x)**2*cos(y)**2 + ] + + # Check that this isn't too slow + x = Symbol('x') + W = 1 + for i in range(1, 21): + W = W * (x - i) + W = W.expand() + assert W.has(-1672280820*x**15) + +def test_expand_mul(): + # part of issue 20597 + e = Mul(2, 3, evaluate=False) + assert e.expand() == 6 + + e = Mul(2, 3, 1/x, evaluate=False) + assert e.expand() == 6/x + e = Mul(2, R(1, 3), evaluate=False) + assert e.expand() == R(2, 3) + +def test_power_expand(): + """Test for Pow.expand()""" + a = Symbol('a') + b = Symbol('b') + p = (a + b)**2 + assert p.expand() == a**2 + b**2 + 2*a*b + + p = (1 + 2*(1 + a))**2 + assert p.expand() == 9 + 4*(a**2) + 12*a + + p = 2**(a + b) + assert p.expand() == 2**a*2**b + + A = Symbol('A', commutative=False) + B = Symbol('B', commutative=False) + assert (2**(A + B)).expand() == 2**(A + B) + assert (A**(a + b)).expand() != A**(a + b) + + +def test_issues_5919_6830(): + # issue 5919 + n = -1 + 1/x + z = n/x/(-n)**2 - 1/n/x + assert expand(z) == 1/(x**2 - 2*x + 1) - 1/(x - 2 + 1/x) - 1/(-x + 1) + + # issue 6830 + p = (1 + x)**2 + assert expand_multinomial((1 + x*p)**2) == ( + x**2*(x**4 + 4*x**3 + 6*x**2 + 4*x + 1) + 2*x*(x**2 + 2*x + 1) + 1) + assert expand_multinomial((1 + (y + x)*p)**2) == ( + 2*((x + y)*(x**2 + 2*x + 1)) + (x**2 + 2*x*y + y**2)* + (x**4 + 4*x**3 + 6*x**2 + 4*x + 1) + 1) + A = Symbol('A', commutative=False) + p = (1 + A)**2 + assert expand_multinomial((1 + x*p)**2) == ( + x**2*(1 + 4*A + 6*A**2 + 4*A**3 + A**4) + 2*x*(1 + 2*A + A**2) + 1) + assert expand_multinomial((1 + (y + x)*p)**2) == ( + (x + y)*(1 + 2*A + A**2)*2 + (x**2 + 2*x*y + y**2)* + (1 + 4*A + 6*A**2 + 4*A**3 + A**4) + 1) + assert expand_multinomial((1 + (y + x)*p)**3) == ( + (x + y)*(1 + 2*A + A**2)*3 + (x**2 + 2*x*y + y**2)*(1 + 4*A + + 6*A**2 + 4*A**3 + A**4)*3 + (x**3 + 3*x**2*y + 3*x*y**2 + y**3)*(1 + 6*A + + 15*A**2 + 20*A**3 + 15*A**4 + 6*A**5 + A**6) + 1) + # unevaluate powers + eq = (Pow((x + 1)*((A + 1)**2), 2, evaluate=False)) + # - in this case the base is not an Add so no further + # expansion is done + assert expand_multinomial(eq) == \ + (x**2 + 2*x + 1)*(1 + 4*A + 6*A**2 + 4*A**3 + A**4) + # - but here, the expanded base *is* an Add so it gets expanded + eq = (Pow(((A + 1)**2), 2, evaluate=False)) + assert expand_multinomial(eq) == 1 + 4*A + 6*A**2 + 4*A**3 + A**4 + + # coverage + def ok(a, b, n): + e = (a + I*b)**n + return verify_numerically(e, expand_multinomial(e)) + + for a in [2, S.Half]: + for b in [3, R(1, 3)]: + for n in range(2, 6): + assert ok(a, b, n) + + assert expand_multinomial((x + 1 + O(z))**2) == \ + 1 + 2*x + x**2 + O(z) + assert expand_multinomial((x + 1 + O(z))**3) == \ + 1 + 3*x + 3*x**2 + x**3 + O(z) + + assert expand_multinomial(3**(x + y + 3)) == 27*3**(x + y) + +def test_expand_log(): + t = Symbol('t', positive=True) + # after first expansion, -2*log(2) + log(4); then 0 after second + assert expand(log(t**2) - log(t**2/4) - 2*log(2)) == 0 + assert expand_log(log(7*6)/log(6)) == 1 + log(7)/log(6) + b = factorial(10) + assert expand_log(log(7*b**4)/log(b) + ) == 4 + log(7)/log(b) + + +def test_issue_23952(): + assert (x**(y + z)).expand(force=True) == x**y*x**z + one = Symbol('1', integer=True, prime=True, odd=True, positive=True) + two = Symbol('2', integer=True, prime=True, even=True) + e = two - one + for b in (0, x): + # 0**e = 0, 0**-e = zoo; but if expanded then nan + assert unchanged(Pow, b, e) # power_exp + assert unchanged(Pow, b, -e) # power_exp + assert unchanged(Pow, b, y - x) # power_exp + assert unchanged(Pow, b, 3 - x) # multinomial + assert (b**e).expand().is_Pow # power_exp + assert (b**-e).expand().is_Pow # power_exp + assert (b**(y - x)).expand().is_Pow # power_exp + assert (b**(3 - x)).expand().is_Pow # multinomial + nn1 = Symbol('nn1', nonnegative=True) + nn2 = Symbol('nn2', nonnegative=True) + nn3 = Symbol('nn3', nonnegative=True) + assert (x**(nn1 + nn2)).expand() == x**nn1*x**nn2 + assert (x**(-nn1 - nn2)).expand() == x**-nn1*x**-nn2 + assert unchanged(Pow, x, nn1 + nn2 - nn3) + assert unchanged(Pow, x, 1 + nn2 - nn3) + assert unchanged(Pow, x, nn1 - nn2) + assert unchanged(Pow, x, 1 - nn2) + assert unchanged(Pow, x, -1 + nn2) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_expr.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_expr.py new file mode 100644 index 0000000000000000000000000000000000000000..8299ca312cad03d68064c592e4f4e5adc7a96fcc --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_expr.py @@ -0,0 +1,2288 @@ +from sympy.assumptions.refine import refine +from sympy.concrete.summations import Sum +from sympy.core.add import Add +from sympy.core.basic import Basic +from sympy.core.containers import Tuple +from sympy.core.expr import (ExprBuilder, unchanged, Expr, + UnevaluatedExpr) +from sympy.core.function import (Function, expand, WildFunction, + AppliedUndef, Derivative, diff, Subs) +from sympy.core.mul import Mul +from sympy.core.numbers import (NumberSymbol, E, zoo, oo, Float, I, + Rational, nan, Integer, Number, pi, _illegal) +from sympy.core.power import Pow +from sympy.core.relational import Ge, Lt, Gt, Le +from sympy.core.singleton import S +from sympy.core.sorting import default_sort_key +from sympy.core.symbol import Symbol, symbols, Dummy, Wild +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.exponential import exp_polar, exp, log +from sympy.functions.elementary.miscellaneous import sqrt, Max +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import tan, sin, cos +from sympy.functions.special.delta_functions import (Heaviside, + DiracDelta) +from sympy.functions.special.error_functions import Si +from sympy.functions.special.gamma_functions import gamma +from sympy.integrals.integrals import integrate, Integral +from sympy.physics.secondquant import FockState +from sympy.polys.partfrac import apart +from sympy.polys.polytools import factor, cancel, Poly +from sympy.polys.rationaltools import together +from sympy.series.order import O +from sympy.sets.sets import FiniteSet +from sympy.simplify.combsimp import combsimp +from sympy.simplify.gammasimp import gammasimp +from sympy.simplify.powsimp import powsimp +from sympy.simplify.radsimp import collect, radsimp +from sympy.simplify.ratsimp import ratsimp +from sympy.simplify.simplify import simplify, nsimplify +from sympy.simplify.trigsimp import trigsimp +from sympy.tensor.indexed import Indexed +from sympy.physics.units import meter + +from sympy.testing.pytest import raises, XFAIL + +from sympy.abc import a, b, c, n, t, u, x, y, z + + +f, g, h = symbols('f,g,h', cls=Function) + + +class DummyNumber: + """ + Minimal implementation of a number that works with SymPy. + + If one has a Number class (e.g. Sage Integer, or some other custom class) + that one wants to work well with SymPy, one has to implement at least the + methods of this class DummyNumber, resp. its subclasses I5 and F1_1. + + Basically, one just needs to implement either __int__() or __float__() and + then one needs to make sure that the class works with Python integers and + with itself. + """ + + def __radd__(self, a): + if isinstance(a, (int, float)): + return a + self.number + return NotImplemented + + def __add__(self, a): + if isinstance(a, (int, float, DummyNumber)): + return self.number + a + return NotImplemented + + def __rsub__(self, a): + if isinstance(a, (int, float)): + return a - self.number + return NotImplemented + + def __sub__(self, a): + if isinstance(a, (int, float, DummyNumber)): + return self.number - a + return NotImplemented + + def __rmul__(self, a): + if isinstance(a, (int, float)): + return a * self.number + return NotImplemented + + def __mul__(self, a): + if isinstance(a, (int, float, DummyNumber)): + return self.number * a + return NotImplemented + + def __rtruediv__(self, a): + if isinstance(a, (int, float)): + return a / self.number + return NotImplemented + + def __truediv__(self, a): + if isinstance(a, (int, float, DummyNumber)): + return self.number / a + return NotImplemented + + def __rpow__(self, a): + if isinstance(a, (int, float)): + return a ** self.number + return NotImplemented + + def __pow__(self, a): + if isinstance(a, (int, float, DummyNumber)): + return self.number ** a + return NotImplemented + + def __pos__(self): + return self.number + + def __neg__(self): + return - self.number + + +class I5(DummyNumber): + number = 5 + + def __int__(self): + return self.number + + +class F1_1(DummyNumber): + number = 1.1 + + def __float__(self): + return self.number + +i5 = I5() +f1_1 = F1_1() + +# basic SymPy objects +basic_objs = [ + Rational(2), + Float("1.3"), + x, + y, + pow(x, y)*y, +] + +# all supported objects +all_objs = basic_objs + [ + 5, + 5.5, + i5, + f1_1 +] + + +def dotest(s): + for xo in all_objs: + for yo in all_objs: + s(xo, yo) + return True + + +def test_basic(): + def j(a, b): + x = a + x = +a + x = -a + x = a + b + x = a - b + x = a*b + x = a/b + x = a**b + del x + assert dotest(j) + + +def test_ibasic(): + def s(a, b): + x = a + x += b + x = a + x -= b + x = a + x *= b + x = a + x /= b + assert dotest(s) + + +class NonBasic: + '''This class represents an object that knows how to implement binary + operations like +, -, etc with Expr but is not a subclass of Basic itself. + The NonExpr subclass below does subclass Basic but not Expr. + + For both NonBasic and NonExpr it should be possible for them to override + Expr.__add__ etc because Expr.__add__ should be returning NotImplemented + for non Expr classes. Otherwise Expr.__add__ would create meaningless + objects like Add(Integer(1), FiniteSet(2)) and it wouldn't be possible for + other classes to override these operations when interacting with Expr. + ''' + def __add__(self, other): + return SpecialOp('+', self, other) + + def __radd__(self, other): + return SpecialOp('+', other, self) + + def __sub__(self, other): + return SpecialOp('-', self, other) + + def __rsub__(self, other): + return SpecialOp('-', other, self) + + def __mul__(self, other): + return SpecialOp('*', self, other) + + def __rmul__(self, other): + return SpecialOp('*', other, self) + + def __truediv__(self, other): + return SpecialOp('/', self, other) + + def __rtruediv__(self, other): + return SpecialOp('/', other, self) + + def __floordiv__(self, other): + return SpecialOp('//', self, other) + + def __rfloordiv__(self, other): + return SpecialOp('//', other, self) + + def __mod__(self, other): + return SpecialOp('%', self, other) + + def __rmod__(self, other): + return SpecialOp('%', other, self) + + def __divmod__(self, other): + return SpecialOp('divmod', self, other) + + def __rdivmod__(self, other): + return SpecialOp('divmod', other, self) + + def __pow__(self, other): + return SpecialOp('**', self, other) + + def __rpow__(self, other): + return SpecialOp('**', other, self) + + def __lt__(self, other): + return SpecialOp('<', self, other) + + def __gt__(self, other): + return SpecialOp('>', self, other) + + def __le__(self, other): + return SpecialOp('<=', self, other) + + def __ge__(self, other): + return SpecialOp('>=', self, other) + + +class NonExpr(Basic, NonBasic): + '''Like NonBasic above except this is a subclass of Basic but not Expr''' + pass + + +class SpecialOp(): + '''Represents the results of operations with NonBasic and NonExpr''' + def __new__(cls, op, arg1, arg2): + obj = object.__new__(cls) + obj.args = (op, arg1, arg2) + return obj + + +class NonArithmetic(Basic): + '''Represents a Basic subclass that does not support arithmetic operations''' + pass + + +def test_cooperative_operations(): + '''Tests that Expr uses binary operations cooperatively. + + In particular it should be possible for non-Expr classes to override + binary operators like +, - etc when used with Expr instances. This should + work for non-Expr classes whether they are Basic subclasses or not. Also + non-Expr classes that do not define binary operators with Expr should give + TypeError. + ''' + # A bunch of instances of Expr subclasses + exprs = [ + Expr(), + S.Zero, + S.One, + S.Infinity, + S.NegativeInfinity, + S.ComplexInfinity, + S.Half, + Float(0.5), + Integer(2), + Symbol('x'), + Mul(2, Symbol('x')), + Add(2, Symbol('x')), + Pow(2, Symbol('x')), + ] + + for e in exprs: + # Test that these classes can override arithmetic operations in + # combination with various Expr types. + for ne in [NonBasic(), NonExpr()]: + + results = [ + (ne + e, ('+', ne, e)), + (e + ne, ('+', e, ne)), + (ne - e, ('-', ne, e)), + (e - ne, ('-', e, ne)), + (ne * e, ('*', ne, e)), + (e * ne, ('*', e, ne)), + (ne / e, ('/', ne, e)), + (e / ne, ('/', e, ne)), + (ne // e, ('//', ne, e)), + (e // ne, ('//', e, ne)), + (ne % e, ('%', ne, e)), + (e % ne, ('%', e, ne)), + (divmod(ne, e), ('divmod', ne, e)), + (divmod(e, ne), ('divmod', e, ne)), + (ne ** e, ('**', ne, e)), + (e ** ne, ('**', e, ne)), + (e < ne, ('>', ne, e)), + (ne < e, ('<', ne, e)), + (e > ne, ('<', ne, e)), + (ne > e, ('>', ne, e)), + (e <= ne, ('>=', ne, e)), + (ne <= e, ('<=', ne, e)), + (e >= ne, ('<=', ne, e)), + (ne >= e, ('>=', ne, e)), + ] + + for res, args in results: + assert type(res) is SpecialOp and res.args == args + + # These classes do not support binary operators with Expr. Every + # operation should raise in combination with any of the Expr types. + for na in [NonArithmetic(), object()]: + + raises(TypeError, lambda : e + na) + raises(TypeError, lambda : na + e) + raises(TypeError, lambda : e - na) + raises(TypeError, lambda : na - e) + raises(TypeError, lambda : e * na) + raises(TypeError, lambda : na * e) + raises(TypeError, lambda : e / na) + raises(TypeError, lambda : na / e) + raises(TypeError, lambda : e // na) + raises(TypeError, lambda : na // e) + raises(TypeError, lambda : e % na) + raises(TypeError, lambda : na % e) + raises(TypeError, lambda : divmod(e, na)) + raises(TypeError, lambda : divmod(na, e)) + raises(TypeError, lambda : e ** na) + raises(TypeError, lambda : na ** e) + raises(TypeError, lambda : e > na) + raises(TypeError, lambda : na > e) + raises(TypeError, lambda : e < na) + raises(TypeError, lambda : na < e) + raises(TypeError, lambda : e >= na) + raises(TypeError, lambda : na >= e) + raises(TypeError, lambda : e <= na) + raises(TypeError, lambda : na <= e) + + +def test_relational(): + from sympy.core.relational import Lt + assert (pi < 3) is S.false + assert (pi <= 3) is S.false + assert (pi > 3) is S.true + assert (pi >= 3) is S.true + assert (-pi < 3) is S.true + assert (-pi <= 3) is S.true + assert (-pi > 3) is S.false + assert (-pi >= 3) is S.false + r = Symbol('r', real=True) + assert (r - 2 < r - 3) is S.false + assert Lt(x + I, x + I + 2).func == Lt # issue 8288 + + +def test_relational_assumptions(): + m1 = Symbol("m1", nonnegative=False) + m2 = Symbol("m2", positive=False) + m3 = Symbol("m3", nonpositive=False) + m4 = Symbol("m4", negative=False) + assert (m1 < 0) == Lt(m1, 0) + assert (m2 <= 0) == Le(m2, 0) + assert (m3 > 0) == Gt(m3, 0) + assert (m4 >= 0) == Ge(m4, 0) + m1 = Symbol("m1", nonnegative=False, real=True) + m2 = Symbol("m2", positive=False, real=True) + m3 = Symbol("m3", nonpositive=False, real=True) + m4 = Symbol("m4", negative=False, real=True) + assert (m1 < 0) is S.true + assert (m2 <= 0) is S.true + assert (m3 > 0) is S.true + assert (m4 >= 0) is S.true + m1 = Symbol("m1", negative=True) + m2 = Symbol("m2", nonpositive=True) + m3 = Symbol("m3", positive=True) + m4 = Symbol("m4", nonnegative=True) + assert (m1 < 0) is S.true + assert (m2 <= 0) is S.true + assert (m3 > 0) is S.true + assert (m4 >= 0) is S.true + m1 = Symbol("m1", negative=False, real=True) + m2 = Symbol("m2", nonpositive=False, real=True) + m3 = Symbol("m3", positive=False, real=True) + m4 = Symbol("m4", nonnegative=False, real=True) + assert (m1 < 0) is S.false + assert (m2 <= 0) is S.false + assert (m3 > 0) is S.false + assert (m4 >= 0) is S.false + + +# See https://github.com/sympy/sympy/issues/17708 +#def test_relational_noncommutative(): +# from sympy import Lt, Gt, Le, Ge +# A, B = symbols('A,B', commutative=False) +# assert (A < B) == Lt(A, B) +# assert (A <= B) == Le(A, B) +# assert (A > B) == Gt(A, B) +# assert (A >= B) == Ge(A, B) + + +def test_basic_nostr(): + for obj in basic_objs: + raises(TypeError, lambda: obj + '1') + raises(TypeError, lambda: obj - '1') + if obj == 2: + assert obj * '1' == '11' + else: + raises(TypeError, lambda: obj * '1') + raises(TypeError, lambda: obj / '1') + raises(TypeError, lambda: obj ** '1') + + +def test_series_expansion_for_uniform_order(): + assert (1/x + y + x).series(x, 0, 0) == 1/x + O(1, x) + assert (1/x + y + x).series(x, 0, 1) == 1/x + y + O(x) + assert (1/x + 1 + x).series(x, 0, 0) == 1/x + O(1, x) + assert (1/x + 1 + x).series(x, 0, 1) == 1/x + 1 + O(x) + assert (1/x + x).series(x, 0, 0) == 1/x + O(1, x) + assert (1/x + y + y*x + x).series(x, 0, 0) == 1/x + O(1, x) + assert (1/x + y + y*x + x).series(x, 0, 1) == 1/x + y + O(x) + + +def test_leadterm(): + assert (3 + 2*x**(log(3)/log(2) - 1)).leadterm(x) == (3, 0) + + assert (1/x**2 + 1 + x + x**2).leadterm(x)[1] == -2 + assert (1/x + 1 + x + x**2).leadterm(x)[1] == -1 + assert (x**2 + 1/x).leadterm(x)[1] == -1 + assert (1 + x**2).leadterm(x)[1] == 0 + assert (x + 1).leadterm(x)[1] == 0 + assert (x + x**2).leadterm(x)[1] == 1 + assert (x**2).leadterm(x)[1] == 2 + + +def test_as_leading_term(): + assert (3 + 2*x**(log(3)/log(2) - 1)).as_leading_term(x) == 3 + assert (1/x**2 + 1 + x + x**2).as_leading_term(x) == 1/x**2 + assert (1/x + 1 + x + x**2).as_leading_term(x) == 1/x + assert (x**2 + 1/x).as_leading_term(x) == 1/x + assert (1 + x**2).as_leading_term(x) == 1 + assert (x + 1).as_leading_term(x) == 1 + assert (x + x**2).as_leading_term(x) == x + assert (x**2).as_leading_term(x) == x**2 + assert (x + oo).as_leading_term(x) is oo + + raises(ValueError, lambda: (x + 1).as_leading_term(1)) + + # https://github.com/sympy/sympy/issues/21177 + e = -3*x + (x + Rational(3, 2) - sqrt(3)*S.ImaginaryUnit/2)**2\ + - Rational(3, 2) + 3*sqrt(3)*S.ImaginaryUnit/2 + assert e.as_leading_term(x) == \ + (12*sqrt(3)*x - 12*S.ImaginaryUnit*x)/(4*sqrt(3) + 12*S.ImaginaryUnit) + + # https://github.com/sympy/sympy/issues/21245 + e = 1 - x - x**2 + d = (1 + sqrt(5))/2 + assert e.subs(x, y + 1/d).as_leading_term(y) == \ + (-576*sqrt(5)*y - 1280*y)/(256*sqrt(5) + 576) + + +def test_leadterm2(): + assert (x*cos(1)*cos(1 + sin(1)) + sin(1 + sin(1))).leadterm(x) == \ + (sin(1 + sin(1)), 0) + + +def test_leadterm3(): + assert (y + z + x).leadterm(x) == (y + z, 0) + + +def test_as_leading_term2(): + assert (x*cos(1)*cos(1 + sin(1)) + sin(1 + sin(1))).as_leading_term(x) == \ + sin(1 + sin(1)) + + +def test_as_leading_term3(): + assert (2 + pi + x).as_leading_term(x) == 2 + pi + assert (2*x + pi*x + x**2).as_leading_term(x) == 2*x + pi*x + + +def test_as_leading_term4(): + # see issue 6843 + n = Symbol('n', integer=True, positive=True) + r = -n**3/(2*n**2 + 4*n + 2) - n**2/(n**2 + 2*n + 1) + \ + n**2/(n + 1) - n/(2*n**2 + 4*n + 2) + n/(n*x + x) + 2*n/(n + 1) - \ + 1 + 1/(n*x + x) + 1/(n + 1) - 1/x + assert r.as_leading_term(x).cancel() == n/2 + + +def test_as_leading_term_stub(): + class foo(Function): + pass + assert foo(1/x).as_leading_term(x) == foo(1/x) + assert foo(1).as_leading_term(x) == foo(1) + raises(NotImplementedError, lambda: foo(x).as_leading_term(x)) + + +def test_as_leading_term_deriv_integral(): + # related to issue 11313 + assert Derivative(x ** 3, x).as_leading_term(x) == 3*x**2 + assert Derivative(x ** 3, y).as_leading_term(x) == 0 + + assert Integral(x ** 3, x).as_leading_term(x) == x**4/4 + assert Integral(x ** 3, y).as_leading_term(x) == y*x**3 + + assert Derivative(exp(x), x).as_leading_term(x) == 1 + assert Derivative(log(x), x).as_leading_term(x) == (1/x).as_leading_term(x) + + +def test_atoms(): + assert x.atoms() == {x} + assert (1 + x).atoms() == {x, S.One} + + assert (1 + 2*cos(x)).atoms(Symbol) == {x} + assert (1 + 2*cos(x)).atoms(Symbol, Number) == {S.One, S(2), x} + + assert (2*(x**(y**x))).atoms() == {S(2), x, y} + + assert S.Half.atoms() == {S.Half} + assert S.Half.atoms(Symbol) == set() + + assert sin(oo).atoms(oo) == set() + + assert Poly(0, x).atoms() == {S.Zero, x} + assert Poly(1, x).atoms() == {S.One, x} + + assert Poly(x, x).atoms() == {x} + assert Poly(x, x, y).atoms() == {x, y} + assert Poly(x + y, x, y).atoms() == {x, y} + assert Poly(x + y, x, y, z).atoms() == {x, y, z} + assert Poly(x + y*t, x, y, z).atoms() == {t, x, y, z} + + assert (I*pi).atoms(NumberSymbol) == {pi} + assert (I*pi).atoms(NumberSymbol, I) == \ + (I*pi).atoms(I, NumberSymbol) == {pi, I} + + assert exp(exp(x)).atoms(exp) == {exp(exp(x)), exp(x)} + assert (1 + x*(2 + y) + exp(3 + z)).atoms(Add) == \ + {1 + x*(2 + y) + exp(3 + z), 2 + y, 3 + z} + + # issue 6132 + e = (f(x) + sin(x) + 2) + assert e.atoms(AppliedUndef) == \ + {f(x)} + assert e.atoms(AppliedUndef, Function) == \ + {f(x), sin(x)} + assert e.atoms(Function) == \ + {f(x), sin(x)} + assert e.atoms(AppliedUndef, Number) == \ + {f(x), S(2)} + assert e.atoms(Function, Number) == \ + {S(2), sin(x), f(x)} + + +def test_is_polynomial(): + k = Symbol('k', nonnegative=True, integer=True) + + assert Rational(2).is_polynomial(x, y, z) is True + assert (S.Pi).is_polynomial(x, y, z) is True + + assert x.is_polynomial(x) is True + assert x.is_polynomial(y) is True + + assert (x**2).is_polynomial(x) is True + assert (x**2).is_polynomial(y) is True + + assert (x**(-2)).is_polynomial(x) is False + assert (x**(-2)).is_polynomial(y) is True + + assert (2**x).is_polynomial(x) is False + assert (2**x).is_polynomial(y) is True + + assert (x**k).is_polynomial(x) is False + assert (x**k).is_polynomial(k) is False + assert (x**x).is_polynomial(x) is False + assert (k**k).is_polynomial(k) is False + assert (k**x).is_polynomial(k) is False + + assert (x**(-k)).is_polynomial(x) is False + assert ((2*x)**k).is_polynomial(x) is False + + assert (x**2 + 3*x - 8).is_polynomial(x) is True + assert (x**2 + 3*x - 8).is_polynomial(y) is True + + assert (x**2 + 3*x - 8).is_polynomial() is True + + assert sqrt(x).is_polynomial(x) is False + assert (sqrt(x)**3).is_polynomial(x) is False + + assert (x**2 + 3*x*sqrt(y) - 8).is_polynomial(x) is True + assert (x**2 + 3*x*sqrt(y) - 8).is_polynomial(y) is False + + assert ((x**2)*(y**2) + x*(y**2) + y*x + exp(2)).is_polynomial() is True + assert ((x**2)*(y**2) + x*(y**2) + y*x + exp(x)).is_polynomial() is False + + assert ( + (x**2)*(y**2) + x*(y**2) + y*x + exp(2)).is_polynomial(x, y) is True + assert ( + (x**2)*(y**2) + x*(y**2) + y*x + exp(x)).is_polynomial(x, y) is False + + assert (1/f(x) + 1).is_polynomial(f(x)) is False + + +def test_is_rational_function(): + assert Integer(1).is_rational_function() is True + assert Integer(1).is_rational_function(x) is True + + assert Rational(17, 54).is_rational_function() is True + assert Rational(17, 54).is_rational_function(x) is True + + assert (12/x).is_rational_function() is True + assert (12/x).is_rational_function(x) is True + + assert (x/y).is_rational_function() is True + assert (x/y).is_rational_function(x) is True + assert (x/y).is_rational_function(x, y) is True + + assert (x**2 + 1/x/y).is_rational_function() is True + assert (x**2 + 1/x/y).is_rational_function(x) is True + assert (x**2 + 1/x/y).is_rational_function(x, y) is True + + assert (sin(y)/x).is_rational_function() is False + assert (sin(y)/x).is_rational_function(y) is False + assert (sin(y)/x).is_rational_function(x) is True + assert (sin(y)/x).is_rational_function(x, y) is False + + for i in _illegal: + assert not i.is_rational_function() + for d in (1, x): + assert not (i/d).is_rational_function() + + +def test_is_meromorphic(): + f = a/x**2 + b + x + c*x**2 + assert f.is_meromorphic(x, 0) is True + assert f.is_meromorphic(x, 1) is True + assert f.is_meromorphic(x, zoo) is True + + g = 3 + 2*x**(log(3)/log(2) - 1) + assert g.is_meromorphic(x, 0) is False + assert g.is_meromorphic(x, 1) is True + assert g.is_meromorphic(x, zoo) is False + + n = Symbol('n', integer=True) + e = sin(1/x)**n*x + assert e.is_meromorphic(x, 0) is False + assert e.is_meromorphic(x, 1) is True + assert e.is_meromorphic(x, zoo) is False + + e = log(x)**pi + assert e.is_meromorphic(x, 0) is False + assert e.is_meromorphic(x, 1) is False + assert e.is_meromorphic(x, 2) is True + assert e.is_meromorphic(x, zoo) is False + + assert (log(x)**a).is_meromorphic(x, 0) is False + assert (log(x)**a).is_meromorphic(x, 1) is False + assert (a**log(x)).is_meromorphic(x, 0) is None + assert (3**log(x)).is_meromorphic(x, 0) is False + assert (3**log(x)).is_meromorphic(x, 1) is True + +def test_is_algebraic_expr(): + assert sqrt(3).is_algebraic_expr(x) is True + assert sqrt(3).is_algebraic_expr() is True + + eq = ((1 + x**2)/(1 - y**2))**(S.One/3) + assert eq.is_algebraic_expr(x) is True + assert eq.is_algebraic_expr(y) is True + + assert (sqrt(x) + y**(S(2)/3)).is_algebraic_expr(x) is True + assert (sqrt(x) + y**(S(2)/3)).is_algebraic_expr(y) is True + assert (sqrt(x) + y**(S(2)/3)).is_algebraic_expr() is True + + assert (cos(y)/sqrt(x)).is_algebraic_expr() is False + assert (cos(y)/sqrt(x)).is_algebraic_expr(x) is True + assert (cos(y)/sqrt(x)).is_algebraic_expr(y) is False + assert (cos(y)/sqrt(x)).is_algebraic_expr(x, y) is False + + +def test_SAGE1(): + #see https://github.com/sympy/sympy/issues/3346 + class MyInt: + def _sympy_(self): + return Integer(5) + m = MyInt() + e = Rational(2)*m + assert e == 10 + + raises(TypeError, lambda: Rational(2)*MyInt) + + +def test_SAGE2(): + class MyInt: + def __int__(self): + return 5 + assert sympify(MyInt()) == 5 + e = Rational(2)*MyInt() + assert e == 10 + + raises(TypeError, lambda: Rational(2)*MyInt) + + +def test_SAGE3(): + class MySymbol: + def __rmul__(self, other): + return ('mys', other, self) + + o = MySymbol() + e = x*o + + assert e == ('mys', x, o) + + +def test_len(): + e = x*y + assert len(e.args) == 2 + e = x + y + z + assert len(e.args) == 3 + + +def test_doit(): + a = Integral(x**2, x) + + assert isinstance(a.doit(), Integral) is False + + assert isinstance(a.doit(integrals=True), Integral) is False + assert isinstance(a.doit(integrals=False), Integral) is True + + assert (2*Integral(x, x)).doit() == x**2 + + +def test_attribute_error(): + raises(AttributeError, lambda: x.cos()) + raises(AttributeError, lambda: x.sin()) + raises(AttributeError, lambda: x.exp()) + + +def test_args(): + assert (x*y).args in ((x, y), (y, x)) + assert (x + y).args in ((x, y), (y, x)) + assert (x*y + 1).args in ((x*y, 1), (1, x*y)) + assert sin(x*y).args == (x*y,) + assert sin(x*y).args[0] == x*y + assert (x**y).args == (x, y) + assert (x**y).args[0] == x + assert (x**y).args[1] == y + + +def test_noncommutative_expand_issue_3757(): + A, B, C = symbols('A,B,C', commutative=False) + assert A*B - B*A != 0 + assert (A*(A + B)*B).expand() == A**2*B + A*B**2 + assert (A*(A + B + C)*B).expand() == A**2*B + A*B**2 + A*C*B + + +def test_as_numer_denom(): + a, b, c = symbols('a, b, c') + + assert nan.as_numer_denom() == (nan, 1) + assert oo.as_numer_denom() == (oo, 1) + assert (-oo).as_numer_denom() == (-oo, 1) + assert zoo.as_numer_denom() == (zoo, 1) + assert (-zoo).as_numer_denom() == (zoo, 1) + + assert x.as_numer_denom() == (x, 1) + assert (1/x).as_numer_denom() == (1, x) + assert (x/y).as_numer_denom() == (x, y) + assert (x/2).as_numer_denom() == (x, 2) + assert (x*y/z).as_numer_denom() == (x*y, z) + assert (x/(y*z)).as_numer_denom() == (x, y*z) + assert S.Half.as_numer_denom() == (1, 2) + assert (1/y**2).as_numer_denom() == (1, y**2) + assert (x/y**2).as_numer_denom() == (x, y**2) + assert ((x**2 + 1)/y).as_numer_denom() == (x**2 + 1, y) + assert (x*(y + 1)/y**7).as_numer_denom() == (x*(y + 1), y**7) + assert (x**-2).as_numer_denom() == (1, x**2) + assert (a/x + b/2/x + c/3/x).as_numer_denom() == \ + (6*a + 3*b + 2*c, 6*x) + assert (a/x + b/2/x + c/3/y).as_numer_denom() == \ + (2*c*x + y*(6*a + 3*b), 6*x*y) + assert (a/x + b/2/x + c/.5/x).as_numer_denom() == \ + (2*a + b + 4.0*c, 2*x) + # this should take no more than a few seconds + assert int(log(Add(*[Dummy()/i/x for i in range(1, 705)] + ).as_numer_denom()[1]/x).n(4)) == 705 + for i in [S.Infinity, S.NegativeInfinity, S.ComplexInfinity]: + assert (i + x/3).as_numer_denom() == \ + (x + i, 3) + assert (S.Infinity + x/3 + y/4).as_numer_denom() == \ + (4*x + 3*y + S.Infinity, 12) + assert (oo*x + zoo*y).as_numer_denom() == \ + (zoo*y + oo*x, 1) + + A, B, C = symbols('A,B,C', commutative=False) + + assert (A*B*C**-1).as_numer_denom() == (A*B*C**-1, 1) + assert (A*B*C**-1/x).as_numer_denom() == (A*B*C**-1, x) + assert (C**-1*A*B).as_numer_denom() == (C**-1*A*B, 1) + assert (C**-1*A*B/x).as_numer_denom() == (C**-1*A*B, x) + assert ((A*B*C)**-1).as_numer_denom() == ((A*B*C)**-1, 1) + assert ((A*B*C)**-1/x).as_numer_denom() == ((A*B*C)**-1, x) + + # the following morphs from Add to Mul during processing + assert Add(0, (x + y)/z/-2, evaluate=False).as_numer_denom( + ) == (-x - y, 2*z) + + +def test_trunc(): + import math + x, y = symbols('x y') + assert math.trunc(2) == 2 + assert math.trunc(4.57) == 4 + assert math.trunc(-5.79) == -5 + assert math.trunc(pi) == 3 + assert math.trunc(log(7)) == 1 + assert math.trunc(exp(5)) == 148 + assert math.trunc(cos(pi)) == -1 + assert math.trunc(sin(5)) == 0 + + raises(TypeError, lambda: math.trunc(x)) + raises(TypeError, lambda: math.trunc(x + y**2)) + raises(TypeError, lambda: math.trunc(oo)) + + +def test_as_independent(): + assert S.Zero.as_independent(x, as_Add=True) == (0, 0) + assert S.Zero.as_independent(x, as_Add=False) == (0, 0) + assert (2*x*sin(x) + y + x).as_independent(x) == (y, x + 2*x*sin(x)) + assert (2*x*sin(x) + y + x).as_independent(y) == (x + 2*x*sin(x), y) + + assert (2*x*sin(x) + y + x).as_independent(x, y) == (0, y + x + 2*x*sin(x)) + + assert (x*sin(x)*cos(y)).as_independent(x) == (cos(y), x*sin(x)) + assert (x*sin(x)*cos(y)).as_independent(y) == (x*sin(x), cos(y)) + + assert (x*sin(x)*cos(y)).as_independent(x, y) == (1, x*sin(x)*cos(y)) + + assert (sin(x)).as_independent(x) == (1, sin(x)) + assert (sin(x)).as_independent(y) == (sin(x), 1) + + assert (2*sin(x)).as_independent(x) == (2, sin(x)) + assert (2*sin(x)).as_independent(y) == (2*sin(x), 1) + + # issue 4903 = 1766b + n1, n2, n3 = symbols('n1 n2 n3', commutative=False) + assert (n1 + n1*n2).as_independent(n2) == (n1, n1*n2) + assert (n2*n1 + n1*n2).as_independent(n2) == (0, n1*n2 + n2*n1) + assert (n1*n2*n1).as_independent(n2) == (n1, n2*n1) + assert (n1*n2*n1).as_independent(n1) == (1, n1*n2*n1) + + assert (3*x).as_independent(x, as_Add=True) == (0, 3*x) + assert (3*x).as_independent(x, as_Add=False) == (3, x) + assert (3 + x).as_independent(x, as_Add=True) == (3, x) + assert (3 + x).as_independent(x, as_Add=False) == (1, 3 + x) + + # issue 5479 + assert (3*x).as_independent(Symbol) == (3, x) + + # issue 5648 + assert (n1*x*y).as_independent(x) == (n1*y, x) + assert ((x + n1)*(x - y)).as_independent(x) == (1, (x + n1)*(x - y)) + assert ((x + n1)*(x - y)).as_independent(y) == (x + n1, x - y) + assert (DiracDelta(x - n1)*DiracDelta(x - y)).as_independent(x) \ + == (1, DiracDelta(x - n1)*DiracDelta(x - y)) + assert (x*y*n1*n2*n3).as_independent(n2) == (x*y*n1, n2*n3) + assert (x*y*n1*n2*n3).as_independent(n1) == (x*y, n1*n2*n3) + assert (x*y*n1*n2*n3).as_independent(n3) == (x*y*n1*n2, n3) + assert (DiracDelta(x - n1)*DiracDelta(y - n1)*DiracDelta(x - n2)).as_independent(y) == \ + (DiracDelta(x - n1)*DiracDelta(x - n2), DiracDelta(y - n1)) + + # issue 5784 + assert (x + Integral(x, (x, 1, 2))).as_independent(x, strict=True) == \ + (Integral(x, (x, 1, 2)), x) + + eq = Add(x, -x, 2, -3, evaluate=False) + assert eq.as_independent(x) == (-1, Add(x, -x, evaluate=False)) + eq = Mul(x, 1/x, 2, -3, evaluate=False) + assert eq.as_independent(x) == (-6, Mul(x, 1/x, evaluate=False)) + + assert (x*y).as_independent(z, as_Add=True) == (x*y, 0) + +@XFAIL +def test_call_2(): + # TODO UndefinedFunction does not subclass Expr + assert (2*f)(x) == 2*f(x) + + +def test_replace(): + e = log(sin(x)) + tan(sin(x**2)) + + assert e.replace(sin, cos) == log(cos(x)) + tan(cos(x**2)) + assert e.replace( + sin, lambda a: sin(2*a)) == log(sin(2*x)) + tan(sin(2*x**2)) + + a = Wild('a') + b = Wild('b') + + assert e.replace(sin(a), cos(a)) == log(cos(x)) + tan(cos(x**2)) + assert e.replace( + sin(a), lambda a: sin(2*a)) == log(sin(2*x)) + tan(sin(2*x**2)) + # test exact + assert (2*x).replace(a*x + b, b - a, exact=True) == 2*x + assert (2*x).replace(a*x + b, b - a) == 2*x + assert (2*x).replace(a*x + b, b - a, exact=False) == 2/x + assert (2*x).replace(a*x + b, lambda a, b: b - a, exact=True) == 2*x + assert (2*x).replace(a*x + b, lambda a, b: b - a) == 2*x + assert (2*x).replace(a*x + b, lambda a, b: b - a, exact=False) == 2/x + + g = 2*sin(x**3) + + assert g.replace( + lambda expr: expr.is_Number, lambda expr: expr**2) == 4*sin(x**9) + + assert cos(x).replace(cos, sin, map=True) == (sin(x), {cos(x): sin(x)}) + assert sin(x).replace(cos, sin) == sin(x) + + cond, func = lambda x: x.is_Mul, lambda x: 2*x + assert (x*y).replace(cond, func, map=True) == (2*x*y, {x*y: 2*x*y}) + assert (x*(1 + x*y)).replace(cond, func, map=True) == \ + (2*x*(2*x*y + 1), {x*(2*x*y + 1): 2*x*(2*x*y + 1), x*y: 2*x*y}) + assert (y*sin(x)).replace(sin, lambda expr: sin(expr)/y, map=True) == \ + (sin(x), {sin(x): sin(x)/y}) + # if not simultaneous then y*sin(x) -> y*sin(x)/y = sin(x) -> sin(x)/y + assert (y*sin(x)).replace(sin, lambda expr: sin(expr)/y, + simultaneous=False) == sin(x)/y + assert (x**2 + O(x**3)).replace(Pow, lambda b, e: b**e/e + ) == x**2/2 + O(x**3) + assert (x**2 + O(x**3)).replace(Pow, lambda b, e: b**e/e, + simultaneous=False) == x**2/2 + O(x**3) + assert (x*(x*y + 3)).replace(lambda x: x.is_Mul, lambda x: 2 + x) == \ + x*(x*y + 5) + 2 + e = (x*y + 1)*(2*x*y + 1) + 1 + assert e.replace(cond, func, map=True) == ( + 2*((2*x*y + 1)*(4*x*y + 1)) + 1, + {2*x*y: 4*x*y, x*y: 2*x*y, (2*x*y + 1)*(4*x*y + 1): + 2*((2*x*y + 1)*(4*x*y + 1))}) + assert x.replace(x, y) == y + assert (x + 1).replace(1, 2) == x + 2 + + # https://groups.google.com/forum/#!topic/sympy/8wCgeC95tz0 + n1, n2, n3 = symbols('n1:4', commutative=False) + assert (n1*f(n2)).replace(f, lambda x: x) == n1*n2 + assert (n3*f(n2)).replace(f, lambda x: x) == n3*n2 + + # issue 16725 + assert S.Zero.replace(Wild('x'), 1) == 1 + # let the user override the default decision of False + assert S.Zero.replace(Wild('x'), 1, exact=True) == 0 + + +def test_find(): + expr = (x + y + 2 + sin(3*x)) + + assert expr.find(lambda u: u.is_Integer) == {S(2), S(3)} + assert expr.find(lambda u: u.is_Symbol) == {x, y} + + assert expr.find(lambda u: u.is_Integer, group=True) == {S(2): 1, S(3): 1} + assert expr.find(lambda u: u.is_Symbol, group=True) == {x: 2, y: 1} + + assert expr.find(Integer) == {S(2), S(3)} + assert expr.find(Symbol) == {x, y} + + assert expr.find(Integer, group=True) == {S(2): 1, S(3): 1} + assert expr.find(Symbol, group=True) == {x: 2, y: 1} + + a = Wild('a') + + expr = sin(sin(x)) + sin(x) + cos(x) + x + + assert expr.find(lambda u: type(u) is sin) == {sin(x), sin(sin(x))} + assert expr.find( + lambda u: type(u) is sin, group=True) == {sin(x): 2, sin(sin(x)): 1} + + assert expr.find(sin(a)) == {sin(x), sin(sin(x))} + assert expr.find(sin(a), group=True) == {sin(x): 2, sin(sin(x)): 1} + + assert expr.find(sin) == {sin(x), sin(sin(x))} + assert expr.find(sin, group=True) == {sin(x): 2, sin(sin(x)): 1} + + +def test_count(): + expr = (x + y + 2 + sin(3*x)) + + assert expr.count(lambda u: u.is_Integer) == 2 + assert expr.count(lambda u: u.is_Symbol) == 3 + + assert expr.count(Integer) == 2 + assert expr.count(Symbol) == 3 + assert expr.count(2) == 1 + + a = Wild('a') + + assert expr.count(sin) == 1 + assert expr.count(sin(a)) == 1 + assert expr.count(lambda u: type(u) is sin) == 1 + + assert f(x).count(f(x)) == 1 + assert f(x).diff(x).count(f(x)) == 1 + assert f(x).diff(x).count(x) == 2 + + +def test_has_basics(): + p = Wild('p') + + assert sin(x).has(x) + assert sin(x).has(sin) + assert not sin(x).has(y) + assert not sin(x).has(cos) + assert f(x).has(x) + assert f(x).has(f) + assert not f(x).has(y) + assert not f(x).has(g) + + assert f(x).diff(x).has(x) + assert f(x).diff(x).has(f) + assert f(x).diff(x).has(Derivative) + assert not f(x).diff(x).has(y) + assert not f(x).diff(x).has(g) + assert not f(x).diff(x).has(sin) + + assert (x**2).has(Symbol) + assert not (x**2).has(Wild) + assert (2*p).has(Wild) + + assert not x.has() + + # see issue at https://github.com/sympy/sympy/issues/5190 + assert not S(1).has(Wild) + assert not x.has(Wild) + + +def test_has_multiple(): + f = x**2*y + sin(2**t + log(z)) + + assert f.has(x) + assert f.has(y) + assert f.has(z) + assert f.has(t) + + assert not f.has(u) + + assert f.has(x, y, z, t) + assert f.has(x, y, z, t, u) + + i = Integer(4400) + + assert not i.has(x) + + assert (i*x**i).has(x) + assert not (i*y**i).has(x) + assert (i*y**i).has(x, y) + assert not (i*y**i).has(x, z) + + +def test_has_piecewise(): + f = (x*y + 3/y)**(3 + 2) + p = Piecewise((g(x), x < -1), (1, x <= 1), (f, True)) + + assert p.has(x) + assert p.has(y) + assert not p.has(z) + assert p.has(1) + assert p.has(3) + assert not p.has(4) + assert p.has(f) + assert p.has(g) + assert not p.has(h) + + +def test_has_iterative(): + A, B, C = symbols('A,B,C', commutative=False) + f = x*gamma(x)*sin(x)*exp(x*y)*A*B*C*cos(x*A*B) + + assert f.has(x) + assert f.has(x*y) + assert f.has(x*sin(x)) + assert not f.has(x*sin(y)) + assert f.has(x*A) + assert f.has(x*A*B) + assert not f.has(x*A*C) + assert f.has(x*A*B*C) + assert not f.has(x*A*C*B) + assert f.has(x*sin(x)*A*B*C) + assert not f.has(x*sin(x)*A*C*B) + assert not f.has(x*sin(y)*A*B*C) + assert f.has(x*gamma(x)) + assert not f.has(x + sin(x)) + + assert (x & y & z).has(x & z) + + +def test_has_integrals(): + f = Integral(x**2 + sin(x*y*z), (x, 0, x + y + z)) + + assert f.has(x + y) + assert f.has(x + z) + assert f.has(y + z) + + assert f.has(x*y) + assert f.has(x*z) + assert f.has(y*z) + + assert not f.has(2*x + y) + assert not f.has(2*x*y) + + +def test_has_tuple(): + assert Tuple(x, y).has(x) + assert not Tuple(x, y).has(z) + assert Tuple(f(x), g(x)).has(x) + assert not Tuple(f(x), g(x)).has(y) + assert Tuple(f(x), g(x)).has(f) + assert Tuple(f(x), g(x)).has(f(x)) + # XXX to be deprecated + #assert not Tuple(f, g).has(x) + #assert Tuple(f, g).has(f) + #assert not Tuple(f, g).has(h) + assert Tuple(True).has(True) + assert Tuple(True).has(S.true) + assert not Tuple(True).has(1) + + +def test_has_units(): + from sympy.physics.units import m, s + + assert (x*m/s).has(x) + assert (x*m/s).has(y, z) is False + + +def test_has_polys(): + poly = Poly(x**2 + x*y*sin(z), x, y, t) + + assert poly.has(x) + assert poly.has(x, y, z) + assert poly.has(x, y, z, t) + + +def test_has_physics(): + assert FockState((x, y)).has(x) + + +def test_as_poly_as_expr(): + f = x**2 + 2*x*y + + assert f.as_poly().as_expr() == f + assert f.as_poly(x, y).as_expr() == f + + assert (f + sin(x)).as_poly(x, y) is None + + p = Poly(f, x, y) + + assert p.as_poly() == p + + # https://github.com/sympy/sympy/issues/20610 + assert S(2).as_poly() is None + assert sqrt(2).as_poly(extension=True) is None + + raises(AttributeError, lambda: Tuple(x, x).as_poly(x)) + raises(AttributeError, lambda: Tuple(x ** 2, x, y).as_poly(x)) + + +def test_nonzero(): + assert bool(S.Zero) is False + assert bool(S.One) is True + assert bool(x) is True + assert bool(x + y) is True + assert bool(x - x) is False + assert bool(x*y) is True + assert bool(x*1) is True + assert bool(x*0) is False + + +def test_is_number(): + assert Float(3.14).is_number is True + assert Integer(737).is_number is True + assert Rational(3, 2).is_number is True + assert Rational(8).is_number is True + assert x.is_number is False + assert (2*x).is_number is False + assert (x + y).is_number is False + assert log(2).is_number is True + assert log(x).is_number is False + assert (2 + log(2)).is_number is True + assert (8 + log(2)).is_number is True + assert (2 + log(x)).is_number is False + assert (8 + log(2) + x).is_number is False + assert (1 + x**2/x - x).is_number is True + assert Tuple(Integer(1)).is_number is False + assert Add(2, x).is_number is False + assert Mul(3, 4).is_number is True + assert Pow(log(2), 2).is_number is True + assert oo.is_number is True + g = WildFunction('g') + assert g.is_number is False + assert (2*g).is_number is False + assert (x**2).subs(x, 3).is_number is True + + # test extensibility of .is_number + # on subinstances of Basic + class A(Basic): + pass + a = A() + assert a.is_number is False + + +def test_as_coeff_add(): + assert S(2).as_coeff_add() == (2, ()) + assert S(3.0).as_coeff_add() == (0, (S(3.0),)) + assert S(-3.0).as_coeff_add() == (0, (S(-3.0),)) + assert x.as_coeff_add() == (0, (x,)) + assert (x - 1).as_coeff_add() == (-1, (x,)) + assert (x + 1).as_coeff_add() == (1, (x,)) + assert (x + 2).as_coeff_add() == (2, (x,)) + assert (x + y).as_coeff_add(y) == (x, (y,)) + assert (3*x).as_coeff_add(y) == (3*x, ()) + # don't do expansion + e = (x + y)**2 + assert e.as_coeff_add(y) == (0, (e,)) + + +def test_as_coeff_mul(): + assert S(2).as_coeff_mul() == (2, ()) + assert S(3.0).as_coeff_mul() == (1, (S(3.0),)) + assert S(-3.0).as_coeff_mul() == (-1, (S(3.0),)) + assert S(-3.0).as_coeff_mul(rational=False) == (-S(3.0), ()) + assert x.as_coeff_mul() == (1, (x,)) + assert (-x).as_coeff_mul() == (-1, (x,)) + assert (2*x).as_coeff_mul() == (2, (x,)) + assert (x*y).as_coeff_mul(y) == (x, (y,)) + assert (3 + x).as_coeff_mul() == (1, (3 + x,)) + assert (3 + x).as_coeff_mul(y) == (3 + x, ()) + # don't do expansion + e = exp(x + y) + assert e.as_coeff_mul(y) == (1, (e,)) + e = 2**(x + y) + assert e.as_coeff_mul(y) == (1, (e,)) + assert (1.1*x).as_coeff_mul(rational=False) == (1.1, (x,)) + assert (1.1*x).as_coeff_mul() == (1, (1.1, x)) + assert (-oo*x).as_coeff_mul(rational=True) == (-1, (oo, x)) + + +def test_as_coeff_exponent(): + assert (3*x**4).as_coeff_exponent(x) == (3, 4) + assert (2*x**3).as_coeff_exponent(x) == (2, 3) + assert (4*x**2).as_coeff_exponent(x) == (4, 2) + assert (6*x**1).as_coeff_exponent(x) == (6, 1) + assert (3*x**0).as_coeff_exponent(x) == (3, 0) + assert (2*x**0).as_coeff_exponent(x) == (2, 0) + assert (1*x**0).as_coeff_exponent(x) == (1, 0) + assert (0*x**0).as_coeff_exponent(x) == (0, 0) + assert (-1*x**0).as_coeff_exponent(x) == (-1, 0) + assert (-2*x**0).as_coeff_exponent(x) == (-2, 0) + assert (2*x**3 + pi*x**3).as_coeff_exponent(x) == (2 + pi, 3) + assert (x*log(2)/(2*x + pi*x)).as_coeff_exponent(x) == \ + (log(2)/(2 + pi), 0) + # issue 4784 + D = Derivative + fx = D(f(x), x) + assert fx.as_coeff_exponent(f(x)) == (fx, 0) + + +def test_extractions(): + for base in (2, S.Exp1): + assert Pow(base**x, 3, evaluate=False + ).extract_multiplicatively(base**x) == base**(2*x) + assert (base**(5*x)).extract_multiplicatively( + base**(3*x)) == base**(2*x) + assert ((x*y)**3).extract_multiplicatively(x**2 * y) == x*y**2 + assert ((x*y)**3).extract_multiplicatively(x**4 * y) is None + assert (2*x).extract_multiplicatively(2) == x + assert (2*x).extract_multiplicatively(3) is None + assert (2*x).extract_multiplicatively(-1) is None + assert (S.Half*x).extract_multiplicatively(3) == x/6 + assert (sqrt(x)).extract_multiplicatively(x) is None + assert (sqrt(x)).extract_multiplicatively(1/x) is None + assert x.extract_multiplicatively(-x) is None + assert (-2 - 4*I).extract_multiplicatively(-2) == 1 + 2*I + assert (-2 - 4*I).extract_multiplicatively(3) is None + assert (-2*x - 4*y - 8).extract_multiplicatively(-2) == x + 2*y + 4 + assert (-2*x*y - 4*x**2*y).extract_multiplicatively(-2*y) == 2*x**2 + x + assert (2*x*y + 4*x**2*y).extract_multiplicatively(2*y) == 2*x**2 + x + assert (-4*y**2*x).extract_multiplicatively(-3*y) is None + assert (2*x).extract_multiplicatively(1) == 2*x + assert (-oo).extract_multiplicatively(5) is -oo + assert (oo).extract_multiplicatively(5) is oo + + assert ((x*y)**3).extract_additively(1) is None + assert (x + 1).extract_additively(x) == 1 + assert (x + 1).extract_additively(2*x) is None + assert (x + 1).extract_additively(-x) is None + assert (-x + 1).extract_additively(2*x) is None + assert (2*x + 3).extract_additively(x) == x + 3 + assert (2*x + 3).extract_additively(2) == 2*x + 1 + assert (2*x + 3).extract_additively(3) == 2*x + assert (2*x + 3).extract_additively(-2) is None + assert (2*x + 3).extract_additively(3*x) is None + assert (2*x + 3).extract_additively(2*x) == 3 + assert x.extract_additively(0) == x + assert S(2).extract_additively(x) is None + assert S(2.).extract_additively(2.) is S.Zero + assert S(2.).extract_additively(2) is S.Zero + assert S(2*x + 3).extract_additively(x + 1) == x + 2 + assert S(2*x + 3).extract_additively(y + 1) is None + assert S(2*x - 3).extract_additively(x + 1) is None + assert S(2*x - 3).extract_additively(y + z) is None + assert ((a + 1)*x*4 + y).extract_additively(x).expand() == \ + 4*a*x + 3*x + y + assert ((a + 1)*x*4 + 3*y).extract_additively(x + 2*y).expand() == \ + 4*a*x + 3*x + y + assert (y*(x + 1)).extract_additively(x + 1) is None + assert ((y + 1)*(x + 1) + 3).extract_additively(x + 1) == \ + y*(x + 1) + 3 + assert ((x + y)*(x + 1) + x + y + 3).extract_additively(x + y) == \ + x*(x + y) + 3 + assert (x + y + 2*((x + y)*(x + 1)) + 3).extract_additively((x + y)*(x + 1)) == \ + x + y + (x + 1)*(x + y) + 3 + assert ((y + 1)*(x + 2*y + 1) + 3).extract_additively(y + 1) == \ + (x + 2*y)*(y + 1) + 3 + assert (-x - x*I).extract_additively(-x) == -I*x + # extraction does not leave artificats, now + assert (4*x*(y + 1) + y).extract_additively(x) == x*(4*y + 3) + y + + n = Symbol("n", integer=True) + assert (Integer(-3)).could_extract_minus_sign() is True + assert (-n*x + x).could_extract_minus_sign() != \ + (n*x - x).could_extract_minus_sign() + assert (x - y).could_extract_minus_sign() != \ + (-x + y).could_extract_minus_sign() + assert (1 - x - y).could_extract_minus_sign() is True + assert (1 - x + y).could_extract_minus_sign() is False + assert ((-x - x*y)/y).could_extract_minus_sign() is False + assert ((x + x*y)/(-y)).could_extract_minus_sign() is True + assert ((x + x*y)/y).could_extract_minus_sign() is False + assert ((-x - y)/(x + y)).could_extract_minus_sign() is False + + class sign_invariant(Function, Expr): + nargs = 1 + def __neg__(self): + return self + foo = sign_invariant(x) + assert foo == -foo + assert foo.could_extract_minus_sign() is False + assert (x - y).could_extract_minus_sign() is False + assert (-x + y).could_extract_minus_sign() is True + assert (x - 1).could_extract_minus_sign() is False + assert (1 - x).could_extract_minus_sign() is True + assert (sqrt(2) - 1).could_extract_minus_sign() is True + assert (1 - sqrt(2)).could_extract_minus_sign() is False + # check that result is canonical + eq = (3*x + 15*y).extract_multiplicatively(3) + assert eq.args == eq.func(*eq.args).args + + +def test_nan_extractions(): + for r in (1, 0, I, nan): + assert nan.extract_additively(r) is None + assert nan.extract_multiplicatively(r) is None + + +def test_coeff(): + assert (x + 1).coeff(x + 1) == 1 + assert (3*x).coeff(0) == 0 + assert (z*(1 + x)*x**2).coeff(1 + x) == z*x**2 + assert (1 + 2*x*x**(1 + x)).coeff(x*x**(1 + x)) == 2 + assert (1 + 2*x**(y + z)).coeff(x**(y + z)) == 2 + assert (3 + 2*x + 4*x**2).coeff(1) == 0 + assert (3 + 2*x + 4*x**2).coeff(-1) == 0 + assert (3 + 2*x + 4*x**2).coeff(x) == 2 + assert (3 + 2*x + 4*x**2).coeff(x**2) == 4 + assert (3 + 2*x + 4*x**2).coeff(x**3) == 0 + + assert (-x/8 + x*y).coeff(x) == Rational(-1, 8) + y + assert (-x/8 + x*y).coeff(-x) == S.One/8 + assert (4*x).coeff(2*x) == 0 + assert (2*x).coeff(2*x) == 1 + assert (-oo*x).coeff(x*oo) == -1 + assert (10*x).coeff(x, 0) == 0 + assert (10*x).coeff(10*x, 0) == 0 + + n1, n2 = symbols('n1 n2', commutative=False) + assert (n1*n2).coeff(n1) == 1 + assert (n1*n2).coeff(n2) == n1 + assert (n1*n2 + x*n1).coeff(n1) == 1 # 1*n1*(n2+x) + assert (n2*n1 + x*n1).coeff(n1) == n2 + x + assert (n2*n1 + x*n1**2).coeff(n1) == n2 + assert (n1**x).coeff(n1) == 0 + assert (n1*n2 + n2*n1).coeff(n1) == 0 + assert (2*(n1 + n2)*n2).coeff(n1 + n2, right=1) == n2 + assert (2*(n1 + n2)*n2).coeff(n1 + n2, right=0) == 2 + + assert (2*f(x) + 3*f(x).diff(x)).coeff(f(x)) == 2 + + expr = z*(x + y)**2 + expr2 = z*(x + y)**2 + z*(2*x + 2*y)**2 + assert expr.coeff(z) == (x + y)**2 + assert expr.coeff(x + y) == 0 + assert expr2.coeff(z) == (x + y)**2 + (2*x + 2*y)**2 + + assert (x + y + 3*z).coeff(1) == x + y + assert (-x + 2*y).coeff(-1) == x + assert (x - 2*y).coeff(-1) == 2*y + assert (3 + 2*x + 4*x**2).coeff(1) == 0 + assert (-x - 2*y).coeff(2) == -y + assert (x + sqrt(2)*x).coeff(sqrt(2)) == x + assert (3 + 2*x + 4*x**2).coeff(x) == 2 + assert (3 + 2*x + 4*x**2).coeff(x**2) == 4 + assert (3 + 2*x + 4*x**2).coeff(x**3) == 0 + assert (z*(x + y)**2).coeff((x + y)**2) == z + assert (z*(x + y)**2).coeff(x + y) == 0 + assert (2 + 2*x + (x + 1)*y).coeff(x + 1) == y + + assert (x + 2*y + 3).coeff(1) == x + assert (x + 2*y + 3).coeff(x, 0) == 2*y + 3 + assert (x**2 + 2*y + 3*x).coeff(x**2, 0) == 2*y + 3*x + assert x.coeff(0, 0) == 0 + assert x.coeff(x, 0) == 0 + + n, m, o, l = symbols('n m o l', commutative=False) + assert n.coeff(n) == 1 + assert y.coeff(n) == 0 + assert (3*n).coeff(n) == 3 + assert (2 + n).coeff(x*m) == 0 + assert (2*x*n*m).coeff(x) == 2*n*m + assert (2 + n).coeff(x*m*n + y) == 0 + assert (2*x*n*m).coeff(3*n) == 0 + assert (n*m + m*n*m).coeff(n) == 1 + m + assert (n*m + m*n*m).coeff(n, right=True) == m # = (1 + m)*n*m + assert (n*m + m*n).coeff(n) == 0 + assert (n*m + o*m*n).coeff(m*n) == o + assert (n*m + o*m*n).coeff(m*n, right=True) == 1 + assert (n*m + n*m*n).coeff(n*m, right=True) == 1 + n # = n*m*(n + 1) + + assert (x*y).coeff(z, 0) == x*y + + assert (x*n + y*n + z*m).coeff(n) == x + y + assert (n*m + n*o + o*l).coeff(n, right=True) == m + o + assert (x*n*m*n + y*n*m*o + z*l).coeff(m, right=True) == x*n + y*o + assert (x*n*m*n + x*n*m*o + z*l).coeff(m, right=True) == n + o + assert (x*n*m*n + x*n*m*o + z*l).coeff(m) == x*n + + +def test_coeff2(): + r, kappa = symbols('r, kappa') + psi = Function("psi") + g = 1/r**2 * (2*r*psi(r).diff(r, 1) + r**2 * psi(r).diff(r, 2)) + g = g.expand() + assert g.coeff(psi(r).diff(r)) == 2/r + + +def test_coeff2_0(): + r, kappa = symbols('r, kappa') + psi = Function("psi") + g = 1/r**2 * (2*r*psi(r).diff(r, 1) + r**2 * psi(r).diff(r, 2)) + g = g.expand() + + assert g.coeff(psi(r).diff(r, 2)) == 1 + + +def test_coeff_expand(): + expr = z*(x + y)**2 + expr2 = z*(x + y)**2 + z*(2*x + 2*y)**2 + assert expr.coeff(z) == (x + y)**2 + assert expr2.coeff(z) == (x + y)**2 + (2*x + 2*y)**2 + + +def test_integrate(): + assert x.integrate(x) == x**2/2 + assert x.integrate((x, 0, 1)) == S.Half + + +def test_as_base_exp(): + assert x.as_base_exp() == (x, S.One) + assert (x*y*z).as_base_exp() == (x*y*z, S.One) + assert (x + y + z).as_base_exp() == (x + y + z, S.One) + assert ((x + y)**z).as_base_exp() == (x + y, z) + + +def test_issue_4963(): + assert hasattr(Mul(x, y), "is_commutative") + assert hasattr(Mul(x, y, evaluate=False), "is_commutative") + assert hasattr(Pow(x, y), "is_commutative") + assert hasattr(Pow(x, y, evaluate=False), "is_commutative") + expr = Mul(Pow(2, 2, evaluate=False), 3, evaluate=False) + 1 + assert hasattr(expr, "is_commutative") + + +def test_action_verbs(): + assert nsimplify(1/(exp(3*pi*x/5) + 1)) == \ + (1/(exp(3*pi*x/5) + 1)).nsimplify() + assert ratsimp(1/x + 1/y) == (1/x + 1/y).ratsimp() + assert trigsimp(log(x), deep=True) == (log(x)).trigsimp(deep=True) + assert radsimp(1/(2 + sqrt(2))) == (1/(2 + sqrt(2))).radsimp() + assert radsimp(1/(a + b*sqrt(c)), symbolic=False) == \ + (1/(a + b*sqrt(c))).radsimp(symbolic=False) + assert powsimp(x**y*x**z*y**z, combine='all') == \ + (x**y*x**z*y**z).powsimp(combine='all') + assert (x**t*y**t).powsimp(force=True) == (x*y)**t + assert simplify(x**y*x**z*y**z) == (x**y*x**z*y**z).simplify() + assert together(1/x + 1/y) == (1/x + 1/y).together() + assert collect(a*x**2 + b*x**2 + a*x - b*x + c, x) == \ + (a*x**2 + b*x**2 + a*x - b*x + c).collect(x) + assert apart(y/(y + 2)/(y + 1), y) == (y/(y + 2)/(y + 1)).apart(y) + assert combsimp(y/(x + 2)/(x + 1)) == (y/(x + 2)/(x + 1)).combsimp() + assert gammasimp(gamma(x)/gamma(x-5)) == (gamma(x)/gamma(x-5)).gammasimp() + assert factor(x**2 + 5*x + 6) == (x**2 + 5*x + 6).factor() + assert refine(sqrt(x**2)) == sqrt(x**2).refine() + assert cancel((x**2 + 5*x + 6)/(x + 2)) == ((x**2 + 5*x + 6)/(x + 2)).cancel() + + +def test_as_powers_dict(): + assert x.as_powers_dict() == {x: 1} + assert (x**y*z).as_powers_dict() == {x: y, z: 1} + assert Mul(2, 2, evaluate=False).as_powers_dict() == {S(2): S(2)} + assert (x*y).as_powers_dict()[z] == 0 + assert (x + y).as_powers_dict()[z] == 0 + + +def test_as_coefficients_dict(): + check = [S.One, x, y, x*y, 1] + assert [Add(3*x, 2*x, y, 3).as_coefficients_dict()[i] for i in check] == \ + [3, 5, 1, 0, 3] + assert [Add(3*x, 2*x, y, 3, evaluate=False).as_coefficients_dict()[i] + for i in check] == [3, 5, 1, 0, 3] + assert [(3*x*y).as_coefficients_dict()[i] for i in check] == \ + [0, 0, 0, 3, 0] + assert [(3.0*x*y).as_coefficients_dict()[i] for i in check] == \ + [0, 0, 0, 3.0, 0] + assert (3.0*x*y).as_coefficients_dict()[3.0*x*y] == 0 + eq = x*(x + 1)*a + x*b + c/x + assert eq.as_coefficients_dict(x) == {x: b, 1/x: c, + x*(x + 1): a} + assert eq.expand().as_coefficients_dict(x) == {x**2: a, x: a + b, 1/x: c} + assert x.as_coefficients_dict() == {x: S.One} + + +def test_args_cnc(): + A = symbols('A', commutative=False) + assert (x + A).args_cnc() == \ + [[], [x + A]] + assert (x + a).args_cnc() == \ + [[a + x], []] + assert (x*a).args_cnc() == \ + [[a, x], []] + assert (x*y*A*(A + 1)).args_cnc(cset=True) == \ + [{x, y}, [A, 1 + A]] + assert Mul(x, x, evaluate=False).args_cnc(cset=True, warn=False) == \ + [{x}, []] + assert Mul(x, x**2, evaluate=False).args_cnc(cset=True, warn=False) == \ + [{x, x**2}, []] + raises(ValueError, lambda: Mul(x, x, evaluate=False).args_cnc(cset=True)) + assert Mul(x, y, x, evaluate=False).args_cnc() == \ + [[x, y, x], []] + # always split -1 from leading number + assert (-1.*x).args_cnc() == [[-1, 1.0, x], []] + + +def test_new_rawargs(): + n = Symbol('n', commutative=False) + a = x + n + assert a.is_commutative is False + assert a._new_rawargs(x).is_commutative + assert a._new_rawargs(x, y).is_commutative + assert a._new_rawargs(x, n).is_commutative is False + assert a._new_rawargs(x, y, n).is_commutative is False + m = x*n + assert m.is_commutative is False + assert m._new_rawargs(x).is_commutative + assert m._new_rawargs(n).is_commutative is False + assert m._new_rawargs(x, y).is_commutative + assert m._new_rawargs(x, n).is_commutative is False + assert m._new_rawargs(x, y, n).is_commutative is False + + assert m._new_rawargs(x, n, reeval=False).is_commutative is False + assert m._new_rawargs(S.One) is S.One + + +def test_issue_5226(): + assert Add(evaluate=False) == 0 + assert Mul(evaluate=False) == 1 + assert Mul(x + y, evaluate=False).is_Add + + +def test_free_symbols(): + # free_symbols should return the free symbols of an object + assert S.One.free_symbols == set() + assert x.free_symbols == {x} + assert Integral(x, (x, 1, y)).free_symbols == {y} + assert (-Integral(x, (x, 1, y))).free_symbols == {y} + assert meter.free_symbols == set() + assert (meter**x).free_symbols == {x} + + +def test_has_free(): + assert x.has_free(x) + assert not x.has_free(y) + assert (x + y).has_free(x) + assert (x + y).has_free(*(x, z)) + assert f(x).has_free(x) + assert f(x).has_free(f(x)) + assert Integral(f(x), (f(x), 1, y)).has_free(y) + assert not Integral(f(x), (f(x), 1, y)).has_free(x) + assert not Integral(f(x), (f(x), 1, y)).has_free(f(x)) + # simple extraction + assert (x + 1 + y).has_free(x + 1) + assert not (x + 2 + y).has_free(x + 1) + assert (2 + 3*x*y).has_free(3*x) + raises(TypeError, lambda: x.has_free({x, y})) + s = FiniteSet(1, 2) + assert Piecewise((s, x > 3), (4, True)).has_free(s) + assert not Piecewise((1, x > 3), (4, True)).has_free(s) + # can't make set of these, but fallback will handle + raises(TypeError, lambda: x.has_free(y, [])) + + +def test_has_xfree(): + assert (x + 1).has_xfree({x}) + assert ((x + 1)**2).has_xfree({x + 1}) + assert not (x + y + 1).has_xfree({x + 1}) + raises(TypeError, lambda: x.has_xfree(x)) + raises(TypeError, lambda: x.has_xfree([x])) + + +def test_issue_5300(): + x = Symbol('x', commutative=False) + assert x*sqrt(2)/sqrt(6) == x*sqrt(3)/3 + + +def test_floordiv(): + from sympy.functions.elementary.integers import floor + assert x // y == floor(x / y) + + +def test_as_coeff_Mul(): + assert Integer(3).as_coeff_Mul() == (Integer(3), Integer(1)) + assert Rational(3, 4).as_coeff_Mul() == (Rational(3, 4), Integer(1)) + assert Float(5.0).as_coeff_Mul() == (Float(5.0), Integer(1)) + assert Float(0.0).as_coeff_Mul() == (Float(0.0), Integer(1)) + + assert (Integer(3)*x).as_coeff_Mul() == (Integer(3), x) + assert (Rational(3, 4)*x).as_coeff_Mul() == (Rational(3, 4), x) + assert (Float(5.0)*x).as_coeff_Mul() == (Float(5.0), x) + + assert (Integer(3)*x*y).as_coeff_Mul() == (Integer(3), x*y) + assert (Rational(3, 4)*x*y).as_coeff_Mul() == (Rational(3, 4), x*y) + assert (Float(5.0)*x*y).as_coeff_Mul() == (Float(5.0), x*y) + + assert (x).as_coeff_Mul() == (S.One, x) + assert (x*y).as_coeff_Mul() == (S.One, x*y) + assert (-oo*x).as_coeff_Mul(rational=True) == (-1, oo*x) + + +def test_as_coeff_Add(): + assert Integer(3).as_coeff_Add() == (Integer(3), Integer(0)) + assert Rational(3, 4).as_coeff_Add() == (Rational(3, 4), Integer(0)) + assert Float(5.0).as_coeff_Add() == (Float(5.0), Integer(0)) + + assert (Integer(3) + x).as_coeff_Add() == (Integer(3), x) + assert (Rational(3, 4) + x).as_coeff_Add() == (Rational(3, 4), x) + assert (Float(5.0) + x).as_coeff_Add() == (Float(5.0), x) + assert (Float(5.0) + x).as_coeff_Add(rational=True) == (0, Float(5.0) + x) + + assert (Integer(3) + x + y).as_coeff_Add() == (Integer(3), x + y) + assert (Rational(3, 4) + x + y).as_coeff_Add() == (Rational(3, 4), x + y) + assert (Float(5.0) + x + y).as_coeff_Add() == (Float(5.0), x + y) + + assert (x).as_coeff_Add() == (S.Zero, x) + assert (x*y).as_coeff_Add() == (S.Zero, x*y) + + +def test_expr_sorting(): + + exprs = [1/x**2, 1/x, sqrt(sqrt(x)), sqrt(x), x, sqrt(x)**3, x**2] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [x, 2*x, 2*x**2, 2*x**3, x**n, 2*x**n, sin(x), sin(x)**n, + sin(x**2), cos(x), cos(x**2), tan(x)] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [x + 1, x**2 + x + 1, x**3 + x**2 + x + 1] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [S(4), x - 3*I/2, x + 3*I/2, x - 4*I + 1, x + 4*I + 1] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [f(1), f(2), f(3), f(1, 2, 3), g(1), g(2), g(3), g(1, 2, 3)] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [f(x), g(x), exp(x), sin(x), cos(x), factorial(x)] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [Tuple(x, y), Tuple(x, z), Tuple(x, y, z)] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [[3], [1, 2]] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [[1, 2], [2, 3]] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [[1, 2], [1, 2, 3]] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [{x: -y}, {x: y}] + assert sorted(exprs, key=default_sort_key) == exprs + + exprs = [{1}, {1, 2}] + assert sorted(exprs, key=default_sort_key) == exprs + + a, b = exprs = [Dummy('x'), Dummy('x')] + assert sorted([b, a], key=default_sort_key) == exprs + + +def test_as_ordered_factors(): + + assert x.as_ordered_factors() == [x] + assert (2*x*x**n*sin(x)*cos(x)).as_ordered_factors() \ + == [Integer(2), x, x**n, sin(x), cos(x)] + + args = [f(1), f(2), f(3), f(1, 2, 3), g(1), g(2), g(3), g(1, 2, 3)] + expr = Mul(*args) + + assert expr.as_ordered_factors() == args + + A, B = symbols('A,B', commutative=False) + + assert (A*B).as_ordered_factors() == [A, B] + assert (B*A).as_ordered_factors() == [B, A] + + +def test_as_ordered_terms(): + + assert x.as_ordered_terms() == [x] + assert (sin(x)**2*cos(x) + sin(x)*cos(x)**2 + 1).as_ordered_terms() \ + == [sin(x)**2*cos(x), sin(x)*cos(x)**2, 1] + + args = [f(1), f(2), f(3), f(1, 2, 3), g(1), g(2), g(3), g(1, 2, 3)] + expr = Add(*args) + + assert expr.as_ordered_terms() == args + + assert (1 + 4*sqrt(3)*pi*x).as_ordered_terms() == [4*pi*x*sqrt(3), 1] + + assert ( 2 + 3*I).as_ordered_terms() == [2, 3*I] + assert (-2 + 3*I).as_ordered_terms() == [-2, 3*I] + assert ( 2 - 3*I).as_ordered_terms() == [2, -3*I] + assert (-2 - 3*I).as_ordered_terms() == [-2, -3*I] + + assert ( 4 + 3*I).as_ordered_terms() == [4, 3*I] + assert (-4 + 3*I).as_ordered_terms() == [-4, 3*I] + assert ( 4 - 3*I).as_ordered_terms() == [4, -3*I] + assert (-4 - 3*I).as_ordered_terms() == [-4, -3*I] + + e = x**2*y**2 + x*y**4 + y + 2 + + assert e.as_ordered_terms(order="lex") == [x**2*y**2, x*y**4, y, 2] + assert e.as_ordered_terms(order="grlex") == [x*y**4, x**2*y**2, y, 2] + assert e.as_ordered_terms(order="rev-lex") == [2, y, x*y**4, x**2*y**2] + assert e.as_ordered_terms(order="rev-grlex") == [2, y, x**2*y**2, x*y**4] + + k = symbols('k') + assert k.as_ordered_terms(data=True) == ([(k, ((1.0, 0.0), (1,), ()))], [k]) + + +def test_sort_key_atomic_expr(): + from sympy.physics.units import m, s + assert sorted([-m, s], key=lambda arg: arg.sort_key()) == [-m, s] + + +def test_eval_interval(): + assert exp(x)._eval_interval(*Tuple(x, 0, 1)) == exp(1) - exp(0) + + # issue 4199 + a = x/y + raises(NotImplementedError, lambda: a._eval_interval(x, S.Zero, oo)._eval_interval(y, oo, S.Zero)) + raises(NotImplementedError, lambda: a._eval_interval(x, S.Zero, oo)._eval_interval(y, S.Zero, oo)) + a = x - y + raises(NotImplementedError, lambda: a._eval_interval(x, S.One, oo)._eval_interval(y, oo, S.One)) + raises(ValueError, lambda: x._eval_interval(x, None, None)) + a = -y*Heaviside(x - y) + assert a._eval_interval(x, -oo, oo) == -y + assert a._eval_interval(x, oo, -oo) == y + + +def test_eval_interval_zoo(): + # Test that limit is used when zoo is returned + assert Si(1/x)._eval_interval(x, S.Zero, S.One) == -pi/2 + Si(1) + + +def test_primitive(): + assert (3*(x + 1)**2).primitive() == (3, (x + 1)**2) + assert (6*x + 2).primitive() == (2, 3*x + 1) + assert (x/2 + 3).primitive() == (S.Half, x + 6) + eq = (6*x + 2)*(x/2 + 3) + assert eq.primitive()[0] == 1 + eq = (2 + 2*x)**2 + assert eq.primitive()[0] == 1 + assert (4.0*x).primitive() == (1, 4.0*x) + assert (4.0*x + y/2).primitive() == (S.Half, 8.0*x + y) + assert (-2*x).primitive() == (2, -x) + assert Add(5*z/7, 0.5*x, 3*y/2, evaluate=False).primitive() == \ + (S.One/14, 7.0*x + 21*y + 10*z) + for i in [S.Infinity, S.NegativeInfinity, S.ComplexInfinity]: + assert (i + x/3).primitive() == \ + (S.One/3, i + x) + assert (S.Infinity + 2*x/3 + 4*y/7).primitive() == \ + (S.One/21, 14*x + 12*y + oo) + assert S.Zero.primitive() == (S.One, S.Zero) + + +def test_issue_5843(): + a = 1 + x + assert (2*a).extract_multiplicatively(a) == 2 + assert (4*a).extract_multiplicatively(2*a) == 2 + assert ((3*a)*(2*a)).extract_multiplicatively(a) == 6*a + + +def test_is_constant(): + from sympy.solvers.solvers import checksol + assert Sum(x, (x, 1, 10)).is_constant() is True + assert Sum(x, (x, 1, n)).is_constant() is False + assert Sum(x, (x, 1, n)).is_constant(y) is True + assert Sum(x, (x, 1, n)).is_constant(n) is False + assert Sum(x, (x, 1, n)).is_constant(x) is True + eq = a*cos(x)**2 + a*sin(x)**2 - a + assert eq.is_constant() is True + assert eq.subs({x: pi, a: 2}) == eq.subs({x: pi, a: 3}) == 0 + assert x.is_constant() is False + assert x.is_constant(y) is True + assert log(x/y).is_constant() is False + + assert checksol(x, x, Sum(x, (x, 1, n))) is False + assert checksol(x, x, Sum(x, (x, 1, n))) is False + assert f(1).is_constant + assert checksol(x, x, f(x)) is False + + assert Pow(x, S.Zero, evaluate=False).is_constant() is True # == 1 + assert Pow(S.Zero, x, evaluate=False).is_constant() is False # == 0 or 1 + assert (2**x).is_constant() is False + assert Pow(S(2), S(3), evaluate=False).is_constant() is True + + z1, z2 = symbols('z1 z2', zero=True) + assert (z1 + 2*z2).is_constant() is True + + assert meter.is_constant() is True + assert (3*meter).is_constant() is True + assert (x*meter).is_constant() is False + + +def test_equals(): + assert (-3 - sqrt(5) + (-sqrt(10)/2 - sqrt(2)/2)**2).equals(0) + assert (x**2 - 1).equals((x + 1)*(x - 1)) + assert (cos(x)**2 + sin(x)**2).equals(1) + assert (a*cos(x)**2 + a*sin(x)**2).equals(a) + r = sqrt(2) + assert (-1/(r + r*x) + 1/r/(1 + x)).equals(0) + assert factorial(x + 1).equals((x + 1)*factorial(x)) + assert sqrt(3).equals(2*sqrt(3)) is False + assert (sqrt(5)*sqrt(3)).equals(sqrt(3)) is False + assert (sqrt(5) + sqrt(3)).equals(0) is False + assert (sqrt(5) + pi).equals(0) is False + assert meter.equals(0) is False + assert (3*meter**2).equals(0) is False + eq = -(-1)**(S(3)/4)*6**(S.One/4) + (-6)**(S.One/4)*I + if eq != 0: # if canonicalization makes this zero, skip the test + assert eq.equals(0) + assert sqrt(x).equals(0) is False + + # from integrate(x*sqrt(1 + 2*x), x); + # diff is zero only when assumptions allow + i = 2*sqrt(2)*x**(S(5)/2)*(1 + 1/(2*x))**(S(5)/2)/5 + \ + 2*sqrt(2)*x**(S(3)/2)*(1 + 1/(2*x))**(S(5)/2)/(-6 - 3/x) + ans = sqrt(2*x + 1)*(6*x**2 + x - 1)/15 + diff = i - ans + assert diff.equals(0) is None # should be False, but previously this was False due to wrong intermediate result + assert diff.subs(x, Rational(-1, 2)/2) == 7*sqrt(2)/120 + # there are regions for x for which the expression is True, for + # example, when x < -1/2 or x > 0 the expression is zero + p = Symbol('p', positive=True) + assert diff.subs(x, p).equals(0) is True + assert diff.subs(x, -1).equals(0) is True + + # prove via minimal_polynomial or self-consistency + eq = sqrt(1 + sqrt(3)) + sqrt(3 + 3*sqrt(3)) - sqrt(10 + 6*sqrt(3)) + assert eq.equals(0) + q = 3**Rational(1, 3) + 3 + p = expand(q**3)**Rational(1, 3) + assert (p - q).equals(0) + + # issue 6829 + # eq = q*x + q/4 + x**4 + x**3 + 2*x**2 - S.One/3 + # z = eq.subs(x, solve(eq, x)[0]) + q = symbols('q') + z = (q*(-sqrt(-2*(-(q - S(7)/8)**S(2)/8 - S(2197)/13824)**(S.One/3) - + S(13)/12)/2 - sqrt((2*q - S(7)/4)/sqrt(-2*(-(q - S(7)/8)**S(2)/8 - + S(2197)/13824)**(S.One/3) - S(13)/12) + 2*(-(q - S(7)/8)**S(2)/8 - + S(2197)/13824)**(S.One/3) - S(13)/6)/2 - S.One/4) + q/4 + (-sqrt(-2*(-(q + - S(7)/8)**S(2)/8 - S(2197)/13824)**(S.One/3) - S(13)/12)/2 - sqrt((2*q + - S(7)/4)/sqrt(-2*(-(q - S(7)/8)**S(2)/8 - S(2197)/13824)**(S.One/3) - + S(13)/12) + 2*(-(q - S(7)/8)**S(2)/8 - S(2197)/13824)**(S.One/3) - + S(13)/6)/2 - S.One/4)**4 + (-sqrt(-2*(-(q - S(7)/8)**S(2)/8 - + S(2197)/13824)**(S.One/3) - S(13)/12)/2 - sqrt((2*q - + S(7)/4)/sqrt(-2*(-(q - S(7)/8)**S(2)/8 - S(2197)/13824)**(S.One/3) - + S(13)/12) + 2*(-(q - S(7)/8)**S(2)/8 - S(2197)/13824)**(S.One/3) - + S(13)/6)/2 - S.One/4)**3 + 2*(-sqrt(-2*(-(q - S(7)/8)**S(2)/8 - + S(2197)/13824)**(S.One/3) - S(13)/12)/2 - sqrt((2*q - + S(7)/4)/sqrt(-2*(-(q - S(7)/8)**S(2)/8 - S(2197)/13824)**(S.One/3) - + S(13)/12) + 2*(-(q - S(7)/8)**S(2)/8 - S(2197)/13824)**(S.One/3) - + S(13)/6)/2 - S.One/4)**2 - Rational(1, 3)) + assert z.equals(0) + + +def test_random(): + from sympy.functions.combinatorial.numbers import lucas + from sympy.simplify.simplify import posify + assert posify(x)[0]._random() is not None + assert lucas(n)._random(2, -2, 0, -1, 1) is None + + # issue 8662 + assert Piecewise((Max(x, y), z))._random() is None + + +def test_round(): + assert str(Float('0.1249999').round(2)) == '0.12' + d20 = 12345678901234567890 + ans = S(d20).round(2) + assert ans.is_Integer and ans == d20 + ans = S(d20).round(-2) + assert ans.is_Integer and ans == 12345678901234567900 + assert str(S('1/7').round(4)) == '0.1429' + assert str(S('.[12345]').round(4)) == '0.1235' + assert str(S('.1349').round(2)) == '0.13' + n = S(12345) + ans = n.round() + assert ans.is_Integer + assert ans == n + ans = n.round(1) + assert ans.is_Integer + assert ans == n + ans = n.round(4) + assert ans.is_Integer + assert ans == n + assert n.round(-1) == 12340 + + r = Float(str(n)).round(-4) + assert r == 10000.0 + + assert n.round(-5) == 0 + + assert str((pi + sqrt(2)).round(2)) == '4.56' + assert (10*(pi + sqrt(2))).round(-1) == 50.0 + raises(TypeError, lambda: round(x + 2, 2)) + assert str(S(2.3).round(1)) == '2.3' + # rounding in SymPy (as in Decimal) should be + # exact for the given precision; we check here + # that when a 5 follows the last digit that + # the rounded digit will be even. + for i in range(-99, 100): + # construct a decimal that ends in 5, e.g. 123 -> 0.1235 + s = str(abs(i)) + p = len(s) # we are going to round to the last digit of i + n = '0.%s5' % s # put a 5 after i's digits + j = p + 2 # 2 for '0.' + if i < 0: # 1 for '-' + j += 1 + n = '-' + n + v = str(Float(n).round(p))[:j] # pertinent digits + if v.endswith('.'): + continue # it ends with 0 which is even + L = int(v[-1]) # last digit + assert L % 2 == 0, (n, '->', v) + + assert (Float(.3, 3) + 2*pi).round() == 7 + assert (Float(.3, 3) + 2*pi*100).round() == 629 + assert (pi + 2*E*I).round() == 3 + 5*I + # don't let request for extra precision give more than + # what is known (in this case, only 3 digits) + assert str((Float(.03, 3) + 2*pi/100).round(5)) == '0.0928' + assert str((Float(.03, 3) + 2*pi/100).round(4)) == '0.0928' + + assert S.Zero.round() == 0 + + a = (Add(1, Float('1.' + '9'*27, ''), evaluate=0)) + assert a.round(10) == Float('3.000000000000000000000000000', '') + assert a.round(25) == Float('3.000000000000000000000000000', '') + assert a.round(26) == Float('3.000000000000000000000000000', '') + assert a.round(27) == Float('2.999999999999999999999999999', '') + assert a.round(30) == Float('2.999999999999999999999999999', '') + #assert a.round(10) == Float('3.0000000000', '') + #assert a.round(25) == Float('3.0000000000000000000000000', '') + #assert a.round(26) == Float('3.00000000000000000000000000', '') + #assert a.round(27) == Float('2.999999999999999999999999999', '') + #assert a.round(30) == Float('2.999999999999999999999999999', '') + + # XXX: Should round set the precision of the result? + # The previous version of the tests above is this but they only pass + # because Floats with unequal precision compare equal: + # + # assert a.round(10) == Float('3.0000000000', '') + # assert a.round(25) == Float('3.0000000000000000000000000', '') + # assert a.round(26) == Float('3.00000000000000000000000000', '') + # assert a.round(27) == Float('2.999999999999999999999999999', '') + # assert a.round(30) == Float('2.999999999999999999999999999', '') + + raises(TypeError, lambda: x.round()) + raises(TypeError, lambda: f(1).round()) + + # exact magnitude of 10 + assert str(S.One.round()) == '1' + assert str(S(100).round()) == '100' + + # applied to real and imaginary portions + assert (2*pi + E*I).round() == 6 + 3*I + assert (2*pi + I/10).round() == 6 + assert (pi/10 + 2*I).round() == 2*I + # the lhs re and im parts are Float with dps of 2 + # and those on the right have dps of 15 so they won't compare + # equal unless we use string or compare components (which will + # then coerce the floats to the same precision) or re-create + # the floats + assert str((pi/10 + E*I).round(2)) == '0.31 + 2.72*I' + assert str((pi/10 + E*I).round(2).as_real_imag()) == '(0.31, 2.72)' + assert str((pi/10 + E*I).round(2)) == '0.31 + 2.72*I' + + # issue 6914 + assert (I**(I + 3)).round(3) == Float('-0.208', '')*I + + # issue 8720 + assert S(-123.6).round() == -124 + assert S(-1.5).round() == -2 + assert S(-100.5).round() == -100 + assert S(-1.5 - 10.5*I).round() == -2 - 10*I + + # issue 7961 + assert str(S(0.006).round(2)) == '0.01' + assert str(S(0.00106).round(4)) == '0.0011' + + # issue 8147 + assert S.NaN.round() is S.NaN + assert S.Infinity.round() is S.Infinity + assert S.NegativeInfinity.round() is S.NegativeInfinity + assert S.ComplexInfinity.round() is S.ComplexInfinity + + # check that types match + for i in range(2): + fi = float(i) + # 2 args + assert all(type(round(i, p)) is int for p in (-1, 0, 1)) + assert all(S(i).round(p).is_Integer for p in (-1, 0, 1)) + assert all(type(round(fi, p)) is float for p in (-1, 0, 1)) + assert all(S(fi).round(p).is_Float for p in (-1, 0, 1)) + # 1 arg (p is None) + assert type(round(i)) is int + assert S(i).round().is_Integer + assert type(round(fi)) is int + assert S(fi).round().is_Integer + + # issue 25698 + n = 6000002 + assert int(n*(log(n) + log(log(n)))) == 110130079 + one = cos(2)**2 + sin(2)**2 + eq = exp(one*I*pi) + qr, qi = eq.as_real_imag() + assert qi.round(2) == 0.0 + assert eq.round(2) == -1.0 + eq = one - 1/S(10**120) + assert S.true not in (eq > 1, eq < 1) + assert int(eq) == int(.9) == 0 + assert int(-eq) == int(-.9) == 0 + + +def test_held_expression_UnevaluatedExpr(): + x = symbols("x") + he = UnevaluatedExpr(1/x) + e1 = x*he + + assert isinstance(e1, Mul) + assert e1.args == (x, he) + assert e1.doit() == 1 + assert UnevaluatedExpr(Derivative(x, x)).doit(deep=False + ) == Derivative(x, x) + assert UnevaluatedExpr(Derivative(x, x)).doit() == 1 + + xx = Mul(x, x, evaluate=False) + assert xx != x**2 + + ue2 = UnevaluatedExpr(xx) + assert isinstance(ue2, UnevaluatedExpr) + assert ue2.args == (xx,) + assert ue2.doit() == x**2 + assert ue2.doit(deep=False) == xx + + x2 = UnevaluatedExpr(2)*2 + assert type(x2) is Mul + assert x2.args == (2, UnevaluatedExpr(2)) + +def test_round_exception_nostr(): + # Don't use the string form of the expression in the round exception, as + # it's too slow + s = Symbol('bad') + try: + s.round() + except TypeError as e: + assert 'bad' not in str(e) + else: + # Did not raise + raise AssertionError("Did not raise") + + +def test_extract_branch_factor(): + assert exp_polar(2.0*I*pi).extract_branch_factor() == (1, 1) + + +def test_identity_removal(): + assert Add.make_args(x + 0) == (x,) + assert Mul.make_args(x*1) == (x,) + + +def test_float_0(): + assert Float(0.0) + 1 == Float(1.0) + + +@XFAIL +def test_float_0_fail(): + assert Float(0.0)*x == Float(0.0) + assert (x + Float(0.0)).is_Add + + +def test_issue_6325(): + ans = (b**2 + z**2 - (b*(a + b*t) + z*(c + t*z))**2/( + (a + b*t)**2 + (c + t*z)**2))/sqrt((a + b*t)**2 + (c + t*z)**2) + e = sqrt((a + b*t)**2 + (c + z*t)**2) + assert diff(e, t, 2) == ans + assert e.diff(t, 2) == ans + assert diff(e, t, 2, simplify=False) != ans + + +def test_issue_7426(): + f1 = a % c + f2 = x % z + assert f1.equals(f2) is None + + +def test_issue_11122(): + x = Symbol('x', extended_positive=False) + assert unchanged(Gt, x, 0) # (x > 0) + # (x > 0) should remain unevaluated after PR #16956 + + x = Symbol('x', positive=False, real=True) + assert (x > 0) is S.false + + +def test_issue_10651(): + x = Symbol('x', real=True) + e1 = (-1 + x)/(1 - x) + e3 = (4*x**2 - 4)/((1 - x)*(1 + x)) + e4 = 1/(cos(x)**2) - (tan(x))**2 + x = Symbol('x', positive=True) + e5 = (1 + x)/x + assert e1.is_constant() is None + assert e3.is_constant() is None + assert e4.is_constant() is None + assert e5.is_constant() is False + + +def test_issue_10161(): + x = symbols('x', real=True) + assert x*abs(x)*abs(x) == x**3 + + +def test_issue_10755(): + x = symbols('x') + raises(TypeError, lambda: int(log(x))) + raises(TypeError, lambda: log(x).round(2)) + + +def test_issue_11877(): + x = symbols('x') + assert integrate(log(S.Half - x), (x, 0, S.Half)) == Rational(-1, 2) -log(2)/2 + + +def test_normal(): + x = symbols('x') + e = Mul(S.Half, 1 + x, evaluate=False) + assert e.normal() == e + + +def test_expr(): + x = symbols('x') + raises(TypeError, lambda: tan(x).series(x, 2, oo, "+")) + + +def test_ExprBuilder(): + eb = ExprBuilder(Mul) + eb.args.extend([x, x]) + assert eb.build() == x**2 + + +def test_issue_22020(): + from sympy.parsing.sympy_parser import parse_expr + x = parse_expr("log((2*V/3-V)/C)/-(R+r)*C") + y = parse_expr("log((2*V/3-V)/C)/-(R+r)*2") + assert x.equals(y) is False + + +def test_non_string_equality(): + # Expressions should not compare equal to strings + x = symbols('x') + one = sympify(1) + assert (x == 'x') is False + assert (x != 'x') is True + assert (one == '1') is False + assert (one != '1') is True + assert (x + 1 == 'x + 1') is False + assert (x + 1 != 'x + 1') is True + + # Make sure == doesn't try to convert the resulting expression to a string + # (e.g., by calling sympify() instead of _sympify()) + + class BadRepr: + def __repr__(self): + raise RuntimeError + + assert (x == BadRepr()) is False + assert (x != BadRepr()) is True + + +def test_21494(): + from sympy.testing.pytest import warns_deprecated_sympy + + with warns_deprecated_sympy(): + assert x.expr_free_symbols == {x} + + with warns_deprecated_sympy(): + assert Basic().expr_free_symbols == set() + + with warns_deprecated_sympy(): + assert S(2).expr_free_symbols == {S(2)} + + with warns_deprecated_sympy(): + assert Indexed("A", x).expr_free_symbols == {Indexed("A", x)} + + with warns_deprecated_sympy(): + assert Subs(x, x, 0).expr_free_symbols == set() + + +def test_Expr__eq__iterable_handling(): + assert x != range(3) + + +def test_format(): + assert '{:1.2f}'.format(S.Zero) == '0.00' + assert '{:+3.0f}'.format(S(3)) == ' +3' + assert '{:23.20f}'.format(pi) == ' 3.14159265358979323846' + assert '{:50.48f}'.format(exp(sin(1))) == '2.319776824715853173956590377503266813254904772376' + + +def test_issue_24045(): + assert powsimp(exp(a)/((c*a - c*b)*(Float(1.0)*c*a - Float(1.0)*c*b))) # doesn't raise diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_exprtools.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_exprtools.py new file mode 100644 index 0000000000000000000000000000000000000000..b550db1606866fb76442980ea2139aaf61219525 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_exprtools.py @@ -0,0 +1,493 @@ +"""Tests for tools for manipulating of large commutative expressions. """ + +from sympy.concrete.summations import Sum +from sympy.core.add import Add +from sympy.core.basic import Basic +from sympy.core.containers import (Dict, Tuple) +from sympy.core.function import Function +from sympy.core.mul import Mul +from sympy.core.numbers import (I, Rational, oo) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, symbols) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import (root, sqrt) +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.integrals.integrals import Integral +from sympy.series.order import O +from sympy.sets.sets import Interval +from sympy.simplify.radsimp import collect +from sympy.simplify.simplify import simplify +from sympy.core.exprtools import (decompose_power, Factors, Term, _gcd_terms, + gcd_terms, factor_terms, factor_nc, _mask_nc, + _monotonic_sign) +from sympy.core.mul import _keep_coeff as _keep_coeff +from sympy.simplify.cse_opts import sub_pre +from sympy.testing.pytest import raises + +from sympy.abc import a, b, t, x, y, z + + +def test_decompose_power(): + assert decompose_power(x) == (x, 1) + assert decompose_power(x**2) == (x, 2) + assert decompose_power(x**(2*y)) == (x**y, 2) + assert decompose_power(x**(2*y/3)) == (x**(y/3), 2) + assert decompose_power(x**(y*Rational(2, 3))) == (x**(y/3), 2) + + +def test_Factors(): + assert Factors() == Factors({}) == Factors(S.One) + assert Factors().as_expr() is S.One + assert Factors({x: 2, y: 3, sin(x): 4}).as_expr() == x**2*y**3*sin(x)**4 + assert Factors(S.Infinity) == Factors({oo: 1}) + assert Factors(S.NegativeInfinity) == Factors({oo: 1, -1: 1}) + # issue #18059: + assert Factors((x**2)**S.Half).as_expr() == (x**2)**S.Half + + a = Factors({x: 5, y: 3, z: 7}) + b = Factors({ y: 4, z: 3, t: 10}) + + assert a.mul(b) == a*b == Factors({x: 5, y: 7, z: 10, t: 10}) + + assert a.div(b) == divmod(a, b) == \ + (Factors({x: 5, z: 4}), Factors({y: 1, t: 10})) + assert a.quo(b) == a/b == Factors({x: 5, z: 4}) + assert a.rem(b) == a % b == Factors({y: 1, t: 10}) + + assert a.pow(3) == a**3 == Factors({x: 15, y: 9, z: 21}) + assert b.pow(3) == b**3 == Factors({y: 12, z: 9, t: 30}) + + assert a.gcd(b) == Factors({y: 3, z: 3}) + assert a.lcm(b) == Factors({x: 5, y: 4, z: 7, t: 10}) + + a = Factors({x: 4, y: 7, t: 7}) + b = Factors({z: 1, t: 3}) + + assert a.normal(b) == (Factors({x: 4, y: 7, t: 4}), Factors({z: 1})) + + assert Factors(sqrt(2)*x).as_expr() == sqrt(2)*x + + assert Factors(-I)*I == Factors() + assert Factors({S.NegativeOne: S(3)})*Factors({S.NegativeOne: S.One, I: S(5)}) == \ + Factors(I) + assert Factors(sqrt(I)*I) == Factors(I**(S(3)/2)) == Factors({I: S(3)/2}) + assert Factors({I: S(3)/2}).as_expr() == I**(S(3)/2) + + assert Factors(S(2)**x).div(S(3)**x) == \ + (Factors({S(2): x}), Factors({S(3): x})) + assert Factors(2**(2*x + 2)).div(S(8)) == \ + (Factors({S(2): 2*x + 2}), Factors({S(8): S.One})) + + # coverage + # /!\ things break if this is not True + assert Factors({S.NegativeOne: Rational(3, 2)}) == Factors({I: S.One, S.NegativeOne: S.One}) + assert Factors({I: S.One, S.NegativeOne: Rational(1, 3)}).as_expr() == I*(-1)**Rational(1, 3) + + assert Factors(-1.) == Factors({S.NegativeOne: S.One, S(1.): 1}) + assert Factors(-2.) == Factors({S.NegativeOne: S.One, S(2.): 1}) + assert Factors((-2.)**x) == Factors({S(-2.): x}) + assert Factors(S(-2)) == Factors({S.NegativeOne: S.One, S(2): 1}) + assert Factors(S.Half) == Factors({S(2): -S.One}) + assert Factors(Rational(3, 2)) == Factors({S(3): S.One, S(2): S.NegativeOne}) + assert Factors({I: S.One}) == Factors(I) + assert Factors({-1.0: 2, I: 1}) == Factors({S(1.0): 1, I: 1}) + assert Factors({S.NegativeOne: Rational(-3, 2)}).as_expr() == I + A = symbols('A', commutative=False) + assert Factors(2*A**2) == Factors({S(2): 1, A**2: 1}) + assert Factors(I) == Factors({I: S.One}) + assert Factors(x).normal(S(2)) == (Factors(x), Factors(S(2))) + assert Factors(x).normal(S.Zero) == (Factors(), Factors(S.Zero)) + raises(ZeroDivisionError, lambda: Factors(x).div(S.Zero)) + assert Factors(x).mul(S(2)) == Factors(2*x) + assert Factors(x).mul(S.Zero).is_zero + assert Factors(x).mul(1/x).is_one + assert Factors(x**sqrt(2)**3).as_expr() == x**(2*sqrt(2)) + assert Factors(x)**Factors(S(2)) == Factors(x**2) + assert Factors(x).gcd(S.Zero) == Factors(x) + assert Factors(x).lcm(S.Zero).is_zero + assert Factors(S.Zero).div(x) == (Factors(S.Zero), Factors()) + assert Factors(x).div(x) == (Factors(), Factors()) + assert Factors({x: .2})/Factors({x: .2}) == Factors() + assert Factors(x) != Factors() + assert Factors(S.Zero).normal(x) == (Factors(S.Zero), Factors()) + n, d = x**(2 + y), x**2 + f = Factors(n) + assert f.div(d) == f.normal(d) == (Factors(x**y), Factors()) + assert f.gcd(d) == Factors() + d = x**y + assert f.div(d) == f.normal(d) == (Factors(x**2), Factors()) + assert f.gcd(d) == Factors(d) + n = d = 2**x + f = Factors(n) + assert f.div(d) == f.normal(d) == (Factors(), Factors()) + assert f.gcd(d) == Factors(d) + n, d = 2**x, 2**y + f = Factors(n) + assert f.div(d) == f.normal(d) == (Factors({S(2): x}), Factors({S(2): y})) + assert f.gcd(d) == Factors() + + # extraction of constant only + n = x**(x + 3) + assert Factors(n).normal(x**-3) == (Factors({x: x + 6}), Factors({})) + assert Factors(n).normal(x**3) == (Factors({x: x}), Factors({})) + assert Factors(n).normal(x**4) == (Factors({x: x}), Factors({x: 1})) + assert Factors(n).normal(x**(y - 3)) == \ + (Factors({x: x + 6}), Factors({x: y})) + assert Factors(n).normal(x**(y + 3)) == (Factors({x: x}), Factors({x: y})) + assert Factors(n).normal(x**(y + 4)) == \ + (Factors({x: x}), Factors({x: y + 1})) + + assert Factors(n).div(x**-3) == (Factors({x: x + 6}), Factors({})) + assert Factors(n).div(x**3) == (Factors({x: x}), Factors({})) + assert Factors(n).div(x**4) == (Factors({x: x}), Factors({x: 1})) + assert Factors(n).div(x**(y - 3)) == \ + (Factors({x: x + 6}), Factors({x: y})) + assert Factors(n).div(x**(y + 3)) == (Factors({x: x}), Factors({x: y})) + assert Factors(n).div(x**(y + 4)) == \ + (Factors({x: x}), Factors({x: y + 1})) + + assert Factors(3 * x / 2) == Factors({3: 1, 2: -1, x: 1}) + assert Factors(x * x / y) == Factors({x: 2, y: -1}) + assert Factors(27 * x / y**9) == Factors({27: 1, x: 1, y: -9}) + + +def test_Term(): + a = Term(4*x*y**2/z/t**3) + b = Term(2*x**3*y**5/t**3) + + assert a == Term(4, Factors({x: 1, y: 2}), Factors({z: 1, t: 3})) + assert b == Term(2, Factors({x: 3, y: 5}), Factors({t: 3})) + + assert a.as_expr() == 4*x*y**2/z/t**3 + assert b.as_expr() == 2*x**3*y**5/t**3 + + assert a.inv() == \ + Term(S.One/4, Factors({z: 1, t: 3}), Factors({x: 1, y: 2})) + assert b.inv() == Term(S.Half, Factors({t: 3}), Factors({x: 3, y: 5})) + + assert a.mul(b) == a*b == \ + Term(8, Factors({x: 4, y: 7}), Factors({z: 1, t: 6})) + assert a.quo(b) == a/b == Term(2, Factors({}), Factors({x: 2, y: 3, z: 1})) + + assert a.pow(3) == a**3 == \ + Term(64, Factors({x: 3, y: 6}), Factors({z: 3, t: 9})) + assert b.pow(3) == b**3 == Term(8, Factors({x: 9, y: 15}), Factors({t: 9})) + + assert a.pow(-3) == a**(-3) == \ + Term(S.One/64, Factors({z: 3, t: 9}), Factors({x: 3, y: 6})) + assert b.pow(-3) == b**(-3) == \ + Term(S.One/8, Factors({t: 9}), Factors({x: 9, y: 15})) + + assert a.gcd(b) == Term(2, Factors({x: 1, y: 2}), Factors({t: 3})) + assert a.lcm(b) == Term(4, Factors({x: 3, y: 5}), Factors({z: 1, t: 3})) + + a = Term(4*x*y**2/z/t**3) + b = Term(2*x**3*y**5*t**7) + + assert a.mul(b) == Term(8, Factors({x: 4, y: 7, t: 4}), Factors({z: 1})) + + assert Term((2*x + 2)**3) == Term(8, Factors({x + 1: 3}), Factors({})) + assert Term((2*x + 2)*(3*x + 6)**2) == \ + Term(18, Factors({x + 1: 1, x + 2: 2}), Factors({})) + + +def test_gcd_terms(): + f = 2*(x + 1)*(x + 4)/(5*x**2 + 5) + (2*x + 2)*(x + 5)/(x**2 + 1)/5 + \ + (2*x + 2)*(x + 6)/(5*x**2 + 5) + + assert _gcd_terms(f) == ((Rational(6, 5))*((1 + x)/(1 + x**2)), 5 + x, 1) + assert _gcd_terms(Add.make_args(f)) == \ + ((Rational(6, 5))*((1 + x)/(1 + x**2)), 5 + x, 1) + + newf = (Rational(6, 5))*((1 + x)*(5 + x)/(1 + x**2)) + assert gcd_terms(f) == newf + args = Add.make_args(f) + # non-Basic sequences of terms treated as terms of Add + assert gcd_terms(list(args)) == newf + assert gcd_terms(tuple(args)) == newf + assert gcd_terms(set(args)) == newf + # but a Basic sequence is treated as a container + assert gcd_terms(Tuple(*args)) != newf + assert gcd_terms(Basic(Tuple(S(1), 3*y + 3*x*y), Tuple(S(1), S(3)))) == \ + Basic(Tuple(S(1), 3*y*(x + 1)), Tuple(S(1), S(3))) + # but we shouldn't change keys of a dictionary or some may be lost + assert gcd_terms(Dict((x*(1 + y), S(2)), (x + x*y, y + x*y))) == \ + Dict({x*(y + 1): S(2), x + x*y: y*(1 + x)}) + + assert gcd_terms((2*x + 2)**3 + (2*x + 2)**2) == 4*(x + 1)**2*(2*x + 3) + + assert gcd_terms(0) == 0 + assert gcd_terms(1) == 1 + assert gcd_terms(x) == x + assert gcd_terms(2 + 2*x) == Mul(2, 1 + x, evaluate=False) + arg = x*(2*x + 4*y) + garg = 2*x*(x + 2*y) + assert gcd_terms(arg) == garg + assert gcd_terms(sin(arg)) == sin(garg) + + # issue 6139-like + alpha, alpha1, alpha2, alpha3 = symbols('alpha:4') + a = alpha**2 - alpha*x**2 + alpha + x**3 - x*(alpha + 1) + rep = (alpha, (1 + sqrt(5))/2 + alpha1*x + alpha2*x**2 + alpha3*x**3) + s = (a/(x - alpha)).subs(*rep).series(x, 0, 1) + assert simplify(collect(s, x)) == -sqrt(5)/2 - Rational(3, 2) + O(x) + + # issue 5917 + assert _gcd_terms([S.Zero, S.Zero]) == (0, 0, 1) + assert _gcd_terms([2*x + 4]) == (2, x + 2, 1) + + eq = x/(x + 1/x) + assert gcd_terms(eq, fraction=False) == eq + eq = x/2/y + 1/x/y + assert gcd_terms(eq, fraction=True, clear=True) == \ + (x**2 + 2)/(2*x*y) + assert gcd_terms(eq, fraction=True, clear=False) == \ + (x**2/2 + 1)/(x*y) + assert gcd_terms(eq, fraction=False, clear=True) == \ + (x + 2/x)/(2*y) + assert gcd_terms(eq, fraction=False, clear=False) == \ + (x/2 + 1/x)/y + + +def test_factor_terms(): + A = Symbol('A', commutative=False) + assert factor_terms(9*(x + x*y + 1) + (3*x + 3)**(2 + 2*x)) == \ + 9*x*y + 9*x + _keep_coeff(S(3), x + 1)**_keep_coeff(S(2), x + 1) + 9 + assert factor_terms(9*(x + x*y + 1) + (3)**(2 + 2*x)) == \ + _keep_coeff(S(9), 3**(2*x) + x*y + x + 1) + assert factor_terms(3**(2 + 2*x) + a*3**(2 + 2*x)) == \ + 9*3**(2*x)*(a + 1) + assert factor_terms(x + x*A) == \ + x*(1 + A) + assert factor_terms(sin(x + x*A)) == \ + sin(x*(1 + A)) + assert factor_terms((3*x + 3)**((2 + 2*x)/3)) == \ + _keep_coeff(S(3), x + 1)**_keep_coeff(Rational(2, 3), x + 1) + assert factor_terms(x + (x*y + x)**(3*x + 3)) == \ + x + (x*(y + 1))**_keep_coeff(S(3), x + 1) + assert factor_terms(a*(x + x*y) + b*(x*2 + y*x*2)) == \ + x*(a + 2*b)*(y + 1) + i = Integral(x, (x, 0, oo)) + assert factor_terms(i) == i + + assert factor_terms(x/2 + y) == x/2 + y + # fraction doesn't apply to integer denominators + assert factor_terms(x/2 + y, fraction=True) == x/2 + y + # clear *does* apply to the integer denominators + assert factor_terms(x/2 + y, clear=True) == Mul(S.Half, x + 2*y, evaluate=False) + + # check radical extraction + eq = sqrt(2) + sqrt(10) + assert factor_terms(eq) == eq + assert factor_terms(eq, radical=True) == sqrt(2)*(1 + sqrt(5)) + eq = root(-6, 3) + root(6, 3) + assert factor_terms(eq, radical=True) == 6**(S.One/3)*(1 + (-1)**(S.One/3)) + + eq = [x + x*y] + ans = [x*(y + 1)] + for c in [list, tuple, set]: + assert factor_terms(c(eq)) == c(ans) + assert factor_terms(Tuple(x + x*y)) == Tuple(x*(y + 1)) + assert factor_terms(Interval(0, 1)) == Interval(0, 1) + e = 1/sqrt(a/2 + 1) + assert factor_terms(e, clear=False) == 1/sqrt(a/2 + 1) + assert factor_terms(e, clear=True) == sqrt(2)/sqrt(a + 2) + + eq = x/(x + 1/x) + 1/(x**2 + 1) + assert factor_terms(eq, fraction=False) == eq + assert factor_terms(eq, fraction=True) == 1 + + assert factor_terms((1/(x**3 + x**2) + 2/x**2)*y) == \ + y*(2 + 1/(x + 1))/x**2 + + # if not True, then processesing for this in factor_terms is not necessary + assert gcd_terms(-x - y) == -x - y + assert factor_terms(-x - y) == Mul(-1, x + y, evaluate=False) + + # if not True, then "special" processesing in factor_terms is not necessary + assert gcd_terms(exp(Mul(-1, x + 1))) == exp(-x - 1) + e = exp(-x - 2) + x + assert factor_terms(e) == exp(Mul(-1, x + 2, evaluate=False)) + x + assert factor_terms(e, sign=False) == e + assert factor_terms(exp(-4*x - 2) - x) == -x + exp(Mul(-2, 2*x + 1, evaluate=False)) + + # sum/integral tests + for F in (Sum, Integral): + assert factor_terms(F(x, (y, 1, 10))) == x * F(1, (y, 1, 10)) + assert factor_terms(F(x, (y, 1, 10)) + x) == x * (1 + F(1, (y, 1, 10))) + assert factor_terms(F(x*y + x*y**2, (y, 1, 10))) == x*F(y*(y + 1), (y, 1, 10)) + + # expressions involving Pow terms with base 0 + assert factor_terms(0**(x - 2) - 1) == 0**(x - 2) - 1 + assert factor_terms(0**(x + 2) - 1) == 0**(x + 2) - 1 + assert factor_terms((0**(x + 2) - 1).subs(x,-2)) == 0 + + +def test_xreplace(): + e = Mul(2, 1 + x, evaluate=False) + assert e.xreplace({}) == e + assert e.xreplace({y: x}) == e + + +def test_factor_nc(): + x, y = symbols('x,y') + k = symbols('k', integer=True) + n, m, o = symbols('n,m,o', commutative=False) + + # mul and multinomial expansion is needed + from sympy.core.function import _mexpand + e = x*(1 + y)**2 + assert _mexpand(e) == x + x*2*y + x*y**2 + + def factor_nc_test(e): + ex = _mexpand(e) + assert ex.is_Add + f = factor_nc(ex) + assert not f.is_Add and _mexpand(f) == ex + + factor_nc_test(x*(1 + y)) + factor_nc_test(n*(x + 1)) + factor_nc_test(n*(x + m)) + factor_nc_test((x + m)*n) + factor_nc_test(n*m*(x*o + n*o*m)*n) + s = Sum(x, (x, 1, 2)) + factor_nc_test(x*(1 + s)) + factor_nc_test(x*(1 + s)*s) + factor_nc_test(x*(1 + sin(s))) + factor_nc_test((1 + n)**2) + + factor_nc_test((x + n)*(x + m)*(x + y)) + factor_nc_test(x*(n*m + 1)) + factor_nc_test(x*(n*m + x)) + factor_nc_test(x*(x*n*m + 1)) + factor_nc_test(n*(m/x + o)) + factor_nc_test(m*(n + o/2)) + factor_nc_test(x*n*(x*m + 1)) + factor_nc_test(x*(m*n + x*n*m)) + factor_nc_test(n*(1 - m)*n**2) + + factor_nc_test((n + m)**2) + factor_nc_test((n - m)*(n + m)**2) + factor_nc_test((n + m)**2*(n - m)) + factor_nc_test((m - n)*(n + m)**2*(n - m)) + + assert factor_nc(n*(n + n*m)) == n**2*(1 + m) + assert factor_nc(m*(m*n + n*m*n**2)) == m*(m + n*m*n)*n + eq = m*sin(n) - sin(n)*m + assert factor_nc(eq) == eq + + # for coverage: + from sympy.physics.secondquant import Commutator + from sympy.polys.polytools import factor + eq = 1 + x*Commutator(m, n) + assert factor_nc(eq) == eq + eq = x*Commutator(m, n) + x*Commutator(m, o)*Commutator(m, n) + assert factor(eq) == x*(1 + Commutator(m, o))*Commutator(m, n) + + # issue 6534 + assert (2*n + 2*m).factor() == 2*(n + m) + + # issue 6701 + _n = symbols('nz', zero=False, commutative=False) + assert factor_nc(_n**k + _n**(k + 1)) == _n**k*(1 + _n) + assert factor_nc((m*n)**k + (m*n)**(k + 1)) == (1 + m*n)*(m*n)**k + + # issue 6918 + assert factor_nc(-n*(2*x**2 + 2*x)) == -2*n*x*(x + 1) + + +def test_issue_6360(): + a, b = symbols("a b") + apb = a + b + eq = apb + apb**2*(-2*a - 2*b) + assert factor_terms(sub_pre(eq)) == a + b - 2*(a + b)**3 + + +def test_issue_7903(): + a = symbols(r'a', real=True) + t = exp(I*cos(a)) + exp(-I*sin(a)) + assert t.simplify() + +def test_issue_8263(): + F, G = symbols('F, G', commutative=False, cls=Function) + x, y = symbols('x, y') + expr, dummies, _ = _mask_nc(F(x)*G(y) - G(y)*F(x)) + for v in dummies.values(): + assert not v.is_commutative + assert not expr.is_zero + +def test_monotonic_sign(): + F = _monotonic_sign + x = symbols('x') + assert F(x) is None + assert F(-x) is None + assert F(Dummy(prime=True)) == 2 + assert F(Dummy(prime=True, odd=True)) == 3 + assert F(Dummy(composite=True)) == 4 + assert F(Dummy(composite=True, odd=True)) == 9 + assert F(Dummy(positive=True, integer=True)) == 1 + assert F(Dummy(positive=True, even=True)) == 2 + assert F(Dummy(positive=True, even=True, prime=False)) == 4 + assert F(Dummy(negative=True, integer=True)) == -1 + assert F(Dummy(negative=True, even=True)) == -2 + assert F(Dummy(zero=True)) == 0 + assert F(Dummy(nonnegative=True)) == 0 + assert F(Dummy(nonpositive=True)) == 0 + + assert F(Dummy(positive=True) + 1).is_positive + assert F(Dummy(positive=True, integer=True) - 1).is_nonnegative + assert F(Dummy(positive=True) - 1) is None + assert F(Dummy(negative=True) + 1) is None + assert F(Dummy(negative=True, integer=True) - 1).is_nonpositive + assert F(Dummy(negative=True) - 1).is_negative + assert F(-Dummy(positive=True) + 1) is None + assert F(-Dummy(positive=True, integer=True) - 1).is_negative + assert F(-Dummy(positive=True) - 1).is_negative + assert F(-Dummy(negative=True) + 1).is_positive + assert F(-Dummy(negative=True, integer=True) - 1).is_nonnegative + assert F(-Dummy(negative=True) - 1) is None + x = Dummy(negative=True) + assert F(x**3).is_nonpositive + assert F(x**3 + log(2)*x - 1).is_negative + x = Dummy(positive=True) + assert F(-x**3).is_nonpositive + + p = Dummy(positive=True) + assert F(1/p).is_positive + assert F(p/(p + 1)).is_positive + p = Dummy(nonnegative=True) + assert F(p/(p + 1)).is_nonnegative + p = Dummy(positive=True) + assert F(-1/p).is_negative + p = Dummy(nonpositive=True) + assert F(p/(-p + 1)).is_nonpositive + + p = Dummy(positive=True, integer=True) + q = Dummy(positive=True, integer=True) + assert F(-2/p/q).is_negative + assert F(-2/(p - 1)/q) is None + + assert F((p - 1)*q + 1).is_positive + assert F(-(p - 1)*q - 1).is_negative + +def test_issue_17256(): + from sympy.sets.fancysets import Range + x = Symbol('x') + s1 = Sum(x + 1, (x, 1, 9)) + s2 = Sum(x + 1, (x, Range(1, 10))) + a = Symbol('a') + r1 = s1.xreplace({x:a}) + r2 = s2.xreplace({x:a}) + + assert r1.doit() == r2.doit() + s1 = Sum(x + 1, (x, 0, 9)) + s2 = Sum(x + 1, (x, Range(10))) + a = Symbol('a') + r1 = s1.xreplace({x:a}) + r2 = s2.xreplace({x:a}) + assert r1 == r2 + +def test_issue_21623(): + from sympy.matrices.expressions.matexpr import MatrixSymbol + M = MatrixSymbol('X', 2, 2) + assert gcd_terms(M[0,0], 1) == M[0,0] diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_facts.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_facts.py new file mode 100644 index 0000000000000000000000000000000000000000..7ca04877d0bdaf8124258ea1d25a10bcfa0f5f3a --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_facts.py @@ -0,0 +1,312 @@ +from sympy.core.facts import (deduce_alpha_implications, + apply_beta_to_alpha_route, rules_2prereq, FactRules, FactKB) +from sympy.core.logic import And, Not +from sympy.testing.pytest import raises + +T = True +F = False +U = None + + +def test_deduce_alpha_implications(): + def D(i): + I = deduce_alpha_implications(i) + P = rules_2prereq({ + (k, True): {(v, True) for v in S} for k, S in I.items()}) + return I, P + + # transitivity + I, P = D([('a', 'b'), ('b', 'c')]) + assert I == {'a': {'b', 'c'}, 'b': {'c'}, Not('b'): + {Not('a')}, Not('c'): {Not('a'), Not('b')}} + assert P == {'a': {'b', 'c'}, 'b': {'a', 'c'}, 'c': {'a', 'b'}} + + # Duplicate entry + I, P = D([('a', 'b'), ('b', 'c'), ('b', 'c')]) + assert I == {'a': {'b', 'c'}, 'b': {'c'}, Not('b'): {Not('a')}, Not('c'): {Not('a'), Not('b')}} + assert P == {'a': {'b', 'c'}, 'b': {'a', 'c'}, 'c': {'a', 'b'}} + + # see if it is tolerant to cycles + assert D([('a', 'a'), ('a', 'a')]) == ({}, {}) + assert D([('a', 'b'), ('b', 'a')]) == ( + {'a': {'b'}, 'b': {'a'}, Not('a'): {Not('b')}, Not('b'): {Not('a')}}, + {'a': {'b'}, 'b': {'a'}}) + + # see if it catches inconsistency + raises(ValueError, lambda: D([('a', Not('a'))])) + raises(ValueError, lambda: D([('a', 'b'), ('b', Not('a'))])) + raises(ValueError, lambda: D([('a', 'b'), ('b', 'c'), ('b', 'na'), + ('na', Not('a'))])) + + # see if it handles implications with negations + I, P = D([('a', Not('b')), ('c', 'b')]) + assert I == {'a': {Not('b'), Not('c')}, 'b': {Not('a')}, 'c': {'b', Not('a')}, Not('b'): {Not('c')}} + assert P == {'a': {'b', 'c'}, 'b': {'a', 'c'}, 'c': {'a', 'b'}} + I, P = D([(Not('a'), 'b'), ('a', 'c')]) + assert I == {'a': {'c'}, Not('a'): {'b'}, Not('b'): {'a', + 'c'}, Not('c'): {Not('a'), 'b'},} + assert P == {'a': {'b', 'c'}, 'b': {'a', 'c'}, 'c': {'a', 'b'}} + + + # Long deductions + I, P = D([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')]) + assert I == {'a': {'b', 'c', 'd', 'e'}, 'b': {'c', 'd', 'e'}, + 'c': {'d', 'e'}, 'd': {'e'}, Not('b'): {Not('a')}, + Not('c'): {Not('a'), Not('b')}, Not('d'): {Not('a'), Not('b'), + Not('c')}, Not('e'): {Not('a'), Not('b'), Not('c'), Not('d')}} + assert P == {'a': {'b', 'c', 'd', 'e'}, 'b': {'a', 'c', 'd', + 'e'}, 'c': {'a', 'b', 'd', 'e'}, 'd': {'a', 'b', 'c', 'e'}, + 'e': {'a', 'b', 'c', 'd'}} + + # something related to real-world + I, P = D([('rat', 'real'), ('int', 'rat')]) + + assert I == {'int': {'rat', 'real'}, 'rat': {'real'}, + Not('real'): {Not('rat'), Not('int')}, Not('rat'): {Not('int')}} + assert P == {'rat': {'int', 'real'}, 'real': {'int', 'rat'}, + 'int': {'rat', 'real'}} + + +# TODO move me to appropriate place +def test_apply_beta_to_alpha_route(): + APPLY = apply_beta_to_alpha_route + + # indicates empty alpha-chain with attached beta-rule #bidx + def Q(bidx): + return (set(), [bidx]) + + # x -> a &(a,b) -> x -- x -> a + A = {'x': {'a'}} + B = [(And('a', 'b'), 'x')] + assert APPLY(A, B) == {'x': ({'a'}, []), 'a': Q(0), 'b': Q(0)} + + # x -> a &(a,!x) -> b -- x -> a + A = {'x': {'a'}} + B = [(And('a', Not('x')), 'b')] + assert APPLY(A, B) == {'x': ({'a'}, []), Not('x'): Q(0), 'a': Q(0)} + + # x -> a b &(a,b) -> c -- x -> a b c + A = {'x': {'a', 'b'}} + B = [(And('a', 'b'), 'c')] + assert APPLY(A, B) == \ + {'x': ({'a', 'b', 'c'}, []), 'a': Q(0), 'b': Q(0)} + + # x -> a &(a,b) -> y -- x -> a [#0] + A = {'x': {'a'}} + B = [(And('a', 'b'), 'y')] + assert APPLY(A, B) == {'x': ({'a'}, [0]), 'a': Q(0), 'b': Q(0)} + + # x -> a b c &(a,b) -> c -- x -> a b c + A = {'x': {'a', 'b', 'c'}} + B = [(And('a', 'b'), 'c')] + assert APPLY(A, B) == \ + {'x': ({'a', 'b', 'c'}, []), 'a': Q(0), 'b': Q(0)} + + # x -> a b &(a,b,c) -> y -- x -> a b [#0] + A = {'x': {'a', 'b'}} + B = [(And('a', 'b', 'c'), 'y')] + assert APPLY(A, B) == \ + {'x': ({'a', 'b'}, [0]), 'a': Q(0), 'b': Q(0), 'c': Q(0)} + + # x -> a b &(a,b) -> c -- x -> a b c d + # c -> d c -> d + A = {'x': {'a', 'b'}, 'c': {'d'}} + B = [(And('a', 'b'), 'c')] + assert APPLY(A, B) == {'x': ({'a', 'b', 'c', 'd'}, []), + 'c': ({'d'}, []), 'a': Q(0), 'b': Q(0)} + + # x -> a b &(a,b) -> c -- x -> a b c d e + # c -> d &(c,d) -> e c -> d e + A = {'x': {'a', 'b'}, 'c': {'d'}} + B = [(And('a', 'b'), 'c'), (And('c', 'd'), 'e')] + assert APPLY(A, B) == {'x': ({'a', 'b', 'c', 'd', 'e'}, []), + 'c': ({'d', 'e'}, []), 'a': Q(0), 'b': Q(0), 'd': Q(1)} + + # x -> a b &(a,y) -> z -- x -> a b y z + # &(a,b) -> y + A = {'x': {'a', 'b'}} + B = [(And('a', 'y'), 'z'), (And('a', 'b'), 'y')] + assert APPLY(A, B) == {'x': ({'a', 'b', 'y', 'z'}, []), + 'a': (set(), [0, 1]), 'y': Q(0), 'b': Q(1)} + + # x -> a b &(a,!b) -> c -- x -> a b + A = {'x': {'a', 'b'}} + B = [(And('a', Not('b')), 'c')] + assert APPLY(A, B) == \ + {'x': ({'a', 'b'}, []), 'a': Q(0), Not('b'): Q(0)} + + # !x -> !a !b &(!a,b) -> c -- !x -> !a !b + A = {Not('x'): {Not('a'), Not('b')}} + B = [(And(Not('a'), 'b'), 'c')] + assert APPLY(A, B) == \ + {Not('x'): ({Not('a'), Not('b')}, []), Not('a'): Q(0), 'b': Q(0)} + + # x -> a b &(b,c) -> !a -- x -> a b + A = {'x': {'a', 'b'}} + B = [(And('b', 'c'), Not('a'))] + assert APPLY(A, B) == {'x': ({'a', 'b'}, []), 'b': Q(0), 'c': Q(0)} + + # x -> a b &(a, b) -> c -- x -> a b c p + # c -> p a + A = {'x': {'a', 'b'}, 'c': {'p', 'a'}} + B = [(And('a', 'b'), 'c')] + assert APPLY(A, B) == {'x': ({'a', 'b', 'c', 'p'}, []), + 'c': ({'p', 'a'}, []), 'a': Q(0), 'b': Q(0)} + + +def test_FactRules_parse(): + f = FactRules('a -> b') + assert f.prereq == {'b': {'a'}, 'a': {'b'}} + + f = FactRules('a -> !b') + assert f.prereq == {'b': {'a'}, 'a': {'b'}} + + f = FactRules('!a -> b') + assert f.prereq == {'b': {'a'}, 'a': {'b'}} + + f = FactRules('!a -> !b') + assert f.prereq == {'b': {'a'}, 'a': {'b'}} + + f = FactRules('!z == nz') + assert f.prereq == {'z': {'nz'}, 'nz': {'z'}} + + +def test_FactRules_parse2(): + raises(ValueError, lambda: FactRules('a -> !a')) + + +def test_FactRules_deduce(): + f = FactRules(['a -> b', 'b -> c', 'b -> d', 'c -> e']) + + def D(facts): + kb = FactKB(f) + kb.deduce_all_facts(facts) + return kb + + assert D({'a': T}) == {'a': T, 'b': T, 'c': T, 'd': T, 'e': T} + assert D({'b': T}) == { 'b': T, 'c': T, 'd': T, 'e': T} + assert D({'c': T}) == { 'c': T, 'e': T} + assert D({'d': T}) == { 'd': T } + assert D({'e': T}) == { 'e': T} + + assert D({'a': F}) == {'a': F } + assert D({'b': F}) == {'a': F, 'b': F } + assert D({'c': F}) == {'a': F, 'b': F, 'c': F } + assert D({'d': F}) == {'a': F, 'b': F, 'd': F } + + assert D({'a': U}) == {'a': U} # XXX ok? + + +def test_FactRules_deduce2(): + # pos/neg/zero, but the rules are not sufficient to derive all relations + f = FactRules(['pos -> !neg', 'pos -> !z']) + + def D(facts): + kb = FactKB(f) + kb.deduce_all_facts(facts) + return kb + + assert D({'pos': T}) == {'pos': T, 'neg': F, 'z': F} + assert D({'pos': F}) == {'pos': F } + assert D({'neg': T}) == {'pos': F, 'neg': T } + assert D({'neg': F}) == { 'neg': F } + assert D({'z': T}) == {'pos': F, 'z': T} + assert D({'z': F}) == { 'z': F} + + # pos/neg/zero. rules are sufficient to derive all relations + f = FactRules(['pos -> !neg', 'neg -> !pos', 'pos -> !z', 'neg -> !z']) + + assert D({'pos': T}) == {'pos': T, 'neg': F, 'z': F} + assert D({'pos': F}) == {'pos': F } + assert D({'neg': T}) == {'pos': F, 'neg': T, 'z': F} + assert D({'neg': F}) == { 'neg': F } + assert D({'z': T}) == {'pos': F, 'neg': F, 'z': T} + assert D({'z': F}) == { 'z': F} + + +def test_FactRules_deduce_multiple(): + # deduction that involves _several_ starting points + f = FactRules(['real == pos | npos']) + + def D(facts): + kb = FactKB(f) + kb.deduce_all_facts(facts) + return kb + + assert D({'real': T}) == {'real': T} + assert D({'real': F}) == {'real': F, 'pos': F, 'npos': F} + assert D({'pos': T}) == {'real': T, 'pos': T} + assert D({'npos': T}) == {'real': T, 'npos': T} + + # --- key tests below --- + assert D({'pos': F, 'npos': F}) == {'real': F, 'pos': F, 'npos': F} + assert D({'real': T, 'pos': F}) == {'real': T, 'pos': F, 'npos': T} + assert D({'real': T, 'npos': F}) == {'real': T, 'pos': T, 'npos': F} + + assert D({'pos': T, 'npos': F}) == {'real': T, 'pos': T, 'npos': F} + assert D({'pos': F, 'npos': T}) == {'real': T, 'pos': F, 'npos': T} + + +def test_FactRules_deduce_multiple2(): + f = FactRules(['real == neg | zero | pos']) + + def D(facts): + kb = FactKB(f) + kb.deduce_all_facts(facts) + return kb + + assert D({'real': T}) == {'real': T} + assert D({'real': F}) == {'real': F, 'neg': F, 'zero': F, 'pos': F} + assert D({'neg': T}) == {'real': T, 'neg': T} + assert D({'zero': T}) == {'real': T, 'zero': T} + assert D({'pos': T}) == {'real': T, 'pos': T} + + # --- key tests below --- + assert D({'neg': F, 'zero': F, 'pos': F}) == {'real': F, 'neg': F, + 'zero': F, 'pos': F} + assert D({'real': T, 'neg': F}) == {'real': T, 'neg': F} + assert D({'real': T, 'zero': F}) == {'real': T, 'zero': F} + assert D({'real': T, 'pos': F}) == {'real': T, 'pos': F} + + assert D({'real': T, 'zero': F, 'pos': F}) == {'real': T, + 'neg': T, 'zero': F, 'pos': F} + assert D({'real': T, 'neg': F, 'pos': F}) == {'real': T, + 'neg': F, 'zero': T, 'pos': F} + assert D({'real': T, 'neg': F, 'zero': F }) == {'real': T, + 'neg': F, 'zero': F, 'pos': T} + + assert D({'neg': T, 'zero': F, 'pos': F}) == {'real': T, 'neg': T, + 'zero': F, 'pos': F} + assert D({'neg': F, 'zero': T, 'pos': F}) == {'real': T, 'neg': F, + 'zero': T, 'pos': F} + assert D({'neg': F, 'zero': F, 'pos': T}) == {'real': T, 'neg': F, + 'zero': F, 'pos': T} + + +def test_FactRules_deduce_base(): + # deduction that starts from base + + f = FactRules(['real == neg | zero | pos', + 'neg -> real & !zero & !pos', + 'pos -> real & !zero & !neg']) + base = FactKB(f) + + base.deduce_all_facts({'real': T, 'neg': F}) + assert base == {'real': T, 'neg': F} + + base.deduce_all_facts({'zero': F}) + assert base == {'real': T, 'neg': F, 'zero': F, 'pos': T} + + +def test_FactRules_deduce_staticext(): + # verify that static beta-extensions deduction takes place + f = FactRules(['real == neg | zero | pos', + 'neg -> real & !zero & !pos', + 'pos -> real & !zero & !neg', + 'nneg == real & !neg', + 'npos == real & !pos']) + + assert ('npos', True) in f.full_implications[('neg', True)] + assert ('nneg', True) in f.full_implications[('pos', True)] + assert ('nneg', True) in f.full_implications[('zero', True)] + assert ('npos', True) in f.full_implications[('zero', True)] diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_function.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_function.py new file mode 100644 index 0000000000000000000000000000000000000000..7cc5df95f2399a96329f1111d3ef2cc9aa1342f8 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_function.py @@ -0,0 +1,1455 @@ +from sympy.concrete.summations import Sum +from sympy.core.basic import Basic, _aresame +from sympy.core.cache import clear_cache +from sympy.core.containers import Dict, Tuple +from sympy.core.expr import Expr, unchanged +from sympy.core.function import (Subs, Function, diff, Lambda, expand, + nfloat, Derivative) +from sympy.core.numbers import E, Float, zoo, Rational, pi, I, oo, nan +from sympy.core.power import Pow +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import symbols, Dummy, Symbol +from sympy.functions.elementary.complexes import im, re +from sympy.functions.elementary.exponential import log, exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import sin, cos, acos +from sympy.functions.special.error_functions import expint +from sympy.functions.special.gamma_functions import loggamma, polygamma +from sympy.matrices.dense import Matrix +from sympy.printing.str import sstr +from sympy.series.order import O +from sympy.tensor.indexed import Indexed +from sympy.core.function import (PoleError, _mexpand, arity, + BadSignatureError, BadArgumentsError) +from sympy.core.parameters import _exp_is_pow +from sympy.core.sympify import sympify, SympifyError +from sympy.matrices import MutableMatrix, ImmutableMatrix +from sympy.sets.sets import FiniteSet +from sympy.solvers.solveset import solveset +from sympy.tensor.array import NDimArray +from sympy.utilities.iterables import subsets, variations +from sympy.testing.pytest import XFAIL, raises, warns_deprecated_sympy, _both_exp_pow + +from sympy.abc import t, w, x, y, z +f, g, h = symbols('f g h', cls=Function) +_xi_1, _xi_2, _xi_3 = [Dummy() for i in range(3)] + +def test_f_expand_complex(): + x = Symbol('x', real=True) + + assert f(x).expand(complex=True) == I*im(f(x)) + re(f(x)) + assert exp(x).expand(complex=True) == exp(x) + assert exp(I*x).expand(complex=True) == cos(x) + I*sin(x) + assert exp(z).expand(complex=True) == cos(im(z))*exp(re(z)) + \ + I*sin(im(z))*exp(re(z)) + + +def test_bug1(): + e = sqrt(-log(w)) + assert e.subs(log(w), -x) == sqrt(x) + + e = sqrt(-5*log(w)) + assert e.subs(log(w), -x) == sqrt(5*x) + + +def test_general_function(): + nu = Function('nu') + + e = nu(x) + edx = e.diff(x) + edy = e.diff(y) + edxdx = e.diff(x).diff(x) + edxdy = e.diff(x).diff(y) + assert e == nu(x) + assert edx != nu(x) + assert edx == diff(nu(x), x) + assert edy == 0 + assert edxdx == diff(diff(nu(x), x), x) + assert edxdy == 0 + +def test_general_function_nullary(): + nu = Function('nu') + + e = nu() + edx = e.diff(x) + edxdx = e.diff(x).diff(x) + assert e == nu() + assert edx != nu() + assert edx == 0 + assert edxdx == 0 + + +def test_derivative_subs_bug(): + e = diff(g(x), x) + assert e.subs(g(x), f(x)) != e + assert e.subs(g(x), f(x)) == Derivative(f(x), x) + assert e.subs(g(x), -f(x)) == Derivative(-f(x), x) + + assert e.subs(x, y) == Derivative(g(y), y) + + +def test_derivative_subs_self_bug(): + d = diff(f(x), x) + + assert d.subs(d, y) == y + + +def test_derivative_linearity(): + assert diff(-f(x), x) == -diff(f(x), x) + assert diff(8*f(x), x) == 8*diff(f(x), x) + assert diff(8*f(x), x) != 7*diff(f(x), x) + assert diff(8*f(x)*x, x) == 8*f(x) + 8*x*diff(f(x), x) + assert diff(8*f(x)*y*x, x).expand() == 8*y*f(x) + 8*y*x*diff(f(x), x) + + +def test_derivative_evaluate(): + assert Derivative(sin(x), x) != diff(sin(x), x) + assert Derivative(sin(x), x).doit() == diff(sin(x), x) + + assert Derivative(Derivative(f(x), x), x) == diff(f(x), x, x) + assert Derivative(sin(x), x, 0) == sin(x) + assert Derivative(sin(x), (x, y), (x, -y)) == sin(x) + + +def test_diff_symbols(): + assert diff(f(x, y, z), x, y, z) == Derivative(f(x, y, z), x, y, z) + assert diff(f(x, y, z), x, x, x) == Derivative(f(x, y, z), x, x, x) == Derivative(f(x, y, z), (x, 3)) + assert diff(f(x, y, z), x, 3) == Derivative(f(x, y, z), x, 3) + + # issue 5028 + assert [diff(-z + x/y, sym) for sym in (z, x, y)] == [-1, 1/y, -x/y**2] + assert diff(f(x, y, z), x, y, z, 2) == Derivative(f(x, y, z), x, y, z, z) + assert diff(f(x, y, z), x, y, z, 2, evaluate=False) == \ + Derivative(f(x, y, z), x, y, z, z) + assert Derivative(f(x, y, z), x, y, z)._eval_derivative(z) == \ + Derivative(f(x, y, z), x, y, z, z) + assert Derivative(Derivative(f(x, y, z), x), y)._eval_derivative(z) == \ + Derivative(f(x, y, z), x, y, z) + + raises(TypeError, lambda: cos(x).diff((x, y)).variables) + assert cos(x).diff((x, y))._wrt_variables == [x] + + # issue 23222 + assert sympify("a*x+b").diff("x") == sympify("a") + +def test_Function(): + class myfunc(Function): + @classmethod + def eval(cls): # zero args + return + + assert myfunc.nargs == FiniteSet(0) + assert myfunc().nargs == FiniteSet(0) + raises(TypeError, lambda: myfunc(x).nargs) + + class myfunc(Function): + @classmethod + def eval(cls, x): # one arg + return + + assert myfunc.nargs == FiniteSet(1) + assert myfunc(x).nargs == FiniteSet(1) + raises(TypeError, lambda: myfunc(x, y).nargs) + + class myfunc(Function): + @classmethod + def eval(cls, *x): # star args + return + + assert myfunc.nargs == S.Naturals0 + assert myfunc(x).nargs == S.Naturals0 + + +def test_nargs(): + f = Function('f') + assert f.nargs == S.Naturals0 + assert f(1).nargs == S.Naturals0 + assert Function('f', nargs=2)(1, 2).nargs == FiniteSet(2) + assert sin.nargs == FiniteSet(1) + assert sin(2).nargs == FiniteSet(1) + assert log.nargs == FiniteSet(1, 2) + assert log(2).nargs == FiniteSet(1, 2) + assert Function('f', nargs=2).nargs == FiniteSet(2) + assert Function('f', nargs=0).nargs == FiniteSet(0) + assert Function('f', nargs=(0, 1)).nargs == FiniteSet(0, 1) + assert Function('f', nargs=None).nargs == S.Naturals0 + raises(ValueError, lambda: Function('f', nargs=())) + +def test_nargs_inheritance(): + class f1(Function): + nargs = 2 + class f2(f1): + pass + class f3(f2): + pass + class f4(f3): + nargs = 1,2 + class f5(f4): + pass + class f6(f5): + pass + class f7(f6): + nargs=None + class f8(f7): + pass + class f9(f8): + pass + class f10(f9): + nargs = 1 + class f11(f10): + pass + assert f1.nargs == FiniteSet(2) + assert f2.nargs == FiniteSet(2) + assert f3.nargs == FiniteSet(2) + assert f4.nargs == FiniteSet(1, 2) + assert f5.nargs == FiniteSet(1, 2) + assert f6.nargs == FiniteSet(1, 2) + assert f7.nargs == S.Naturals0 + assert f8.nargs == S.Naturals0 + assert f9.nargs == S.Naturals0 + assert f10.nargs == FiniteSet(1) + assert f11.nargs == FiniteSet(1) + +def test_arity(): + f = lambda x, y: 1 + assert arity(f) == 2 + def f(x, y, z=None): + pass + assert arity(f) == (2, 3) + assert arity(lambda *x: x) is None + assert arity(log) == (1, 2) + + +def test_Lambda(): + e = Lambda(x, x**2) + assert e(4) == 16 + assert e(x) == x**2 + assert e(y) == y**2 + + assert Lambda((), 42)() == 42 + assert unchanged(Lambda, (), 42) + assert Lambda((), 42) != Lambda((), 43) + assert Lambda((), f(x))() == f(x) + assert Lambda((), 42).nargs == FiniteSet(0) + + assert unchanged(Lambda, (x,), x**2) + assert Lambda(x, x**2) == Lambda((x,), x**2) + assert Lambda(x, x**2) != Lambda(x, x**2 + 1) + assert Lambda((x, y), x**y) != Lambda((y, x), y**x) + assert Lambda((x, y), x**y) != Lambda((x, y), y**x) + + assert Lambda((x, y), x**y)(x, y) == x**y + assert Lambda((x, y), x**y)(3, 3) == 3**3 + assert Lambda((x, y), x**y)(x, 3) == x**3 + assert Lambda((x, y), x**y)(3, y) == 3**y + assert Lambda(x, f(x))(x) == f(x) + assert Lambda(x, x**2)(e(x)) == x**4 + assert e(e(x)) == x**4 + + x1, x2 = (Indexed('x', i) for i in (1, 2)) + assert Lambda((x1, x2), x1 + x2)(x, y) == x + y + + assert Lambda((x, y), x + y).nargs == FiniteSet(2) + + p = x, y, z, t + assert Lambda(p, t*(x + y + z))(*p) == t * (x + y + z) + + eq = Lambda(x, 2*x) + Lambda(y, 2*y) + assert eq != 2*Lambda(x, 2*x) + assert eq.as_dummy() == 2*Lambda(x, 2*x).as_dummy() + assert Lambda(x, 2*x) not in [ Lambda(x, x) ] + raises(BadSignatureError, lambda: Lambda(1, x)) + assert Lambda(x, 1)(1) is S.One + + raises(BadSignatureError, lambda: Lambda((x, x), x + 2)) + raises(BadSignatureError, lambda: Lambda(((x, x), y), x)) + raises(BadSignatureError, lambda: Lambda(((y, x), x), x)) + raises(BadSignatureError, lambda: Lambda(((y, 1), 2), x)) + + with warns_deprecated_sympy(): + assert Lambda([x, y], x+y) == Lambda((x, y), x+y) + + flam = Lambda(((x, y),), x + y) + assert flam((2, 3)) == 5 + flam = Lambda(((x, y), z), x + y + z) + assert flam((2, 3), 1) == 6 + flam = Lambda((((x, y), z),), x + y + z) + assert flam(((2, 3), 1)) == 6 + raises(BadArgumentsError, lambda: flam(1, 2, 3)) + flam = Lambda( (x,), (x, x)) + assert flam(1,) == (1, 1) + assert flam((1,)) == ((1,), (1,)) + flam = Lambda( ((x,),), (x, x)) + raises(BadArgumentsError, lambda: flam(1)) + assert flam((1,)) == (1, 1) + + # Previously TypeError was raised so this is potentially needed for + # backwards compatibility. + assert issubclass(BadSignatureError, TypeError) + assert issubclass(BadArgumentsError, TypeError) + + # These are tested to see they don't raise: + hash(Lambda(x, 2*x)) + hash(Lambda(x, x)) # IdentityFunction subclass + + +def test_IdentityFunction(): + assert Lambda(x, x) is Lambda(y, y) is S.IdentityFunction + assert Lambda(x, 2*x) is not S.IdentityFunction + assert Lambda((x, y), x) is not S.IdentityFunction + + +def test_Lambda_symbols(): + assert Lambda(x, 2*x).free_symbols == set() + assert Lambda(x, x*y).free_symbols == {y} + assert Lambda((), 42).free_symbols == set() + assert Lambda((), x*y).free_symbols == {x,y} + + +def test_functionclas_symbols(): + assert f.free_symbols == set() + + +def test_Lambda_arguments(): + raises(TypeError, lambda: Lambda(x, 2*x)(x, y)) + raises(TypeError, lambda: Lambda((x, y), x + y)(x)) + raises(TypeError, lambda: Lambda((), 42)(x)) + + +def test_Lambda_equality(): + assert Lambda((x, y), 2*x) == Lambda((x, y), 2*x) + # these, of course, should never be equal + assert Lambda(x, 2*x) != Lambda((x, y), 2*x) + assert Lambda(x, 2*x) != 2*x + # But it is tempting to want expressions that differ only + # in bound symbols to compare the same. But this is not what + # Python's `==` is intended to do; two objects that compare + # as equal means that they are indistibguishable and cache to the + # same value. We wouldn't want to expression that are + # mathematically the same but written in different variables to be + # interchanged else what is the point of allowing for different + # variable names? + assert Lambda(x, 2*x) != Lambda(y, 2*y) + + +def test_Subs(): + assert Subs(1, (), ()) is S.One + # check null subs influence on hashing + assert Subs(x, y, z) != Subs(x, y, 1) + # neutral subs works + assert Subs(x, x, 1).subs(x, y).has(y) + # self mapping var/point + assert Subs(Derivative(f(x), (x, 2)), x, x).doit() == f(x).diff(x, x) + assert Subs(x, x, 0).has(x) # it's a structural answer + assert not Subs(x, x, 0).free_symbols + assert Subs(Subs(x + y, x, 2), y, 1) == Subs(x + y, (x, y), (2, 1)) + assert Subs(x, (x,), (0,)) == Subs(x, x, 0) + assert Subs(x, x, 0) == Subs(y, y, 0) + assert Subs(x, x, 0).subs(x, 1) == Subs(x, x, 0) + assert Subs(y, x, 0).subs(y, 1) == Subs(1, x, 0) + assert Subs(f(x), x, 0).doit() == f(0) + assert Subs(f(x**2), x**2, 0).doit() == f(0) + assert Subs(f(x, y, z), (x, y, z), (0, 1, 1)) != \ + Subs(f(x, y, z), (x, y, z), (0, 0, 1)) + assert Subs(x, y, 2).subs(x, y).doit() == 2 + assert Subs(f(x, y), (x, y, z), (0, 1, 1)) != \ + Subs(f(x, y) + z, (x, y, z), (0, 1, 0)) + assert Subs(f(x, y), (x, y), (0, 1)).doit() == f(0, 1) + assert Subs(Subs(f(x, y), x, 0), y, 1).doit() == f(0, 1) + raises(ValueError, lambda: Subs(f(x, y), (x, y), (0, 0, 1))) + raises(ValueError, lambda: Subs(f(x, y), (x, x, y), (0, 0, 1))) + + assert len(Subs(f(x, y), (x, y), (0, 1)).variables) == 2 + assert Subs(f(x, y), (x, y), (0, 1)).point == Tuple(0, 1) + + assert Subs(f(x), x, 0) == Subs(f(y), y, 0) + assert Subs(f(x, y), (x, y), (0, 1)) == Subs(f(x, y), (y, x), (1, 0)) + assert Subs(f(x)*y, (x, y), (0, 1)) == Subs(f(y)*x, (y, x), (0, 1)) + assert Subs(f(x)*y, (x, y), (1, 1)) == Subs(f(y)*x, (x, y), (1, 1)) + + assert Subs(f(x), x, 0).subs(x, 1).doit() == f(0) + assert Subs(f(x), x, y).subs(y, 0) == Subs(f(x), x, 0) + assert Subs(y*f(x), x, y).subs(y, 2) == Subs(2*f(x), x, 2) + assert (2 * Subs(f(x), x, 0)).subs(Subs(f(x), x, 0), y) == 2*y + + assert Subs(f(x), x, 0).free_symbols == set() + assert Subs(f(x, y), x, z).free_symbols == {y, z} + + assert Subs(f(x).diff(x), x, 0).doit(), Subs(f(x).diff(x), x, 0) + assert Subs(1 + f(x).diff(x), x, 0).doit(), 1 + Subs(f(x).diff(x), x, 0) + assert Subs(y*f(x, y).diff(x), (x, y), (0, 2)).doit() == \ + 2*Subs(Derivative(f(x, 2), x), x, 0) + assert Subs(y**2*f(x), x, 0).diff(y) == 2*y*f(0) + + e = Subs(y**2*f(x), x, y) + assert e.diff(y) == e.doit().diff(y) == y**2*Derivative(f(y), y) + 2*y*f(y) + + assert Subs(f(x), x, 0) + Subs(f(x), x, 0) == 2*Subs(f(x), x, 0) + e1 = Subs(z*f(x), x, 1) + e2 = Subs(z*f(y), y, 1) + assert e1 + e2 == 2*e1 + assert e1.__hash__() == e2.__hash__() + assert Subs(z*f(x + 1), x, 1) not in [ e1, e2 ] + assert Derivative(f(x), x).subs(x, g(x)) == Derivative(f(g(x)), g(x)) + assert Derivative(f(x), x).subs(x, x + y) == Subs(Derivative(f(x), x), + x, x + y) + assert Subs(f(x)*cos(y) + z, (x, y), (0, pi/3)).n(2) == \ + Subs(f(x)*cos(y) + z, (x, y), (0, pi/3)).evalf(2) == \ + z + Rational('1/2').n(2)*f(0) + + assert f(x).diff(x).subs(x, 0).subs(x, y) == f(x).diff(x).subs(x, 0) + assert (x*f(x).diff(x).subs(x, 0)).subs(x, y) == y*f(x).diff(x).subs(x, 0) + assert Subs(Derivative(g(x)**2, g(x), x), g(x), exp(x) + ).doit() == 2*exp(x) + assert Subs(Derivative(g(x)**2, g(x), x), g(x), exp(x) + ).doit(deep=False) == 2*Derivative(exp(x), x) + assert Derivative(f(x, g(x)), x).doit() == Derivative( + f(x, g(x)), g(x))*Derivative(g(x), x) + Subs(Derivative( + f(y, g(x)), y), y, x) + +def test_doitdoit(): + done = Derivative(f(x, g(x)), x, g(x)).doit() + assert done == done.doit() + + +@XFAIL +def test_Subs2(): + # this reflects a limitation of subs(), probably won't fix + assert Subs(f(x), x**2, x).doit() == f(sqrt(x)) + + +def test_expand_function(): + assert expand(x + y) == x + y + assert expand(x + y, complex=True) == I*im(x) + I*im(y) + re(x) + re(y) + assert expand((x + y)**11, modulus=11) == x**11 + y**11 + + +def test_function_comparable(): + assert sin(x).is_comparable is False + assert cos(x).is_comparable is False + + assert sin(Float('0.1')).is_comparable is True + assert cos(Float('0.1')).is_comparable is True + + assert sin(E).is_comparable is True + assert cos(E).is_comparable is True + + assert sin(Rational(1, 3)).is_comparable is True + assert cos(Rational(1, 3)).is_comparable is True + + +def test_function_comparable_infinities(): + assert sin(oo).is_comparable is False + assert sin(-oo).is_comparable is False + assert sin(zoo).is_comparable is False + assert sin(nan).is_comparable is False + + +def test_deriv1(): + # These all require derivatives evaluated at a point (issue 4719) to work. + # See issue 4624 + assert f(2*x).diff(x) == 2*Subs(Derivative(f(x), x), x, 2*x) + assert (f(x)**3).diff(x) == 3*f(x)**2*f(x).diff(x) + assert (f(2*x)**3).diff(x) == 6*f(2*x)**2*Subs( + Derivative(f(x), x), x, 2*x) + + assert f(2 + x).diff(x) == Subs(Derivative(f(x), x), x, x + 2) + assert f(2 + 3*x).diff(x) == 3*Subs( + Derivative(f(x), x), x, 3*x + 2) + assert f(3*sin(x)).diff(x) == 3*cos(x)*Subs( + Derivative(f(x), x), x, 3*sin(x)) + + # See issue 8510 + assert f(x, x + z).diff(x) == ( + Subs(Derivative(f(y, x + z), y), y, x) + + Subs(Derivative(f(x, y), y), y, x + z)) + assert f(x, x**2).diff(x) == ( + 2*x*Subs(Derivative(f(x, y), y), y, x**2) + + Subs(Derivative(f(y, x**2), y), y, x)) + # but Subs is not always necessary + assert f(x, g(y)).diff(g(y)) == Derivative(f(x, g(y)), g(y)) + + +def test_deriv2(): + assert (x**3).diff(x) == 3*x**2 + assert (x**3).diff(x, evaluate=False) != 3*x**2 + assert (x**3).diff(x, evaluate=False) == Derivative(x**3, x) + + assert diff(x**3, x) == 3*x**2 + assert diff(x**3, x, evaluate=False) != 3*x**2 + assert diff(x**3, x, evaluate=False) == Derivative(x**3, x) + + +def test_func_deriv(): + assert f(x).diff(x) == Derivative(f(x), x) + # issue 4534 + assert f(x, y).diff(x, y) - f(x, y).diff(y, x) == 0 + assert Derivative(f(x, y), x, y).args[1:] == ((x, 1), (y, 1)) + assert Derivative(f(x, y), y, x).args[1:] == ((y, 1), (x, 1)) + assert (Derivative(f(x, y), x, y) - Derivative(f(x, y), y, x)).doit() == 0 + + +def test_suppressed_evaluation(): + a = sin(0, evaluate=False) + assert a != 0 + assert a.func is sin + assert a.args == (0,) + + +def test_function_evalf(): + def eq(a, b, eps): + return abs(a - b) < eps + assert eq(sin(1).evalf(15), Float("0.841470984807897"), 1e-13) + assert eq( + sin(2).evalf(25), Float("0.9092974268256816953960199", 25), 1e-23) + assert eq(sin(1 + I).evalf( + 15), Float("1.29845758141598") + Float("0.634963914784736")*I, 1e-13) + assert eq(exp(1 + I).evalf(15), Float( + "1.46869393991588") + Float("2.28735528717884239")*I, 1e-13) + assert eq(exp(-0.5 + 1.5*I).evalf(15), Float( + "0.0429042815937374") + Float("0.605011292285002")*I, 1e-13) + assert eq(log(pi + sqrt(2)*I).evalf( + 15), Float("1.23699044022052") + Float("0.422985442737893")*I, 1e-13) + assert eq(cos(100).evalf(15), Float("0.86231887228768"), 1e-13) + + +def test_extensibility_eval(): + class MyFunc(Function): + @classmethod + def eval(cls, *args): + return (0, 0, 0) + assert MyFunc(0) == (0, 0, 0) + + +@_both_exp_pow +def test_function_non_commutative(): + x = Symbol('x', commutative=False) + assert f(x).is_commutative is False + assert sin(x).is_commutative is False + assert exp(x).is_commutative is False + assert log(x).is_commutative is False + assert f(x).is_complex is False + assert sin(x).is_complex is False + assert exp(x).is_complex is False + assert log(x).is_complex is False + + +def test_function_complex(): + x = Symbol('x', complex=True) + xzf = Symbol('x', complex=True, zero=False) + assert f(x).is_commutative is True + assert sin(x).is_commutative is True + assert exp(x).is_commutative is True + assert log(x).is_commutative is True + assert f(x).is_complex is None + assert sin(x).is_complex is True + assert exp(x).is_complex is True + assert log(x).is_complex is None + assert log(xzf).is_complex is True + + +def test_function__eval_nseries(): + n = Symbol('n') + + assert sin(x)._eval_nseries(x, 2, None) == x + O(x**2) + assert sin(x + 1)._eval_nseries(x, 2, None) == x*cos(1) + sin(1) + O(x**2) + assert sin(pi*(1 - x))._eval_nseries(x, 2, None) == pi*x + O(x**2) + assert acos(1 - x**2)._eval_nseries(x, 2, None) == sqrt(2)*sqrt(x**2) + O(x**2) + assert polygamma(n, x + 1)._eval_nseries(x, 2, None) == \ + polygamma(n, 1) + polygamma(n + 1, 1)*x + O(x**2) + raises(PoleError, lambda: sin(1/x)._eval_nseries(x, 2, None)) + assert acos(1 - x)._eval_nseries(x, 2, None) == sqrt(2)*sqrt(x) + sqrt(2)*x**(S(3)/2)/12 + O(x**2) + assert acos(1 + x)._eval_nseries(x, 2, None) == sqrt(2)*sqrt(-x) + sqrt(2)*(-x)**(S(3)/2)/12 + O(x**2) + assert loggamma(1/x)._eval_nseries(x, 0, None) == \ + log(x)/2 - log(x)/x - 1/x + O(1, x) + assert loggamma(log(1/x)).nseries(x, n=1, logx=y) == loggamma(-y) + + # issue 6725: + assert expint(Rational(3, 2), -x)._eval_nseries(x, 5, None) == \ + 2 - 2*sqrt(pi)*sqrt(-x) - 2*x + x**2 + x**3/3 + x**4/12 + 4*I*x**(S(3)/2)*sqrt(-x)/3 + \ + 2*I*x**(S(5)/2)*sqrt(-x)/5 + 2*I*x**(S(7)/2)*sqrt(-x)/21 + O(x**5) + assert sin(sqrt(x))._eval_nseries(x, 3, None) == \ + sqrt(x) - x**Rational(3, 2)/6 + x**Rational(5, 2)/120 + O(x**3) + + # issue 19065: + s1 = f(x,y).series(y, n=2) + assert {i.name for i in s1.atoms(Symbol)} == {'x', 'xi', 'y'} + xi = Symbol('xi') + s2 = f(xi, y).series(y, n=2) + assert {i.name for i in s2.atoms(Symbol)} == {'xi', 'xi0', 'y'} + +def test_doit(): + n = Symbol('n', integer=True) + f = Sum(2 * n * x, (n, 1, 3)) + d = Derivative(f, x) + assert d.doit() == 12 + assert d.doit(deep=False) == Sum(2*n, (n, 1, 3)) + + +def test_evalf_default(): + from sympy.functions.special.gamma_functions import polygamma + assert type(sin(4.0)) == Float + assert type(re(sin(I + 1.0))) == Float + assert type(im(sin(I + 1.0))) == Float + assert type(sin(4)) == sin + assert type(polygamma(2.0, 4.0)) == Float + assert type(sin(Rational(1, 4))) == sin + + +def test_issue_5399(): + args = [x, y, S(2), S.Half] + + def ok(a): + """Return True if the input args for diff are ok""" + if not a: + return False + if a[0].is_Symbol is False: + return False + s_at = [i for i in range(len(a)) if a[i].is_Symbol] + n_at = [i for i in range(len(a)) if not a[i].is_Symbol] + # every symbol is followed by symbol or int + # every number is followed by a symbol + return (all(a[i + 1].is_Symbol or a[i + 1].is_Integer + for i in s_at if i + 1 < len(a)) and + all(a[i + 1].is_Symbol + for i in n_at if i + 1 < len(a))) + eq = x**10*y**8 + for a in subsets(args): + for v in variations(a, len(a)): + if ok(v): + eq.diff(*v) # does not raise + else: + raises(ValueError, lambda: eq.diff(*v)) + + +def test_derivative_numerically(): + z0 = x._random() + assert abs(Derivative(sin(x), x).doit_numerically(z0) - cos(z0)) < 1e-15 + + +def test_fdiff_argument_index_error(): + from sympy.core.function import ArgumentIndexError + + class myfunc(Function): + nargs = 1 # define since there is no eval routine + + def fdiff(self, idx): + raise ArgumentIndexError + mf = myfunc(x) + assert mf.diff(x) == Derivative(mf, x) + raises(TypeError, lambda: myfunc(x, x)) + + +def test_deriv_wrt_function(): + x = f(t) + xd = diff(x, t) + xdd = diff(xd, t) + y = g(t) + yd = diff(y, t) + + assert diff(x, t) == xd + assert diff(2 * x + 4, t) == 2 * xd + assert diff(2 * x + 4 + y, t) == 2 * xd + yd + assert diff(2 * x + 4 + y * x, t) == 2 * xd + x * yd + xd * y + assert diff(2 * x + 4 + y * x, x) == 2 + y + assert (diff(4 * x**2 + 3 * x + x * y, t) == 3 * xd + x * yd + xd * y + + 8 * x * xd) + assert (diff(4 * x**2 + 3 * xd + x * y, t) == 3 * xdd + x * yd + xd * y + + 8 * x * xd) + assert diff(4 * x**2 + 3 * xd + x * y, xd) == 3 + assert diff(4 * x**2 + 3 * xd + x * y, xdd) == 0 + assert diff(sin(x), t) == xd * cos(x) + assert diff(exp(x), t) == xd * exp(x) + assert diff(sqrt(x), t) == xd / (2 * sqrt(x)) + + +def test_diff_wrt_value(): + assert Expr()._diff_wrt is False + assert x._diff_wrt is True + assert f(x)._diff_wrt is True + assert Derivative(f(x), x)._diff_wrt is True + assert Derivative(x**2, x)._diff_wrt is False + + +def test_diff_wrt(): + fx = f(x) + dfx = diff(f(x), x) + ddfx = diff(f(x), x, x) + + assert diff(sin(fx) + fx**2, fx) == cos(fx) + 2*fx + assert diff(sin(dfx) + dfx**2, dfx) == cos(dfx) + 2*dfx + assert diff(sin(ddfx) + ddfx**2, ddfx) == cos(ddfx) + 2*ddfx + assert diff(fx**2, dfx) == 0 + assert diff(fx**2, ddfx) == 0 + assert diff(dfx**2, fx) == 0 + assert diff(dfx**2, ddfx) == 0 + assert diff(ddfx**2, dfx) == 0 + + assert diff(fx*dfx*ddfx, fx) == dfx*ddfx + assert diff(fx*dfx*ddfx, dfx) == fx*ddfx + assert diff(fx*dfx*ddfx, ddfx) == fx*dfx + + assert diff(f(x), x).diff(f(x)) == 0 + assert (sin(f(x)) - cos(diff(f(x), x))).diff(f(x)) == cos(f(x)) + + assert diff(sin(fx), fx, x) == diff(sin(fx), x, fx) + + # Chain rule cases + assert f(g(x)).diff(x) == \ + Derivative(g(x), x)*Derivative(f(g(x)), g(x)) + assert diff(f(g(x), h(y)), x) == \ + Derivative(g(x), x)*Derivative(f(g(x), h(y)), g(x)) + assert diff(f(g(x), h(x)), x) == ( + Derivative(f(g(x), h(x)), g(x))*Derivative(g(x), x) + + Derivative(f(g(x), h(x)), h(x))*Derivative(h(x), x)) + assert f( + sin(x)).diff(x) == cos(x)*Subs(Derivative(f(x), x), x, sin(x)) + + assert diff(f(g(x)), g(x)) == Derivative(f(g(x)), g(x)) + + +def test_diff_wrt_func_subs(): + assert f(g(x)).diff(x).subs(g, Lambda(x, 2*x)).doit() == f(2*x).diff(x) + + +def test_subs_in_derivative(): + expr = sin(x*exp(y)) + u = Function('u') + v = Function('v') + assert Derivative(expr, y).subs(expr, y) == Derivative(y, y) + assert Derivative(expr, y).subs(y, x).doit() == \ + Derivative(expr, y).doit().subs(y, x) + assert Derivative(f(x, y), y).subs(y, x) == Subs(Derivative(f(x, y), y), y, x) + assert Derivative(f(x, y), y).subs(x, y) == Subs(Derivative(f(x, y), y), x, y) + assert Derivative(f(x, y), y).subs(y, g(x, y)) == Subs(Derivative(f(x, y), y), y, g(x, y)).doit() + assert Derivative(f(x, y), y).subs(x, g(x, y)) == Subs(Derivative(f(x, y), y), x, g(x, y)) + assert Derivative(f(x, y), g(y)).subs(x, g(x, y)) == Derivative(f(g(x, y), y), g(y)) + assert Derivative(f(u(x), h(y)), h(y)).subs(h(y), g(x, y)) == \ + Subs(Derivative(f(u(x), h(y)), h(y)), h(y), g(x, y)).doit() + assert Derivative(f(x, y), y).subs(y, z) == Derivative(f(x, z), z) + assert Derivative(f(x, y), y).subs(y, g(y)) == Derivative(f(x, g(y)), g(y)) + assert Derivative(f(g(x), h(y)), h(y)).subs(h(y), u(y)) == \ + Derivative(f(g(x), u(y)), u(y)) + assert Derivative(f(x, f(x, x)), f(x, x)).subs( + f, Lambda((x, y), x + y)) == Subs( + Derivative(z + x, z), z, 2*x) + assert Subs(Derivative(f(f(x)), x), f, cos).doit() == sin(x)*sin(cos(x)) + assert Subs(Derivative(f(f(x)), f(x)), f, cos).doit() == -sin(cos(x)) + # Issue 13791. No comparison (it's a long formula) but this used to raise an exception. + assert isinstance(v(x, y, u(x, y)).diff(y).diff(x).diff(y), Expr) + # This is also related to issues 13791 and 13795; issue 15190 + F = Lambda((x, y), exp(2*x + 3*y)) + abstract = f(x, f(x, x)).diff(x, 2) + concrete = F(x, F(x, x)).diff(x, 2) + assert (abstract.subs(f, F).doit() - concrete).simplify() == 0 + # don't introduce a new symbol if not necessary + assert x in f(x).diff(x).subs(x, 0).atoms() + # case (4) + assert Derivative(f(x,f(x,y)), x, y).subs(x, g(y) + ) == Subs(Derivative(f(x, f(x, y)), x, y), x, g(y)) + + assert Derivative(f(x, x), x).subs(x, 0 + ) == Subs(Derivative(f(x, x), x), x, 0) + # issue 15194 + assert Derivative(f(y, g(x)), (x, z)).subs(z, x + ) == Derivative(f(y, g(x)), (x, x)) + + df = f(x).diff(x) + assert df.subs(df, 1) is S.One + assert df.diff(df) is S.One + dxy = Derivative(f(x, y), x, y) + dyx = Derivative(f(x, y), y, x) + assert dxy.subs(Derivative(f(x, y), y, x), 1) is S.One + assert dxy.diff(dyx) is S.One + assert Derivative(f(x, y), x, 2, y, 3).subs( + dyx, g(x, y)) == Derivative(g(x, y), x, 1, y, 2) + assert Derivative(f(x, x - y), y).subs(x, x + y) == Subs( + Derivative(f(x, x - y), y), x, x + y) + + +def test_diff_wrt_not_allowed(): + # issue 7027 included + for wrt in ( + cos(x), re(x), x**2, x*y, 1 + x, + Derivative(cos(x), x), Derivative(f(f(x)), x)): + raises(ValueError, lambda: diff(f(x), wrt)) + # if we don't differentiate wrt then don't raise error + assert diff(exp(x*y), x*y, 0) == exp(x*y) + + +def test_diff_wrt_intlike(): + class Two: + def __int__(self): + return 2 + + assert cos(x).diff(x, Two()) == -cos(x) + + +def test_klein_gordon_lagrangian(): + m = Symbol('m') + phi = f(x, t) + + L = -(diff(phi, t)**2 - diff(phi, x)**2 - m**2*phi**2)/2 + eqna = Eq( + diff(L, phi) - diff(L, diff(phi, x), x) - diff(L, diff(phi, t), t), 0) + eqnb = Eq(diff(phi, t, t) - diff(phi, x, x) + m**2*phi, 0) + assert eqna == eqnb + + +def test_sho_lagrangian(): + m = Symbol('m') + k = Symbol('k') + x = f(t) + + L = m*diff(x, t)**2/2 - k*x**2/2 + eqna = Eq(diff(L, x), diff(L, diff(x, t), t)) + eqnb = Eq(-k*x, m*diff(x, t, t)) + assert eqna == eqnb + + assert diff(L, x, t) == diff(L, t, x) + assert diff(L, diff(x, t), t) == m*diff(x, t, 2) + assert diff(L, t, diff(x, t)) == -k*x + m*diff(x, t, 2) + + +def test_straight_line(): + F = f(x) + Fd = F.diff(x) + L = sqrt(1 + Fd**2) + assert diff(L, F) == 0 + assert diff(L, Fd) == Fd/sqrt(1 + Fd**2) + + +def test_sort_variable(): + vsort = Derivative._sort_variable_count + def vsort0(*v, reverse=False): + return [i[0] for i in vsort([(i, 0) for i in ( + reversed(v) if reverse else v)])] + + for R in range(2): + assert vsort0(y, x, reverse=R) == [x, y] + assert vsort0(f(x), x, reverse=R) == [x, f(x)] + assert vsort0(f(y), f(x), reverse=R) == [f(x), f(y)] + assert vsort0(g(x), f(y), reverse=R) == [f(y), g(x)] + assert vsort0(f(x, y), f(x), reverse=R) == [f(x), f(x, y)] + fx = f(x).diff(x) + assert vsort0(fx, y, reverse=R) == [y, fx] + fy = f(y).diff(y) + assert vsort0(fy, fx, reverse=R) == [fx, fy] + fxx = fx.diff(x) + assert vsort0(fxx, fx, reverse=R) == [fx, fxx] + assert vsort0(Basic(x), f(x), reverse=R) == [f(x), Basic(x)] + assert vsort0(Basic(y), Basic(x), reverse=R) == [Basic(x), Basic(y)] + assert vsort0(Basic(y, z), Basic(x), reverse=R) == [ + Basic(x), Basic(y, z)] + assert vsort0(fx, x, reverse=R) == [ + x, fx] if R else [fx, x] + assert vsort0(Basic(x), x, reverse=R) == [ + x, Basic(x)] if R else [Basic(x), x] + assert vsort0(Basic(f(x)), f(x), reverse=R) == [ + f(x), Basic(f(x))] if R else [Basic(f(x)), f(x)] + assert vsort0(Basic(x, z), Basic(x), reverse=R) == [ + Basic(x), Basic(x, z)] if R else [Basic(x, z), Basic(x)] + assert vsort([]) == [] + assert _aresame(vsort([(x, 1)]), [Tuple(x, 1)]) + assert vsort([(x, y), (x, z)]) == [(x, y + z)] + assert vsort([(y, 1), (x, 1 + y)]) == [(x, 1 + y), (y, 1)] + # coverage complete; legacy tests below + assert vsort([(x, 3), (y, 2), (z, 1)]) == [(x, 3), (y, 2), (z, 1)] + assert vsort([(h(x), 1), (g(x), 1), (f(x), 1)]) == [ + (f(x), 1), (g(x), 1), (h(x), 1)] + assert vsort([(z, 1), (y, 2), (x, 3), (h(x), 1), (g(x), 1), + (f(x), 1)]) == [(x, 3), (y, 2), (z, 1), (f(x), 1), (g(x), 1), + (h(x), 1)] + assert vsort([(x, 1), (f(x), 1), (y, 1), (f(y), 1)]) == [(x, 1), + (y, 1), (f(x), 1), (f(y), 1)] + assert vsort([(y, 1), (x, 2), (g(x), 1), (f(x), 1), (z, 1), + (h(x), 1), (y, 2), (x, 1)]) == [(x, 3), (y, 3), (z, 1), + (f(x), 1), (g(x), 1), (h(x), 1)] + assert vsort([(z, 1), (y, 1), (f(x), 1), (x, 1), (f(x), 1), + (g(x), 1)]) == [(x, 1), (y, 1), (z, 1), (f(x), 2), (g(x), 1)] + assert vsort([(z, 1), (y, 2), (f(x), 1), (x, 2), (f(x), 2), + (g(x), 1), (z, 2), (z, 1), (y, 1), (x, 1)]) == [(x, 3), (y, 3), + (z, 4), (f(x), 3), (g(x), 1)] + assert vsort(((y, 2), (x, 1), (y, 1), (x, 1))) == [(x, 2), (y, 3)] + assert isinstance(vsort([(x, 3), (y, 2), (z, 1)])[0], Tuple) + assert vsort([(x, 1), (f(x), 1), (x, 1)]) == [(x, 2), (f(x), 1)] + assert vsort([(y, 2), (x, 3), (z, 1)]) == [(x, 3), (y, 2), (z, 1)] + assert vsort([(h(y), 1), (g(x), 1), (f(x), 1)]) == [ + (f(x), 1), (g(x), 1), (h(y), 1)] + assert vsort([(x, 1), (y, 1), (x, 1)]) == [(x, 2), (y, 1)] + assert vsort([(f(x), 1), (f(y), 1), (f(x), 1)]) == [ + (f(x), 2), (f(y), 1)] + dfx = f(x).diff(x) + self = [(dfx, 1), (x, 1)] + assert vsort(self) == self + assert vsort([ + (dfx, 1), (y, 1), (f(x), 1), (x, 1), (f(y), 1), (x, 1)]) == [ + (y, 1), (f(x), 1), (f(y), 1), (dfx, 1), (x, 2)] + dfy = f(y).diff(y) + assert vsort([(dfy, 1), (dfx, 1)]) == [(dfx, 1), (dfy, 1)] + d2fx = dfx.diff(x) + assert vsort([(d2fx, 1), (dfx, 1)]) == [(dfx, 1), (d2fx, 1)] + + +def test_multiple_derivative(): + # Issue #15007 + assert f(x, y).diff(y, y, x, y, x + ) == Derivative(f(x, y), (x, 2), (y, 3)) + + +def test_unhandled(): + class MyExpr(Expr): + def _eval_derivative(self, s): + if not s.name.startswith('xi'): + return self + else: + return None + + eq = MyExpr(f(x), y, z) + assert diff(eq, x, y, f(x), z) == Derivative(eq, f(x)) + assert diff(eq, f(x), x) == Derivative(eq, f(x)) + assert f(x, y).diff(x,(y, z)) == Derivative(f(x, y), x, (y, z)) + assert f(x, y).diff(x,(y, 0)) == Derivative(f(x, y), x) + + +def test_nfloat(): + from sympy.core.basic import _aresame + from sympy.polys.rootoftools import rootof + + x = Symbol("x") + eq = x**Rational(4, 3) + 4*x**(S.One/3)/3 + assert _aresame(nfloat(eq), x**Rational(4, 3) + (4.0/3)*x**(S.One/3)) + assert _aresame(nfloat(eq, exponent=True), x**(4.0/3) + (4.0/3)*x**(1.0/3)) + eq = x**Rational(4, 3) + 4*x**(x/3)/3 + assert _aresame(nfloat(eq), x**Rational(4, 3) + (4.0/3)*x**(x/3)) + big = 12345678901234567890 + # specify precision to match value used in nfloat + Float_big = Float(big, 15) + assert _aresame(nfloat(big), Float_big) + assert _aresame(nfloat(big*x), Float_big*x) + assert _aresame(nfloat(x**big, exponent=True), x**Float_big) + assert nfloat(cos(x + sqrt(2))) == cos(x + nfloat(sqrt(2))) + + # issue 6342 + f = S('x*lamda + lamda**3*(x/2 + 1/2) + lamda**2 + 1/4') + assert not any(a.free_symbols for a in solveset(f.subs(x, -0.139))) + + # issue 6632 + assert nfloat(-100000*sqrt(2500000001) + 5000000001) == \ + 9.99999999800000e-11 + + # issue 7122 + eq = cos(3*x**4 + y)*rootof(x**5 + 3*x**3 + 1, 0) + assert str(nfloat(eq, exponent=False, n=1)) == '-0.7*cos(3.0*x**4 + y)' + + # issue 10933 + for ti in (dict, Dict): + d = ti({S.Half: S.Half}) + n = nfloat(d) + assert isinstance(n, ti) + assert _aresame(list(n.items()).pop(), (S.Half, Float(.5))) + for ti in (dict, Dict): + d = ti({S.Half: S.Half}) + n = nfloat(d, dkeys=True) + assert isinstance(n, ti) + assert _aresame(list(n.items()).pop(), (Float(.5), Float(.5))) + d = [S.Half] + n = nfloat(d) + assert type(n) is list + assert _aresame(n[0], Float(.5)) + assert _aresame(nfloat(Eq(x, S.Half)).rhs, Float(.5)) + assert _aresame(nfloat(S(True)), S(True)) + assert _aresame(nfloat(Tuple(S.Half))[0], Float(.5)) + assert nfloat(Eq((3 - I)**2/2 + I, 0)) == S.false + # pass along kwargs + assert nfloat([{S.Half: x}], dkeys=True) == [{Float(0.5): x}] + + # Issue 17706 + A = MutableMatrix([[1, 2], [3, 4]]) + B = MutableMatrix( + [[Float('1.0', precision=53), Float('2.0', precision=53)], + [Float('3.0', precision=53), Float('4.0', precision=53)]]) + assert _aresame(nfloat(A), B) + A = ImmutableMatrix([[1, 2], [3, 4]]) + B = ImmutableMatrix( + [[Float('1.0', precision=53), Float('2.0', precision=53)], + [Float('3.0', precision=53), Float('4.0', precision=53)]]) + assert _aresame(nfloat(A), B) + + # issue 22524 + f = Function('f') + assert not nfloat(f(2)).atoms(Float) + + +def test_issue_7068(): + from sympy.abc import a, b + f = Function('f') + y1 = Dummy('y') + y2 = Dummy('y') + func1 = f(a + y1 * b) + func2 = f(a + y2 * b) + func1_y = func1.diff(y1) + func2_y = func2.diff(y2) + assert func1_y != func2_y + z1 = Subs(f(a), a, y1) + z2 = Subs(f(a), a, y2) + assert z1 != z2 + + +def test_issue_7231(): + from sympy.abc import a + ans1 = f(x).series(x, a) + res = (f(a) + (-a + x)*Subs(Derivative(f(y), y), y, a) + + (-a + x)**2*Subs(Derivative(f(y), y, y), y, a)/2 + + (-a + x)**3*Subs(Derivative(f(y), y, y, y), + y, a)/6 + + (-a + x)**4*Subs(Derivative(f(y), y, y, y, y), + y, a)/24 + + (-a + x)**5*Subs(Derivative(f(y), y, y, y, y, y), + y, a)/120 + O((-a + x)**6, (x, a))) + assert res == ans1 + ans2 = f(x).series(x, a) + assert res == ans2 + + +def test_issue_7687(): + from sympy.core.function import Function + from sympy.abc import x + f = Function('f')(x) + ff = Function('f')(x) + match_with_cache = ff.matches(f) + assert isinstance(f, type(ff)) + clear_cache() + ff = Function('f')(x) + assert isinstance(f, type(ff)) + assert match_with_cache == ff.matches(f) + + +def test_issue_7688(): + from sympy.core.function import Function, UndefinedFunction + + f = Function('f') # actually an UndefinedFunction + clear_cache() + class A(UndefinedFunction): + pass + a = A('f') + assert isinstance(a, type(f)) + + +def test_mexpand(): + from sympy.abc import x + assert _mexpand(None) is None + assert _mexpand(1) is S.One + assert _mexpand(x*(x + 1)**2) == (x*(x + 1)**2).expand() + + +def test_issue_8469(): + # This should not take forever to run + N = 40 + def g(w, theta): + return 1/(1+exp(w-theta)) + + ws = symbols(['w%i'%i for i in range(N)]) + import functools + expr = functools.reduce(g, ws) + assert isinstance(expr, Pow) + + +def test_issue_12996(): + # foo=True imitates the sort of arguments that Derivative can get + # from Integral when it passes doit to the expression + assert Derivative(im(x), x).doit(foo=True) == Derivative(im(x), x) + + +def test_should_evalf(): + # This should not take forever to run (see #8506) + assert isinstance(sin((1.0 + 1.0*I)**10000 + 1), sin) + + +def test_Derivative_as_finite_difference(): + # Central 1st derivative at gridpoint + x, h = symbols('x h', real=True) + dfdx = f(x).diff(x) + assert (dfdx.as_finite_difference([x-2, x-1, x, x+1, x+2]) - + (S.One/12*(f(x-2)-f(x+2)) + Rational(2, 3)*(f(x+1)-f(x-1)))).simplify() == 0 + + # Central 1st derivative "half-way" + assert (dfdx.as_finite_difference() - + (f(x + S.Half)-f(x - S.Half))).simplify() == 0 + assert (dfdx.as_finite_difference(h) - + (f(x + h/S(2))-f(x - h/S(2)))/h).simplify() == 0 + assert (dfdx.as_finite_difference([x - 3*h, x-h, x+h, x + 3*h]) - + (S(9)/(8*2*h)*(f(x+h) - f(x-h)) + + S.One/(24*2*h)*(f(x - 3*h) - f(x + 3*h)))).simplify() == 0 + + # One sided 1st derivative at gridpoint + assert (dfdx.as_finite_difference([0, 1, 2], 0) - + (Rational(-3, 2)*f(0) + 2*f(1) - f(2)/2)).simplify() == 0 + assert (dfdx.as_finite_difference([x, x+h], x) - + (f(x+h) - f(x))/h).simplify() == 0 + assert (dfdx.as_finite_difference([x-h, x, x+h], x-h) - + (-S(3)/(2*h)*f(x-h) + 2/h*f(x) - + S.One/(2*h)*f(x+h))).simplify() == 0 + + # One sided 1st derivative "half-way" + assert (dfdx.as_finite_difference([x-h, x+h, x + 3*h, x + 5*h, x + 7*h]) + - 1/(2*h)*(-S(11)/(12)*f(x-h) + S(17)/(24)*f(x+h) + + Rational(3, 8)*f(x + 3*h) - Rational(5, 24)*f(x + 5*h) + + S.One/24*f(x + 7*h))).simplify() == 0 + + d2fdx2 = f(x).diff(x, 2) + # Central 2nd derivative at gridpoint + assert (d2fdx2.as_finite_difference([x-h, x, x+h]) - + h**-2 * (f(x-h) + f(x+h) - 2*f(x))).simplify() == 0 + + assert (d2fdx2.as_finite_difference([x - 2*h, x-h, x, x+h, x + 2*h]) - + h**-2 * (Rational(-1, 12)*(f(x - 2*h) + f(x + 2*h)) + + Rational(4, 3)*(f(x+h) + f(x-h)) - Rational(5, 2)*f(x))).simplify() == 0 + + # Central 2nd derivative "half-way" + assert (d2fdx2.as_finite_difference([x - 3*h, x-h, x+h, x + 3*h]) - + (2*h)**-2 * (S.Half*(f(x - 3*h) + f(x + 3*h)) - + S.Half*(f(x+h) + f(x-h)))).simplify() == 0 + + # One sided 2nd derivative at gridpoint + assert (d2fdx2.as_finite_difference([x, x+h, x + 2*h, x + 3*h]) - + h**-2 * (2*f(x) - 5*f(x+h) + + 4*f(x+2*h) - f(x+3*h))).simplify() == 0 + + # One sided 2nd derivative at "half-way" + assert (d2fdx2.as_finite_difference([x-h, x+h, x + 3*h, x + 5*h]) - + (2*h)**-2 * (Rational(3, 2)*f(x-h) - Rational(7, 2)*f(x+h) + Rational(5, 2)*f(x + 3*h) - + S.Half*f(x + 5*h))).simplify() == 0 + + d3fdx3 = f(x).diff(x, 3) + # Central 3rd derivative at gridpoint + assert (d3fdx3.as_finite_difference() - + (-f(x - Rational(3, 2)) + 3*f(x - S.Half) - + 3*f(x + S.Half) + f(x + Rational(3, 2)))).simplify() == 0 + + assert (d3fdx3.as_finite_difference( + [x - 3*h, x - 2*h, x-h, x, x+h, x + 2*h, x + 3*h]) - + h**-3 * (S.One/8*(f(x - 3*h) - f(x + 3*h)) - f(x - 2*h) + + f(x + 2*h) + Rational(13, 8)*(f(x-h) - f(x+h)))).simplify() == 0 + + # Central 3rd derivative at "half-way" + assert (d3fdx3.as_finite_difference([x - 3*h, x-h, x+h, x + 3*h]) - + (2*h)**-3 * (f(x + 3*h)-f(x - 3*h) + + 3*(f(x-h)-f(x+h)))).simplify() == 0 + + # One sided 3rd derivative at gridpoint + assert (d3fdx3.as_finite_difference([x, x+h, x + 2*h, x + 3*h]) - + h**-3 * (f(x + 3*h)-f(x) + 3*(f(x+h)-f(x + 2*h)))).simplify() == 0 + + # One sided 3rd derivative at "half-way" + assert (d3fdx3.as_finite_difference([x-h, x+h, x + 3*h, x + 5*h]) - + (2*h)**-3 * (f(x + 5*h)-f(x-h) + + 3*(f(x+h)-f(x + 3*h)))).simplify() == 0 + + # issue 11007 + y = Symbol('y', real=True) + d2fdxdy = f(x, y).diff(x, y) + + ref0 = Derivative(f(x + S.Half, y), y) - Derivative(f(x - S.Half, y), y) + assert (d2fdxdy.as_finite_difference(wrt=x) - ref0).simplify() == 0 + + half = S.Half + xm, xp, ym, yp = x-half, x+half, y-half, y+half + ref2 = f(xm, ym) + f(xp, yp) - f(xp, ym) - f(xm, yp) + assert (d2fdxdy.as_finite_difference() - ref2).simplify() == 0 + + +def test_issue_11159(): + # Tests Application._eval_subs + with _exp_is_pow(False): + expr1 = E + expr0 = expr1 * expr1 + expr1 = expr0.subs(expr1,expr0) + assert expr0 == expr1 + with _exp_is_pow(True): + expr1 = E + expr0 = expr1 * expr1 + expr2 = expr0.subs(expr1, expr0) + assert expr2 == E ** 4 + + +def test_issue_12005(): + e1 = Subs(Derivative(f(x), x), x, x) + assert e1.diff(x) == Derivative(f(x), x, x) + e2 = Subs(Derivative(f(x), x), x, x**2 + 1) + assert e2.diff(x) == 2*x*Subs(Derivative(f(x), x, x), x, x**2 + 1) + e3 = Subs(Derivative(f(x) + y**2 - y, y), y, y**2) + assert e3.diff(y) == 4*y + e4 = Subs(Derivative(f(x + y), y), y, (x**2)) + assert e4.diff(y) is S.Zero + e5 = Subs(Derivative(f(x), x), (y, z), (y, z)) + assert e5.diff(x) == Derivative(f(x), x, x) + assert f(g(x)).diff(g(x), g(x)) == Derivative(f(g(x)), g(x), g(x)) + + +def test_issue_13843(): + x = symbols('x') + f = Function('f') + m, n = symbols('m n', integer=True) + assert Derivative(Derivative(f(x), (x, m)), (x, n)) == Derivative(f(x), (x, m + n)) + assert Derivative(Derivative(f(x), (x, m+5)), (x, n+3)) == Derivative(f(x), (x, m + n + 8)) + + assert Derivative(f(x), (x, n)).doit() == Derivative(f(x), (x, n)) + + +def test_order_could_be_zero(): + x, y = symbols('x, y') + n = symbols('n', integer=True, nonnegative=True) + m = symbols('m', integer=True, positive=True) + assert diff(y, (x, n)) == Piecewise((y, Eq(n, 0)), (0, True)) + assert diff(y, (x, n + 1)) is S.Zero + assert diff(y, (x, m)) is S.Zero + + +def test_undefined_function_eq(): + f = Function('f') + f2 = Function('f') + g = Function('g') + f_real = Function('f', is_real=True) + + # This test may only be meaningful if the cache is turned off + assert f == f2 + assert hash(f) == hash(f2) + assert f == f + + assert f != g + + assert f != f_real + + +def test_function_assumptions(): + x = Symbol('x') + f = Function('f') + f_real = Function('f', real=True) + f_real1 = Function('f', real=1) + f_real_inherit = Function(Symbol('f', real=True)) + + assert f_real == f_real1 # assumptions are sanitized + assert f != f_real + assert f(x) != f_real(x) + + assert f(x).is_real is None + assert f_real(x).is_real is True + assert f_real_inherit(x).is_real is True and f_real_inherit.name == 'f' + + # Can also do it this way, but it won't be equal to f_real because of the + # way UndefinedFunction.__new__ works. Any non-recognized assumptions + # are just added literally as something which is used in the hash + f_real2 = Function('f', is_real=True) + assert f_real2(x).is_real is True + + +def test_undef_fcn_float_issue_6938(): + f = Function('ceil') + assert not f(0.3).is_number + f = Function('sin') + assert not f(0.3).is_number + assert not f(pi).evalf().is_number + x = Symbol('x') + assert not f(x).evalf(subs={x:1.2}).is_number + + +def test_undefined_function_eval(): + # Issue 15170. Make sure UndefinedFunction with eval defined works + # properly. + + fdiff = lambda self, argindex=1: cos(self.args[argindex - 1]) + eval = classmethod(lambda cls, t: None) + _imp_ = classmethod(lambda cls, t: sin(t)) + + temp = Function('temp', fdiff=fdiff, eval=eval, _imp_=_imp_) + + expr = temp(t) + assert sympify(expr) == expr + assert type(sympify(expr)).fdiff.__name__ == "" + assert expr.diff(t) == cos(t) + + +def test_issue_15241(): + F = f(x) + Fx = F.diff(x) + assert (F + x*Fx).diff(x, Fx) == 2 + assert (F + x*Fx).diff(Fx, x) == 1 + assert (x*F + x*Fx*F).diff(F, x) == x*Fx.diff(x) + Fx + 1 + assert (x*F + x*Fx*F).diff(x, F) == x*Fx.diff(x) + Fx + 1 + y = f(x) + G = f(y) + Gy = G.diff(y) + assert (G + y*Gy).diff(y, Gy) == 2 + assert (G + y*Gy).diff(Gy, y) == 1 + assert (y*G + y*Gy*G).diff(G, y) == y*Gy.diff(y) + Gy + 1 + assert (y*G + y*Gy*G).diff(y, G) == y*Gy.diff(y) + Gy + 1 + + +def test_issue_15226(): + assert Subs(Derivative(f(y), x, y), y, g(x)).doit() != 0 + + +def test_issue_7027(): + for wrt in (cos(x), re(x), Derivative(cos(x), x)): + raises(ValueError, lambda: diff(f(x), wrt)) + + +def test_derivative_quick_exit(): + assert f(x).diff(y) == 0 + assert f(x).diff(y, f(x)) == 0 + assert f(x).diff(x, f(y)) == 0 + assert f(f(x)).diff(x, f(x), f(y)) == 0 + assert f(f(x)).diff(x, f(x), y) == 0 + assert f(x).diff(g(x)) == 0 + assert f(x).diff(x, f(x).diff(x)) == 1 + df = f(x).diff(x) + assert f(x).diff(df) == 0 + dg = g(x).diff(x) + assert dg.diff(df).doit() == 0 + + +def test_issue_15084_13166(): + eq = f(x, g(x)) + assert eq.diff((g(x), y)) == Derivative(f(x, g(x)), (g(x), y)) + # issue 13166 + assert eq.diff(x, 2).doit() == ( + (Derivative(f(x, g(x)), (g(x), 2))*Derivative(g(x), x) + + Subs(Derivative(f(x, _xi_2), _xi_2, x), _xi_2, g(x)))*Derivative(g(x), + x) + Derivative(f(x, g(x)), g(x))*Derivative(g(x), (x, 2)) + + Derivative(g(x), x)*Subs(Derivative(f(_xi_1, g(x)), _xi_1, g(x)), + _xi_1, x) + Subs(Derivative(f(_xi_1, g(x)), (_xi_1, 2)), _xi_1, x)) + # issue 6681 + assert diff(f(x, t, g(x, t)), x).doit() == ( + Derivative(f(x, t, g(x, t)), g(x, t))*Derivative(g(x, t), x) + + Subs(Derivative(f(_xi_1, t, g(x, t)), _xi_1), _xi_1, x)) + # make sure the order doesn't matter when using diff + assert eq.diff(x, g(x)) == eq.diff(g(x), x) + + +def test_negative_counts(): + # issue 13873 + raises(ValueError, lambda: sin(x).diff(x, -1)) + + +def test_Derivative__new__(): + raises(TypeError, lambda: f(x).diff((x, 2), 0)) + assert f(x, y).diff([(x, y), 0]) == f(x, y) + assert f(x, y).diff([(x, y), 1]) == NDimArray([ + Derivative(f(x, y), x), Derivative(f(x, y), y)]) + assert f(x,y).diff(y, (x, z), y, x) == Derivative( + f(x, y), (x, z + 1), (y, 2)) + assert Matrix([x]).diff(x, 2) == Matrix([0]) # is_zero exit + + +def test_issue_14719_10150(): + class V(Expr): + _diff_wrt = True + is_scalar = False + assert V().diff(V()) == Derivative(V(), V()) + assert (2*V()).diff(V()) == 2*Derivative(V(), V()) + class X(Expr): + _diff_wrt = True + assert X().diff(X()) == 1 + assert (2*X()).diff(X()) == 2 + + +def test_noncommutative_issue_15131(): + x = Symbol('x', commutative=False) + t = Symbol('t', commutative=False) + fx = Function('Fx', commutative=False)(x) + ft = Function('Ft', commutative=False)(t) + A = Symbol('A', commutative=False) + eq = fx * A * ft + eqdt = eq.diff(t) + assert eqdt.args[-1] == ft.diff(t) + + +def test_Subs_Derivative(): + a = Derivative(f(g(x), h(x)), g(x), h(x),x) + b = Derivative(Derivative(f(g(x), h(x)), g(x), h(x)),x) + c = f(g(x), h(x)).diff(g(x), h(x), x) + d = f(g(x), h(x)).diff(g(x), h(x)).diff(x) + e = Derivative(f(g(x), h(x)), x) + eqs = (a, b, c, d, e) + subs = lambda arg: arg.subs(f, Lambda((x, y), exp(x + y)) + ).subs(g(x), 1/x).subs(h(x), x**3) + ans = 3*x**2*exp(1/x)*exp(x**3) - exp(1/x)*exp(x**3)/x**2 + assert all(subs(i).doit().expand() == ans for i in eqs) + assert all(subs(i.doit()).doit().expand() == ans for i in eqs) + +def test_issue_15360(): + f = Function('f') + assert f.name == 'f' + + +def test_issue_15947(): + assert f._diff_wrt is False + raises(TypeError, lambda: f(f)) + raises(TypeError, lambda: f(x).diff(f)) + + +def test_Derivative_free_symbols(): + f = Function('f') + n = Symbol('n', integer=True, positive=True) + assert diff(f(x), (x, n)).free_symbols == {n, x} + + +def test_issue_20683(): + x = Symbol('x') + y = Symbol('y') + z = Symbol('z') + y = Derivative(z, x).subs(x,0) + assert y.doit() == 0 + y = Derivative(8, x).subs(x,0) + assert y.doit() == 0 + + +def test_issue_10503(): + f = exp(x**3)*cos(x**6) + assert f.series(x, 0, 14) == 1 + x**3 + x**6/2 + x**9/6 - 11*x**12/24 + O(x**14) + + +def test_issue_17382(): + # copied from sympy/core/tests/test_evalf.py + def NS(e, n=15, **options): + return sstr(sympify(e).evalf(n, **options), full_prec=True) + + x = Symbol('x') + expr = solveset(2 * cos(x) * cos(2 * x) - 1, x, S.Reals) + expected = "Union(" \ + "ImageSet(Lambda(_n, 6.28318530717959*_n + 5.79812359592087), Integers), " \ + "ImageSet(Lambda(_n, 6.28318530717959*_n + 0.485061711258717), Integers))" + assert NS(expr) == expected + +def test_eval_sympified(): + # Check both arguments and return types from eval are sympified + + class F(Function): + @classmethod + def eval(cls, x): + assert x is S.One + return 1 + + assert F(1) is S.One + + # String arguments are not allowed + class F2(Function): + @classmethod + def eval(cls, x): + if x == 0: + return '1' + + raises(SympifyError, lambda: F2(0)) + F2(1) # Doesn't raise + + # TODO: Disable string inputs (https://github.com/sympy/sympy/issues/11003) + # raises(SympifyError, lambda: F2('2')) + +def test_eval_classmethod_check(): + with raises(TypeError): + class F(Function): + def eval(self, x): + pass diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_kind.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_kind.py new file mode 100644 index 0000000000000000000000000000000000000000..cbfdffb9304b49488756752ca198fd4067087437 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_kind.py @@ -0,0 +1,57 @@ +from sympy.core.add import Add +from sympy.core.kind import NumberKind, UndefinedKind +from sympy.core.mul import Mul +from sympy.core.numbers import pi, zoo, I, AlgebraicNumber +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.integrals.integrals import Integral +from sympy.core.function import Derivative +from sympy.matrices import (Matrix, SparseMatrix, ImmutableMatrix, + ImmutableSparseMatrix, MatrixSymbol, MatrixKind, MatMul) + +comm_x = Symbol('x') +noncomm_x = Symbol('x', commutative=False) + +def test_NumberKind(): + assert S.One.kind is NumberKind + assert pi.kind is NumberKind + assert S.NaN.kind is NumberKind + assert zoo.kind is NumberKind + assert I.kind is NumberKind + assert AlgebraicNumber(1).kind is NumberKind + +def test_Add_kind(): + assert Add(2, 3, evaluate=False).kind is NumberKind + assert Add(2,comm_x).kind is NumberKind + assert Add(2,noncomm_x).kind is UndefinedKind + +def test_mul_kind(): + assert Mul(2,comm_x, evaluate=False).kind is NumberKind + assert Mul(2,3, evaluate=False).kind is NumberKind + assert Mul(noncomm_x,2, evaluate=False).kind is UndefinedKind + assert Mul(2,noncomm_x, evaluate=False).kind is UndefinedKind + +def test_Symbol_kind(): + assert comm_x.kind is NumberKind + assert noncomm_x.kind is UndefinedKind + +def test_Integral_kind(): + A = MatrixSymbol('A', 2,2) + assert Integral(comm_x, comm_x).kind is NumberKind + assert Integral(A, comm_x).kind is MatrixKind(NumberKind) + +def test_Derivative_kind(): + A = MatrixSymbol('A', 2,2) + assert Derivative(comm_x, comm_x).kind is NumberKind + assert Derivative(A, comm_x).kind is MatrixKind(NumberKind) + +def test_Matrix_kind(): + classes = (Matrix, SparseMatrix, ImmutableMatrix, ImmutableSparseMatrix) + for cls in classes: + m = cls.zeros(3, 2) + assert m.kind is MatrixKind(NumberKind) + +def test_MatMul_kind(): + M = Matrix([[1,2],[3,4]]) + assert MatMul(2, M).kind is MatrixKind(NumberKind) + assert MatMul(comm_x, M).kind is MatrixKind(NumberKind) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_logic.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_logic.py new file mode 100644 index 0000000000000000000000000000000000000000..df5647f32ea7c4e326eb4e3aec6a7b2987f32aee --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_logic.py @@ -0,0 +1,198 @@ +from sympy.core.logic import (fuzzy_not, Logic, And, Or, Not, fuzzy_and, + fuzzy_or, _fuzzy_group, _torf, fuzzy_nand, fuzzy_xor) +from sympy.testing.pytest import raises + +from itertools import product + +T = True +F = False +U = None + + + +def test_torf(): + v = [T, F, U] + for i in product(*[v]*3): + assert _torf(i) is (True if all(j for j in i) else + (False if all(j is False for j in i) else None)) + + +def test_fuzzy_group(): + v = [T, F, U] + for i in product(*[v]*3): + assert _fuzzy_group(i) is (None if None in i else + (True if all(j for j in i) else False)) + assert _fuzzy_group(i, quick_exit=True) is \ + (None if (i.count(False) > 1) else + (None if None in i else (True if all(j for j in i) else False))) + it = (True if (i == 0) else None for i in range(2)) + assert _torf(it) is None + it = (True if (i == 1) else None for i in range(2)) + assert _torf(it) is None + + +def test_fuzzy_not(): + assert fuzzy_not(T) == F + assert fuzzy_not(F) == T + assert fuzzy_not(U) == U + + +def test_fuzzy_and(): + assert fuzzy_and([T, T]) == T + assert fuzzy_and([T, F]) == F + assert fuzzy_and([T, U]) == U + assert fuzzy_and([F, F]) == F + assert fuzzy_and([F, U]) == F + assert fuzzy_and([U, U]) == U + assert [fuzzy_and([w]) for w in [U, T, F]] == [U, T, F] + assert fuzzy_and([T, F, U]) == F + assert fuzzy_and([]) == T + raises(TypeError, lambda: fuzzy_and()) + + +def test_fuzzy_or(): + assert fuzzy_or([T, T]) == T + assert fuzzy_or([T, F]) == T + assert fuzzy_or([T, U]) == T + assert fuzzy_or([F, F]) == F + assert fuzzy_or([F, U]) == U + assert fuzzy_or([U, U]) == U + assert [fuzzy_or([w]) for w in [U, T, F]] == [U, T, F] + assert fuzzy_or([T, F, U]) == T + assert fuzzy_or([]) == F + raises(TypeError, lambda: fuzzy_or()) + + +def test_logic_cmp(): + l1 = And('a', Not('b')) + l2 = And('a', Not('b')) + + assert hash(l1) == hash(l2) + assert (l1 == l2) == T + assert (l1 != l2) == F + + assert And('a', 'b', 'c') == And('b', 'a', 'c') + assert And('a', 'b', 'c') == And('c', 'b', 'a') + assert And('a', 'b', 'c') == And('c', 'a', 'b') + + assert Not('a') < Not('b') + assert (Not('b') < Not('a')) is False + assert (Not('a') < 2) is False + + +def test_logic_onearg(): + assert And() is True + assert Or() is False + + assert And(T) == T + assert And(F) == F + assert Or(T) == T + assert Or(F) == F + + assert And('a') == 'a' + assert Or('a') == 'a' + + +def test_logic_xnotx(): + assert And('a', Not('a')) == F + assert Or('a', Not('a')) == T + + +def test_logic_eval_TF(): + assert And(F, F) == F + assert And(F, T) == F + assert And(T, F) == F + assert And(T, T) == T + + assert Or(F, F) == F + assert Or(F, T) == T + assert Or(T, F) == T + assert Or(T, T) == T + + assert And('a', T) == 'a' + assert And('a', F) == F + assert Or('a', T) == T + assert Or('a', F) == 'a' + + +def test_logic_combine_args(): + assert And('a', 'b', 'a') == And('a', 'b') + assert Or('a', 'b', 'a') == Or('a', 'b') + + assert And(And('a', 'b'), And('c', 'd')) == And('a', 'b', 'c', 'd') + assert Or(Or('a', 'b'), Or('c', 'd')) == Or('a', 'b', 'c', 'd') + + assert Or('t', And('n', 'p', 'r'), And('n', 'r'), And('n', 'p', 'r'), 't', + And('n', 'r')) == Or('t', And('n', 'p', 'r'), And('n', 'r')) + + +def test_logic_expand(): + t = And(Or('a', 'b'), 'c') + assert t.expand() == Or(And('a', 'c'), And('b', 'c')) + + t = And(Or('a', Not('b')), 'b') + assert t.expand() == And('a', 'b') + + t = And(Or('a', 'b'), Or('c', 'd')) + assert t.expand() == \ + Or(And('a', 'c'), And('a', 'd'), And('b', 'c'), And('b', 'd')) + + +def test_logic_fromstring(): + S = Logic.fromstring + + assert S('a') == 'a' + assert S('!a') == Not('a') + assert S('a & b') == And('a', 'b') + assert S('a | b') == Or('a', 'b') + assert S('a | b & c') == And(Or('a', 'b'), 'c') + assert S('a & b | c') == Or(And('a', 'b'), 'c') + assert S('a & b & c') == And('a', 'b', 'c') + assert S('a | b | c') == Or('a', 'b', 'c') + + raises(ValueError, lambda: S('| a')) + raises(ValueError, lambda: S('& a')) + raises(ValueError, lambda: S('a | | b')) + raises(ValueError, lambda: S('a | & b')) + raises(ValueError, lambda: S('a & & b')) + raises(ValueError, lambda: S('a |')) + raises(ValueError, lambda: S('a|b')) + raises(ValueError, lambda: S('!')) + raises(ValueError, lambda: S('! a')) + raises(ValueError, lambda: S('!(a + 1)')) + raises(ValueError, lambda: S('')) + + +def test_logic_not(): + assert Not('a') != '!a' + assert Not('!a') != 'a' + assert Not(True) == False + assert Not(False) == True + + # NOTE: we may want to change default Not behaviour and put this + # functionality into some method. + assert Not(And('a', 'b')) == Or(Not('a'), Not('b')) + assert Not(Or('a', 'b')) == And(Not('a'), Not('b')) + + raises(ValueError, lambda: Not(1)) + + +def test_formatting(): + S = Logic.fromstring + raises(ValueError, lambda: S('a&b')) + raises(ValueError, lambda: S('a|b')) + raises(ValueError, lambda: S('! a')) + + +def test_fuzzy_xor(): + assert fuzzy_xor((None,)) is None + assert fuzzy_xor((None, True)) is None + assert fuzzy_xor((None, False)) is None + assert fuzzy_xor((True, False)) is True + assert fuzzy_xor((True, True)) is False + assert fuzzy_xor((True, True, False)) is False + assert fuzzy_xor((True, True, False, True)) is True + +def test_fuzzy_nand(): + for args in [(1, 0), (1, 1), (0, 0)]: + assert fuzzy_nand(args) == fuzzy_not(fuzzy_and(args)) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_match.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_match.py new file mode 100644 index 0000000000000000000000000000000000000000..caa25e3c9dc1233e4566484f38a6b002ed4e72bd --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_match.py @@ -0,0 +1,766 @@ +from sympy import abc +from sympy.concrete.summations import Sum +from sympy.core.add import Add +from sympy.core.function import (Derivative, Function, diff) +from sympy.core.mul import Mul +from sympy.core.numbers import (Float, I, Integer, Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, Wild, symbols) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.hyper import meijerg +from sympy.polys.polytools import Poly +from sympy.simplify.radsimp import collect +from sympy.simplify.simplify import signsimp + +from sympy.testing.pytest import XFAIL + + +def test_symbol(): + x = Symbol('x') + a, b, c, p, q = map(Wild, 'abcpq') + + e = x + assert e.match(x) == {} + assert e.matches(x) == {} + assert e.match(a) == {a: x} + + e = Rational(5) + assert e.match(c) == {c: 5} + assert e.match(e) == {} + assert e.match(e + 1) is None + + +def test_add(): + x, y, a, b, c = map(Symbol, 'xyabc') + p, q, r = map(Wild, 'pqr') + + e = a + b + assert e.match(p + b) == {p: a} + assert e.match(p + a) == {p: b} + + e = 1 + b + assert e.match(p + b) == {p: 1} + + e = a + b + c + assert e.match(a + p + c) == {p: b} + assert e.match(b + p + c) == {p: a} + + e = a + b + c + x + assert e.match(a + p + x + c) == {p: b} + assert e.match(b + p + c + x) == {p: a} + assert e.match(b) is None + assert e.match(b + p) == {p: a + c + x} + assert e.match(a + p + c) == {p: b + x} + assert e.match(b + p + c) == {p: a + x} + + e = 4*x + 5 + assert e.match(4*x + p) == {p: 5} + assert e.match(3*x + p) == {p: x + 5} + assert e.match(p*x + 5) == {p: 4} + + +def test_power(): + x, y, a, b, c = map(Symbol, 'xyabc') + p, q, r = map(Wild, 'pqr') + + e = (x + y)**a + assert e.match(p**q) == {p: x + y, q: a} + assert e.match(p**p) is None + + e = (x + y)**(x + y) + assert e.match(p**p) == {p: x + y} + assert e.match(p**q) == {p: x + y, q: x + y} + + e = (2*x)**2 + assert e.match(p*q**r) == {p: 4, q: x, r: 2} + + e = Integer(1) + assert e.match(x**p) == {p: 0} + + +def test_match_exclude(): + x = Symbol('x') + y = Symbol('y') + p = Wild("p") + q = Wild("q") + r = Wild("r") + + e = Rational(6) + assert e.match(2*p) == {p: 3} + + e = 3/(4*x + 5) + assert e.match(3/(p*x + q)) == {p: 4, q: 5} + + e = 3/(4*x + 5) + assert e.match(p/(q*x + r)) == {p: 3, q: 4, r: 5} + + e = 2/(x + 1) + assert e.match(p/(q*x + r)) == {p: 2, q: 1, r: 1} + + e = 1/(x + 1) + assert e.match(p/(q*x + r)) == {p: 1, q: 1, r: 1} + + e = 4*x + 5 + assert e.match(p*x + q) == {p: 4, q: 5} + + e = 4*x + 5*y + 6 + assert e.match(p*x + q*y + r) == {p: 4, q: 5, r: 6} + + a = Wild('a', exclude=[x]) + + e = 3*x + assert e.match(p*x) == {p: 3} + assert e.match(a*x) == {a: 3} + + e = 3*x**2 + assert e.match(p*x) == {p: 3*x} + assert e.match(a*x) is None + + e = 3*x + 3 + 6/x + assert e.match(p*x**2 + p*x + 2*p) == {p: 3/x} + assert e.match(a*x**2 + a*x + 2*a) is None + + +def test_mul(): + x, y, a, b, c = map(Symbol, 'xyabc') + p, q = map(Wild, 'pq') + + e = 4*x + assert e.match(p*x) == {p: 4} + assert e.match(p*y) is None + assert e.match(e + p*y) == {p: 0} + + e = a*x*b*c + assert e.match(p*x) == {p: a*b*c} + assert e.match(c*p*x) == {p: a*b} + + e = (a + b)*(a + c) + assert e.match((p + b)*(p + c)) == {p: a} + + e = x + assert e.match(p*x) == {p: 1} + + e = exp(x) + assert e.match(x**p*exp(x*q)) == {p: 0, q: 1} + + e = I*Poly(x, x) + assert e.match(I*p) == {p: x} + + +def test_mul_noncommutative(): + x, y = symbols('x y') + A, B, C = symbols('A B C', commutative=False) + u, v = symbols('u v', cls=Wild) + w, z = symbols('w z', cls=Wild, commutative=False) + + assert (u*v).matches(x) in ({v: x, u: 1}, {u: x, v: 1}) + assert (u*v).matches(x*y) in ({v: y, u: x}, {u: y, v: x}) + assert (u*v).matches(A) is None + assert (u*v).matches(A*B) is None + assert (u*v).matches(x*A) is None + assert (u*v).matches(x*y*A) is None + assert (u*v).matches(x*A*B) is None + assert (u*v).matches(x*y*A*B) is None + + assert (v*w).matches(x) is None + assert (v*w).matches(x*y) is None + assert (v*w).matches(A) == {w: A, v: 1} + assert (v*w).matches(A*B) == {w: A*B, v: 1} + assert (v*w).matches(x*A) == {w: A, v: x} + assert (v*w).matches(x*y*A) == {w: A, v: x*y} + assert (v*w).matches(x*A*B) == {w: A*B, v: x} + assert (v*w).matches(x*y*A*B) == {w: A*B, v: x*y} + + assert (v*w).matches(-x) is None + assert (v*w).matches(-x*y) is None + assert (v*w).matches(-A) == {w: A, v: -1} + assert (v*w).matches(-A*B) == {w: A*B, v: -1} + assert (v*w).matches(-x*A) == {w: A, v: -x} + assert (v*w).matches(-x*y*A) == {w: A, v: -x*y} + assert (v*w).matches(-x*A*B) == {w: A*B, v: -x} + assert (v*w).matches(-x*y*A*B) == {w: A*B, v: -x*y} + + assert (w*z).matches(x) is None + assert (w*z).matches(x*y) is None + assert (w*z).matches(A) is None + assert (w*z).matches(A*B) == {w: A, z: B} + assert (w*z).matches(B*A) == {w: B, z: A} + assert (w*z).matches(A*B*C) in [{w: A, z: B*C}, {w: A*B, z: C}] + assert (w*z).matches(x*A) is None + assert (w*z).matches(x*y*A) is None + assert (w*z).matches(x*A*B) is None + assert (w*z).matches(x*y*A*B) is None + + assert (w*A).matches(A) is None + assert (A*w*B).matches(A*B) is None + + assert (u*w*z).matches(x) is None + assert (u*w*z).matches(x*y) is None + assert (u*w*z).matches(A) is None + assert (u*w*z).matches(A*B) == {u: 1, w: A, z: B} + assert (u*w*z).matches(B*A) == {u: 1, w: B, z: A} + assert (u*w*z).matches(x*A) is None + assert (u*w*z).matches(x*y*A) is None + assert (u*w*z).matches(x*A*B) == {u: x, w: A, z: B} + assert (u*w*z).matches(x*B*A) == {u: x, w: B, z: A} + assert (u*w*z).matches(x*y*A*B) == {u: x*y, w: A, z: B} + assert (u*w*z).matches(x*y*B*A) == {u: x*y, w: B, z: A} + + assert (u*A).matches(x*A) == {u: x} + assert (u*A).matches(x*A*B) is None + assert (u*B).matches(x*A) is None + assert (u*A*B).matches(x*A*B) == {u: x} + assert (u*A*B).matches(x*B*A) is None + assert (u*A*B).matches(x*A) is None + + assert (u*w*A).matches(x*A*B) is None + assert (u*w*B).matches(x*A*B) == {u: x, w: A} + + assert (u*v*A*B).matches(x*A*B) in [{u: x, v: 1}, {v: x, u: 1}] + assert (u*v*A*B).matches(x*B*A) is None + assert (u*v*A*B).matches(u*v*A*C) is None + + +def test_mul_noncommutative_mismatch(): + A, B, C = symbols('A B C', commutative=False) + w = symbols('w', cls=Wild, commutative=False) + + assert (w*B*w).matches(A*B*A) == {w: A} + assert (w*B*w).matches(A*C*B*A*C) == {w: A*C} + assert (w*B*w).matches(A*C*B*A*B) is None + assert (w*B*w).matches(A*B*C) is None + assert (w*w*C).matches(A*B*C) is None + + +def test_mul_noncommutative_pow(): + A, B, C = symbols('A B C', commutative=False) + w = symbols('w', cls=Wild, commutative=False) + + assert (A*B*w).matches(A*B**2) == {w: B} + assert (A*(B**2)*w*(B**3)).matches(A*B**8) == {w: B**3} + assert (A*B*w*C).matches(A*(B**4)*C) == {w: B**3} + + assert (A*B*(w**(-1))).matches(A*B*(C**(-1))) == {w: C} + assert (A*(B*w)**(-1)*C).matches(A*(B*C)**(-1)*C) == {w: C} + + assert ((w**2)*B*C).matches((A**2)*B*C) == {w: A} + assert ((w**2)*B*(w**3)).matches((A**2)*B*(A**3)) == {w: A} + assert ((w**2)*B*(w**4)).matches((A**2)*B*(A**2)) is None + +def test_complex(): + a, b, c = map(Symbol, 'abc') + x, y = map(Wild, 'xy') + + assert (1 + I).match(x + I) == {x: 1} + assert (a + I).match(x + I) == {x: a} + assert (2*I).match(x*I) == {x: 2} + assert (a*I).match(x*I) == {x: a} + assert (a*I).match(x*y) == {x: I, y: a} + assert (2*I).match(x*y) == {x: 2, y: I} + assert (a + b*I).match(x + y*I) == {x: a, y: b} + + +def test_functions(): + from sympy.core.function import WildFunction + x = Symbol('x') + g = WildFunction('g') + p = Wild('p') + q = Wild('q') + + f = cos(5*x) + notf = x + assert f.match(p*cos(q*x)) == {p: 1, q: 5} + assert f.match(p*g) == {p: 1, g: cos(5*x)} + assert notf.match(g) is None + + +@XFAIL +def test_functions_X1(): + from sympy.core.function import WildFunction + x = Symbol('x') + g = WildFunction('g') + p = Wild('p') + q = Wild('q') + + f = cos(5*x) + assert f.match(p*g(q*x)) == {p: 1, g: cos, q: 5} + + +def test_interface(): + x, y = map(Symbol, 'xy') + p, q = map(Wild, 'pq') + + assert (x + 1).match(p + 1) == {p: x} + assert (x*3).match(p*3) == {p: x} + assert (x**3).match(p**3) == {p: x} + assert (x*cos(y)).match(p*cos(q)) == {p: x, q: y} + + assert (x*y).match(p*q) in [{p:x, q:y}, {p:y, q:x}] + assert (x + y).match(p + q) in [{p:x, q:y}, {p:y, q:x}] + assert (x*y + 1).match(p*q) in [{p:1, q:1 + x*y}, {p:1 + x*y, q:1}] + + +def test_derivative1(): + x, y = map(Symbol, 'xy') + p, q = map(Wild, 'pq') + + f = Function('f', nargs=1) + fd = Derivative(f(x), x) + + assert fd.match(p) == {p: fd} + assert (fd + 1).match(p + 1) == {p: fd} + assert (fd).match(fd) == {} + assert (3*fd).match(p*fd) is not None + assert (3*fd - 1).match(p*fd + q) == {p: 3, q: -1} + + +def test_derivative_bug1(): + f = Function("f") + x = Symbol("x") + a = Wild("a", exclude=[f, x]) + b = Wild("b", exclude=[f]) + pattern = a * Derivative(f(x), x, x) + b + expr = Derivative(f(x), x) + x**2 + d1 = {b: x**2} + d2 = pattern.xreplace(d1).matches(expr, d1) + assert d2 is None + + +def test_derivative2(): + f = Function("f") + x = Symbol("x") + a = Wild("a", exclude=[f, x]) + b = Wild("b", exclude=[f]) + e = Derivative(f(x), x) + assert e.match(Derivative(f(x), x)) == {} + assert e.match(Derivative(f(x), x, x)) is None + e = Derivative(f(x), x, x) + assert e.match(Derivative(f(x), x)) is None + assert e.match(Derivative(f(x), x, x)) == {} + e = Derivative(f(x), x) + x**2 + assert e.match(a*Derivative(f(x), x) + b) == {a: 1, b: x**2} + assert e.match(a*Derivative(f(x), x, x) + b) is None + e = Derivative(f(x), x, x) + x**2 + assert e.match(a*Derivative(f(x), x) + b) is None + assert e.match(a*Derivative(f(x), x, x) + b) == {a: 1, b: x**2} + + +def test_match_deriv_bug1(): + n = Function('n') + l = Function('l') + + x = Symbol('x') + p = Wild('p') + + e = diff(l(x), x)/x - diff(diff(n(x), x), x)/2 - \ + diff(n(x), x)**2/4 + diff(n(x), x)*diff(l(x), x)/4 + e = e.subs(n(x), -l(x)).doit() + t = x*exp(-l(x)) + t2 = t.diff(x, x)/t + assert e.match( (p*t2).expand() ) == {p: Rational(-1, 2)} + + +def test_match_bug2(): + x, y = map(Symbol, 'xy') + p, q, r = map(Wild, 'pqr') + res = (x + y).match(p + q + r) + assert (p + q + r).subs(res) == x + y + + +def test_match_bug3(): + x, a, b = map(Symbol, 'xab') + p = Wild('p') + assert (b*x*exp(a*x)).match(x*exp(p*x)) is None + + +def test_match_bug4(): + x = Symbol('x') + p = Wild('p') + e = x + assert e.match(-p*x) == {p: -1} + + +def test_match_bug5(): + x = Symbol('x') + p = Wild('p') + e = -x + assert e.match(-p*x) == {p: 1} + + +def test_match_bug6(): + x = Symbol('x') + p = Wild('p') + e = x + assert e.match(3*p*x) == {p: Rational(1)/3} + + +def test_match_polynomial(): + x = Symbol('x') + a = Wild('a', exclude=[x]) + b = Wild('b', exclude=[x]) + c = Wild('c', exclude=[x]) + d = Wild('d', exclude=[x]) + + eq = 4*x**3 + 3*x**2 + 2*x + 1 + pattern = a*x**3 + b*x**2 + c*x + d + assert eq.match(pattern) == {a: 4, b: 3, c: 2, d: 1} + assert (eq - 3*x**2).match(pattern) == {a: 4, b: 0, c: 2, d: 1} + assert (x + sqrt(2) + 3).match(a + b*x + c*x**2) == \ + {b: 1, a: sqrt(2) + 3, c: 0} + + +def test_exclude(): + x, y, a = map(Symbol, 'xya') + p = Wild('p', exclude=[1, x]) + q = Wild('q') + r = Wild('r', exclude=[sin, y]) + + assert sin(x).match(r) is None + assert cos(y).match(r) is None + + e = 3*x**2 + y*x + a + assert e.match(p*x**2 + q*x + r) == {p: 3, q: y, r: a} + + e = x + 1 + assert e.match(x + p) is None + assert e.match(p + 1) is None + assert e.match(x + 1 + p) == {p: 0} + + e = cos(x) + 5*sin(y) + assert e.match(r) is None + assert e.match(cos(y) + r) is None + assert e.match(r + p*sin(q)) == {r: cos(x), p: 5, q: y} + + +def test_floats(): + a, b = map(Wild, 'ab') + + e = cos(0.12345, evaluate=False)**2 + r = e.match(a*cos(b)**2) + assert r == {a: 1, b: Float(0.12345)} + + +def test_Derivative_bug1(): + f = Function("f") + x = abc.x + a = Wild("a", exclude=[f(x)]) + b = Wild("b", exclude=[f(x)]) + eq = f(x).diff(x) + assert eq.match(a*Derivative(f(x), x) + b) == {a: 1, b: 0} + + +def test_match_wild_wild(): + p = Wild('p') + q = Wild('q') + r = Wild('r') + + assert p.match(q + r) in [ {q: p, r: 0}, {q: 0, r: p} ] + assert p.match(q*r) in [ {q: p, r: 1}, {q: 1, r: p} ] + + p = Wild('p') + q = Wild('q', exclude=[p]) + r = Wild('r') + + assert p.match(q + r) == {q: 0, r: p} + assert p.match(q*r) == {q: 1, r: p} + + p = Wild('p') + q = Wild('q', exclude=[p]) + r = Wild('r', exclude=[p]) + + assert p.match(q + r) is None + assert p.match(q*r) is None + + +def test__combine_inverse(): + x, y = symbols("x y") + assert Mul._combine_inverse(x*I*y, x*I) == y + assert Mul._combine_inverse(x*x**(1 + y), x**(1 + y)) == x + assert Mul._combine_inverse(x*I*y, y*I) == x + assert Mul._combine_inverse(oo*I*y, y*I) is oo + assert Mul._combine_inverse(oo*I*y, oo*I) == y + assert Mul._combine_inverse(oo*I*y, oo*I) == y + assert Mul._combine_inverse(oo*y, -oo) == -y + assert Mul._combine_inverse(-oo*y, oo) == -y + assert Mul._combine_inverse((1-exp(x/y)),(exp(x/y)-1)) == -1 + assert Add._combine_inverse(oo, oo) is S.Zero + assert Add._combine_inverse(oo*I, oo*I) is S.Zero + assert Add._combine_inverse(x*oo, x*oo) is S.Zero + assert Add._combine_inverse(-x*oo, -x*oo) is S.Zero + assert Add._combine_inverse((x - oo)*(x + oo), -oo) + + +def test_issue_3773(): + x = symbols('x') + z, phi, r = symbols('z phi r') + c, A, B, N = symbols('c A B N', cls=Wild) + l = Wild('l', exclude=(0,)) + + eq = z * sin(2*phi) * r**7 + matcher = c * sin(phi*N)**l * r**A * log(r)**B + + assert eq.match(matcher) == {c: z, l: 1, N: 2, A: 7, B: 0} + assert (-eq).match(matcher) == {c: -z, l: 1, N: 2, A: 7, B: 0} + assert (x*eq).match(matcher) == {c: x*z, l: 1, N: 2, A: 7, B: 0} + assert (-7*x*eq).match(matcher) == {c: -7*x*z, l: 1, N: 2, A: 7, B: 0} + + matcher = c*sin(phi*N)**l * r**A + + assert eq.match(matcher) == {c: z, l: 1, N: 2, A: 7} + assert (-eq).match(matcher) == {c: -z, l: 1, N: 2, A: 7} + assert (x*eq).match(matcher) == {c: x*z, l: 1, N: 2, A: 7} + assert (-7*x*eq).match(matcher) == {c: -7*x*z, l: 1, N: 2, A: 7} + + +def test_issue_3883(): + from sympy.abc import gamma, mu, x + f = (-gamma * (x - mu)**2 - log(gamma) + log(2*pi))/2 + a, b, c = symbols('a b c', cls=Wild, exclude=(gamma,)) + + assert f.match(a * log(gamma) + b * gamma + c) == \ + {a: Rational(-1, 2), b: -(-mu + x)**2/2, c: log(2*pi)/2} + assert f.expand().collect(gamma).match(a * log(gamma) + b * gamma + c) == \ + {a: Rational(-1, 2), b: (-(x - mu)**2/2).expand(), c: (log(2*pi)/2).expand()} + g1 = Wild('g1', exclude=[gamma]) + g2 = Wild('g2', exclude=[gamma]) + g3 = Wild('g3', exclude=[gamma]) + assert f.expand().match(g1 * log(gamma) + g2 * gamma + g3) == \ + {g3: log(2)/2 + log(pi)/2, g1: Rational(-1, 2), g2: -mu**2/2 + mu*x - x**2/2} + + +def test_issue_4418(): + x = Symbol('x') + a, b, c = symbols('a b c', cls=Wild, exclude=(x,)) + f, g = symbols('f g', cls=Function) + + eq = diff(g(x)*f(x).diff(x), x) + + assert eq.match( + g(x).diff(x)*f(x).diff(x) + g(x)*f(x).diff(x, x) + c) == {c: 0} + assert eq.match(a*g(x).diff( + x)*f(x).diff(x) + b*g(x)*f(x).diff(x, x) + c) == {a: 1, b: 1, c: 0} + + +def test_issue_4700(): + f = Function('f') + x = Symbol('x') + a, b = symbols('a b', cls=Wild, exclude=(f(x),)) + + p = a*f(x) + b + eq1 = sin(x) + eq2 = f(x) + sin(x) + eq3 = f(x) + x + sin(x) + eq4 = x + sin(x) + + assert eq1.match(p) == {a: 0, b: sin(x)} + assert eq2.match(p) == {a: 1, b: sin(x)} + assert eq3.match(p) == {a: 1, b: x + sin(x)} + assert eq4.match(p) == {a: 0, b: x + sin(x)} + + +def test_issue_5168(): + a, b, c = symbols('a b c', cls=Wild) + x = Symbol('x') + f = Function('f') + + assert x.match(a) == {a: x} + assert x.match(a*f(x)**c) == {a: x, c: 0} + assert x.match(a*b) == {a: 1, b: x} + assert x.match(a*b*f(x)**c) == {a: 1, b: x, c: 0} + + assert (-x).match(a) == {a: -x} + assert (-x).match(a*f(x)**c) == {a: -x, c: 0} + assert (-x).match(a*b) == {a: -1, b: x} + assert (-x).match(a*b*f(x)**c) == {a: -1, b: x, c: 0} + + assert (2*x).match(a) == {a: 2*x} + assert (2*x).match(a*f(x)**c) == {a: 2*x, c: 0} + assert (2*x).match(a*b) == {a: 2, b: x} + assert (2*x).match(a*b*f(x)**c) == {a: 2, b: x, c: 0} + + assert (-2*x).match(a) == {a: -2*x} + assert (-2*x).match(a*f(x)**c) == {a: -2*x, c: 0} + assert (-2*x).match(a*b) == {a: -2, b: x} + assert (-2*x).match(a*b*f(x)**c) == {a: -2, b: x, c: 0} + + +def test_issue_4559(): + x = Symbol('x') + e = Symbol('e') + w = Wild('w', exclude=[x]) + y = Wild('y') + + # this is as it should be + + assert (3/x).match(w/y) == {w: 3, y: x} + assert (3*x).match(w*y) == {w: 3, y: x} + assert (x/3).match(y/w) == {w: 3, y: x} + assert (3*x).match(y/w) == {w: S.One/3, y: x} + assert (3*x).match(y/w) == {w: Rational(1, 3), y: x} + + # these could be allowed to fail + + assert (x/3).match(w/y) == {w: S.One/3, y: 1/x} + assert (3*x).match(w/y) == {w: 3, y: 1/x} + assert (3/x).match(w*y) == {w: 3, y: 1/x} + + # Note that solve will give + # multiple roots but match only gives one: + # + # >>> solve(x**r-y**2,y) + # [-x**(r/2), x**(r/2)] + + r = Symbol('r', rational=True) + assert (x**r).match(y**2) == {y: x**(r/2)} + assert (x**e).match(y**2) == {y: sqrt(x**e)} + + # since (x**i = y) -> x = y**(1/i) where i is an integer + # the following should also be valid as long as y is not + # zero when i is negative. + + a = Wild('a') + + e = S.Zero + assert e.match(a) == {a: e} + assert e.match(1/a) is None + assert e.match(a**.3) is None + + e = S(3) + assert e.match(1/a) == {a: 1/e} + assert e.match(1/a**2) == {a: 1/sqrt(e)} + e = pi + assert e.match(1/a) == {a: 1/e} + assert e.match(1/a**2) == {a: 1/sqrt(e)} + assert (-e).match(sqrt(a)) is None + assert (-e).match(a**2) == {a: I*sqrt(pi)} + +# The pattern matcher doesn't know how to handle (x - a)**2 == (a - x)**2. To +# avoid ambiguity in actual applications, don't put a coefficient (including a +# minus sign) in front of a wild. +@XFAIL +def test_issue_4883(): + a = Wild('a') + x = Symbol('x') + + e = [i**2 for i in (x - 2, 2 - x)] + p = [i**2 for i in (x - a, a- x)] + for eq in e: + for pat in p: + assert eq.match(pat) == {a: 2} + + +def test_issue_4319(): + x, y = symbols('x y') + + p = -x*(S.One/8 - y) + ans = {S.Zero, y - S.One/8} + + def ok(pat): + assert set(p.match(pat).values()) == ans + + ok(Wild("coeff", exclude=[x])*x + Wild("rest")) + ok(Wild("w", exclude=[x])*x + Wild("rest")) + ok(Wild("coeff", exclude=[x])*x + Wild("rest")) + ok(Wild("w", exclude=[x])*x + Wild("rest")) + ok(Wild("e", exclude=[x])*x + Wild("rest")) + ok(Wild("ress", exclude=[x])*x + Wild("rest")) + ok(Wild("resu", exclude=[x])*x + Wild("rest")) + + +def test_issue_3778(): + p, c, q = symbols('p c q', cls=Wild) + x = Symbol('x') + + assert (sin(x)**2).match(sin(p)*sin(q)*c) == {q: x, c: 1, p: x} + assert (2*sin(x)).match(sin(p) + sin(q) + c) == {q: x, c: 0, p: x} + + +def test_issue_6103(): + x = Symbol('x') + a = Wild('a') + assert (-I*x*oo).match(I*a*oo) == {a: -x} + + +def test_issue_3539(): + a = Wild('a') + x = Symbol('x') + assert (x - 2).match(a - x) is None + assert (6/x).match(a*x) is None + assert (6/x**2).match(a/x) == {a: 6/x} + +def test_gh_issue_2711(): + x = Symbol('x') + f = meijerg(((), ()), ((0,), ()), x) + a = Wild('a') + b = Wild('b') + + assert f.find(a) == {(S.Zero,), ((), ()), ((S.Zero,), ()), x, S.Zero, + (), meijerg(((), ()), ((S.Zero,), ()), x)} + assert f.find(a + b) == \ + {meijerg(((), ()), ((S.Zero,), ()), x), x, S.Zero} + assert f.find(a**2) == {meijerg(((), ()), ((S.Zero,), ()), x), x} + + +def test_issue_17354(): + from sympy.core.symbol import (Wild, symbols) + x, y = symbols("x y", real=True) + a, b = symbols("a b", cls=Wild) + assert ((0 <= x).reversed | (y <= x)).match((1/a <= b) | (a <= b)) is None + + +def test_match_issue_17397(): + f = Function("f") + x = Symbol("x") + a3 = Wild('a3', exclude=[f(x), f(x).diff(x), f(x).diff(x, 2)]) + b3 = Wild('b3', exclude=[f(x), f(x).diff(x), f(x).diff(x, 2)]) + c3 = Wild('c3', exclude=[f(x), f(x).diff(x), f(x).diff(x, 2)]) + deq = a3*(f(x).diff(x, 2)) + b3*f(x).diff(x) + c3*f(x) + + eq = (x-2)**2*(f(x).diff(x, 2)) + (x-2)*(f(x).diff(x)) + ((x-2)**2 - 4)*f(x) + r = collect(eq, [f(x).diff(x, 2), f(x).diff(x), f(x)]).match(deq) + assert r == {a3: (x - 2)**2, c3: (x - 2)**2 - 4, b3: x - 2} + + eq =x*f(x) + x*Derivative(f(x), (x, 2)) - 4*f(x) + Derivative(f(x), x) \ + - 4*Derivative(f(x), (x, 2)) - 2*Derivative(f(x), x)/x + 4*Derivative(f(x), (x, 2))/x + r = collect(eq, [f(x).diff(x, 2), f(x).diff(x), f(x)]).match(deq) + assert r == {a3: x - 4 + 4/x, b3: 1 - 2/x, c3: x - 4} + + +def test_match_issue_21942(): + a, r, w = symbols('a, r, w', nonnegative=True) + p = symbols('p', positive=True) + g_ = Wild('g') + pattern = g_ ** (1 / (1 - p)) + eq = (a * r ** (1 - p) + w ** (1 - p) * (1 - a)) ** (1 / (1 - p)) + m = {g_: a * r ** (1 - p) + w ** (1 - p) * (1 - a)} + assert pattern.matches(eq) == m + assert (-pattern).matches(-eq) == m + assert pattern.matches(signsimp(eq)) is None + + +def test_match_terms(): + X, Y = map(Wild, "XY") + x, y, z = symbols('x y z') + assert (5*y - x).match(5*X - Y) == {X: y, Y: x} + # 15907 + assert (x + (y - 1)*z).match(x + X*z) == {X: y - 1} + # 20747 + assert (x - log(x/y)*(1-exp(x/y))).match(x - log(X/y)*(1-exp(x/y))) == {X: x} + + +def test_match_bound(): + V, W = map(Wild, "VW") + x, y = symbols('x y') + assert Sum(x, (x, 1, 2)).match(Sum(y, (y, 1, W))) == {W: 2} + assert Sum(x, (x, 1, 2)).match(Sum(V, (V, 1, W))) == {W: 2, V:x} + assert Sum(x, (x, 1, 2)).match(Sum(V, (V, 1, 2))) == {V:x} + + +def test_issue_22462(): + x, f = symbols('x'), Function('f') + n, Q = symbols('n Q', cls=Wild) + pattern = -Q*f(x)**n + eq = 5*f(x)**2 + assert pattern.matches(eq) == {n: 2, Q: -5} diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_multidimensional.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_multidimensional.py new file mode 100644 index 0000000000000000000000000000000000000000..765c78adf8dbed2ead43721ca4ab9510dbeeb282 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_multidimensional.py @@ -0,0 +1,24 @@ +from sympy.core.function import (Derivative, Function, diff) +from sympy.core.symbol import symbols +from sympy.functions.elementary.trigonometric import sin +from sympy.core.multidimensional import vectorize +x, y, z = symbols('x y z') +f, g, h = list(map(Function, 'fgh')) + + +def test_vectorize(): + @vectorize(0) + def vsin(x): + return sin(x) + + assert vsin([1, x, y]) == [sin(1), sin(x), sin(y)] + + @vectorize(0, 1) + def vdiff(f, y): + return diff(f, y) + + assert vdiff([f(x, y, z), g(x, y, z), h(x, y, z)], [x, y, z]) == \ + [[Derivative(f(x, y, z), x), Derivative(f(x, y, z), y), + Derivative(f(x, y, z), z)], [Derivative(g(x, y, z), x), + Derivative(g(x, y, z), y), Derivative(g(x, y, z), z)], + [Derivative(h(x, y, z), x), Derivative(h(x, y, z), y), Derivative(h(x, y, z), z)]] diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_noncommutative.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_noncommutative.py new file mode 100644 index 0000000000000000000000000000000000000000..b3d3a3cec2ef64aa500aad08b438c90cc8987581 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_noncommutative.py @@ -0,0 +1,140 @@ +"""Tests for noncommutative symbols and expressions.""" + +from sympy.core.function import expand +from sympy.core.numbers import I +from sympy.core.symbol import symbols +from sympy.functions.elementary.complexes import (adjoint, conjugate, transpose) +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.polys.polytools import (cancel, factor) +from sympy.simplify.combsimp import combsimp +from sympy.simplify.gammasimp import gammasimp +from sympy.simplify.radsimp import (collect, radsimp, rcollect) +from sympy.simplify.ratsimp import ratsimp +from sympy.simplify.simplify import (posify, simplify) +from sympy.simplify.trigsimp import trigsimp +from sympy.abc import x, y, z +from sympy.testing.pytest import XFAIL + +A, B, C = symbols("A B C", commutative=False) +X = symbols("X", commutative=False, hermitian=True) +Y = symbols("Y", commutative=False, antihermitian=True) + + +def test_adjoint(): + assert adjoint(A).is_commutative is False + assert adjoint(A*A) == adjoint(A)**2 + assert adjoint(A*B) == adjoint(B)*adjoint(A) + assert adjoint(A*B**2) == adjoint(B)**2*adjoint(A) + assert adjoint(A*B - B*A) == adjoint(B)*adjoint(A) - adjoint(A)*adjoint(B) + assert adjoint(A + I*B) == adjoint(A) - I*adjoint(B) + + assert adjoint(X) == X + assert adjoint(-I*X) == I*X + assert adjoint(Y) == -Y + assert adjoint(-I*Y) == -I*Y + + assert adjoint(X) == conjugate(transpose(X)) + assert adjoint(Y) == conjugate(transpose(Y)) + assert adjoint(X) == transpose(conjugate(X)) + assert adjoint(Y) == transpose(conjugate(Y)) + + +def test_cancel(): + assert cancel(A*B - B*A) == A*B - B*A + assert cancel(A*B*(x - 1)) == A*B*(x - 1) + assert cancel(A*B*(x**2 - 1)/(x + 1)) == A*B*(x - 1) + assert cancel(A*B*(x**2 - 1)/(x + 1) - B*A*(x - 1)) == A*B*(x - 1) + (1 - x)*B*A + + +@XFAIL +def test_collect(): + assert collect(A*B - B*A, A) == A*B - B*A + assert collect(A*B - B*A, B) == A*B - B*A + assert collect(A*B - B*A, x) == A*B - B*A + + +def test_combsimp(): + assert combsimp(A*B - B*A) == A*B - B*A + + +def test_gammasimp(): + assert gammasimp(A*B - B*A) == A*B - B*A + + +def test_conjugate(): + assert conjugate(A).is_commutative is False + assert (A*A).conjugate() == conjugate(A)**2 + assert (A*B).conjugate() == conjugate(A)*conjugate(B) + assert (A*B**2).conjugate() == conjugate(A)*conjugate(B)**2 + assert (A*B - B*A).conjugate() == \ + conjugate(A)*conjugate(B) - conjugate(B)*conjugate(A) + assert (A*B).conjugate() - (B*A).conjugate() == \ + conjugate(A)*conjugate(B) - conjugate(B)*conjugate(A) + assert (A + I*B).conjugate() == conjugate(A) - I*conjugate(B) + + +def test_expand(): + assert expand((A*B)**2) == A*B*A*B + assert expand(A*B - B*A) == A*B - B*A + assert expand((A*B/A)**2) == A*B*B/A + assert expand(B*A*(A + B)*B) == B*A**2*B + B*A*B**2 + assert expand(B*A*(A + C)*B) == B*A**2*B + B*A*C*B + + +def test_factor(): + assert factor(A*B - B*A) == A*B - B*A + + +def test_posify(): + assert posify(A)[0].is_commutative is False + for q in (A*B/A, (A*B/A)**2, (A*B)**2, A*B - B*A): + p = posify(q) + assert p[0].subs(p[1]) == q + + +def test_radsimp(): + assert radsimp(A*B - B*A) == A*B - B*A + + +@XFAIL +def test_ratsimp(): + assert ratsimp(A*B - B*A) == A*B - B*A + + +@XFAIL +def test_rcollect(): + assert rcollect(A*B - B*A, A) == A*B - B*A + assert rcollect(A*B - B*A, B) == A*B - B*A + assert rcollect(A*B - B*A, x) == A*B - B*A + + +def test_simplify(): + assert simplify(A*B - B*A) == A*B - B*A + + +def test_subs(): + assert (x*y*A).subs(x*y, z) == A*z + assert (x*A*B).subs(x*A, C) == C*B + assert (x*A*x*x).subs(x**2*A, C) == x*C + assert (x*A*x*B).subs(x**2*A, C) == C*B + assert (A**2*B**2).subs(A*B**2, C) == A*C + assert (A*A*A + A*B*A).subs(A*A*A, C) == C + A*B*A + + +def test_transpose(): + assert transpose(A).is_commutative is False + assert transpose(A*A) == transpose(A)**2 + assert transpose(A*B) == transpose(B)*transpose(A) + assert transpose(A*B**2) == transpose(B)**2*transpose(A) + assert transpose(A*B - B*A) == \ + transpose(B)*transpose(A) - transpose(A)*transpose(B) + assert transpose(A + I*B) == transpose(A) + I*transpose(B) + + assert transpose(X) == conjugate(X) + assert transpose(-I*X) == -I*conjugate(X) + assert transpose(Y) == -conjugate(Y) + assert transpose(-I*Y) == I*conjugate(Y) + + +def test_trigsimp(): + assert trigsimp(A*sin(x)**2 + A*cos(x)**2) == A diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_numbers.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_numbers.py new file mode 100644 index 0000000000000000000000000000000000000000..054fd7591b28d352b648c98d78cdda10a4fe2cb1 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_numbers.py @@ -0,0 +1,2300 @@ +import numbers as nums +import decimal +from sympy.concrete.summations import Sum +from sympy.core import (EulerGamma, Catalan, TribonacciConstant, + GoldenRatio) +from sympy.core.containers import Tuple +from sympy.core.expr import unchanged +from sympy.core.logic import fuzzy_not +from sympy.core.mul import Mul +from sympy.core.numbers import (mpf_norm, seterr, + Integer, I, pi, comp, Rational, E, nan, + oo, AlgebraicNumber, Number, Float, zoo, equal_valued, + int_valued, all_close) +from sympy.core.intfunc import (igcd, igcdex, igcd2, igcd_lehmer, + ilcm, integer_nthroot, isqrt, integer_log, mod_inverse) +from sympy.core.power import Pow +from sympy.core.relational import Ge, Gt, Le, Lt +from sympy.core.singleton import S +from sympy.core.symbol import Dummy, Symbol +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.integers import floor +from sympy.functions.combinatorial.numbers import fibonacci +from sympy.functions.elementary.exponential import exp, log +from sympy.functions.elementary.miscellaneous import sqrt, cbrt +from sympy.functions.elementary.trigonometric import cos, sin +from sympy.polys.domains.realfield import RealField +from sympy.printing.latex import latex +from sympy.printing.repr import srepr +from sympy.simplify import simplify +from sympy.polys.domains.groundtypes import PythonRational +from sympy.utilities.decorator import conserve_mpmath_dps +from sympy.utilities.iterables import permutations +from sympy.testing.pytest import XFAIL, raises, _both_exp_pow +from sympy import Add + +from mpmath import mpf +import mpmath +from sympy.core import numbers +t = Symbol('t', real=False) + +_ninf = float(-oo) +_inf = float(oo) + + +def same_and_same_prec(a, b): + # stricter matching for Floats + return a == b and a._prec == b._prec + + +def test_seterr(): + seterr(divide=True) + raises(ValueError, lambda: S.Zero/S.Zero) + seterr(divide=False) + assert S.Zero / S.Zero is S.NaN + + +def test_mod(): + x = S.Half + y = Rational(3, 4) + z = Rational(5, 18043) + + assert x % x == 0 + assert x % y == S.Half + assert x % z == Rational(3, 36086) + assert y % x == Rational(1, 4) + assert y % y == 0 + assert y % z == Rational(9, 72172) + assert z % x == Rational(5, 18043) + assert z % y == Rational(5, 18043) + assert z % z == 0 + + a = Float(2.6) + + assert (a % .2) == 0.0 + assert (a % 2).round(15) == 0.6 + assert (a % 0.5).round(15) == 0.1 + + p = Symbol('p', infinite=True) + + assert oo % oo is nan + assert zoo % oo is nan + assert 5 % oo is nan + assert p % 5 is nan + + # In these two tests, if the precision of m does + # not match the precision of the ans, then it is + # likely that the change made now gives an answer + # with degraded accuracy. + r = Rational(500, 41) + f = Float('.36', 3) + m = r % f + ans = Float(r % Rational(f), 3) + assert m == ans and m._prec == ans._prec + f = Float('8.36', 3) + m = f % r + ans = Float(Rational(f) % r, 3) + assert m == ans and m._prec == ans._prec + + s = S.Zero + + assert s % float(1) == 0.0 + + # No rounding required since these numbers can be represented + # exactly. + assert Rational(3, 4) % Float(1.1) == 0.75 + assert Float(1.5) % Rational(5, 4) == 0.25 + assert Rational(5, 4).__rmod__(Float('1.5')) == 0.25 + assert Float('1.5').__rmod__(Float('2.75')) == Float('1.25') + assert 2.75 % Float('1.5') == Float('1.25') + + a = Integer(7) + b = Integer(4) + + assert type(a % b) == Integer + assert a % b == Integer(3) + assert Integer(1) % Rational(2, 3) == Rational(1, 3) + assert Rational(7, 5) % Integer(1) == Rational(2, 5) + assert Integer(2) % 1.5 == 0.5 + + assert Integer(3).__rmod__(Integer(10)) == Integer(1) + assert Integer(10) % 4 == Integer(2) + assert 15 % Integer(4) == Integer(3) + + +def test_divmod(): + x = Symbol("x") + assert divmod(S(12), S(8)) == Tuple(1, 4) + assert divmod(-S(12), S(8)) == Tuple(-2, 4) + assert divmod(S.Zero, S.One) == Tuple(0, 0) + raises(ZeroDivisionError, lambda: divmod(S.Zero, S.Zero)) + raises(ZeroDivisionError, lambda: divmod(S.One, S.Zero)) + assert divmod(S(12), 8) == Tuple(1, 4) + assert divmod(12, S(8)) == Tuple(1, 4) + assert S(1024)//x == 1024//x == floor(1024/x) + + assert divmod(S("2"), S("3/2")) == Tuple(S("1"), S("1/2")) + assert divmod(S("3/2"), S("2")) == Tuple(S("0"), S("3/2")) + assert divmod(S("2"), S("3.5")) == Tuple(S("0"), S("2.")) + assert divmod(S("3.5"), S("2")) == Tuple(S("1"), S("1.5")) + assert divmod(S("2"), S("1/3")) == Tuple(S("6"), S("0")) + assert divmod(S("1/3"), S("2")) == Tuple(S("0"), S("1/3")) + assert divmod(S("2"), S("1/10")) == Tuple(S("20"), S("0")) + assert divmod(S("2"), S(".1"))[0] == 19 + assert divmod(S("0.1"), S("2")) == Tuple(S("0"), S("0.1")) + assert divmod(S("2"), 2) == Tuple(S("1"), S("0")) + assert divmod(2, S("2")) == Tuple(S("1"), S("0")) + assert divmod(S("2"), 1.5) == Tuple(S("1"), S("0.5")) + assert divmod(1.5, S("2")) == Tuple(S("0"), S("1.5")) + assert divmod(0.3, S("2")) == Tuple(S("0"), S("0.3")) + assert divmod(S("3/2"), S("3.5")) == Tuple(S("0"), S(3/2)) + assert divmod(S("3.5"), S("3/2")) == Tuple(S("2"), S("0.5")) + assert divmod(S("3/2"), S("1/3")) == Tuple(S("4"), S("1/6")) + assert divmod(S("1/3"), S("3/2")) == Tuple(S("0"), S("1/3")) + assert divmod(S("3/2"), S("0.1"))[0] == 14 + assert divmod(S("0.1"), S("3/2")) == Tuple(S("0"), S("0.1")) + assert divmod(S("3/2"), 2) == Tuple(S("0"), S("3/2")) + assert divmod(2, S("3/2")) == Tuple(S("1"), S("1/2")) + assert divmod(S("3/2"), 1.5) == Tuple(S("1"), S("0.")) + assert divmod(1.5, S("3/2")) == Tuple(S("1"), S("0.")) + assert divmod(S("3/2"), 0.3) == Tuple(S("5"), S("0.")) + assert divmod(0.3, S("3/2")) == Tuple(S("0"), S("0.3")) + assert divmod(S("1/3"), S("3.5")) == (0, 1/3) + assert divmod(S("3.5"), S("0.1")) == Tuple(S("35"), S("0.")) + assert divmod(S("0.1"), S("3.5")) == Tuple(S("0"), S("0.1")) + assert divmod(S("3.5"), 2) == Tuple(S("1"), S("1.5")) + assert divmod(2, S("3.5")) == Tuple(S("0"), S("2.")) + assert divmod(S("3.5"), 1.5) == Tuple(S("2"), S("0.5")) + assert divmod(1.5, S("3.5")) == Tuple(S("0"), S("1.5")) + assert divmod(0.3, S("3.5")) == Tuple(S("0"), S("0.3")) + assert divmod(S("0.1"), S("1/3")) == Tuple(S("0"), S("0.1")) + assert divmod(S("1/3"), 2) == Tuple(S("0"), S("1/3")) + assert divmod(2, S("1/3")) == Tuple(S("6"), S("0")) + assert divmod(S("1/3"), 1.5) == (0, 1/3) + assert divmod(0.3, S("1/3")) == (0, 0.3) + assert divmod(S("0.1"), 2) == (0, 0.1) + assert divmod(2, S("0.1"))[0] == 19 + assert divmod(S("0.1"), 1.5) == (0, 0.1) + assert divmod(1.5, S("0.1")) == Tuple(S("15"), S("0.")) + assert divmod(S("0.1"), 0.3) == Tuple(S("0"), S("0.1")) + + assert str(divmod(S("2"), 0.3)) == '(6, 0.2)' + assert str(divmod(S("3.5"), S("1/3"))) == '(10, 0.166666666666667)' + assert str(divmod(S("3.5"), 0.3)) == '(11, 0.2)' + assert str(divmod(S("1/3"), S("0.1"))) == '(3, 0.0333333333333333)' + assert str(divmod(1.5, S("1/3"))) == '(4, 0.166666666666667)' + assert str(divmod(S("1/3"), 0.3)) == '(1, 0.0333333333333333)' + assert str(divmod(0.3, S("0.1"))) == '(2, 0.1)' + + assert divmod(-3, S(2)) == (-2, 1) + assert divmod(S(-3), S(2)) == (-2, 1) + assert divmod(S(-3), 2) == (-2, 1) + + assert divmod(oo, 1) == (S.NaN, S.NaN) + assert divmod(S.NaN, 1) == (S.NaN, S.NaN) + assert divmod(1, S.NaN) == (S.NaN, S.NaN) + ans = [(-1, oo), (-1, oo), (0, 0), (0, 1), (0, 2)] + OO = float('inf') + ANS = [tuple(map(float, i)) for i in ans] + assert [divmod(i, oo) for i in range(-2, 3)] == ans + ans = [(0, -2), (0, -1), (0, 0), (-1, -oo), (-1, -oo)] + ANS = [tuple(map(float, i)) for i in ans] + assert [divmod(i, -oo) for i in range(-2, 3)] == ans + assert [divmod(i, -OO) for i in range(-2, 3)] == ANS + + # sympy's divmod gives an Integer for the quotient rather than a float + dmod = lambda a, b: tuple([j if i else int(j) for i, j in enumerate(divmod(a, b))]) + for a in (4, 4., 4.25, 0, 0., -4, -4. -4.25): + for b in (2, 2., 2.5, -2, -2., -2.5): + assert divmod(S(a), S(b)) == dmod(a, b) + + +def test_igcd(): + assert igcd(0, 0) == 0 + assert igcd(0, 1) == 1 + assert igcd(1, 0) == 1 + assert igcd(0, 7) == 7 + assert igcd(7, 0) == 7 + assert igcd(7, 1) == 1 + assert igcd(1, 7) == 1 + assert igcd(-1, 0) == 1 + assert igcd(0, -1) == 1 + assert igcd(-1, -1) == 1 + assert igcd(-1, 7) == 1 + assert igcd(7, -1) == 1 + assert igcd(8, 2) == 2 + assert igcd(4, 8) == 4 + assert igcd(8, 16) == 8 + assert igcd(7, -3) == 1 + assert igcd(-7, 3) == 1 + assert igcd(-7, -3) == 1 + assert igcd(*[10, 20, 30]) == 10 + raises(TypeError, lambda: igcd()) + raises(TypeError, lambda: igcd(2)) + raises(ValueError, lambda: igcd(0, None)) + raises(ValueError, lambda: igcd(1, 2.2)) + for args in permutations((45.1, 1, 30)): + raises(ValueError, lambda: igcd(*args)) + for args in permutations((1, 2, None)): + raises(ValueError, lambda: igcd(*args)) + + +def test_igcd_lehmer(): + a, b = fibonacci(10001), fibonacci(10000) + # len(str(a)) == 2090 + # small divisors, long Euclidean sequence + assert igcd_lehmer(a, b) == 1 + c = fibonacci(100) + assert igcd_lehmer(a*c, b*c) == c + # big divisor + assert igcd_lehmer(a, 10**1000) == 1 + # swapping argument + assert igcd_lehmer(1, 2) == igcd_lehmer(2, 1) + + +def test_igcd2(): + # short loop + assert igcd2(2**100 - 1, 2**99 - 1) == 1 + # Lehmer's algorithm + a, b = int(fibonacci(10001)), int(fibonacci(10000)) + assert igcd2(a, b) == 1 + + +def test_ilcm(): + assert ilcm(0, 0) == 0 + assert ilcm(1, 0) == 0 + assert ilcm(0, 1) == 0 + assert ilcm(1, 1) == 1 + assert ilcm(2, 1) == 2 + assert ilcm(8, 2) == 8 + assert ilcm(8, 6) == 24 + assert ilcm(8, 7) == 56 + assert ilcm(*[10, 20, 30]) == 60 + raises(ValueError, lambda: ilcm(8.1, 7)) + raises(ValueError, lambda: ilcm(8, 7.1)) + raises(TypeError, lambda: ilcm(8)) + + +def test_igcdex(): + assert igcdex(2, 3) == (-1, 1, 1) + assert igcdex(10, 12) == (-1, 1, 2) + assert igcdex(100, 2004) == (-20, 1, 4) + assert igcdex(0, 0) == (0, 1, 0) + assert igcdex(1, 0) == (1, 0, 1) + + +def _strictly_equal(a, b): + return (a.p, a.q, type(a.p), type(a.q)) == \ + (b.p, b.q, type(b.p), type(b.q)) + + +def _test_rational_new(cls): + """ + Tests that are common between Integer and Rational. + """ + assert cls(0) is S.Zero + assert cls(1) is S.One + assert cls(-1) is S.NegativeOne + # These look odd, but are similar to int(): + assert cls('1') is S.One + assert cls('-1') is S.NegativeOne + + i = Integer(10) + assert _strictly_equal(i, cls('10')) + assert _strictly_equal(i, cls('10')) + assert _strictly_equal(i, cls(int(10))) + assert _strictly_equal(i, cls(i)) + + raises(TypeError, lambda: cls(Symbol('x'))) + + +def test_Integer_new(): + """ + Test for Integer constructor + """ + _test_rational_new(Integer) + + assert _strictly_equal(Integer(0.9), S.Zero) + assert _strictly_equal(Integer(10.5), Integer(10)) + raises(ValueError, lambda: Integer("10.5")) + assert Integer(Rational('1.' + '9'*20)) == 1 + + +def test_Rational_new(): + """" + Test for Rational constructor + """ + _test_rational_new(Rational) + + n1 = S.Half + assert n1 == Rational(Integer(1), 2) + assert n1 == Rational(Integer(1), Integer(2)) + assert n1 == Rational(1, Integer(2)) + assert n1 == Rational(S.Half) + assert 1 == Rational(n1, n1) + assert Rational(3, 2) == Rational(S.Half, Rational(1, 3)) + assert Rational(3, 1) == Rational(1, Rational(1, 3)) + n3_4 = Rational(3, 4) + assert Rational('3/4') == n3_4 + assert -Rational('-3/4') == n3_4 + assert Rational('.76').limit_denominator(4) == n3_4 + assert Rational(19, 25).limit_denominator(4) == n3_4 + assert Rational('19/25').limit_denominator(4) == n3_4 + assert Rational(1.0, 3) == Rational(1, 3) + assert Rational(1, 3.0) == Rational(1, 3) + assert Rational(Float(0.5)) == S.Half + assert Rational('1e2/1e-2') == Rational(10000) + assert Rational('1 234') == Rational(1234) + assert Rational('1/1 234') == Rational(1, 1234) + assert Rational(-1, 0) is S.ComplexInfinity + assert Rational(1, 0) is S.ComplexInfinity + # Make sure Rational doesn't lose precision on Floats + assert Rational(pi.evalf(100)).evalf(100) == pi.evalf(100) + raises(TypeError, lambda: Rational('3**3')) + raises(TypeError, lambda: Rational('1/2 + 2/3')) + + # handle fractions.Fraction instances + try: + import fractions + assert Rational(fractions.Fraction(1, 2)) == S.Half + except ImportError: + pass + + assert Rational(PythonRational(2, 6)) == Rational(1, 3) + + assert Rational(2, 4, gcd=1).q == 4 + n = Rational(2, -4, gcd=1) + assert n.q == 4 + assert n.p == -2 + +def test_issue_24543(): + for p in ('1.5', 1.5, 2): + for q in ('1.5', 1.5, 2): + assert Rational(p, q).as_numer_denom() == Rational('%s/%s'%(p,q)).as_numer_denom() + + assert Rational('0.5', '100') == Rational(1, 200) + + +def test_Number_new(): + """" + Test for Number constructor + """ + # Expected behavior on numbers and strings + assert Number(1) is S.One + assert Number(2).__class__ is Integer + assert Number(-622).__class__ is Integer + assert Number(5, 3).__class__ is Rational + assert Number(5.3).__class__ is Float + assert Number('1') is S.One + assert Number('2').__class__ is Integer + assert Number('-622').__class__ is Integer + assert Number('5/3').__class__ is Rational + assert Number('5.3').__class__ is Float + raises(ValueError, lambda: Number('cos')) + raises(TypeError, lambda: Number(cos)) + a = Rational(3, 5) + assert Number(a) is a # Check idempotence on Numbers + u = ['inf', '-inf', 'nan', 'iNF', '+inf'] + v = [oo, -oo, nan, oo, oo] + for i, a in zip(u, v): + assert Number(i) is a, (i, Number(i), a) + + +def test_Number_cmp(): + n1 = Number(1) + n2 = Number(2) + n3 = Number(-3) + + assert n1 < n2 + assert n1 <= n2 + assert n3 < n1 + assert n2 > n3 + assert n2 >= n3 + + raises(TypeError, lambda: n1 < S.NaN) + raises(TypeError, lambda: n1 <= S.NaN) + raises(TypeError, lambda: n1 > S.NaN) + raises(TypeError, lambda: n1 >= S.NaN) + + +def test_Rational_cmp(): + n1 = Rational(1, 4) + n2 = Rational(1, 3) + n3 = Rational(2, 4) + n4 = Rational(2, -4) + n5 = Rational(0) + n6 = Rational(1) + n7 = Rational(3) + n8 = Rational(-3) + + assert n8 < n5 + assert n5 < n6 + assert n6 < n7 + assert n8 < n7 + assert n7 > n8 + assert (n1 + 1)**n2 < 2 + assert ((n1 + n6)/n7) < 1 + + assert n4 < n3 + assert n2 < n3 + assert n1 < n2 + assert n3 > n1 + assert not n3 < n1 + assert not (Rational(-1) > 0) + assert Rational(-1) < 0 + + raises(TypeError, lambda: n1 < S.NaN) + raises(TypeError, lambda: n1 <= S.NaN) + raises(TypeError, lambda: n1 > S.NaN) + raises(TypeError, lambda: n1 >= S.NaN) + + +def test_Float(): + def eq(a, b): + t = Float("1.0E-15") + return (-t < a - b < t) + + zeros = (0, S.Zero, 0., Float(0)) + for i, j in permutations(zeros[:-1], 2): + assert i == j + for i, j in permutations(zeros[-2:], 2): + assert i == j + for z in zeros: + assert z in zeros + assert S.Zero.is_zero + + a = Float(2) ** Float(3) + assert eq(a.evalf(), Float(8)) + assert eq((pi ** -1).evalf(), Float("0.31830988618379067")) + a = Float(2) ** Float(4) + assert eq(a.evalf(), Float(16)) + assert (S(.3) == S(.5)) is False + + mpf = (0, 5404319552844595, -52, 53) + x_str = Float((0, '13333333333333', -52, 53)) + x_0xstr = Float((0, '0x13333333333333', -52, 53)) + x2_str = Float((0, '26666666666666', -53, 54)) + x_hex = Float((0, int(0x13333333333333), -52, 53)) + x_dec = Float(mpf) + assert x_str == x_0xstr == x_hex == x_dec == Float(1.2) + # x2_str was entered slightly malformed in that the mantissa + # was even -- it should be odd and the even part should be + # included with the exponent, but this is resolved by normalization + # ONLY IF REQUIREMENTS of mpf_norm are met: the bitcount must + # be exact: double the mantissa ==> increase bc by 1 + assert Float(1.2)._mpf_ == mpf + assert x2_str._mpf_ == mpf + + assert Float((0, int(0), -123, -1)) is S.NaN + assert Float((0, int(0), -456, -2)) is S.Infinity + assert Float((1, int(0), -789, -3)) is S.NegativeInfinity + # if you don't give the full signature, it's not special + assert Float((0, int(0), -123)) == Float(0) + assert Float((0, int(0), -456)) == Float(0) + assert Float((1, int(0), -789)) == Float(0) + + raises(ValueError, lambda: Float((0, 7, 1, 3), '')) + + assert Float('0.0').is_finite is True + assert Float('0.0').is_negative is False + assert Float('0.0').is_positive is False + assert Float('0.0').is_infinite is False + assert Float('0.0').is_zero is True + + # rationality properties + # if the integer test fails then the use of intlike + # should be removed from gamma_functions.py + assert Float(1).is_integer is None + assert Float(1).is_rational is None + assert Float(1).is_irrational is None + assert sqrt(2).n(15).is_rational is None + assert sqrt(2).n(15).is_irrational is None + + # do not automatically evalf + def teq(a): + assert (a.evalf() == a) is False + assert (a.evalf() != a) is True + assert (a == a.evalf()) is False + assert (a != a.evalf()) is True + + teq(pi) + teq(2*pi) + teq(cos(0.1, evaluate=False)) + + # long integer + i = 12345678901234567890 + assert same_and_same_prec(Float(12, ''), Float('12', '')) + assert same_and_same_prec(Float(Integer(i), ''), Float(i, '')) + assert same_and_same_prec(Float(i, ''), Float(str(i), 20)) + assert same_and_same_prec(Float(str(i)), Float(i, '')) + assert same_and_same_prec(Float(i), Float(i, '')) + + # inexact floats (repeating binary = denom not multiple of 2) + # cannot have precision greater than 15 + assert Float(.125, 22)._prec == 76 + assert Float(2.0, 22)._prec == 76 + # only default prec is equal, even for exactly representable float + assert Float(.125, 22) != .125 + #assert Float(2.0, 22) == 2 + assert float(Float('.12500000000000001', '')) == .125 + raises(ValueError, lambda: Float(.12500000000000001, '')) + + # allow spaces + assert Float('123 456.123 456') == Float('123456.123456') + assert Integer('123 456') == Integer('123456') + assert Rational('123 456.123 456') == Rational('123456.123456') + assert Float(' .3e2') == Float('0.3e2') + # but treat them as strictly ass underscore between digits: only 1 + raises(ValueError, lambda: Float('1 2')) + + # allow underscore between digits + assert Float('1_23.4_56') == Float('123.456') + # assert Float('1_23.4_5_6', 12) == Float('123.456', 12) + # ...but not in all cases (per Py 3.6) + raises(ValueError, lambda: Float('1_')) + raises(ValueError, lambda: Float('1__2')) + raises(ValueError, lambda: Float('_1')) + raises(ValueError, lambda: Float('_inf')) + + # allow auto precision detection + assert Float('.1', '') == Float(.1, 1) + assert Float('.125', '') == Float(.125, 3) + assert Float('.100', '') == Float(.1, 3) + assert Float('2.0', '') == Float('2', 2) + + raises(ValueError, lambda: Float("12.3d-4", "")) + raises(ValueError, lambda: Float(12.3, "")) + raises(ValueError, lambda: Float('.')) + raises(ValueError, lambda: Float('-.')) + + zero = Float('0.0') + assert Float('-0') == zero + assert Float('.0') == zero + assert Float('-.0') == zero + assert Float('-0.0') == zero + assert Float(0.0) == zero + assert Float(0) == zero + assert Float(0, '') == Float('0', '') + assert Float(1) == Float(1.0) + assert Float(S.Zero) == zero + assert Float(S.One) == Float(1.0) + + assert Float(decimal.Decimal('0.1'), 3) == Float('.1', 3) + assert Float(decimal.Decimal('nan')) is S.NaN + assert Float(decimal.Decimal('Infinity')) is S.Infinity + assert Float(decimal.Decimal('-Infinity')) is S.NegativeInfinity + + assert '{:.3f}'.format(Float(4.236622)) == '4.237' + assert '{:.35f}'.format(Float(pi.n(40), 40)) == \ + '3.14159265358979323846264338327950288' + + # unicode + assert Float('0.73908513321516064100000000') == \ + Float('0.73908513321516064100000000') + assert Float('0.73908513321516064100000000', 28) == \ + Float('0.73908513321516064100000000', 28) + + # binary precision + # Decimal value 0.1 cannot be expressed precisely as a base 2 fraction + a = Float(S.One/10, dps=15) + b = Float(S.One/10, dps=16) + p = Float(S.One/10, precision=53) + q = Float(S.One/10, precision=54) + assert a._mpf_ == p._mpf_ + assert not a._mpf_ == q._mpf_ + assert not b._mpf_ == q._mpf_ + + # Precision specifying errors + raises(ValueError, lambda: Float("1.23", dps=3, precision=10)) + raises(ValueError, lambda: Float("1.23", dps="", precision=10)) + raises(ValueError, lambda: Float("1.23", dps=3, precision="")) + raises(ValueError, lambda: Float("1.23", dps="", precision="")) + + # from NumberSymbol + assert same_and_same_prec(Float(pi, 32), pi.evalf(32)) + assert same_and_same_prec(Float(Catalan), Catalan.evalf()) + + # oo and nan + u = ['inf', '-inf', 'nan', 'iNF', '+inf'] + v = [oo, -oo, nan, oo, oo] + for i, a in zip(u, v): + assert Float(i) is a + + +def test_zero_not_false(): + # https://github.com/sympy/sympy/issues/20796 + assert (S(0.0) == S.false) is False + assert (S.false == S(0.0)) is False + assert (S(0) == S.false) is False + assert (S.false == S(0)) is False + + +@conserve_mpmath_dps +def test_float_mpf(): + import mpmath + mpmath.mp.dps = 100 + mp_pi = mpmath.pi() + + assert Float(mp_pi, 100) == Float(mp_pi._mpf_, 100) == pi.evalf(100) + + mpmath.mp.dps = 15 + + assert Float(mp_pi, 100) == Float(mp_pi._mpf_, 100) == pi.evalf(100) + + +def test_Float_RealElement(): + repi = RealField(dps=100)(pi.evalf(100)) + # We still have to pass the precision because Float doesn't know what + # RealElement is, but make sure it keeps full precision from the result. + assert Float(repi, 100) == pi.evalf(100) + + +def test_Float_default_to_highprec_from_str(): + s = str(pi.evalf(128)) + assert same_and_same_prec(Float(s), Float(s, '')) + + +def test_Float_eval(): + a = Float(3.2) + assert (a**2).is_Float + + +def test_Float_issue_2107(): + a = Float(0.1, 10) + b = Float("0.1", 10) + + assert a - a == 0 + assert a + (-a) == 0 + assert S.Zero + a - a == 0 + assert S.Zero + a + (-a) == 0 + + assert b - b == 0 + assert b + (-b) == 0 + assert S.Zero + b - b == 0 + assert S.Zero + b + (-b) == 0 + + +def test_issue_14289(): + from sympy.polys.numberfields import to_number_field + + a = 1 - sqrt(2) + b = to_number_field(a) + assert b.as_expr() == a + assert b.minpoly(a).expand() == 0 + + +def test_Float_from_tuple(): + a = Float((0, '1L', 0, 1)) + b = Float((0, '1', 0, 1)) + assert a == b + + +def test_Infinity(): + assert oo != 1 + assert 1*oo is oo + assert 1 != oo + assert oo != -oo + assert oo != Symbol("x")**3 + assert oo + 1 is oo + assert 2 + oo is oo + assert 3*oo + 2 is oo + assert S.Half**oo == 0 + assert S.Half**(-oo) is oo + assert -oo*3 is -oo + assert oo + oo is oo + assert -oo + oo*(-5) is -oo + assert 1/oo == 0 + assert 1/(-oo) == 0 + assert 8/oo == 0 + assert oo % 2 is nan + assert 2 % oo is nan + assert oo/oo is nan + assert oo/-oo is nan + assert -oo/oo is nan + assert -oo/-oo is nan + assert oo - oo is nan + assert oo - -oo is oo + assert -oo - oo is -oo + assert -oo - -oo is nan + assert oo + -oo is nan + assert -oo + oo is nan + assert oo + oo is oo + assert -oo + oo is nan + assert oo + -oo is nan + assert -oo + -oo is -oo + assert oo*oo is oo + assert -oo*oo is -oo + assert oo*-oo is -oo + assert -oo*-oo is oo + assert oo/0 is oo + assert -oo/0 is -oo + assert 0/oo == 0 + assert 0/-oo == 0 + assert oo*0 is nan + assert -oo*0 is nan + assert 0*oo is nan + assert 0*-oo is nan + assert oo + 0 is oo + assert -oo + 0 is -oo + assert 0 + oo is oo + assert 0 + -oo is -oo + assert oo - 0 is oo + assert -oo - 0 is -oo + assert 0 - oo is -oo + assert 0 - -oo is oo + assert oo/2 is oo + assert -oo/2 is -oo + assert oo/-2 is -oo + assert -oo/-2 is oo + assert oo*2 is oo + assert -oo*2 is -oo + assert oo*-2 is -oo + assert 2/oo == 0 + assert 2/-oo == 0 + assert -2/oo == 0 + assert -2/-oo == 0 + assert 2*oo is oo + assert 2*-oo is -oo + assert -2*oo is -oo + assert -2*-oo is oo + assert 2 + oo is oo + assert 2 - oo is -oo + assert -2 + oo is oo + assert -2 - oo is -oo + assert 2 + -oo is -oo + assert 2 - -oo is oo + assert -2 + -oo is -oo + assert -2 - -oo is oo + assert S(2) + oo is oo + assert S(2) - oo is -oo + assert oo/I == -oo*I + assert -oo/I == oo*I + assert oo*float(1) == _inf and (oo*float(1)) is oo + assert -oo*float(1) == _ninf and (-oo*float(1)) is -oo + assert oo/float(1) == _inf and (oo/float(1)) is oo + assert -oo/float(1) == _ninf and (-oo/float(1)) is -oo + assert oo*float(-1) == _ninf and (oo*float(-1)) is -oo + assert -oo*float(-1) == _inf and (-oo*float(-1)) is oo + assert oo/float(-1) == _ninf and (oo/float(-1)) is -oo + assert -oo/float(-1) == _inf and (-oo/float(-1)) is oo + assert oo + float(1) == _inf and (oo + float(1)) is oo + assert -oo + float(1) == _ninf and (-oo + float(1)) is -oo + assert oo - float(1) == _inf and (oo - float(1)) is oo + assert -oo - float(1) == _ninf and (-oo - float(1)) is -oo + assert float(1)*oo == _inf and (float(1)*oo) is oo + assert float(1)*-oo == _ninf and (float(1)*-oo) is -oo + assert float(1)/oo == 0 + assert float(1)/-oo == 0 + assert float(-1)*oo == _ninf and (float(-1)*oo) is -oo + assert float(-1)*-oo == _inf and (float(-1)*-oo) is oo + assert float(-1)/oo == 0 + assert float(-1)/-oo == 0 + assert float(1) + oo is oo + assert float(1) + -oo is -oo + assert float(1) - oo is -oo + assert float(1) - -oo is oo + assert oo == float(oo) + assert (oo != float(oo)) is False + assert type(float(oo)) is float + assert -oo == float(-oo) + assert (-oo != float(-oo)) is False + assert type(float(-oo)) is float + + assert Float('nan') is nan + assert nan*1.0 is nan + assert -1.0*nan is nan + assert nan*oo is nan + assert nan*-oo is nan + assert nan/oo is nan + assert nan/-oo is nan + assert nan + oo is nan + assert nan + -oo is nan + assert nan - oo is nan + assert nan - -oo is nan + assert -oo * S.Zero is nan + + assert oo*nan is nan + assert -oo*nan is nan + assert oo/nan is nan + assert -oo/nan is nan + assert oo + nan is nan + assert -oo + nan is nan + assert oo - nan is nan + assert -oo - nan is nan + assert S.Zero * oo is nan + assert oo.is_Rational is False + assert isinstance(oo, Rational) is False + + assert S.One/oo == 0 + assert -S.One/oo == 0 + assert S.One/-oo == 0 + assert -S.One/-oo == 0 + assert S.One*oo is oo + assert -S.One*oo is -oo + assert S.One*-oo is -oo + assert -S.One*-oo is oo + assert S.One/nan is nan + assert S.One - -oo is oo + assert S.One + nan is nan + assert S.One - nan is nan + assert nan - S.One is nan + assert nan/S.One is nan + assert -oo - S.One is -oo + + +def test_Infinity_2(): + x = Symbol('x') + assert oo*x != oo + assert oo*(pi - 1) is oo + assert oo*(1 - pi) is -oo + + assert (-oo)*x != -oo + assert (-oo)*(pi - 1) is -oo + assert (-oo)*(1 - pi) is oo + + assert (-1)**S.NaN is S.NaN + assert oo - _inf is S.NaN + assert oo + _ninf is S.NaN + assert oo*0 is S.NaN + assert oo/_inf is S.NaN + assert oo/_ninf is S.NaN + assert oo**S.NaN is S.NaN + assert -oo + _inf is S.NaN + assert -oo - _ninf is S.NaN + assert -oo*S.NaN is S.NaN + assert -oo*0 is S.NaN + assert -oo/_inf is S.NaN + assert -oo/_ninf is S.NaN + assert -oo/S.NaN is S.NaN + assert abs(-oo) is oo + assert all((-oo)**i is S.NaN for i in (oo, -oo, S.NaN)) + assert (-oo)**3 is -oo + assert (-oo)**2 is oo + assert abs(S.ComplexInfinity) is oo + + +def test_Mul_Infinity_Zero(): + assert Float(0)*_inf is nan + assert Float(0)*_ninf is nan + assert Float(0)*_inf is nan + assert Float(0)*_ninf is nan + assert _inf*Float(0) is nan + assert _ninf*Float(0) is nan + assert _inf*Float(0) is nan + assert _ninf*Float(0) is nan + + +def test_Div_By_Zero(): + assert 1/S.Zero is zoo + assert 1/Float(0) is zoo + assert 0/S.Zero is nan + assert 0/Float(0) is nan + assert S.Zero/0 is nan + assert Float(0)/0 is nan + assert -1/S.Zero is zoo + assert -1/Float(0) is zoo + + +@_both_exp_pow +def test_Infinity_inequations(): + assert oo > pi + assert not (oo < pi) + assert exp(-3) < oo + + assert _inf > pi + assert not (_inf < pi) + assert exp(-3) < _inf + + raises(TypeError, lambda: oo < I) + raises(TypeError, lambda: oo <= I) + raises(TypeError, lambda: oo > I) + raises(TypeError, lambda: oo >= I) + raises(TypeError, lambda: -oo < I) + raises(TypeError, lambda: -oo <= I) + raises(TypeError, lambda: -oo > I) + raises(TypeError, lambda: -oo >= I) + + raises(TypeError, lambda: I < oo) + raises(TypeError, lambda: I <= oo) + raises(TypeError, lambda: I > oo) + raises(TypeError, lambda: I >= oo) + raises(TypeError, lambda: I < -oo) + raises(TypeError, lambda: I <= -oo) + raises(TypeError, lambda: I > -oo) + raises(TypeError, lambda: I >= -oo) + + assert oo > -oo and oo >= -oo + assert (oo < -oo) == False and (oo <= -oo) == False + assert -oo < oo and -oo <= oo + assert (-oo > oo) == False and (-oo >= oo) == False + + assert (oo < oo) == False # issue 7775 + assert (oo > oo) == False + assert (-oo > -oo) == False and (-oo < -oo) == False + assert oo >= oo and oo <= oo and -oo >= -oo and -oo <= -oo + assert (-oo < -_inf) == False + assert (oo > _inf) == False + assert -oo >= -_inf + assert oo <= _inf + + x = Symbol('x') + b = Symbol('b', finite=True, real=True) + assert (x < oo) == Lt(x, oo) # issue 7775 + assert b < oo and b > -oo and b <= oo and b >= -oo + assert oo > b and oo >= b and (oo < b) == False and (oo <= b) == False + assert (-oo > b) == False and (-oo >= b) == False and -oo < b and -oo <= b + assert (oo < x) == Lt(oo, x) and (oo > x) == Gt(oo, x) + assert (oo <= x) == Le(oo, x) and (oo >= x) == Ge(oo, x) + assert (-oo < x) == Lt(-oo, x) and (-oo > x) == Gt(-oo, x) + assert (-oo <= x) == Le(-oo, x) and (-oo >= x) == Ge(-oo, x) + + +def test_NaN(): + assert nan is nan + assert nan != 1 + assert 1*nan is nan + assert 1 != nan + assert -nan is nan + assert oo != Symbol("x")**3 + assert 2 + nan is nan + assert 3*nan + 2 is nan + assert -nan*3 is nan + assert nan + nan is nan + assert -nan + nan*(-5) is nan + assert 8/nan is nan + raises(TypeError, lambda: nan > 0) + raises(TypeError, lambda: nan < 0) + raises(TypeError, lambda: nan >= 0) + raises(TypeError, lambda: nan <= 0) + raises(TypeError, lambda: 0 < nan) + raises(TypeError, lambda: 0 > nan) + raises(TypeError, lambda: 0 <= nan) + raises(TypeError, lambda: 0 >= nan) + assert nan**0 == 1 # as per IEEE 754 + assert 1**nan is nan # IEEE 754 is not the best choice for symbolic work + # test Pow._eval_power's handling of NaN + assert Pow(nan, 0, evaluate=False)**2 == 1 + for n in (1, 1., S.One, S.NegativeOne, Float(1)): + assert n + nan is nan + assert n - nan is nan + assert nan + n is nan + assert nan - n is nan + assert n/nan is nan + assert nan/n is nan + + +def test_special_numbers(): + assert isinstance(S.NaN, Number) is True + assert isinstance(S.Infinity, Number) is True + assert isinstance(S.NegativeInfinity, Number) is True + + assert S.NaN.is_number is True + assert S.Infinity.is_number is True + assert S.NegativeInfinity.is_number is True + assert S.ComplexInfinity.is_number is True + + assert isinstance(S.NaN, Rational) is False + assert isinstance(S.Infinity, Rational) is False + assert isinstance(S.NegativeInfinity, Rational) is False + + assert S.NaN.is_rational is not True + assert S.Infinity.is_rational is not True + assert S.NegativeInfinity.is_rational is not True + + +def test_powers(): + assert integer_nthroot(1, 2) == (1, True) + assert integer_nthroot(1, 5) == (1, True) + assert integer_nthroot(2, 1) == (2, True) + assert integer_nthroot(2, 2) == (1, False) + assert integer_nthroot(2, 5) == (1, False) + assert integer_nthroot(4, 2) == (2, True) + assert integer_nthroot(123**25, 25) == (123, True) + assert integer_nthroot(123**25 + 1, 25) == (123, False) + assert integer_nthroot(123**25 - 1, 25) == (122, False) + assert integer_nthroot(1, 1) == (1, True) + assert integer_nthroot(0, 1) == (0, True) + assert integer_nthroot(0, 3) == (0, True) + assert integer_nthroot(10000, 1) == (10000, True) + assert integer_nthroot(4, 2) == (2, True) + assert integer_nthroot(16, 2) == (4, True) + assert integer_nthroot(26, 2) == (5, False) + assert integer_nthroot(1234567**7, 7) == (1234567, True) + assert integer_nthroot(1234567**7 + 1, 7) == (1234567, False) + assert integer_nthroot(1234567**7 - 1, 7) == (1234566, False) + b = 25**1000 + assert integer_nthroot(b, 1000) == (25, True) + assert integer_nthroot(b + 1, 1000) == (25, False) + assert integer_nthroot(b - 1, 1000) == (24, False) + c = 10**400 + c2 = c**2 + assert integer_nthroot(c2, 2) == (c, True) + assert integer_nthroot(c2 + 1, 2) == (c, False) + assert integer_nthroot(c2 - 1, 2) == (c - 1, False) + assert integer_nthroot(2, 10**10) == (1, False) + + p, r = integer_nthroot(int(factorial(10000)), 100) + assert p % (10**10) == 5322420655 + assert not r + + # Test that this is fast + assert integer_nthroot(2, 10**10) == (1, False) + + # output should be int if possible + assert type(integer_nthroot(2**61, 2)[0]) is int + + +def test_integer_nthroot_overflow(): + assert integer_nthroot(10**(50*50), 50) == (10**50, True) + assert integer_nthroot(10**100000, 10000) == (10**10, True) + + +def test_integer_log(): + raises(ValueError, lambda: integer_log(2, 1)) + raises(ValueError, lambda: integer_log(0, 2)) + raises(ValueError, lambda: integer_log(1.1, 2)) + raises(ValueError, lambda: integer_log(1, 2.2)) + + assert integer_log(1, 2) == (0, True) + assert integer_log(1, 3) == (0, True) + assert integer_log(2, 3) == (0, False) + assert integer_log(3, 3) == (1, True) + assert integer_log(3*2, 3) == (1, False) + assert integer_log(3**2, 3) == (2, True) + assert integer_log(3*4, 3) == (2, False) + assert integer_log(3**3, 3) == (3, True) + assert integer_log(27, 5) == (2, False) + assert integer_log(2, 3) == (0, False) + assert integer_log(-4, 2) == (2, False) + assert integer_log(-16, 4) == (0, False) + assert integer_log(-4, -2) == (2, False) + assert integer_log(4, -2) == (2, True) + assert integer_log(-8, -2) == (3, True) + assert integer_log(8, -2) == (3, False) + assert integer_log(-9, 3) == (0, False) + assert integer_log(-9, -3) == (2, False) + assert integer_log(9, -3) == (2, True) + assert integer_log(-27, -3) == (3, True) + assert integer_log(27, -3) == (3, False) + + +def test_isqrt(): + from math import sqrt as _sqrt + limit = 4503599761588223 + assert int(_sqrt(limit)) == integer_nthroot(limit, 2)[0] + assert int(_sqrt(limit + 1)) != integer_nthroot(limit + 1, 2)[0] + assert isqrt(limit + 1) == integer_nthroot(limit + 1, 2)[0] + assert isqrt(limit + S.Half) == integer_nthroot(limit, 2)[0] + assert isqrt(limit + 1 + S.Half) == integer_nthroot(limit + 1, 2)[0] + assert isqrt(limit + 2 + S.Half) == integer_nthroot(limit + 2, 2)[0] + + # Regression tests for https://github.com/sympy/sympy/issues/17034 + assert isqrt(4503599761588224) == 67108864 + assert isqrt(9999999999999999) == 99999999 + + # Other corner cases, especially involving non-integers. + raises(ValueError, lambda: isqrt(-1)) + raises(ValueError, lambda: isqrt(-10**1000)) + raises(ValueError, lambda: isqrt(Rational(-1, 2))) + + tiny = Rational(1, 10**1000) + raises(ValueError, lambda: isqrt(-tiny)) + assert isqrt(1-tiny) == 0 + assert isqrt(4503599761588224-tiny) == 67108864 + assert isqrt(10**100 - tiny) == 10**50 - 1 + + +def test_powers_Integer(): + """Test Integer._eval_power""" + # check infinity + assert S.One ** S.Infinity is S.NaN + assert S.NegativeOne** S.Infinity is S.NaN + assert S(2) ** S.Infinity is S.Infinity + assert S(-2)** S.Infinity == zoo + assert S(0) ** S.Infinity is S.Zero + + # check Nan + assert S.One ** S.NaN is S.NaN + assert S.NegativeOne ** S.NaN is S.NaN + + # check for exact roots + assert S.NegativeOne ** Rational(6, 5) == - (-1)**(S.One/5) + assert sqrt(S(4)) == 2 + assert sqrt(S(-4)) == I * 2 + assert S(16) ** Rational(1, 4) == 2 + assert S(-16) ** Rational(1, 4) == 2 * (-1)**Rational(1, 4) + assert S(9) ** Rational(3, 2) == 27 + assert S(-9) ** Rational(3, 2) == -27*I + assert S(27) ** Rational(2, 3) == 9 + assert S(-27) ** Rational(2, 3) == 9 * (S.NegativeOne ** Rational(2, 3)) + assert (-2) ** Rational(-2, 1) == Rational(1, 4) + + # not exact roots + assert sqrt(-3) == I*sqrt(3) + assert (3) ** (Rational(3, 2)) == 3 * sqrt(3) + assert (-3) ** (Rational(3, 2)) == - 3 * sqrt(-3) + assert (-3) ** (Rational(5, 2)) == 9 * I * sqrt(3) + assert (-3) ** (Rational(7, 2)) == - I * 27 * sqrt(3) + assert (2) ** (Rational(3, 2)) == 2 * sqrt(2) + assert (2) ** (Rational(-3, 2)) == sqrt(2) / 4 + assert (81) ** (Rational(2, 3)) == 9 * (S(3) ** (Rational(2, 3))) + assert (-81) ** (Rational(2, 3)) == 9 * (S(-3) ** (Rational(2, 3))) + assert (-3) ** Rational(-7, 3) == \ + -(-1)**Rational(2, 3)*3**Rational(2, 3)/27 + assert (-3) ** Rational(-2, 3) == \ + -(-1)**Rational(1, 3)*3**Rational(1, 3)/3 + + # join roots + assert sqrt(6) + sqrt(24) == 3*sqrt(6) + assert sqrt(2) * sqrt(3) == sqrt(6) + + # separate symbols & constansts + x = Symbol("x") + assert sqrt(49 * x) == 7 * sqrt(x) + assert sqrt((3 - sqrt(pi)) ** 2) == 3 - sqrt(pi) + + # check that it is fast for big numbers + assert (2**64 + 1) ** Rational(4, 3) + assert (2**64 + 1) ** Rational(17, 25) + + # negative rational power and negative base + assert (-3) ** Rational(-7, 3) == \ + -(-1)**Rational(2, 3)*3**Rational(2, 3)/27 + assert (-3) ** Rational(-2, 3) == \ + -(-1)**Rational(1, 3)*3**Rational(1, 3)/3 + assert (-2) ** Rational(-10, 3) == \ + (-1)**Rational(2, 3)*2**Rational(2, 3)/16 + assert abs(Pow(-2, Rational(-10, 3)).n() - + Pow(-2, Rational(-10, 3), evaluate=False).n()) < 1e-16 + + # negative base and rational power with some simplification + assert (-8) ** Rational(2, 5) == \ + 2*(-1)**Rational(2, 5)*2**Rational(1, 5) + assert (-4) ** Rational(9, 5) == \ + -8*(-1)**Rational(4, 5)*2**Rational(3, 5) + + assert S(1234).factors() == {617: 1, 2: 1} + assert Rational(2*3, 3*5*7).factors() == {2: 1, 5: -1, 7: -1} + + # test that eval_power factors numbers bigger than + # the current limit in factor_trial_division (2**15) + from sympy.ntheory.generate import nextprime + n = nextprime(2**15) + assert sqrt(n**2) == n + assert sqrt(n**3) == n*sqrt(n) + assert sqrt(4*n) == 2*sqrt(n) + + # check that factors of base with powers sharing gcd with power are removed + assert (2**4*3)**Rational(1, 6) == 2**Rational(2, 3)*3**Rational(1, 6) + assert (2**4*3)**Rational(5, 6) == 8*2**Rational(1, 3)*3**Rational(5, 6) + + # check that bases sharing a gcd are exptracted + assert 2**Rational(1, 3)*3**Rational(1, 4)*6**Rational(1, 5) == \ + 2**Rational(8, 15)*3**Rational(9, 20) + assert sqrt(8)*24**Rational(1, 3)*6**Rational(1, 5) == \ + 4*2**Rational(7, 10)*3**Rational(8, 15) + assert sqrt(8)*(-24)**Rational(1, 3)*(-6)**Rational(1, 5) == \ + 4*(-3)**Rational(8, 15)*2**Rational(7, 10) + assert 2**Rational(1, 3)*2**Rational(8, 9) == 2*2**Rational(2, 9) + assert 2**Rational(2, 3)*6**Rational(1, 3) == 2*3**Rational(1, 3) + assert 2**Rational(2, 3)*6**Rational(8, 9) == \ + 2*2**Rational(5, 9)*3**Rational(8, 9) + assert (-2)**Rational(2, S(3))*(-4)**Rational(1, S(3)) == -2*2**Rational(1, 3) + assert 3*Pow(3, 2, evaluate=False) == 3**3 + assert 3*Pow(3, Rational(-1, 3), evaluate=False) == 3**Rational(2, 3) + assert (-2)**Rational(1, 3)*(-3)**Rational(1, 4)*(-5)**Rational(5, 6) == \ + -(-1)**Rational(5, 12)*2**Rational(1, 3)*3**Rational(1, 4) * \ + 5**Rational(5, 6) + + assert Integer(-2)**Symbol('', even=True) == \ + Integer(2)**Symbol('', even=True) + assert (-1)**Float(.5) == 1.0*I + + +def test_powers_Rational(): + """Test Rational._eval_power""" + # check infinity + assert S.Half ** S.Infinity == 0 + assert Rational(3, 2) ** S.Infinity is S.Infinity + assert Rational(-1, 2) ** S.Infinity == 0 + assert Rational(-3, 2) ** S.Infinity == zoo + + # check Nan + assert Rational(3, 4) ** S.NaN is S.NaN + assert Rational(-2, 3) ** S.NaN is S.NaN + + # exact roots on numerator + assert sqrt(Rational(4, 3)) == 2 * sqrt(3) / 3 + assert Rational(4, 3) ** Rational(3, 2) == 8 * sqrt(3) / 9 + assert sqrt(Rational(-4, 3)) == I * 2 * sqrt(3) / 3 + assert Rational(-4, 3) ** Rational(3, 2) == - I * 8 * sqrt(3) / 9 + assert Rational(27, 2) ** Rational(1, 3) == 3 * (2 ** Rational(2, 3)) / 2 + assert Rational(5**3, 8**3) ** Rational(4, 3) == Rational(5**4, 8**4) + + # exact root on denominator + assert sqrt(Rational(1, 4)) == S.Half + assert sqrt(Rational(1, -4)) == I * S.Half + assert sqrt(Rational(3, 4)) == sqrt(3) / 2 + assert sqrt(Rational(3, -4)) == I * sqrt(3) / 2 + assert Rational(5, 27) ** Rational(1, 3) == (5 ** Rational(1, 3)) / 3 + + # not exact roots + assert sqrt(S.Half) == sqrt(2) / 2 + assert sqrt(Rational(-4, 7)) == I * sqrt(Rational(4, 7)) + assert Rational(-3, 2)**Rational(-7, 3) == \ + -4*(-1)**Rational(2, 3)*2**Rational(1, 3)*3**Rational(2, 3)/27 + assert Rational(-3, 2)**Rational(-2, 3) == \ + -(-1)**Rational(1, 3)*2**Rational(2, 3)*3**Rational(1, 3)/3 + assert Rational(-3, 2)**Rational(-10, 3) == \ + 8*(-1)**Rational(2, 3)*2**Rational(1, 3)*3**Rational(2, 3)/81 + assert abs(Pow(Rational(-2, 3), Rational(-7, 4)).n() - + Pow(Rational(-2, 3), Rational(-7, 4), evaluate=False).n()) < 1e-16 + + # negative integer power and negative rational base + assert Rational(-2, 3) ** Rational(-2, 1) == Rational(9, 4) + + a = Rational(1, 10) + assert a**Float(a, 2) == Float(a, 2)**Float(a, 2) + assert Rational(-2, 3)**Symbol('', even=True) == \ + Rational(2, 3)**Symbol('', even=True) + + +def test_powers_Float(): + assert str((S('-1/10')**S('3/10')).n()) == str(Float(-.1)**(.3)) + + +def test_lshift_Integer(): + assert Integer(0) << Integer(2) == Integer(0) + assert Integer(0) << 2 == Integer(0) + assert 0 << Integer(2) == Integer(0) + + assert Integer(0b11) << Integer(0) == Integer(0b11) + assert Integer(0b11) << 0 == Integer(0b11) + assert 0b11 << Integer(0) == Integer(0b11) + + assert Integer(0b11) << Integer(2) == Integer(0b11 << 2) + assert Integer(0b11) << 2 == Integer(0b11 << 2) + assert 0b11 << Integer(2) == Integer(0b11 << 2) + + assert Integer(-0b11) << Integer(2) == Integer(-0b11 << 2) + assert Integer(-0b11) << 2 == Integer(-0b11 << 2) + assert -0b11 << Integer(2) == Integer(-0b11 << 2) + + raises(TypeError, lambda: Integer(2) << 0.0) + raises(TypeError, lambda: 0.0 << Integer(2)) + raises(ValueError, lambda: Integer(1) << Integer(-1)) + + +def test_rshift_Integer(): + assert Integer(0) >> Integer(2) == Integer(0) + assert Integer(0) >> 2 == Integer(0) + assert 0 >> Integer(2) == Integer(0) + + assert Integer(0b11) >> Integer(0) == Integer(0b11) + assert Integer(0b11) >> 0 == Integer(0b11) + assert 0b11 >> Integer(0) == Integer(0b11) + + assert Integer(0b11) >> Integer(2) == Integer(0) + assert Integer(0b11) >> 2 == Integer(0) + assert 0b11 >> Integer(2) == Integer(0) + + assert Integer(-0b11) >> Integer(2) == Integer(-1) + assert Integer(-0b11) >> 2 == Integer(-1) + assert -0b11 >> Integer(2) == Integer(-1) + + assert Integer(0b1100) >> Integer(2) == Integer(0b1100 >> 2) + assert Integer(0b1100) >> 2 == Integer(0b1100 >> 2) + assert 0b1100 >> Integer(2) == Integer(0b1100 >> 2) + + assert Integer(-0b1100) >> Integer(2) == Integer(-0b1100 >> 2) + assert Integer(-0b1100) >> 2 == Integer(-0b1100 >> 2) + assert -0b1100 >> Integer(2) == Integer(-0b1100 >> 2) + + raises(TypeError, lambda: Integer(0b10) >> 0.0) + raises(TypeError, lambda: 0.0 >> Integer(2)) + raises(ValueError, lambda: Integer(1) >> Integer(-1)) + + +def test_and_Integer(): + assert Integer(0b01010101) & Integer(0b10101010) == Integer(0) + assert Integer(0b01010101) & 0b10101010 == Integer(0) + assert 0b01010101 & Integer(0b10101010) == Integer(0) + + assert Integer(0b01010101) & Integer(0b11011011) == Integer(0b01010001) + assert Integer(0b01010101) & 0b11011011 == Integer(0b01010001) + assert 0b01010101 & Integer(0b11011011) == Integer(0b01010001) + + assert -Integer(0b01010101) & Integer(0b11011011) == Integer(-0b01010101 & 0b11011011) + assert Integer(-0b01010101) & 0b11011011 == Integer(-0b01010101 & 0b11011011) + assert -0b01010101 & Integer(0b11011011) == Integer(-0b01010101 & 0b11011011) + + assert Integer(0b01010101) & -Integer(0b11011011) == Integer(0b01010101 & -0b11011011) + assert Integer(0b01010101) & -0b11011011 == Integer(0b01010101 & -0b11011011) + assert 0b01010101 & Integer(-0b11011011) == Integer(0b01010101 & -0b11011011) + + raises(TypeError, lambda: Integer(2) & 0.0) + raises(TypeError, lambda: 0.0 & Integer(2)) + + +def test_xor_Integer(): + assert Integer(0b01010101) ^ Integer(0b11111111) == Integer(0b10101010) + assert Integer(0b01010101) ^ 0b11111111 == Integer(0b10101010) + assert 0b01010101 ^ Integer(0b11111111) == Integer(0b10101010) + + assert Integer(0b01010101) ^ Integer(0b11011011) == Integer(0b10001110) + assert Integer(0b01010101) ^ 0b11011011 == Integer(0b10001110) + assert 0b01010101 ^ Integer(0b11011011) == Integer(0b10001110) + + assert -Integer(0b01010101) ^ Integer(0b11011011) == Integer(-0b01010101 ^ 0b11011011) + assert Integer(-0b01010101) ^ 0b11011011 == Integer(-0b01010101 ^ 0b11011011) + assert -0b01010101 ^ Integer(0b11011011) == Integer(-0b01010101 ^ 0b11011011) + + assert Integer(0b01010101) ^ -Integer(0b11011011) == Integer(0b01010101 ^ -0b11011011) + assert Integer(0b01010101) ^ -0b11011011 == Integer(0b01010101 ^ -0b11011011) + assert 0b01010101 ^ Integer(-0b11011011) == Integer(0b01010101 ^ -0b11011011) + + raises(TypeError, lambda: Integer(2) ^ 0.0) + raises(TypeError, lambda: 0.0 ^ Integer(2)) + + +def test_or_Integer(): + assert Integer(0b01010101) | Integer(0b10101010) == Integer(0b11111111) + assert Integer(0b01010101) | 0b10101010 == Integer(0b11111111) + assert 0b01010101 | Integer(0b10101010) == Integer(0b11111111) + + assert Integer(0b01010101) | Integer(0b11011011) == Integer(0b11011111) + assert Integer(0b01010101) | 0b11011011 == Integer(0b11011111) + assert 0b01010101 | Integer(0b11011011) == Integer(0b11011111) + + assert -Integer(0b01010101) | Integer(0b11011011) == Integer(-0b01010101 | 0b11011011) + assert Integer(-0b01010101) | 0b11011011 == Integer(-0b01010101 | 0b11011011) + assert -0b01010101 | Integer(0b11011011) == Integer(-0b01010101 | 0b11011011) + + assert Integer(0b01010101) | -Integer(0b11011011) == Integer(0b01010101 | -0b11011011) + assert Integer(0b01010101) | -0b11011011 == Integer(0b01010101 | -0b11011011) + assert 0b01010101 | Integer(-0b11011011) == Integer(0b01010101 | -0b11011011) + + raises(TypeError, lambda: Integer(2) | 0.0) + raises(TypeError, lambda: 0.0 | Integer(2)) + + +def test_invert_Integer(): + assert ~Integer(0b01010101) == Integer(-0b01010110) + assert ~Integer(0b01010101) == Integer(~0b01010101) + assert ~(~Integer(0b01010101)) == Integer(0b01010101) + + +def test_abs1(): + assert Rational(1, 6) != Rational(-1, 6) + assert abs(Rational(1, 6)) == abs(Rational(-1, 6)) + + +def test_accept_int(): + assert not Float(4) == 4 + assert Float(4) != 4 + assert Float(4) == 4.0 + + +def test_dont_accept_str(): + assert Float("0.2") != "0.2" + assert not (Float("0.2") == "0.2") + + +def test_int(): + a = Rational(5) + assert int(a) == 5 + a = Rational(9, 10) + assert int(a) == int(-a) == 0 + assert 1/(-1)**Rational(2, 3) == -(-1)**Rational(1, 3) + # issue 10368 + a = Rational(32442016954, 78058255275) + assert type(int(a)) is type(int(-a)) is int + + +def test_int_NumberSymbols(): + assert int(Catalan) == 0 + assert int(EulerGamma) == 0 + assert int(pi) == 3 + assert int(E) == 2 + assert int(GoldenRatio) == 1 + assert int(TribonacciConstant) == 1 + for i in [Catalan, E, EulerGamma, GoldenRatio, TribonacciConstant, pi]: + a, b = i.approximation_interval(Integer) + ia = int(i) + assert ia == a + assert isinstance(ia, int) + assert b == a + 1 + assert a.is_Integer and b.is_Integer + + +def test_real_bug(): + x = Symbol("x") + assert str(2.0*x*x) in ["(2.0*x)*x", "2.0*x**2", "2.00000000000000*x**2"] + assert str(2.1*x*x) != "(2.0*x)*x" + + +def test_bug_sqrt(): + assert ((sqrt(Rational(2)) + 1)*(sqrt(Rational(2)) - 1)).expand() == 1 + + +def test_pi_Pi(): + "Test that pi (instance) is imported, but Pi (class) is not" + from sympy import pi # noqa + with raises(ImportError): + from sympy import Pi # noqa + + +def test_no_len(): + # there should be no len for numbers + raises(TypeError, lambda: len(Rational(2))) + raises(TypeError, lambda: len(Rational(2, 3))) + raises(TypeError, lambda: len(Integer(2))) + + +def test_issue_3321(): + assert sqrt(Rational(1, 5)) == Rational(1, 5)**S.Half + assert 5 * sqrt(Rational(1, 5)) == sqrt(5) + + +def test_issue_3692(): + assert ((-1)**Rational(1, 6)).expand(complex=True) == I/2 + sqrt(3)/2 + assert ((-5)**Rational(1, 6)).expand(complex=True) == \ + 5**Rational(1, 6)*I/2 + 5**Rational(1, 6)*sqrt(3)/2 + assert ((-64)**Rational(1, 6)).expand(complex=True) == I + sqrt(3) + + +def test_issue_3423(): + x = Symbol("x") + assert sqrt(x - 1).as_base_exp() == (x - 1, S.Half) + assert sqrt(x - 1) != I*sqrt(1 - x) + + +def test_issue_3449(): + x = Symbol("x") + assert sqrt(x - 1).subs(x, 5) == 2 + + +def test_issue_13890(): + x = Symbol("x") + e = (-x/4 - S.One/12)**x - 1 + f = simplify(e) + a = Rational(9, 5) + assert abs(e.subs(x,a).evalf() - f.subs(x,a).evalf()) < 1e-15 + + +def test_Integer_factors(): + def F(i): + return Integer(i).factors() + + assert F(1) == {} + assert F(2) == {2: 1} + assert F(3) == {3: 1} + assert F(4) == {2: 2} + assert F(5) == {5: 1} + assert F(6) == {2: 1, 3: 1} + assert F(7) == {7: 1} + assert F(8) == {2: 3} + assert F(9) == {3: 2} + assert F(10) == {2: 1, 5: 1} + assert F(11) == {11: 1} + assert F(12) == {2: 2, 3: 1} + assert F(13) == {13: 1} + assert F(14) == {2: 1, 7: 1} + assert F(15) == {3: 1, 5: 1} + assert F(16) == {2: 4} + assert F(17) == {17: 1} + assert F(18) == {2: 1, 3: 2} + assert F(19) == {19: 1} + assert F(20) == {2: 2, 5: 1} + assert F(21) == {3: 1, 7: 1} + assert F(22) == {2: 1, 11: 1} + assert F(23) == {23: 1} + assert F(24) == {2: 3, 3: 1} + assert F(25) == {5: 2} + assert F(26) == {2: 1, 13: 1} + assert F(27) == {3: 3} + assert F(28) == {2: 2, 7: 1} + assert F(29) == {29: 1} + assert F(30) == {2: 1, 3: 1, 5: 1} + assert F(31) == {31: 1} + assert F(32) == {2: 5} + assert F(33) == {3: 1, 11: 1} + assert F(34) == {2: 1, 17: 1} + assert F(35) == {5: 1, 7: 1} + assert F(36) == {2: 2, 3: 2} + assert F(37) == {37: 1} + assert F(38) == {2: 1, 19: 1} + assert F(39) == {3: 1, 13: 1} + assert F(40) == {2: 3, 5: 1} + assert F(41) == {41: 1} + assert F(42) == {2: 1, 3: 1, 7: 1} + assert F(43) == {43: 1} + assert F(44) == {2: 2, 11: 1} + assert F(45) == {3: 2, 5: 1} + assert F(46) == {2: 1, 23: 1} + assert F(47) == {47: 1} + assert F(48) == {2: 4, 3: 1} + assert F(49) == {7: 2} + assert F(50) == {2: 1, 5: 2} + assert F(51) == {3: 1, 17: 1} + + +def test_Rational_factors(): + def F(p, q, visual=None): + return Rational(p, q).factors(visual=visual) + + assert F(2, 3) == {2: 1, 3: -1} + assert F(2, 9) == {2: 1, 3: -2} + assert F(2, 15) == {2: 1, 3: -1, 5: -1} + assert F(6, 10) == {3: 1, 5: -1} + + +def test_issue_4107(): + assert pi*(E + 10) + pi*(-E - 10) != 0 + assert pi*(E + 10**10) + pi*(-E - 10**10) != 0 + assert pi*(E + 10**20) + pi*(-E - 10**20) != 0 + assert pi*(E + 10**80) + pi*(-E - 10**80) != 0 + + assert (pi*(E + 10) + pi*(-E - 10)).expand() == 0 + assert (pi*(E + 10**10) + pi*(-E - 10**10)).expand() == 0 + assert (pi*(E + 10**20) + pi*(-E - 10**20)).expand() == 0 + assert (pi*(E + 10**80) + pi*(-E - 10**80)).expand() == 0 + + +def test_IntegerInteger(): + a = Integer(4) + b = Integer(a) + + assert a == b + + +def test_Rational_gcd_lcm_cofactors(): + assert Integer(4).gcd(2) == Integer(2) + assert Integer(4).lcm(2) == Integer(4) + assert Integer(4).gcd(Integer(2)) == Integer(2) + assert Integer(4).lcm(Integer(2)) == Integer(4) + a, b = 720**99911, 480**12342 + assert Integer(a).lcm(b) == a*b/Integer(a).gcd(b) + + assert Integer(4).gcd(3) == Integer(1) + assert Integer(4).lcm(3) == Integer(12) + assert Integer(4).gcd(Integer(3)) == Integer(1) + assert Integer(4).lcm(Integer(3)) == Integer(12) + + assert Rational(4, 3).gcd(2) == Rational(2, 3) + assert Rational(4, 3).lcm(2) == Integer(4) + assert Rational(4, 3).gcd(Integer(2)) == Rational(2, 3) + assert Rational(4, 3).lcm(Integer(2)) == Integer(4) + + assert Integer(4).gcd(Rational(2, 9)) == Rational(2, 9) + assert Integer(4).lcm(Rational(2, 9)) == Integer(4) + + assert Rational(4, 3).gcd(Rational(2, 9)) == Rational(2, 9) + assert Rational(4, 3).lcm(Rational(2, 9)) == Rational(4, 3) + assert Rational(4, 5).gcd(Rational(2, 9)) == Rational(2, 45) + assert Rational(4, 5).lcm(Rational(2, 9)) == Integer(4) + assert Rational(5, 9).lcm(Rational(3, 7)) == Rational(Integer(5).lcm(3),Integer(9).gcd(7)) + + assert Integer(4).cofactors(2) == (Integer(2), Integer(2), Integer(1)) + assert Integer(4).cofactors(Integer(2)) == \ + (Integer(2), Integer(2), Integer(1)) + + assert Integer(4).gcd(Float(2.0)) == Float(1.0) + assert Integer(4).lcm(Float(2.0)) == Float(8.0) + assert Integer(4).cofactors(Float(2.0)) == (Float(1.0), Float(4.0), Float(2.0)) + + assert S.Half.gcd(Float(2.0)) == Float(1.0) + assert S.Half.lcm(Float(2.0)) == Float(1.0) + assert S.Half.cofactors(Float(2.0)) == \ + (Float(1.0), Float(0.5), Float(2.0)) + + +def test_Float_gcd_lcm_cofactors(): + assert Float(2.0).gcd(Integer(4)) == Float(1.0) + assert Float(2.0).lcm(Integer(4)) == Float(8.0) + assert Float(2.0).cofactors(Integer(4)) == (Float(1.0), Float(2.0), Float(4.0)) + + assert Float(2.0).gcd(S.Half) == Float(1.0) + assert Float(2.0).lcm(S.Half) == Float(1.0) + assert Float(2.0).cofactors(S.Half) == \ + (Float(1.0), Float(2.0), Float(0.5)) + + +def test_issue_4611(): + assert abs(pi._evalf(50) - 3.14159265358979) < 1e-10 + assert abs(E._evalf(50) - 2.71828182845905) < 1e-10 + assert abs(Catalan._evalf(50) - 0.915965594177219) < 1e-10 + assert abs(EulerGamma._evalf(50) - 0.577215664901533) < 1e-10 + assert abs(GoldenRatio._evalf(50) - 1.61803398874989) < 1e-10 + assert abs(TribonacciConstant._evalf(50) - 1.83928675521416) < 1e-10 + + x = Symbol("x") + assert (pi + x).evalf() == pi.evalf() + x + assert (E + x).evalf() == E.evalf() + x + assert (Catalan + x).evalf() == Catalan.evalf() + x + assert (EulerGamma + x).evalf() == EulerGamma.evalf() + x + assert (GoldenRatio + x).evalf() == GoldenRatio.evalf() + x + assert (TribonacciConstant + x).evalf() == TribonacciConstant.evalf() + x + + +@conserve_mpmath_dps +def test_conversion_to_mpmath(): + assert mpmath.mpmathify(Integer(1)) == mpmath.mpf(1) + assert mpmath.mpmathify(S.Half) == mpmath.mpf(0.5) + assert mpmath.mpmathify(Float('1.23', 15)) == mpmath.mpf('1.23') + + assert mpmath.mpmathify(I) == mpmath.mpc(1j) + + assert mpmath.mpmathify(1 + 2*I) == mpmath.mpc(1 + 2j) + assert mpmath.mpmathify(1.0 + 2*I) == mpmath.mpc(1 + 2j) + assert mpmath.mpmathify(1 + 2.0*I) == mpmath.mpc(1 + 2j) + assert mpmath.mpmathify(1.0 + 2.0*I) == mpmath.mpc(1 + 2j) + assert mpmath.mpmathify(S.Half + S.Half*I) == mpmath.mpc(0.5 + 0.5j) + + assert mpmath.mpmathify(2*I) == mpmath.mpc(2j) + assert mpmath.mpmathify(2.0*I) == mpmath.mpc(2j) + assert mpmath.mpmathify(S.Half*I) == mpmath.mpc(0.5j) + + mpmath.mp.dps = 100 + assert mpmath.mpmathify(pi.evalf(100) + pi.evalf(100)*I) == mpmath.pi + mpmath.pi*mpmath.j + assert mpmath.mpmathify(pi.evalf(100)*I) == mpmath.pi*mpmath.j + + +def test_relational(): + # real + x = S(.1) + assert (x != cos) is True + assert (x == cos) is False + + # rational + x = Rational(1, 3) + assert (x != cos) is True + assert (x == cos) is False + + # integer defers to rational so these tests are omitted + + # number symbol + x = pi + assert (x != cos) is True + assert (x == cos) is False + + +def test_Integer_as_index(): + assert 'hello'[Integer(2):] == 'llo' + + +def test_Rational_int(): + assert int( Rational(7, 5)) == 1 + assert int( S.Half) == 0 + assert int(Rational(-1, 2)) == 0 + assert int(-Rational(7, 5)) == -1 + + +def test_zoo(): + b = Symbol('b', finite=True) + nz = Symbol('nz', nonzero=True) + p = Symbol('p', positive=True) + n = Symbol('n', negative=True) + im = Symbol('i', imaginary=True) + c = Symbol('c', complex=True) + pb = Symbol('pb', positive=True) + nb = Symbol('nb', negative=True) + imb = Symbol('ib', imaginary=True, finite=True) + for i in [I, S.Infinity, S.NegativeInfinity, S.Zero, S.One, S.Pi, S.Half, S(3), log(3), + b, nz, p, n, im, pb, nb, imb, c]: + if i.is_finite and (i.is_real or i.is_imaginary): + assert i + zoo is zoo + assert i - zoo is zoo + assert zoo + i is zoo + assert zoo - i is zoo + elif i.is_finite is not False: + assert (i + zoo).is_Add + assert (i - zoo).is_Add + assert (zoo + i).is_Add + assert (zoo - i).is_Add + else: + assert (i + zoo) is S.NaN + assert (i - zoo) is S.NaN + assert (zoo + i) is S.NaN + assert (zoo - i) is S.NaN + + if fuzzy_not(i.is_zero) and (i.is_extended_real or i.is_imaginary): + assert i*zoo is zoo + assert zoo*i is zoo + elif i.is_zero: + assert i*zoo is S.NaN + assert zoo*i is S.NaN + else: + assert (i*zoo).is_Mul + assert (zoo*i).is_Mul + + if fuzzy_not((1/i).is_zero) and (i.is_real or i.is_imaginary): + assert zoo/i is zoo + elif (1/i).is_zero: + assert zoo/i is S.NaN + elif i.is_zero: + assert zoo/i is zoo + else: + assert (zoo/i).is_Mul + + assert (I*oo).is_Mul # allow directed infinity + assert zoo + zoo is S.NaN + assert zoo * zoo is zoo + assert zoo - zoo is S.NaN + assert zoo/zoo is S.NaN + assert zoo**zoo is S.NaN + assert zoo**0 is S.One + assert zoo**2 is zoo + assert 1/zoo is S.Zero + + assert Mul.flatten([S.NegativeOne, oo, S(0)]) == ([S.NaN], [], None) + + +def test_issue_4122(): + x = Symbol('x', nonpositive=True) + assert oo + x is oo + x = Symbol('x', extended_nonpositive=True) + assert (oo + x).is_Add + x = Symbol('x', finite=True) + assert (oo + x).is_Add # x could be imaginary + x = Symbol('x', nonnegative=True) + assert oo + x is oo + x = Symbol('x', extended_nonnegative=True) + assert oo + x is oo + x = Symbol('x', finite=True, real=True) + assert oo + x is oo + + # similarly for negative infinity + x = Symbol('x', nonnegative=True) + assert -oo + x is -oo + x = Symbol('x', extended_nonnegative=True) + assert (-oo + x).is_Add + x = Symbol('x', finite=True) + assert (-oo + x).is_Add + x = Symbol('x', nonpositive=True) + assert -oo + x is -oo + x = Symbol('x', extended_nonpositive=True) + assert -oo + x is -oo + x = Symbol('x', finite=True, real=True) + assert -oo + x is -oo + + +def test_GoldenRatio_expand(): + assert GoldenRatio.expand(func=True) == S.Half + sqrt(5)/2 + + +def test_TribonacciConstant_expand(): + assert TribonacciConstant.expand(func=True) == \ + (1 + cbrt(19 - 3*sqrt(33)) + cbrt(19 + 3*sqrt(33))) / 3 + + +def test_as_content_primitive(): + assert S.Zero.as_content_primitive() == (1, 0) + assert S.Half.as_content_primitive() == (S.Half, 1) + assert (Rational(-1, 2)).as_content_primitive() == (S.Half, -1) + assert S(3).as_content_primitive() == (3, 1) + assert S(3.1).as_content_primitive() == (1, 3.1) + + +def test_hashing_sympy_integers(): + # Test for issue 5072 + assert {Integer(3)} == {int(3)} + assert hash(Integer(4)) == hash(int(4)) + + +def test_rounding_issue_4172(): + assert int((E**100).round()) == \ + 26881171418161354484126255515800135873611119 + assert int((pi**100).round()) == \ + 51878483143196131920862615246303013562686760680406 + assert int((Rational(1)/EulerGamma**100).round()) == \ + 734833795660954410469466 + + +@XFAIL +def test_mpmath_issues(): + from mpmath.libmp.libmpf import _normalize + import mpmath.libmp as mlib + rnd = mlib.round_nearest + mpf = (0, int(0), -123, -1, 53, rnd) # nan + assert _normalize(mpf, 53) != (0, int(0), 0, 0) + mpf = (0, int(0), -456, -2, 53, rnd) # +inf + assert _normalize(mpf, 53) != (0, int(0), 0, 0) + mpf = (1, int(0), -789, -3, 53, rnd) # -inf + assert _normalize(mpf, 53) != (0, int(0), 0, 0) + + from mpmath.libmp.libmpf import fnan + assert mlib.mpf_eq(fnan, fnan) + + +def test_Catalan_EulerGamma_prec(): + n = GoldenRatio + f = Float(n.n(), 5) + assert f._mpf_ == (0, int(212079), -17, 18) + assert f._prec == 20 + assert n._as_mpf_val(20) == f._mpf_ + + n = EulerGamma + f = Float(n.n(), 5) + assert f._mpf_ == (0, int(302627), -19, 19) + assert f._prec == 20 + assert n._as_mpf_val(20) == f._mpf_ + + +def test_Catalan_rewrite(): + k = Dummy('k', integer=True, nonnegative=True) + assert Catalan.rewrite(Sum).dummy_eq( + Sum((-1)**k/(2*k + 1)**2, (k, 0, oo))) + assert Catalan.rewrite() == Catalan + + +def test_bool_eq(): + assert 0 == False + assert S(0) == False + assert S(0) != S.false + assert 1 == True + assert S.One == True + assert S.One != S.true + + +def test_Float_eq(): + # Floats with different precision should not compare equal + assert Float(.5, 10) != Float(.5, 11) != Float(.5, 1) + # but floats that aren't exact in base-2 still + # don't compare the same because they have different + # underlying mpf values + assert Float(.12, 3) != Float(.12, 4) + assert Float(.12, 3) != .12 + assert 0.12 != Float(.12, 3) + assert Float('.12', 22) != .12 + # issue 11707 + # but Float/Rational -- except for 0 -- + # are exact so Rational(x) = Float(y) only if + # Rational(x) == Rational(Float(y)) + assert Float('1.1') != Rational(11, 10) + assert Rational(11, 10) != Float('1.1') + # coverage + assert not Float(3) == 2 + assert not Float(3) == Float(2) + assert not Float(3) == 3 + assert not Float(2**2) == S.Half + assert Float(2**2) == 4.0 + assert not Float(2**-2) == 1 + assert Float(2**-1) == 0.5 + assert not Float(2*3) == 3 + assert not Float(2*3) == 0.5 + assert Float(2*3) == 6.0 + assert not Float(2*3) == 6 + assert not Float(2*3) == 8 + assert not Float(.75) == Rational(3, 4) + assert Float(.75) == 0.75 + assert Float(5/18) == 5/18 + # 4473 + assert Float(2.) != 3 + assert not Float((0,1,-3)) == S.One/8 + assert Float((0,1,-3)) == 1/8 + assert Float((0,1,-3)) != S.One/9 + # 16196 + assert not 2 == Float(2) # unlike Python + assert t**2 != t**2.0 + + +def test_issue_6640(): + from mpmath.libmp.libmpf import finf, fninf + # fnan is not included because Float no longer returns fnan, + # but otherwise, the same sort of test could apply + assert Float(finf).is_zero is False + assert Float(fninf).is_zero is False + assert bool(Float(0)) is False + + +def test_issue_6349(): + assert Float('23.e3', '')._prec == 10 + assert Float('23e3', '')._prec == 20 + assert Float('23000', '')._prec == 20 + assert Float('-23000', '')._prec == 20 + + +def test_mpf_norm(): + assert mpf_norm((1, 0, 1, 0), 10) == mpf('0')._mpf_ + assert Float._new((1, 0, 1, 0), 10)._mpf_ == mpf('0')._mpf_ + + +def test_latex(): + assert latex(pi) == r"\pi" + assert latex(E) == r"e" + assert latex(GoldenRatio) == r"\phi" + assert latex(TribonacciConstant) == r"\text{TribonacciConstant}" + assert latex(EulerGamma) == r"\gamma" + assert latex(oo) == r"\infty" + assert latex(-oo) == r"-\infty" + assert latex(zoo) == r"\tilde{\infty}" + assert latex(nan) == r"\text{NaN}" + assert latex(I) == r"i" + + +def test_issue_7742(): + assert -oo % 1 is nan + + +def test_simplify_AlgebraicNumber(): + A = AlgebraicNumber + e = 3**(S.One/6)*(3 + (135 + 78*sqrt(3))**Rational(2, 3))/(45 + 26*sqrt(3))**(S.One/3) + assert simplify(A(e)) == A(12) # wester test_C20 + + e = (41 + 29*sqrt(2))**(S.One/5) + assert simplify(A(e)) == A(1 + sqrt(2)) # wester test_C21 + + e = (3 + 4*I)**Rational(3, 2) + assert simplify(A(e)) == A(2 + 11*I) # issue 4401 + + +def test_Float_idempotence(): + x = Float('1.23', '') + y = Float(x) + z = Float(x, 15) + assert same_and_same_prec(y, x) + assert not same_and_same_prec(z, x) + x = Float(10**20) + y = Float(x) + z = Float(x, 15) + assert same_and_same_prec(y, x) + assert not same_and_same_prec(z, x) + + +def test_comp1(): + # sqrt(2) = 1.414213 5623730950... + a = sqrt(2).n(7) + assert comp(a, 1.4142129) is False + assert comp(a, 1.4142130) + # ... + assert comp(a, 1.4142141) + assert comp(a, 1.4142142) is False + assert comp(sqrt(2).n(2), '1.4') + assert comp(sqrt(2).n(2), Float(1.4, 2), '') + assert comp(sqrt(2).n(2), 1.4, '') + assert comp(sqrt(2).n(2), Float(1.4, 3), '') is False + assert comp(sqrt(2) + sqrt(3)*I, 1.4 + 1.7*I, .1) + assert not comp(sqrt(2) + sqrt(3)*I, (1.5 + 1.7*I)*0.89, .1) + assert comp(sqrt(2) + sqrt(3)*I, (1.5 + 1.7*I)*0.90, .1) + assert comp(sqrt(2) + sqrt(3)*I, (1.5 + 1.7*I)*1.07, .1) + assert not comp(sqrt(2) + sqrt(3)*I, (1.5 + 1.7*I)*1.08, .1) + assert [(i, j) + for i in range(130, 150) + for j in range(170, 180) + if comp((sqrt(2)+ I*sqrt(3)).n(3), i/100. + I*j/100.)] == [ + (141, 173), (142, 173)] + raises(ValueError, lambda: comp(t, '1')) + raises(ValueError, lambda: comp(t, 1)) + assert comp(0, 0.0) + assert comp(.5, S.Half) + assert comp(2 + sqrt(2), 2.0 + sqrt(2)) + assert not comp(0, 1) + assert not comp(2, sqrt(2)) + assert not comp(2 + I, 2.0 + sqrt(2)) + assert not comp(2.0 + sqrt(2), 2 + I) + assert not comp(2.0 + sqrt(2), sqrt(3)) + assert comp(1/pi.n(4), 0.3183, 1e-5) + assert not comp(1/pi.n(4), 0.3183, 8e-6) + + +def test_issue_9491(): + assert oo**zoo is nan + + +def test_issue_10063(): + assert 2**Float(3) == Float(8) + + +def test_issue_10020(): + assert oo**I is S.NaN + assert oo**(1 + I) is S.ComplexInfinity + assert oo**(-1 + I) is S.Zero + assert (-oo)**I is S.NaN + assert (-oo)**(-1 + I) is S.Zero + assert oo**t == Pow(oo, t, evaluate=False) + assert (-oo)**t == Pow(-oo, t, evaluate=False) + + +def test_invert_numbers(): + assert S(2).invert(5) == 3 + assert S(2).invert(Rational(5, 2)) == S.Half + assert S(2).invert(5.) == S.Half + assert S(2).invert(S(5)) == 3 + assert S(2.).invert(5) == 0.5 + assert S(sqrt(2)).invert(5) == 1/sqrt(2) + assert S(sqrt(2)).invert(sqrt(3)) == 1/sqrt(2) + + +def test_mod_inverse(): + assert mod_inverse(3, 11) == 4 + assert mod_inverse(5, 11) == 9 + assert mod_inverse(21124921, 521512) == 7713 + assert mod_inverse(124215421, 5125) == 2981 + assert mod_inverse(214, 12515) == 1579 + assert mod_inverse(5823991, 3299) == 1442 + assert mod_inverse(123, 44) == 39 + assert mod_inverse(2, 5) == 3 + assert mod_inverse(-2, 5) == 2 + assert mod_inverse(2, -5) == -2 + assert mod_inverse(-2, -5) == -3 + assert mod_inverse(-3, -7) == -5 + x = Symbol('x') + assert S(2).invert(x) == S.Half + raises(TypeError, lambda: mod_inverse(2, x)) + raises(ValueError, lambda: mod_inverse(2, S.Half)) + raises(ValueError, lambda: mod_inverse(2, cos(1)**2 + sin(1)**2)) + + +def test_golden_ratio_rewrite_as_sqrt(): + assert GoldenRatio.rewrite(sqrt) == S.Half + sqrt(5)*S.Half + + +def test_tribonacci_constant_rewrite_as_sqrt(): + assert TribonacciConstant.rewrite(sqrt) == \ + (1 + cbrt(19 - 3*sqrt(33)) + cbrt(19 + 3*sqrt(33))) / 3 + + +def test_comparisons_with_unknown_type(): + class Foo: + """ + Class that is unaware of Basic, and relies on both classes returning + the NotImplemented singleton for equivalence to evaluate to False. + + """ + + ni, nf, nr = Integer(3), Float(1.0), Rational(1, 3) + foo = Foo() + + for n in ni, nf, nr, oo, -oo, zoo, nan: + assert n != foo + assert foo != n + assert not n == foo + assert not foo == n + raises(TypeError, lambda: n < foo) + raises(TypeError, lambda: foo > n) + raises(TypeError, lambda: n > foo) + raises(TypeError, lambda: foo < n) + raises(TypeError, lambda: n <= foo) + raises(TypeError, lambda: foo >= n) + raises(TypeError, lambda: n >= foo) + raises(TypeError, lambda: foo <= n) + + class Bar: + """ + Class that considers itself equal to any instance of Number except + infinities and nans, and relies on SymPy types returning the + NotImplemented singleton for symmetric equality relations. + + """ + def __eq__(self, other): + if other in (oo, -oo, zoo, nan): + return False + if isinstance(other, Number): + return True + return NotImplemented + + def __ne__(self, other): + return not self == other + + bar = Bar() + + for n in ni, nf, nr: + assert n == bar + assert bar == n + assert not n != bar + assert not bar != n + + for n in oo, -oo, zoo, nan: + assert n != bar + assert bar != n + assert not n == bar + assert not bar == n + + for n in ni, nf, nr, oo, -oo, zoo, nan: + raises(TypeError, lambda: n < bar) + raises(TypeError, lambda: bar > n) + raises(TypeError, lambda: n > bar) + raises(TypeError, lambda: bar < n) + raises(TypeError, lambda: n <= bar) + raises(TypeError, lambda: bar >= n) + raises(TypeError, lambda: n >= bar) + raises(TypeError, lambda: bar <= n) + + +def test_NumberSymbol_comparison(): + from sympy.core.tests.test_relational import rel_check + rpi = Rational('905502432259640373/288230376151711744') + fpi = Float(float(pi)) + assert rel_check(rpi, fpi) + + +def test_Integer_precision(): + # Make sure Integer inputs for keyword args work + assert Float('1.0', dps=Integer(15))._prec == 53 + assert Float('1.0', precision=Integer(15))._prec == 15 + assert type(Float('1.0', precision=Integer(15))._prec) == int + assert sympify(srepr(Float('1.0', precision=15))) == Float('1.0', precision=15) + + +def test_numpy_to_float(): + from sympy.testing.pytest import skip + from sympy.external import import_module + np = import_module('numpy') + if not np: + skip('numpy not installed. Abort numpy tests.') + + def check_prec_and_relerr(npval, ratval): + prec = np.finfo(npval).nmant + 1 + x = Float(npval) + assert x._prec == prec + y = Float(ratval, precision=prec) + assert abs((x - y)/y) < 2**(-(prec + 1)) + + check_prec_and_relerr(np.float16(2.0/3), Rational(2, 3)) + check_prec_and_relerr(np.float32(2.0/3), Rational(2, 3)) + check_prec_and_relerr(np.float64(2.0/3), Rational(2, 3)) + # extended precision, on some arch/compilers: + x = np.longdouble(2)/3 + check_prec_and_relerr(x, Rational(2, 3)) + y = Float(x, precision=10) + assert same_and_same_prec(y, Float(Rational(2, 3), precision=10)) + + raises(TypeError, lambda: Float(np.complex64(1+2j))) + raises(TypeError, lambda: Float(np.complex128(1+2j))) + + +def test_Integer_ceiling_floor(): + a = Integer(4) + + assert a.floor() == a + assert a.ceiling() == a + + +def test_ComplexInfinity(): + assert zoo.floor() is zoo + assert zoo.ceiling() is zoo + assert zoo**zoo is S.NaN + + +def test_Infinity_floor_ceiling_power(): + assert oo.floor() is oo + assert oo.ceiling() is oo + assert oo**S.NaN is S.NaN + assert oo**zoo is S.NaN + + +def test_One_power(): + assert S.One**12 is S.One + assert S.NegativeOne**S.NaN is S.NaN + + +def test_NegativeInfinity(): + assert (-oo).floor() is -oo + assert (-oo).ceiling() is -oo + assert (-oo)**11 is -oo + assert (-oo)**12 is oo + + +def test_issue_6133(): + raises(TypeError, lambda: (-oo < None)) + raises(TypeError, lambda: (S(-2) < None)) + raises(TypeError, lambda: (oo < None)) + raises(TypeError, lambda: (oo > None)) + raises(TypeError, lambda: (S(2) < None)) + + +def test_abc(): + x = numbers.Float(5) + assert(isinstance(x, nums.Number)) + assert(isinstance(x, numbers.Number)) + assert(isinstance(x, nums.Real)) + y = numbers.Rational(1, 3) + assert(isinstance(y, nums.Number)) + assert(y.numerator == 1) + assert(y.denominator == 3) + assert(isinstance(y, nums.Rational)) + z = numbers.Integer(3) + assert(isinstance(z, nums.Number)) + assert(isinstance(z, numbers.Number)) + assert(isinstance(z, nums.Rational)) + assert(isinstance(z, numbers.Rational)) + assert(isinstance(z, nums.Integral)) + + +def test_floordiv(): + assert S(2)//S.Half == 4 + + +def test_negation(): + assert -S.Zero is S.Zero + assert -Float(0) is not S.Zero and -Float(0) == 0.0 + + +def test_exponentiation_of_0(): + x = Symbol('x') + assert 0**-x == zoo**x + assert unchanged(Pow, 0, x) + x = Symbol('x', zero=True) + assert 0**-x == S.One + assert 0**x == S.One + + +def test_int_valued(): + x = Symbol('x') + assert int_valued(x) == False + assert int_valued(S.Half) == False + assert int_valued(S.One) == True + assert int_valued(Float(1)) == True + assert int_valued(Float(1.1)) == False + assert int_valued(pi) == False + + +def test_equal_valued(): + x = Symbol('x') + + equal_values = [ + [1, 1.0, S(1), S(1.0), S(1).n(5)], + [2, 2.0, S(2), S(2.0), S(2).n(5)], + [-1, -1.0, -S(1), -S(1.0), -S(1).n(5)], + [0.5, S(0.5), S(1)/2], + [-0.5, -S(0.5), -S(1)/2], + [0, 0.0, S(0), S(0.0), S(0).n()], + [pi], [pi.n()], # <-- not equal + [S(1)/10], [0.1, S(0.1)], # <-- not equal + [S(0.1).n(5)], + [oo], + [cos(x/2)], [cos(0.5*x)], # <-- no recursion + ] + + for m, values_m in enumerate(equal_values): + for value_i in values_m: + + # All values in same list equal + for value_j in values_m: + assert equal_valued(value_i, value_j) is True + + # Not equal to anything in any other list: + for n, values_n in enumerate(equal_values): + if n == m: + continue + for value_j in values_n: + assert equal_valued(value_i, value_j) is False + + +def test_all_close(): + x = Symbol('x') + assert all_close(2, 2) is True + assert all_close(2, 2.0000) is True + assert all_close(2, 2.0001) is False + assert all_close(1/3, 1/3.0001) is False + assert all_close(1/3, 1/3.0001, 1e-3, 1e-3) is True + assert all_close(1/3, Rational(1, 3)) is True + assert all_close(0.1*exp(0.2*x), exp(x/5)/10) is True + # The expressions should be structurally the same: + assert all_close(1.4142135623730951, sqrt(2)) is False + assert all_close(1.4142135623730951, sqrt(2).evalf()) is True + assert all_close(x + 1e-20, x) is False + # We should be able to match terms of an Add/Mul in any order + assert all_close(Add(1, 2, evaluate=False), Add(2, 1, evaluate=False)) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_operations.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_operations.py new file mode 100644 index 0000000000000000000000000000000000000000..c60d691ef00ee9601ada04ef68e2db37794a81ad --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_operations.py @@ -0,0 +1,110 @@ +from sympy.core.expr import Expr +from sympy.core.numbers import Integer +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.core.operations import AssocOp, LatticeOp +from sympy.testing.pytest import raises +from sympy.core.sympify import SympifyError +from sympy.core.add import Add, add +from sympy.core.mul import Mul, mul + +# create the simplest possible Lattice class + + +class join(LatticeOp): + zero = Integer(0) + identity = Integer(1) + + +def test_lattice_simple(): + assert join(join(2, 3), 4) == join(2, join(3, 4)) + assert join(2, 3) == join(3, 2) + assert join(0, 2) == 0 + assert join(1, 2) == 2 + assert join(2, 2) == 2 + + assert join(join(2, 3), 4) == join(2, 3, 4) + assert join() == 1 + assert join(4) == 4 + assert join(1, 4, 2, 3, 1, 3, 2) == join(2, 3, 4) + + +def test_lattice_shortcircuit(): + raises(SympifyError, lambda: join(object)) + assert join(0, object) == 0 + + +def test_lattice_print(): + assert str(join(5, 4, 3, 2)) == 'join(2, 3, 4, 5)' + + +def test_lattice_make_args(): + assert join.make_args(join(2, 3, 4)) == {S(2), S(3), S(4)} + assert join.make_args(0) == {0} + assert list(join.make_args(0))[0] is S.Zero + assert Add.make_args(0)[0] is S.Zero + + +def test_issue_14025(): + a, b, c, d = symbols('a,b,c,d', commutative=False) + assert Mul(a, b, c).has(c*b) == False + assert Mul(a, b, c).has(b*c) == True + assert Mul(a, b, c, d).has(b*c*d) == True + + +def test_AssocOp_flatten(): + a, b, c, d = symbols('a,b,c,d') + + class MyAssoc(AssocOp): + identity = S.One + + assert MyAssoc(a, MyAssoc(b, c)).args == \ + MyAssoc(MyAssoc(a, b), c).args == \ + MyAssoc(MyAssoc(a, b, c)).args == \ + MyAssoc(a, b, c).args == \ + (a, b, c) + u = MyAssoc(b, c) + v = MyAssoc(u, d, evaluate=False) + assert v.args == (u, d) + # like Add, any unevaluated outer call will flatten inner args + assert MyAssoc(a, v).args == (a, b, c, d) + + +def test_add_dispatcher(): + + class NewBase(Expr): + @property + def _add_handler(self): + return NewAdd + class NewAdd(NewBase, Add): + pass + add.register_handlerclass((Add, NewAdd), NewAdd) + + a, b = Symbol('a'), NewBase() + + # Add called as fallback + assert add(1, 2) == Add(1, 2) + assert add(a, a) == Add(a, a) + + # selection by registered priority + assert add(a,b,a) == NewAdd(2*a, b) + + +def test_mul_dispatcher(): + + class NewBase(Expr): + @property + def _mul_handler(self): + return NewMul + class NewMul(NewBase, Mul): + pass + mul.register_handlerclass((Mul, NewMul), NewMul) + + a, b = Symbol('a'), NewBase() + + # Mul called as fallback + assert mul(1, 2) == Mul(1, 2) + assert mul(a, a) == Mul(a, a) + + # selection by registered priority + assert mul(a,b,a) == NewMul(a**2, b) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_parameters.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_parameters.py new file mode 100644 index 0000000000000000000000000000000000000000..21e03d717872a9a8165ceeebf7ef58e9842702c0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_parameters.py @@ -0,0 +1,126 @@ +from sympy.abc import x, y +from sympy.core.parameters import evaluate +from sympy.core import Mul, Add, Pow, S +from sympy.core.numbers import oo +from sympy.functions.elementary.miscellaneous import sqrt + +def test_add(): + with evaluate(False): + p = oo - oo + assert isinstance(p, Add) and p.args == (oo, -oo) + p = 5 - oo + assert isinstance(p, Add) and p.args == (-oo, 5) + p = oo - 5 + assert isinstance(p, Add) and p.args == (oo, -5) + p = oo + 5 + assert isinstance(p, Add) and p.args == (oo, 5) + p = 5 + oo + assert isinstance(p, Add) and p.args == (oo, 5) + p = -oo + 5 + assert isinstance(p, Add) and p.args == (-oo, 5) + p = -5 - oo + assert isinstance(p, Add) and p.args == (-oo, -5) + + with evaluate(False): + expr = x + x + assert isinstance(expr, Add) + assert expr.args == (x, x) + + with evaluate(True): + assert (x + x).args == (2, x) + + assert (x + x).args == (x, x) + + assert isinstance(x + x, Mul) + + with evaluate(False): + assert S.One + 1 == Add(1, 1) + assert 1 + S.One == Add(1, 1) + + assert S(4) - 3 == Add(4, -3) + assert -3 + S(4) == Add(4, -3) + + assert S(2) * 4 == Mul(2, 4) + assert 4 * S(2) == Mul(2, 4) + + assert S(6) / 3 == Mul(6, Pow(3, -1)) + assert S.One / 3 * 6 == Mul(S.One / 3, 6) + + assert 9 ** S(2) == Pow(9, 2) + assert S(2) ** 9 == Pow(2, 9) + + assert S(2) / 2 == Mul(2, Pow(2, -1)) + assert S.One / 2 * 2 == Mul(S.One / 2, 2) + + assert S(2) / 3 + 1 == Add(S(2) / 3, 1) + assert 1 + S(2) / 3 == Add(1, S(2) / 3) + + assert S(4) / 7 - 3 == Add(S(4) / 7, -3) + assert -3 + S(4) / 7 == Add(-3, S(4) / 7) + + assert S(2) / 4 * 4 == Mul(S(2) / 4, 4) + assert 4 * (S(2) / 4) == Mul(4, S(2) / 4) + + assert S(6) / 3 == Mul(6, Pow(3, -1)) + assert S.One / 3 * 6 == Mul(S.One / 3, 6) + + assert S.One / 3 + sqrt(3) == Add(S.One / 3, sqrt(3)) + assert sqrt(3) + S.One / 3 == Add(sqrt(3), S.One / 3) + + assert S.One / 2 * 10.333 == Mul(S.One / 2, 10.333) + assert 10.333 * (S.One / 2) == Mul(10.333, S.One / 2) + + assert sqrt(2) * sqrt(2) == Mul(sqrt(2), sqrt(2)) + + assert S.One / 2 + x == Add(S.One / 2, x) + assert x + S.One / 2 == Add(x, S.One / 2) + + assert S.One / x * x == Mul(S.One / x, x) + assert x * (S.One / x) == Mul(x, Pow(x, -1)) + + assert S.One / 3 == Pow(3, -1) + assert S.One / x == Pow(x, -1) + assert 1 / S(3) == Pow(3, -1) + assert 1 / x == Pow(x, -1) + +def test_nested(): + with evaluate(False): + expr = (x + x) + (y + y) + assert expr.args == ((x + x), (y + y)) + assert expr.args[0].args == (x, x) + +def test_reentrantcy(): + with evaluate(False): + expr = x + x + assert expr.args == (x, x) + with evaluate(True): + expr = x + x + assert expr.args == (2, x) + expr = x + x + assert expr.args == (x, x) + +def test_reusability(): + f = evaluate(False) + + with f: + expr = x + x + assert expr.args == (x, x) + + expr = x + x + assert expr.args == (2, x) + + with f: + expr = x + x + assert expr.args == (x, x) + + # Assure reentrancy with reusability + ctx = evaluate(False) + with ctx: + expr = x + x + assert expr.args == (x, x) + with ctx: + expr = x + x + assert expr.args == (x, x) + + expr = x + x + assert expr.args == (2, x) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_power.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_power.py new file mode 100644 index 0000000000000000000000000000000000000000..9dcc828d854c75cebc8177663035e976ae10f9e5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_power.py @@ -0,0 +1,663 @@ +from sympy.core import ( + Basic, Rational, Symbol, S, Float, Integer, Mul, Number, Pow, + Expr, I, nan, pi, symbols, oo, zoo, N) +from sympy.core.parameters import global_parameters +from sympy.core.tests.test_evalf import NS +from sympy.core.function import expand_multinomial +from sympy.functions.elementary.miscellaneous import sqrt, cbrt +from sympy.functions.elementary.exponential import exp, log +from sympy.functions.special.error_functions import erf +from sympy.functions.elementary.trigonometric import ( + sin, cos, tan, sec, csc, atan) +from sympy.functions.elementary.hyperbolic import cosh, sinh, tanh +from sympy.polys import Poly +from sympy.series.order import O +from sympy.sets import FiniteSet +from sympy.core.power import power +from sympy.core.intfunc import integer_nthroot +from sympy.testing.pytest import warns, _both_exp_pow +from sympy.utilities.exceptions import SymPyDeprecationWarning +from sympy.abc import a, b, c, x, y + +def test_rational(): + a = Rational(1, 5) + + r = sqrt(5)/5 + assert sqrt(a) == r + assert 2*sqrt(a) == 2*r + + r = a*a**S.Half + assert a**Rational(3, 2) == r + assert 2*a**Rational(3, 2) == 2*r + + r = a**5*a**Rational(2, 3) + assert a**Rational(17, 3) == r + assert 2 * a**Rational(17, 3) == 2*r + + +def test_large_rational(): + e = (Rational(123712**12 - 1, 7) + Rational(1, 7))**Rational(1, 3) + assert e == 234232585392159195136 * (Rational(1, 7)**Rational(1, 3)) + + +def test_negative_real(): + def feq(a, b): + return abs(a - b) < 1E-10 + + assert feq(S.One / Float(-0.5), -Integer(2)) + + +def test_expand(): + assert (2**(-1 - x)).expand() == S.Half*2**(-x) + + +def test_issue_3449(): + #test if powers are simplified correctly + #see also issue 3995 + assert ((x**Rational(1, 3))**Rational(2)) == x**Rational(2, 3) + assert ( + (x**Rational(3))**Rational(2, 5)) == (x**Rational(3))**Rational(2, 5) + + a = Symbol('a', real=True) + b = Symbol('b', real=True) + assert (a**2)**b == (abs(a)**b)**2 + assert sqrt(1/a) != 1/sqrt(a) # e.g. for a = -1 + assert (a**3)**Rational(1, 3) != a + assert (x**a)**b != x**(a*b) # e.g. x = -1, a=2, b=1/2 + assert (x**.5)**b == x**(.5*b) + assert (x**.5)**.5 == x**.25 + assert (x**2.5)**.5 != x**1.25 # e.g. for x = 5*I + + k = Symbol('k', integer=True) + m = Symbol('m', integer=True) + assert (x**k)**m == x**(k*m) + assert Number(5)**Rational(2, 3) == Number(25)**Rational(1, 3) + + assert (x**.5)**2 == x**1.0 + assert (x**2)**k == (x**k)**2 == x**(2*k) + + a = Symbol('a', positive=True) + assert (a**3)**Rational(2, 5) == a**Rational(6, 5) + assert (a**2)**b == (a**b)**2 + assert (a**Rational(2, 3))**x == a**(x*Rational(2, 3)) != (a**x)**Rational(2, 3) + + +def test_issue_3866(): + assert --sqrt(sqrt(5) - 1) == sqrt(sqrt(5) - 1) + + +def test_negative_one(): + x = Symbol('x', complex=True) + y = Symbol('y', complex=True) + assert 1/x**y == x**(-y) + + +def test_issue_4362(): + neg = Symbol('neg', negative=True) + nonneg = Symbol('nonneg', nonnegative=True) + any = Symbol('any') + num, den = sqrt(1/neg).as_numer_denom() + assert num == sqrt(-1) + assert den == sqrt(-neg) + num, den = sqrt(1/nonneg).as_numer_denom() + assert num == 1 + assert den == sqrt(nonneg) + num, den = sqrt(1/any).as_numer_denom() + assert num == sqrt(1/any) + assert den == 1 + + def eqn(num, den, pow): + return (num/den)**pow + npos = 1 + nneg = -1 + dpos = 2 - sqrt(3) + dneg = 1 - sqrt(3) + assert dpos > 0 and dneg < 0 and npos > 0 and nneg < 0 + # pos or neg integer + eq = eqn(npos, dpos, 2) + assert eq.is_Pow and eq.as_numer_denom() == (1, dpos**2) + eq = eqn(npos, dneg, 2) + assert eq.is_Pow and eq.as_numer_denom() == (1, dneg**2) + eq = eqn(nneg, dpos, 2) + assert eq.is_Pow and eq.as_numer_denom() == (1, dpos**2) + eq = eqn(nneg, dneg, 2) + assert eq.is_Pow and eq.as_numer_denom() == (1, dneg**2) + eq = eqn(npos, dpos, -2) + assert eq.is_Pow and eq.as_numer_denom() == (dpos**2, 1) + eq = eqn(npos, dneg, -2) + assert eq.is_Pow and eq.as_numer_denom() == (dneg**2, 1) + eq = eqn(nneg, dpos, -2) + assert eq.is_Pow and eq.as_numer_denom() == (dpos**2, 1) + eq = eqn(nneg, dneg, -2) + assert eq.is_Pow and eq.as_numer_denom() == (dneg**2, 1) + # pos or neg rational + pow = S.Half + eq = eqn(npos, dpos, pow) + assert eq.is_Pow and eq.as_numer_denom() == (npos**pow, dpos**pow) + eq = eqn(npos, dneg, pow) + assert eq.is_Pow is False and eq.as_numer_denom() == ((-npos)**pow, (-dneg)**pow) + eq = eqn(nneg, dpos, pow) + assert not eq.is_Pow or eq.as_numer_denom() == (nneg**pow, dpos**pow) + eq = eqn(nneg, dneg, pow) + assert eq.is_Pow and eq.as_numer_denom() == ((-nneg)**pow, (-dneg)**pow) + eq = eqn(npos, dpos, -pow) + assert eq.is_Pow and eq.as_numer_denom() == (dpos**pow, npos**pow) + eq = eqn(npos, dneg, -pow) + assert eq.is_Pow is False and eq.as_numer_denom() == (-(-npos)**pow*(-dneg)**pow, npos) + eq = eqn(nneg, dpos, -pow) + assert not eq.is_Pow or eq.as_numer_denom() == (dpos**pow, nneg**pow) + eq = eqn(nneg, dneg, -pow) + assert eq.is_Pow and eq.as_numer_denom() == ((-dneg)**pow, (-nneg)**pow) + # unknown exponent + pow = 2*any + eq = eqn(npos, dpos, pow) + assert eq.is_Pow and eq.as_numer_denom() == (npos**pow, dpos**pow) + eq = eqn(npos, dneg, pow) + assert eq.is_Pow and eq.as_numer_denom() == ((-npos)**pow, (-dneg)**pow) + eq = eqn(nneg, dpos, pow) + assert eq.is_Pow and eq.as_numer_denom() == (nneg**pow, dpos**pow) + eq = eqn(nneg, dneg, pow) + assert eq.is_Pow and eq.as_numer_denom() == ((-nneg)**pow, (-dneg)**pow) + eq = eqn(npos, dpos, -pow) + assert eq.as_numer_denom() == (dpos**pow, npos**pow) + eq = eqn(npos, dneg, -pow) + assert eq.is_Pow and eq.as_numer_denom() == ((-dneg)**pow, (-npos)**pow) + eq = eqn(nneg, dpos, -pow) + assert eq.is_Pow and eq.as_numer_denom() == (dpos**pow, nneg**pow) + eq = eqn(nneg, dneg, -pow) + assert eq.is_Pow and eq.as_numer_denom() == ((-dneg)**pow, (-nneg)**pow) + + assert ((1/(1 + x/3))**(-S.One)).as_numer_denom() == (3 + x, 3) + notp = Symbol('notp', positive=False) # not positive does not imply real + b = ((1 + x/notp)**-2) + assert (b**(-y)).as_numer_denom() == (1, b**y) + assert (b**(-S.One)).as_numer_denom() == ((notp + x)**2, notp**2) + nonp = Symbol('nonp', nonpositive=True) + assert (((1 + x/nonp)**-2)**(-S.One)).as_numer_denom() == ((-nonp - + x)**2, nonp**2) + + n = Symbol('n', negative=True) + assert (x**n).as_numer_denom() == (1, x**-n) + assert sqrt(1/n).as_numer_denom() == (S.ImaginaryUnit, sqrt(-n)) + n = Symbol('0 or neg', nonpositive=True) + # if x and n are split up without negating each term and n is negative + # then the answer might be wrong; if n is 0 it won't matter since + # 1/oo and 1/zoo are both zero as is sqrt(0)/sqrt(-x) unless x is also + # zero (in which case the negative sign doesn't matter): + # 1/sqrt(1/-1) = -I but sqrt(-1)/sqrt(1) = I + assert (1/sqrt(x/n)).as_numer_denom() == (sqrt(-n), sqrt(-x)) + c = Symbol('c', complex=True) + e = sqrt(1/c) + assert e.as_numer_denom() == (e, 1) + i = Symbol('i', integer=True) + assert ((1 + x/y)**i).as_numer_denom() == ((x + y)**i, y**i) + + +def test_Pow_Expr_args(): + bases = [Basic(), Poly(x, x), FiniteSet(x)] + for base in bases: + # The cache can mess with the stacklevel test + with warns(SymPyDeprecationWarning, test_stacklevel=False): + Pow(base, S.One) + + +def test_Pow_signs(): + """Cf. issues 4595 and 5250""" + n = Symbol('n', even=True) + assert (3 - y)**2 != (y - 3)**2 + assert (3 - y)**n != (y - 3)**n + assert (-3 + y - x)**2 != (3 - y + x)**2 + assert (y - 3)**3 != -(3 - y)**3 + + +def test_power_with_noncommutative_mul_as_base(): + x = Symbol('x', commutative=False) + y = Symbol('y', commutative=False) + assert not (x*y)**3 == x**3*y**3 + assert (2*x*y)**3 == 8*(x*y)**3 + + +@_both_exp_pow +def test_power_rewrite_exp(): + assert (I**I).rewrite(exp) == exp(-pi/2) + + expr = (2 + 3*I)**(4 + 5*I) + assert expr.rewrite(exp) == exp((4 + 5*I)*(log(sqrt(13)) + I*atan(Rational(3, 2)))) + assert expr.rewrite(exp).expand() == \ + 169*exp(5*I*log(13)/2)*exp(4*I*atan(Rational(3, 2)))*exp(-5*atan(Rational(3, 2))) + + assert ((6 + 7*I)**5).rewrite(exp) == 7225*sqrt(85)*exp(5*I*atan(Rational(7, 6))) + + expr = 5**(6 + 7*I) + assert expr.rewrite(exp) == exp((6 + 7*I)*log(5)) + assert expr.rewrite(exp).expand() == 15625*exp(7*I*log(5)) + + assert Pow(123, 789, evaluate=False).rewrite(exp) == 123**789 + assert (1**I).rewrite(exp) == 1**I + assert (0**I).rewrite(exp) == 0**I + + expr = (-2)**(2 + 5*I) + assert expr.rewrite(exp) == exp((2 + 5*I)*(log(2) + I*pi)) + assert expr.rewrite(exp).expand() == 4*exp(-5*pi)*exp(5*I*log(2)) + + assert ((-2)**S(-5)).rewrite(exp) == (-2)**S(-5) + + x, y = symbols('x y') + assert (x**y).rewrite(exp) == exp(y*log(x)) + if global_parameters.exp_is_pow: + assert (7**x).rewrite(exp) == Pow(S.Exp1, x*log(7), evaluate=False) + else: + assert (7**x).rewrite(exp) == exp(x*log(7), evaluate=False) + assert ((2 + 3*I)**x).rewrite(exp) == exp(x*(log(sqrt(13)) + I*atan(Rational(3, 2)))) + assert (y**(5 + 6*I)).rewrite(exp) == exp(log(y)*(5 + 6*I)) + + assert all((1/func(x)).rewrite(exp) == 1/(func(x).rewrite(exp)) for func in + (sin, cos, tan, sec, csc, sinh, cosh, tanh)) + + +def test_zero(): + assert 0**x != 0 + assert 0**(2*x) == 0**x + assert 0**(1.0*x) == 0**x + assert 0**(2.0*x) == 0**x + assert (0**(2 - x)).as_base_exp() == (0, 2 - x) + assert 0**(x - 2) != S.Infinity**(2 - x) + assert 0**(2*x*y) == 0**(x*y) + assert 0**(-2*x*y) == S.ComplexInfinity**(x*y) + assert Float(0)**2 is not S.Zero + assert Float(0)**2 == 0.0 + assert Float(0)**-2 is zoo + assert Float(0)**oo is S.Zero + + #Test issue 19572 + assert 0 ** -oo is zoo + assert power(0, -oo) is zoo + assert Float(0)**-oo is zoo + +def test_pow_as_base_exp(): + assert (S.Infinity**(2 - x)).as_base_exp() == (S.Infinity, 2 - x) + assert (S.Infinity**(x - 2)).as_base_exp() == (S.Infinity, x - 2) + p = S.Half**x + assert p.base, p.exp == p.as_base_exp() == (S(2), -x) + p = (S(3)/2)**x + assert p.base, p.exp == p.as_base_exp() == (3*S.Half, x) + p = (S(2)/3)**x + assert p.as_base_exp() == (S(3)/2, -x) + assert p.base, p.exp == (S(2)/3, x) + # issue 8344: + assert Pow(1, 2, evaluate=False).as_base_exp() == (S.One, S(2)) + + +def test_nseries(): + assert sqrt(I*x - 1)._eval_nseries(x, 4, None, 1) == I + x/2 + I*x**2/8 - x**3/16 + O(x**4) + assert sqrt(I*x - 1)._eval_nseries(x, 4, None, -1) == -I - x/2 - I*x**2/8 + x**3/16 + O(x**4) + assert cbrt(I*x - 1)._eval_nseries(x, 4, None, 1) == (-1)**(S(1)/3) - (-1)**(S(5)/6)*x/3 + \ + (-1)**(S(1)/3)*x**2/9 + 5*(-1)**(S(5)/6)*x**3/81 + O(x**4) + assert cbrt(I*x - 1)._eval_nseries(x, 4, None, -1) == -(-1)**(S(2)/3) - (-1)**(S(1)/6)*x/3 - \ + (-1)**(S(2)/3)*x**2/9 + 5*(-1)**(S(1)/6)*x**3/81 + O(x**4) + assert (1 / (exp(-1/x) + 1/x))._eval_nseries(x, 2, None) == x + O(x**2) + # test issue 23752 + assert sqrt(-I*x**2 + x - 3)._eval_nseries(x, 4, None, 1) == -sqrt(3)*I + sqrt(3)*I*x/6 - \ + sqrt(3)*I*x**2*(-S(1)/72 + I/6) - sqrt(3)*I*x**3*(-S(1)/432 + I/36) + O(x**4) + assert sqrt(-I*x**2 + x - 3)._eval_nseries(x, 4, None, -1) == -sqrt(3)*I + sqrt(3)*I*x/6 - \ + sqrt(3)*I*x**2*(-S(1)/72 + I/6) - sqrt(3)*I*x**3*(-S(1)/432 + I/36) + O(x**4) + assert cbrt(-I*x**2 + x - 3)._eval_nseries(x, 4, None, 1) == -(-1)**(S(2)/3)*3**(S(1)/3) + \ + (-1)**(S(2)/3)*3**(S(1)/3)*x/9 - (-1)**(S(2)/3)*3**(S(1)/3)*x**2*(-S(1)/81 + I/9) - \ + (-1)**(S(2)/3)*3**(S(1)/3)*x**3*(-S(5)/2187 + 2*I/81) + O(x**4) + assert cbrt(-I*x**2 + x - 3)._eval_nseries(x, 4, None, -1) == -(-1)**(S(2)/3)*3**(S(1)/3) + \ + (-1)**(S(2)/3)*3**(S(1)/3)*x/9 - (-1)**(S(2)/3)*3**(S(1)/3)*x**2*(-S(1)/81 + I/9) - \ + (-1)**(S(2)/3)*3**(S(1)/3)*x**3*(-S(5)/2187 + 2*I/81) + O(x**4) + + +def test_issue_6100_12942_4473(): + assert x**1.0 != x + assert x != x**1.0 + assert True != x**1.0 + assert x**1.0 is not True + assert x is not True + assert x*y != (x*y)**1.0 + # Pow != Symbol + assert (x**1.0)**1.0 != x + assert (x**1.0)**2.0 != x**2 + b = Expr() + assert Pow(b, 1.0, evaluate=False) != b + # if the following gets distributed as a Mul (x**1.0*y**1.0 then + # __eq__ methods could be added to Symbol and Pow to detect the + # power-of-1.0 case. + assert ((x*y)**1.0).func is Pow + + +def test_issue_6208(): + from sympy.functions.elementary.miscellaneous import root + assert sqrt(33**(I*9/10)) == -33**(I*9/20) + assert root((6*I)**(2*I), 3).as_base_exp()[1] == Rational(1, 3) # != 2*I/3 + assert root((6*I)**(I/3), 3).as_base_exp()[1] == I/9 + assert sqrt(exp(3*I)) == exp(3*I/2) + assert sqrt(-sqrt(3)*(1 + 2*I)) == sqrt(sqrt(3))*sqrt(-1 - 2*I) + assert sqrt(exp(5*I)) == -exp(5*I/2) + assert root(exp(5*I), 3).exp == Rational(1, 3) + + +def test_issue_6990(): + assert (sqrt(a + b*x + x**2)).series(x, 0, 3).removeO() == \ + sqrt(a)*x**2*(1/(2*a) - b**2/(8*a**2)) + sqrt(a) + b*x/(2*sqrt(a)) + + +def test_issue_6068(): + assert sqrt(sin(x)).series(x, 0, 7) == \ + sqrt(x) - x**Rational(5, 2)/12 + x**Rational(9, 2)/1440 - \ + x**Rational(13, 2)/24192 + O(x**7) + assert sqrt(sin(x)).series(x, 0, 9) == \ + sqrt(x) - x**Rational(5, 2)/12 + x**Rational(9, 2)/1440 - \ + x**Rational(13, 2)/24192 - 67*x**Rational(17, 2)/29030400 + O(x**9) + assert sqrt(sin(x**3)).series(x, 0, 19) == \ + x**Rational(3, 2) - x**Rational(15, 2)/12 + x**Rational(27, 2)/1440 + O(x**19) + assert sqrt(sin(x**3)).series(x, 0, 20) == \ + x**Rational(3, 2) - x**Rational(15, 2)/12 + x**Rational(27, 2)/1440 - \ + x**Rational(39, 2)/24192 + O(x**20) + + +def test_issue_6782(): + assert sqrt(sin(x**3)).series(x, 0, 7) == x**Rational(3, 2) + O(x**7) + assert sqrt(sin(x**4)).series(x, 0, 3) == x**2 + O(x**3) + + +def test_issue_6653(): + assert (1 / sqrt(1 + sin(x**2))).series(x, 0, 3) == 1 - x**2/2 + O(x**3) + + +def test_issue_6429(): + f = (c**2 + x)**(0.5) + assert f.series(x, x0=0, n=1) == (c**2)**0.5 + O(x) + assert f.taylor_term(0, x) == (c**2)**0.5 + assert f.taylor_term(1, x) == 0.5*x*(c**2)**(-0.5) + assert f.taylor_term(2, x) == -0.125*x**2*(c**2)**(-1.5) + + +def test_issue_7638(): + f = pi/log(sqrt(2)) + assert ((1 + I)**(I*f/2))**0.3 == (1 + I)**(0.15*I*f) + # if 1/3 -> 1.0/3 this should fail since it cannot be shown that the + # sign will be +/-1; for the previous "small arg" case, it didn't matter + # that this could not be proved + assert (1 + I)**(4*I*f) == ((1 + I)**(12*I*f))**Rational(1, 3) + + assert (((1 + I)**(I*(1 + 7*f)))**Rational(1, 3)).exp == Rational(1, 3) + r = symbols('r', real=True) + assert sqrt(r**2) == abs(r) + assert cbrt(r**3) != r + assert sqrt(Pow(2*I, 5*S.Half)) != (2*I)**Rational(5, 4) + p = symbols('p', positive=True) + assert cbrt(p**2) == p**Rational(2, 3) + assert NS(((0.2 + 0.7*I)**(0.7 + 1.0*I))**(0.5 - 0.1*I), 1) == '0.4 + 0.2*I' + assert sqrt(1/(1 + I)) == sqrt(1 - I)/sqrt(2) # or 1/sqrt(1 + I) + e = 1/(1 - sqrt(2)) + assert sqrt(e) == I/sqrt(-1 + sqrt(2)) + assert e**Rational(-1, 2) == -I*sqrt(-1 + sqrt(2)) + assert sqrt((cos(1)**2 + sin(1)**2 - 1)**(3 + I)).exp in [S.Half, + Rational(3, 2) + I/2] + assert sqrt(r**Rational(4, 3)) != r**Rational(2, 3) + assert sqrt((p + I)**Rational(4, 3)) == (p + I)**Rational(2, 3) + + for q in 1+I, 1-I: + assert sqrt(q**2) == q + for q in -1+I, -1-I: + assert sqrt(q**2) == -q + + assert sqrt((p + r*I)**2) != p + r*I + e = (1 + I/5) + assert sqrt(e**5) == e**(5*S.Half) + assert sqrt(e**6) == e**3 + assert sqrt((1 + I*r)**6) != (1 + I*r)**3 + + +def test_issue_8582(): + assert 1**oo is nan + assert 1**(-oo) is nan + assert 1**zoo is nan + assert 1**(oo + I) is nan + assert 1**(1 + I*oo) is nan + assert 1**(oo + I*oo) is nan + + +def test_issue_8650(): + n = Symbol('n', integer=True, nonnegative=True) + assert (n**n).is_positive is True + x = 5*n + 5 + assert (x**(5*(n + 1))).is_positive is True + + +def test_issue_13914(): + b = Symbol('b') + assert (-1)**zoo is nan + assert 2**zoo is nan + assert (S.Half)**(1 + zoo) is nan + assert I**(zoo + I) is nan + assert b**(I + zoo) is nan + + +def test_better_sqrt(): + n = Symbol('n', integer=True, nonnegative=True) + assert sqrt(3 + 4*I) == 2 + I + assert sqrt(3 - 4*I) == 2 - I + assert sqrt(-3 - 4*I) == 1 - 2*I + assert sqrt(-3 + 4*I) == 1 + 2*I + assert sqrt(32 + 24*I) == 6 + 2*I + assert sqrt(32 - 24*I) == 6 - 2*I + assert sqrt(-32 - 24*I) == 2 - 6*I + assert sqrt(-32 + 24*I) == 2 + 6*I + + # triple (3, 4, 5): + # parity of 3 matches parity of 5 and + # den, 4, is a square + assert sqrt((3 + 4*I)/4) == 1 + I/2 + # triple (8, 15, 17) + # parity of 8 doesn't match parity of 17 but + # den/2, 8/2, is a square + assert sqrt((8 + 15*I)/8) == (5 + 3*I)/4 + # handle the denominator + assert sqrt((3 - 4*I)/25) == (2 - I)/5 + assert sqrt((3 - 4*I)/26) == (2 - I)/sqrt(26) + # mul + # issue #12739 + assert sqrt((3 + 4*I)/(3 - 4*I)) == (3 + 4*I)/5 + assert sqrt(2/(3 + 4*I)) == sqrt(2)/5*(2 - I) + assert sqrt(n/(3 + 4*I)).subs(n, 2) == sqrt(2)/5*(2 - I) + assert sqrt(-2/(3 + 4*I)) == sqrt(2)/5*(1 + 2*I) + assert sqrt(-n/(3 + 4*I)).subs(n, 2) == sqrt(2)/5*(1 + 2*I) + # power + assert sqrt(1/(3 + I*4)) == (2 - I)/5 + assert sqrt(1/(3 - I)) == sqrt(10)*sqrt(3 + I)/10 + # symbolic + i = symbols('i', imaginary=True) + assert sqrt(3/i) == Mul(sqrt(3), 1/sqrt(i), evaluate=False) + # multiples of 1/2; don't make this too automatic + assert sqrt(3 + 4*I)**3 == (2 + I)**3 + assert Pow(3 + 4*I, Rational(3, 2)) == 2 + 11*I + assert Pow(6 + 8*I, Rational(3, 2)) == 2*sqrt(2)*(2 + 11*I) + n, d = (3 + 4*I), (3 - 4*I)**3 + a = n/d + assert a.args == (1/d, n) + eq = sqrt(a) + assert eq.args == (a, S.Half) + assert expand_multinomial(eq) == sqrt((-117 + 44*I)*(3 + 4*I))/125 + assert eq.expand() == (7 - 24*I)/125 + + # issue 12775 + # pos im part + assert sqrt(2*I) == (1 + I) + assert sqrt(2*9*I) == Mul(3, 1 + I, evaluate=False) + assert Pow(2*I, 3*S.Half) == (1 + I)**3 + # neg im part + assert sqrt(-I/2) == Mul(S.Half, 1 - I, evaluate=False) + # fractional im part + assert Pow(Rational(-9, 2)*I, Rational(3, 2)) == 27*(1 - I)**3/8 + + +def test_issue_2993(): + assert str((2.3*x - 4)**0.3) == '1.5157165665104*(0.575*x - 1)**0.3' + assert str((2.3*x + 4)**0.3) == '1.5157165665104*(0.575*x + 1)**0.3' + assert str((-2.3*x + 4)**0.3) == '1.5157165665104*(1 - 0.575*x)**0.3' + assert str((-2.3*x - 4)**0.3) == '1.5157165665104*(-0.575*x - 1)**0.3' + assert str((2.3*x - 2)**0.3) == '1.28386201800527*(x - 0.869565217391304)**0.3' + assert str((-2.3*x - 2)**0.3) == '1.28386201800527*(-x - 0.869565217391304)**0.3' + assert str((-2.3*x + 2)**0.3) == '1.28386201800527*(0.869565217391304 - x)**0.3' + assert str((2.3*x + 2)**0.3) == '1.28386201800527*(x + 0.869565217391304)**0.3' + assert str((2.3*x - 4)**Rational(1, 3)) == '2**(2/3)*(0.575*x - 1)**(1/3)' + eq = (2.3*x + 4) + assert eq**2 == 16*(0.575*x + 1)**2 + assert (1/eq).args == (eq, -1) # don't change trivial power + # issue 17735 + q=.5*exp(x) - .5*exp(-x) + 0.1 + assert int((q**2).subs(x, 1)) == 1 + # issue 17756 + y = Symbol('y') + assert len(sqrt(x/(x + y)**2 + Float('0.008', 30)).subs(y, pi.n(25)).atoms(Float)) == 2 + # issue 17756 + a, b, c, d, e, f, g = symbols('a:g') + expr = sqrt(1 + a*(c**4 + g*d - 2*g*e - f*(-g + d))**2/ + (c**3*b**2*(d - 3*e + 2*f)**2))/2 + r = [ + (a, N('0.0170992456333788667034850458615', 30)), + (b, N('0.0966594956075474769169134801223', 30)), + (c, N('0.390911862903463913632151616184', 30)), + (d, N('0.152812084558656566271750185933', 30)), + (e, N('0.137562344465103337106561623432', 30)), + (f, N('0.174259178881496659302933610355', 30)), + (g, N('0.220745448491223779615401870086', 30))] + tru = expr.n(30, subs=dict(r)) + seq = expr.subs(r) + # although `tru` is the right way to evaluate + # expr with numerical values, `seq` will have + # significant loss of precision if extraction of + # the largest coefficient of a power's base's terms + # is done improperly + assert seq == tru + +def test_issue_17450(): + assert (erf(cosh(1)**7)**I).is_real is None + assert (erf(cosh(1)**7)**I).is_imaginary is False + assert (Pow(exp(1+sqrt(2)), ((1-sqrt(2))*I*pi), evaluate=False)).is_real is None + assert ((-10)**(10*I*pi/3)).is_real is False + assert ((-5)**(4*I*pi)).is_real is False + + +def test_issue_18190(): + assert sqrt(1 / tan(1 + I)) == 1 / sqrt(tan(1 + I)) + + +def test_issue_14815(): + x = Symbol('x', real=True) + assert sqrt(x).is_extended_negative is False + x = Symbol('x', real=False) + assert sqrt(x).is_extended_negative is None + x = Symbol('x', complex=True) + assert sqrt(x).is_extended_negative is False + x = Symbol('x', extended_real=True) + assert sqrt(x).is_extended_negative is False + assert sqrt(zoo, evaluate=False).is_extended_negative is False + assert sqrt(nan, evaluate=False).is_extended_negative is None + + +def test_issue_18509(): + x = Symbol('x', prime=True) + assert x**oo is oo + assert (1/x)**oo is S.Zero + assert (-1/x)**oo is S.Zero + assert (-x)**oo is zoo + assert (-oo)**(-1 + I) is S.Zero + assert (-oo)**(1 + I) is zoo + assert (oo)**(-1 + I) is S.Zero + assert (oo)**(1 + I) is zoo + + +def test_issue_18762(): + e, p = symbols('e p') + g0 = sqrt(1 + e**2 - 2*e*cos(p)) + assert len(g0.series(e, 1, 3).args) == 4 + + +def test_issue_21860(): + e = 3*2**Rational(66666666667,200000000000)*3**Rational(16666666667,50000000000)*x**Rational(66666666667, 200000000000) + ans = Mul(Rational(3, 2), + Pow(Integer(2), Rational(33333333333, 100000000000)), + Pow(Integer(3), Rational(26666666667, 40000000000))) + assert e.xreplace({x: Rational(3,8)}) == ans + + +def test_issue_21647(): + e = log((Integer(567)/500)**(811*(Integer(567)/500)**x/100)) + ans = log(Mul(Rational(64701150190720499096094005280169087619821081527, + 76293945312500000000000000000000000000000000000), + Pow(Integer(2), Rational(396204892125479941, 781250000000000000)), + Pow(Integer(3), Rational(385045107874520059, 390625000000000000)), + Pow(Integer(5), Rational(407364676376439823, 1562500000000000000)), + Pow(Integer(7), Rational(385045107874520059, 1562500000000000000)))) + assert e.xreplace({x: 6}) == ans + + +def test_issue_21762(): + e = (x**2 + 6)**(Integer(33333333333333333)/50000000000000000) + ans = Mul(Rational(5, 4), + Pow(Integer(2), Rational(16666666666666667, 25000000000000000)), + Pow(Integer(5), Rational(8333333333333333, 25000000000000000))) + assert e.xreplace({x: S.Half}) == ans + + +def test_issue_14704(): + a = 144**144 + x, xexact = integer_nthroot(a,a) + assert x == 1 and xexact is False + + +def test_rational_powers_larger_than_one(): + assert Rational(2, 3)**Rational(3, 2) == 2*sqrt(6)/9 + assert Rational(1, 6)**Rational(9, 4) == 6**Rational(3, 4)/216 + assert Rational(3, 7)**Rational(7, 3) == 9*3**Rational(1, 3)*7**Rational(2, 3)/343 + + +def test_power_dispatcher(): + + class NewBase(Expr): + pass + class NewPow(NewBase, Pow): + pass + a, b = Symbol('a'), NewBase() + + @power.register(Expr, NewBase) + @power.register(NewBase, Expr) + @power.register(NewBase, NewBase) + def _(a, b): + return NewPow(a, b) + + # Pow called as fallback + assert power(2, 3) == 8*S.One + assert power(a, 2) == Pow(a, 2) + assert power(a, a) == Pow(a, a) + + # NewPow called by dispatch + assert power(a, b) == NewPow(a, b) + assert power(b, a) == NewPow(b, a) + assert power(b, b) == NewPow(b, b) + + +def test_powers_of_I(): + assert [sqrt(I)**i for i in range(13)] == [ + 1, sqrt(I), I, sqrt(I)**3, -1, -sqrt(I), -I, -sqrt(I)**3, + 1, sqrt(I), I, sqrt(I)**3, -1] + assert sqrt(I)**(S(9)/2) == -I**(S(1)/4) + + +def test_issue_23918(): + b = S(2)/3 + assert (b**x).as_base_exp() == (1/b, -x) + + +def test_issue_26546(): + x = Symbol('x', real=True) + assert x.is_extended_real is True + assert sqrt(x+I).is_extended_real is False + assert Pow(x+I, S.Half).is_extended_real is False + assert Pow(x+I, Rational(1,2)).is_extended_real is False + assert Pow(x+I, Rational(1,13)).is_extended_real is False + assert Pow(x+I, Rational(2,3)).is_extended_real is None diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_priority.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_priority.py new file mode 100644 index 0000000000000000000000000000000000000000..7be30f24033698e43ed68bdbaa0f3566465de173 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_priority.py @@ -0,0 +1,144 @@ +from sympy.core.decorators import call_highest_priority +from sympy.core.expr import Expr +from sympy.core.mod import Mod +from sympy.core.numbers import Integer +from sympy.core.symbol import Symbol +from sympy.functions.elementary.integers import floor + + +class Higher(Integer): + ''' + Integer of value 1 and _op_priority 20 + + Operations handled by this class return 1 and reverse operations return 2 + ''' + + _op_priority = 20.0 + result = 1 + + def __new__(cls): + obj = Expr.__new__(cls) + obj.p = 1 + return obj + + @call_highest_priority('__rmul__') + def __mul__(self, other): + return self.result + + @call_highest_priority('__mul__') + def __rmul__(self, other): + return 2*self.result + + @call_highest_priority('__radd__') + def __add__(self, other): + return self.result + + @call_highest_priority('__add__') + def __radd__(self, other): + return 2*self.result + + @call_highest_priority('__rsub__') + def __sub__(self, other): + return self.result + + @call_highest_priority('__sub__') + def __rsub__(self, other): + return 2*self.result + + @call_highest_priority('__rpow__') + def __pow__(self, other): + return self.result + + @call_highest_priority('__pow__') + def __rpow__(self, other): + return 2*self.result + + @call_highest_priority('__rtruediv__') + def __truediv__(self, other): + return self.result + + @call_highest_priority('__truediv__') + def __rtruediv__(self, other): + return 2*self.result + + @call_highest_priority('__rmod__') + def __mod__(self, other): + return self.result + + @call_highest_priority('__mod__') + def __rmod__(self, other): + return 2*self.result + + @call_highest_priority('__rfloordiv__') + def __floordiv__(self, other): + return self.result + + @call_highest_priority('__floordiv__') + def __rfloordiv__(self, other): + return 2*self.result + + +class Lower(Higher): + ''' + Integer of value -1 and _op_priority 5 + + Operations handled by this class return -1 and reverse operations return -2 + ''' + + _op_priority = 5.0 + result = -1 + + def __new__(cls): + obj = Expr.__new__(cls) + obj.p = -1 + return obj + + +x = Symbol('x') +h = Higher() +l = Lower() + + +def test_mul(): + assert h*l == h*x == 1 + assert l*h == x*h == 2 + assert x*l == l*x == -x + + +def test_add(): + assert h + l == h + x == 1 + assert l + h == x + h == 2 + assert x + l == l + x == x - 1 + + +def test_sub(): + assert h - l == h - x == 1 + assert l - h == x - h == 2 + assert x - l == -(l - x) == x + 1 + + +def test_pow(): + assert h**l == h**x == 1 + assert l**h == x**h == 2 + assert (x**l).args == (1/x).args and (x**l).is_Pow + assert (l**x).args == ((-1)**x).args and (l**x).is_Pow + + +def test_div(): + assert h/l == h/x == 1 + assert l/h == x/h == 2 + assert x/l == 1/(l/x) == -x + + +def test_mod(): + assert h%l == h%x == 1 + assert l%h == x%h == 2 + assert x%l == Mod(x, -1) + assert l%x == Mod(-1, x) + + +def test_floordiv(): + assert h//l == h//x == 1 + assert l//h == x//h == 2 + assert x//l == floor(-x) + assert l//x == floor(-1/x) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_random.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_random.py new file mode 100644 index 0000000000000000000000000000000000000000..01c677126285eb66349253368b94b3270fb97793 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_random.py @@ -0,0 +1,61 @@ +import random +from sympy.core.random import random as rand, seed, shuffle, _assumptions_shuffle +from sympy.core.symbol import Symbol, symbols +from sympy.functions.elementary.trigonometric import sin, acos +from sympy.abc import x + + +def test_random(): + random.seed(42) + a = random.random() + random.seed(42) + Symbol('z').is_finite + b = random.random() + assert a == b + + got = set() + for i in range(2): + random.seed(28) + m0, m1 = symbols('m_0 m_1', real=True) + _ = acos(-m0/m1) + got.add(random.uniform(0,1)) + assert len(got) == 1 + + random.seed(10) + y = 0 + for i in range(4): + y += sin(random.uniform(-10,10) * x) + random.seed(10) + z = 0 + for i in range(4): + z += sin(random.uniform(-10,10) * x) + assert y == z + + +def test_seed(): + assert rand() < 1 + seed(1) + a = rand() + b = rand() + seed(1) + c = rand() + d = rand() + assert a == c + if not c == d: + assert a != b + else: + assert a == b + + abc = 'abc' + first = list(abc) + second = list(abc) + third = list(abc) + + seed(123) + shuffle(first) + + seed(123) + shuffle(second) + _assumptions_shuffle(third) + + assert first == second == third diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_relational.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_relational.py new file mode 100644 index 0000000000000000000000000000000000000000..6ab6405c49db677b2c0cbdec7892d46cda841428 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_relational.py @@ -0,0 +1,1271 @@ +from sympy.core.logic import fuzzy_and +from sympy.core.sympify import _sympify +from sympy.multipledispatch import dispatch +from sympy.testing.pytest import XFAIL, raises +from sympy.assumptions.ask import Q +from sympy.core.add import Add +from sympy.core.basic import Basic +from sympy.core.expr import Expr, unchanged +from sympy.core.function import Function +from sympy.core.mul import Mul +from sympy.core.numbers import (Float, I, Rational, nan, oo, pi, zoo) +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import sign, Abs +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.exponential import (exp, exp_polar, log) +from sympy.functions.elementary.integers import (ceiling, floor) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.logic.boolalg import (And, Implies, Not, Or, Xor) +from sympy.sets import Reals +from sympy.simplify.simplify import simplify +from sympy.simplify.trigsimp import trigsimp +from sympy.core.relational import (Relational, Equality, Unequality, + GreaterThan, LessThan, StrictGreaterThan, + StrictLessThan, Rel, Eq, Lt, Le, + Gt, Ge, Ne, is_le, is_gt, is_ge, is_lt, is_eq, is_neq) +from sympy.sets.sets import Interval, FiniteSet + +from itertools import combinations + +x, y, z, t = symbols('x,y,z,t') + + +def rel_check(a, b): + from sympy.testing.pytest import raises + assert a.is_number and b.is_number + for do in range(len({type(a), type(b)})): + if S.NaN in (a, b): + v = [(a == b), (a != b)] + assert len(set(v)) == 1 and v[0] == False + assert not (a != b) and not (a == b) + assert raises(TypeError, lambda: a < b) + assert raises(TypeError, lambda: a <= b) + assert raises(TypeError, lambda: a > b) + assert raises(TypeError, lambda: a >= b) + else: + E = [(a == b), (a != b)] + assert len(set(E)) == 2 + v = [ + (a < b), (a <= b), (a > b), (a >= b)] + i = [ + [True, True, False, False], + [False, True, False, True], # <-- i == 1 + [False, False, True, True]].index(v) + if i == 1: + assert E[0] or (a.is_Float != b.is_Float) # ugh + else: + assert E[1] + a, b = b, a + return True + + +def test_rel_ne(): + assert Relational(x, y, '!=') == Ne(x, y) + + # issue 6116 + p = Symbol('p', positive=True) + assert Ne(p, 0) is S.true + + +def test_rel_subs(): + e = Relational(x, y, '==') + e = e.subs(x, z) + + assert isinstance(e, Equality) + assert e.lhs == z + assert e.rhs == y + + e = Relational(x, y, '>=') + e = e.subs(x, z) + + assert isinstance(e, GreaterThan) + assert e.lhs == z + assert e.rhs == y + + e = Relational(x, y, '<=') + e = e.subs(x, z) + + assert isinstance(e, LessThan) + assert e.lhs == z + assert e.rhs == y + + e = Relational(x, y, '>') + e = e.subs(x, z) + + assert isinstance(e, StrictGreaterThan) + assert e.lhs == z + assert e.rhs == y + + e = Relational(x, y, '<') + e = e.subs(x, z) + + assert isinstance(e, StrictLessThan) + assert e.lhs == z + assert e.rhs == y + + e = Eq(x, 0) + assert e.subs(x, 0) is S.true + assert e.subs(x, 1) is S.false + + +def test_wrappers(): + e = x + x**2 + + res = Relational(y, e, '==') + assert Rel(y, x + x**2, '==') == res + assert Eq(y, x + x**2) == res + + res = Relational(y, e, '<') + assert Lt(y, x + x**2) == res + + res = Relational(y, e, '<=') + assert Le(y, x + x**2) == res + + res = Relational(y, e, '>') + assert Gt(y, x + x**2) == res + + res = Relational(y, e, '>=') + assert Ge(y, x + x**2) == res + + res = Relational(y, e, '!=') + assert Ne(y, x + x**2) == res + + +def test_Eq_Ne(): + + assert Eq(x, x) # issue 5719 + + # issue 6116 + p = Symbol('p', positive=True) + assert Eq(p, 0) is S.false + + # issue 13348; 19048 + # SymPy is strict about 0 and 1 not being + # interpreted as Booleans + assert Eq(True, 1) is S.false + assert Eq(False, 0) is S.false + assert Eq(~x, 0) is S.false + assert Eq(~x, 1) is S.false + assert Ne(True, 1) is S.true + assert Ne(False, 0) is S.true + assert Ne(~x, 0) is S.true + assert Ne(~x, 1) is S.true + + assert Eq((), 1) is S.false + assert Ne((), 1) is S.true + + +def test_as_poly(): + from sympy.polys.polytools import Poly + # Only Eq should have an as_poly method: + assert Eq(x, 1).as_poly() == Poly(x - 1, x, domain='ZZ') + raises(AttributeError, lambda: Ne(x, 1).as_poly()) + raises(AttributeError, lambda: Ge(x, 1).as_poly()) + raises(AttributeError, lambda: Gt(x, 1).as_poly()) + raises(AttributeError, lambda: Le(x, 1).as_poly()) + raises(AttributeError, lambda: Lt(x, 1).as_poly()) + + +def test_rel_Infinity(): + # NOTE: All of these are actually handled by sympy.core.Number, and do + # not create Relational objects. + assert (oo > oo) is S.false + assert (oo > -oo) is S.true + assert (oo > 1) is S.true + assert (oo < oo) is S.false + assert (oo < -oo) is S.false + assert (oo < 1) is S.false + assert (oo >= oo) is S.true + assert (oo >= -oo) is S.true + assert (oo >= 1) is S.true + assert (oo <= oo) is S.true + assert (oo <= -oo) is S.false + assert (oo <= 1) is S.false + assert (-oo > oo) is S.false + assert (-oo > -oo) is S.false + assert (-oo > 1) is S.false + assert (-oo < oo) is S.true + assert (-oo < -oo) is S.false + assert (-oo < 1) is S.true + assert (-oo >= oo) is S.false + assert (-oo >= -oo) is S.true + assert (-oo >= 1) is S.false + assert (-oo <= oo) is S.true + assert (-oo <= -oo) is S.true + assert (-oo <= 1) is S.true + + +def test_infinite_symbol_inequalities(): + x = Symbol('x', extended_positive=True, infinite=True) + y = Symbol('y', extended_positive=True, infinite=True) + z = Symbol('z', extended_negative=True, infinite=True) + w = Symbol('w', extended_negative=True, infinite=True) + + inf_set = (x, y, oo) + ninf_set = (z, w, -oo) + + for inf1 in inf_set: + assert (inf1 < 1) is S.false + assert (inf1 > 1) is S.true + assert (inf1 <= 1) is S.false + assert (inf1 >= 1) is S.true + + for inf2 in inf_set: + assert (inf1 < inf2) is S.false + assert (inf1 > inf2) is S.false + assert (inf1 <= inf2) is S.true + assert (inf1 >= inf2) is S.true + + for ninf1 in ninf_set: + assert (inf1 < ninf1) is S.false + assert (inf1 > ninf1) is S.true + assert (inf1 <= ninf1) is S.false + assert (inf1 >= ninf1) is S.true + assert (ninf1 < inf1) is S.true + assert (ninf1 > inf1) is S.false + assert (ninf1 <= inf1) is S.true + assert (ninf1 >= inf1) is S.false + + for ninf1 in ninf_set: + assert (ninf1 < 1) is S.true + assert (ninf1 > 1) is S.false + assert (ninf1 <= 1) is S.true + assert (ninf1 >= 1) is S.false + + for ninf2 in ninf_set: + assert (ninf1 < ninf2) is S.false + assert (ninf1 > ninf2) is S.false + assert (ninf1 <= ninf2) is S.true + assert (ninf1 >= ninf2) is S.true + + +def test_bool(): + assert Eq(0, 0) is S.true + assert Eq(1, 0) is S.false + assert Ne(0, 0) is S.false + assert Ne(1, 0) is S.true + assert Lt(0, 1) is S.true + assert Lt(1, 0) is S.false + assert Le(0, 1) is S.true + assert Le(1, 0) is S.false + assert Le(0, 0) is S.true + assert Gt(1, 0) is S.true + assert Gt(0, 1) is S.false + assert Ge(1, 0) is S.true + assert Ge(0, 1) is S.false + assert Ge(1, 1) is S.true + assert Eq(I, 2) is S.false + assert Ne(I, 2) is S.true + raises(TypeError, lambda: Gt(I, 2)) + raises(TypeError, lambda: Ge(I, 2)) + raises(TypeError, lambda: Lt(I, 2)) + raises(TypeError, lambda: Le(I, 2)) + a = Float('.000000000000000000001', '') + b = Float('.0000000000000000000001', '') + assert Eq(pi + a, pi + b) is S.false + + +def test_rich_cmp(): + assert (x < y) == Lt(x, y) + assert (x <= y) == Le(x, y) + assert (x > y) == Gt(x, y) + assert (x >= y) == Ge(x, y) + + +def test_doit(): + from sympy.core.symbol import Symbol + p = Symbol('p', positive=True) + n = Symbol('n', negative=True) + np = Symbol('np', nonpositive=True) + nn = Symbol('nn', nonnegative=True) + + assert Gt(p, 0).doit() is S.true + assert Gt(p, 1).doit() == Gt(p, 1) + assert Ge(p, 0).doit() is S.true + assert Le(p, 0).doit() is S.false + assert Lt(n, 0).doit() is S.true + assert Le(np, 0).doit() is S.true + assert Gt(nn, 0).doit() == Gt(nn, 0) + assert Lt(nn, 0).doit() is S.false + + assert Eq(x, 0).doit() == Eq(x, 0) + + +def test_new_relational(): + x = Symbol('x') + + assert Eq(x, 0) == Relational(x, 0) # None ==> Equality + assert Eq(x, 0) == Relational(x, 0, '==') + assert Eq(x, 0) == Relational(x, 0, 'eq') + assert Eq(x, 0) == Equality(x, 0) + + assert Eq(x, 0) != Relational(x, 1) # None ==> Equality + assert Eq(x, 0) != Relational(x, 1, '==') + assert Eq(x, 0) != Relational(x, 1, 'eq') + assert Eq(x, 0) != Equality(x, 1) + + assert Eq(x, -1) == Relational(x, -1) # None ==> Equality + assert Eq(x, -1) == Relational(x, -1, '==') + assert Eq(x, -1) == Relational(x, -1, 'eq') + assert Eq(x, -1) == Equality(x, -1) + assert Eq(x, -1) != Relational(x, 1) # None ==> Equality + assert Eq(x, -1) != Relational(x, 1, '==') + assert Eq(x, -1) != Relational(x, 1, 'eq') + assert Eq(x, -1) != Equality(x, 1) + + assert Ne(x, 0) == Relational(x, 0, '!=') + assert Ne(x, 0) == Relational(x, 0, '<>') + assert Ne(x, 0) == Relational(x, 0, 'ne') + assert Ne(x, 0) == Unequality(x, 0) + assert Ne(x, 0) != Relational(x, 1, '!=') + assert Ne(x, 0) != Relational(x, 1, '<>') + assert Ne(x, 0) != Relational(x, 1, 'ne') + assert Ne(x, 0) != Unequality(x, 1) + + assert Ge(x, 0) == Relational(x, 0, '>=') + assert Ge(x, 0) == Relational(x, 0, 'ge') + assert Ge(x, 0) == GreaterThan(x, 0) + assert Ge(x, 1) != Relational(x, 0, '>=') + assert Ge(x, 1) != Relational(x, 0, 'ge') + assert Ge(x, 1) != GreaterThan(x, 0) + assert (x >= 1) == Relational(x, 1, '>=') + assert (x >= 1) == Relational(x, 1, 'ge') + assert (x >= 1) == GreaterThan(x, 1) + assert (x >= 0) != Relational(x, 1, '>=') + assert (x >= 0) != Relational(x, 1, 'ge') + assert (x >= 0) != GreaterThan(x, 1) + + assert Le(x, 0) == Relational(x, 0, '<=') + assert Le(x, 0) == Relational(x, 0, 'le') + assert Le(x, 0) == LessThan(x, 0) + assert Le(x, 1) != Relational(x, 0, '<=') + assert Le(x, 1) != Relational(x, 0, 'le') + assert Le(x, 1) != LessThan(x, 0) + assert (x <= 1) == Relational(x, 1, '<=') + assert (x <= 1) == Relational(x, 1, 'le') + assert (x <= 1) == LessThan(x, 1) + assert (x <= 0) != Relational(x, 1, '<=') + assert (x <= 0) != Relational(x, 1, 'le') + assert (x <= 0) != LessThan(x, 1) + + assert Gt(x, 0) == Relational(x, 0, '>') + assert Gt(x, 0) == Relational(x, 0, 'gt') + assert Gt(x, 0) == StrictGreaterThan(x, 0) + assert Gt(x, 1) != Relational(x, 0, '>') + assert Gt(x, 1) != Relational(x, 0, 'gt') + assert Gt(x, 1) != StrictGreaterThan(x, 0) + assert (x > 1) == Relational(x, 1, '>') + assert (x > 1) == Relational(x, 1, 'gt') + assert (x > 1) == StrictGreaterThan(x, 1) + assert (x > 0) != Relational(x, 1, '>') + assert (x > 0) != Relational(x, 1, 'gt') + assert (x > 0) != StrictGreaterThan(x, 1) + + assert Lt(x, 0) == Relational(x, 0, '<') + assert Lt(x, 0) == Relational(x, 0, 'lt') + assert Lt(x, 0) == StrictLessThan(x, 0) + assert Lt(x, 1) != Relational(x, 0, '<') + assert Lt(x, 1) != Relational(x, 0, 'lt') + assert Lt(x, 1) != StrictLessThan(x, 0) + assert (x < 1) == Relational(x, 1, '<') + assert (x < 1) == Relational(x, 1, 'lt') + assert (x < 1) == StrictLessThan(x, 1) + assert (x < 0) != Relational(x, 1, '<') + assert (x < 0) != Relational(x, 1, 'lt') + assert (x < 0) != StrictLessThan(x, 1) + + # finally, some fuzz testing + from sympy.core.random import randint + for i in range(100): + while 1: + strtype, length = (chr, 65535) if randint(0, 1) else (chr, 255) + relation_type = strtype(randint(0, length)) + if randint(0, 1): + relation_type += strtype(randint(0, length)) + if relation_type not in ('==', 'eq', '!=', '<>', 'ne', '>=', 'ge', + '<=', 'le', '>', 'gt', '<', 'lt', ':=', + '+=', '-=', '*=', '/=', '%='): + break + + raises(ValueError, lambda: Relational(x, 1, relation_type)) + assert all(Relational(x, 0, op).rel_op == '==' for op in ('eq', '==')) + assert all(Relational(x, 0, op).rel_op == '!=' + for op in ('ne', '<>', '!=')) + assert all(Relational(x, 0, op).rel_op == '>' for op in ('gt', '>')) + assert all(Relational(x, 0, op).rel_op == '<' for op in ('lt', '<')) + assert all(Relational(x, 0, op).rel_op == '>=' for op in ('ge', '>=')) + assert all(Relational(x, 0, op).rel_op == '<=' for op in ('le', '<=')) + + +def test_relational_arithmetic(): + for cls in [Eq, Ne, Le, Lt, Ge, Gt]: + rel = cls(x, y) + raises(TypeError, lambda: 0+rel) + raises(TypeError, lambda: 1*rel) + raises(TypeError, lambda: 1**rel) + raises(TypeError, lambda: rel**1) + raises(TypeError, lambda: Add(0, rel)) + raises(TypeError, lambda: Mul(1, rel)) + raises(TypeError, lambda: Pow(1, rel)) + raises(TypeError, lambda: Pow(rel, 1)) + + +def test_relational_bool_output(): + # https://github.com/sympy/sympy/issues/5931 + raises(TypeError, lambda: bool(x > 3)) + raises(TypeError, lambda: bool(x >= 3)) + raises(TypeError, lambda: bool(x < 3)) + raises(TypeError, lambda: bool(x <= 3)) + raises(TypeError, lambda: bool(Eq(x, 3))) + raises(TypeError, lambda: bool(Ne(x, 3))) + + +def test_relational_logic_symbols(): + # See issue 6204 + assert (x < y) & (z < t) == And(x < y, z < t) + assert (x < y) | (z < t) == Or(x < y, z < t) + assert ~(x < y) == Not(x < y) + assert (x < y) >> (z < t) == Implies(x < y, z < t) + assert (x < y) << (z < t) == Implies(z < t, x < y) + assert (x < y) ^ (z < t) == Xor(x < y, z < t) + + assert isinstance((x < y) & (z < t), And) + assert isinstance((x < y) | (z < t), Or) + assert isinstance(~(x < y), GreaterThan) + assert isinstance((x < y) >> (z < t), Implies) + assert isinstance((x < y) << (z < t), Implies) + assert isinstance((x < y) ^ (z < t), (Or, Xor)) + + +def test_univariate_relational_as_set(): + assert (x > 0).as_set() == Interval(0, oo, True, True) + assert (x >= 0).as_set() == Interval(0, oo) + assert (x < 0).as_set() == Interval(-oo, 0, True, True) + assert (x <= 0).as_set() == Interval(-oo, 0) + assert Eq(x, 0).as_set() == FiniteSet(0) + assert Ne(x, 0).as_set() == Interval(-oo, 0, True, True) + \ + Interval(0, oo, True, True) + + assert (x**2 >= 4).as_set() == Interval(-oo, -2) + Interval(2, oo) + + +@XFAIL +def test_multivariate_relational_as_set(): + assert (x*y >= 0).as_set() == Interval(0, oo)*Interval(0, oo) + \ + Interval(-oo, 0)*Interval(-oo, 0) + + +def test_Not(): + assert Not(Equality(x, y)) == Unequality(x, y) + assert Not(Unequality(x, y)) == Equality(x, y) + assert Not(StrictGreaterThan(x, y)) == LessThan(x, y) + assert Not(StrictLessThan(x, y)) == GreaterThan(x, y) + assert Not(GreaterThan(x, y)) == StrictLessThan(x, y) + assert Not(LessThan(x, y)) == StrictGreaterThan(x, y) + + +def test_evaluate(): + assert str(Eq(x, x, evaluate=False)) == 'Eq(x, x)' + assert Eq(x, x, evaluate=False).doit() == S.true + assert str(Ne(x, x, evaluate=False)) == 'Ne(x, x)' + assert Ne(x, x, evaluate=False).doit() == S.false + + assert str(Ge(x, x, evaluate=False)) == 'x >= x' + assert str(Le(x, x, evaluate=False)) == 'x <= x' + assert str(Gt(x, x, evaluate=False)) == 'x > x' + assert str(Lt(x, x, evaluate=False)) == 'x < x' + + +def assert_all_ineq_raise_TypeError(a, b): + raises(TypeError, lambda: a > b) + raises(TypeError, lambda: a >= b) + raises(TypeError, lambda: a < b) + raises(TypeError, lambda: a <= b) + raises(TypeError, lambda: b > a) + raises(TypeError, lambda: b >= a) + raises(TypeError, lambda: b < a) + raises(TypeError, lambda: b <= a) + + +def assert_all_ineq_give_class_Inequality(a, b): + """All inequality operations on `a` and `b` result in class Inequality.""" + from sympy.core.relational import _Inequality as Inequality + assert isinstance(a > b, Inequality) + assert isinstance(a >= b, Inequality) + assert isinstance(a < b, Inequality) + assert isinstance(a <= b, Inequality) + assert isinstance(b > a, Inequality) + assert isinstance(b >= a, Inequality) + assert isinstance(b < a, Inequality) + assert isinstance(b <= a, Inequality) + + +def test_imaginary_compare_raises_TypeError(): + # See issue #5724 + assert_all_ineq_raise_TypeError(I, x) + + +def test_complex_compare_not_real(): + # two cases which are not real + y = Symbol('y', imaginary=True) + z = Symbol('z', complex=True, extended_real=False) + for w in (y, z): + assert_all_ineq_raise_TypeError(2, w) + # some cases which should remain un-evaluated + t = Symbol('t') + x = Symbol('x', real=True) + z = Symbol('z', complex=True) + for w in (x, z, t): + assert_all_ineq_give_class_Inequality(2, w) + + +def test_imaginary_and_inf_compare_raises_TypeError(): + # See pull request #7835 + y = Symbol('y', imaginary=True) + assert_all_ineq_raise_TypeError(oo, y) + assert_all_ineq_raise_TypeError(-oo, y) + + +def test_complex_pure_imag_not_ordered(): + raises(TypeError, lambda: 2*I < 3*I) + + # more generally + x = Symbol('x', real=True, nonzero=True) + y = Symbol('y', imaginary=True) + z = Symbol('z', complex=True) + assert_all_ineq_raise_TypeError(I, y) + + t = I*x # an imaginary number, should raise errors + assert_all_ineq_raise_TypeError(2, t) + + t = -I*y # a real number, so no errors + assert_all_ineq_give_class_Inequality(2, t) + + t = I*z # unknown, should be unevaluated + assert_all_ineq_give_class_Inequality(2, t) + + +def test_x_minus_y_not_same_as_x_lt_y(): + """ + A consequence of pull request #7792 is that `x - y < 0` and `x < y` + are not synonymous. + """ + x = I + 2 + y = I + 3 + raises(TypeError, lambda: x < y) + assert x - y < 0 + + ineq = Lt(x, y, evaluate=False) + raises(TypeError, lambda: ineq.doit()) + assert ineq.lhs - ineq.rhs < 0 + + t = Symbol('t', imaginary=True) + x = 2 + t + y = 3 + t + ineq = Lt(x, y, evaluate=False) + raises(TypeError, lambda: ineq.doit()) + assert ineq.lhs - ineq.rhs < 0 + + # this one should give error either way + x = I + 2 + y = 2*I + 3 + raises(TypeError, lambda: x < y) + raises(TypeError, lambda: x - y < 0) + + +def test_nan_equality_exceptions(): + # See issue #7774 + import random + assert Equality(nan, nan) is S.false + assert Unequality(nan, nan) is S.true + + # See issue #7773 + A = (x, S.Zero, S.One/3, pi, oo, -oo) + assert Equality(nan, random.choice(A)) is S.false + assert Equality(random.choice(A), nan) is S.false + assert Unequality(nan, random.choice(A)) is S.true + assert Unequality(random.choice(A), nan) is S.true + + +def test_nan_inequality_raise_errors(): + # See discussion in pull request #7776. We test inequalities with + # a set including examples of various classes. + for q in (x, S.Zero, S(10), S.One/3, pi, S(1.3), oo, -oo, nan): + assert_all_ineq_raise_TypeError(q, nan) + + +def test_nan_complex_inequalities(): + # Comparisons of NaN with non-real raise errors, we're not too + # fussy whether its the NaN error or complex error. + for r in (I, zoo, Symbol('z', imaginary=True)): + assert_all_ineq_raise_TypeError(r, nan) + + +def test_complex_infinity_inequalities(): + raises(TypeError, lambda: zoo > 0) + raises(TypeError, lambda: zoo >= 0) + raises(TypeError, lambda: zoo < 0) + raises(TypeError, lambda: zoo <= 0) + + +def test_inequalities_symbol_name_same(): + """Using the operator and functional forms should give same results.""" + # We test all combinations from a set + # FIXME: could replace with random selection after test passes + A = (x, y, S.Zero, S.One/3, pi, oo, -oo) + for a in A: + for b in A: + assert Gt(a, b) == (a > b) + assert Lt(a, b) == (a < b) + assert Ge(a, b) == (a >= b) + assert Le(a, b) == (a <= b) + + for b in (y, S.Zero, S.One/3, pi, oo, -oo): + assert Gt(x, b, evaluate=False) == (x > b) + assert Lt(x, b, evaluate=False) == (x < b) + assert Ge(x, b, evaluate=False) == (x >= b) + assert Le(x, b, evaluate=False) == (x <= b) + + for b in (y, S.Zero, S.One/3, pi, oo, -oo): + assert Gt(b, x, evaluate=False) == (b > x) + assert Lt(b, x, evaluate=False) == (b < x) + assert Ge(b, x, evaluate=False) == (b >= x) + assert Le(b, x, evaluate=False) == (b <= x) + + +def test_inequalities_symbol_name_same_complex(): + """Using the operator and functional forms should give same results. + With complex non-real numbers, both should raise errors. + """ + # FIXME: could replace with random selection after test passes + for a in (x, S.Zero, S.One/3, pi, oo, Rational(1, 3)): + raises(TypeError, lambda: Gt(a, I)) + raises(TypeError, lambda: a > I) + raises(TypeError, lambda: Lt(a, I)) + raises(TypeError, lambda: a < I) + raises(TypeError, lambda: Ge(a, I)) + raises(TypeError, lambda: a >= I) + raises(TypeError, lambda: Le(a, I)) + raises(TypeError, lambda: a <= I) + + +def test_inequalities_cant_sympify_other(): + # see issue 7833 + from operator import gt, lt, ge, le + + bar = "foo" + + for a in (x, S.Zero, S.One/3, pi, I, zoo, oo, -oo, nan, Rational(1, 3)): + for op in (lt, gt, le, ge): + raises(TypeError, lambda: op(a, bar)) + + +def test_ineq_avoid_wild_symbol_flip(): + # see issue #7951, we try to avoid this internally, e.g., by using + # __lt__ instead of "<". + from sympy.core.symbol import Wild + p = symbols('p', cls=Wild) + # x > p might flip, but Gt should not: + assert Gt(x, p) == Gt(x, p, evaluate=False) + # Previously failed as 'p > x': + e = Lt(x, y).subs({y: p}) + assert e == Lt(x, p, evaluate=False) + # Previously failed as 'p <= x': + e = Ge(x, p).doit() + assert e == Ge(x, p, evaluate=False) + + +def test_issue_8245(): + a = S("6506833320952669167898688709329/5070602400912917605986812821504") + assert rel_check(a, a.n(10)) + assert rel_check(a, a.n(20)) + assert rel_check(a, a.n()) + # prec of 31 is enough to fully capture a as mpf + assert Float(a, 31) == Float(str(a.p), '')/Float(str(a.q), '') + for i in range(31): + r = Rational(Float(a, i)) + f = Float(r) + assert (f < a) == (Rational(f) < a) + # test sign handling + assert (-f < -a) == (Rational(-f) < -a) + # test equivalence handling + isa = Float(a.p,'')/Float(a.q,'') + assert isa <= a + assert not isa < a + assert isa >= a + assert not isa > a + assert isa > 0 + + a = sqrt(2) + r = Rational(str(a.n(30))) + assert rel_check(a, r) + + a = sqrt(2) + r = Rational(str(a.n(29))) + assert rel_check(a, r) + + assert Eq(log(cos(2)**2 + sin(2)**2), 0) is S.true + + +def test_issue_8449(): + p = Symbol('p', nonnegative=True) + assert Lt(-oo, p) + assert Ge(-oo, p) is S.false + assert Gt(oo, -p) + assert Le(oo, -p) is S.false + + +def test_simplify_relational(): + assert simplify(x*(y + 1) - x*y - x + 1 < x) == (x > 1) + assert simplify(x*(y + 1) - x*y - x - 1 < x) == (x > -1) + assert simplify(x < x*(y + 1) - x*y - x + 1) == (x < 1) + q, r = symbols("q r") + assert (((-q + r) - (q - r)) <= 0).simplify() == (q >= r) + root2 = sqrt(2) + equation = ((root2 * (-q + r) - root2 * (q - r)) <= 0).simplify() + assert equation == (q >= r) + r = S.One < x + # canonical operations are not the same as simplification, + # so if there is no simplification, canonicalization will + # be done unless the measure forbids it + assert simplify(r) == r.canonical + assert simplify(r, ratio=0) != r.canonical + # this is not a random test; in _eval_simplify + # this will simplify to S.false and that is the + # reason for the 'if r.is_Relational' in Relational's + # _eval_simplify routine + assert simplify(-(2**(pi*Rational(3, 2)) + 6**pi)**(1/pi) + + 2*(2**(pi/2) + 3**pi)**(1/pi) < 0) is S.false + # canonical at least + assert Eq(y, x).simplify() == Eq(x, y) + assert Eq(x - 1, 0).simplify() == Eq(x, 1) + assert Eq(x - 1, x).simplify() == S.false + assert Eq(2*x - 1, x).simplify() == Eq(x, 1) + assert Eq(2*x, 4).simplify() == Eq(x, 2) + z = cos(1)**2 + sin(1)**2 - 1 # z.is_zero is None + assert Eq(z*x, 0).simplify() == S.true + + assert Ne(y, x).simplify() == Ne(x, y) + assert Ne(x - 1, 0).simplify() == Ne(x, 1) + assert Ne(x - 1, x).simplify() == S.true + assert Ne(2*x - 1, x).simplify() == Ne(x, 1) + assert Ne(2*x, 4).simplify() == Ne(x, 2) + assert Ne(z*x, 0).simplify() == S.false + + # No real-valued assumptions + assert Ge(y, x).simplify() == Le(x, y) + assert Ge(x - 1, 0).simplify() == Ge(x, 1) + assert Ge(x - 1, x).simplify() == S.false + assert Ge(2*x - 1, x).simplify() == Ge(x, 1) + assert Ge(2*x, 4).simplify() == Ge(x, 2) + assert Ge(z*x, 0).simplify() == S.true + assert Ge(x, -2).simplify() == Ge(x, -2) + assert Ge(-x, -2).simplify() == Le(x, 2) + assert Ge(x, 2).simplify() == Ge(x, 2) + assert Ge(-x, 2).simplify() == Le(x, -2) + + assert Le(y, x).simplify() == Ge(x, y) + assert Le(x - 1, 0).simplify() == Le(x, 1) + assert Le(x - 1, x).simplify() == S.true + assert Le(2*x - 1, x).simplify() == Le(x, 1) + assert Le(2*x, 4).simplify() == Le(x, 2) + assert Le(z*x, 0).simplify() == S.true + assert Le(x, -2).simplify() == Le(x, -2) + assert Le(-x, -2).simplify() == Ge(x, 2) + assert Le(x, 2).simplify() == Le(x, 2) + assert Le(-x, 2).simplify() == Ge(x, -2) + + assert Gt(y, x).simplify() == Lt(x, y) + assert Gt(x - 1, 0).simplify() == Gt(x, 1) + assert Gt(x - 1, x).simplify() == S.false + assert Gt(2*x - 1, x).simplify() == Gt(x, 1) + assert Gt(2*x, 4).simplify() == Gt(x, 2) + assert Gt(z*x, 0).simplify() == S.false + assert Gt(x, -2).simplify() == Gt(x, -2) + assert Gt(-x, -2).simplify() == Lt(x, 2) + assert Gt(x, 2).simplify() == Gt(x, 2) + assert Gt(-x, 2).simplify() == Lt(x, -2) + + assert Lt(y, x).simplify() == Gt(x, y) + assert Lt(x - 1, 0).simplify() == Lt(x, 1) + assert Lt(x - 1, x).simplify() == S.true + assert Lt(2*x - 1, x).simplify() == Lt(x, 1) + assert Lt(2*x, 4).simplify() == Lt(x, 2) + assert Lt(z*x, 0).simplify() == S.false + assert Lt(x, -2).simplify() == Lt(x, -2) + assert Lt(-x, -2).simplify() == Gt(x, 2) + assert Lt(x, 2).simplify() == Lt(x, 2) + assert Lt(-x, 2).simplify() == Gt(x, -2) + + # Test particular branches of _eval_simplify + m = exp(1) - exp_polar(1) + assert simplify(m*x > 1) is S.false + # These two test the same branch + assert simplify(m*x + 2*m*y > 1) is S.false + assert simplify(m*x + y > 1 + y) is S.false + + +def test_equals(): + w, x, y, z = symbols('w:z') + f = Function('f') + assert Eq(x, 1).equals(Eq(x*(y + 1) - x*y - x + 1, x)) + assert Eq(x, y).equals(x < y, True) == False + assert Eq(x, f(1)).equals(Eq(x, f(2)), True) == f(1) - f(2) + assert Eq(f(1), y).equals(Eq(f(2), y), True) == f(1) - f(2) + assert Eq(x, f(1)).equals(Eq(f(2), x), True) == f(1) - f(2) + assert Eq(f(1), x).equals(Eq(x, f(2)), True) == f(1) - f(2) + assert Eq(w, x).equals(Eq(y, z), True) == False + assert Eq(f(1), f(2)).equals(Eq(f(3), f(4)), True) == f(1) - f(3) + assert (x < y).equals(y > x, True) == True + assert (x < y).equals(y >= x, True) == False + assert (x < y).equals(z < y, True) == False + assert (x < y).equals(x < z, True) == False + assert (x < f(1)).equals(x < f(2), True) == f(1) - f(2) + assert (f(1) < x).equals(f(2) < x, True) == f(1) - f(2) + + +def test_reversed(): + assert (x < y).reversed == (y > x) + assert (x <= y).reversed == (y >= x) + assert Eq(x, y, evaluate=False).reversed == Eq(y, x, evaluate=False) + assert Ne(x, y, evaluate=False).reversed == Ne(y, x, evaluate=False) + assert (x >= y).reversed == (y <= x) + assert (x > y).reversed == (y < x) + + +def test_canonical(): + c = [i.canonical for i in ( + x + y < z, + x + 2 > 3, + x < 2, + S(2) > x, + x**2 > -x/y, + Gt(3, 2, evaluate=False) + )] + assert [i.canonical for i in c] == c + assert [i.reversed.canonical for i in c] == c + assert not any(i.lhs.is_Number and not i.rhs.is_Number for i in c) + + c = [i.reversed.func(i.rhs, i.lhs, evaluate=False).canonical for i in c] + assert [i.canonical for i in c] == c + assert [i.reversed.canonical for i in c] == c + assert not any(i.lhs.is_Number and not i.rhs.is_Number for i in c) + assert Eq(y < x, x > y).canonical is S.true + + +@XFAIL +def test_issue_8444_nonworkingtests(): + x = symbols('x', real=True) + assert (x <= oo) == (x >= -oo) == True + + x = symbols('x') + assert x >= floor(x) + assert (x < floor(x)) == False + assert x <= ceiling(x) + assert (x > ceiling(x)) == False + + +def test_issue_8444_workingtests(): + x = symbols('x') + assert Gt(x, floor(x)) == Gt(x, floor(x), evaluate=False) + assert Ge(x, floor(x)) == Ge(x, floor(x), evaluate=False) + assert Lt(x, ceiling(x)) == Lt(x, ceiling(x), evaluate=False) + assert Le(x, ceiling(x)) == Le(x, ceiling(x), evaluate=False) + i = symbols('i', integer=True) + assert (i > floor(i)) == False + assert (i < ceiling(i)) == False + + +def test_issue_10304(): + d = cos(1)**2 + sin(1)**2 - 1 + assert d.is_comparable is False # if this fails, find a new d + e = 1 + d*I + assert simplify(Eq(e, 0)) is S.false + + +def test_issue_18412(): + d = (Rational(1, 6) + z / 4 / y) + assert Eq(x, pi * y**3 * d).replace(y**3, z) == Eq(x, pi * z * d) + + +def test_issue_10401(): + x = symbols('x') + fin = symbols('inf', finite=True) + inf = symbols('inf', infinite=True) + inf2 = symbols('inf2', infinite=True) + infx = symbols('infx', infinite=True, extended_real=True) + # Used in the commented tests below: + #infx2 = symbols('infx2', infinite=True, extended_real=True) + infnx = symbols('inf~x', infinite=True, extended_real=False) + infnx2 = symbols('inf~x2', infinite=True, extended_real=False) + infp = symbols('infp', infinite=True, extended_positive=True) + infp1 = symbols('infp1', infinite=True, extended_positive=True) + infn = symbols('infn', infinite=True, extended_negative=True) + zero = symbols('z', zero=True) + nonzero = symbols('nz', zero=False, finite=True) + + assert Eq(1/(1/x + 1), 1).func is Eq + assert Eq(1/(1/x + 1), 1).subs(x, S.ComplexInfinity) is S.true + assert Eq(1/(1/fin + 1), 1) is S.false + + T, F = S.true, S.false + assert Eq(fin, inf) is F + assert Eq(inf, inf2) not in (T, F) and inf != inf2 + assert Eq(1 + inf, 2 + inf2) not in (T, F) and inf != inf2 + assert Eq(infp, infp1) is T + assert Eq(infp, infn) is F + assert Eq(1 + I*oo, I*oo) is F + assert Eq(I*oo, 1 + I*oo) is F + assert Eq(1 + I*oo, 2 + I*oo) is F + assert Eq(1 + I*oo, 2 + I*infx) is F + assert Eq(1 + I*oo, 2 + infx) is F + # FIXME: The test below fails because (-infx).is_extended_positive is True + # (should be None) + #assert Eq(1 + I*infx, 1 + I*infx2) not in (T, F) and infx != infx2 + # + assert Eq(zoo, sqrt(2) + I*oo) is F + assert Eq(zoo, oo) is F + r = Symbol('r', real=True) + i = Symbol('i', imaginary=True) + assert Eq(i*I, r) not in (T, F) + assert Eq(infx, infnx) is F + assert Eq(infnx, infnx2) not in (T, F) and infnx != infnx2 + assert Eq(zoo, oo) is F + assert Eq(inf/inf2, 0) is F + assert Eq(inf/fin, 0) is F + assert Eq(fin/inf, 0) is T + assert Eq(zero/nonzero, 0) is T and ((zero/nonzero) != 0) + # The commented out test below is incorrect because: + assert zoo == -zoo + assert Eq(zoo, -zoo) is T + assert Eq(oo, -oo) is F + assert Eq(inf, -inf) not in (T, F) + + assert Eq(fin/(fin + 1), 1) is S.false + + o = symbols('o', odd=True) + assert Eq(o, 2*o) is S.false + + p = symbols('p', positive=True) + assert Eq(p/(p - 1), 1) is F + + +def test_issue_10633(): + assert Eq(True, False) == False + assert Eq(False, True) == False + assert Eq(True, True) == True + assert Eq(False, False) == True + + +def test_issue_10927(): + x = symbols('x') + assert str(Eq(x, oo)) == 'Eq(x, oo)' + assert str(Eq(x, -oo)) == 'Eq(x, -oo)' + + +def test_issues_13081_12583_12534(): + # 13081 + r = Rational('905502432259640373/288230376151711744') + assert (r < pi) is S.false + assert (r > pi) is S.true + # 12583 + v = sqrt(2) + u = sqrt(v) + 2/sqrt(10 - 8/sqrt(2 - v) + 4*v*(1/sqrt(2 - v) - 1)) + assert (u >= 0) is S.true + # 12534; Rational vs NumberSymbol + # here are some precisions for which Rational forms + # at a lower and higher precision bracket the value of pi + # e.g. for p = 20: + # Rational(pi.n(p + 1)).n(25) = 3.14159265358979323846 2834 + # pi.n(25) = 3.14159265358979323846 2643 + # Rational(pi.n(p )).n(25) = 3.14159265358979323846 1987 + assert [p for p in range(20, 50) if + (Rational(pi.n(p)) < pi) and + (pi < Rational(pi.n(p + 1)))] == [20, 24, 27, 33, 37, 43, 48] + # pick one such precision and affirm that the reversed operation + # gives the opposite result, i.e. if x < y is true then x > y + # must be false + for i in (20, 21): + v = pi.n(i) + assert rel_check(Rational(v), pi) + assert rel_check(v, pi) + assert rel_check(pi.n(20), pi.n(21)) + # Float vs Rational + # the rational form is less than the floating representation + # at the same precision + assert [i for i in range(15, 50) if Rational(pi.n(i)) > pi.n(i)] == [] + # this should be the same if we reverse the relational + assert [i for i in range(15, 50) if pi.n(i) < Rational(pi.n(i))] == [] + +def test_issue_18188(): + from sympy.sets.conditionset import ConditionSet + result1 = Eq(x*cos(x) - 3*sin(x), 0) + assert result1.as_set() == ConditionSet(x, Eq(x*cos(x) - 3*sin(x), 0), Reals) + + result2 = Eq(x**2 + sqrt(x*2) + sin(x), 0) + assert result2.as_set() == ConditionSet(x, Eq(sqrt(2)*sqrt(x) + x**2 + sin(x), 0), Reals) + +def test_binary_symbols(): + ans = {x} + for f in Eq, Ne: + for t in S.true, S.false: + eq = f(x, S.true) + assert eq.binary_symbols == ans + assert eq.reversed.binary_symbols == ans + assert f(x, 1).binary_symbols == set() + + +def test_rel_args(): + # can't have Boolean args; this is automatic for True/False + # with Python 3 and we confirm that SymPy does the same + # for true/false + for op in ['<', '<=', '>', '>=']: + for b in (S.true, x < 1, And(x, y)): + for v in (0.1, 1, 2**32, t, S.One): + raises(TypeError, lambda: Relational(b, v, op)) + + +def test_nothing_happens_to_Eq_condition_during_simplify(): + # issue 25701 + r = symbols('r', real=True) + assert Eq(2*sign(r + 3)/(5*Abs(r + 3)**Rational(3, 5)), 0 + ).simplify() == Eq(Piecewise( + (0, Eq(r, -3)), ((r + 3)/(5*Abs((r + 3)**Rational(8, 5)))*2, True)), 0) + + +def test_issue_15847(): + a = Ne(x*(x + y), x**2 + x*y) + assert simplify(a) == False + + +def test_negated_property(): + eq = Eq(x, y) + assert eq.negated == Ne(x, y) + + eq = Ne(x, y) + assert eq.negated == Eq(x, y) + + eq = Ge(x + y, y - x) + assert eq.negated == Lt(x + y, y - x) + + for f in (Eq, Ne, Ge, Gt, Le, Lt): + assert f(x, y).negated.negated == f(x, y) + + +def test_reversedsign_property(): + eq = Eq(x, y) + assert eq.reversedsign == Eq(-x, -y) + + eq = Ne(x, y) + assert eq.reversedsign == Ne(-x, -y) + + eq = Ge(x + y, y - x) + assert eq.reversedsign == Le(-x - y, x - y) + + for f in (Eq, Ne, Ge, Gt, Le, Lt): + assert f(x, y).reversedsign.reversedsign == f(x, y) + + for f in (Eq, Ne, Ge, Gt, Le, Lt): + assert f(-x, y).reversedsign.reversedsign == f(-x, y) + + for f in (Eq, Ne, Ge, Gt, Le, Lt): + assert f(x, -y).reversedsign.reversedsign == f(x, -y) + + for f in (Eq, Ne, Ge, Gt, Le, Lt): + assert f(-x, -y).reversedsign.reversedsign == f(-x, -y) + + +def test_reversed_reversedsign_property(): + for f in (Eq, Ne, Ge, Gt, Le, Lt): + assert f(x, y).reversed.reversedsign == f(x, y).reversedsign.reversed + + for f in (Eq, Ne, Ge, Gt, Le, Lt): + assert f(-x, y).reversed.reversedsign == f(-x, y).reversedsign.reversed + + for f in (Eq, Ne, Ge, Gt, Le, Lt): + assert f(x, -y).reversed.reversedsign == f(x, -y).reversedsign.reversed + + for f in (Eq, Ne, Ge, Gt, Le, Lt): + assert f(-x, -y).reversed.reversedsign == \ + f(-x, -y).reversedsign.reversed + + +def test_improved_canonical(): + def test_different_forms(listofforms): + for form1, form2 in combinations(listofforms, 2): + assert form1.canonical == form2.canonical + + def generate_forms(expr): + return [expr, expr.reversed, expr.reversedsign, + expr.reversed.reversedsign] + + test_different_forms(generate_forms(x > -y)) + test_different_forms(generate_forms(x >= -y)) + test_different_forms(generate_forms(Eq(x, -y))) + test_different_forms(generate_forms(Ne(x, -y))) + test_different_forms(generate_forms(pi < x)) + test_different_forms(generate_forms(pi - 5*y < -x + 2*y**2 - 7)) + + assert (pi >= x).canonical == (x <= pi) + + +def test_set_equality_canonical(): + a, b, c = symbols('a b c') + + A = Eq(FiniteSet(a, b, c), FiniteSet(1, 2, 3)) + B = Ne(FiniteSet(a, b, c), FiniteSet(4, 5, 6)) + + assert A.canonical == A.reversed + assert B.canonical == B.reversed + + +def test_trigsimp(): + # issue 16736 + s, c = sin(2*x), cos(2*x) + eq = Eq(s, c) + assert trigsimp(eq) == eq # no rearrangement of sides + # simplification of sides might result in + # an unevaluated Eq + changed = trigsimp(Eq(s + c, sqrt(2))) + assert isinstance(changed, Eq) + assert changed.subs(x, pi/8) is S.true + # or an evaluated one + assert trigsimp(Eq(cos(x)**2 + sin(x)**2, 1)) is S.true + + +def test_polynomial_relation_simplification(): + assert Ge(3*x*(x + 1) + 4, 3*x).simplify() in [Ge(x**2, -Rational(4,3)), Le(-x**2, Rational(4, 3))] + assert Le(-(3*x*(x + 1) + 4), -3*x).simplify() in [Ge(x**2, -Rational(4,3)), Le(-x**2, Rational(4, 3))] + assert ((x**2+3)*(x**2-1)+3*x >= 2*x**2).simplify() in [(x**4 + 3*x >= 3), (-x**4 - 3*x <= -3)] + + +def test_multivariate_linear_function_simplification(): + assert Ge(x + y, x - y).simplify() == Ge(y, 0) + assert Le(-x + y, -x - y).simplify() == Le(y, 0) + assert Eq(2*x + y, 2*x + y - 3).simplify() == False + assert (2*x + y > 2*x + y - 3).simplify() == True + assert (2*x + y < 2*x + y - 3).simplify() == False + assert (2*x + y < 2*x + y + 3).simplify() == True + a, b, c, d, e, f, g = symbols('a b c d e f g') + assert Lt(a + b + c + 2*d, 3*d - f + g). simplify() == Lt(a, -b - c + d - f + g) + + +def test_nonpolymonial_relations(): + assert Eq(cos(x), 0).simplify() == Eq(cos(x), 0) + +def test_18778(): + raises(TypeError, lambda: is_le(Basic(), Basic())) + raises(TypeError, lambda: is_gt(Basic(), Basic())) + raises(TypeError, lambda: is_ge(Basic(), Basic())) + raises(TypeError, lambda: is_lt(Basic(), Basic())) + +def test_EvalEq(): + """ + + This test exists to ensure backwards compatibility. + The method to use is _eval_is_eq + """ + from sympy.core.expr import Expr + + class PowTest(Expr): + def __new__(cls, base, exp): + return Basic.__new__(PowTest, _sympify(base), _sympify(exp)) + + def _eval_Eq(lhs, rhs): + if type(lhs) == PowTest and type(rhs) == PowTest: + return lhs.args[0] == rhs.args[0] and lhs.args[1] == rhs.args[1] + + assert is_eq(PowTest(3, 4), PowTest(3,4)) + assert is_eq(PowTest(3, 4), _sympify(4)) is None + assert is_neq(PowTest(3, 4), PowTest(3,7)) + + +def test_is_eq(): + # test assumptions + assert is_eq(x, y, Q.infinite(x) & Q.finite(y)) is False + assert is_eq(x, y, Q.infinite(x) & Q.infinite(y) & Q.extended_real(x) & ~Q.extended_real(y)) is False + assert is_eq(x, y, Q.infinite(x) & Q.infinite(y) & Q.extended_positive(x) & Q.extended_negative(y)) is False + + assert is_eq(x+I, y+I, Q.infinite(x) & Q.finite(y)) is False + assert is_eq(1+x*I, 1+y*I, Q.infinite(x) & Q.finite(y)) is False + + assert is_eq(x, S(0), assumptions=Q.zero(x)) + assert is_eq(x, S(0), assumptions=~Q.zero(x)) is False + assert is_eq(x, S(0), assumptions=Q.nonzero(x)) is False + assert is_neq(x, S(0), assumptions=Q.zero(x)) is False + assert is_neq(x, S(0), assumptions=~Q.zero(x)) + assert is_neq(x, S(0), assumptions=Q.nonzero(x)) + + # test registration + class PowTest(Expr): + def __new__(cls, base, exp): + return Basic.__new__(cls, _sympify(base), _sympify(exp)) + + @dispatch(PowTest, PowTest) + def _eval_is_eq(lhs, rhs): + if type(lhs) == PowTest and type(rhs) == PowTest: + return fuzzy_and([is_eq(lhs.args[0], rhs.args[0]), is_eq(lhs.args[1], rhs.args[1])]) + + assert is_eq(PowTest(3, 4), PowTest(3,4)) + assert is_eq(PowTest(3, 4), _sympify(4)) is None + assert is_neq(PowTest(3, 4), PowTest(3,7)) + + +def test_is_ge_le(): + # test assumptions + assert is_ge(x, S(0), Q.nonnegative(x)) is True + assert is_ge(x, S(0), Q.negative(x)) is False + + # test registration + class PowTest(Expr): + def __new__(cls, base, exp): + return Basic.__new__(cls, _sympify(base), _sympify(exp)) + + @dispatch(PowTest, PowTest) + def _eval_is_ge(lhs, rhs): + if type(lhs) == PowTest and type(rhs) == PowTest: + return fuzzy_and([is_ge(lhs.args[0], rhs.args[0]), is_ge(lhs.args[1], rhs.args[1])]) + + assert is_ge(PowTest(3, 9), PowTest(3,2)) + assert is_gt(PowTest(3, 9), PowTest(3,2)) + assert is_le(PowTest(3, 2), PowTest(3,9)) + assert is_lt(PowTest(3, 2), PowTest(3,9)) + + +def test_weak_strict(): + for func in (Eq, Ne): + eq = func(x, 1) + assert eq.strict == eq.weak == eq + eq = Gt(x, 1) + assert eq.weak == Ge(x, 1) + assert eq.strict == eq + eq = Lt(x, 1) + assert eq.weak == Le(x, 1) + assert eq.strict == eq + eq = Ge(x, 1) + assert eq.strict == Gt(x, 1) + assert eq.weak == eq + eq = Le(x, 1) + assert eq.strict == Lt(x, 1) + assert eq.weak == eq + + +def test_issue_23731(): + i = symbols('i', integer=True) + assert unchanged(Eq, i, 1.0) + assert unchanged(Eq, i/2, 0.5) + ni = symbols('ni', integer=False) + assert Eq(ni, 1) == False + assert unchanged(Eq, ni, .1) + assert Eq(ni, 1.0) == False + nr = symbols('nr', rational=False) + assert Eq(nr, .1) == False + + +def test_rewrite_Add(): + from sympy.testing.pytest import warns_deprecated_sympy + with warns_deprecated_sympy(): + assert Eq(x, y).rewrite(Add) == x - y diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_rules.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_rules.py new file mode 100644 index 0000000000000000000000000000000000000000..31cb88b52db21f39653033b4567526e992be99f0 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_rules.py @@ -0,0 +1,14 @@ +from sympy.core.rules import Transform + +from sympy.testing.pytest import raises + + +def test_Transform(): + add1 = Transform(lambda x: x + 1, lambda x: x % 2 == 1) + assert add1[1] == 2 + assert (1 in add1) is True + assert add1.get(1) == 2 + + raises(KeyError, lambda: add1[2]) + assert (2 in add1) is False + assert add1.get(2) is None diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_singleton.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_singleton.py new file mode 100644 index 0000000000000000000000000000000000000000..893713f27d74b884391ad800d186eafe5337ab1c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_singleton.py @@ -0,0 +1,76 @@ +from sympy.core.basic import Basic +from sympy.core.numbers import Rational +from sympy.core.singleton import S, Singleton + +def test_Singleton(): + + class MySingleton(Basic, metaclass=Singleton): + pass + + MySingleton() # force instantiation + assert MySingleton() is not Basic() + assert MySingleton() is MySingleton() + assert S.MySingleton is MySingleton() + + class MySingleton_sub(MySingleton): + pass + + MySingleton_sub() + assert MySingleton_sub() is not MySingleton() + assert MySingleton_sub() is MySingleton_sub() + +def test_singleton_redefinition(): + class TestSingleton(Basic, metaclass=Singleton): + pass + + assert TestSingleton() is S.TestSingleton + + class TestSingleton(Basic, metaclass=Singleton): + pass + + assert TestSingleton() is S.TestSingleton + +def test_names_in_namespace(): + # Every singleton name should be accessible from the 'from sympy import *' + # namespace in addition to the S object. However, it does not need to be + # by the same name (e.g., oo instead of S.Infinity). + + # As a general rule, things should only be added to the singleton registry + # if they are used often enough that code can benefit either from the + # performance benefit of being able to use 'is' (this only matters in very + # tight loops), or from the memory savings of having exactly one instance + # (this matters for the numbers singletons, but very little else). The + # singleton registry is already a bit overpopulated, and things cannot be + # removed from it without breaking backwards compatibility. So if you got + # here by adding something new to the singletons, ask yourself if it + # really needs to be singletonized. Note that SymPy classes compare to one + # another just fine, so Class() == Class() will give True even if each + # Class() returns a new instance. Having unique instances is only + # necessary for the above noted performance gains. It should not be needed + # for any behavioral purposes. + + # If you determine that something really should be a singleton, it must be + # accessible to sympify() without using 'S' (hence this test). Also, its + # str printer should print a form that does not use S. This is because + # sympify() disables attribute lookups by default for safety purposes. + d = {} + exec('from sympy import *', d) + + for name in dir(S) + list(S._classes_to_install): + if name.startswith('_'): + continue + if name == 'register': + continue + if isinstance(getattr(S, name), Rational): + continue + if getattr(S, name).__module__.startswith('sympy.physics'): + continue + if name in ['MySingleton', 'MySingleton_sub', 'TestSingleton']: + # From the tests above + continue + if name == 'NegativeInfinity': + # Accessible by -oo + continue + + # Use is here to ensure it is the exact same object + assert any(getattr(S, name) is i for i in d.values()), name diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_sorting.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_sorting.py new file mode 100644 index 0000000000000000000000000000000000000000..a18dbfb624552cf2fa11bb7f3c3a9e865caeb0c4 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_sorting.py @@ -0,0 +1,28 @@ +from sympy.core.sorting import default_sort_key, ordered +from sympy.testing.pytest import raises + +from sympy.abc import x + + +def test_default_sort_key(): + func = lambda x: x + assert sorted([func, x, func], key=default_sort_key) == [func, func, x] + + class C: + def __repr__(self): + return 'x.y' + func = C() + assert sorted([x, func], key=default_sort_key) == [func, x] + + +def test_ordered(): + # Issue 7210 - this had been failing with python2/3 problems + assert (list(ordered([{1:3, 2:4, 9:10}, {1:3}])) == \ + [{1: 3}, {1: 3, 2: 4, 9: 10}]) + # warnings should not be raised for identical items + l = [1, 1] + assert list(ordered(l, warn=True)) == l + l = [[1], [2], [1]] + assert list(ordered(l, warn=True)) == [[1], [1], [2]] + raises(ValueError, lambda: list(ordered(['a', 'ab'], keys=[lambda x: x[0]], + default=False, warn=True))) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_subs.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_subs.py new file mode 100644 index 0000000000000000000000000000000000000000..0803a4b1b5e93b8a35f43516ccef3ab9a16f08ec --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_subs.py @@ -0,0 +1,895 @@ +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.core.add import Add +from sympy.core.basic import Basic +from sympy.core.containers import (Dict, Tuple) +from sympy.core.function import (Derivative, Function, Lambda, Subs) +from sympy.core.mul import Mul +from sympy.core.numbers import (Float, I, Integer, Rational, oo, pi, zoo) +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, Wild, symbols) +from sympy.core.sympify import SympifyError +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (atan2, cos, cot, sin, tan) +from sympy.matrices.dense import (Matrix, zeros) +from sympy.matrices.expressions.special import ZeroMatrix +from sympy.polys.polytools import factor +from sympy.polys.rootoftools import RootOf +from sympy.simplify.cse_main import cse +from sympy.simplify.simplify import nsimplify +from sympy.core.basic import _aresame +from sympy.testing.pytest import XFAIL, raises +from sympy.abc import a, x, y, z, t + + +def test_subs(): + n3 = Rational(3) + e = x + e = e.subs(x, n3) + assert e == Rational(3) + + e = 2*x + assert e == 2*x + e = e.subs(x, n3) + assert e == Rational(6) + + +def test_subs_Matrix(): + z = zeros(2) + z1 = ZeroMatrix(2, 2) + assert (x*y).subs({x:z, y:0}) in [z, z1] + assert (x*y).subs({y:z, x:0}) == 0 + assert (x*y).subs({y:z, x:0}, simultaneous=True) in [z, z1] + assert (x + y).subs({x: z, y: z}, simultaneous=True) in [z, z1] + assert (x + y).subs({x: z, y: z}) in [z, z1] + + # Issue #15528 + assert Mul(Matrix([[3]]), x).subs(x, 2.0) == Matrix([[6.0]]) + # Does not raise a TypeError, see comment on the MatAdd postprocessor + assert Add(Matrix([[3]]), x).subs(x, 2.0) == Add(Matrix([[3]]), 2.0) + + +def test_subs_AccumBounds(): + e = x + e = e.subs(x, AccumBounds(1, 3)) + assert e == AccumBounds(1, 3) + + e = 2*x + e = e.subs(x, AccumBounds(1, 3)) + assert e == AccumBounds(2, 6) + + e = x + x**2 + e = e.subs(x, AccumBounds(-1, 1)) + assert e == AccumBounds(-1, 2) + + +def test_trigonometric(): + n3 = Rational(3) + e = (sin(x)**2).diff(x) + assert e == 2*sin(x)*cos(x) + e = e.subs(x, n3) + assert e == 2*cos(n3)*sin(n3) + + e = (sin(x)**2).diff(x) + assert e == 2*sin(x)*cos(x) + e = e.subs(sin(x), cos(x)) + assert e == 2*cos(x)**2 + + assert exp(pi).subs(exp, sin) == 0 + assert cos(exp(pi)).subs(exp, sin) == 1 + + i = Symbol('i', integer=True) + zoo = S.ComplexInfinity + assert tan(x).subs(x, pi/2) is zoo + assert cot(x).subs(x, pi) is zoo + assert cot(i*x).subs(x, pi) is zoo + assert tan(i*x).subs(x, pi/2) == tan(i*pi/2) + assert tan(i*x).subs(x, pi/2).subs(i, 1) is zoo + o = Symbol('o', odd=True) + assert tan(o*x).subs(x, pi/2) == tan(o*pi/2) + + +def test_powers(): + assert sqrt(1 - sqrt(x)).subs(x, 4) == I + assert (sqrt(1 - x**2)**3).subs(x, 2) == - 3*I*sqrt(3) + assert (x**Rational(1, 3)).subs(x, 27) == 3 + assert (x**Rational(1, 3)).subs(x, -27) == 3*(-1)**Rational(1, 3) + assert ((-x)**Rational(1, 3)).subs(x, 27) == 3*(-1)**Rational(1, 3) + n = Symbol('n', negative=True) + assert (x**n).subs(x, 0) is S.ComplexInfinity + assert exp(-1).subs(S.Exp1, 0) is S.ComplexInfinity + assert (x**(4.0*y)).subs(x**(2.0*y), n) == n**2.0 + assert (2**(x + 2)).subs(2, 3) == 3**(x + 3) + + +def test_logexppow(): # no eval() + x = Symbol('x', real=True) + w = Symbol('w') + e = (3**(1 + x) + 2**(1 + x))/(3**x + 2**x) + assert e.subs(2**x, w) != e + assert e.subs(exp(x*log(Rational(2))), w) != e + + +def test_bug(): + x1 = Symbol('x1') + x2 = Symbol('x2') + y = x1*x2 + assert y.subs(x1, Float(3.0)) == Float(3.0)*x2 + + +def test_subbug1(): + # see that they don't fail + (x**x).subs(x, 1) + (x**x).subs(x, 1.0) + + +def test_subbug2(): + # Ensure this does not cause infinite recursion + assert Float(7.7).epsilon_eq(abs(x).subs(x, -7.7)) + + +def test_dict_set(): + a, b, c = map(Wild, 'abc') + + f = 3*cos(4*x) + r = f.match(a*cos(b*x)) + assert r == {a: 3, b: 4} + e = a/b*sin(b*x) + assert e.subs(r) == r[a]/r[b]*sin(r[b]*x) + assert e.subs(r) == 3*sin(4*x) / 4 + s = set(r.items()) + assert e.subs(s) == r[a]/r[b]*sin(r[b]*x) + assert e.subs(s) == 3*sin(4*x) / 4 + + assert e.subs(r) == r[a]/r[b]*sin(r[b]*x) + assert e.subs(r) == 3*sin(4*x) / 4 + assert x.subs(Dict((x, 1))) == 1 + + +def test_dict_ambigous(): # see issue 3566 + f = x*exp(x) + g = z*exp(z) + + df = {x: y, exp(x): y} + dg = {z: y, exp(z): y} + + assert f.subs(df) == y**2 + assert g.subs(dg) == y**2 + + # and this is how order can affect the result + assert f.subs(x, y).subs(exp(x), y) == y*exp(y) + assert f.subs(exp(x), y).subs(x, y) == y**2 + + # length of args and count_ops are the same so + # default_sort_key resolves ordering...if one + # doesn't want this result then an unordered + # sequence should not be used. + e = 1 + x*y + assert e.subs({x: y, y: 2}) == 5 + # here, there are no obviously clashing keys or values + # but the results depend on the order + assert exp(x/2 + y).subs({exp(y + 1): 2, x: 2}) == exp(y + 1) + + +def test_deriv_sub_bug3(): + f = Function('f') + pat = Derivative(f(x), x, x) + assert pat.subs(y, y**2) == Derivative(f(x), x, x) + assert pat.subs(y, y**2) != Derivative(f(x), x) + + +def test_equality_subs1(): + f = Function('f') + eq = Eq(f(x)**2, x) + res = Eq(Integer(16), x) + assert eq.subs(f(x), 4) == res + + +def test_equality_subs2(): + f = Function('f') + eq = Eq(f(x)**2, 16) + assert bool(eq.subs(f(x), 3)) is False + assert bool(eq.subs(f(x), 4)) is True + + +def test_issue_3742(): + e = sqrt(x)*exp(y) + assert e.subs(sqrt(x), 1) == exp(y) + + +def test_subs_dict1(): + assert (1 + x*y).subs(x, pi) == 1 + pi*y + assert (1 + x*y).subs({x: pi, y: 2}) == 1 + 2*pi + + c2, c3, q1p, q2p, c1, s1, s2, s3 = symbols('c2 c3 q1p q2p c1 s1 s2 s3') + test = (c2**2*q2p*c3 + c1**2*s2**2*q2p*c3 + s1**2*s2**2*q2p*c3 + - c1**2*q1p*c2*s3 - s1**2*q1p*c2*s3) + assert (test.subs({c1**2: 1 - s1**2, c2**2: 1 - s2**2, c3**3: 1 - s3**2}) + == c3*q2p*(1 - s2**2) + c3*q2p*s2**2*(1 - s1**2) + - c2*q1p*s3*(1 - s1**2) + c3*q2p*s1**2*s2**2 - c2*q1p*s3*s1**2) + + +def test_mul(): + x, y, z, a, b, c = symbols('x y z a b c') + A, B, C = symbols('A B C', commutative=0) + assert (x*y*z).subs(z*x, y) == y**2 + assert (z*x).subs(1/x, z) == 1 + assert (x*y/z).subs(1/z, a) == a*x*y + assert (x*y/z).subs(x/z, a) == a*y + assert (x*y/z).subs(y/z, a) == a*x + assert (x*y/z).subs(x/z, 1/a) == y/a + assert (x*y/z).subs(x, 1/a) == y/(z*a) + assert (2*x*y).subs(5*x*y, z) != z*Rational(2, 5) + assert (x*y*A).subs(x*y, a) == a*A + assert (x**2*y**(x*Rational(3, 2))).subs(x*y**(x/2), 2) == 4*y**(x/2) + assert (x*exp(x*2)).subs(x*exp(x), 2) == 2*exp(x) + assert ((x**(2*y))**3).subs(x**y, 2) == 64 + assert (x*A*B).subs(x*A, y) == y*B + assert (x*y*(1 + x)*(1 + x*y)).subs(x*y, 2) == 6*(1 + x) + assert ((1 + A*B)*A*B).subs(A*B, x*A*B) + assert (x*a/z).subs(x/z, A) == a*A + assert (x**3*A).subs(x**2*A, a) == a*x + assert (x**2*A*B).subs(x**2*B, a) == a*A + assert (x**2*A*B).subs(x**2*A, a) == a*B + assert (b*A**3/(a**3*c**3)).subs(a**4*c**3*A**3/b**4, z) == \ + b*A**3/(a**3*c**3) + assert (6*x).subs(2*x, y) == 3*y + assert (y*exp(x*Rational(3, 2))).subs(y*exp(x), 2) == 2*exp(x/2) + assert (y*exp(x*Rational(3, 2))).subs(y*exp(x), 2) == 2*exp(x/2) + assert (A**2*B*A**2*B*A**2).subs(A*B*A, C) == A*C**2*A + assert (x*A**3).subs(x*A, y) == y*A**2 + assert (x**2*A**3).subs(x*A, y) == y**2*A + assert (x*A**3).subs(x*A, B) == B*A**2 + assert (x*A*B*A*exp(x*A*B)).subs(x*A, B) == B**2*A*exp(B*B) + assert (x**2*A*B*A*exp(x*A*B)).subs(x*A, B) == B**3*exp(B**2) + assert (x**3*A*exp(x*A*B)*A*exp(x*A*B)).subs(x*A, B) == \ + x*B*exp(B**2)*B*exp(B**2) + assert (x*A*B*C*A*B).subs(x*A*B, C) == C**2*A*B + assert (-I*a*b).subs(a*b, 2) == -2*I + + # issue 6361 + assert (-8*I*a).subs(-2*a, 1) == 4*I + assert (-I*a).subs(-a, 1) == I + + # issue 6441 + assert (4*x**2).subs(2*x, y) == y**2 + assert (2*4*x**2).subs(2*x, y) == 2*y**2 + assert (-x**3/9).subs(-x/3, z) == -z**2*x + assert (-x**3/9).subs(x/3, z) == -z**2*x + assert (-2*x**3/9).subs(x/3, z) == -2*x*z**2 + assert (-2*x**3/9).subs(-x/3, z) == -2*x*z**2 + assert (-2*x**3/9).subs(-2*x, z) == z*x**2/9 + assert (-2*x**3/9).subs(2*x, z) == -z*x**2/9 + assert (2*(3*x/5/7)**2).subs(3*x/5, z) == 2*(Rational(1, 7))**2*z**2 + assert (4*x).subs(-2*x, z) == 4*x # try keep subs literal + + +def test_subs_simple(): + a = symbols('a', commutative=True) + x = symbols('x', commutative=False) + + assert (2*a).subs(1, 3) == 2*a + assert (2*a).subs(2, 3) == 3*a + assert (2*a).subs(a, 3) == 6 + assert sin(2).subs(1, 3) == sin(2) + assert sin(2).subs(2, 3) == sin(3) + assert sin(a).subs(a, 3) == sin(3) + + assert (2*x).subs(1, 3) == 2*x + assert (2*x).subs(2, 3) == 3*x + assert (2*x).subs(x, 3) == 6 + assert sin(x).subs(x, 3) == sin(3) + + +def test_subs_constants(): + a, b = symbols('a b', commutative=True) + x, y = symbols('x y', commutative=False) + + assert (a*b).subs(2*a, 1) == a*b + assert (1.5*a*b).subs(a, 1) == 1.5*b + assert (2*a*b).subs(2*a, 1) == b + assert (2*a*b).subs(4*a, 1) == 2*a*b + + assert (x*y).subs(2*x, 1) == x*y + assert (1.5*x*y).subs(x, 1) == 1.5*y + assert (2*x*y).subs(2*x, 1) == y + assert (2*x*y).subs(4*x, 1) == 2*x*y + + +def test_subs_commutative(): + a, b, c, d, K = symbols('a b c d K', commutative=True) + + assert (a*b).subs(a*b, K) == K + assert (a*b*a*b).subs(a*b, K) == K**2 + assert (a*a*b*b).subs(a*b, K) == K**2 + assert (a*b*c*d).subs(a*b*c, K) == d*K + assert (a*b**c).subs(a, K) == K*b**c + assert (a*b**c).subs(b, K) == a*K**c + assert (a*b**c).subs(c, K) == a*b**K + assert (a*b*c*b*a).subs(a*b, K) == c*K**2 + assert (a**3*b**2*a).subs(a*b, K) == a**2*K**2 + + +def test_subs_noncommutative(): + w, x, y, z, L = symbols('w x y z L', commutative=False) + alpha = symbols('alpha', commutative=True) + someint = symbols('someint', commutative=True, integer=True) + + assert (x*y).subs(x*y, L) == L + assert (w*y*x).subs(x*y, L) == w*y*x + assert (w*x*y*z).subs(x*y, L) == w*L*z + assert (x*y*x*y).subs(x*y, L) == L**2 + assert (x*x*y).subs(x*y, L) == x*L + assert (x*x*y*y).subs(x*y, L) == x*L*y + assert (w*x*y).subs(x*y*z, L) == w*x*y + assert (x*y**z).subs(x, L) == L*y**z + assert (x*y**z).subs(y, L) == x*L**z + assert (x*y**z).subs(z, L) == x*y**L + assert (w*x*y*z*x*y).subs(x*y*z, L) == w*L*x*y + assert (w*x*y*y*w*x*x*y*x*y*y*x*y).subs(x*y, L) == w*L*y*w*x*L**2*y*L + + # Check fractional power substitutions. It should not do + # substitutions that choose a value for noncommutative log, + # or inverses that don't already appear in the expressions. + assert (x*x*x).subs(x*x, L) == L*x + assert (x*x*x*y*x*x*x*x).subs(x*x, L) == L*x*y*L**2 + for p in range(1, 5): + for k in range(10): + assert (y * x**k).subs(x**p, L) == y * L**(k//p) * x**(k % p) + assert (x**Rational(3, 2)).subs(x**S.Half, L) == x**Rational(3, 2) + assert (x**S.Half).subs(x**S.Half, L) == L + assert (x**Rational(-1, 2)).subs(x**S.Half, L) == x**Rational(-1, 2) + assert (x**Rational(-1, 2)).subs(x**Rational(-1, 2), L) == L + + assert (x**(2*someint)).subs(x**someint, L) == L**2 + assert (x**(2*someint + 3)).subs(x**someint, L) == L**2*x**3 + assert (x**(3*someint + 3)).subs(x**someint, L) == L**3*x**3 + assert (x**(3*someint)).subs(x**(2*someint), L) == L * x**someint + assert (x**(4*someint)).subs(x**(2*someint), L) == L**2 + assert (x**(4*someint + 1)).subs(x**(2*someint), L) == L**2 * x + assert (x**(4*someint)).subs(x**(3*someint), L) == L * x**someint + assert (x**(4*someint + 1)).subs(x**(3*someint), L) == L * x**(someint + 1) + + assert (x**(2*alpha)).subs(x**alpha, L) == x**(2*alpha) + assert (x**(2*alpha + 2)).subs(x**2, L) == x**(2*alpha + 2) + assert ((2*z)**alpha).subs(z**alpha, y) == (2*z)**alpha + assert (x**(2*someint*alpha)).subs(x**someint, L) == x**(2*someint*alpha) + assert (x**(2*someint + alpha)).subs(x**someint, L) == x**(2*someint + alpha) + + # This could in principle be substituted, but is not currently + # because it requires recognizing that someint**2 is divisible by + # someint. + assert (x**(someint**2 + 3)).subs(x**someint, L) == x**(someint**2 + 3) + + # alpha**z := exp(log(alpha) z) is usually well-defined + assert (4**z).subs(2**z, y) == y**2 + + # Negative powers + assert (x**(-1)).subs(x**3, L) == x**(-1) + assert (x**(-2)).subs(x**3, L) == x**(-2) + assert (x**(-3)).subs(x**3, L) == L**(-1) + assert (x**(-4)).subs(x**3, L) == L**(-1) * x**(-1) + assert (x**(-5)).subs(x**3, L) == L**(-1) * x**(-2) + + assert (x**(-1)).subs(x**(-3), L) == x**(-1) + assert (x**(-2)).subs(x**(-3), L) == x**(-2) + assert (x**(-3)).subs(x**(-3), L) == L + assert (x**(-4)).subs(x**(-3), L) == L * x**(-1) + assert (x**(-5)).subs(x**(-3), L) == L * x**(-2) + + assert (x**1).subs(x**(-3), L) == x + assert (x**2).subs(x**(-3), L) == x**2 + assert (x**3).subs(x**(-3), L) == L**(-1) + assert (x**4).subs(x**(-3), L) == L**(-1) * x + assert (x**5).subs(x**(-3), L) == L**(-1) * x**2 + + +def test_subs_basic_funcs(): + a, b, c, d, K = symbols('a b c d K', commutative=True) + w, x, y, z, L = symbols('w x y z L', commutative=False) + + assert (x + y).subs(x + y, L) == L + assert (x - y).subs(x - y, L) == L + assert (x/y).subs(x, L) == L/y + assert (x**y).subs(x, L) == L**y + assert (x**y).subs(y, L) == x**L + assert ((a - c)/b).subs(b, K) == (a - c)/K + assert (exp(x*y - z)).subs(x*y, L) == exp(L - z) + assert (a*exp(x*y - w*z) + b*exp(x*y + w*z)).subs(z, 0) == \ + a*exp(x*y) + b*exp(x*y) + assert ((a - b)/(c*d - a*b)).subs(c*d - a*b, K) == (a - b)/K + assert (w*exp(a*b - c)*x*y/4).subs(x*y, L) == w*exp(a*b - c)*L/4 + + +def test_subs_wild(): + R, S, T, U = symbols('R S T U', cls=Wild) + + assert (R*S).subs(R*S, T) == T + assert (S*R).subs(R*S, T) == T + assert (R + S).subs(R + S, T) == T + assert (R**S).subs(R, T) == T**S + assert (R**S).subs(S, T) == R**T + assert (R*S**T).subs(R, U) == U*S**T + assert (R*S**T).subs(S, U) == R*U**T + assert (R*S**T).subs(T, U) == R*S**U + + +def test_subs_mixed(): + a, b, c, d, K = symbols('a b c d K', commutative=True) + w, x, y, z, L = symbols('w x y z L', commutative=False) + R, S, T, U = symbols('R S T U', cls=Wild) + + assert (a*x*y).subs(x*y, L) == a*L + assert (a*b*x*y*x).subs(x*y, L) == a*b*L*x + assert (R*x*y*exp(x*y)).subs(x*y, L) == R*L*exp(L) + assert (a*x*y*y*x - x*y*z*exp(a*b)).subs(x*y, L) == a*L*y*x - L*z*exp(a*b) + e = c*y*x*y*x**(R*S - a*b) - T*(a*R*b*S) + assert e.subs(x*y, L).subs(a*b, K).subs(R*S, U) == \ + c*y*L*x**(U - K) - T*(U*K) + + +def test_division(): + a, b, c = symbols('a b c', commutative=True) + x, y, z = symbols('x y z', commutative=True) + + assert (1/a).subs(a, c) == 1/c + assert (1/a**2).subs(a, c) == 1/c**2 + assert (1/a**2).subs(a, -2) == Rational(1, 4) + assert (-(1/a**2)).subs(a, -2) == Rational(-1, 4) + + assert (1/x).subs(x, z) == 1/z + assert (1/x**2).subs(x, z) == 1/z**2 + assert (1/x**2).subs(x, -2) == Rational(1, 4) + assert (-(1/x**2)).subs(x, -2) == Rational(-1, 4) + + #issue 5360 + assert (1/x).subs(x, 0) == 1/S.Zero + + +def test_add(): + a, b, c, d, x, y, t = symbols('a b c d x y t') + + assert (a**2 - b - c).subs(a**2 - b, d) in [d - c, a**2 - b - c] + assert (a**2 - c).subs(a**2 - c, d) == d + assert (a**2 - b - c).subs(a**2 - c, d) in [d - b, a**2 - b - c] + assert (a**2 - x - c).subs(a**2 - c, d) in [d - x, a**2 - x - c] + assert (a**2 - b - sqrt(a)).subs(a**2 - sqrt(a), c) == c - b + assert (a + b + exp(a + b)).subs(a + b, c) == c + exp(c) + assert (c + b + exp(c + b)).subs(c + b, a) == a + exp(a) + assert (a + b + c + d).subs(b + c, x) == a + d + x + assert (a + b + c + d).subs(-b - c, x) == a + d - x + assert ((x + 1)*y).subs(x + 1, t) == t*y + assert ((-x - 1)*y).subs(x + 1, t) == -t*y + assert ((x - 1)*y).subs(x + 1, t) == y*(t - 2) + assert ((-x + 1)*y).subs(x + 1, t) == y*(-t + 2) + + # this should work every time: + e = a**2 - b - c + assert e.subs(Add(*e.args[:2]), d) == d + e.args[2] + assert e.subs(a**2 - c, d) == d - b + + # the fallback should recognize when a change has + # been made; while .1 == Rational(1, 10) they are not the same + # and the change should be made + assert (0.1 + a).subs(0.1, Rational(1, 10)) == Rational(1, 10) + a + + e = (-x*(-y + 1) - y*(y - 1)) + ans = (-x*(x) - y*(-x)).expand() + assert e.subs(-y + 1, x) == ans + + #Test issue 18747 + assert (exp(x) + cos(x)).subs(x, oo) == oo + assert Add(*[AccumBounds(-1, 1), oo]) == oo + assert Add(*[oo, AccumBounds(-1, 1)]) == oo + + +def test_subs_issue_4009(): + assert (I*Symbol('a')).subs(1, 2) == I*Symbol('a') + + +def test_functions_subs(): + f, g = symbols('f g', cls=Function) + l = Lambda((x, y), sin(x) + y) + assert (g(y, x) + cos(x)).subs(g, l) == sin(y) + x + cos(x) + assert (f(x)**2).subs(f, sin) == sin(x)**2 + assert (f(x, y)).subs(f, log) == log(x, y) + assert (f(x, y)).subs(f, sin) == f(x, y) + assert (sin(x) + atan2(x, y)).subs([[atan2, f], [sin, g]]) == \ + f(x, y) + g(x) + assert (g(f(x + y, x))).subs([[f, l], [g, exp]]) == exp(x + sin(x + y)) + + +def test_derivative_subs(): + f = Function('f') + g = Function('g') + assert Derivative(f(x), x).subs(f(x), y) != 0 + # need xreplace to put the function back, see #13803 + assert Derivative(f(x), x).subs(f(x), y).xreplace({y: f(x)}) == \ + Derivative(f(x), x) + # issues 5085, 5037 + assert cse(Derivative(f(x), x) + f(x))[1][0].has(Derivative) + assert cse(Derivative(f(x, y), x) + + Derivative(f(x, y), y))[1][0].has(Derivative) + eq = Derivative(g(x), g(x)) + assert eq.subs(g, f) == Derivative(f(x), f(x)) + assert eq.subs(g(x), f(x)) == Derivative(f(x), f(x)) + assert eq.subs(g, cos) == Subs(Derivative(y, y), y, cos(x)) + + +def test_derivative_subs2(): + f_func, g_func = symbols('f g', cls=Function) + f, g = f_func(x, y, z), g_func(x, y, z) + assert Derivative(f, x, y).subs(Derivative(f, x, y), g) == g + assert Derivative(f, y, x).subs(Derivative(f, x, y), g) == g + assert Derivative(f, x, y).subs(Derivative(f, x), g) == Derivative(g, y) + assert Derivative(f, x, y).subs(Derivative(f, y), g) == Derivative(g, x) + assert (Derivative(f, x, y, z).subs( + Derivative(f, x, z), g) == Derivative(g, y)) + assert (Derivative(f, x, y, z).subs( + Derivative(f, z, y), g) == Derivative(g, x)) + assert (Derivative(f, x, y, z).subs( + Derivative(f, z, y, x), g) == g) + + # Issue 9135 + assert (Derivative(f, x, x, y).subs( + Derivative(f, y, y), g) == Derivative(f, x, x, y)) + assert (Derivative(f, x, y, y, z).subs( + Derivative(f, x, y, y, y), g) == Derivative(f, x, y, y, z)) + + assert Derivative(f, x, y).subs(Derivative(f_func(x), x, y), g) == Derivative(f, x, y) + + +def test_derivative_subs3(): + dex = Derivative(exp(x), x) + assert Derivative(dex, x).subs(dex, exp(x)) == dex + assert dex.subs(exp(x), dex) == Derivative(exp(x), x, x) + + +def test_issue_5284(): + A, B = symbols('A B', commutative=False) + assert (x*A).subs(x**2*A, B) == x*A + assert (A**2).subs(A**3, B) == A**2 + assert (A**6).subs(A**3, B) == B**2 + + +def test_subs_iter(): + assert x.subs(reversed([[x, y]])) == y + it = iter([[x, y]]) + assert x.subs(it) == y + assert x.subs(Tuple((x, y))) == y + + +def test_subs_dict(): + a, b, c, d, e = symbols('a b c d e') + + assert (2*x + y + z).subs({"x": 1, "y": 2}) == 4 + z + + l = [(sin(x), 2), (x, 1)] + assert (sin(x)).subs(l) == \ + (sin(x)).subs(dict(l)) == 2 + assert sin(x).subs(reversed(l)) == sin(1) + + expr = sin(2*x) + sqrt(sin(2*x))*cos(2*x)*sin(exp(x)*x) + reps = {sin(2*x): c, + sqrt(sin(2*x)): a, + cos(2*x): b, + exp(x): e, + x: d,} + assert expr.subs(reps) == c + a*b*sin(d*e) + + l = [(x, 3), (y, x**2)] + assert (x + y).subs(l) == 3 + x**2 + assert (x + y).subs(reversed(l)) == 12 + + # If changes are made to convert lists into dictionaries and do + # a dictionary-lookup replacement, these tests will help to catch + # some logical errors that might occur + l = [(y, z + 2), (1 + z, 5), (z, 2)] + assert (y - 1 + 3*x).subs(l) == 5 + 3*x + l = [(y, z + 2), (z, 3)] + assert (y - 2).subs(l) == 3 + + +def test_no_arith_subs_on_floats(): + assert (x + 3).subs(x + 3, a) == a + assert (x + 3).subs(x + 2, a) == a + 1 + + assert (x + y + 3).subs(x + 3, a) == a + y + assert (x + y + 3).subs(x + 2, a) == a + y + 1 + + assert (x + 3.0).subs(x + 3.0, a) == a + assert (x + 3.0).subs(x + 2.0, a) == x + 3.0 + + assert (x + y + 3.0).subs(x + 3.0, a) == a + y + assert (x + y + 3.0).subs(x + 2.0, a) == x + y + 3.0 + + +def test_issue_5651(): + a, b, c, K = symbols('a b c K', commutative=True) + assert (a/(b*c)).subs(b*c, K) == a/K + assert (a/(b**2*c**3)).subs(b*c, K) == a/(c*K**2) + assert (1/(x*y)).subs(x*y, 2) == S.Half + assert ((1 + x*y)/(x*y)).subs(x*y, 1) == 2 + assert (x*y*z).subs(x*y, 2) == 2*z + assert ((1 + x*y)/(x*y)/z).subs(x*y, 1) == 2/z + + +def test_issue_6075(): + assert Tuple(1, True).subs(1, 2) == Tuple(2, True) + + +def test_issue_6079(): + # since x + 2.0 == x + 2 we can't do a simple equality test + assert _aresame((x + 2.0).subs(2, 3), x + 2.0) + assert _aresame((x + 2.0).subs(2.0, 3), x + 3) + assert not _aresame(x + 2, x + 2.0) + assert not _aresame(Basic(cos(x), S(1)), Basic(cos(x), S(1.))) + assert _aresame(cos, cos) + assert not _aresame(1, S.One) + assert not _aresame(x, symbols('x', positive=True)) + + +def test_issue_4680(): + N = Symbol('N') + assert N.subs({"N": 3}) == 3 + + +def test_issue_6158(): + assert (x - 1).subs(1, y) == x - y + assert (x - 1).subs(-1, y) == x + y + assert (x - oo).subs(oo, y) == x - y + assert (x - oo).subs(-oo, y) == x + y + + +def test_Function_subs(): + f, g, h, i = symbols('f g h i', cls=Function) + p = Piecewise((g(f(x, y)), x < -1), (g(x), x <= 1)) + assert p.subs(g, h) == Piecewise((h(f(x, y)), x < -1), (h(x), x <= 1)) + assert (f(y) + g(x)).subs({f: h, g: i}) == i(x) + h(y) + + +def test_simultaneous_subs(): + reps = {x: 0, y: 0} + assert (x/y).subs(reps) != (y/x).subs(reps) + assert (x/y).subs(reps, simultaneous=True) == \ + (y/x).subs(reps, simultaneous=True) + reps = reps.items() + assert (x/y).subs(reps) != (y/x).subs(reps) + assert (x/y).subs(reps, simultaneous=True) == \ + (y/x).subs(reps, simultaneous=True) + assert Derivative(x, y, z).subs(reps, simultaneous=True) == \ + Subs(Derivative(0, y, z), y, 0) + + +def test_issue_6419_6421(): + assert (1/(1 + x/y)).subs(x/y, x) == 1/(1 + x) + assert (-2*I).subs(2*I, x) == -x + assert (-I*x).subs(I*x, x) == -x + assert (-3*I*y**4).subs(3*I*y**2, x) == -x*y**2 + + +def test_issue_6559(): + assert (-12*x + y).subs(-x, 1) == 12 + y + # though this involves cse it generated a failure in Mul._eval_subs + x0, x1 = symbols('x0 x1') + e = -log(-12*sqrt(2) + 17)/24 - log(-2*sqrt(2) + 3)/12 + sqrt(2)/3 + # XXX modify cse so x1 is eliminated and x0 = -sqrt(2)? + assert cse(e) == ( + [(x0, sqrt(2))], [x0/3 - log(-12*x0 + 17)/24 - log(-2*x0 + 3)/12]) + + +def test_issue_5261(): + x = symbols('x', real=True) + e = I*x + assert exp(e).subs(exp(x), y) == y**I + assert (2**e).subs(2**x, y) == y**I + eq = (-2)**e + assert eq.subs((-2)**x, y) == eq + + +def test_issue_6923(): + assert (-2*x*sqrt(2)).subs(2*x, y) == -sqrt(2)*y + + +def test_2arg_hack(): + N = Symbol('N', commutative=False) + ans = Mul(2, y + 1, evaluate=False) + assert (2*x*(y + 1)).subs(x, 1, hack2=True) == ans + assert (2*(y + 1 + N)).subs(N, 0, hack2=True) == ans + + +@XFAIL +def test_mul2(): + """When this fails, remove things labelled "2-arg hack" + 1) remove special handling in the fallback of subs that + was added in the same commit as this test + 2) remove the special handling in Mul.flatten + """ + assert (2*(x + 1)).is_Mul + + +def test_noncommutative_subs(): + x,y = symbols('x,y', commutative=False) + assert (x*y*x).subs([(x, x*y), (y, x)], simultaneous=True) == (x*y*x**2*y) + + +def test_issue_2877(): + f = Float(2.0) + assert (x + f).subs({f: 2}) == x + 2 + + def r(a, b, c): + return factor(a*x**2 + b*x + c) + e = r(5.0/6, 10, 5) + assert nsimplify(e) == 5*x**2/6 + 10*x + 5 + + +def test_issue_5910(): + t = Symbol('t') + assert (1/(1 - t)).subs(t, 1) is zoo + n = t + d = t - 1 + assert (n/d).subs(t, 1) is zoo + assert (-n/-d).subs(t, 1) is zoo + + +def test_issue_5217(): + s = Symbol('s') + z = (1 - 2*x*x) + w = (1 + 2*x*x) + q = 2*x*x*2*y*y + sub = {2*x*x: s} + assert w.subs(sub) == 1 + s + assert z.subs(sub) == 1 - s + assert q == 4*x**2*y**2 + assert q.subs(sub) == 2*y**2*s + + +def test_issue_10829(): + assert (4**x).subs(2**x, y) == y**2 + assert (9**x).subs(3**x, y) == y**2 + + +def test_pow_eval_subs_no_cache(): + # Tests pull request 9376 is working + from sympy.core.cache import clear_cache + + s = 1/sqrt(x**2) + # This bug only appeared when the cache was turned off. + # We need to approximate running this test without the cache. + # This creates approximately the same situation. + clear_cache() + + # This used to fail with a wrong result. + # It incorrectly returned 1/sqrt(x**2) before this pull request. + result = s.subs(sqrt(x**2), y) + assert result == 1/y + + +def test_RootOf_issue_10092(): + x = Symbol('x', real=True) + eq = x**3 - 17*x**2 + 81*x - 118 + r = RootOf(eq, 0) + assert (x < r).subs(x, r) is S.false + + +def test_issue_8886(): + from sympy.physics.mechanics import ReferenceFrame as R + # if something can't be sympified we assume that it + # doesn't play well with SymPy and disallow the + # substitution + v = R('A').x + raises(SympifyError, lambda: x.subs(x, v)) + raises(SympifyError, lambda: v.subs(v, x)) + assert v.__eq__(x) is False + + +def test_issue_12657(): + # treat -oo like the atom that it is + reps = [(-oo, 1), (oo, 2)] + assert (x < -oo).subs(reps) == (x < 1) + assert (x < -oo).subs(list(reversed(reps))) == (x < 1) + reps = [(-oo, 2), (oo, 1)] + assert (x < oo).subs(reps) == (x < 1) + assert (x < oo).subs(list(reversed(reps))) == (x < 1) + + +def test_recurse_Application_args(): + F = Lambda((x, y), exp(2*x + 3*y)) + f = Function('f') + A = f(x, f(x, x)) + C = F(x, F(x, x)) + assert A.subs(f, F) == A.replace(f, F) == C + + +def test_Subs_subs(): + assert Subs(x*y, x, x).subs(x, y) == Subs(x*y, x, y) + assert Subs(x*y, x, x + 1).subs(x, y) == \ + Subs(x*y, x, y + 1) + assert Subs(x*y, y, x + 1).subs(x, y) == \ + Subs(y**2, y, y + 1) + a = Subs(x*y*z, (y, x, z), (x + 1, x + z, x)) + b = Subs(x*y*z, (y, x, z), (x + 1, y + z, y)) + assert a.subs(x, y) == b and \ + a.doit().subs(x, y) == a.subs(x, y).doit() + f = Function('f') + g = Function('g') + assert Subs(2*f(x, y) + g(x), f(x, y), 1).subs(y, 2) == Subs( + 2*f(x, y) + g(x), (f(x, y), y), (1, 2)) + + +def test_issue_13333(): + eq = 1/x + assert eq.subs({"x": '1/2'}) == 2 + assert eq.subs({"x": '(1/2)'}) == 2 + + +def test_issue_15234(): + x, y = symbols('x y', real=True) + p = 6*x**5 + x**4 - 4*x**3 + 4*x**2 - 2*x + 3 + p_subbed = 6*x**5 - 4*x**3 - 2*x + y**4 + 4*y**2 + 3 + assert p.subs([(x**i, y**i) for i in [2, 4]]) == p_subbed + x, y = symbols('x y', complex=True) + p = 6*x**5 + x**4 - 4*x**3 + 4*x**2 - 2*x + 3 + p_subbed = 6*x**5 - 4*x**3 - 2*x + y**4 + 4*y**2 + 3 + assert p.subs([(x**i, y**i) for i in [2, 4]]) == p_subbed + + +def test_issue_6976(): + x, y = symbols('x y') + assert (sqrt(x)**3 + sqrt(x) + x + x**2).subs(sqrt(x), y) == \ + y**4 + y**3 + y**2 + y + assert (x**4 + x**3 + x**2 + x + sqrt(x)).subs(x**2, y) == \ + sqrt(x) + x**3 + x + y**2 + y + assert x.subs(x**3, y) == x + assert x.subs(x**Rational(1, 3), y) == y**3 + + # More substitutions are possible with nonnegative symbols + x, y = symbols('x y', nonnegative=True) + assert (x**4 + x**3 + x**2 + x + sqrt(x)).subs(x**2, y) == \ + y**Rational(1, 4) + y**Rational(3, 2) + sqrt(y) + y**2 + y + assert x.subs(x**3, y) == y**Rational(1, 3) + + +def test_issue_11746(): + assert (1/x).subs(x**2, 1) == 1/x + assert (1/(x**3)).subs(x**2, 1) == x**(-3) + assert (1/(x**4)).subs(x**2, 1) == 1 + assert (1/(x**3)).subs(x**4, 1) == x**(-3) + assert (1/(y**5)).subs(x**5, 1) == y**(-5) + + +def test_issue_17823(): + from sympy.physics.mechanics import dynamicsymbols + q1, q2 = dynamicsymbols('q1, q2') + expr = q1.diff().diff()**2*q1 + q1.diff()*q2.diff() + reps={q1: a, q1.diff(): a*x*y, q1.diff().diff(): z} + assert expr.subs(reps) == a*x*y*Derivative(q2, t) + a*z**2 + + +def test_issue_19326(): + x, y = [i(t) for i in map(Function, 'xy')] + assert (x*y).subs({x: 1 + x, y: x}) == (1 + x)*x + + +def test_issue_19558(): + e = (7*x*cos(x) - 12*log(x)**3)*(-log(x)**4 + 2*sin(x) + 1)**2/ \ + (2*(x*cos(x) - 2*log(x)**3)*(3*log(x)**4 - 7*sin(x) + 3)**2) + + assert e.subs(x, oo) == AccumBounds(-oo, oo) + assert (sin(x) + cos(x)).subs(x, oo) == AccumBounds(-2, 2) + + +def test_issue_22033(): + xr = Symbol('xr', real=True) + e = (1/xr) + assert e.subs(xr**2, y) == e + + +def test_guard_against_indeterminate_evaluation(): + eq = x**y + assert eq.subs([(x, 1), (y, oo)]) == 1 # because 1**y == 1 + assert eq.subs([(y, oo), (x, 1)]) is S.NaN + assert eq.subs({x: 1, y: oo}) is S.NaN + assert eq.subs([(x, 1), (y, oo)], simultaneous=True) is S.NaN diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_symbol.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_symbol.py new file mode 100644 index 0000000000000000000000000000000000000000..acf27700825c4822456207afe95108480505ce2c --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_symbol.py @@ -0,0 +1,421 @@ +import threading + +from sympy.core.function import Function, UndefinedFunction +from sympy.core.numbers import (I, Rational, pi) +from sympy.core.relational import (GreaterThan, LessThan, StrictGreaterThan, StrictLessThan) +from sympy.core.symbol import (Dummy, Symbol, Wild, symbols) +from sympy.core.sympify import sympify # can't import as S yet +from sympy.core.symbol import uniquely_named_symbol, _symbol, Str + +from sympy.testing.pytest import raises, skip_under_pyodide +from sympy.core.symbol import disambiguate + + +def test_Str(): + a1 = Str('a') + a2 = Str('a') + b = Str('b') + assert a1 == a2 != b + raises(TypeError, lambda: Str()) + + +def test_Symbol(): + a = Symbol("a") + x1 = Symbol("x") + x2 = Symbol("x") + xdummy1 = Dummy("x") + xdummy2 = Dummy("x") + + assert a != x1 + assert a != x2 + assert x1 == x2 + assert x1 != xdummy1 + assert xdummy1 != xdummy2 + + assert Symbol("x") == Symbol("x") + assert Dummy("x") != Dummy("x") + d = symbols('d', cls=Dummy) + assert isinstance(d, Dummy) + c, d = symbols('c,d', cls=Dummy) + assert isinstance(c, Dummy) + assert isinstance(d, Dummy) + raises(TypeError, lambda: Symbol()) + + +def test_Dummy(): + assert Dummy() != Dummy() + + +def test_Dummy_force_dummy_index(): + raises(AssertionError, lambda: Dummy(dummy_index=1)) + assert Dummy('d', dummy_index=2) == Dummy('d', dummy_index=2) + assert Dummy('d1', dummy_index=2) != Dummy('d2', dummy_index=2) + d1 = Dummy('d', dummy_index=3) + d2 = Dummy('d') + # might fail if d1 were created with dummy_index >= 10**6 + assert d1 != d2 + d3 = Dummy('d', dummy_index=3) + assert d1 == d3 + assert Dummy()._count == Dummy('d', dummy_index=3)._count + + +def test_lt_gt(): + S = sympify + x, y = Symbol('x'), Symbol('y') + + assert (x >= y) == GreaterThan(x, y) + assert (x >= 0) == GreaterThan(x, 0) + assert (x <= y) == LessThan(x, y) + assert (x <= 0) == LessThan(x, 0) + + assert (0 <= x) == GreaterThan(x, 0) + assert (0 >= x) == LessThan(x, 0) + assert (S(0) >= x) == GreaterThan(0, x) + assert (S(0) <= x) == LessThan(0, x) + + assert (x > y) == StrictGreaterThan(x, y) + assert (x > 0) == StrictGreaterThan(x, 0) + assert (x < y) == StrictLessThan(x, y) + assert (x < 0) == StrictLessThan(x, 0) + + assert (0 < x) == StrictGreaterThan(x, 0) + assert (0 > x) == StrictLessThan(x, 0) + assert (S(0) > x) == StrictGreaterThan(0, x) + assert (S(0) < x) == StrictLessThan(0, x) + + e = x**2 + 4*x + 1 + assert (e >= 0) == GreaterThan(e, 0) + assert (0 <= e) == GreaterThan(e, 0) + assert (e > 0) == StrictGreaterThan(e, 0) + assert (0 < e) == StrictGreaterThan(e, 0) + + assert (e <= 0) == LessThan(e, 0) + assert (0 >= e) == LessThan(e, 0) + assert (e < 0) == StrictLessThan(e, 0) + assert (0 > e) == StrictLessThan(e, 0) + + assert (S(0) >= e) == GreaterThan(0, e) + assert (S(0) <= e) == LessThan(0, e) + assert (S(0) < e) == StrictLessThan(0, e) + assert (S(0) > e) == StrictGreaterThan(0, e) + + +def test_no_len(): + # there should be no len for numbers + x = Symbol('x') + raises(TypeError, lambda: len(x)) + + +def test_ineq_unequal(): + S = sympify + x, y, z = symbols('x,y,z') + + e = ( + S(-1) >= x, S(-1) >= y, S(-1) >= z, + S(-1) > x, S(-1) > y, S(-1) > z, + S(-1) <= x, S(-1) <= y, S(-1) <= z, + S(-1) < x, S(-1) < y, S(-1) < z, + S(0) >= x, S(0) >= y, S(0) >= z, + S(0) > x, S(0) > y, S(0) > z, + S(0) <= x, S(0) <= y, S(0) <= z, + S(0) < x, S(0) < y, S(0) < z, + S('3/7') >= x, S('3/7') >= y, S('3/7') >= z, + S('3/7') > x, S('3/7') > y, S('3/7') > z, + S('3/7') <= x, S('3/7') <= y, S('3/7') <= z, + S('3/7') < x, S('3/7') < y, S('3/7') < z, + S(1.5) >= x, S(1.5) >= y, S(1.5) >= z, + S(1.5) > x, S(1.5) > y, S(1.5) > z, + S(1.5) <= x, S(1.5) <= y, S(1.5) <= z, + S(1.5) < x, S(1.5) < y, S(1.5) < z, + S(2) >= x, S(2) >= y, S(2) >= z, + S(2) > x, S(2) > y, S(2) > z, + S(2) <= x, S(2) <= y, S(2) <= z, + S(2) < x, S(2) < y, S(2) < z, + x >= -1, y >= -1, z >= -1, + x > -1, y > -1, z > -1, + x <= -1, y <= -1, z <= -1, + x < -1, y < -1, z < -1, + x >= 0, y >= 0, z >= 0, + x > 0, y > 0, z > 0, + x <= 0, y <= 0, z <= 0, + x < 0, y < 0, z < 0, + x >= 1.5, y >= 1.5, z >= 1.5, + x > 1.5, y > 1.5, z > 1.5, + x <= 1.5, y <= 1.5, z <= 1.5, + x < 1.5, y < 1.5, z < 1.5, + x >= 2, y >= 2, z >= 2, + x > 2, y > 2, z > 2, + x <= 2, y <= 2, z <= 2, + x < 2, y < 2, z < 2, + + x >= y, x >= z, y >= x, y >= z, z >= x, z >= y, + x > y, x > z, y > x, y > z, z > x, z > y, + x <= y, x <= z, y <= x, y <= z, z <= x, z <= y, + x < y, x < z, y < x, y < z, z < x, z < y, + + x - pi >= y + z, y - pi >= x + z, z - pi >= x + y, + x - pi > y + z, y - pi > x + z, z - pi > x + y, + x - pi <= y + z, y - pi <= x + z, z - pi <= x + y, + x - pi < y + z, y - pi < x + z, z - pi < x + y, + True, False + ) + + left_e = e[:-1] + for i, e1 in enumerate( left_e ): + for e2 in e[i + 1:]: + assert e1 != e2 + + +def test_Wild_properties(): + S = sympify + # these tests only include Atoms + x = Symbol("x") + y = Symbol("y") + p = Symbol("p", positive=True) + k = Symbol("k", integer=True) + n = Symbol("n", integer=True, positive=True) + + given_patterns = [ x, y, p, k, -k, n, -n, S(-3), S(3), + pi, Rational(3, 2), I ] + + integerp = lambda k: k.is_integer + positivep = lambda k: k.is_positive + symbolp = lambda k: k.is_Symbol + realp = lambda k: k.is_extended_real + + S = Wild("S", properties=[symbolp]) + R = Wild("R", properties=[realp]) + Y = Wild("Y", exclude=[x, p, k, n]) + P = Wild("P", properties=[positivep]) + K = Wild("K", properties=[integerp]) + N = Wild("N", properties=[positivep, integerp]) + + given_wildcards = [ S, R, Y, P, K, N ] + + goodmatch = { + S: (x, y, p, k, n), + R: (p, k, -k, n, -n, -3, 3, pi, Rational(3, 2)), + Y: (y, -3, 3, pi, Rational(3, 2), I ), + P: (p, n, 3, pi, Rational(3, 2)), + K: (k, -k, n, -n, -3, 3), + N: (n, 3)} + + for A in given_wildcards: + for pat in given_patterns: + d = pat.match(A) + if pat in goodmatch[A]: + assert d[A] in goodmatch[A] + else: + assert d is None + + +def test_symbols(): + x = Symbol('x') + y = Symbol('y') + z = Symbol('z') + + assert symbols('x') == x + assert symbols('x ') == x + assert symbols(' x ') == x + assert symbols('x,') == (x,) + assert symbols('x, ') == (x,) + assert symbols('x ,') == (x,) + + assert symbols('x , y') == (x, y) + + assert symbols('x,y,z') == (x, y, z) + assert symbols('x y z') == (x, y, z) + + assert symbols('x,y,z,') == (x, y, z) + assert symbols('x y z ') == (x, y, z) + + xyz = Symbol('xyz') + abc = Symbol('abc') + + assert symbols('xyz') == xyz + assert symbols('xyz,') == (xyz,) + assert symbols('xyz,abc') == (xyz, abc) + + assert symbols(('xyz',)) == (xyz,) + assert symbols(('xyz,',)) == ((xyz,),) + assert symbols(('x,y,z,',)) == ((x, y, z),) + assert symbols(('xyz', 'abc')) == (xyz, abc) + assert symbols(('xyz,abc',)) == ((xyz, abc),) + assert symbols(('xyz,abc', 'x,y,z')) == ((xyz, abc), (x, y, z)) + + assert symbols(('x', 'y', 'z')) == (x, y, z) + assert symbols(['x', 'y', 'z']) == [x, y, z] + assert symbols({'x', 'y', 'z'}) == {x, y, z} + + raises(ValueError, lambda: symbols('')) + raises(ValueError, lambda: symbols(',')) + raises(ValueError, lambda: symbols('x,,y,,z')) + raises(ValueError, lambda: symbols(('x', '', 'y', '', 'z'))) + + a, b = symbols('x,y', real=True) + assert a.is_real and b.is_real + + x0 = Symbol('x0') + x1 = Symbol('x1') + x2 = Symbol('x2') + + y0 = Symbol('y0') + y1 = Symbol('y1') + + assert symbols('x0:0') == () + assert symbols('x0:1') == (x0,) + assert symbols('x0:2') == (x0, x1) + assert symbols('x0:3') == (x0, x1, x2) + + assert symbols('x:0') == () + assert symbols('x:1') == (x0,) + assert symbols('x:2') == (x0, x1) + assert symbols('x:3') == (x0, x1, x2) + + assert symbols('x1:1') == () + assert symbols('x1:2') == (x1,) + assert symbols('x1:3') == (x1, x2) + + assert symbols('x1:3,x,y,z') == (x1, x2, x, y, z) + + assert symbols('x:3,y:2') == (x0, x1, x2, y0, y1) + assert symbols(('x:3', 'y:2')) == ((x0, x1, x2), (y0, y1)) + + a = Symbol('a') + b = Symbol('b') + c = Symbol('c') + d = Symbol('d') + + assert symbols('x:z') == (x, y, z) + assert symbols('a:d,x:z') == (a, b, c, d, x, y, z) + assert symbols(('a:d', 'x:z')) == ((a, b, c, d), (x, y, z)) + + aa = Symbol('aa') + ab = Symbol('ab') + ac = Symbol('ac') + ad = Symbol('ad') + + assert symbols('aa:d') == (aa, ab, ac, ad) + assert symbols('aa:d,x:z') == (aa, ab, ac, ad, x, y, z) + assert symbols(('aa:d','x:z')) == ((aa, ab, ac, ad), (x, y, z)) + + assert type(symbols(('q:2', 'u:2'), cls=Function)[0][0]) == UndefinedFunction # issue 23532 + + # issue 6675 + def sym(s): + return str(symbols(s)) + assert sym('a0:4') == '(a0, a1, a2, a3)' + assert sym('a2:4,b1:3') == '(a2, a3, b1, b2)' + assert sym('a1(2:4)') == '(a12, a13)' + assert sym('a0:2.0:2') == '(a0.0, a0.1, a1.0, a1.1)' + assert sym('aa:cz') == '(aaz, abz, acz)' + assert sym('aa:c0:2') == '(aa0, aa1, ab0, ab1, ac0, ac1)' + assert sym('aa:ba:b') == '(aaa, aab, aba, abb)' + assert sym('a:3b') == '(a0b, a1b, a2b)' + assert sym('a-1:3b') == '(a-1b, a-2b)' + assert sym(r'a:2\,:2' + chr(0)) == '(a0,0%s, a0,1%s, a1,0%s, a1,1%s)' % ( + (chr(0),)*4) + assert sym('x(:a:3)') == '(x(a0), x(a1), x(a2))' + assert sym('x(:c):1') == '(xa0, xb0, xc0)' + assert sym('x((:a)):3') == '(x(a)0, x(a)1, x(a)2)' + assert sym('x(:a:3') == '(x(a0, x(a1, x(a2)' + assert sym(':2') == '(0, 1)' + assert sym(':b') == '(a, b)' + assert sym(':b:2') == '(a0, a1, b0, b1)' + assert sym(':2:2') == '(00, 01, 10, 11)' + assert sym(':b:b') == '(aa, ab, ba, bb)' + + raises(ValueError, lambda: symbols(':')) + raises(ValueError, lambda: symbols('a:')) + raises(ValueError, lambda: symbols('::')) + raises(ValueError, lambda: symbols('a::')) + raises(ValueError, lambda: symbols(':a:')) + raises(ValueError, lambda: symbols('::a')) + + +def test_symbols_become_functions_issue_3539(): + from sympy.abc import alpha, phi, beta, t + raises(TypeError, lambda: beta(2)) + raises(TypeError, lambda: beta(2.5)) + raises(TypeError, lambda: phi(2.5)) + raises(TypeError, lambda: alpha(2.5)) + raises(TypeError, lambda: phi(t)) + + +def test_unicode(): + xu = Symbol('x') + x = Symbol('x') + assert x == xu + + raises(TypeError, lambda: Symbol(1)) + + +def test_uniquely_named_symbol_and_Symbol(): + F = uniquely_named_symbol + x = Symbol('x') + assert F(x) == x + assert F('x') == x + assert str(F('x', x)) == 'x0' + assert str(F('x', (x + 1, 1/x))) == 'x0' + _x = Symbol('x', real=True) + assert F(('x', _x)) == _x + assert F((x, _x)) == _x + assert F('x', real=True).is_real + y = Symbol('y') + assert F(('x', y), real=True).is_real + r = Symbol('x', real=True) + assert F(('x', r)).is_real + assert F(('x', r), real=False).is_real + assert F('x1', Symbol('x1'), + compare=lambda i: str(i).rstrip('1')).name == 'x0' + assert F('x1', Symbol('x1'), + modify=lambda i: i + '_').name == 'x1_' + assert _symbol(x, _x) == x + + +def test_disambiguate(): + x, y, y_1, _x, x_1, x_2 = symbols('x y y_1 _x x_1 x_2') + t1 = Dummy('y'), _x, Dummy('x'), Dummy('x') + t2 = Dummy('x'), Dummy('x') + t3 = Dummy('x'), Dummy('y') + t4 = x, Dummy('x') + t5 = Symbol('x', integer=True), x, Symbol('x_1') + + assert disambiguate(*t1) == (y, x_2, x, x_1) + assert disambiguate(*t2) == (x, x_1) + assert disambiguate(*t3) == (x, y) + assert disambiguate(*t4) == (x_1, x) + assert disambiguate(*t5) == (t5[0], x_2, x_1) + assert disambiguate(*t5)[0] != x # assumptions are retained + + t6 = _x, Dummy('x')/y + t7 = y*Dummy('y'), y + + assert disambiguate(*t6) == (x_1, x/y) + assert disambiguate(*t7) == (y*y_1, y_1) + assert disambiguate(Dummy('x_1'), Dummy('x_1') + ) == (x_1, Symbol('x_1_1')) + + +@skip_under_pyodide("Cannot create threads under pyodide.") +def test_issue_gh_16734(): + # https://github.com/sympy/sympy/issues/16734 + + syms = list(symbols('x, y')) + + def thread1(): + for n in range(1000): + syms[0], syms[1] = symbols(f'x{n}, y{n}') + syms[0].is_positive # Check an assumption in this thread. + syms[0] = None + + def thread2(): + while syms[0] is not None: + # Compare the symbol in this thread. + result = (syms[0] == syms[1]) # noqa + + # Previously this would be very likely to raise an exception: + thread = threading.Thread(target=thread1) + thread.start() + thread2() + thread.join() diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_sympify.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_sympify.py new file mode 100644 index 0000000000000000000000000000000000000000..8cd0787bc6f5320c6be1cf3279c82cbff3ab97ce --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_sympify.py @@ -0,0 +1,885 @@ +from sympy.core.add import Add +from sympy.core.containers import Tuple +from sympy.core.function import (Function, Lambda) +from sympy.core.mul import Mul +from sympy.core.numbers import (Float, I, Integer, Rational, pi, oo) +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.logic.boolalg import (false, Or, true, Xor) +from sympy.matrices.dense import Matrix +from sympy.parsing.sympy_parser import null +from sympy.polys.polytools import Poly +from sympy.printing.repr import srepr +from sympy.sets.fancysets import Range +from sympy.sets.sets import Interval +from sympy.abc import x, y +from sympy.core.sympify import (sympify, _sympify, SympifyError, kernS, + CantSympify, converter) +from sympy.core.decorators import _sympifyit +from sympy.external import import_module +from sympy.testing.pytest import raises, XFAIL, skip +from sympy.utilities.decorator import conserve_mpmath_dps +from sympy.geometry import Point, Line +from sympy.functions.combinatorial.factorials import factorial, factorial2 +from sympy.abc import _clash, _clash1, _clash2 +from sympy.external.gmpy import gmpy as _gmpy, flint as _flint +from sympy.sets import FiniteSet, EmptySet +from sympy.tensor.array.dense_ndim_array import ImmutableDenseNDimArray + +import mpmath +from collections import defaultdict, OrderedDict + + +numpy = import_module('numpy') + + +def test_issue_3538(): + v = sympify("exp(x)") + assert v == exp(x) + assert type(v) == type(exp(x)) + assert str(type(v)) == str(type(exp(x))) + + +def test_sympify1(): + assert sympify("x") == Symbol("x") + assert sympify(" x") == Symbol("x") + assert sympify(" x ") == Symbol("x") + # issue 4877 + assert sympify('--.5') == 0.5 + assert sympify('-1/2') == -S.Half + assert sympify('-+--.5') == -0.5 + assert sympify('-.[3]') == Rational(-1, 3) + assert sympify('.[3]') == Rational(1, 3) + assert sympify('+.[3]') == Rational(1, 3) + assert sympify('+0.[3]*10**-2') == Rational(1, 300) + assert sympify('.[052631578947368421]') == Rational(1, 19) + assert sympify('.0[526315789473684210]') == Rational(1, 19) + assert sympify('.034[56]') == Rational(1711, 49500) + # options to make reals into rationals + assert sympify('1.22[345]', rational=True) == \ + 1 + Rational(22, 100) + Rational(345, 99900) + assert sympify('2/2.6', rational=True) == Rational(10, 13) + assert sympify('2.6/2', rational=True) == Rational(13, 10) + assert sympify('2.6e2/17', rational=True) == Rational(260, 17) + assert sympify('2.6e+2/17', rational=True) == Rational(260, 17) + assert sympify('2.6e-2/17', rational=True) == Rational(26, 17000) + assert sympify('2.1+3/4', rational=True) == \ + Rational(21, 10) + Rational(3, 4) + assert sympify('2.234456', rational=True) == Rational(279307, 125000) + assert sympify('2.234456e23', rational=True) == 223445600000000000000000 + assert sympify('2.234456e-23', rational=True) == \ + Rational(279307, 12500000000000000000000000000) + assert sympify('-2.234456e-23', rational=True) == \ + Rational(-279307, 12500000000000000000000000000) + assert sympify('12345678901/17', rational=True) == \ + Rational(12345678901, 17) + assert sympify('1/.3 + x', rational=True) == Rational(10, 3) + x + # make sure longs in fractions work + assert sympify('222222222222/11111111111') == \ + Rational(222222222222, 11111111111) + # ... even if they come from repetend notation + assert sympify('1/.2[123456789012]') == Rational(333333333333, 70781892967) + # ... or from high precision reals + assert sympify('.1234567890123456', rational=True) == \ + Rational(19290123283179, 156250000000000) + + +def test_sympify_Fraction(): + try: + import fractions + except ImportError: + pass + else: + value = sympify(fractions.Fraction(101, 127)) + assert value == Rational(101, 127) and type(value) is Rational + + +def test_sympify_gmpy(): + if _gmpy is not None: + import gmpy2 + + value = sympify(gmpy2.mpz(1000001)) + assert value == Integer(1000001) and type(value) is Integer + + value = sympify(gmpy2.mpq(101, 127)) + assert value == Rational(101, 127) and type(value) is Rational + + +def test_sympify_flint(): + if _flint is not None: + import flint + + value = sympify(flint.fmpz(1000001)) + assert value == Integer(1000001) and type(value) is Integer + + value = sympify(flint.fmpq(101, 127)) + assert value == Rational(101, 127) and type(value) is Rational + + +@conserve_mpmath_dps +def test_sympify_mpmath(): + value = sympify(mpmath.mpf(1.0)) + assert value == Float(1.0) and type(value) is Float + + mpmath.mp.dps = 12 + assert sympify( + mpmath.pi).epsilon_eq(Float("3.14159265359"), Float("1e-12")) == True + assert sympify( + mpmath.pi).epsilon_eq(Float("3.14159265359"), Float("1e-13")) == False + + mpmath.mp.dps = 6 + assert sympify( + mpmath.pi).epsilon_eq(Float("3.14159"), Float("1e-5")) == True + assert sympify( + mpmath.pi).epsilon_eq(Float("3.14159"), Float("1e-6")) == False + + mpmath.mp.dps = 15 + assert sympify(mpmath.mpc(1.0 + 2.0j)) == Float(1.0) + Float(2.0)*I + + +def test_sympify2(): + class A: + def _sympy_(self): + return Symbol("x")**3 + + a = A() + + assert _sympify(a) == x**3 + assert sympify(a) == x**3 + assert a == x**3 + + +def test_sympify3(): + assert sympify("x**3") == x**3 + assert sympify("x^3") == x**3 + assert sympify("1/2") == Integer(1)/2 + + raises(SympifyError, lambda: _sympify('x**3')) + raises(SympifyError, lambda: _sympify('1/2')) + + +def test_sympify_keywords(): + raises(SympifyError, lambda: sympify('if')) + raises(SympifyError, lambda: sympify('for')) + raises(SympifyError, lambda: sympify('while')) + raises(SympifyError, lambda: sympify('lambda')) + + +def test_sympify_float(): + assert sympify("1e-64") != 0 + assert sympify("1e-20000") != 0 + + +def test_sympify_bool(): + assert sympify(True) is true + assert sympify(False) is false + + +def test_sympyify_iterables(): + ans = [Rational(3, 10), Rational(1, 5)] + assert sympify(['.3', '.2'], rational=True) == ans + assert sympify({"x": 0, "y": 1}) == {x: 0, y: 1} + assert sympify(['1', '2', ['3', '4']]) == [S(1), S(2), [S(3), S(4)]] + + +@XFAIL +def test_issue_16772(): + # because there is a converter for tuple, the + # args are only sympified without the flags being passed + # along; list, on the other hand, is not converted + # with a converter so its args are traversed later + ans = [Rational(3, 10), Rational(1, 5)] + assert sympify(('.3', '.2'), rational=True) == Tuple(*ans) + + +def test_issue_16859(): + class no(float, CantSympify): + pass + raises(SympifyError, lambda: sympify(no(1.2))) + + +def test_sympify4(): + class A: + def _sympy_(self): + return Symbol("x") + + a = A() + + assert _sympify(a)**3 == x**3 + assert sympify(a)**3 == x**3 + assert a == x + + +def test_sympify_text(): + assert sympify('some') == Symbol('some') + assert sympify('core') == Symbol('core') + + assert sympify('True') is True + assert sympify('False') is False + + assert sympify('Poly') == Poly + assert sympify('sin') == sin + + +def test_sympify_function(): + assert sympify('factor(x**2-1, x)') == -(1 - x)*(x + 1) + assert sympify('sin(pi/2)*cos(pi)') == -Integer(1) + + +def test_sympify_poly(): + p = Poly(x**2 + x + 1, x) + + assert _sympify(p) is p + assert sympify(p) is p + + +def test_sympify_factorial(): + assert sympify('x!') == factorial(x) + assert sympify('(x+1)!') == factorial(x + 1) + assert sympify('(1 + y*(x + 1))!') == factorial(1 + y*(x + 1)) + assert sympify('(1 + y*(x + 1)!)^2') == (1 + y*factorial(x + 1))**2 + assert sympify('y*x!') == y*factorial(x) + assert sympify('x!!') == factorial2(x) + assert sympify('(x+1)!!') == factorial2(x + 1) + assert sympify('(1 + y*(x + 1))!!') == factorial2(1 + y*(x + 1)) + assert sympify('(1 + y*(x + 1)!!)^2') == (1 + y*factorial2(x + 1))**2 + assert sympify('y*x!!') == y*factorial2(x) + assert sympify('factorial2(x)!') == factorial(factorial2(x)) + + raises(SympifyError, lambda: sympify("+!!")) + raises(SympifyError, lambda: sympify(")!!")) + raises(SympifyError, lambda: sympify("!")) + raises(SympifyError, lambda: sympify("(!)")) + raises(SympifyError, lambda: sympify("x!!!")) + + +def test_issue_3595(): + assert sympify("a_") == Symbol("a_") + assert sympify("_a") == Symbol("_a") + + +def test_lambda(): + x = Symbol('x') + assert sympify('lambda: 1') == Lambda((), 1) + assert sympify('lambda x: x') == Lambda(x, x) + assert sympify('lambda x: 2*x') == Lambda(x, 2*x) + assert sympify('lambda x, y: 2*x+y') == Lambda((x, y), 2*x + y) + + +def test_lambda_raises(): + raises(SympifyError, lambda: sympify("lambda *args: args")) # args argument error + raises(SympifyError, lambda: sympify("lambda **kwargs: kwargs[0]")) # kwargs argument error + raises(SympifyError, lambda: sympify("lambda x = 1: x")) # Keyword argument error + with raises(SympifyError): + _sympify('lambda: 1') + + +def test_sympify_raises(): + raises(SympifyError, lambda: sympify("fx)")) + + class A: + def __str__(self): + return 'x' + + raises(SympifyError, lambda: sympify(A())) + + +def test__sympify(): + x = Symbol('x') + f = Function('f') + + # positive _sympify + assert _sympify(x) is x + assert _sympify(1) == Integer(1) + assert _sympify(0.5) == Float("0.5") + assert _sympify(1 + 1j) == 1.0 + I*1.0 + + # Function f is not Basic and can't sympify to Basic. We allow it to pass + # with sympify but not with _sympify. + # https://github.com/sympy/sympy/issues/20124 + assert sympify(f) is f + raises(SympifyError, lambda: _sympify(f)) + + class A: + def _sympy_(self): + return Integer(5) + + a = A() + assert _sympify(a) == Integer(5) + + # negative _sympify + raises(SympifyError, lambda: _sympify('1')) + raises(SympifyError, lambda: _sympify([1, 2, 3])) + + +def test_sympifyit(): + x = Symbol('x') + y = Symbol('y') + + @_sympifyit('b', NotImplemented) + def add(a, b): + return a + b + + assert add(x, 1) == x + 1 + assert add(x, 0.5) == x + Float('0.5') + assert add(x, y) == x + y + + assert add(x, '1') == NotImplemented + + @_sympifyit('b') + def add_raises(a, b): + return a + b + + assert add_raises(x, 1) == x + 1 + assert add_raises(x, 0.5) == x + Float('0.5') + assert add_raises(x, y) == x + y + + raises(SympifyError, lambda: add_raises(x, '1')) + + +def test_int_float(): + class F1_1: + def __float__(self): + return 1.1 + + class F1_1b: + """ + This class is still a float, even though it also implements __int__(). + """ + def __float__(self): + return 1.1 + + def __int__(self): + return 1 + + class F1_1c: + """ + This class is still a float, because it implements _sympy_() + """ + def __float__(self): + return 1.1 + + def __int__(self): + return 1 + + def _sympy_(self): + return Float(1.1) + + class I5: + def __int__(self): + return 5 + + class I5b: + """ + This class implements both __int__() and __float__(), so it will be + treated as Float in SymPy. One could change this behavior, by using + float(a) == int(a), but deciding that integer-valued floats represent + exact numbers is arbitrary and often not correct, so we do not do it. + If, in the future, we decide to do it anyway, the tests for I5b need to + be changed. + """ + def __float__(self): + return 5.0 + + def __int__(self): + return 5 + + class I5c: + """ + This class implements both __int__() and __float__(), but also + a _sympy_() method, so it will be Integer. + """ + def __float__(self): + return 5.0 + + def __int__(self): + return 5 + + def _sympy_(self): + return Integer(5) + + i5 = I5() + i5b = I5b() + i5c = I5c() + f1_1 = F1_1() + f1_1b = F1_1b() + f1_1c = F1_1c() + assert sympify(i5) == 5 + assert isinstance(sympify(i5), Integer) + assert sympify(i5b) == 5.0 + assert isinstance(sympify(i5b), Float) + assert sympify(i5c) == 5 + assert isinstance(sympify(i5c), Integer) + assert abs(sympify(f1_1) - 1.1) < 1e-5 + assert abs(sympify(f1_1b) - 1.1) < 1e-5 + assert abs(sympify(f1_1c) - 1.1) < 1e-5 + + assert _sympify(i5) == 5 + assert isinstance(_sympify(i5), Integer) + assert _sympify(i5b) == 5.0 + assert isinstance(_sympify(i5b), Float) + assert _sympify(i5c) == 5 + assert isinstance(_sympify(i5c), Integer) + assert abs(_sympify(f1_1) - 1.1) < 1e-5 + assert abs(_sympify(f1_1b) - 1.1) < 1e-5 + assert abs(_sympify(f1_1c) - 1.1) < 1e-5 + + +def test_evaluate_false(): + cases = { + '2 + 3': Add(2, 3, evaluate=False), + '2**2 / 3': Mul(Pow(2, 2, evaluate=False), Pow(3, -1, evaluate=False), evaluate=False), + '2 + 3 * 5': Add(2, Mul(3, 5, evaluate=False), evaluate=False), + '2 - 3 * 5': Add(2, Mul(-1, Mul(3, 5,evaluate=False), evaluate=False), evaluate=False), + '1 / 3': Mul(1, Pow(3, -1, evaluate=False), evaluate=False), + 'True | False': Or(True, False, evaluate=False), + '1 + 2 + 3 + 5*3 + integrate(x)': Add(1, 2, 3, Mul(5, 3, evaluate=False), x**2/2, evaluate=False), + '2 * 4 * 6 + 8': Add(Mul(2, 4, 6, evaluate=False), 8, evaluate=False), + '2 - 8 / 4': Add(2, Mul(-1, Mul(8, Pow(4, -1, evaluate=False), evaluate=False), evaluate=False), evaluate=False), + '2 - 2**2': Add(2, Mul(-1, Pow(2, 2, evaluate=False), evaluate=False), evaluate=False), + } + for case, result in cases.items(): + assert sympify(case, evaluate=False) == result + + +def test_issue_4133(): + a = sympify('Integer(4)') + + assert a == Integer(4) + assert a.is_Integer + + +def test_issue_3982(): + a = [3, 2.0] + assert sympify(a) == [Integer(3), Float(2.0)] + assert sympify(tuple(a)) == Tuple(Integer(3), Float(2.0)) + assert sympify(set(a)) == FiniteSet(Integer(3), Float(2.0)) + + +def test_S_sympify(): + assert S(1)/2 == sympify(1)/2 == S.Half + assert (-2)**(S(1)/2) == sqrt(2)*I + + +def test_issue_4788(): + assert srepr(S(1.0 + 0J)) == srepr(S(1.0)) == srepr(Float(1.0)) + + +def test_issue_4798_None(): + assert S(None) is None + + +def test_issue_3218(): + assert sympify("x+\ny") == x + y + +def test_issue_19399(): + if not numpy: + skip("numpy not installed.") + + a = numpy.array(Rational(1, 2)) + b = Rational(1, 3) + assert (a * b, type(a * b)) == (b * a, type(b * a)) + + +def test_issue_4988_builtins(): + C = Symbol('C') + vars = {'C': C} + exp1 = sympify('C') + assert exp1 == C # Make sure it did not get mixed up with sympy.C + + exp2 = sympify('C', vars) + assert exp2 == C # Make sure it did not get mixed up with sympy.C + + +def test_geometry(): + p = sympify(Point(0, 1)) + assert p == Point(0, 1) and isinstance(p, Point) + L = sympify(Line(p, (1, 0))) + assert L == Line((0, 1), (1, 0)) and isinstance(L, Line) + + +def test_kernS(): + s = '-1 - 2*(-(-x + 1/x)/(x*(x - 1/x)**2) - 1/(x*(x - 1/x)))' + # when 1497 is fixed, this no longer should pass: the expression + # should be unchanged + assert -1 - 2*(-(-x + 1/x)/(x*(x - 1/x)**2) - 1/(x*(x - 1/x))) == -1 + # sympification should not allow the constant to enter a Mul + # or else the structure can change dramatically + ss = kernS(s) + assert ss != -1 and ss.simplify() == -1 + s = '-1 - 2*(-(-x + 1/x)/(x*(x - 1/x)**2) - 1/(x*(x - 1/x)))'.replace( + 'x', '_kern') + ss = kernS(s) + assert ss != -1 and ss.simplify() == -1 + # issue 6687 + assert (kernS('Interval(-1,-2 - 4*(-3))') + == Interval(-1, Add(-2, Mul(12, 1, evaluate=False), evaluate=False))) + assert kernS('_kern') == Symbol('_kern') + assert kernS('E**-(x)') == exp(-x) + e = 2*(x + y)*y + assert kernS(['2*(x + y)*y', ('2*(x + y)*y',)]) == [e, (e,)] + assert kernS('-(2*sin(x)**2 + 2*sin(x)*cos(x))*y/2') == \ + -y*(2*sin(x)**2 + 2*sin(x)*cos(x))/2 + # issue 15132 + assert kernS('(1 - x)/(1 - x*(1-y))') == kernS('(1-x)/(1-(1-y)*x)') + assert kernS('(1-2**-(4+1)*(1-y)*x)') == (1 - x*(1 - y)/32) + assert kernS('(1-2**(4+1)*(1-y)*x)') == (1 - 32*x*(1 - y)) + assert kernS('(1-2.*(1-y)*x)') == 1 - 2.*x*(1 - y) + one = kernS('x - (x - 1)') + assert one != 1 and one.expand() == 1 + assert kernS("(2*x)/(x-1)") == 2*x/(x-1) + + +def test_issue_6540_6552(): + assert S('[[1/3,2], (2/5,)]') == [[Rational(1, 3), 2], (Rational(2, 5),)] + assert S('[[2/6,2], (2/4,)]') == [[Rational(1, 3), 2], (S.Half,)] + assert S('[[[2*(1)]]]') == [[[2]]] + assert S('Matrix([2*(1)])') == Matrix([2]) + + +def test_issue_6046(): + assert str(S("Q & C", locals=_clash1)) == 'C & Q' + assert str(S('pi(x)', locals=_clash2)) == 'pi(x)' + locals = {} + exec("from sympy.abc import Q, C", locals) + assert str(S('C&Q', locals)) == 'C & Q' + # clash can act as Symbol or Function + assert str(S('pi(C, Q)', locals=_clash)) == 'pi(C, Q)' + assert len(S('pi + x', locals=_clash2).free_symbols) == 2 + # but not both + raises(TypeError, lambda: S('pi + pi(x)', locals=_clash2)) + assert all(set(i.values()) == {null} for i in ( + _clash, _clash1, _clash2)) + + +def test_issue_8821_highprec_from_str(): + s = str(pi.evalf(128)) + p = sympify(s) + assert Abs(sin(p)) < 1e-127 + + +def test_issue_10295(): + if not numpy: + skip("numpy not installed.") + + A = numpy.array([[1, 3, -1], + [0, 1, 7]]) + sA = S(A) + assert sA.shape == (2, 3) + for (ri, ci), val in numpy.ndenumerate(A): + assert sA[ri, ci] == val + + B = numpy.array([-7, x, 3*y**2]) + sB = S(B) + assert sB.shape == (3,) + assert B[0] == sB[0] == -7 + assert B[1] == sB[1] == x + assert B[2] == sB[2] == 3*y**2 + + C = numpy.arange(0, 24) + C.resize(2,3,4) + sC = S(C) + assert sC[0, 0, 0].is_integer + assert sC[0, 0, 0] == 0 + + a1 = numpy.array([1, 2, 3]) + a2 = numpy.array(list(range(24))) + a2.resize(2, 4, 3) + assert sympify(a1) == ImmutableDenseNDimArray([1, 2, 3]) + assert sympify(a2) == ImmutableDenseNDimArray(list(range(24)), (2, 4, 3)) + + +def test_Range(): + # Only works in Python 3 where range returns a range type + assert sympify(range(10)) == Range(10) + assert _sympify(range(10)) == Range(10) + + +def test_sympify_set(): + n = Symbol('n') + assert sympify({n}) == FiniteSet(n) + assert sympify(set()) == EmptySet + + +def test_sympify_numpy(): + if not numpy: + skip('numpy not installed. Abort numpy tests.') + np = numpy + + def equal(x, y): + return x == y and type(x) == type(y) + + assert sympify(np.bool_(1)) is S(True) + try: + assert equal( + sympify(np.int_(1234567891234567891)), S(1234567891234567891)) + assert equal( + sympify(np.intp(1234567891234567891)), S(1234567891234567891)) + except OverflowError: + # May fail on 32-bit systems: Python int too large to convert to C long + pass + assert equal(sympify(np.intc(1234567891)), S(1234567891)) + assert equal(sympify(np.int8(-123)), S(-123)) + assert equal(sympify(np.int16(-12345)), S(-12345)) + assert equal(sympify(np.int32(-1234567891)), S(-1234567891)) + assert equal( + sympify(np.int64(-1234567891234567891)), S(-1234567891234567891)) + assert equal(sympify(np.uint8(123)), S(123)) + assert equal(sympify(np.uint16(12345)), S(12345)) + assert equal(sympify(np.uint32(1234567891)), S(1234567891)) + assert equal( + sympify(np.uint64(1234567891234567891)), S(1234567891234567891)) + assert equal(sympify(np.float32(1.123456)), Float(1.123456, precision=24)) + assert equal(sympify(np.float64(1.1234567891234)), + Float(1.1234567891234, precision=53)) + + # The exact precision of np.longdouble, npfloat128 and other extended + # precision dtypes is platform dependent. + ldprec = np.finfo(np.longdouble(1)).nmant + 1 + assert equal(sympify(np.longdouble(1.123456789)), + Float(1.123456789, precision=ldprec)) + + assert equal(sympify(np.complex64(1 + 2j)), S(1.0 + 2.0*I)) + assert equal(sympify(np.complex128(1 + 2j)), S(1.0 + 2.0*I)) + + lcprec = np.finfo(np.clongdouble(1)).nmant + 1 + assert equal(sympify(np.clongdouble(1 + 2j)), + Float(1.0, precision=lcprec) + Float(2.0, precision=lcprec)*I) + + #float96 does not exist on all platforms + if hasattr(np, 'float96'): + f96prec = np.finfo(np.float96(1)).nmant + 1 + assert equal(sympify(np.float96(1.123456789)), + Float(1.123456789, precision=f96prec)) + + #float128 does not exist on all platforms + if hasattr(np, 'float128'): + f128prec = np.finfo(np.float128(1)).nmant + 1 + assert equal(sympify(np.float128(1.123456789123)), + Float(1.123456789123, precision=f128prec)) + + +@XFAIL +def test_sympify_rational_numbers_set(): + ans = [Rational(3, 10), Rational(1, 5)] + assert sympify({'.3', '.2'}, rational=True) == FiniteSet(*ans) + + +def test_sympify_mro(): + """Tests the resolution order for classes that implement _sympy_""" + class a: + def _sympy_(self): + return Integer(1) + class b(a): + def _sympy_(self): + return Integer(2) + class c(a): + pass + + assert sympify(a()) == Integer(1) + assert sympify(b()) == Integer(2) + assert sympify(c()) == Integer(1) + + +def test_sympify_converter(): + """Tests the resolution order for classes in converter""" + class a: + pass + class b(a): + pass + class c(a): + pass + + converter[a] = lambda x: Integer(1) + converter[b] = lambda x: Integer(2) + + assert sympify(a()) == Integer(1) + assert sympify(b()) == Integer(2) + assert sympify(c()) == Integer(1) + + class MyInteger(Integer): + pass + + if int in converter: + int_converter = converter[int] + else: + int_converter = None + + try: + converter[int] = MyInteger + assert sympify(1) == MyInteger(1) + finally: + if int_converter is None: + del converter[int] + else: + converter[int] = int_converter + + +def test_issue_13924(): + if not numpy: + skip("numpy not installed.") + + a = sympify(numpy.array([1])) + assert isinstance(a, ImmutableDenseNDimArray) + assert a[0] == 1 + + +def test_numpy_sympify_args(): + # Issue 15098. Make sure sympify args work with numpy types (like numpy.str_) + if not numpy: + skip("numpy not installed.") + + a = sympify(numpy.str_('a')) + assert type(a) is Symbol + assert a == Symbol('a') + + class CustomSymbol(Symbol): + pass + + a = sympify(numpy.str_('a'), {"Symbol": CustomSymbol}) + assert isinstance(a, CustomSymbol) + + a = sympify(numpy.str_('x^y')) + assert a == x**y + a = sympify(numpy.str_('x^y'), convert_xor=False) + assert a == Xor(x, y) + + raises(SympifyError, lambda: sympify(numpy.str_('x'), strict=True)) + + a = sympify(numpy.str_('1.1')) + assert isinstance(a, Float) + assert a == 1.1 + + a = sympify(numpy.str_('1.1'), rational=True) + assert isinstance(a, Rational) + assert a == Rational(11, 10) + + a = sympify(numpy.str_('x + x')) + assert isinstance(a, Mul) + assert a == 2*x + + a = sympify(numpy.str_('x + x'), evaluate=False) + assert isinstance(a, Add) + assert a == Add(x, x, evaluate=False) + + +def test_issue_5939(): + a = Symbol('a') + b = Symbol('b') + assert sympify('''a+\nb''') == a + b + + +def test_issue_16759(): + d = sympify({.5: 1}) + assert S.Half not in d + assert Float(.5) in d + assert d[.5] is S.One + d = sympify(OrderedDict({.5: 1})) + assert S.Half not in d + assert Float(.5) in d + assert d[.5] is S.One + d = sympify(defaultdict(int, {.5: 1})) + assert S.Half not in d + assert Float(.5) in d + assert d[.5] is S.One + + +def test_issue_17811(): + a = Function('a') + assert sympify('a(x)*5', evaluate=False) == Mul(a(x), 5, evaluate=False) + + +def test_issue_8439(): + assert sympify(float('inf')) == oo + assert x + float('inf') == x + oo + assert S(float('inf')) == oo + + +def test_issue_14706(): + if not numpy: + skip("numpy not installed.") + + z1 = numpy.zeros((1, 1), dtype=numpy.float64) + z2 = numpy.zeros((2, 2), dtype=numpy.float64) + z3 = numpy.zeros((), dtype=numpy.float64) + + y1 = numpy.ones((1, 1), dtype=numpy.float64) + y2 = numpy.ones((2, 2), dtype=numpy.float64) + y3 = numpy.ones((), dtype=numpy.float64) + + assert numpy.all(x + z1 == numpy.full((1, 1), x)) + assert numpy.all(x + z2 == numpy.full((2, 2), x)) + assert numpy.all(z1 + x == numpy.full((1, 1), x)) + assert numpy.all(z2 + x == numpy.full((2, 2), x)) + for z in [z3, + numpy.int64(0), + numpy.float64(0), + numpy.complex64(0)]: + assert x + z == x + assert z + x == x + assert isinstance(x + z, Symbol) + assert isinstance(z + x, Symbol) + + # If these tests fail, then it means that numpy has finally + # fixed the issue of scalar conversion for rank>0 arrays + # which is mentioned in numpy/numpy#10404. In that case, + # some changes have to be made in sympify.py. + # Note: For future reference, for anyone who takes up this + # issue when numpy has finally fixed their side of the problem, + # the changes for this temporary fix were introduced in PR 18651 + assert numpy.all(x + y1 == numpy.full((1, 1), x + 1.0)) + assert numpy.all(x + y2 == numpy.full((2, 2), x + 1.0)) + assert numpy.all(y1 + x == numpy.full((1, 1), x + 1.0)) + assert numpy.all(y2 + x == numpy.full((2, 2), x + 1.0)) + for y_ in [y3, + numpy.int64(1), + numpy.float64(1), + numpy.complex64(1)]: + assert x + y_ == y_ + x + assert isinstance(x + y_, Add) + assert isinstance(y_ + x, Add) + + assert x + numpy.array(x) == 2 * x + assert x + numpy.array([x]) == numpy.array([2*x], dtype=object) + + assert sympify(numpy.array([1])) == ImmutableDenseNDimArray([1], 1) + assert sympify(numpy.array([[[1]]])) == ImmutableDenseNDimArray([1], (1, 1, 1)) + assert sympify(z1) == ImmutableDenseNDimArray([0.0], (1, 1)) + assert sympify(z2) == ImmutableDenseNDimArray([0.0, 0.0, 0.0, 0.0], (2, 2)) + assert sympify(z3) == ImmutableDenseNDimArray([0.0], ()) + assert sympify(z3, strict=True) == 0.0 + + raises(SympifyError, lambda: sympify(numpy.array([1]), strict=True)) + raises(SympifyError, lambda: sympify(z1, strict=True)) + raises(SympifyError, lambda: sympify(z2, strict=True)) + + +def test_issue_21536(): + #test to check evaluate=False in case of iterable input + u = sympify("x+3*x+2", evaluate=False) + v = sympify("2*x+4*x+2+4", evaluate=False) + + assert u.is_Add and set(u.args) == {x, 3*x, 2} + assert v.is_Add and set(v.args) == {2*x, 4*x, 2, 4} + assert sympify(["x+3*x+2", "2*x+4*x+2+4"], evaluate=False) == [u, v] + + #test to check evaluate=True in case of iterable input + u = sympify("x+3*x+2", evaluate=True) + v = sympify("2*x+4*x+2+4", evaluate=True) + + assert u.is_Add and set(u.args) == {4*x, 2} + assert v.is_Add and set(v.args) == {6*x, 6} + assert sympify(["x+3*x+2", "2*x+4*x+2+4"], evaluate=True) == [u, v] + + #test to check evaluate with no input in case of iterable input + u = sympify("x+3*x+2") + v = sympify("2*x+4*x+2+4") + + assert u.is_Add and set(u.args) == {4*x, 2} + assert v.is_Add and set(v.args) == {6*x, 6} + assert sympify(["x+3*x+2", "2*x+4*x+2+4"]) == [u, v] diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_traversal.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_traversal.py new file mode 100644 index 0000000000000000000000000000000000000000..8bf067283eaba5d4a073a73feb07aac199055a7f --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_traversal.py @@ -0,0 +1,119 @@ +from sympy.core.basic import Basic +from sympy.core.containers import Tuple +from sympy.core.sorting import default_sort_key +from sympy.core.symbol import symbols +from sympy.core.singleton import S +from sympy.core.function import expand, Function +from sympy.core.numbers import I +from sympy.integrals.integrals import Integral +from sympy.polys.polytools import factor +from sympy.core.traversal import preorder_traversal, use, postorder_traversal, iterargs, iterfreeargs +from sympy.functions.elementary.piecewise import ExprCondPair, Piecewise +from sympy.testing.pytest import warns_deprecated_sympy +from sympy.utilities.iterables import capture + +b1 = Basic() +b2 = Basic(b1) +b3 = Basic(b2) +b21 = Basic(b2, b1) + + +def test_preorder_traversal(): + expr = Basic(b21, b3) + assert list( + preorder_traversal(expr)) == [expr, b21, b2, b1, b1, b3, b2, b1] + assert list(preorder_traversal(('abc', ('d', 'ef')))) == [ + ('abc', ('d', 'ef')), 'abc', ('d', 'ef'), 'd', 'ef'] + + result = [] + pt = preorder_traversal(expr) + for i in pt: + result.append(i) + if i == b2: + pt.skip() + assert result == [expr, b21, b2, b1, b3, b2] + + w, x, y, z = symbols('w:z') + expr = z + w*(x + y) + assert list(preorder_traversal([expr], keys=default_sort_key)) == \ + [[w*(x + y) + z], w*(x + y) + z, z, w*(x + y), w, x + y, x, y] + assert list(preorder_traversal((x + y)*z, keys=True)) == \ + [z*(x + y), z, x + y, x, y] + + +def test_use(): + x, y = symbols('x y') + + assert use(0, expand) == 0 + + f = (x + y)**2*x + 1 + + assert use(f, expand, level=0) == x**3 + 2*x**2*y + x*y**2 + + 1 + assert use(f, expand, level=1) == x**3 + 2*x**2*y + x*y**2 + + 1 + assert use(f, expand, level=2) == 1 + x*(2*x*y + x**2 + y**2) + assert use(f, expand, level=3) == (x + y)**2*x + 1 + + f = (x**2 + 1)**2 - 1 + kwargs = {'gaussian': True} + + assert use(f, factor, level=0, kwargs=kwargs) == x**2*(x**2 + 2) + assert use(f, factor, level=1, kwargs=kwargs) == (x + I)**2*(x - I)**2 - 1 + assert use(f, factor, level=2, kwargs=kwargs) == (x + I)**2*(x - I)**2 - 1 + assert use(f, factor, level=3, kwargs=kwargs) == (x**2 + 1)**2 - 1 + + +def test_postorder_traversal(): + x, y, z, w = symbols('x y z w') + expr = z + w*(x + y) + expected = [z, w, x, y, x + y, w*(x + y), w*(x + y) + z] + assert list(postorder_traversal(expr, keys=default_sort_key)) == expected + assert list(postorder_traversal(expr, keys=True)) == expected + + expr = Piecewise((x, x < 1), (x**2, True)) + expected = [ + x, 1, x, x < 1, ExprCondPair(x, x < 1), + 2, x, x**2, S.true, + ExprCondPair(x**2, True), Piecewise((x, x < 1), (x**2, True)) + ] + assert list(postorder_traversal(expr, keys=default_sort_key)) == expected + assert list(postorder_traversal( + [expr], keys=default_sort_key)) == expected + [[expr]] + + assert list(postorder_traversal(Integral(x**2, (x, 0, 1)), + keys=default_sort_key)) == [ + 2, x, x**2, 0, 1, x, Tuple(x, 0, 1), + Integral(x**2, Tuple(x, 0, 1)) + ] + assert list(postorder_traversal(('abc', ('d', 'ef')))) == [ + 'abc', 'd', 'ef', ('d', 'ef'), ('abc', ('d', 'ef'))] + + +def test_iterargs(): + f = Function('f') + x = symbols('x') + assert list(iterfreeargs(Integral(f(x), (f(x), 1)))) == [ + Integral(f(x), (f(x), 1)), 1] + assert list(iterargs(Integral(f(x), (f(x), 1)))) == [ + Integral(f(x), (f(x), 1)), f(x), (f(x), 1), x, f(x), 1, x] + +def test_deprecated_imports(): + x = symbols('x') + + with warns_deprecated_sympy(): + from sympy.core.basic import preorder_traversal + preorder_traversal(x) + with warns_deprecated_sympy(): + from sympy.simplify.simplify import bottom_up + bottom_up(x, lambda x: x) + with warns_deprecated_sympy(): + from sympy.simplify.simplify import walk + walk(x, lambda x: x) + with warns_deprecated_sympy(): + from sympy.simplify.traversaltools import use + use(x, lambda x: x) + with warns_deprecated_sympy(): + from sympy.utilities.iterables import postorder_traversal + postorder_traversal(x) + with warns_deprecated_sympy(): + from sympy.utilities.iterables import interactive_traversal + capture(lambda: interactive_traversal(x)) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_truediv.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_truediv.py new file mode 100644 index 0000000000000000000000000000000000000000..1fcf9e1ab754d05a3b47e7ec0c2be5ea9929da02 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_truediv.py @@ -0,0 +1,54 @@ +#this module tests that SymPy works with true division turned on + +from sympy.core.numbers import (Float, Rational) +from sympy.core.symbol import Symbol + + +def test_truediv(): + assert 1/2 != 0 + assert Rational(1)/2 != 0 + + +def dotest(s): + x = Symbol("x") + y = Symbol("y") + l = [ + Rational(2), + Float("1.3"), + x, + y, + pow(x, y)*y, + 5, + 5.5 + ] + for x in l: + for y in l: + s(x, y) + return True + + +def test_basic(): + def s(a, b): + x = a + x = +a + x = -a + x = a + b + x = a - b + x = a*b + x = a/b + x = a**b + del x + assert dotest(s) + + +def test_ibasic(): + def s(a, b): + x = a + x += b + x = a + x -= b + x = a + x *= b + x = a + x /= b + assert dotest(s) diff --git a/.venv/lib/python3.11/site-packages/sympy/core/tests/test_var.py b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_var.py new file mode 100644 index 0000000000000000000000000000000000000000..a02709464c9878082fecaf70fa47067ac8838ac6 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/core/tests/test_var.py @@ -0,0 +1,62 @@ +from sympy.core.function import (Function, FunctionClass) +from sympy.core.symbol import (Symbol, var) +from sympy.testing.pytest import raises + +def test_var(): + ns = {"var": var, "raises": raises} + eval("var('a')", ns) + assert ns["a"] == Symbol("a") + + eval("var('b bb cc zz _x')", ns) + assert ns["b"] == Symbol("b") + assert ns["bb"] == Symbol("bb") + assert ns["cc"] == Symbol("cc") + assert ns["zz"] == Symbol("zz") + assert ns["_x"] == Symbol("_x") + + v = eval("var(['d', 'e', 'fg'])", ns) + assert ns['d'] == Symbol('d') + assert ns['e'] == Symbol('e') + assert ns['fg'] == Symbol('fg') + +# check return value + assert v != ['d', 'e', 'fg'] + assert v == [Symbol('d'), Symbol('e'), Symbol('fg')] + + +def test_var_return(): + ns = {"var": var, "raises": raises} + "raises(ValueError, lambda: var(''))" + v2 = eval("var('q')", ns) + v3 = eval("var('q p')", ns) + + assert v2 == Symbol('q') + assert v3 == (Symbol('q'), Symbol('p')) + + +def test_var_accepts_comma(): + ns = {"var": var} + v1 = eval("var('x y z')", ns) + v2 = eval("var('x,y,z')", ns) + v3 = eval("var('x,y z')", ns) + + assert v1 == v2 + assert v1 == v3 + + +def test_var_keywords(): + ns = {"var": var} + eval("var('x y', real=True)", ns) + assert ns['x'].is_real and ns['y'].is_real + + +def test_var_cls(): + ns = {"var": var, "Function": Function} + eval("var('f', cls=Function)", ns) + + assert isinstance(ns['f'], FunctionClass) + + eval("var('g,h', cls=Function)", ns) + + assert isinstance(ns['g'], FunctionClass) + assert isinstance(ns['h'], FunctionClass) diff --git a/.venv/lib/python3.11/site-packages/sympy/crypto/__pycache__/crypto.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/crypto/__pycache__/crypto.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e98deae45ca0e4ce6bb8313386c308c1a2683f3 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/crypto/__pycache__/crypto.cpython-311.pyc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:854063ddd939b173a11d7d6b1d8ebdf2bab4d0791f068dbc82aec6ab155bb194 +size 118326 diff --git a/.venv/lib/python3.11/site-packages/sympy/simplify/__pycache__/hyperexpand.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/simplify/__pycache__/hyperexpand.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0ca8f85dbc1461f54dc280f346ff3c713afe19e5 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/simplify/__pycache__/hyperexpand.cpython-311.pyc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b39486e2957cfcbdf4164b6b74646481ca188ed7a034398dc75db3b26d360400 +size 149511 diff --git a/.venv/lib/python3.11/site-packages/sympy/simplify/tests/__pycache__/test_simplify.cpython-311.pyc b/.venv/lib/python3.11/site-packages/sympy/simplify/tests/__pycache__/test_simplify.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c15bb0cb3ea19e87719e3c68537b081890a03f51 --- /dev/null +++ b/.venv/lib/python3.11/site-packages/sympy/simplify/tests/__pycache__/test_simplify.cpython-311.pyc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5caed389b3575874d30d527d03f83b9532f91a7056b0658b9dbfa77fe5d11d2 +size 118475