Ticket #13787: trac_13787.patch

File trac_13787.patch, 5.7 KB (added by ncohen, 8 years ago)
  • sage/graphs/generic_graph.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1354446887 -3600
    # Node ID da8fa0c9ccce5243ef949479e81358dbdd192c60
    # Parent  ffa112def1286bbce6d47eb6fb0b8a8d7f20c3e7
    Bug in GenericGraph.line_graph() when the vertices cannot be compared
    
    diff --git a/sage/graphs/generic_graph.py b/sage/graphs/generic_graph.py
    a b  
    1290112901                if not self.has_edge(u,v):
    1290212902                    G.add_edge(u,v)
    1290312903        return G
    12904    
     12904
    1290512905    def line_graph(self, labels=True):
    1290612906        """
    1290712907        Returns the line graph of the (di)graph.
    12908        
     12908
     12909        INPUT:
     12910
     12911        - ``labels`` (boolean) -- whether edge labels should be taken in
     12912          consideration. If ``labels=True``, the vertices of the line graph will
     12913          be triples ``(u,v,label)``, and pairs of vertices otherwise.
     12914
     12915          This is set to ``True`` by default.
     12916
    1290912917        The line graph of an undirected graph G is an undirected graph H
    1291012918        such that the vertices of H are the edges of G and two vertices e
    1291112919        and f of H are adjacent if e and f share a common vertex in G. In
    1291212920        other words, an edge in H represents a path of length 2 in G.
    12913        
     12921
    1291412922        The line graph of a directed graph G is a directed graph H such
    1291512923        that the vertices of H are the edges of G and two vertices e and f
    1291612924        of H are adjacent if e and f share a common vertex in G and the
    1291712925        terminal vertex of e is the initial vertex of f. In other words, an
    1291812926        edge in H represents a (directed) path of length 2 in G.
    12919        
    12920         EXAMPLES::
    12921        
     12927
     12928        .. NOTE::
     12929
     12930            As a :class:`Graph` object only accepts hashable objects as vertices
     12931            (and as the vertices of the line graph are the edges of the graph),
     12932            this code will fail if edge labels are not hashable. You can also
     12933            set the argument ``labels=False`` to ignore labels.
     12934
     12935        EXAMPLES::
     12936
    1292212937            sage: g=graphs.CompleteGraph(4)
    1292312938            sage: h=g.line_graph()
    1292412939            sage: h.vertices()
     
    1295412969             ((1, 2, None), (2, 4, None), None),
    1295512970             ((1, 3, None), (3, 4, None), None),
    1295612971             ((2, 3, None), (3, 4, None), None)]
     12972
     12973        Tests:
     12974
     12975        :trac:`13787`::
     12976
     12977            sage: g=graphs.KneserGraph(7,1)
     12978            sage: C = graphs.CompleteGraph(7)
     12979            sage: C.is_isomorphic(g)
     12980            True
     12981            sage: C.line_graph().is_isomorphic(g.line_graph())
     12982            True
    1295712983        """
    1295812984        if self._directed:
    1295912985            from sage.graphs.digraph import DiGraph
     
    1296712993        else:
    1296812994            from sage.graphs.all import Graph
    1296912995            G=Graph()
    12970             # We must sort the edges' endpoints so that (1,2,None) is
    12971             # seen as the same edge as (2,1,None).
    12972             if labels:
    12973                 elist=[(min(i[0:2]),max(i[0:2]),i[2] if i[2] != {} else None)
    12974                        for i in self.edge_iterator()]
    12975             else:
    12976                 elist=[(min(i),max(i))
    12977                        for i in self.edge_iterator(labels=False)]
     12996
     12997            # We must sort the edges' endpoints so that (1,2,None) is seen as
     12998            # the same edge as (2,1,None).
     12999            #
     13000            # We do so by comparing hashes, just in case all the natural order
     13001            # (<) on vertices would not be a total order (for instance when
     13002            # vertices are sets). If two adjacent vertices have the same hash,
     13003            # then we store the pair in the dictionary of conflicts
     13004
     13005            conflicts = {}
     13006
     13007            # 1) List of vertices in the line graph
     13008            elist = []
     13009            for e in self.edge_iterator(labels = labels):
     13010                if hash(e[0]) < hash(e[1]):
     13011                    elist.append(e)
     13012                elif hash(e[0]) > hash(e[1]):
     13013                    elist.append((e[1],e[0])+e[2:])
     13014                else:
     13015                    # Settle the conflict arbitrarily
     13016                    conflicts[e] = e
     13017                    conflicts[(e[1],e[0])+e[2:]] = e
     13018                    elist.append(e)
     13019
    1297813020            G.add_vertices(elist)
     13021
     13022            # 2) adjacencies in the line graph
    1297913023            for v in self:
    12980                 if labels:
    12981                     elist=[(min(i[0:2]),max(i[0:2]),i[2] if i[2] != {} else None)
    12982                            for i in self.edge_iterator(v)]
    12983                 else:
    12984                     elist=[(min(i),max(i))
    12985                            for i in self.edge_iterator(v, labels=False)]
    12986                 G.add_edges([(e, f) for e in elist for f in elist])
     13024                elist = []
     13025
     13026                # Add the edge to the list, according to hashes, as previously
     13027                for e in self.edge_iterator(v, labels=labels):
     13028                    if hash(e[0]) < hash(e[1]):
     13029                        elist.append(e)
     13030                    elif hash(e[0]) > hash(e[1]):
     13031                        elist.append((e[1],e[0])+e[2:])
     13032                    else:
     13033                        elist.append(conflicts[e])
     13034
     13035                # Alls pairs of elements in elist are pairs of the
     13036                # graph
     13037                while elist:
     13038                    x = elist.pop()
     13039                    for y in elist:
     13040                        G.add_edge(x,y)
     13041
    1298713042            return G
    1298813043
    1298913044    def to_simple(self):
    1299013045        """
    1299113046        Returns a simple version of itself (i.e., undirected and loops and
    1299213047        multiple edges are removed).
    12993        
    12994         EXAMPLES::
    12995        
     13048
     13049        EXAMPLES::
     13050
    1299613051            sage: G = DiGraph(loops=True,multiedges=True,sparse=True)
    1299713052            sage: G.add_edges( [ (0,0), (1,1), (2,2), (2,3,1), (2,3,2), (3,2) ] )
    1299813053            sage: G.edges(labels=False)