Skip to content

Commit cc3c8e0

Browse files
roed314claude
andcommitted
Clarify genus 2 minimal/simplified model snippets (LMFDB#5344)
Rename C/X to Cmin/Csim in the genus 2 curve code snippets and add // minimal equation and // simplified equation comments, so it is clear which model each variable refers to; display Csim after defining it. Point the simplified-model rational points snippet at Csim instead of Cmin, and fix simplify_hyperelliptic_point/comp_poly to divide the y-coordinate by sqrt(n/squarefree_part(n)) rather than n, so the displayed simplified-model points (and the snippet) actually lie on the simplified model when h = 0. Mirror the renaming in the Code-to-Magma download and add a Simplified equation step to it. Verified by running the generated Magma snippets for 169.a.169.1, 400.a.409600.1 and 336.a.172032.1 (all pass except pre-existing Magma package issues), the sage snippets in a sage REPL, page renders and the Magma download via the flask test client, and the genus2_curves test suite (42 passed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 5ef81bd commit cc3c8e0

3 files changed

Lines changed: 47 additions & 36 deletions

File tree

lmfdb/genus2_curves/code.yaml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,37 @@ frontmatter:
2121
{lang} code for working with genus 2 curve {label}.
2222
2323
curve:
24-
comment: Define the curve
24+
comment: Define the curve (minimal equation)
2525
magma: |
2626
R<x> := PolynomialRing(Rationals());
2727
fh := %s;
2828
f := R![a : a in fh[1]];
2929
h := R![a : a in fh[2]];
30-
C := HyperellipticCurve(f, h);
30+
Cmin := HyperellipticCurve(f, h);
31+
32+
simple_curve:
33+
comment: Simplified equation
34+
magma: Csim := SimplifiedModel(Cmin);
3135

3236
aut:
3337
comment: Automorphism group
34-
magma: AutomorphismGroup(C);
38+
magma: AutomorphismGroup(Cmin);
3539

3640
jacobian:
3741
comment: Jacobian
38-
magma: J := Jacobian(SimplifiedModel(C));
42+
magma: J := Jacobian(Csim);
3943

4044
tors:
4145
comment: Torsion subgroup
4246
magma: TorsionSubgroup(J);
4347

4448
cond:
4549
comment: Conductor
46-
magma: Conductor(LSeries(C));
50+
magma: Conductor(LSeries(Cmin));
4751

4852
disc:
4953
comment: Discriminant
50-
magma: Discriminant(C);
54+
magma: Discriminant(Cmin);
5155

5256
ntors:
5357
comment: Torsion order of Jacobian

lmfdb/genus2_curves/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ def labels_page():
926926
learnmore=learnmore_list_remove("labels"),
927927
)
928928

929-
sorted_code_names = ['curve', 'aut', 'jacobian', 'tors', 'cond', 'disc', 'ntors', 'mwgroup']
929+
sorted_code_names = ['curve', 'simple_curve', 'aut', 'jacobian', 'tors', 'cond', 'disc', 'ntors', 'mwgroup']
930930

931931
Comment = {'magma': '//', 'sage': '#', 'gp': '\\\\', 'pari': '\\\\'}
932932

lmfdb/genus2_curves/web_g2c.py

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -67,27 +67,33 @@ def simplify_hyperelliptic(fh):
6767
return f.coefficients(sparse=False)
6868

6969

