-
Notifications
You must be signed in to change notification settings - Fork 62
/
test_mv.py
216 lines (177 loc) · 7.43 KB
/
test_mv.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
import distutils.version
import pytest
import sympy
from galgebra.ga import Ga
class TestMv:
def test_deprecations(self):
ga, e_1, e_2, e_3 = Ga.build('e*1|2|3')
with pytest.warns(DeprecationWarning):
ga.mv_x
with pytest.warns(DeprecationWarning):
ga.mv_I
def test_is_base(self):
"""
Various tests on several multivectors.
"""
_g3d, e_1, e_2, e_3 = Ga.build('e*1|2|3')
assert (e_1).is_base()
assert (e_2).is_base()
assert (e_3).is_base()
assert (e_1 ^ e_2).is_base()
assert (e_2 ^ e_3).is_base()
assert (e_1 ^ e_3).is_base()
assert (e_1 ^ e_2 ^ e_3).is_base()
assert not (2 * e_1).is_base()
assert not (e_1 + e_2).is_base()
assert not (e_3 * 4).is_base()
assert not ((3 * e_1) ^ e_2).is_base()
assert not (2 * (e_2 ^ e_3)).is_base()
assert not (e_3 ^ e_1).is_base()
assert not (e_2 ^ e_1 ^ e_3).is_base()
def test_get_coefs(self):
_g3d, e_1, e_2, e_3 = Ga.build('e*1|2|3')
assert (e_1 * 3 + e_3).get_coefs(1) == [3, 0, 1]
# can always get coefficients of 0
assert (0*e_1).get_coefs(0) == [0]
assert (0*e_1).get_coefs(1) == [0, 0, 0]
assert (0*e_1).get_coefs(2) == [0, 0, 0]
assert (0*e_1).get_coefs(3) == [0]
# grade is wrong
with pytest.raises(ValueError):
(e_1 ^ e_2).get_coefs(1)
with pytest.raises(ValueError):
(e_1 ^ e_2).get_coefs(3)
def test_blade_coefs(self):
"""
Various tests on several multivectors.
"""
_g3d, e_1, e_2, e_3 = Ga.build('e*1|2|3')
m0 = 2 * e_1 + e_2 - e_3 + 3 * (e_1 ^ e_3) + (e_1 ^ e_3) + (e_2 ^ (3 * e_3))
assert m0.blade_coefs([e_1]) == [2]
assert m0.blade_coefs([e_2]) == [1]
assert m0.blade_coefs([e_1, e_2]) == [2, 1]
assert m0.blade_coefs([e_1 ^ e_3]) == [4]
assert m0.blade_coefs([e_1 ^ e_3, e_2 ^ e_3]) == [4, 3]
assert m0.blade_coefs([e_2 ^ e_3, e_1 ^ e_3]) == [3, 4]
assert m0.blade_coefs([e_1, e_2 ^ e_3]) == [2, 3]
a = sympy.Symbol('a')
b = sympy.Symbol('b')
m1 = a * e_1 + e_2 - e_3 + b * (e_1 ^ e_2)
assert m1.blade_coefs([e_1]) == [a]
assert m1.blade_coefs([e_2]) == [1]
assert m1.blade_coefs([e_3]) == [-1]
assert m1.blade_coefs([e_1, e_2, e_3]) == [a, 1, -1]
assert m1.list() == [a, 1, -1] # alias
assert m1.blade_coefs([e_1 ^ e_2]) == [b]
assert m1.blade_coefs([e_2 ^ e_3]) == [0]
assert m1.blade_coefs([e_1 ^ e_3]) == [0]
assert m1.blade_coefs([e_1 ^ e_2 ^ e_3]) == [0]
# Invalid parameters
pytest.raises(ValueError, lambda: m1.blade_coefs([e_1 + e_2]))
pytest.raises(ValueError, lambda: m1.blade_coefs([e_2 ^ e_1]))
pytest.raises(ValueError, lambda: m1.blade_coefs([e_1, e_2 ^ e_1]))
pytest.raises(ValueError, lambda: m1.blade_coefs([a * e_1]))
pytest.raises(ValueError, lambda: m1.blade_coefs([3 * e_3]))
def test_rep_switching(self):
# this ga has a non-diagonal metric
_g3d, e_1, e_2, e_3 = Ga.build('e*1|2|3')
m0 = 2 * e_1 + e_2 - e_3 + 3 * (e_1 ^ e_3) + (e_1 ^ e_3) + (e_2 ^ (3 * e_3))
m1 = (-4*(e_1 | e_3)-3*(e_2 | e_3))+2*e_1+e_2-e_3+4*e_1*e_3+3*e_2*e_3
# m1 was chosen to make this true
assert m0 == m1
# all objects start off in blade rep
assert m0.is_blade_rep
# convert to base rep
m0_base = m0.base_rep()
assert m0.is_blade_rep # original should not change
assert not m0_base.is_blade_rep
assert m0 == m0_base
# convert back
m0_base_blade = m0_base.blade_rep()
assert not m0_base.is_blade_rep # original should not change
assert m0_base_blade.is_blade_rep
assert m0 == m0_base_blade
def test_construction(self):
ga, e_1, e_2, e_3 = Ga.build('e*1|2|3')
def check(x, expected_grades):
assert x.grades == expected_grades
assert x != 0
# non-function symbol construction
check(ga.mv('A', 'scalar'), [0])
check(ga.mv('A', 'grade', 0), [0])
check(ga.mv('A', 0), [0])
check(ga.mv('A', 'vector'), [1])
check(ga.mv('A', 'grade', 1), [1])
check(ga.mv('A', 1), [1])
check(ga.mv('A', 'bivector'), [2])
check(ga.mv('A', 'grade2'), [2])
check(ga.mv('A', 2), [2])
check(ga.mv('A', 'pseudo'), [3])
check(ga.mv('A', 'spinor'), [0, 2])
check(ga.mv('A', 'even'), [0, 2])
check(ga.mv('A', 'odd'), [1, 3])
check(ga.mv('A', 'mv'), [0, 1, 2, 3])
# value construction
check(ga.mv([1, 2, 3], 'vector'), [1])
# illegal arguments
with pytest.raises(TypeError):
ga.mv('A', 'vector', "too many arguments")
with pytest.raises(TypeError):
ga.mv('A', 'grade') # too few arguments
with pytest.raises(TypeError):
ga.mv('A', 'grade', not_an_argument=True) # invalid kwarg
with pytest.raises(TypeError):
ga.mv([1, 2, 3], 'vector', f=True) # can't pass f with coefficients
def test_abs(self):
ga, e_1, e_2, e_3 = Ga.build('e*1|2|3', g=[1, 1, 1])
B = ga.mv('B', 'bivector')
assert abs(B*B) == -(B*B).scalar()
def test_hashable(self):
ga, e_1, e_2, e_3 = Ga.build('e*1|2|3')
d = {}
d[e_1] = 1
d[e_2] = 2
assert d[e_1 + 0] == 1
d[10] = 3 # note: not a multivector key!
assert d[e_1 * 0 + 10] == 3
def test_subs(self):
ga, e_1, e_2, e_3 = Ga.build('e*1|2|3', g=[1, 1, 1])
B = ga.mv('B', 'bivector')
B_inv = B.inv()
B_mag = sympy.Symbol('|B|')
# both of the sympy subs syntaxes work:
assert (-B / B_mag**2).subs(B_mag, abs(B)) == B_inv
assert (-B / B_mag**2).subs({B_mag: abs(B)}) == B_inv
def test_sympify(self):
ga, e_1, e_2, e_3 = Ga.build('e*1|2|3', g=[1, 1, 1])
# Letting this succeed silently and not return an Mv instance would be
# dangerous.
with pytest.raises(sympy.SympifyError):
sympy.sympify(e_1)
# this is fine
sympy.sympify(e_1.obj)
def test_arithmetic(self):
ga, e_1, e_2, e_3 = Ga.build('e*1|2|3', g=[1, 1, 1])
one = ga.mv(sympy.S.One)
# test that scalars are promoted to Mvs correctly
assert e_1 + 1 == e_1 + one
assert 1 + e_1 == one + e_1
assert e_1 - 1 == e_1 - one
assert 1 - e_1 == one - e_1
@pytest.mark.parametrize('make_one', [
lambda ga: 1,
lambda ga: ga.mv(sympy.S.One),
pytest.param(lambda ga: sympy.S.One, marks=pytest.mark.skipif(
distutils.version.LooseVersion(sympy.__version__) < "1.6",
# until sympy/sympy@bec42df53cf2486d485065ddad1c31011a48bf3b
reason="Cannot override < and > on sympy.Expr"
))
])
def test_contraction(self, make_one):
ga, e_1, e_2 = Ga.build('e*1|2', g=[1, 1])
e12 = e_1 ^ e_2
one = make_one(ga)
assert (one < e12) == e12
assert (e12 > one) == e12
assert (e12 < one) == 0
assert (one > e12) == 0