Beispiel #1
0
    def plot_generators(self):
        r"""
        Plot ray generators.

        Ray generators must be specified during construction or using
        :meth:`set_rays` before calling this method.

        OUTPUT:

        - a plot.

        EXAMPLES::

            sage: from sage.geometry.toric_plotter import ToricPlotter
            sage: tp = ToricPlotter(dict(), 2, [(3,4)])
            sage: print tp.plot_generators()
            Graphics object consisting of 1 graphics primitive
        """
        generators = self.generators
        result = Graphics()
        if not generators or not self.show_generators:
            return result
        colors = color_list(self.generator_color, len(generators))
        d = self.dimension
        extra_options = self.extra_options
        origin = self.origin
        thickness = self.generator_thickness
        zorder = self.generator_zorder
        for generator, ray, color in zip(generators, self.rays, colors):
            if ray.norm() < generator.norm():
                result += line([origin, ray],
                               color=color,
                               thickness=thickness,
                               zorder=zorder,
                               **extra_options)
            else:
                # This should not be the case, but as of 4.6 plotting
                # functions are inconsistent and arrows behave very
                # different compared to lines.
                if d <= 2:
                    result += arrow(origin,
                                    generator,
                                    color=color,
                                    width=thickness,
                                    arrowsize=thickness + 1,
                                    zorder=zorder,
                                    **extra_options)
                else:
                    result += line([origin, generator],
                                   arrow_head=True,
                                   color=color,
                                   thickness=thickness,
                                   zorder=zorder,
                                   **extra_options)
        return result
Beispiel #2
0
    def plot_generators(self):
        r"""
        Plot ray generators.

        Ray generators must be specified during construction or using
        :meth:`set_rays` before calling this method.

        OUTPUT:

        - a plot.

        EXAMPLES::

            sage: from sage.geometry.toric_plotter import ToricPlotter
            sage: tp = ToricPlotter(dict(), 2, [(3,4)])
            sage: print tp.plot_generators()
            Graphics object consisting of 1 graphics primitive
        """
        generators = self.generators
        result = Graphics()
        if not generators or not self.show_generators:
            return result
        colors = color_list(self.generator_color, len(generators))
        d = self.dimension
        extra_options = self.extra_options
        origin = self.origin
        thickness = self.generator_thickness
        zorder = self.generator_zorder
        for generator, ray, color in zip(generators, self.rays, colors):
            if ray.norm() < generator.norm():
                result += line([origin, ray], color=color, thickness=thickness, zorder=zorder, **extra_options)
            else:
                # This should not be the case, but as of 4.6 plotting
                # functions are inconsistent and arrows behave very
                # different compared to lines.
                if d <= 2:
                    result += arrow(
                        origin,
                        generator,
                        color=color,
                        width=thickness,
                        arrowsize=thickness + 1,
                        zorder=zorder,
                        **extra_options
                    )
                else:
                    result += line(
                        [origin, generator],
                        arrow_head=True,
                        color=color,
                        thickness=thickness,
                        zorder=zorder,
                        **extra_options
                    )
        return result
Beispiel #3
0
    def plot_rays(self):
        r"""
        Plot rays and their labels.

        Ray generators must be specified during construction or using
        :meth:`set_rays` before calling this method.

        OUTPUT:

        - a plot.

        EXAMPLES::

            sage: from sage.geometry.toric_plotter import ToricPlotter
            sage: tp = ToricPlotter(dict(), 2, [(3,4)])
            sage: tp.plot_rays()
            Graphics object consisting of 2 graphics primitives
        """
        result = Graphics()
        rays = self.rays
        if not rays or not self.show_rays:
            return result
        extra_options = self.extra_options
        origin = self.origin
        colors = color_list(self.ray_color, len(rays))
        thickness = self.ray_thickness
        zorder = self.ray_zorder
        for end, color in zip(rays, colors):
            result += line([origin, end],
                           color=color, thickness=thickness,
                           zorder=zorder, **extra_options)
        result += self.plot_ray_labels()
        return result
Beispiel #4
0
    def plot_rays(self):
        r"""
        Plot rays and their labels.

        Ray generators must be specified during construction or using
        :meth:`set_rays` before calling this method.

        OUTPUT:

        - a plot.

        EXAMPLES::

            sage: from sage.geometry.toric_plotter import ToricPlotter
            sage: tp = ToricPlotter(dict(), 2, [(3,4)])
            sage: print tp.plot_rays()
            Graphics object consisting of 2 graphics primitives
        """
        result = Graphics()
        rays = self.rays
        if not rays or not self.show_rays:
            return result
        extra_options = self.extra_options
        origin = self.origin
        colors = color_list(self.ray_color, len(rays))
        thickness = self.ray_thickness
        zorder = self.ray_zorder
        for end, color in zip(rays, colors):
            result += line([origin, end],
                           color=color,
                           thickness=thickness,
                           zorder=zorder,
                           **extra_options)
        result += self.plot_ray_labels()
        return result
Beispiel #5
0
 def newton_plot(self):
     S = [QQ(s) for s in self.polygon_slopes]
     C = Counter(S)
     pts = [(0, 0)]
     x = y = 0
     for s in sorted(C):
         c = C[s]
         x += c
         y += c * s
         pts.append((x, y))
     L = Graphics()
     L += line([(0, 0), (0, y + 0.2)], color="grey")
     for i in range(1, y + 1):
         L += line([(0, i), (0.06, i)], color="grey")
     for i in range(1, C[0]):
         L += line([(i, 0), (i, 0.06)], color="grey")
     for i in range(len(pts) - 1):
         P = pts[i]
         Q = pts[i + 1]
         for x in range(P[0], Q[0] + 1):
             L += line(
                 [(x, P[1]),
                  (x, P[1] + (x - P[0]) * (Q[1] - P[1]) / (Q[0] - P[0]))],
                 color="grey",
             )
         for y in range(P[1], Q[1]):
             L += line(
                 [(P[0] + (y - P[1]) * (Q[0] - P[0]) / (Q[1] - P[1]), y),
                  (Q[0], y)],
                 color="grey",
             )
     L += line(pts, thickness=2)
     L.axes(False)
     L.set_aspect_ratio(1)
     return encode_plot(L, pad=0, pad_inches=0, bbox_inches="tight")
Beispiel #6
0
 def newton_plot(self):
     S = [QQ(s) for s in self.slopes]
     C = Counter(S)
     pts = [(0,0)]
     x = y = 0
     for s in sorted(C):
         c = C[s]
         x += c
         y += c*s
         pts.append((x,y))
     L = Graphics()
     L += line([(0,0),(0,y+0.2)],color="grey")
     for i in range(1,y+1):
         L += line([(0,i),(0.06,i)],color="grey")
     for i in range(1,C[0]):
         L += line([(i,0),(i,0.06)],color="grey")
     for i in range(len(pts)-1):
         P = pts[i]
         Q = pts[i+1]
         for x in range(P[0],Q[0]+1):
             L += line([(x,P[1]),(x,P[1] + (x-P[0])*(Q[1]-P[1])/(Q[0]-P[0]))],color="grey")
         for y in range(P[1],Q[1]):
             L += line([(P[0] + (y-P[1])*(Q[0]-P[0])/(Q[1]-P[1]),y),(Q[0],y)],color="grey")
     L += line(pts, thickness = 2)
     L.axes(False)
     L.set_aspect_ratio(1)
     return encode_plot(L, pad=0, pad_inches=0, bbox_inches='tight')
Beispiel #7
0
 def plot(self, disks=False, **kwds):
     gr  = plot.point2d(self.dop._singularities(CC),
                        marker='*', color='red', **kwds)
     gr += plot.line([z.iv().mid() for z in self.vert])
     gr.set_aspect_ratio(1)
     if disks:
         for step in self:
             z = step.start.iv().mid()
             gr += plot.circle((z.real(), z.imag()),
                               step.start.dist_to_sing().lower(),
                               linestyle='dotted', color='red')
             gr += plot.circle((z.real(), z.imag()),
                               step.length().lower(),
                               linestyle='dashed')
     return gr
Beispiel #8
0
    def plot(self):
        """
        Plot the points of the sequence.

        Elements of the sequence are assumed to be real or from a
        finite field, with a real indexing set ``I = range(len(self))``.

        EXAMPLES::

            sage: I = range(3)
            sage: A = [ZZ(i^2)+1 for i in I]
            sage: s = IndexedSequence(A,I)
            sage: P = s.plot()
            sage: show(P) # Not tested
        """
        # elements must be coercible into RR
        I = self.index_object()
        S = self.list()
        return line([[RR(I[i]),RR(S[i])] for i in range(len(I)-1)])
Beispiel #9
0
    def plot(self):
        """
        Plot the points of the sequence.

        Elements of the sequence are assumed to be real or from a
        finite field, with a real indexing set ``I = range(len(self))``.

        EXAMPLES::

            sage: I = range(3)
            sage: A = [ZZ(i^2)+1 for i in I]
            sage: s = IndexedSequence(A,I)
            sage: P = s.plot()
            sage: show(P) # Not tested
        """
        # elements must be coercible into RR
        I = self.index_object()
        S = self.list()
        return line([[RR(I[i]),RR(S[i])] for i in range(len(I)-1)])
Beispiel #10
0
    def plot(self):
        """
        Plots the points of the sequence, whose elements are assumed
        to be real or from a finite field, with a real indexing set I
        = range(len(self)).
    
        EXAMPLES:
            sage: I = range(3)
            sage: A = [ZZ(i^2)+1 for i in I]
            sage: s = IndexedSequence(A,I)
            sage: P = s.plot()

        Now type show(P) to view this in a browser.
        """
        F = self.base_ring()   ## elements must be coercible into RR
        I = self.index_object()
        N = len(I)
        S = self.list()
        P = line([[RR(I[i]),RR(S[i])] for i in range(N-1)])
        return P
Beispiel #11
0
    def plot(self):
        """
        Plots the points of the sequence, whose elements are assumed
        to be real or from a finite field, with a real indexing set I
        = range(len(self)).

        EXAMPLES:
            sage: I = range(3)
            sage: A = [ZZ(i^2)+1 for i in I]
            sage: s = IndexedSequence(A,I)
            sage: P = s.plot()

        Now type show(P) to view this in a browser.
        """
        F = self.base_ring()   ## elements must be coercible into RR
        I = self.index_object()
        N = len(I)
        S = self.list()
        P = line([[RR(I[i]),RR(S[i])] for i in range(N-1)])
        return P
Beispiel #12
0
    def plot(self, xmin=None, xmax=None, **kwds):
        """
        Special fast plot method for spike functions.

        EXAMPLES::

            sage: S = spike_function([(-1,1),(1,40)])
            sage: P = plot(S)
            sage: P[0]
            Line defined by 8 points
        """
        v = []
        xmin, xmax = self._ranges(xmin, xmax)
        x = xmin
        eps = self.eps
        while x < xmax:
            y, i = self._eval(x)
            v.append((x, y))
            if i != -1:
                x0 = self.support[i] + eps
                v.extend([(x0, y), (x0, 0)])
                if i + 1 < len(self.support):
                    x = self.support[i + 1] - eps
                    v.append((x, 0))
                else:
                    x = xmax
                    v.append((xmax, 0))
            else:
                new_x = None
                for j in range(len(self.support)):
                    if self.support[j] - eps > x:
                        new_x = self.support[j] - eps
                        break
                if new_x is None:
                    new_x = xmax
                v.append((new_x, 0))
                x = new_x
        L = line(v, **kwds)
        L.xmin(xmin - 1)
        L.xmax(xmax)
        return L
Beispiel #13
0
    def plot(self, xmin=None, xmax=None, **kwds):
        """
        Special fast plot method for spike functions.

        EXAMPLES::

            sage: S = spike_function([(-1,1),(1,40)])
            sage: P = plot(S)
            sage: P[0]
            Line defined by 8 points
        """
        v = []
        xmin, xmax = self._ranges(xmin, xmax)
        x = xmin
        eps = self.eps
        while x < xmax:
            y, i = self._eval(x)
            v.append((x, y))
            if i != -1:
                x0 = self.support[i] + eps
                v.extend([(x0, y), (x0, 0)])
                if i + 1 < len(self.support):
                    x = self.support[i + 1] - eps
                    v.append((x, 0))
                else:
                    x = xmax
                    v.append((xmax, 0))
            else:
                new_x = None
                for j in range(len(self.support)):
                    if self.support[j] - eps > x:
                        new_x = self.support[j] - eps
                        break
                if new_x is None:
                    new_x = xmax
                v.append((new_x, 0))
                x = new_x
        L = line(v, **kwds)
        L.xmin(xmin - 1)
        L.xmax(xmax)
        return L
