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') }}: