def __init__(self, base_ring, coordinate): self.coordinate = coordinate self.Vector = flatsurf.Vector._unwrapped[self.coordinate] self._isomorphic_vector_space = FreeModule(base_ring, 2) if isinstance(base_ring, real_embedded_number_field.RealEmbeddedNumberField): self._isomorphic_vector_space = FreeModule(base_ring.number_field, 2) Parent.__init__(self, base_ring, category=FreeModules(base_ring)) self.register_coercion(self._isomorphic_vector_space) self._isomorphic_vector_space.register_conversion(ConversionVectorSpace(self))
def min_reol_maybe_with3gens(data): forms = data.relatively_prime_3forms_maybe() d = data.brackets_dict if forms is None: return None F = FreeModule(R, 2) f, g, h = forms e0, e1 = F.gens() a = d[(g, h)] b = -d[(f, h)] c = d[(f, g)] f = e0 * c g = e1 * c h = -(a * e0 + b * e1) if c.degree() > 0: n = smodule(f, h) idl = sideal(b) m = squotient(n, idl) else: m = smodule(f, g) wts = data.weight_of_basis() mls = list(takewhile(lambda l: any(x != 0 for x in l), slist(smres(m, 0)))) mls = [[list(v) for v in list(l)] for l in mls] wts_of_mls = [] wts_of_mls.append([degree_vec(v, wts) for v in mls[0]]) for i, l in enumerate(mls[1:]): wts = wts_of_mls[i] wts_of_mls.append([degree_vec(v, wts) for v in l]) return (mls, wts_of_mls, (forms[0], forms[1], c))
def is_product(n, den_tuple): r""" INPUT: - ``n`` - number of variables - ``den_tuple`` - tuple of pairs ``(vector, power)`` TESTS:: sage: from surface_dynamics.misc.generalized_multiple_zeta_values import is_product sage: is_product(3, [((1,0,0),2), ((0,1,0),5), ((1,1,0),1), ((0,0,1),3)]) [(2, (((0, 1), 5), ((1, 0), 2), ((1, 1), 1))), (1, (((1), 3),))] sage: is_product(3, [((1,0,0),2), ((0,1,0),3), ((1,0,1),1), ((0,0,1),5)]) [(2, (((0, 1), 5), ((1, 0), 2), ((1, 1), 1))), (1, (((1), 3),))] sage: is_product(3, [((1,1,1),3)]) is None True """ D = DisjointSet(n) assert all(len(v) == n for v, p in den_tuple), (n, den_tuple) # 1. product structure for v, _ in den_tuple: i0 = 0 while not v[i0]: i0 += 1 i = i0 + 1 while i < n: if v[i]: D.union(i0, i) i += 1 if D.number_of_subsets() == 1: # no way to split variables return # split variables Rdict = D.root_to_elements_dict() keys = sorted(Rdict.keys()) key_indices = {k: i for i, k in enumerate(keys)} values = [Rdict[k] for k in keys] values_indices = [{v: i for i, v in enumerate(v)} for v in values] n_list = [len(J) for J in values] F = [FreeModule(ZZ, nn) for nn in n_list] new_terms = [[] for _ in range(len(Rdict))] for v, p in den_tuple: i0 = 0 while not v[i0]: i0 += 1 i0 = D.find(i0) assert all(D.find(i) == i0 for i in range(n) if v[i]), (i0, [D.find(i) for i in range(n) if v[i]]) k = key_indices[i0] vv = F[k]() for i in range(n): if v[i]: vv[values_indices[k][i]] = v[i] vv.set_immutable() new_terms[k].append((vv, p)) return list(zip(n_list, [tuple(sorted(terms)) for terms in new_terms]))
def __init__(self, surface): if isinstance(surface, TranslationSurface): base_ring = surface.base_ring() from flatsurf.geometry.pyflatsurf_conversion import to_pyflatsurf self._surface = to_pyflatsurf(surface) else: from flatsurf.geometry.pyflatsurf_conversion import sage_base_ring base_ring, _ = sage_base_ring(surface) self._surface = surface # A model of the vector space R² in libflatsurf, e.g., to represent the # vector associated to a saddle connection. self.V2 = pyflatsurf.vector.Vectors(base_ring) # We construct a spanning set of edges, that is a subset of the # edges that form a basis of H_1(S, Sigma; Z) # It comes together with a projection matrix t, m = self._spanning_tree() assert set(t.keys()) == set(f[0] for f in self._faces()) self.spanning_set = [] v = set(t.values()) for e in self._surface.edges(): if e.positive() not in v and e.negative() not in v: self.spanning_set.append(e) self.d = len(self.spanning_set) assert 3*self.d - 3 == self._surface.size() assert m.rank() == self.d m = m.transpose() # projection matrix from Z^E to H_1(S, Sigma; Z) in the basis # of spanning edges self.proj = matrix(ZZ, [r for r in m.rows() if not r.is_zero()]) self.Omega = self._intersection_matrix(t, self.spanning_set) self.V = FreeModule(self.V2.base_ring(), self.d) self.H = matrix(self.V2.base_ring(), self.d, 2) for i in range(self.d): s = self._surface.fromHalfEdge(self.spanning_set[i].positive()) self.H[i] = self.V2._isomorphic_vector_space(self.V2(s)) self.Hdual = self.Omega * self.H # Note that we don't use Sage vector spaces because they are usually # way too slow (in particular we avoid calling .echelonize()) self._U = matrix(self.V2._algebraic_ring(), self.d) if self._U.base_ring() is not QQ: from sage.all import next_prime self._good_prime = self._U.base_ring().ideal(next_prime(2**30)).factor()[0][0] self._Ubar = matrix(self._good_prime.residue_field(), self.d) self._U_rank = 0 self.update_tangent_space_from_vector(self.H.transpose()[0]) self.update_tangent_space_from_vector(self.H.transpose()[1])
def test_skipper_cpa_enc(skipper=Skipper4, kyber=Kyber, t=128, l=None, exhaustive=False): if not exhaustive: for i in range(t): pk, sk = kyber.key_gen(seed=i) m0 = random_vector(GF(2), kyber.n) c = skipper.enc(kyber, pk, m0, seed=i, l=l) m1 = kyber.dec(sk, c) assert(m0 == m1) else: # exhaustive test for i in range(16): pk, sk = kyber.key_gen(seed=i) for m0 in FreeModule(GF(2), kyber.n): c = skipper.enc(kyber, pk, m0, seed=i, l=l) m1 = kyber.dec(sk, c) assert(m0 == m1)
def boundaries(self): r""" Return the list of boundaries (ie sum of edges around a triangular face). These are elements of H_1(S, Sigma; Z). TESTS:: sage: from flatsurf import polygons, similarity_surfaces sage: from flatsurf import GL2ROrbitClosure # optional: pyflatsurf sage: from itertools import product sage: for a in range(1,5): # optional: pyflatsurf ....: for b in range(a, 5): ....: for c in range(b, 5): ....: if gcd([a, b, c]) != 1 or (a,b,c) == (1,1,2): ....: continue ....: T = polygons.triangle(a, b, c) ....: S = similarity_surfaces.billiard(T) ....: S = S.minimal_cover(cover_type="translation") ....: O = GL2ROrbitClosure(S) ....: for b in O.boundaries(): ....: assert (O.proj * b).is_zero() """ n = self._surface.size() V = FreeModule(ZZ, n) B = [] for (f1,f2,f3) in self._faces(): i1 = f1.index() s1 = -1 if i1%2 else 1 i2 = f2.index() s2 = -1 if i2%2 else 1 i3 = f3.index() s3 = -1 if i3%2 else 1 i1 = f1.edge().index() i2 = f2.edge().index() i3 = f3.edge().index() v = [0] * n v[i1] = 1 v[i2] = s1 * s2 v[i3] = s1 * s3 B.append(V(v)) B[-1].set_immutable() return B
def linear_forms(d): r""" EXAMPLES:: sage: from surface_dynamics.misc.generalized_multiple_zeta_values import linear_forms sage: list(linear_forms(1)) [(1)] sage: list(linear_forms(2)) [(1, 0), (0, 1), (1, 1)] sage: L1 = list(linear_forms(3)) sage: L2 = L1[:] sage: L2.sort(key = lambda x: x[::-1]) sage: assert L1 == L2 """ F = FreeModule(ZZ, d) for n in range(1, 2**d): v = F(ZZ(n).digits(2, padto=d)) v.set_immutable() yield v
def is_reducible(n, den_tuple): r""" If (x1+x2+...+xd) is not present, use a linear relation to create it. Then try to kill using other forms. Then try to write as P(x1,x2,...,x_{d-1}) (x1+x2+...+xd) and recurse. Should solve all Tonrheim EXAMPLES:: sage: from surface_dynamics.misc.generalized_multiple_zeta_values import linear_forms, is_reducible sage: va, vb, vd, vc, ve, vf, vg = linear_forms(3) sage: is_reducible(3, ((va,3),(vb,3),(vc,3))) [(1, (((0, 0, 1), 3), ((0, 1, 1), 3), ((1, 1, 1), 3))), (1, (((0, 1, 0), 3), ((0, 1, 1), 3), ((1, 1, 1), 3))), (3, (((0, 0, 1), 2), ((0, 1, 1), 4), ((1, 1, 1), 3))), (3, (((0, 1, 0), 2), ((0, 1, 1), 4), ((1, 1, 1), 3))), ... (90, (((1, 0, 0), 1), ((1, 0, 1), 1), ((1, 1, 1), 7))), (90, (((0, 1, 0), 1), ((1, 1, 0), 1), ((1, 1, 1), 7))), (90, (((1, 0, 0), 1), ((1, 1, 0), 1), ((1, 1, 1), 7)))] """ F = FreeModule(ZZ, n) vmax = F([1] * n) vmax.set_immutable() if len(den_tuple) == 1: return # force the max vector (1,1,...,1) to appear imax = None for i, (v, p) in enumerate(den_tuple): if v == vmax: imax = i break if imax is None: imax = len(den_tuple) den_tuple = den_tuple + ((vmax, 0), ) if imax != len(den_tuple) - 1: den_tuple = list(den_tuple) den_tuple.append(den_tuple.pop(imax)) den_tuple = tuple(den_tuple) imax = len(den_tuple) - 1 assert den_tuple[imax][0] == vmax M = matrix(QQ, [v for v, p in den_tuple if v != vmax]) try: relation = M.solve_left(vmax) except ValueError: if den_tuple[-1][1] == 0: return den_tuple2 = den_tuple[:-1] variables = set().union(*[[i for i in range(n) if v[i]] for v, p in den_tuple2]) if len(variables) == n: return killed = [(1, den_tuple)] else: killed = kill_relation(n, den_tuple, imax, list(relation) + [0]) ans = defaultdict(QQ) for coeff, den_tuple2 in killed: assert den_tuple2[-1][0] == vmax pmax = den_tuple2[-1][1] assert pmax den_tuple2 = den_tuple2[:-1] variables = set().union(*[[i for i in range(n) if v[i]] for v, p in den_tuple2]) if len(variables) == n: # removing the maximal vector (1,1,...,1) is not enough to make a variable disappear data = is_reducible(n, den_tuple2) if data is None: data = [(1, den_tuple2)] else: # less variables! nn = len(variables) variables = sorted(variables) new_indices = {j: i for i, j in enumerate(variables)} G = FreeModule(ZZ, nn) new_den_tuple2 = [] for v, p in den_tuple2: vv = G([v[i] for i in variables]) vv.set_immutable() new_den_tuple2.append((vv, p)) new_den_tuple2 = tuple(new_den_tuple2) data = is_reducible(nn, new_den_tuple2) if data is None: data = [(1, new_den_tuple2)] # lift to the n variables version new_data = [] for coeff3, den_tuple3 in data: den_tuple3 = [(F([ v[new_indices[j]] if j in new_indices else 0 for j in range(n) ]), p) for v, p in den_tuple3] for v, p in den_tuple3: v.set_immutable() new_data.append((coeff3, tuple(sorted(den_tuple3)))) data = new_data # update the answer for coeff3, den_tuple3 in data: imax = None for i, (v, p) in enumerate(den_tuple3): if v == vmax: imax = i break if imax is None: den_tuple3 = den_tuple3 + ((vmax, pmax), ) else: den_tuple3 = den_tuple3[:imax] + ( (vmax, den_tuple3[imax][1] + pmax), ) + den_tuple3[imax + 1:] ans[den_tuple3] += coeff * coeff3 if len(ans) > 1: return [(coeff, den_tuple) for den_tuple, coeff in ans.items()]