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 )
5353from lmfdb .utils .interesting import interesting_knowls
5454from lmfdb .utils .search_columns import SearchColumns , LinkCol , MathCol , CheckCol , SpacerCol , ProcessedCol , MultiProcessedCol , ColGroup
5555from lmfdb .api import datapage
@@ -104,6 +104,7 @@ def yesno(val):
104104
105105def 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 )
0 commit comments