def __iter__(self):
        """
        Iterate over ``self``.

        EXAMPLES::

            sage: G = SymmetricGroup(4)
            sage: C = G.conjugacy_class(Partition([3,1]))
            sage: for x in C: x
            (2,3,4)
            (2,4,3)
            (1,3,4)
            (1,4,3)
            (1,2,4)
            (1,4,2)
            (1,2,3)
            (1,3,2)
        """
        if self._set:
            for x in self._set:
                yield x
            return

        for x in conjugacy_class_iterator(self._part, self._parent.domain()):
            yield PermutationGroupElement(x, self._parent, check=False)
def perm_to_permutation(l):
    r"""
    Returns a permutation on `[1, n]` from a list on `[0, n-1]`

    EXAMPLES::

        sage: from surface_dynamics.misc.permutation import perm_to_permutation
        sage: perm_to_permutation([2,1,0])
        (1,3)
    """
    from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
    return PermutationGroupElement(map(lambda x: x + 1, l))
Exemple #3
0
    def __cmp__(self, other):
        r"""
        Compare self to other. For some bizarre reason, if you just let it
        inherit the cmp routine from PermutationGroupElement, cmp(x, y) works
        but sorting lists doesn't.

        TEST::

            sage: K.<a> = NumberField(x^6 + 40*x^3 + 1372);G = K.galois_group()
            sage: sorted([G.artin_symbol(Q) for Q in K.primes_above(5)])
            [(1,3)(2,6)(4,5), (1,2)(3,4)(5,6), (1,5)(2,4)(3,6)]
        """
        return PermutationGroupElement.__cmp__(self, other)
Exemple #4
0
 def __cmp__(self, other):
     r"""
     Compare self to other. For some bizarre reason, if you just let it
     inherit the cmp routine from PermutationGroupElement, cmp(x, y) works
     but sorting lists doesn't.
     
     TEST::
     
         sage: K.<a> = NumberField(x^6 + 40*x^3 + 1372);G = K.galois_group()
         sage: sorted([G.artin_symbol(Q) for Q in K.primes_above(5)])
         [(1,3)(2,6)(4,5), (1,2)(3,4)(5,6), (1,5)(2,4)(3,6)]
     """
     return PermutationGroupElement.__cmp__(self, other)
    def set(self):
        r"""
        The set of all elements in the conjugacy class ``self``.

        EXAMPLES::

            sage: G = SymmetricGroup(3)
            sage: g = G((1,2))
            sage: C = G.conjugacy_class(g)
            sage: S = [(2,3), (1,2), (1,3)]
            sage: C.set() == Set(G(x) for x in S)
            True
        """
        if not self._set:
            self._set = Set(PermutationGroupElement(x, self._parent, check=False)
                            for x in conjugacy_class_iterator(self._part, self._domain) )
        return self._set
    def _tableau_dict(self):
        r"""
        A dictionary pairing the vertices of the underlying Yang-Baxter
        graph with standard tableau.

        EXAMPLES::

            sage: orth = SymmetricGroupRepresentation([3,2], "orthogonal")
            sage: orth._tableau_dict
            {(0, 2, 1, -1, 0): [[1, 3, 4], [2, 5]], (2, 0, -1, 1, 0): [[1, 2, 5], [3, 4]], (2, 0, 1, -1, 0): [[1, 3, 5], [2, 4]], (0, 2, -1, 1, 0): [[1, 2, 4], [3, 5]], (0, -1, 2, 1, 0): [[1, 2, 3], [4, 5]]}
        """
        # construct a dictionary pairing vertices with tableau
        t = StandardTableaux(self._partition).last()
        tableau_dict = {self._yang_baxter_graph.root():t}
        for (u,w,(i,beta)) in self._yang_baxter_graph._edges_in_bfs():
            # TODO: improve the following
            si = PermutationGroupElement((i,i+1))
            tableau_dict[w] = Tableau([map(si, row) for row in tableau_dict[u]])
        return tableau_dict
