diff --git a/lmfdb/galois_groups/code.yaml b/lmfdb/galois_groups/code.yaml index dfd89d4026..8c623980b1 100644 --- a/lmfdb/galois_groups/code.yaml +++ b/lmfdb/galois_groups/code.yaml @@ -2,11 +2,13 @@ prompt: magma: 'magma' sage: 'sage' oscar: 'oscar' + gap: 'gap' logo: magma: sage: oscar: + gap: comment: sage: | @@ -15,6 +17,8 @@ comment: // oscar: | # + gap: | + # not-implemented: sage: | @@ -23,6 +27,9 @@ not-implemented: // (not yet implemented) oscar: | # (not yet implemented) + gap: | + # (not yet implemented) + frontmatter: all: | @@ -33,89 +40,105 @@ gg: magma: G := TransitiveGroup({n}, {t}); sage: G = TransitiveGroup({n}, {t}) oscar: G = transitive_group({n}, {t}) + gap: G := TransitiveGroup({n}, {t}); n: comment: Degree magma: t, n := TransitiveGroupIdentification(G); n; sage: G.degree() oscar: degree(G) + gap: NrMovedPoints(G); t: comment: Transitive number magma: t, n := TransitiveGroupIdentification(G); t; sage: G.transitive_number() oscar: transitive_group_identification(G)[2] + gap: TransitiveIdentification(G); primitive: comment: Determine if group is primitive magma: IsPrimitive(G); sage: G.is_primitive() oscar: is_primitive(G) + gap: IsPrimitive(G); even: comment: Parity magma: IsEven(G); sage: all(g.SignPerm() == 1 for g in libgap(G).GeneratorsOfGroup()) oscar: is_even(G) + gap: ForAll(GeneratorsOfGroup(G), g -> SignPerm(g) = 1); nilpotent: comment: Nilpotency class magma: NilpotencyClass(G); sage: libgap(G).NilpotencyClassOfGroup() if G.is_nilpotent() else -1 oscar: if is_nilpotent(G) nilpotency_class(G) end + gap: if IsNilpotentGroup(G) then NilpotencyClassOfGroup(G); fi; auts: comment: Order of the centralizer of G in S_n magma: Order(Centralizer(SymmetricGroup(n), G)); sage: SymmetricGroup({n}).centralizer(G).order() oscar: order(centralizer(symmetric_group({n}), G)[1]) + gap: Order(Centralizer(SymmetricGroup({n}), G)); gens: comment: Generators magma: Generators(G); sage: G.gens() oscar: gens(G) + gap: GeneratorsOfGroup(G); ccs: comment: Conjugacy classes magma: ConjugacyClasses(G); sage: G.conjugacy_classes() oscar: conjugacy_classes(G) + gap: ConjugacyClasses(G); order: comment: Order magma: Order(G); sage: G.order() oscar: order(G) + gap: Order(G); cyclic: comment: Determine if group is cyclic magma: IsCyclic(G); sage: G.is_cyclic() oscar: is_cyclic(G) + gap: IsCyclic(G); abelian: comment: Determine if group is abelian magma: IsAbelian(G); sage: G.is_abelian() oscar: is_abelian(G) + gap: IsAbelian(G); solvable: comment: Determine if group is solvable magma: IsSolvable(G); sage: G.is_solvable() oscar: is_solvable(G) + gap: IsSolvable(G); id: comment: Abstract group ID magma: IdentifyGroup(G); sage: G.id() + oscar: small_group_identification(G) + gap: IdGroup(G); char_table: comment: Character table magma: CharacterTable(G); sage: G.character_table() oscar: character_table(G) + gap: CharacterTable(G); # specify which code snippets to test diff --git a/lmfdb/galois_groups/main.py b/lmfdb/galois_groups/main.py index b59325282a..98f73c654a 100644 --- a/lmfdb/galois_groups/main.py +++ b/lmfdb/galois_groups/main.py @@ -353,7 +353,7 @@ def render_group_webpage(args): data['dispv'] = sparse_cyclotomic_to_mathml data['malle_a'] = wgg.malle_a downloads = [] - for lang in [("Magma", "magma"), ("Oscar", "oscar"), ("SageMath", "sage")]: + for lang in [("Gap", "gap"), ("Magma", "magma"), ("Oscar", "oscar"), ("SageMath", "sage")]: downloads.append(('{} commands'.format(lang[0]), url_for(".gg_code_download", label=label, download_type=lang[1]))) downloads.append(('Underlying data', url_for(".gg_data", label=label))) # split the label so that breadcrumbs point to a search for this object's degree diff --git a/lmfdb/groups/abstract/code.yaml b/lmfdb/groups/abstract/code.yaml index eeffa1afba..99fc92233a 100644 --- a/lmfdb/groups/abstract/code.yaml +++ b/lmfdb/groups/abstract/code.yaml @@ -3,13 +3,14 @@ prompt: gap: 'gap' sage: 'sage' sage_gap: 'sage' # For implementing groups in SageMath, but using the GAP interface + oscar: 'oscar' logo: magma: gap: sage: sage_gap: - + oscar: comment: magma: | @@ -20,7 +21,8 @@ comment: # sage_gap: | # - + oscar: | + # not-implemented: magma: | @@ -31,7 +33,14 @@ not-implemented: # (not yet implemented) sage_gap: | # (not yet implemented) + oscar: | + # (not yet implemented) +frontmatter: + all: | + {lang} code for working with abstract group {label}. + rest: | + Some of these functions may take a long time to execute (this depends on the group). presentation: comment: Define the group with the given generators and relations @@ -49,6 +58,8 @@ permutation: magma: G := PermutationGroup< {deg} | {perms} >; gap: G := Group( {perms} ); sage: G = PermutationGroup([{perms_sage}]) + sage_gap: G = gap.new('Group( {perms} )') + oscar: G = @permutation_group({deg}, {perms}) GLZ: comment: Define the group as a matrix group with coefficients in Z @@ -57,6 +68,8 @@ GLZ: sage: | MS = MatrixSpace(Integers(), {nZ}, {nZ}) G = MatrixGroup({LZsage}) + sage_gap: G = gap.new('Group({LZsplit})') + oscar: G = matrix_group({LZoscar}) GLFp: comment: Define the group as a matrix group with coefficients in GLFp @@ -65,6 +78,8 @@ GLFp: sage: | MS = MatrixSpace(GF({Fp}), {nFp}, {nFp}) G = MatrixGroup({LFpsage}) + sage_gap: G = gap.new('Group({LFpsplit})') + oscar: G = matrix_group({LFposcar}) GLZN: comment: Define the group as a matrix group with coefficients in GLZN @@ -73,6 +88,8 @@ GLZN: sage: | MS = MatrixSpace(Integers({N}), {nZN}, {nZN}) G = MatrixGroup({LZNsage}) + sage_gap: G = gap.new('Group({LZNsplit})') + oscar: G = matrix_group({LZNoscar}) GLZq: comment: Define the group as a matrix group with coefficients in GLZq @@ -81,6 +98,8 @@ GLZq: sage: | MS = MatrixSpace(Integers({Zq}), {nZq}, {nZq}) G = MatrixGroup({LZqsage}) + sage_gap: G = gap.new('Group({LZqsplit})') + oscar: G = matrix_group({LZqoscar}) GLFq: comment: Define the group as a matrix group with coefficients in GLFq @@ -89,56 +108,69 @@ GLFq: sage: | F = GF({Fq}); al = F.0; MS = MatrixSpace(F, {nFq}, {nFq}) G = MatrixGroup({LFqsage}) + sage_gap: G = gap.new('Group({LFqsplit})') + oscar: F = GF({Fq}); al = gen(F); G = matrix_group({LFqoscar}) transitive: comment: Define the group from the transitive group database - magma: G := TransitiveGroup(d,n); - gap: G := TransitiveGroup(d,n); - sage: G = TransitiveGroup(d,n) + magma: G := TransitiveGroup({deg}, {t}); + gap: G := TransitiveGroup({deg}, {t}); + sage: G = TransitiveGroup({deg}, {t}) + sage_gap: G = libgap.TransitiveGroup({deg}, {t}) + oscar: G = transitive_group({deg}, {t}) order: comment: Order of the group magma: Order(G); gap: Order(G); - sage: G.order() - sage_gap: G.Order() + sage: G.order() + sage_gap: G.Order() + oscar: order(G) exponent: comment: Exponent of the group magma: Exponent(G); gap: Exponent(G); - sage: G.exponent() - sage_gap: G.Exponent() + sage: G.exponent() + sage_gap: G.Exponent() + oscar: exponent(G) automorphism_group: comment: Automorphism group gap: AutomorphismGroup(G); magma: AutomorphismGroup(G); + sage: libgap(G).AutomorphismGroup() sage_gap: G.AutomorphismGroup() + oscar: automorphism_group(G) outer_automorphism_group: comment: The outer automorphism group of G - gap: FactorGroup(AutomorphismGroup(G), InnerAutomorphismGroup(G)); + gap: FactorGroup(AutomorphismGroup(G), InnerAutomorphismGroup(G)); composition_factors: comment: Composition factors of the group magma: CompositionFactors(G); - gap: CompositionSeries(G); - sage: G.composition_series() + gap: CompositionSeries(G); + sage: G.composition_series() sage_gap: G.CompositionSeries() + oscar: composition_series(G) nilpotency_class: - comment: Nilpotency class of the group + comment: Nilpotency class of the group magma: NilpotencyClass(G); - gap: NilpotencyClassOfGroup(G); - sage_gap: G.NilpotencyClassOfGroup() + gap: if IsNilpotentGroup(G) then NilpotencyClassOfGroup(G); fi; + sage: libgap(G).NilpotencyClassOfGroup() if G.is_nilpotent() else -1 + sage_gap: G.NilpotencyClassOfGroup() if G.IsNilpotentGroup() else -1 + oscar: if is_nilpotent(G) nilpotency_class(G) end derived_length: comment: Derived length of the group magma: DerivedLength(G); gap: DerivedLength(G); + sage: libgap(G).DerivedLength() sage_gap: G.DerivedLength() + oscar: derived_length(G) is_abelian: comment: Determine if the group G is abelian @@ -146,6 +178,7 @@ is_abelian: gap: IsAbelian(G); sage: G.is_abelian() sage_gap: G.IsAbelian() + oscar: is_abelian(G) is_cyclic: comment: Determine if the group G is cyclic @@ -153,6 +186,7 @@ is_cyclic: gap: IsCyclic(G); sage: G.is_cyclic() sage_gap: G.IsCyclic() + oscar: is_cyclic(G) is_elementary_abelian: comment: Determine if the group G is elementary abelian @@ -160,31 +194,35 @@ is_elementary_abelian: gap: IsElementaryAbelian(G); sage: G.is_elementary_abelian() sage_gap: G.IsElementaryAbelian() + oscar: is_elementary_abelian(G) is_monomial: comment: Determine if the group G is a monomial group gap: IsMonomialGroup(G); - sage_gap: G.IsMonomialGroup() + sage_gap: G.IsMonomialGroup() is_nilpotent: comment: Determine if the group G is nilpotent magma: IsNilpotent(G); gap: IsNilpotentGroup(G); sage: G.is_nilpotent() - sage_gap: G.IsNilpotentGroup() + sage_gap: G.IsNilpotentGroup() + oscar: is_nilpotent(G) is_perfect: comment: Determine if the group G is perfect magma: IsPerfect(G); gap: IsPerfectGroup(G); sage: G.is_perfect() - sage_gap: G.IsPerfect() + sage_gap: G.IsPerfect() + oscar: is_perfect(G) is_pgroup: comment: Determine if the group G is a p-group gap: IsPGroup(G); sage: G.is_pgroup() sage_gap: G.IsPGroup() + oscar: is_pgroup(G) is_polycyclic: comment: Determine if the group G is polycyclic @@ -196,7 +234,9 @@ is_simple: comment: Determine if the group G is simple magma: IsSimple(G); gap: IsSimpleGroup(G); - sage_gap: G.IsSimpleGroup() + sage: G.is_simple() + sage_gap: G.IsSimpleGroup() + oscar: is_simple(G) is_solvable: comment: Determine if the group G is solvable @@ -204,12 +244,14 @@ is_solvable: gap: IsSolvableGroup(G); sage: G.is_solvable() sage_gap: G.IsSolvableGroup() + oscar: is_solvable(G) is_supersolvable: comment: Determine if the group G is supersolvable gap: IsSupersolvableGroup(G); sage: G.is_supersolvable() sage_gap: G.IsSupersolvableGroup() + oscar: is_supersolvable(G) group_statistics: @@ -240,17 +282,38 @@ group_statistics: print("Elements:", [element_orders.count(n) for n in orders], G.order()) cc_orders = [cc[0].order() for cc in G.conjugacy_classes()] print("Conjugacy classes:", [cc_orders.count(n) for n in orders], len(cc_orders)) + sage_gap: | + # Sage code (using the GAP interface) to output the first two rows of the group statistics table + element_orders = [g.Order() for g in G.Elements()] + orders = sorted(list(set(element_orders))) + print("Orders:", orders) + print("Elements:", [element_orders.count(n) for n in orders], G.Order()) + cc_orders = [cc.Representative().Order() for cc in G.ConjugacyClasses()] + print("Conjugacy classes:", [cc_orders.count(n) for n in orders], len(cc_orders)) + oscar: | + # Oscar code to output the first two rows of the group statistics table + element_orders = [order(g) for g in elements(G)] + orders = sort(unique(element_orders)) + println("Orders: ", orders) + element_counts = [count(==(n), element_orders) for n in orders] + println("Elements: ", element_counts, " ", order(G)) + ccs = conjugacy_classes(G) + cc_orders = [order(representative(cc)) for cc in ccs] + cc_counts = [count(==(n), cc_orders) for n in orders] + println("Conjugacy classes: ", cc_counts, " ", length(ccs)) conjugacy_classes: comment: List of conjugacy classes of the group magma: | ConjugacyClasses(G); // Output not guaranteed to exactly match the LMFDB table gap: | - ConjugacyClasses(G); # Output not guaranteed to exactly match the LMFDB table + ConjugacyClasses(G); # Output not guaranteed to exactly match the LMFDB table sage: | G.conjugacy_classes() # Output not guaranteed to exactly match the LMFDB table sage_gap: | G.ConjugacyClasses() # Output not guaranteed to exactly match the LMFDB table + oscar: | + conjugacy_classes(G) # Output not guaranteed to exactly match the LMFDB table character_statistics: comment: Compute statistics about the characters of G @@ -264,9 +327,12 @@ character_statistics: # Outputs [[d_1,c_1], [d_2,c_2], ...] where c_i is the number of irr. complex chars. of G with degree d_i character_degrees = [c[0] for c in G.character_table()] [[n, character_degrees.count(n)] for n in set(character_degrees)] - sage_gap: + sage_gap: | # Outputs [[d_1,c_1], [d_2,c_2], ...] where c_i is the number of irr. complex chars. of G with degree d_i G.CharacterDegrees() + oscar: | + # Outputs an MSet containing the absolutely irreducible degrees of G and their multiplicities. + character_degrees(G) primary_decomposition: @@ -274,12 +340,15 @@ primary_decomposition: magma: PrimaryInvariants(G); gap: AbelianInvariants(G); sage_gap: G.AbelianInvariants() + oscar: abelian_invariants(G) abelianization: - comment: The abelianization of the group - magma: quo< G | CommutatorSubgroup(G) >; - gap: FactorGroup(G, DerivedSubgroup(G)); - sage: G.quotient(G.commutator()) + comment: The abelianization of the group + magma: quo< G | CommutatorSubgroup(G) >; + gap: FactorGroup(G, DerivedSubgroup(G)); + sage: G.quotient(G.commutator()) + sage_gap: G.FactorGroup(G.DerivedSubgroup()) + oscar: quo(G, derived_subgroup(G)[1]) schur_multiplier: comment: The Schur multiplier of the group @@ -288,37 +357,41 @@ schur_multiplier: sage_gap: G.AbelianInvariantsMultiplier() commutator_length: - comment: The commutator length of the group + comment: The commutator length of the group gap: CommutatorLength(G); sage_gap: G.CommutatorLength() subgroups: - comment: List of subgroups of the group - magma: Subgroups(G); - gap: AllSubgroups(G); - sage: G.subgroups() + comment: List of subgroups of the group + magma: Subgroups(G); + gap: AllSubgroups(G); + sage: G.subgroups() sage_gap: G.AllSubgroups() + oscar: subgroups(G) center: comment: Center of the group magma: Center(G); - gap: Center(G); - sage: G.center() - sage_gap: G.Center() + gap: Center(G); + sage: G.center() + sage_gap: G.Center() + oscar: center(G) commutator_subgroup: comment: Commutator subgroup of the group G - magma: CommutatorSubgroup(G); - gap: DerivedSubgroup(G); - sage: G.commutator() - sage_gap: G.DerivedSubgroup() + magma: CommutatorSubgroup(G); + gap: DerivedSubgroup(G); + sage: G.commutator() + sage_gap: G.DerivedSubgroup() + oscar: derived_subgroup(G) frattini_subgroup: comment: Frattini subgroup of the group G - magma: FrattiniSubgroup(G); + magma: FrattiniSubgroup(G); gap: FrattiniSubgroup(G); - sage: G.frattini_subgroup() + sage: G.frattini_subgroup() sage_gap: G.FrattiniSubgroup() + oscar: frattini_subgroup(G) fitting_subgroup: comment: Fitting subgroup of the group G @@ -326,12 +399,14 @@ fitting_subgroup: gap: FittingSubgroup(G); sage: G.fitting_subgroup() sage_gap: G.FittingSubgroup() + oscar: fitting_subgroup(G) radical: comment: Radical of the group G magma: Radical(G); gap: SolvableRadical(G); sage_gap: G.SolvableRadical() + oscar: solvable_radical(G) socle: comment: Socle of the group G @@ -339,19 +414,23 @@ socle: gap: Socle(G); sage: G.socle() sage_gap: G.Socle() + oscar: socle(G) derived_series: - comment: Derived series of the group GF + comment: Derived series of the group G magma: DerivedSeries(G); gap: DerivedSeriesOfGroup(G); sage: G.derived_series() sage_gap: G.DerivedSeriesOfGroup() + oscar: derived_series(G) chief_series: comment: Chief series of the group G magma: ChiefSeries(G); gap: ChiefSeries(G); + sage: libgap(G).ChiefSeries() sage_gap: G.ChiefSeries() + oscar: chief_series(G) lower_central_series: comment: The lower central series of the group G @@ -359,13 +438,15 @@ lower_central_series: gap: LowerCentralSeriesOfGroup(G); sage: G.lower_central_series() sage_gap: G.LowerCentralSeriesOfGroup() + oscar: lower_central_series(G) upper_central_series: comment: The upper central series of the group G - magma: UpperCentralSeries(G); + magma: UpperCentralSeries(G); gap: UpperCentralSeriesOfGroup(G); sage: G.upper_central_series() - sage_gap: G.UpperCentralSeriesOfGroup() + sage_gap: G.UpperCentralSeriesOfGroup() + oscar: upper_central_series(G) character_table: comment: Character table @@ -377,3 +458,86 @@ character_table: G.character_table() # Output not guaranteed to exactly match the LMFDB table sage_gap: | G.CharacterTable() # Output not guaranteed to exactly match the LMFDB table + oscar: | + character_table(G) # Output not guaranteed to exactly match the LMFDB table + + +# Code snippets for special group families (used in the construction of the top code snippet) +cyclic_group: + comment: Define group as a cyclic group + magma: G := CyclicGroup({ordgp}); + gap: G := CyclicGroup({ordgp}); + sage: G = CyclicPermutationGroup({ordgp}) + sage_gap: G = libgap.eval('CyclicGroup({ordgp})') + oscar: G = cyclic_group({ordgp}) + +symmetric_group: + comment: Define group as a symmetric group + magma: G := SymmetricGroup({symn}); + gap: G := SymmetricGroup({symn}); + sage: G = SymmetricGroup({symn}) + sage_gap: G = libgap.eval('SymmetricGroup({symn})') + oscar: G = symmetric_group({symn}) + +dihedral_group: + comment: Define group as a dihedral group + magma: G := DihedralGroup({ordgp_half}); # Magma D(n) has order 2n + gap: G := DihedralGroup({ordgp}); # GAP D(n) has order n + sage: G = DihedralGroup({ordgp_half}) # Sage D(n) has order 2n + sage_gap: G = libgap.eval('DihedralGroup({ordgp})') # Sage GAP D(n) has order n + oscar: G = dihedral_group({ordgp}) # Oscar D(n) has order n + +alternating_group: + comment: Define group as an alternating group + magma: G := AlternatingGroup({altn}); + gap: G := AlternatingGroup({altn}); + sage: G = AlternatingGroup({altn}) + sage_gap: G = libgap.eval('AlternatingGroup({altn})') + oscar: G = alternating_group({altn}) + +dicyclic_group: + comment: Define group as a dicyclic group + magma: G := DicyclicGroup({ordgp_quarter}); # Magma Dic(n) has order 4n + gap: G := DicyclicGroup({ordgp}); # GAP Dic(n) has order n + sage: G = DiCyclicGroup({ordgp_quarter}) # Sage Dic(n) has order 4n + sage_gap: libgap.eval('DicyclicGroup({ordgp})') # Sage GAP Dic(n) has order n + oscar: G = dicyclic_group({ordgp}) # Oscar Dic(n) has order n + +chevalley_group: + comment: Define group as a Chevalley group + magma: G := ChevalleyGroup("{chev_fam}", {chev_params}); + +small_group: + comment: Define group as element of the GAP SmallGroups database + magma: G := SmallGroup({ordgp}, {gap_id}); + gap: G := SmallGroup({ordgp}, {gap_id}); + sage_gap: G = libgap.SmallGroup({ordgp}, {gap_id}) + oscar: G = small_group({ordgp}, {gap_id}) + +abelian_group: + comment: Define group as an abelian group + magma: G := AbelianGroup({abelian_invariants}); + gap: G := AbelianGroup({abelian_invariants}); + sage: G = AbelianGroup({abelian_invariants}) + sage_gap: G = libgap.eval('AbelianGroup({abelian_invariants})') + oscar: G = abelian_group({abelian_invariants}) + + +# Code snippet tests for abstract group pages +snippet_test: + # Trivial group + testC1: + label: C1 + url: Groups/Abstract/1.1/codedownload/{lang} + # Symmetric group S_3 + testS3: + label: S3 + url: Groups/Abstract/6.1/codedownload/{lang} + # Dihedral group D_4 (of order 8) + testD4: + label: D4 + url: Groups/Abstract/8.3/codedownload/{lang} + # Alternating group A_5 + testA5: + label: A5 + url: Groups/Abstract/60.5/codedownload/{lang} diff --git a/lmfdb/groups/abstract/main.py b/lmfdb/groups/abstract/main.py index 449222216d..aaac66bb92 100644 --- a/lmfdb/groups/abstract/main.py +++ b/lmfdb/groups/abstract/main.py @@ -49,6 +49,7 @@ sparse_cyclotomic_to_mathml, integer_to_mathml, redirect_no_cache, + CodeSnippet, ) from lmfdb.utils.search_parsing import (parse_multiset, search_parser, collapse_ors) from lmfdb.utils.interesting import interesting_knowls @@ -1889,6 +1890,11 @@ def render_abstract_group(label, data=None): info['pos_int_and_factor'] = pos_int_and_factor info['conv'] = integer_to_mathml info['dispv'] = sparse_cyclotomic_to_mathml + + code = gp.code_snippets() + if code and len(code['prompt']) == 0: # no codes + code = None + if gp.live(): title = f"Abstract group {label}" friends = [] @@ -1906,10 +1912,12 @@ def render_abstract_group(label, data=None): # disable until we can fix downloads downloads = [("Group to Gap", url_for(".download_group", label=label, download_type="gap")), - ("Group to Magma", url_for(".download_group", label=label, download_type="magma")), - # ("Group to Oscar", url_for(".download_group", label=label, download_type="oscar")), - ("Underlying data", url_for(".gp_data", label=label)), - ] + ("Group to Magma", url_for(".download_group", label=label, download_type="magma"))] + #("Group to Oscar", url_for(".download_group", label=label, download_type="oscar")), + for lang in [("Gap","gap"), ("Magma","magma"), ("SageMath","sage"), ("SageMath (using Gap)","sage_gap"), ("Oscar","oscar")]: + if lang[1] in code['prompt']: + downloads.append(('{} commands'.format(lang[0]), url_for(".download_group_code", label=label, download_type=lang[1]))) + downloads.append(("Underlying data", url_for(".gp_data", label=label))) # "internal" friends sbgp_of_url = ( @@ -1977,9 +1985,7 @@ def render_abstract_group(label, data=None): bread = get_bread([(gp.label_compress(), "")]) learnmore_gp_picture = ('Picture description', url_for(".picture_page")) - code = gp.code_snippets() - if code and len(code['prompt']) == 0: # no codes - code = None + return render_template( "abstract-show-group.html", @@ -2570,6 +2576,41 @@ def download_group(**args): #strIO.seek(0) #return send_file(strIO, attachment_filename=filename, as_attachment=True, add_etags=False) +# Sorted list of abstract group code snippets to download +sorted_code_names = ["code_description", "order", "exponent", "automorphism_group", "outer_automorphism_group", "composition_factors", + "nilpotency_class", "derived_length", "is_abelian", "is_cyclic", "is_elementary_abelian", "is_monomial", + "is_nilpotent", "is_perfect", "is_pgroup", "is_polycyclic", "is_simple", "is_solvable", "is_supersolvable", + "group_statistics", "conjugacy_classes", "character_statistics", "lie_reps_all", "presentation", "permutation", + "GLZ", "GLFp", "GLZN", "GLZq", "GLFq", "transitive_all", "primary_decomposition", "abelianization", + "schur_multiplier", "commutator_length", "subgroups", "center", "commutator_subgroup", "frattini_subgroup", + "fitting_subgroup", "radical", "socle", "derived_series", "chief_series", "lower_central_series", + "upper_central_series", "character_table"] + +@abstract_page.route("/