Beispiel #14
0
def plot_bounds(dop, ini=None, pt=None, eps=None, **kwds):
    r"""
    EXAMPLES::

        sage: from ore_algebra import *
        sage: from ore_algebra.analytic.naive_sum import *
        sage: Dops, x, Dx = DifferentialOperators()

        sage: plot_bounds(Dx - 1, [CBF(1)], CBF(i)/2, RBF(1e-20))
        Graphics object consisting of 5 graphics primitives

        sage: plot_bounds(x*Dx^3 + 2*Dx^2 + x*Dx, eps=1e-8)
        Graphics object consisting of 5 graphics primitives

        sage: dop = x*Dx^2 + Dx + x
        sage: plot_bounds(dop, eps=1e-8,
        ....:       ini=LogSeriesInitialValues(0, {0: (1, 0)}, dop))
        Graphics object consisting of 5 graphics primitives

        sage: dop = ((x^2 + 10*x + 50)*Dx^10 + (5/9*x^2 + 50/9*x + 155/9)*Dx^9
        ....: + (-10/3*x^2 - 100/3*x - 190/3)*Dx^8 + (30*x^2 + 300*x + 815)*Dx^7
        ....: + (145*x^2 + 1445*x + 3605)*Dx^6 + (5/2*x^2 + 25*x + 115/2)*Dx^5
        ....: + (20*x^2 + 395/2*x + 1975/4)*Dx^4 + (-5*x^2 - 50*x - 130)*Dx^3
        ....: + (5/4*x^2 + 25/2*x + 105/4)*Dx^2 + (-20*x^2 - 195*x - 480)*Dx
        ....: + 5*x - 10)
        sage: plot_bounds(dop, pol_part_len=4, bound_inverse="solve", eps=1e-10) # long time
        Graphics object consisting of 5 graphics primitives
    """
    import sage.plot.all as plot
    from sage.all import VectorSpace, QQ, RIF
    from ore_algebra.analytic.bounds import abs_min_nonzero_root
    if ini is None:
        ini = _random_ini(dop)
    if pt is None:
        rad = abs_min_nonzero_root(dop.leading_coefficient())
        pt = QQ(2) if rad == infinity else RIF(rad/2).simplest_rational()
    if eps is None:
        eps = RBF(1e-50)
    logger.info("point: %s", pt)
    logger.info("initial values: %s", ini)
    recd = []
    maj = bounds.DiffOpBound(dop, max_effort=0, **kwds)
    series_sum(dop, ini, pt, eps, stride=1, record_bounds_in=recd, maj=maj)
    ref_sum = recd[-1][1][0].add_error(recd[-1][2])
    recd[-1:] = []
    # Note: this won't work well when the errors get close to the double
    # precision underflow threshold.
    err = [(psum[0]-ref_sum).abs() for n, psum, _ in recd]
    large = float(1e200) # plot() is not robust to large values
    error_plot_upper = plot.line(
            [(n, v.upper()) for (n, v) in enumerate(err)
                            if abs(float(v.upper())) < large],
            color="lightgray", scale="semilogy")
    error_plot = plot.line(
            [(n, v.lower()) for (n, v) in enumerate(err)
                            if abs(float(v.lower())) < large],
            color="black", scale="semilogy")
    bound_plot_lower = plot.line(
            [(n, bound.lower()) for n, _, bound in recd
                                if abs(float(bound.lower())) < large],
            color="lightblue", scale="semilogy")
    bound_plot = plot.line(
            [(n, bound.upper()) for n, _, bound in recd
                                if abs(float(bound.upper())) < large],
            color="blue", scale="semilogy")
    title = repr(dop) + " @ x=" + repr(pt)
    title = title if len(title) < 80 else title[:77]+"..."
    myplot = error_plot_upper + error_plot + bound_plot_lower + bound_plot
    ymax = myplot.ymax()
    if ymax < float('inf'):
        txt = plot.text(title, (myplot.xmax(), ymax),
                        horizontal_alignment='right', vertical_alignment='top')
        myplot += txt
    return myplot
Beispiel #15
0
    def plot(self, cell_colors=None, **kwds):
        """
        Return a graphical representation for 2-dimensional Voronoi diagrams.

        INPUT:

        - ``cell_colors`` -- (default: ``None``) provide the colors for the cells, either as
          dictionary. Randomly colored cells are provided with ``None``.
        - ``**kwds`` -- optional keyword parameters, passed on as arguments for
          plot().

        OUTPUT:

        A graphics object.

        EXAMPLES::

            sage: P = [[0.671, 0.650], [0.258, 0.767], [0.562, 0.406], [0.254, 0.709], [0.493, 0.879]]

            sage: V = VoronoiDiagram(P); S=V.plot()
            sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false)

            sage: S=V.plot(cell_colors={0:'red', 1:'blue', 2:'green', 3:'white', 4:'yellow'})
            sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false)

            sage: S=V.plot(cell_colors=['red','blue','red','white', 'white'])
            sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false)

            sage: S=V.plot(cell_colors='something else')
            Traceback (most recent call last):
            ...
            AssertionError: 'cell_colors' must be a list or a dictionary


        Trying to plot a Voronoi diagram of dimension other than 2 gives an
        error::

            sage: VoronoiDiagram([[1, 2, 3], [6, 5, 4]]).plot()
            Traceback (most recent call last):
            ...
            NotImplementedError: Plotting of 3-dimensional Voronoi diagrams not
            implemented
        """

        if self.ambient_dim() == 2:
            S = line([])

            if cell_colors is None:
                from random import shuffle
                cell_colors = rainbow(self._n)
                shuffle(cell_colors)
            else:
                if not (isinstance(cell_colors, list) or (isinstance(cell_colors, dict))):
                    raise AssertionError("'cell_colors' must be a list or a dictionary")
            for i, p in enumerate(self._P):
                col = cell_colors[i]
                S += (self.regions()[p]).render_solid(color=col, zorder=1)
                S += point(p, color=col, pointsize=10, zorder=3)
                S += point(p, color='black', pointsize=20, zorder=2)
            return plot(S, **kwds)
        raise NotImplementedError('Plotting of ' + str(self.ambient_dim()) +
                                  '-dimensional Voronoi diagrams not' +
                                  ' implemented')
Beispiel #16
0
def geomrep(M1, B1=None, lineorders1=None, pd=None, sp=False):
    """
    Return a sage graphics object containing geometric representation of
    matroid M1.

    INPUT:

    - ``M1`` -- A matroid.
    - ``B1`` -- (optional) A list of elements in ``M1.groundset()`` that
    correspond to a basis of ``M1`` and will be placed as vertices of the
    triangle in the geometric representation of ``M1``.
    - ``lineorders1`` -- (optional) A list of ordered lists of elements of
    ``M1.grondset()`` such that if a line in geometric representation is
    setwise same as any of these then points contained will be traversed in
    that order thus overriding internal order deciding heuristic.
    - ``pd`` - (optional) A dictionary mapping ground set elements to their
    (x,y) positions.
    - ``sp`` -- (optional) If True, a positioning dictionary and line orders
    will be placed in ``M._cached_info``.

    OUTPUT:

    A sage graphics object of type <class 'sage.plot.graphics.Graphics'> that
    corresponds to the geometric representation of the matroid.

    EXAMPLES::

        sage: from sage.matroids import matroids_plot_helpers
        sage: M=matroids.named_matroids.P7()
        sage: G=matroids_plot_helpers.geomrep(M)
        sage: G.show(xmin=-2, xmax=3, ymin=-2, ymax=3)
        sage: M=matroids.named_matroids.P7()
        sage: G=matroids_plot_helpers.geomrep(M,lineorders1=[['f','e','d']])
        sage: G.show(xmin=-2, xmax=3, ymin=-2, ymax=3)

    .. NOTE::

            This method does NOT do any checks.
    """
    G = Graphics()
    # create lists of loops and parallel elements and simplify given matroid
    [M, L, P] = slp(M1, pos_dict=pd, B=B1)
    if B1 is None:
        B1 = list(M.basis())
    M._cached_info = M1._cached_info

    if M.rank() == 0:
        limits = None
        loops = L
        looptext = ", ".join([str(l) for l in loops])
        rectx = -1
        recty = -1
        rectw = 0.5 + 0.4*len(loops) + 0.5  # controlled based on len(loops)
        recth = 0.6
        G += polygon2d([[rectx, recty], [rectx, recty+recth],
                        [rectx+rectw, recty+recth], [rectx+rectw, recty]],
                       color='black', fill=False, thickness=4)
        G += text(looptext, (rectx+0.5, recty+0.3), color='black',
                  fontsize=13)
        G += point((rectx+0.2, recty+0.3), color=Color('#BDBDBD'), size=300,
                   zorder=2)
        G += text('Loop(s)', (rectx+0.5+0.4*len(loops)+0.1, recty+0.3),
                  fontsize=13, color='black')
        limits = tracklims(limits, [rectx, rectx+rectw], [recty, recty+recth])
        G.axes(False)
        G.axes_range(xmin=limits[0]-0.5, xmax=limits[1]+0.5,
                     ymin=limits[2]-0.5, ymax=limits[3]+0.5)
        return G
    elif M.rank() == 1:
        if M._cached_info is not None and \
           'plot_positions' in M._cached_info.keys() and \
           M._cached_info['plot_positions'] is not None:
            pts = M._cached_info['plot_positions']
        else:
            pts = {}
            gnd = sorted(M.groundset())
        pts[gnd[0]] = (1, float(2)/3)
        G += point((1, float(2)/3), size=300, color=Color('#BDBDBD'), zorder=2)
        pt = [1, float(2)/3]
        if len(P) == 0:
            G += text(gnd[0], (float(pt[0]), float(pt[1])), color='black',
                      fontsize=13)
        pts2 = pts
        # track limits [xmin,xmax,ymin,ymax]
        pl = [list(x) for x in pts2.values()]
        lims = tracklims([None, None, None, None], [pt[0] for pt in pl],
                         [pt[1] for pt in pl])
    elif M.rank() == 2:
        nB1 = list(set(list(M.groundset())) - set(B1))
        bline = []
        for j in nB1:
            if M.is_dependent([j, B1[0], B1[1]]):
                bline.append(j)
        interval = len(bline)+1
        if M._cached_info is not None and \
           'plot_positions' in M._cached_info.keys() and \
           M._cached_info['plot_positions'] is not None:
            pts2 = M._cached_info['plot_positions']
        else:
            pts2 = {}
            pts2[B1[0]] = (0, 0)
            pts2[B1[1]] = (2, 0)
            lpt = list(pts2[B1[0]])
            rpt = list(pts2[B1[1]])
            for k in range(len(bline)):
                cc = (float(1)/interval)*(k+1)
                pts2[bline[k]] = (cc*lpt[0]+(1-cc)*rpt[0],
                                  cc*lpt[1]+(1-cc)*rpt[1])
            if sp is True:
                M._cached_info['plot_positions'] = pts2
        # track limits [xmin,xmax,ymin,ymax]
        pl = [list(x) for x in pts2.values()]
        lims = tracklims([None, None, None, None], [pt[0] for pt in pl],
                         [pt[1] for pt in pl])
        bline.extend(B1)
        ptsx, ptsy, x_i, y_i = createline(pts2, bline, lineorders1)
        lims = tracklims(lims, x_i, y_i)
        G += line(zip(x_i, y_i), color='black', thickness=3, zorder=1)
        pels = [p for p in pts2.keys() if any([M1.rank([p, q]) == 1
                for q in P])]
        allpts = [list(pts2[i]) for i in M.groundset()]
        xpts = [float(k[0]) for k in allpts]
        ypts = [float(k[1]) for k in allpts]
        G += points(zip(xpts, ypts), color=Color('#BDBDBD'), size=300,
                    zorder=2)
        for i in pts2:
            if i not in pels:
                pt = list(pts2[i])
                G += text(i, (float(pt[0]), float(pt[1])), color='black',
                          fontsize=13)
    else:
        if M._cached_info is None or \
           'plot_positions' not in M._cached_info.keys() or \
           M._cached_info['plot_positions'] is None:
            (pts, trilines,
             nontripts, curvedlines) = it(M1, B1,
                                          list(set(M.groundset())-set(B1)),
                                          list(set(L) | set(P)))
            pts2 = addnontripts([B1[0], B1[1], B1[2]], nontripts, pts)
            trilines.extend(curvedlines)
        else:
            pts2 = M._cached_info['plot_positions']
            trilines = [list(set(list(x)).difference(L | P))
                        for x in M1.flats(2)
                        if len(list(x)) >= 3]
        pl = [list(x) for x in pts2.values()]
        lims = tracklims([None, None, None, None], [pt[0] for pt in pl],
                         [pt[1] for pt in pl])
        j = 0
        for ll in trilines:
            if len(ll) >= 3:
                ptsx, ptsy, x_i, y_i = createline(pts2, ll, lineorders1)
                lims = tracklims(lims, x_i, y_i)
                G += line(zip(x_i, y_i), color='black', thickness=3, zorder=1)
        pels = [p for p in pts2.keys() if any([M1.rank([p, q]) == 1
                for q in P])]
        allpts = [list(pts2[i]) for i in M.groundset()]
        xpts = [float(k[0]) for k in allpts]
        ypts = [float(k[1]) for k in allpts]
        G += points(zip(xpts, ypts), color=Color('#BDBDBD'), size=300,
                    zorder=2)
        for i in pts2:
            if i not in pels:
                pt = list(pts2[i])
                G += text(i, (float(pt[0]), float(pt[1])), color='black',
                          fontsize=13)
        if sp is True:
            M1._cached_info['plot_positions'] = pts2
            M1._cached_info['plot_lineorders'] = lineorders1
    # deal with loops and parallel elements
    G, lims = addlp(M1, M, L, P, pts2, G, lims)
    G.axes(False)
    G.axes_range(xmin=lims[0]-0.5, xmax=lims[1]+0.5, ymin=lims[2]-0.5,
                 ymax=lims[3]+0.5)
    return G
