Skip to content

Commit 60cf8f2

Browse files
authored
Merge pull request #6881 from rvisser7/galois
Add Sage and Oscar code snippets for Galois groups
2 parents b85c39f + d1874ab commit 60cf8f2

9 files changed

Lines changed: 415 additions & 81 deletions

File tree

lmfdb/galois_groups/code.yaml

Lines changed: 90 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,128 @@
11
prompt:
2-
magma: 'magma'
2+
magma: 'magma'
3+
sage: 'sage'
4+
oscar: 'oscar'
35

46
logo:
5-
magma: <img src = "https://i.stack.imgur.com/0468s.png" width="50px">
7+
magma: <img src = "https://i.stack.imgur.com/0468s.png" width="50px">
8+
sage: <img src ="https://www.sagemath.org/pix/sage_logo_new.png" width = "50px">
9+
oscar: <img src = "https://oscar-system.github.io/Oscar.jl/stable/assets/logo.png" width="50px">
10+
11+
comment:
12+
sage: |
13+
#
14+
magma: |
15+
//
16+
oscar: |
17+
#
18+
19+
not-implemented:
20+
sage: |
21+
# (not yet implemented)
22+
magma: |
23+
// (not yet implemented)
24+
oscar: |
25+
# (not yet implemented)
26+
27+
frontmatter:
28+
all: |
29+
{lang} code for working with transitive group {label}
630
731
gg:
8-
magma: G := TransitiveGroup(%s, %s);
32+
comment: Define the Galois group
33+
magma: G := TransitiveGroup({n}, {t});
34+
sage: G = TransitiveGroup({n}, {t})
35+
oscar: G = transitive_group({n}, {t})
936

1037
n:
11-
magma: t, n := TransitiveGroupIdentification(G); n;
38+
comment: Degree
39+
magma: t, n := TransitiveGroupIdentification(G); n;
40+
sage: G.degree()
41+
oscar: degree(G)
1242

1343
t:
14-
magma: t, n := TransitiveGroupIdentification(G); t;
44+
comment: Transitive number
45+
magma: t, n := TransitiveGroupIdentification(G); t;
46+
sage: G.transitive_number()
47+
oscar: transitive_group_identification(G)[2]
1548

1649
primitive:
17-
magma: IsPrimitive(G);
50+
comment: Determine if group is primitive
51+
magma: IsPrimitive(G);
52+
sage: G.is_primitive()
53+
oscar: is_primitive(G)
1854

1955
even:
20-
magma: IsEven(G);
56+
comment: Parity
57+
magma: IsEven(G);
58+
sage: all(g.SignPerm() == 1 for g in libgap(G).GeneratorsOfGroup())
59+
oscar: is_even(G)
2160

2261
nilpotent:
23-
magma: NilpotencyClass(G);
62+
comment: Nilpotency class
63+
magma: NilpotencyClass(G);
64+
sage: libgap(G).NilpotencyClassOfGroup() if G.is_nilpotent() else -1
65+
oscar: if is_nilpotent(G) nilpotency_class(G) end
2466

2567
auts:
26-
magma: Order(Centralizer(SymmetricGroup(n), G));
68+
comment: Order of the centralizer of G in S_n
69+
magma: Order(Centralizer(SymmetricGroup(n), G));
70+
sage: SymmetricGroup({n}).centralizer(G).order()
71+
oscar: order(centralizer(symmetric_group({n}), G)[1])
2772

2873
gens:
29-
magma: Generators(G);
74+
comment: Generators
75+
magma: Generators(G);
76+
sage: G.gens()
77+
oscar: gens(G)
3078

3179
ccs:
32-
magma: ConjugacyClasses(G);
80+
comment: Conjugacy classes
81+
magma: ConjugacyClasses(G);
82+
sage: G.conjugacy_classes()
83+
oscar: conjugacy_classes(G)
3384

3485
order:
35-
magma: Order(G);
86+
comment: Order
87+
magma: Order(G);
88+
sage: G.order()
89+
oscar: order(G)
3690

3791
cyclic:
38-
magma: IsCyclic(G);
92+
comment: Determine if group is cyclic
93+
magma: IsCyclic(G);
94+
sage: G.is_cyclic()
95+
oscar: is_cyclic(G)
3996

