Skip to content

Commit eed056e

Browse files
authored
Merge pull request #6896 from roed314/alpha
main -> alpha
2 parents 87027cf + 3ece7e7 commit eed056e

37 files changed

Lines changed: 767 additions & 167 deletions

lmfdb/api/templates/database_options.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<div style="max-width:700px;">
66
<p>
7-
The LMFDB contains two types of underlying data: the main PostgreSQL database and a collection of <a href="{{url_for('datasets')}}">auxiliary datasets</a>. There are three options available for accessing large parts of the main database.
7+
The LMFDB contains two types of underlying data: the main PostgreSQL database and a collection of <a href="{{url_for('datasets')}}">auxiliary datasets</a>; all data is <a href="{{url_for('license')}}">licensed</a> under <a href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">CC-BY-SA</a>. There are three options available for accessing large parts of the main database.
88
</p>
99
</div>
1010

lmfdb/app.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,12 @@ def citation():
544544
b = [(t, url_for("citation"))]
545545
return render_template('citation.html', title=t, body_class='', bread=b)
546546

547+
@app.route("/license")
548+
def license():
549+
t = "LMFDB Data and Code Licenses"
550+
b = [("LMFDB Licenses", " ")]
551+
return render_template('license.html', title=t, bread=b)
552+
547553

548554
@app.route("/contact")
549555
def contact():

lmfdb/elliptic_curves/elliptic_curve.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ def make_modcurve_link(label):
466466
short_title="j-invariant", align="center", default=False),
467467
FloatCol("abc_quality", "ec.q.abc_quality", "$abc$ quality", short_title="abc quality", prec=5, default=False),
468468
FloatCol("szpiro_ratio", "ec.q.szpiro_ratio", "Szpiro ratio", prec=5, default=False),
469+
MathCol("intrinsic_torsion", "ec.intrinsic_torsion", "Intrinsic torsion order", align="center", default=False),
469470
MathCol("ainvs", "ec.weierstrass_coeffs", "Weierstrass coefficients", short_title="Weierstrass coeffs", align="left", default=False),
470471
ProcessedCol("equation", "ec.q.minimal_weierstrass_equation", "Weierstrass equation", latex_equation, short_title="Weierstrass equation", align="left", orig="ainvs", download_col="ainvs"),
471472
ProcessedCol("modm_images", "ec.galois_rep", r"mod-$m$ images", lambda v: "<span>" + ", ".join([make_modcurve_link(s) for s in v[:5]] + ([r"$\ldots$"] if len(v) > 5 else [])) + "</span>",
@@ -563,6 +564,7 @@ def elliptic_curve_search(info, query):
563564
parse_floats(info,query,'faltings_height','faltings_height')
564565
parse_floats(info,query,'abc_quality')
565566
parse_floats(info,query,'szpiro_ratio')
567+
parse_ints(info,query,'intrinsic_torsion')
566568
if info.get('reduction'):
567569
if info['reduction'] == 'semistable':
568570
query['semistable'] = True
@@ -1242,7 +1244,8 @@ class ECSearchArray(SearchArray):
12421244
("adelic_genus", "adelic genus", ["adelic_genus", "adelic_level", "adelic_index"]),
12431245
("faltings_height", "Faltings height", ["faltings_height", "conductor", "iso_nlabel", "lmfdb_number"]),
12441246
("abc_quality", "$abc$ quality", ["abc_quality", "conductor", "iso_nlabel", "lmfdb_number"]),
1245-
("szpiro_ratio", "Szpiro ratio", ["szpiro_ratio", "conductor", "iso_nlabel", "lmfdb_number"])]
1247+
("szpiro_ratio", "Szpiro ratio", ["szpiro_ratio", "conductor", "iso_nlabel", "lmfdb_number"]),
1248+
("intrinsic torsion", "Intrinsic torsion order", ["intrinsic_torsion", "conductor", "iso_nlabel", "lmfdb_number"])]
12461249
jump_example = "11.a2"
12471250
jump_egspan = "e.g. 11.a2 or 389.a or 11a1 or 389a or [0,1,1,-2,0] or [-3024, 46224] or y^2 = x^3 + 1"
12481251
jump_prompt = "Label or coefficients"
@@ -1437,6 +1440,12 @@ def __init__(self):
14371440
knowl="ec.q.szpiro_ratio",
14381441
example="8-",
14391442
advanced=True)
1443+
intrinsic_torsion = TextBox(
1444+
name="intrinsic_torsion",
1445+
label="Intrinsic torsion order",
1446+
knowl="ec.intrinsic_torsion",
1447+
example="3",
1448+
advanced=True)
14401449