Beispiel #17
0
    def plot(self, **kwds):
        """
        Returns a graphics object representing the (di)graph.
        
        INPUT:
            - pos -- an optional positioning dictionary
            - layout -- what kind of layout to use, takes precedence over pos

              - 'circular' -- plots the graph with vertices evenly distributed
                on a circle
              - 'spring' -- uses the traditional spring layout, using the
                graph's current positions as initial positions
              - 'tree' -- the (di)graph must be a tree. One can specify the root
                of the tree using the keyword tree_root, otherwise a root
                will be selected at random. Then the tree will be plotted in
                levels, depending on minimum distance for the root.
            - vertex_labels -- whether to print vertex labels
              edge_labels -- whether to print edge labels. By default, False,
              but if True, the result of str(l) is printed on the edge for
              each label l. Labels equal to None are not printed (to set edge
              labels, see set_edge_label).
            - vertex_size -- size of vertices displayed
            - vertex_shape -- the shape to draw the vertices (Not available for
              multiedge digraphs.
            - graph_border -- whether to include a box around the graph
            - vertex_colors -- optional dictionary to specify vertex colors: each
              key is a color recognizable by matplotlib, and each corresponding
              entry is a list of vertices. If a vertex is not listed, it looks
              invisible on the resulting plot (it doesn't get drawn).
            - edge_colors -- a dictionary specifying edge colors: each key is a
              color recognized by matplotlib, and each entry is a list of edges.
            - partition -- a partition of the vertex set. if specified, plot will
              show each cell in a different color. vertex_colors takes precedence.
            - talk -- if true, prints large vertices with white backgrounds so that
              labels are legible on slides
            - iterations -- how many iterations of the spring layout algorithm to
              go through, if applicable
            - color_by_label -- if True, color edges by their labels
            - heights -- if specified, this is a dictionary from a set of
              floating point heights to a set of vertices
            - edge_style -- keyword arguments passed into the
              edge-drawing routine.  This currently only works for
              directed graphs, since we pass off the undirected graph to
              networkx
            - tree_root -- a vertex of the tree to be used as the root for
              the layout="tree" option. If no root is specified, then one
              is chosen at random. Ignored unless layout='tree'. 
            - tree_orientation -- "up" or "down" (default is "down"). 
              If "up" (resp., "down"), then the root of the tree will
              appear on the bottom (resp., top) and the tree will grow
              upwards (resp. downwards). Ignored unless layout='tree'.
            - save_pos -- save position computed during plotting

        EXAMPLES::

            sage: from sage.graphs.graph_plot import graphplot_options
            sage: list(sorted(graphplot_options.iteritems()))
            [('by_component', 'Whether to do the spring layout by connected component -- a boolean.'),
             ('color_by_label', 'Whether or not to color the edges by their label values.'),
             ('dim', 'The dimension of the layout -- 2 or 3.'),
             ('dist', 'The distance between multiedges.'),
             ('edge_color', 'The default color for edges.'),
             ('edge_colors', 'Dictionary of edge coloring.'),
             ('edge_labels', 'Whether or not to draw edge labels.'),
             ('edge_style', 'The linestyle of the edges-- one of "solid", "dashed", "dotted", dashdot".'),
             ('graph_border', 'Whether or not to draw a frame around the graph.'),
             ('heights', 'A dictionary mapping heights to the list of vertices at this height.'),
             ('iterations', 'The number of times to execute the spring layout algorithm.'),
             ('layout', 'A layout algorithm -- one of "acyclic", "circular", "ranked", "graphviz", "planar", "spring", or "tree".'),
             ('loop_size', 'The radius of the smallest loop.'),
             ('max_dist', 'The max distance range to allow multiedges.'),
             ('partition', 'A partition of the vertex set.  (Draws each cell of vertices in a different color).'),
             ('pos', 'The position dictionary of vertices'),
             ('prog', 'Which graphviz layout program to use -- one of "circo", "dot", "fdp", "neato", or "twopi".'),
             ('save_pos', 'Whether or not to save the computed position for the graph.'),
             ('spring', 'Use spring layout to finalize the current layout.'),
             ('talk', 'Whether to display the vertices in talk mode (larger and white)'),
             ('tree_orientation', 'The direction of tree branches -- "up" or "down".'),
             ('tree_root', 'A vertex designation for drawing trees.'),
             ('vertex_colors', 'Dictionary of vertex coloring.'),
             ('vertex_labels', 'Whether or not to draw vertex labels.'),
             ('vertex_shape', 'The shape to draw the vertices, Currently unavailable for Multi-edged DiGraphs.'),
             ('vertex_size', 'The size to draw the vertices.')]

            sage: from math import sin, cos, pi
            sage: P = graphs.PetersenGraph()
            sage: d = {'#FF0000':[0,5], '#FF9900':[1,6], '#FFFF00':[2,7], '#00FF00':[3,8], '#0000FF':[4,9]}
            sage: pos_dict = {}
            sage: for i in range(5):
            ...    x = float(cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: for i in range(10)[5:]:
            ...    x = float(0.5*cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(0.5*sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: pl = P.graphplot(pos=pos_dict, vertex_colors=d)
            sage: pl.show()
            
            sage: C = graphs.CubeGraph(8)
            sage: P = C.graphplot(vertex_labels=False, vertex_size=0, graph_border=True)
            sage: P.show()
            
            sage: G = graphs.HeawoodGraph().copy(sparse=True)
            sage: for u,v,l in G.edges():
            ...    G.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: G.graphplot(edge_labels=True).show()
            
            sage: D = DiGraph( { 0: [1, 10, 19], 1: [8, 2], 2: [3, 6], 3: [19, 4], 4: [17, 5], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], 11: [12, 18], 12: [16, 13], 13: [14], 14: [15], 15: [16], 16: [17], 17: [18], 18: [19], 19: []}, implementation='networkx' )
            sage: for u,v,l in D.edges():
            ...    D.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: D.graphplot(edge_labels=True, layout='circular').show()

            sage: from sage.plot.colors import rainbow
            sage: C = graphs.CubeGraph(5)
            sage: R = rainbow(5)
            sage: edge_colors = {}
            sage: for i in range(5):
            ...    edge_colors[R[i]] = []
            sage: for u,v,l in C.edges():
            ...    for i in range(5):
            ...        if u[i] != v[i]:
            ...            edge_colors[R[i]].append((u,v,l))
            sage: C.graphplot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show()

            sage: D = graphs.DodecahedralGraph()
            sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]]
            sage: D.show(partition=Pi)

            sage: G = graphs.PetersenGraph()
            sage: G.allow_loops(True)
            sage: G.add_edge(0,0)
            sage: G.show()

            sage: D = DiGraph({0:[0,1], 1:[2], 2:[3]}, loops=True)
            sage: D.show()
            sage: D.show(edge_colors={(0,1,0):[(0,1,None),(1,2,None)],(0,0,0):[(2,3,None)]}) 

            sage: pos = {0:[0.0, 1.5], 1:[-0.8, 0.3], 2:[-0.6, -0.8], 3:[0.6, -0.8], 4:[0.8, 0.3]}
            sage: g = Graph({0:[1], 1:[2], 2:[3], 3:[4], 4:[0]})
            sage: g.graphplot(pos=pos, layout='spring', iterations=0).plot()

            sage: G = Graph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False
            sage: G = DiGraph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()
            sage: t.set_edge_label(0,1,-7)
            sage: t.set_edge_label(0,5,3)
            sage: t.set_edge_label(0,5,99)
            sage: t.set_edge_label(1,2,1000)
            sage: t.set_edge_label(3,2,'spam')
            sage: t.set_edge_label(2,6,3/2)
            sage: t.set_edge_label(0,4,66)
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}, edge_labels=True).plot()

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(layout='tree').show()

            sage: t = DiGraph('JCC???@A??GO??CO??GO??')
            sage: t.graphplot(layout='tree', tree_root=0, tree_orientation="up").show()

            sage: D = DiGraph({0:[1,2,3], 2:[1,4], 3:[0]})
            sage: D.graphplot().show()
            
            sage: D = DiGraph(multiedges=True, sparse=True)
            sage: for i in range(5):
            ...     D.add_edge((i,i+1,'a'))
            ...     D.add_edge((i,i-1,'b'))
            sage: D.graphplot(edge_labels=True,edge_colors=D._color_by_label()).plot()
            
            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='dashed').plot()
        """
        G = Graphics()
        for comp in self._plot_components.values():
            if not isinstance(comp, list):
                G += comp
            else:
                for item in comp:
                    G += item
        G.set_axes_range(*(self._graph._layout_bounding_box(self._pos)))
        if self._options['graph_border']:
            xmin = G.xmin()
            xmax = G.xmax()
            ymin = G.ymin()
            ymax = G.ymax()
            dx = (xmax-xmin)/10.0
            dy = (ymax-ymin)/10.0
            border = (line([( xmin - dx, ymin - dy), ( xmin - dx, ymax + dy ), ( xmax + dx, ymax + dy ), ( xmax + dx, ymin - dy ), ( xmin - dx, ymin - dy )], thickness=1.3))
            border.axes_range(xmin = (xmin - dx), xmax = (xmax + dx), ymin = (ymin - dy), ymax = (ymax + dy))
            G += border
        G.set_aspect_ratio(1)
        G.axes(False)
        G._extra_kwds['axes_pad']=.05
        return G
