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,499 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ from itertools import chain, islice
4
+
5
+ from sage.rings.polynomial.pbori.pbori import (
6
+ Polynomial,
7
+ Variable,
8
+ VariableBlock,
9
+ VariableFactory,
10
+ )
11
+ from sage.rings.polynomial.pbori.PyPolyBoRi import Ring
12
+
13
+
14
+ class Block:
15
+ r"""
16
+ The block class represents a block of variables
17
+ <var_name>(start_index,...,start_index+size-1), it is the preferred
18
+ block type for simple one-dimensional variable sets
19
+ """
20
+ def __init__(self, var_name, size, start_index=0, reverse=False):
21
+ indices = range(start_index, start_index + size)
22
+ if reverse:
23
+ indices = reversed(indices)
24
+ self.names = [var_name + "(" + str(i) + ")" for i in indices]
25
+ self.var_name = var_name
26
+ self.start_index = start_index
27
+ self.reverse = reverse
28
+ self.size = size
29
+
30
+ def __iter__(self):
31
+ return iter(self.names)
32
+
33
+ def __getitem__(self, i):
34
+ return self.names[i]
35
+
36
+ def __len__(self):
37
+ return self.size
38
+
39
+ def register(self, start, context):
40
+ ring_context = context
41
+ while isinstance(ring_context, PrefixedDictProxy):
42
+ ring_context = ring_context.wrapped
43
+ ring = ring_context['r']
44
+
45
+ var_func = VariableBlock(self.size, self.start_index, start, self.
46
+ reverse, ring)
47
+ var_func.__name__ = self.var_name
48
+ context[self.var_name] = var_func
49
+
50
+
51
+ class AlternatingBlock:
52
+ r"""
53
+ The Alternating Block class is used for doing tricky variable
54
+ schemes,where base names vary, e.g.
55
+ a(0),b(0),a(1),b(1),a(2),b(2)
56
+ """
57
+ def __init__(self, var_names, size_per_variable, start_index=0,
58
+ reverse=False):
59
+ self.var_names = var_names
60
+ self.size_per_variable = size_per_variable
61
+ self.reverse = reverse
62
+ indices = range(start_index, start_index + size_per_variable)
63
+
64
+ if reverse:
65
+ indices = reversed(indices)
66
+ names = [f"{n}({str(i)})" for i in indices for n in var_names]
67
+ self.indices = indices
68
+ self.index2pos = {v: k for k, v in enumerate(indices)}
69
+ self.names = names
70
+
71
+ def __len__(self):
72
+ return self.size_per_variable * len(self.var_names)
73
+
74
+ def __iter__(self):
75
+ return iter(self.names)
76
+
77
+ def __getitem__(self, i):
78
+ return self.names[i]
79
+
80
+ def register(self, start, context):
81
+ def gen_var_func(var_pos):
82
+
83
+ class var_factory:
84
+ def __init__(self, ring, index2pos, size):
85
+ self.ring = ring
86
+ self.index2pos = index2pos
87
+ self.size = size
88
+
89
+ def __call__(self, idx):
90
+ return self.ring.variable(self.index2pos[idx] * self.size +
91
+ var_pos + start)
92
+ ring_context = context
93
+ while isinstance(ring_context, PrefixedDictProxy):
94
+ ring_context = ring_context.wrapped
95
+ ring = ring_context['r']
96
+
97
+ return var_factory(ring, self.index2pos, len(self.var_names))
98
+
99
+ for (var_pos, n) in enumerate(self.var_names):
100
+ var_func = gen_var_func(var_pos)
101
+ var_func.__name__ = n
102
+ context[n] = var_func
103
+
104
+
105
+ def shift(f, i):
106
+ def g(j):
107
+ return f(i + j)
108
+ g.__name__ = f.__name__
109
+ return g
110
+
111
+
112
+ class AdderBlock(AlternatingBlock):
113
+ def __init__(self, adder_bits, sums='s', carries='c', input1='a',
114
+ input2='b', start_index=0):
115
+ AlternatingBlock.__init__(self, (sums, carries, input1, input2),
116
+ adder_bits, start_index=start_index,
117
+ reverse=True)
118
+ self.input1 = input1
119
+ self.input2 = input2
120
+ self.sums = sums
121
+ self.carries = carries
122
+ self.start_index = start_index
123
+ self.adder_bits = adder_bits
124
+
125
+ def register(self, start, context):
126
+ super().register(start, context)
127
+ a = context[self.input1]
128
+ b = context[self.input2]
129
+ self.s = shift(context[self.sums], self.start_index)
130
+ self.c = shift(context[self.carries], self.start_index)
131
+ a = shift(a, self.start_index)
132
+ b = shift(b, self.start_index)
133
+ carries = [Polynomial(a(0).ring().zero())]
134
+ last = carries[0]
135
+ for i in range(self.adder_bits):
136
+ c = 1 + (1 + a(i) * b(i)) * (1 + last * a(i)) * (1 + last * b(i))
137
+ carries.append(c)
138
+ last = c
139
+
140
+ self.add_results = [a(i) + b(i) + carries[i]
141
+ for i in range(self.adder_bits)]
142
+ self.carries_polys = carries[1:]
143
+
144
+ # def s(i):
145
+ # return self.add_results[i-self.start_index]
146
+ # def c(i):
147
+ # return self.carries_polys[i-self.start_index]
148
+ # context[self.sums]=s
149
+ # context[self.carries]=c
150
+
151
+ def implement(self, equations):
152
+ for i in range(self.adder_bits):
153
+ equations.append(self.s(i) + self.add_results[i])
154
+ equations.append(self.c(i) + self.carries_polys[i])
155
+
156
+
157
+ class HigherOrderBlock:
158
+ r"""
159
+ HigherOrderBlocks are multidimensional blocks of variables.
160
+
161
+ For each dimension a separate ``start_index`` and ``size`` can be specified.
162
+
163
+ var_name : variables will be called <var_name>(multiindex), where
164
+ multiindex is a tuple of the size <size_tuple>
165
+
166
+ size_tuple : specifies the sizes of the ranges of each component of the
167
+ multi-indices
168
+
169
+ start_index_tuple : the multi-indices will be of the form
170
+ start_index_tuple + a, where a is a multi-index with nonnegative components
171
+ """
172
+ def __init__(self, var_name, size_tuple, start_index_tuple=None,
173
+ reverse=False):
174
+ if start_index_tuple is None:
175
+ start_index_tuple = len(size_tuple) * (0, )
176
+ cart = [()]
177
+ assert len(size_tuple) == len(start_index_tuple)
178
+ outer_indices = reversed(range(len(size_tuple)))
179
+ for i in outer_indices:
180
+ s_i = start_index_tuple[i]
181
+ s = size_tuple[i]
182
+ cart = [(j, ) + c for j in range(s_i, s_i + s) for c in cart]
183
+ if reverse:
184
+ cart.reverse()
185
+ self.cart = cart
186
+ self.cart2index = {v: k for k, v in enumerate(cart)}
187
+ self.var_name = var_name
188
+ self.names = [var_name + str(c) for c in cart]
189
+
190
+ def __getitem__(self, i):
191
+ return self.names[i]
192
+
193
+ def __iter__(self):
194
+ return iter(self.names)
195
+
196
+ def __len__(self):
197
+ return len(self.names)
198
+
199
+ def register(self, start, context):
200
+ def var_func(*indices):
201
+ return Variable(self.cart2index[indices] + start)
202
+ var_func.__name__ = self.var_name
203
+ context[self.var_name] = var_func
204
+
205
+
206
+ class InOutBlock:
207
+ def __init__(self, out_size, in_size, output='out', input='in',
208
+ in_start_index=0, out_start_index=0,
209
+ out_reverse=False, in_reverse=False):
210
+ self.output = Block(var_name=output, start_index=out_start_index,
211
+ size=out_size, reverse=out_reverse)
212
+ self.input = Block(var_name=input, start_index=in_start_index,
213
+ size=in_size, reverse=in_reverse)
214
+ self.out_start_index = out_start_index
215
+
216
+ self.in_start_index = in_start_index
217
+
218
+ def __iter__(self):
219
+ return chain(self.output, self.input)
220
+
221
+ def __getitem__(self, i):
222
+ if i < len(self.output):
223
+ return self.output[i]
224
+ return self.input[i - len(self.output)]
225
+
226
+ def __len__(self):
227
+ return len(self.output) + len(self.input)
228
+
229
+ def register(self, start, context):
230
+ self.output.register(start, context)
231
+ self.input.register(start + len(self.output), context)
232
+ self.out_vars = shift(context[self.output.var_name], self.
233
+ out_start_index)
234
+ self.in_vars = shift(context[self.input.var_name], self.in_start_index)
235
+
236
+
237
+ class MultiBlock:
238
+ def __init__(self, sizes=None, var_names=["v"],
239
+ start_indices=[], reverses=None):
240
+ if reverses is None:
241
+ reverses = []
242
+ if sizes is None:
243
+ sizes = []
244
+ self.start_indices = start_indices + [0] * (len(var_names) -
245
+ len(start_indices))
246
+ reverses += [False] * (len(var_names) - len(reverses))
247
+ sizes += [1] * (len(var_names) - len(sizes))
248
+
249
+ self.blocks = [Block(var_name=var_names[idx], size=sizes[idx],
250
+ start_index=self.start_indices[idx],
251
+ reverse=reverses[idx])
252
+ for idx in range(len(var_names))]
253
+
254
+ def __iter__(self):
255
+ return chain(*self.blocks)
256
+
257
+ def __getitem__(self, i):
258
+ return next(islice(chain(*self.blocks), i, i + 1))
259
+ # sum([bl.names for bl in self.blocks])[i]
260
+
261
+ def __len__(self):
262
+ return sum(len(bl) for bl in self.blocks)
263
+
264
+ def register(self, start, context):
265
+ offset = 0
266
+ for bl in self.blocks:
267
+ bl.register(start + offset, context)
268
+ offset += len(bl)
269
+
270
+ self.vars = [shift(context[self.blocks[idx].var_name],
271
+ self.start_indices[idx])
272
+ for idx in range(len(self.blocks))]
273
+
274
+
275
+ class PrefixedDictProxy:
276
+ """docstring for PrefixedDictProxy"""
277
+
278
+ def __init__(self, wrapped, prefix):
279
+ super().__init__()
280
+ self.wrapped = wrapped
281
+ self.prefix = prefix
282
+
283
+ def __getitem__(self, k):
284
+ try:
285
+ return self.wrapped[self.prefix + k]
286
+ except KeyError:
287
+ print(self.prefix, k, list(self.wrapped))
288
+ raise KeyError
289
+
290
+ def __setitem__(self, k, v):
291
+ self.wrapped[self.prefix + k] = v
292
+
293
+
294
+ class MacroBlock:
295
+ def __init__(self, prefix):
296
+
297
+ self.prefix = prefix
298
+ self.blocks = []
299
+ self.combinations = []
300
+ self.connections = []
301
+
302
+ def declare(self, blocks):
303
+ self.blocks = blocks
304
+
305
+ def connect(self, combinations):
306
+ self.combinations = combinations
307
+
308
+ def __iter__(self):
309
+ return (self.prefix + "_" + n for n in chain(*self.blocks))
310
+
311
+ def __getitem__(self, i):
312
+ return self.prefix + "_" + next(islice(chain(*self.blocks), i, i + 1))
313
+
314
+ def __len__(self):
315
+ return sum(len(bl) for bl in self.blocks)
316
+
317
+ def resolve(self, localname):
318
+ return self.prefix + "_" + localname
319
+
320
+ def register(self, start, context):
321
+ context = PrefixedDictProxy(context, self.prefix + "_")
322
+ offset = 0
323
+ for bl in self.blocks:
324
+ bl.register(start + offset, context)
325
+ offset += len(bl)
326
+
327
+ for ((con1, indices1), (con2, indices2)) in self.combinations:
328
+ for idx in range(min(len(indices1), len(indices2))):
329
+ self.connections += [context[con1](indices1[idx]) + context[
330
+ con2](indices2[idx])]
331
+
332
+ def implement(self, equations):
333
+ for bl in self.blocks:
334
+ if hasattr(bl, "implement"):
335
+ bl.implement(equations)
336
+
337
+ equations += self.connections
338
+
339
+
340
+ class IfThen:
341
+ def __init__(self, ifpart, thenpart, supposed_to_be_valid=True):
342
+ self.ifpart = [Polynomial(p) for p in ifpart]
343
+ self.thenpart = [Polynomial(p) for p in thenpart]
344
+ self.supposedToBeValid = supposed_to_be_valid
345
+
346
+ def __str__(self):
347
+ return ("If(AND(" + ", ".join(f"{p} == 0" for p in self.ifpart) +
348
+ ")), THEN " + ", ".join(f"{p} == 0" for p in self.thenpart))
349
+
350
+
351
+ def if_then(i, t, supposed_to_be_valid=True):
352
+ return IfThen(i, t, supposed_to_be_valid)
353
+
354
+
355
+ def declare_ring(blocks, context=None):
356
+ r"""
357
+ Declare Ring is the preferred function to create a ring and declare a variable scheme.
358
+
359
+ The number of variables is automatically determined. Usually you
360
+ pass ``globals()`` as context argument to store the ring and the
361
+ variable mapping.
362
+
363
+ EXAMPLES::
364
+
365
+ sage: from sage.rings.polynomial.pbori import *
366
+ sage: declare_ring([Block("x",10),Block("y",5)],globals())
367
+ Boolean PolynomialRing in x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, y0, y1, y2, y3, y4
368
+
369
+ gives a ring with x(0..9),y(0..4) and registers the ring as r, and
370
+ the variable blocks x and y in the context dictionary ``globals()``,
371
+ which consists of the global variables of the python module
372
+ """
373
+ def canonicalize(blocks):
374
+ for elt in blocks:
375
+ if isinstance(elt, str):
376
+ yield elt
377
+ else:
378
+ yield from elt
379
+
380
+ blocks = list(blocks)
381
+ n = 0
382
+
383
+ for b in blocks:
384
+ n = n + 1 if isinstance(b, str) else n + len(b)
385
+
386
+ r = Ring(n, names=canonicalize(blocks))
387
+
388
+ context["internalVariable"] = VariableFactory(r)
389
+ # context["Monomial"] = MonomialFactory(r)
390
+ context["r"] = r
391
+ declare_block_scheme(blocks, context)
392
+ return r
393
+
394
+
395
+ def declare_block_scheme(blocks, context):
396
+ start = 0
397
+ block_starts = []
398
+ for b in blocks:
399
+ if start:
400
+ block_starts.append(start)
401
+ if isinstance(b, str):
402
+ context[b] = context["internalVariable"](start)
403
+ start = start + 1
404
+ else:
405
+ b.register(start, context)
406
+ start = start + len(b)
407
+ context["block_start_hints"] = block_starts
408
+ context["number_of_declared_vars"] = start
409
+
410
+
411
+ def main_test():
412
+ """
413
+ EXAMPLES::
414
+
415
+ sage: from sage.rings.polynomial.pbori.blocks import main_test
416
+ sage: main_test()
417
+ x(0)
418
+ x(1)
419
+ x(2)
420
+ x(3)
421
+ x(4)
422
+ x(5)
423
+ x(6)
424
+ x(7)
425
+ x(8)
426
+ x(9)
427
+ ['a(0)', 'b(0)', 'c(0)', 'a(1)', 'b(1)', ...]
428
+ x(0)
429
+ x(1)
430
+ x(2)
431
+ x(3)
432
+ x(4)
433
+ x(5)
434
+ x(6)
435
+ x(7)
436
+ x(8)
437
+ x(9)
438
+ x(364) x(367) x(370) x(365) x(368) x(366)
439
+ x(99)
440
+ x(98)
441
+ x(97)
442
+ x(96)
443
+ x(95)
444
+ x(94)
445
+ x(93)
446
+ x(92)
447
+ x(91)
448
+ x(90)
449
+ x(0) x(1) x(2)
450
+ """
451
+ r = Ring(1000)
452
+ dic = {"r": r}
453
+ dic["internalVariable"] = VariableFactory(r)
454
+
455
+ # first test
456
+ ablock = AlternatingBlock(["a", "b", "c"], 100)
457
+ declare_block_scheme([ablock], dic)
458
+ for i in range(10):
459
+ print(r.variable(i))
460
+ print(list(ablock))
461
+
462
+ # second test
463
+ declare_block_scheme([Block(var_name="x", size=100),
464
+ HigherOrderBlock("y", (3, 4, 11, 2)),
465
+ AlternatingBlock(["a", "b", "c"], 100)],
466
+ dic)
467
+ x = dic['x']
468
+ a, b, c = dic['a'], dic['b'], dic['c']
469
+ for i in range(10):
470
+ print(x(i))
471
+ # y are currently broken ?
472
+ # print(y(0, 0, 0, 0))
473
+ # print(y(0, 0, 0, 1))
474
+ # print(y(0, 0, 1, 0))
475
+ # print(y(0, 0, 1, 1))
476
+ print(a(0), a(1), a(2), b(0), b(1), c(0))
477
+
478
+ # third test
479
+ declare_block_scheme([Block(var_name="x", size=100, reverse=True),
480
+ HigherOrderBlock("y", (3, 4, 11, 2), reverse=True),
481
+ AlternatingBlock(["a", "b", "c"], 100, reverse=True)],
482
+ dic)
483
+ x = dic['x']
484
+ a, b, c = dic['a'], dic['b'], dic['c']
485
+ for i in range(10):
486
+ print(x(i))
487
+ # y are currently broken ?
488
+ # print(y(0, 0, 0, 0))
489
+ # print(y(0, 0, 0, 1))
490
+ # print(y(0, 0, 1, 0))
491
+ # print(y(0, 0, 1, 1))
492
+
493
+ # a also broken ?
494
+ # print(a(0), a(1), a(2), b(0), b(1), c(0))
495
+
496
+ # fourth test
497
+ declare_block_scheme(["a", "b", "c"], dic)
498
+ a, b, c = dic['a'], dic['b'], dic['c']
499
+ print(a, b, c)