def default_representative(part, G):
    r"""
    Construct the default representative for the conjugacy class of
    cycle type ``part`` of a symmetric group ``G``.

    Let `\lambda` be a partition of `n`. We pick a representative by

    .. MATH::

        (1, 2, \ldots, \lambda_1)
        (\lambda_1 + 1, \ldots, \lambda_1 + \lambda_2)
        (\lambda_1 + \lambda_2 + \cdots + \lambda_{\ell-1}, \ldots, n),

    where `\ell` is the length (or number of parts) of `\lambda`.

    INPUT:

    - ``part`` -- partition

    - ``G`` -- a symmetric group

    EXAMPLES::

        sage: from sage.groups.perm_gps.symgp_conjugacy_class import default_representative
        sage: S = SymmetricGroup(4)
        sage: for p in Partitions(4):
        ....:     print default_representative(p, S)
        (1,2,3,4)
        (1,2,3)
        (1,2)(3,4)
        (1,2)
        ()
    """
    D = G.domain()
    total = 0
    cycles = []
    for p in part:
        cycles.append(tuple(D[total:total+p]))
        total += p
    # TODO: Change this to G.element_class(cycles, check=False)
    #   once SymmetricGroup is a proper parent.
    return PermutationGroupElement(cycles, G, check=False)
Exemple #8
0
    def extrude_edge(self, vertex, dart1, dart2):
        r"""
        Return a ribbon graph resulting from extruding an edge from a
        vertex, pulling from it, all darts from ``dart1`` to ``dart2``
        including both.

        INPUT:

        - ``vertex`` -- the position of the vertex in the permutation
          `\sigma`, which must have valency at least 2

        - ``dart1`` -- the position of the first in the
          cycle corresponding to ``vertex``

        - ``dart2`` -- the position of the second dart in the cycle
          corresponding to ``vertex``

        OUTPUT:

        A ribbon graph resulting from extruding a new edge that 
        pulls from ``vertex`` a new vertex that is, now, adjacent
        to all the darts from ``dart1``to ``dart2`` (not including
        ``dart2``) in the cyclic ordering given by the cycle corresponding
        to ``vertex``. Note that ``dart1`` may be equal to ``dart2``
        allowing thus to extrude a contractible edge from a vertex.

        EXAMPLES:

        We try several possibilities in the same graph::

            sage: s1 = PermutationGroupElement('(1,3,5)(2,4,6)')
            sage: r1 = PermutationGroupElement('(1,2)(3,4)(5,6)')
            sage: R1 = RibbonGraph(s1,r1); R1
            Ribbon graph of genus 1 and 1 boundary components
            sage: E1 = R1.extrude_edge(1,1,2); E1
            Ribbon graph of genus 1 and 1 boundary components
            sage: E1.sigma()
            (1,3,5)(2,8,6)(4,7)
            sage: E1.rho()
            (1,2)(3,4)(5,6)(7,8)
            sage: E2 = R1.extrude_edge(1,1,3); E2
            Ribbon graph of genus 1 and 1 boundary components
            sage: E2.sigma()
            (1,3,5)(2,8)(4,6,7)
            sage: E2.rho()
            (1,2)(3,4)(5,6)(7,8)

        We can also extrude a contractible edge from a vertex. This
        new edge will end at a vertex of valency 1::

            sage: E1p = R1.extrude_edge(0,0,0); E1p
            Ribbon graph of genus 1 and 1 boundary components
            sage: E1p.sigma()
            (1,3,5,8)(2,4,6)
            sage: E1p.rho()
            (1,2)(3,4)(5,6)(7,8)

        In the following example we first extrude one edge from a vertex
        of valency 3 generating a new vertex of valency 2. Then we 
        extrude a new edge from this vertex of valency 2::

            sage: s1 = PermutationGroupElement('(1,3,5)(2,4,6)')
            sage: r1 = PermutationGroupElement('(1,2)(3,4)(5,6)')
            sage: R1 = RibbonGraph(s1,r1); R1
            Ribbon graph of genus 1 and 1 boundary components
            sage: E1 = R1.extrude_edge(0,0,1); E1
            Ribbon graph of genus 1 and 1 boundary components
            sage: E1.sigma()
            (1,7)(2,4,6)(3,5,8)
            sage: E1.rho()
            (1,2)(3,4)(5,6)(7,8)
            sage: F1 = E1.extrude_edge(0,0,1); F1
            Ribbon graph of genus 1 and 1 boundary components
            sage: F1.sigma()
            (1,9)(2,4,6)(3,5,8)(7,10)
            sage: F1.rho()
            (1,2)(3,4)(5,6)(7,8)(9,10)
        """
        #We first compute the vertices of valency 1 as in _repr_
        repr_sigma = [list(x) for x in self._sigma.cycle_tuples()]
        repr_rho = [list(x) for x in self._rho.cycle_tuples()]
        darts_rho = flatten(repr_rho)
        darts_sigma = flatten(repr_sigma)
        val_one = [x for x in darts_rho if x not in darts_sigma]
        for val in val_one:
            repr_sigma += [[val]]

        # We find which is the highes value a dart has, in order to
        #   add new darts that do not conflict with previous ones.
        k = max(darts_rho)

        # We create the new vertex and append it to sigma.
        new_vertex = [repr_sigma[vertex][j] for j in range(dart1, dart2)]
        new_vertex.insert(0, k + 1)
        repr_sigma.append(new_vertex)

        # We add the new dart at the vertex from which we are extruding
        #   an edge. Also we delete the darts that have been extruded.
        repr_sigma[vertex].insert(dart1, k + 2)
        del repr_sigma[vertex][dart1 + 1:dart2 + 1]

        #We update rho
        repr_rho.append([k + 1, k + 2])

        perm_group = self._sigma.parent()
        return RibbonGraph(
            PermutationGroupElement([tuple(x) for x in repr_sigma]),
            PermutationGroupElement([tuple(x) for x in repr_rho]))