Beispiel #18
0
def geomrep(M1, B1=None, lineorders1=None, pd=None, sp=False):
    """
    Return a sage graphics object containing geometric representation of
    matroid M1.

    INPUT:

    - ``M1`` -- A matroid.
    - ``B1`` -- (optional) A list of elements in ``M1.groundset()`` that
      correspond to a basis of ``M1`` and will be placed as vertices of the
      triangle in the geometric representation of ``M1``.
    - ``lineorders1`` -- (optional) A list of ordered lists of elements of
      ``M1.grondset()`` such that if a line in geometric representation is
      setwise same as any of these then points contained will be traversed in
      that order thus overriding internal order deciding heuristic.
    - ``pd`` - (optional) A dictionary mapping ground set elements to their
      (x,y) positions.
    - ``sp`` -- (optional) If True, a positioning dictionary and line orders
      will be placed in ``M._cached_info``.

    OUTPUT:

    A sage graphics object of type <class 'sage.plot.graphics.Graphics'> that
    corresponds to the geometric representation of the matroid.

    EXAMPLES::

        sage: from sage.matroids import matroids_plot_helpers
        sage: M=matroids.named_matroids.P7()
        sage: G=matroids_plot_helpers.geomrep(M)
        sage: G.show(xmin=-2, xmax=3, ymin=-2, ymax=3)
        sage: M=matroids.named_matroids.P7()
        sage: G=matroids_plot_helpers.geomrep(M,lineorders1=[['f','e','d']])
        sage: G.show(xmin=-2, xmax=3, ymin=-2, ymax=3)

    .. NOTE::

            This method does NOT do any checks.
    """
    G = Graphics()
    # create lists of loops and parallel elements and simplify given matroid
    [M, L, P] = slp(M1, pos_dict=pd, B=B1)
    if B1 is None:
        B1 = list(M.basis())
    M._cached_info = M1._cached_info

    if M.rank() == 0:
        limits = None
        loops = L
        looptext = ", ".join([str(l) for l in loops])
        rectx = -1
        recty = -1
        rectw = 0.5 + 0.4 * len(loops) + 0.5  # controlled based on len(loops)
        recth = 0.6
        G += polygon2d(
            [[rectx, recty], [rectx, recty + recth],
             [rectx + rectw, recty + recth], [rectx + rectw, recty]],
            color='black',
            fill=False,
            thickness=4)
        G += text(looptext, (rectx + 0.5, recty + 0.3),
                  color='black',
                  fontsize=13)
        G += point((rectx + 0.2, recty + 0.3),
                   color=Color('#BDBDBD'),
                   size=300,
                   zorder=2)
        G += text('Loop(s)',
                  (rectx + 0.5 + 0.4 * len(loops) + 0.1, recty + 0.3),
                  fontsize=13,
                  color='black')
        limits = tracklims(limits, [rectx, rectx + rectw],
                           [recty, recty + recth])
        G.axes(False)
        G.axes_range(xmin=limits[0] - 0.5,
                     xmax=limits[1] + 0.5,
                     ymin=limits[2] - 0.5,
                     ymax=limits[3] + 0.5)
        return G
    elif M.rank() == 1:
        if M._cached_info is not None and \
           'plot_positions' in M._cached_info.keys() and \
           M._cached_info['plot_positions'] is not None:
            pts = M._cached_info['plot_positions']
        else:
            pts = {}
            gnd = sorted(M.groundset())
        pts[gnd[0]] = (1, float(2) / 3)
        G += point((1, float(2) / 3),
                   size=300,
                   color=Color('#BDBDBD'),
                   zorder=2)
        pt = [1, float(2) / 3]
        if len(P) == 0:
            G += text(gnd[0], (float(pt[0]), float(pt[1])),
                      color='black',
                      fontsize=13)
        pts2 = pts
        # track limits [xmin,xmax,ymin,ymax]
        pl = [list(x) for x in pts2.values()]
        lims = tracklims([None, None, None, None], [pt[0] for pt in pl],
                         [pt[1] for pt in pl])
    elif M.rank() == 2:
        nB1 = list(set(list(M.groundset())) - set(B1))
        bline = []
        for j in nB1:
            if M.is_dependent([j, B1[0], B1[1]]):
                bline.append(j)
        interval = len(bline) + 1
        if M._cached_info is not None and \
           'plot_positions' in M._cached_info.keys() and \
           M._cached_info['plot_positions'] is not None:
            pts2 = M._cached_info['plot_positions']
        else:
            pts2 = {}
            pts2[B1[0]] = (0, 0)
            pts2[B1[1]] = (2, 0)
            lpt = list(pts2[B1[0]])
            rpt = list(pts2[B1[1]])
            for k in range(len(bline)):
                cc = (float(1) / interval) * (k + 1)
                pts2[bline[k]] = (cc * lpt[0] + (1 - cc) * rpt[0],
                                  cc * lpt[1] + (1 - cc) * rpt[1])
            if sp is True:
                M._cached_info['plot_positions'] = pts2
        # track limits [xmin,xmax,ymin,ymax]
        pl = [list(x) for x in pts2.values()]
        lims = tracklims([None, None, None, None], [pt[0] for pt in pl],
                         [pt[1] for pt in pl])
        bline.extend(B1)
        ptsx, ptsy, x_i, y_i = createline(pts2, bline, lineorders1)
        lims = tracklims(lims, x_i, y_i)
        G += line(zip(x_i, y_i), color='black', thickness=3, zorder=1)
        pels = [
            p for p in pts2.keys() if any([M1.rank([p, q]) == 1 for q in P])
        ]
        allpts = [list(pts2[i]) for i in M.groundset()]
        xpts = [float(k[0]) for k in allpts]
        ypts = [float(k[1]) for k in allpts]
        G += points(zip(xpts, ypts),
                    color=Color('#BDBDBD'),
                    size=300,
                    zorder=2)
        for i in pts2:
            if i not in pels:
                pt = list(pts2[i])
                G += text(i, (float(pt[0]), float(pt[1])),
                          color='black',
                          fontsize=13)
    else:
        if M._cached_info is None or \
           'plot_positions' not in M._cached_info.keys() or \
           M._cached_info['plot_positions'] is None:
            (pts, trilines, nontripts,
             curvedlines) = it(M1, B1, list(set(M.groundset()) - set(B1)),
                               list(set(L) | set(P)))
            pts2 = addnontripts([B1[0], B1[1], B1[2]], nontripts, pts)
            trilines.extend(curvedlines)
        else:
            pts2 = M._cached_info['plot_positions']
            trilines = [
                list(set(list(x)).difference(L | P)) for x in M1.flats(2)
                if len(list(x)) >= 3
            ]
        pl = [list(x) for x in pts2.values()]
        lims = tracklims([None, None, None, None], [pt[0] for pt in pl],
                         [pt[1] for pt in pl])
        j = 0
        for ll in trilines:
            if len(ll) >= 3:
                ptsx, ptsy, x_i, y_i = createline(pts2, ll, lineorders1)
                lims = tracklims(lims, x_i, y_i)
                G += line(zip(x_i, y_i), color='black', thickness=3, zorder=1)
        pels = [
            p for p in pts2.keys() if any([M1.rank([p, q]) == 1 for q in P])
        ]
        allpts = [list(pts2[i]) for i in M.groundset()]
        xpts = [float(k[0]) for k in allpts]
        ypts = [float(k[1]) for k in allpts]
        G += points(zip(xpts, ypts),
                    color=Color('#BDBDBD'),
                    size=300,
                    zorder=2)
        for i in pts2:
            if i not in pels:
                pt = list(pts2[i])
                G += text(i, (float(pt[0]), float(pt[1])),
                          color='black',
                          fontsize=13)
        if sp is True:
            M1._cached_info['plot_positions'] = pts2
            M1._cached_info['plot_lineorders'] = lineorders1
    # deal with loops and parallel elements
    G, lims = addlp(M1, M, L, P, pts2, G, lims)
    G.axes(False)
    G.axes_range(xmin=lims[0] - 0.5,
                 xmax=lims[1] + 0.5,
                 ymin=lims[2] - 0.5,
                 ymax=lims[3] + 0.5)
    return G
Beispiel #19
0
    def plot(self, **kwds):
        """
        Returns a graphics object representing the (di)graph.

        INPUT:

        The options accepted by this method are to be found in the documentation
        of module :mod:`sage.graphs.graph_plot`.

        .. NOTE::

            See :mod:`the module's documentation <sage.graphs.graph_plot>` for
            information on default values of this method.

        We can specify some pretty precise plotting of familiar graphs::

            sage: from math import sin, cos, pi
            sage: P = graphs.PetersenGraph()
            sage: d = {'#FF0000':[0,5], '#FF9900':[1,6], '#FFFF00':[2,7], '#00FF00':[3,8], '#0000FF':[4,9]}
            sage: pos_dict = {}
            sage: for i in range(5):
            ...    x = float(cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: for i in range(10)[5:]:
            ...    x = float(0.5*cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(0.5*sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: pl = P.graphplot(pos=pos_dict, vertex_colors=d)
            sage: pl.show()

        Here are some more common graphs with typical options::

            sage: C = graphs.CubeGraph(8)
            sage: P = C.graphplot(vertex_labels=False, vertex_size=0, graph_border=True)
            sage: P.show()

            sage: G = graphs.HeawoodGraph().copy(sparse=True)
            sage: for u,v,l in G.edges():
            ...    G.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: G.graphplot(edge_labels=True).show()

        The options for plotting also work with directed graphs::

            sage: D = DiGraph( { 0: [1, 10, 19], 1: [8, 2], 2: [3, 6], 3: [19, 4], 4: [17, 5], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], 11: [12, 18], 12: [16, 13], 13: [14], 14: [15], 15: [16], 16: [17], 17: [18], 18: [19], 19: []}, implementation='networkx' )
            sage: for u,v,l in D.edges():
            ...    D.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: D.graphplot(edge_labels=True, layout='circular').show()

        This example shows off the coloring of edges::

            sage: from sage.plot.colors import rainbow
            sage: C = graphs.CubeGraph(5)
            sage: R = rainbow(5)
            sage: edge_colors = {}
            sage: for i in range(5):
            ...    edge_colors[R[i]] = []
            sage: for u,v,l in C.edges():
            ...    for i in range(5):
            ...        if u[i] != v[i]:
            ...            edge_colors[R[i]].append((u,v,l))
            sage: C.graphplot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show()

        With the ``partition`` option, we can separate out same-color groups
        of vertices::

            sage: D = graphs.DodecahedralGraph()
            sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]]
            sage: D.show(partition=Pi)

        Loops are also plotted correctly::

            sage: G = graphs.PetersenGraph()
            sage: G.allow_loops(True)
            sage: G.add_edge(0,0)
            sage: G.show()

        ::

            sage: D = DiGraph({0:[0,1], 1:[2], 2:[3]}, loops=True)
            sage: D.show()
            sage: D.show(edge_colors={(0,1,0):[(0,1,None),(1,2,None)],(0,0,0):[(2,3,None)]})

        More options::

            sage: pos = {0:[0.0, 1.5], 1:[-0.8, 0.3], 2:[-0.6, -0.8], 3:[0.6, -0.8], 4:[0.8, 0.3]}
            sage: g = Graph({0:[1], 1:[2], 2:[3], 3:[4], 4:[0]})
            sage: g.graphplot(pos=pos, layout='spring', iterations=0).plot()

            sage: G = Graph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False
            sage: G = DiGraph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False

        We can plot multiple graphs::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()

        ::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()
            sage: t.set_edge_label(0,1,-7)
            sage: t.set_edge_label(0,5,3)
            sage: t.set_edge_label(0,5,99)
            sage: t.set_edge_label(1,2,1000)
            sage: t.set_edge_label(3,2,'spam')
            sage: t.set_edge_label(2,6,3/2)
            sage: t.set_edge_label(0,4,66)
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}, edge_labels=True).plot()

        ::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(layout='tree').show()

        The tree layout is also useful::

            sage: t = DiGraph('JCC???@A??GO??CO??GO??')
            sage: t.graphplot(layout='tree', tree_root=0, tree_orientation="up").show()

        More examples::

            sage: D = DiGraph({0:[1,2,3], 2:[1,4], 3:[0]})
            sage: D.graphplot().show()

            sage: D = DiGraph(multiedges=True, sparse=True)
            sage: for i in range(5):
            ...     D.add_edge((i,i+1,'a'))
            ...     D.add_edge((i,i-1,'b'))
            sage: D.graphplot(edge_labels=True,edge_colors=D._color_by_label()).plot()

            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='dashed').plot()

        Wrong input (any input) :trac:`13891`::

            sage: graphs.PetersenGraph().graphplot().plot(aertataert=346345345)
            doctest:...: DeprecationWarning: This method takes no argument ! You may want to give it as an argument to graphplot instead.
            See http://trac.sagemath.org/13891 for details.
            <BLANKLINE>
        """
        # This method takes NO input
        # This has been added in early 2013. Remove it before my death, please.
        if kwds:
            from sage.misc.superseded import deprecation
            deprecation(13891, "This method takes no argument ! You may want "
                               "to give it as an argument to graphplot instead.")

        G = Graphics()
        for comp in self._plot_components.values():
            if not isinstance(comp, list):
                G += comp
            else:
                for item in comp:
                    G += item

        G.set_axes_range(*(self._graph._layout_bounding_box(self._pos)))
        if self._options['graph_border']:
            xmin = G.xmin()
            xmax = G.xmax()
            ymin = G.ymin()
            ymax = G.ymax()
            dx = (xmax-xmin)/10.0
            dy = (ymax-ymin)/10.0
            border = (line([( xmin - dx, ymin - dy), ( xmin - dx, ymax + dy ), ( xmax + dx, ymax + dy ), ( xmax + dx, ymin - dy ), ( xmin - dx, ymin - dy )], thickness=1.3))
            border.axes_range(xmin = (xmin - dx), xmax = (xmax + dx), ymin = (ymin - dy), ymax = (ymax + dy))
            G += border
        G.set_aspect_ratio(1)
        G.axes(False)
        G._extra_kwds['axes_pad']=.05
        return G
Beispiel #20
0
    def plot_heap(self):
        r"""
        Display the Hasse diagram of the heap of ``self``.

        The Hasse diagram is rendered in the lattice `S \times \NN`, with
        every element `i` in the poset drawn as a point labelled by its label
        `s_i`. Every point is placed in the column for its label at a certain
        level. The levels start at 0 and the level k of an element `i` is the
        maximal number `k` such that the heap contains a chain `i_0\prec
        i_1\prec ... \prec i_k` where `i_k=i`. See [Ste1996]_ and [GX2020]_.

        OUTPUT: GraphicsObject

        EXAMPLES::

            sage: FC = CoxeterGroup(['B', 5]).fully_commutative_elements()
            sage: FC([3,2,4,3,1]).plot_heap()
            Graphics object consisting of 15 graphics primitives

        .. PLOT::
            :width: 400px

            FC = CoxeterGroup(['B', 5]).fully_commutative_elements()
            g = FC([3,2,4,3,1]).plot_heap()
            sphinx_plot(g)
        """
        import sage.plot.all as plot

        m = self.parent().coxeter_group().coxeter_matrix()
        letters = self.parent().coxeter_group().index_set()
        graphics = []

        h = self.heap()
        levels = h.level_sets()
        letters_at_level = [set(self[i] for i in level) for level in levels]

        for (level_zero_index, members) in enumerate(levels):
            level = level_zero_index + 1
            for i in members:
                x = self[i]

                # Draw the node
                graphics.append(
                    plot.circle((x, level),
                                0.1,
                                fill=True,
                                facecolor='white',
                                edgecolor='blue',
                                zorder=1))
                graphics.append(
                    plot.text(str(x), (x, level), color='blue', zorder=2))

                neighbors = {z for z in letters if m[x, z] >= 3}
                for other in neighbors:
                    highest_level = max((j + 1 for j in range(level_zero_index)
                                         if other in letters_at_level[j]),
                                        default=None)
                    if highest_level:
                        graphics.append(
                            plot.line([(other, highest_level), (x, level)],
                                      color='black',
                                      zorder=0))

        g = sum(graphics)
        g.axes(False)
        return g
