Exemple #1
0
    def plot_n_matrices_eigenvectors(self, n, side='right', color_index=0, draw_line=False):
        r"""
        INPUT:

        - ``n`` -- integer, length
        - ``side`` -- ``'left'`` or ``'right'``, drawing left or right
          eigenvectors
        - ``color_index`` -- 0 for first letter, -1 for last letter
        - ``draw_line`` -- boolean

        EXAMPLES::

            sage: from slabbe.matrix_cocycle import cocycles
            sage: ARP = cocycles.ARP()
            sage: G = ARP.plot_n_matrices_eigenvectors(2)
        """
        from sage.plot.graphics import Graphics
        from sage.plot.point import point
        from sage.plot.line import line
        from sage.plot.text import text
        from sage.plot.colors import hue
        from sage.modules.free_module_element import vector
        from matrices import M3to2
        R = self.n_matrices_eigenvectors(n)
        L = [(w, M3to2*(a/sum(a)), M3to2*(b/sum(b))) for (w,a,b) in R]
        G = Graphics()
        alphabet = self._language._alphabet
        color_ = dict( (letter, hue(i/float(len(alphabet)))) for i,letter in
                enumerate(alphabet))
        for letter in alphabet:
            L_filtered = [(w,p1,p2) for (w,p1,p2) in L if w[color_index] == letter]
            words,rights,lefts = zip(*L_filtered)
            if side == 'right':
                G += point(rights, color=color_[letter], legend_label=letter)
            elif side == 'left':
                G += point(lefts,  color=color_[letter], legend_label=letter)
            else:
                raise ValueError("side(=%s) should be left or right" % side)

        if draw_line:
            for (a,b) in L:
                G += line([a,b], color='black', linestyle=":")
        G += line([M3to2*vector(a) for a in [(1,0,0), (0,1,0), (0,0,1), (1,0,0)]]) 
        title = "%s eigenvectors, colored by letter w[%s] of cylinder w" % (side, color_index)
        G += text(title, (0.5, 1.05), axis_coords=True)
        G.axes(False)
        return G
Exemple #2
0
    def plot_n_matrices_eigenvectors(self, n, side='right', color_index=0, draw_line=False):
        r"""
        INPUT:

        - ``n`` -- integer, length
        - ``side`` -- ``'left'`` or ``'right'``, drawing left or right
          eigenvectors
        - ``color_index`` -- 0 for first letter, -1 for last letter
        - ``draw_line`` -- boolean

        EXAMPLES::

            sage: from slabbe.matrix_cocycle import cocycles
            sage: ARP = cocycles.ARP()
            sage: G = ARP.plot_n_matrices_eigenvectors(2)
        """
        from sage.plot.graphics import Graphics
        from sage.plot.point import point
        from sage.plot.line import line
        from sage.plot.text import text
        from sage.plot.colors import hue
        from sage.modules.free_module_element import vector
        from .matrices import M3to2
        R = self.n_matrices_eigenvectors(n)
        L = [(w, M3to2*(a/sum(a)), M3to2*(b/sum(b))) for (w,a,b) in R]
        G = Graphics()
        alphabet = self._language._alphabet
        color_ = dict( (letter, hue(i/float(len(alphabet)))) for i,letter in
                enumerate(alphabet))
        for letter in alphabet:
            L_filtered = [(w,p1,p2) for (w,p1,p2) in L if w[color_index] == letter]
            words,rights,lefts = zip(*L_filtered)
            if side == 'right':
                G += point(rights, color=color_[letter], legend_label=letter)
            elif side == 'left':
                G += point(lefts,  color=color_[letter], legend_label=letter)
            else:
                raise ValueError("side(=%s) should be left or right" % side)

        if draw_line:
            for (a,b) in L:
                G += line([a,b], color='black', linestyle=":")
        G += line([M3to2*vector(a) for a in [(1,0,0), (0,1,0), (0,0,1), (1,0,0)]]) 
        title = "%s eigenvectors, colored by letter w[%s] of cylinder w" % (side, color_index)
        G += text(title, (0.5, 1.05), axis_coords=True)
        G.axes(False)
        return G
Exemple #3
0
    def plot(self, m, pointsize=100, thickness=3, axes=False):
        r"""
        Return 2d graphics object contained in the primal box [-m,m]^d.

        INPUT:

        - ``pointsize``, integer (default:``100``),
        - ``thickness``, integer (default:``3``),
        - ``axes``, bool (default:``False``),

        EXAMPLES::

            sage: from slabbe import BondPercolationSample
            sage: S = BondPercolationSample(0.5,2)
            sage: S.plot(2)           # optional long

        It works in 3d!!::

            sage: S = BondPercolationSample(0.5,3)
            sage: S.plot(3, pointsize=10, thickness=1)     # optional long
            Graphics3d Object

        """
        s = ""
        s += "\\begin{tikzpicture}\n"
        s += "[inner sep=0pt,thick,\n"
        s += "reddot/.style={fill=red,draw=red,circle,minimum size=5pt}]\n"
        s += "\\clip %s rectangle %s;\n" % ((-m - .4, -m - .4),
                                            (m + .4, m + .4))
        G = Graphics()
        for u in self.cluster_in_box(m + 1):
            G += point(u, color='blue', size=pointsize)
        for (u, v) in self.edges_in_box(m + 1):
            G += line((u, v), thickness=thickness, alpha=0.8)
        G += text("p=%.3f" % self._p, (0.5, 1.03),
                  axis_coords=True,
                  color='black')
        G += circle((0, 0), 0.5, color='red', thickness=thickness)
        if self._dimension == 2:
            G.axes(axes)
        return G
Exemple #4
0
    def plot(self, m, pointsize=100, thickness=3, axes=False):
        r"""
        Return 2d graphics object contained in the primal box [-m,m]^d.

        INPUT:

        - ``pointsize``, integer (default:``100``),
        - ``thickness``, integer (default:``3``),
        - ``axes``, bool (default:``False``),

        EXAMPLES::

            sage: from slabbe import BondPercolationSample
            sage: S = BondPercolationSample(0.5,2)
            sage: S.plot(2)           # optional long

        It works in 3d!!::

            sage: S = BondPercolationSample(0.5,3)
            sage: S.plot(3, pointsize=10, thickness=1)     # optional long
            Graphics3d Object

        """
        s = ""
        s += "\\begin{tikzpicture}\n"
        s += "[inner sep=0pt,thick,\n"
        s += "reddot/.style={fill=red,draw=red,circle,minimum size=5pt}]\n"
        s += "\\clip %s rectangle %s;\n" % ((-m-.4,-m-.4), (m+.4,m+.4))
        G = Graphics()
        for u in self.cluster_in_box(m+1):
            G += point(u, color='blue', size=pointsize)
        for (u,v) in self.edges_in_box(m+1):
            G += line((u,v), thickness=thickness, alpha=0.8)
        G += text("p=%.3f" % self._p, (0.5,1.03), axis_coords=True, color='black')
        G += circle((0,0), 0.5, color='red', thickness=thickness)
        if self._dimension == 2:
            G.axes(axes)
        return G