70-
def simplify_hyperelliptic_point(fh, pt):
70+
def simplify_hyperelliptic_scale(fh):
71+
# The simplified model is y^2 = g with g = squarefree_part(n)*(4f+h^2)/n,
72+
# where n is the content of 4f+h^2, so the y-coordinate of a point on the
73+
# minimal model transforms as y -> (2y+h)/s, where s = sqrt(n/squarefree_part(n))
7174
xR = PolynomialRing(QQ, 'x')
7275
f = 4*xR(fh[0]) + xR(fh[1])**2
73-
f1 = xR(fh[1])
74-
n = gcd(f.coefficients())
76+
n = ZZ(gcd(f.coefficients()))
77+
return (n // integer_squarefree_part(n)).isqrt()
78+
79+
80+
def simplify_hyperelliptic_point(fh, pt):
81+
s = simplify_hyperelliptic_scale(fh)
82+
f1 = PolynomialRing(QQ, 'x')(fh[1])
7583
xzR = PolynomialRing(QQ,['x', 'z'])
7684
z = xzR('z')
7785
f1 = (xzR(f1)*z**(4-len(fh[1]))).homogenize(z)
78-
return [pt[0], (2*pt[1] + f1([pt[0],pt[2]])) / n, pt[2]]
86+
return [pt[0], (2*pt[1] + f1([pt[0],pt[2]])) / s, pt[2]]
7987

8088

8189
def comp_poly(fh):
82-
xR = PolynomialRing(QQ, 'x')
83-
f = 4*xR(fh[0]) + xR(fh[1])**2
84-
f1 = xR(fh[1])
85-
n = gcd(f.coefficients())
90+
s = simplify_hyperelliptic_scale(fh)
91+
f1 = PolynomialRing(QQ, 'x')(fh[1])
8692
xyzR = PolynomialRing(QQ,['x', 'y', 'z'])
8793
y = xyzR('y')
8894
z = xyzR('z')
8995
f1 = (xyzR(f1)*z**(4-len(fh[1]))).homogenize(z)
90-
return (2*y + f1) / n
96+
return (2*y + f1) / s
9197

9298

9399
def min_eqns_pretty(fh):
@@ -1120,34 +1126,35 @@ def make_object(self, curve, endo, tama, ratpts, clus, galrep, nonsurj, is_curve
11201126
code['show'] = {'sage':'', 'magma':''} # use default show names
11211127
f,h = fh = data['min_eqn']
11221128
g = simplify_hyperelliptic(fh)
1123-
code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s));' % (f, h),
1124-
'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);' % (f, h) }
1125-
code['simple_curve'] = {'sage':'X = HyperellipticCurve(R(%s))' % (g), 'magma':'X,pi:= SimplifiedModel(C);' }
1129+
code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); Cmin = HyperellipticCurve(R(%s), R(%s)) # minimal equation' % (f, h),
1130+
'magma':'R<x> := PolynomialRing(Rationals()); Cmin := HyperellipticCurve(R!%s, R!%s); // minimal equation' % (f, h) }
1131+
code['simple_curve'] = {'sage':'Csim = HyperellipticCurve(R(%s)); Csim # simplified equation' % (g),
1132+
'magma':'Csim, pi := SimplifiedModel(Cmin); Csim; // simplified equation' }
11261133
if data['abs_disc'] % 4096 == 0:
11271134
ind2 = [a[0] for a in data['bad_lfactors']].index(2)
11281135
bad2 = data['bad_lfactors'][ind2][1]
11291136
magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(data['cond'])+',2),R!'+str(bad2)+'>*]'
11301137
else:
11311138
magma_cond_option = ''
1132-
code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);' % magma_cond_option}
1133-
code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'}
1134-
code['geom_inv'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]',
1135-
'magma':'IgusaClebschInvariants(C); IgusaInvariants(C); G2Invariants(C);'}
1136-
code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'}
1137-
code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'}
1138-
code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'}
1139+
code['cond'] = {'magma': 'Conductor(LSeries(Cmin%s)); Factorization($1);' % magma_cond_option}
1140+
code['disc'] = {'magma':'Discriminant(Cmin); Factorization(Integers()!$1);'}
1141+
code['geom_inv'] = {'sage':'Cmin.igusa_clebsch_invariants(); [factor(a) for a in _]',
1142+
'magma':'IgusaClebschInvariants(Cmin); IgusaInvariants(Cmin); G2Invariants(Cmin);'}
1143+
code['aut'] = {'magma':'AutomorphismGroup(Cmin); IdentifyGroup($1);'}
1144+
code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(Cmin,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'}
1145+
code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(Cmin)));'}
11391146
if ratpts:
1140-
code['rat_pts'] = {'magma': '[' + ','.join("C![%s,%s,%s]" % (p[0], p[1], p[2]) for p in ratpts['rat_pts']) + ']; // minimal model'}
1141-
code['rat_pts_simp'] = {'magma': '[' + ','.join(["C![%s,%s,%s]" % (p[0], p[1], p[2]) for p in [simplify_hyperelliptic_point(data['min_eqn'], pt) for pt in ratpts['rat_pts']]]) + ']; // simplified model'}
1142-
code['mw_group'] = {'magma':'MordellWeilGroupGenus2(Jacobian(C));'}
1143-
code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'}
1144-
code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'}
1145-
code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'}
1146-
code['torsion_subgroup'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}
1147-
code['decomp'] = {'magma':'HeuristicDecompositionFactors(C);'}
1147+
code['rat_pts'] = {'magma': '[' + ','.join("Cmin![%s,%s,%s]" % (p[0], p[1], p[2]) for p in ratpts['rat_pts']) + ']; // minimal model'}
1148+
code['rat_pts_simp'] = {'magma': '[' + ','.join(["Csim![%s,%s,%s]" % (p[0], p[1], p[2]) for p in [simplify_hyperelliptic_point(data['min_eqn'], pt) for pt in ratpts['rat_pts']]]) + ']; // simplified model'}
1149+
code['mw_group'] = {'magma':'MordellWeilGroupGenus2(Jacobian(Cmin));'}
1150+
code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(Cmin)); NumberOfGenerators($1);'}
1151+
code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(Cmin));'}
1152+
code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(Cmin); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'}
1153+
code['torsion_subgroup'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(Cmin))); AbelianInvariants($1);'}
1154+
code['decomp'] = {'magma':'HeuristicDecompositionFactors(Cmin);'}
11481155
code['endos0'] = {'magma':'//Please install CHIMP (https://github.com/edgarcosta/CHIMP) if you want to run this code'}
1149-
code['endos1'] = {'magma':'HeuristicIsGL2(C); HeuristicEndomorphismDescription(C); HeuristicEndomorphismFieldOfDefinition(C);'}
1150-
code['endos2'] = {'magma':'HeuristicIsGL2(C : Geometric := true); HeuristicEndomorphismDescription(C : Geometric := true); HeuristicEndomorphismLatticeDescription(C);'}
1156+
code['endos1'] = {'magma':'HeuristicIsGL2(Cmin); HeuristicEndomorphismDescription(Cmin); HeuristicEndomorphismFieldOfDefinition(Cmin);'}
1157+
code['endos2'] = {'magma':'HeuristicIsGL2(Cmin : Geometric := true); HeuristicEndomorphismDescription(Cmin : Geometric := true); HeuristicEndomorphismLatticeDescription(Cmin);'}
11511158

11521159
self._code = None
11531160

0 commit comments

Comments
 (0)