Beispiel #21
0
    def plot(self, **kwds):
        """
        Returns a graphics object representing the (di)graph.

        INPUT:

        The options accepted by this method are to be found in the documentation
        of the :mod:`sage.graphs.graph_plot` module, and the
        :meth:`~sage.plot.graphics.Graphics.show` method.

        .. NOTE::

            See :mod:`the module's documentation <sage.graphs.graph_plot>` for
            information on default values of this method.

        We can specify some pretty precise plotting of familiar graphs::

            sage: from math import sin, cos, pi
            sage: P = graphs.PetersenGraph()
            sage: d = {'#FF0000':[0,5], '#FF9900':[1,6], '#FFFF00':[2,7], '#00FF00':[3,8], '#0000FF':[4,9]}
            sage: pos_dict = {}
            sage: for i in range(5):
            ...    x = float(cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: for i in range(10)[5:]:
            ...    x = float(0.5*cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(0.5*sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: pl = P.graphplot(pos=pos_dict, vertex_colors=d)
            sage: pl.show()

        Here are some more common graphs with typical options::

            sage: C = graphs.CubeGraph(8)
            sage: P = C.graphplot(vertex_labels=False, vertex_size=0, graph_border=True)
            sage: P.show()

            sage: G = graphs.HeawoodGraph().copy(sparse=True)
            sage: for u,v,l in G.edges():
            ...    G.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: G.graphplot(edge_labels=True).show()

        The options for plotting also work with directed graphs::

            sage: D = DiGraph( { 0: [1, 10, 19], 1: [8, 2], 2: [3, 6], 3: [19, 4], 4: [17, 5], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], 11: [12, 18], 12: [16, 13], 13: [14], 14: [15], 15: [16], 16: [17], 17: [18], 18: [19], 19: []})
            sage: for u,v,l in D.edges():
            ...    D.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: D.graphplot(edge_labels=True, layout='circular').show()

        This example shows off the coloring of edges::

            sage: from sage.plot.colors import rainbow
            sage: C = graphs.CubeGraph(5)
            sage: R = rainbow(5)
            sage: edge_colors = {}
            sage: for i in range(5):
            ...    edge_colors[R[i]] = []
            sage: for u,v,l in C.edges():
            ...    for i in range(5):
            ...        if u[i] != v[i]:
            ...            edge_colors[R[i]].append((u,v,l))
            sage: C.graphplot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show()


        With the ``partition`` option, we can separate out same-color groups
        of vertices::

            sage: D = graphs.DodecahedralGraph()
            sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]]
            sage: D.show(partition=Pi)

        Loops are also plotted correctly::

            sage: G = graphs.PetersenGraph()
            sage: G.allow_loops(True)
            sage: G.add_edge(0,0)
            sage: G.show()

        ::

            sage: D = DiGraph({0:[0,1], 1:[2], 2:[3]}, loops=True)
            sage: D.show()
            sage: D.show(edge_colors={(0,1,0):[(0,1,None),(1,2,None)],(0,0,0):[(2,3,None)]})

        More options::

            sage: pos = {0:[0.0, 1.5], 1:[-0.8, 0.3], 2:[-0.6, -0.8], 3:[0.6, -0.8], 4:[0.8, 0.3]}
            sage: g = Graph({0:[1], 1:[2], 2:[3], 3:[4], 4:[0]})
            sage: g.graphplot(pos=pos, layout='spring', iterations=0).plot()
            Graphics object consisting of 11 graphics primitives

            sage: G = Graph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False
            sage: G = DiGraph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False

        We can plot multiple graphs::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()
            Graphics object consisting of 14 graphics primitives

        ::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()
            Graphics object consisting of 14 graphics primitives
            sage: t.set_edge_label(0,1,-7)
            sage: t.set_edge_label(0,5,3)
            sage: t.set_edge_label(0,5,99)
            sage: t.set_edge_label(1,2,1000)
            sage: t.set_edge_label(3,2,'spam')
            sage: t.set_edge_label(2,6,3/2)
            sage: t.set_edge_label(0,4,66)
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}, edge_labels=True).plot()
            Graphics object consisting of 20 graphics primitives

        ::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(layout='tree').show()

        The tree layout is also useful::

            sage: t = DiGraph('JCC???@A??GO??CO??GO??')
            sage: t.graphplot(layout='tree', tree_root=0, tree_orientation="up").show()

        More examples::

            sage: D = DiGraph({0:[1,2,3], 2:[1,4], 3:[0]})
            sage: D.graphplot().show()

            sage: D = DiGraph(multiedges=True, sparse=True)
            sage: for i in range(5):
            ...     D.add_edge((i,i+1,'a'))
            ...     D.add_edge((i,i-1,'b'))
            sage: D.graphplot(edge_labels=True,edge_colors=D._color_by_label()).plot()
            Graphics object consisting of 34 graphics primitives

            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='dashed').plot()
            Graphics object consisting of 22 graphics primitives

        The ``edge_style`` option may be provided in the short format too::

            sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='--').plot()
            Graphics object consisting of 22 graphics primitives

        TESTS:

        Make sure that show options work with plot also::

            sage: g = Graph({})
            sage: g.plot(title='empty graph', axes=True)
            Graphics object consisting of 0 graphics primitives

        Check for invalid inputs::

            sage: p = graphs.PetersenGraph().plot(egabrag='garbage')
            Traceback (most recent call last):
            ...
            ValueError: Invalid input 'egabrag=garbage'

        Make sure that no graphics primitive is clipped::

            sage: tadpole = Graph({0:[0,1]}).plot()
            sage: bbox = tadpole.get_minmax_data()
            sage: for part in tadpole:
            ....:      part_bbox = part.get_minmax_data()
            ....:      assert bbox['xmin'] <= part_bbox['xmin'] <= part_bbox['xmax'] <= bbox['xmax']
            ....:      assert bbox['ymin'] <= part_bbox['ymin'] <= part_bbox['ymax'] <= bbox['ymax']
        """
        G = Graphics()
        options = self._options.copy()
        options.update(kwds)
        G._set_extra_kwds(Graphics._extract_kwds_for_show(options))

        # Check the arguments
        for o in options:
            if o not in graphplot_options and o not in G._extra_kwds:
                raise ValueError("Invalid input '{}={}'".format(o, options[o]))

        for comp in self._plot_components.values():
            if not isinstance(comp, list):
                G += comp
            else:
                for item in comp:
                    G += item

        if self._options['graph_border']:
            xmin = G.xmin()
            xmax = G.xmax()
            ymin = G.ymin()
            ymax = G.ymax()
            dx = (xmax - xmin) / 10.0
            dy = (ymax - ymin) / 10.0
            border = (line([(xmin - dx, ymin - dy), (xmin - dx, ymax + dy),
                            (xmax + dx, ymax + dy), (xmax + dx, ymin - dy),
                            (xmin - dx, ymin - dy)],
                           thickness=1.3))
            border.axes_range(xmin=(xmin - dx),
                              xmax=(xmax + dx),
                              ymin=(ymin - dy),
                              ymax=(ymax + dy))
            G += border
        G.set_aspect_ratio(1)
        G.axes(False)
        return G
Beispiel #22
0
    def plot(self, cell_colors=None, **kwds):
        """
        Return a graphical representation for 2-dimensional Voronoi diagrams.

        INPUT:

        - ``cell_colors`` -- (default: ``None``) provide the colors for the cells, either as
          dictionary. Randomly colored cells are provided with ``None``.
        - ``**kwds`` -- optional keyword parameters, passed on as arguments for
          plot().

        OUTPUT:

        A graphics object.

        EXAMPLES::

            sage: P = [[0.671, 0.650], [0.258, 0.767], [0.562, 0.406], [0.254, 0.709], [0.493, 0.879]]

            sage: V = VoronoiDiagram(P); S=V.plot()
            sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false)

            sage: S=V.plot(cell_colors={0:'red', 1:'blue', 2:'green', 3:'white', 4:'yellow'})
            sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false)

            sage: S=V.plot(cell_colors=['red','blue','red','white', 'white'])
            sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false)

            sage: S=V.plot(cell_colors='something else')
            Traceback (most recent call last):
            ...
            AssertionError: 'cell_colors' must be a list or a dictionary


        Trying to plot a Voronoi diagram of dimension other than 2 gives an
        error::

            sage: VoronoiDiagram([[1, 2, 3], [6, 5, 4]]).plot()
            Traceback (most recent call last):
            ...
            NotImplementedError: Plotting of 3-dimensional Voronoi diagrams not
            implemented
        """

        if self.ambient_dim() == 2:
            S = line([])

            if cell_colors is None:
                from random import shuffle
                cell_colors = rainbow(self._n)
                shuffle(cell_colors)
            else:
                if not (isinstance(cell_colors, list) or (isinstance(cell_colors, dict))):
                    raise AssertionError("'cell_colors' must be a list or a dictionary")
            for i, p in enumerate(self._P):
                col = cell_colors[i]
                S += (self.regions()[p]).render_solid(color=col, zorder=1)
                S += point(p, color=col, pointsize=10, zorder=3)
                S += point(p, color='black', pointsize=20, zorder=2)
            return plot(S, **kwds)
        raise NotImplementedError('Plotting of ' + str(self.ambient_dim()) +
                                  '-dimensional Voronoi diagrams not' +
                                  ' implemented')