Exemple #5
0
    def plot(self, color='sign'):
        """
        Return a plot of ``self``.

        INPUT:

        - ``color`` -- can be any of the following:

          * ``4`` - use 4 colors: black, red, blue, and green with each
            corresponding to up, right, down, and left respectively
          * ``2`` - use 2 colors: red for horizontal, blue for vertical arrows
          * ``'sign'`` - use red for right and down arrows, blue for left
            and up arrows
          * a list of 4 colors for each direction
          * a function which takes a direction and a boolean corresponding
            to the sign

        EXAMPLES::

            sage: M = SixVertexModel(2, boundary_conditions='ice')
            sage: print(M[0].plot().description())
            Arrow from (-1.0,0.0) to (0.0,0.0)
            Arrow from (-1.0,1.0) to (0.0,1.0)
            Arrow from (0.0,0.0) to (0.0,-1.0)
            Arrow from (0.0,0.0) to (1.0,0.0)
            Arrow from (0.0,1.0) to (0.0,0.0)
            Arrow from (0.0,1.0) to (0.0,2.0)
            Arrow from (1.0,0.0) to (1.0,-1.0)
            Arrow from (1.0,0.0) to (1.0,1.0)
            Arrow from (1.0,1.0) to (0.0,1.0)
            Arrow from (1.0,1.0) to (1.0,2.0)
            Arrow from (2.0,0.0) to (1.0,0.0)
            Arrow from (2.0,1.0) to (1.0,1.0)
        """
        from sage.plot.graphics import Graphics
        from sage.plot.circle import circle
        from sage.plot.arrow import arrow

        if color == 4:
            color_list = ['black', 'red', 'blue', 'green']
            cfunc = lambda d,pm: color_list[d]
        elif color == 2:
            cfunc = lambda d,pm: 'red' if d % 2 == 0 else 'blue'
        elif color == 1 or color is None:
            cfunc = lambda d,pm: 'black'
        elif color == 'sign':
            cfunc = lambda d,pm: 'red' if pm else 'blue' # RD are True
        elif isinstance(color, (list, tuple)):
            cfunc = lambda d,pm: color[d]
        else:
            cfunc = color

        G = Graphics()
        for j,row in enumerate(reversed(self)):
            for i,entry in enumerate(row):
                if entry == 0: # LR
                    G += arrow((i,j+1), (i,j), color=cfunc(2, True))
                    G += arrow((i,j), (i+1,j), color=cfunc(1, True))
                    if j == 0:
                        G += arrow((i,j-1), (i,j), color=cfunc(0, False))
                    if i == 0:
                        G += arrow((i,j), (i-1,j), color=cfunc(3, False))
                elif entry == 1: # LU
                    G += arrow((i,j), (i,j+1), color=cfunc(0, False))
                    G += arrow((i+1,j), (i,j), color=cfunc(3, False))
                    if j == 0:
                        G += arrow((i,j-1), (i,j), color=cfunc(0, False))
                    if i == 0:
                        G += arrow((i,j), (i-1,j), color=cfunc(3, False))
                elif entry == 2: # LD
                    G += arrow((i,j+1), (i,j), color=cfunc(2, True))
                    G += arrow((i+1,j), (i,j), color=cfunc(3, False))
                    if j == 0:
                        G += arrow((i,j), (i,j-1), color=cfunc(2, True))
                    if i == 0:
                        G += arrow((i,j), (i-1,j), color=cfunc(3, False))
                elif entry == 3: # UD
                    G += arrow((i,j), (i,j+1), color=cfunc(0, False))
                    G += arrow((i+1,j), (i,j), color=cfunc(3, False))
                    if j == 0:
                        G += arrow((i,j), (i,j-1), color=cfunc(2, True))
                    if i == 0:
                        G += arrow((i-1,j), (i,j), color=cfunc(1, True))
                elif entry == 4: # UR
                    G += arrow((i,j), (i,j+1), color=cfunc(0, False))
                    G += arrow((i,j), (i+1,j), color=cfunc(1, True))
                    if j == 0:
                        G += arrow((i,j-1), (i,j), color=cfunc(0, False))
                    if i == 0:
                        G += arrow((i-1,j), (i,j), color=cfunc(1, True))
                elif entry == 5: # RD
                    G += arrow((i,j+1), (i,j), color=cfunc(2, True))
                    G += arrow((i,j), (i+1,j), color=cfunc(1, True))
                    if j == 0:
                        G += arrow((i,j), (i,j-1), color=cfunc(2, True))
                    if i == 0:
                        G += arrow((i-1,j), (i,j), color=cfunc(1, True))
        G.axes(False)
        return G
    def plot(self, color='sign'):
        """
        Return a plot of ``self``.

        INPUT:

        - ``color`` -- can be any of the following:

          * ``4`` - use 4 colors: black, red, blue, and green with each
            corresponding to up, right, down, and left respectively
          * ``2`` - use 2 colors: red for horizontal, blue for vertical arrows
          * ``'sign'`` - use red for right and down arrows, blue for left
            and up arrows
          * a list of 4 colors for each direction
          * a function which takes a direction and a boolean corresponding
            to the sign

        EXAMPLES::

            sage: M = SixVertexModel(2, boundary_conditions='ice')
            sage: print(M[0].plot().description())
            Arrow from (-1.0,0.0) to (0.0,0.0)
            Arrow from (-1.0,1.0) to (0.0,1.0)
            Arrow from (0.0,0.0) to (0.0,-1.0)
            Arrow from (0.0,0.0) to (1.0,0.0)
            Arrow from (0.0,1.0) to (0.0,0.0)
            Arrow from (0.0,1.0) to (0.0,2.0)
            Arrow from (1.0,0.0) to (1.0,-1.0)
            Arrow from (1.0,0.0) to (1.0,1.0)
            Arrow from (1.0,1.0) to (0.0,1.0)
            Arrow from (1.0,1.0) to (1.0,2.0)
            Arrow from (2.0,0.0) to (1.0,0.0)
            Arrow from (2.0,1.0) to (1.0,1.0)
        """
        from sage.plot.graphics import Graphics
        from sage.plot.arrow import arrow

        if color == 4:
            color_list = ['black', 'red', 'blue', 'green']
            cfunc = lambda d,pm: color_list[d]
        elif color == 2:
            cfunc = lambda d,pm: 'red' if d % 2 == 0 else 'blue'
        elif color == 1 or color is None:
            cfunc = lambda d,pm: 'black'
        elif color == 'sign':
            cfunc = lambda d,pm: 'red' if pm else 'blue' # RD are True
        elif isinstance(color, (list, tuple)):
            cfunc = lambda d,pm: color[d]
        else:
            cfunc = color

        G = Graphics()
        for j,row in enumerate(reversed(self)):
            for i,entry in enumerate(row):
                if entry == 0: # LR
                    G += arrow((i,j+1), (i,j), color=cfunc(2, True))
                    G += arrow((i,j), (i+1,j), color=cfunc(1, True))
                    if j == 0:
                        G += arrow((i,j-1), (i,j), color=cfunc(0, False))
                    if i == 0:
                        G += arrow((i,j), (i-1,j), color=cfunc(3, False))
                elif entry == 1: # LU
                    G += arrow((i,j), (i,j+1), color=cfunc(0, False))
                    G += arrow((i+1,j), (i,j), color=cfunc(3, False))
                    if j == 0:
                        G += arrow((i,j-1), (i,j), color=cfunc(0, False))
                    if i == 0:
                        G += arrow((i,j), (i-1,j), color=cfunc(3, False))
                elif entry == 2: # LD
                    G += arrow((i,j+1), (i,j), color=cfunc(2, True))
                    G += arrow((i+1,j), (i,j), color=cfunc(3, False))
                    if j == 0:
                        G += arrow((i,j), (i,j-1), color=cfunc(2, True))
                    if i == 0:
                        G += arrow((i,j), (i-1,j), color=cfunc(3, False))
                elif entry == 3: # UD
                    G += arrow((i,j), (i,j+1), color=cfunc(0, False))
                    G += arrow((i+1,j), (i,j), color=cfunc(3, False))
                    if j == 0:
                        G += arrow((i,j), (i,j-1), color=cfunc(2, True))
                    if i == 0:
                        G += arrow((i-1,j), (i,j), color=cfunc(1, True))
                elif entry == 4: # UR
                    G += arrow((i,j), (i,j+1), color=cfunc(0, False))
                    G += arrow((i,j), (i+1,j), color=cfunc(1, True))
                    if j == 0:
                        G += arrow((i,j-1), (i,j), color=cfunc(0, False))
                    if i == 0:
                        G += arrow((i-1,j), (i,j), color=cfunc(1, True))
                elif entry == 5: # RD
                    G += arrow((i,j+1), (i,j), color=cfunc(2, True))
                    G += arrow((i,j), (i+1,j), color=cfunc(1, True))
                    if j == 0:
                        G += arrow((i,j), (i,j-1), color=cfunc(2, True))
                    if i == 0:
                        G += arrow((i-1,j), (i,j), color=cfunc(1, True))
        G.axes(False)
        return G