Exemple #9
0
    def contract_edge(self, k):
        r"""
        Return the ribbon graph resulting from the contraction of
        the ``k``-th edge in ``self``.

        For a ribbon graph `(\sigma, \rho)`, we contract the edge
        corresponding to the `k`-th transposition of `\rho`.

        INPUT:

        - ``k`` -- non-negative integer; the position in `\rho` of the 
          transposition that is going to be contracted

        OUTPUT:

        - a ribbon graph resulting from the contraction of that edge

        EXAMPLES:

        We start again with the one-holed torus ribbon graph::

            sage: s1 = PermutationGroupElement('(1,3,5)(2,4,6)')
            sage: r1 = PermutationGroupElement('(1,2)(3,4)(5,6)')
            sage: R1 = RibbonGraph(s1,r1); R1
            Ribbon graph of genus 1 and 1 boundary components
            sage: S1 = R1.contract_edge(1); S1
            Ribbon graph of genus 1 and 1 boundary components
            sage: S1.sigma()
            (1,6,2,5)
            sage: S1.rho()
            (1,2)(5,6)

        However, this ribbon graphs is formed only by loops and hence
        it cannot be longer reduced, we get an error if we try to
        contract a loop::

            sage: S1.contract_edge(1)
            Traceback (most recent call last):
            ...
            ValueError: the edge is a loop and cannot be contracted

        In this example, we consider a graph that has one edge ``(19,20)``
        such that one of its ends is a vertex of valency 1. This is 
        the vertex ``(20)`` that is not specified when defining `\sigma`.
        We contract precisely this edge and get a ribbon graph with no
        vertices of valency 1::

            sage: s2 = PermutationGroupElement('(1,2,3)(4,5,6)(7,8,9)(10,11,12)(13,14,15)(16,17,18,19)')
            sage: r2 = PermutationGroupElement('(1,16)(2,13)(3,10)(4,17)(5,14)(6,11)(7,18)(8,15)(9,12)(19,20)')
            sage: R2 = RibbonGraph(s2,r2); R2
            Ribbon graph of genus 1 and 3 boundary components
            sage: R2.sigma()
            (1,2,3)(4,5,6)(7,8,9)(10,11,12)(13,14,15)(16,17,18,19)
            sage: R2c = R2.contract_edge(9); R2; R2c.sigma(); R2c.rho()
            Ribbon graph of genus 1 and 3 boundary components
            (1,2,3)(4,5,6)(7,8,9)(10,11,12)(13,14,15)(16,17,18)
            (1,16)(2,13)(3,10)(4,17)(5,14)(6,11)(7,18)(8,15)(9,12)
        """
        #the following two lines convert the list of tuples to list of lists
        aux_sigma = [
            list(x) for x in self._sigma.cycle_tuples(singletons=True)
        ]
        aux_rho = [list(x) for x in self._rho.cycle_tuples()]
        #The following ''if'' rules out the cases when we would be
        #contracting a loop (which is not admissible since we would
        #lose the topological type of the graph).
        if (_find(aux_sigma,
                  aux_rho[k][0])[0] == _find(aux_sigma, aux_rho[k][1])[0]):
            raise ValueError("the edge is a loop and cannot be contracted")
        #We store in auxiliary variables the positions of the vertices
        #that are the ends of the edge to be contracted and we delete
        #from them the darts corresponding to the edge that is going
        #to be contracted. We also delete the contracted edge
        #from aux_rho
        pos1 = _find(aux_sigma, aux_rho[k][0])
        pos2 = _find(aux_sigma, aux_rho[k][1])
        del aux_sigma[pos1[0]][pos1[1]]
        del aux_sigma[pos2[0]][pos2[1]]
        del aux_rho[k]

        #Now we insert in one of the two vertices, the darts of the other
        #vertex that appears after. We make sure that we don't
        #change the topological type of the thickening of the graph by
        #preserving the cyclic ordering.
        n = len(aux_sigma[pos2[0]])
        for i in range(n):
            aux_sigma[pos1[0]].insert(pos1[1] + i,
                                      aux_sigma[pos2[0]][(pos2[1] + i) % n])
        #Finally we delete the vertex from which we copied all the darts.
        del aux_sigma[pos2[0]]

        #Now we convert this data that is on the form of lists of lists
        #to actual permutations that form a ribbon graph.
        return RibbonGraph(
            PermutationGroupElement([tuple(x) for x in aux_sigma]),
            PermutationGroupElement([tuple(x) for x in aux_rho]))
