From 9d065f4c72c3157b27ffee1863e90eef93d003ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A1=BE=E6=98=8A=E6=A5=A0?=
Date: Sun, 16 Nov 2025 04:33:52 -0500
Subject: [PATCH 01/12] Display cyclic group of points info on AV/Fq page
---
lmfdb/abvar/fq/isog_class.py | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/lmfdb/abvar/fq/isog_class.py b/lmfdb/abvar/fq/isog_class.py
index 4a93cbca8f..4aeb74de3f 100644
--- a/lmfdb/abvar/fq/isog_class.py
+++ b/lmfdb/abvar/fq/isog_class.py
@@ -84,6 +84,11 @@ def __init__(self, dbdata):
dbdata["hyp_count"] = None
if "jacobian_count" not in dbdata:
dbdata["jacobian_count"] = None
+ # New invariants: cyclicity and noncyclic primes
+ if "is_cyclic" not in dbdata:
+ dbdata["is_cyclic"] = None
+ if "noncyclic_primes" not in dbdata:
+ dbdata["noncyclic_primes"] = []
self.__dict__.update(dbdata)
@classmethod
@@ -231,6 +236,20 @@ def properties(self):
("Geometrically simple", "yes" if self.is_geometrically_simple else "no"),
("Primitive", "yes" if self.is_primitive else "no"),
]
+ # Cyclicity information (new)
+ ic = getattr(self, "is_cyclic", None)
+ if ic is True:
+ cyclic_val = "yes"
+ elif ic is False:
+ cyclic_val = "no"
+ else:
+ cyclic_val = "unknown"
+ props.append(("Cyclic group of points", cyclic_val))
+
+ primes = getattr(self, "noncyclic_primes", None)
+ if primes:
+ primes_str = "{" + ", ".join(str(p) for p in primes) + "}"
+ props.append(("Noncyclic primes", primes_str))
if self.has_principal_polarization != 0:
props += [("Principally polarizable", "yes" if self.has_principal_polarization == 1 else "no")]
if self.has_jacobian != 0:
From 1abca1b9f79fa7edfb1e0fdae00cdc8b271b6dd2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A1=BE=E6=98=8A=E6=A5=A0?=
Date: Sun, 16 Nov 2025 04:45:14 -0500
Subject: [PATCH 02/12] Add cyclic isogeny invariants, search options, and
tests for AV/Fq
---
lmfdb/abvar/fq/main.py | 20 +++++++++++++++++---
lmfdb/abvar/fq/test_av.py | 9 +++++++++
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/lmfdb/abvar/fq/main.py b/lmfdb/abvar/fq/main.py
index 52c81732ec..992674beac 100644
--- a/lmfdb/abvar/fq/main.py
+++ b/lmfdb/abvar/fq/main.py
@@ -23,6 +23,7 @@
from lmfdb.utils import redirect_no_cache
from lmfdb.utils.search_columns import SearchColumns, SearchCol, MathCol, LinkCol, ProcessedCol, CheckCol, CheckMaybeCol
from lmfdb.abvar.fq.download import AbvarFq_download
+from lmfdb.utils.search_parsing import parse_primes
logger = make_logger("abvarfq")
@@ -401,6 +402,16 @@ def nbsp(knowl, label):
label="Jacobian",
knowl="ag.jacobian"
)
+ cyclic = YesNoBox(
+ "cyclic",
+ label="Cyclic group of points",
+ )
+ noncyclic_primes = TextBox(
+ "noncyclic_primes",
+ label="Non-cyclic primes",
+ example="2 or 2,3,5",
+ advanced=True,
+ )
uglabel = "Use %s in the following inputs" % display_knowl("av.decomposition", "Geometric decomposition")
use_geom_decomp = CheckBox(
"use_geom_decomp",
@@ -506,6 +517,7 @@ def short_label(d):
[newton_polygon, abvar_point_count, curve_point_count, simple_factors],
[newton_elevation, jac_cnt, hyp_cnt, twist_count, max_twist_degree],
[angle_rank, angle_corank, geom_deg, p_corank, geom_squarefree],
+ [cyclic, noncyclic_primes],
use_geom_refine,
[dim1, dim2, dim3, dim4, dim5],
[dim1d, dim2d, dim3d, number_field, galois_group],
@@ -515,7 +527,7 @@ def short_label(d):
[p, simple],
[g, geom_simple],
[initial_coefficients, polarizable],
- [p_rank, jacobian],
+ [p_rank, jacobian, cyclic],
[p_corank, geom_squarefree],
[jac_cnt, hyp_cnt],
[angle_rank, angle_corank],
@@ -552,6 +564,7 @@ def common_parse(info, query):
parse_bool(info, query, "primitive", qfield="is_primitive")
parse_bool_unknown(info, query, "jacobian", qfield="has_jacobian")
parse_bool_unknown(info, query, "polarizable", qfield="has_principal_polarization")
+ parse_bool(info, query, "cyclic", qfield="is_cyclic")
parse_ints(info, query, "p_rank")
parse_ints(info, query, "p_corank", qfield="p_rank_deficit")
parse_ints(info, query, "angle_rank")
@@ -561,6 +574,7 @@ def common_parse(info, query):
parse_ints(info, query, "hyp_cnt", qfield="hyp_count", name="Number of Hyperelliptic Jacobians")
parse_ints(info, query, "twist_count")
parse_ints(info, query, "max_twist_degree")
+ parse_primes(info, query, "noncyclic_primes", qfield="noncyclic_primes")
parse_ints(info, query, "size")
parse_newton_polygon(info, query, "newton_polygon", qfield="slopes")
parse_string_start(info, query, "initial_coefficients", qfield="poly_str", initial_segment=["1"])
@@ -680,7 +694,7 @@ def extended_code(c):
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),
SearchCol("galois_groups_pretty", "nf.galois_group", "Galois groups", download_col="galois_groups", default=False),
SearchCol("decomposition_display_search", "av.decomposition", "Isogeny factors", download_col="decompositionraw")],
- 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"])
+ 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"])
def abvar_postprocess(res, info, query):
gals = set()
@@ -878,4 +892,4 @@ def split_label(lab):
return lmfdb_label_regex.match(lab).groups()
def abvar_label(g, q, iso):
- return "%s.%s.%s" % (g, q, iso)
+ return "%s.%s.%s" % (g, q, iso)
\ No newline at end of file
diff --git a/lmfdb/abvar/fq/test_av.py b/lmfdb/abvar/fq/test_av.py
index e7c4cf0ca6..95dd68cec2 100644
--- a/lmfdb/abvar/fq/test_av.py
+++ b/lmfdb/abvar/fq/test_av.py
@@ -157,3 +157,12 @@ def test_download_curves(self):
page = self.tc.get('Variety/Abelian/Fq/download_curves/5.3.ac_e_ai_v_abl', follow_redirects=True)
assert 'No curves for abelian variety isogeny class 5.3.ac_e_ai_v_abl' in page.get_data(as_text=True)
+
+ def test_cyclic_group_of_points_display(self):
+ r"""
+ Check that the cyclic group of points information is displayed
+ on the isogeny-class page.
+ """
+ page = self.tc.get("/Variety/Abelian/Fq/2/9/aj_bl").get_data(as_text=True)
+ assert "Cyclic" in page
+
From f9238a082619c0bda611f8d3852aa403b209ad9e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A1=BE=E6=98=8A=E6=A5=A0?=
Date: Sun, 16 Nov 2025 04:51:32 -0500
Subject: [PATCH 03/12] Adjust AV/Fq browse tests for cyclic invariants
---
lmfdb/abvar/fq/test_browse_page.py | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/lmfdb/abvar/fq/test_browse_page.py b/lmfdb/abvar/fq/test_browse_page.py
index 55ac1771f7..e9be1e5d02 100644
--- a/lmfdb/abvar/fq/test_browse_page.py
+++ b/lmfdb/abvar/fq/test_browse_page.py
@@ -12,6 +12,7 @@ def test_index_page(self):
"""
homepage = self.tc.get("/Variety/Abelian/Fq/").get_data(as_text=True)
assert "by dimension and base field" in homepage
+ assert "Cyclic group of points" in homepage
def test_stats_page(self):
self.check_args("/Variety/Abelian/Fq/stats","Abelian variety isogeny classes: Statistics")
@@ -279,3 +280,30 @@ def test_search_combos(self):
# Combining unknown fields on Jacobian and Principal polarization.
self.check_args("/Variety/Abelian/Fq/?g=3&jacobian=no&polarizable=not_no", "3.2.a_a_ae")
self.check_args("/Variety/Abelian/Fq/?g=3&jacobian=no&polarizable=yes", "3.2.a_ac_a")
+
+ def test_search_cyclic_group(self):
+ r"""
+ Check that we can restrict to cyclic or non-cyclic groups of points
+ using the is_cyclic search parameter.
+ """
+ # We only check that the search runs and returns the usual search
+ # results page; we do not assert specific labels since the data
+ # on devmirror can change.
+ self.check_args(
+ "/Variety/Abelian/Fq/?is_cyclic=yes",
+ "Abelian variety search results"
+ )
+ self.check_args(
+ "/Variety/Abelian/Fq/?is_cyclic=no",
+ "Abelian variety search results"
+ )
+
+ def test_search_noncyclic_primes(self):
+ r"""
+ Check that the noncyclic_primes search parameter is accepted.
+ """
+ self.check_args(
+ "/Variety/Abelian/Fq/?noncyclic_primes=2",
+ "Abelian variety search results"
+ )
+
From 903cc4b978d489fb9597e9ddec123a1351e9d4a4 Mon Sep 17 00:00:00 2001
From: Haonan Gu <160513517+hgu2699@users.noreply.github.com>
Date: Fri, 21 Nov 2025 11:54:58 -0500
Subject: [PATCH 04/12] #6696 lmfdb/abvar/fq/isog_class.py
---
lmfdb/abvar/fq/isog_class.py | 26 +++++++++-----------------
1 file changed, 9 insertions(+), 17 deletions(-)
diff --git a/lmfdb/abvar/fq/isog_class.py b/lmfdb/abvar/fq/isog_class.py
index 4aeb74de3f..b1da3090af 100644
--- a/lmfdb/abvar/fq/isog_class.py
+++ b/lmfdb/abvar/fq/isog_class.py
@@ -222,7 +222,7 @@ def _make_jacpol_property(self):
ans.append((None, "Does not contain a Jacobian"))
return ans
- def properties(self):
+ def properties(self):
props = [
("Label", self.label),
(None, '
' % self.circle_plot()),
@@ -236,24 +236,16 @@ def properties(self):
("Geometrically simple", "yes" if self.is_geometrically_simple else "no"),
("Primitive", "yes" if self.is_primitive else "no"),
]
- # Cyclicity information (new)
- ic = getattr(self, "is_cyclic", None)
- if ic is True:
- cyclic_val = "yes"
- elif ic is False:
- cyclic_val = "no"
- else:
- cyclic_val = "unknown"
- props.append(("Cyclic group of points", cyclic_val))
-
- primes = getattr(self, "noncyclic_primes", None)
- if primes:
- primes_str = "{" + ", ".join(str(p) for p in primes) + "}"
- props.append(("Noncyclic primes", primes_str))
if self.has_principal_polarization != 0:
- props += [("Principally polarizable", "yes" if self.has_principal_polarization == 1 else "no")]
+ props += [(
+ "Principally polarizable",
+ "yes" if self.has_principal_polarization == 1 else "no",
+ )]
if self.has_jacobian != 0:
- props += [("Contains a Jacobian", "yes" if self.has_jacobian == 1 else "no")]
+ props += [(
+ "Contains a Jacobian",
+ "yes" if self.has_jacobian == 1 else "no",
+ )]
return props
# at some point we were going to display the weil_numbers instead of the frobenius angles
From f3c9b8684e893187ffc67b50e0ac6e597e3b0a67 Mon Sep 17 00:00:00 2001
From: Haonan Gu <160513517+hgu2699@users.noreply.github.com>
Date: Fri, 21 Nov 2025 11:58:07 -0500
Subject: [PATCH 05/12] #6696 lmfdb/abvar/fq/isog_class.py
---
lmfdb/abvar/fq/isog_class.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lmfdb/abvar/fq/isog_class.py b/lmfdb/abvar/fq/isog_class.py
index b1da3090af..361e28e4d0 100644
--- a/lmfdb/abvar/fq/isog_class.py
+++ b/lmfdb/abvar/fq/isog_class.py
@@ -222,7 +222,7 @@ def _make_jacpol_property(self):
ans.append((None, "Does not contain a Jacobian"))
return ans
- def properties(self):
+ def properties(self):
props = [
("Label", self.label),
(None, '
' % self.circle_plot()),
From 25f726423e49fe4356bc06ea67d81df0d2ed1041 Mon Sep 17 00:00:00 2001
From: Haonan Gu <160513517+hgu2699@users.noreply.github.com>
Date: Fri, 21 Nov 2025 12:31:24 -0500
Subject: [PATCH 06/12] Update show-abvarfq.html
---
lmfdb/abvar/fq/templates/show-abvarfq.html | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/lmfdb/abvar/fq/templates/show-abvarfq.html b/lmfdb/abvar/fq/templates/show-abvarfq.html
index bc8290a69f..7bb7463834 100644
--- a/lmfdb/abvar/fq/templates/show-abvarfq.html
+++ b/lmfdb/abvar/fq/templates/show-abvarfq.html
@@ -31,6 +31,28 @@ Invariants
{% if cl.size is not none %}
| {{KNOWL('av.fq.isogeny_class_size',title='Isomorphism classes')}}: | {{cl.size}} |
{% endif %}
+ {# --- NEW: cyclicity invariants --- #}
+ {% if cl.is_cyclic is not none %}
+
+ | {{ KNOWL('av.fq.cyclic_group_points', title='Cyclic group of points') }}: |
+
+ {% if cl.is_cyclic == 1 or cl.is_cyclic is true %}
+ yes
+ {% elif cl.is_cyclic == 0 or cl.is_cyclic is false %}
+ no
+ {% else %}
+ unknown
+ {% endif %}
+ |
+
+ {% endif %}
+
+ {% if cl.noncyclic_primes %}
+
+ | {{ KNOWL('av.fq.noncyclic_primes', title='Non-cyclic primes') }}: |
+ ${{ cl.noncyclic_primes|join(', ') }}$ |
+
+ {% endif %}
From 75e79a7574ee09a19cfd520a03f9df5df908d280 Mon Sep 17 00:00:00 2001
From: Haonan Gu <160513517+hgu2699@users.noreply.github.com>
Date: Fri, 21 Nov 2025 12:44:32 -0500
Subject: [PATCH 07/12] Update main.py
---
lmfdb/abvar/fq/main.py | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/lmfdb/abvar/fq/main.py b/lmfdb/abvar/fq/main.py
index 992674beac..8cf5ac3024 100644
--- a/lmfdb/abvar/fq/main.py
+++ b/lmfdb/abvar/fq/main.py
@@ -400,18 +400,31 @@ def nbsp(knowl, label):
jacobian = YesNoMaybeBox(
"jacobian",
label="Jacobian",
- knowl="ag.jacobian"
+ knowl="ag.jacobian",
)
+
+ # Cyclic group of points (advanced yes/no box)
cyclic = YesNoBox(
"cyclic",
label="Cyclic group of points",
+ knowl="av.fq.cyclic_group_points",
+ advanced=True,
+ )
+
+ # Non-cyclic primes with mode selector (include / exactly / subset)
+ noncyclic_mode = SubsetBox(
+ "noncyclic_primes_mode",
+ advanced=True,
)
- noncyclic_primes = TextBox(
+ noncyclic_primes = TextBoxWithSelect(
"noncyclic_primes",
label="Non-cyclic primes",
+ select_box=noncyclic_mode,
+ knowl="av.fq.noncyclic_primes",
example="2 or 2,3,5",
advanced=True,
)
+
uglabel = "Use %s in the following inputs" % display_knowl("av.decomposition", "Geometric decomposition")
use_geom_decomp = CheckBox(
"use_geom_decomp",
@@ -527,7 +540,8 @@ def short_label(d):
[p, simple],
[g, geom_simple],
[initial_coefficients, polarizable],
- [p_rank, jacobian, cyclic],
+ [p_rank, jacobian],
+ [cyclic, noncyclic_primes],
[p_corank, geom_squarefree],
[jac_cnt, hyp_cnt],
[angle_rank, angle_corank],
@@ -548,6 +562,7 @@ def short_label(d):
[count],
]
+
def search_types(self, info):
return self._search_again(info, [
('List', 'List of isogeny classes'),
@@ -574,7 +589,14 @@ def common_parse(info, query):
parse_ints(info, query, "hyp_cnt", qfield="hyp_count", name="Number of Hyperelliptic Jacobians")
parse_ints(info, query, "twist_count")
parse_ints(info, query, "max_twist_degree")
- parse_primes(info, query, "noncyclic_primes", qfield="noncyclic_primes")
+ parse_primes(
+ info,
+ query,
+ "noncyclic_primes",
+ qfield="noncyclic_primes",
+ mode=info.get("noncyclic_primes_mode"),
+ )
+
parse_ints(info, query, "size")
parse_newton_polygon(info, query, "newton_polygon", qfield="slopes")
parse_string_start(info, query, "initial_coefficients", qfield="poly_str", initial_segment=["1"])
@@ -892,4 +914,4 @@ def split_label(lab):
return lmfdb_label_regex.match(lab).groups()
def abvar_label(g, q, iso):
- return "%s.%s.%s" % (g, q, iso)
\ No newline at end of file
+ return "%s.%s.%s" % (g, q, iso)
From 625534eba20842371d16c8ce936a827c64a96d54 Mon Sep 17 00:00:00 2001
From: Haonan Gu <160513517+hgu2699@users.noreply.github.com>
Date: Fri, 21 Nov 2025 13:36:46 -0500
Subject: [PATCH 08/12] Update test_browse_page.py
---
lmfdb/abvar/fq/test_browse_page.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lmfdb/abvar/fq/test_browse_page.py b/lmfdb/abvar/fq/test_browse_page.py
index e9be1e5d02..939484894f 100644
--- a/lmfdb/abvar/fq/test_browse_page.py
+++ b/lmfdb/abvar/fq/test_browse_page.py
@@ -290,11 +290,11 @@ def test_search_cyclic_group(self):
# results page; we do not assert specific labels since the data
# on devmirror can change.
self.check_args(
- "/Variety/Abelian/Fq/?is_cyclic=yes",
+ "/Variety/Abelian/Fq/?cyclic=yes",
"Abelian variety search results"
)
self.check_args(
- "/Variety/Abelian/Fq/?is_cyclic=no",
+ "/Variety/Abelian/Fq/?cyclic=no",
"Abelian variety search results"
)
From 8626128f648a6b416313964f3be008f3dd5ff1b3 Mon Sep 17 00:00:00 2001
From: Haonan Gu <160513517+hgu2699@users.noreply.github.com>
Date: Fri, 21 Nov 2025 14:17:46 -0500
Subject: [PATCH 09/12] Update test_browse_page.py
---
lmfdb/abvar/fq/test_browse_page.py | 58 ++++++++++++++++++++----------
1 file changed, 40 insertions(+), 18 deletions(-)
diff --git a/lmfdb/abvar/fq/test_browse_page.py b/lmfdb/abvar/fq/test_browse_page.py
index 939484894f..4b6798da50 100644
--- a/lmfdb/abvar/fq/test_browse_page.py
+++ b/lmfdb/abvar/fq/test_browse_page.py
@@ -15,7 +15,7 @@ def test_index_page(self):
assert "Cyclic group of points" in homepage
def test_stats_page(self):
- self.check_args("/Variety/Abelian/Fq/stats","Abelian variety isogeny classes: Statistics")
+ self.check_args("/Variety/Abelian/Fq/stats", "Abelian variety isogeny classes: Statistics")
# TODO test dynamic stats
@@ -44,7 +44,10 @@ def test_lookup(self):
r"""
Check that Variety/Abelian/Fq/?jump works
"""
- 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")
+ 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"
+ )
# Various searches
# Many things are checked twice: Once from main index/browse page, and once from the refining search page
@@ -149,7 +152,10 @@ def test_search_newton(self):
# slope not a rational number
self.check_args("/Variety/Abelian/Fq/?newton_polygon=t", "is not a valid input")
# slopes are not increasing
- self.check_args("/Variety/Abelian/Fq/?start=&count=&newton_polygon=%5B1%2C1%2F2%2C0%5D", "Slopes must be increasing")
+ self.check_args(
+ "/Variety/Abelian/Fq/?start=&count=&newton_polygon=%5B1%2C1%2F2%2C0%5D",
+ "Slopes must be increasing"
+ )
def test_search_initcoeffs(self):
r"""
@@ -158,7 +164,10 @@ def test_search_initcoeffs(self):
self.check_args("/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D", "4.3.b_ab_d_j")
self.check_args("/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D", "4.3.b_ab_d_j")
# there should be only one match, if ranges were supported
- self.check_args("/Variety/Abelian/Fq/?angle_ranks=&initial_coefficients=%5B3%2C+9%2C+10%2C+87-100%5D", "Ranges not supported")
+ self.check_args(
+ "/Variety/Abelian/Fq/?angle_ranks=&initial_coefficients=%5B3%2C+9%2C+10%2C+87-100%5D",
+ "Ranges not supported"
+ )
def test_search_pointcountsav(self):
r"""
@@ -188,8 +197,14 @@ def test_search_isogfactor(self):
Check that we can search by decomposition into isogeny factors
"""
# [3.5.ah_y_ach,*]
- self.check_args("/Variety/Abelian/Fq/?simple_quantifier=include&simple_factors=3.5.ah_y_ach", "4.5.ak_by_agk_qb")
- 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")
+ self.check_args(
+ "/Variety/Abelian/Fq/?simple_quantifier=include&simple_factors=3.5.ah_y_ach",
+ "4.5.ak_by_agk_qb"
+ )
+ 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"
+ )
self.check_args("/Variety/Abelian/Fq/?dim1_factors=6&dim1_distinct=1", "5 matches")
def test_search_numberfield(self):
@@ -275,35 +290,42 @@ def test_search_combos(self):
self.check_args("/Variety/Abelian/Fq/?p_rank=2&initial_coefficients=%5B1%2C-1%2C3%2C9%5D", "4.3.b_ab_d_j")
self.check_args("/Variety/Abelian/Fq/?p_rank=2&initial_coefficients=%5B1%2C-1%2C3%2C9%5D", "4.3.b_ab_d_j")
# initial coefficients and point counts of the abelian variety
- self.check_args("/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D&abvar_point_count=%5B75%2C7125%5D", "No matches")
- self.check_args("/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D&abvar_point_count=%5B75%2C7125%5D", "No matches")
+ self.check_args(
+ "/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D&abvar_point_count=%5B75%2C7125%5D",
+ "No matches"
+ )
+ self.check_args(
+ "/Variety/Abelian/Fq/?initial_coefficients=%5B1%2C-1%2C3%2C9%5D&abvar_point_count=%5B75%2C7125%5D",
+ "No matches"
+ )
# Combining unknown fields on Jacobian and Principal polarization.
self.check_args("/Variety/Abelian/Fq/?g=3&jacobian=no&polarizable=not_no", "3.2.a_a_ae")
self.check_args("/Variety/Abelian/Fq/?g=3&jacobian=no&polarizable=yes", "3.2.a_ac_a")
-
+
def test_search_cyclic_group(self):
r"""
Check that we can restrict to cyclic or non-cyclic groups of points
- using the is_cyclic search parameter.
+ using the cyclic search parameter.
"""
- # We only check that the search runs and returns the usual search
- # results page; we do not assert specific labels since the data
- # on devmirror can change.
- self.check_args(
+ # 1.3.a is known to be non-cyclic (is_cyclic = False), so it should
+ # not appear in the cyclic=yes search, but should appear for cyclic=no.
+ self.not_check_args(
"/Variety/Abelian/Fq/?cyclic=yes",
- "Abelian variety search results"
+ "1.3.a"
)
self.check_args(
"/Variety/Abelian/Fq/?cyclic=no",
- "Abelian variety search results"
+ "1.3.a"
)
def test_search_noncyclic_primes(self):
r"""
- Check that the noncyclic_primes search parameter is accepted.
+ Check that the noncyclic_primes search parameter is accepted and
+ actually filters on the noncyclic_primes column.
"""
+ # 1.3.a has 2 in noncyclic_primes, so it should appear here.
self.check_args(
"/Variety/Abelian/Fq/?noncyclic_primes=2",
- "Abelian variety search results"
+ "1.3.a"
)
From dbde38130d5a7f3eb739e77e4701101e4c3c96b2 Mon Sep 17 00:00:00 2001
From: Haonan Gu <160513517+hgu2699@users.noreply.github.com>
Date: Fri, 21 Nov 2025 20:47:59 -0500
Subject: [PATCH 10/12] Update test_browse_page.py
---
lmfdb/abvar/fq/test_browse_page.py | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/lmfdb/abvar/fq/test_browse_page.py b/lmfdb/abvar/fq/test_browse_page.py
index 4b6798da50..8746a6f5b3 100644
--- a/lmfdb/abvar/fq/test_browse_page.py
+++ b/lmfdb/abvar/fq/test_browse_page.py
@@ -307,25 +307,27 @@ def test_search_cyclic_group(self):
Check that we can restrict to cyclic or non-cyclic groups of points
using the cyclic search parameter.
"""
- # 1.3.a is known to be non-cyclic (is_cyclic = False), so it should
- # not appear in the cyclic=yes search, but should appear for cyclic=no.
- self.not_check_args(
+ # Example with cyclic group of points (is_cyclic = True).
+ self.check_args(
"/Variety/Abelian/Fq/?cyclic=yes",
- "1.3.a"
+ "1.2.ac",
)
+
+ # Example with non-cyclic group of points (is_cyclic = False).
self.check_args(
"/Variety/Abelian/Fq/?cyclic=no",
- "1.3.a"
+ "1.3.a",
)
+
def test_search_noncyclic_primes(self):
r"""
Check that the noncyclic_primes search parameter is accepted and
- actually filters on the noncyclic_primes column.
+ finds classes that are non-cyclic at p = 2.
"""
- # 1.3.a has 2 in noncyclic_primes, so it should appear here.
self.check_args(
"/Variety/Abelian/Fq/?noncyclic_primes=2",
- "1.3.a"
+ "1.3.a",
)
+
From fd9d9052bbd81e18120ba9a9888b6629ab283ff8 Mon Sep 17 00:00:00 2001
From: Haonan Gu <160513517+hgu2699@users.noreply.github.com>
Date: Fri, 21 Nov 2025 21:00:41 -0500
Subject: [PATCH 11/12] Update test_browse_page.py
---
lmfdb/abvar/fq/test_browse_page.py | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/lmfdb/abvar/fq/test_browse_page.py b/lmfdb/abvar/fq/test_browse_page.py
index 8746a6f5b3..07785af791 100644
--- a/lmfdb/abvar/fq/test_browse_page.py
+++ b/lmfdb/abvar/fq/test_browse_page.py
@@ -307,18 +307,27 @@ def test_search_cyclic_group(self):
Check that we can restrict to cyclic or non-cyclic groups of points
using the cyclic search parameter.
"""
- # Example with cyclic group of points (is_cyclic = True).
+ # 1.2.ac has cyclic group of points (is_cyclic = True)
self.check_args(
"/Variety/Abelian/Fq/?cyclic=yes",
- "1.2.ac",
+ ">1.2.ac<",
)
- # Example with non-cyclic group of points (is_cyclic = False).
+ # 1.3.a has non-cyclic group of points (is_cyclic = False)
self.check_args(
"/Variety/Abelian/Fq/?cyclic=no",
- "1.3.a",
+ ">1.3.a<",
)
+ # And make sure they do not appear in the wrong list
+ self.not_check_args(
+ "/Variety/Abelian/Fq/?cyclic=yes",
+ ">1.3.a<",
+ )
+ self.not_check_args(
+ "/Variety/Abelian/Fq/?cyclic=no",
+ ">1.2.ac<",
+ )
def test_search_noncyclic_primes(self):
r"""
@@ -327,7 +336,8 @@ def test_search_noncyclic_primes(self):
"""
self.check_args(
"/Variety/Abelian/Fq/?noncyclic_primes=2",
- "1.3.a",
+ ">1.3.a<",
)
+
From c459dd348a05f8869b65a7b28e3c77f57eb8fcc7 Mon Sep 17 00:00:00 2001
From: Haonan Gu <160513517+hgu2699@users.noreply.github.com>
Date: Mon, 24 Nov 2025 17:52:47 -0500
Subject: [PATCH 12/12] Update show-abvarfq.html
---
lmfdb/abvar/fq/templates/show-abvarfq.html | 23 +++++++++++-----------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/lmfdb/abvar/fq/templates/show-abvarfq.html b/lmfdb/abvar/fq/templates/show-abvarfq.html
index 7bb7463834..ae6986b148 100644
--- a/lmfdb/abvar/fq/templates/show-abvarfq.html
+++ b/lmfdb/abvar/fq/templates/show-abvarfq.html
@@ -33,20 +33,19 @@ Invariants
{% endif %}
{# --- NEW: cyclicity invariants --- #}
{% if cl.is_cyclic is not none %}
-
- | {{ KNOWL('av.fq.cyclic_group_points', title='Cyclic group of points') }}: |
-
- {% if cl.is_cyclic == 1 or cl.is_cyclic is true %}
- yes
- {% elif cl.is_cyclic == 0 or cl.is_cyclic is false %}
- no
- {% else %}
- unknown
- {% endif %}
- |
-
+
+ | {{ KNOWL('av.fq.cyclic_group_points', title='Cyclic group of points') }}: |
+
+ {% if cl.is_cyclic %}
+ yes
+ {% else %}
+ no
+ {% endif %}
+ |
+
{% endif %}
+
{% if cl.noncyclic_primes %}
| {{ KNOWL('av.fq.noncyclic_primes', title='Non-cyclic primes') }}: |