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,129 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ import base64 as uu
4
+ import gzip
5
+ import re
6
+ from io import StringIO
7
+ from types import ModuleType
8
+
9
+ from sage.rings.polynomial.pbori.PyPolyBoRi import Polynomial
10
+
11
+ AUTO = "auto"
12
+ SINGLE = "single"
13
+
14
+
15
+ # def ref_file_name(f):
16
+ # name=re.sub("data/","",f)
17
+ # name=sub(r"\.py","",name)
18
+ # l=name.split("/")[:-1]
19
+
20
+
21
+ def reencode_blocks(block_str):
22
+ return str(block_str).replace(",", "_")
23
+
24
+
25
+ def parse_blocks(block_str, data):
26
+ if block_str == AUTO:
27
+ return data.block_start_hints
28
+ if block_str == SINGLE:
29
+ return []
30
+ return [int(i) for i in block_str.split(",")]
31
+
32
+
33
+ def load_ref_raw(s):
34
+ s = re.sub("data/", "", s)
35
+ s = re.sub(r"data\.", "", s)
36
+ s = re.sub(r"\.py", "", s)
37
+ s = re.sub(r"\.", "/", s)
38
+
39
+ ref_file = "ref/" + s + ".ref"
40
+ with open(ref_file) as res_f:
41
+ res = res_f.read()
42
+ return res
43
+
44
+
45
+ def load_ref(s, ordering='lp', blocks=SINGLE):
46
+ return load_ref_gz_uu(s, ordering, blocks)
47
+
48
+
49
+ def ordering_suffix(o, blocks=None):
50
+ if o == "lp":
51
+ return ""
52
+ if re.match("block", o):
53
+ return "." + o + "_" + reencode_blocks(blocks)
54
+ return "." + o
55
+
56
+
57
+ def number_of_declared_vars(data):
58
+ try:
59
+ return data.number_of_declared_vars
60
+ except AttributeError:
61
+ return data.r.ngens()
62
+
63
+
64
+ def load_ref_gz_uu(s, o, b):
65
+ s = re.sub("data/", "", s)
66
+ s = re.sub(r"data\.", "", s)
67
+ s = re.sub(r"\.py", "", s)
68
+ s = re.sub(r"\.", "/", s)
69
+
70
+ ref_file = "ref/" + s + ordering_suffix(o, b) + ".ref.gz.uu"
71
+ res = StringIO()
72
+ uu.decode(ref_file, res)
73
+ res = res.getvalue()
74
+ res = StringIO(res)
75
+ res = gzip.GzipFile(fileobj=res, mode='r').read()
76
+ res = res.replace(" ", "")
77
+ return res
78
+
79
+
80
+ def convert_refs(ref_file_orig):
81
+ with open(ref_file_orig) as file:
82
+ content = file.read()
83
+ buf_out = StringIO()
84
+ zipped = gzip.GzipFile(filename=ref_file_orig, mode='w', fileobj=buf_out)
85
+ zipped.write(content)
86
+ zipped.close()
87
+ val = buf_out.getvalue()
88
+ with open(ref_file_orig + ".gz.uu", "w") as out:
89
+ uu.encode(out_file=out, in_file=StringIO(val))
90
+
91
+
92
+ def dyn_generate(content, name):
93
+ module = ModuleType(name)
94
+ import_header = """from .PyPolyBoRi import Variable,Monomial, Polynomial, Ring, OrderCode
95
+ from itertools import chain
96
+ from .blocks import AlternatingBlock,Block,AdderBlock,if_then,HigherOrderBlock,declare_ring as orig_declare_ring,declare_block_scheme,MacroBlock\n
97
+ def declare_ring(blocks, context=None):
98
+ if context is None:
99
+ context=globals()
100
+ return orig_declare_ring(blocks,context)
101
+ """
102
+ exec(import_header + content, module.__dict__)
103
+ if hasattr(module, "ideal"):
104
+ module.ideal = [Polynomial(p) for p in module.ideal]
105
+ return module
106
+
107
+
108
+ def clean_data(data):
109
+ for a in dir(data):
110
+ if a != "r":
111
+ delattr(data, a)
112
+
113
+
114
+ def load_data(file_name, base_dir='./'):
115
+ in_file = file_name
116
+ if not re.match("^data", in_file):
117
+ in_file = "data/" + in_file
118
+ in_file = re.sub(r".py$", "", in_file)
119
+ in_file = re.sub(r"\.", "/", in_file)
120
+ in_file = in_file + ".py"
121
+ with open(base_dir + in_file) as f:
122
+ in_file = f.read()
123
+ return dyn_generate(in_file, "pb_data")
124
+
125
+
126
+ def load_file(file_name):
127
+ with open(file_name) as f:
128
+ in_file = f.read()
129
+ return dyn_generate(in_file, "pb_data")
@@ -0,0 +1,35 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ from sage.rings.polynomial.pbori.PyPolyBoRi import Polynomial, gauss_on_polys
4
+
5
+
6
+ def dense_system(I):
7
+ I = (Polynomial(p) for p in I)
8
+ I = (p for p in I if not p.is_zero())
9
+ for p in I:
10
+ d = p.deg()
11
+ if d == 1:
12
+ continue
13
+ try:
14
+ if len(p) > 2**d + 5:
15
+ return True
16
+ except OverflowError:
17
+ return True
18
+ return False
19
+
20
+
21
+ def gauss_on_linear(I):
22
+ I = (Polynomial(p) for p in I)
23
+ linear = []
24
+ non_linear = []
25
+ for p in I:
26
+ if p.is_zero():
27
+ continue
28
+ if p.deg() <= 1:
29
+ linear.append(p)
30
+ else:
31
+ non_linear.append(p)
32
+ if not linear:
33
+ return non_linear
34
+ linear = list(gauss_on_polys(linear))
35
+ return linear + non_linear
@@ -0,0 +1,122 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ # Copyright (c) 2005-2007 by The PolyBoRi Team
4
+ from random import Random
5
+ from time import process_time as clock
6
+
7
+ from sage.rings.polynomial.pbori.blocks import Block, declare_ring
8
+ from sage.rings.polynomial.pbori.pbori import (
9
+ BooleSet,
10
+ Monomial,
11
+ Polynomial,
12
+ Variable,
13
+ add_up_polynomials,
14
+ interpolate,
15
+ interpolate_smallest_lex,
16
+ )
17
+ from sage.rings.polynomial.pbori.PyPolyBoRi import (
18
+ BoolePolynomialVector,
19
+ )
20
+ from sage.rings.polynomial.pbori.randompoly import gen_random_poly
21
+
22
+ generator = Random()
23
+
24
+
25
+ def add_up_poly_list(l, init):
26
+ v = BoolePolynomialVector()
27
+ for p in l:
28
+ v.append(p)
29
+ return add_up_polynomials(v, init)
30
+
31
+
32
+ def bench_interpolate(degree, nvariables, points):
33
+ c = points
34
+ h = len(points) / 2
35
+ terms = set(c.terms())
36
+ part1 = generator.sample(terms, h)
37
+ part1 = add_up_poly_list(part1, Polynomial(c.ring().zero()))
38
+ part2 = c + part1
39
+ p = part1
40
+ q = part2
41
+ assert part1.set().intersect(part2).empty()
42
+ c1 = clock()
43
+ res2 = interpolate_smallest_lex(p, q)
44
+ c2 = clock()
45
+ print("finished interpolate_smallest_lex(p,q),len:", len(res2),
46
+ "time", c2 - c1)
47
+ c1 = clock()
48
+ res1 = interpolate(p, q)
49
+ c2 = clock()
50
+ print("finished interpolate(p,q)" + len("_smallest_lex") * " " + ",len:",
51
+ res1.set().size_double(), "time:", c2 - c1)
52
+ return res2
53
+
54
+
55
+ def nf_lex_points(f, p):
56
+ f = Polynomial(f)
57
+ p = BooleSet(p)
58
+ z = f.zeros_in(p)
59
+ return interpolate_smallest_lex(z, p.diff(z))
60
+
61
+
62
+ def gen_random_o_z(points, points_p):
63
+ k = generator.randrange(len(points) + 1)
64
+ ones = generator.sample(points, k)
65
+ vec = BoolePolynomialVector()
66
+ for p in ones:
67
+ vec.append(p)
68
+ ones = add_up_polynomials(vec, Polynomial(points_p.ring().zero()))
69
+ return interpolate_smallest_lex(points_p.set().diff(ones), ones)
70
+
71
+
72
+ def variety_lex_leading_terms(points, variables):
73
+ assert isinstance(points, BooleSet), "Points needs to be a BooleSet"
74
+ ring = variables.ring()
75
+ standards = BooleSet(ring.zero())
76
+ points_tuple = tuple(points)
77
+ myvars_div = variables.divisors()
78
+ if points != myvars_div:
79
+ standards = BooleSet(ring.one())
80
+ len_standards = len(standards)
81
+ standards_old = standards
82
+ while len_standards < len(points):
83
+ standards = standards.union(gen_random_o_z(points_tuple, points))
84
+
85
+ if standards_old != standards:
86
+ standards = BooleSet(standards).include_divisors()
87
+ len_standards = len(standards)
88
+ standards_old = standards
89
+
90
+ return BooleSet(myvars_div.diff(standards)).minimal_elements()
91
+
92
+
93
+ def lex_groebner_basis_points(points, variables):
94
+ leads = variety_lex_leading_terms(points, variables)
95
+ return [nf_lex_points(l, points) + l for l in leads]
96
+
97
+
98
+ def lex_groebner_basis_for_polynomial_via_variety(p):
99
+ variables = p.vars_as_monomial()
100
+ return lex_groebner_basis_points(p.zeros_in(variables.divisors()),
101
+ variables)
102
+
103
+
104
+ if __name__ == '__main__':
105
+ nvariables = 100
106
+ r = declare_ring([Block("x", nvariables)])
107
+ for number_of_points in (100, 500, 1000, 2000, 3000,
108
+ 4000, 5000, 10000,
109
+ 20000, 50000, 100000):
110
+ print("----------")
111
+ print("number_of_points:", number_of_points)
112
+ print("generate points")
113
+ points = gen_random_poly(r, number_of_points,
114
+ nvariables,
115
+ [Variable(i, r) for i in range(nvariables)])
116
+ print("points generated")
117
+ bench_interpolate(nvariables, nvariables, points)
118
+ vars_mon = Monomial(r)
119
+ for i in reversed(range(nvariables)):
120
+ vars_mon = vars_mon * Variable(i, r)
121
+ print(len(variety_lex_leading_terms(points, vars_mon)),
122
+ "elements in groebner basis")
@@ -0,0 +1,34 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ from sage.rings.polynomial.pbori.pbori import Polynomial, ReductionStrategy
4
+
5
+
6
+ def interred(l, completely=False):
7
+ r"""
8
+ Compute a new generating system (g1, ...,gn),
9
+ spanning the same ideal modulo field equations.
10
+
11
+ The system is interreduced: For i!=j:
12
+ gi.lead() does not divide any leading term of gj.
13
+
14
+ If completely is set to ``True``, then also terms in the
15
+ tail are not reducible by other polynomials.
16
+ """
17
+ l = [Polynomial(p) for p in l if p != 0]
18
+ if not l:
19
+ return []
20
+ ring = l[0].ring()
21
+ l_old = None
22
+ l = tuple(l)
23
+ while l_old != l:
24
+ l_old = l
25
+ l = sorted(l, key=Polynomial.lead)
26
+ g = ReductionStrategy(ring)
27
+ if completely:
28
+ g.opt_red_tail = True
29
+ for p in l:
30
+ gp = g.nf(p)
31
+ if not gp.is_zero():
32
+ g.add_generator(gp)
33
+ l = tuple(e.p for e in g)
34
+ return l
@@ -0,0 +1,302 @@
1
+ # sage_setup: distribution = sagemath-brial
2
+ # sage.doctest: needs sage.rings.polynomial.pbori
3
+ from sage.rings.polynomial.pbori.pbori import (
4
+ BooleSet,
5
+ Monomial,
6
+ Polynomial,
7
+ if_then_else,
8
+ ll_red_nf_noredsb,
9
+ ll_red_nf_noredsb_single_recursive_call,
10
+ ll_red_nf_redsb,
11
+ substitute_variables,
12
+ top_index,
13
+ )
14
+ from sage.rings.polynomial.pbori.PyPolyBoRi import (
15
+ BoolePolynomialVector,
16
+ Ring,
17
+ )
18
+ from sage.rings.polynomial.pbori.rank import rank
19
+ from sage.rings.polynomial.pbori.statistics import used_vars_set
20
+
21
+ lead_index = top_index
22
+
23
+
24
+ def combine(reductors, p, reduce=None):
25
+ p_nav = p.navigation()
26
+ assert p_nav.value() < reductors.navigation().value()
27
+ p_else = BooleSet(p_nav.else_branch(), p.ring())
28
+ if reduce:
29
+ p_else = reduce(p_else, reductors)
30
+ return if_then_else(p_nav.value(), reductors, p_else)
31
+
32
+
33
+ def llredsb_Cudd_style(polys):
34
+
35
+ reductors = Polynomial(polys[0].ring().one()).set() if polys else None
36
+
37
+ linear_lead = sorted(polys, key=lead_index, reverse=True)
38
+ assert len({p.lex_lead() for p in linear_lead}) == len(polys)
39
+ assert not any(p.constant() for p in polys)
40
+ assert len([p for p in polys if p.lex_lead_deg() == 1]) == len(polys)
41
+ assert len({p.navigation().value() for p in polys}) == len(polys)
42
+ for p in linear_lead:
43
+ reductors = combine(reductors, p, reduce=ll_red_nf_redsb)
44
+ return reductors
45
+
46
+
47
+ def ll_encode(polys, reduce=False, prot=False, reduce_by_linear=True):
48
+ polys = [Polynomial(p) for p in polys]
49
+ linear_lead = sorted(polys, key=lead_index, reverse=True)
50
+ assert len({p.lex_lead() for p in linear_lead}) == len(polys)
51
+ assert not any(p.constant() for p in polys)
52
+ assert len([p for p in polys if p.lex_lead_deg() == 1]) == len(polys)
53
+ assert len({p.navigation().value() for p in polys}) == len(polys)
54
+ if (not reduce) and reduce_by_linear:
55
+ linear_polys = [p for p in polys if p.deg() == 1]
56
+ if linear_polys:
57
+ linear_ll = ll_encode(linear_polys, reduce=True,
58
+ reduce_by_linear=False)
59
+ polys = [p.lex_lead() + ll_red_nf_redsb(p + p.lex_lead(),
60
+ linear_ll) for p in polys]
61
+ reduce = ll_red_nf_redsb if reduce else None
62
+
63
+ reductors = Polynomial(polys[0].ring().one()).set() if polys else None
64
+
65
+ last = None
66
+ counter = 0
67
+ for p in linear_lead:
68
+
69
+ if prot:
70
+ counter = counter + 1
71
+ progress = (counter * 100) / len(linear_lead)
72
+ if last != progress:
73
+ print(str(progress) + "%")
74
+ last = progress
75
+ reductors = combine(reductors, p, reduce=reduce)
76
+ return reductors
77
+
78
+
79
+ def eliminate(polys, on_the_fly=False, prot=False, reduction_function=None,
80
+ optimized=True):
81
+ r"""
82
+ There exists an optimized variant, which reorders the variable in a different ring.
83
+ """
84
+ polys = [Polynomial(p) for p in polys]
85
+ rest = []
86
+ linear_leads = []
87
+ linear_leading_monomials = set()
88
+ for p in polys:
89
+ if p.is_zero():
90
+ continue
91
+ lm = p.lex_lead()
92
+ if lm.deg() == 1:
93
+
94
+ if lm not in linear_leading_monomials:
95
+ linear_leading_monomials.add(lm)
96
+ linear_leads.append(p)
97
+ else:
98
+ rest.append(p)
99
+ else:
100
+ rest.append(p)
101
+ if not linear_leads:
102
+ def identity(p):
103
+ return p
104
+ return (linear_leads, identity, rest)
105
+ if reduction_function is None:
106
+ if on_the_fly:
107
+ if optimized:
108
+ reduction_function = ll_red_nf_noredsb_single_recursive_call
109
+ else:
110
+ reduction_function = ll_red_nf_noredsb
111
+ else:
112
+ reduction_function = ll_red_nf_redsb
113
+
114
+ if optimized:
115
+ llnf, reduced_list = eliminate_ll_ranked(linear_leads, rest,
116
+ reduction_function=reduction_function,
117
+ reduce_ll_system=(not on_the_fly),
118
+ prot=prot)
119
+ else:
120
+ def llnf(p):
121
+ return reduction_function(p, reductors)
122
+ reduced_list = []
123
+ reductors = ll_encode(linear_leads, reduce=(not on_the_fly), prot=prot)
124
+ for p in rest:
125
+ rp = reduction_function(p, reductors)
126
+ if rp.is_one():
127
+ reduced_list = [rp]
128
+ break
129
+ reduced_list.append(rp)
130
+
131
+ return (linear_leads, llnf, reduced_list)
132
+
133
+
134
+ def construct_map_by_indices(to_ring, idx_mapping):
135
+ v = BoolePolynomialVector((max(idx_mapping.keys()) + 1) * [to_ring.zero()])
136
+ for (from_idx, to_idx) in idx_mapping.items():
137
+ val = to_ring.variable(to_idx)
138
+ v[from_idx] = val
139
+ return v
140
+
141
+
142
+ def eliminate_ll_ranked(ll_system, to_reduce,
143
+ reduction_function=ll_red_nf_noredsb,
144
+ reduce_ll_system=False, prot=False):
145
+
146
+ assert ll_system
147
+ from_ring = ll_system[0].ring()
148
+
149
+ ll_ranks = rank(ll_system)
150
+ add_vars = set(used_vars_set(to_reduce).variables()).difference(ll_ranks.
151
+ keys())
152
+ for v in add_vars:
153
+ ll_ranks[v] = -1
154
+
155
+ # pushing variables ignored by ll to the front means,
156
+ # that the routines will quickly eliminate them
157
+ # and they won't give any overhead
158
+ def sort_key(v):
159
+ return (ll_ranks[v], v.index())
160
+ sorted_vars = sorted(ll_ranks.keys(), key=sort_key)
161
+
162
+ def var_index(v):
163
+ return next(iter(Monomial(v).variables())).index()
164
+
165
+ to_ring = Ring(len(sorted_vars))
166
+ map_back_indices = {i: var_index(v) for i, v in enumerate(sorted_vars)}
167
+ map_from_indices = {var_index(v): i for i, v in enumerate(sorted_vars)}
168
+
169
+ var_names = [str(v) for v in sorted_vars]
170
+ try:
171
+ for (i, v) in enumerate(sorted_vars):
172
+ assert var_names[i] == str(v), (var_names[i], v, var_index(v), i)
173
+
174
+ finally:
175
+ pass
176
+ try:
177
+ map_from_vec = construct_map_by_indices(to_ring, map_from_indices)
178
+ finally:
179
+ pass
180
+ map_back_vec = construct_map_by_indices(from_ring, map_back_indices)
181
+
182
+ def map_from(p):
183
+ res = substitute_variables(to_ring, map_from_vec, p)
184
+ return res
185
+
186
+ def map_back(p):
187
+ return substitute_variables(from_ring, map_back_vec, p)
188
+
189
+ try:
190
+ ll_opt_encoded = ll_encode([map_from(p) for p in ll_system],
191
+ prot=False,
192
+ reduce=reduce_ll_system)
193
+
194
+ def llnf(p):
195
+ return map_back(reduction_function(map_from(p), ll_opt_encoded))
196
+ opt_eliminated = [llnf(p) for p in to_reduce]
197
+ finally:
198
+ pass
199
+ return (llnf, opt_eliminated)
200
+
201
+
202
+ class RingMap:
203
+ r"""
204
+ Define a mapping between two rings by common variable names.
205
+
206
+ TESTS::
207
+
208
+ sage: from sage.rings.polynomial.pbori.pbori import *
209
+ sage: from sage.rings.polynomial.pbori.blocks import declare_ring, Block
210
+ sage: to_ring = declare_ring([Block("x", 10)], globals())
211
+ sage: from_ring = declare_ring([Block("y", 5), Block("x", 10)], globals())
212
+ sage: from sage.rings.polynomial.pbori.ll import RingMap
213
+ sage: mapping = RingMap(to_ring, from_ring)
214
+ sage: (x(1)+1).navigation().value()
215
+ 6
216
+ sage: mapping(x(1)+1)
217
+ x(1) + 1
218
+ sage: mapping(x(1)+1).navigation().value()
219
+ 1
220
+ sage: mapping.invert(mapping(x(1)+1))
221
+ x(1) + 1
222
+ sage: mapping.invert(mapping(x(1)+1)).navigation().value()
223
+ 6
224
+ sage: mapping(y(1)+1)
225
+ Traceback (most recent call last):
226
+ ...
227
+ RuntimeError: Operands come from different manager.
228
+ """
229
+
230
+ def __init__(self, to_ring, from_ring):
231
+ r"""
232
+ Initialize map by two given rings.
233
+
234
+ TESTS::
235
+
236
+ sage: from sage.rings.polynomial.pbori.pbori import *
237
+ sage: from sage.rings.polynomial.pbori.blocks import declare_ring, Block
238
+ sage: to_ring = declare_ring([Block("x", 10)], globals())
239
+ sage: from_ring = declare_ring([Block("y", 5), Block("x", 10)], globals())
240
+ sage: from sage.rings.polynomial.pbori.ll import RingMap
241
+ sage: mapping = RingMap(to_ring, from_ring)
242
+ sage: mapping(x(1)+1)
243
+ x(1) + 1
244
+ """
245
+ def vars(ring):
246
+ return [ring.variable(i) for i in range(ring.n_variables())]
247
+
248
+ def indices(vars):
249
+ return {str(v): idx for idx, v in enumerate(vars)}
250
+
251
+ self.to_ring = to_ring
252
+ self.from_ring = from_ring
253
+ to_vars = vars(to_ring)
254
+ from_vars = vars(from_ring)
255
+ to_indices = indices(to_vars)
256
+ from_indices = indices(from_vars)
257
+ common = list(set(to_indices.keys()) & set(from_indices.keys()))
258
+
259
+ to_map = list(from_vars)
260
+ for elt in common:
261
+ to_map[from_indices[elt]] = to_vars[to_indices[elt]]
262
+
263
+ from_map = list(to_vars)
264
+ for elt in common:
265
+ from_map[to_indices[elt]] = from_vars[from_indices[elt]]
266
+
267
+ self.to_map = BoolePolynomialVector(to_map)
268
+ self.from_map = BoolePolynomialVector(from_map)
269
+
270
+ def __call__(self, poly):
271
+ r"""
272
+ Execute the map to change rings.
273
+
274
+ TESTS::
275
+
276
+ sage: from sage.rings.polynomial.pbori.pbori import *
277
+ sage: from sage.rings.polynomial.pbori.blocks import declare_ring, Block
278
+ sage: to_ring = declare_ring([Block("x", 10)], globals())
279
+ sage: from_ring = declare_ring([Block("y", 5), Block("x", 10)], globals())
280
+ sage: from sage.rings.polynomial.pbori.ll import RingMap
281
+ sage: mapping = RingMap(to_ring, from_ring)
282
+ sage: mapping(x(1)+1)
283
+ x(1) + 1
284
+ """
285
+ return substitute_variables(self.to_ring, self.to_map, poly)
286
+
287
+ def invert(self, poly):
288
+ r"""
289
+ Inverted map to initial ring.
290
+
291
+ EXAMPLES::
292
+
293
+ sage: from sage.rings.polynomial.pbori.pbori import *
294
+ sage: from sage.rings.polynomial.pbori.blocks import declare_ring, Block
295
+ sage: to_ring = declare_ring([Block("x", 10)], globals())
296
+ sage: from_ring = declare_ring([Block("y", 5), Block("x", 10)], globals())
297
+ sage: from sage.rings.polynomial.pbori.ll import RingMap
298
+ sage: mapping = RingMap(to_ring, from_ring)
299
+ sage: mapping.invert(mapping(x(1)+1))
300
+ x(1) + 1
301
+ """
302
+ return substitute_variables(self.from_ring, self.from_map, poly)