Skip to content

Commit 4b1cd02

Browse files
authored
Merge pull request #6780 from LMFDB/main
main -> dev
2 parents 68fb521 + 3c5c9cc commit 4b1cd02

30 files changed

Lines changed: 3086 additions & 182 deletions

lmfdb/abvar/fq/isog_class.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ def __init__(self, dbdata):
8484
dbdata["hyp_count"] = None
8585
if "jacobian_count" not in dbdata:
8686
dbdata["jacobian_count"] = None
87+
# New invariants: cyclicity and noncyclic primes
88+
if "is_cyclic" not in dbdata:
89+
dbdata["is_cyclic"] = None
90+
if "noncyclic_primes" not in dbdata:
91+
dbdata["noncyclic_primes"] = []
8792
self.__dict__.update(dbdata)
8893

8994
@classmethod
@@ -232,9 +237,15 @@ def properties(self):
232237
("Primitive", "yes" if self.is_primitive else "no"),
233238
]
234239
if self.has_principal_polarization != 0:
235-
props += [("Principally polarizable", "yes" if self.has_principal_polarization == 1 else "no")]
240+
props += [(
241+
"Principally polarizable",
242+
"yes" if self.has_principal_polarization == 1 else "no",
243+
)]
236244
if self.has_jacobian != 0:
237-
props += [("Contains a Jacobian", "yes" if self.has_jacobian == 1 else "no")]
245+
props += [(
246+
"Contains a Jacobian",
247+
"yes" if self.has_jacobian == 1 else "no",
248+
)]
238249
return props
239250

240251
# at some point we were going to display the weil_numbers instead of the frobenius angles

lmfdb/abvar/fq/main.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from lmfdb.utils import redirect_no_cache
2424
from lmfdb.utils.search_columns import SearchColumns, SearchCol, MathCol, LinkCol, ProcessedCol, CheckCol, CheckMaybeCol
2525
from lmfdb.abvar.fq.download import AbvarFq_download
26+
from lmfdb.utils.search_parsing import parse_primes
2627

2728
logger = make_logger("abvarfq")
2829

