Ticket #7533: trac_7533_distance_graphs_2.patch

File trac_7533_distance_graphs_2.patch, 6.7 KB (added by Rob Beezer, 13 years ago)
  • sage/graphs/graph.py

    # HG changeset patch
    # User Rob Beezer <beezer@ups.edu>
    # Date 1259311949 28800
    # Node ID 40c537df338ef79d857ab54ad4a62db5f1c6222b
    # Parent  44f70d431d43e3dfaa1487641ee6864d5025fb06
    [mq]: distancegraph
    
    diff -r 44f70d431d43 -r 40c537df338e sage/graphs/graph.py
    a b  
    55115511            return 0
    55125512        return max(e)
    55135513
     5514    def distance_graph(self, dist):
     5515        r"""
     5516        Returns the graph on the same vertex set as
     5517        the original graph but vertices are adjacent
     5518        in the returned graph if and only if they are
     5519        at specified distances in the original graph.
     5520
     5521        INPUT:
     5522
     5523        - ``dist`` is a nonnegative integer or
     5524          a list of nonnegative integers.
     5525          ``Infinity`` may be used here to describe
     5526          vertex pairs in separate components.
     5527
     5528        OUTPUT:
     5529
     5530        The returned value is an undirected graph.  The
     5531        vertex set is identical to the calling graph, but edges
     5532        of the returned graph join vertices whose distance in
     5533        the calling graph are present in the input ``dist``.
     5534        Loops will only be present if distance 0 is included.  If
     5535        the original graph has a position dictionary specifying
     5536        locations of vertices for plotting, then this information
     5537        is copied over to the distance graph.  In some instances
     5538        this layout may not be the best, and might even be confusing
     5539        when edges run on top of each other due to symmetries
     5540        chosen for the layout.
     5541
     5542        EXAMPLES::
     5543
     5544            sage: G = graphs.CompleteGraph(3)
     5545            sage: H = G.cartesian_product(graphs.CompleteGraph(2))
     5546            sage: K = H.distance_graph(2)
     5547            sage: K.am()
     5548            [0 0 0 1 0 1]
     5549            [0 0 1 0 1 0]
     5550            [0 1 0 0 0 1]
     5551            [1 0 0 0 1 0]
     5552            [0 1 0 1 0 0]
     5553            [1 0 1 0 0 0]
     5554
     5555        To obtain the graph where vertices are adjacent if their
     5556        distance apart is ``d`` or less use a ``range()`` command
     5557        to create the input, using ``d+1`` as the input to ``range``.
     5558        Notice that this will include distance 0 and hence place a loop
     5559        at each vertex.  To avoid this, use ``range(1,d+1)``. ::
     5560
     5561            sage: G = graphs.OddGraph(4)
     5562            sage: d = G.diameter()
     5563            sage: n = G.num_verts()
     5564            sage: H = G.distance_graph(range(d+1))
     5565            sage: H.is_isomorphic(graphs.CompleteGraph(n))
     5566            False
     5567            sage: H = G.distance_graph(range(1,d+1))
     5568            sage: H.is_isomorphic(graphs.CompleteGraph(n))
     5569            True
     5570
     5571        A complete collection of distance graphs will have
     5572        adjacency matrices that sum to the matrix of all ones. ::
     5573
     5574            sage: P = graphs.PathGraph(20)
     5575            sage: all_ones = sum([P.distance_graph(i).am() for i in range(20)])
     5576            sage: all_ones == matrix(ZZ, 20, 20, [1]*400)
     5577            True
     5578
     5579        Four-bit strings differing in one bit is the same as
     5580        four-bit strings differing in three bits.  ::
     5581
     5582            sage: G = graphs.CubeGraph(4)
     5583            sage: H = G.distance_graph(3)
     5584            sage: G.is_isomorphic(H)
     5585            True
     5586
     5587        The graph of eight-bit strings, adjacent if different
     5588        in an odd number of bits.  ::
     5589
     5590            sage: G = graphs.CubeGraph(8)
     5591            sage: H = G.distance_graph([1,3,5,7])
     5592            sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]])
     5593            sage: degrees.append(2^8)
     5594            sage: degrees == H.degree_histogram()
     5595            True
     5596
     5597        An example of using ``Infinity`` as the distance in
     5598        a graph that is not connected. ::
     5599
     5600            sage: G = graphs.CompleteGraph(3)
     5601            sage: H = G.disjoint_union(graphs.CompleteGraph(2))
     5602            sage: L = H.distance_graph(Infinity)
     5603            sage: L.am()
     5604            [0 0 0 1 1]
     5605            [0 0 0 1 1]
     5606            [0 0 0 1 1]
     5607            [1 1 1 0 0]
     5608            [1 1 1 0 0]
     5609
     5610        TESTS:
     5611
     5612        Empty input, or unachievable distances silently yield empty graphs. ::
     5613
     5614            sage: G = graphs.CompleteGraph(5)
     5615            sage: G.distance_graph([]).num_edges()
     5616            0
     5617            sage: G = graphs.CompleteGraph(5)
     5618            sage: G.distance_graph(23).num_edges()
     5619            0
     5620
     5621        It is an error to provide a distance that is not an integer type. ::
     5622
     5623            sage: G = graphs.CompleteGraph(5)
     5624            sage: G.distance_graph('junk')
     5625            Traceback (most recent call last):
     5626            ...
     5627            TypeError: unable to convert x (=junk) to an integer
     5628
     5629        It is an error to provide a negative distance. ::
     5630
     5631            sage: G = graphs.CompleteGraph(5)
     5632            sage: G.distance_graph(-3)
     5633            Traceback (most recent call last):
     5634            ...
     5635            ValueError: Distance graph for a negative distance (d=-3) is not defined
     5636
     5637        AUTHOR:
     5638
     5639        Rob Beezer, 2009-11-25
     5640        """
     5641        from sage.rings.infinity import Infinity
     5642        from copy import copy
     5643        # If input is not a list, make a list with this single object
     5644        if not isinstance(dist, list):
     5645            dist = [dist]
     5646        # Create a list of positive integer (or infinite) distances
     5647        distances = []
     5648        for d in dist:
     5649            if d == Infinity:
     5650                distances.append(d)
     5651            else:
     5652                dint = Integer(d)
     5653                if dint < 0:
     5654                    raise ValueError('Distance graph for a negative distance (d=%d) is not defined' % dint)
     5655                distances.append(dint)
     5656        # Build a graph on the same vertex set, with loops for distance 0
     5657        vertices = {}
     5658        for v in self.vertex_iterator():
     5659            vertices[v] = {}
     5660        positions = copy(self.get_pos())
     5661        if Integer(0) in distances:
     5662            looped = True
     5663        else:
     5664            looped = False
     5665        D = Graph(vertices, pos=positions, multiedges=False, loops=looped)
     5666        if len(distances) == 1:
     5667            dstring = "distance " + str(distances[0])
     5668        else:
     5669            dstring = "distances " + str(sorted(distances))
     5670        D.name("Distance graph for %s in " % dstring + self.name())
     5671        # Create the appropriate edges
     5672        # Using shortest_path_all_pairs() here is much slower, see Trac 7533
     5673        for u in self.vertex_iterator():
     5674            for v in self.vertex_iterator():
     5675                if self.distance(u,v) in distances:
     5676                    D.add_edge(u,v)
     5677        return D
     5678
    55145679    def girth(self):
    55155680        """
    55165681        Computes the girth of the graph. For directed graphs, computes the