Beispiel #23
0
    def set_edges(self, **edge_options):
        """
        Sets the edge (or arrow) plotting parameters for the GraphPlot object.  This 
        function is called by the constructor but can also be called to make updates to
        the vertex options of an existing GraphPlot object.  Note that the changes are 
        cumulative.
        
        EXAMPLES::

            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: GP = g.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed')
            sage: GP.set_edges(edge_style='solid')
            sage: GP.plot()
            sage: GP.set_edges(edge_color='black')
            sage: GP.plot()
            
            sage: d = DiGraph({}, loops=True, multiedges=True, sparse=True)
            sage: d.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: GP = d.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed')
            sage: GP.set_edges(edge_style='solid')
            sage: GP.plot()
            sage: GP.set_edges(edge_color='black')
            sage: GP.plot()

        TESTS::
        
            sage: G = Graph("Fooba")
            sage: G.show(edge_colors={'red':[(3,6),(2,5)]})

        Verify that default edge labels are pretty close to being between the vertices
        in some cases where they weren't due to truncating division (trac #10124)::

            sage: test_graphs = graphs.FruchtGraph(), graphs.BullGraph()
            sage: tol = 0.001
            sage: for G in test_graphs:
            ...       E=G.edges()
            ...       for e0, e1, elab in E:
            ...           G.set_edge_label(e0, e1, '%d %d' % (e0, e1))
            ...       gp = G.graphplot(save_pos=True,edge_labels=True)
            ...       vx = gp._plot_components['vertices'][0].xdata
            ...       vy = gp._plot_components['vertices'][0].ydata
            ...       for elab in gp._plot_components['edge_labels']:
            ...           textobj = elab[0]
            ...           x, y, s = textobj.x, textobj.y, textobj.string
            ...           v0, v1 = map(int, s.split())
            ...           vn = vector(((x-(vx[v0]+vx[v1])/2.),y-(vy[v0]+vy[v1])/2.)).norm()
            ...           assert vn < tol


        """
        for arg in edge_options:
            self._options[arg] = edge_options[arg]
        if 'edge_colors' in edge_options: self._options['color_by_label'] = False
        
        # Handle base edge options: thickness, linestyle
        eoptions={}
        if 'edge_style' in self._options:
            eoptions['linestyle'] = self._options['edge_style']
        if 'thickness' in self._options:
            eoptions['thickness'] = self._options['thickness']
            
        # Set labels param to add labels on the fly
        labels = False
        if self._options['edge_labels']:
            labels = True
            self._plot_components['edge_labels'] = []

        # Make dict collection of all edges (keep label and edge color)           
        edges_to_draw = {}
        if self._options['color_by_label'] or isinstance(self._options['edge_colors'], dict):
            if self._options['color_by_label']: edge_colors = self._graph._color_by_label()
            else: edge_colors = self._options['edge_colors']
            for color in edge_colors:
                for edge in edge_colors[color]:
                    key = tuple(sorted([edge[0],edge[1]]))
                    if key == (edge[0],edge[1]): head = 1
                    else: head = 0 
                    
                    if len(edge) < 3:
                        label = self._graph.edge_label(edge[0],edge[1])
                        if isinstance(label, list):
                            if key in edges_to_draw:
                                edges_to_draw[key].append((label[-1], color, head))
                            else:
                                edges_to_draw[key] = [(label[-1], color, head)]
                            for i in range(len(label)-1):
                                edges_to_draw[key].append((label[-1], color, head))
                    else:
                        label = edge[2]
                        
                    if key in edges_to_draw:
                        edges_to_draw[key].append((label, color, head))
                    else:
                        edges_to_draw[key] = [(label, color, head)]
            # add unspecified edges in (default color black)
            for edge in self._graph.edge_iterator():
                key = tuple(sorted([edge[0],edge[1]]))
                label = edge[2]
                specified = False
                if key in edges_to_draw:
                    for old_label, old_color, old_head in edges_to_draw[key]:
                        if label == old_label:
                            specified = True
                            break
                if not specified:
                    if key == (edge[0],edge[1]): head = 1
                    else: head = 0 
                    edges_to_draw[key] = [(label, 'black', head)]
        else:
            for edge in self._graph.edges(sort=True):
                key = tuple(sorted([edge[0],edge[1]]))
                if key == (edge[0],edge[1]): head = 1
                else: head = 0 
                if key in edges_to_draw:
                    edges_to_draw[key].append((edge[2], self._options['edge_color'], head))
                else:
                    edges_to_draw[key] = [(edge[2], self._options['edge_color'], head)]
                
        if edges_to_draw:
            self._plot_components['edges'] = []
        else:
            return
                        
        # Check for multi-edges or loops
        if self._arcs or self._loops:
            tmp = edges_to_draw.copy()
            dist = self._options['dist']*2.
            loop_size = self._options['loop_size']
            max_dist = self._options['max_dist']
            from sage.functions.all import sqrt
            for (a,b) in tmp:
                if a == b:
                    # Loops 
                    distance = dist
                    local_labels = edges_to_draw.pop((a,b))
                    if len(local_labels)*dist > max_dist:
                        distance = float(max_dist)/len(local_labels)
                    curr_loop_size = loop_size
                    for i in range(len(local_labels)):
                        self._plot_components['edges'].append(circle((self._pos[a][0],self._pos[a][1]-curr_loop_size), curr_loop_size, rgbcolor=local_labels[i][1], **eoptions))
                        if labels:
                            self._plot_components['edge_labels'].append(text(local_labels[i][0], (self._pos[a][0], self._pos[a][1]-2*curr_loop_size)))
                        curr_loop_size += distance/4
                elif len(edges_to_draw[(a,b)]) > 1:
                    # Multi-edge
                    local_labels = edges_to_draw.pop((a,b))
                    
                    # Compute perpendicular bisector
                    p1 = self._pos[a]
                    p2 = self._pos[b]
                    M = ((p1[0]+p2[0])/2., (p1[1]+p2[1])/2.) # midpoint
                    if not p1[1] == p2[1]:
                        S = float(p1[0]-p2[0])/(p2[1]-p1[1]) # perp slope
                        y = lambda x : S*x-S*M[0]+M[1] # perp bisector line
                        
                        # f,g are functions of distance d to determine x values 
                        # on line y at d from point M
                        f = lambda d : sqrt(d**2/(1.+S**2)) + M[0]
                        g = lambda d : -sqrt(d**2/(1.+S**2)) + M[0]
                        
                        odd_x = f
                        even_x = g
                        if p1[0] == p2[0]:
                            odd_y = lambda d : M[1]
                            even_y = odd_y
                        else:
                            odd_y = lambda x : y(f(x))
                            even_y = lambda x : y(g(x))
                    else:
                        odd_x = lambda d : M[0]
                        even_x = odd_x
                        odd_y = lambda d : M[1] + d
                        even_y = lambda d : M[1] - d
                    
                    # We now have the control points for each bezier curve
                    # in terms of distance parameter d.
                    # Also note that the label for each edge should be drawn at d/2.
                    # (This is because we're using the perp bisectors).
                    distance = dist
                    if len(local_labels)*dist > max_dist:
                        distance = float(max_dist)/len(local_labels)
                    for i in range(len(local_labels)/2):
                        k = (i+1.0)*distance
                        if self._arcdigraph:
                            odd_start = self._polar_hack_for_multidigraph(p1, [odd_x(k),odd_y(k)], self._vertex_radius)[0]
                            odd_end = self._polar_hack_for_multidigraph([odd_x(k),odd_y(k)], p2, self._vertex_radius)[1]
                            even_start = self._polar_hack_for_multidigraph(p1, [even_x(k),even_y(k)], self._vertex_radius)[0]
                            even_end = self._polar_hack_for_multidigraph([even_x(k),even_y(k)], p2, self._vertex_radius)[1]
                            self._plot_components['edges'].append(arrow(path=[[odd_start,[odd_x(k),odd_y(k)],odd_end]], head=local_labels[2*i][2], zorder=1, rgbcolor=local_labels[2*i][1], **eoptions))
                            self._plot_components['edges'].append(arrow(path=[[even_start,[even_x(k),even_y(k)],even_end]], head=local_labels[2*i+1][2], zorder=1, rgbcolor=local_labels[2*i+1][1], **eoptions))
                        else:
                            self._plot_components['edges'].append(bezier_path([[p1,[odd_x(k),odd_y(k)],p2]],zorder=1, rgbcolor=local_labels[2*i][1], **eoptions))
                            self._plot_components['edges'].append(bezier_path([[p1,[even_x(k),even_y(k)],p2]],zorder=1, rgbcolor=local_labels[2*i+1][1], **eoptions))
                        if labels:
                            j = k/2.0
                            self._plot_components['edge_labels'].append(text(local_labels[2*i][0],[odd_x(j),odd_y(j)]))
                            self._plot_components['edge_labels'].append(text(local_labels[2*i+1][0],[even_x(j),even_y(j)]))
                    if len(local_labels)%2 == 1:
                        edges_to_draw[(a,b)] = [local_labels[-1]] # draw line for last odd    
        
        dir = self._graph.is_directed()                                
        for (a,b) in edges_to_draw:
            if self._arcdigraph:
                C,D = self._polar_hack_for_multidigraph(self._pos[a], self._pos[b], self._vertex_radius)
                self._plot_components['edges'].append(arrow(C,D, rgbcolor=edges_to_draw[(a,b)][0][1], head=edges_to_draw[(a,b)][0][2], **eoptions))
                if labels:
                    self._plot_components['edge_labels'].append(text(str(edges_to_draw[(a,b)][0][0]),[(C[0]+D[0])/2., (C[1]+D[1])/2.]))
            elif dir:
                self._plot_components['edges'].append(arrow(self._pos[a],self._pos[b], rgbcolor=edges_to_draw[(a,b)][0][1], arrowshorten=self._arrowshorten, head=edges_to_draw[(a,b)][0][2], **eoptions))
            else:
                self._plot_components['edges'].append(line([self._pos[a],self._pos[b]], rgbcolor=edges_to_draw[(a,b)][0][1], **eoptions))
            if labels and not self._arcdigraph:
                self._plot_components['edge_labels'].append(text(str(edges_to_draw[(a,b)][0][0]),[(self._pos[a][0]+self._pos[b][0])/2., (self._pos[a][1]+self._pos[b][1])/2.]))
Beispiel #24
0
    def set_edges(self, **edge_options):
        """
        Sets the edge (or arrow) plotting parameters for the GraphPlot object.  This 
        function is called by the constructor but can also be called to make updates to
        the vertex options of an existing GraphPlot object.  Note that the changes are 
        cumulative.
        
        EXAMPLES::

            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: GP = g.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed')
            sage: GP.set_edges(edge_style='solid')
            sage: GP.plot()
            sage: GP.set_edges(edge_color='black')
            sage: GP.plot()
            
            sage: d = DiGraph({}, loops=True, multiedges=True, sparse=True)
            sage: d.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: GP = d.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed')
            sage: GP.set_edges(edge_style='solid')
            sage: GP.plot()
            sage: GP.set_edges(edge_color='black')
            sage: GP.plot()

        TESTS::
        
            sage: G = Graph("Fooba")
            sage: G.show(edge_colors={'red':[(3,6),(2,5)]})

        Verify that default edge labels are pretty close to being between the vertices
        in some cases where they weren't due to truncating division (trac #10124)::

            sage: test_graphs = graphs.FruchtGraph(), graphs.BullGraph()
            sage: tol = 0.001
            sage: for G in test_graphs:
            ...       E=G.edges()
            ...       for e0, e1, elab in E:
            ...           G.set_edge_label(e0, e1, '%d %d' % (e0, e1))
            ...       gp = G.graphplot(save_pos=True,edge_labels=True)
            ...       vx = gp._plot_components['vertices'][0].xdata
            ...       vy = gp._plot_components['vertices'][0].ydata
            ...       for elab in gp._plot_components['edge_labels']:
            ...           textobj = elab[0]
            ...           x, y, s = textobj.x, textobj.y, textobj.string
            ...           v0, v1 = map(int, s.split())
            ...           vn = vector(((x-(vx[v0]+vx[v1])/2.),y-(vy[v0]+vy[v1])/2.)).norm()
            ...           assert vn < tol


        """
        for arg in edge_options:
            self._options[arg] = edge_options[arg]
        if 'edge_colors' in edge_options:
            self._options['color_by_label'] = False

        # Handle base edge options: thickness, linestyle
        eoptions = {}
        if 'edge_style' in self._options:
            eoptions['linestyle'] = self._options['edge_style']
        if 'thickness' in self._options:
            eoptions['thickness'] = self._options['thickness']

        # Set labels param to add labels on the fly
        labels = False
        if self._options['edge_labels']:
            labels = True
            self._plot_components['edge_labels'] = []

        # Make dict collection of all edges (keep label and edge color)
        edges_to_draw = {}
        if self._options['color_by_label'] or isinstance(
                self._options['edge_colors'], dict):
            if self._options['color_by_label']:
                edge_colors = self._graph._color_by_label()
            else:
                edge_colors = self._options['edge_colors']
            for color in edge_colors:
                for edge in edge_colors[color]:
                    key = tuple(sorted([edge[0], edge[1]]))
                    if key == (edge[0], edge[1]): head = 1
                    else: head = 0

                    if len(edge) < 3:
                        label = self._graph.edge_label(edge[0], edge[1])
                        if isinstance(label, list):
                            if key in edges_to_draw:
                                edges_to_draw[key].append(
                                    (label[-1], color, head))
                            else:
                                edges_to_draw[key] = [(label[-1], color, head)]
                            for i in range(len(label) - 1):
                                edges_to_draw[key].append(
                                    (label[-1], color, head))
                    else:
                        label = edge[2]

                    if key in edges_to_draw:
                        edges_to_draw[key].append((label, color, head))
                    else:
                        edges_to_draw[key] = [(label, color, head)]
            # add unspecified edges in (default color black)
            for edge in self._graph.edge_iterator():
                key = tuple(sorted([edge[0], edge[1]]))
                label = edge[2]
                specified = False
                if key in edges_to_draw:
                    for old_label, old_color, old_head in edges_to_draw[key]:
                        if label == old_label:
                            specified = True
                            break
                if not specified:
                    if key == (edge[0], edge[1]): head = 1
                    else: head = 0
                    edges_to_draw[key] = [(label, 'black', head)]
        else:
            for edge in self._graph.edges(sort=True):
                key = tuple(sorted([edge[0], edge[1]]))
                if key == (edge[0], edge[1]): head = 1
                else: head = 0
                if key in edges_to_draw:
                    edges_to_draw[key].append(
                        (edge[2], self._options['edge_color'], head))
                else:
                    edges_to_draw[key] = [(edge[2],
                                           self._options['edge_color'], head)]

        if edges_to_draw:
            self._plot_components['edges'] = []
        else:
            return

        # Check for multi-edges or loops
        if self._arcs or self._loops:
            tmp = edges_to_draw.copy()
            dist = self._options['dist'] * 2.
            loop_size = self._options['loop_size']
            max_dist = self._options['max_dist']
            from sage.functions.all import sqrt
            for (a, b) in tmp:
                if a == b:
                    # Loops
                    distance = dist
                    local_labels = edges_to_draw.pop((a, b))
                    if len(local_labels) * dist > max_dist:
                        distance = float(max_dist) / len(local_labels)
                    curr_loop_size = loop_size
                    for i in range(len(local_labels)):
                        self._plot_components['edges'].append(
                            circle((self._pos[a][0],
                                    self._pos[a][1] - curr_loop_size),
                                   curr_loop_size,
                                   rgbcolor=local_labels[i][1],
                                   **eoptions))
                        if labels:
                            self._plot_components['edge_labels'].append(
                                text(local_labels[i][0],
                                     (self._pos[a][0],
                                      self._pos[a][1] - 2 * curr_loop_size)))
                        curr_loop_size += distance / 4
                elif len(edges_to_draw[(a, b)]) > 1:
                    # Multi-edge
                    local_labels = edges_to_draw.pop((a, b))

                    # Compute perpendicular bisector
                    p1 = self._pos[a]
                    p2 = self._pos[b]
                    M = (
                        (p1[0] + p2[0]) / 2., (p1[1] + p2[1]) / 2.)  # midpoint
                    if not p1[1] == p2[1]:
                        S = float(p1[0] - p2[0]) / (p2[1] - p1[1]
                                                    )  # perp slope
                        y = lambda x: S * x - S * M[0] + M[
                            1]  # perp bisector line

                        # f,g are functions of distance d to determine x values
                        # on line y at d from point M
                        f = lambda d: sqrt(d**2 / (1. + S**2)) + M[0]
                        g = lambda d: -sqrt(d**2 / (1. + S**2)) + M[0]

                        odd_x = f
                        even_x = g
                        if p1[0] == p2[0]:
                            odd_y = lambda d: M[1]
                            even_y = odd_y
                        else:
                            odd_y = lambda x: y(f(x))
                            even_y = lambda x: y(g(x))
                    else:
                        odd_x = lambda d: M[0]
                        even_x = odd_x
                        odd_y = lambda d: M[1] + d
                        even_y = lambda d: M[1] - d

                    # We now have the control points for each bezier curve
                    # in terms of distance parameter d.
                    # Also note that the label for each edge should be drawn at d/2.
                    # (This is because we're using the perp bisectors).
                    distance = dist
                    if len(local_labels) * dist > max_dist:
                        distance = float(max_dist) / len(local_labels)
                    for i in range(len(local_labels) / 2):
                        k = (i + 1.0) * distance
                        if self._arcdigraph:
                            odd_start = self._polar_hack_for_multidigraph(
                                p1, [odd_x(k), odd_y(k)],
                                self._vertex_radius)[0]
                            odd_end = self._polar_hack_for_multidigraph(
                                [odd_x(k), odd_y(k)], p2,
                                self._vertex_radius)[1]
                            even_start = self._polar_hack_for_multidigraph(
                                p1, [even_x(k), even_y(k)],
                                self._vertex_radius)[0]
                            even_end = self._polar_hack_for_multidigraph(
                                [even_x(k), even_y(k)], p2,
                                self._vertex_radius)[1]
                            self._plot_components['edges'].append(
                                arrow(path=[[
                                    odd_start, [odd_x(k), odd_y(k)], odd_end
                                ]],
                                      head=local_labels[2 * i][2],
                                      zorder=1,
                                      rgbcolor=local_labels[2 * i][1],
                                      **eoptions))
                            self._plot_components['edges'].append(
                                arrow(path=[[
                                    even_start, [even_x(k),
                                                 even_y(k)], even_end
                                ]],
                                      head=local_labels[2 * i + 1][2],
                                      zorder=1,
                                      rgbcolor=local_labels[2 * i + 1][1],
                                      **eoptions))
                        else:
                            self._plot_components['edges'].append(
                                bezier_path(
                                    [[p1, [odd_x(k), odd_y(k)], p2]],
                                    zorder=1,
                                    rgbcolor=local_labels[2 * i][1],
                                    **eoptions))
                            self._plot_components['edges'].append(
                                bezier_path(
                                    [[p1, [even_x(k), even_y(k)], p2]],
                                    zorder=1,
                                    rgbcolor=local_labels[2 * i + 1][1],
                                    **eoptions))
                        if labels:
                            j = k / 2.0
                            self._plot_components['edge_labels'].append(
                                text(local_labels[2 * i][0],
                                     [odd_x(j), odd_y(j)]))
                            self._plot_components['edge_labels'].append(
                                text(local_labels[2 * i + 1][0],
                                     [even_x(j), even_y(j)]))
                    if len(local_labels) % 2 == 1:
                        edges_to_draw[(a, b)] = [local_labels[-1]
                                                 ]  # draw line for last odd

        dir = self._graph.is_directed()
        for (a, b) in edges_to_draw:
            if self._arcdigraph:
                C, D = self._polar_hack_for_multidigraph(
                    self._pos[a], self._pos[b], self._vertex_radius)
                self._plot_components['edges'].append(
                    arrow(C,
                          D,
                          rgbcolor=edges_to_draw[(a, b)][0][1],
                          head=edges_to_draw[(a, b)][0][2],
                          **eoptions))
                if labels:
                    self._plot_components['edge_labels'].append(
                        text(str(edges_to_draw[(a, b)][0][0]),
                             [(C[0] + D[0]) / 2., (C[1] + D[1]) / 2.]))
            elif dir:
                self._plot_components['edges'].append(
                    arrow(self._pos[a],
                          self._pos[b],
                          rgbcolor=edges_to_draw[(a, b)][0][1],
                          arrowshorten=self._arrowshorten,
                          head=edges_to_draw[(a, b)][0][2],
                          **eoptions))
            else:
                self._plot_components['edges'].append(
                    line([self._pos[a], self._pos[b]],
                         rgbcolor=edges_to_draw[(a, b)][0][1],
                         **eoptions))
            if labels and not self._arcdigraph:
                self._plot_components['edge_labels'].append(
                    text(str(edges_to_draw[(a, b)][0][0]),
                         [(self._pos[a][0] + self._pos[b][0]) / 2.,
                          (self._pos[a][1] + self._pos[b][1]) / 2.]))
