def T(self, n): """ Return matrix mod 2 of the n-th Hecke operator on the +1 quotient of cuspidal modular symbols. INPUT: - `n` -- integer OUTPUT: matrix modulo 2 EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.T(2) 22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) sage: C.T(2)[0] (1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1) """ if self.verbose: tm = cputime(); mem = get_memory_usage(); print("T(%s) start" % (n)) T = self.M.hecke_matrix(n).restrict(self.S_integral, check=False) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "T created") if self.verbose: print("sparsity", len(T.nonzero_positions()) / RR(T.nrows()**2), T.nrows()) T = matrix_modp(T) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "T reduced") #self.M._hecke_matrices={} #self.S._hecke_matrices={} #if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "T freed" return matrix_modp(T)
def verify_gamma1(self,d,t,v): dependencies=[] if self.verbose: tm = cputime(); mem = get_memory_usage(); print "verif gamma1 start" satisfied=True message="" for i in xrange(d, (d - 1) // 2, -1): #We only need to start at d/2 since the dependencies(k,l) contains all neccesary #checks for largest partition of zise at most k and second largest at most l dependency = self.dependencies(t, i, d - i, v) dependencies.append(dependency) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "dep (%s,%s)" % (i, d - i) assert dependency.degree() == len(self.coset_representatives_H()) * (d - i) + 2 * i - d assert dependency.degree() - dependency.dimension() <= self.S.dimension() if dependency.dimension() == 0: if self.verbose: print "...no dependencies found" elif dependency.dimension() > 12: satisfied=False print "dependency dimension to large to search through" else: if self.verbose: print "dependency dimension is:", dependency.dimension() min_dist = LinearCode(dependency).minimum_distance() if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "min dist" if self.verbose: print "...the smallest dependency has %s nonzero coefficients." % (min_dist) if min_dist > d: if self.verbose: print i, d - i, "passed" else: satisfied,message= False, "There is a dependency of weigt %s in dependencies(%s,%s)" % (min_dist, i, d - i) return satisfied, message,dependencies
def render_curve_webpage_by_label(label): cpt0 = cputime() t0 = time.time() data = WebEC.by_label(label) if data == "Invalid label": return elliptic_curve_jump_error(label, {}) if data == "Curve not found": return elliptic_curve_jump_error(label, {}, missing_curve=True) try: lmfdb_label = data.lmfdb_label except AttributeError: return elliptic_curve_jump_error(label, {}) data.modform_display = url_for(".modular_form_display", label=lmfdb_label, number="") code = data.code() code['show'] = {'magma':'','pari':'','sage':''} # use default show names T = render_template("ec-curve.html", properties=data.properties, credit=ec_credit(), data=data, # set default show names but actually code snippets are filled in only when needed code=code, bread=data.bread, title=data.title, friends=data.friends, downloads=data.downloads, KNOWL_ID="ec.q.%s"%lmfdb_label, BACKUP_KNOWL_ID="ec.q.%s"%data.lmfdb_iso, learnmore=learnmore_list()) ec_logger.debug("Total walltime: %ss"%(time.time() - t0)) ec_logger.debug("Total cputime: %ss"%(cputime(cpt0))) return T
def render_curve_webpage_by_label(label): cpt0 = cputime() t0 = time.time() data = WebEC.by_label(label) if data == "Invalid label": return elliptic_curve_jump_error(label, {}, wellformed_label=False) if data == "Curve not found": return elliptic_curve_jump_error(label, {}, wellformed_label=True, missing_curve=True) try: lmfdb_label = data.lmfdb_label except AttributeError: return elliptic_curve_jump_error(label, {}, wellformed_label=False) data.modform_display = url_for(".modular_form_display", label=lmfdb_label, number="") code = data.code() code['show'] = {'magma':'','pari':'','sage':''} # use default show names T = render_template("ec-curve.html", properties2=data.properties, credit=ec_credit(), data=data, # set default show names but actually code snippets are filled in only when needed code=code, bread=data.bread, title=data.title, friends=data.friends, downloads=data.downloads, KNOWL_ID="ec.q.%s"%label, BACKUP_KNOWL_ID="ec.q.%s"%data.lmfdb_iso, learnmore=learnmore_list()) ec_logger.debug("Total walltime: %ss"%(time.time() - t0)) ec_logger.debug("Total cputime: %ss"%(cputime(cpt0))) return T
def compute_ambient_space(N, k, i): if i == 'all': G = DirichletGroup(N).galois_orbits() sgn = (-1)**k for j, g in enumerate(G): if g[0](-1) == sgn: compute_ambient_space(N,k,j) return if i == 'quadratic': G = DirichletGroup(N).galois_orbits() sgn = (-1)**k for j, g in enumerate(G): if g[0](-1) == sgn and g[0].order()==2: compute_ambient_space(N,k,j) return filename = filenames.ambient(N, k, i) if os.path.exists(filename): return eps = character(N, i) t = cputime() M = ModularSymbols(eps, weight=k, sign=1) tm = cputime(t) save(M, filename) meta = {'cputime':tm, 'dim':M.dimension(), 'M':str(M), 'version':version()} save(meta, filenames.meta(filename))
def T(self, n): """ Return matrix mod 2 of the n-th Hecke operator on the +1 quotient of cuspidal modular symbols. INPUT: - `n` -- integer OUTPUT: matrix modulo 2 EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.T(2) 22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) sage: C.T(2)[0] (1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1) """ if self.verbose: tm = cputime(); mem = get_memory_usage(); print "T(%s) start" % (n) T = self.M.hecke_matrix(n).restrict(self.S_integral, check=False) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "T created" if self.verbose: print "sparsity", len(T.nonzero_positions()) / RR(T.nrows()**2), T.nrows() T = matrix_modp(T) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "T reduced" #self.M._hecke_matrices={} #self.S._hecke_matrices={} #if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "T freed" return matrix_modp(T)
def compute_atkin_lehner(N, k, i): filename = filenames.ambient(N, k, i) if not os.path.exists(filename): print "Ambient (%s,%s,%s) space not computed."%(N,k,i) return #compute_ambient_space(N, k, i) print "computing atkin-lehner for (%s,%s,%s)"%(N,k,i) m = filenames.number_of_known_factors(N, k, i) M = load_ambient_space(N, k, i) for d in range(m): atkin_lehner_file = filenames.factor_atkin_lehner(N, k, i, d, False) if os.path.exists(atkin_lehner_file): print "skipping computing atkin_lehner for (%s,%s,%s,%s) since it already exists"%(N,k,i,d) # already done continue # compute atkin_lehner print "computing atkin_lehner for (%s,%s,%s,%s)"%(N,k,i,d) t = cputime() A = load_factor(N, k, i, d, M) al = ' '.join(['+' if a > 0 else '-' for a in atkin_lehner_signs(A)]) print al open(atkin_lehner_file, 'w').write(al) tm = cputime(t) meta = {'cputime':tm, 'version':version()} save(meta, filenames.meta(atkin_lehner_file))
def verify_gamma1(self,d,t,v): dependencies=[] if self.verbose: tm = cputime(); mem = get_memory_usage(); print("verif gamma1 start") satisfied=True message="" for i in range(d, (d - 1) // 2, -1): #We only need to start at d/2 since the dependencies(k,l) contains all neccesary #checks for largest partition of zise at most k and second largest at most l dependency = self.dependencies(t, i, d - i, v) dependencies.append(dependency) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "dep (%s,%s)" % (i, d - i)) assert dependency.degree() == len(self.coset_representatives_H()) * (d - i) + 2 * i - d assert dependency.degree() - dependency.dimension() <= self.S.dimension() if dependency.dimension() == 0: if self.verbose: print("...no dependencies found") elif dependency.dimension() > 12: satisfied=False print("dependency dimension to large to search through") else: if self.verbose: print("dependency dimension is:", dependency.dimension()) min_dist = LinearCode(dependency).minimum_distance() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "min dist") if self.verbose: print("...the smallest dependency has %s nonzero coefficients." % (min_dist)) if min_dist > d: if self.verbose: print(i, d - i, "passed") else: satisfied,message= False, "There is a dependency of weigt %s in dependencies(%s,%s)" % (min_dist, i, d - i) return satisfied, message,dependencies
def g(N): from sage.misc.misc import alarm, cancel_alarm alarm(maxtime) from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine('postgresql://[email protected]:6432/mrc2', echo=False) s = sessionmaker(bind=engine)() t = cputime() x,y,z = ideal_to_tuple(N) q = s.query(Space).filter(Space.x==x).filter(Space.y==y).filter(Space.z==z) if q.count() > 0: M = q.one() if M.number_of_rational_newforms == len(M.rational_newforms): return "Already done with level %s (norm = %s)"%(N, N.norm()) H = M.hmf() else: H = QuaternionicModule(N) M = store_space(s, H) V, rational_oldform_dimension = H.dual_rational_newforms(verb=verb) for vdual, aplist in V: f = RationalNewform() for p, ap in aplist: f.store_eigenvalue(p, ap) M.rational_newforms.append(f) f.dual_vector = ns_str(canonically_scale(vdual)) M.number_of_rational_newforms = len(V) M.rational_oldform_dimension = int(rational_oldform_dimension) M.time_to_compute_newforms = cputime(t) s.commit() cancel_alarm() return N.norm(), cputime(t), len(V)
def compute_aplists(N, k, i, *args): if i == 'all': G = DirichletGroup(N).galois_orbits() sgn = (-1)**k for j, g in enumerate(G): if g[0](-1) == sgn: compute_aplists(N,k,j,*args) return if i == 'quadratic': G = DirichletGroup(N).galois_orbits() sgn = (-1)**k for j, g in enumerate(G): if g[0](-1) == sgn and g[0].order()==2: compute_aplists(N,k,j,*args) return if len(args) == 0: args = (100, ) filename = filenames.ambient(N, k, i) if not os.path.exists(filename): print "Ambient (%s,%s,%s) space not computed."%(N,k,i) return #compute_ambient_space(N, k, i) print "computing aplists for (%s,%s,%s)"%(N,k,i) m = filenames.number_of_known_factors(N, k, i) if m == 0: # nothing to do return M = load_ambient_space(N, k, i) for d in range(m): aplist_file = filenames.factor_aplist(N, k, i, d, False, *args) if os.path.exists(aplist_file): print "skipping computing aplist(%s) for (%s,%s,%s,%s) since it already exists"%(args, N,k,i,d) # already done continue # compute aplist print "computing aplist(%s) for (%s,%s,%s,%s)"%(args, N,k,i,d) t = cputime() A = load_factor(N, k, i, d, M) aplist, _ = A.compact_system_of_eigenvalues(prime_range(*args), 'a') print aplist, aplist_file save(aplist, aplist_file) tm = cputime(t) meta = {'cputime':tm, 'version':version()} save(meta, filenames.meta(aplist_file))
def compute_decompositions(N, k, i): if i == 'all': G = DirichletGroup(N).galois_orbits() sgn = (-1)**k for j, g in enumerate(G): if g[0](-1) == sgn: compute_decompositions(N,k,j) return if i == 'quadratic': G = DirichletGroup(N).galois_orbits() sgn = (-1)**k for j, g in enumerate(G): if g[0](-1) == sgn and g[0].order()==2: compute_decompositions(N,k,j) return filename = filenames.ambient(N, k, i) if not os.path.exists(filename): print "Ambient space (%s,%s,%s) not computed."%(N,k,i) return #compute_ambient_space(N, k, i) if not os.path.exists(filename): return eps = DirichletGroup(N).galois_orbits()[i][0] if os.path.exists(filenames.factor(N, k, i, 0, makedir=False)): return t = cputime() M = load_ambient_space(N, k, i) D = M.cuspidal_subspace().new_subspace().decomposition() for d in range(len(D)): f = filenames.factor_basis_matrix(N, k, i, d) if os.path.exists(f): continue A = D[d] B = A.free_module().basis_matrix() Bd = A.dual_free_module().basis_matrix() v = A.dual_eigenvector(names='a', lift=False) # vector over number field nz = A._eigen_nonzero() save(B, filenames.factor_basis_matrix(N, k, i, d)) save(Bd, filenames.factor_dual_basis_matrix(N, k, i, d)) save(v, filenames.factor_dual_eigenvector(N, k, i, d)) save(nz, filenames.factor_eigen_nonzero(N, k, i, d)) tm = cputime(t) meta = {'cputime':tm, 'number':len(D), 'version':version()} save(meta, filenames.decomp_meta(N, k, i))
def process_curve_batch(folder, batch, digits=600, power=15): # cursor = list(C.genus2_curves.curves.find({'is_simple_geom': true,'real_geom_end_alg': u'R x R'}).sort([("cond", ASCENDING)])) totalcurves = len(batch) D = {} success = 0 total = 0 failed = [] for i, curve in enumerate(batch): label = curve['label'] stdout_filename = os.path.join(folder, label + ".stdout") output_filename = os.path.join(folder, label + ".sage") print "%d of %d : label = %s" % (i + 1, totalcurves, label) sys.stdout = open(stdout_filename, 'w') c, w = cputime(), walltime() data, sout = process_curve_lmfdb(curve, digits, power=power, verbose=True, internalverbose=False) print "Time: CPU %.2f s, Wall: %.2f s" % ( cputime(c), walltime(w), ) output_file = open(output_filename, 'w') output_file.write(sout) output_file.close() D[label] = True sys.stdout.flush() os.fsync(sys.stdout.fileno()) sys.stdout = sys.__stdout__ total += 1 if label in D.keys(): success += 1 print "Done: label = %s" % (label) print os.popen("tail -n 1 %s" % stdout_filename).read() else: failed += [label] print "ERROR: label = %s\n" % (label) print "Success rate: %.0f%%\n" % (100. * success / total) print "Failed so far %s" % failed
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 xrange(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 xrange(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 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 dbd(self, d): """ Return matrix of <d>. INPUT: - `d` -- integer OUTPUT: - a matrix modulo 2 EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.dbd(2) 22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) sage: C.dbd(2)^14==1 True sage: C.dbd(2)[0] (0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1) """ d=ZZ(d) if self.verbose: tm = cputime(); mem = get_memory_usage(); print "dbd start" try: return self._dbd[d % self.p] except AttributeError: pass # Find generators of the integers modulo p: gens = Integers(self.p).unit_gens() orders = [g.multiplicative_order() for g in gens] # Compute corresponding <z> operator on integral cuspidal modular symbols X = [self.M.diamond_bracket_operator(z).matrix() for z in gens] if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "create d" X = [x.restrict(self.S_integral, check=False) for x in X] if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "restrict d" X = [matrix_modp(x) for x in X] if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "mod d" # Take combinations to make list self._dbd of all dbd's such that # self._dbd[d] = <d> from itertools import product v = [None] * self.p for ei in product(*[range(i) for i in orders]): di = prod(g**e for e,g in zip(ei,gens)).lift() m = prod(g**e for e,g in zip(ei,X)) v[di] = m if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "mul" assert v.count(None) == (self.p-euler_phi(self.p)) self._dbd = v if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "bdb finnished" return v[d % self.p]
def dbd(self, d): """ Return matrix of <d>. INPUT: - `d` -- integer OUTPUT: - a matrix modulo 2 EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.dbd(2) 22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) sage: C.dbd(2)^14==1 True sage: C.dbd(2)[0] (0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1) """ d=ZZ(d) if self.verbose: tm = cputime(); mem = get_memory_usage(); print("dbd start") try: return self._dbd[d % self.p] except AttributeError: pass # Find generators of the integers modulo p: gens = Integers(self.p).unit_gens() orders = [g.multiplicative_order() for g in gens] # Compute corresponding <z> operator on integral cuspidal modular symbols X = [self.M.diamond_bracket_operator(z).matrix() for z in gens] if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "create d") X = [x.restrict(self.S_integral, check=False) for x in X] if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "restrict d") X = [matrix_modp(x) for x in X] if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "mod d") # Take combinations to make list self._dbd of all dbd's such that # self._dbd[d] = <d> from itertools import product v = [None] * self.p for ei in product(*[list(range(i)) for i in orders]): di = prod(g**e for e,g in zip(ei,gens)).lift() m = prod(g**e for e,g in zip(ei,X)) v[di] = m if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "mul") assert v.count(None) == (self.p-euler_phi(self.p)) self._dbd = v if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "bdb finnished") return v[d % self.p]
def cuspidal_integral_structure_matrix(M,verbose=False): """ Computes the cuspidal integral structure matrix of a modular symbols space in a runningtime hopefully faster then that of sage Input: - M - a modular symbols space Output: - a matrix whose rows give a ZZ basis for the cuspidals supspace with respect to the standard basis of M Tests:: sage: from mdsage import * sage: M = ModularSymbols(Gamma1(15)) sage: cuspidal_integral_structure_matrix(M) [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 -1 0] [ 0 0 0 0 0 1 0 0 1 0 0 -1 0 0 0 0 0] """ #now we compute the integral kernel of the boundary map with respect to the integral basis. This will give us the integral cuspidal submodule. if verbose: tm = cputime(); mem = get_memory_usage(); ZZbasis = ambient_integral_structure_matrix(M,verbose=verbose) boundary_matrix = M.boundary_map().matrix() if verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "Boundary matrix" ZZboundary_matrix=(ZZbasis*boundary_matrix).change_ring(ZZ) if 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 verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "kernel matrix" ZZcuspidal_basis=left_kernel_matrix*ZZbasis if verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "ZZkernel matrix" S=M.cuspidal_subspace() assert ZZcuspidal_basis.change_ring(QQ).echelon_form()==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 verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "finnished" return ZZcuspidal_basis
def cuspidal_integral_structure_matrix(M,verbose=False): """ Computes the cuspidal integral structure matrix of a modular symbols space in a runningtime hopefully faster then that of sage Input: - M - a modular symbols space Output: - a matrix whose rows give a ZZ basis for the cuspidals supspace with respect to the standard basis of M Tests:: sage: from mdsage import * sage: M = ModularSymbols(Gamma1(15)) sage: cuspidal_integral_structure_matrix(M) [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 -1 0] [ 0 0 0 0 0 1 0 0 1 0 0 -1 0 0 0 0 0] """ #now we compute the integral kernel of the boundary map with respect to the integral basis. This will give us the integral cuspidal submodule. if verbose: tm = cputime(); mem = get_memory_usage(); ZZbasis = ambient_integral_structure_matrix(M,verbose=verbose) boundary_matrix = M.boundary_map().matrix() if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "Boundary matrix") ZZboundary_matrix=(ZZbasis*boundary_matrix).change_ring(ZZ) if 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 verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "kernel matrix") ZZcuspidal_basis=left_kernel_matrix*ZZbasis if verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "ZZkernel matrix") S=M.cuspidal_subspace() assert ZZcuspidal_basis.change_ring(QQ).echelon_form()==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 verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "finnished") return ZZcuspidal_basis
def certify_heuristic(g, label=None, digits=600, power=15, verbose=True, internalverbose=False): from heuristic_endomorphisms import EndomorphismData out = "" curve_dict = {} curve_dict['label'] = label curve_dict['digits'] = digits prec = ceil(log(10) / log(2) * digits) curve_dict['prec'] = prec buffer = "curve_dict = {};\n" for key in ['digits', 'prec']: buffer += "curve_dict['%s'] = %s;\n" % (key, curve_dict[key]) buffer += "curve_dict['%s'] = '%s';\n" % ('label', label) if verbose: print buffer out += buffer #Ambient ring buffer = "" buffer += "\n# basic rings\n" buffer += "curve_dict['%s'] = %s;\n" % ('QQx', 'PolynomialRing(QQ, \'x\')') buffer += "# curve_dict, x, and the number field's generator are the only variables are the only global variables\n\n" buffer += "x = curve_dict['QQx'].gen();\n\n" out += buffer Qx = PolynomialRing(QQ, "x") x = Qx.gen() curve_dict['QQx'] = Qx # force g in Qx g = Qx(g.list()) # Compute EndomorphismData # field of definition # and endomorphisms xsubs_list = [x, x + 1, x - 1, 1 - x, -1 - x, x + 2, x - 2, -x - 2, 2 - x] if label == '540800.a.540800.1': xsubs_list = xsubs_list[1:] for xsubs in xsubs_list: try: gtry = g(xsubs) if gtry.degree() == 5: gtry = Qx(gtry(x**(-1)) * x**6) if gtry.degree() == 5: gtry = Qx(gtry((x - 1) / x) * x**6) if verbose: print "Computing the EndomorphismData..." c, w = cputime(), walltime() End = EndomorphismData(gtry, prec=digits) print "Time: CPU %.2f s, Wall: %.2f s" % ( cputime(c), walltime(w), ) else: End = EndomorphismData(gtry, prec=digits) geo = End.geometric_representations() K = End.field_of_definition() g = gtry break except TypeError: pass if label == '810.a.196830.1': power += 2 buffer = "#working with the model y^2 = g(x)\n" buffer += "curve_dict['%s'] = %s;\n" % ('g', g.list()) curve_dict['g'] = g.list() out += buffer if verbose: print buffer # initialize numerical methods iaj = InvertAJglobal(g, prec, internalverbose) #CCap = iaj.C; buffer += "curve_dict['%s'] = %s;\n" % ('CCap', ' ComplexField(%s)' % curve_dict['prec']) #buffer += "CCap = curve_dict['CCap'];\n\n" # generator is r K = End.field_of_definition() if K.degree() == 1: K = QQ buffer = "# Field of definition of alpha\n" buffer += "curve_dict['%s'] = %s;\n" % ('K', sage_str_numberfield(K, 'x', 'r')) buffer += "K = %s\n" % ("curve_dict['K']") if K is not QQ: buffer += "r_approx = %s\n" % (K.gen().complex_embedding(), ) out += buffer out += "r = K.gen();\n" if verbose: print buffer #get the matrices over K geo = End.geometric_representations() #convert to sage # we also must take the transpose alphas = [convert_magma_matrix_to_sage(y, K).transpose() for y in geo[0]] alphas_geo = [y.sage() for y in geo[2]] d = len(alphas) out += "curve_dict['alphas_K'] = [None] * %d\n\n" % d out += "curve_dict['alphas_geo'] = [None] * %d\n\n" % d for i, _ in enumerate(alphas): alpha = alphas[i] alpha_geo = alphas_geo[i] buffer = "curve_dict['alphas_K'][%d] = Matrix(K, %s);\n" % ( i, alpha.rows(), ) buffer += "curve_dict['alphas_geo'][%d] = Matrix(%s);\n\n" % ( i, alpha_geo.rows(), ) out += buffer if verbose: print buffer curve_dict['alphas_K'] = alphas curve_dict['alphas_geo'] = alphas_geo out += "# where we stored all the data, for each alpha\n" out += "curve_dict['data'] = [{} for _ in range(%d) ] ;" % d curve_dict['data'] = [{} for _ in range(d)] for i in range(d): if alphas[i] == Matrix([[1, 0], [0, 1]]): curve_dict['data'][i] = None else: if verbose: print "Computing alpha(P + P)" print "where alpha = Matrix(K, %s)\n" % (alphas[i].rows(), ) # Pick a rational point, or a point over a quadratic extension with small discriminant for j, P0 in enumerate(find_rational_point(g)): if label in [ '540800.a.540800.1', '529.a.529.1', '1521.a.41067.1', '12500.a.12500.1', '18225.c.164025.1' ] and j < 2: pass elif label in ['810.a.196830.1'] and i == 2 and j == 0: pass else: if verbose: print "j = %s" % j sys.stdout.flush() sys.stderr.flush() try: output_alpha = compute_alpha_point(g, iaj, alphas[i], P0, digits, power, verbose=verbose, aggressive=True, append=str(i)) verified, trace_and_norm = add_trace_and_norm_ladic( g, output_alpha, alphas_geo[i], verbose=verbose) break except ZeroDivisionError: pass except OverflowError: if verbose: print "the mesh for numerical integral is too big" pass if verbose: print "trying with a new point\n" if verbose: print "\n\n\n" output_alpha['trace_and_norm'] = trace_and_norm output_alpha['verified'] = verified output_alpha['alphas_geo'] = alphas_geo[i] internal_out = "\n" #local_dict = {}\n\n"; # # the fields internal_out += "# L the field where P and the algx_poly are defined\n" internal_out += "curve_dict['data'][%d]['L'] = %s\n" % ( i, sage_str_numberfield(output_alpha['L'], 'x', 'b' + str(i)), ) if output_alpha['L'] is not QQ: internal_out += "b%d = curve_dict['data'][%d]['L'].gen()\n" % ( i, i) internal_out += "curve_dict['data'][%d]['Lgen_approx'] = %s\n" % ( i, output_alpha['L'].gen().complex_embedding()) internal_out += "\n" internal_out += "curve_dict['data'][%d]['alpha'] = Matrix(curve_dict['data'][%d]['L'], %s) \n\n" % ( i, i, [[elt for elt in row] for row in output_alpha['alpha'].rows()]) internal_out += "curve_dict['data'][%d]['alpha_geo'] = curve_dict['alphas_geo'][%d]\n\n" % ( i, i) internal_out += "curve_dict['data'][%d]['P'] = vector(curve_dict['data'][%d]['L'], %s)\n\n" % ( i, i, output_alpha['P']) internal_out += "# alpha(P + P) - \inf = R0 + R1 - \inf\n" internal_out += "\n\n\n" for key in [ 'algx_poly', 'R', 'x_poly', 'trace_and_norm', 'verified' ]: internal_out += "curve_dict['data'][%d]['%s'] = %s;\n" % ( i, key, output_alpha[key]) # this just clutters the file, # internal_out += "curve_dict['data'][%d]['ajP'] = vector(%s)\n\n" % (i, output_alpha['ajP']); # internal_out += "curve_dict['data'][%d]['alpha2P0'] = alphas_ap[%d] * 2 * local_dict['ajP']\n\n" % (i, i) internal_out += "\n\n\n" curve_dict['data'][i] = output_alpha out += internal_out verified = all( [elt['verified'] for elt in curve_dict['data'] if elt is not None]) out += "curve_dict['verified'] = %s\n\n" % verified return curve_dict, out, verified
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 compute_alpha_point(g, iaj, alpha, P0, digits, power, verbose, aggressive=True, append=""): # input: # * g, defining polynomial of the hyperelliptic curve # * iaj = InvertAJglobal class # * alpha = analytic representation of the endomorphism acting on the tangent space # * digits = how many digits to work with # * power, we will divide by 2**power before inverting the abel jacobi map # * P0, a point in the curve for which we will compute alpha*2(P - \infty) = P1 + P2 - \infty # * verbose # * agressive, raise ZeroDivisionError if we get a P1[0] = P2[0] or one of the points is infty # * append, a string to append to the numberfield generators # # output: a dictionary with the following keys # TODO add the keys output = {} K = alpha.base_ring() CCap = iaj.C prec = CCap.precision() output['prec'] = prec x0, y0 = P0 Kz = PolynomialRing(K, "z") z = Kz.gen() if verbose: print "compute_alpha_point()" print "P0 = %s" % (P0, ) #deal with the field of definition if y0 in K: if K is QQ: L = K from_K_to_L = QQ.hom(1, QQ) else: L = K.change_names("b" + append) from_K_to_L = L.structure()[1] else: L, from_K_to_L = (z**2 - g(x0)).splitting_field("b" + append, simplify_all=True, map=True) output['L'] = L # output['L_str'] = sage_str_numberfield(L, 'x','b'+append); output['from_K_to_L'] = from_K_to_L # output['L_gen'] = toCCap(L.gen(), 53); # figure out y0 in L y0_ap = toCCap(y0, prec) y0s = [elt for elt, _ in (z**2 - g(x0)).roots(L)] assert len(y0s) == 2 y0s_ap = [toCCap(elt, prec) for elt in y0s] if norm(y0_ap - y0s_ap[0]) < norm(y0_ap - y0s_ap[1]): y0 = y0s[0] else: y0 = y0s[1] P0 = vector(L, [x0, y0]) alpha_L = Matrix(L, [[from_K_to_L(elt) for elt in row] for row in alpha.rows()]) alpha_ap = Matrix(CCap, [toCCap_list(row, prec) for row in alpha_L.rows()]) output['P'] = P0 output['alpha'] = alpha_L if verbose: print "L = %s" % L print "%s = %s" % (L.gen(), toCCap(L.gen(), 53)) print "P0 = %s" % (P0, ) print "alpha = %s" % ([[elt for elt in row] for row in alpha_L.rows()], ) P0_ap = vector(CCap, toCCap_list(P0, prec + 192)) if verbose: print "P0_ap = %s" % (vector(CC, P0_ap), ) if verbose: print "Computing AJ of P0..." c, w = cputime(), walltime() ajP0 = vector(CCap, AJ1_digits(g, P0_ap, digits)) print "Time: CPU %.2f s, Wall: %.2f s" % ( cputime(c), walltime(w), ) print else: ajP0 = vector(CCap, AJ1_digits(g, P0_ap, digits)) output['ajP'] = ajP0 aj2P0 = 2 * ajP0 alpha2P0_an = alpha_ap * aj2P0 if verbose: print "Working over %s" % CCap invertAJ_tries = 3 for i in range(invertAJ_tries): #try invertAJ_tries times to invertAJ try: if verbose: print "\n\ninverting AJ..." c, w = cputime(), walltime() alpha2P0_div = iaj.invertAJ(alpha2P0_an, power) print "Time: CPU %.2f s, Wall: %.2f s" % ( cputime(c), walltime(w), ) print "\n\n" else: alpha2P0_div = iaj.invertAJ(alpha2P0_an, power) break except AssertionError as error: print error if verbose: print "an assertion failed while inverting AJ.." if i == invertAJ_tries - 1: if verbose: print "retrying with a new P0" print raise ZeroDivisionError else: iaj.iajlocal.set_basepoints() if verbose: print "retrying again with a new set of base points" if verbose: print "Computing the Mumford coordinates of alpha(2*P0 - 2*W)" c, w = cputime(), walltime() R0, R1 = alpha2P0_div.coordinates() print "Time: CPU %.2f s, Wall: %.2f s" % ( cputime(c), walltime(w), ) else: R0, R1 = alpha2P0_div.coordinates() points = [R0, R1] x_poly = alpha2P0_div.x_coordinates() output['R'] = points output['x_poly'] = x_poly if (R0 in [+Infinity, -Infinity]) or (R1 in [+Infinity, -Infinity]): if aggressive: # we want to avoid these situations if verbose: print "One of the coordinates is at infinity" if R0 in [+Infinity, -Infinity]: print "R0 = %s" % (R0, ) else: print "R1 = %s" % (R1, ) print "retrying with a new P0" print raise ZeroDivisionError else: return output buffer = "# R0 = %s\n" % (vector(CC, R0), ) buffer += "# R1 = %s\n" % (vector(CC, R1), ) buffer += "# and \n# x_poly = %s\n" % (vector(CC, x_poly), ) if verbose: print buffer assert len(x_poly) == 3 algx_poly = [NF_embedding(coeff, L) for coeff in x_poly] buffer = "algx_poly = %s;\n" % (algx_poly, ) if L != QQ: buffer += "#where %s ~ %s\n" % (L.gen(), L.gen().complex_embedding()) buffer += "\n" if verbose: print buffer sys.stdout.flush() sys.stderr.flush() output['algx_poly'] = algx_poly if None in algx_poly: if aggressive: if verbose: print "No algebraic expression for the polynomial" print "retrying with a new P0" sys.stdout.flush() sys.stderr.flush() raise ZeroDivisionError else: return output #c, b, a = algx_poly #if aggressive and b**2 - 4*a*c == 0: # raise ZeroDivisionError if verbose: print "Done compute_alpha_point()" return output
def trace_and_norm_ladic(L, M, P0, P1, P2, f, alpha, degree_bound, primes=120, bits=62, verbose=True): if verbose: print "trace_and_norm_ladic()" print "primes = %d, bits = %d" % (primes, bits) # Input: # * L the number field where P0, alpha, norm and trace are defined over # * M a relative extension of L where P1 and P2 are defined over # * P0 initial point already embedded in M # * P1, P2 image points alpha(2 * P0 - \infty) = P1 + P2 - \infty # * alpha the matrix represing the endomorphism on the tangent space in M # * f the defining polynomial of the curve such that y^2 = f(x) # * degree bound for the trace and norm as rational maps # Note: Due to inconsistencies of the complex embeddings of L and M we require P0 and alpha to be given in M # Output: # * [trace_numberator, trace_denominator, norm_numberator, norm_denominator] # represented as lists of elements in L for arg in [P0, P1, P2, alpha]: assert arg.base_ring() is M hard_bound = 2 * degree_bound + 1 soft_bound = hard_bound + 10 if verbose: print "hard_bound = %d\nsoft_bound = %d" % (hard_bound, soft_bound) print "Generating split primes..." c, w = cputime(), walltime() ps_roots = random_split_primes(field=L, bits=bits, primes=primes, relative_ext=M.relative_polynomial()) print "Time: CPU %.2f s, Wall: %.2f s" % ( cputime(c), walltime(w), ) else: ps_roots = random_split_primes(field=L, bits=bits, primes=primes, relative_ext=M.relative_polynomial()) to_lift_raw = [] if verbose: print "Applying newton lift at each prime" for p_root in ps_roots: ell, root = p_root FF = FiniteField(ell) FF_xell = PolynomialRing(FF, "xell") Lpoly = FF_xell( reduce_list_split(M.relative_polynomial().list(), p_root)) assert Lpoly.degree() == len(Lpoly.roots()) Lroot = Lpoly.roots()[0][0].lift() PSring_ell = PowerSeriesRing(FF, "Tell", default_prec=soft_bound) P0_ell = vector(FF, reduce_list_split_relative(P0, p_root, Lroot)) P1_ell = vector(FF, reduce_list_split_relative(P1, p_root, Lroot)) P2_ell = vector(FF, reduce_list_split_relative(P2, p_root, Lroot)) f_ell = FF_xell(reduce_list_split(f.list(), p_root)) alpha_ell = reduce_matrix_split_relative(alpha, p_root, Lroot) x1_ell, x2_ell = newton_linear(P0_ell, P1_ell, P2_ell, f_ell, alpha_ell, PSring_ell, soft_bound) trace_series_ell = x1_ell + x2_ell norm_series_ell = x1_ell * x2_ell trace_numerator_ell, trace_denominator_ell = rational_reconstruct_poly( FF_xell(trace_series_ell.list()), FF_xell.gen()**trace_series_ell.prec()) norm_numerator_ell, norm_denominator_ell = rational_reconstruct_poly( FF_xell(norm_series_ell.list()), FF_xell.gen()**norm_series_ell.prec()) # shift the series back to zero shift = FF_xell.gen() - P0_ell[0] factors_ell = [ trace_numerator_ell(shift).list(), trace_denominator_ell(shift).list(), norm_numerator_ell(shift).list(), norm_denominator_ell(shift).list() ] degrees_ell = tuple([len(elt) for elt in factors_ell]) to_lift_raw.append((p_root, degrees_ell, factors_ell)) if verbose: print "Getting rid of bad primes..." # get rid of badprimes degrees_count = {} for _, degrees_ell, _ in to_lift_raw: if degrees_ell in degrees_count: degrees_count[degrees_ell] += 1 else: degrees_count[degrees_ell] = 1 max_value = 0 max_arg = None for degrees_ell, count in degrees_count.items(): if count > max_value: max_arg = degrees_ell max_value = count output = [None] * 4 for i, elt in enumerate(max_arg): output[i] = [0] * elt to_lift = [] ps_roots = [] for p_root, degrees_ell, factors_ell in to_lift_raw: if degrees_ell == max_arg: ps_roots.append(p_root) to_lift.append(factors_ell) extra_factor = to_lift[-1] extra_p_root = ps_roots[-1] to_lift = to_lift[:-1] ps_roots = ps_roots[:-1] OL = L.ring_of_integers() p_ideals = [OL.ideal(p, L.gen() - r) for p, r in ps_roots] I = prod(p_ideals) if L is QQ: BI_coordinates = None else: BI = I.basis() # basis as a ZZ-module BI_coordinates = [OL.coordinates(b) for b in BI] if verbose: print "Lifting everything" for i, lift in enumerate(output): for j, elt in enumerate(lift): residues = [residue[i][j] for residue in to_lift] output[i][j] = fractional_CRT_split(residues=residues, ps_roots=ps_roots, K=L, BI_coordinates=BI_coordinates) assert reduce_constant_split(output[i][j], extra_p_root) == extra_factor[i][j] if verbose: print "trace_and_norm_ladic() Done" return output
def __init__(self, p, congruence_type=1, sign=1, algorithm="custom", verbose=False, dump_dir=None): """ Create a Kamienny criterion object. INPUT: - `p` -- prime -- verify that there is no order p torsion over a degree `d` field - `sign` -- 1 (default),-1 or 0 -- the sign of the modular symbols space to use - ``algorithm`` -- "default" or "custom" whether to use a custom (faster) integral structure algorithm or to use the sage builtin algortihm - ``verbose`` -- bool; whether to print extra stuff while running. EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29, algorithm="custom", verbose=False); C Kamienny's Criterion for p=29 sage: C.use_custom_algorithm True sage: C.p 29 sage: C.verbose False """ self.verbose = verbose self.dump_dir = dump_dir if self.verbose: tm = cputime(); mem = get_memory_usage(); print "init" assert congruence_type == 0 or congruence_type == 1 self.congruence_type=congruence_type try: p = ZZ(p) if congruence_type==0: self.congruence_group = Gamma0(p) if congruence_type==1: self.congruence_group = GammaH(p,[-1]) except TypeError: self.congruence_group = GammaH(p.level(),[-1]+p._generators_for_H()) self.congruence_type = ("H",self.congruence_group._list_of_elements_in_H()) self.p = self.congruence_group.level() self.algorithm=algorithm self.sign=sign self.M = ModularSymbols(self.congruence_group, sign=sign) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "modsym" self.S = self.M.cuspidal_submodule() if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "cuspsub" self.use_custom_algorithm = False if algorithm=="custom": self.use_custom_algorithm = True if self.use_custom_algorithm: int_struct = self.integral_cuspidal_subspace() if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "custom int_struct" else: int_struct = self.S.integral_structure() if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "sage int_struct" self.S_integral = int_struct v = VectorSpace(GF(2), self.S.dimension()).random_element() self.v=v if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "rand_vect" if dump_dir: v.dump(dump_dir+"/vector%s_%s" % (p,congruence_type)) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "dump"
def silke(A, c, beta, h, m=None, scale=1, float_type="double"): """ :param A: LWE matrix :param c: LWE vector :param beta: BKW block size :param m: number of samples to consider :param scale: scale rhs of lattice by this factor """ from fpylll import BKZ, IntegerMatrix, LLL, GSO from fpylll.algorithms.bkz2 import BKZReduction as BKZ2 if m is None: m = A.nrows() L = dual_instance1(A, scale=scale) L = IntegerMatrix.from_matrix(L) L = LLL.reduction(L, flags=LLL.VERBOSE) M = GSO.Mat(L, float_type=float_type) bkz = BKZ2(M) t = 0.0 param = BKZ.Param(block_size=beta, strategies=BKZ.DEFAULT_STRATEGY, auto_abort=True, max_loops=16, flags=BKZ.VERBOSE | BKZ.AUTO_ABORT | BKZ.MAX_LOOPS) bkz(param) t += bkz.stats.total_time H = copy(L) import pickle pickle.dump(L, open("L-%d-%d.sobj" % (L.nrows, beta), "wb")) E = [] Y = set() V = set() y_i = vector(ZZ, tuple(L[0])) Y.add(tuple(y_i)) E.append(apply_short1(y_i, A, c, scale=scale)[1]) v = L[0].norm() v_ = v / sqrt(L.ncols) v_r = 3.2 * sqrt(L.ncols - A.ncols()) * v_ / scale v_l = sqrt(h) * v_ fmt = u"{\"t\": %5.1fs, \"log(sigma)\": %5.1f, \"log(|y|)\": %5.1f, \"log(E[sigma]):\" %5.1f}" print print fmt % (t, log(abs(E[-1]), 2), log(L[0].norm(), 2), log(sqrt(v_r**2 + v_l**2), 2)) print for i in range(m): t = cputime() M = GSO.Mat(L, float_type=float_type) bkz = BKZ2(M) t = cputime() bkz.randomize_block(0, L.nrows, stats=None, density=3) LLL.reduction(L) y_i = vector(ZZ, tuple(L[0])) l_n = L[0].norm() if L[0].norm() > H[0].norm(): L = copy(H) t = cputime(t) Y.add(tuple(y_i)) V.add(y_i.norm()) E.append(apply_short1(y_i, A, c, scale=scale)[1]) if len(V) >= 2: fmt = u"{\"i\": %4d, \"t\": %5.1fs, \"log(|e_i|)\": %5.1f, \"log(|y_i|)\": %5.1f," fmt += u"\"log(sigma)\": (%5.1f,%5.1f), \"log(|y|)\": (%5.1f,%5.1f), |Y|: %5d}" print fmt % (i + 2, t, log(abs(E[-1]), 2), log( l_n, 2), log_mean(E), log_var(E), log_mean(V), log_var(V), len(Y)) return E
def check_unproven_ranks(jobs=1, jobid=0, use_weak_bsd=False, skip_real_char=False): todo = list( db.mf_newforms.search({ u'analytic_rank': { '$gt': int(1) }, u'analytic_rank_proved': False })) todo2 = [] todo3 = [] todo4 = [] cnt = 0 vcnt = 0 for i in range(len(todo)): if i % jobs != jobid: continue start = cputime() data = todo[i] if skip_real_char and data[u"char_is_real"]: continue if use_weak_bsd and data[u'weight'] == 2 and data[ u'dim'] == 1 and data[u'char_orbit_index'] == 1: ec_label = "%d.%s1" % ( data[u'level'], cremona_letter_code(data[u'hecke_orbit'] - 1)) r = db.ec_curves.lookup(ec_label)[u'rank'] if data[u'analytic_rank'] != r: print "*** winding element is nonzero, positive analytic rank %d for newform %s appears to be wrong ***" % ( data[u'rank'], data[u'label']) print data[u'label'] todo2.append(data[u'label']) else: print "verified that analytic rank %d of newform %s matches Mordell-Weil rank of elliptic curve %s" % ( data[u'analytic_rank'], data[u'label'], ec_label) continue print "Checking newform %s of dimension %d with analytic rank <= %d..." % ( data[u'label'], data[u'dim'], data[u'analytic_rank']) w = windingelement_hecke_cutter_projected(data, extra_cutter_bound=100) if w != 0: print "*** winding element is nonzero, positive analytic rank %d for newform %s appears to be wrong ***" % ( data[u'rank'], data[u'label']) print data[u'label'] todo2.append(data[u'label']) else: if data[u'analytic_rank'] == 2 and data["is_self_dual"]: print "Verified analytic rank is 2." vcnt += 1 else: print "Verified analytic rank > 0" todo3.append(data[u'label']) print "Processed newform %s in %.3f CPU seconds" % (data[u'label'], cputime() - start) cnt += 1 todo = list( db.mf_newforms.search({ u'analytic_rank': int(1), u'is_self_dual': False, u'analytic_rank_proved': False })) for i in range(len(todo)): if i % jobs != jobid: continue start = cputime() data = todo[i] if skip_real_char and data[u"char_is_real"]: continue print "Checking non-self-dual newform %s of dimension %d with analytic rank <= %d..." % ( data[u'label'], data[u'dim'], data[u'analytic_rank']) w = windingelement_hecke_cutter_projected(data, extra_cutter_bound=100) if w != 0: print "*** winding element is nonzero, positive analytic rank appears to be wrong ***" print data[u'label'] todo4.append(data[u'label']) else: print "Verified analytic rank is 1." vcnt += 1 print "Processed newform %s in %.3f CPU seconds" % (data[u'label'], cputime() - start) cnt += 1 print "Checked analytic ranks of %d newforms, of which %d were verified" % ( cnt, vcnt) if len(todo2) > 0 or len(todo4) > 0: print "The following newforms appear to have the wrong analytic rank:" for r in todo2: print " %s (claimed analytic rank %d)" % (r[u'lable'], r[u'analytic_rank']) for r in todo4: print " %s (claimed analytic rank %d)" % (r[u'lable'], r[u'analytic_rank']) if len(todo3) > 0: print "The following newforms have positive but unverified analytic ranks:" for r in todo2: print " %s (claimed analytic rank %d, proved nonzero)" % ( r[u'lable'], r[u'analytic_rank'])
def solve(self, beta, max_iterations=100, tolerance=None, x0=None): # solve \sum_j (\int_bj ^{P_j} w_i)_i = beta # assumes beta is small if tolerance == None: tolerance = mpmath.mpf(2)**(-mpmath.mp.prec + 3) #print "tolerance = %s" % tolerance beta = mpmath.matrix([b for b in beta]) while True: try: basepoints = self.get_basepoints() if x0 is None: x = mpmath.matrix([b[0] for b in basepoints]) value = mpmath.matrix([0 for _ in range(self.genus)]) else: assert len(x0) == self.genus x = mpmath.matrix(x0) if self.verbose: c, w = cputime(), walltime() value = self.to_J_sum(x) print "Time: CPU %.2f s, Wall: %.2f s" % ( cputime(c), walltime(w), ) else: value = self.to_J_sum(x) previous_norm = 1 divg_bound = 3 divergingQ = 0 for k in range(max_iterations): J = self.jacobian(x) # J y = f(x) - beta y = mpmath.lu_solve(J, value - beta) x = x - y norm = mpmath.norm(y) / mpmath.norm(x) if self.verbose: print "k = %d norm = %.3e" % (k, norm) if norm < tolerance: return (x, y) if norm / previous_norm > 1.5: divergingQ += 1 else: divergingQ = 0 previous_norm = norm if divergingQ > divg_bound: raise RuntimeWarning( "method failed: the error diverged") if self.verbose: c, w = cputime(), walltime() value = self.to_J_sum(x) print "Time: CPU %.2f s, Wall: %.2f s" % ( cputime(c), walltime(w), ) else: value = self.to_J_sum(x) else: raise RuntimeWarning( "method failed: max number of iterations reached") except NotImplementedError as e: print e print "Generating new basepoints" self.set_basepoints()
def t1_prime(self, n=5, p=65521): """ Return a multiple of element t1 of the Hecke algebra mod 2, computed using the Hecke operator $T_n$, where n is self.n. To make computation faster we only check if ...==0 mod p. Hence J will contain more elements, hence we get a multiple. INPUT: - `n` -- integer (optional default=5) - `p` -- prime (optional default=65521) OUTPUT: - a mod 2 matrix EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.t1_prime() 22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) sage: C.t1_prime(n=3) == 1 True sage: C = KamiennyCriterion(37) sage: C.t1_prime()[0] (1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0) """ if self.verbose: tm = cputime(); mem = get_memory_usage(); print "t1 start" T = self.S.hecke_matrix(n) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "hecke 1" f = self.hecke_polynomial(n) # this is the same as T.charpoly() if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "char 1" Fint = f.factor() if all(i[1]!=1 for i in Fint): return matrix_modp(zero_matrix(T.nrows())) # raise ValueError("T_%s needs to be a generator of the hecke algebra"%n) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "factor 1, Fint = %s"%(Fint) R = f.parent().change_ring(GF(p)) F = Fint.base_change(R) # Compute the iterators of T acting on the winding element. e = self.M([0, oo]).element().dense_vector().change_ring(GF(p)) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "wind" t = matrix_modp(self.M.hecke_matrix(n).dense_matrix(), p) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "hecke 2" g = t.charpoly() if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "char 2" Z = t.iterates(e, t.nrows(), rows=True) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "iter" # We find all factors F[i][0] for f such that # (g/F[i][0])(t) * e = 0. # We do this by computing the polynomial # h = g/F[i][0], # turning it into a vector v, and computing # the matrix product v * Z. If the product # is 0, then e is killed by h(t). J = [] for i in range(len(F)): if F[i][1]!=1: J.append(i) continue h, r = g.quo_rem(F[i][0] ** F[i][1]) assert r == 0 v = vector(GF(p), h.padded_list(t.nrows())) if v * Z == 0: J.append(i) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "zero check" if self.verbose: print "J =", J if len(J) == 0: # The annihilator of e is the 0 ideal. return matrix_modp(identity_matrix(T.nrows())) # Finally compute t1. I'm concerned about how # long this will take, so we reduce T mod 2 first. # It is important to call "self.T(2)" to get the mod-2 # reduction of T2 with respect to the right basis (e.g., the # integral basis in case use_integral_structure is true. Tmod2 = self.T(n) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "hecke mod" g = prod(Fint[i][0].change_ring(GF(2)) ** Fint[i][1] for i in J) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "g has degree %s"%(g.degree()) t1 = g(Tmod2) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "t1 finnished" return t1
def verify_criterion(self, d, t=None, n=5, p=65521, q=3, v=None, use_rand_vec=False, verbose=False): """ Attempt to verify the criterion at p using the input t. If t is not given compute it using n, p and q INPUT: - `t` -- hecke operator (optional default=None) - `n` -- integer (optional default=5), used in computing t1 - `p` -- prime (optional default=46337), used in computing t1 - `q` -- prime (optional default=3), used in computing t2 - `verbose` -- bool (default: True); if true, print to stdout as the computation is performed. OUTPUT: - bool -- True if criterion satisfied; otherwise, False - string -- message about what happened or went wrong EXAMPLES: We can't get p=29 to work no matter what I try, which nicely illustrates the various ways the criterion can fail:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.verify_criterion(4,n=5) dependency dimension to large to search through (False, 'There is a dependency of weigt 2 in dependencies(3,1)', [Vector space of degree 4 and dimension 0 over Finite Field of size 2 Basis matrix: [], Vector space of degree 16 and dimension 8 over Finite Field of size 2 Basis matrix: [1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] [0 1 0 0 0 0 1 0 1 1 0 1 1 1 0 0] [0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0] [0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0] [0 0 0 0 1 0 1 0 1 1 0 1 1 1 0 0] [0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0], Vector space of degree 28 and dimension 19 over Finite Field of size 2 Basis matrix: [1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1] [0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 1 1 0] [0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0] [0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 1 1 0] [0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0] [0 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 1 1] [0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 1 1] [0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 1 0 1 1 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 1 1 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0]]) With p=43 the criterion is satisfied for d=4, thus proving that 43 is not the order of a torsion point on any elliptic curve over a quartic field:: sage: C = KamiennyCriterion(43); C Kamienny's Criterion for p=43 sage: C.verify_criterion(4) (True, 'All conditions are satified for Gamma1 d=4 p=43. Using n=5, modp=65521, q=3 in Kamienny Version 1.5 and SageMath version ...', [Vector space of degree 4 and dimension 0 over Finite Field of size 2 Basis matrix: [], Vector space of degree 23 and dimension 2 over Finite Field of size 2 Basis matrix: [1 1 0 1 0 0 1 1 1 0 1 0 1 1 1 1 1 1 0 0 1 0 0] [0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 1 1 1 1 0 0 0], Vector space of degree 42 and dimension 11 over Finite Field of size 2 Basis matrix: [1 0 0 0 0 0 0 1 0 1 1 1 0 1 1 0 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 1 1 0 0 1 1 1 1 1 1] [0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 0 0 1 0 0 0 1 1 1 1 0 0 0 1 0 0] [0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0] [0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 1 1 0 1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0] [0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0] [0 0 0 0 0 1 0 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 1 0 0 1 0 0 0 1 1 0 1] [0 0 0 0 0 0 1 0 0 0 1 0 1 1 1 0 1 1 0 1 0 0 1 0 0 0 1 0 1 0 1 0 0 1 1 0 0 0 1 1 1 1] [0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 1 1 0 1 1 0 0 0]]) """ if self.verbose: tm = cputime(); mem = get_memory_usage(); print "verif start" if self.p < (1 + 2 ** (d / 2)) ** 2 and self.verbose: print "WARNING: p must be at least (1+2^(d/2))^2 for the criterion to work." if t == None: t = self.t(n, p, q) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "t" if v==None: if use_rand_vec: v=self.v else: v=t.parent()(1) if self.congruence_type==0: verified,message,dependencies=self.verify_gamma0(d,t,v) else: verified,message,dependencies=self.verify_gamma1(d,t,v) if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "total verif time" if not verified: return verified,message,dependencies return True, "All conditions are satified for Gamma%s d=%s p=%s. Using n=%s, modp=%s, q=%s in Kamienny Version %s and %s" % (self.congruence_type,d, self.p, n, p, q, Kamienny_Version, version()),dependencies
def verify_criterion(self, d, t=None, n=5, p=65521, q=3, v=None, use_rand_vec=False, verbose=False): """ Attempt to verify the criterion at p using the input t. If t is not given compute it using n, p and q INPUT: - `t` -- hecke operator (optional default=None) - `n` -- integer (optional default=5), used in computing t1 - `p` -- prime (optional default=46337), used in computing t1 - `q` -- prime (optional default=3), used in computing t2 - `verbose` -- bool (default: True); if true, print to stdout as the computation is performed. OUTPUT: - bool -- True if criterion satisfied; otherwise, False - string -- message about what happened or went wrong EXAMPLES: We can't get p=29 to work no matter what I try, which nicely illustrates the various ways the criterion can fail:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.verify_criterion(4,n=5) dependency dimension to large to search through (False, 'There is a dependency of weigt 2 in dependencies(3,1)', [Vector space of degree 4 and dimension 0 over Finite Field of size 2 Basis matrix: [], Vector space of degree 16 and dimension 8 over Finite Field of size 2 Basis matrix: [1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0] [0 1 0 0 0 0 1 0 1 1 0 1 1 1 0 0] [0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0] [0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0] [0 0 0 0 1 0 1 0 1 1 0 1 1 1 0 0] [0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0], Vector space of degree 28 and dimension 19 over Finite Field of size 2 Basis matrix: [1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1] [0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 1 1 0] [0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0] [0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 1 1 0] [0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0] [0 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 1 1] [0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 1 1] [0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 1 0 1 1 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 1 1 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0]]) With p=43 the criterion is satisfied for d=4, thus proving that 43 is not the order of a torsion point on any elliptic curve over a quartic field:: sage: C = KamiennyCriterion(43); C Kamienny's Criterion for p=43 sage: C.verify_criterion(4) (True, 'All conditions are satified for Gamma1 d=4 p=43. Using n=5, modp=65521, q=3 in Kamienny Version 1.5 and SageMath version ...', [Vector space of degree 4 and dimension 0 over Finite Field of size 2 Basis matrix: [], Vector space of degree 23 and dimension 2 over Finite Field of size 2 Basis matrix: [1 1 0 1 0 0 1 1 1 0 1 0 1 1 1 1 1 1 0 0 1 0 0] [0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 1 1 1 1 0 0 0], Vector space of degree 42 and dimension 11 over Finite Field of size 2 Basis matrix: [1 0 0 0 0 0 0 1 0 1 1 1 0 1 1 0 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 1 1 0 0 1 1 1 1 1 1] [0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 0 0 1 0 0 0 1 1 1 1 0 0 0 1 0 0] [0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0] [0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 1 1 0 1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0] [0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0] [0 0 0 0 0 1 0 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 1 0 0 1 1 0 0 1 1 1 0 0 1 0 0 0 1 1 0 1] [0 0 0 0 0 0 1 0 0 0 1 0 1 1 1 0 1 1 0 1 0 0 1 0 0 0 1 0 1 0 1 0 0 1 1 0 0 0 1 1 1 1] [0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 1 1 0 1 1 0 0 0]]) """ if self.verbose: tm = cputime(); mem = get_memory_usage(); print("verif start") if self.p < (1 + 2 ** (d / 2)) ** 2 and self.verbose: print("WARNING: p must be at least (1+2^(d/2))^2 for the criterion to work.") if t == None: t = self.t(n, p, q) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "t") if v==None: if use_rand_vec: v=self.v else: v=t.parent()(1) if self.congruence_type==0: verified,message,dependencies=self.verify_gamma0(d,t,v) else: verified,message,dependencies=self.verify_gamma1(d,t,v) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "total verif time") if not verified: return verified,message,dependencies return True, "All conditions are satified for Gamma%s d=%s p=%s. Using n=%s, modp=%s, q=%s in Kamienny Version %s and %s" % (self.congruence_type,d, self.p, n, p, q, Kamienny_Version, version()),dependencies
def process_curve_standalone(label, digits=600, power=15, verbose=True, internalverbose=False, folder=None): import os set_random_seed(1) import random random.seed(1) C = lmfdb.getDBconnection() curve = C.genus2_curves.curves.find_one({'label': label}) if curve is None: print "Wrong label" return 2 endo_alg = curve['real_geom_end_alg'] # deals with the default folders if folder is None: if not '__datadir__' in globals(): import os import inspect filename = inspect.getframeinfo(inspect.currentframe())[0] __datadir__ = os.path.dirname(filename) + "/data/" base_folder = __datadir__ if endo_alg == 'R': print "End = QQ, Nothing to do" return 0 elif endo_alg == 'R x R': if curve['is_simple_geom']: type_folder = 'simple/RM' else: type_folder = 'split/nonCM_times_nonCM' elif endo_alg == 'C x R': type_folder = 'split/CM_times_nonCM' elif endo_alg == 'C x C': if curve['is_simple_geom']: type_folder = 'simple/CM' else: type_folder = 'split/CM_times_CM' elif endo_alg == 'M_2(R)': if curve['is_simple_geom']: type_folder = 'simple/QM' else: type_folder = 'split/nonCM_square' elif endo_alg == 'M_2(C)': type_folder = 'split/CM_square' else: print "did I forget a case?" return 1 folder = os.path.join(base_folder, type_folder) if not os.path.exists(folder): print "Creating dir: %s" % folder os.makedirs(folder) assert os.path.exists(folder) #filenames stdout_filename = os.path.join(folder, label + ".stdout") stderr_filename = os.path.join(folder, label + ".stderr") output_filename = os.path.join(folder, label + ".sage") sys.stdout = open(stdout_filename, 'w', int(0)) sys.stderr = open(stderr_filename, 'w') c, w = cputime(), walltime() data, sout, verified = process_curve_lmfdb(curve, digits, power=power, verbose=True, internalverbose=False) print "Time: CPU %.2f s, Wall: %.2f s" % ( cputime(c), walltime(w), ) output_file = open(output_filename, 'w') output_file.write(sout) output_file.close() sys.stdout.flush() os.fsync(sys.stdout.fileno()) sys.stderr.flush() os.fsync(sys.stderr.fileno()) sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ print "Done: label = %s, verified = %s" % (label, verified) print os.popen("tail -n 1 %s" % stdout_filename).read() if verified: return 0 else: return 1
def silke(A, c, beta, h, m=None, scale=1, float_type="double"): """ :param A: LWE matrix :param c: LWE vector :param beta: BKW block size :param m: number of samples to consider :param scale: scale rhs of lattice by this factor """ from fpylll import BKZ, IntegerMatrix, LLL, GSO from fpylll.algorithms.bkz2 import BKZReduction as BKZ2 if m is None: m = A.nrows() L = dual_instance1(A, scale=scale) L = IntegerMatrix.from_matrix(L) L = LLL.reduction(L, flags=LLL.VERBOSE) M = GSO.Mat(L, float_type=float_type) bkz = BKZ2(M) t = 0.0 param = BKZ.Param(block_size=beta, strategies=BKZ.DEFAULT_STRATEGY, auto_abort=True, max_loops=16, flags=BKZ.VERBOSE|BKZ.AUTO_ABORT|BKZ.MAX_LOOPS) bkz(param) t += bkz.stats.total_time H = copy(L) import pickle pickle.dump(L, open("L-%d-%d.sobj"%(L.nrows, beta), "wb")) E = [] Y = set() V = set() y_i = vector(ZZ, tuple(L[0])) Y.add(tuple(y_i)) E.append(apply_short1(y_i, A, c, scale=scale)[1]) v = L[0].norm() v_ = v/sqrt(L.ncols) v_r = 3.2*sqrt(L.ncols - A.ncols())*v_/scale v_l = sqrt(h)*v_ fmt = u"{\"t\": %5.1fs, \"log(sigma)\": %5.1f, \"log(|y|)\": %5.1f, \"log(E[sigma]):\" %5.1f}" print print fmt%(t, log(abs(E[-1]), 2), log(L[0].norm(), 2), log(sqrt(v_r**2 + v_l**2), 2)) print for i in range(m): t = cputime() M = GSO.Mat(L, float_type=float_type) bkz = BKZ2(M) t = cputime() bkz.randomize_block(0, L.nrows, stats=None, density=3) LLL.reduction(L) y_i = vector(ZZ, tuple(L[0])) l_n = L[0].norm() if L[0].norm() > H[0].norm(): L = copy(H) t = cputime(t) Y.add(tuple(y_i)) V.add(y_i.norm()) E.append(apply_short1(y_i, A, c, scale=scale)[1]) if len(V) >= 2: fmt = u"{\"i\": %4d, \"t\": %5.1fs, \"log(|e_i|)\": %5.1f, \"log(|y_i|)\": %5.1f," fmt += u"\"log(sigma)\": (%5.1f,%5.1f), \"log(|y|)\": (%5.1f,%5.1f), |Y|: %5d}" print fmt%(i+2, t, log(abs(E[-1]), 2), log(l_n, 2), log_mean(E), log_var(E), log_mean(V), log_var(V), len(Y)) return E
def t1_prime(self, n=5, p=65521): """ Return a multiple of element t1 of the Hecke algebra mod 2, computed using the Hecke operator $T_n$, where n is self.n. To make computation faster we only check if ...==0 mod p. Hence J will contain more elements, hence we get a multiple. INPUT: - `n` -- integer (optional default=5) - `p` -- prime (optional default=65521) OUTPUT: - a mod 2 matrix EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.t1_prime() 22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) sage: C.t1_prime(n=3) == 1 True sage: C = KamiennyCriterion(37) sage: C.t1_prime()[0] (1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0) """ if self.verbose: tm = cputime(); mem = get_memory_usage(); print("t1 start") T = self.S.hecke_matrix(n) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "hecke 1") f = self.hecke_polynomial(n) # this is the same as T.charpoly() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "char 1") Fint = f.factor() if all(i[1]!=1 for i in Fint): return matrix_modp(zero_matrix(T.nrows())) # raise ValueError("T_%s needs to be a generator of the hecke algebra"%n) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "factor 1, Fint = %s"%(Fint)) R = f.parent().change_ring(GF(p)) F = Fint.base_change(R) # Compute the iterators of T acting on the winding element. e = self.M([0, oo]).element().dense_vector().change_ring(GF(p)) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "wind") t = matrix_modp(self.M.hecke_matrix(n).dense_matrix(), p) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "hecke 2") g = t.charpoly() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "char 2") Z = t.iterates(e, t.nrows(), rows=True) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "iter") # We find all factors F[i][0] for f such that # (g/F[i][0])(t) * e = 0. # We do this by computing the polynomial # h = g/F[i][0], # turning it into a vector v, and computing # the matrix product v * Z. If the product # is 0, then e is killed by h(t). J = [] for i in range(len(F)): if F[i][1]!=1: J.append(i) continue h, r = g.quo_rem(F[i][0] ** F[i][1]) assert r == 0 v = vector(GF(p), h.padded_list(t.nrows())) if v * Z == 0: J.append(i) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "zero check") if self.verbose: print("J =", J) if len(J) == 0: # The annihilator of e is the 0 ideal. return matrix_modp(identity_matrix(T.nrows())) # Finally compute t1. I'm concerned about how # long this will take, so we reduce T mod 2 first. # It is important to call "self.T(2)" to get the mod-2 # reduction of T2 with respect to the right basis (e.g., the # integral basis in case use_integral_structure is true. Tmod2 = self.T(n) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "hecke mod") g = prod(Fint[i][0].change_ring(GF(2)) ** Fint[i][1] for i in J) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "g has degree %s"%(g.degree())) t1 = g(Tmod2) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "t1 finnished") return t1
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 xrange(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 xrange(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 __init__(self, p, congruence_type=1, sign=1, algorithm="custom", verbose=False, dump_dir=None): """ Create a Kamienny criterion object. INPUT: - `p` -- prime -- verify that there is no order p torsion over a degree `d` field - `sign` -- 1 (default),-1 or 0 -- the sign of the modular symbols space to use - ``algorithm`` -- "default" or "custom" whether to use a custom (faster) integral structure algorithm or to use the sage builtin algortihm - ``verbose`` -- bool; whether to print extra stuff while running. EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29, algorithm="custom", verbose=False); C Kamienny's Criterion for p=29 sage: C.use_custom_algorithm True sage: C.p 29 sage: C.verbose False """ self.verbose = verbose self.dump_dir = dump_dir if self.verbose: tm = cputime(); mem = get_memory_usage(); print("init") assert congruence_type == 0 or congruence_type == 1 self.congruence_type=congruence_type try: p = ZZ(p) if congruence_type==0: self.congruence_group = Gamma0(p) if congruence_type==1: self.congruence_group = GammaH(p,[-1]) except TypeError: self.congruence_group = GammaH(p.level(),[-1]+p._generators_for_H()) self.congruence_type = ("H",self.congruence_group._list_of_elements_in_H()) self.p = self.congruence_group.level() self.algorithm=algorithm self.sign=sign self.M = ModularSymbols(self.congruence_group, sign=sign) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "modsym") self.S = self.M.cuspidal_submodule() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "cuspsub") self.use_custom_algorithm = False if algorithm=="custom": self.use_custom_algorithm = True if self.use_custom_algorithm: int_struct = self.integral_cuspidal_subspace() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "custom int_struct") else: int_struct = self.S.integral_structure() if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "sage int_struct") self.S_integral = int_struct v = VectorSpace(GF(2), self.S.dimension()).random_element() self.v=v if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "rand_vect") if dump_dir: v.dump(dump_dir+"/vector%s_%s" % (p,congruence_type)) if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "dump")