Exemple #7
0
    def plot(self):
        r"""
        Return a graphical object of the Fully Packed Loop

        EXAMPLES:

        Here is the fully packed loop for

        .. MATH::

            \begin{pmatrix} 0&1&1 \\ 1&-1&1 \\ 0&1&0 \end{pmatrix}:

        .. PLOT::
            :width: 200 px

            A = AlternatingSignMatrix([[0, 1, 0], [1, -1, 1], [0, 1, 0]])
            fpl = FullyPackedLoop(A)
            p = fpl.plot()
            sphinx_plot(p)

        Here is how Sage represents this::

            sage: A = AlternatingSignMatrix([[0, 1, 0], [1, -1, 1], [0, 1, 0]])
            sage: fpl = FullyPackedLoop(A)
            sage: print(fpl.plot().description())
            Line defined by 2 points:       [(-1.0, 1.0), (0.0, 1.0)]
            Line defined by 2 points:       [(0.0, 0.0), (0.0, -1.0)]
            Line defined by 2 points:       [(0.0, 0.0), (1.0, 0.0)]
            Line defined by 2 points:       [(0.0, 2.0), (0.0, 3.0)]
            Line defined by 2 points:       [(0.0, 2.0), (0.0, 3.0)]
            Line defined by 2 points:       [(0.0, 2.0), (1.0, 2.0)]
            Line defined by 2 points:       [(1.0, 1.0), (0.0, 1.0)]
            Line defined by 2 points:       [(1.0, 1.0), (2.0, 1.0)]
            Line defined by 2 points:       [(2.0, 0.0), (1.0, 0.0)]
            Line defined by 2 points:       [(2.0, 0.0), (2.0, -1.0)]
            Line defined by 2 points:       [(2.0, 2.0), (1.0, 2.0)]
            Line defined by 2 points:       [(2.0, 2.0), (2.0, 3.0)]
            Line defined by 2 points:       [(2.0, 2.0), (2.0, 3.0)]
            Line defined by 2 points:       [(3.0, 1.0), (2.0, 1.0)]
            Line defined by 2 points:       [(3.0, 1.0), (2.0, 1.0)]

        Here are the other 3 by 3 Alternating Sign Matrices and their corresponding
        fully packed loops:

        .. MATH::

            A = \begin{pmatrix} 1&0&0 \\ 0&1&0 \\ 0&0&1 \\ \end{pmatrix}

        gives:

        .. PLOT::
            :width: 200 px

            A = AlternatingSignMatrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
            fpl = FullyPackedLoop(A)
            p = fpl.plot()
            sphinx_plot(p)

        .. MATH::

            A = \begin{pmatrix} 1&0&0 \\ 0&0&1 \\ 0&1&0 \\ \end{pmatrix}

        gives:

        .. PLOT::
            :width: 200 px

            A = AlternatingSignMatrix([[1, 0, 0], [0, 0, 1], [0, 1, 0]])
            fpl = FullyPackedLoop(A)
            p = fpl.plot()
            sphinx_plot(p)

        .. MATH::

            A = \begin{pmatrix} 0&1&0\\ 1&0&0\\ 0&0&1\\ \end{pmatrix}

        gives:

        .. PLOT::
            :width: 200 px

            A = AlternatingSignMatrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]])
            fpl = FullyPackedLoop(A)
            p = fpl.plot()
            sphinx_plot(p)

        .. MATH::

            A = \begin{pmatrix} 0&1&0\\ 0&0&1\\ 1&0&0\\ \end{pmatrix}

        gives:

        .. PLOT::
            :width: 200 px

            A = AlternatingSignMatrix([[0, 1, 0], [0, 0, 1], [1, 0, 0]])
            fpl = FullyPackedLoop(A)
            p = fpl.plot()
            sphinx_plot(p)

        .. MATH::

            A = \begin{pmatrix} 0&0&1\\ 1&0&0\\ 0&1&0\\ \end{pmatrix}

        gives:

        .. PLOT::
            :width: 200 px

            A = AlternatingSignMatrix([[0, 0, 1], [1, 0, 0], [0, 1, 0]])
            fpl = FullyPackedLoop(A)
            p = fpl.plot()
            sphinx_plot(p)

        .. MATH::

            A = \begin{pmatrix} 0&0&1\\ 0&1&0\\ 1&0&0\\ \end{pmatrix}

        gives:

        .. PLOT::
            :width: 200 px

            A = AlternatingSignMatrix([[0, 0, 1], [0, 1, 0], [1, 0, 0]])
            fpl = FullyPackedLoop(A)
            p = fpl.plot()
            sphinx_plot(p)

        EXAMPLES::

            sage: A = AlternatingSignMatrix([[0, 1, 0, 0], [1, -1, 0, 1], \
            [0, 1, 0, 0],[0, 0, 1, 0]])
            sage: fpl = FullyPackedLoop(A)
            sage: print(fpl.plot().description())
            Line defined by 2 points:       [(-1.0, 0.0), (0.0, 0.0)]
            Line defined by 2 points:       [(-1.0, 2.0), (0.0, 2.0)]
            Line defined by 2 points:       [(0.0, 1.0), (0.0, 0.0)]
            Line defined by 2 points:       [(0.0, 1.0), (1.0, 1.0)]
            Line defined by 2 points:       [(0.0, 3.0), (0.0, 4.0)]
            Line defined by 2 points:       [(0.0, 3.0), (0.0, 4.0)]
            Line defined by 2 points:       [(0.0, 3.0), (1.0, 3.0)]
            Line defined by 2 points:       [(1.0, 0.0), (1.0, -1.0)]
            Line defined by 2 points:       [(1.0, 0.0), (2.0, 0.0)]
            Line defined by 2 points:       [(1.0, 2.0), (0.0, 2.0)]
            Line defined by 2 points:       [(1.0, 2.0), (2.0, 2.0)]
            Line defined by 2 points:       [(2.0, 1.0), (1.0, 1.0)]
            Line defined by 2 points:       [(2.0, 1.0), (2.0, 2.0)]
            Line defined by 2 points:       [(2.0, 3.0), (1.0, 3.0)]
            Line defined by 2 points:       [(2.0, 3.0), (2.0, 4.0)]
            Line defined by 2 points:       [(2.0, 3.0), (2.0, 4.0)]
            Line defined by 2 points:       [(3.0, 0.0), (2.0, 0.0)]
            Line defined by 2 points:       [(3.0, 0.0), (3.0, -1.0)]
            Line defined by 2 points:       [(3.0, 2.0), (3.0, 1.0)]
            Line defined by 2 points:       [(3.0, 2.0), (3.0, 3.0)]
            Line defined by 2 points:       [(4.0, 1.0), (3.0, 1.0)]
            Line defined by 2 points:       [(4.0, 1.0), (3.0, 1.0)]
            Line defined by 2 points:       [(4.0, 3.0), (3.0, 3.0)]
            Line defined by 2 points:       [(4.0, 3.0), (3.0, 3.0)]

        Here is the plot:

        .. PLOT::
            :width: 300 px

            A = AlternatingSignMatrix([[0, 1, 0, 0], [1, -1, 0, 1], [0, 1, 0, 0],[0, 0, 1, 0]])
            fpl = FullyPackedLoop(A)
            p = fpl.plot()
            sphinx_plot(p)

        """
        G = Graphics()
        n=len(self._six_vertex_model)-1
        for j,row in enumerate(reversed(self._six_vertex_model)):
            for i,entry in enumerate(row):
                if i == 0 and (i+j+n+1) % 2 ==0:
                    G+= line([(i-1,j),(i,j)])
                if i == n and (i+j+n+1) % 2 ==0:
                    G+= line([(i+1,j),(i,j)])
                if j == 0 and (i+j+n) % 2 ==0:
                    G+= line([(i,j),(i,j-1)])
                if j == n and (i+j+n) % 2 ==0:
                    G+= line([(i,j),(i,j+1)])
                if entry == 0: # LR
                    if (i+j+n) % 2==0:
                        G += line([(i,j), (i+1,j)])
                    else:
                        G += line([(i,j),(i,j+1)])
                elif entry == 1: # LU
                    if (i+j+n) % 2 ==0:
                        G += line([(i,j), (i,j+1)])
                    else:
                        G += line([(i+1,j), (i,j)])
                elif entry == 2: # LD
                    if (i+j+n) % 2 == 0:
                        pass
                    else:
                        G += line([(i,j+1), (i,j)])
                        G += line([(i+1,j), (i,j)])
                elif entry == 3: # UD
                    if (i+j+n) % 2 == 0:
                        G += line([(i,j), (i,j+1)])
                    else:
                        G += line([(i+1,j), (i,j)])
                elif entry == 4: # UR
                    if (i+j+n) % 2 ==0:
                        G += line([(i,j), (i,j+1)])
                        G += line([(i,j), (i+1,j)])
                    else:
                        pass
                elif entry == 5: # RD
                    if (i+j+n) % 2 ==0:
                        G += line([(i,j), (i+1,j)])
                    else:
                        G += line([(i,j+1), (i,j)])
        G.axes(False)
        return G
