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,241 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ from random import Random
4
+
5
+ from sage.rings.polynomial.pbori.pbori import if_then_else as ite
6
+ from sage.rings.polynomial.pbori.PyPolyBoRi import Polynomial
7
+ from sage.rings.polynomial.pbori.statistics import used_vars_set
8
+
9
+
10
+ class CNFEncoder:
11
+ def __init__(self, r, random_seed=16):
12
+ self.random_generator = Random(random_seed)
13
+ self.one_set = r.one().set()
14
+ self.empty_set = r.zero().set()
15
+ self.r = r
16
+
17
+ def zero_blocks(self, f):
18
+ r"""
19
+ Divide the zero set of f into blocks.
20
+
21
+ TESTS::
22
+
23
+ sage: from sage.rings.polynomial.pbori import *
24
+ sage: r = declare_ring(["x", "y", "z"], dict())
25
+ sage: from sage.rings.polynomial.pbori.cnf import CNFEncoder
26
+ sage: e = CNFEncoder(r)
27
+ sage: e.zero_blocks(r.variable(0)*r.variable(1)*r.variable(2))
28
+ [{z: 0}, {y: 0}, {x: 0}]
29
+ """
30
+ f = Polynomial(f)
31
+ variables = f.vars_as_monomial()
32
+
33
+ space = variables.divisors()
34
+ variables = list(variables.variables())
35
+ zeros = f.zeros_in(space)
36
+ rest = zeros
37
+ res = []
38
+
39
+ # inefficient compared to polynomials lex_lead
40
+ def choose(s):
41
+ indices = []
42
+ assert not s.empty()
43
+ nav = s.navigation()
44
+ while not nav.constant():
45
+ e = nav.else_branch()
46
+ t = nav.then_branch()
47
+ if e.constant() and not e.terminal_one():
48
+ indices.append(nav.value())
49
+ nav = t
50
+ elif self.random_generator.randint(0, 1):
51
+ indices.append(nav.value())
52
+ nav = t
53
+
54
+ else:
55
+ nav = e
56
+ assert nav.terminal_one()
57
+ res = self.one_set
58
+ for i in reversed(indices):
59
+ res = ite(i, res, self.empty_set)
60
+ return next(iter(res))
61
+ while not rest.empty():
62
+ l = choose(rest)
63
+ l_variables = set(l.variables())
64
+
65
+ def get_val(var):
66
+ if var in l_variables:
67
+ return 1
68
+ return 0
69
+ block_dict = {v: get_val(v) for v in variables}
70
+
71
+ l = l.set()
72
+ self.random_generator.shuffle(variables)
73
+ for v in variables:
74
+ candidate = l.change(v.index())
75
+ if candidate.diff(zeros).empty():
76
+ l = l.union(candidate)
77
+ del block_dict[v]
78
+ rest = rest.diff(l)
79
+ res.append(block_dict)
80
+ return res
81
+
82
+ def clauses(self, f):
83
+ r"""
84
+
85
+ TESTS::
86
+
87
+ sage: from sage.rings.polynomial.pbori import *
88
+ sage: r = declare_ring(["x", "y", "z"], dict())
89
+ sage: from sage.rings.polynomial.pbori.cnf import CNFEncoder
90
+ sage: e = CNFEncoder(r)
91
+ sage: sorted(e.clauses(r.variable(0)*r.variable(1)*r.variable(2)), key=lambda d: sorted(d.items()))
92
+ [{z: 0, y: 0, x: 0}]
93
+ sage: sorted(e.clauses(r.variable(Integer(1))+r.variable(Integer(0))), key=lambda d: sorted(d.items()))
94
+ [{y: 0, x: 1}, {y: 1, x: 0}]
95
+ """
96
+ # we form an expression for a var configuration *not* lying in the
97
+ # block it is evaluated to 0 by f, iff it is not lying in any zero
98
+ # block of f+1
99
+ return [{variable: 1 - value for variable, value in b.items()}
100
+ for b in self.zero_blocks(f + 1)]
101
+
102
+ def polynomial_clauses(self, f):
103
+ r"""
104
+
105
+ TESTS::
106
+
107
+ sage: from sage.rings.polynomial.pbori import *
108
+ sage: r = declare_ring(["x", "y", "z"], dict())
109
+ sage: from sage.rings.polynomial.pbori.cnf import CNFEncoder
110
+ sage: e = CNFEncoder(r)
111
+ sage: e.polynomial_clauses(r.variable(0)*r.variable(1)*r.variable(2))
112
+ [x*y*z]
113
+ sage: v = r.variable
114
+ sage: p = v(1)*v(2)+v(2)*v(0)+1
115
+ sage: groebner_basis([p], heuristic = False)==groebner_basis(e.polynomial_clauses(p), heuristic = False)
116
+ True
117
+ """
118
+
119
+ def product(l):
120
+ res = l[0]
121
+ for p in l[1:]:
122
+ res = res * p
123
+ # please care about the order of these multiplications for
124
+ # performance
125
+ return res
126
+ return [product([variable + value for (variable, value)
127
+ in b.items()]) for b in self.clauses(f)]
128
+
129
+ def to_dimacs_index(self, v):
130
+ return v.index() + 1
131
+
132
+ def dimacs_encode_clause(self, c):
133
+ def get_sign(value):
134
+ if value == 1:
135
+ return 1
136
+ return -1
137
+
138
+ items = sorted(c.items(), reverse=True)
139
+ return " ".join([str(v) for v in [
140
+ get_sign(value) * self.to_dimacs_index(variable)
141
+ for (variable, value) in items] + [0]])
142
+
143
+ def dimacs_encode_polynomial(self, p):
144
+ r"""
145
+
146
+ TESTS::
147
+
148
+ sage: from sage.rings.polynomial.pbori import *
149
+ sage: d = {}
150
+ sage: r = declare_ring(["x", "y", "z"], d)
151
+ sage: from sage.rings.polynomial.pbori.cnf import CNFEncoder
152
+ sage: e = CNFEncoder(r)
153
+ sage: sorted(e.dimacs_encode_polynomial(d["x"]+d["y"]+d["z"]))
154
+ ['-1 -2 -3 0', '-1 2 3 0', '1 -2 3 0', '1 2 -3 0']
155
+ """
156
+ return [self.dimacs_encode_clause(c) for c in self.clauses(p)]
157
+
158
+ def dimacs_cnf(self, polynomial_system):
159
+ r"""
160
+
161
+ TESTS::
162
+
163
+ sage: from sage.rings.polynomial.pbori import *
164
+ sage: r = declare_ring(["x", "y", "z"], dict())
165
+ sage: from sage.rings.polynomial.pbori.cnf import CNFEncoder
166
+ sage: e = CNFEncoder(r)
167
+ sage: e.dimacs_cnf([r.variable(0)*r.variable(1)*r.variable(2)])
168
+ 'c cnf generated by PolyBoRi\np cnf 3 1\n-1 -2 -3 0'
169
+ sage: e.dimacs_cnf([r.variable(1)+r.variable(0)])
170
+ 'c cnf generated by PolyBoRi\np cnf 3 2\n-1 2 0\n1 -2 0'
171
+ sage: e.dimacs_cnf([r.variable(0)*r.variable(1)*r.variable(2), r.variable(1)+r.variable(0)])
172
+ 'c cnf generated by PolyBoRi\np cnf 3 3\n-1 -2 -3 0\n1 -2 0\n-1 2 0'
173
+ """
174
+ clauses_list = [c for p in polynomial_system for c in self.
175
+ dimacs_encode_polynomial(p)]
176
+ res = ["c cnf generated by PolyBoRi"]
177
+ r = polynomial_system[0].ring()
178
+ n_variables = r.n_variables()
179
+ res.append(f"p cnf {n_variables} {len(clauses_list)}")
180
+ res.extend(clauses_list)
181
+ return "\n".join(res)
182
+
183
+
184
+ class CryptoMiniSatEncoder(CNFEncoder):
185
+ group_counter = 0
186
+
187
+ def dimacs_encode_polynomial(self, p):
188
+ r"""
189
+
190
+ TESTS::
191
+
192
+ sage: from sage.rings.polynomial.pbori import *
193
+ sage: d=dict()
194
+ sage: r = declare_ring(["x", "y", "z"], d)
195
+ sage: from sage.rings.polynomial.pbori.cnf import CryptoMiniSatEncoder
196
+ sage: e = CryptoMiniSatEncoder(r)
197
+ sage: p = d["x"]+d["y"]+d["z"]
198
+ sage: p.deg()
199
+ 1
200
+ sage: len(p)
201
+ 3
202
+ sage: e.dimacs_encode_polynomial(p)
203
+ ['x1 2 3 0\nc g 1 x + y + z']
204
+ sage: e.dimacs_encode_polynomial(p+1)
205
+ ['x1 2 -3 0\nc g 2 x + y + z + 1']
206
+ """
207
+ if p.deg() != 1 or len(p) <= 1:
208
+ res = super().dimacs_encode_polynomial(p)
209
+ else:
210
+ invert_last = bool(p.has_constant_part())
211
+ variables = list(p.vars_as_monomial().variables())
212
+ indices = [self.to_dimacs_index(v) for v in variables]
213
+ if invert_last:
214
+ indices[-1] = -indices[-1]
215
+ indices.append(0)
216
+ res = ["x" + " ".join(str(v) for v in indices)]
217
+ self.group_counter = self.group_counter + 1
218
+ group_comment = f"\nc g {self.group_counter} {str(p)[:30]}"
219
+ return [c + group_comment for c in res]
220
+
221
+ def dimacs_cnf(self, polynomial_system):
222
+ r"""
223
+
224
+ TESTS::
225
+
226
+ sage: from sage.rings.polynomial.pbori import *
227
+ sage: r = declare_ring(["x", "y", "z"], dict())
228
+ sage: from sage.rings.polynomial.pbori.cnf import CryptoMiniSatEncoder
229
+ sage: e = CryptoMiniSatEncoder(r)
230
+ sage: e.dimacs_cnf([r.variable(0)*r.variable(1)*r.variable(2)])
231
+ 'c cnf generated by PolyBoRi\np cnf 3 1\n-1 -2 -3 0\nc g 1 x*y*z\nc v 1 x\nc v 2 y\nc v 3 z'
232
+ sage: e.dimacs_cnf([r.variable(1)+r.variable(0)])
233
+ 'c cnf generated by PolyBoRi\np cnf 3 1\nx1 2 0\nc g 2 x + y\nc v 1 x\nc v 2 y'
234
+ sage: e.dimacs_cnf([r.variable(0)*r.variable(1)*r.variable(2), r.variable(1)+r.variable(0)])
235
+ 'c cnf generated by PolyBoRi\np cnf 3 2\n-1 -2 -3 0\nc g 3 x*y*z\nx1 2 0\nc g 4 x + y\nc v 1 x\nc v 2 y\nc v 3 z'
236
+ """
237
+ uv = list(used_vars_set(polynomial_system).variables())
238
+ res = super().dimacs_cnf(polynomial_system)
239
+ res += "\n" + "\n".join(f"c v {self.to_dimacs_index(v)} {v}"
240
+ for v in uv)
241
+ return res
@@ -0,0 +1,59 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ from sage.rings.polynomial.pbori.interpolate import (
4
+ nf_lex_points,
5
+ variety_lex_leading_terms,
6
+ )
7
+ from sage.rings.polynomial.pbori.pbori import easy_linear_factors
8
+
9
+
10
+ def easy_linear_polynomials(p):
11
+ r"""
12
+ Get linear polynomials implied by given polynomial.
13
+
14
+ EXAMPLES::
15
+
16
+ sage: from sage.rings.polynomial.pbori.frontend import x
17
+ sage: from sage.rings.polynomial.pbori.easy_polynomials import easy_linear_polynomials
18
+ sage: easy_linear_polynomials(x(1)*x(2) + 1)
19
+ [x(1) + 1, x(2) + 1]
20
+ sage: easy_linear_polynomials(x(1)*x(2) + 0)
21
+ []
22
+ sage: easy_linear_polynomials(x(0)*x(1) + x(0)*x(2) + 1)
23
+ [x(0) + 1, x(1) + x(2) + 1]
24
+ """
25
+ res = []
26
+ if p.deg() >= 2:
27
+ if p.vars_as_monomial().deg() > 8:
28
+ res.extend(q + 1 for q in easy_linear_factors(p + 1))
29
+ else:
30
+ res = easy_linear_polynomials_via_interpolation(p)
31
+ return res
32
+
33
+
34
+ def easy_linear_polynomials_via_interpolation(p):
35
+ r"""
36
+ Get linear polynomials implied by given polynomial using interpolation of the variety.
37
+
38
+ TESTS::
39
+
40
+ sage: from sage.rings.polynomial.pbori.frontend import x
41
+ sage: from sage.rings.polynomial.pbori.easy_polynomials import easy_linear_polynomials_via_interpolation
42
+ sage: easy_linear_polynomials_via_interpolation(x(1)*x(2) + 1)
43
+ [x(1) + 1, x(2) + 1]
44
+ sage: easy_linear_polynomials_via_interpolation(x(1)*x(2) + 0)
45
+ []
46
+ sage: easy_linear_polynomials_via_interpolation(x(0)*x(1) + x(0)*x(2) + 1)
47
+ [x(0) + 1, x(1) + x(2) + 1]
48
+ """
49
+ res = []
50
+ p_vars = p.vars_as_monomial()
51
+ space = p_vars.divisors()
52
+ zeros = p.zeros_in(space)
53
+ lex_leads = variety_lex_leading_terms(zeros, p_vars)
54
+ for m in lex_leads:
55
+ if m.deg() == 1:
56
+ red = m + nf_lex_points(m, zeros)
57
+ if red.lead_deg() == 1: # normal ordering
58
+ res.append(red)
59
+ return res
@@ -0,0 +1,93 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ from sage.rings.polynomial.pbori.pbori import BooleSet, FGLMStrategy
4
+ from sage.rings.polynomial.pbori.PyPolyBoRi import BoolePolynomialVector, Polynomial
5
+
6
+
7
+ def _fglm(I, from_ring, to_ring):
8
+ r"""
9
+ Unchecked variant of fglm
10
+ """
11
+ vec = BoolePolynomialVector(I)
12
+ return FGLMStrategy(from_ring, to_ring, vec).main()
13
+
14
+
15
+ def fglm(I, from_ring, to_ring):
16
+ r"""
17
+ Convert *reduced* Groebner Basis in ``from_ring`` to a GroebnerBasis
18
+ in ``to_ring``.
19
+
20
+ It acts independent of the global ring, which is restored at the end of the
21
+ computation.
22
+
23
+ TESTS::
24
+
25
+ sage: from sage.rings.polynomial.pbori import *
26
+ sage: from sage.rings.polynomial.pbori.PyPolyBoRi import OrderCode
27
+ sage: from sage.rings.polynomial.pbori.fglm import fglm
28
+ sage: dp_asc = OrderCode.dp_asc
29
+ sage: r = declare_ring(['x','y','z'],dict())
30
+ sage: old_ring = r
31
+ sage: new_ring = old_ring.clone(ordering=dp_asc)
32
+ sage: x,y,z = (old_ring.variable(i) for i in range(3))
33
+ sage: ideal = [x+z, y+z] # lp Groebner basis
34
+ sage: list(fglm(ideal, old_ring, new_ring))
35
+ [y + x, z + x]
36
+ """
37
+ for poly in I:
38
+ if poly.ring().id() != from_ring.id():
39
+ raise ValueError("Ideal I must be from the first ring argument")
40
+ return _fglm(I, from_ring, to_ring)
41
+
42
+
43
+ def vars_real_divisors(monomial, monomial_set):
44
+ r"""
45
+ Return all elements of ``monomial_set``, which result multiplied by a variable in monomial.
46
+
47
+ EXAMPLES::
48
+
49
+ sage: from sage.rings.polynomial.pbori.pbori import *
50
+ sage: from sage.rings.polynomial.pbori.PyPolyBoRi import OrderCode
51
+ sage: dp_asc = OrderCode.dp_asc
52
+ sage: from sage.rings.polynomial.pbori.PyPolyBoRi import Ring
53
+ sage: r = Ring(1000)
54
+ sage: x = r.variable
55
+ sage: b = BooleSet([x(1)*x(2),x(2)])
56
+ sage: from sage.rings.polynomial.pbori.fglm import vars_real_divisors
57
+ sage: vars_real_divisors(x(1)*x(2)*x(3),b)
58
+ {{x(1),x(2)}}
59
+ """
60
+ return BooleSet(Polynomial(monomial_set.divisors_of(monomial)).
61
+ graded_part(monomial.deg() - 1))
62
+
63
+
64
+ def m_k_plus_one(completed_elements, variables):
65
+ r"""
66
+ Calculate `m_{k+1}` from the FGLM algorithm.
67
+
68
+ Calculate `m_{k+1}` from the FGLM algorithm as described in Wichmann [Wich1997]_.
69
+
70
+ .. NOTE::
71
+
72
+ It would be nice to be able to efficiently extract the smallest term of a polynomial.
73
+
74
+ EXAMPLES::
75
+
76
+ sage: from sage.rings.polynomial.pbori.pbori import *
77
+ sage: from sage.rings.polynomial.pbori.PyPolyBoRi import OrderCode
78
+ sage: from sage.rings.polynomial.pbori.fglm import m_k_plus_one
79
+ sage: dp_asc = OrderCode.dp_asc
80
+ sage: from sage.rings.polynomial.pbori.PyPolyBoRi import Ring
81
+ sage: r = Ring(1000)
82
+ sage: x = r.variable
83
+ sage: from sage.rings.polynomial.pbori.PyPolyBoRi import Monomial
84
+ sage: s = BooleSet([x(1)*x(2),x(1),x(2),Monomial(r),x(3)])
85
+ sage: variables = BooleSet([x(1),x(2),x(3)])
86
+ sage: m_k_plus_one(s,variables)
87
+ x(2)*x(3)
88
+ sage: r2 = r.clone(ordering=dp_asc)
89
+ sage: m_k_plus_one(r2(s).set(),r2(variables).set())
90
+ x(1)*x(3)
91
+ """
92
+ return sorted(completed_elements.cartesian_product(variables).diff(
93
+ completed_elements))[0]
@@ -0,0 +1,70 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ # Import basic functionality
4
+ r"""
5
+ This module defines an initial ring, and patches the declare_ring to use
6
+ a given context.
7
+
8
+ EXAMPLES::
9
+
10
+ sage: from sage.rings.polynomial.pbori.frontend import x
11
+ sage: x(0)
12
+ x(0)
13
+ sage: x(0)*x(0)
14
+ x(0)
15
+ sage: x(0) + x(0)
16
+ 0
17
+ sage: x(9999)
18
+ x(9999)
19
+ sage: x(9999)*x(9999)
20
+ x(9999)
21
+ sage: x(9999) + x(9999)
22
+ 0
23
+
24
+ sage: from sage.rings.polynomial.pbori.frontend import x, polybori_start
25
+ sage: context = dict(globals())
26
+ sage: polybori_start(context)
27
+ ipbori...
28
+ sage: r = context['declare_ring']('abc')
29
+ sage: context['a']
30
+ a
31
+ sage: r.variable(0)
32
+ a
33
+ """
34
+
35
+
36
+ from sage.rings.polynomial.pbori.blocks import declare_ring as orig_declare_ring
37
+ from sage.rings.polynomial.pbori.pbori import VariableFactory
38
+ from sage.rings.polynomial.pbori.PyPolyBoRi import Ring
39
+
40
+
41
+ def block_scheme_names(blocks):
42
+ r"""
43
+ Helper for Singular interface.
44
+ """
45
+ context = {}
46
+ from .blocks import declare_block_scheme
47
+ declare_block_scheme(blocks, context)
48
+
49
+ return list(context.keys())
50
+
51
+
52
+ ipbname = 'ipbori'
53
+
54
+
55
+ def polybori_start(global_context):
56
+ def declare_ring(blocks, context=None):
57
+ if context is None:
58
+ context = global_context
59
+
60
+ return orig_declare_ring(blocks, context)
61
+ declare_ring.__doc__ = orig_declare_ring.__doc__
62
+ global_context["declare_ring"] = declare_ring
63
+
64
+ print(ipbname + """ -- The interactive command line tool of PolyBoRi/BRiAL %s
65
+ """ % global_context.get("polybori_version", ''))
66
+
67
+
68
+ # Here come the defaults
69
+ r = Ring(10000)
70
+ x = VariableFactory(r)