//p is a prime number //k is a weight function GetFactors(p,k) m:=(p-1)*Bernoulli(k)/(-2*k); m:=Numerator(m); s:=Factorization(m); r:=[ [f[1],f[2]]: f in s]; return r; end function; //name - the name of the file to print congruences data //The function which uses the valuation approach. This is the right function to compute. function Congruence(p,k,name) factors:=GetFactors(p,k); S:=Newforms(CuspForms(Gamma0(p),k)); print("Newforms of level p=" cat IntegerToString(p) cat " computed"); if( k gt 2) then E1:=EisensteinSeries(ModularForms(Gamma0(p),k)); e1:=E1[1]; e2:=E1[2]; E:=e1-(p^(k-1))*e2; else E1:=EisensteinSeries(ModularForms(Gamma0(p),k)); E:=E1[1]; end if; B:=Ceiling(k*Index(Gamma0(p))/12); Collection:=[]; for lfactors in factors do l:=lfactors[1]; e:=lfactors[2]; for ind1 in [1..#S] do print("Computing congruence with form i=" cat IntegerToString(ind1) cat ", j=" cat IntegerToString(1)); //Hardcoded 1 f:=S[ind1][1]; K:=CoefficientField(f); print("Working with number field"); print(K); d:=Discriminant(K); //There is no reason to use this condition, just practical..) if (d le 10^14000) then if not(K eq Rationals()) then O:=EquationOrder(K); O:=pMaximalOrder(O,l); end if; if (K eq Rationals()) then O:=Integers(); end if; //Due to computational complexity I have abondened the computation of maximal order //O:=MaximalOrder(K); print("pMaximal order computed for p=" cat IntegerToString(p) cat " and l=" cat IntegerToString(l)); I:=ideal; //There is no proper factorization of ideals in general in p-maximal orders hence we use Decomposition, //which for a prime away from the discriminant produces de facto a factorization //factI:=Factorization(I); factI:=Decomposition(O,l); for ind3 in [1..#factI] do ptuple:=factI[ind3]; J:=ptuple[1]; if (K eq Rationals()) then max_exponent:=Valuation(Numerator(Coefficient(E,0)),l); congruenceExp:=max_exponent; for i in [0..B] do cf:=Coefficient(f,i); nf:=Numerator(cf); df:=Denominator(cf); ce:=Coefficient(E,i); In:=nf-ce*df; Id:=df; val:=Valuation(In,l)-Valuation(Id,l); tmp_congruenceExp:=Minimum(congruenceExp,val); congruenceExp:=tmp_congruenceExp; end for; pExponent:=Valuation(l,l); else max_exponent:=Valuation(ideal,J); congruenceExp:=max_exponent; for i in [0..B] do cf:=Coefficient(f,i); nf:=Numerator(cf); df:=Denominator(cf); ce:=Coefficient(E,i); In:=ideal; Id:=ideal; val:=Valuation(In,J)-Valuation(Id,J); tmp_congruenceExp:=Minimum(congruenceExp,val); congruenceExp:=tmp_congruenceExp; end for; pExponent:=Valuation(I,J); end if; if (congruenceExp gt 0) then Include(~Collection,[p,l,k,ind1,1,ind3]); print("CONGRUENCE FOUND!"); list:=[p,l,e,ind1,1,ind3]; exp:=[ x[2] : x in factI]; expprint:=&cat[IntegerToString(x) cat " " : x in exp]; if (pExponent gt 1) then ram:="t"; else ram:="n"; end if; PrintFile(name,"p = " cat IntegerToString(p)); PrintFile(name, "l = " cat IntegerToString(l)); PrintFile(name,"k = " cat IntegerToString(k)); PrintFile(name,"Form label (i,j)= " cat IntegerToString(list[4]) cat ", " cat IntegerToString(list[5])); PrintFile(name,"Coefficient field"); PrintFile(name,K); PrintFile(name,"Splitting of ideal " cat IntegerToString(p)); PrintFile(name,exp); PrintFile(name,"Ideal number = " cat IntegerToString(list[6])); PrintFile(name,"Ramification index = " cat IntegerToString(factI[list[6]][2])); PrintFile(name,"Residue degree = " cat IntegerToString(#ResidueClassField(factI[list[6]][1]))); PrintFile(name," "); print("p = " cat IntegerToString(p)); print( "l = " cat IntegerToString(l)); print("k = " cat IntegerToString(k)); print("Form label (i,j)= " cat IntegerToString(list[4]) cat ", " cat IntegerToString(list[5])); print("Coefficient field"); print(K); print("Splitting of ideal " cat IntegerToString(p)); print(exp); print("Ideal number = " cat IntegerToString(list[6])); print("Ramification index = " cat IntegerToString(factI[list[6]][2])); print("Residue degree = " cat IntegerToString(#ResidueClassField(factI[list[6]][1]))); print(" "); //return " "; end if; end for; end if; end for; end for; return Collection; end function;