Ticket #7358: trac_7358.patch

File trac_7358.patch, 4.0 KB (added by ncohen, 11 years ago)
  • sage/graphs/graph.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1257105416 -3600
    # Node ID 9a73e8e07a855462e77c51830a0b35cfe96d2f0a
    # Parent  964c2f4ce74db0417a771de0b0cfc951b1fab73c
    strong orientation in the Graph class
    
    diff -r 964c2f4ce74d -r 9a73e8e07a85 sage/graphs/graph.py
    a b  
    1035810358        except:
    1035910359            return False
    1036010360
     10361    ### Orientations
     10362
     10363    def strong_orientation(self):
     10364        r"""
     10365        Returns a strongly connected orientation of the current graph.
     10366        ( cf. http://en.wikipedia.org/wiki/Strongly_connected_component )
     10367
     10368        An orientation of a an undirected graph is a digraph obtained by
     10369        giving an unique direction to each of its edges. An orientation
     10370        is said to be strong if there is a directed path between each
     10371        pair of vertices.
     10372
     10373        If the graph is 2-edge-connected, a strongly connected orientation
     10374        can be found in linear time. If the given graph is not 2-connected,
     10375        the orientation returned will ensure that each 2-connected component
     10376        has a strongly connected orientation.
     10377
     10378        OUTPUT:
     10379
     10380        A digraph representing an orientation of the current graph.
     10381
     10382        NOTES:
     10383       
     10384        - This method assumes the graph is connected.
     10385        - This algorithm works in O(m).
     10386
     10387        EXAMPLE:
     10388
     10389        For a 2-regular graph, a strong orientation gives to each vertex
     10390        an out-degree equal to 1::
     10391
     10392            sage: g = graphs.CycleGraph(5)
     10393            sage: g.strong_orientation().out_degree()
     10394            [1, 1, 1, 1, 1]
     10395
     10396        The Petersen Graph is 2-edge connected. It then has a strongly
     10397        connected orientation::
     10398
     10399            sage: g = graphs.PetersenGraph()
     10400            sage: o = g.strong_orientation()
     10401            sage: len(o.strongly_connected_components())
     10402            1
     10403
     10404        The same goes for the CubeGraph in any dimension ::
     10405
     10406            sage: for i in range(2,5):
     10407            ...     g = graphs.CubeGraph(i)
     10408            ...     o = g.strong_orientation()
     10409            ...     len(o.strongly_connected_components())
     10410            1
     10411            1
     10412            1
     10413         
     10414        """
     10415
     10416        d = DiGraph(multiedges=self.allows_multiple_edges())
     10417
     10418        id = {}
     10419        i = 0
     10420       
     10421        # The algorithm works through a depth-first search. Any edge
     10422        # used in the depth-first search is oriented in the direction
     10423        # in which it has been used. All the other edges are oriented
     10424        # backward
     10425       
     10426        v = self.vertex_iterator().next()
     10427        seen = {}
     10428        i=1
     10429
     10430        # Time at which the vertices have been discovered
     10431        seen[v] = i
     10432
     10433        # indicates the stack of edges to explore
     10434        next = self.edges_incident(v)
     10435
     10436        while next:
     10437            e = next.pop(-1)
     10438            # We assume e[0] to be a `seen` vertex
     10439            e = e if seen.get(e[0],False) != False else (e[1],e[0],e[2])
     10440
     10441            # If we discovered a new vertex
     10442            if seen.get(e[1],False) == False:
     10443                d.add_edge(e)
     10444                next.extend([ee for ee in self.edges_incident(e[1]) if (((e[0],e[1]) != (ee[0],ee[1])) and ((e[0],e[1]) != (ee[1],ee[0])))])
     10445                i+=1
     10446                seen[e[1]]=i
     10447
     10448            # Else, we orient the edges backward
     10449            else:
     10450                if seen[e[0]] < seen[e[1]]:
     10451                    d.add_edge((e[1],e[0],e[2]))
     10452                else:
     10453                    d.add_edge(e)
     10454
     10455        # Case of multiple edges. If another edge has already been inserted, we add the new one
     10456        # in the opposite direction.
     10457        tmp = None
     10458        for e in self.multiple_edges():
     10459            if tmp == (e[0],e[1]):
     10460                if d.has_edge(e[0].e[1]):
     10461                    d.add_edge(e[1],e[0],e[2])
     10462                else:
     10463                    d.add_edge(e)
     10464            tmp = (e[0],e[1])
     10465           
     10466        return d
     10467
    1036110468    ### Coloring
    1036210469
    1036310470    def bipartite_color(self):