Attachment 'g1reduction-2008.m'
Download 1 /************************************************************************\
2 * Reduction of Genus One Models over Q (of degrees n = 2,3,4 and 5) *
3 * Author: T. Fisher *
4 * Date: 22nd July 2008 *
5 * Version for n = 2 calls "QuarticReduce" *
6 * Versions for n = 3,4 based on joint work with J. Cremona and M. Stoll *
7 \************************************************************************/
8
9 declare verbose Reduction,4;
10
11 // Find pathname by typing e.g. "Hessian:Maximal;" at the magma prompt
12 import "/usr/magma/package/Geometry/CrvG1/g1invariants.m" :
13 SL4Covariants,MultiFact,AuxiliaryQuadrics,ExactPfaffianMatrix;
14 import "/usr/magma/package/Geometry/CrvG1/3descent-testeq.m" :
15 RedTorsPts,ReductionInnerProduct;
16
17 MC := MonomialCoefficient;
18 MD := MonomialsOfDegree;
19 Id := IdentityMatrix;
20 Deriv := Derivative;
21 MySign := func<x|x ge 0 select 1 else -1>;
22 dyadic_rep := func<x|x eq 0 select 0
23 else a*2^b where a,b is MantissaExponent(x)>;
24 L2Norm := func<model|&+[x^2: x in Eltseq(model)]>;
25
26 function FirstSign(seq)
27 xx := [x : x in seq | x ne 0];
28 fnz := #xx eq 0 select 1 else xx[1];
29 return MySign(fnz);
30 end function;
31
32 function IntegerMatrix(mat)
33 n := Nrows(mat);
34 mat1 := Matrix(n,n,[dyadic_rep(mat[i,j]):i,j in [1..n]]);
35 denom := LCM([Integers()|Denominator(x) : x in Eltseq(mat1)]);
36 return MatrixAlgebra(Integers(),n)!(denom*mat1);
37 end function;
38
39 function MyEchelonForm(mat,tol)
40 // Row reduce an m by n matrix over the reals or complexes,
41 // always using largest available entry as the next pivot.
42 // Matrix returned is of form ( Id(m) | B )
43 m := Nrows(mat);
44 n := Ncols(mat);
45 for j in [1..m] do
46 _,jj := Maximum([Abs(mat[k,j]): k in [j..m]]);
47 jj +:= (j-1);
48 temp := mat[j]; mat[j] := mat[jj]; mat[jj] := temp;
49 if Abs(mat[j,j]) lt tol then return 0; end if;
50 mat[j] *:= (1/mat[j,j]);
51 for k in [1..m] do
52 if k ne j then mat[k] -:= mat[k,j]*mat[j]; end if;
53 end for;
54 end for;
55 return mat;
56 end function;
57
58 function SizeString(model)
59 size := Round(L2Norm(model));
60 logsize := Ilog(10,size);
61 if logsize lt 10 then
62 return "L2Norm = " cat IntegerToString(size);
63 else
64 return "Log10(L2Norm) = " cat IntegerToString(logsize);
65 end if;
66 end function;
67
68 function CoefficientSize(model:name:="Model");
69 cs := Ilog(10,Max([Round(Abs(c)): c in Eltseq(model)]));
70 if cs lt 10 then
71 vprintf Reduction, 2: "%o has coefficients\n%o\n",name,Eltseq(model);
72 else
73 vprintf Reduction, 2: "%o has coefficients of length %o\n",name,cs;
74 end if;
75 return cs;
76 end function;
77
78 //////////////////////////////////////////////////////////////
79 // Case n = 2 //
80 //////////////////////////////////////////////////////////////
81
82 function ReduceTwo(model)
83 assert Degree(model) eq 2;
84 P<X> := PolynomialRing(Integers());
85 CrossTerms := (#Eltseq(model) eq 8);
86 model1 := CrossTerms select CompleteTheSquare(model) else model;
87 quartic := Evaluate(Equation(model1),[X,1]);
88 _,M := QuarticReduce(quartic); // from CrvEll/FourDesc/quartred.m
89 M := ChangeRing(M,Rationals());
90 tr := <1,Transpose(M)>;
91 model := tr*model;
92 if CrossTerms then
93 coeffs := Eltseq(model);
94 r := [ -(Integers()!(coeffs[i]) div 2) : i in [1..3]];
95 tr1 := <1,r,Id(Rationals(),2)>;
96 model := tr1*model;
97 tr := tr1*tr;
98 end if;
99 return model,tr;
100 end function;
101
102 //////////////////////////////////////////////////////////////
103 // Case n = 4 //
104 //////////////////////////////////////////////////////////////
105
106 SRCompare := func<b,a| Abs(a[2]) ne Abs(b[2])
107 select Abs(b[2])-Abs(a[2]) else Abs(b[3])-Abs(a[3]) >;
108
109 function WomackTransformation(model)
110 // Returns a pair of "signed permutations" in GL(2,Z) and GL(4,Z)
111 // (just to make the final answer look pretty)
112 Q := Rationals();
113 assert Degree(model) eq 4;
114 assert CoefficientRing(model) eq Q;
115 R := PolynomialRing(model);
116 q1,q2 := Explode(Equations(model));
117 d0 := [<i,MC(q1,R.i^2),MC(q2,R.i^2)> : i in [1..4]];
118 Sort(~d0, SRCompare);
119 N1 := Matrix(Q,4,4,[<i,d0[i][1],1>: i in [1..4]]);
120 model := <Id(Q,2),N1>*model;
121 qq := Equations(model);
122 signs := [Q|FirstSign([MC(q,R.i^2): i in [1..4]]): q in qq];
123 M := DiagonalMatrix(signs);
124 model := <M,Id(Q,4)>*model;
125 q1,q2 := Explode(Equations(model));
126 s1 := [Sign(MC(q1,R.1*R.j)): j in [1..4]];
127 s2 := [MySign(MC(q2,R.1*R.j)): j in [1..4]];
128 s := [Q|s1[i] ne 0 select s1[i] else s2[i]: i in [1..4]];
129 N2 := DiagonalMatrix(s);
130 return <M,N2*N1>;
131 end function;
132
133 function ReductionCovariantFour(model,prec)
134 Q := Rationals();
135 R := RealField(prec);
136 C := ComplexField(prec);
137 P<X> := PolynomialRing(Q);
138 a,bb,c,dd,e := Explode(SL4Invariants(model));
139 covars := SL4Covariants(model); // from g1invariants.m
140 g := a*X^4 + 2*bb*X^3 + c*X^2 + 2*dd*X + e;
141 ff := [f[1]: f in Factorization(g)| f[1] ne X];
142 quadrics := <>;
143 if a eq 0 then
144 qA,T1,T2,qB := Explode(covars);
145 Append(~quadrics,T2 - 2*bb*qB);
146 end if;
147 if e eq 0 then
148 qA,T1,T2,qB := Explode(covars);
149 Append(~quadrics,T1 - 2*dd*qA);
150 end if;
151 for f in ff do
152 if Degree(f) gt 1 then
153 F<theta> := NumberField(f);
154 // Since we use "Conjugates" below, we need to set the
155 // precision of F. This seems quite slow for large precisons, so it
156 // might be worth re-writing to avoid the Kant machinery.
157 SetKantPrecision(F,prec);
158 else
159 F := Q;
160 theta := Roots(f)[1][1];
161 end if;
162 RR := PolynomialRing(F,4);
163 covarsF := ChangeUniverse(covars,RR);
164 qA,T1,T2,qB := Explode(covarsF);
165 GG := theta^(-1)*e*qA + T1 + theta*T2 + theta^2*a*qB;
166 Append(~quadrics,GG);
167 end for;
168 mats := <>;
169 diagelts := [];
170 for GG in quadrics do
171 RR := Parent(GG);
172 F := BaseRing(RR);
173 G := Factorization(GG)[1][1];
174 alpha := F!ExactQuotient(GG,G^2);
175 assert alpha ne 0;
176 assert GG eq alpha*G^2;
177 M1 := Matrix(C,4,Degree(F),[Conjugates(MC(G,RR.i)): i in [1..4]]);
178 Append(~mats,M1);
179 aa := [C|Abs(x): x in Conjugates(alpha)];
180 dg := [C|Abs(x): x in Conjugates(Evaluate(Derivative(g),theta))];
181 ll := [aa[i]/dg[i]^(1/2) : i in [1..Degree(F)]];
182 diagelts cat:= ll;
183 end for;
184 M1 := HorizontalJoin(mats);
185 M2 := Matrix(C,4,4,[Conjugate(M1[j,i]):i,j in [1..4]]);
186 D := DiagonalMatrix(C,diagelts);
187 M := M1*D*M2;
188 Qmat := Matrix(R,4,4,[Re(M[i,j]): i,j in [1..4]]);
189 dd := &+[Abs(x)^2: x in Eltseq(Qmat)];
190 Qmat *:= dd^(-1/2);
191 return Qmat + Transpose(Qmat);
192 end function;
193
194 //////////////////////////////////////////////////////////////
195 // Case n = 5 //
196 //////////////////////////////////////////////////////////////
197
198 function InvariantsAndHessian(model)
199 // Computes the invariants c4,c6 and Hessian H of a genus one model
200 // of degree 5. (Calling the existing functions cInvariants and
201 // Hessian separately leads to some duplication of effort.)
202 assert Degree(model) eq 5;
203 assert BaseRing(model) cmpeq Rationals();
204 phi := Matrix(model);
205 p := Equations(model);
206 q := AuxiliaryQuadrics(p); // from g1invariants.m
207 R := BaseRing(phi);
208 RR<u> := PolynomialRing(R);
209 SS<t> := quo<RR|u^4>; // this trick would speed up cInvariants
210 U := Matrix(SS,5,5,[&+[MC(phi[j,k],R.i)*R.k: k in [1..5]]: i,j in [1..5]]);
211 P := Matrix(R,5,5,
212 [&+[MC(Deriv(p[k],j),R.i)*R.k: k in [1..5]]: i,j in [1..5]]);
213 Q := Matrix(SS,5,5,[Deriv(q[i],j):i,j in [1..5]]);
214 det1 := Determinant(P);
215 det2 := Determinant(U+t*Q);
216 T := [R|Coefficient(det2,i): i in [1,3]];
217 cc := [&+[MultiFact(mon)*MC(det1,mon)*MC(d2,mon):mon in MD(R,5)]:d2 in T];
218 c4 := cc[1]/40;
219 c6 := -cc[2]/320;
220 RR<y1,y2,y3,y4,y5> := PolynomialRing(R,5);
221 M := Determinant(Matrix(RR,5,5,
222 [&+[MC(Deriv(p[k],j),R.i)*RR.k : k in [1..5]]:i,j in [1..5]]));
223 for ctr in [1..2] do
224 M := &+[R.i*MC(q[i],R.j*R.k)*Deriv(Deriv(M,RR.j),RR.k)
225 : j,k in [1..5], i in [1..5] | j le k ];
226 end for;
227 q2m := [R|MC(M,RR.i): i in [1..5]];
228 p22 := Eltseq(4*c4*Vector(p)-(3/16)*Vector(q2m));
229 hessian := ExactPfaffianMatrix(p22,1,1); // from g1invariants.m
230 coeffs := func<f|[MC(f,R.k): k in [1..5]]>;
231 Umat := Matrix(10,5,[coeffs(phi[i,j]): i,j in [1..5] | i lt j]);
232 Hmat := Matrix(10,5,[coeffs(hessian[i,j]): i,j in [1..5] | i lt j]);
233 Dmat := HorizontalJoin(Umat,Hmat);
234 discr1 := Determinant(Dmat);
235 discr2 := 12^2*(c4^3-c6^2);
236 if discr1 eq -discr2 then hessian*:= -1; end if;
237 return c4,c6,GenusOneModel(hessian);
238 end function;
239
240 function SyzygeticMatrix(model)
241 // This is a 3 by 5 matrix of quadratic forms. The first row contains
242 // the 4 by 4 Pfaffians of the model, and the last row contains the
243 // the 4 by 4 Pfaffians of the Hessian.
244 // The Hesse family has 12 singular fibres: the "syzygetic pentagons".
245 // These pentagons have 30 vertices in total. These make up the locus
246 // where the syzygetic matrix has rank 1. (The total space of the Hesse
247 // family is the locus where the matrix has rank 2.)
248 assert Degree(model) eq 5;
249 assert BaseRing(model) cmpeq Rationals();
250 P<t> := PolynomialRing(Rationals());
251 vprintf Reduction,2 :
252 "Computing the invariants, Hessian and syzygetic matrix\n";
253 c4,c6,H := InvariantsAndHessian(model);
254 vprintf Reduction,3 : "cInvariants = %o\n",[c4,c6];
255 coeffsize := CoefficientSize(H:name:="Hessian");
256 F := t*Vector(P,50,Eltseq(model))+Vector(P,50,Eltseq(H));
257 FF := GenusOneModel(5,Eltseq(F));
258 eqns := Equations(FF);
259 R := PolynomialRing(model);
260 RR := Universe(eqns);
261 mons := MD(R,2);
262 coeffs := [[MC(f,RR!mon): mon in mons]: f in eqns];
263 p2 := [&+[Coefficient(c[j],2)*mons[j]: j in [1..#mons]]: c in coeffs];
264 p12 := [&+[Coefficient(c[j],1)*mons[j]: j in [1..#mons]]: c in coeffs];
265 p22 := [&+[Coefficient(c[j],0)*mons[j]: j in [1..#mons]]: c in coeffs];
266 assert p2 eq Equations(model);
267 assert p22 eq Equations(H);
268 return Matrix(R,3,5,[p2,p12,p22]),c4,c6;
269 end function;
270
271 function ApplyToMat(tr,mat)
272 // Since the Hessian is a covariant, there is no need to to keep
273 // recomputing the syzygetic matrix.
274 R := BaseRing(mat);
275 S := ChangeRing(Adjoint(tr[1]),R);
276 T := Transpose(tr[2]);
277 mat := Matrix(3,5,[mat[i,j]^T:j in [1..5],i in [1..3]]);
278 return mat*S;
279 end function;
280
281 function SolveForPentagons(qq,C,tol)
282 matR := 0;
283 matC := 0;
284 for quads in qq do
285 assert #quads eq 10; // 10 homogeneous quadrics
286 RR := Universe(quads);
287 assert Rank(RR) eq 5; // in 5 variables
288 R := BaseRing(RR); // over the reals
289 mons := [RR.i*RR.j: i,j in [1..4]|i le j] cat [RR.i*RR.5: i in [1..5]];
290 coeffmat := Matrix(10,15,[MC(q,mon): mon in mons,q in quads]);
291 coeffmat := MyEchelonForm(coeffmat,tol);
292 if coeffmat eq 0 then
293 vprintf Reduction,2 : "Pentagon not in general position\n";
294 return 0,0;
295 end if;
296 charmat := Matrix(4,5,[-coeffmat[i,j]: j in [11..15],i in [1..4]]);
297 charmat := VerticalJoin(charmat,Vector(R,5,[1,0,0,0,0]));
298 evals := Eigenvalues(charmat);
299 s := func<n|n eq 1 select "ex" else "ices">;
300 vprintf Reduction,2 : "Pentagon has %o real vert%o\n",#evals,s(#evals);
301 realflag := true;
302 if #evals ne 5 then
303 charmat := ChangeRing(charmat,C);
304 charpoly := CharacteristicPolynomial(charmat);
305 evals := Roots(charpoly,C);
306 // Don't use Eigenvalues(charmat), since in "CovariantFromHyperplanes"
307 // we assume the pairs of complex conjugate roots are adjacent.
308 if #evals ne 5 then
309 vprintf Reduction,2 : "Unable to find all complex vertices\n";
310 return 0,0;
311 end if;
312 realflag := false;
313 end if;
314 F := realflag select R else C;
315 evals := [F| x[1]: x in evals];
316 mm := Minimum([Abs(evals[i]-evals[j]):i,j in [1..5]|i lt j]);
317 if mm lt tol then
318 vprintf Reduction,2 : "Unable to distinguish vertices\n";
319 return 0,0;
320 end if;
321 VdM := Matrix(F,5,5,[x^i : x in evals,i in [0..4]]);
322 v := Vector(F,5,[0,0,0,0,1]);
323 vv := [];
324 for i in [1..5] do vv cat:= [v]; v := v*charmat; end for;
325 augmat := HorizontalJoin(VdM,VerticalJoin(vv));
326 augmat := MyEchelonForm(augmat,tol);
327 if augmat eq 0 then return 0,0; end if;
328 mat := Matrix(5,5,[augmat[i,j]: j in [6..10],i in [1..5]]);
329 dd := [1/Sqrt(&+[Abs(x)^2: x in Eltseq(mat[i])]): i in [1..5]];
330 mat := DiagonalMatrix(F,dd)*mat;
331 if realflag then matR := mat; else matC := mat; end if;
332 end for;
333 return matR,matC;
334 end function;
335
336 function GramSchmidt(mat)
337 d := Ncols(mat);
338 for i := 1 to Nrows(mat) do
339 s := [&+[mat[j,k]*mat[i,k]: k in [1..d]]: j in [1..i-1]];
340 if i gt 1 then
341 mat[i] -:= &+[s[j]*mat[j]: j in [1..i-1]];
342 end if;
343 n := Sqrt(&+[mat[i,j]^2 : j in [1..d]]);
344 mat[i] *:= (1/n);
345 end for;
346 return mat;
347 end function;
348
349 function MyProjection(mat,vec)
350 m := Nrows(mat);
351 n := Ncols(mat);
352 a := [&+[mat[j,k]*vec[k]: k in [1..n]]: j in [1..m]];
353 vec -:= &+[a[j]*mat[j]: j in [1..m]];
354 n := Sqrt(&+[vec[i]^2 : i in [1..n]]);
355 return (1/n)*vec;
356 end function;
357
358 function RotationMatrix(theta)
359 c := Cos(theta);
360 s := Sin(theta);
361 return Matrix(2,2,[c,s,-s,c]);
362 end function;
363
364 function ClosestPointOnCircle(A,B)
365 // Given matrices A and B whose rows are orthonormal bases
366 // for subspaces V and W of Euclidean space R^d, finds
367 // cos(phi)*B[1] + sin(phi)*B[2] such that distance to V
368 // is minimal.
369 assert Ncols(A) eq Ncols(B);
370 assert Nrows(B) eq 2;
371 n := Nrows(A);
372 M := B*Transpose(A);
373 x := &+[M[1,i]^2-M[2,i]^2: i in [1..n]];
374 y := &+[2*M[1,i]*M[2,i]: i in [1..n]];
375 phi := Arctan2(x,y)/2; // N.B. don't reverse the arguments!
376 R := RotationMatrix(phi);
377 S := R*M;
378 dd := [1-&+[S[i,j]^2: j in [1..n]]: i in [1..2]];
379 dist,m := Minimum(dd);
380 return R[m]*B,dist;
381 end function;
382
383 function CommonVector(A,B)
384 // Computes a basis for the intersection of the row spaces
385 // of A and B, where the intersection is assumed 1-dimensional
386 assert Nrows(A) eq 5;
387 assert Nrows(B) eq 3;
388 A := GramSchmidt(A);
389 B := GramSchmidt(B);
390 M := A*Transpose(B);
391 dd := [1-&+[M[i,j]^2: i in [1..5]]: j in [1..3]];
392 _,m := Maximum(dd);
393 AA := VerticalJoin(A,MyProjection(A,B[m]));
394 BB := Matrix([Eltseq(B[i]): i in [1..3]| i ne m]);
395 vec,d1 := ClosestPointOnCircle(AA,BB);
396 BB := VerticalJoin(vec,B[m]);
397 vec,d2 := ClosestPointOnCircle(A,BB);
398 return vec,Maximum(d1,d2);
399 end function;
400
401 function CovariantFromHyperplanes(realforms,complexforms,prec)
402 // Finds the covariant positive definite Hermitian form from the
403 // given linear forms associated to a elliptic normal quintic
404 P := Universe(realforms);
405 PP := Universe(complexforms);
406 R := BaseRing(P); // real field
407 Rprint := RealField(5);
408 mons := MD(P,2);
409 A := Matrix(R,5,15,[MC(realforms[i]^2,mon): mon in mons, i in [1..5]]);
410 // vprintf Reduction,3 :
411 // "Basis for 5-dimensional vector space :\n%o\n",ChangeRing(A,Rprint);
412 cc := complexforms;
413 scores := [&+[Im(MC(c,PP.i))^2: i in [1..5]]: c in complexforms];
414 _,m := Minimum(scores);
415 if m notin {1,3,5} then
416 vprintf Reduction,1 : "Failed to recognise real form\n";
417 return 0;
418 end if;
419 case m :
420 when 1 : polysC := [cc[1]^2,cc[2]*cc[3],cc[4]*cc[5]];
421 when 3 : polysC := [cc[1]*cc[2],cc[3]^2,cc[4]*cc[5]];
422 when 5 : polysC := [cc[1]*cc[2],cc[3]*cc[4],cc[5]^2];
423 end case;
424 coeffs := [[MC(f,PP!mon): mon in mons]: f in polysC];
425 imsize := &+[Im(c[i])^2: i in [1..15],c in coeffs];
426 vprintf Reduction,2 : "Rounding error = %o\n",Rprint!imsize;
427 if imsize gt 10^(-3) then
428 vprint Reduction,1 : "Rounding error is too large";
429 return 0;
430 end if;
431 B := Matrix(R,3,15,[Re(c[i]): i in [1..15], c in coeffs]);
432 // vprintf Reduction,3 :
433 // "Basis for 3-dimensional vector space :\n%o\n",ChangeRing(B,Rprint);
434 vec,dist := CommonVector(A,B);
435 vprintf Reduction,2 : "Minimum distance = %o\n",Rprint!dist;
436 if dist gt 10^(-3) then
437 vprint Reduction,1 : "Minimum distance is too large";
438 return 0;
439 end if;
440 Q := &+[vec[i]*mons[i] : i in [1..#mons]];
441 if MC(Q,P.1^2) lt 0 then Q := -Q; end if;
442 Qmat := Matrix(R,5,5,[Deriv(Deriv(Q,i),j): i,j in [1..5]]);
443 if not IsPositiveDefinite(Qmat) then
444 vprint Reduction,1 : "Covariant matrix is not positive definite";
445 return 0;
446 end if;
447 dd := &+[Abs(x)^2: x in Eltseq(Qmat)];
448 Qmat *:= dd^(-1/2);
449 return Qmat + Transpose(Qmat);
450 end function;
451
452 RandomMats := [
453 [1,0,0,2,-2,0,-7,4,-8,6,3,0,1,6,-6,0,5,-6,9,-6,0,-2,0,-1,1],
454 [-1,4,2,1,0,-1,2,1,1,0,-1,5,3,0,0,-2,9,5,2,0,1,-3,-1,-1,1],
455 [3,0,-2,4,6,1,1,-2,4,1,-1,0,1,-2,-2,3,0,0,1,7,5,0,0,1,12],
456 [1,1,-1,0,-1,0,1,3,-2,0,-1,-1,1,1,1,1,2,1,-2,-1,-1,-3,-8,8,2],
457 [1,-1,-4,-7,-2,-2,2,3,6,0,3,-2,-5,-11,-1,1,-1,-3,-5,-1,1,-1,-2,-4,0],
458 [0,-2,1,2,3,1,1,0,0,-1,0,0,0,-1,-1,0,-1,1,2,3,-2,-1,-1,-1,1]
459 ];
460
461 function RealMultipliers(c4,c6,prec)
462 R := RealField(prec);
463 P<X> := PolynomialRing(Rationals());
464 if c6 ne 0 then
465 f1 := X^6 - 15*c4*X^4 + 40*c6*X^3 - 45*c4^2*X^2 + 24*c4*c6*X - 5*c6^2;
466 f2 := (-2*X^5 + 30*c4*X^3 - 82*c6*X^2 + 90*c4^2*X - 33*c4*c6)/(3*c6);
467 realrts := Roots(f1,R);
468 vprintf Reduction,3 :
469 "RealRoots = %o\n",[RealField(15)|rt[1]: rt in realrts];
470 ans := [[2*rt[1],Evaluate(f2,rt[1])]: rt in realrts];
471 error if #ans ne 2,
472 "Failed to compute real roots (prec = ",prec,
473 ") - try increasing precision";
474 else
475 rt5 := SquareRoot(R!5);
476 u := SquareRoot(3*rt5*c4);
477 ans := [[sgn*u*(1+rt5),-3*rt5*c4]: sgn in [-1,1]];
478 end if;
479 return ans;
480 end function;
481
482 function ReductionCovariantFive(A,nos,prec)
483 R := RealField(prec);
484 C := ComplexField(prec);
485 RR := PolynomialRing(R,5);
486 CC := PolynomialRing(C,5);
487 AR := ChangeRing(A,RR);
488 qq := [ quads1 cat quads2
489 where quads1 is [AR[2,j] - nn[1]*AR[1,j]: j in [1..5]]
490 where quads2 is [AR[3,j] - nn[2]*AR[1,j]: j in [1..5]]
491 : nn in nos ];
492 ctr := 0;
493 repeat
494 if ctr eq 0 then
495 matR,matC := SolveForPentagons(qq,C,10^(-prec/2));
496 elif ctr le #RandomMats then
497 T := Matrix(Integers(),5,5,RandomMats[ctr]);
498 vprintf Reduction,2 : "We make a change of co-ordinates\n";
499 TT := ChangeRing(T,R);
500 qq1 := [[q^TT: q in q1]: q1 in qq];
501 matR,matC := SolveForPentagons(qq1,C,10^(-prec/2));
502 matR := matR*T^(-1);
503 matC := matC*T^(-1);
504 else
505 vprint Reduction,1 :
506 "Problem was not resolved by a change of co-ordinates";
507 return 0;
508 end if;
509 ctr +:= 1;
510 until matR ne 0 and matC ne 0;
511 forms1 := [&+[matR[i,j]*RR.j: j in [1..5]]: i in [1..5]];
512 forms2 := [&+[matC[i,j]*CC.j: j in [1..5]]: i in [1..5]];
513 Rprint := RealField(8);
514 Cprint<i> := ComplexField(8);
515 RRR<x1,x2,x3,x4,x5> := PolynomialRing(Rprint,5);
516 CCC<x1,x2,x3,x4,x5> := PolynomialRing(Cprint,5);
517 vprintf Reduction,3 : "Real pentagon defined by linear forms : \n%o\n",
518 [&+[matR[i,j]*RRR.j: j in [1..5]]: i in [1..5]];
519 vprintf Reduction,3 : "Imaginary pentagon defined by linear forms : \n%o\n",
520 [&+[matC[i,j]*CCC.j: j in [1..5]]: i in [1..5]];
521 return CovariantFromHyperplanes(forms1,forms2,prec);
522 end function;
523
524 //////////////////////////////////////////////////////////////
525 // Cases n = 2,3,4,5 //
526 //////////////////////////////////////////////////////////////
527
528 function LLLReduceOnEquations(model)
529 Q := Rationals();
530 n := Degree(model);
531 assert n in {4,5};
532 eqns := Equations(model);
533 R := Universe(eqns);
534 mons := MD(R,2);
535 coeffmat := Matrix(Q,#eqns,#mons,[MC(f,mon): mon in mons,f in eqns]);
536 _,T := LLL(coeffmat : Delta:= 0.999);
537 if n eq 5 then T := Transpose(T^(-1)); end if;
538 tr := <ChangeRing(T,Q),Id(Q,n)>;
539 return tr*model,tr;
540 end function;
541
542 function LLLReduceOnAmbient(model)
543 Q := Rationals();
544 n := Degree(model);
545 assert n in {4,5};
546 d := n eq 4 select 2 else 5;
547 if n eq 4 then
548 mat := ChangeRing(Matrices(model)[1],Integers());
549 _,T := LLLGram(mat); // This is (usually) indefinite LLL
550 else
551 R := PolynomialRing(model);
552 phi := Matrix(model);
553 coeffmat := Matrix(Q,5,10,
554 [[MC(phi[j,k],R.i):j,k in [1..5]|j lt k]: i in [1..5]]);
555 _,T := LLL(coeffmat : Delta:= 0.999);
556 end if;
557 tr := <Id(Q,d),ChangeRing(T,Q)>;
558 return tr*model,tr;
559 end function;
560
561 function AdHocReduce(model)
562 Q := Rationals();
563 n := Degree(model);
564 assert n in {4,5};
565 tr := n eq 4 select <Id(Q,2),Id(Q,4)> else <Id(Q,5),Id(Q,5)>;
566 vprintf Reduction,2: "Performing ad hoc reduction \n";
567 IndentPush();
568 while true do
569 model1,tr1 := LLLReduceOnEquations(model);
570 vprintf Reduction,2:
571 "LLL reduction on equations => %o\n",SizeString(model);
572 if L2Norm(model1) lt L2Norm(model) then
573 model := model1;
574 tr := tr1*tr;
575 end if;
576 model1,tr1 := LLLReduceOnAmbient(model);
577 vprintf Reduction,2:
578 "LLL reduction on ambient => %o\n",SizeString(model);
579 if L2Norm(model1) lt L2Norm(model) then
580 model := model1;
581 tr := tr1*tr;
582 else
583 break;
584 end if;
585 end while;
586 IndentPop();
587 vprintf Reduction,1: "Ad hoc reduction => %o\n",SizeString(model);
588 return model,tr;
589 end function;
590
591 function DefaultPrecision(n,coeffsize)
592 // TO DO : work out sensible default precisions
593 case n :
594 when 3 : return Max(10, coeffsize*3 div 2);
595 // from previous magma code
596 when 4 : return 10 + 2*coeffsize;
597 // a wild guess
598 when 5 : return 50 + 12*coeffsize;
599 // a guess based on a few examples
600 end case;
601 end function;
602
603 intrinsic Reduce2008(model::ModelG1:prec:=0,Minkowski:=false) -> ModelG1, Tup
604 {A reduced genus one model integrally equivalent to the given one.}
605 Q := Rationals();
606 require CoefficientRing(model) cmpeq Q
607 : "Model must be defined over the rationals";
608 require Discriminant(model) ne 0 : "Model is singular";
609 n := Degree(model);
610 vprintf Reduction, 1 :"Reducing a genus one model of degree %o\n",n;
611 require n in {2,3,4,5} : "Model must have degree 2,3,4 or 5.";
612 require forall{ x : x in Eltseq(model) | IsIntegral(x) }
613 : "Coefficients of model must be integers";
614 if n eq 2 then
615 return ReduceTwo(model); // see above
616 end if;
617 idtrans1 := case<n| 3:1, 4:Id(Q,2), 5:Id(Q,5), default:"">;
618 tr := <idtrans1,Id(Q,n)>;
619 vprintf Reduction,1: "Size of model given %o\n",SizeString(model);
620 if n in {4,5} then
621 model,tr1 := AdHocReduce(model);
622 tr := tr1*tr;
623 end if;
624 coeffsize := CoefficientSize(model);
625 if n eq 5 then syzmat,c4,c6 := SyzygeticMatrix(model); end if;
626 if prec eq 0 then prec := DefaultPrecision(n,coeffsize); end if;
627 vprintf Reduction,1 : "Working to real precision %o\n",prec;
628 case n :
629 when 3 :
630 torspts := RedTorsPts(Equation(model),prec);
631 when 5 :
632 nos := RealMultipliers(c4,c6,prec);
633 end case;
634 history := {};
635 done := false;
636 earlyexit := false;
637 while not done do
638 vprintf Reduction,2 :
639 "Computing the reduction covariant (prec = %o)\n",prec;
640 IndentPush();
641 case n :
642 when 3 : cov := ReductionInnerProduct(Equation(model),torspts,prec);
643 when 4 : cov := ReductionCovariantFour(model,prec);
644 when 5 : cov := ReductionCovariantFive(syzmat,nos,prec);
645 end case;
646 IndentPop();
647 error if cov eq 0,
648 "Failed to compute reduction covariant ( prec =",prec,
649 ") - try increasing precision";
650 if n eq 3 then // scale to make nice for printing
651 dd := &+[Abs(x)^2: x in Eltseq(cov)];
652 cov *:= dd^(-1/2);
653 cov := cov + Transpose(cov);
654 end if;
655 vprintf Reduction, 3:
656 "Reduction covariant:\n%o\n",ChangeRing(cov,RealField(Round(50/n)));
657 if n eq 3 and IsDiagonal(cov) then
658 vprint Reduction, 2: "Diagonal matrix => early exit";
659 earlyexit := true;
660 break;
661 end if;
662 vprintf Reduction, 2: "Performing Heisenberg reduction\n";
663 covZ := IntegerMatrix(cov); // Taken from earlier code for n = 4
664 _,T := LLLGram(covZ : Delta:=0.999);
665 vprintf Reduction, 3: "Transformation:\n%o\n", T;
666 tr1 := <idtrans1,ChangeRing(T,Q)>;
667 model := tr1*model;
668 if n in {4,5} then
669 model,tr2 := LLLReduceOnEquations(model);
670 tr1 := tr2*tr1;
671 end if;
672 vprintf Reduction,1: "Heisenberg reduction => %o\n",SizeString(model);
673 done := (model in history);
674 Include(~history,model);
675 if not done and n in {4,5} then
676 model,tr2 := AdHocReduce(model);
677 tr1 := tr2*tr1;
678 end if;
679 if not done and n eq 5 then
680 vprint Reduction,2: "Updating the syzygetic matrix";
681 syzmat := ApplyToMat(tr1,syzmat);
682 end if;
683 // Perhaps could decrease precision for next iteration?
684 tr := tr1*tr;
685 end while;
686 if Minkowski and (not earlyexit) then
687 coeffsize := CoefficientSize(model);
688 vprint Reduction,1: "Final stage - Minkowski reduction";
689 // Taken from earlier code for n = 3
690 cov := tr1[2]*cov*Transpose(tr1[2]);
691 c := 16;
692 repeat
693 c *:= 2;
694 M := Matrix(n,n,[Round(c*e) : e in Eltseq(cov)]);
695 until IsPositiveDefinite(M);
696 // Could we just use "IntegerMatrix" here?
697 M := Matrix(n,n,[Round(1000*c*e) : e in Eltseq(cov)]);
698 // TO DO: Sort out why SuccessiveMinima takes so long,
699 // in some examples, especially for diagonal matrices!!!
700 vprint Reduction, 3: "Calling SuccessiveMinima";
701 _,mins1 := SuccessiveMinima(LatticeWithGram(M));
702 T := Matrix([Eltseq(v) : v in mins1]);
703 vprintf Reduction, 3: "Transformation:\n%o\n", T;
704 tr1 := <idtrans1,ChangeRing(T,Q)>;
705 model := tr1*model;
706 if n in {4,5} then
707 model,tr2 := LLLReduceOnEquations(model);
708 tr1 := tr2*tr1;
709 end if;
710 tr := tr1*tr;
711 end if;
712 if n eq 4 then
713 tr1 := WomackTransformation(model);
714 // This is just a signed permutation to make the answer look pretty.
715 // Perhaps do something similar for n=3,5?
716 model := tr1*model;
717 tr := tr1*tr;
718 end if;
719 return model,tr;
720 end intrinsic;
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.