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 _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 randomize(self, prime): assert not self.randomized prev = None for i in xrange(0, len(self.bp)): d_i_minus_one = self.bp[i].zero.nrows() d_i = self.bp[i].zero.ncols() MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), d_i_minus_one, d_i) MSZp_square = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), d_i, d_i) if i != 0: MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), d_i_minus_one, d_i) self.bp[i] = self.bp[i].group(MSZp, prime).mult_left(prev.adjoint()) if i != len(self.bp) - 1: cur = MSZp_square.random_element() self.bp[i] = self.bp[i].group(MSZp, prime).mult_right(cur) prev = cur # compute S * B_0 d_0 = self.bp[0].zero.nrows() d_1 = self.bp[0].zero.ncols() S = matrix.identity(d_0) for i in xrange(d_0): S[i, i] = random.randint(0, prime - 1) MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), d_0, d_1) self.bp[0] = self.bp[0].group(MSZp, prime).mult_left(S) # compute B_ell * T r = self.bp[-1].zero.nrows() c = self.bp[-1].zero.ncols() T = matrix.identity(c) for i in xrange(c): T[i, i] = random.randint(0, prime - 1) MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), r, c) self.bp[-1] = self.bp[-1].group(MSZp, prime).mult_right(T) self.randomized = True
def integral_cuspidal_subspace(self): """ In certatain cases this might return the integral structure of the cuspidal subspace. This code is mainly a way to compute the integral structe faster than sage does now. It returns None if it cannot find the integral subspace. """ if self.verbose: tm = cputime(); mem = get_memory_usage(); print("Int struct start") #This code is the same as the firs part of self.M.integral_structure G = set([i for i, _ in self.M._mod2term]) G = list(G) G.sort() #if there is a two term relation between two manin symbols we only need one of the two #so that's why we only use elements from G instead of all manin symbols. if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "G") B = self.M._manin_gens_to_basis.matrix_from_rows(list(G)).sparse_matrix() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "B") #The collums of B now span self.M.integral_structure as ZZ-module B, d = B._clear_denom() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "Clear denom") if d == 1: #for explanation see d == 2 assert len(set([B.nonzero_positions_in_row(i)[0] for i in range(B.nrows()) if len(B.nonzero_positions_in_row(i)) == 1 and B[i, B.nonzero_positions_in_row(i)[0]] == 1])) == B.ncols(), "B doesn't contain the Identity" if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "Check Id") ZZbasis = MatrixSpace(QQ, B.ncols(), sparse=True)(1) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "ZZbasis") elif d == 2: #in this case the matrix B will contain 2*Id as a minor this allows us to compute the hermite normal form of B in a very efficient way. This will give us the integral basis ZZbasis. #if it turns out to be nessecarry this can be generalized to the case d%4==2 if we don't mind to only get the right structure localized at 2 assert len(set([B.nonzero_positions_in_row(i)[0] for i in range(B.nrows()) if len(B.nonzero_positions_in_row(i)) == 1 and B[i, B.nonzero_positions_in_row(i)[0]] == 2])) == B.ncols(), "B doesn't contain 2*Identity" if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "Check 2*Id") E = matrix_modp(B,sparse=True) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "matmodp") E = E.echelon_form() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "echelon") ZZbasis = MatrixSpace(QQ, B.ncols(), sparse=True)(1) for (pivot_row, pivot_col) in zip(E.pivot_rows(), E.pivots()): for j in E.nonzero_positions_in_row(pivot_row): ZZbasis[pivot_col, j] = QQ(1) / 2 if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "ZZbasis") else: return None #now we compute the integral kernel of the boundary map with respect to the integral basis. This will give us the integral cuspidal submodule. boundary_matrix = self.M.boundary_map().matrix() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "Boundary matrix") ZZboundary_matrix=(ZZbasis*boundary_matrix).change_ring(ZZ) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "ZZBoundary matrix") left_kernel_matrix=ZZboundary_matrix.transpose().dense_matrix()._right_kernel_matrix(algorithm='pari') if type(left_kernel_matrix)==tuple: left_kernel_matrix=left_kernel_matrix[1] if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "kernel matrix") ZZcuspidal_basis=left_kernel_matrix*ZZbasis if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "ZZkernel matrix") assert ZZcuspidal_basis.change_ring(QQ).echelon_form()==self.S.basis_matrix() , "the calculated integral basis does not span the right QQ vector space" # a little sanity check. This shows that the colums of ZZcuspidal_basis really span the right QQ vectorspace if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "check") #finally create the sub-module, we delibarately do this as a QQ vector space with custom basis, because this is faster then dooing the calculations over ZZ since sage will then use a slow hermite normal form algorithm. ambient_module=VectorSpace(QQ,ZZcuspidal_basis.ncols()) int_struct = ambient_module.submodule_with_basis(ZZcuspidal_basis.rows()) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "finnished") return int_struct
def is_quotient(M, sym, rank): symbol = GenusSymbol_global_ring(MatrixSpace(ZZ, rank, rank).one()) symbol._local_symbols = [ Genus_Symbol_p_adic_ring(p, syms) for p, syms in sym.iteritems() ] s = get_symbol_string(symbol) print s N = FiniteQuadraticModule(s) t = N.order() / M.order() if not Integer(t).is_square(): return False else: t = sqrt(t) for p in Integer(N.order()).prime_factors(): if not N.signature(p) == M.signature(p): return False # if not N.signature() == M.signature(): # return False for G in N.subgroups(): if G.order() == t and G.is_isotropic(): Q = G.quotient() if Q.is_isomorphic(M): print Q return N else: del Q del N return False
def semidirect_rep_from_twisted_cocycle(self, cocycle): """ Given a representation rho to GL(R, n) and a rho-twisted 1-cocycle, construct the representation to GL(R, n + 1) corresponding to the semidirect product. Note: Since we prefer to stick to left-actions only, unlike [HLK] this is the semidirect produce associated to the left action of GL(R, n) on V = R^n. That is, pairs (v, A) with v in V and A in GL(R, n) where (v, A) * (w, B) = (v + A*w, A*B):: sage: G = Manifold('K12a169').fundamental_group() sage: A = matrix(GF(5), [[0, 4], [1, 4]]) sage: rho = cyclic_rep(G, A) sage: cocycle = vector(GF(5), (0, 0, 1, 0)) sage: rho_til = rho.semidirect_rep_from_twisted_cocycle(cocycle) sage: rho_til('abAB') [1 0 4] [0 1 1] [0 0 1] """ gens, rels, rho = self.generators, self.relators, self n = rho.dim assert len(cocycle) == len(gens) * n new_mats = [] for i, g in enumerate(gens): v = matrix([cocycle[i * n:(i + 1) * n]]).transpose() zeros = matrix(n * [0]) one = matrix([[1]]) A = block_matrix([[rho(g), v], [zeros, one]]) new_mats.append(A) target = MatrixSpace(rho.base_ring, n + 1) return MatrixRepresentation(gens, rels, target, new_mats)
def _compute_IJ(self, p, e): global B, F if p.number_field() != B.base(): raise ValueError( "p must be a prime ideal in the base field of the quaternion algebra" ) if not p.is_prime(): raise ValueError("p must be prime") if p.number_field() != B.base(): raise ValueError( "p must be a prime ideal in the base field of the quaternion algebra" ) if not p.is_prime(): raise ValueError("p must be prime") if F is not p.number_field(): raise ValueError("p must be a prime of {0}".format(F)) R = residue_ring(p**e) if isinstance(R, ResidueRing_base): k = R.ring() else: k = R from sage.all import MatrixSpace M = MatrixSpace(k, 2) i2, j2 = B.invariants() i2 = R(i2) j2 = R(j2) if k.characteristic() == 2: raise NotImplementedError # Find I -- just write it down I = M([0, i2, 1, 0]) # Find J -- I figured this out by just writing out the general case # and seeing what the parameters have to satisfy i2inv = k(1) / i2 a = None for b in R.list(): if not b: continue c = j2 + i2inv * b * b if c.is_square(): a = -c.sqrt() break if a is None: # do a fallback search; needed in char 3 sometimes. for J in M: K = I * J if J * J == j2 and K == -J * I: return I, J, K J = M([a, b, (j2 - a * a) / b, -a]) K = I * J assert K == -J * I, "bug in that I,J don't skew commute" return I, J, R
def ambient_integral_structure_matrix(M,verbose=False): """ In certatain cases (weight two any level) this might return the integral structure of a an ambient modular symbol space. I wrote this because for high level this is very slow in sage because there is no good sparse hermite normal form code in sage for huge matrices. """ if verbose: tm = cputime(); mem = get_memory_usage(); print("Int struct start") #This code is the same as the firs part of M.integral_structure G = set([i for i, _ in M._mod2term]) G = list(G) G.sort() #if there is a two term relation between two manin symbols we only need one of the two #so that's why we only use elements from G instead of all manin symbols. if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "G") B = M._manin_gens_to_basis.matrix_from_rows(list(G)).sparse_matrix() if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "B") #The collums of B now span M.integral_structure as ZZ-module B, d = B._clear_denom() if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "Clear denom") if d == 1: #for explanation see d == 2 assert len(set([B.nonzero_positions_in_row(i)[0] for i in range(B.nrows()) if len(B.nonzero_positions_in_row(i)) == 1 and B[i, B.nonzero_positions_in_row(i)[0]] == 1])) == B.ncols(), "B doesn't contain the Identity" if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "Check Id") ZZbasis = MatrixSpace(QQ, B.ncols(), sparse=True)(1) if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "ZZbasis") elif d == 2: #in this case the matrix B will contain 2*Id as a minor this allows us to compute the hermite normal form of B in a very efficient way. This will give us the integral basis ZZbasis. #if it turns out to be nessecarry this can be generalized to the case d%4==2 if we don't mind to only get the right structure localized at 2 assert len(set([B.nonzero_positions_in_row(i)[0] for i in range(B.nrows()) if len(B.nonzero_positions_in_row(i)) == 1 and B[i, B.nonzero_positions_in_row(i)[0]] == 2])) == B.ncols(), "B doesn't contain 2*Identity" if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "Check 2*Id") E = matrix_modp(B,sparse=True) if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "matmodp") E = E.echelon_form() if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "echelon") ZZbasis = MatrixSpace(QQ, B.ncols(), sparse=True)(1) for (pivot_row, pivot_col) in zip(E.pivot_rows(), E.pivots()): for j in E.nonzero_positions_in_row(pivot_row): ZZbasis[pivot_col, j] = QQ(1) / 2 if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "ZZbasis") else: raise NotImplementedError return ZZbasis
def induced_rep_from_twisted_cocycle(p, rho, chi, cocycle): """ The main metabelian representation from Section 7 of [HKL] for the group of a knot complement, where p is the degree of the branched cover, rho is an irreducible cyclic representation acting on the F_q vector space V, chi is a homomorpism V -> F_q, and cocycle describes the semidirect product extension. We differ from [HKL] in that all actions are on the left, meaning that this representation is defined in terms of the convention for the semidirect product discussed in:: MatrixRepresentation.semidirect_rep_from_twisted_cocycle Here is an example:: sage: G = Manifold('K12n132').fundamental_group() sage: A = matrix(GF(5), [[0, 4], [1, 4]]) sage: rho = cyclic_rep(G, A) sage: cocycle = (0, 0, 0, 1, 1, 2) sage: chi = lambda v: v[0] + 4*v[1] sage: rho_ind = induced_rep_from_twisted_cocycle(3, rho, chi, cocycle) sage: rho_ind('c').list() [0, 0, (-z^3 - z^2 - z - 1), z^2*t^-1, 0, 0, 0, (-z^3 - z^2 - z - 1)*t^-1, 0] """ q = rho.base_ring.order() n = rho.dim K = CyclotomicField(q, 'z') z = K.gen() A = rho.A R = LaurentPolynomialRing(K, 't') t = R.gen() MatSp = MatrixSpace(R, p) gens = rho.generators images = dict() for s, g in enumerate(gens): v = vector(cocycle[s * n:(s + 1) * n]) e = rho.epsilon(g)[0] U = MatSp(0) for j in range(0, p): k, l = (e + j).quo_rem(p) U[l, j] = t**k * z**chi(A**(-l) * v) images[g] = U e, v = -e, -A**(-e) * v V = MatSp(0) for j in range(0, p): k, l = (e + j).quo_rem(p) V[l, j] = t**k * z**chi(A**(-l) * v) images[g.swapcase()] = V alpha = MatrixRepresentation(gens, rho.relators, MatSp, images) alpha.epsilon = rho.epsilon return alpha
def test_eigenvalues(prec=100, nmax=10, dimmax=10): r""" Test the eigenvalue computations for some random matrices. """ F = MPComplexField(prec) dim = ZZ.random_element(2, dimmax) M = MatrixSpace(F, dim) for n in range(nmax): A, U, l = random_matrix_eigenvalues(F, dim) ev = A.eigenvalues() ev.sort() l.sort() test = max([abs(ev[j] - l[j]) for j in range(len(ev))]) assert test < A.eps() * 100
def _test_matrix_smith(self, **options): r""" Test that :meth:`_matrix_smith_form` works correctly. EXAMPLES:: sage: ZpCA(5, 15)._test_matrix_smith() """ tester = self._tester(**options) tester.assertEqual(self.residue_field().characteristic(), self.residue_characteristic()) from itertools import chain from sage.all import MatrixSpace from .precision_error import PrecisionError matrices = chain(*[ MatrixSpace(self, n, m).some_elements() for n in (1, 3, 7) for m in (1, 4, 7) ]) for M in tester.some_elements(matrices): bases = [self] if self is not self.integer_ring(): bases.append(self.integer_ring()) for base in bases: try: S, U, V = M.smith_form(integral=base) except PrecisionError: continue if self.is_exact() or self._prec_type() not in [ 'fixed-mod', 'floating-point' ]: tester.assertEqual(U * M * V, S) tester.assertEqual(U.nrows(), U.ncols()) tester.assertEqual(U.base_ring(), base) tester.assertEqual(V.nrows(), V.ncols()) tester.assertEqual(V.base_ring(), base) for d in S.diagonal(): if not d.is_zero(): tester.assertTrue(d.unit_part().is_one()) for (d, dd) in zip(S.diagonal(), S.diagonal()[1:]): tester.assertTrue(d.divides(dd))
def random_matrix_eigenvalues(F, n): r""" Give a random matrix together with its eigenvalues. """ l = list() M = MatrixSpace(F, n) U = Matrix(F, n) D = Matrix(F, n) for i in xrange(n): x = F.random_element() l.append(x) D[i, i] = x # now we need a unitary matrix: # make a random choice of vectors and use Gram-Schmidt to orthogonolize U = random_unitary_matrix(F, n) UT = U.transpose().conjugate() A = U * D * UT l.sort(cmp=my_abscmp) return A, U, l
def __pow__(self, n, _=None): r""" Return the vector space of dimension ``n`` over this field. EXAMPLES:: sage: from pyeantic import RealEmbeddedNumberField sage: K = NumberField(x**2 - 2, 'a', embedding=sqrt(AA(2))) sage: K = RealEmbeddedNumberField(K) sage: K^3 Vector space of dimension 3 over Real Embedded Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095? """ if isinstance(n, tuple): m, n = n from sage.all import MatrixSpace return MatrixSpace(self, m, n) else: from sage.all import VectorSpace return VectorSpace(self, n)
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 prev = None for i in xrange(0, len(self.bp)): d_i_minus_one = self.bp[i].zero.nrows() d_i = self.bp[i].zero.ncols() MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), d_i_minus_one, d_i) MSZp_square = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), d_i, d_i) if i != 0: MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), d_i_minus_one, d_i) self.bp[i] = self.bp[i].group(MSZp, prime).mult_left(prev.adjoint()) if i != len(self.bp) - 1: cur = MSZp_square.random_element() self.bp[i] = self.bp[i].group(MSZp, prime).mult_right(cur) prev = cur # compute S * B_0 d_0 = self.bp[0].zero.nrows() d_1 = self.bp[0].zero.ncols() S = matrix.identity(d_0) for i in xrange(d_0): S[i, i] = random.randint(0, prime - 1) MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), d_0, d_1) self.bp[0] = self.bp[0].group(MSZp, prime).mult_left(S) # compute B_ell * T r = self.bp[-1].zero.nrows() c = self.bp[-1].zero.ncols() T = matrix.identity(c) for i in xrange(c): T[i, i] = random.randint(0, prime - 1) MSZp = MatrixSpace(ZZ.residue_field(ZZ.ideal(prime)), r, c) self.bp[-1] = self.bp[-1].group(MSZp, prime).mult_right(T) self.randomized = True
""" Tools for use in Sage. """ import os, sys, re, string, tempfile from ..sage_helper import _within_sage, sage_method if _within_sage: import sage from sage.all import (ZZ, vector, matrix, block_matrix, gcd, prod, det, MatrixSpace, AbelianGroup, GroupAlgebra, SageObject, PolynomialRing, LaurentPolynomialRing) from .polished_reps import polished_holonomy, MatrixRepresentation Id2 = MatrixSpace(ZZ, 2)(1) else: SageObject = object ZZ, Id2 = None, None def search_for_low_rank_triangulation(M, trys=100, target_lower_bound=0): rank_lower_bound = max(M.homology().rank(), target_lower_bound) rank_upper_bound = M.fundamental_group().num_generators() N = M.copy() curr_best_tri = N.copy() for i in range(trys): if rank_upper_bound == rank_lower_bound: break N.randomize() new_rank = N.fundamental_group().num_generators()
def vector_to_double_char(v): assert len(v) == 2 return CHARSET[v[0]] + CHARSET[v[1]] def encrypt(msg, K): assert all(c in CHARSET for c in msg) assert len(msg) % 2 == 0 A, v = K ciphertext = "" for i in range(0, len(msg), 2): tmp = A * double_char_to_vector(msg[i:i + 2]) + v ciphertext += vector_to_double_char(tmp) return ciphertext if __name__ == '__main__': from secret import flag assert flag.startswith('kmactf') A = MatrixSpace(Fp, 2, 2).random_element() v = VectorSpace(Fp, 2).random_element() assert A.determinant() != 0 print('ciphertext =', repr(encrypt(flag, (A, v)))) # Output: # ciphertext = 'u_rm3eefa}_7det1znb{sce{qo0h7yf0b}sktse8xtr6'
def solve(vectors, goal): M = MatrixSpace(GF(2), len(vectors), len(vectors[0])) V = VectorSpace(GF(2), len(goal)) A = M(vectors) b = V(goal) return A.solve_left(b)
def rho(self,M,silent=0,numeric=0,prec=-1): r""" The Weil representation acting on SL(2,Z). INPUT:: -``M`` -- element of SL2Z - ''numeric'' -- set to 1 to return a Matrix_complex_dense with prec=prec instead of exact - ''prec'' -- precision EXAMPLES:: sage: WR=WeilRepDiscriminantForm(1,dual=False) sage: S,T=SL2Z.gens() sage: WR.rho(S) [ [-zeta8^3 -zeta8^3] [-zeta8^3 zeta8^3], sqrt(1/2) ] sage: WR.rho(T) [ [ 1 0] [ 0 -zeta8^2], 1 ] sage: A=SL2Z([-1,1,-4,3]); WR.rho(A) [ [zeta8^2 0] [ 0 1], 1 ] sage: A=SL2Z([41,77,33,62]); WR.rho(A) [ [-zeta8^3 zeta8^3] [ zeta8 zeta8], sqrt(1/2) ] """ N=self._N; D=2*N; D2=2*D if numeric==0: K=CyclotomicField (lcm(4*self._N,8)) z=K(CyclotomicField(4*self._N).gen()) rho=matrix(K,D) else: CF = MPComplexField(prec) RF = CF.base() MS = MatrixSpace(CF,int(D),int(D)) rho = Matrix_complex_dense(MS) #arg = RF(2)*RF.pi()/RF(4*self._N) z = CF(0,RF(2)*RF.pi()/RF(4*self._N)).exp() [a,b,c,d]=M fak=1; sig=1 if c<0: # need to use the reflection # r(-A)=r(Z)r(A)sigma(Z,A) where sigma(Z,A)=-1 if c>0 sig=-1 if numeric==0: fz=CyclotomicField(4).gen() # = i else: fz=CF(0,1) # the factor is rho(Z) sigma(Z,-A) #if(c < 0 or (c==0 and d>0)): # fak=-fz #else: #sig=1 #fz=1 fak=fz a=-a; b=-b; c=-c; d=-d; A=SL2Z([a,b,c,d]) if numeric==0: chi=self.xi(A) else: chi=CF(self.xi(A).complex_embedding(prec)) if(silent>0): print("fz={0}".format(fz)) print("chi={0}".format(chi)) elif c == 0: # then we use the simple formula if d < 0: sig=-1 if numeric == 0: fz=CyclotomicField(4).gen() else: fz=CF(0,1) fak=fz a=-a; b=-b; c=-c; d=-d; else: fak=1 for alpha in range(D): arg=(b*alpha*alpha ) % D2 if(sig==-1): malpha = (D - alpha) % D rho[malpha,alpha]=fak*z**arg else: #print "D2=",D2 #print "b=",b #print "arg=",arg rho[alpha,alpha]=z**arg return [rho,1] else: if numeric==0: chi=self.xi(M) else: chi=CF(self.xi(M).complex_embedding(prec)) Nc=gcd(Integer(D),Integer(c)) #chi=chi*sqrt(CF(Nc)/CF(D)) if(valuation(Integer(c),2)==valuation(Integer(D),2)): xc=Integer(N) else: xc=0 if silent>0: print("c={0}".format(c)) print("xc={0}".format(xc)) print("chi={0}".format(chi)) for alpha in range(D): al=QQ(alpha)/QQ(D) for beta in range(D): be=QQ(beta)/QQ(D) c_div=False if(xc==0): alpha_minus_dbeta=(alpha-d*beta) % D else: alpha_minus_dbeta=(alpha-d*beta-xc) % D if silent > 0: # and alpha==7 and beta == 7): print("alpha,beta={0},{1}".format(alpha,beta)) print("c,d={0},{1}".format(c,d)) print("alpha-d*beta={0}".format(alpha_minus_dbeta)) invers=0 for r in range(D): if (r*c - alpha_minus_dbeta) % D ==0: c_div=True invers=r break if c_div and silent > 0: print("invers={0}".format(invers)) print(" inverse(alpha-d*beta) mod c={0}".format(invers)) elif(silent>0): print(" no inverse!") if(c_div): y=invers if xc==0: argu=a*c*y**2+b*d*beta**2+2*b*c*y*beta else: argu=a*c*y**2+2*xc*(a*y+b*beta)+b*d*beta**2+2*b*c*y*beta argu = argu % D2 tmp1=z**argu # exp(2*pi*I*argu) if silent>0:# and alpha==7 and beta==7): print("a,b,c,d={0},{1},{2},{3}".format(a,b,c,d)) print("xc={0}".format(xc)) print("argu={0}".format(argu)) print("exp(...)={0}".format(tmp1)) print("chi={0}".format(chi)) print("sig={0}".format(sig)) if sig == -1: minus_alpha = (D - alpha) % D rho[minus_alpha,beta]=tmp1*chi else: rho[alpha,beta]=tmp1*chi #print "fak=",fak if numeric==0: return [fak*rho,sqrt(QQ(Nc)/QQ(D))] else: return [CF(fak)*rho,RF(sqrt(QQ(Nc)/QQ(D)))]
def __init__(self, phi, alpha, N): self.base_ring = phi.range() self.image_ring = MatrixSpace(self.base_ring, N) self.phi, self.alpha, self.N = phi, alpha, N
def modp_splitting(p): """ INPUT: - p -- ideal of the number field K = B.base() with ring O of integers. OUTPUT: - matrices I, J in M_2(O/p) such that i |--> I and j |--> J defines an algebra morphism, i.e., I^2=a, J^2=b, I*J=-J*I. EXAMPLES:: sage: from psage.modform.hilbert.sqrt5.sqrt5 import F, B, modp_splitting sage: c = F.factor(31)[0][0] sage: modp_splitting(c) ( [ 0 30] [18 4] [ 1 0], [ 4 13] ) sage: c = F.factor(37)[0][0]; c Fractional ideal (37) sage: I, J = modp_splitting(c); I, J ( [ 0 36] [23*abar + 21 36*abar + 8] [ 1 0], [ 36*abar + 8 14*abar + 16] ) sage: I^2 [36 0] [ 0 36] sage: J^2 [36 0] [ 0 36] sage: I*J == -J*I True AUTHOR: William Stein """ global B, F # Inspired by the code in the function # modp_splitting_data in algebras/quatalg/quaternion_algebra.py if p.number_field() != B.base(): raise ValueError, "p must be a prime ideal in the base field of the quaternion algebra" if not p.is_prime(): raise ValueError, "p must be prime" if F is not p.number_field(): raise ValueError, "p must be a prime of %s" % F k = p.residue_field() from sage.all import MatrixSpace M = MatrixSpace(k, 2) i2, j2 = B.invariants() i2 = k(i2) j2 = k(j2) if k.characteristic() == 2: if i2 == 0 or j2 == 0: raise NotImplementedError return M([0, 1, 1, 0]), M([1, 1, 0, 1]) # Find I -- just write it down I = M([0, i2, 1, 0]) # Find J -- I figured this out by just writing out the general case # and seeing what the parameters have to satisfy i2inv = 1 / i2 a = None for b in list(k): if not b: continue c = j2 + i2inv * b * b if c.is_square(): a = -c.sqrt() break if a is None: # do a fallback search; needed in char 3 sometimes. for J in M: K = I * J if J * J == j2 and K == -J * I: return I, J, K J = M([a, b, (j2 - a * a) / b, -a]) K = I * J assert K == -J * I, "bug in that I,J don't skew commute" return I, J
3-manifold to very high precision. """ import os, sys, re, string, tempfile from itertools import product, chain from functools import reduce from ..sage_helper import _within_sage from ..pari import pari from .fundamental_polyhedron import * if _within_sage: import sage from sage.all import RealField, ComplexField, gcd, prod, powerset from sage.all import MatrixSpace, matrix, vector, ZZ Object = sage.structure.sage_object.SageObject identity = lambda A: MatrixSpace(A.base_ring(), A.nrows())(1) abelian_group_elt = lambda v: vector(ZZ, v) else: Object = object from .utilities import Matrix2x2 as matrix, powerset from ..number import Number def identity(A): return matrix(A.base_ring(), 1.0, 0.0, 0.0, 1.0) def prod(L, initial=None): if initial: return reduce(lambda x, y: x * y, L, initial) elif L: return reduce(lambda x, y: x * y, L) else: