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("/