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