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, -1, 2, 1, 0): [[1, 2, 3], [4, 5]],
             (0, 2, -1, 1, 0): [[1, 2, 4], [3, 5]],
             (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]]}
        """
        # 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 = PermutationConstructor((i, i + 1))
            tableau_dict[w] = Tableau([[si(b) for b in row]
                                       for row in tableau_dict[u]])
        return tableau_dict
Пример #2
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 highest 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])

        return RibbonGraph(PermutationConstructor([tuple(x) for x in repr_sigma]),
                           PermutationConstructor([tuple(x) for x in repr_rho]))
Пример #3
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(PermutationConstructor([tuple(x) for x in aux_sigma]),
                           PermutationConstructor([tuple(x) for x in aux_rho]))
Пример #4
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(
                       PermutationConstructor([tuple(x) for x in sigma]),
                       PermutationConstructor([tuple(x) for x in rho])
                       )
Пример #5
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(PermutationConstructor([tuple(x) for x in repr_sigma]),
                       PermutationConstructor([tuple(x) for x in repr_rho]))
Пример #6
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(
                        PermutationConstructor([tuple(x) for x in aux_sigma]),
                        PermutationConstructor([tuple(x) for x in aux_rho])
                        )