Beispiel #25
0
    def plot(self, **kwds):
        """
        Returns a graphics object representing the (di)graph.

        INPUT:

        The options accepted by this method are to be found in the documentation
        of the :mod:`sage.graphs.graph_plot` module, and the
        :meth:`~sage.plot.graphics.Graphics.show` method.

        .. NOTE::

            See :mod:`the module's documentation <sage.graphs.graph_plot>` for
            information on default values of this method.

        We can specify some pretty precise plotting of familiar graphs::

            sage: from math import sin, cos, pi
            sage: P = graphs.PetersenGraph()
            sage: d = {'#FF0000':[0,5], '#FF9900':[1,6], '#FFFF00':[2,7], '#00FF00':[3,8], '#0000FF':[4,9]}
            sage: pos_dict = {}
            sage: for i in range(5):
            ...    x = float(cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: for i in range(10)[5:]:
            ...    x = float(0.5*cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(0.5*sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: pl = P.graphplot(pos=pos_dict, vertex_colors=d)
            sage: pl.show()

        Here are some more common graphs with typical options::

            sage: C = graphs.CubeGraph(8)
            sage: P = C.graphplot(vertex_labels=False, vertex_size=0, graph_border=True)
            sage: P.show()

            sage: G = graphs.HeawoodGraph().copy(sparse=True)
            sage: for u,v,l in G.edges():
            ...    G.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: G.graphplot(edge_labels=True).show()

        The options for plotting also work with directed graphs::

            sage: D = DiGraph( { 0: [1, 10, 19], 1: [8, 2], 2: [3, 6], 3: [19, 4], 4: [17, 5], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], 11: [12, 18], 12: [16, 13], 13: [14], 14: [15], 15: [16], 16: [17], 17: [18], 18: [19], 19: []})
            sage: for u,v,l in D.edges():
            ...    D.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: D.graphplot(edge_labels=True, layout='circular').show()

        This example shows off the coloring of edges::

            sage: from sage.plot.colors import rainbow
            sage: C = graphs.CubeGraph(5)
            sage: R = rainbow(5)
            sage: edge_colors = {}
            sage: for i in range(5):
            ...    edge_colors[R[i]] = []
            sage: for u,v,l in C.edges():
            ...    for i in range(5):
            ...        if u[i] != v[i]:
            ...            edge_colors[R[i]].append((u,v,l))
            sage: C.graphplot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show()


        With the ``partition`` option, we can separate out same-color groups
        of vertices::

            sage: D = graphs.DodecahedralGraph()
            sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]]
            sage: D.show(partition=Pi)

        Loops are also plotted correctly::

            sage: G = graphs.PetersenGraph()
            sage: G.allow_loops(True)
            sage: G.add_edge(0,0)
            sage: G.show()

        ::

            sage: D = DiGraph({0:[0,1], 1:[2], 2:[3]}, loops=True)
            sage: D.show()
            sage: D.show(edge_colors={(0,1,0):[(0,1,None),(1,2,None)],(0,0,0):[(2,3,None)]})

        More options::

            sage: pos = {0:[0.0, 1.5], 1:[-0.8, 0.3], 2:[-0.6, -0.8], 3:[0.6, -0.8], 4:[0.8, 0.3]}
            sage: g = Graph({0:[1], 1:[2], 2:[3], 3:[4], 4:[0]})
            sage: g.graphplot(pos=pos, layout='spring', iterations=0).plot()
            Graphics object consisting of 11 graphics primitives

            sage: G = Graph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False
            sage: G = DiGraph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False

        We can plot multiple graphs::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()
            Graphics object consisting of 14 graphics primitives

        ::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()
            Graphics object consisting of 14 graphics primitives
            sage: t.set_edge_label(0,1,-7)
            sage: t.set_edge_label(0,5,3)
            sage: t.set_edge_label(0,5,99)
            sage: t.set_edge_label(1,2,1000)
            sage: t.set_edge_label(3,2,'spam')
            sage: t.set_edge_label(2,6,3/2)
            sage: t.set_edge_label(0,4,66)
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}, edge_labels=True).plot()
            Graphics object consisting of 20 graphics primitives

        ::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(layout='tree').show()

        The tree layout is also useful::

            sage: t = DiGraph('JCC???@A??GO??CO??GO??')
            sage: t.graphplot(layout='tree', tree_root=0, tree_orientation="up").show()

        More examples::

            sage: D = DiGraph({0:[1,2,3], 2:[1,4], 3:[0]})
            sage: D.graphplot().show()

            sage: D = DiGraph(multiedges=True, sparse=True)
            sage: for i in range(5):
            ...     D.add_edge((i,i+1,'a'))
            ...     D.add_edge((i,i-1,'b'))
            sage: D.graphplot(edge_labels=True,edge_colors=D._color_by_label()).plot()
            Graphics object consisting of 34 graphics primitives

            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='dashed').plot()
            Graphics object consisting of 22 graphics primitives

        The ``edge_style`` option may be provided in the short format too::

            sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='--').plot()
            Graphics object consisting of 22 graphics primitives

        TESTS:

        Make sure that show options work with plot also::

            sage: g = Graph({})
            sage: g.plot(title='empty graph', axes=True)
            Graphics object consisting of 0 graphics primitives

        Check for invalid inputs::

            sage: p = graphs.PetersenGraph().plot(egabrag='garbage')
            Traceback (most recent call last):
            ...
            ValueError: Invalid input 'egabrag=garbage'

        Make sure that no graphics primitive is clipped::

            sage: tadpole = Graph({0:[0,1]}).plot()
            sage: bbox = tadpole.get_minmax_data()
            sage: for part in tadpole:
            ....:      part_bbox = part.get_minmax_data()
            ....:      assert bbox['xmin'] <= part_bbox['xmin'] <= part_bbox['xmax'] <= bbox['xmax']
            ....:      assert bbox['ymin'] <= part_bbox['ymin'] <= part_bbox['ymax'] <= bbox['ymax']
        """
        G = Graphics()
        options = self._options.copy()
        options.update(kwds)
        G._set_extra_kwds(Graphics._extract_kwds_for_show(options))

        # Check the arguments
        for o in options:
            if o not in graphplot_options and o not in G._extra_kwds:
                raise ValueError("Invalid input '{}={}'".format(o, options[o]))

        for comp in self._plot_components.values():
            if not isinstance(comp, list):
                G += comp
            else:
                for item in comp:
                    G += item

        if self._options['graph_border']:
            xmin = G.xmin()
            xmax = G.xmax()
            ymin = G.ymin()
            ymax = G.ymax()
            dx = (xmax-xmin)/10.0
            dy = (ymax-ymin)/10.0
            border = (line([( xmin - dx, ymin - dy), ( xmin - dx, ymax + dy ), ( xmax + dx, ymax + dy ), ( xmax + dx, ymin - dy ), ( xmin - dx, ymin - dy )], thickness=1.3))
            border.axes_range(xmin = (xmin - dx), xmax = (xmax + dx), ymin = (ymin - dy), ymax = (ymax + dy))
            G += border
        G.set_aspect_ratio(1)
        G.axes(False)
        return G