4097
abelian:
41-
magma: IsAbelian(G);
98+
comment: Determine if group is abelian
99+
magma: IsAbelian(G);
100+
sage: G.is_abelian()
101+
oscar: is_abelian(G)
42102

43103
solvable:
44-
magma: IsSolvable(G);
104+
comment: Determine if group is solvable
105+
magma: IsSolvable(G);
106+
sage: G.is_solvable()
107+
oscar: is_solvable(G)
45108

46109
id:
47-
magma: IdentifyGroup(G);
110+
comment: Abstract group ID
111+
magma: IdentifyGroup(G);
112+
sage: G.id()
48113

49114
char_table:
50-
magma: CharacterTable(G);
115+
comment: Character table
116+
magma: CharacterTable(G);
117+
sage: G.character_table()
118+
oscar: character_table(G)
51119

120+
121+
# specify which code snippets to test
52122
snippet_test:
53123
test4T2:
54124
label: 4T2
55125
url: GaloisGroup/4T2/download/{lang}
56-
test11T6:
57-
label: 11T6
58-
url: GaloisGroup/11T6/download/{lang}
126+
test11T5:
127+
label: 11T5
128+
url: GaloisGroup/11T5/download/{lang}

lmfdb/galois_groups/main.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
clean_input, prep_ranges, parse_bool, parse_ints, parse_galgrp,
1414
SearchArray, TextBox, TextBoxNoEg, YesNoBox, ParityBox, CountBox,
1515
StatsDisplay, totaler, proportioners, prop_int_pretty, Downloader,
16-
sparse_cyclotomic_to_mathml, search_wrap, redirect_no_cache)
16+
sparse_cyclotomic_to_mathml, search_wrap, redirect_no_cache, CodeSnippet)
1717
from lmfdb.utils.interesting import interesting_knowls
1818
from lmfdb.utils.search_columns import SearchColumns, LinkCol, MultiProcessedCol, MathCol, CheckCol, SearchCol
1919
from lmfdb.api import datapage
@@ -341,7 +341,7 @@ def render_group_webpage(args):
341341
data['malle_a'] = wgg.malle_a
342342
downloads = []
343343
for lang in [("Magma", "magma"), ("Oscar", "oscar"), ("SageMath", "sage")]:
344-
downloads.append(('{} commands'.format(lang[0]), url_for(".gg_code", label=label, download_type=lang[1])))
344+
downloads.append(('{} commands'.format(lang[0]), url_for(".gg_code_download", label=label, download_type=lang[1])))
345345
downloads.append(('Underlying data', url_for(".gg_data", label=label)))
346346
# split the label so that breadcrumbs point to a search for this object's degree
347347
parent_id, child_id = label.split("T")
@@ -360,20 +360,22 @@ def render_group_webpage(args):
360360
KNOWL_ID="gg.%s" % label,
361361
learnmore=learnmore_list()+[('Picture description', url_for('.pictures'))])
362362

363+
364+
sorted_code_names = ['gg', 'id', 'order', 'cyclic', 'abelian', 'solvable', 'nilpotent',
365+
'n', 't', 'even', 'primitive', 'auts', 'gens', 'ccs', 'char_table']
366+
367+
def gg_code(label, download_type):
368+
gg = WebGaloisGroup(label)
369+
gg.make_code_snippets()
370+
code = CodeSnippet(gg.code)
371+
return code.export_code(label, download_type, sorted_code_names)
372+
363373
@galois_groups_page.route('/<label>/download/<download_type>')
364-
def gg_code(label,download_type):
365-
if download_type == "magma":
366-
s = "// Magma code for creating transitive group " + label + "\n\n"
367-
s += "G := TransitiveGroup(%s,%s);\n" % tuple(label.split("T"))
368-
elif download_type == "oscar":
369-
s = "# Oscar code for creating transitive group " + label + "\n\n"
370-
s += "G = transitive_group(%s,%s)\n" % tuple(label.split("T"))
371-
elif download_type == "sage":
372-
s = "# Sage code for creating transitive group " + label + "\n\n"
373-
s += "G = TransitiveGroup(%s,%s)\n" % tuple(label.split("T"))
374-
else:
375-
return abort(404, f"Invalid download type {download_type}")
376-
response = make_response(s)
374+
def gg_code_download(**args):
375+
try:
376+
response = make_response(gg_code(**args))
377+
except Exception as err:
378+
return abort(404, str(err))
377379
response.headers['Content-type'] = 'text/plain'
378380
return response
379381