Exemple #8
0
    def finalize(self, G):
        r"""
        Finalize a root system plot.

        INPUT:

        - ``G`` -- a root system plot or ``0``

        This sets the aspect ratio to 1 and remove the axes. This
        should be called by all the user-level plotting methods of
        root systems. This will become mostly obsolete when
        customization options won't be lost anymore upon addition of
        graphics objects and there will be a proper empty object for
        2D and 3D plots.

        EXAMPLES::

            sage: L = RootSystem(["B",2,1]).ambient_space()
            sage: options = L.plot_parse_options()
            sage: p = L.plot_roots(plot_options=options)
            sage: p += L.plot_coroots(plot_options=options)
            sage: p.axes()
            True
            sage: p = options.finalize(p)
            sage: p.axes()
            False
            sage: p.aspect_ratio()
            1.0

            sage: options = L.plot_parse_options(affine=False)
            sage: p = L.plot_roots(plot_options=options)
            sage: p += point([[1,1,0]])
            sage: p = options.finalize(p)
            sage: p.aspect_ratio()
            [1.0, 1.0, 1.0]

        If the input is ``0``, this returns an empty graphics object::

            sage: type(options.finalize(0))
            <class 'sage.plot.plot3d.base.Graphics3dGroup'>

            sage: options = L.plot_parse_options()
            sage: type(options.finalize(0))
            <class 'sage.plot.graphics.Graphics'>
            sage: list(options.finalize(0))
            []
        """
        from sage.plot.graphics import Graphics
        if self.dimension == 2:
            if G == 0:
                G = Graphics()
            G.set_aspect_ratio(1)
            # TODO: make this customizable
            G.axes(False)
        elif self.dimension == 3:
            if G == 0:
                from sage.plot.plot3d.base import Graphics3dGroup
                G = Graphics3dGroup()
            G.aspect_ratio(1)
            # TODO: Configuration axes
        return G
Exemple #9
0
    def finalize(self, G):
        r"""
        Finalize a root system plot.

        INPUT:

        - ``G`` -- a root system plot or ``0``

        This sets the aspect ratio to 1 and remove the axes. This
        should be called by all the user-level plotting methods of
        root systems. This will become mostly obsolete when
        customization options won't be lost anymore upon addition of
        graphics objects and there will be a proper empty object for
        2D and 3D plots.

        EXAMPLES::

            sage: L = RootSystem(["B",2,1]).ambient_space()
            sage: options = L.plot_parse_options()
            sage: p = L.plot_roots(plot_options=options)
            sage: p += L.plot_coroots(plot_options=options)
            sage: p.axes()
            True
            sage: p = options.finalize(p)
            sage: p.axes()
            False
            sage: p.aspect_ratio()
            1.0

            sage: options = L.plot_parse_options(affine=False)
            sage: p = L.plot_roots(plot_options=options)
            sage: p += point([[1,1,0]])
            sage: p = options.finalize(p)
            sage: p.aspect_ratio()
            [1.0, 1.0, 1.0]

        If the input is ``0``, this returns an empty graphics object::

            sage: type(options.finalize(0))
            <class 'sage.plot.plot3d.base.Graphics3dGroup'>

            sage: options = L.plot_parse_options()
            sage: type(options.finalize(0))
            <class 'sage.plot.graphics.Graphics'>
            sage: list(options.finalize(0))
            []
        """
        from sage.plot.graphics import Graphics
        if self.dimension == 2:
            if G == 0:
                G = Graphics()
            G.set_aspect_ratio(1)
            # TODO: make this customizable
            G.axes(False)
        elif self.dimension == 3:
            if G == 0:
                from sage.plot.plot3d.base import Graphics3dGroup
                G = Graphics3dGroup()
            G.aspect_ratio(1)
            # TODO: Configuration axes
        return G
