Skip to content

Commit fd7cdae

Browse files
authored
Merge pull request #6643 from roed314/cox_search
2 parents 268ff37 + 47e93f3 commit fd7cdae

File tree

2 files changed

+91
-22
lines changed

2 files changed

+91
-22
lines changed

lmfdb/groups/abstract/main.py

Lines changed: 79 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
sparse_cyclotomic_to_mathml,
5050
integer_to_mathml,
5151
)
52-
from lmfdb.utils.search_parsing import (parse_multiset, search_parser)
52+
from lmfdb.utils.search_parsing import (parse_multiset, search_parser, collapse_ors)
5353
from lmfdb.utils.interesting import interesting_knowls
5454
from lmfdb.utils.search_columns import SearchColumns, LinkCol, MathCol, CheckCol, SpacerCol, ProcessedCol, MultiProcessedCol, ColGroup
5555
from lmfdb.api import datapage
@@ -104,6 +104,7 @@ def yesno(val):
104104

105105
def deTeX_name(s):
106106
s = re.sub(r"[{}\\$]", "", s)
107+
s = s.replace("Orth", "O").replace("Unitary", "U")
107108
return s
108109

109110
@cached_function
@@ -114,20 +115,25 @@ def group_families(deTeX=False):
114115
# Here, we're directly adding the individual Chevalley group families (i.e. 'A(n,q)', 'B(n,q)', ...) to the group families list
115116
# (doing this here to avoid manually adding new families to the data; this avoids re-duplicating data which is already stored in the database)
116117
chev_index = [t[0] for t in L].index("Chev")+1
117-
for f in ['An','Bn','Cn','Dn','En','F4', 'G2']:
118+
for f in ['An','Bn','Cn','Dn','En','F4','G2']:
118119
L.insert(chev_index, ("Chev"+f[0], "$"+f[0]+"({"+f[1]+"}, {q})$"))
119120
chev_index += 1
120121
twistchev_index = [t[0] for t in L].index("TwistChev")+1
121122
for f in ['2An','2B2','2Dn','3D4','2E6','2F4','2G2']:
122123
L.insert(twistchev_index, ("TwistChev"+f[:2], "$^{"+f[0]+"}{"+f[1]+"}({"+f[2]+"},{q})$"))
123124
twistchev_index += 1
125+
# Adding the individual irreducible Coxeter group families
126+
cox_index = [t[0] for t in L].index("Cox")+1
127+
for f in ['A','B','D','E','F']:
128+
L.insert(cox_index, ("Cox"+f[0], "$W("+f+"_{{n}})$"))
129+
cox_index += 1
124130

125131
if deTeX:
126132
# Used for constructing the dropdown
127133
return [(fam, deTeX_name(name)) for (fam, name) in L]
128134

129135
def hidden(fam):
130-
return fam not in ["C", "S", "D", "A", "Q", "GL", "SL", "PSL", "Sp", "SO", "Sporadic"]
136+
return fam not in ["C", "S", "D", "A", "Q", "GL", "SL", "PSL", "Sp", "SO", "Sporadic", "Cox"]
131137
L = [(fam, name, "fam_more" if hidden(fam) else "fam_always", hidden(fam)) for (fam, name) in L]
132138
return L
133139

@@ -203,6 +209,16 @@ def parse_family(inp, query, qfield):
203209
query[qfield] = {'$in':list(db.gps_special_names.search({'family':"Chev", 'parameters.fam':inp[4]}, projection='label'))}
204210
elif inp[:9] == 'TwistChev' and len(inp) == 11:
205211
query[qfield] = {'$in':list(db.gps_special_names.search({'family':"TwistChev", 'parameters.twist':int(inp[9]), 'parameters.fam':inp[10]}, projection='label'))}
212+
# Searching for Coxeter families should include all dihedral groups and all symmetric S_n for n >= 2
213+
elif inp == 'Cox':
214+
labels = list(db.gps_special_names.search({'family': {'$or': ['Cox', 'CoxH']}}, projection='label'))
215+
collapse_ors(["$or", [{"dihedral":True}, {"label": {"$in": labels}}]], query)
216+
# Case of CoxI2 (return all dihedral groups D_n)
217+
elif inp == 'CoxI':
218+
query["dihedral"] = True
219+
# Case to check if family is one of the individual irreducible Coxeter families
220+
elif inp[:3] == 'Cox' and inp[3] != "H":
221+
query[qfield] = {'$in':list(db.gps_special_names.search({'family':"Cox", 'parameters.fam':inp[3]}, projection='label'))}
206222

