diff --git a/lmfdb/groups/abstract/main.py b/lmfdb/groups/abstract/main.py
index a32bc03cf7..76fab68c4b 100644
--- a/lmfdb/groups/abstract/main.py
+++ b/lmfdb/groups/abstract/main.py
@@ -766,10 +766,9 @@ def auto_gens(label):
return render_template(
"auto_gens_page.html",
gp=gp,
- title="Generators of automorphism group for %s" % label,
- bread=get_bread([("Automorphism group generators", " ")]),
- learnmore=learnmore_list(),
- )
+ title="Generators of automorphism group for $%s$" % gp.tex_name,
+ bread=get_bread([(label, url_for(".by_label", label=label)), ("Automorphism group generators", " ")]),
+ )
@abstract_page.route("/sub/")
@@ -791,9 +790,8 @@ def char_table(label):
return render_template(
"character_table_page.html",
gp=gp,
- title="Character table for %s" % label,
- bread=get_bread([("Character table", " ")]),
- learnmore=learnmore_list(),
+ title="Character table for $%s$" % gp.tex_name,
+ bread=get_bread([(label, url_for(".by_label", label=label)), ("Character table", " ")]),
)
@@ -807,9 +805,8 @@ def Qchar_table(label):
return render_template(
"rational_character_table_page.html",
gp=gp,
- title="Rational character table for %s" % label,
- bread=get_bread([("Rational character table", " ")]),
- learnmore=learnmore_list(),
+ title="Rational character table for $%s$" % gp.tex_name,
+ bread=get_bread([(label, url_for(".by_label", label=label)), ("Rational character table", " ")]),
)
def _subgroup_diagram(label, title, only, style):
@@ -916,6 +913,13 @@ def show_factor(n):
return "$0$"
return f"${latex(ZZ(n).factor())}$"
+#for irrQ_degree and irrC_degree gives negative value as "-"
+def remove_negatives(n):
+ if n < 1:
+ return "-"
+ return n
+
+
def get_url(label):
return url_for(".by_label", label=label)
@@ -988,8 +992,8 @@ def group_postprocess(res, info, query):
ProcessedCol("outer_order", "group.outer_aut", r"$\card{\mathrm{Out}(G)}$", show_factor, align="center", short_title="outer automorphisms", default=False),
MathCol("transitive_degree", "group.transitive_degree", "Tr. deg", short_title="transitive degree", default=False),
MathCol("permutation_degree", "group.permutation_degree", "Perm. deg", short_title="permutation degree", default=False),
- MathCol("irrC_degree", "group.min_complex_irrep_deg", r"$\C$-irrep deg", short_title=r"$\C$-irrep degree", default=False),
- MathCol("irrQ_degree", "group.min_rational_irrep_deg", r"$\Q$-irrep deg", short_title=r"$\Q$-irrep degree", default=False),
+ ProcessedCol("irrC_degree", "group.min_complex_irrep_deg", r"$\C$-irrep deg", remove_negatives, short_title=r"$\C$-irrep degree", default=False, align="center"),
+ ProcessedCol("irrQ_degree", "group.min_rational_irrep_deg", r"$\Q$-irrep deg", remove_negatives, short_title=r"$\Q$-irrep degree", default=False, align="center"),
MultiProcessedCol("type", "group.type", "Type - length",
["abelian", "nilpotent", "solvable", "smith_abelian_invariants", "nilpotency_class", "derived_length", "composition_length"],
show_type,
diff --git a/lmfdb/groups/abstract/templates/abstract-show-group.html b/lmfdb/groups/abstract/templates/abstract-show-group.html
index 2d0fbedc30..6aa1a9440e 100644
--- a/lmfdb/groups/abstract/templates/abstract-show-group.html
+++ b/lmfdb/groups/abstract/templates/abstract-show-group.html
@@ -162,7 +162,7 @@ Minimal Presentations
{{KNOWL('group.rank', 'Rank')}}:
{% if gp.rank %}
- ${{gp.rank}}$
+ {{gp.rank}}
{% else %}
not computed
{% endif %}
@@ -170,7 +170,7 @@ Minimal Presentations
{{KNOWL('group.generators', 'Inequivalent ' + gp.gen_noun())}}:
{% if gp.eulerian_function != None %}
- ${{gp.eulerian_function}}$
+ {{gp.eulerian_function}}
{% else %} not computed {% endif %}
@@ -309,8 +309,8 @@ Homology
{{KNOWL('group.commutator_length', 'Commutator length')}}:
{% if gp.commutator_count %}
- ${{gp.commutator_count}}$
- {% elif gp.abelian %} $0$
+ {{gp.commutator_count}}
+ {% elif gp.abelian %} 0
{% else %} not computed {% endif %}
{% endif %}
@@ -584,6 +584,7 @@ Character theory
+
{% if not gp.rational_characters and gp.number_conjugacy_classes == None %}
The character tables for this group have not been computed.
@@ -592,6 +593,17 @@ Character theory
{{KNOWL('group.complex_character_table','Complex character table')}}
+ {% if gp.number_divisions == gp.number_conjugacy_classes %}
+
+
+ Every character has rational values, so the {{KNOWL('group.complex_character_table','complex character table')}} is the same as the rational character table below.
+
+
+
+ {% else %}
+
+
+
{% if gp.number_conjugacy_classes == None %}
The complex character table for this group is not computed.
@@ -626,16 +638,9 @@ {{KNOWL('group.complex_character_table','Complex character table')}}
{% endif %}
- {% if gp.number_divisions == gp.number_conjugacy_classes %}
-
-
- Every character has rational values, so the {{KNOWL('group.rational_character_table','rational character table')}} is the same as the complex character table.
-
- {% else %}
-
-
+{% endif %}
{{KNOWL('group.rational_character_table','Rational character table')}}
@@ -656,7 +661,6 @@ {{KNOWL('group.rational_character_table','Rational character table')}}
{% endif %}
{% endif %}
-{% endif %}
{% endif %} {# gp.live() #}
{% endblock %}
diff --git a/lmfdb/groups/abstract/templates/auto_gens_page.html b/lmfdb/groups/abstract/templates/auto_gens_page.html
index 36fc052ffa..867db6c4a7 100644
--- a/lmfdb/groups/abstract/templates/auto_gens_page.html
+++ b/lmfdb/groups/abstract/templates/auto_gens_page.html
@@ -1,9 +1,9 @@
-{% extends "base.html" %}
+{% extends "homepage.html" %}
+
+{% block content %}
-{% block body %}
-
Each row represents an {{KNOWL('group.automorphism', 'automorphism')}} given by its image on a set of {{KNOWL('group.generators','generators')}} of the group (listed as the headers of the columns).
@@ -33,6 +33,16 @@
+{% endblock %}
+{# Hack to remove the sidebar and move main content over #}
+{% block sidebar %}
+
{% endblock %}
diff --git a/lmfdb/groups/abstract/templates/character_table_page.html b/lmfdb/groups/abstract/templates/character_table_page.html
index 2e476d32fb..3523509eee 100644
--- a/lmfdb/groups/abstract/templates/character_table_page.html
+++ b/lmfdb/groups/abstract/templates/character_table_page.html
@@ -1,7 +1,18 @@
-{% extends "base.html" %}
+{% extends "homepage.html" %}
-{% block body %}
+{% block content %}
{% include 'character_table.html' %}
{% endblock %}
+
+{# Hack to remove the sidebar and move main content over #}
+{% block sidebar %}
+
+{% endblock %}
diff --git a/lmfdb/groups/abstract/templates/rational_character_table.html b/lmfdb/groups/abstract/templates/rational_character_table.html
index 077615f176..3477fb92e6 100644
--- a/lmfdb/groups/abstract/templates/rational_character_table.html
+++ b/lmfdb/groups/abstract/templates/rational_character_table.html
@@ -22,9 +22,12 @@
{% endfor %}
+ {% if gp.has_nontrivial_schur_character %}
+ {{KNOWL('group.representation.schur_index', 'Schur')}}
+ {% endif %}
{% for chtr in gp.rational_characters %}
- {{ chtr.display_knowl() | safe }}
+ {{ chtr.display_knowl() | safe }} {% if gp.has_nontrivial_schur_character %} {% if chtr.schur_index != 1 %} {{chtr.schur_index}} {% endif %} {% endif %}
{% for c in gp.conjugacy_class_divisions %}
${{ chtr.qvalues[c.classes.0.counter - 1] }}$
{% endfor %}
diff --git a/lmfdb/groups/abstract/templates/rational_character_table_page.html b/lmfdb/groups/abstract/templates/rational_character_table_page.html
index 8da49606a0..fea2c5afe4 100644
--- a/lmfdb/groups/abstract/templates/rational_character_table_page.html
+++ b/lmfdb/groups/abstract/templates/rational_character_table_page.html
@@ -1,7 +1,18 @@
-{% extends "base.html" %}
+{% extends "homepage.html" %}
-{% block body %}
+{% block content %}
{% include 'rational_character_table.html' %}
{% endblock %}
+
+{# Hack to remove the sidebar and move main content over #}
+{% block sidebar %}
+
+{% endblock %}
diff --git a/lmfdb/groups/abstract/verify.py b/lmfdb/groups/abstract/verify.py
new file mode 100644
index 0000000000..95fa118916
--- /dev/null
+++ b/lmfdb/groups/abstract/verify.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+#from lmfdb.groups.abstract import verify
+#TO DO: subgroups, larger order + 1024
+
+
+from lmfdb import db
+from sage.all import libgap
+
+def test_small_gps(sample_gp):
+ print(sample_gp['label'])
+
+ if sample_gp['order'] != 1024: #1024 doesn't have standard labels, need to construct another way
+ #create corresponding GAP group
+ id_nums = sample_gp['label'].split(".")
+ G = libgap.SmallGroup(int(id_nums[0]),int(id_nums[1]))
+ #Confirm group order matches
+ print("Group orders match: " + str(sample_gp['order'] == libgap.Order(G)))
+ #Confirm IsAbelian returns same value
+ print("Groups abelian-ness match: " + str((sample_gp['abelian']) == bool(libgap.IsAbelian(G))))
+ #Confirm IsSimple returns same value
+ print("Groups simple-ness match: " + str((sample_gp['simple']) == bool(libgap.IsSimple(G))))
+ #Confirm IsPerfect returns same value
+ print("Groups perfect-ness match: " + str((sample_gp['perfect']) == bool(libgap.IsPerfect(G))))
+ #Confirm IsMonomial returns same value
+ print("Groups monomial-ness match: " + str((sample_gp['monomial']) == bool(libgap.IsMonomial(G))))
+
+ #Confirm number of non-conjugate subgroups (if known in database)
+ if sample_gp['number_subgroup_classes']:
+ SubLat = libgap.LatticeSubgroups(G)
+ Cons = libgap.ConjugacyClassesSubgroups(SubLat)
+ print ("Number of subgroup classes match: " + str(libgap.Size(Cons) == sample_gp['number_subgroup_classes']))
+ if sample_gp['number_normal_subgroups']:
+ NormLat = libgap.NormalSubgroups(G)
+ print ("Number of normal subgroups match: " + str(libgap.Size(NormLat) == sample_gp['number_normal_subgroups']))
+
+
+ # check if minimal permutation degrees match
+ if sample_gp['permutation_degree']:
+ minpermdeg_gap = libgap.MinimalFaithfulPermutationDegree(G)
+ print("Minimal permutation degrees match: " + str(minpermdeg_gap == sample_gp['permutation_degree']))
+
+
+ # check order stats
+ stupid_str = 'Set(ConjugacyClasses(SmallGroup(' + id_nums[0]+ ',' + id_nums[1] + ")), z->Order(Representative(z))) "
+ ords = libgap.eval(stupid_str)
+
+ ordsLMFDB = []
+ ords_list = sample_gp['order_stats']
+ for i in range(len(ords_list)):
+ ordsLMFDB.append(ords_list[i][0])
+ print("Order set matches: " + str(ords == ordsLMFDB))
+ #print(ords,ordsLMFDB)
+
+ #check degrees
+ irr_stats = sample_gp['irrep_stats']
+ degLMFDB = []
+ for i in range(len(irr_stats)):
+ for j in range(irr_stats[i][1]):
+ degLMFDB.append(irr_stats[i][0])
+ stupid_str_2 = 'List(Irr(SmallGroup(' + id_nums[0] + ',' + id_nums[1]+ ')), z -> z[1])'
+ degs = libgap.eval(stupid_str_2)
+
+ print("Degrees of characters match: " + str(degs == degLMFDB))
+ #print(degs,degLMFDB)
+
+
+#pick random group of order <= 2000 from DB
+
+for i in range(10):
+ x = db.gps_groups_test.random({'order': {"$lte" :2000}})
+ sample_gp =db.gps_groups_test.lucky({'label': x})
+ test_small_gps(sample_gp)
diff --git a/lmfdb/groups/abstract/web_groups.py b/lmfdb/groups/abstract/web_groups.py
index b094480090..c6b693d904 100644
--- a/lmfdb/groups/abstract/web_groups.py
+++ b/lmfdb/groups/abstract/web_groups.py
@@ -842,7 +842,7 @@ def subgp_paragraph(self):
elif self.number_characteristic_subgroups is None:
return """There are """ +str(self.number_normal_subgroups) + " normal subgroups. "+normalcolor
else:
- ret_str = """ There are """ +str(self.number_normal_subgroups) + """ normal subgroups """
+ ret_str = """ There are """ +str(self.number_normal_subgroups) + """ normal subgroups """
if self.number_characteristic_subgroups < self.number_normal_subgroups:
ret_str = ret_str + """ (""" + str(self.number_characteristic_subgroups) + " characteristic ).
"+charcolor+" "+normalcolor
else:
@@ -1339,6 +1339,10 @@ def rational_characters(self):
]
return sorted(chrs, key=lambda x: x.counter)
+ @lazy_attribute
+ def has_nontrivial_schur_character(self):
+ return any(chtr.schur_index > 1 for chtr in self.rational_characters)
+
@lazy_attribute
def maximal_subgroup_of(self):
# Could show up multiple times as non-conjugate maximal subgroups in the same ambient group