passagemath-brial 10.8.1a3__cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.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.
Files changed (39) hide show
  1. passagemath_brial/__init__.py +3 -0
  2. passagemath_brial-10.8.1a3.dist-info/METADATA +96 -0
  3. passagemath_brial-10.8.1a3.dist-info/RECORD +39 -0
  4. passagemath_brial-10.8.1a3.dist-info/WHEEL +6 -0
  5. passagemath_brial-10.8.1a3.dist-info/top_level.txt +3 -0
  6. passagemath_brial.libs/libbrial-a2b87c7c.so.3.0.7 +0 -0
  7. passagemath_brial.libs/libbrial_groebner-607bf574.so.3.0.7 +0 -0
  8. passagemath_brial.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
  9. passagemath_brial.libs/libm4ri-4311ab86.so.2.0.1 +0 -0
  10. passagemath_brial.libs/libpng16-5d944a30.so.16.54.0 +0 -0
  11. sage/all__sagemath_brial.py +9 -0
  12. sage/libs/all__sagemath_brial.py +1 -0
  13. sage/libs/polybori/__init__.pxd +2 -0
  14. sage/libs/polybori/decl.pxd +401 -0
  15. sage/libs/polybori/pb_wrap.h +133 -0
  16. sage/rings/all__sagemath_brial.py +1 -0
  17. sage/rings/polynomial/all__sagemath_brial.py +1 -0
  18. sage/rings/polynomial/pbori/PyPolyBoRi.py +124 -0
  19. sage/rings/polynomial/pbori/__init__.py +46 -0
  20. sage/rings/polynomial/pbori/blocks.py +499 -0
  21. sage/rings/polynomial/pbori/cnf.py +241 -0
  22. sage/rings/polynomial/pbori/easy_polynomials.py +59 -0
  23. sage/rings/polynomial/pbori/fglm.py +93 -0
  24. sage/rings/polynomial/pbori/frontend.py +70 -0
  25. sage/rings/polynomial/pbori/gbcore.py +644 -0
  26. sage/rings/polynomial/pbori/gbrefs.py +129 -0
  27. sage/rings/polynomial/pbori/heuristics.py +35 -0
  28. sage/rings/polynomial/pbori/interpolate.py +122 -0
  29. sage/rings/polynomial/pbori/interred.py +34 -0
  30. sage/rings/polynomial/pbori/ll.py +302 -0
  31. sage/rings/polynomial/pbori/nf.py +671 -0
  32. sage/rings/polynomial/pbori/parallel.py +308 -0
  33. sage/rings/polynomial/pbori/pbori.cpython-314-aarch64-linux-gnu.so +0 -0
  34. sage/rings/polynomial/pbori/pbori.pxd +127 -0
  35. sage/rings/polynomial/pbori/pbori.pyx +8103 -0
  36. sage/rings/polynomial/pbori/randompoly.py +111 -0
  37. sage/rings/polynomial/pbori/rank.py +27 -0
  38. sage/rings/polynomial/pbori/specialsets.py +119 -0
  39. sage/rings/polynomial/pbori/statistics.py +35 -0
