Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
0
    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)
Exemple #6
0
    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])
Exemple #7
0
    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)
Exemple #9
0
    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)
        ])
Exemple #10
0
    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)])
Exemple #11
0
 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)
Exemple #12
0
    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())
Exemple #15
0
    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)
Exemple #16
0
    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
Exemple #18
0
    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)
Exemple #19
0
 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)
Exemple #20
0
    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)
Exemple #21
0
    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())
Exemple #22
0
    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)]))
Exemple #23
0
    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))
Exemple #24
0
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
Exemple #25
0
    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
Exemple #26
0
    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
Exemple #27
0
    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
Exemple #30
0
    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)