14411450
manin_constant = TextBox(
14421451
name="manin_constant",
@@ -1460,7 +1469,8 @@ def __init__(self):
14601469
[adelic_level, adelic_index],
14611470
[adelic_genus, faltings_height],
14621471
[abc_quality, szpiro_ratio],
1463-
[count, manin_constant]
1472+
[intrinsic_torsion, manin_constant],
1473+
[count]
14641474
]
14651475

14661476
self.refine_array = [
@@ -1470,4 +1480,5 @@ def __init__(self):
14701480
[sha, sha_primes, regulator, reduction, faltings_height],
14711481
[galois_image, adelic_level, adelic_index, adelic_genus],
14721482
[nonmax_primes, abc_quality, szpiro_ratio, manin_constant],
1483+
[intrinsic_torsion]
14731484
]

lmfdb/elliptic_curves/templates/ec-curve.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,12 @@ <h2> Invariants </h2>
251251
<td>{{ place_code('szpiro_ratio') }}</td>
252252
</tr>
253253

254+
<tr>
255+
<td>{{ KNOWL('ec.intrinsic_torsion', title='Intrinsic torsion order') }}:</td>
256+
<td>$\#E(\mathbb Q)_\text{tors}^\text{is}$</td><td>&nbsp;=&nbsp;</td><td colspan=3>${{ data.intrinsic_torsion }}$</td>
257+
<td>{{ place_code('intrinsic_torsion') }}</td>
258+
</tr>
259+
254260
</table>
255261

256262
<h2> {{ KNOWL('ec.q.bsdconjecture', title='BSD invariants') }}</h2>

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

lmfdb/groups/abstract/templates/character_table.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@
4343
<td></td><td class="right">{{KNOWL('group.conjugacy_class.power_classes',"{} P".format(p))}}</td>
4444
{% for c in ccs %}
4545
{% if loop.index == highlight_i %}
46-
<td class="highlighted">{{ ccs[c['powers'][ploop.index-1]-1].label }}</td>
46+
<td class="highlighted">{{ ccs[c.prime_powers()[ploop.index-1]-1].label }}</td>
4747
{% else %}
48-
<td class="right">{{ ccs[c['powers'][ploop.index-1]-1].label }}</td>
48+
<td class="right">{{ ccs[c.prime_powers()[ploop.index-1]-1].label }}</td>
4949
{% endif %}
5050
{% endfor %}
5151
</tr>

lmfdb/groups/abstract/templates/rational_character_table.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<tr>
2525
<td></td><td>{{KNOWL('group.conjugacy_class.power_classes',"{} P".format(p))}}</td>
2626
{% for c in gp.conjugacy_class_divisions %}
27-
<td>{{ gp.conjugacy_classes[c.classes.0.powers[ploop.index0]-1].division.label }}</td>
27+
<td>{{ gp.conjugacy_classes[c.classes.0.prime_powers()[ploop.index0]-1].division.label }}</td>
2828
{% endfor %}
2929
</tr>
3030
{% endfor %}

lmfdb/groups/abstract/web_groups.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
is_prime,
2525
cartesian_product_iterator,
2626
exists,
27+
euler_phi,
2728
)
2829
from sage.libs.gap.libgap import libgap
2930
from sage.libs.gap.element import GapElement
@@ -3763,6 +3764,14 @@ def force_repr(self, newrep):
37633764
self.representative = newrep
37643765
self.force_repr_elt = True
37653766

3767+
# extract from powers list the ones corresponding to ones dividing the order
3768+
def prime_powers(self):
3769+
plist = [z[0] for z in ZZ(self.group_order).factor()]
3770+
Nphi = self.group_order*euler_phi(self.group_order)
3771+
plist_long = [z[0] for z in ZZ(Nphi).factor()]
3772+
assert len(plist_long) == len(self.powers)
3773+
return [self.powers[plist_long.index(p)] for p in plist]
3774+
37663775
def display_knowl(self, name=None):
37673776
if not name:
37683777
name = self.label

0 commit comments

Comments
 (0)