Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/wapython
Path: blob/main/python/py-sympy/src/test_basic.py
1067 views
1
"""This tests sympy/core/basic.py with (ideally) no reference to subclasses
2
of Basic or Atom."""
3
4
import collections
5
6
from sympy.assumptions.ask import Q
7
from sympy.core.basic import (Basic, Atom, as_Basic,
8
_atomic, _aresame)
9
from sympy.core.containers import Tuple
10
from sympy.core.function import Function, Lambda
11
from sympy.core.numbers import I, pi
12
from sympy.core.singleton import S
13
from sympy.core.symbol import symbols, Symbol, Dummy
14
from sympy.concrete.summations import Sum
15
from sympy.functions.elementary.trigonometric import (cos, sin)
16
from sympy.functions.special.gamma_functions import gamma
17
from sympy.integrals.integrals import Integral
18
from sympy.functions.elementary.exponential import exp
19
from sympy.testing.pytest import raises
20
21
b1 = Basic()
22
b2 = Basic(b1)
23
b3 = Basic(b2)
24
b21 = Basic(b2, b1)
25
26
27
def test__aresame():
28
assert not _aresame(Basic(Tuple()), Basic())
29
assert not _aresame(Basic(S(2)), Basic(S(2.)))
30
31
32
def test_structure():
33
assert b21.args == (b2, b1)
34
assert b21.func(*b21.args) == b21
35
assert bool(b1)
36
37
38
def test_immutable():
39
assert not hasattr(b1, '__dict__')
40
with raises(AttributeError):
41
b1.x = 1
42
43
44
def test_equality():
45
instances = [b1, b2, b3, b21, Basic(b1, b1, b1), Basic]
46
for i, b_i in enumerate(instances):
47
for j, b_j in enumerate(instances):
48
assert (b_i == b_j) == (i == j)
49
assert (b_i != b_j) == (i != j)
50
51
assert Basic() != []
52
assert not(Basic() == [])
53
assert Basic() != 0
54
assert not(Basic() == 0)
55
56
class Foo:
57
"""
58
Class that is unaware of Basic, and relies on both classes returning
59
the NotImplemented singleton for equivalence to evaluate to False.
60
61
"""
62
63
b = Basic()
64
foo = Foo()
65
66
assert b != foo
67
assert foo != b
68
assert not b == foo
69
assert not foo == b
70
71
class Bar:
72
"""
73
Class that considers itself equal to any instance of Basic, and relies
74
on Basic returning the NotImplemented singleton in order to achieve
75
a symmetric equivalence relation.
76
77
"""
78
def __eq__(self, other):
79
if isinstance(other, Basic):
80
return True
81
return NotImplemented
82
83
def __ne__(self, other):
84
return not self == other
85
86
bar = Bar()
87
88
assert b == bar
89
assert bar == b
90
assert not b != bar
91
assert not bar != b
92
93
94
def test_matches_basic():
95
instances = [Basic(b1, b1, b2), Basic(b1, b2, b1), Basic(b2, b1, b1),
96
Basic(b1, b2), Basic(b2, b1), b2, b1]
97
for i, b_i in enumerate(instances):
98
for j, b_j in enumerate(instances):
99
if i == j:
100
assert b_i.matches(b_j) == {}
101
else:
102
assert b_i.matches(b_j) is None
103
assert b1.match(b1) == {}
104
105
106
def test_has():
107
assert b21.has(b1)
108
assert b21.has(b3, b1)
109
assert b21.has(Basic)
110
assert not b1.has(b21, b3)
111
assert not b21.has()
112
assert not b21.has(str)
113
assert not Symbol("x").has("x")
114
115
116
def test_subs():
117
assert b21.subs(b2, b1) == Basic(b1, b1)
118
assert b21.subs(b2, b21) == Basic(b21, b1)
119
assert b3.subs(b2, b1) == b2
120
121
assert b21.subs([(b2, b1), (b1, b2)]) == Basic(b2, b2)
122
123
assert b21.subs({b1: b2, b2: b1}) == Basic(b2, b2)
124
assert b21.subs(collections.ChainMap({b1: b2}, {b2: b1})) == Basic(b2, b2)
125
assert b21.subs(collections.OrderedDict([(b2, b1), (b1, b2)])) == Basic(b2, b2)
126
127
raises(ValueError, lambda: b21.subs('bad arg'))
128
raises(ValueError, lambda: b21.subs(b1, b2, b3))
129
# dict(b1=foo) creates a string 'b1' but leaves foo unchanged; subs
130
# will convert the first to a symbol but will raise an error if foo
131
# cannot be sympified; sympification is strict if foo is not string
132
raises(ValueError, lambda: b21.subs(b1='bad arg'))
133
134
assert Symbol("text").subs({"text": b1}) == b1
135
assert Symbol("s").subs({"s": 1}) == 1
136
137
138
def test_subs_with_unicode_symbols():
139
expr = Symbol('var1')
140
replaced = expr.subs('var1', 'x')
141
assert replaced.name == 'x'
142
143
replaced = expr.subs('var1', 'x')
144
assert replaced.name == 'x'
145
146
147
def test_atoms():
148
assert b21.atoms() == {Basic()}
149
150
151
def test_free_symbols_empty():
152
assert b21.free_symbols == set()
153
154
155
def test_doit():
156
assert b21.doit() == b21
157
assert b21.doit(deep=False) == b21
158
159
160
def test_S():
161
assert repr(S) == 'S'
162
163
164
def test_xreplace():
165
assert b21.xreplace({b2: b1}) == Basic(b1, b1)
166
assert b21.xreplace({b2: b21}) == Basic(b21, b1)
167
assert b3.xreplace({b2: b1}) == b2
168
assert Basic(b1, b2).xreplace({b1: b2, b2: b1}) == Basic(b2, b1)
169
assert Atom(b1).xreplace({b1: b2}) == Atom(b1)
170
assert Atom(b1).xreplace({Atom(b1): b2}) == b2
171
raises(TypeError, lambda: b1.xreplace())
172
raises(TypeError, lambda: b1.xreplace([b1, b2]))
173
for f in (exp, Function('f')):
174
assert f.xreplace({}) == f
175
assert f.xreplace({}, hack2=True) == f
176
assert f.xreplace({f: b1}) == b1
177
assert f.xreplace({f: b1}, hack2=True) == b1
178
179
180
def test_sorted_args():
181
x = symbols('x')
182
assert b21._sorted_args == b21.args
183
raises(AttributeError, lambda: x._sorted_args)
184
185
def test_call():
186
x, y = symbols('x y')
187
# See the long history of this in issues 5026 and 5105.
188
189
raises(TypeError, lambda: sin(x)({ x : 1, sin(x) : 2}))
190
raises(TypeError, lambda: sin(x)(1))
191
192
# No effect as there are no callables
193
assert sin(x).rcall(1) == sin(x)
194
assert (1 + sin(x)).rcall(1) == 1 + sin(x)
195
196
# Effect in the pressence of callables
197
l = Lambda(x, 2*x)
198
assert (l + x).rcall(y) == 2*y + x
199
assert (x**l).rcall(2) == x**4
200
# TODO UndefinedFunction does not subclass Expr
201
#f = Function('f')
202
#assert (2*f)(x) == 2*f(x)
203
204
assert (Q.real & Q.positive).rcall(x) == Q.real(x) & Q.positive(x)
205
206
207
def test_rewrite():
208
x, y, z = symbols('x y z')
209
a, b = symbols('a b')
210
f1 = sin(x) + cos(x)
211
assert f1.rewrite(cos,exp) == exp(I*x)/2 + sin(x) + exp(-I*x)/2
212
assert f1.rewrite([cos],sin) == sin(x) + sin(x + pi/2, evaluate=False)
213
f2 = sin(x) + cos(y)/gamma(z)
214
assert f2.rewrite(sin,exp) == -I*(exp(I*x) - exp(-I*x))/2 + cos(y)/gamma(z)
215
216
assert f1.rewrite() == f1
217
218
def test_literal_evalf_is_number_is_zero_is_comparable():
219
x = symbols('x')
220
f = Function('f')
221
222
# issue 5033
223
assert f.is_number is False
224
# issue 6646
225
assert f(1).is_number is False
226
i = Integral(0, (x, x, x))
227
# expressions that are symbolically 0 can be difficult to prove
228
# so in case there is some easy way to know if something is 0
229
# it should appear in the is_zero property for that object;
230
# if is_zero is true evalf should always be able to compute that
231
# zero
232
assert i.n() == 0
233
assert i.is_zero
234
assert i.is_number is False
235
assert i.evalf(2, strict=False) == 0
236
237
# issue 10268
238
n = sin(1)**2 + cos(1)**2 - 1
239
assert n.is_comparable is False
240
assert n.n(2).is_comparable is False
241
assert n.n(2).n(2).is_comparable
242
243
244
def test_as_Basic():
245
assert as_Basic(1) is S.One
246
assert as_Basic(()) == Tuple()
247
raises(TypeError, lambda: as_Basic([]))
248
249
250
def test_atomic():
251
g, h = map(Function, 'gh')
252
x = symbols('x')
253
assert _atomic(g(x + h(x))) == {g(x + h(x))}
254
assert _atomic(g(x + h(x)), recursive=True) == {h(x), x, g(x + h(x))}
255
assert _atomic(1) == set()
256
assert _atomic(Basic(S(1), S(2))) == set()
257
258
259
def test_as_dummy():
260
u, v, x, y, z, _0, _1 = symbols('u v x y z _0 _1')
261
assert Lambda(x, x + 1).as_dummy() == Lambda(_0, _0 + 1)
262
assert Lambda(x, x + _0).as_dummy() == Lambda(_1, _0 + _1)
263
eq = (1 + Sum(x, (x, 1, x)))
264
ans = 1 + Sum(_0, (_0, 1, x))
265
once = eq.as_dummy()
266
assert once == ans
267
twice = once.as_dummy()
268
assert twice == ans
269
assert Integral(x + _0, (x, x + 1), (_0, 1, 2)
270
).as_dummy() == Integral(_0 + _1, (_0, x + 1), (_1, 1, 2))
271
for T in (Symbol, Dummy):
272
d = T('x', real=True)
273
D = d.as_dummy()
274
assert D != d and D.func == Dummy and D.is_real is None
275
assert Dummy().as_dummy().is_commutative
276
assert Dummy(commutative=False).as_dummy().is_commutative is False
277
278
279
def test_canonical_variables():
280
x, i0, i1 = symbols('x _:2')
281
assert Integral(x, (x, x + 1)).canonical_variables == {x: i0}
282
assert Integral(x, (x, x + 1), (i0, 1, 2)).canonical_variables == {
283
x: i0, i0: i1}
284
assert Integral(x, (x, x + i0)).canonical_variables == {x: i1}
285
286
287
def test_replace_exceptions():
288
from sympy.core.symbol import Wild
289
x, y = symbols('x y')
290
e = (x**2 + x*y)
291
raises(TypeError, lambda: e.replace(sin, 2))
292
b = Wild('b')
293
c = Wild('c')
294
raises(TypeError, lambda: e.replace(b*c, c.is_real))
295
raises(TypeError, lambda: e.replace(b.is_real, 1))
296
raises(TypeError, lambda: e.replace(lambda d: d.is_Number, 1))
297
298
if __name__ == "__main__":
299
tests = [f for f in globals().keys() if f.startswith('test_')]
300
for f in tests:
301
globals()[f]()
302