schubmult 2.0.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.
- schubmult/__init__.py +1 -0
- schubmult/_base_argparse.py +174 -0
- schubmult/perm_lib.py +999 -0
- schubmult/sage_integration/__init__.py +25 -0
- schubmult/sage_integration/_fast_double_schubert_polynomial_ring.py +528 -0
- schubmult/sage_integration/_fast_schubert_polynomial_ring.py +356 -0
- schubmult/sage_integration/_indexing.py +44 -0
- schubmult/schubmult_double/__init__.py +18 -0
- schubmult/schubmult_double/__main__.py +5 -0
- schubmult/schubmult_double/_funcs.py +1590 -0
- schubmult/schubmult_double/_script.py +407 -0
- schubmult/schubmult_double/_vars.py +16 -0
- schubmult/schubmult_py/__init__.py +10 -0
- schubmult/schubmult_py/__main__.py +5 -0
- schubmult/schubmult_py/_funcs.py +111 -0
- schubmult/schubmult_py/_script.py +115 -0
- schubmult/schubmult_py/_vars.py +3 -0
- schubmult/schubmult_q/__init__.py +12 -0
- schubmult/schubmult_q/__main__.py +5 -0
- schubmult/schubmult_q/_funcs.py +304 -0
- schubmult/schubmult_q/_script.py +157 -0
- schubmult/schubmult_q/_vars.py +18 -0
- schubmult/schubmult_q_double/__init__.py +14 -0
- schubmult/schubmult_q_double/__main__.py +5 -0
- schubmult/schubmult_q_double/_funcs.py +507 -0
- schubmult/schubmult_q_double/_script.py +337 -0
- schubmult/schubmult_q_double/_vars.py +21 -0
- schubmult-2.0.0.dist-info/METADATA +455 -0
- schubmult-2.0.0.dist-info/RECORD +36 -0
- schubmult-2.0.0.dist-info/WHEEL +5 -0
- schubmult-2.0.0.dist-info/entry_points.txt +5 -0
- schubmult-2.0.0.dist-info/licenses/LICENSE +674 -0
- schubmult-2.0.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/test_fast_double_schubert.py +145 -0
- tests/test_fast_schubert.py +38 -0
@@ -0,0 +1,507 @@
|
|
1
|
+
from ._vars import (
|
2
|
+
var_y,
|
3
|
+
var_x,
|
4
|
+
var2,
|
5
|
+
var3,
|
6
|
+
q_var2,
|
7
|
+
)
|
8
|
+
from symengine import Add, Mul, Pow, expand
|
9
|
+
from schubmult.perm_lib import (
|
10
|
+
elem_sym_perms_q,
|
11
|
+
add_perm_dict,
|
12
|
+
compute_vpathdicts,
|
13
|
+
inverse,
|
14
|
+
strict_theta,
|
15
|
+
medium_theta,
|
16
|
+
permtrim,
|
17
|
+
inv,
|
18
|
+
mulperm,
|
19
|
+
uncode,
|
20
|
+
double_elem_sym_q,
|
21
|
+
elem_sym_poly_q,
|
22
|
+
elem_sym_perms_q_op,
|
23
|
+
elem_sym_func_q,
|
24
|
+
call_zvars,
|
25
|
+
q_var,
|
26
|
+
)
|
27
|
+
import schubmult.schubmult_double as norm_yz
|
28
|
+
|
29
|
+
|
30
|
+
def E(p, k, varl=var_y[1:]):
|
31
|
+
return elem_sym_poly_q(p, k, var_x[1:], varl)
|
32
|
+
|
33
|
+
|
34
|
+
def single_variable(coeff_dict, varnum, var2=var2, q_var=q_var):
|
35
|
+
ret = {}
|
36
|
+
for u in coeff_dict:
|
37
|
+
if varnum - 1 < len(u):
|
38
|
+
ret[u] = ret.get(u, 0) + var2[u[varnum - 1]] * coeff_dict[u]
|
39
|
+
else:
|
40
|
+
ret[u] = ret.get(u, 0) + var2[varnum] * coeff_dict[u]
|
41
|
+
new_perms_k = elem_sym_perms_q(u, 1, varnum, q_var)
|
42
|
+
new_perms_km1 = []
|
43
|
+
if varnum > 1:
|
44
|
+
new_perms_km1 = elem_sym_perms_q(u, 1, varnum - 1, q_var)
|
45
|
+
for perm, udiff, mul_val in new_perms_k:
|
46
|
+
if udiff == 1:
|
47
|
+
ret[perm] = ret.get(perm, 0) + coeff_dict[u] * mul_val
|
48
|
+
for perm, udiff, mul_val in new_perms_km1:
|
49
|
+
if udiff == 1:
|
50
|
+
ret[perm] = ret.get(perm, 0) - coeff_dict[u] * mul_val
|
51
|
+
return ret
|
52
|
+
|
53
|
+
|
54
|
+
def mult_poly(coeff_dict, poly, var_x=var_x, var_y=var_y, q_var=q_var):
|
55
|
+
if poly in var_x:
|
56
|
+
return single_variable(coeff_dict, var_x.index(poly), var_y, q_var)
|
57
|
+
elif isinstance(poly, Mul):
|
58
|
+
ret = coeff_dict
|
59
|
+
for a in poly.args:
|
60
|
+
ret = mult_poly(ret, a, var_x, var_y, q_var)
|
61
|
+
return ret
|
62
|
+
elif isinstance(poly, Pow):
|
63
|
+
base = poly.args[0]
|
64
|
+
exponent = int(poly.args[1])
|
65
|
+
ret = coeff_dict
|
66
|
+
for i in range(int(exponent)):
|
67
|
+
ret = mult_poly(ret, base, var_x, var_y, q_var)
|
68
|
+
return ret
|
69
|
+
elif isinstance(poly, Add):
|
70
|
+
ret = {}
|
71
|
+
for a in poly.args:
|
72
|
+
ret = add_perm_dict(ret, mult_poly(coeff_dict, a, var_x, var_y, q_var))
|
73
|
+
return ret
|
74
|
+
else:
|
75
|
+
ret = {}
|
76
|
+
for perm in coeff_dict:
|
77
|
+
ret[perm] = poly * coeff_dict[perm]
|
78
|
+
return ret
|
79
|
+
|
80
|
+
|
81
|
+
def nil_hecke(perm_dict, v, n, var2=var2, var3=var3):
|
82
|
+
if v == (1, 2):
|
83
|
+
return perm_dict
|
84
|
+
th = strict_theta(inverse(v))
|
85
|
+
mu = permtrim(uncode(th))
|
86
|
+
vmu = permtrim(mulperm([*v], mu))
|
87
|
+
|
88
|
+
ret_dict = {}
|
89
|
+
while th[-1] == 0:
|
90
|
+
th.pop()
|
91
|
+
thL = len(th)
|
92
|
+
vpathdicts = compute_vpathdicts(th, vmu, True)
|
93
|
+
for u, val in perm_dict.items():
|
94
|
+
vpathsums = {u: {(1, 2): val}}
|
95
|
+
for index in range(thL):
|
96
|
+
mx_th = 0
|
97
|
+
for vp in vpathdicts[index]:
|
98
|
+
for v2, vdiff, s in vpathdicts[index][vp]:
|
99
|
+
if th[index] - vdiff > mx_th:
|
100
|
+
mx_th = th[index] - vdiff
|
101
|
+
newpathsums = {}
|
102
|
+
for up in vpathsums:
|
103
|
+
newperms = elem_sym_perms_q_op(up, mx_th, th[index], n)
|
104
|
+
for up2, udiff, mul_val in newperms:
|
105
|
+
if up2 not in newpathsums:
|
106
|
+
newpathsums[up2] = {}
|
107
|
+
for v in vpathdicts[index]:
|
108
|
+
sumval = vpathsums[up].get(v, 0) * mul_val
|
109
|
+
if sumval == 0:
|
110
|
+
continue
|
111
|
+
for v2, vdiff, s in vpathdicts[index][v]:
|
112
|
+
newpathsums[up2][v2] = newpathsums[up2].get(
|
113
|
+
v2, 0
|
114
|
+
) + s * sumval * elem_sym_func_q(
|
115
|
+
th[index],
|
116
|
+
index + 1,
|
117
|
+
up2,
|
118
|
+
up,
|
119
|
+
v,
|
120
|
+
v2,
|
121
|
+
udiff,
|
122
|
+
vdiff,
|
123
|
+
var2,
|
124
|
+
var3,
|
125
|
+
)
|
126
|
+
vpathsums = newpathsums
|
127
|
+
toget = tuple(vmu)
|
128
|
+
ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
|
129
|
+
return ret_dict
|
130
|
+
|
131
|
+
|
132
|
+
def elem_sym_func_q_q(k, i, u1, u2, v1, v2, udiff, vdiff, varl1, varl2, q_var=q_var):
|
133
|
+
newk = k - udiff
|
134
|
+
if newk < vdiff:
|
135
|
+
return 0
|
136
|
+
if newk == vdiff:
|
137
|
+
return 1
|
138
|
+
yvars = []
|
139
|
+
mlen = max(len(u1), len(u2))
|
140
|
+
u1 = [*u1] + [a + 1 for a in range(len(u1), mlen)]
|
141
|
+
u2 = [*u2] + [a + 1 for a in range(len(u2), mlen)]
|
142
|
+
for j in range(min(len(u1), k)):
|
143
|
+
if u1[j] == u2[j]:
|
144
|
+
yvars += [varl1[u2[j]]]
|
145
|
+
for j in range(len(u1), min(k, len(u2))):
|
146
|
+
if u2[j] == j + 1:
|
147
|
+
yvars += [varl1[u2[j]]]
|
148
|
+
for j in range(len(u2), k):
|
149
|
+
yvars += [varl1[j + 1]]
|
150
|
+
zvars = [varl2[a] for a in call_zvars(v1, v2, k, i)]
|
151
|
+
return elem_sym_poly_q(newk - vdiff, newk, yvars, zvars, q_var)
|
152
|
+
|
153
|
+
|
154
|
+
def schubpoly_quantum(v, var_x=var_x, var_y=var2, q_var=q_var, coeff=1):
|
155
|
+
th = strict_theta(inverse(v))
|
156
|
+
mu = permtrim(uncode(th))
|
157
|
+
vmu = permtrim(mulperm([*v], mu))
|
158
|
+
if len(th) == 0:
|
159
|
+
return coeff
|
160
|
+
while th[-1] == 0:
|
161
|
+
th.pop()
|
162
|
+
vpathdicts = compute_vpathdicts(th, vmu)
|
163
|
+
vpathsums = {(1, 2): {(1, 2): coeff}}
|
164
|
+
inv_mu = inv(mu)
|
165
|
+
inv_vmu = inv(vmu)
|
166
|
+
inv_u = 0
|
167
|
+
ret_dict = {}
|
168
|
+
for index in range(len(th)):
|
169
|
+
mx_th = 0
|
170
|
+
for vp in vpathdicts[index]:
|
171
|
+
for v2, vdiff, s in vpathdicts[index][vp]:
|
172
|
+
if th[index] - vdiff > mx_th:
|
173
|
+
mx_th = th[index] - vdiff
|
174
|
+
newpathsums = {}
|
175
|
+
for up in vpathsums:
|
176
|
+
inv_up = inv(up)
|
177
|
+
newperms = elem_sym_perms_q(
|
178
|
+
up, min(mx_th, (inv_mu - (inv_up - inv_u)) - inv_vmu), th[index], q_var
|
179
|
+
)
|
180
|
+
for up2, udiff, mul_val in newperms:
|
181
|
+
if up2 not in newpathsums:
|
182
|
+
newpathsums[up2] = {}
|
183
|
+
for v in vpathdicts[index]:
|
184
|
+
sumval = vpathsums[up].get(v, 0) * mul_val
|
185
|
+
if sumval == 0:
|
186
|
+
continue
|
187
|
+
for v2, vdiff, s in vpathdicts[index][v]:
|
188
|
+
newpathsums[up2][v2] = newpathsums[up2].get(
|
189
|
+
v2, 0
|
190
|
+
) + s * sumval * elem_sym_func_q_q(
|
191
|
+
th[index],
|
192
|
+
index + 1,
|
193
|
+
up,
|
194
|
+
up2,
|
195
|
+
v,
|
196
|
+
v2,
|
197
|
+
udiff,
|
198
|
+
vdiff,
|
199
|
+
var_x,
|
200
|
+
var_y,
|
201
|
+
q_var,
|
202
|
+
)
|
203
|
+
vpathsums = newpathsums
|
204
|
+
toget = tuple(vmu)
|
205
|
+
ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
|
206
|
+
return ret_dict[(1, 2)]
|
207
|
+
|
208
|
+
|
209
|
+
def schubmult(perm_dict, v, var2=var2, var3=var3, q_var=q_var):
|
210
|
+
if v == (1, 2):
|
211
|
+
return perm_dict
|
212
|
+
th = strict_theta(inverse(v))
|
213
|
+
mu = permtrim(uncode(th))
|
214
|
+
vmu = permtrim(mulperm([*v], mu))
|
215
|
+
inv_vmu = inv(vmu)
|
216
|
+
inv_mu = inv(mu)
|
217
|
+
ret_dict = {}
|
218
|
+
if len(th) == 0:
|
219
|
+
return perm_dict
|
220
|
+
while th[-1] == 0:
|
221
|
+
th.pop()
|
222
|
+
thL = len(th)
|
223
|
+
vpathdicts = compute_vpathdicts(th, vmu, True)
|
224
|
+
for u, val in perm_dict.items():
|
225
|
+
inv_u = inv(u)
|
226
|
+
vpathsums = {u: {(1, 2): val}}
|
227
|
+
for index in range(thL):
|
228
|
+
mx_th = 0
|
229
|
+
for vp in vpathdicts[index]:
|
230
|
+
for v2, vdiff, s in vpathdicts[index][vp]:
|
231
|
+
if th[index] - vdiff > mx_th:
|
232
|
+
mx_th = th[index] - vdiff
|
233
|
+
newpathsums = {}
|
234
|
+
for up in vpathsums:
|
235
|
+
inv_up = inv(up)
|
236
|
+
newperms = elem_sym_perms_q(
|
237
|
+
up,
|
238
|
+
min(mx_th, (inv_mu - (inv_up - inv_u)) - inv_vmu),
|
239
|
+
th[index],
|
240
|
+
q_var,
|
241
|
+
)
|
242
|
+
for up2, udiff, mul_val in newperms:
|
243
|
+
if up2 not in newpathsums:
|
244
|
+
newpathsums[up2] = {}
|
245
|
+
for v in vpathdicts[index]:
|
246
|
+
sumval = vpathsums[up].get(v, 0) * mul_val
|
247
|
+
if sumval == 0:
|
248
|
+
continue
|
249
|
+
for v2, vdiff, s in vpathdicts[index][v]:
|
250
|
+
newpathsums[up2][v2] = newpathsums[up2].get(
|
251
|
+
v2, 0
|
252
|
+
) + s * sumval * elem_sym_func_q(
|
253
|
+
th[index],
|
254
|
+
index + 1,
|
255
|
+
up,
|
256
|
+
up2,
|
257
|
+
v,
|
258
|
+
v2,
|
259
|
+
udiff,
|
260
|
+
vdiff,
|
261
|
+
var2,
|
262
|
+
var3,
|
263
|
+
)
|
264
|
+
vpathsums = newpathsums
|
265
|
+
toget = tuple(vmu)
|
266
|
+
ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
|
267
|
+
return ret_dict
|
268
|
+
|
269
|
+
|
270
|
+
def schubmult_db(perm_dict, v, var2=var2, var3=var3, q_var=q_var):
|
271
|
+
if v == (1, 2):
|
272
|
+
return perm_dict
|
273
|
+
th = medium_theta(inverse(v))
|
274
|
+
if len(th) == 0:
|
275
|
+
return perm_dict
|
276
|
+
while th[-1] == 0:
|
277
|
+
th.pop()
|
278
|
+
mu = permtrim(uncode(th))
|
279
|
+
vmu = permtrim(mulperm([*v], mu))
|
280
|
+
inv_vmu = inv(vmu)
|
281
|
+
inv_mu = inv(mu)
|
282
|
+
ret_dict = {}
|
283
|
+
|
284
|
+
thL = len(th)
|
285
|
+
vpathdicts = compute_vpathdicts(th, vmu, True)
|
286
|
+
for u, val in perm_dict.items():
|
287
|
+
inv_u = inv(u)
|
288
|
+
vpathsums = {u: {(1, 2): val}}
|
289
|
+
for index in range(thL):
|
290
|
+
if index > 0 and th[index - 1] == th[index]:
|
291
|
+
continue
|
292
|
+
mx_th = 0
|
293
|
+
for vp in vpathdicts[index]:
|
294
|
+
for v2, vdiff, s in vpathdicts[index][vp]:
|
295
|
+
if th[index] - vdiff > mx_th:
|
296
|
+
mx_th = th[index] - vdiff
|
297
|
+
if index < len(th) - 1 and th[index] == th[index + 1]:
|
298
|
+
mx_th1 = 0
|
299
|
+
for vp in vpathdicts[index + 1]:
|
300
|
+
for v2, vdiff, s in vpathdicts[index + 1][vp]:
|
301
|
+
if th[index + 1] - vdiff > mx_th1:
|
302
|
+
mx_th1 = th[index + 1] - vdiff
|
303
|
+
newpathsums = {}
|
304
|
+
for up in vpathsums:
|
305
|
+
newpathsums0 = {}
|
306
|
+
inv_up = inv(up)
|
307
|
+
newperms = double_elem_sym_q(up, mx_th, mx_th1, th[index], q_var)
|
308
|
+
for v in vpathdicts[index]:
|
309
|
+
sumval = vpathsums[up].get(v, 0)
|
310
|
+
if sumval == 0:
|
311
|
+
continue
|
312
|
+
for v2, vdiff2, s2 in vpathdicts[index][v]:
|
313
|
+
for up1, udiff1, mul_val1 in newperms:
|
314
|
+
esim1 = (
|
315
|
+
elem_sym_func_q(
|
316
|
+
th[index],
|
317
|
+
index + 1,
|
318
|
+
up,
|
319
|
+
up1,
|
320
|
+
v,
|
321
|
+
v2,
|
322
|
+
udiff1,
|
323
|
+
vdiff2,
|
324
|
+
var2,
|
325
|
+
var3,
|
326
|
+
)
|
327
|
+
* mul_val1
|
328
|
+
* s2
|
329
|
+
)
|
330
|
+
mulfac = sumval * esim1
|
331
|
+
if (up1, udiff1, mul_val1) not in newpathsums0:
|
332
|
+
newpathsums0[(up1, udiff1, mul_val1)] = {}
|
333
|
+
# newpathsums0[(up1, udiff1, mul_val1
|
334
|
+
newpathsums0[(up1, udiff1, mul_val1)][v2] = (
|
335
|
+
newpathsums0[(up1, udiff1, mul_val1)].get(v2, 0) + mulfac
|
336
|
+
)
|
337
|
+
|
338
|
+
for up1, udiff1, mul_val1 in newpathsums0:
|
339
|
+
for v in vpathdicts[index + 1]:
|
340
|
+
sumval = newpathsums0[(up1, udiff1, mul_val1)].get(v, 0)
|
341
|
+
if sumval == 0:
|
342
|
+
continue
|
343
|
+
for v2, vdiff2, s2 in vpathdicts[index + 1][v]:
|
344
|
+
for up2, udiff2, mul_val2 in newperms[(up1, udiff1, mul_val1)]:
|
345
|
+
esim1 = (
|
346
|
+
elem_sym_func_q(
|
347
|
+
th[index + 1],
|
348
|
+
index + 2,
|
349
|
+
up1,
|
350
|
+
up2,
|
351
|
+
v,
|
352
|
+
v2,
|
353
|
+
udiff2,
|
354
|
+
vdiff2,
|
355
|
+
var2,
|
356
|
+
var3,
|
357
|
+
)
|
358
|
+
* mul_val2
|
359
|
+
* s2
|
360
|
+
)
|
361
|
+
mulfac = sumval * esim1
|
362
|
+
if up2 not in newpathsums:
|
363
|
+
newpathsums[up2] = {}
|
364
|
+
newpathsums[up2][v2] = newpathsums[up2].get(v2, 0) + mulfac
|
365
|
+
else:
|
366
|
+
newpathsums = {}
|
367
|
+
for up in vpathsums:
|
368
|
+
inv_up = inv(up)
|
369
|
+
newperms = elem_sym_perms_q(
|
370
|
+
up,
|
371
|
+
min(mx_th, (inv_mu - (inv_up - inv_u)) - inv_vmu),
|
372
|
+
th[index],
|
373
|
+
q_var,
|
374
|
+
)
|
375
|
+
for up2, udiff, mul_val in newperms:
|
376
|
+
if up2 not in newpathsums:
|
377
|
+
newpathsums[up2] = {}
|
378
|
+
for v in vpathdicts[index]:
|
379
|
+
sumval = vpathsums[up].get(v, 0) * mul_val
|
380
|
+
if sumval == 0:
|
381
|
+
continue
|
382
|
+
for v2, vdiff, s in vpathdicts[index][v]:
|
383
|
+
newpathsums[up2][v2] = newpathsums[up2].get(
|
384
|
+
v2, 0
|
385
|
+
) + s * sumval * elem_sym_func_q(
|
386
|
+
th[index],
|
387
|
+
index + 1,
|
388
|
+
up,
|
389
|
+
up2,
|
390
|
+
v,
|
391
|
+
v2,
|
392
|
+
udiff,
|
393
|
+
vdiff,
|
394
|
+
var2,
|
395
|
+
var3,
|
396
|
+
)
|
397
|
+
vpathsums = newpathsums
|
398
|
+
toget = tuple(vmu)
|
399
|
+
ret_dict = add_perm_dict({ep: vpathsums[ep].get(toget, 0) for ep in vpathsums}, ret_dict)
|
400
|
+
return ret_dict
|
401
|
+
|
402
|
+
|
403
|
+
def div_diff(v, w, var2=var2, var3=var3):
|
404
|
+
coeff_dict = {v: 1}
|
405
|
+
coeff_dict = norm_yz.schubmult_down(coeff_dict, w, var2, var3)
|
406
|
+
return coeff_dict.get((1, 2), 0)
|
407
|
+
|
408
|
+
|
409
|
+
def sum_q_dict(q_dict1, q_dict2):
|
410
|
+
ret = {**q_dict1}
|
411
|
+
for key in q_dict2:
|
412
|
+
ret[key] = ret.get(key, 0) + q_dict2[key]
|
413
|
+
return ret
|
414
|
+
|
415
|
+
|
416
|
+
def mul_q_dict(q_dict1, q_dict2):
|
417
|
+
ret = {}
|
418
|
+
for key1 in q_dict1:
|
419
|
+
for key2 in q_dict2:
|
420
|
+
key3 = key1 * key2
|
421
|
+
ret[key3] = ret.get(key3, 0) + q_dict1[key1] * q_dict2[key2]
|
422
|
+
return ret
|
423
|
+
|
424
|
+
|
425
|
+
def factor_out_q_keep_factored(poly):
|
426
|
+
ret = {}
|
427
|
+
if str(poly).find("q") == -1:
|
428
|
+
ret[1] = poly
|
429
|
+
return ret
|
430
|
+
elif poly in q_var2:
|
431
|
+
ret[poly] = 1
|
432
|
+
return ret
|
433
|
+
elif isinstance(poly, Add):
|
434
|
+
ag = poly.args
|
435
|
+
ret = factor_out_q_keep_factored(ag[0])
|
436
|
+
for i in range(1, len(ag)):
|
437
|
+
ret = sum_q_dict(ret, factor_out_q_keep_factored(ag[i]))
|
438
|
+
return ret
|
439
|
+
elif isinstance(poly, Mul):
|
440
|
+
ag = poly.args
|
441
|
+
ret = factor_out_q_keep_factored(ag[0])
|
442
|
+
for i in range(1, len(ag)):
|
443
|
+
ret = mul_q_dict(ret, factor_out_q_keep_factored(ag[i]))
|
444
|
+
return ret
|
445
|
+
elif isinstance(poly, Pow):
|
446
|
+
base = poly.args[0]
|
447
|
+
exponent = int(poly.args[1])
|
448
|
+
|
449
|
+
ret = factor_out_q_keep_factored(base)
|
450
|
+
ret0 = dict(ret)
|
451
|
+
for i in range(exponent - 1):
|
452
|
+
ret = mul_q_dict(ret, ret0)
|
453
|
+
|
454
|
+
# print(f"exponent {exponent}")
|
455
|
+
# work_val = factor_out_q_keep_factored(base)
|
456
|
+
# ret = {1: 1}
|
457
|
+
# while exponent > 0:
|
458
|
+
# if exponent % 2 == 1:
|
459
|
+
# if ret == {1: 1}:
|
460
|
+
# ret = {**work_val}
|
461
|
+
# else:
|
462
|
+
# ret = mul_q_dict(ret,work_val)
|
463
|
+
# exponent -= 1
|
464
|
+
# else:
|
465
|
+
# work_val = mul_q_dict(work_val,work_val)
|
466
|
+
# exponent //= 2
|
467
|
+
return ret
|
468
|
+
return ret
|
469
|
+
|
470
|
+
|
471
|
+
def factor_out_q(poly):
|
472
|
+
coeff_dict = expand(poly).as_coefficients_dict()
|
473
|
+
ret = {}
|
474
|
+
for key in coeff_dict:
|
475
|
+
coeff = coeff_dict[key]
|
476
|
+
if coeff == 0:
|
477
|
+
continue
|
478
|
+
q_part = 1
|
479
|
+
yz_part = coeff
|
480
|
+
if isinstance(key, Mul):
|
481
|
+
for var_maybe_pow in key.args:
|
482
|
+
if isinstance(var_maybe_pow, Pow):
|
483
|
+
real_var = var_maybe_pow.args[0]
|
484
|
+
if real_var in q_var2:
|
485
|
+
q_part *= var_maybe_pow
|
486
|
+
else:
|
487
|
+
yz_part *= var_maybe_pow
|
488
|
+
else:
|
489
|
+
real_var = var_maybe_pow
|
490
|
+
if real_var in q_var2:
|
491
|
+
q_part *= var_maybe_pow
|
492
|
+
else:
|
493
|
+
yz_part *= var_maybe_pow
|
494
|
+
elif isinstance(key, Pow):
|
495
|
+
real_var = key.args[0]
|
496
|
+
if real_var in q_var2:
|
497
|
+
q_part *= key
|
498
|
+
else:
|
499
|
+
yz_part *= key
|
500
|
+
else:
|
501
|
+
if key in q_var2:
|
502
|
+
q_part *= key
|
503
|
+
else:
|
504
|
+
yz_part *= key
|
505
|
+
|
506
|
+
ret[q_part] = ret.get(q_part, 0) + yz_part
|
507
|
+
return ret
|