-
Notifications
You must be signed in to change notification settings - Fork 0
/
EvenConductorExponent_Core.mag
300 lines (256 loc) · 11.3 KB
/
EvenConductorExponent_Core.mag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
// This file is part of Genus2Conductor
// Copyright (C) 2018 Christopher Doris
//
// Genus2Conductor is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Genus2Conductor is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Genus2Conductor. If not, see <http://www.gnu.org/licenses/>.
declare verbose EvenConductorExponent_Genus2, 2;
//////////////////////////////////////////////////////////////////////////////////////////////////////
// SEVERAL FUNCTIONS COPIED FROM Geometry/Crv/RegModel/interface.m
function special_points_count(model)
if not assigned model`special_points_count then
model`special_points_count := [];
allfibres := model`abstract_fibres;
inds := [i : i in [1..#allfibres] | allfibres[i]`is_regular];
fibres := [allfibres[i] : i in inds];
p1_inds := [fib`patch1 : fib in allfibres];
// Intersection points (points possibly contained in more than one component)
// Note: second condition for same reason as in IntersectionMatrix
intn_pts := [pt : pt in model`points | pt`is_regular and pt`fibres subset inds];
// pt is counted on (the affine patch of) the component for fib
// <==> pt`patch = fib`patch1
for pt in intn_pts do
idx := pt`patch;
//printf "%o, %o\n", pt`fibres, [i : i in pt`fibres | p1_inds[i] eq idx];
count := #[i : i in pt`fibres | p1_inds[i] eq idx];
Append(~model`special_points_count, <Degree(pt`field,model`k), count> );
end for;
//"intn_points_count is ", model`special_points_count;
// Consider each pt in the locus at infinity of each component:
// if pt was already considered as an intn_pt, do nothing;
// otherwise count = 1.
for fib_idx in inds do
fib := allfibres[fib_idx];
fib_intn_pts := [pt : pt in intn_pts | fib_idx in pt`fibres];
for p in [p: p in Keys(fib`explicit) | p ne fib`patch1] do
// get intersection of fib with domain of patch p
// as a disjoint union of 0-dimensional ideals
dom := model`patches[p]`domain;
fibp := [fib`explicit[p]`ideal + D : D in dom[3]];
pts := &cat [RadicalDecomposition(I) : I in fibp];
pts := [I : I in pts | forall{D: D in dom[1] | not D subset I}];
for I in pts do
for pt0 in fib_intn_pts do
if pt0`patch eq p and pt0`explicit[p]`ideal eq I then
continue I;
end if;
end for;
degI := Degree(Scheme(AffineSpace(Generic(I)), I));
Append(~model`special_points_count, <degI, 0>);
end for; // I
end for; // p
end for;
//"special_points_count is", model`special_points_count;
end if;
return model`special_points_count;
end function;
function number_of_points_on_special_fibre(model, degree)
F := ext< model`k | degree >;
p := Characteristic(F);
n := Ilog(p, #F);
// Count points on each fibre's affine patch1
// Note: #RationalPoints code is garbage !!!
// avoid regular_model_indices (which sorts by computing Multiplicities)
fibres := [fib : fib in model`abstract_fibres | fib`is_regular];
ideals := [* fib`explicit[fib`patch1]`ideal : fib in fibres *];
comps := [* Scheme(AffineSpace(Generic(I)), I) : I in ideals *];
affine := [ #RationalPoints(C, F) : C in comps ];
num := &+ affine;
vprint RegularModel, 2 : "Affine counts:", affine;
// Adjust for intersection points appearing on more than 1 fibre,
// and for points at infinity not appearing
for tup in special_points_count(model) do
if degree mod tup[1] eq 0 then
num +:= tup[1] * (1 - tup[2]); // has been counted tup[2] times
end if;
end for;
// Adjust for blownup points (currently counted once for each fibre they lie on)
// TO DO: is this correct?
// (alternative: only adjust for blownup points lying in patch1 of fibres,
// and above only consider points at infinity that are regular)
//"Adjust nonregular:";
reg_fib_inds := [i : i in [1..#allfibres] | allfibres[i]`is_regular]
where allfibres is model`abstract_fibres;
for pt in model`points do
if not pt`is_regular then
pt_meets := [i : i in pt`fibres | i in reg_fib_inds];
num -:= #pt_meets;
//"pt meets", pt_meets;
end if;
end for;
return num;
end function;
function splitting_field(I)
assert IsPrime(I) and Dimension(I) eq 1;
C := Curve(AffineSpace(Generic(I)), I);
FF := AlgorithmicFunctionField(FunctionField(C));
return ExactConstantField(FF);
end function;
function geo_splitting_field(fib)
if not assigned fib`geo_splitting_field then
I := fib`explicit[fib`patch1]`ideal;
fib`geo_splitting_field := splitting_field(I);
end if;
return fib`geo_splitting_field;
end function;
function splitting_degrees(model)
return [ Degree(geo_splitting_field(fib), model`k)
: fib in model`abstract_fibres | fib`is_regular ];
end function;
// END COPIED FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////
Z := Integers();
function SemistableType(C,P : big:=200)
// Potential semistable types in genus 2 (from Liu's paper "Courbes stables de genre 2...")
// returns LiuType,M2D2Type,AbelianPart,ToricPart
// e.g. "I","2",2,0 for potentially good, "VI","1xIn",1,1 for potentially ell-x-nodal
if Type(C) eq RngUPolElt then C:=HyperellipticCurve(C); end if;
K:=BaseField(C);
// if Type(K) eq FldRat then
// u:=P;
// p:=P;
// else
// error if Type(K) notin [FldNum,FldCyc,FldQuad],
// "SemistableType only implemented over Q or number fields";
// u:=UniformizingElement(P);
// p:=Characteristic(ResidueClassField(P));
// end if;
u:=Type(P) eq RngInt select Generator(P) else UniformizingElement(P);
p:=Characteristic(ResidueClassField(P));
error if Genus(C) ne 2,
"SemistableType: only implemented in genus 2";
J2,J4,J6,J8,J10:=Explode(JInvariants(C)); // Igusa's Js
I2:=J2/12;
I4:=J2^2-2^3*3*J4;
if I4 eq 0 then I4:=u^big; end if;
//! Perturb I4,I12 p-adically in the case it is 0; better ways?
I6:=J6;
I8:=J8;
I12:=-2^3*J4^3+3^2*J2*J4*J6-3^3*J6^2-J2^2*J8;
if I12 eq 0 then I12:=u^big; end if;
J:=[0,J2,0,J4,0,J6,0,J8,0,J10];
I:=[0,I2,0,I4,0,I6,0,I8,0,0,0,I12];
int:=func<x|Valuation(x,P) ge 0>;
max:=func<x|Valuation(x,P) gt 0>;
vz:= func<x|Valuation(x,P) eq 0>;
eps:=p eq 2 select 4 else (p eq 3 select 3 else 1);
if forall{i: i in [1..5] | int(J[2*i]^5/J10^i) }
then data:=<"I","2",2,0>;
elif forall{i: i in [1..5] | int(J[2*i]^6/I12^i)} and max(J10^6/I12^5) then
data:=<"II","1n",1,1>;
elif forall{i: i in [1..5] | int(J[2*i]^2/I4^i)} and max(J10^2/I4^5)
and max(I12/I4^3) and (vz(J4/I4) or vz(J6^2/I4^3)) then
data:=<"III","Inm",0,2>;
elif forall{i: i in [2..5] | max(J[2*i]^2/I4^i)} then
data:=<"IV","Unmr",0,2>;
elif (max(I4^eps/I[2*eps]^2) and max(J10^eps/I[2*eps]^5) and max(I12^eps/I[2*eps]^6)) then
if int(I4^(3*eps)/J10^eps/I[2*eps]) and int(I12^eps/J10^eps/I[2*eps]) then
data:=<"V","1x1",2,0>;
elif int(I4^3/I12) and max(J10^eps*I[2*eps]/I12^eps) then
data:=<"VI","1xIn",1,1>;
elif max(I12/I4^3) and max(J10^eps*I[2*eps]/I4^(3*eps)) then
data:=<"VII","InxIm",0,2>;
else
data:=<"?","Fail1",2,0>;
end if;
else
data:=<"?","Fail0",2,0>;
end if;
return Explode(data);
end function;
function TameConductorFromRegularModel(C,p)
vprint EvenConductorExponent_Genus2: "using regular model...";
// print "using regular model";
Q:=Rationals();
g:=Genus(C);
R:=RegularModel(C,p: Warnings:=false);
q:=#R`k;
spldegs:=splitting_degrees(R);
numgeocomps:=&+spldegs;
T:=PowerSeriesRing(Q,2*g+1).1;
ser:=Exp(&+[Parent(T)|number_of_points_on_special_fibre(R,n)/n*T^n: n in [1..2*g]]);
h0term:=1-T;
h2term:=&*[1-(q*T)^j: j in spldegs];
localfactor:=PolynomialRing(Q)!Eltseq(ser * h0term * h2term);
tamecond:=2*g-Degree(localfactor);
return tamecond;
end function;
function TameConductorFrom3Torsion(C,p,IOrder,dim3I : UseRegularModels:=false)
vprint EvenConductorExponent_Genus2: "computing tame conductor...";
if Type(C) eq RngUPolElt then C:=HyperellipticCurve(C); end if;
_,_,a,t:=SemistableType(C,p);
n:=4-dim3I;
// case (1)
if (dim3I eq 0) then return n; end if; // two extremes: no invariants; e.g. I=C18
// case (2)
if dim3I eq 4 then return t; end if; // or semistable
// case (3)
if t eq 0 then // I,V [totally abelian]
if (IOrder eq 3) and (dim3I eq 2) then return 4; end if;
return IsEven(dim3I) select n else n+1;
end if;
// case (4)
if IOrder eq 3 or ((t eq 1) and (IOrder in [2,6])) // use regular model
then return UseRegularModels select TameConductorFromRegularModel(C,p) else false; end if;
// case (5) split into a few sub-cases
if IOrder mod 9 eq 0 then
assert IOrder eq 9;
return t eq 1 select 3 else 4;
end if;
if t eq 2 then // III,IV,VII [totally toric]
assert (IOrder in [2,6]) and (n eq 2);
return 3;
end if;
assert t eq 1; // II,VI [1-dim toric part]
assert IOrder mod 4 eq 0; // no invariants on the abelian part
assert dim3I in [1,2];
return 3;
//g:=GeometricGenus(Curve(Reduction(pMinimalWeierstrassModel(C,p),p)));
end function;
function wild_conductor_exponent(dus)
assert &+[du[1] : du in dus] eq 80;
us := Sort(SetToSequence({0,1} join {du[2] : du in dus}));
assert us[1] eq 0;
assert us[2] eq 1;
ds := [&+[Z | du[1] : du in dus | du[2] le u] : u in us];
error if not forall{d : d in ds | IsPowerOf(d+1, 3)}, "not powers of 3";
Ds := [D where _,D := IsPowerOf(d+1,3) : d in ds];
error if Ds[#Ds] ne 4, "last Ds ne 4";
cs := [(us[i+1] - us[i])*(4 - Ds[i]) : i in [1..#Ds-1]];
return Z ! &+cs[2..#cs], Z ! Ds[1];
end function;
function conductor_exponent_data(f, p, dues : UseRegularModels:=false, ExtraData:=false)
cwild, dtame := wild_conductor_exponent([<due[1], due[2]> : due in dues]);
e := LCM([due[3] : due in dues]);
ctame := TameConductorFrom3Torsion(f, p, e, dtame : UseRegularModels:=UseRegularModels);
ret := rec<recformat<WildExponent, TameExponent, TameFixedDegree, RamificationDegreeBound, Exponent, Error, DUEs, ExtraData> | DUEs:=dues, ExtraData:=ExtraData>;
ret`WildExponent := Z ! cwild;
ret`TameFixedDegree := Z ! dtame;
if ctame cmpne false then
ret`TameExponent := Z ! ctame;
ret`Exponent := ctame + cwild;
else
ret`Error := "could not compute tame conductor exponent";
end if;
ret`RamificationDegreeBound := Z ! e;
return ret;
end function;