Exemple #10
0
def bipartite_ribbon_graph(p, q):
    r"""
    Return the bipartite graph modeling the corresponding
    Brieskorn-Pham singularity.

    Take two parallel lines in the plane, and consider `p` points in
    one of them and `q` points in the other. Join with a line each
    point from the first set with every point with the second set.
    The resulting is a planar projection of the complete bipartite
    graph of type `(p,q)`. If you consider the cyclic ordering at
    each vertex induced by the positive orientation of the plane,
    the result is a ribbon graph whose associated orientable surface
    with boundary is homeomorphic to the Milnor fiber of the
    Brieskorn-Pham singularity `x^p + y^q`. It satisfies that it has
    `\gcd(p,q)` number of  boundary components and genus
    `(pq - p - q - \gcd(p,q) - 2) / 2`.

    INPUT:

    - ``p`` -- a positive integer
    - ``q`` -- a positive integer

    EXAMPLES::

        sage: B23 = RibbonGraph(2,3,bipartite=True); B23; B23.sigma(); B23.rho()
        Ribbon graph of genus 1 and 1 boundary components
        (1,2,3)(4,5,6)(7,8)(9,10)(11,12)
        (1,8)(2,10)(3,12)(4,7)(5,9)(6,11)

        sage: B32 = RibbonGraph(3,2,bipartite=True); B32; B32.sigma(); B32.rho()
        Ribbon graph of genus 1 and 1 boundary components
        (1,2)(3,4)(5,6)(7,8,9)(10,11,12)
        (1,9)(2,12)(3,8)(4,11)(5,7)(6,10)

        sage: B33 = RibbonGraph(3,3,bipartite=True); B33; B33.sigma(); B33.rho()
        Ribbon graph of genus 1 and 3 boundary components
        (1,2,3)(4,5,6)(7,8,9)(10,11,12)(13,14,15)(16,17,18)
        (1,12)(2,15)(3,18)(4,11)(5,14)(6,17)(7,10)(8,13)(9,16)

        sage: B24 = RibbonGraph(2,4,bipartite=True); B24; B24.sigma(); B24.rho()
        Ribbon graph of genus 1 and 2 boundary components
        (1,2,3,4)(5,6,7,8)(9,10)(11,12)(13,14)(15,16)
        (1,10)(2,12)(3,14)(4,16)(5,9)(6,11)(7,13)(8,15)

        sage: B47 = RibbonGraph(4,7, bipartite=True); B47; B47.sigma(); B47.rho()
        Ribbon graph of genus 9 and 1 boundary components
        (1,2,3,4,5,6,7)(8,9,10,11,12,13,14)(15,16,17,18,19,20,21)(22,23,24,25,26,27,28)(29,30,31,32)(33,34,35,36)(37,38,39,40)(41,42,43,44)(45,46,47,48)(49,50,51,52)(53,54,55,56)
        (1,32)(2,36)(3,40)(4,44)(5,48)(6,52)(7,56)(8,31)(9,35)(10,39)(11,43)(12,47)(13,51)(14,55)(15,30)(16,34)(17,38)(18,42)(19,46)(20,50)(21,54)(22,29)(23,33)(24,37)(25,41)(26,45)(27,49)(28,53)

    """
    sigma = []
    rho = []
    for i in range(p):
        aux_tuple = [i * q + j + 1 for j in range(q)]
        sigma += [aux_tuple]
    for i in range(q):
        aux_tuple = [p * q + i * p + j + 1 for j in range(p)]
        sigma += [aux_tuple]
    for i in range(p * q):
        if (i + 1) % q == 0:
            k = q
        elif (i + 1) % q != 0:
            k = (i + 1) % q
        t = 0
        if (i + 1) % q != 0:
            t = 1
        aux_edge = [i + 1, p * q + k * p - ((i + 1 + t * q) / q).floor() + 1]
        rho += [aux_edge]
    return RibbonGraph(PermutationGroupElement([tuple(x) for x in sigma]),
                       PermutationGroupElement([tuple(x) for x in rho]))