207223
else:
208224
query[qfield] = {'$in':list(db.gps_special_names.search({'family':inp}, projection='label'))}
@@ -1116,14 +1132,54 @@ def group_jump(info):
11161132
elif len(labs) == 2:
11171133
return redirect(url_for(".index", name=jump.replace(" ", "")))
11181134
# by special name
1135+
def int_try(x):
1136+
if x.isdigit():
1137+
return int(x)
1138+
return x
1139+
def valid_params(fam, params):
1140+
n = ZZ(params.get("n"))
1141+
q = ZZ(params.get("q"))
1142+
if fam in ["Q", "SD", "OD"]:
1143+
return n.is_power_of(2)
1144+
if fam == "F":
1145+
return n.is_prime_power()
1146+
elif fam == "He":
1147+
return n > 2 and n.is_prime()
1148+
elif fam in ["Sp", "PSp", "SOPlus", "SOMinus", "GOPlus", "GOMinus", "OmegaPlus", "OmegaMinus", "PSOPlus", "PSOMinus", "PGOPlus", "PGOMinus", "POmegaPlus", "POmegaMinus", "SpinPlus", "SpinMinus", "CSp", "CSOPlus", "CSOMinus", "COPlus", "COMinus", "PSigmaSp", "ASigmaSp"]:
1149+
return n % 2 == 0
1150+
elif fam in ["SO", "PSO", "GO", "Omega", "PGO", "POmega", "Spin", "CSO", "CO"]:
1151+
return n % 2 == 1
1152+
elif fam == "CoxH":
1153+
return n in [3,4]
1154+
elif fam in ["Cox", "Chev"]:
1155+
if params["fam"] == "E":
1156+
return n in [6,7,8]
1157+
elif params["fam"] == "F":
1158+
return n == 4
1159+
elif params["fam"] == "G":
1160+
return n == 2
1161+
elif fam == "TwistChev":
1162+
if params["fam"] == "A":
1163+
return params["twist"] == 2
1164+
elif params["fam"] == "B":
1165+
return n == 2 and params["twist"] == 2 and q.is_power_of(2) and not q.is_power_of(4)
1166+
elif params["fam"] == "D":
1167+
return params["twist"] == 2 or (params["twist"] == 3 and n == 4)
1168+
elif params["fam"] == "E":
1169+
return n == 6 and params["twist"] == 2
1170+
elif params["fam"] == "F":
1171+
return n == 4 and params["twist"] == 2 and q.is_power_of(2) and not q.is_power_of(4)
1172+
elif params["fam"] == "G":
1173+
return n == 2 and params["twist"] == 2 and q.is_power_of(3) and not q.is_power_of(9)
11191174
for family in db.gps_families.search():
11201175
m = re.fullmatch(family["input"], jump)
11211176
if m:
1122-
m_dict = dict([a, int(x)] for a, x in m.groupdict().items()) # convert string to int
1177+
m_dict = dict([a, int_try(x)] for a, x in m.groupdict().items()) # convert string to int
11231178
lab = db.gps_special_names.lucky({"family":family["family"], "parameters":m_dict}, projection="label")
11241179
if lab:
11251180
return redirect(url_for(".by_label", label=lab))
1126-
else:
1181+
elif valid_params(family["family"], m_dict):
1182+
# Only display this messages for groups that exist
11271183
flash_error("The group %s has not yet been added to the database." % jump)
11281184
return redirect(url_for(".index"))
11291185
flash_error("%s is not a valid name for a group or subgroup; see %s for a list of possible families" % (jump, display_knowl('group.families', 'here')))
@@ -1237,18 +1293,23 @@ def group_postprocess(res, info, query):
12371293
for rec in res:
12381294
rec["tex_cache"] = tex_cache
12391295
if "family" in info:
1240-
if info["family"] == "any":
1296+
family = info["family"]
1297+
if family == "any":
12411298
fquery = {}
12421299

12431300
# Special case to convert the family "ChevX" (for X = A..G) to just "Chev" for the database query
1244-
elif info["family"][:4] == "Chev":
1301+
elif family[:4] == "Chev":
12451302
fquery = {"family": "Chev"}
12461303
# Also special case to convert the family "TwistChevNX" to just "TwistChev" for the database query
1247-
elif info["family"][:9] == "TwistChev":
1304+
elif family[:9] == "TwistChev":
12481305
fquery = {"family": "TwistChev"}
1249-
1306+
# Convert "CoxX" to: ("Cox" or "S" or "D") for database query
1307+
elif family == "Cox":
1308+
fquery = {"family": {"$or": ["Cox", "CoxH", "CoxI"]}}
1309+
elif family[:3] == "Cox" and family[3] not in "HI":
1310+
fquery = {"family": "Cox"}
12501311
else:
1251-
fquery = {"family": info["family"]}
1312+
fquery = {"family": family}
12521313
fams = {rec["family"]: (rec["priority"], rec["tex_name"]) for rec in db.gps_families.search(fquery, ["family", "priority", "tex_name"])}
12531314
fquery["label"] = {"$in":[rec["label"] for rec in res]}
12541315
special_names = defaultdict(list)
@@ -1262,11 +1323,14 @@ def group_postprocess(res, info, query):
12621323