Beispiel #26
0
    def plot(self, **kwds):
        """
        Returns a graphics object representing the (di)graph.
        
        INPUT:
            - pos -- an optional positioning dictionary
            - layout -- what kind of layout to use, takes precedence over pos

              - 'circular' -- plots the graph with vertices evenly distributed
                on a circle
              - 'spring' -- uses the traditional spring layout, using the
                graph's current positions as initial positions
              - 'tree' -- the (di)graph must be a tree. One can specify the root
                of the tree using the keyword tree_root, otherwise a root
                will be selected at random. Then the tree will be plotted in
                levels, depending on minimum distance for the root.
            - vertex_labels -- whether to print vertex labels
              edge_labels -- whether to print edge labels. By default, False,
              but if True, the result of str(l) is printed on the edge for
              each label l. Labels equal to None are not printed (to set edge
              labels, see set_edge_label).
            - vertex_size -- size of vertices displayed
            - vertex_shape -- the shape to draw the vertices (Not available for
              multiedge digraphs.
            - graph_border -- whether to include a box around the graph
            - vertex_colors -- optional dictionary to specify vertex colors: each
              key is a color recognizable by matplotlib, and each corresponding
              entry is a list of vertices. If a vertex is not listed, it looks
              invisible on the resulting plot (it doesn't get drawn).
            - edge_colors -- a dictionary specifying edge colors: each key is a
              color recognized by matplotlib, and each entry is a list of edges.
            - partition -- a partition of the vertex set. if specified, plot will
              show each cell in a different color. vertex_colors takes precedence.
            - talk -- if true, prints large vertices with white backgrounds so that
              labels are legible on slides
            - iterations -- how many iterations of the spring layout algorithm to
              go through, if applicable
            - color_by_label -- if True, color edges by their labels
            - heights -- if specified, this is a dictionary from a set of
              floating point heights to a set of vertices
            - edge_style -- keyword arguments passed into the
              edge-drawing routine.  This currently only works for
              directed graphs, since we pass off the undirected graph to
              networkx
            - tree_root -- a vertex of the tree to be used as the root for
              the layout="tree" option. If no root is specified, then one
              is chosen at random. Ignored unless layout='tree'. 
            - tree_orientation -- "up" or "down" (default is "down"). 
              If "up" (resp., "down"), then the root of the tree will
              appear on the bottom (resp., top) and the tree will grow
              upwards (resp. downwards). Ignored unless layout='tree'.
            - save_pos -- save position computed during plotting

        EXAMPLES::

            sage: from sage.graphs.graph_plot import graphplot_options
            sage: list(sorted(graphplot_options.iteritems()))
            [('by_component', 'Whether to do the spring layout by connected component -- a boolean.'),
             ('color_by_label', 'Whether or not to color the edges by their label values.'),
             ('dim', 'The dimension of the layout -- 2 or 3.'),
             ('dist', 'The distance between multiedges.'),
             ('edge_color', 'The default color for edges.'),
             ('edge_colors', 'Dictionary of edge coloring.'),
             ('edge_labels', 'Whether or not to draw edge labels.'),
             ('edge_style', 'The linestyle of the edges-- one of "solid", "dashed", "dotted", dashdot".'),
             ('graph_border', 'Whether or not to draw a frame around the graph.'),
             ('heights', 'A dictionary mapping heights to the list of vertices at this height.'),
             ('iterations', 'The number of times to execute the spring layout algorithm.'),
             ('layout', 'A layout algorithm -- one of "acyclic", "circular", "ranked", "graphviz", "planar", "spring", or "tree".'),
             ('loop_size', 'The radius of the smallest loop.'),
             ('max_dist', 'The max distance range to allow multiedges.'),
             ('partition', 'A partition of the vertex set.  (Draws each cell of vertices in a different color).'),
             ('pos', 'The position dictionary of vertices'),
             ('prog', 'Which graphviz layout program to use -- one of "circo", "dot", "fdp", "neato", or "twopi".'),
             ('save_pos', 'Whether or not to save the computed position for the graph.'),
             ('spring', 'Use spring layout to finalize the current layout.'),
             ('talk', 'Whether to display the vertices in talk mode (larger and white)'),
             ('tree_orientation', 'The direction of tree branches -- "up" or "down".'),
             ('tree_root', 'A vertex designation for drawing trees.'),
             ('vertex_colors', 'Dictionary of vertex coloring.'),
             ('vertex_labels', 'Whether or not to draw vertex labels.'),
             ('vertex_shape', 'The shape to draw the vertices, Currently unavailable for Multi-edged DiGraphs.'),
             ('vertex_size', 'The size to draw the vertices.')]

            sage: from math import sin, cos, pi
            sage: P = graphs.PetersenGraph()
            sage: d = {'#FF0000':[0,5], '#FF9900':[1,6], '#FFFF00':[2,7], '#00FF00':[3,8], '#0000FF':[4,9]}
            sage: pos_dict = {}
            sage: for i in range(5):
            ...    x = float(cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: for i in range(10)[5:]:
            ...    x = float(0.5*cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(0.5*sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: pl = P.graphplot(pos=pos_dict, vertex_colors=d)
            sage: pl.show()
            
            sage: C = graphs.CubeGraph(8)
            sage: P = C.graphplot(vertex_labels=False, vertex_size=0, graph_border=True)
            sage: P.show()
            
            sage: G = graphs.HeawoodGraph().copy(sparse=True)
            sage: for u,v,l in G.edges():
            ...    G.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: G.graphplot(edge_labels=True).show()
            
            sage: D = DiGraph( { 0: [1, 10, 19], 1: [8, 2], 2: [3, 6], 3: [19, 4], 4: [17, 5], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], 11: [12, 18], 12: [16, 13], 13: [14], 14: [15], 15: [16], 16: [17], 17: [18], 18: [19], 19: []}, implementation='networkx' )
            sage: for u,v,l in D.edges():
            ...    D.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: D.graphplot(edge_labels=True, layout='circular').show()

            sage: from sage.plot.colors import rainbow
            sage: C = graphs.CubeGraph(5)
            sage: R = rainbow(5)
            sage: edge_colors = {}
            sage: for i in range(5):
            ...    edge_colors[R[i]] = []
            sage: for u,v,l in C.edges():
            ...    for i in range(5):
            ...        if u[i] != v[i]:
            ...            edge_colors[R[i]].append((u,v,l))
            sage: C.graphplot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show()

            sage: D = graphs.DodecahedralGraph()
            sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]]
            sage: D.show(partition=Pi)

            sage: G = graphs.PetersenGraph()
            sage: G.allow_loops(True)
            sage: G.add_edge(0,0)
            sage: G.show()

            sage: D = DiGraph({0:[0,1], 1:[2], 2:[3]}, loops=True)
            sage: D.show()
            sage: D.show(edge_colors={(0,1,0):[(0,1,None),(1,2,None)],(0,0,0):[(2,3,None)]}) 

            sage: pos = {0:[0.0, 1.5], 1:[-0.8, 0.3], 2:[-0.6, -0.8], 3:[0.6, -0.8], 4:[0.8, 0.3]}
            sage: g = Graph({0:[1], 1:[2], 2:[3], 3:[4], 4:[0]})
            sage: g.graphplot(pos=pos, layout='spring', iterations=0).plot()

            sage: G = Graph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False
            sage: G = DiGraph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()
            sage: t.set_edge_label(0,1,-7)
            sage: t.set_edge_label(0,5,3)
            sage: t.set_edge_label(0,5,99)
            sage: t.set_edge_label(1,2,1000)
            sage: t.set_edge_label(3,2,'spam')
            sage: t.set_edge_label(2,6,3/2)
            sage: t.set_edge_label(0,4,66)
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}, edge_labels=True).plot()

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(layout='tree').show()

            sage: t = DiGraph('JCC???@A??GO??CO??GO??')
            sage: t.graphplot(layout='tree', tree_root=0, tree_orientation="up").show()

            sage: D = DiGraph({0:[1,2,3], 2:[1,4], 3:[0]})
            sage: D.graphplot().show()
            
            sage: D = DiGraph(multiedges=True, sparse=True)
            sage: for i in range(5):
            ...     D.add_edge((i,i+1,'a'))
            ...     D.add_edge((i,i-1,'b'))
            sage: D.graphplot(edge_labels=True,edge_colors=D._color_by_label()).plot()
            
            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='dashed').plot()
        """
        G = Graphics()
        for comp in self._plot_components.values():
            if not isinstance(comp, list):
                G += comp
            else:
                for item in comp:
                    G += item
        G.set_axes_range(*(self._graph._layout_bounding_box(self._pos)))
        if self._options['graph_border']:
            xmin = G.xmin()
            xmax = G.xmax()
            ymin = G.ymin()
            ymax = G.ymax()
            dx = (xmax - xmin) / 10.0
            dy = (ymax - ymin) / 10.0
            border = (line([(xmin - dx, ymin - dy), (xmin - dx, ymax + dy),
                            (xmax + dx, ymax + dy), (xmax + dx, ymin - dy),
                            (xmin - dx, ymin - dy)],
                           thickness=1.3))
            border.axes_range(xmin=(xmin - dx),
                              xmax=(xmax + dx),
                              ymin=(ymin - dy),
                              ymax=(ymax + dy))
            G += border
        G.set_aspect_ratio(1)
        G.axes(False)
        G._extra_kwds['axes_pad'] = .05
        return G
Beispiel #27
0
    def plot(self, **kwds):
        """
        Returns a graphics object representing the (di)graph.

        INPUT:

        The options accepted by this method are to be found in the documentation
        of module :mod:`sage.graphs.graph_plot`.

        .. NOTE::

            See :mod:`the module's documentation <sage.graphs.graph_plot>` for
            information on default values of this method.

        We can specify some pretty precise plotting of familiar graphs::

            sage: from math import sin, cos, pi
            sage: P = graphs.PetersenGraph()
            sage: d = {'#FF0000':[0,5], '#FF9900':[1,6], '#FFFF00':[2,7], '#00FF00':[3,8], '#0000FF':[4,9]}
            sage: pos_dict = {}
            sage: for i in range(5):
            ...    x = float(cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: for i in range(10)[5:]:
            ...    x = float(0.5*cos(pi/2 + ((2*pi)/5)*i))
            ...    y = float(0.5*sin(pi/2 + ((2*pi)/5)*i))
            ...    pos_dict[i] = [x,y]
            ...
            sage: pl = P.graphplot(pos=pos_dict, vertex_colors=d)
            sage: pl.show()

        Here are some more common graphs with typical options::

            sage: C = graphs.CubeGraph(8)
            sage: P = C.graphplot(vertex_labels=False, vertex_size=0, graph_border=True)
            sage: P.show()

            sage: G = graphs.HeawoodGraph().copy(sparse=True)
            sage: for u,v,l in G.edges():
            ...    G.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: G.graphplot(edge_labels=True).show()

        The options for plotting also work with directed graphs::

            sage: D = DiGraph( { 0: [1, 10, 19], 1: [8, 2], 2: [3, 6], 3: [19, 4], 4: [17, 5], 5: [6, 15], 6: [7], 7: [8, 14], 8: [9], 9: [10, 13], 10: [11], 11: [12, 18], 12: [16, 13], 13: [14], 14: [15], 15: [16], 16: [17], 17: [18], 18: [19], 19: []}, implementation='networkx' )
            sage: for u,v,l in D.edges():
            ...    D.set_edge_label(u,v,'(' + str(u) + ',' + str(v) + ')')
            sage: D.graphplot(edge_labels=True, layout='circular').show()

        This example shows off the coloring of edges::

            sage: from sage.plot.colors import rainbow
            sage: C = graphs.CubeGraph(5)
            sage: R = rainbow(5)
            sage: edge_colors = {}
            sage: for i in range(5):
            ...    edge_colors[R[i]] = []
            sage: for u,v,l in C.edges():
            ...    for i in range(5):
            ...        if u[i] != v[i]:
            ...            edge_colors[R[i]].append((u,v,l))
            sage: C.graphplot(vertex_labels=False, vertex_size=0, edge_colors=edge_colors).show()

        With the ``partition`` option, we can separate out same-color groups
        of vertices::

            sage: D = graphs.DodecahedralGraph()
            sage: Pi = [[6,5,15,14,7],[16,13,8,2,4],[12,17,9,3,1],[0,19,18,10,11]]
            sage: D.show(partition=Pi)

        Loops are also plotted correctly::

            sage: G = graphs.PetersenGraph()
            sage: G.allow_loops(True)
            sage: G.add_edge(0,0)
            sage: G.show()

        ::

            sage: D = DiGraph({0:[0,1], 1:[2], 2:[3]}, loops=True)
            sage: D.show()
            sage: D.show(edge_colors={(0,1,0):[(0,1,None),(1,2,None)],(0,0,0):[(2,3,None)]})

        More options::

            sage: pos = {0:[0.0, 1.5], 1:[-0.8, 0.3], 2:[-0.6, -0.8], 3:[0.6, -0.8], 4:[0.8, 0.3]}
            sage: g = Graph({0:[1], 1:[2], 2:[3], 3:[4], 4:[0]})
            sage: g.graphplot(pos=pos, layout='spring', iterations=0).plot()

            sage: G = Graph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False
            sage: G = DiGraph()
            sage: P = G.graphplot().plot()
            sage: P.axes()
            False

        We can plot multiple graphs::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()

        ::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}).plot()
            sage: t.set_edge_label(0,1,-7)
            sage: t.set_edge_label(0,5,3)
            sage: t.set_edge_label(0,5,99)
            sage: t.set_edge_label(1,2,1000)
            sage: t.set_edge_label(3,2,'spam')
            sage: t.set_edge_label(2,6,3/2)
            sage: t.set_edge_label(0,4,66)
            sage: t.graphplot(heights={0:[0], 1:[4,5,1], 2:[2], 3:[3,6]}, edge_labels=True).plot()

        ::

            sage: T = list(graphs.trees(7))
            sage: t = T[3]
            sage: t.graphplot(layout='tree').show()

        The tree layout is also useful::

            sage: t = DiGraph('JCC???@A??GO??CO??GO??')
            sage: t.graphplot(layout='tree', tree_root=0, tree_orientation="up").show()

        More examples::

            sage: D = DiGraph({0:[1,2,3], 2:[1,4], 3:[0]})
            sage: D.graphplot().show()

            sage: D = DiGraph(multiedges=True, sparse=True)
            sage: for i in range(5):
            ...     D.add_edge((i,i+1,'a'))
            ...     D.add_edge((i,i-1,'b'))
            sage: D.graphplot(edge_labels=True,edge_colors=D._color_by_label()).plot()

            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: g.graphplot(edge_labels=True, color_by_label=True, edge_style='dashed').plot()

        Wrong input (any input) :trac:`13891`::

            sage: graphs.PetersenGraph().graphplot().plot(aertataert=346345345)
            doctest:...: DeprecationWarning: This method takes no argument ! You may want to give it as an argument to graphplot instead.
            See http://trac.sagemath.org/13891 for details.
            <BLANKLINE>
        """
        # This method takes NO input
        # This has been added in early 2013. Remove it before my death, please.
        if kwds:
            from sage.misc.superseded import deprecation
            deprecation(
                13891, "This method takes no argument ! You may want "
                "to give it as an argument to graphplot instead.")

        G = Graphics()
        for comp in self._plot_components.values():
            if not isinstance(comp, list):
                G += comp
            else:
                for item in comp:
                    G += item

        G.set_axes_range(*(self._graph._layout_bounding_box(self._pos)))
        if self._options['graph_border']:
            xmin = G.xmin()
            xmax = G.xmax()
            ymin = G.ymin()
            ymax = G.ymax()
            dx = (xmax - xmin) / 10.0
            dy = (ymax - ymin) / 10.0
            border = (line([(xmin - dx, ymin - dy), (xmin - dx, ymax + dy),
                            (xmax + dx, ymax + dy), (xmax + dx, ymin - dy),
                            (xmin - dx, ymin - dy)],
                           thickness=1.3))
            border.axes_range(xmin=(xmin - dx),
                              xmax=(xmax + dx),
                              ymin=(ymin - dy),
                              ymax=(ymax + dy))
            G += border
        G.set_aspect_ratio(1)
        G.axes(False)
        G._extra_kwds['axes_pad'] = .05
        return G