Commutation 1.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ from .expression import Expression, Term, Operator, Scalar
2
+ from .commutatoralgebra import \
3
+ AntiCommutatorUnknownException, AntiCommutatorAlgebra, \
4
+ CommutatorAlgebra, CommutatorUnknownException
5
+ from .style import show
@@ -0,0 +1,248 @@
1
+ from .expression import Operator, Term, Expression
2
+ from warnings import warn
3
+
4
+ class CommutatorUnknownException(Exception):
5
+ def __init__(self, o1, o2):
6
+ super().__init__(f"commutator algebra does not know [{o1}, {o2}]_-")
7
+
8
+
9
+ class AntiCommutatorUnknownException(Exception):
10
+ def __init__(self, o1, o2):
11
+ super().__init__(f"anticommutator algebra does not know [{o1}, {o2}]_+")
12
+
13
+ class AbstractCommutatorAlgebra:
14
+ def __init__(self, strict=False):
15
+ self.strict = strict
16
+ self.relations = {}
17
+
18
+
19
+ def _add_operator(self, op, default_self, default_rel):
20
+ assert isinstance(op, Operator)
21
+ s = str(op)
22
+
23
+ if s not in self.relations:
24
+ col = {}
25
+ for k in self.relations:
26
+ self.relations[k][s] = default_rel
27
+ col[k] = default_rel
28
+
29
+ col[s] = default_self
30
+ self.relations[s] = col
31
+
32
+
33
+ def _move_right(self, r_mover, expr:Expression, A):
34
+ assert isinstance(A, Operator)
35
+
36
+ # Strategy: Go through each term in self.terms
37
+ # Within each term's operator list, iteratively keep moving it up in index using the elementary operation
38
+ # AB -> BA + [A, B]
39
+ # repeat until done
40
+ # expr = Expression(expr)
41
+
42
+ if A.name not in expr.operators:
43
+ return expr
44
+
45
+ extra_terms = Expression()
46
+ for term in expr.terms:
47
+ indices = reversed(term.findall(A))
48
+
49
+ for I in indices:
50
+ for i in range(I, len(term.ops) - 1):
51
+ assert term.ops[i] == A
52
+ extra_terms += r_mover(term, i)
53
+
54
+ self._move_right(r_mover, extra_terms, A)
55
+ expr.terms += extra_terms.terms
56
+ expr.collect()
57
+
58
+
59
+ def _move_left(self, l_mover, expr:Expression, A):
60
+ '''
61
+ Moves all instances of the operator 'A' to the left of the expression.
62
+ '''
63
+ assert isinstance(A, Operator)
64
+
65
+ # # Strategy: Go through each term in self.terms
66
+ # # Within each term's operator list, iteratively keep moving it up in index using the elementary operation
67
+ # # AB -> BA + [A, B]
68
+ if A.name not in expr.operators:
69
+ return expr
70
+
71
+ extra_terms = Expression()
72
+ for term in expr.terms:
73
+ indices = term.findall(A)
74
+ for I in indices:
75
+ for i in range(I, 0, -1):
76
+ assert term.ops[i] == A
77
+ extra_terms += l_mover(term, i)
78
+
79
+ self._move_left(l_mover, extra_terms, A)
80
+ expr.terms += extra_terms.terms
81
+ expr.collect()
82
+
83
+
84
+
85
+
86
+ class CommutatorAlgebra(AbstractCommutatorAlgebra):
87
+ def add_operator(self, op):
88
+ if self.strict:
89
+ self._add_operator(op, 0, None)
90
+ else:
91
+ self._add_operator(op, 0, 0)
92
+
93
+ def set_commutator(self, l_op, r_op):
94
+ assert isinstance(l_op, Operator)
95
+ assert isinstance(r_op, Operator)
96
+ l = l_op.name
97
+ r = r_op.name
98
+
99
+ if l not in self.relations:
100
+ self.add_operator(l_op)
101
+ if r not in self.relations:
102
+ self.add_operator(r_op)
103
+
104
+ def setter(rhs):
105
+ rel = Expression(rhs) if rhs is not None else None
106
+ if l == r:
107
+ s = 'Setting [%s, %s] to something other than default (0) ... are you sure?' % (l, r)
108
+ warn(s)
109
+ if rel is None:
110
+ self.relations[l][r] = None
111
+ self.relations[r][l] = None
112
+ else:
113
+ self.relations[l][r] = rel
114
+ self.relations[r][l] = -rel
115
+
116
+ return setter
117
+
118
+ def get_commutator(self, l: Operator, r: Operator):
119
+ assert isinstance(l, Operator)
120
+ assert isinstance(r, Operator)
121
+ if l.is_scalar or r.is_scalar:
122
+ return 0
123
+ elif l.name not in self.relations:
124
+ s = 'Non-scalar operator "' + \
125
+ str(l)+'" is not in the commutator database, assuming it commutes...'
126
+ if self.strict:
127
+ raise CommutatorUnknownException(l, r)
128
+ else:
129
+ warn(s)
130
+ return 0
131
+ elif r.name not in self.relations:
132
+ s = 'Non-scalar operator "' + \
133
+ str(r)+'" is not in the commutator database, assuming it commutes...'
134
+ if self.strict:
135
+ raise CommutatorUnknownException(l, r)
136
+ else:
137
+ warn(s)
138
+ return 0
139
+ else:
140
+ return self.relations[l.name][r.name]
141
+
142
+
143
+ def _move_operator_right_once(self, term:Term, i):
144
+ front = Term(*term.ops[:i])
145
+ back = Term(*term.ops[i+2:])
146
+
147
+ c = self.get_commutator(term.ops[i], term.ops[i+1])
148
+ extra = front * c * back * term.multiplier
149
+
150
+ term.ops[i], term.ops[i+1] = term.ops[i+1], term.ops[i]
151
+ return extra
152
+
153
+
154
+ def _move_operator_left_once(self, term:Term, i, use_commutator=True):
155
+ A = term.ops[i]
156
+ B = term.ops[i-1]
157
+ front = Term(*term.ops[:i-1])
158
+ back = Term(*term.ops[i+1:])
159
+
160
+ c = self.get_commutator(A, B)
161
+ extra = front * c * back * term.multiplier
162
+
163
+ term.ops[i-1], term.ops[i] = term.ops[i], term.ops[i-1]
164
+ return extra
165
+
166
+ def move_right(self, expr:Expression, A):
167
+ self._move_right(self._move_operator_right_once, expr, A)
168
+
169
+ def move_left(self, expr:Expression, A):
170
+ self._move_left(self._move_operator_left_once, expr, A)
171
+
172
+
173
+
174
+ class AntiCommutatorAlgebra(AbstractCommutatorAlgebra):
175
+ def add_operator(self, op):
176
+ if self.strict:
177
+ self._add_operator(op, 2*op, None)
178
+ else:
179
+ self._add_operator(op, 2*op, None)
180
+
181
+ def set_anticommutator(self, l_op, r_op):
182
+ assert isinstance(l_op, Operator)
183
+ assert isinstance(r_op, Operator)
184
+ l = l_op.name
185
+ r = r_op.name
186
+
187
+ if l not in self.relations:
188
+ self.add_operator(l_op)
189
+ if r not in self.relations:
190
+ self.add_operator(r_op)
191
+
192
+ def setter(rhs):
193
+ rel = Expression(rhs) if rhs is not None else None
194
+ if l == r:
195
+ s = 'Setting {%s, %s} to something other than default (2%s) ... are you sure?' % (l, l, l)
196
+ warn(s)
197
+ self.relations[l][r] = rel
198
+ self.relations[r][l] = rel
199
+
200
+ return setter
201
+
202
+ def get_anticommutator(self, l, r):
203
+ assert isinstance(l, Operator)
204
+ assert isinstance(r, Operator)
205
+ if l.is_scalar or r.is_scalar:
206
+ return None # no Grassman for you
207
+ elif not (l.name in self.relations and r.name in self.relations):
208
+ return None # idk how to commute this
209
+ else:
210
+ return self.relations[l.name][r.name]
211
+
212
+
213
+
214
+ def _move_operator_right_once(self, term:Term, i):
215
+ front = Term(*term.ops[:i])
216
+ back = Term(*term.ops[i+2:])
217
+
218
+ c = self.get_anticommutator(
219
+ term.ops[i], term.ops[i+1])
220
+ extra = Expression(front) * \
221
+ c * Expression(back)*term.multiplier
222
+ term.multiplier *= -1
223
+
224
+ term.ops[i], term.ops[i+1] = term.ops[i+1], term.ops[i]
225
+ return extra
226
+
227
+
228
+ def _move_operator_left_once(self, term:Term, i):
229
+ A = term.ops[i]
230
+ B = term.ops[i-1]
231
+ front = Term(*term.ops[:i-1])
232
+ back = Term(*term.ops[i+1:])
233
+
234
+ c = self.get_anticommutator(A, B)
235
+ if c is None:
236
+ raise AntiCommutatorUnknownException(A, B)
237
+ extra = Expression(front) * c * Expression(back) * term.multiplier
238
+ term.multiplier *= -1
239
+
240
+ term.ops[i-1], term.ops[i] = term.ops[i], term.ops[i-1]
241
+ return extra
242
+
243
+ def move_right(self, expr:Expression, A):
244
+ self._move_right(self._move_operator_right_once, expr, A)
245
+
246
+ def move_left(self, expr:Expression, A):
247
+ self._move_left(self._move_operator_left_once, expr, A)
248
+