"""This tests sympy/core/basic.py with (ideally) no reference to subclasses
of Basic or Atom."""
import collections
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
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
b1 = Basic()
b2 = Basic(b1)
b3 = Basic(b2)
b21 = Basic(b2, b1)
def test__aresame():
assert not _aresame(Basic(Tuple()), Basic())
assert not _aresame(Basic(S(2)), Basic(S(2.)))
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))
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')
raises(TypeError, lambda: sin(x)({ x : 1, sin(x) : 2}))
raises(TypeError, lambda: sin(x)(1))
assert sin(x).rcall(1) == sin(x)
assert (1 + sin(x)).rcall(1) == 1 + sin(x)
l = Lambda(x, 2*x)
assert (l + x).rcall(y) == 2*y + x
assert (x**l).rcall(2) == x**4
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')
assert f.is_number is False
assert f(1).is_number is False
i = Integral(0, (x, x, x))
assert i.n() == 0
assert i.is_zero
assert i.is_number is False
assert i.evalf(2, strict=False) == 0
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))
if __name__ == "__main__":
tests = [f for f in globals().keys() if f.startswith('test_')]
for f in tests:
globals()[f]()