Exemple #10
0
    def plot(self, **kwds):
        r"""
        Plot the initial triangulation associated to ``self``.

        INPUT:

        - ``radius`` - the radius of the disk; by default the length of
          the circle is the number of vertices
        - ``points_color`` - the color of the vertices; default 'black'
        - ``points_size`` - the size of the vertices; default 7
        - ``triangulation_color`` - the color of the arcs; default 'black'
        - ``triangulation_thickness`` - the thickness of the arcs; default 0.5
        - ``shading_color`` - the color of the shading used on neuter
          intervals; default 'lightgray'
        - ``reflections_color`` - the color of the reflection axes; default
          'blue'
        - ``reflections_thickness`` - the thickness of the reflection axes;
          default 1

        EXAMPLES::

            sage: Y = SineGordonYsystem('A',(6,4,3))
            sage: Y.plot()  # long time 2s
            Graphics object consisting of 219 graphics primitives
        """
        # Set up plotting options
        if 'radius' in kwds:
            radius = kwds['radius']
        else:
            radius = ceil(self.r() / (2 * pi))
        points_opts = {}
        if 'points_color' in kwds:
            points_opts['color'] = kwds['points_color']
        else:
            points_opts['color'] = 'black'
        if 'points_size' in kwds:
            points_opts['size'] = kwds['points_size']
        else:
            points_opts['size'] = 7
        triangulation_opts = {}
        if 'triangulation_color' in kwds:
            triangulation_opts['color'] = kwds['triangulation_color']
        else:
            triangulation_opts['color'] = 'black'
        if 'triangulation_thickness' in kwds:
            triangulation_opts['thickness'] = kwds['triangulation_thickness']
        else:
            triangulation_opts['thickness'] = 0.5
        shading_opts = {}
        if 'shading_color' in kwds:
            shading_opts['color'] = kwds['shading_color']
        else:
            shading_opts['color'] = 'lightgray'
        reflections_opts = {}
        if 'reflections_color' in kwds:
            reflections_opts['color'] = kwds['reflections_color']
        else:
            reflections_opts['color'] = 'blue'
        if 'reflections_thickness' in kwds:
            reflections_opts['thickness'] = kwds['reflections_thickness']
        else:
            reflections_opts['thickness'] = 1
        # Helper functions

        def triangle(x):
            (a, b) = sorted(x[:2])
            for p in self.vertices():
                if (p, a) in self.triangulation() or (a, p) in self.triangulation():
                    if (p, b) in self.triangulation() or (b, p) in self.triangulation():
                        if p < a or p > b:
                            return sorted((a, b, p))

        def plot_arc(radius, p, q, **opts):
            # TODO: THIS SHOULD USE THE EXISTING PLOT OF ARCS!
            # plot the arc from p to q differently depending on the type of self
            p = ZZ(p)
            q = ZZ(q)
            t = var('t')
            if p - q in [1, -1]:
                def f(t):
                    return (radius * cos(t), radius * sin(t))
                (p, q) = sorted([p, q])
                angle_p = vertex_to_angle(p)
                angle_q = vertex_to_angle(q)
                return parametric_plot(f(t), (t, angle_q, angle_p), **opts)
            if self.type() == 'A':
                angle_p = vertex_to_angle(p)
                angle_q = vertex_to_angle(q)
                if angle_p < angle_q:
                    angle_p += 2 * pi
                internal_angle = angle_p - angle_q
                if internal_angle > pi:
                    (angle_p, angle_q) = (angle_q + 2 * pi, angle_p)
                    internal_angle = angle_p - angle_q
                angle_center = (angle_p+angle_q) / 2
                hypotenuse = radius / cos(internal_angle / 2)
                radius_arc = hypotenuse * sin(internal_angle / 2)
                center = (hypotenuse * cos(angle_center),
                          hypotenuse * sin(angle_center))
                center_angle_p = angle_p + pi / 2
                center_angle_q = angle_q + 3 * pi / 2

                def f(t):
                    return (radius_arc * cos(t) + center[0],
                            radius_arc * sin(t) + center[1])
                return parametric_plot(f(t), (t, center_angle_p,
                                              center_angle_q), **opts)
            elif self.type() == 'D':
                if p >= q:
                    q += self.r()
                px = -2 * pi * p / self.r() + pi / 2
                qx = -2 * pi * q / self.r() + pi / 2
                arc_radius = (px - qx) / 2
                arc_center = qx + arc_radius

                def f(t):
                    return exp(I * ((cos(t) + I * sin(t)) *
                                    arc_radius + arc_center)) * radius
                return parametric_plot((real_part(f(t)), imag_part(f(t))),
                                       (t, 0, pi), **opts)

        def vertex_to_angle(v):
            # v==0 corresponds to pi/2
            return -2 * pi * RR(v) / self.r() + 5 * pi / 2

        # Begin plotting
        P = Graphics()
        # Shade neuter intervals
        neuter_intervals = [x for x in flatten(self.intervals()[:-1],
                                               max_level=1)
                            if x[2] in ["NR", "NL"]]
        shaded_triangles = map(triangle, neuter_intervals)
        for (p, q, r) in shaded_triangles:
            points = list(plot_arc(radius, p, q)[0])
            points += list(plot_arc(radius, q, r)[0])
            points += list(reversed(plot_arc(radius, p, r)[0]))
            P += polygon2d(points, **shading_opts)
        # Disk boundary
        P += circle((0, 0), radius, **triangulation_opts)
        # Triangulation
        for (p, q) in self.triangulation():
            P += plot_arc(radius, p, q, **triangulation_opts)
        if self.type() == 'D':
            s = radius / 50.0
            P += polygon2d([(s, 5 * s), (s, 7 * s),
                            (3 * s, 5 * s), (3 * s, 7 * s)],
                           color=triangulation_opts['color'])
            P += bezier_path([[(0, 0), (2 * s, 1 * s), (2 * s, 6 * s)],
                              [(2 * s, 10 * s), (s, 20 * s)],
                              [(0, 30 * s), (0, radius)]],
                             **triangulation_opts)
            P += bezier_path([[(0, 0), (-2 * s, 1 * s), (-2 * s, 6 * s)],
                              [(-2 * s, 10 * s), (-s, 20 * s)],
                              [(0, 30 * s), (0, radius)]],
                             **triangulation_opts)
            P += point((0, 0), zorder=len(P), **points_opts)
        # Vertices
        v_points = {x: (radius * cos(vertex_to_angle(x)),
                        radius * sin(vertex_to_angle(x)))
                    for x in self.vertices()}
        for v in v_points:
            P += point(v_points[v], zorder=len(P), **points_opts)
        # Reflection axes
        P += line([(0, 1.1 * radius), (0, -1.1 * radius)],
                  zorder=len(P), **reflections_opts)
        axis_angle = vertex_to_angle(-0.5 * (self.rk() + (1, 1))[1])
        (a, b) = (1.1 * radius * cos(axis_angle),
                  1.1 * radius * sin(axis_angle))
        P += line([(a, b), (-a, -b)], zorder=len(P), **reflections_opts)
        # Wrap up
        P.set_aspect_ratio(1)
        P.axes(False)
        return P
