def random_even_arithgroup(index, nu2_max=None, nu3_max=None): r""" Return a random even arithmetic subgroup EXAMPLES:: sage: import sage.modular.arithgroup.tests as tests sage: G = tests.random_even_arithgroup(30); G # random Arithmetic subgroup of index 30 sage: G.is_even() True """ from sage.groups.perm_gps.permgroup import PermutationGroup test = False if nu2_max is None: nu2_max = index // 5 elif nu2_max == 0: assert index % 2 == 0 if nu3_max is None: nu3_max = index // 7 elif nu3_max == 0: assert index % 3 == 0 while not test: nu2 = prandom.randint(0, nu2_max) nu2 = index % 2 + nu2 * 2 nu3 = prandom.randint(0, nu3_max) nu3 = index % 3 + nu3 * 3 l = list(range(1, index + 1)) prandom.shuffle(l) S2 = [] for i in range(nu2): S2.append((l[i], )) for i in range(nu2, index, 2): S2.append((l[i], l[i + 1])) prandom.shuffle(l) S3 = [] for i in range(nu3): S3.append((l[i], )) for i in range(nu3, index, 3): S3.append((l[i], l[i + 1], l[i + 2])) G = PermutationGroup([S2, S3]) test = G.is_transitive() return ArithmeticSubgroup_Permutation(S2=S2, S3=S3)
def random_even_arithgroup(index,nu2_max=None,nu3_max=None): r""" Return a random even arithmetic subgroup EXAMPLES:: sage: import sage.modular.arithgroup.tests as tests sage: G = tests.random_even_arithgroup(30); G # random Arithmetic subgroup of index 30 sage: G.is_even() True """ from sage.groups.perm_gps.permgroup import PermutationGroup test = False if nu2_max is None: nu2_max = index//5 elif nu2_max == 0: assert index%2 == 0 if nu3_max is None: nu3_max = index//7 elif nu3_max == 0: assert index%3 == 0 while not test: nu2 = prandom.randint(0,nu2_max) nu2 = index%2 + nu2*2 nu3 = prandom.randint(0,nu3_max) nu3 = index%3 + nu3*3 l = range(1,index+1) prandom.shuffle(l) S2 = [] for i in xrange(nu2): S2.append((l[i],)) for i in xrange(nu2,index,2): S2.append((l[i],l[i+1])) prandom.shuffle(l) S3 = [] for i in xrange(nu3): S3.append((l[i],)) for i in xrange(nu3,index,3): S3.append((l[i],l[i+1],l[i+2])) G = PermutationGroup([S2,S3]) test = G.is_transitive() return ArithmeticSubgroup_Permutation(S2=S2,S3=S3)
def automorphism_group(self): r""" Returns the automorphism group. For more information on the automorphism group of a hypergraph, see the :wikipedia:`Hypergraph`. EXAMPLE:: sage: H = designs.steiner_triple_system(7).blocks() sage: H = Hypergraph(H) sage: g = H.automorphism_group(); g Permutation Group with generators [(2,4)(5,6), (2,5)(4,6), (1,2)(3,4), (1,3)(5,6), (0,1)(2,5)] sage: g.is_isomorphic(groups.permutation.PGL(3,2)) True """ from sage.groups.perm_gps.permgroup import PermutationGroup G, part = self.to_bipartite_graph(with_partition=True) domain = part[0] ag = G.automorphism_group(partition=part) gens = [[tuple(c) for c in g.cycle_tuples() if c[0] in domain] for g in ag.gens()] return PermutationGroup(gens=gens, domain=domain)
def automorphism_group(self): """ Returns the subgroup of the automorphism group of the incidence graph which respects the P B partition. It is (isomorphic to) the automorphism group of the block design, although the degrees differ. EXAMPLES:: sage: P = designs.DesarguesianProjectivePlaneDesign(2); P Incidence structure with 7 points and 7 blocks sage: G = P.automorphism_group() sage: G.is_isomorphic(PGL(3,2)) True sage: G Permutation Group with generators [(2,3)(4,5), (2,4)(3,5), (1,2)(4,6), (0,1)(4,5)] A non self-dual example:: sage: from sage.combinat.designs.incidence_structures import IncidenceStructure sage: IS = IncidenceStructure(range(4), [[0,1,2,3],[1,2,3]]) sage: IS.automorphism_group().cardinality() 6 sage: IS.dual_design().automorphism_group().cardinality() 1 """ from sage.groups.perm_gps.partn_ref.refinement_matrices import MatrixStruct from sage.groups.perm_gps.permgroup import PermutationGroup from sage.groups.perm_gps.permgroup_named import SymmetricGroup M1 = self.incidence_matrix().transpose() M2 = MatrixStruct(M1) M2.run() gens = M2.automorphism_group()[0] return PermutationGroup(gens, domain=range(self.v))
def automorphism_group(self): """ Returns the subgroup of the automorphism group of the incidence graph which respects the P B partition. This is (isomorphic to) the automorphism group of the block design, although the degrees differ. EXAMPLES:: sage: from sage.combinat.designs.block_design import BlockDesign sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]]) sage: G = BD.automorphism_group(); G Permutation Group with generators [(4,5)(6,7), (4,6)(5,7), (2,3)(6,7), (2,4)(3,5), (1,2)(5,6)] sage: BD = BlockDesign(4,[[0],[0,1],[1,2],[3,3]],test=False) sage: G = BD.automorphism_group(); G Permutation Group with generators [()] sage: BD = BlockDesign(7,[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]]) sage: G = BD.automorphism_group(); G Permutation Group with generators [(4,5)(6,7), (4,6)(5,7), (2,3)(6,7), (2,4)(3,5), (1,2)(5,6)] """ from sage.groups.perm_gps.partn_ref.refinement_matrices import MatrixStruct from sage.groups.perm_gps.permgroup import PermutationGroup from sage.groups.perm_gps.permgroup_named import SymmetricGroup M1 = self.incidence_matrix() M2 = MatrixStruct(M1) M2.run() gens = M2.automorphism_group()[0] v = len(self.points()) G = SymmetricGroup(v) gns = [] for g in gens: L = [j+1 for j in g] gns.append(G(L)) return PermutationGroup(gns)
def K3Surface(self): """ Returns a minimal triangulation of the K3 surface. This is a pure simplicial complex of dimension 4 with 16 vertices and 288 facets. It was constructed by Casella and Kühnel in [CK2001]_. The construction here uses the labeling from Spreer and Kühnel [SK2011]_. REFERENCES: .. [CK2001] M. Casella and W. Kühnel, "A triangulated K3 surface with the minimum number of vertices", Topology 40 (2001), 753–772. .. [SK2011] J. Spreer and W. Kühnel, "Combinatorial properties of the K3 surface: Simplicial blowups and slicings", Experimental Mathematics, Volume 20, Issue 2, 2011. EXAMPLES:: sage: K3=simplicial_complexes.K3Surface() ; K3 Simplicial complex with 16 vertices and 288 facets sage: K3.f_vector() [1, 16, 120, 560, 720, 288] """ from sage.groups.perm_gps.permgroup import PermutationGroup G = PermutationGroup([[ (1, 3, 8, 4, 9, 16, 15, 2, 14, 12, 6, 7, 13, 5, 10) ], [(1, 11, 16), (2, 10, 14), (3, 12, 13), (4, 9, 15), (5, 7, 8)]]) return SimplicialComplex( [tuple([g(i) for i in (1, 2, 3, 8, 12)]) for g in G] + [tuple([g(i) for i in (1, 2, 5, 8, 14)]) for g in G])
def image(self, J): """ J must be a subgroup of G. Computes the subgroup of H which is the image of J. EXAMPLES:: sage: G = CyclicPermutationGroup(4) sage: H = DihedralGroup(4) sage: g = G([(1,2,3,4)]) sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens())) sage: phi.image(G) Subgroup generated by [(1,2,3,4)] of (Dihedral group of order 8 as a permutation group) sage: phi.image(g) (1,2,3,4) :: sage: G = PSL(2,7) sage: D = G.direct_product(G) sage: H = D[0] sage: pr1 = D[3] sage: pr1.image(G) Subgroup generated by [(3,7,5)(4,8,6), (1,2,6)(3,4,8)] of (The projective special linear group of degree 2 over Finite Field of size 7) sage: G.is_isomorphic(pr1.image(G)) True """ H = self.codomain() if J in self.domain(): J = PermutationGroup([J]) G = self._gap_().Image(J) return H.subgroup(gap_group=G).gens()[0] else: G = self._gap_().Image(J) return H.subgroup(gap_group=G)
def permutation_group(self): r""" Return the permutation group attached to this group. EXAMPLES:: sage: G = AdditiveAbelianGroup([2, 3]) sage: G.permutation_group() Permutation Group with generators [(3,4,5), (1,2)] TESTS: Check that :trac:`25692` is fixed:: sage: G = AdditiveAbelianGroup([0]) sage: G.permutation_group() Traceback (most recent call last): ... TypeError: Additive Abelian group must be finite """ # GAP does not support infinite permutation groups if not self.is_finite(): raise TypeError('Additive Abelian group must be finite') from sage.groups.perm_gps.permgroup import PermutationGroup s = 'Image(IsomorphismPermGroup(AbelianGroup(%s)))' % (list( self.invariants()), ) return PermutationGroup(gap_group=s)
def as_permutation_group(self, limit=4096000): """ Return an isomorphic permutation group. The generators of the resulting group correspond to the images by the isomorphism of the generators of the given group. INPUT: - ``limit`` -- integer (default: 4096000). The maximal number of cosets before the computation is aborted. OUTPUT: A Sage :func:`~sage.groups.perm_gps.permgroup.PermutationGroup`. If the number of cosets exceeds the given ``limit``, a ``ValueError`` is returned. EXAMPLES:: sage: G.<a,b> = FreeGroup() sage: H = G / (a^2, b^3, a*b*~a*~b) sage: H.as_permutation_group() Permutation Group with generators [(1,2)(3,5)(4,6), (1,3,4)(2,5,6)] sage: G.<a,b> = FreeGroup() sage: H = G / [a^3*b] sage: H.as_permutation_group(limit=1000) Traceback (most recent call last): ... ValueError: Coset enumeration exceeded limit, is the group finite? ALGORITHM: Uses GAP's coset enumeration on the trivial subgroup. .. WARNING:: This is in general not a decidable problem (in fact, it is not even posible to check if the group is finite or not). If the group is infinite, or too big, you should be prepared for a long computation that consumes all the memory without finishing if you do not set a sensible ``limit``. """ with libgap.global_context('CosetTableDefaultMaxLimit', limit): try: trivial_subgroup = self.gap().TrivialSubgroup() coset_table = self.gap().CosetTable(trivial_subgroup).sage() except ValueError: raise ValueError( 'Coset enumeration exceeded limit, is the group finite?') from sage.combinat.permutation import Permutation from sage.groups.perm_gps.permgroup import PermutationGroup return PermutationGroup([ Permutation(coset_table[2 * i]) for i in range(len(coset_table) / 2) ])
def _get_random_ribbon_graph(self): r""" Return a random ribbon graph with right parameters. """ n = random.randint(self.min_num_seps, self.max_num_seps) S = SymmetricGroup(2 * n) e = S([(2 * i + 1, 2 * i + 2) for i in range(n)]) f = S.random_element() P = PermutationGroup([e, f]) while not P.is_transitive(): f = S.random_element() P = PermutationGroup([e, f]) return RibbonGraph(edges=[e(i + 1) - 1 for i in range(2 * n)], faces=[f(i + 1) - 1 for i in range(2 * n)])
def __init__(self): U = "( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19)" ## U = top L = "( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35)" ## L = left F = "(17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11)" ## F = front R = "(25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24)" ## R = right B = "(33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27)" ## B = back or rear D = "(41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)" ## D = down or bottom self.__gens = [B, D, F, L, R, U] self._group = PermutationGroup([B, D, F, L, R, U], canonicalize=False)
def _get_random_ribbon_graph(self): r""" Return a random ribbon graph with right parameters. """ n = random.randint(self.min_num_seps,self.max_num_seps) S = SymmetricGroup(2*n) e = S([(2*i+1,2*i+2) for i in xrange(n)]) f = S.random_element() P = PermutationGroup([e,f]) while not P.is_transitive(): f = S.random_element() P = PermutationGroup([e,f]) return RibbonGraph( edges=[e(i+1)-1 for i in xrange(2*n)], faces=[f(i+1)-1 for i in xrange(2*n)])
def monodromy(self): r""" Return the monodromy group of the pillowcase cover. The monodromy group of an origami is the group generated by the permutations `g_i` for `i` in 0,1,2,3. """ from sage.groups.perm_gps.permgroup import PermutationGroup return PermutationGroup(self.g())
def permutation_group(self): r""" Return a permutation group giving the action on the roots of a defining polynomial. This is the regular representation for the abelian group, which is not necessarily the smallest degree permutation representation. EXAMPLES:: sage: GF(3^10).galois_group().permutation_group() Permutation Group with generators [(1,2,3,4,5,6,7,8,9,10)] """ return PermutationGroup( gap_group=self._gap_().RegularActionHomomorphism().Image())
def permutation_group(self): r""" Return the permutation group attached to this group. EXAMPLE:: sage: G = AdditiveAbelianGroup([2, 3]) sage: G.permutation_group() Permutation Group with generators [(3,4,5), (1,2)] """ from sage.groups.perm_gps.permgroup import PermutationGroup s = 'Image(IsomorphismPermGroup(AbelianGroup(%s)))'%(list(self.invariants()),) return PermutationGroup(gap_group=s)
def automorphism_group(self): r""" Return the subgroup of the automorphism group of the incidence graph which respects the P B partition. It is (isomorphic to) the automorphism group of the block design, although the degrees differ. EXAMPLES:: sage: P = designs.DesarguesianProjectivePlaneDesign(2); P Incidence structure with 7 points and 7 blocks sage: G = P.automorphism_group() sage: G.is_isomorphic(PGL(3,2)) True sage: G Permutation Group with generators [(2,3)(4,5), (2,4)(3,5), (1,2)(4,6), (0,1)(4,5)] A non self-dual example:: sage: IS = designs.IncidenceStructure(range(4), [[0,1,2,3],[1,2,3]]) sage: IS.automorphism_group().cardinality() 6 sage: IS.dual().automorphism_group().cardinality() 1 Examples with non-integer points:: sage: I = designs.IncidenceStructure('abc', ('ab','ac','bc')) sage: I.automorphism_group() Permutation Group with generators [('b','c'), ('a','b')] sage: designs.IncidenceStructure([[(1,2),(3,4)]]).automorphism_group() Permutation Group with generators [((1,2),(3,4))] """ from sage.groups.perm_gps.partn_ref.refinement_matrices import MatrixStruct from sage.groups.perm_gps.permgroup import PermutationGroup from sage.groups.perm_gps.permgroup_element import standardize_generator from sage.groups.perm_gps.permgroup_named import SymmetricGroup M1 = self.incidence_matrix().transpose() M2 = MatrixStruct(M1) M2.run() gens = M2.automorphism_group()[0] gens = [standardize_generator([x + 1 for x in g]) for g in gens] if self._point_to_index: gens = [[ tuple([self._points[i - 1] for i in cycle]) for cycle in g ] for g in gens] else: gens = [[tuple([i - 1 for i in cycle]) for cycle in g] for g in gens] return PermutationGroup(gens, domain=self._points)
def galois_action_on_embeddings(G_K): K = G_K.number_field() Kgal = G_K.splitting_field() embeddings = K.embeddings(Kgal) # first a shortcut in the case where G_K is normal in S_d since then it doesn't # matter for our application since we only care about the image # of the galois group in S_d d = K.absolute_degree() G_K_roots = TransitiveGroup(d, G_K.transitive_number()) if G_K_roots.is_normal(SymmetricGroup(d)): id_G_K = G_K.Hom(G_K).identity() return G_K, id_G_K, id_G_K, Kgal, embeddings # now for the actual computation permutations = [] for g in G_K.gens(): phi = g.as_hom() g_perm = Permutation( [embeddings.index(phi * emb) + 1 for emb in embeddings]).inverse() permutations.append(g_perm) G_K_emb = PermutationGroup(permutations, canonicalize=False) to_emb = G_K.hom(G_K_emb.gens()) from_emb = G_K_emb.hom(G_K.gens()) return G_K_emb, to_emb, from_emb, Kgal, embeddings
def image(self, J): """ J must be a subgroup of G. Computes the subgroup of H which is the image of J. EXAMPLES:: sage: G = CyclicPermutationGroup(4) sage: H = DihedralGroup(4) sage: g = G([(1,2,3,4)]) sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens())) sage: phi.image(G) Subgroup generated by [(1,2,3,4)] of (Dihedral group of order 8 as a permutation group) sage: phi.image(g) (1,2,3,4) :: sage: G = PSL(2,7) sage: D = G.direct_product(G) sage: H = D[0] sage: pr1 = D[3] sage: pr1.image(G) Subgroup generated by [(3,7,5)(4,8,6), (1,2,6)(3,4,8)] of (The projective special linear group of degree 2 over Finite Field of size 7) sage: G.is_isomorphic(pr1.image(G)) True Check that :trac:`28324` is fixed:: sage: R.<x> = QQ[] sage: f = x^4 + x^2 - 3 sage: L.<a> = f.splitting_field() sage: G = L.galois_group() sage: D4 = DihedralGroup(4) sage: h = D4.isomorphism_to(G) sage: h.image(D4).is_isomorphic(G) True sage: all(h.image(g) in G for g in D4.gens()) True """ H = self.codomain() if J in self.domain(): J = PermutationGroup([J]) G = self._gap_().Image(J) return H.subgroup(gap_group=G).gens()[0] else: G = self._gap_().Image(J) return H.subgroup(gap_group=G)
def permutation_group(self): r""" Return the permutation group isomorphic to this abelian group. If the invariants are `q_1, \ldots, q_n` then the generators of the permutation will be of order `q_1, \ldots, q_n`, respectively. EXAMPLES:: sage: G = AbelianGroup(2,[2,3]); G Multiplicative Abelian Group isomorphic to C2 x C3 sage: G.permutation_group() Permutation Group with generators [(1,2,3)(4,5,6), (1,4)(2,5)(3,6)] """ from sage.groups.perm_gps.permgroup import PermutationGroup s = 'Image(IsomorphismPermGroup(%s))' % self._gap_init_() return PermutationGroup(gap_group=s)
def monodromy(self): r""" Return the monodromy of this covering. That it to say the permutation group generated by the action of the fundamental group. EXAMPLES:: sage: from surface_dynamics.all import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2,3)', '(1,3,2)', '']).monodromy() Permutation Group with generators [(1,2,3), (1,3,2), ()] sage: p.cover(['(1,2)', '(1,3)', '']).monodromy() Permutation Group with generators [(1,2), (1,3), ()] """ from sage.groups.perm_gps.permgroup import PermutationGroup return PermutationGroup([self.covering_data(a) for a in self._base.letters()], canonicalize=False)
def automorphism_group(self): r""" Return the Deck group of the cover. EXAMPLES:: sage: from surface_dynamics.all import * sage: p = iet.GeneralizedPermutation('a a b', 'b c c') sage: p.cover(['(1,2,3)', '(1,3,2)', '']).automorphism_group() Permutation Group with generators [(1,2,3), (1,3,2)] sage: p.cover(['(1,2)', '(1,3)', '']).automorphism_group() Permutation Group with generators [()] """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup from sage.groups.perm_gps.permgroup import PermutationGroup Sd = SymmetricGroup(self._degree_cover) G = libgap.Subgroup(Sd, [self.covering_data(a) for a in self._base.letters()]) C = libgap.Centralizer(Sd, G) return PermutationGroup(libgap.GeneratorsOfGroup(C).sage())
def as_permutation_group(self): """ Return an isomorphic permutation group. The generators of the resulting group correspond to the images by the isomorphism of the generators of the given group. EXAMPLES:: sage: G.<a,b> = FreeGroup() sage: H = G / (a^2, b^3, a*b*~a*~b) sage: H.as_permutation_group() Permutation Group with generators [(1,2)(3,5)(4,6), (1,3,4)(2,5,6)] ALGORITHM: Uses GAP's coset enumeration on the trivial subgroup. .. WARNING:: This is in general not a decidable problem (in fact, it is not even posible to check if the group is finite or not). If all the memory available in the gap session is used, it returns a Memory Error. In this case, there could be future issues with orphaned objects. It is in general a good idea to be cautious when using this method. If the group is infinite, or too big, you should be prepared for a long computation that consumes all the memory without finishing. """ try: l = list( map(lambda i: i.sage(), self.gap().CosetTable(self.gap().TrivialSubgroup()))) except StandardError: MemoryError( 'Coset Enumeration ran out of memory of the GAP session') from sage.combinat.permutation import Permutation from sage.groups.perm_gps.permgroup import PermutationGroup return PermutationGroup( map(Permutation, [l[2 * i] for i in range(len(l) / 2)]))
def RealProjectiveSpace(self, n): r""" A triangulation of `\Bold{R}P^n` for any `n \geq 0`. INPUT: - ``n`` - integer, the dimension of the real projective space to construct The first few cases are pretty trivial: - `\Bold{R}P^0` is a point. - `\Bold{R}P^1` is a circle, triangulated as the boundary of a single 2-simplex. - `\Bold{R}P^2` is the real projective plane, here given its minimal triangulation with 6 vertices, 15 edges, and 10 triangles. - `\Bold{R}P^3`: any triangulation has at least 11 vertices by a result of Walkup; this function returns a triangulation with 11 vertices, as given by Lutz. - `\Bold{R}P^4`: any triangulation has at least 16 vertices by a result of Walkup; this function returns a triangulation with 16 vertices as given by Lutz; see also Datta, Example 3.12. - `\Bold{R}P^n`: Lutz has found a triangulation of `\Bold{R}P^5` with 24 vertices, but it does not seem to have been published. Kühnel has described a triangulation of `\Bold{R}P^n`, in general, with `2^{n+1}-1` vertices; see also Datta, Example 3.21. This triangulation is presumably not minimal, but it seems to be the best in the published literature as of this writing. So this function returns it when `n > 4`. ALGORITHM: For `n < 4`, these are constructed explicitly by listing the facets. For `n = 4`, this is constructed by specifying 16 vertices, two facets, and a certain subgroup `G` of the symmetric group `S_{16}`. Then the set of all facets is the `G`-orbit of the two given facets. For `n > 4`, the construction is as follows: let `S` denote the simplicial complex structure on the `n`-sphere given by the first barycentric subdivision of the boundary of an `(n+1)`-simplex. This has a simplicial antipodal action: if `V` denotes the vertices in the boundary of the simplex, then the vertices in its barycentric subdivision `S` correspond to nonempty proper subsets `U` of `V`, and the antipodal action sends any subset `U` to its complement. One can show that modding out by this action results in a triangulation for `\Bold{R}P^n`. To find the facets in this triangulation, find the facets in `S`. These are indentified in pairs to form `\Bold{R}P^n`, so choose a representative from each pair: for each facet in `S`, replace any vertex in `S` containing 0 with its complement. Of course these complexes increase in size pretty quickly as `n` increases. REFERENCES: - Basudeb Datta, "Minimal triangulations of manifolds", J. Indian Inst. Sci. 87 (2007), no. 4, 429-449. - W. Kühnel, "Minimal triangulations of Kummer varieties", Abh. Math. Sem. Univ. Hamburg 57 (1987), 7-20. - Frank H. Lutz, "Triangulated Manifolds with Few Vertices: Combinatorial Manifolds", preprint (2005), arXiv:math/0506372. - David W. Walkup, "The lower bound conjecture for 3- and 4-manifolds", Acta Math. 125 (1970), 75-107. EXAMPLES:: sage: P3 = simplicial_complexes.RealProjectiveSpace(3) sage: P3.f_vector() [1, 11, 51, 80, 40] sage: P3.homology() {0: 0, 1: C2, 2: 0, 3: Z} sage: P4 = simplicial_complexes.RealProjectiveSpace(4) # long time (2s on sage.math, 2011) sage: P4.f_vector() # long time [1, 16, 120, 330, 375, 150] sage: P4.homology() # long time {0: 0, 1: C2, 2: 0, 3: C2, 4: 0} sage: P5 = simplicial_complexes.RealProjectiveSpace(5) # long time (40s on sage.math, 2011) sage: P5.f_vector() # long time [1, 63, 903, 4200, 8400, 7560, 2520] The following computation can take a long time -- over half an hour -- with Sage's default computation of homology groups, but if you have CHomP installed, Sage will use that and the computation should only take a second or two. (You can download CHomP from http://chomp.rutgers.edu/, or you can install it as a Sage package using "sage -i chomp"). :: sage: P5.homology() # long time # optional - CHomP {0: 0, 1: C2, 2: 0, 3: C2, 4: 0, 5: Z} sage: simplicial_complexes.RealProjectiveSpace(2).dimension() 2 sage: P3.dimension() 3 sage: P4.dimension() # long time 4 sage: P5.dimension() # long time 5 """ if n == 0: return self.Simplex(0) if n == 1: return self.Sphere(1) if n == 2: return self.RealProjectivePlane() if n == 3: # Minimal triangulation found by Walkup and given # explicitly by Lutz return SimplicialComplex([[1, 2, 3, 7], [1, 4, 7, 9], [2, 3, 4, 8], [2, 5, 8, 10], [3, 6, 7, 10], [1, 2, 3, 11], [1, 4, 7, 10], [2, 3, 4, 11], [2, 5, 9, 10], [3, 6, 8, 9], [1, 2, 6, 9], [1, 4, 8, 9], [2, 3, 7, 8], [2, 6, 9, 10], [3, 6, 9, 10], [1, 2, 6, 11], [1, 4, 8, 10], [2, 4, 6, 10], [3, 4, 5, 9], [4, 5, 6, 7], [1, 2, 7, 9], [1, 5, 6, 8], [2, 4, 6, 11], [3, 4, 5, 11], [4, 5, 6, 11], [1, 3, 5, 10], [1, 5, 6, 11], [2, 4, 8, 10], [3, 4, 8, 9], [4, 5, 7, 9], [1, 3, 5, 11], [1, 5, 8, 10], [2, 5, 7, 8], [3, 5, 9, 10], [4, 6, 7, 10], [1, 3, 7, 10], [1, 6, 8, 9], [2, 5, 7, 9], [3, 6, 7, 8], [5, 6, 7, 8]]) if n == 4: # The facets in RP^4 are constructed by specifying two # simplices on 16 vertices, and then finding their orbit # under a certain subgroup of the permutation group on 16 # letters. See the description in Example 3.12 in Datta. # # Define the group: from sage.groups.perm_gps.permgroup import PermutationGroup g1 = '(2,7)(4,10)(5,6)(11,12)' g2 = '(1, 2, 3, 4, 5, 10)(6, 8, 9)(11, 12, 13, 14, 15, 16)' G = PermutationGroup([g1, g2]) # Define the two simplices: t1 = (1, 2, 4, 5, 11) t2 = (1, 2, 4, 11, 13) # Apply the group elements to the simplices: facets = [] for g in G: d = g.dict() for t in [t1, t2]: new = tuple([d[j] for j in t]) if new not in facets: facets.append(new) return SimplicialComplex(facets) if n >= 5: # Use the construction given by Datta in Example 3.21. V = set(range(0, n + 2)) S = simplicial_complexes.Sphere(n).barycentric_subdivision() X = S.facets() facets = set([]) for f in X: new = [] for v in f: if 0 in v: new.append(tuple(V.difference(v))) else: new.append(v) facets.add(tuple(new)) return SimplicialComplex(list(facets))
def self_dual_codes_binary(n): r""" Returns the dictionary of inequivalent sd codes of length n. For n=4 even, returns the sd codes of a given length, up to (perm) equivalence, the (perm) aut gp, and the type. The number of inequiv "diagonal" sd binary codes in the database of length n is ("diagonal" is defined by the conjecture above) is the same as the restricted partition number of n, where only integers from the set 1,4,6,8,... are allowed. This is the coefficient of `x^n` in the series expansion `(1-x)^{-1}\prod_{2^\infty (1-x^{2j})^{-1}}`. Typing the command f = (1-x)(-1)\*prod([(1-x(2\*j))(-1) for j in range(2,18)]) into Sage, we obtain for the coeffs of `x^4`, `x^6`, ... [1, 1, 2, 2, 3, 3, 5, 5, 7, 7, 11, 11, 15, 15, 22, 22, 30, 30, 42, 42, 56, 56, 77, 77, 101, 101, 135, 135, 176, 176, 231] These numbers grow too slowly to account for all the sd codes (see Huffman+Pless' Table 9.1, referenced above). In fact, in Table 9.10 of [HP], the number B_n of inequivalent sd binary codes of length n is given:: n 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 B_n 1 1 1 2 2 3 4 7 9 16 25 55 103 261 731 According to http://oeis.org/classic/A003179, the next 2 entries are: 3295, 24147. EXAMPLES:: sage: C = self_dual_codes_binary(10) sage: C["10"]["0"]["code"] == C["10"]["0"]["code"].dual_code() True sage: C["10"]["1"]["code"] == C["10"]["1"]["code"].dual_code() True sage: len(C["10"].keys()) # number of inequiv sd codes of length 10 2 sage: C = self_dual_codes_binary(12) sage: C["12"]["0"]["code"] == C["12"]["0"]["code"].dual_code() True sage: C["12"]["1"]["code"] == C["12"]["1"]["code"].dual_code() True sage: C["12"]["2"]["code"] == C["12"]["2"]["code"].dual_code() True """ sd_codes = {} if n == 4: # this code is Type I # [4,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup([ "(2,4)", "(1,2)(3,4)" ]) spectrum = [1, 0, 2, 0, 1] sd_codes_4_0 = {"order autgp":8,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Unique."} sd_codes["4"] = {"0":sd_codes_4_0} return sd_codes if n == 6: # this is Type I # [6,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup( ["(3,6)", "(2,3)(5,6)", "(1,2)(4,5)"] ) spectrum = [1, 0, 3, 0, 3, 0, 1] sd_codes_6_0 = {"order autgp":48,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Unique"} sd_codes["6"] = {"0":sd_codes_6_0} return sd_codes if n == 8: # the first code is Type I, the second is Type II # the second code is equiv to the extended Hamming [8,4,4] code. # [8,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup( ["(4,8)", "(3,4)(7,8)", "(2,3)(6,7)", "(1,2)(5,6)"] ) spectrum = [1, 0, 4, 0, 6, 0, 4, 0, 1] sd_codes_8_0 = {"order autgp":384,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Unique Type I of this length."} # [8,1]: genmat = I2(n).augment(matA(n)[4]) # G = PermutationGroup( ["(4,5)(6,7)", "(4,6)(5,7)", "(3,4)(7,8)",\ # "(2,3)(6,7)", "(1,2)(5,6)"] ) spectrum = [1, 0, 0, 0, 14, 0, 0, 0, 1] sd_codes_8_1 = {"order autgp":1344,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"II","Comment":"Unique Type II of this length."} sd_codes["8"] = {"0":sd_codes_8_0,"1":sd_codes_8_1} return sd_codes if n == 10: # Both of these are Type I; one has a unique lowest weight codeword # [10,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup( ["(5,10)", "(4,5)(9,10)", "(3,4)(8,9)",\ # "(2,3)(7,8)", "(1,2)(6,7)"] ) spectrum = [1, 0, 5, 0, 10, 0, 10, 0, 5, 0, 1] sd_codes_10_0 = {"order autgp":3840,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"No Type II of this length."} # [10,1]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matId(n)[4]])) # G = PermutationGroup( ["(5,10)", "(4,6)(7,8)", "(4,7)(6,8)", "(3,4)(8,9)",\ # "(2,3)(7,8)", "(1,2)(6,7)"] ) spectrum = [1, 0, 1, 0, 14, 0, 14, 0, 1, 0, 1] sd_codes_10_1 = {"order autgp":2688,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Unique lowest weight nonzero codeword."} sd_codes["10"] = {"0":sd_codes_10_0,"1":sd_codes_10_1} return sd_codes if n == 12: # all of these are Type I # [12,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup( ["(6,12)", "(5,6)(11,12)", "(4,5)(10,11)", "(3,4)(9,10)",\ # "(2,3)(8,9)", "(1,2)(7,8)"] ) spectrum = [1, 0, 6, 0, 15, 0, 20, 0, 15, 0, 6, 0, 1] sd_codes_12_0 = {"order autgp":48080,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"No Type II of this length."} # [12,1]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matId(n)[4]])) # G = PermutationGroup( ["(2,3)(4,7)", "(2,4)(3,7)", "(2,4,9)(3,7,8)", "(2,4,8,10)(3,9)",\ # "(1,2,4,7,8,10)(3,9)", "(2,4,8,10)(3,9)(6,12)", "(2,4,8,10)(3,9)(5,6,11,12)"] ) spectrum = [1, 0, 2, 0, 15, 0, 28, 0, 15, 0, 2, 0, 1] sd_codes_12_1 = {"order autgp":10752,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Smallest automorphism group of these."} # [12,2]: genmat = I2(n).augment(matA(n)[6]) # G = PermutationGroup( ["(5,6)(11,12)", "(5,11)(6,12)", "(4,5)(10,11)", "(3,4)(9,10)",\ # "(2,3)(8,9)", "(1,2)(7,8)"] ) spectrum = [1, 0, 0, 0, 15, 0, 32, 0, 15, 0, 0, 0, 1] sd_codes_12_2 = {"order autgp":23040,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Largest minimum distance of these."} sd_codes["12"] = {"0":sd_codes_12_0,"1":sd_codes_12_1,"2":sd_codes_12_2} return sd_codes if n == 14: # all of these are Type I; one has a unique lowest weight codeword # (there are 4 total inequiv sd codes of n = 14, by Table 9.10 [HP]) # [14,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup( ["(7,14)", "(6,7)(13,14)", "(5,6)(12,13)", "(4,5)(11,12)",\ # "(3,4)(10,11)", "(2,3)(9,10)", "(1,2)(8,9)"] ) spectrum = [1, 0, 7, 0, 21, 0, 35, 0, 35, 0, 21, 0, 7, 0, 1] sd_codes_14_0 = {"order autgp":645120,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"No Type II of this length. Huge aut gp."} # [14,1]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matId(n)[4]])) # G = PermutationGroup( ["(7,14)", "(6,7)(13,14)", "(5,6)(12,13)", "(4,8)(9,10)",\ # "(4,9)(8,10)", "(3,4)(10,11)", "(2,3)(9,10)", "(1,2)(8,9)"] ) spectrum = [1, 0, 3, 0, 17, 0, 43, 0, 43, 0, 17, 0, 3, 0, 1] sd_codes_14_1 = {"order autgp":64512,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Automorphism group has order 64512."} # [14,2]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[6],matId(n)[6]])) # G = PermutationGroup( ["(7,14)", "(5,6)(12,13)", "(5,12)(6,13)", "(4,5)(11,12)",\ # "(3,4)(10,11)", "(2,3)(9,10)", "(1,2)(8,9)"] ) spectrum = [1, 0, 1, 0, 15, 0, 47, 0, 47, 0, 15, 0, 1, 0, 1] sd_codes_14_2 = {"order autgp":46080,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Unique codeword of weight 2."} # [14,3]: genmat = I2(n).augment(And7) # G = PermutationGroup( ["(7,11)(12,13)", "(7,12)(11,13)", "(6,9)(10,14)",\ # "(6,10)(9,14)", "(5,6)(8,9)", "(4,5)(9,10), (2,3)(11,12)", "(2,7)(3,13)",\ # "(1,2)(12,13)", "(1,4)(2,5)(3,8)(6,7)(9,13)(10,12)(11,14)"]) spectrum = [1, 0, 0, 0, 14, 0, 49, 0, 49, 0, 14, 0, 0, 0, 1] sd_codes_14_3 = {"order autgp":56448,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Largest minimum distance of these."} sd_codes["14"] = {"0":sd_codes_14_0,"1":sd_codes_14_1,"2":sd_codes_14_2,\ "3":sd_codes_14_3} return sd_codes if n == 16: # 4 of these are Type I, 2 are Type II. The 2 Type II codes # are formally equivalent but with different automorphism groups # [16,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup( [ "(8,16)", "(7,8)(15,16)", "(6,7)(14,15)", "(5,6)(13,14)", # "(4,5)(12,13)", "(3,4)(11,12)", "(2,3)(10,11)", "(1,2)(9,10)"] ) spectrum = [1, 0, 8, 0, 28, 0, 56, 0, 70, 0, 56, 0, 28, 0, 8, 0, 1] sd_codes_16_0 = {"order autgp":10321920,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Huge aut gp."} # [16,1]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matId(n)[4]])) # G = PermutationGroup( [ "(8,16)", "(7,8)(15,16)", "(6,7)(14,15)", "(5,6)(13,14)",\ # "(4,9)(10,11)", "(4,10)(9,11)", "(3,4)(11,12)", "(2,3)(10,11)", "(1,2)(9,10)"] ) spectrum = [1, 0, 4, 0, 20, 0, 60, 0, 86, 0, 60, 0, 20, 0, 4, 0, 1] sd_codes_16_1 = {"order autgp":516096,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":""} # [16,2]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matA(n)[4]])) # G = PermutationGroup( [ "(8,13)(14,15)", "(8,14)(13,15)", "(7,8)(15,16)", "(6,7)(14,15)",\ # "(5,6)(13,14)", "(4,9)(10,11)", "(4,10)(9,11)", "(3,4)(11,12)", "(2,3)(10,11)",\ # "(1,2)(9,10)","(1,5)(2,6)(3,7)(4,8)(9,13)(10,14)(11,15)(12,16)"] ) spectrum = [1, 0, 0, 0, 28, 0, 0, 0, 198, 0, 0, 0, 28, 0, 0, 0, 1] sd_codes_16_2 = {"order autgp":3612672,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"II","Comment":"Same spectrum as the other Type II code."} # [16,3]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[6],matId(n)[6]])) # G = PermutationGroup( [ "(8,16)", "(7,8)(15,16)", "(5,6)(13,14)", "(5,13)(6,14)",\ # "(4,5)(12,13)", "(3,4)(11,12)", "(2,3)(10,11)", "(1,2)(9,10)"] ) spectrum = [1, 0, 2, 0, 16, 0, 62, 0, 94, 0, 62, 0, 16, 0, 2, 0, 1] sd_codes_16_3 = {"order autgp":184320,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":""} # [16,4]: genmat = I2(n).augment(matA(n)[8]) # an equivalent form: See also [20,8] using A[10] # [(1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1), # (0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1), # (0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0), # (0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0), # (0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0), # (0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0), # (0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0), # (0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1)] # G = PermutationGroup( [ "(7,8)(15,16)", "(7,15)(8,16)", "(6,7)(14,15)",\ # "(5,6)(13,14)","(4,5)(12,13)","(3,4)(11,12)", "(2,3)(10,11)", "(1,2)(9,10)"] ) spectrum = [1, 0, 0, 0, 28, 0, 0, 0, 198, 0, 0, 0, 28, 0, 0, 0, 1] sd_codes_16_4 = {"order autgp":5160960,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"II","Comment":"Same spectrum as the other Type II code. Large aut gp."} # [16,5]: genmat = I2(n).augment(block_diagonal_matrix([And7,matId(n)[7]])) # G = PermutationGroup( [ "(8,16)", "(7,12)(13,14)", "(7,13)(12,14)",\ # "(6,10)(11,15)", "(6,11)(10,15)", "(5,6)(9,10)", "(4,5)(10,11)",\ # "(2,3)(12,13)", "(2,7)(3,14)", "(1,2)(13,14)",\ # "(1,4)(2,5)(3,9)(6,7)(10,14)(11,13)(12,15)" ] ) spectrum = [1, 0, 1, 0, 14, 0, 63, 0, 98, 0, 63, 0, 14, 0, 1, 0, 1] sd_codes_16_5 = {"order autgp":112896,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"'Exceptional' construction."} # [16,6]: J8 = MatrixSpace(ZZ,8,8)(64*[1]) genmat = I2(n).augment(I2(n)+MS2(n)((H8+J8)/2)) # G = PermutationGroup( [ "(7,9)(10,16)", "(7,10)(9,16)", "(6,7)(10,11)",\ # "(4,6)(11,13)", "(3,5)(12,14)", "(3,12)(5,14)", "(2,3)(14,15)",\ # "(1,2)(8,15)", "(1,4)(2,6)(3,7)(5,16)(8,13)(9,12)(10,14)(11,15)" ] ) spectrum = [1, 0, 0, 0, 12, 0, 64, 0, 102, 0, 64, 0, 12, 0, 0, 0, 1] sd_codes_16_6 = {"order autgp":73728,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"'Exceptional' construction. Min dist 4."} sd_codes["16"] = {"0":sd_codes_16_0,"1":sd_codes_16_1,"2":sd_codes_16_2,\ "3":sd_codes_16_3,"4":sd_codes_16_4,"5":sd_codes_16_5,"6":sd_codes_16_6} return sd_codes if n == 18: # all of these are Type I, all are "extensions" of the n=16 codes # [18,3] and [18,4] each has a unique lowest weight codeword. Also, they # are formally equivalent but with different automorphism groups # [18,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup( [ "(9,18)", "(8,9)(17,18)", "(7,8)(16,17)", "(6,7)(15,16)",\ # "(5,6)(14,15)", "(4,5)(13,14)", "(3,4)(12,13)", "(2,3)(11,12)", "(1,2)(10,11)" ] ) spectrum = [1, 0, 9, 0, 36, 0, 84, 0, 126, 0, 126, 0, 84, 0, 36, 0, 9, 0, 1] sd_codes_18_0 = {"order autgp":185794560,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "Huge aut gp. S_9x(ZZ/2ZZ)^9?"} # [18,1]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matId(n)[4]])) # G = PermutationGroup( [ "(9,18)", "(8,9)(17,18)", "(7,8)(16,17)", "(6,7)(15,16)",\ # "(5,6)(14,15)", "(4,10)(11,12)", "(4,11)(10,12)", "(3,4)(12,13)",\ # "(2,3)(11,12)", "(1,2)(10,11)" ] ) spectrum = [1, 0, 5, 0, 24, 0, 80, 0, 146, 0, 146, 0, 80, 0, 24, 0, 5, 0, 1] sd_codes_18_1 = {"order autgp":5160960,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "Large aut gp."} # [18,2]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[6],matId(n)[6]])) # G = PermutationGroup( [ "(9,18)", "(8,9)(17,18)", "(7,8)(16,17)", "(5,6)(14,15)",\ # "(5,14)(6,15)","(4,5)(13,14)", "(3,4)(12,13)", "(2,3)(11,12)", "(1,2)(10,11)"] ) spectrum = [1, 0, 3, 0, 18, 0, 78, 0, 156, 0, 156, 0, 78, 0, 18, 0, 3, 0, 1] sd_codes_18_2 = {"order autgp":1105920,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": ""} # [18,3]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matA(n)[4],matId(n)[8]])) # G = PermutationGroup( [ "(9,18)", "(8,14)(15,16)", "(8,15)(14,16)", "(7,8)(16,17)",\ # "(6,7)(15,16)","(5,6)(14,15)", "(4,10)(11,12)", "(4,11)(10,12)",\ # "(3,4)(12,13)", "(2,3)(11,12)","(1,2)(10,11)",\ # "(1,5)(2,6)(3,7)(4,8)(10,14)(11,15)(12,16)(13,17)" ] ) spectrum = [1, 0, 1, 0, 28, 0, 28, 0, 198, 0, 198, 0, 28, 0, 28, 0, 1, 0, 1] sd_codes_18_3 = {"order autgp":7225344,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "Large aut gp. Unique codeword of smallest non-zero wt.\ Same spectrum as '[18,4]' sd code."} # [18,4]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[8],matId(n)[8]])) # G = PermutationGroup( [ "(9,18)", "(7,8)(16,17)", "(7,16)(8,17)", "(6,7)(15,16)", \ # "(5,6)(14,15)", "(4,5)(13,14)", "(3,4)(12,13)", "(2,3)(11,12)", "(1,2)(10,11)" ] ) spectrum = [1, 0, 1, 0, 28, 0, 28, 0, 198, 0, 198, 0, 28, 0, 28, 0, 1, 0, 1] sd_codes_18_4 = {"order autgp":10321920,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "Huge aut gp. Unique codeword of smallest non-zero wt.\ Same spectrum as '[18,3]' sd code."} # [18,5]: C = self_dual_codes_binary(n-2)["%s"%(n-2)]["5"]["code"] A0 = C.redundancy_matrix() genmat = I2(n).augment(block_diagonal_matrix([A0,matId(n)[8]])) # G = PermutationGroup( [ "(5,10)(6,11)", "(5,11)(6,10)", "(5,11,12)(6,7,10)",\ # "(5,11,10,7,12,6,13)", "(2,15)(3,16)(5,11,10,7,12,6,13)",\ # "(2,16)(3,15)(5,11,10,7,12,6,13)", "(2,16,14)(3,15,4)(5,11,10,7,12,6,13)",\ # "(1,2,16,15,4,3,14)(5,11,10,7,12,6,13)", "(1,5,14,6,16,11,15,7,3,10,4,12,2,13)",\ # "(2,16,14)(3,15,4)(5,11,10,7,12,6,13)(9,18)",\ # "(2,16,14)(3,15,4)(5,11,10,7,12,6,13)(8,9,17,18)" ] ) spectrum = [1, 0, 2, 0, 15, 0, 77, 0, 161, 0, 161, 0, 77, 0, 15, 0, 2, 0, 1] sd_codes_18_5 = {"order autgp":451584,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "'Exceptional' construction."} # [18,6]: C = self_dual_codes_binary(n-2)["%s"%(n-2)]["6"]["code"] A0 = C.redundancy_matrix() genmat = I2(n).augment(block_diagonal_matrix([A0,matId(n)[8]])) G = PermutationGroup( [ "(9,18)", "(7,10)(11,17)", "(7,11)(10,17)", "(6,7)(11,12)",\ "(4,6)(12,14)", "(3,5)(13,15)", "(3,13)(5,15)", "(2,3)(15,16)", "(1,2)(8,16)",\ "(1,4)(2,6)(3,7)(5,17)(8,14)(10,13)(11,15)(12,16)" ] ) spectrum = [1, 0, 1, 0, 12, 0, 76, 0, 166, 0, 166, 0, 76, 0, 12, 0, 1, 0, 1] sd_codes_18_6 = {"order autgp":147456,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "'Exceptional'. Unique codeword of smallest non-zero wt."} # [18,7] (equiv to H18 in [P]) genmat = MS(n)([[1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0],\ [0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1],\ [0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1],\ [0,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1],\ [0,0,0,0,1,0,0,0,0,1,1,0,0,1,0,1,1,0],\ [0,0,0,0,0,1,0,0,0,1,0,1,0,1,0,1,1,0],\ [0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0],\ [0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,1],\ [0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1]]) # G = PermutationGroup( [ "(9,10)(16,18)", "(9,16)(10,18)", "(8,9)(14,16)",\ # "(7,11)(12,17)", "(7,12)(11,17)", "(5,6)(11,12)", "(5,7)(6,17)",\ # "(4,13)(5,8)(6,14)(7,9)(10,12)(11,18)(16,17)", "(3,4)(13,15)",\ # "(1,2)(5,8)(6,14)(7,9)(10,12)(11,18)(16,17)", "(1,3)(2,15)",\ # "(1,5)(2,6)(3,7)(4,11)(10,18)(12,13)(15,17)" ] ) spectrum = [1, 0, 0, 0, 9, 0, 75, 0, 171, 0, 171, 0, 75, 0, 9, 0, 0, 0, 1] sd_codes_18_7 = {"order autgp":82944,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "'Exceptional' construction. Min dist 4."} # [18, 8] (equiv to I18 in [P]) I18 = MS(n)([[1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0],\ [1,0,1,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0],\ [0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1],\ [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]) genmat = MS(n)([[1,0,0,0,0,0,0,0,0, 1, 1, 1, 1, 1, 0, 0, 0, 0],\ [0,1,0,0,0,0,0,0,0, 1, 0, 1, 1, 1, 0, 1, 1, 1],\ [0,0,1,0,0,0,0,0,0, 0, 1, 1, 0, 0, 0, 1, 1, 1],\ [0,0,0,1,0,0,0,0,0, 0, 1, 0, 0, 1, 0, 1, 1, 1],\ [0,0,0,0,1,0,0,0,0, 0, 1, 0, 1, 0, 0, 1, 1, 1],\ [0,0,0,0,0,1,0,0,0, 1, 1, 0, 0, 0, 0, 1, 1, 1],\ [0,0,0,0,0,0,1,0,0, 0, 0, 0, 0, 0, 1, 0, 1, 1],\ [0,0,0,0,0,0,0,1,0, 0, 0, 0, 0, 0, 1, 1, 0, 1],\ [0,0,0,0,0,0,0,0,1, 0, 0, 0, 0, 0, 1, 1, 1, 0]]) G = PermutationGroup( [ "(9,15)(16,17)", "(9,16)(15,17)", "(8,9)(17,18)",\ "(7,8)(16,17)", "(5,6)(10,13)", "(5,10)(6,13)", "(4,5)(13,14)",\ "(3,4)(12,14)", "(1,2)(6,10)", "(1,3)(2,12)" ] ) spectrum = [1, 0, 0, 0, 17, 0, 51, 0, 187, 0, 187, 0, 51, 0, 17, 0, 0, 0, 1] sd_codes_18_8 = {"order autgp":322560,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "'Exceptional' construction. Min dist 4."} sd_codes["18"] = {"0":sd_codes_18_0,"1":sd_codes_18_1,"2":sd_codes_18_2,\ "3":sd_codes_18_3,"4":sd_codes_18_4,"5":sd_codes_18_5,\ "6":sd_codes_18_6,"7":sd_codes_18_7,"8":sd_codes_18_8} return sd_codes if n == 20: # all of these of these are Type I; 2 of these codes # are formally equivalent but with different automorphism groups; # one of these has a unique codeword of lowest weight A10 = MatrixSpace(F,10,10)([[1, 1, 1, 1, 1, 1, 1, 1, 1, 0],\ [1, 1, 1, 0, 1, 0, 1, 0, 1, 1],\ [1, 0, 0, 1, 0, 1, 0, 1, 0, 1],\ [0, 0, 0, 1, 1, 1, 0, 1, 0, 1],\ [0, 0, 1, 1, 0, 1, 0, 1, 0, 1],\ [0, 0, 0, 1, 0, 1, 1, 1, 0, 1],\ [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],\ [0, 0, 0, 1, 0, 0, 0, 0, 1, 1],\ [0, 0, 0, 0, 0, 1, 0, 0, 1, 1],\ [0, 0, 0, 0, 0, 0, 0, 1, 1, 1]]) # [20,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup( ["(10,20)", "(9,10)(19,20)", "(8,9)(18,19)", "(7,8)(17,18)", "(6,7)(16,17)",\ # "(5,6)(15,16)", "(4,5)(14,15)", "(3,4)(13,14)", "(2,3)(12,13)", "(1,2)(11,12)"] ) spectrum = [1, 0, 10, 0, 45, 0, 120, 0, 210, 0, 252, 0, 210, 0, 120, 0, 45, 0, 10, 0, 1] sd_codes_20_0 = {"order autgp":3715891200,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "Huge aut gp"} # [20,1]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matId(n)[4]])) # G = PermutationGroup( [ "(10,20)", "(9,10)(19,20)", "(8,9)(18,19)", "(7,8)(17,18)", "(6,7)(16,17)",\ # "(5,6)(15,16)", "(4,11)(12,13)", "(4,12)(11,13)", "(3,4)(13,14)",\ # "(2,3)(12,13)", "(1,2)(11,12)"] ) spectrum = [1, 0, 6, 0, 29, 0, 104, 0, 226, 0, 292, 0, 226, 0, 104, 0, 29, 0, 6, 0, 1] sd_codes_20_1 = {"order autgp":61931520,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":""} # [20,2]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[6],matId(n)[6]])) # G = PermutationGroup( [ "(10,20)", "(9,10)(19,20)", "(8,9)(18,19)", "(7,8)(17,18)",\ # "(5,6)(15,16)", "(5,15)(6,16)", "(4,5)(14,15)", "(3,4)(13,14)",\ # "(2,3)(12,13)", "(1,2)(11,12)"] ) spectrum = [1, 0, 4, 0, 21, 0, 96, 0, 234, 0, 312, 0, 234, 0, 96, 0, 21, 0, 4, 0, 1] sd_codes_20_2 = {"order autgp":8847360,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":""} # [20,3]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[6],matA(n)[4]])) # G = PermutationGroup( [ "(5,6)(15,16)", "(5,15)(6,16)", "(4,5)(14,15)", "(3,4)(13,14)",\ # "(2,3)(12,13)", "(1,2)(11,12)", "(8,17)(9,10)", "(8,10)(9,17)", "(8,10,20)(9,19,17)",\ # "(8,19,20,9,17,10,18)", "(7,8,19,20,9,18)(10,17)"] ) spectrum =[1, 0, 0, 0, 29, 0, 32, 0, 226, 0, 448, 0, 226, 0, 32, 0, 29, 0, 0, 0, 1] sd_codes_20_3 = {"order autgp":30965760,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Min dist 4."} # [20,4]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matA(n)[4],matId(n)[8]])) # G = PermutationGroup( [ "(5,15)(6,16)", "(5,16)(6,15)", "(5,16,7)(6,17,15)", "(5,15,8)(6,17,7)",\ # "(5,17,18)(6,15,8), (3,14)(4,13)(5,17,18)(6,15,8)", "(3,13)(4,14)(5,17,18)(6,15,8)",\ # "(2,3,14)(4,13,11)(5,17,18)(6,15,8)"," (2,3,12)(4,11,14)(5,17,18)(6,15,8)",\ # "(1,2,3,11,14,4,12)(5,17,18)(6,15,8)", "(1,5,13,17,14,8,2,7,3,16,12,6,11,18)(4,15)",\ # "(2,3,12)(4,11,14)(5,17,18)(6,15,8)(10,20)",\ # "(2,3,12)(4,11,14)(5,17,18)(6,15,8)(9,10,19,20)"] ) spectrum =[1, 0, 2, 0, 29, 0, 56, 0, 226, 0, 396, 0, 226, 0, 56, 0, 29, 0, 2, 0, 1] sd_codes_20_4 = {"order autgp":28901376,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":""} # [20,5]: genmat = I2(n).augment(block_diagonal_matrix([And7,matId(n)[7]])) # G = PermutationGroup( [ "(10,20)", "(9,10)(19,20)", "(8,9)(18,19)",\ # "(7,11)(12,14)", "(7,12)(11,14)", "(6,7)(12,13)", "(5,6)(11,12)",\ # "(4,15)(16,17)", "(4,16)(15,17)", "(2,3)(16,17)", "(2,4)(3,15)",\ # "(1,2)(15,16)", "(1,5)(2,6)(3,13)(4,7)(11,16)(12,15)(14,17)" ] ) # order 2709504 spectrum = [1, 0, 3, 0, 17, 0, 92, 0, 238, 0, 322, 0, 238, 0, 92, 0, 17, 0, 3, 0, 1] sd_codes_20_5 = {"order autgp":2709504,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "'Exceptional' construction."} # [20,6]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[8],matId(n)[8]])) # G = PermutationGroup( [ "(7,8)(17,18)", "(7,17)(8,18)", "(6,7)(16,17)", "(5,6)(15,16)",\ # "(4,5)(14,15)", "(3,4)(13,14)", "(2,3)(12,13)", "(1,2)(11,12)",\ # "(10,20)", "(9,10,19,20)"] ) spectrum = [1, 0, 2, 0, 29, 0, 56, 0, 226, 0, 396, 0, 226, 0, 56, 0, 29, 0, 2, 0, 1] sd_codes_20_6 = {"order autgp":41287680,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":""} # [20,7]: A0 = self_dual_codes_binary(n-4)["16"]["6"]["code"].redundancy_matrix() genmat = I2(n).augment(block_diagonal_matrix([A0,matId(n)[8]])) # G = PermutationGroup( [ "(10,20)", "(9,10)(19,20)", "(7,11)(12,18)",\ # "(7,12)(11,18)", "(6,7)(12,13)", "(4,6)(13,15)", "(3,5)(14,16)",\ # "(3,14)(5,16)", "(2,3)(16,17)", "(1,2)(8,17)",\ # "(1,4)(2,6)(3,7)(5,18)(8,15)(11,14)(12,16)(13,17)" ] ) spectrum = [1,0,2,0,13,0,88,0,242,0,332,0,242,0,88,0,13,0,2,0,1] sd_codes_20_7 = {"order autgp":589824,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"'Exceptional' construction."} # [20,8]: (genmat, J20, and genmat2 are all equiv) genmat = I2(n).augment(matA(n)[10]) J20 = MS(n)([[1,1,1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\ [0,0,1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\ [0,0,0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\ [0,0,0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\ [0,0,0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\ [0,0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],\ [0,0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],\ [0,0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],\ [0,0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],\ [1,0,1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]) genmat2 = MS(n)([[1,0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1],\ [0,1,0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1],\ [0,0,1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],\ [0,0,0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0],\ [0,0,0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0],\ [0,0,0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0],\ [0,0,0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0],\ [0,0,0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0],\ [0,0,0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0],\ [0,0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1]]) # G = PermutationGroup( [ "(9,10)(19,20)", "(9,19)(10,20)", "(8,9)(18,19)", "(7,8)(17,18)",\ # "(6,7)(16,17)", "(5,6)(15,16)", "(4,5)(14,15)", "(3,4)(13,14)",\ # "(2,3)(12,13)", "(1,2)(11,12)"] ) spectrum =[1, 0, 0, 0, 45, 0, 0, 0, 210, 0, 512, 0, 210, 0, 0, 0, 45, 0, 0, 0, 1] sd_codes_20_8 = {"order autgp":1857945600,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Huge aut gp. Min dist 4."} # [20,9]: (genmat, K20 are equiv) genmat = I2(n).augment(A10) K20 = MS(n)([[1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],\ [1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0]]) #genmat = K20 # not in standard form # G = PermutationGroup( [ "(4,13)(5,15)", "(4,15)(5,13)", "(3,4,13)(5,11,15)", # "(3,4,6,11,15,17)(5,13)", "(3,5,17,4,12)(6,15,7,11,13)", # "(1,2)(3,5,17,4,7,11,13,6,15,12)", "(1,3,5,17,4,12)(2,11,13,6,15,7)", # "(3,5,17,4,12)(6,15,7,11,13)(10,18)(19,20)", "(3,5,17,4,12)(6,15,7,11,13)(10,19)(18,20)", # "(3,5,17,4,12)(6,15,7,11,13)(9,10)(16,18)", # "(3,5,17,4,12)(6,15,7,11,13)(8,9)(14,16)" ] ) spectrum = [1, 0, 0, 0, 21, 0, 48, 0, 234, 0, 416, 0, 234, 0, 48, 0, 21, 0, 0, 0, 1] sd_codes_20_9 = {"order autgp":4423680,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "Min dist 4."} # [20,10] L20 = MS(n)([[1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],\ [0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,1,0,0,0,0],\ [0,1,0,1,0,1,0,0,0,0,0,0,0,0,1,0,1,0,1,0]]) genmat = L20 # not in standard form # G = PermutationGroup( [ "(17,18)(19,20)", "(17,19)(18,20)", "(15,16)(19,20)", # "(15,17)(16,18)", "(10,11)(12,13)", "(10,12)(11,13)", "(9,10)(13,14)", # "(8,9)(12,13)", "(3,4)(5,6)", "(3,5)(4,6)", "(2,3)(6,7)", "(1,2)(5,6)", # "(1,8)(2,9)(3,10)(4,11)(5,12)(6,13)(7,14)(19,20)" ] ) # order 1354752 spectrum = [1, 0, 0, 0, 17, 0, 56, 0, 238, 0, 400, 0, 238, 0, 56, 0, 17, 0, 0, 0, 1] sd_codes_20_10 = {"order autgp":1354752,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "Min dist 4."} # [20,11] S20 = MS(n)([[1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],\ [1,0,1,0,1,0,1,0,1,1,0,0,0,0,0,0,1,1,0,0],\ [1,1,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,0,0],\ [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,1,0]] ) genmat = S20 # not in standard form # G = PermutationGroup( [ "(17,18)(19,20)", "(17,19)(18,20)", "(13,14)(15,16)", # "(13,15)(14,16)", "(11,12)(15,16)", "(11,13)(12,14)", "(9,10)(15,16)", # "(9,11)(10,12)", "(5,6)(7,8)", "(5,7)(6,8)", "(3,4)(7,8)", "(3,5)(4,6)", # "(1,2)(7,8)", "(1,3)(2,4)", "(1,9)(2,10)(3,11)(4,12)(5,13)(6,14)(7,15)(8,16)" ] ) # G.order() = 294912 spectrum = [1, 0, 0, 0, 13, 0, 64, 0, 242, 0, 384, 0, 242, 0, 64, 0, 13, 0, 0, 0, 1] sd_codes_20_11 = {"order autgp":294912,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Min dist 4."} # [20,12] R20 = MS(n)([[0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],\ [0,1,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,1,1,0],\ [1,1,1,0,1,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0],\ [1,1,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,1],\ [1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1]]) genmat = R20 # not in standard form # G = PermutationGroup( [ "(17,18)(19,20)", "(17,19)(18,20)", "(15,16)(19,20)", # "(15,17)(16,18)", "(11,12)(13,14)", "(11,13)(12,14)", "(9,10)(13,14)", # "(9,11)(10,12)", "(5,6)(7,8)", "(5,7)(6,8)", "(3,4)(7,8)", "(3,5)(4,6)", # "(3,9,15)(4,10,16)(5,11,17)(6,12,18)(7,14,19)(8,13,20)", # "(1,2)(7,8)(9,15)(10,16)(11,17)(12,18)(13,19)(14,20)" ] ) # order 82944 spectrum = [1, 0, 0, 0, 9, 0, 72, 0, 246, 0, 368, 0, 246, 0, 72, 0, 9, 0, 0, 0, 1] sd_codes_20_12 = {"order autgp":82944,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Min dist 4."} # [20,13] M20 = MS(n)([[1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0],\ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],\ [0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0],\ [1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0],\ [0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1],\ [0,0,1,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0],\ [0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,1,0,0,0,0]]) genmat = M20 # not in standard form # G = PermutationGroup( [ "(17,18)(19,20)", "(17,19)(18,20)", "(13,14)(15,16)", # "(13,15)(14,16)", "(9,10)(11,12)", "(9,11)(10,12)", "(5,6)(7,8)", # "(5,7)(6,8)", "(5,9)(6,11)(7,12)(8,10)(13,17)(14,19)(15,18)(16,20)", # "(5,13)(6,15)(7,14)(8,16)(9,17)(10,20)(11,18)(12,19)", # "(3,4)(6,7)(11,12)(13,17)(14,18)(15,19)(16,20)", # "(2,3)(7,8)(9,13)(10,14)(11,15)(12,16)(19,20)", # "(1,2)(6,7)(11,12)(13,17)(14,18)(15,19)(16,20)", # "(1,5)(2,6)(3,7)(4,8)(9,17)(10,18)(11,19)(12,20)" ] ) spectrum = [1, 0, 0, 0, 5, 0, 80, 0, 250, 0, 352, 0, 250, 0, 80, 0, 5, 0, 0, 0, 1] sd_codes_20_13 = {"order autgp":122880,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "Min dist 4."} # [20,14]: # aut gp of this computed using a program by Robert Miller A0 = self_dual_codes_binary(n-2)["18"]["8"]["code"].redundancy_matrix() genmat = I2(n).augment(block_diagonal_matrix([A0,matId(n)[9]])) # [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], # [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0], # [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0], # [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0], # [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0], # [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0], # [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0], # [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0], # [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0], # [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]] # G = PermutationGroup( [ "(8,19)(16,17)", "(8,16)(17,19)", "(9,18)(16,17)", "(8,9)(18,19)", # "(7,8)(17,18)", "(4,15)(5,14)", "(4,5)(14,15)", "(4,15)(6,11)", "(5,6)(11,14)", # "(3,13)(4,15)", "(3,15)(4,13)", "(1,2)(4,15)", "(1,4)(2,15)(3,5)(13,14)", "(10,20)" ] ) spectrum = [1, 0, 1, 0, 17, 0, 68, 0, 238, 0, 374, 0, 238, 0, 68, 0, 17, 0, 1, 0, 1] sd_codes_20_14 = {"order autgp":645120,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment": "'Exceptional' construction."} # [20,15]: A0 = self_dual_codes_binary(n-2)["18"]["7"]["code"].redundancy_matrix() genmat = I2(n).augment(block_diagonal_matrix([A0,matId(n)[9]])) # [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], # [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0], # [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0], # [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0], # [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0], # [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0], # [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0], # [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0], # [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0], # [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]] # G = PermutationGroup( [ "(10,20)", "(9,11)(17,19)", "(9,17)(11,19)", "(8,9)(15,17)", # "(7,12)(13,18)", "(7,13)(12,18)", "(5,6)(12,13)", "(5,7)(6,18)", # "(4,14)(5,8)(6,15)(7,9)(11,13)(12,19)(17,18)", "(3,4)(14,16)", # "(1,2)(5,8)(6,15)(7,9)(11,13)(12,19)(17,18)", "(1,3)(2,16)", # "(1,5)(2,6)(3,7)(4,12)(11,19)(13,14)(16,18)" ] ) # order 165888 spectrum = [1, 0, 1, 0, 9, 0, 84, 0, 246, 0, 342, 0, 246, 0, 84, 0, 9, 0, 1, 0, 1] sd_codes_20_15 = {"order autgp":165888,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"'Exceptional' construction. Unique lowest wt codeword."} sd_codes["20"] = {"0":sd_codes_20_0,"1":sd_codes_20_1,"2":sd_codes_20_2,\ "3":sd_codes_20_3,"4":sd_codes_20_4,"5":sd_codes_20_5,\ "6":sd_codes_20_6,"7":sd_codes_20_7,"8":sd_codes_20_8,\ "9":sd_codes_20_9,"10":sd_codes_20_10,"11":sd_codes_20_11,\ "12":sd_codes_20_12,"13":sd_codes_20_13,"14":sd_codes_20_14, "15":sd_codes_20_15} return sd_codes if n == 22: # all of these of these are Type I; 2 of these codes # are formally equivalent but with different automorphism groups # *** Incomplete *** (7 out of 25) # [22,0]: genmat = I2(n).augment(I2(n)) # G = PermutationGroup( [ "(11,22)", "(10,11)(21,22)", "(9,10)(20,21)",\ # "(8,9)(19,20)", "(7,8)(18,19)", "(6,7)(17,18)", "(5,6)(16,17)",\ # "(4,5)(15,16)", "(3,4)(14,15)", "(2,3)(13,14)", "(1,2)(12,13)" ] ) # S_11x(ZZ/2ZZ)^11?? spectrum = [1, 0, 11, 0, 55, 0, 165, 0, 330, 0, 462, 0, 462, 0, 330, 0, 165, 0, 55, 0, 11, 0, 1] sd_codes_22_0 = {"order autgp":81749606400,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Huge aut gp."} # [22,1]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matId(n)[4]])) # G = PermutationGroup( [ "(11,22)", "(10,11)(21,22)", "(9,10)(20,21)",\ # "(8,9)(19,20)", "(7,8)(18,19)", "(6,7)(17,18)", "(5,6)(16,17)",\ # "(4,12)(13,14)", "(4,13)(12,14)", "(3,4)(14,15)", "(2,3)(13,14)", "(1,2)(12,13)" ] ) spectrum = [1, 0, 7, 0, 35, 0, 133, 0, 330, 0, 518, 0, 518, 0, 330, 0, 133, 0, 35, 0, 7, 0, 1] sd_codes_22_1 = {"order autgp":867041280,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":""} # [22,2]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[6],matId(n)[6]])) # G = PermutationGroup( [ "(11,22)", "(10,11)(21,22)", "(9,10)(20,21)",\ # "(8,9)(19,20)", "(7,8)(18,19)", "(5,6)(16,17)", "(5,16)(6,17)",\ # "(4,5)(15,16)", "(3,4)(14,15)", "(2,3)(13,14)", "(1,2)(12,13)" ] ) spectrum = [1, 0, 5, 0, 25, 0, 117, 0, 330, 0, 546, 0, 546, 0, 330, 0, 117, 0, 25, 0, 5, 0, 1] sd_codes_22_2 = {"order autgp":88473600,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":""} # [22,3]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[8],matId(n)[8]])) # G = PermutationGroup( [ "(11,22)", "(10,11)(21,22)", "(9,10)(20,21)",\ # "(7,8)(18,19)", "(7,18)(8,19)", "(6,7)(17,18)", "(5,6)(16,17)",\ # "(4,5)(15,16)", "(3,4)(14,15)", "(2,3)(13,14)", "(1,2)(12,13)" ] ) spectrum = [1, 0, 3, 0, 31, 0, 85, 0, 282, 0, 622, 0, 622, 0, 282, 0, 85, 0, 31, 0, 3, 0, 1] sd_codes_22_3 = {"order autgp":247726080,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Same spectrum as the '[20,5]' code."} # [22,4]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[10],matId(n)[10]])) # G = PermutationGroup( [ "(11,22)", "(9,10)(20,21)", "(9,20)(10,21)",\ # "(8,9)(19,20)", "(7,8)(18,19)", "(6,7)(17,18)", "(5,6)(16,17)",\ # "(4,5)(15,16)", "(3,4)(14,15)", "(2,3)(13,14)", "(1,2)(12,13)" ] ) spectrum = [1, 0, 1, 0, 45, 0, 45, 0, 210, 0, 722, 0, 722, 0, 210, 0, 45, 0, 45, 0, 1, 0, 1] sd_codes_22_4 = {"order autgp":3715891200,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Unique lowest weight codeword."} # [22,5]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[4],matA(n)[4],matId(n)[8]])) # G = PermutationGroup( [ "(11,22)", "(10,11)(21,22)", "(9,10)(20,21)",\ # "(8,16)(17,18)", "(8,17)(16,18)", "(7,8)(18,19)", "(6,7)(17,18)",\ # "(5,6)(16,17)", "(4,12)(13,14)", "(4,13)(12,14)", "(3,4)(14,15)",\ # "(2,3)(13,14)", "(1,2)(12,13)", "(1,5)(2,6)(3,7)(4,8)(12,16)(13,17)(14,18)(15,19)" ] ) spectrum = [1, 0, 3, 0, 31, 0, 85, 0, 282, 0, 622, 0, 622, 0, 282, 0, 85, 0, 31, 0, 3, 0, 1] sd_codes_22_5 = {"order autgp":173408256,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Same spectrum as the '[20,3]' code."} # [22,6]: genmat = I2(n).augment(block_diagonal_matrix([matA(n)[6],matA(n)[4],matId(n)[10]])) # G = PermutationGroup( [ "(11,22)", "(10,18)(19,20)", "(10,19)(18,20)",\ # "(9,10)(20,21)", "(8,9)(19,20)", "(7,8)(18,19)", "(5,6)(16,17)",\ # "(5,16)(6,17)", "(4,5)(15,16)", "(3,4)(14,15)", "(2,3)(13,14)", "(1,2)(12,13)" ] ) spectrum = [1, 0, 1, 0, 29, 0, 61, 0, 258, 0, 674, 0, 674, 0, 258, 0, 61, 0, 29, 0, 1, 0, 1] sd_codes_22_6 = {"order autgp":61931520,"code":LinearCode(genmat),"spectrum":spectrum,\ "Type":"I","Comment":"Unique lowest weight codeword."} sd_codes["22"] = {"0":sd_codes_22_0,"1":sd_codes_22_1,"2":sd_codes_22_2,\ "3":sd_codes_22_3,"4":sd_codes_22_4,"5":sd_codes_22_5,\ "6":sd_codes_22_6} return sd_codes
def as_permutation_group(self, algorithm=None): r""" Return a permutation group representation for the group. In most cases occurring in practice, this is a permutation group of minimal degree (the degree being determined from orbits under the group action). When these orbits are hard to compute, the procedure can be time-consuming and the degree may not be minimal. INPUT: - ``algorithm`` -- ``None`` or ``'smaller'``. In the latter case, try harder to find a permutation representation of small degree. OUTPUT: A permutation group isomorphic to ``self``. The ``algorithm='smaller'`` option tries to return an isomorphic group of low degree, but is not guaranteed to find the smallest one. EXAMPLES:: sage: MS = MatrixSpace(GF(2), 5, 5) sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]]) sage: G = MatrixGroup([A]) sage: G.as_permutation_group() Permutation Group with generators [(1,2)] A finite subgroup of GL(12,Z) as a permutation group:: sage: imf=libgap.function_factory('ImfMatrixGroup') sage: GG = imf( 12, 3 ) sage: G = MatrixGroup(GG.GeneratorsOfGroup()) sage: G.cardinality() 21499084800 sage: set_random_seed(0); current_randstate().set_seed_gap() sage: P = G.as_permutation_group() sage: P.cardinality() 21499084800 sage: P.degree() # random output 144 sage: set_random_seed(3); current_randstate().set_seed_gap() sage: Psmaller = G.as_permutation_group(algorithm="smaller") sage: Psmaller.cardinality() 21499084800 sage: Psmaller.degree() # random output 108 In this case, the "smaller" option returned an isomorphic group of lower degree. The above example used GAP's library of irreducible maximal finite ("imf") integer matrix groups to construct the MatrixGroup G over GF(7). The section "Irreducible Maximal Finite Integral Matrix Groups" in the GAP reference manual has more details. TESTS:: sage: A= matrix(QQ, 2, [0, 1, 1, 0]) sage: B= matrix(QQ, 2, [1, 0, 0, 1]) sage: a, b= MatrixGroup([A, B]).as_permutation_group().gens() sage: a.order(), b.order() (2, 1) The above example in GL(12,Z), reduced modulo 7:: sage: MS = MatrixSpace( GF(7), 12, 12) sage: G = MatrixGroup(map(MS, GG.GeneratorsOfGroup())) sage: G.cardinality() 21499084800 sage: P = G.as_permutation_group() sage: P.cardinality() 21499084800 Check that large degree is still working:: sage: Sp(6,3).as_permutation_group().cardinality() 9170703360 Check that ``_permutation_group_morphism`` works (:trac:`25706`):: sage: MG = GU(3,2).as_matrix_group() sage: PG = MG.as_permutation_group() # this constructs the morphism sage: mg = MG.an_element() sage: MG._permutation_group_morphism(mg) (1,2,6,19,35,33)(3,9,26,14,31,23)(4,13,5)(7,22,17)(8,24,12)(10,16,32,27,20,28)(11,30,18)(15,25,36,34,29,21) """ # Note that the output of IsomorphismPermGroup() depends on # memory locations and will change if you change the order of # doctests and/or architecture from sage.groups.perm_gps.permgroup import PermutationGroup if not self.is_finite(): raise NotImplementedError("Group must be finite.") iso = self._libgap_().IsomorphismPermGroup() if algorithm == "smaller": iso = iso.Image().SmallerDegreePermutationRepresentation() PG = PermutationGroup(iso.Image().GeneratorsOfGroup().sage(), \ canonicalize=False) # applying gap() - as PermutationGroup is not libGAP def permutation_group_map(element): return PG(iso.ImageElm(element.gap()).sage()) from sage.categories.homset import Hom self._permutation_group_morphism = Hom(self, PG)(permutation_group_map) return PG
def as_permutation_group(self, algorithm=None): r""" Return a permutation group representation for the group. In most cases occurring in practice, this is a permutation group of minimal degree (the degree being determined from orbits under the group action). When these orbits are hard to compute, the procedure can be time-consuming and the degree may not be minimal. INPUT: - ``algorithm`` -- ``None`` or ``'smaller'``. In the latter case, try harder to find a permutation representation of small degree. OUTPUT: A permutation group isomorphic to ``self``. The ``algorithm='smaller'`` option tries to return an isomorphic group of low degree, but is not guaranteed to find the smallest one. EXAMPLES:: sage: MS = MatrixSpace(GF(2), 5, 5) sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]]) sage: G = MatrixGroup([A]) sage: G.as_permutation_group() Permutation Group with generators [(1,2)] sage: MS = MatrixSpace( GF(7), 12, 12) sage: GG = gap("ImfMatrixGroup( 12, 3 )") sage: GG.GeneratorsOfGroup().Length() 3 sage: g1 = MS(eval(str(GG.GeneratorsOfGroup()[1]).replace("\n",""))) sage: g2 = MS(eval(str(GG.GeneratorsOfGroup()[2]).replace("\n",""))) sage: g3 = MS(eval(str(GG.GeneratorsOfGroup()[3]).replace("\n",""))) sage: G = MatrixGroup([g1, g2, g3]) sage: G.cardinality() 21499084800 sage: set_random_seed(0); current_randstate().set_seed_gap() sage: P = G.as_permutation_group() sage: P.cardinality() 21499084800 sage: P.degree() # random output 144 sage: set_random_seed(3); current_randstate().set_seed_gap() sage: Psmaller = G.as_permutation_group(algorithm="smaller") sage: Psmaller.cardinality() 21499084800 sage: Psmaller.degree() # random output 108 In this case, the "smaller" option returned an isomorphic group of lower degree. The above example used GAP's library of irreducible maximal finite ("imf") integer matrix groups to construct the MatrixGroup G over GF(7). The section "Irreducible Maximal Finite Integral Matrix Groups" in the GAP reference manual has more details. TESTS:: sage: A= matrix(QQ, 2, [0, 1, 1, 0]) sage: B= matrix(QQ, 2, [1, 0, 0, 1]) sage: a, b= MatrixGroup([A, B]).as_permutation_group().gens() sage: a.order(), b.order() (2, 1) Check that ``_permutation_group_morphism`` works (:trac:`25706`):: sage: MG = GU(3,2).as_matrix_group() sage: PG = MG.as_permutation_group() # this constructs the morphism sage: mg = MG.an_element() sage: MG._permutation_group_morphism(mg) (1,2,6,19,35,33)(3,9,26,14,31,23)(4,13,5)(7,22,17)(8,24,12)(10,16,32,27,20,28)(11,30,18)(15,25,36,34,29,21) """ # Note that the output of IsomorphismPermGroup() depends on # memory locations and will change if you change the order of # doctests and/or architecture from sage.groups.perm_gps.permgroup import PermutationGroup if not self.is_finite(): raise NotImplementedError("Group must be finite.") n = self.degree() MS = MatrixSpace(self.base_ring(), n, n) mats = [] # initializing list of mats by which the gens act on self for g in self.gens(): p = MS(g.matrix()) m = p.rows() mats.append(m) mats_str = str(gap([[list(r) for r in m] for m in mats])) gap.eval("iso:=IsomorphismPermGroup(Group("+mats_str+"))") gap_permutation_map = gap("iso;") if algorithm == "smaller": gap.eval("small:= SmallerDegreePermutationRepresentation( Image( iso ) );") C = gap("Image( small )") else: C = gap("Image( iso )") PG = PermutationGroup(gap_group=C, canonicalize=False) def permutation_group_map(element): return PG(gap_permutation_map.ImageElm(element.gap())) from sage.categories.homset import Hom self._permutation_group_morphism = Hom(self, PG)(permutation_group_map) return PG
def as_permutation_group(self, algorithm=None, seed=None): r""" Return a permutation group representation for the group. In most cases occurring in practice, this is a permutation group of minimal degree (the degree being determined from orbits under the group action). When these orbits are hard to compute, the procedure can be time-consuming and the degree may not be minimal. INPUT: - ``algorithm`` -- ``None`` or ``'smaller'``. In the latter case, try harder to find a permutation representation of small degree. - ``seed`` -- ``None`` or an integer specifying the seed to fix results depending on pseudo-random-numbers. Here it makes sense to be used with respect to the ``'smaller'`` option, since gap produces random output in that context. OUTPUT: A permutation group isomorphic to ``self``. The ``algorithm='smaller'`` option tries to return an isomorphic group of low degree, but is not guaranteed to find the smallest one and must not even differ from the one obtained without the option. In that case repeating the invocation may help (see the example below). EXAMPLES:: sage: MS = MatrixSpace(GF(2), 5, 5) sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]]) sage: G = MatrixGroup([A]) sage: G.as_permutation_group() Permutation Group with generators [(1,2)] A finite subgroup of GL(12,Z) as a permutation group:: sage: imf=libgap.function_factory('ImfMatrixGroup') sage: GG = imf( 12, 3 ) sage: G = MatrixGroup(GG.GeneratorsOfGroup()) sage: G.cardinality() 21499084800 sage: P = G.as_permutation_group() sage: Psmaller = G.as_permutation_group(algorithm="smaller", seed=6) sage: P == Psmaller # see the note below True sage: Psmaller = G.as_permutation_group(algorithm="smaller") sage: P == Psmaller False sage: P.cardinality() 21499084800 sage: P.degree() 144 sage: Psmaller.cardinality() 21499084800 sage: Psmaller.degree() 80 .. NOTE:: In this case, the "smaller" option returned an isomorphic group of lower degree. The above example used GAP's library of irreducible maximal finite ("imf") integer matrix groups to construct the MatrixGroup G over GF(7). The section "Irreducible Maximal Finite Integral Matrix Groups" in the GAP reference manual has more details. .. NOTE:: Concerning the option ``algorithm='smaller'`` you should note the following from GAP documentation: "The methods used might involve the use of random elements and the permutation representation (or even the degree of the representation) is not guaranteed to be the same for different calls of SmallerDegreePermutationRepresentation." To obtain a reproducible result the optional argument ``seed`` may be used as in the example above. TESTS:: sage: A= matrix(QQ, 2, [0, 1, 1, 0]) sage: B= matrix(QQ, 2, [1, 0, 0, 1]) sage: a, b= MatrixGroup([A, B]).as_permutation_group().gens() sage: a.order(), b.order() (2, 1) The above example in GL(12,Z), reduced modulo 7:: sage: MS = MatrixSpace(GF(7), 12, 12) sage: G = MatrixGroup([MS(g) for g in GG.GeneratorsOfGroup()]) sage: G.cardinality() 21499084800 sage: P = G.as_permutation_group() sage: P.cardinality() 21499084800 Check that large degree is still working:: sage: Sp(6,3).as_permutation_group().cardinality() 9170703360 Check that :trac:`25706` still works after :trac:`26903`:: sage: MG = GU(3,2).as_matrix_group() sage: PG = MG.as_permutation_group() sage: mg = MG.an_element() sage: PG(mg) (1,2,6,19,35,33)(3,9,26,14,31,23)(4,13,5)(7,22,17)(8,24,12)(10,16,32,27,20,28)(11,30,18)(15,25,36,34,29,21) """ # Note that the output of IsomorphismPermGroup() depends on # memory locations and will change if you change the order of # doctests and/or architecture from sage.groups.perm_gps.permgroup import PermutationGroup if not self.is_finite(): raise NotImplementedError("Group must be finite.") if seed is not None: from sage.libs.gap.libgap import libgap libgap.set_seed(ZZ(seed)) iso = self._libgap_().IsomorphismPermGroup() if algorithm == "smaller": iso = iso.Image().SmallerDegreePermutationRepresentation() return PermutationGroup(iso.Image().GeneratorsOfGroup().sage(), \ canonicalize=False)
def lattice_automorphism_group(self, points=None, point_labels=None): """ The integral subgroup of the restricted automorphism group. INPUT: - ``points`` -- A tuple of coordinate vectors or ``None`` (default). If specified, the points must form complete orbits under the lattice automorphism group. If ``None`` all vertices are used. - ``point_labels`` -- A tuple of labels for the ``points`` or ``None`` (default). These will be used as labels for the do permutation group. If ``None`` the ``points`` will be used themselves. OUTPUT: The integral subgroup of the restricted automorphism group acting on the given ``points``, or all vertices if not specified. EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: Z3square = LatticePolytope_PPL((0,0), (1,2), (2,1), (3,3)) sage: Z3square.lattice_automorphism_group() Permutation Group with generators [(), ((1,2),(2,1)), ((0,0),(3,3)), ((0,0),(3,3))((1,2),(2,1))] sage: G1 = Z3square.lattice_automorphism_group(point_labels=(1,2,3,4)); G1 Permutation Group with generators [(), (2,3), (1,4), (1,4)(2,3)] sage: G1.cardinality() 4 sage: G2 = Z3square.restricted_automorphism_group(vertex_labels=(1,2,3,4)) sage: G2 == PermutationGroup([[(2,3)], [(1,2),(3,4)], [(1,4)]]) True sage: G2.cardinality() 8 sage: points = Z3square.integral_points(); points ((0, 0), (1, 1), (1, 2), (2, 1), (2, 2), (3, 3)) sage: Z3square.lattice_automorphism_group(points, point_labels=(1,2,3,4,5,6)) Permutation Group with generators [(), (3,4), (1,6)(2,5), (1,6)(2,5)(3,4)] Point labels also work for lattice polytopes that are not full-dimensional, see :trac:`16669`:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: lp = LatticePolytope_PPL((1,0,0),(0,1,0),(-1,-1,0)) sage: lp.lattice_automorphism_group(point_labels=(0,1,2)) Permutation Group with generators [(), (1,2), (0,1), (0,1,2), (0,2,1), (0,2)] """ if not self.is_full_dimensional(): return self.affine_lattice_polytope().lattice_automorphism_group( point_labels=point_labels) if points is None: points = self.vertices() if point_labels is None: point_labels = tuple(points) points = [ vector(ZZ, [1]+v.list()) for v in points ] for p in points: p.set_immutable() vertices = [ vector(ZZ, [1]+v.list()) for v in self.vertices() ] pivots = matrix(ZZ, vertices).pivot_rows() basis = matrix(ZZ, [ vertices[i] for i in pivots ]) Mat_ZZ = basis.parent() basis_inverse = basis.inverse() from sage.groups.perm_gps.permgroup import PermutationGroup lattice_gens = [] G = self.restricted_automorphism_group( vertex_labels=tuple(range(len(vertices)))) for g in G: image = matrix(ZZ, [ vertices[g(i)] for i in pivots ]) m = basis_inverse*image if m not in Mat_ZZ: continue perm_list = [ point_labels[points.index(p*m)] for p in points ] lattice_gens.append(perm_list) return PermutationGroup(lattice_gens, domain=point_labels)
def permute_indices(self, permutation): r""" Return a tensor with indices with permuted indices. INPUT: - ``permutation`` -- permutation that has to be applied to the indices the input should be a ``list`` containing the second line of the permutation in Cauchy notation. OUTPUT: - an instance of ``TensorWithIndices`` whose indices names and place are those of ``self`` but whose components have been permuted with ``permutation``. EXAMPLES:: sage: M = FiniteRankFreeModule(QQ, 3, name='M') sage: e = M.basis('e') sage: a = M.tensor((2,0), name='a') sage: a[:] = [[1,2,3], [4,5,6], [7,8,9]] sage: b = M.tensor((2,0), name='b') sage: b[:] = [[-1,2,-3], [-4,5,6], [7,-8,9]] sage: identity = [0,1] sage: transposition = [1,0] sage: a["ij"].permute_indices(identity) == a["ij"] True sage: a["ij"].permute_indices(transposition)[:] == a[:].transpose() True sage: cycle = [1,2,3,0] # the cyclic permutation sending 0 to 1 sage: (a*b)[0,1,2,0] == (a*b)["ijkl"].permute_indices(cycle)[1,2,0,0] True TESTS:: sage: M = FiniteRankFreeModule(QQ, 3, name='M') sage: e = M.basis('e') sage: a = M.tensor((2,0), name='a') sage: a[:] = [[1,2,3], [4,5,6], [7,8,9]] sage: identity = [0,1] sage: transposition = [1,0] sage: a["ij"].permute_indices(identity) == a["ij"] True sage: a["ij"].permute_indices(transposition)[:] == a[:].transpose() True sage: (a*a)["ijkl"].permute_indices([1,2,3,0])[0,1,2,1] == (a*a)[1,2,1,0] True """ # Decomposition of the permutation of the components of self # into product of swaps given by the method # sage.tensor.modules.comp.Components.swap_adjacent_indices # A swap is determined by 3 distinct integers swap_params = list( combinations(range(self._tensor.tensor_rank() + 1), 3)) # The associated permutation is as follows def swap(param, N): i, j, k = param L = list(range(1, N + 1)) L = L[:i] + L[j:k] + L[i:j] + L[k:] return L # Construction of the permutation group generated by swaps perm_group = PermutationGroup( [swap(param, self._tensor.tensor_rank()) for param in swap_params], canonicalize=False) # Compute a decomposition of the permutation as a product of swaps decomposition_as_string = perm_group( [x + 1 for x in permutation]).word_problem(perm_group.gens(), display=False)[0] if decomposition_as_string != "<identity ...>": decomposition_as_string = [ # Two cases wether the term appear with an exponent or not ("^" in term) * term.split("^") + ("^" not in term) * (term.split("^") + ['1']) for term in decomposition_as_string.replace("x", "").split("*") ] decomposition = [(swap_params[int(x) - 1], int(y)) for x, y in decomposition_as_string] decomposition.reverse( ) # /!\ The symetric group acts on the right by default /!\. else: decomposition = [] # Choice of a basis basis = self._tensor._fmodule._def_basis # Swap of components swaped_components = self._tensor.comp(basis) for swap_param, exponent in decomposition: if exponent > 0: for i in range(exponent): # Apply the swap given by swap_param swaped_components = swaped_components\ .swap_adjacent_indices(*swap_param) elif exponent < 0: for i in range(-exponent): # Apply the opposite of the swap given by swap_param swaped_components = swaped_components\ .swap_adjacent_indices( swap_param[0], swap_param[0] + swap_param[2] - swap_param[1], swap_param[2] ) else: pass result = self.__pos__() result._tensor = self._tensor._fmodule.tensor_from_comp( self._tensor.tensor_type(), swaped_components) return result
def as_permutation_group(self, algorithm=None): r""" Return a permutation group representation for the group. In most cases occurring in practice, this is a permutation group of minimal degree (the degree begin determined from orbits under the group action). When these orbits are hard to compute, the procedure can be time-consuming and the degree may not be minimal. INPUT: - ``algorithm`` -- ``None`` or ``'smaller'``. In the latter case, try harder to find a permutation representation of small degree. OUTPUT: A permutation group isomorphic to ``self``. The ``algorithm='smaller'`` option tries to return an isomorphic group of low degree, but is not guaranteed to find the smallest one. EXAMPLES:: sage: MS = MatrixSpace(GF(2), 5, 5) sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]]) sage: G = MatrixGroup([A]) sage: G.as_permutation_group() Permutation Group with generators [(1,2)] sage: MS = MatrixSpace( GF(7), 12, 12) sage: GG = gap("ImfMatrixGroup( 12, 3 )") sage: GG.GeneratorsOfGroup().Length() 3 sage: g1 = MS(eval(str(GG.GeneratorsOfGroup()[1]).replace("\n",""))) sage: g2 = MS(eval(str(GG.GeneratorsOfGroup()[2]).replace("\n",""))) sage: g3 = MS(eval(str(GG.GeneratorsOfGroup()[3]).replace("\n",""))) sage: G = MatrixGroup([g1, g2, g3]) sage: G.cardinality() 21499084800 sage: set_random_seed(0); current_randstate().set_seed_gap() sage: P = G.as_permutation_group() sage: P.cardinality() 21499084800 sage: P.degree() # random output 144 sage: set_random_seed(3); current_randstate().set_seed_gap() sage: Psmaller = G.as_permutation_group(algorithm="smaller") sage: Psmaller.cardinality() 21499084800 sage: Psmaller.degree() # random output 108 In this case, the "smaller" option returned an isomorphic group of lower degree. The above example used GAP's library of irreducible maximal finite ("imf") integer matrix groups to construct the MatrixGroup G over GF(7). The section "Irreducible Maximal Finite Integral Matrix Groups" in the GAP reference manual has more details. """ # Note that the output of IsomorphismPermGroup() depends on # memory locations and will change if you change the order of # doctests and/or architecture from sage.groups.perm_gps.permgroup import PermutationGroup if not self.is_finite(): raise NotImplementedError, "Group must be finite." n = self.degree() MS = MatrixSpace(self.base_ring(), n, n) mats = [] # initializing list of mats by which the gens act on self for g in self.gens(): p = MS(g.matrix()) m = p.rows() mats.append(m) mats_str = str(gap([[list(r) for r in m] for m in mats])) gap.eval("iso:=IsomorphismPermGroup(Group(" + mats_str + "))") if algorithm == "smaller": gap.eval( "small:= SmallerDegreePermutationRepresentation( Image( iso ) );" ) C = gap("Image( small )") else: C = gap("Image( iso )") return PermutationGroup(gap_group=C)