def __init__(self, G, coloring, name=None, check=True): from flexible_rigid_graph import FlexRiGraph if type(G) == FlexRiGraph or 'FlexRiGraph' in str( type(G)) or isinstance(G, FlexRiGraph): self._graph = G else: raise exceptions.TypeError('The graph G must be FlexRiGraph.') if type(coloring) in [list, Set] and len(coloring) == 2: self._red_edges = Set([Set(e) for e in coloring[0]]) self._blue_edges = Set([Set(e) for e in coloring[1]]) elif type(coloring) == dict: self._red_edges = Set( [Set(e) for e in coloring if coloring[e] == 'red']) self._blue_edges = Set( [Set(e) for e in coloring if coloring[e] == 'blue']) elif type(coloring) == NACcoloring or isinstance( coloring, NACcoloring) or 'NACcoloring' in str(type(coloring)): self._red_edges = copy(coloring._red_edges) self._blue_edges = copy(coloring._blue_edges) else: raise exceptions.TypeError( 'The coloring must be a dict, list consisting of two lists or an instance of NACcoloring.' ) self._check_edges() self._name = name if check and not self.is_NAC_coloring(): raise exceptions.ValueError('The coloring is not a NAC-coloring.')
def _to_relaxed_matrix_bp(self, graph): # convert graph to a topological sorting of the vertices nodes = nx.topological_sort(graph.graph) # the accept vertex must be last a = nodes.index(('acc', graph.num)) b = nodes.index(('rej', graph.num)) if a < b: nodes[b], nodes[a] = nodes[a], nodes[b] # the source vertex must be first src = nodes.index(('src', graph.num)) nodes[0], nodes[src] = nodes[src], nodes[0] mapping = dict(zip(nodes, range(self.size))) g = nx.relabel_nodes(graph.graph, mapping) # convert graph to relaxed matrix BP self.bp = [] G = MatrixSpace(GF(2), self.size) for layer in xrange(self.nlayers): zero = copy(G.one()) one = copy(G.one()) for edge in g.edges_iter(): e = g[edge[0]][edge[1]] assert e['label'] in (0, 1) if g.node[edge[0]]['layer'] == layer: if e['label'] == 0: zero[edge[0], edge[1]] = 1 else: one[edge[0], edge[1]] = 1 self.bp.append(Layer(graph.inp(layer), zero, one)) self.zero = G.one()
def __init__(self, L, **MetaData): r""" NOTE: An instance of ``BarCode`` should not be directly constructed. Usually, it is obtained as output of :meth:`~pGroupCohomology.cohomology.COHO.bar_code` INPUT: ``L`` - a list of persistence data ``M`` - Metadata in the form of optional parameters ASSUMPTIONS: ``dict(L)`` should yield a dictionary whose keys give the positions and whose values give the marks of a persistence matrix. A persistence matrix is an upper triangular matrix whose marks are univariate power series with non-negative integer coefficients (Poincaré series). For each degree, the corresponding coefficients of the Poincaré series yield an upper triangular integer matrix with the additional property that the matrix columns are increasing from top to bottom and the maatrix rows are decreasing from left to right. However, this is not a sufficient condition. We are sorry for the fact that the numbering of rows and colums does not start with zero; instead, the numbering ranges from ``-d`` to ``d``, where ``d`` is given by the length of the normal series (non-trivial terms only) by which the bar code is defined. TESTS:: sage: from pGroupCohomology.barcode import BarCode sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: R.<t> = ZZ[] sage: L = [((-1, -1), -1/(t - 1)), ((-1, 0), -1/(t^2 - 1)), ((-1, 1), 1), ((0, 0), 1/(t^2 - 2*t + 1)), ((0, 1), (-t - 1)/(t - 1)), ((1, 1), 1/(t^2 - 2*t + 1))] sage: B = BarCode(L,ring='some ring') # indirect doctest sage: B Persistence data for some ring sage: ascii_art(B[3]) * * *-* *-* * * * """ from sage.all import copy self._Meta = copy(MetaData) self._L = dict(copy(L)) self._length = max([X[1] for X in self._L.keys()])
def compare_data(d1, d2, keylist=['dims', 'traces', 'polys', 'ALs', 'eigdata'], verbose=False): assert d1.keys() == d1.keys() QX = PolynomialRing(QQ, 'x') nforms = len(d1.keys()) nstep = ZZ(max(1, int(nforms / 20.0))) nf = 0 print("Comparing data for {} newforms".format(nforms)) for k in d1.keys(): nf += 1 if nf % nstep == 0: print("compared {}/{} ({:0.3f}%)".format(nf, nforms, 100.0 * nf / nforms)) if d1[k] != d2[k]: for key in keylist: # take copies! we want to be able to change these without affecting the input dicts t1 = copy(d1[k][key]) t2 = copy(d2[k][key]) if key == 'polys': n = len(t1) for i in range(n): if t1[i] != t2[i]: pol1 = QX(t1[i]) pol2 = QX(t2[i]) F1 = NumberField(pol1, 'a') F2 = NumberField(pol2, 'a') if F1.is_isomorphic(F2): pol1 = pol2 = F1.optimized_representation( )[0].defining_polynomial() t1[i] = t2[i] = list(pol1) if t1 != t2: if key == 'traces': print( "traces differ for {}: \nfirst #= {}, \nsecond #={}" .format(k, [len(t) for t in t1], [len(t) for t in t2])) print("first starts\t {}".format(t1[0][:10])) print("second starts\t {}".format(t2[0][:10])) elif key == 'eigdata': for f1, f2 in zip(t1, t2): ok, reason = compare_eigdata(k, f1, f2, verbose) if not ok: print("an do not match for (N,k,o)={}: {}". format(k, reason)) else: print("{} differ for {}: \nfirst {}, \nsecond {}". format(key, k, t1, t2))
def mul(self, a): assert a in ZZ if a == 1: return copy(self) if a == 0: return Divisor(self.Pic) if a < 0: self.neg().mul(-a) a = -a sign = 1 else: sign = 0 result = copy(self) negself = None #negselflower = None; n = floor(log(a, 2)) + 1 for i in range(n - 2, -1, -1): result = result.mDouble() sign = (sign + 1) % 2 if a & (1 << i): if sign == 1: if negself == None: negself = self.neg() # result = -correct tmp, lower = self.Pic.AddFlip(result.basis_RR, negself.basis_RR) lower = max(result.lower, lower, negself.lower) result = Divisor(self.Pic, basis_RR=tmp, lower=lower) #result = - (-correct - self) = self + correct sign = 0 else: #result = correct tmp, lower = self.Pic.AddFlip(result.basis_RR, self.basis_RR) lower = max(result.lower, lower, self.lower) result = Divisor(self.Pic, basis_RR=tmp, lower=lower) #result = -correct - self sign = 1 if sign == 1: result = result.neg() return result
def rrkc_precomputations(self): self.Li = [m.inverse() for m in self.Lt] self.LiK = [self.Kt[i + 1] * self.Li[i] for i in range(self.r)] self.LiC = [self.C[i] * self.Li[i] for i in range(self.r)] mod_Li = [copy(self.Li[i]) for i in range(self.r)] for j in range(self.r): mod_Li[j][self.n - 3 * self.s:, :self.n] = matrix( F, 3 * self.s, self.n) self.precomputed_key_matrix = None self.precomputed_key_matrix_nl = matrix(F, self.n, (self.s * 3) * self.r) self.precomputed_constant = None self.precomputed_constant_nl = vector(F, (self.s * 3) * self.r) for round in range(self.r): tmp = copy(self.LiK[round]) tmpC = copy(self.LiC[round]) for i in range(round + 1, self.r): x = self.LiK[i] c = self.LiC[i] for j in range(i - 1, round - 1, -1): x = x * mod_Li[j] c = c * mod_Li[j] tmp += x tmpC += c # non-linear part idx = round * (3 * self.s) self.precomputed_key_matrix_nl[:self.n, idx:idx + 3 * self.s] = tmp[:self.n, self.n - 3 * self.s:] self.precomputed_constant_nl[idx:idx + 3 * self.s] = tmpC[self.n - 3 * self.s:] # linear part if round == 0: tmp[:, self.n - 3 * self.s:] = matrix(F, self.n, 3 * self.s) tmpC[self.n - 3 * self.s:] = vector(F, 3 * self.s) self.precomputed_key_matrix = tmp self.precomputed_constant = tmpC self.rrkc_precomputations_done = True
def __init__(self,M=None,genus_list=None): #print genus_list if M: self.M = copy(M) elif genus_list: self.M = Matrix(StrataGraph.R,len(genus_list)+1,1,[-1]+genus_list) else: self.M = Matrix(StrataGraph.R,1,1,-1)
def show(self, *args, **kwds): r""" Show a 3D picture of self. INPUT: - ``dmin`` (default = 1): optional non-negative integer, the lowest shown degree - ``dmax`` (default = 10): optional non-negative integer, the highest shown degree The resulting picture combines the planar bar codes for each degree between ``dmin`` and ``dmax`` to a 3-dimensional arrangement of bars. TESTS:: sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(16,3) sage: H.make() sage: B = H.bar_code('LowerCentralSeries') sage: show(B,dmin=3,dmax=15) <html><script type="math/tex">\newcommand{\Bold}[1]{\mathbf{#1}}\verb|Persistence|\phantom{\verb!x!}\verb|data|\phantom{\verb!x!}\verb|for|\phantom{\verb!x!}\verb|H^*(SmallGroup(16,3);|\phantom{\verb!x!}\verb|GF(2))|\phantom{\verb!x!}\verb|associated|\phantom{\verb!x!}\verb|with|\phantom{\verb!x!}\verb|LowerCentralSeries|</script></html> For seeing a nice picture, you should instead do ``B.show(dmin=3, dmax=15)``. """ dmin = kwds.get('dmin', 1) dmax = kwds.get('dmax', 10) from sage.all import sphere, line if dmin >= dmax: raise ValueError( "Optional parameters dmin, dmax must satisfy dmin < dmax") bars = [self[i]._bars for i in range(dmin, dmax + 1)] G = None for d in range(0, dmax - dmin + 1): l = len(bars[d]) for B in range(l): if bars[d][B][0] != bars[d][B][1]: G += line( [(X, dmin + d, l + 1 - B) for X in range(bars[d][B][0], bars[d][B][1] + 1)], thickness=2) G = sum([ sphere(center=(X, dmin + d, l + 1 - B), size=0.1, color=(0, 0, 1)) for X in range(bars[d][B][0], bars[d][B][1] + 1) ], G) from sage.all import copy KWDS = copy(kwds) if 'dmin' in KWDS: del KWDS['dmin'] if 'dmax' in KWDS: del KWDS['dmax'] G.show(*args, **KWDS)
def __init__(self, M=None, genus_list=None): #print genus_list if M: self.M = copy(M) elif genus_list: self.M = Matrix(StrataGraph.R, len(genus_list) + 1, 1, [-1] + genus_list) else: self.M = Matrix(StrataGraph.R, 1, 1, -1)
def dual_multiplier(self): r""" Returns the dual multiplier of self. """ m = copy(self) m._is_dual = int(not self._is_dual) o = self._character.order() m._character = self._character**(o-1) m._weight = QQ(2) - QQ(self._weight) return m
def dual_multiplier(self): r""" Returns the dual multiplier of self. """ m = copy(self) m._is_dual = int(not self._is_dual) o = self._character.order() m._character = self._character**(o - 1) m._weight = QQ(2) - QQ(self.weight()) return m
def randomize(self, prime): assert not self.randomized MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), self.size) def random_matrix(): while True: m = MSZp.random_element() if not m.is_singular() and m.rank() == self.size: return m, m.inverse() m0, m0i = random_matrix() self.bp[0] = self.bp[0].group(MSZp, prime).mult_left(m0) for i in xrange(1, len(self.bp)): mi, mii = random_matrix() self.bp[i-1] = self.bp[i-1].group(MSZp, prime).mult_right(mii) self.bp[i] = self.bp[i].group(MSZp, prime).mult_left(mi) self.bp[-1] = self.bp[-1].group(MSZp, prime).mult_right(m0i) VSZp = VectorSpace(ZZ.residue_field(ZZ.ideal(prime)), self.size) self.s = copy(VSZp.zero()) self.s[0] = 1 self.t = copy(VSZp.zero()) self.t[len(self.t) - 1] = 1 self.m0, self.m0i = m0, m0i self.randomized = True
def randomize(self, prime): assert not self.randomized MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), self.size) def random_matrix(): while True: m = MSZp.random_element() if not m.is_singular() and m.rank() == self.size: return m, m.inverse() m0, m0i = random_matrix() self.bp[0] = self.bp[0].group(MSZp, prime).mult_left(m0) for i in xrange(1, len(self.bp)): mi, mii = random_matrix() self.bp[i - 1] = self.bp[i - 1].group(MSZp, prime).mult_right(mii) self.bp[i] = self.bp[i].group(MSZp, prime).mult_left(mi) self.bp[-1] = self.bp[-1].group(MSZp, prime).mult_right(m0i) VSZp = VectorSpace(ZZ.residue_field(ZZ.ideal(prime)), self.size) self.s = copy(VSZp.zero()) self.s[0] = 1 self.t = copy(VSZp.zero()) self.t[len(self.t) - 1] = 1 self.m0, self.m0i = m0, m0i self.randomized = True
def _action(self, A): #if A not in self._group: # raise ValueError,"Action is only defined for {0}!".format(self._group) a, b, c, d = A [z, n, l] = factor_matrix_in_sl2z(int(a), int(b), int(c), int(d)) #l,ep = factor_matrix_in_sl2z_in_S_and_T(A_in) res = copy(self.T.parent().one()) if z == -1 and self.v != None: tmp = self.v(SL2Z([-1, 0, 0, -1])) for j in range(self._dim): res[j, j] = tmp if n != 0: res = self.T**n for i in range(len(l)): res = res * self.S * self.T**l[i] return res
def graph(self): r""" Return the weighted graph underlying this resolution graph. Output: An undirected, weighted Sage Graph. The vertices are labeled by the integers `0,\ldots,n-1`. The weight of an edge is the intersection number of the components corresponding to the vertices connected by the edge. """ if not hasattr(self, "_graph"): M = copy(self._intersection_matrix) for i in self.components(): M[i, i] = 0 self._graph = Graph(M, format='weighted_adjacency_matrix') return self._graph
def _action(self,A): #if A not in self._group: # raise ValueError,"Action is only defined for {0}!".format(self._group) a,b,c,d=A [z,n,l]=factor_matrix_in_sl2z(int(a),int(b),int(c),int(d)) #l,ep = factor_matrix_in_sl2z_in_S_and_T(A_in) res = copy(self.T.parent().one()) if z==-1 and self.v<>None: tmp = self.v(SL2Z([-1,0,0,-1])) for j in range(self._dim): res[j,j]=tmp if n<>0: res = self.T**n for i in range(len(l)): res = res*self.S*self.T**l[i] return res
print "\t\t!! WARNING !!" print "\t\t\tsomething went wrong?" print "\t\t\tsign = %s R1 = %s" % (sign, R1) print "\t\t\tP = %s" % vector(CC, P) print "\t\t\tR0 = %s" % vector(CC, R0) print "\tTesting P, Q -> Divisor(P,Q) -> Divisor(P,Q).compute_coordinates() = P + Q - D0?" for i, pair in enumerate(pairs): p0, p1 = pair Dp0p1 = Divisor(Pic, [p0, p1]) R0, R1 = Dp0p1.coordinates() R0 = vector(R0) R1 = vector(R1) if norm(R0 - p0) > norm(R0 - p1): tmp = copy(R1) R1 = R0 R0 = tmp N = [norm(R0 - p0), norm(R1 - p1)] N = RealField(15)(max(N)) print "\t\tP + Q = R0 + R1? :%s" % N if N > threshold: print "\t\t!! WARNING !!" print "\t\t\tsomething went wrong?" print "\t\t\tP = %s" % vector(CC, p0) print "\t\t\tQ = %s" % vector(CC, p1) print "\t\t\tR0 = %s" % vector(CC, R0) print "\t\t\tR1 = %s" % vector(CC, R1) print "\tTesting P, Q -> (Divisor(P,0) + Divisor(Q,1)) -> (Divisor(P,0) + Divisor(Q,1)).compute_coordinates() = P + Q - D0?"
def smith_normal_form(A, v): r""" Return the Smith normal form of the matrix ``A``. INPUT: - ``A`` -- a matrix over a field `K` - ``v`` -- a discrete valuation on `K` OUTPUT: a tuple`(D, S, T, rank)` `D, S, T` matrices, such that .. MATH:: S\cdot A\codt T = D, where `S` and `T` are square invertible matrices over the valuation ring `R` of `v`, `D` is the Smith normal form of `A` over `R`, and `rank` is the rank of `D`. """ K = A.base_ring() m = A.nrows() n = A.ncols() # assert all([v(a) >= 0 for a in A.coefficients()]), "A must have integral coefficients" D = copy(A) S = matrix.identity(K, m) T = matrix.identity(K, n) k = -1 while not D.submatrix(k + 1, k + 1).is_zero(): # the parameter k indicates that the rows i=0,..,k and columns j=0,..,k # are already in the required form i, j, e = find_pivot(v, D, k) # the entry D[i, j] is the next entry with the smallest valuation e switch_rows(D, k + 1, i) switch_columns(S, k + 1, i) switch_columns(D, k + 1, j) switch_rows(T, k + 1, j) assert A == S * D * T, "something is wrong!" # now D[k + 1, k + 1] is a nonzero entry, with minimal valuation e a0 = v.element_with_valuation(e) a = a0 / D[k + 1, k + 1] D.rescale_col(k + 1, a) T.rescale_row(k + 1, 1 / a) assert A == S * D * T, "something is wrong!" for j in range(k + 2, n): if not D[k + 1, j].is_zero(): x = -D[k + 1, j] / a0 D.add_multiple_of_column(j, k + 1, x) T.add_multiple_of_row(k + 1, j, -x) assert A == S * D * T, "something is wrong!" # now we kill the rest of the (k+1)th column for i in range(k + 2, m): if not D[i, k + 1].is_zero(): x = -D[i, k + 1] / a0 D.add_multiple_of_row(i, k + 1, x) S.add_multiple_of_column(k + 1, i, -x) assert A == S * D * T, "something is wrong!" if k < n - 1 and k < m - 1: k += 1 assert v(S.determinant()) == 0, "S is not invertible!" assert v(T.determinant()) == 0, "T is not invertible!" return D, S, T, k + 1
def make_luts(field, sub_folder, seed, sparse=False): global FIELD, RING print(f"Making LUTs for {field}") ############################################################################### # Finite field arithmetic ############################################################################### folder = os.path.join(PATH, "fields", "data", sub_folder) if os.path.exists(folder): shutil.rmtree(folder) os.mkdir(folder) FIELD = field RING = PolynomialRing(field, names="x") characteristic = int(field.characteristic()) order = int(field.order()) dtype = np.int64 if order <= np.iinfo(np.int64).max else object alpha = field.primitive_element() # assert field.gen() == field.multiplicative_generator() d = { "characteristic": int(field.characteristic()), "degree": int(field.degree()), "order": int(field.order()), "primitive_element": I(field.primitive_element()), "irreducible_poly": [int(c) for c in field.modulus().list()[::-1]] } save_json(d, folder, "properties.json", indent=True) set_seed(seed + 1) X, Y, XX, YY, ZZ = io_2d(0, order, 0, order, sparse=sparse) for i in range(ZZ.shape[0]): for j in range(ZZ.shape[1]): ZZ[i, j] = I(F(XX[i, j]) + F(YY[i, j])) d = {"X": X, "Y": Y, "Z": ZZ} save_pickle(d, folder, "add.pkl") set_seed(seed + 2) X, Y, XX, YY, ZZ = io_2d(0, order, 0, order, sparse=sparse) for i in range(ZZ.shape[0]): for j in range(ZZ.shape[1]): ZZ[i, j] = I(F(XX[i, j]) - F(YY[i, j])) d = {"X": X, "Y": Y, "Z": ZZ} save_pickle(d, folder, "subtract.pkl") set_seed(seed + 3) X, Y, XX, YY, ZZ = io_2d(0, order, 0, order, sparse=sparse) for i in range(ZZ.shape[0]): for j in range(ZZ.shape[1]): ZZ[i, j] = I(F(XX[i, j]) * F(YY[i, j])) d = {"X": X, "Y": Y, "Z": ZZ} save_pickle(d, folder, "multiply.pkl") set_seed(seed + 4) X, Y, XX, YY, ZZ = io_2d(0, order, -order - 2, order + 3, sparse=sparse) for i in range(ZZ.shape[0]): for j in range(ZZ.shape[1]): ZZ[i, j] = I(F(XX[i, j]) * YY[i, j]) d = {"X": X, "Y": Y, "Z": ZZ} save_pickle(d, folder, "scalar_multiply.pkl") set_seed(seed + 5) X, Y, XX, YY, ZZ = io_2d(0, order, 1, order, sparse=sparse) for i in range(ZZ.shape[0]): for j in range(ZZ.shape[1]): ZZ[i, j] = I(F(XX[i, j]) / F(YY[i, j])) d = {"X": X, "Y": Y, "Z": ZZ} save_pickle(d, folder, "divide.pkl") set_seed(seed + 6) X, Z = io_1d(0, order, sparse=sparse) for i in range(X.shape[0]): Z[i] = I(-F(X[i])) d = {"X": X, "Z": Z} save_pickle(d, folder, "additive_inverse.pkl") set_seed(seed + 7) X, Z = io_1d(1, order, sparse=sparse) for i in range(X.shape[0]): Z[i] = I(1 / F(X[i])) d = {"X": X, "Z": Z} save_pickle(d, folder, "multiplicative_inverse.pkl") set_seed(seed + 8) X, Y, XX, YY, ZZ = io_2d(1, order, -order - 2, order + 3, sparse=sparse) for i in range(ZZ.shape[0]): for j in range(ZZ.shape[1]): ZZ[i, j] = I(F(XX[i, j])**YY[i, j]) d = {"X": X, "Y": Y, "Z": ZZ} save_pickle(d, folder, "power.pkl") set_seed(seed + 9) X, Z = io_1d(1, order, sparse=sparse) for i in range(Z.shape[0]): try: Z[i] = I(field.fetch_int(X[i]).log(alpha)) except: Z[i] = I(log(F(X[i]), alpha)) d = {"X": X, "Z": Z} save_pickle(d, folder, "log.pkl") set_seed(seed + 10) X, Z = io_1d(0, order, sparse=sparse) for i in range(X.shape[0]): Z[i] = int(F(X[i]).additive_order()) d = {"X": X, "Z": Z} save_pickle(d, folder, "additive_order.pkl") set_seed(seed + 11) X, Z = io_1d(1, order, sparse=sparse) for i in range(X.shape[0]): Z[i] = int(F(X[i]).multiplicative_order()) d = {"X": X, "Z": Z} save_pickle(d, folder, "multiplicative_order.pkl") set_seed(seed + 12) X, _ = io_1d(0, order, sparse=sparse) Z = [] for i in range(len(X)): x = F(X[i]) p = x.charpoly() z = poly_to_list(p) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "characteristic_poly_element.pkl") set_seed(seed + 13) shapes = [(2, 2), (3, 3), (4, 4), (5, 5), (6, 6)] X = [] Z = [] for i in range(len(shapes)): x = randint_matrix(0, order, shapes[i]) X.append(x) x = matrix(FIELD, [[F(e) for e in row] for row in x]) p = x.charpoly() z = poly_to_list(p) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "characteristic_poly_matrix.pkl") set_seed(seed + 14) X, _ = io_1d(0, order, sparse=sparse) Z = [] for i in range(len(X)): x = F(X[i]) p = x.minpoly() z = poly_to_list(p) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "minimal_poly_element.pkl") # set_seed(seed + 15) # shapes = [(2,2), (3,3), (4,4), (5,5), (6,6)] # X = [] # Z = [] # for i in range(len(shapes)): # x = randint_matrix(0, order, shapes[i]) # X.append(x) # x = matrix(FIELD, [[F(e) for e in row] for row in x]) # p = x.minpoly() # z = np.array([I(e) for e in p.list()[::-1]], dtype=dtype).tolist() # z = z if z != [] else [0] # Z.append(z) # d = {"X": X, "Z": Z} # save_pickle(d, folder, "minimal_poly_matrix.pkl") set_seed(seed + 16) X, Z = io_1d(0, order, sparse=sparse) for i in range(X.shape[0]): z = F(X[i]).trace() Z[i] = int(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "field_trace.pkl") set_seed(seed + 17) X, Z = io_1d(0, order, sparse=sparse) for i in range(X.shape[0]): z = F(X[i]).norm() Z[i] = int(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "field_norm.pkl") ############################################################################### # Linear algebra ############################################################################### set_seed(seed + 201) X_shapes = [(2, 2), (2, 3), (3, 2), (3, 3), (3, 4)] Y_shapes = [(2, 2), (3, 3), (2, 4), (3, 3), (4, 5)] X = [] Y = [] Z = [] for i in range(len(shapes)): x = randint_matrix(0, order, X_shapes[i]) y = randint_matrix(0, order, Y_shapes[i]) X.append(x) Y.append(y) x = matrix(FIELD, [[F(e) for e in row] for row in x]) y = matrix(FIELD, [[F(e) for e in row] for row in y]) z = x * y z = np.array([[I(e) for e in row] for row in z], dtype) Z.append(z) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "matrix_multiply.pkl") set_seed(seed + 202) shapes = [(2, 2), (2, 3), (3, 2), (3, 3), (3, 4)] X = [] Z = [] for i in range(len(shapes)): x = randint_matrix(0, order, shapes[i]) X.append(x) x = matrix(FIELD, [[F(e) for e in row] for row in x]) z = x.rref() z = np.array([[I(e) for e in row] for row in z], dtype) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "row_reduce.pkl") set_seed(seed + 203) shapes = [(2, 2), (2, 3), (3, 2), (3, 3), (3, 4), (4, 3), (4, 4), (4, 5), (5, 4), (5, 5), (5, 6), (6, 5), (6, 6)] X = [] L = [] U = [] for i in range(len(shapes)): while True: # Ensure X has a PLU decomposition with P = I, which means it has an LU decomposition x = randint_matrix(0, order, shapes[i]) x_orig = x.copy() x = matrix(FIELD, [[F(e) for e in row] for row in x]) p, l, u = x.LU() if p == matrix.identity(FIELD, shapes[i][0]): break X.append(x_orig) l = np.array([[I(e) for e in row] for row in l], dtype) u = np.array([[I(e) for e in row] for row in u], dtype) L.append(l) U.append(u) d = {"X": X, "L": L, "U": U} save_pickle(d, folder, "lu_decompose.pkl") set_seed(seed + 204) shapes = [(2, 2), (2, 3), (3, 2), (3, 3), (3, 4), (4, 3), (4, 4), (4, 5), (5, 4), (5, 5), (5, 6), (6, 5), (6, 6)] X = [] L = [] U = [] P = [] for i in range(len(shapes)): x = randint_matrix(0, order, shapes[i]) X.append(x) x = matrix(FIELD, [[F(e) for e in row] for row in x]) p, l, u = x.LU() p = np.array([[I(e) for e in row] for row in p], dtype) l = np.array([[I(e) for e in row] for row in l], dtype) u = np.array([[I(e) for e in row] for row in u], dtype) P.append(p) L.append(l) U.append(u) d = {"X": X, "P": P, "L": L, "U": U} save_pickle(d, folder, "plu_decompose.pkl") set_seed(seed + 205) shapes = [(2, 2), (3, 3), (4, 4), (5, 5), (6, 6)] X = [] Z = [] for i in range(len(shapes)): while True: x = randint_matrix(0, order, shapes[i]) x_orig = x.copy() x = matrix(FIELD, [[F(e) for e in row] for row in x]) if x.rank() == shapes[i][0]: break X.append(x_orig) z = x.inverse() z = np.array([[I(e) for e in row] for row in z], dtype) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "matrix_inverse.pkl") set_seed(seed + 206) shapes = [(2, 2), (2, 2), (2, 2), (3, 3), (3, 3), (3, 3), (4, 4), (4, 4), (4, 4), (5, 5), (5, 5), (5, 5), (6, 6), (6, 6), (6, 6)] X = [] Z = [] for i in range(len(shapes)): x = randint_matrix(0, order, shapes[i]) X.append(x) x = matrix(FIELD, [[F(e) for e in row] for row in x]) z = I(x.determinant()) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "matrix_determinant.pkl") set_seed(seed + 207) shapes = [(2, 2), (2, 2), (2, 2), (3, 3), (3, 3), (3, 3), (4, 4), (4, 4), (4, 4), (5, 5), (5, 5), (5, 5), (6, 6), (6, 6), (6, 6)] X = [] Y = [] Z = [] for i in range(len(shapes)): while True: x = randint_matrix(0, order, shapes[i]) x_orig = x.copy() x = matrix(FIELD, [[F(e) for e in row] for row in x]) if x.rank() == shapes[i][0]: break X.append(x_orig) y = randint_matrix(0, order, shapes[i][1]) # 1-D vector Y.append(y) y = vector(FIELD, [F(e) for e in y]) z = x.solve_right(y) z = np.array([I(e) for e in z], dtype) Z.append(z) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "matrix_solve.pkl") set_seed(seed + 208) shapes = [(2, 2), (2, 3), (2, 4), (3, 2), (4, 2), (3, 3)] X = [] Z = [] for i in range(len(shapes)): deg = shapes[i][1] # The degree of the vector space # Random matrix x = randint_matrix(0, order, shapes[i]) X.append(x) x = matrix(FIELD, [[F(e) for e in row] for row in x]) z = x.row_space() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) Z.append(z) # Reduce the row space by 1 by copying the 0th row to the jth row for j in range(1, shapes[i][0]): x = copy(x) x[j, :] = F(random.randint(0, order - 1)) * x[0, :] z = x.row_space() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) X.append(np.array([[I(e) for e in row] for row in x], dtype)) Z.append(z) # Zero matrix x = copy(x) x[:] = F(0) z = x.row_space() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) X.append(np.array([[I(e) for e in row] for row in x], dtype)) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "row_space.pkl") set_seed(seed + 209) shapes = [(2, 2), (2, 3), (2, 4), (3, 2), (4, 2), (3, 3)] X = [] Z = [] for i in range(len(shapes)): deg = shapes[i][0] # The degree of the vector space # Random matrix x = randint_matrix(0, order, shapes[i]) X.append(x) x = matrix(FIELD, [[F(e) for e in row] for row in x]) z = x.column_space() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) Z.append(z) # Reduce the column space by 1 by copying the 0th column to the jth column for j in range(1, shapes[i][1]): x = copy(x) x[:, j] = F(random.randint(0, order - 1)) * x[:, 0] z = x.column_space() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) X.append(np.array([[I(e) for e in row] for row in x], dtype)) Z.append(z) # Zero matrix x = copy(x) x[:] = F(0) z = x.column_space() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) X.append(np.array([[I(e) for e in row] for row in x], dtype)) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "column_space.pkl") set_seed(seed + 210) shapes = [(2, 2), (2, 3), (2, 4), (3, 2), (4, 2), (3, 3)] X = [] Z = [] for i in range(len(shapes)): deg = shapes[i][0] # The degree of the vector space # Random matrix x = randint_matrix(0, order, shapes[i]) X.append(x) x = matrix(FIELD, [[F(e) for e in row] for row in x]) z = x.left_kernel() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) Z.append(z) # Reduce the left null space by 1 by copying the 0th row to the jth row for j in range(1, shapes[i][0]): x = copy(x) x[j, :] = F(random.randint(0, order - 1)) * x[0, :] z = x.left_kernel() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) X.append(np.array([[I(e) for e in row] for row in x], dtype)) Z.append(z) # Zero matrix x = copy(x) x[:] = F(0) z = x.left_kernel() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) X.append(np.array([[I(e) for e in row] for row in x], dtype)) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "left_null_space.pkl") set_seed(seed + 211) shapes = [(2, 2), (2, 3), (2, 4), (3, 2), (4, 2), (3, 3)] X = [] Z = [] for i in range(len(shapes)): deg = shapes[i][1] # The degree of the vector space # Random matrix x = randint_matrix(0, order, shapes[i]) X.append(x) x = matrix(FIELD, [[F(e) for e in row] for row in x]) z = x.right_kernel() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) Z.append(z) # Reduce the null space by 1 by copying the 0th column to the jth column for j in range(1, shapes[i][1]): x = copy(x) x[:, j] = F(random.randint(0, order - 1)) * x[:, 0] z = x.right_kernel() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) X.append(np.array([[I(e) for e in row] for row in x], dtype)) Z.append(z) # Zero matrix x = copy(x) x[:] = F(0) z = x.right_kernel() if z.dimension() == 0: z = randint_matrix(0, 1, (0, deg)) else: z = z.basis_matrix() z = np.array([[I(e) for e in row] for row in z], dtype) X.append(np.array([[I(e) for e in row] for row in x], dtype)) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "null_space.pkl") ############################################################################### # Polynomial arithmetic ############################################################################### folder = os.path.join(PATH, "polys", "data", sub_folder) if os.path.exists(folder): shutil.rmtree(folder) os.mkdir(folder) MIN_COEFFS = 1 MAX_COEFFS = 12 set_seed(seed + 101) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Y = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Z = [] for i in range(len(X)): x = list_to_poly(X[i]) y = list_to_poly(Y[i]) z = x + y z = poly_to_list(z) Z.append(z) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "add.pkl") set_seed(seed + 102) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Y = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Z = [] for i in range(len(X)): x = list_to_poly(X[i]) y = list_to_poly(Y[i]) z = x - y z = poly_to_list(z) Z.append(z) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "subtract.pkl") set_seed(seed + 103) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Y = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Z = [] for i in range(len(X)): x = list_to_poly(X[i]) y = list_to_poly(Y[i]) z = x * y z = poly_to_list(z) Z.append(z) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "multiply.pkl") set_seed(seed + 104) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Y = [random.randint(1, 2 * characteristic) for i in range(20)] Z = [] for i in range(len(X)): x = list_to_poly(X[i]) y = Y[i] z = x * y z = poly_to_list(z) Z.append(z) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "scalar_multiply.pkl") set_seed(seed + 105) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Y = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] # Add some specific polynomial types X.append([0]), Y.append(random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS)) # 0 / y X.append(random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS // 2)), Y.append( random_coeffs(0, order, MAX_COEFFS // 2, MAX_COEFFS)) # x / y with x.degree < y.degree X.append(random_coeffs(0, order, 2, MAX_COEFFS)), Y.append( random_coeffs(0, order, 1, 2)) # x / y with y.degree = 0 Q = [] R = [] for i in range(len(X)): x = list_to_poly(X[i]) y = list_to_poly(Y[i]) q = x // y r = x % y q = poly_to_list(q) Q.append(q) r = poly_to_list(r) R.append(r) d = {"X": X, "Y": Y, "Q": Q, "R": R} save_pickle(d, folder, "divmod.pkl") set_seed(seed + 106) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(4)] X.append(random_coeffs(0, order, 1, 2)) Y = [0, 1, 2, 3] Z = [] for i in range(len(X)): x = list_to_poly(X[i]) ZZ = [] for j in range(len(Y)): y = Y[j] z = x**y z = poly_to_list(z) ZZ.append(z) Z.append(ZZ) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "power.pkl") set_seed(seed + 107) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Y = arange(0, order, sparse=sparse) Z = np.array(np.zeros((len(X), len(Y))), dtype=dtype) for i in range(len(X)): for j in range(len(Y)): x = list_to_poly(X[i]) y = F(Y[j]) z = x(y) Z[i, j] = I(z) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "evaluate.pkl") set_seed(seed + 108) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Y = [randint_matrix(0, order, (2, 2)) for i in range(20)] Z = [] for i in range(len(X)): x = list_to_poly(X[i]) y = matrix(FIELD, [[F(e) for e in row] for row in Y[i]]) z = x(y) z = np.array([[I(e) for e in row] for row in z], dtype) Z.append(z) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "evaluate_matrix.pkl") ############################################################################### # Polynomial arithmetic methods ############################################################################### set_seed(seed + 301) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Z = [] for i in range(len(X)): x = list_to_poly(X[i]) z = x.reverse() z = poly_to_list(z) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "reverse.pkl") set_seed(seed + 302) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] R = [] M = [] for i in range(len(X)): x = list_to_poly(X[i]) roots = x.roots() RR, MM = [], [] for root in roots: r = root[0] m = root[1] RR.append(I(r)) MM.append(int(m)) idxs = np.argsort(RR) # Sort by ascending roots RR = (np.array(RR, dtype=dtype)[idxs]).tolist() MM = (np.array(MM, dtype=dtype)[idxs]).tolist() R.append(RR) M.append(MM) d = {"X": X, "R": R, "M": M} save_pickle(d, folder, "roots.pkl") set_seed(seed + 303) X = [ random_coeffs(0, order, 2 * FIELD.degree(), 6 * FIELD.degree()) for i in range(20) ] Y = [ 1, ] * 10 + [random.randint(2, FIELD.degree() + 1) for i in range(10)] Z = [] for i in range(len(X)): x = list_to_poly(X[i]) z = x.derivative(Y[i]) z = poly_to_list(z) Z.append(z) d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "derivative.pkl") ############################################################################### # Polynomial arithmetic functions ############################################################################### set_seed(seed + 401) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Y = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] D = [] S = [] T = [] for i in range(len(X)): x = list_to_poly(X[i]) y = list_to_poly(Y[i]) d, s, t = xgcd(x, y) d = poly_to_list(d) s = poly_to_list(s) t = poly_to_list(t) D.append(d) S.append(s) T.append(t) d = {"X": X, "Y": Y, "D": D, "S": S, "T": T} save_pickle(d, folder, "egcd.pkl") set_seed(seed + 402) X = [] Z = [] for i in range(20): XX = [ random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(random.randint(2, 5)) ] X.append(XX) xx = [list_to_poly(XXi) for XXi in XX] z = lcm(xx) z = poly_to_list(z) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "lcm.pkl") set_seed(seed + 403) X = [] Z = [] for i in range(20): XX = [ random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(random.randint(2, 5)) ] X.append(XX) xx = [list_to_poly(XXi) for XXi in XX] z = prod(xx) z = poly_to_list(z) Z.append(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "prod.pkl") set_seed(seed + 404) X = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] E = [random.randint(2, 10) for i in range(20)] M = [random_coeffs(0, order, MIN_COEFFS, MAX_COEFFS) for i in range(20)] Z = [] for i in range(20): x = list_to_poly(X[i]) e = E[i] m = list_to_poly(M[i]) z = (x**e) % m z = poly_to_list(z) Z.append(z) d = {"X": X, "E": E, "M": M, "Z": Z} save_pickle(d, folder, "modular_power.pkl") set_seed(seed + 405) X = [ 0, ] * 20 # The remainder Y = [ 0, ] * 20 # The modulus Z = [ 0, ] * 20 # The solution for i in range(20): n = random.randint(2, 4) # The number of polynomials x, y = [], [] for j in range(n): d = random.randint(3, 5) x.append(random_coeffs(0, order, d, d + 1)) y.append(random_coeffs( 0, order, d + 1, d + 2)) # Ensure modulus degree is greater than remainder degree X[i] = x Y[i] = y try: x = [list_to_poly(xx) for xx in x] y = [list_to_poly(yy) for yy in y] z = crt(x, y) Z[i] = poly_to_list(z) except: Z[i] = None d = {"X": X, "Y": Y, "Z": Z} save_pickle(d, folder, "crt.pkl") ############################################################################### # Special polynomials ############################################################################### set_seed(seed + 501) X = [random_coeffs(0, order, 1, 6) for _ in range(20)] Z = [ False, ] * len(X) for i in range(len(X)): if random.choice(["one", "other"]) == "one": X[i][0] = 1 x = list_to_poly(X[i]) z = x.is_monic() Z[i] = bool(z) d = {"X": X, "Z": Z} save_pickle(d, folder, "is_monic.pkl") set_seed(seed + 502) IS = [] IS_NOT = [] if order <= 2**16: while len(IS) < 10: x = random_coeffs(0, order, 1, 6) f = list_to_poly(x) if f.is_irreducible(): IS.append(x) while len(IS_NOT) < 10: x = random_coeffs(0, order, 1, 6) f = list_to_poly(x) if not f.is_irreducible(): IS_NOT.append(x) d = {"IS": IS, "IS_NOT": IS_NOT} save_pickle(d, folder, "is_irreducible.pkl") set_seed(seed + 503) IS = [] IS_NOT = [] if order <= 2**16: while len(IS) < 10: x = random_coeffs(0, order, 1, 6) f = list_to_poly(x) # f = f / f.coefficients()[-1] # Make monic # assert f.is_monic() if f.degree() == 1 and f.coefficients(sparse=False)[0] == 0: continue # For some reason `is_primitive()` crashes on f(x) = a*x if not f.is_irreducible(): continue # Want to find an irreducible polynomial that is also primitive if f.is_primitive(): IS.append(x) while len(IS_NOT) < 10: x = random_coeffs(0, order, 1, 6) f = list_to_poly(x) # f = f / f.coefficients()[-1] # Make monic # assert f.is_monic() if f.degree() == 1 and f.coefficients(sparse=False)[0] == 0: continue # For some reason `is_primitive()` crashes on f(x) = a*x if not f.is_irreducible(): continue # Want to find an irreducible polynomial that is not primitive if not f.is_primitive(): IS_NOT.append(x) d = {"IS": IS, "IS_NOT": IS_NOT} save_pickle(d, folder, "is_primitive.pkl") set_seed(seed + 504) if order <= 2**16: X = [random_coeffs(0, order, 1, 6) for _ in range(20)] Z = [ False, ] * len(X) for i in range(len(X)): x = list_to_poly(X[i]) z = x.is_squarefree() Z[i] = bool(z) else: X = [] Z = [] d = {"X": X, "Z": Z} save_pickle(d, folder, "is_square_free.pkl")
def linearequations(self, W): maxlower = self.lower # From W = H0( 3*D0 - D ), return H0((g + 1)*\infty - E), where E is effective of degree g s.t. E - (g/2) * \infty + D-(g+1)\infty ~ 0. /!\ Assumes g even /!\ # E0 = (3g/2+2)\infty = E + D + \infty # H0(3D0 - D - E0) = W( - E0) = {w in W : w*x**(3g/2+2) in W} has dim >= 1 # phi \in W(-E0) # <=> div phi + 3D0 - D - E0 >= 0 # <=> div phi + 3D0 - D - E0 = E effective # <=> div phi = E + D - (3g/2 + 1)\infty assert self.g % 2 == 0, "the genus must be even for this implementation to work"; KW, upper, lower = EqnMatrix(W.change_ring(self.Rextraprec), 2 * self.d0 + 1 - self.g); assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower)); maxlower = max(maxlower, lower); KWnrows = KW.nrows(); KWncols = KW.ncols(); K = KW.stack(Matrix(self.Rextraprec, KWnrows, KWncols)); for j, (x, y) in enumerate(self.Z): xpower = x**( 3 * self.g/2 + 2); for i in range(KWnrows): K[i + KWnrows,j] = KW[i,j] * xpower; phi, upper, lower = Kernel(K, KWncols - 1); # rank >= 1 if self.verbose: print "phi upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower)) assert self.threshold_check(1,lower), "upper = %s lower = %s" % (RealField(35)(1), RealField(35)(lower)) maxlower = max(maxlower, lower); # phi*H0( (5g/2+3) \infty) = H0( (4g + 4) \infty - D - E) Exps=[] for i in range( 5 * self.g / 2 + 4 ): Exps.append((i,0)) if i > self.g: Exps.append(( i - self.g - 1, 1)) # H0((4g+4)\infty-D-E) H4 = Matrix(self.Rextraprec, self.nZ, 4 * self.g + 7) for j, (u,v) in enumerate(Exps): for i, (x, y) in enumerate(self.Z): H4[i,j] = phi[i, 0] * x**u * y**v K4, upper, lower = EqnMatrix(H4, 4 * self.g + 7 ) assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower)) maxlower = max(maxlower, lower); # H0((g+1)\infty - E) = {s in V : s*W c H0((4g+4)OO-D-E)} # \dim >= 3 = self.d0 + 1 - 2 * self.g (equality holds for g <= 3) if self.g >= 4: print "Warning: Riemann--Roch correction term ignored when computing \dim H**0((g+1)\infty - E)!!!" K4nrows = K4.nrows(); K4ncols = K4.ncols(); while True: l = 2; Kres = copy(self.KV); Kres_old_rows = Kres.nrows(); Kres = Kres.stack(Matrix(self.R, l * K4nrows, K4ncols)); for m in range(l): # Attempt of IGS of W v=random_vector_in_span(W) for i in range(K4nrows): for j in range(K4ncols): Kres[i + m*K4nrows + Kres_old_rows, j] = v[j] * K4[i, j] res, upper, lower = Kernel(Kres, Kres.ncols() - (self.d0 + 1 - 2 * self.g)); if self.threshold_check(upper, lower): maxlower = max(maxlower, lower); break; if self.verbose: print "Warning: In MakOutput, failed IGS at step 3, retrying." print "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower)) # Expressing H0((g+1)\infty-E) in terms of H0(D0) S = Matrix(self.R, self.nZ, (self.g + 3) + (self.d0 + 1 - 2 * self.g) ) for i in range( self.nZ ): for j in range( self.g + 3): S[i,j] = self.Vout[i,j] for j in range( self.d0 + 1 - 2 * self.g): S[i ,j + self.g + 3] = res[i, j ] K, upper, lower = Kernel(S, S.ncols() - ( self.d0 + 1 - 2 * self.g)) # S.cols - 3 assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower)) maxlower = max(maxlower, lower); # dropping the last (self.d0 + 1 - 2 * self.g) rows # K.rows = self.g + 3 out = K.matrix_from_rows([i for i in range(self.g + 3)]) # a basis in H**0( D_0) for H**0((g+1)\infty - E) return out, maxlower
def AddFlip(self, A, B): maxlower = self.lower; field = self.R; output_field = self.R if A.base_ring() == self.Rextraprec or B.base_ring() == self.Rextraprec: field = self.Rextraprec; if A.base_ring() == self.Rextraprec and B.base_ring() == self.Rextraprec: output_field = self.Rextraprec; # Takes H0(3D0-A), H0(3D0-B), and returns H0(3D0-C), with C s.t. A+B+C~3D0 # H0(6D0-A-B) = H0(3D0-A) * H0(3D0-B) if self.verbose: print "PicardGroup.AddFlip(self, A, B)" #### STEP 1 #### if self.verbose: print "Step 1"; AB = Matrix(field, self.nZ, 4 * self.d0 + 1 - self.g); KAB = Matrix(field, AB.nrows() - AB.ncols(), AB.nrows()); ABncols = AB.ncols(); ABnrows = AB.nrows(); rank = AB.ncols(); while True: # 5 picked at random l = 5; ABtmp = Matrix(field, self.nZ, 4 * self.d0 + 1 - self.g + l); for j in range(ABtmp.ncols()): a = random_vector_in_span(A); b = random_vector_in_span(B); for i in range(ABnrows): ABtmp[i, j] = a[i] * b[i]; Q, R, P = qrp(ABtmp, ABncols ); upper = R[rank - 1, rank - 1].abs(); lower = 0; if ABtmp.ncols() > rank and ABnrows > rank: lower = R[rank, rank ].abs(); if self.threshold_check(upper, lower): # the first AB.cols columns are a basis for H0(6D0-A-B) = H0(3D0-A) * H0(3D0-B) # v in AB iff KAB * v = 0 for i in range(ABnrows): for j in range(ABncols): AB[i, j] = Q[i, j] for j in range(ABnrows - rank): KAB[j, i] = Q[i, j + rank].conjugate(); maxlower = max(maxlower, lower); break; if self.verbose: print "Warning: In AddFlip, not full rank at step 1, retrying." print "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower)) #### STEP 2 #### # H0(3D0-A-B) = {s in V : s*V c H0(6D0-A-B)} if self.verbose: print "Step 2" #### Prec Test #### if self.verbose: a = random_vector_in_span(A); b = random_vector_in_span(B); ab = Matrix(field, self.nZ, 1); for i in range(self.nZ): ab[i, 0] = a[i] * b[i]; print field print "maxlower = %s ,lower = %s " % (RealField(15)(maxlower), RealField(15)(lower)) print "Precision of the input of MakAddflip: %s"% (RealField(15)(max(map(lambda x: RR(x[0].abs()), list(KAB * ab)))),) KABnrows = KAB.nrows(); KABncols = KAB.ncols(); while True: # columns = equations for H0(3D0-A-B) = {s in V : s*V c H0(6D0-A-B)} \subset H0(6D0-A-B) l = 2; KABred = copy(KAB); KABred = KABred.stack( Matrix(field, l*KABnrows, KABncols ) ); for m in range(l): # Attempt of IGS of V v = random_vector_in_span( self.V ) for j in xrange(KABncols): for i in range( KABnrows ): KABred[i + m * KABnrows + KABnrows , j] = KAB[i, j] * v[j] ABred, upper, lower = Kernel(KABred, KABred.ncols() - (self.d0 + 1 - self.g)); if self.threshold_check(upper, lower): maxlower = max(maxlower, lower); break; if self.verbose: print "Warning: In AddFlip, failed IGS at step 2, retrying." print "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower)) #### STEP 3 #### # H0(6D0-A-B-C) = f*H0(3D0), where f in H0(30-A-B) if self.verbose: print "Step 3" # fv represents f*H0(3D0) fV= copy(self.V) for j in xrange(3*self.d0 + 1 - self.g): for i in xrange(self.nZ): fV[i,j] *= ABred[i,0] KfV, upper, lower = EqnMatrix( fV, 3 * self.d0 + 1 - self.g ) # Equations for f*V assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower)) maxlower = max(maxlower, lower); KfVnrows = KfV.nrows(); KfVncols = KfV.ncols(); ### STEP 4 ### # H0(3D0-C) = {s in V : s*H0(3D0-A-B) c H0(6D0-A-B-C)} = {s in V : s*H0(3D0-A-B) c f*V} if self.verbose: print "Step 4" while True: # Equations for H0(3D0-C) #expand KC l = 2; KC = self.KV.stack(Matrix(field, l * KfV.nrows(), self.KV.ncols())); KC_old_rows = self.KV.nrows(); for m in range(l): # Attempt of IGS of H0(3D0-A-B) v = random_vector_in_span(ABred) for i in range(KfVnrows): for j in range(KfVncols): KC[i + m * KfVnrows + KC_old_rows, j] = v[j] * KfV[i, j]; output, upper, lower = Kernel(KC, KC.ncols() - (2 * self.d0 + 1 - self.g) ); if self.threshold_check(upper, lower): maxlower = max(maxlower, lower); break; if self.verbose: print "Warning: In MakAddFlip, failed IGS at step 4, retrying." print "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower)) return output.change_ring(output_field), maxlower;
def forget_kappas(self): M = copy(self.M) for v in range(1, self.num_vertices()+1): M[v,0] = M[v,0][0] return StrataGraph(M)
def __init__(self, L, **MetaData): r""" NOTE: An instance of ``BarCode2d`` should not be directly constructed. Usually, it is obtained as output of :meth:`~pGroupCohomology.cohomology.COHO.bar_code`, or as a slice of an instance of :class:`~pGroupCohomology.barcode.BarCode`. INPUT: ``L`` - a list of persistence data ``M`` - Metadata in the form of optional parameters ASSUMPTIONS: ``dict(L)`` should yield a dictionary whose keys give the positions and whose values give the marks of a persistence matrix. A persistence matrix is an upper triangular non-negative integer matrix, with the additional property that the matrix columns are increasing from top to bottom and the maatrix rows are decreasing from left to right. However, this is not a sufficient condition. We are sorry for the fact that the numbering of rows and colums does not start with zero; instead, the numbering ranges from ``-d`` to ``d``, where ``d`` is given by the length of the normal series (non-trivial terms only) by which the bar code is defined. The metadata can be anything. Currently used is: - ``degree``, an integer, the degree to which this bar code belongs - ``ring``, the name (string) of the cohomology ring of a group ``G`` - ``command``, the GAP command producing the normal series of ``G`` by which the bar code is defined. EXAMPLES:: sage: from pGroupCohomology.barcode import BarCode2d sage: L = [((-2,-2),2),((-2,-1),2),((-2,0),1),((-2,1),1),((-2,2),0),((-1,-1),3),((-1,0),1),((-1,1),1),((-1,2),0),((0,0),3),((0,1),2),((0,2),1),((1,1),2),((1,2),1),((2,2),2)] sage: B = BarCode2d(L, ring='some ring', degree=3, command='my favourite GAP command') # indirect doctest sage: B Barcode of degree 3 for some ring associated with my favourite GAP command sage: ascii_art(B) * *-*-* * * *-*-*-* *-* sage: B.matrix() [2 2 1 1 0] [0 3 1 1 0] [0 0 3 2 1] [0 0 0 2 1] [0 0 0 0 2] """ from sage.all import copy self._Meta = copy(MetaData) D = self._D = dict(L) l = self._length = max([X[1] for X in D.keys()]) # our codes will always range from -self._length to +self._length bars = [] lowerbars = dict([(k, 0) for k in range(-l, l + 1)]) for i in range(-l, l + 1): for j in range(l - i + 1): n = D[i, l - j] - lowerbars[l - j] # - drawn for k in range(i, l + 1 - j): lowerbars[k] = lowerbars[k] + n for k in range(n): bars.append([i, l - j]) bars.sort() bars.reverse() self._bars = bars
def forget_kappas(self): M = copy(self.M) for v in range(1, self.num_vertices() + 1): M[v, 0] = M[v, 0][0] return StrataGraph(M)
def add_trace_and_norm_ladic(g, D, alpha_geo, verbose=True): if verbose: print "add_trace_and_norm_ladic()" #load Fields L = D['L'] if L is QQ: QQx = PolynomialRing(QQ, "x") L = NumberField(QQx.gen(), "b") prec = D['prec'] CCap = ComplexField(prec) # load endo alpha = D['alpha'] rosati = bound_rosati(alpha_geo) if alpha.base_ring() is not L: alpha_K = copy(alpha) alpha = Matrix(L, 2, 2) #shift alpha field from K to L for i, row in enumerate(alpha_K.rows()): for j, elt in enumerate(row): if elt not in L: assert elt.base_ring().absolute_polynomial( ) == L.absolute_polynomial() alpha[i, j] = L(elt.list()) else: alpha[i, j] = L(elt) # load algx_poly algx_poly_coeff = D['algx_poly'] #sometimes, by mistake the algx_poly is defined over K where K == L, but with a different name for i, elt in enumerate(algx_poly_coeff): if elt not in L: assert elt.base_ring().absolute_polynomial( ) == L.absolute_polynomial() algx_poly_coeff[i] = L(elt.list()) else: algx_poly_coeff[i] = L(elt) x_poly = vector(CCap, D['x_poly']) for i in [0, 1]: assert almost_equal( x_poly[i], algx_poly_coeff[i]), "%s != %s" % (algx_poly_coeff[i], x_poly[i]) # load P P0 = vector(L, [D['P'][0], D['P'][1]]) for i, elt in enumerate(P0): if elt not in L: assert elt.base_ring().absolute_polynomial( ) == L.absolute_polynomial() P0[i] = L(elt.list()) else: P0[i] = L(elt) if verbose: print "P0 = %s" % (P0, ) # load image points, P1 and P2 L_poly = PolynomialRing(L, "xL") xL = L_poly.gen() Xpoly = L_poly(algx_poly_coeff) if Xpoly.is_irreducible(): M = Xpoly.root_field("c") else: # this avoids bifurcation later on in the code, we don't want to be always checking if M is L M = NumberField(xL, "c") # trying to be sure that we keep the same complex_embedding... M_complex_embedding = 0 if L.gen() not in QQ: M_complex_embedding = None Lgen_CC = toCCap(L.gen(), prec=prec) for i, _ in enumerate(M.complex_embeddings()): if norm(Lgen_CC - M(L.gen()).complex_embedding(prec=prec, i=i) ) < CCap(2)**(-0.7 * Lgen_CC.prec()) * Lgen_CC.abs(): M_complex_embedding = i assert M_complex_embedding is not None, "\nL = %s\n%s = %s\n%s" % ( L, L.gen(), Lgen_CC, M.complex_embeddings()) M_poly = PolynomialRing(M, "xM") xM = M_poly.gen() # convert everything to M P0_M = vector(M, [elt for elt in P0]) alpha_M = Matrix(M, [[elt for elt in row] for row in alpha.rows()]) Xpoly_M = M_poly(Xpoly) for i in [0, 1]: assert almost_equal(x_poly[i], Xpoly_M.list()[i], ithcomplex_embedding=M_complex_embedding ), "%s != %s" % (Xpoly_M.list()[i], x_poly[i]) P1 = vector(M, 2) P1_ap = vector(CCap, D['R'][0]) P2 = vector(M, 2) P2_ap = vector(CCap, D['R'][1]) M_Xpoly_roots = Xpoly_M.roots() assert len(M_Xpoly_roots) > 0 Ypoly_M = prod([xM**2 - g(root) for root, _ in M_Xpoly_roots]) # also \in L_poly assert sum(m for _, m in Ypoly_M.roots(M)) == Ypoly_M.degree( ), "%s != %s\n%s\n%s" % (sum(m for _, m in Ypoly_M.roots(M)), Ypoly_M.degree(), Ypoly_M, Ypoly_M.roots(M)) if len(M_Xpoly_roots) == 1: # we have a double root P1[0] = M_Xpoly_roots[0][0] P2[0] = M_Xpoly_roots[0][0] ae_prec = prec * 0.4 else: assert len(M_Xpoly_roots) == 2 ae_prec = prec # we have two distinct roots P1[0] = M_Xpoly_roots[0][0] P2[0] = M_Xpoly_roots[1][0] if not_equal(P1_ap[0], P1[0], ithcomplex_embedding=M_complex_embedding): P1[0] = M_Xpoly_roots[1][0] P2[0] = M_Xpoly_roots[0][0] assert almost_equal( P1_ap[0], P1[0], ithcomplex_embedding=M_complex_embedding, prec=ae_prec), "\n%s = %s \n != %s" % ( P1[0], toCCap( P1[0], ithcomplex_embedding=M_complex_embedding), CC(P1_ap[0])) assert almost_equal( P2_ap[0], P2[0], ithcomplex_embedding=M_complex_embedding, prec=ae_prec), "\n%s = %s \n != %s" % ( P2[0], toCCap( P2[0], ithcomplex_embedding=M_complex_embedding), CC(P2_ap[0])) # figure out the right square root # pick the default branch P1[1] = sqrt(g(P1[0])) P2[1] = sqrt(g(P2[0])) if 0 in [P1[1], P2[1]]: print "one of image points is a Weirstrass point" print P1 print P2 raise ZeroDivisionError #switch if necessary if not_equal(P1_ap[1], P1[1], ithcomplex_embedding=M_complex_embedding, prec=ae_prec): P1[1] *= -1 if not_equal(P2_ap[1], P2[1], ithcomplex_embedding=M_complex_embedding, prec=ae_prec): P2[1] *= -1 # double check for i in [0, 1]: assert almost_equal(P1_ap[i], P1[i], ithcomplex_embedding=M_complex_embedding, prec=ae_prec), "%s != %s" % (P1_ap[i], P1[i]) assert almost_equal(P2_ap[i], P2[i], ithcomplex_embedding=M_complex_embedding, prec=ae_prec), "%s != %s" % (P2_ap[i], P2[i]) # now alpha, P0 \in L # P1, P2 \in L if verbose: print "P1 = %s\nP2 = %s" % (P1, P2) print "Computing the trace and the norm ladically\n" trace_and_norm = trace_and_norm_ladic(L, M, P0_M, P1, P2, g, 2 * alpha_M, 16 * rosati, primes=ceil(prec * L.degree() / 61)) else: trace_and_norm = trace_and_norm_ladic(L, M, P0_M, P1, P2, g, 2 * alpha_M, 16 * rosati, primes=ceil(prec * L.degree() / 61)) # Convert the coefficients to polynomials trace_numerator, trace_denominator, norm_numerator, norm_denominator = [ L_poly(coeff) for coeff in trace_and_norm ] assert trace_numerator(P0[0]) == trace_denominator( P0[0]) * -algx_poly_coeff[1], "%s/%s (%s) != %s" % ( trace_numerator, trace_denominator, P0[0], -algx_poly_coeff[1]) assert norm_numerator(P0[0]) == norm_denominator( P0[0]) * algx_poly_coeff[0], "%s/%s (%s) != %s" % ( norm_numerator, norm_denominator, P0[0], algx_poly_coeff[0]) buffer = "# x1 + x2 = degree %d/ degree %d\n" % ( trace_numerator.degree(), trace_denominator.degree()) buffer += "# = (%s) / (%s) \n" % (trace_numerator, trace_denominator) buffer += "# max(%d, %d) <= %d\n\n" % ( trace_numerator.degree(), trace_denominator.degree(), 16 * rosati) buffer += "# x1 * x2 = degree %d/ degree %d\n" % ( norm_numerator.degree(), norm_denominator.degree()) buffer += "# = (%s) / (%s) \n" % (norm_numerator, norm_denominator) buffer += "# max(%d, %d) <= %d\n" % ( norm_numerator.degree(), norm_denominator.degree(), 16 * rosati) if verbose: print buffer print "\n" assert max(trace_numerator.degree(), trace_denominator.degree()) <= 16 * rosati assert max(norm_numerator.degree(), norm_denominator.degree()) <= 16 * rosati if verbose: print "Veritfying if x1*x2 and x1 + x2 are correct..." verified = verify_algebraically(g, P0, alpha, trace_and_norm, verbose=verbose) if verbose: print "\nDoes it act on the tangent space as expected? %s\n" % verified print "Done add_trace_and_norm_ladic()" return verified, [ trace_numerator.list(), trace_denominator.list(), norm_numerator.list(), norm_denominator.list() ]
def main(filein, vhdl_fileout, blocksize=256, keysize=256, rounds=19, sboxes=10): with io.open(filein, 'rb') as matfile: inst = pickle.load(matfile) if inst.n != blocksize or inst.k != keysize or inst.r != rounds: raise ValueError("Unexpected LowMC instance.") if blocksize != keysize: raise ValueError("Only blocksize == keysize is currently supported!") P = matrix(F, blocksize, blocksize) for i in range(blocksize): P[blocksize - i - 1, i] = 1 Ls = [P * matrix(F, L) * P for L in inst.L] Ks = [P * matrix(F, K) * P for K in inst.K] Cs = [P * vector(F, C) for C in inst.R] Kt = [m.transpose() for m in Ks] Lt = [m.transpose() for m in Ls] Li = [m.inverse() for m in Lt] LiK = [Kt[i + 1] * Li[i] for i in range(inst.r)] LiC = [Cs[i] * Li[i] for i in range(inst.r)] mod_Li = [copy(Li[i]) for i in range(inst.r)] for j in range(inst.r): mod_Li[j][inst.n - 3 * sboxes:, :inst.n] = matrix( F, 3 * sboxes, inst.n) precomputed_key_matrix = None precomputed_key_matrix_nl = matrix(F, inst.n, (sboxes * 3) * inst.r) precomputed_constant = None precomputed_constant_nl = vector(F, (sboxes * 3) * inst.r) for round in range(inst.r): tmp = copy(LiK[round]) tmpC = copy(LiC[round]) for i in range(round + 1, inst.r): x = LiK[i] c = LiC[i] for j in range(i - 1, round - 1, -1): x = x * mod_Li[j] c = c * mod_Li[j] tmp += x tmpC += c # non-linear part idx = round * (3 * sboxes) precomputed_key_matrix_nl[:inst.n, idx:idx + 3 * sboxes] = tmp[:inst.n, inst.n - 3 * sboxes:] precomputed_constant_nl[idx:idx + 3 * sboxes] = tmpC[inst.n - 3 * sboxes:] # linear part if round == 0: tmp[:, inst.n - 3 * sboxes:] = matrix(F, inst.n, 3 * sboxes) tmpC[inst.n - 3 * sboxes:] = vector(F, 3 * sboxes) precomputed_key_matrix = tmp precomputed_constant = tmpC #RRKC precomputation done R_full = [] R_dot = [] R_dot_inv = [] R_wedge = [] T_vee = [] R_wedge_snipped = [] R_cols = [] Z_i = [] # i = 1 R_full.append(Lt[0][:, 0:inst.n - 3 * sboxes]) Rdot, colR = calc_dot_from_full_rank(R_full[0]) R_dot.append(Rdot) R_dot_inv.append(R_dot[0].inverse()) R_cols.append(colR) R_wedge.append(R_full[0] * R_dot_inv[0]) Z_i.append(Lt[0][:, inst.n - 3 * sboxes:inst.n]) R_wedge_snipped.append(snip_r_wedge(R_wedge[0], colR)) # i = 2...r-1 for i in range(1, rounds - 1): T_vee.append(R_dot[i - 1] * Lt[i][0:inst.n - sboxes * 3, :]) R = matrix(F, inst.n, inst.n - sboxes * 3) R[0:inst.n - 3 * sboxes, :] = T_vee[-1][0:inst.n - 3 * sboxes, 0:inst.n - 3 * sboxes] R[inst.n - 3 * sboxes:inst.n, :] = Lt[i][inst.n - 3 * sboxes:inst.n, 0:inst.n - 3 * sboxes] R_full.append(R) Rdot, colR = calc_dot_from_full_rank(R_full[i]) R_dot.append(Rdot) R_dot_inv.append(R_dot[i].inverse()) R_cols.append(colR) R_wedge.append(R_full[i] * R_dot_inv[i]) Z_i.append( T_vee[i - 1][0:inst.n - 3 * sboxes, inst.n - 3 * sboxes:inst.n].transpose().augment( Lt[i][inst.n - sboxes * 3:inst.n, inst.n - sboxes * 3:inst.n].transpose()).transpose()) R_wedge_snipped.append(snip_r_wedge(R_wedge[-1], colR)) # i = r T_vee.append(R_dot[rounds - 2] * Lt[rounds - 1][0:inst.n - sboxes * 3, :]) # vhdl fileout with io.open(vhdl_fileout, 'w') as matfile: matfile.write("library ieee;\n") matfile.write("use ieee.std_logic_1164.all;\n\n") matfile.write("library work;\n\n") matfile.write("package lowmc_pkg is\n") matfile.write(" constant N : integer := {};\n".format(blocksize)) matfile.write(" constant K : integer := {};\n".format(keysize)) matfile.write(" constant M : integer := {};\n".format(sboxes)) matfile.write(" constant R : integer := {};\n".format(rounds)) matfile.write(" constant S : integer := {};\n\n".format(3 * sboxes)) matfile.write( " type T_NK_MATRIX is array(0 to N - 1) of std_logic_vector(K - 1 downto 0);\n" ) matfile.write( " type T_NN_MATRIX is array(0 to N - 1) of std_logic_vector(N - 1 downto 0);\n" ) matfile.write( " type T_SK_MATRIX is array(0 to S - 1) of std_logic_vector(K - 1 downto 0);\n" ) matfile.write( " type T_SN_MATRIX is array(0 to S - 1) of std_logic_vector(N - 1 downto 0);\n" ) matfile.write( " type T_NSS_MATRIX is array(0 to (N - S) - 1) of std_logic_vector(S - 1 downto 0);\n" ) matfile.write( " type T_RS_MATRIX is array(0 to R - 1) of std_logic_vector(S - 1 downto 0);\n\n" ) matfile.write( " type T_KMATRIX is array (0 to R - 1) of T_SK_MATRIX;\n") matfile.write( " type T_ZMATRIX is array (0 to R - 2) of T_SN_MATRIX;\n") matfile.write( " type T_RMATRIX is array (0 to R - 2) of T_NSS_MATRIX;\n\n") # linaer part of key matrices (n x k) K0 = (precomputed_key_matrix + Kt[0]).transpose() matfile.write(" constant K0 : T_NK_MATRIX := (\n") for i, k in enumerate(K0): print_vector_vhdl(matfile, k, keysize) if i != K0.nrows() - 1: matfile.write(",") matfile.write("\n") matfile.write(" );\n\n") # nonlinear part of key matrices (s x k) precomputed_key_matrix_nlt = precomputed_key_matrix_nl.transpose() matfile.write(" constant KMATRIX : T_KMATRIX := (\n") for i in range(rounds): index_a = i * sboxes * 3 index_b = (i + 1) * sboxes * 3 print_matrix_vhdl(matfile, precomputed_key_matrix_nlt[index_a:index_b], keysize) if i != rounds - 1: matfile.write(",") matfile.write("\n") matfile.write(" );\n\n") # linear part of Constants (n x 1) matfile.write( " constant C0 : std_logic_vector(N - 1 downto 0) := (\n") print_vector_vhdl(matfile, precomputed_constant, blocksize) matfile.write("\n") matfile.write(" );\n\n") # nonlinear part of Constants (s x 1) matfile.write(" constant CONSTANTS : T_RS_MATRIX := (\n") for i in range(rounds): index_a = i * sboxes * 3 index_b = (i + 1) * sboxes * 3 print_vector_vhdl(matfile, precomputed_constant_nl[index_a:index_b], sboxes * 3) if i != rounds - 1: matfile.write(",") matfile.write("\n") matfile.write(" );\n\n") # L1_0* (s x n) L1 = Lt[0][:, blocksize - 3 * sboxes:blocksize].transpose() # Z_i (s x n) matfile.write(" constant ZMATRIX : T_ZMATRIX := (\n") for i in range(0, rounds - 1): if i == 0: print_matrix_vhdl(matfile, L1, blocksize) else: print_matrix_vhdl(matfile, Z_i[i].transpose(), blocksize) if i != rounds - 2: matfile.write(",") matfile.write("\n") matfile.write(" );\n\n") # Z_r (s x s) Z_r = T_vee[-1].transpose().augment( Lt[-1][inst.n - sboxes * 3:inst.n, :].transpose()) matfile.write(" constant ZR : T_NN_MATRIX := (\n") for i, z in enumerate(Z_r): print_vector_vhdl(matfile, z, blocksize) if i != Z_r.nrows() - 1: matfile.write(",") matfile.write("\n") matfile.write(" );\n\n") # Ri_wedge_snipped ((n - s) x s) matfile.write(" constant RMATRIX : T_RMATRIX := (\n") for i in range(0, rounds - 1): Ri = R_wedge_snipped[i].transpose() print_matrix_vhdl(matfile, Ri, sboxes * 3) if i != rounds - 2: matfile.write(",") matfile.write("\n") matfile.write(" );\n\n") matfile.write( "-------------------------------------------------------------------------------\n\n" ) matfile.write(" -- constants for State permutation for RMATRIX\n") max = 0 for i, R in enumerate(R_cols): if len(R) > max: max = len(R) matfile.write( " type INT_ARRAY is array(integer range <>) of integer;\n") if (max > 0): matfile.write( " type R_C_ARRAY is array(0 to {}) of integer;\n".format(max - 1)) matfile.write( " type R_ARRAY is array(0 to R - 2) of R_C_ARRAY;\n\n") matfile.write(" -- number of columns to swap per matrix\n") matfile.write(" constant R_CC : INT_ARRAY(0 to R - 2) := (\n") for i, R in enumerate(R_cols): matfile.write(" {}".format(len(R))) if (i != len(R_cols) - 1): matfile.write(",") matfile.write("\n") matfile.write(" );\n\n") matfile.write(" -- columns to swap per matrix\n") matfile.write(" constant R_C : R_ARRAY := (\n") for i, R in enumerate(R_cols): matfile.write(" (\n") matfile.write(" ") for j in range(max): idx = 0 if j < len(R): idx = R[j] matfile.write("{}".format(idx)) if (j != max - 1): matfile.write(", ") matfile.write("\n") matfile.write(" )") if (i != len(R_cols) - 1): matfile.write(",") matfile.write("\n") matfile.write(" );\n\n") matfile.write("end lowmc_pkg;\n")