Exemple #11
0
    def plot(self, **kwds):
        r"""
        Plot the initial triangulation associated to ``self``.

        INPUT:

        - ``radius`` - the radius of the disk; by default the length of
          the circle is the number of vertices
        - ``points_color`` - the color of the vertices; default 'black'
        - ``points_size`` - the size of the vertices; default 7
        - ``triangulation_color`` - the color of the arcs; default 'black'
        - ``triangulation_thickness`` - the thickness of the arcs; default 0.5
        - ``shading_color`` - the color of the shading used on neuter
          intervals; default 'lightgray'
        - ``reflections_color`` - the color of the reflection axes; default
          'blue'
        - ``reflections_thickness`` - the thickness of the reflection axes;
          default 1

        EXAMPLES::

            sage: Y = SineGordonYsystem('A',(6,4,3));
            sage: Y.plot()      # not tested
        """
        # Set up plotting options
        if 'radius' in kwds:
            radius = kwds['radius']
        else:
            radius = ceil(self.r() / (2 * pi))
        points_opts = {}
        if 'points_color' in kwds:
            points_opts['color'] = kwds['points_color']
        else:
            points_opts['color'] = 'black'
        if 'points_size' in kwds:
            points_opts['size'] = kwds['points_size']
        else:
            points_opts['size'] = 7
        triangulation_opts = {}
        if 'triangulation_color' in kwds:
            triangulation_opts['color'] = kwds['triangulation_color']
        else:
            triangulation_opts['color'] = 'black'
        if 'triangulation_thickness' in kwds:
            triangulation_opts['thickness'] = kwds['triangulation_thickness']
        else:
            triangulation_opts['thickness'] = 0.5
        shading_opts = {}
        if 'shading_color' in kwds:
            shading_opts['color'] = kwds['shading_color']
        else:
            shading_opts['color'] = 'lightgray'
        reflections_opts = {}
        if 'reflections_color' in kwds:
            reflections_opts['color'] = kwds['reflections_color']
        else:
            reflections_opts['color'] = 'blue'
        if 'reflections_thickness' in kwds:
            reflections_opts['thickness'] = kwds['reflections_thickness']
        else:
            reflections_opts['thickness'] = 1
        # Helper functions

        def triangle(x):
            (a, b) = sorted(x[:2])
            for p in self.vertices():
                if (p, a) in self.triangulation() or (a, p) in self.triangulation():
                    if (p, b) in self.triangulation() or (b, p) in self.triangulation():
                        if p < a or p > b:
                            return sorted((a, b, p))

        def plot_arc(radius, p, q, **opts):
            # plot the arc from p to q differently depending on the type of self
            p = ZZ(p)
            q = ZZ(q)
            t = var('t')
            if p - q in [1, -1]:
                def f(t):
                    return (radius * cos(t), radius * sin(t))
                (p, q) = sorted([p, q])
                angle_p = vertex_to_angle(p)
                angle_q = vertex_to_angle(q)
                return parametric_plot(f(t), (t, angle_q, angle_p), **opts)
            if self.type() == 'A':
                angle_p = vertex_to_angle(p)
                angle_q = vertex_to_angle(q)
                if angle_p < angle_q:
                    angle_p += 2 * pi
                internal_angle = angle_p - angle_q
                if internal_angle > pi:
                    (angle_p, angle_q) = (angle_q + 2 * pi, angle_p)
                    internal_angle = angle_p - angle_q
                angle_center = (angle_p+angle_q) / 2
                hypotenuse = radius / cos(internal_angle / 2)
                radius_arc = hypotenuse * sin(internal_angle / 2)
                center = (hypotenuse * cos(angle_center),
                          hypotenuse * sin(angle_center))
                center_angle_p = angle_p + pi / 2
                center_angle_q = angle_q + 3 * pi / 2

                def f(t):
                    return (radius_arc * cos(t) + center[0],
                            radius_arc * sin(t) + center[1])
                return parametric_plot(f(t), (t, center_angle_p,
                                              center_angle_q), **opts)
            elif self.type() == 'D':
                if p >= q:
                    q += self.r()
                px = -2 * pi * p / self.r() + pi / 2
                qx = -2 * pi * q / self.r() + pi / 2
                arc_radius = (px - qx) / 2
                arc_center = qx + arc_radius

                def f(t):
                    return exp(I * ((cos(t) + I * sin(t)) *
                                    arc_radius + arc_center)) * radius
                return parametric_plot((real_part(f(t)), imag_part(f(t))),
                                       (t, 0, pi), **opts)

        def vertex_to_angle(v):
            # v==0 corresponds to pi/2
            return -2 * pi * RR(v) / self.r() + 5 * pi / 2

        # Begin plotting
        P = Graphics()
        # Shade neuter intervals
        neuter_intervals = [x for x in flatten(self.intervals()[:-1],
                                               max_level=1)
                            if x[2] in ["NR", "NL"]]
        shaded_triangles = map(triangle, neuter_intervals)
        for (p, q, r) in shaded_triangles:
            points = list(plot_arc(radius, p, q)[0])
            points += list(plot_arc(radius, q, r)[0])
            points += list(reversed(plot_arc(radius, p, r)[0]))
            P += polygon2d(points, **shading_opts)
        # Disk boundary
        P += circle((0, 0), radius, **triangulation_opts)
        # Triangulation
        for (p, q) in self.triangulation():
            P += plot_arc(radius, p, q, **triangulation_opts)
        if self.type() == 'D':
            s = radius / 50.0
            P += polygon2d([(s, 5 * s), (s, 7 * s),
                            (3 * s, 5 * s), (3 * s, 7 * s)],
                           color=triangulation_opts['color'])
            P += bezier_path([[(0, 0), (2 * s, 1 * s), (2 * s, 6 * s)],
                              [(2 * s, 10 * s), (s, 20 * s)],
                              [(0, 30 * s), (0, radius)]],
                             **triangulation_opts)
            P += bezier_path([[(0, 0), (-2 * s, 1 * s), (-2 * s, 6 * s)],
                              [(-2 * s, 10 * s), (-s, 20 * s)],
                              [(0, 30 * s), (0, radius)]],
                             **triangulation_opts)
            P += point((0, 0), zorder=len(P), **points_opts)
        # Vertices
        v_points = {x: (radius * cos(vertex_to_angle(x)),
                        radius * sin(vertex_to_angle(x)))
                    for x in self.vertices()}
        for v in v_points:
            P += point(v_points[v], zorder=len(P), **points_opts)
        # Reflection axes
        P += line([(0, 1.1 * radius), (0, -1.1 * radius)],
                  zorder=len(P), **reflections_opts)
        axis_angle = vertex_to_angle(-0.5 * (self.rk() + (1, 1))[1])
        (a, b) = (1.1 * radius * cos(axis_angle),
                  1.1 * radius * sin(axis_angle))
        P += line([(a, b), (-a, -b)], zorder=len(P), **reflections_opts)
        # Wrap up
        P.set_aspect_ratio(1)
        P.axes(False)
        return P
    def plot(self,radius=1, orientation=1, cyclic_order_0=None, cyclic_order_1=None,verbose=False):

        """Plot the set of ideal curves on the surface S=S(g,1) of genus g with
        one puncture.

        The free group has rank N=2g, the trees T0 and T1 are roses
        transverse to a maximal set of ideal curves on S. The convex
        core is transverse to the two collections of curves: vertices
        are connected components of the complement of the union of the
        two sets of curves, edges are arcs separating two regions and
        squares are around intersections points of curves.

        For instance T0 can be set to be the rose with the trivial
        marking, while T1 is obtained from T0 by applying a mapping
        class (and not a general automorphism). The embedding of the
        mapping class group is that generated by the
        ``surface_dehn_twist()`` method of the ``FreeGroup`` class.

        The set of ideal curves of T0 is drawn as the boundary of a
        regular 2N-gone, and the set of ideal curves of T1 is drawn
        inside this 2N-gone.

        INPUT:

        - ``radius``: (default 1) the radius of the regular 2N-gone
          which is the fondamental domain of the surface.

        -``cyclic_order_0``: (default None) List of edges outgoing
         from the sole vertex of T0 ordered according to the embedding
         in the surface. A typical value in rank 4, compatible with
         the definition of ``FreeGroup.surface_dehn_twist()`` is :
         ['A','B','a','C','D','c','d','b']

        -``cyclic_order_1``: (default None) List of edges outgoing
         from the sole vertex of T1 ordered according to the embedding
         in the surface.

        EXAMPLES::
        
        sage: F=FreeGroup(4)
        sage: phi=mul([F.surface_dehn_twist(i) for i in [2,1,1,4]])
        sage: C=ConvexCore(phi)
        sage: C.plot_ideal_curve_diagram(cyclic_order_0=['A','B','a','C','D','c','d','b'])

        """

        from sage.plot.graphics import Graphics
        from sage.plot.line import Line
        from sage.plot.arrow import Arrow
        
        T0=self.tree(0)
        T1=self.tree(1)
        A0=T0.alphabet()
        N=len(A0)
        A1=T1.alphabet()

        # Let ``self`` be the convex core of trees T0 and T1. T0 and
        # T1 need to be roses. The trees T0 and T1 may be given as
        # embedded inside the surface. In this case the edges outgoing
        # from the sole vertex are cyclically ordered.

        if len(T0.vertices())!=1:
            raise ValueError('The tree on side 0 must be a rose')
        if len(T1.vertices())!=1:
            raise ValueError('The tree on side 1 must be a rose')
            
        
        if cyclic_order_0 is None:
            cyclic_order_0=getattr(T0,'cyclic_order',None)
        if cyclic_order_1 is None:
            cyclic_order_1=getattr(T1,'cyclic_order',None)

        if verbose:
            if cyclic_order_0 is not None:
                print "The tree on side 0 is embedded in the surface:",cyclic_order_0
            else:
                print "The tree on side 0 is not embedded in the surface, we will try to guess an embedding"
            if cyclic_order_1 is not None:
                print "The tree on side 1 is embedded in the surface:",cyclic_order_1
            else:
                print "The tree on side 1 is not embedded in the surface, we will try to guess an embedding"
            
        squares=self.squares()

        # Coherent orientation of the squares
            

        orientation=self.squares_orientation(orientation=orientation,verbose=verbose and verbose>1 and verbose-1)
            
        if verbose:
            print "Orientation of the squares:"
            if verbose>1:
                for i,sq in enumerate(squares):
                    print i,":",sq,":",orientation[i] 

        boundary=self.surface_boundary(orientation=orientation,verbose=verbose and verbose>1 and verbose-1)


        if verbose:
            print "Edges of the boundary:"
            print boundary
        
        # The boundary of the surface is an Eulerian circuit in the surface_boundary_graph

        
        eulerian_circuits=[]

	boundary_length=2*(self.tree(side=0).alphabet().cardinality()+self.tree(side=1).alphabet().cardinality())

        next=[(boundary[0],0)]
        if boundary[0][2][2]!=0:
            next.append((boundary[1],0))

        if verbose:
            print "Looking for an eulerian circuit in the boundary"

        while len(next)>0:

            e,current=next.pop()

            if verbose:
                print e,current
            
            for i in xrange(current+1,len(boundary)):
                if boundary[i]==e:
                    boundary[i],boundary[current]=boundary[current],boundary[i]
                    # now the boundary is the beginning of an eulerian
                    # circuit up to current
                    break

            # We check that the boundary up to current is acceptable

            acceptable=True

            # First, we check that two edges bounding a strongly
            # connected component of squares share the same
            # orientation
            
            oriented=set()
            for i in xrange(current+1):
                e=boundary[i]
                if e[2][2]!=0 and -e[2][2] in oriented: # edges with orientation 0 are isolated edges
                    acceptable=False
                    if verbose:
                        print "The current boundary does not respect orientation",e[2][2]
                    break
                else:
                    oriented.add(e[2][2])

            if not acceptable:
                continue
            
            # Next we check that this is compatible with the given
            # cyclic order

            if cyclic_order_0 is not None:                
                i=0
                j0=None
                while i<current+1 and boundary[i][2][1]!=0: 
                    i+=1
                if i<current+1:
                    j0=0
                    while j0<len(cyclic_order_0) and cyclic_order_0[j0]!=boundary[i][2][0]:
                        j0+=1
                
                while i<current:
                    i+=1
                    while i<current+1 and boundary[i][2][1]!=0:
                        i+=1
                    if i<current+1:
                        j0+=1
                        if j0==len(cyclic_order_0):
                            j0=0
                        if boundary[i][2][0]!=cyclic_order_0[j0]:
                            acceptable=False
                            if verbose:
                                print "The current boundary does not respect the given cyclic order on side 0"
                            break

            if not acceptable:
                continue
            
            if cyclic_order_1 is not None:                
                i=0
                j1=None
                while i<current+1 and boundary[i][2][1]!=1:
                    i+=1
                if i<current+1:
                    j1=0
                    while j1<len(cyclic_order_1) and cyclic_order_1[j1]!=boundary[i][2][0]:
                        j1+=1
                while i<current:
                    i+=1
                    while i<current+1 and boundary[i][2][1]!=1:
                        i+=1
                    if i<current+1:
                        j1+=1
                        if j1==len(cyclic_order_1):
                            j1=0
                        if boundary[i][2][0]!=cyclic_order_1[j1]:
                            acceptable=False
                            if verbose:
                                print "The current boundary does not respect the given cyclic order on side 1"

                            break

            if not acceptable:
                continue


            # If there are no given cyclic orders we check that on
            # both side there is only one connected component.

            if (cyclic_order_0 is None) and (cyclic_order_1 is None):
                tmp_cyclic_0=[boundary[i][2][0] for i in xrange(current+1) if boundary[i][2][1]==0] 
                i=0
                if len(tmp_cyclic_0)<2*len(A0):
                    while i<len(tmp_cyclic_0):
                        j=i
                        done=False
                        while True: 
                            aa=A0.inverse_letter(tmp_cyclic_0[j])
                            j=0
                            while j<len(tmp_cyclic_0) and tmp_cyclic_0[j]!=aa:
                                j+=1
                            if j==len(tmp_cyclic_0) or j==0:
                                i+=1
                                break
                            j-=1
                            if i==j:
                                acceptable=False
                                if verbose:
                                    print "There is more than one boundary component on side 0"
                                    print "Cyclic order on side 0:",tmp_cyclic_0
                                i=len(tmp_cyclic_0)
                                break

                if not acceptable:
                    continue


                tmp_cyclic_1=[boundary[i][2][0] for i in xrange(current+1) if boundary[i][2][1]==1] 
                i=0
                if len(tmp_cyclic_1)<2*len(A1):
                    while i<len(tmp_cyclic_1):
                        j=i
                        done=False
                        while True: 
                            aa=A1.inverse_letter(tmp_cyclic_1[j])
                            j=0
                            while j<len(tmp_cyclic_1) and tmp_cyclic_1[j]!=aa:
                                j+=1
                            if j==len(tmp_cyclic_1) or j==0:
                                i+=1
                                break
                            j-=1
                            if i==j:
                                acceptable=False
                                if verbose:
                                    print "There is more than one boundary component on side 1"
                                    print "Cyclic order on side 1:",tmp_cyclic_1
                                i=len(tmp_cyclic_1)
                                break

                if not acceptable:
                    continue

            if current+1==boundary_length:
                eulerian_circuits.append(boundary[:current+1])    
            
            for i in xrange(current+1,len(boundary)):
                e=boundary[i]
                if e[0]!=boundary[current][1] or (e[2][2]!=0 and -e[2][2] in oriented):
                    continue
                if e[2][1]==0 and (cyclic_order_0 is not None) and (j0 is not None):
                    jj0=j0+1
                    if jj0==len(cyclic_order_0):
                        jj0=0
                    if e[2][0]!=cyclic_order_0[jj0]:
                        continue
                elif e[2][1]==1 and (cyclic_order_1 is not None) and (j1 is not None):
                    jj1=j1+1
                    if jj1==len(cyclic_order_1):
                        jj1=0
                    if e[2][0]!=cyclic_order_1[jj1]:
                        continue

                next.append((e,current+1))
                
                            

                
        if verbose:
            print "Possible boundaries:",eulerian_circuits
        
        if len(eulerian_circuits)>1:
            print "There is an ambiguity on the choice of the boundary of the surface."
            print "Specify using optionnal argument cyclic_order_0 and cyclic_order_1."
            print "Possible choices:"
            for cyclic_order in eulerian_circuits:
                print "side 0:",[e[2][0] for e in cyclic_order if e[2][1]==0]
                print "side 1:",[e[2][0] for e in cyclic_order if e[2][1]==1]
            print "The first one is chosen"    
        elif len(eulerian_circuits)==0:
            print "There are no eulerian circuit in the boundary compatible with the given cyclic orders."
            print "Probably changing the orientation will solve this problem"
            return False
        
        cyclic_order=eulerian_circuits[0]

        # Now we can fix the orientation of the squares according to
        # the chosen boundary

        direct_orientation=set(e[2][2] for e in cyclic_order if e[2][2]!=0)
        
        for i in xrange(len(self.squares())):
            if orientation[i] in direct_orientation:
                orientation[i]=-1
            else:
                orientation[i]=1
        

        if verbose:
            print "Orientation of the squares coherent with the choice of the boundary"
            print orientation

        self._squares_orientation=orientation

        # We put the edges in the fundamental domain
                    
        initial_vertex=dict()
        terminal_vertex=dict()

        for a in A0.positive_letters():
            aa=A0.inverse_letter(a)
            slicea=[i for i in xrange(len(squares)) if squares[i][4]==a]
            size=len(slicea)+1

            if size==1:
                continue

            # sort the edges of the slice
            i=1
            sqi=slicea[0]
            sq=squares[sqi]
            if orientation[sqi]==1:
                start0=(sq[0],sq[1])
                endi=(sq[3],sq[2])
            else:
                start0=(sq[3],sq[2])
                endi=(sq[0],sq[1])

            while i<len(slicea):
                j=i
                while j<len(slicea):
                    sqjj=slicea[j]
                    sqj=squares[sqjj]
                    if orientation[sqjj]==1:
                        startj=(sqj[0],sqj[1])
                        endj=(sqj[3],sqj[2])
                    else:
                        startj=(sqj[3],sqj[2])
                        endj=(sqj[0],sqj[1])
                    
                    if endi==startj: # next(es[i-1])==es[j]:
                        slicea[j],slicea[i]=slicea[i],slicea[j]
                        i+=1
                        endi=endj
                        if i<j:
                            j=j-1
                    elif endj==start0: #next(es[j])==es[0]:
                        slicea=[slicea[j]]+slicea[:j]+slicea[j+1:]
                        i+=1
                        start0=startj
                        if i<j:
                            j=j-1
                    j+=1

            if verbose:
                print "Slice of", a,":",slicea       

            # put a curve for each edge of the slice
            for i,sqi in enumerate(slicea):
                sq=squares[sqi]
                if orientation[sqi]==1:
                    initial_vertex[(sq[0],sq[3],sq[5])]=(a,(i+1.0)/size)
                    terminal_vertex[(sq[1],sq[2],sq[5])]=(aa,(size-i-1.0)/size)
                else:
                    terminal_vertex[(sq[0],sq[3],sq[5])]=(a,(i+1.0)/size)
                    initial_vertex[(sq[1],sq[2],sq[5])]=(aa,(size-i-1.0)/size)


        # We compute the regular 2N-gone that is the foundamental domain
        # of the surface on side 0

        i=0
        while cyclic_order[i][2][1]==1:
            i+=1


        a=A0.inverse_letter(cyclic_order[i][2][0])
        polygon_side_0=[a]

        for j in xrange(2*N-1):
            k=0
            while cyclic_order[k][2][1]==1 or cyclic_order[k][2][0]!=a:
                k+=1
            k-=1
            while cyclic_order[k][2][1]==1:
                k-=1
                if k==0:
                    k=boundary_length-1
            a=A0.inverse_letter(cyclic_order[k][2][0])
            polygon_side_0.append(a)


        if verbose:
            print "Polygon bounding the fundamental domain of the surface:",polygon_side_0

        i=0
        while polygon_side_0[i]!=A0[0]:
            i+=1
        polygon_side_0=polygon_side_0[i:]+polygon_side_0[:i]
            
            
        g=Graphics()

        boundary_initial_vertex=dict()
        boundary_terminal_vertex=dict()

        for i,a in enumerate(polygon_side_0):
            boundary_initial_vertex[a]=(RR(radius*cos(i*pi/N)),RR(radius*sin(i*pi/N)))
            boundary_terminal_vertex[a]=(RR(radius*cos((i+1)*pi/N)),RR(radius*sin((i+1)*pi/N)))


        # Regular polygon
        text_decalage=1.05
        for a in polygon_side_0:
            x,y=boundary_initial_vertex[a]
            xx,yy=boundary_terminal_vertex[a]
            g+=line([(x,y),(xx,yy)],alpha=1,thickness=2,hue=5.0/6)
            g+=text(a,((x+xx)/2*text_decalage**2,(y+yy)/2*text_decalage**2),hue=5.0/6)
 

        for e in initial_vertex:
            a,p=initial_vertex[e]
            b=e[2]
            x=boundary_initial_vertex[a][0]+p*(boundary_terminal_vertex[a][0]-boundary_initial_vertex[a][0])
            y=boundary_initial_vertex[a][1]+p*(boundary_terminal_vertex[a][1]-boundary_initial_vertex[a][1])
            if e in terminal_vertex:
                aa,pp=terminal_vertex[e]
            else: # the end of e is at the singularity
                i=0
                j=0
                while cyclic_order[i][2][1]==0 or cyclic_order[i][2][0]!=b:
                    if cyclic_order[i][2][1]==0:
                        j=i
                    i+=1
                    
                if j==0 and cyclic_order[j][2][1]==1:
                    j=len(cyclic_order)-1
                    while cyclic_order[j][2][1]==1:
                        j-=1
                aa=A0.inverse_letter(cyclic_order[j][2][0])
                pp=0

            xx=boundary_initial_vertex[aa][0]+pp*(boundary_terminal_vertex[aa][0]-boundary_initial_vertex[aa][0])
            yy=boundary_initial_vertex[aa][1]+pp*(boundary_terminal_vertex[aa][1]-boundary_initial_vertex[aa][1])

            g+=line([(x,y),(xx,yy)],alpha=1,thickness=2,hue=RR(A1.rank(b))/N)
            
        for e in terminal_vertex:
            if e not in initial_vertex: # the initial vertex of e is the singularity
                aa,pp=terminal_vertex[e]
                xx=boundary_initial_vertex[aa][0]+pp*(boundary_terminal_vertex[aa][0]-boundary_initial_vertex[aa][0])
                yy=boundary_initial_vertex[aa][1]+pp*(boundary_terminal_vertex[aa][1]-boundary_initial_vertex[aa][1])
                b=A1.inverse_letter(e[2][0])
                i=0
                j=0
                while cyclic_order[i][2][1]==0 or cyclic_order[i][2][0]!=b:
                    if cyclic_order[i][2][1]==0:
                         j=i
                    i+=1
                    
                if j==0 and cyclic_order[j][2][1]==1:
                    j=len(cyclic_order)-1
                    while cyclic_order[j][2][1]==1:
                        j-=1
                a=A0.inverse_letter(cyclic_order[j][2][0])
                x=boundary_initial_vertex[a][0]
                y=boundary_initial_vertex[a][1]
                
                g+=line([(x,y),(xx,yy)],alpha=1,thickness=2,hue=RR(A1.rank(b))/N)

                g+=text(e[2][0],(text_decalage*xx,text_decalage*yy),hue=RR(A1.rank(b))/N)

        
        for e in self.isolated_edges():
            if e[2][1]==1:
                #The end of e is at the singularity
                b=e[2][0]
                i=0
                j=0
                while cyclic_order[i][2][1]==0 or cyclic_order[i][2][0]!=b:
                    if cyclic_order[i][2][1]==0:
                         j=i
                    i+=1
                    
                if j==0 and cyclic_order[j][2][1]==1:
                    j=len(cyclic_order)-1
                    while cyclic_order[j][2][1]==1:
                        j-=1
                a=A0.inverse_letter(cyclic_order[j][2][0])
                x=boundary_initial_vertex[a][0]
                y=boundary_initial_vertex[a][1]

                #The start of e is also at the singularity 
                bb=A1.inverse_letter(b)
                i=0
                j=0
                while cyclic_order[i][2][1]==0 or cyclic_order[i][2][0]!=bb:
                    if cyclic_order[i][2][1]==0:
                        j=i
                    i+=1
                    
                if j==0 and cyclic_order[j][2][1]==1:
                    j=len(cyclic_order)-1
                    while cyclic_order[j][2][1]==1:
                        j-=1
                aa=A0.inverse_letter(cyclic_order[j][2][0])


                xx=boundary_initial_vertex[aa][0]
                yy=boundary_initial_vertex[aa][1]

                
                g+=line([(x,y),(xx,yy)],alpha=1,thickness=2,hue=RR(A1.rank(b))/N)

                g+=text(b,(text_decalage*x,text_decalage*y),hue=RR(A1.rank(b))/N)

        for sq in self.twice_light_squares():
            b=A1.to_positive_letter(sq[5])
            #The end of b is at the singularity
            i=0
            j=0
            while cyclic_order[i][2][1]==0 or cyclic_order[i][2][0]!=b:
                if cyclic_order[i][2][1]==0:
                     j=i
                i+=1

            if j==0 and cyclic_order[j][2][1]==1:
                j=len(cyclic_order)-1
                while cyclic_order[j][2][1]==1:
                    j-=1
            a=A0.inverse_letter(cyclic_order[j][2][0])
            x=boundary_initial_vertex[a][0]
            y=boundary_initial_vertex[a][1]

            #The start of b is also at the singularity 
            bb=A1.inverse_letter(b)
            i=0
            j=0
            while cyclic_order[i][2][1]==0 or cyclic_order[i][2][0]!=bb:
                if cyclic_order[i][2][1]==0:
                    j=i
                i+=1

            if j==0 and cyclic_order[j][2][1]==1:
                j=len(cyclic_order)-1
                while cyclic_order[j][2][1]==1:
                    j-=1
            aa=A0.inverse_letter(cyclic_order[j][2][0])


            xx=boundary_initial_vertex[aa][0]
            yy=boundary_initial_vertex[aa][1]


            g+=line([(x,y),(xx,yy)],alpha=1,thickness=2,hue=RR(A1.rank(b))/N)

            g+=text(b,(text_decalage*x,text_decalage*y),hue=RR(A1.rank(b))/N)


        g.axes(False)

        return g