from collections import defaultdict
def subgroup_conj_classes(G):
"""
Returns [cc_1, cc_2, ... cc_n] : each cc_i is a list containing subgroups of G that belong to the same conjugacy class.
"""
ccs = G._gap_().ConjugacyClassesSubgroups()
return [tuple([G.subgroup(gap_group = H) for H in cc.Elements()]) for cc in ccs]
def are_subgroups(cc1,cc2):
"""
Returns True if some element of cc1 is a subgroup of an element of cc2.
"""
if len(cc1) <= len(cc2):
h2 = cc2[0]
for h1 in cc1:
if h1.is_subgroup(h2):
return True
else:
h1 = cc1[0]
for h2 in cc2:
if h1.is_subgroup(h2):
return True
return False
@interact
def subgroup_class_lattices(Cardinality= 6):
group_list = {Cardinality: {}}
for G_gap in gap.AllSmallGroups(Cardinality):
G = PermutationGroup(list(gap.GeneratorsOfGroup(G_gap.AsPermGroup())))
group_list[Cardinality][G.structure_description()] = str(G.gens())
@interact
def group_select(Group = selector(values = group_list[Cardinality].keys())):
G = PermutationGroup(gap(group_list[Cardinality][Group]))
sub_classes = subgroup_conj_classes(G)
poset = Poset((sub_classes,are_subgroups))
@interact
def display_options(Show = selector(values = ['Conjugacy classes of subgroups', 'All subgroups']),
Vertex_Colors = selector(values = ['Normal (Green), Commutator (Pink), Center (Blue)','None'], label = 'Vertex colors'),
Edge_Colors = selector(values = ['Is normal subgroup of','None',], label = 'Edge colors'),
Edge_Labels = selector(values =['Contains','Contained by', 'Both','None',], label = 'Edge labels')):
if Show == 'All subgroups':
subgroups = [h for cc in sub_classes for h in cc ]
covers = []
for cc1,cc2 in poset.cover_relations():
for h1 in cc1:
for h2 in cc2:
if h1.is_subgroup(h2):
covers.append([h1,h2])
full_poset = Poset((subgroups,covers),cover_relations = True)
if Vertex_Colors is not 'None':
vertex_colors = defaultdict(list)
for h in subgroups:
if not h.is_normal():
vertex_colors['white'].append(h)
else:
if h == G.subgroup(G.commutator().gens()):
vertex_colors['pink'].append(h)
elif h == G.center():
vertex_colors['lightblue'].append(h)
else:
vertex_colors['lightgreen'].append(h)
else:
vertex_colors = 'white'
if Edge_Colors is not 'None':
edge_colors = {'#60D6D6':[],'lightgray':[]}
for h,k in full_poset.cover_relations():
if h.is_normal(k):
edge_colors['#60D6D6'].append((h,k))
else:
edge_colors['lightgray'].append((h,k))
else:
edge_colors = None
vertex_labels = {h : h.structure_description() for h in subgroups}
rank_function = full_poset.rank_function()
if rank_function:
heights = defaultdict(list)
for i in full_poset:
heights[rank_function(i)].append(i)
else:
heights = None
graph = full_poset.hasse_diagram()
gplot = graph.graphplot(vertex_labels=None,layout='acyclic',vertex_colors = vertex_colors, edge_colors = edge_colors, vertex_size = 1000)
gplot._plot_components['vertex_labels'] = []
for v in gplot._nodelist:
gplot._plot_components['vertex_labels'].append(text(vertex_labels[v],
gplot._pos[v], rgbcolor=(0,0,0), zorder=8))
gplot.show(figsize=(10,10))
else:
if Vertex_Colors is not 'None':
vertex_colors = defaultdict(list)
for cc in sub_classes:
if not cc[0].is_normal():
vertex_colors['white'].append(cc)
else:
if cc[0] == G.subgroup(G.commutator().gens()):
vertex_colors['pink'].append(cc)
elif cc[0] == G.center():
vertex_colors['lightblue'].append(cc)
else:
vertex_colors['lightgreen'].append(cc)
else:
vertex_colors = 'white'
if Edge_Colors is not 'None':
edge_colors = {'#60D6D6':[],'lightgray':[]}
for cc1,cc2 in poset.cover_relations():
h1 = cc1[0]
is_normal = False
for h2 in cc2:
if h1.is_subgroup(h2) and h1.is_normal(h2):
edge_colors['#60D6D6'].append((cc1,cc2))
is_normal = True
break
if not is_normal:
edge_colors['lightgray'].append((cc1,cc2))
else:
edge_colors = None
vertex_labels = {cc : cc[0].structure_description() for cc in sub_classes}
rank_function = poset.rank_function()
if rank_function:
heights = defaultdict(list)
for i in poset:
heights[rank_function(i)].append(i)
else:
heights = None
graph = poset.hasse_diagram()
label_edges = True
if Edge_Labels == 'Contained by':
for cc1,cc2,label in graph.edges():
count = sum([cc1[0].is_subgroup(h2) for h2 in cc2])
if count == 1:
graph.set_edge_label(cc1,cc2,'')
else:
graph.set_edge_label(cc1,cc2,' ' + str(count))
elif Edge_Labels == 'Contains':
for cc1,cc2,label in graph.edges():
count = sum([h1.is_subgroup(cc2[0]) for h1 in cc1])
if count == 1:
graph.set_edge_label(cc1,cc2,'')
else:
graph.set_edge_label(cc1,cc2,' ' + str(count))
elif Edge_Labels == 'Both':
for cc1,cc2,label in graph.edges():
count1 = sum([cc1[0].is_subgroup(h2) for h2 in cc2])
count2 = sum([h1.is_subgroup(cc2[0]) for h1 in cc1])
if count1 == 1 and count2 == 1:
graph.set_edge_label(cc1,cc2,'')
else:
graph.set_edge_label(cc1,cc2,' ' + '{},{}'.format(count1,count2))
else:
label_edges = False
gplot = graph.graphplot(vertex_labels=None,layout='acyclic',vertex_colors = vertex_colors, edge_colors = edge_colors, edge_labels = label_edges, vertex_size = 1000)
gplot._plot_components['vertex_labels'] = []
for v in gplot._nodelist:
gplot._plot_components['vertex_labels'].append(text(vertex_labels[v],
gplot._pos[v], rgbcolor=(0,0,0), zorder=8))
gplot.show(figsize=(7,7))