lmfdb/galois_groups/transitive_group.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,10 @@ def make_code_snippets(self):
304304
# read in code.yaml from galois_groups directory:
305305
_curdir = os.path.dirname(os.path.abspath(__file__))
306306
self.code = yaml.load(open(os.path.join(_curdir, "code.yaml")), Loader=yaml.FullLoader)
307-
for lang in self.code['gg']:
308-
self.code['gg'][lang] = self.code['gg'][lang] % (self.n(),self.t())
307+
308+
for prop in ['gg', 'auts']:
309+
for lang in self.code[prop]:
310+
self.code[prop][lang] = self.code[prop][lang].format(**{'n':self.n(), 't':self.t()})
309311
self.code['show'] = { lang:'' for lang in self.code['prompt'] }
310312

311313
############ Misc Functions
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# snippet evaluation file generated by generate_snippet_tests.py
2+
3+
julia> G = transitive_group(11, 5)
4+
Permutation group of degree 11
5+
6+
julia> order(G)
7+
660
8+
9+
julia> is_cyclic(G)
10+
false
11+
12+
julia> is_abelian(G)
13+
false
14+
15+
julia> is_solvable(G)
16+
false
17+
18+
julia> if is_nilpotent(G) nilpotency_class(G) end
19+
20+
julia> degree(G)
21+
11
22+
23+
julia> transitive_group_identification(G)[2]
24+
5
25+
26+
julia> is_even(G)
27+
true
28+
29+
julia> is_primitive(G)
30+
true
31+
32+
julia> order(centralizer(symmetric_group(11), G)[1])
33+
1
34+
35+
julia> gens(G)
36+
2-element Vector{PermGroupElem}:
37+
(1,2,3,4,5,6,7,8,9,10,11)
38+
(2,10)(3,4)(5,9)(6,7)
39+
40+
julia> conjugacy_classes(G)
41+
8-element Vector{GAPGroupConjClass{PermGroup, PermGroupElem}}:
42+
Conjugacy class of () in G
43+
Conjugacy class of (3,4)(5,7)(6,9)(8,11) in G
44+
Conjugacy class of (3,5,8)(4,11,7)(6,9,10) in G
45+
Conjugacy class of (2,3,6,9,4)(5,10,7,8,11) in G
46+
Conjugacy class of (2,3,10,9,7)(4,5,11,8,6) in G
47+
Conjugacy class of (1,2)(3,4,8,7,5,11)(6,9,10) in G
48+
Conjugacy class of (1,2,3,4,5,6,7,8,9,10,11) in G
49+
Conjugacy class of (1,2,3,6,10,7,5,9,11,8,4) in G
50+
51+
julia> character_table(G)
52+
Character table of permutation group of degree 11 and order 660
53+
54+
2 2 2 1 . . 1
55+
3 1 1 1 . . 1
56+
5 1 . . 1 1 .
57+
11 1 . . . . .
58+
59+
1a 2a 3a 5a 5b 6a
60+
2P 1a 1a 3a 5b 5a 3a
61+
3P 1a 2a 1a 5b 5a 2a
62+
5P 1a 2a 3a 1a 1a 6a
63+
7P 1a 2a 3a 5b 5a 6a
64+
11P 1a 2a 3a 5a 5b 6a
65+
66+
X_1 1 1 1 1 1 1
67+
X_2 5 1 -1 . . 1
68+
X_3 5 1 -1 . . 1
69+
X_4 10 -2 1 . . 1
70+
X_5 10 2 1 . . -1
71+
X_6 11 -1 -1 1 1 -1
72+
X_7 12 . . z_5^3 + z_5^2 -z_5^3 - z_5^2 - 1 .
73+
X_8 12 . . -z_5^3 - z_5^2 - 1 z_5^3 + z_5^2 .
74+
75+
2 .
76+
3 .
77+
5 .
78+
11 1
79+
80+
11a
81+
2P 11b
82+
3P 11a
83+
5P 11a
84+
7P 11b
85+
11P 1a
86+
87+
X_1 1
88+
X_2 z_11^9 + z_11^5 + z_11^4 + z_11^3 + z_11
89+
X_3 -z_11^9 - z_11^5 - z_11^4 - z_11^3 - z_11 - 1
90+
X_4 -1
91+
X_5 -1
92+
X_6 .
93+
X_7 1
94+
X_8 1
95+
96+
2 .
97+
3 .
98+
5 .
99+
11 1
100+
101+
11b
102+
2P 11a
103+
3P 11b
104+
5P 11b
105+
7P 11a
106+
11P 1a
107+
108+
X_1 1
109+
X_2 -z_11^9 - z_11^5 - z_11^4 - z_11^3 - z_11 - 1
110+
X_3 z_11^9 + z_11^5 + z_11^4 + z_11^3 + z_11
111+
X_4 -1
112+
X_5 -1
113+
X_6 .
114+
X_7 1
115+
X_8 1
116+
117+
julia>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# snippet evaluation file generated by generate_snippet_tests.py
2+
sage: G = TransitiveGroup(11, 5)
3+
sage: G.id()
4+
[660, 13]
5+
sage: G.order()
6+
660
7+
sage: G.is_cyclic()
8+
False
9+
sage: G.is_abelian()
10+
False
11+
sage: G.is_solvable()
12+
False
13+
sage: libgap(G).NilpotencyClassOfGroup() if G.is_nilpotent() else -1
14+
-1
15+
sage: G.degree()
16+
11
17+
sage: G.transitive_number()
18+
5
19+
sage: all(g.SignPerm() == 1 for g in libgap(G).GeneratorsOfGroup())
20+
True
21+
sage: G.is_primitive()
22+
True
23+
sage: SymmetricGroup(11).centralizer(G).order()
24+
1
25+
sage: G.gens()
26+
((1,2,3,4,5,6,7,8,9,10,11), (2,10)(3,4)(5,9)(6,7))
27+
sage: G.conjugacy_classes()
28+
[Conjugacy class of () in Transitive group number 5 of degree 11,
29+
Conjugacy class of (3,4)(5,7)(6,9)(8,11) in Transitive group number 5 of degree 11,
30+
Conjugacy class of (3,5,8)(4,11,7)(6,9,10) in Transitive group number 5 of degree 11,
31+
Conjugacy class of (2,3,6,9,4)(5,10,7,8,11) in Transitive group number 5 of degree 11,
32+
Conjugacy class of (2,3,10,9,7)(4,5,11,8,6) in Transitive group number 5 of degree 11,
33+
Conjugacy class of (1,2)(3,4,8,7,5,11)(6,9,10) in Transitive group number 5 of degree 11,
34+
Conjugacy class of (1,2,3,4,5,6,7,8,9,10,11) in Transitive group number 5 of degree 11,
35+
Conjugacy class of (1,2,3,6,10,7,5,9,11,8,4) in Transitive group number 5 of degree 11]
36+
sage: G.character_table()
37+
[ 1 1 1 1 1 1 1 1]
38+
[ 5 1 -1 0 0 1 -zeta55^34 + zeta55^25 - zeta55^23 + zeta55^20 + zeta55^15 - zeta55^12 + zeta55^5 - zeta55 zeta55^34 - zeta55^25 + zeta55^23 - zeta55^20 - zeta55^15 + zeta55^12 - zeta55^5 + zeta55 - 1]
39+
[ 5 1 -1 0 0 1 zeta55^34 - zeta55^25 + zeta55^23 - zeta55^20 - zeta55^15 + zeta55^12 - zeta55^5 + zeta55 - 1 -zeta55^34 + zeta55^25 - zeta55^23 + zeta55^20 + zeta55^15 - zeta55^12 + zeta55^5 - zeta55]
40+
[ 10 -2 1 0 0 1 -1 -1]
41+
[ 10 2 1 0 0 -1 -1 -1]
42+
[ 11 -1 -1 1 1 -1 0 0]
43+
[ 12 0 0 zeta55^33 + zeta55^22 -zeta55^33 - zeta55^22 - 1 0 1 1]
44+
[ 12 0 0 -zeta55^33 - zeta55^22 - 1 zeta55^33 + zeta55^22 0 1 1]
45+
sage:

0 commit comments

Comments
 (0)