@@ -0,0 +1,671 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ from pathlib import Path
4
+ from warnings import warn
5
+
6
+ from sage.rings.polynomial.pbori.easy_polynomials import (
7
+ easy_linear_polynomials as easy_linear_polynomials_func,
8
+ )
9
+ from sage.rings.polynomial.pbori.pbori import (
10
+ BooleSet,
11
+ GroebnerStrategy,
12
+ Monomial,
13
+ Polynomial,
14
+ ReductionStrategy,
15
+ Variable,
16
+ easy_linear_factors,
17
+ mod_mon_set,
18
+ parallel_reduce,
19
+ )
20
+ from sage.rings.polynomial.pbori.PyPolyBoRi import (
21
+ BoolePolynomialVector,
22
+ )
23
+ from sage.rings.polynomial.pbori.statistics import used_vars_set
24
+
25
+
26
+ class GeneratorLimitExceeded(Exception):
27
+ r"""
28
+ Docstring for GeneratorLimitExceeded
29
+ """
30
+
31
+ def __init__(self, strat):
32
+ self.strat = strat
33
+
34
+
35
+ def pkey(p):
36
+ return (p[0], len(p))
37
+
38
+
39
+ mat_counter = 0
40
+
41
+
42
+ def build_and_print_matrices(v, strat):
43
+ r"""
44
+ Old solution using PIL, the currently used implementation is done in C++
45
+ and plots the same matrices, as being calculated
46
+ """
47
+ treated = BooleSet()
48
+ v = list(v)
49
+ if not v:
50
+ return
51
+ rows = 0
52
+ polys_in_mat = []
53
+ while v:
54
+ rows = rows + 1
55
+ p = v[0]
56
+ v = v[1:]
57
+ for m in list(p.terms()):
58
+ mom = Monomial(m)
59
+ if mom not in BooleSet(treated):
60
+ i = strat.select(mom)
61
+ if i >= 0:
62
+ p2 = strat[i]
63
+ p2 = p2 * (mom // p2.lead())
64
+ v.append(p2)
65
+ polys_in_mat.append(p)
66
+ treated = treated.union(p.set())
67
+ m2i = {v: k
68
+ for k, v in enumerate(list(Polynomial(BooleSet(treated)).terms()))}
69
+ polys_in_mat.sort(key=Polynomial.lead, reverse=True)
70
+ polys_in_mat = [[m2i[t] for t in p.terms()] for p in polys_in_mat]
71
+
72
+ global mat_counter
73
+ mat_counter = mat_counter + 1
74
+ from PIL import Image
75
+
76
+ rows = len(polys_in_mat)
77
+ cols = len(m2i)
78
+ im = Image.new("1", (cols, rows), "white")
79
+ for i, pi in enumerate(polys_in_mat):
80
+ for j in pi:
81
+ assert i < rows
82
+ assert j < cols
83
+ im.putpixel((j, i), 0)
84
+
85
+ file_name = Path(strat.matrix_prefix + str(mat_counter) + ".png")
86
+ file_name.unlink(missing_ok=True)
87
+ im.save(file_name)
88
+ del im
89
+
90
+ print("MATRIX_SIZE:", rows, "x", cols)
91
+
92
+
93
+ def multiply_polynomials(l, ring):
94
+ r"""
95
+
96
+ TESTS::
97
+
98
+ sage: from sage.rings.polynomial.pbori import *
99
+ sage: r = Ring(1000)
100
+ sage: x = r.variable
101
+ sage: from sage.rings.polynomial.pbori.nf import multiply_polynomials
102
+ sage: multiply_polynomials([x(3), x(2)+x(5)*x(6), x(0), x(0)+1], r)
103
+ 0
104
+ """
105
+ l = [Polynomial(p) for p in l]
106
+
107
+ def sort_key(p):
108
+ return p.navigation().value()
109
+ l = sorted(l, key=sort_key)
110
+ res = Polynomial(ring.one())
111
+ for p in l:
112
+ res = p * res
113
+ return res
114
+
115
+
116
+ def build_and_print_matrices_deg_colored(v, strat):
117
+ r"""
118
+ old PIL solution using a different color for each degree
119
+ """
120
+ if not v:
121
+ return
122
+
123
+ treated = BooleSet()
124
+ v = list(v)
125
+ rows = 0
126
+ polys_in_mat = []
127
+
128
+ while v:
129
+ rows = rows + 1
130
+ p = v[0]
131
+ v = v[1:]
132
+ for m in list(p.terms()):
133
+ mom = Monomial(m)
134
+ if m not in BooleSet(treated):
135
+ i = strat.select(mom)
136
+ if i >= 0:
137
+ p2 = strat[i]
138
+ p2 = p2 * (mom // p2.lead())
139
+ v.append(p2)
140
+ polys_in_mat.append(p)
141
+ treated = treated.union(p.set())
142
+ m2i = {v: k for k, v in enumerate(BooleSet(treated))}
143
+ max_deg = max(m.deg() for m in BooleSet(treated))
144
+ if max_deg == 0:
145
+ max_deg = 1
146
+ i2deg = {m2i[m]: m.deg() for m in BooleSet(treated)}
147
+ polys_in_mat = [[m2i[t] for t in p.terms()] for p in polys_in_mat]
148
+ polys_in_mat.sort(key=pkey)
149
+ global mat_counter
150
+ mat_counter = mat_counter + 1
151
+ from PIL import Image, ImageColor
152
+
153
+ rows = len(polys_in_mat)
154
+ cols = len(m2i)
155
+ im = Image.new("RGB", (cols, rows), "white")
156
+ for i in range(len(polys_in_mat)):
157
+ p = polys_in_mat[i]
158
+ for j in p:
159
+ assert i < rows
160
+ assert j < cols
161
+ hsl = str(270 - (270 * i2deg[j]) / max_deg)
162
+ im.putpixel((j, i), ImageColor.getrgb("hsl(" + hsl + ",100%,50%)"))
163
+ file_name = Path(strat.matrix_prefix + str(mat_counter) + ".png")
164
+ file_name.unlink(missing_ok=True)
165
+ im.save(file_name)
166
+ del im
167
+
168
+ print("MATRIX_SIZE:", rows, "x", cols)
169
+
170
+
171
+ def high_probability_polynomials_trick(p, strat):
172
+ lead_deg = p.lead_deg()
173
+ if lead_deg <= 4:
174
+ return
175
+
176
+ ring = p.ring()
177
+ factor = multiply_polynomials(easy_linear_factors(p), ring)
178
+ p = p / factor
179
+
180
+ # again, do it twice, it's cheap
181
+ lead_deg = p.lead_deg()
182
+ if lead_deg <= 3:
183
+ return
184
+
185
+ if lead_deg > 9:
186
+ return
187
+ uv = p.vars_as_monomial()
188
+
189
+ candidates = []
190
+
191
+ if uv.deg() <= 4:
192
+ return
193
+
194
+ if not uv.deg() <= lead_deg + 1:
195
+ return
196
+
197
+ space = uv.divisors()
198
+
199
+ lead = p.lead()
200
+ for v in lead.variables():
201
+ variable_selection = lead // v
202
+ vars_reversed = list(reversed(variable_selection.variables()))
203
+ # it's just a way to loop over the cartesian product
204
+ for assignment in variable_selection.divisors():
205
+ c_p = assignment
206
+ for var in vars_reversed:
207
+ if not assignment.reducible_by(var):
208
+ c_p = (var + 1) * c_p
209
+
210
+ points = (c_p + 1).zeros_in(space)
211
+ if p.zeros_in(points).empty():
212
+ candidates.append(c_p * factor)
213
+ # there many more combinations depending on plugged in values
214
+ for c in candidates:
215
+ strat.add_as_you_wish(c)
216
+
217
+
218
+ def symmGB_F2_python(G, deg_bound=1000000000000, over_deg_bound=0,
219
+ use_faugere=False, use_noro=False,
220
+ opt_lazy=True, opt_red_tail=True,
221
+ max_growth=2.0, step_factor=1.0,
222
+ implications=False, prot=False,
223
+ full_prot=False, selection_size=1000, opt_exchange=True,
224
+ opt_allow_recursion=False, ll=False,
225
+ opt_linear_algebra_in_last_block=True,
226
+ max_generators=None,
227
+ red_tail_deg_growth=True, matrix_prefix='mat',
228
+ modified_linear_algebra=True, draw_matrices=False,
229
+ easy_linear_polynomials=True):
230
+ if use_noro and use_faugere:
231
+ raise ValueError('both use_noro and use_faugere specified')
232
+
233
+ def add_to_basis(strat, p):
234
+ if p.is_zero():
235
+ if prot:
236
+ print("-")
237
+ else:
238
+ if prot:
239
+ if full_prot:
240
+ print(p)
241
+ print("Result: ", "deg:", p.deg(), "lm: ",
242
+ p.lead(), "el: ", p.elength())
243
+ if easy_linear_polynomials and p.lead_deg() > 2:
244
+ lin = easy_linear_polynomials_func(p)
245
+ for q in lin:
246
+ strat.add_generator_delayed(q)
247
+ old_len = len(strat)
248
+ strat.add_as_you_wish(p)
249
+ new_len = len(strat)
250
+ if new_len == 1 + old_len:
251
+ high_probability_polynomials_trick(p, strat)
252
+
253
+ if prot:
254
+ print("#Generators:", len(strat))
255
+
256
+ if isinstance(G, list):
257
+ if not G:
258
+ return []
259
+ G = [Polynomial(g) for g in G]
260
+ current_ring = G[0].ring()
261
+ strat = GroebnerStrategy(current_ring)
262
+ strat.reduction_strategy.opt_red_tail = opt_red_tail
263
+ strat.opt_lazy = opt_lazy
264
+ strat.opt_exchange = opt_exchange
265
+ strat.opt_allow_recursion = opt_allow_recursion
266
+ strat.enabled_log = prot
267
+ strat.reduction_strategy.opt_ll = ll
268
+ strat.opt_modified_linear_algebra = modified_linear_algebra
269
+ strat.opt_linear_algebra_in_last_block = (
270
+ opt_linear_algebra_in_last_block)
271
+ strat.opt_red_by_reduced = False # True
272
+ strat.reduction_strategy.opt_red_tail_deg_growth = red_tail_deg_growth
273
+
274
+ strat.opt_draw_matrices = draw_matrices
275
+ strat.matrix_prefix = matrix_prefix
276
+
277
+ for g in G:
278
+ if not g.is_zero():
279
+ strat.add_generator_delayed(g)
280
+ else:
281
+ strat = G
282
+
283
+ if prot:
284
+ print("added delayed")
285
+ i = 0
286
+ try:
287
+ while strat.npairs() > 0:
288
+ if max_generators and len(strat) > max_generators:
289
+ raise GeneratorLimitExceeded(strat)
290
+ i = i + 1
291
+ if prot:
292
+ print("Current Degree:", strat.top_sugar())
293
+ if (strat.top_sugar() > deg_bound) and (over_deg_bound <= 0):
294
+ return strat
295
+ if (strat.top_sugar() > deg_bound):
296
+ ps = strat.some_spolys_in_next_degree(over_deg_bound)
297
+ over_deg_bound -= len(ps)
298
+ else:
299
+ ps = strat.some_spolys_in_next_degree(selection_size)
300
+
301
+ if ps and ps[0].ring().has_degree_order():
302
+ ps = [strat.reduction_strategy.cheap_reductions(p) for p in ps]
303
+ ps = [p for p in ps if not p.is_zero()]
304
+ if ps:
305
+ min_deg = min(p.deg() for p in ps)
306
+ new_ps = []
307
+ for p in ps:
308
+ if p.deg() <= min_deg:
309
+ new_ps.append(p)
310
+ else:
311
+ strat.add_generator_delayed(p)
312
+ ps = new_ps
313
+
314
+ if prot:
315
+ print("(", strat.npairs(), ")")
316
+ if prot:
317
+ print("start reducing")
318
+ print("Chain Crit. : ", strat.chain_criterions, "VC:", strat.
319
+ variable_chain_criterions, "EASYP", strat.
320
+ easy_product_criterions, "EXTP", strat.
321
+ extended_product_criterions)
322
+ print(len(ps), "spolys added")
323
+
324
+ if use_noro or use_faugere:
325
+ v = BoolePolynomialVector()
326
+
327
+ for p in ps:
328
+ if not p.is_zero():
329
+ v.append(p)
330
+ res = strat.noro_step(v) if use_noro else strat.faugere_step_dense(v)
331
+
332
+ else:
333
+ v = BoolePolynomialVector()
334
+ for p in ps:
335
+ rp = Polynomial(mod_mon_set(
336
+ BooleSet(p.set()),
337
+ strat.reduction_strategy.monomials))
338
+ if not rp.is_zero():
339
+ v.append(rp)
340
+ if len(v) > 100:
341
+ res = parallel_reduce(v, strat, int(step_factor * 10),
342
+ max_growth)
343
+ elif len(v) > 10:
344
+ res = parallel_reduce(v, strat, int(step_factor * 30),
345
+ max_growth)
346
+ else:
347
+ res = parallel_reduce(v, strat, int(step_factor * 100),
348
+ max_growth)
349
+
350
+ if prot:
351
+ print("end reducing")
352
+
353
+ if res and res[0].ring().has_degree_order():
354
+ res_min_deg = min([p.deg() for p in res])
355
+ new_res = []
356
+ for p in res:
357
+ if p.deg() == res_min_deg:
358
+ new_res.append(p)
359
+ else:
360
+ strat.add_generator_delayed(p)
361
+ res = new_res
362
+
363
+ def sort_key(p):
364
+ return p.lead()
365
+ res_cp = sorted(res, key=sort_key)
366
+
367
+ for p in res_cp:
368
+ old_len = len(strat)
369
+ add_to_basis(strat, p)
370
+ if implications and old_len == len(strat) - 1:
371
+ strat.implications(len(strat) - 1)
372
+ if p.is_one():
373
+ if prot:
374
+ print("GB is 1")
375
+ return strat
376
+ if prot:
377
+ print("(", strat.npairs(), ")")
378
+
379
+ strat.clean_top_by_chain_criterion()
380
+ return strat
381
+ except KeyboardInterrupt:
382
+ raise
383
+
384
+
385
+ def GPS(G, vars_start, vars_end):
386
+ def step(strat, trace, var, val):
387
+ print("plugin: ", var, val)
388
+ print("npairs", strat.npairs())
389
+ strat = GroebnerStrategy(strat)
390
+ print("npairs", strat.npairs())
391
+ strat.add_generator_delayed(Polynomial(
392
+ Monomial(Variable(var, strat.r)) + val))
393
+ strat = symmGB_F2_python(strat, prot=True, deg_bound=2,
394
+ over_deg_bound=10)
395
+ if var <= vars_start:
396
+ strat = symmGB_F2_python(strat, prot=True, opt_lazy=False,
397
+ opt_red_tail=False)
398
+ if strat.containsOne():
399
+ pass
400
+ else:
401
+ if var <= vars_start:
402
+ # bug: may contain Delayed polynomials
403
+ print("!!!!!!! SOLUTION", trace)
404
+ raise Exception
405
+ # yield trace
406
+ branch(strat, trace + [(var, val)], var - 1)
407
+
408
+ def branch(strat, trace, var):
409
+ while strat.variableHasValue(var):
410
+ # remember to add value to trace
411
+ var -= 1
412
+ step(strat, trace, var, 0)
413
+ step(strat, trace, var, 1)
414
+ if G:
415
+ strat = GroebnerStrategy(G[0].ring())
416
+ # strat.add_generator(G[0])
417
+ for g in G[:]:
418
+ strat.add_generator_delayed(g)
419
+ branch(strat, [], vars_end - 1)
420
+
421
+
422
+ def GPS_with_proof_path(G, proof_path, deg_bound, over_deg_bound):
423
+ def step(strat, trace, proof_path, pos, val):
424
+ print(proof_path)
425
+ print("plugin: ", pos, val, proof_path[pos])
426
+ print("npairs", strat.npairs())
427
+ strat = GroebnerStrategy(strat)
428
+ print("npairs", strat.npairs())
429
+ print("npairs", strat.npairs())
430
+ plug_p = Polynomial(proof_path[pos]) + val
431
+ plug_p_lead = plug_p.lead()
432
+ if len(plug_p) == 2 and (plug_p + plug_p_lead).deg() == 0:
433
+ for v in plug_p_lead:
434
+ strat.add_generator_delayed(v + 1)
435
+ else:
436
+ strat.add_generator_delayed(plug_p)
437
+ print("npairs", strat.npairs())
438
+ print("pos:", pos)
439
+ strat = symmGB_F2_python(strat, deg_bound=deg_bound, opt_lazy=False,
440
+ over_deg_bound=over_deg_bound, prot=True)
441
+ print("npairs", strat.npairs())
442
+ pos = pos + 1
443
+ if pos >= len(proof_path):
444
+ print("OVER")
445
+ strat = symmGB_F2_python(strat, prot=True)
446
+ if strat.containsOne():
447
+ pass
448
+ else:
449
+ if pos >= len(proof_path):
450
+ print("npairs", strat.npairs())
451
+ print("minimized:")
452
+ for p in strat.minimalize_and_tail_reduce():
453
+ print(p)
454
+ # bug: may contain Delayed polynomials
455
+ print("!!!!!!! SOLUTION", trace)
456
+ raise Exception
457
+ # yield trace
458
+ branch(strat, trace + [(pos, val)], proof_path, pos)
459
+
460
+ def branch(strat, trace, proof_path, pos):
461
+
462
+ step(strat, trace, proof_path, pos, 0)
463
+ step(strat, trace, proof_path, pos, 1)
464
+ strat = GroebnerStrategy(G[0].ring())
465
+ strat.add_generator(Polynomial(G[0]))
466
+ for g in G[1:]:
467
+ strat.add_generator_delayed(Polynomial(g))
468
+ branch(strat, [], proof_path, 0)
469
+
470
+
471
+ def GPS_with_suggestions(G, deg_bound, over_deg_bound, opt_lazy=True,
472
+ opt_red_tail=True, initial_bb=True):
473
+ def step(strat, trace, var, val):
474
+ print(trace)
475
+ plug_p = val + var
476
+ print("plugin: ", len(trace), plug_p)
477
+ trace = trace + [plug_p]
478
+ strat = GroebnerStrategy(strat)
479
+
480
+ strat.add_generator_delayed(plug_p)
481
+ print("npairs", strat.npairs())
482
+
483
+ strat = symmGB_F2_python(strat, deg_bound=deg_bound,
484
+ opt_lazy=opt_lazy,
485
+ over_deg_bound=over_deg_bound, prot=True)
486
+
487
+ if not strat.containsOne():
488
+ branch(strat, trace)
489
+
490
+ def branch(strat, trace):
491
+ print("branching")
492
+ index = strat.suggestPluginVariable()
493
+
494
+ if index < 0:
495
+ uv = set(used_vars_set(strat))
496
+ lv = {next(iter(p.lead())).index()
497
+ for p in strat if p.lead_deg() == 1}
498
+ candidates = uv.difference(lv)
499
+ if candidates:
500
+ index = next(iter(candidates)).index()
501
+ if index >= 0:
502
+ print("chosen index:", index)
503
+ step(strat, trace, Polynomial(Monomial(Variable(index))), 0)
504
+ step(strat, trace, Polynomial(Monomial(Variable(index))), 1)
505
+ else:
506
+ print("FINAL!!!", index)
507
+ strat = symmGB_F2_python(strat, prot=True)
508
+ if not strat.containsOne():
509
+ print("TRACE", trace)
510
+ print("SOLUTION")
511
+ for p in strat.minimalize_and_tail_reduce():
512
+ print(p)
513
+ raise Exception
514
+
515
+ def sort_crit(p):
516
+ return (p.lead(), p.deg(), p.elength())
517
+ if not G:
518
+ return
519
+ strat = GroebnerStrategy(G[0].ring())
520
+ strat.reduction_strategy.opt_red_tail = opt_red_tail # True
521
+ strat.opt_exchange = False
522
+ strat.opt_allow_recursion = False
523
+ strat.opt_lazy = opt_lazy
524
+ first_deg_bound = 1
525
+ G = [Polynomial(p) for p in G]
526
+ G.sort(key=sort_crit)
527
+ if initial_bb:
528
+ for g in G:
529
+ print(g)
530
+ if g.deg() == 1: # (index<0):
531
+ strat.add_as_you_wish(g)
532
+ else:
533
+ first_deg_bound = max(first_deg_bound, g.deg())
534
+ strat.add_generator_delayed(g)
535
+ print(g, len(strat))
536
+ else:
537
+ for g in G:
538
+ strat.add_as_you_wish(g)
539
+ if initial_bb:
540
+ strat = symmGB_F2_python(strat, deg_bound=max(deg_bound,
541
+ first_deg_bound),
542
+ opt_lazy=opt_lazy, over_deg_bound=0,
543
+ prot=True)
544
+ strat.opt_lazy = opt_lazy
545
+ print("INITIALIZED")
546
+ branch(strat, [])
547
+
548
+
549
+ def GPS_with_non_binary_proof_path(G, proof_path, deg_bound, over_deg_bound):
550
+ def step(strat, trace, proof_path, pos, choice):
551
+ print(proof_path)
552
+ print("plugin: ", pos)
553
+ print("npairs", strat.npairs())
554
+ strat = GroebnerStrategy(strat)
555
+ print("npairs", strat.npairs())
556
+ print("npairs", strat.npairs())
557
+ for p in proof_path[pos][choice]:
558
+ print(p)
559
+ strat.add_generator_delayed(Polynomial(p))
560
+
561
+ print("npairs", strat.npairs())
562
+ print("pos:", pos)
563
+ strat = symmGB_F2_python(strat, deg_bound=deg_bound,
564
+ over_deg_bound=over_deg_bound, prot=True)
565
+ print("npairs", strat.npairs())
566
+ pos = pos + 1
567
+ if pos >= len(proof_path):
568
+ print("OVER")
569
+ strat = symmGB_F2_python(strat)
570
+ if strat.containsOne():
571
+ pass
572
+ else:
573
+ if pos >= len(proof_path):
574
+ print("npairs", strat.npairs())
575
+ # bug: may contain Delayed polynomials
576
+ print("!!!!!!! SOLUTION", trace)
577
+ raise Exception
578
+ # yield trace
579
+ branch(strat, trace + [(pos, choice)], proof_path, pos)
580
+ # workaround because of stack depth
581
+ # step(strat,trace+[(var,val)],var-1, 0)
582
+ # step(strat,trace+[(var,val)],var-1, 1)
583
+
584
+ def branch(strat, trace, proof_path, pos):
585
+ for i in range(len(proof_path[pos])):
586
+ step(strat, trace, proof_path, pos, i)
587
+
588
+ strat = GroebnerStrategy(G[0].ring())
589
+ strat.add_generator(G[0])
590
+ for g in G[1:]:
591
+ strat.add_generator_delayed(g)
592
+ branch(strat, [], proof_path, 0)
593
+
594
+
595
+ def symmGB_F2_C(G, opt_exchange=True,
596
+ deg_bound=1000000000000, opt_lazy=False,
597
+ over_deg_bound=0, opt_red_tail=True,
598
+ max_growth=2.0, step_factor=1.0,
599
+ implications=False, prot=False,
600
+ full_prot=False, selection_size=1000,
601
+ opt_allow_recursion=False, use_noro=False, use_faugere=False,
602
+ ll=False, opt_linear_algebra_in_last_block=True,
603
+ max_generators=None, red_tail_deg_growth=True,
604
+ modified_linear_algebra=True, matrix_prefix='',
605
+ draw_matrices=False):
606
+ if use_noro:
607
+ raise NotImplementedError("noro not implemented for symmgb")
608
+ if isinstance(G, list):
609
+ if not G:
610
+ return []
611
+
612
+ G = [Polynomial(g) for g in G]
613
+ strat = GroebnerStrategy(G[0].ring())
614
+ strat.reduction_strategy.opt_red_tail = opt_red_tail
615
+ strat.enabled_log = prot
616
+ strat.opt_lazy = opt_lazy
617
+ strat.opt_exchange = opt_exchange
618
+ strat.reduction_strategy.opt_ll = ll
619
+ strat.opt_allow_recursion = opt_allow_recursion
620
+ strat.opt_linear_algebra_in_last_block = (
621
+ opt_linear_algebra_in_last_block)
622
+ strat.enabled_log = prot
623
+ strat.opt_modified_linear_algebra = modified_linear_algebra
624
+ strat.matrix_prefix = matrix_prefix
625
+ strat.opt_draw_matrices = draw_matrices
626
+ strat.reduction_strategy.opt_red_tail_deg_growth = red_tail_deg_growth
627
+
628
+ strat.redByReduced = False # True
629
+
630
+ for g in G: # [1:]:
631
+ if not g.is_zero():
632
+ strat.add_generator_delayed(g)
633
+ strat.symmGB_F2()
634
+ return strat
635
+
636
+
637
+ def normal_form(poly, ideal, reduced=True):
638
+ r"""
639
+ Simple normal form computation of a polynomial against an ideal.
640
+
641
+ TESTS::
642
+
643
+ sage: from sage.rings.polynomial.pbori import declare_ring, normal_form
644
+ sage: r=declare_ring(['x','y'], globals())
645
+ sage: normal_form(x+y, [y],reduced=True)
646
+ x
647
+ sage: normal_form(x+y,[x,y])
648
+ 0
649
+ """
650
+ ring = poly.ring()
651
+ strat = ReductionStrategy(ring)
652
+ strat.opt_red_tail = reduced
653
+ ideal = [Polynomial(p) for p in ideal if p != 0]
654
+ ideal = sorted(ideal, key=Polynomial.lead)
655
+ last = None
656
+ for p in ideal:
657
+ if p.lead() != last:
658
+ strat.add_generator(p)
659
+ else:
660
+ warn("%s will not used for reductions" % p)
661
+ last = p.lead()
662
+ return strat.nf(poly)
663
+
664
+
665
+ def _test():
666
+ import doctest
667
+ doctest.testmod()
668
+
669
+
670
+ if __name__ == "__main__":
671
+ _test()