@@ -399,8 +400,31 @@ def nbsp(knowl, label):
399400
jacobian = YesNoMaybeBox(
400401
"jacobian",
401402
label="Jacobian",
402-
knowl="ag.jacobian"
403+
knowl="ag.jacobian",
403404
)
405+
406+
# Cyclic group of points (advanced yes/no box)
407+
cyclic = YesNoBox(
408+
"cyclic",
409+
label="Cyclic group of points",
410+
knowl="av.fq.cyclic_group_points",
411+
advanced=True,
412+
)
413+
414+
# Non-cyclic primes with mode selector (include / exactly / subset)
415+
noncyclic_mode = SubsetBox(
416+
"noncyclic_primes_mode",
417+
advanced=True,
418+
)
419+
noncyclic_primes = TextBoxWithSelect(
420+
"noncyclic_primes",
421+
label="Non-cyclic primes",
422+
select_box=noncyclic_mode,
423+
knowl="av.fq.noncyclic_primes",
424+
example="2 or 2,3,5",
425+
advanced=True,
426+
)
427+
404428
uglabel = "Use %s in the following inputs" % display_knowl("av.decomposition", "Geometric decomposition")
405429
use_geom_decomp = CheckBox(
406430
"use_geom_decomp",
@@ -506,6 +530,7 @@ def short_label(d):
506530
[newton_polygon, abvar_point_count, curve_point_count, simple_factors],
507531
[newton_elevation, jac_cnt, hyp_cnt, twist_count, max_twist_degree],
508532
[angle_rank, angle_corank, geom_deg, p_corank, geom_squarefree],
533+
[cyclic, noncyclic_primes],
509534
use_geom_refine,
510535
[dim1, dim2, dim3, dim4, dim5],
511536
[dim1d, dim2d, dim3d, number_field, galois_group],
@@ -516,6 +541,7 @@ def short_label(d):
516541
[g, geom_simple],
517542
[initial_coefficients, polarizable],
518543
[p_rank, jacobian],
544+
[cyclic, noncyclic_primes],
519545
[p_corank, geom_squarefree],
520546
[jac_cnt, hyp_cnt],
521547
[angle_rank, angle_corank],
@@ -552,6 +578,7 @@ def common_parse(info, query):
552578
parse_bool(info, query, "primitive", qfield="is_primitive")
553579
parse_bool_unknown(info, query, "jacobian", qfield="has_jacobian")
554580
parse_bool_unknown(info, query, "polarizable", qfield="has_principal_polarization")
581+
parse_bool(info, query, "cyclic", qfield="is_cyclic")
555582
parse_ints(info, query, "p_rank")
556583
parse_ints(info, query, "p_corank", qfield="p_rank_deficit")
557584
parse_ints(info, query, "angle_rank")
@@ -561,6 +588,14 @@ def common_parse(info, query):
561588
parse_ints(info, query, "hyp_cnt", qfield="hyp_count", name="Number of Hyperelliptic Jacobians")
562589
parse_ints(info, query, "twist_count")
563590
parse_ints(info, query, "max_twist_degree")
591+
parse_primes(
592+
info,
593+
query,
594+
"noncyclic_primes",
595+
qfield="noncyclic_primes",
596+
mode=info.get("noncyclic_primes_mode"),
597+
)
598+
564599
parse_ints(info, query, "size")
565600
parse_newton_polygon(info, query, "newton_polygon", qfield="slopes")
566601
parse_string_start(info, query, "initial_coefficients", qfield="poly_str", initial_segment=["1"])
@@ -680,7 +715,7 @@ def extended_code(c):
680715
ProcessedCol("number_fields", "av.fq.number_field", "Number fields", lambda nfs: ", ".join(nf_display_knowl(nf, field_pretty(nf)) for nf in nfs), default=False),
681716
SearchCol("galois_groups_pretty", "nf.galois_group", "Galois groups", download_col="galois_groups", default=False),
682717
SearchCol("decomposition_display_search", "av.decomposition", "Isogeny factors", download_col="decompositionraw")],
683-
db_cols=["label", "g", "q", "poly", "p_rank", "p_rank_deficit", "is_simple", "is_geometrically_simple", "simple_distinct", "simple_multiplicities", "is_primitive", "primitive_models", "curve_count", "curve_counts", "abvar_count", "abvar_counts", "jacobian_count", "hyp_count", "number_fields", "galois_groups", "slopes", "newton_elevation", "twist_count", "max_twist_degree", "geometric_extension_degree", "angle_rank", "angle_corank", "is_supersingular", "has_principal_polarization", "has_jacobian"])
718+
db_cols=["label", "g", "q", "poly", "p_rank", "p_rank_deficit", "is_simple", "is_geometrically_simple", "simple_distinct", "simple_multiplicities", "is_primitive", "primitive_models", "curve_count", "curve_counts", "abvar_count", "abvar_counts", "jacobian_count", "hyp_count", "number_fields", "galois_groups", "slopes", "newton_elevation", "twist_count", "max_twist_degree", "geometric_extension_degree", "angle_rank", "angle_corank", "is_supersingular", "has_principal_polarization", "has_jacobian", "is_cyclic", "noncyclic_primes"])
684719

685720
def abvar_postprocess(res, info, query):
686721
gals = set()