Exemple #11
0
def make_ribbon(g, r):
    r"""
    Return a ribbon graph whose thickening has genus ``g`` and ``r``
    boundary components.

    INPUT:

    - ``g`` -- non-negative integer representing the genus of the
      thickening

    - ``r`` -- positive integer representing the number of boundary
      components of the thickening

    OUTPUT:

    - a ribbon graph that has 2 vertices (two non-trivial cycles 
      in its sigma permutation) of valency `2g + r` and it has 
      `2g + r` edges (and hence `4g + 2r` darts)

    EXAMPLES::

        sage: from sage.geometry.ribbon_graph import make_ribbon
        sage: R = make_ribbon(0,1); R
        Ribbon graph of genus 0 and 1 boundary components
        sage: R.sigma()
        ()
        sage: R.rho()
        (1,2)

        sage: R = make_ribbon(0,5); R
        Ribbon graph of genus 0 and 5 boundary components
        sage: R.sigma()
        (1,9,7,5,3)(2,4,6,8,10)
        sage: R.rho()
        (1,2)(3,4)(5,6)(7,8)(9,10)

        sage: R = make_ribbon(1,1); R
        Ribbon graph of genus 1 and 1 boundary components
        sage: R.sigma()
        (1,2,3)(4,5,6)
        sage: R.rho()
        (1,4)(2,5)(3,6)

        sage: R = make_ribbon(7,3); R
        Ribbon graph of genus 7 and 3 boundary components
        sage: R.sigma()
        (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,33,31)(16,32,34,17,18,19,20,21,22,23,24,25,26,27,28,29,30)
        sage: R.rho()
        (1,16)(2,17)(3,18)(4,19)(5,20)(6,21)(7,22)(8,23)(9,24)(10,25)(11,26)(12,27)(13,28)(14,29)(15,30)(31,32)(33,34)

    """
    #Initialize the two vertices of sigma and the edge joining them
    repr_sigma = [[1], [2 * g + 2]]
    repr_rho = [[1, 2 * g + 2]]

    #We first generate the surface of genus g and 1 boundary component.
    #This is done by considering the usual planar representation of
    #a surface as a polygon of 4*g+2 edges with identifications. (see
    #any topology  book on the classification of surfaces)
    for i in range(2 * g):
        repr_sigma[0].append(i + 2)
        repr_sigma[1].append(i + (2 * g + 2) + 1)
        repr_rho += [[i + 2, i + (2 * g + 2) + 1]]

    #finally we add an edge for each additional boundary component.
    max_dart = 4 * g + 2
    for j in range(r - 1):
        repr_sigma[0].insert(0, max_dart + 2 * (j + 1) - 1)
        repr_sigma[1].insert(j + 1, max_dart + 2 * (j + 1))
        repr_rho += [[max_dart + 2 * (j + 1) - 1, max_dart + 2 * (j + 1)]]

    return RibbonGraph(PermutationGroupElement([tuple(x) for x in repr_sigma]),
                       PermutationGroupElement([tuple(x) for x in repr_rho]))