12631324
# Special case to deal with individual Chevalley families
12641325
# (e.g. querying the "A(n,q)" family should ensure the "B(n,q)" family names don't show up under "Family name" search column)
1265-
if (info["family"][:4] == "Chev") and (len(info["family"]) == 5):
1266-
if name[0] != info["family"][4]:
1326+
if (family[:4] == "Chev") and (len(family) == 5):
1327+
if name[0] != family[4]:
1328+
continue
1329+
elif (family[:9] == "TwistChev") and (len(family) == 11):
1330+
if name[3:5] != family[9:11]:
12671331
continue
1268-
if (info["family"][:9] == "TwistChev") and (len(info["family"]) == 11):
1269-
if name[3:5] != info["family"][9:11]:
1332+
elif (fam == "Cox" and family[:3] == "Cox" and len(family) == 4):
1333+
if params["fam"] != family[3]:
12701334
continue
12711335

12721336
special_names[rec["label"]].append((fams[fam][0], params.get("n"), params.get("q"), name))
@@ -2894,7 +2958,7 @@ def __init__(self):
28942958
)
28952959
family = SelectBox(
28962960
name="family",
2897-
options=[("", "")] + group_families(deTeX=True) + [("any", "any")],
2961+
options=[("", ""), ("any", "any")] + group_families(deTeX=True),
28982962
knowl="group.families",
28992963
label="Family",
29002964
)

lmfdb/templates/base.html

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,22 +81,24 @@
8181
"\\AGL": '{\\textrm{AGL}}',
8282
"\\ASp": '{\\textrm{ASp}}',
8383
"\\Sp": '{\\textrm{Sp}}',
84-
"\\GSp": '{\\textrm{GSp}}',
8584
"\\PSp": '{\\textrm{PSp}}',
8685
"\\SO": '{\\textrm{SO}}',
8786
"\\PSO": '{\\textrm{PSO}}',
88-
"\\PGO": '{\\textrm{PGO}}',
87+
"\\PO": '{\\textrm{PO}}',
88+
"\\PGO": '{\\textrm{PO}}',
8989
"\\SU": '{\\textrm{SU}}',
9090
"\\PSU": '{\\textrm{PSU}}',
9191
"\\SOPlus": '{\\textrm{SO}^+}',
9292
"\\SOMinus": '{\\textrm{SO}^-}',
9393
"\\GO": '{\\textrm{O}}',
9494
"\\Orth": '{\\textrm{O}}',
9595
"\\GOPlus": '{\\textrm{O}^+}',
96+
"\\OPlus": '{\\textrm{O}^+}',
9697
"\\OrthPlus": '{\\textrm{O}^+}',
9798
"\\GOMinus": '{\\textrm{O}^-}',
9899
"\\OrthMinus": '{\\textrm{O}^-}',
99-
"\\GU": '{\\textrm{U}}',
100+
"\\OMinus": '{\\textrm{O}^-}',
101+
"\\GU": '{\\textrm{GU}}',
100102
"\\Unitary": '{\\textrm{U}}',
101103
"\\CSp": '{\\textrm{GSp}}',
102104
"\\GSp": '{\\textrm{GSp}}',
@@ -109,7 +111,7 @@
109111
"\\CSU": '{\\textrm{GSU}}',
110112
"\\GSU": '{\\textrm{GSU}}',
111113
"\\CO": '{\\textrm{GO}}',
112-
"\\Gorth": '{\\textrm{GO}}',
114+
"\\GOrth": '{\\textrm{GO}}',
113115
"\\COPlus": '{\\textrm{GO}^+}',
114116
"\\GOrthPlus": '{\\textrm{GO}^+}',
115117
"\\COMinus": '{\\textrm{GO}^-}',
@@ -122,10 +124,13 @@
122124
"\\SpinPlus": '{\\textrm{Spin}^+}',
123125
"\\SpinMinus": '{\\textrm{Spin}^-}',
124126
"\\PSOPlus": '{\\textrm{PSO}^+}',
125-
"\\PGOPlus": '{\\textrm{PGO}^+}',
126-
"\\PGU": '{\\textrm{PGU}}',
127+
"\\POPlus": '{\\textrm{PO}^+}',
128+
"\\PGOPlus": '{\\textrm{PO}^+}',
129+
"\\PU": '{\\textrm{PU}}',
130+
"\\PGU": '{\\textrm{PU}}',
127131
"\\PSOMinus": '{\\textrm{PSO}^-}',
128-
"\\PGOMinus": '{\\textrm{PGO}^-}',
132+
"\\POMinus": '{\\textrm{PO}^-}',
133+
"\\PGOMinus": '{\\textrm{PO}^-}',
129134
"\\POmega": '{\\textrm{P}\\Omega}',
130135
"\\POmegaPlus": '{\\textrm{P}\\Omega^+}',
131136
"\\POmegaMinus": '{\\textrm{P}\\Omega^-}',

0 commit comments

Comments
 (0)