lmfdb/abvar/fq/templates/show-abvarfq.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ <h2>Invariants</h2>
3131
{% if cl.size is not none %}
3232
<tr><td>{{KNOWL('av.fq.isogeny_class_size',title='Isomorphism classes')}}:</td><td>&nbsp;&nbsp;{{cl.size}}</td></tr>
3333
{% endif %}
34+
{# --- NEW: cyclicity invariants --- #}
35+
{% if cl.is_cyclic is not none %}
36+
<tr>
37+
<td>{{ KNOWL('av.fq.cyclic_group_points', title='Cyclic group of points') }}:</td>
38+
<td>&nbsp;&nbsp;
39+
{% if cl.is_cyclic %}
40+
yes
41+
{% else %}
42+
no
43+
{% endif %}
44+
</td>
45+
</tr>
46+
{% endif %}
47+
48+
49+
{% if cl.noncyclic_primes %}
50+
<tr>
51+
<td>{{ KNOWL('av.fq.noncyclic_primes', title='Non-cyclic primes') }}:</td>
52+
<td>&nbsp;&nbsp;${{ cl.noncyclic_primes|join(', ') }}$</td>
53+
</tr>
54+
{% endif %}
3455
</table>
3556
</p>
3657

lmfdb/abvar/fq/test_av.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,11 @@ def test_download_curves(self):
157157

158158
page = self.tc.get('Variety/Abelian/Fq/download_curves/5.3.ac_e_ai_v_abl', follow_redirects=True)
159159
assert 'No curves for abelian variety isogeny class 5.3.ac_e_ai_v_abl' in page.get_data(as_text=True)
160+
161+
def test_cyclic_group_of_points_display(self):
162+
r"""
163+
Check that the cyclic group of points information is displayed
164+
on the isogeny-class page.
165+
"""
166+
page = self.tc.get("/Variety/Abelian/Fq/2/9/aj_bl").get_data(as_text=True)
167+
assert "Cyclic" in page

lmfdb/abvar/fq/test_browse_page.py

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ def test_index_page(self):
1212
"""
1313
homepage = self.tc.get("/Variety/Abelian/Fq/").get_data(as_text=True)
1414
assert "by dimension and base field" in homepage
15+
assert "Cyclic group of points" in homepage
1516

1617
def test_stats_page(self):
17-
self.check_args("/Variety/Abelian/Fq/stats","Abelian variety isogeny classes: Statistics")
18+
self.check_args("/Variety/Abelian/Fq/stats", "Abelian variety isogeny classes: Statistics")
1819

1920
# TODO test dynamic stats
2021

@@ -43,7 +44,10 @@ def test_lookup(self):
4344
r"""
4445
Check that Variety/Abelian/Fq/?jump works
4546
"""
46-
self.check_args("/Variety/Abelian/Fq/?jump=x^6-3*x^5%2B3*x^4-2*x^3%2B6*x^2-12*x%2B8", "3.2.ad_d_ac")
47+
self.check_args(
48+
"/Variety/Abelian/Fq/?jump=x^6-3*x^5%2B3*x^4-2*x^3%2B6*x^2-12*x%2B8",
49+
"3.2.ad_d_ac"
50+
)
4751

4852
# Various searches
4953
# Many things are checked twice: Once from main index/browse page, and once from the refining search page
@@ -148,7 +152,10 @@ def test_search_newton(self):
148152
# slope not a rational number
149153
self.check_args("/Variety/Abelian/Fq/?newton_polygon=t", "is not a valid input")
150154
# slopes are not increasing
151-
self.check_args("/Variety/Abelian/Fq/?start=&count=&newton_polygon=%5B1%2C1%2F2%2C0%5D", "Slopes must be increasing")
155+
self.check_args(
156+
"/Variety/Abelian/Fq/?start=&count=&newton_polygon=%5B1%2C1%2F2%2C0%5D",
157+
"Slopes must be increasing"
158+
)
152159

153160
def test_search_initcoeffs(self):
154161
r"""
@@ -157,7 +164,10 @@ def test_search_initcoeffs(self):
157164
self.check_args("/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D", "4.3.b_ab_d_j")
158165
self.check_args("/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D", "4.3.b_ab_d_j")
159166
# there should be only one match, if ranges were supported
160-
self.check_args("/Variety/Abelian/Fq/?angle_ranks=&initial_coefficients=%5B3%2C+9%2C+10%2C+87-100%5D", "Ranges not supported")
167+
self.check_args(
168+
"/Variety/Abelian/Fq/?angle_ranks=&initial_coefficients=%5B3%2C+9%2C+10%2C+87-100%5D",
169+
"Ranges not supported"
170+
)
161171

162172
def test_search_pointcountsav(self):
163173
r"""
@@ -187,8 +197,14 @@ def test_search_isogfactor(self):
187197
Check that we can search by decomposition into isogeny factors
188198
"""
189199
# [3.5.ah_y_ach,*]
190-
self.check_args("/Variety/Abelian/Fq/?simple_quantifier=include&simple_factors=3.5.ah_y_ach", "4.5.ak_by_agk_qb")
191-
self.check_args("/Variety/Abelian/Fq/?p_rank=4&dim1_factors=2&dim2_factors=2&dim1_distinct=1&dim2_distinct=1", "6.2.ag_p_aw_bh_acu_ey")
200+
self.check_args(
201+
"/Variety/Abelian/Fq/?simple_quantifier=include&simple_factors=3.5.ah_y_ach",
202+
"4.5.ak_by_agk_qb"
203+
)
204+
self.check_args(
205+
"/Variety/Abelian/Fq/?p_rank=4&dim1_factors=2&dim2_factors=2&dim1_distinct=1&dim2_distinct=1",
206+
"6.2.ag_p_aw_bh_acu_ey"
207+
)
192208
self.check_args("/Variety/Abelian/Fq/?dim1_factors=6&dim1_distinct=1", "5 matches")
193209

194210
def test_search_numberfield(self):
@@ -274,8 +290,51 @@ def test_search_combos(self):
274290
self.check_args("/Variety/Abelian/Fq/?p_rank=2&initial_coefficients=%5B1%2C-1%2C3%2C9%5D", "4.3.b_ab_d_j")
275291
self.check_args("/Variety/Abelian/Fq/?p_rank=2&initial_coefficients=%5B1%2C-1%2C3%2C9%5D", "4.3.b_ab_d_j")
276292
# initial coefficients and point counts of the abelian variety
277-
self.check_args("/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D&abvar_point_count=%5B75%2C7125%5D", "No matches")
278-
self.check_args("/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D&abvar_point_count=%5B75%2C7125%5D", "No matches")
293+
self.check_args(
294+
"/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D&abvar_point_count=%5B75%2C7125%5D",
295+
"No matches"
296+
)
297+
self.check_args(
298+
"/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D&abvar_point_count=%5B75%2C7125%5D",
299+
"No matches"
300+
)
279301
# Combining unknown fields on Jacobian and Principal polarization.
280302
self.check_args("/Variety/Abelian/Fq/?g=3&jacobian=no&polarizable=not_no", "3.2.a_a_ae")
281303
self.check_args("/Variety/Abelian/Fq/?g=3&jacobian=no&polarizable=yes", "3.2.a_ac_a")
304+
305+
def test_search_cyclic_group(self):
306+
r"""
307+
Check that we can restrict to cyclic or non-cyclic groups of points
308+
using the cyclic search parameter.
309+
"""
310+
# 1.2.ac has cyclic group of points (is_cyclic = True)
311+
self.check_args(
312+
"/Variety/Abelian/Fq/?cyclic=yes",
313+
">1.2.ac<",
314+
)
315+
316+
# 1.3.a has non-cyclic group of points (is_cyclic = False)
317+
self.check_args(
318+
"/Variety/Abelian/Fq/?cyclic=no",
319+
">1.3.a<",
320+
)
321+
322+
# And make sure they do not appear in the wrong list
323+
self.not_check_args(
324+
"/Variety/Abelian/Fq/?cyclic=yes",
325+
">1.3.a<",
326+
)
327+
self.not_check_args(
328+
"/Variety/Abelian/Fq/?cyclic=no",
329+
">1.2.ac<",
330+
)
331+
332+
def test_search_noncyclic_primes(self):
333+
r"""
334+
Check that the noncyclic_primes search parameter is accepted and
335+
finds classes that are non-cyclic at p = 2.
336+
"""
337+
self.check_args(
338+
"/Variety/Abelian/Fq/?noncyclic_primes=2",
339+
">1.3.a<",
340+
)

lmfdb/ecnf/code.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ cond:
4646
cond_norm:
4747
comment: Compute the norm of the conductor
4848
sage: E.conductor().norm()
49-
pari: idealnorm(ellglobalred(E)[1])
49+
pari: idealnorm(K, ellglobalred(E)[1])
5050
magma: Norm(Conductor(E));
5151

5252
disc:
@@ -128,4 +128,6 @@ snippet_test:
128128
label: 81.1-CMa1
129129
langs:
130130
url: EllipticCurve/2.0.3.1/81.1/CMa/1/download/{lang}
131+
132+
131133

lmfdb/elliptic_curves/code.yaml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,6 @@ qexp:
180180
comment: q-expansion of modular form
181181
sage: E.q_eigenform(20)
182182
pari: |
183-
\\ actual modular form, use for small N
184-
[mf,F] = mffromell(E)
185-
Ser(mfcoefs(mf,20),q)
186-
\\ or just the series
187183
Ser(ellan(E,20),q)*q
188184
magma: ModularForm(E);
189185

@@ -251,4 +247,4 @@ snippet_test:
251247
test37a1:
252248
label: 37.a1
253249
url: EllipticCurve/Q/37/a/1/download/{lang}?label=37.a1
254-
250+

lmfdb/groups/abstract/templates/abstract-show-subgroup.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,7 @@ <h2> Automorphism information </h2>
160160
<table>
161161
<tr><td>$\operatorname{Aut}(G)$</td><td>{{seq.amb.show_aut_group()|safe}}</td></tr>
162162
<tr><td>$\operatorname{Aut}(H)$</td><td>
163-
{% if seq.sub|attr('show_aut_group') %}
164163
{{seq.sub.show_aut_group()|safe}}
165-
{% else %}
166-
not computed
167-
{% endif %}
168164
</td></tr>
169165
{% if seq.aut_weyl_group is not none %}
170166
<tr><td>$\operatorname{res}({{S}})$</td><td><a href="{{url_for('.by_label', label=seq.aut_weyl_group)}}">${{seq.aut_weyl.tex_name}}$</a>, of order {{info.pos_int_and_factor(seq.aut_weyl.order) | safe}}</td></tr>

lmfdb/groups/abstract/web_groups.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2572,26 +2572,23 @@ def show_aut_group(self):
25722572
if self.aut_order is None:
25732573
return "not computed"
25742574
aut_order = pos_int_and_factor(self.aut_order)
2575-
tex = self.aut_tex
2575+
tex = getattr(self, "aut_tex", None)
25762576
if tex is None:
25772577
return f'Group of order {aut_order}'
25782578
else:
25792579
tex = tex.replace("\t",r"\t")
25802580
if self.aut_group is not None:
25812581
url = url_for(".by_label", label=self.aut_group)
25822582
return f'<a href="{url}">${tex}$</a>, of order {aut_order}'
2583-
if tex is None:
2584-
return f"Group of order {aut_order}"
2585-
else:
2586-
return f'${tex}$'
2583+
return f"${tex}$, of order {aut_order}"
25872584

25882585
def aut_group_knowl(self):
25892586
if self.aut_order is None:
25902587
return "not computed"
25912588
if self.live():
25922589
return f"Group of order {self.aut_order}"
25932590
aut_order = pos_int_and_factor(self.aut_order)
2594-
tex = self.aut_tex
2591+
tex = getattr(self, "aut_tex", None)
25952592
if tex is None:
25962593
tex = "Group"
25972594
knowl = f'<a title = "{tex} [lmfdb.object_information]" knowl="lmfdb.object_information" kwargs="args={self.label}&func=autknowl_data">{tex}</a>'

lmfdb/higher_genus_w_automorphisms/main.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,12 @@ class HGCWASearchArray(SearchArray):
12761276
jump_egspan = "e.g. 2.12-4.0.2-2-2-3 or 3.168-42.0.2-3-7.2"
12771277
jump_knowl = "curve.highergenus.aut.search_input"
12781278
jump_prompt = "Label"
1279+
null_column_explanations = { # No need to display warnings for these
1280+
'hyperelliptic': False,
1281+
'cyclic_trigonal': False,
1282+
'full_label': False,
1283+
'full_auto': False,
1284+
}
12791285

12801286
def __init__(self):
12811287
genus = TextBox(

0 commit comments

Comments
 (0)