Exemple #12
0
    def normalize(self):
        r"""
        Return an equivalent graph such that the enumeration of its darts
        exhausts all numbers from 1 to the number of darts.

        OUTPUT:

        - a ribbon graph equivalent to ``self`` such that the enumeration
          of its darts exhausts all numbers from 1 to the number of darts.

        EXAMPLES::

            sage: s0 = PermutationGroupElement('(1,22,3,4,5,6,7,15)(8,16,9,10,11,12,13,14)')
            sage: r0 = PermutationGroupElement('(1,8)(22,9)(3,10)(4,11)(5,12)(6,13)(7,14)(15,16)')
            sage: R0 = RibbonGraph(s0,r0); R0
            Ribbon graph of genus 3 and 2 boundary components
            sage: RN0 = R0.normalize(); RN0; RN0.sigma(); RN0.rho()
            Ribbon graph of genus 3 and 2 boundary components
            (1,16,2,3,4,5,6,14)(7,15,8,9,10,11,12,13)
            (1,7)(2,9)(3,10)(4,11)(5,12)(6,13)(8,16)(14,15)

            sage: s1 = PermutationGroupElement('(5,10,12)(30,34,78)')
            sage: r1 = PermutationGroupElement('(5,30)(10,34)(12,78)')
            sage: R1 = RibbonGraph(s1,r1); R1
            Ribbon graph of genus 1 and 1 boundary components
            sage: RN1 = R1.normalize(); RN1; RN1.sigma(); RN1.rho()
            Ribbon graph of genus 1 and 1 boundary components
            (1,2,3)(4,5,6)
            (1,4)(2,5)(3,6)

        """
        #First we compute the vertices of valency 1 and store them in val_one.
        aux_sigma = [list(x) for x in self._sigma.cycle_tuples()]
        aux_rho = [list(x) for x in self._rho.cycle_tuples()]
        darts_rho = flatten(aux_rho)
        darts_sigma = flatten(aux_sigma)
        val_one = [x for x in darts_rho if x not in darts_sigma]

        #We add them to aux_sigma
        for i in range(len(val_one)):
            aux_sigma += [[val_one[i]]]
        #Now we proceed to normalize the numbers enumerating the darts.
        #We do this by checking if every number from 1 to len(darts_rho)
        #is actually in darts_rho.
        for i in range(len(darts_rho)):
            found = i + 1 in darts_rho
            #if a value is not in darts_rho, we take the next number that appears
            #and change it to the new value.
            if not found:
                aux_val = min(x for x in darts_rho if x > i + 1)
                pos_darts = darts_rho.index(aux_val)
                pos_rho = _find(aux_rho, aux_val)
                pos_sigma = _find(aux_sigma, aux_val)

                #Now we set the found positions to the new normalized value
                darts_rho[pos_darts] = i + 1
                aux_sigma[pos_sigma[0]][pos_sigma[1]] = i + 1
                aux_rho[pos_rho[0]][pos_rho[1]] = i + 1

        return RibbonGraph(
            PermutationGroupElement([tuple(x) for x in aux_sigma]),
            PermutationGroupElement([tuple(x) for x in aux_rho]))