Ticket #7541: trac_7541.patch

File trac_7541.patch, 6.4 KB (added by rlm, 11 years ago)

changed successor to neighbor_out

  • sage/graphs/graph.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1259499757 -3600
    # Node ID 37589a52b8d9b0370dfb546dee153f6062cde6d4
    # Parent  89c9f97b55c319ea421adfb46aaad7202e027037
    Functions is_chordal and Lex BFS
    
    diff -r 89c9f97b55c3 -r 37589a52b8d9 sage/graphs/graph.py
    a b  
    52545254                vertices.append(v)
    52555255        return self.subgraph(vertices=vertices, inplace=inplace)
    52565256
     5257    def is_chordal(self):
     5258        r"""
     5259        Tests whether the given graph is chordal.
     5260   
     5261        A Graph `G` is said to be chordal if it contains no induced
     5262        hole. Being chordal is equivalent to having an elimination
     5263        order on the vertices such that the neighborhood of each
     5264        vertex, before being removed from the graph, is a complete
     5265        graph [Fulkerson65]_.
     5266
     5267        Such an ordering is called a Perfect Elimination Order.
     5268   
     5269        ALGORITHM:
     5270   
     5271        This algorithm works through computing a Lex BFS on the
     5272        graph, then checking whether the order is a Perfect
     5273        Elimination Order by computing for each vertex `v` the
     5274        subgraph induces by its non-deleted neighbors, then
     5275        testing whether this graph is complete.
     5276   
     5277        This problem can be solved in `O(m)` [Rose75]_ ( where `m`
     5278        is the number of edges in the graph ) but this
     5279        implementation is not linear because of the complexity of
     5280        Lex BFS. Improving Lex BFS to linear complexity would make
     5281        this algorithm linear.
     5282   
     5283        The complexity of this algorithm is equal to the
     5284        complexity of the implementation of Lex BFS.
     5285   
     5286        EXAMPLES:
     5287   
     5288        The lexicographic product of a Path and a Complete Graph
     5289        is chordal ::
     5290   
     5291            sage: g = graphs.PathGraph(5).lexicographic_product(graphs.CompleteGraph(3))
     5292            sage: g.is_chordal()
     5293            True
     5294   
     5295        The same goes with the product of a random lobster
     5296        ( which is a tree ) and a Complete Graph ::
     5297       
     5298            sage: g = graphs.RandomLobster(10,.5,.5).lexicographic_product(graphs.CompleteGraph(3))
     5299            sage: g.is_chordal()
     5300            True
     5301   
     5302        Of course, the Petersen Graph is not chordal as it has girth 5 ::
     5303   
     5304            sage: g = graphs.PetersenGraph()
     5305            sage: g.girth()
     5306            5
     5307            sage: g.is_chordal()
     5308            False
     5309   
     5310        REFERENCES:
     5311   
     5312        .. [Rose75] Rose, D.J. and Tarjan, R.E.,
     5313          Algorithmic aspects of vertex elimination,
     5314          Proceedings of seventh annual ACM symposium on Theory of computing
     5315          Page 254, ACM 1975
     5316   
     5317        .. [Fulkerson65] Fulkerson, D.R. and Gross, OA
     5318          Incidence matrices and interval graphs
     5319          Pacific J. Math 1965
     5320          Vol. 15, number 3, pages 835--855
     5321        """
     5322   
     5323        peo,t_peo = self.lex_BFS(tree=True)
     5324   
     5325        g = self.copy()
     5326   
     5327        from sage.combinat.subset import Subsets
     5328        neighbors_subsets = dict([(v,Subsets(self.neighbors(v)+[v])) for v in self.vertex_iterator()])
     5329   
     5330        while peo:
     5331            v = peo.pop()
     5332            if t_peo.out_degree(v)>0 and g.neighbors(v) not in neighbors_subsets[t_peo.neighbor_out_iterator(v).next()]:
     5333                return False
     5334            g.delete_vertex(v)
     5335        return True
     5336
    52575337    def is_clique(self, vertices=None, directed_clique=False):
    52585338        """
    52595339        Returns True if the set ``vertices`` is a clique, False
     
    67156795                        if w not in seen:
    67166796                            queue.append((w, d+1))
    67176797
     6798    def lex_BFS(self,reverse=False,tree=False):
     6799        r"""
     6800        Performs a Lex BFS on the graph.
     6801   
     6802        A Lex BFS ( or Lexicographic Breadth-First Search ) is a Breadth
     6803        First Search used for the recognition of Chordal Graphs.
     6804   
     6805        More information on this page :
     6806        http://en.wikipedia.org/wiki/Lexicographic_breadth-first_search
     6807   
     6808        INPUT:
     6809   
     6810        - ``reverse`` ( boolean ) -- whether to return the vertices
     6811          in discovery order, or the reverse.
     6812   
     6813        ALGORITHM:
     6814   
     6815        This algorithm maintains for each vertex left in the graph
     6816        a code corresponding to the vertices already removed. The
     6817        vertex of maximal code ( according to the lexicographic
     6818        order ) is then removed, and the codes are updated.
     6819   
     6820        This algorithm runs in time `O(n^2)` ( where `n` is the
     6821        number of vertices in the graph ), which is not optimal.
     6822        An optimal algorithm would run in time `O(m)` ( where `m`
     6823        is the number of edges in the graph ), and require the use
     6824        of a doubly-linked list which are not available in python
     6825        and can not really be written efficiently. This could be
     6826        done in Cython, though.
     6827   
     6828        EXAMPLE:
     6829   
     6830        A Lex BFS is obviously an ordering of the vertices::
     6831   
     6832            sage: g = graphs.PetersenGraph()
     6833            sage: len(g.lex_BFS()) == g.order()
     6834            True
     6835   
     6836        For a Chordal Graph, a reversed Lex BFS is a Perfect
     6837        Elimination Order ::
     6838   
     6839            sage: g = graphs.PathGraph(3).lexicographic_product(graphs.CompleteGraph(2))
     6840            sage: g.lex_BFS(reverse=True)
     6841            [(2, 1), (2, 0), (1, 1), (1, 0), (0, 1), (0, 0)]
     6842        """
     6843        id_inv = dict([(i,v) for (v,i) in zip(self.vertices(),range(self.order()))])
     6844        code = [[] for i in range(self.order())]
     6845        m = self.am()
     6846       
     6847        l = lambda x : code[x]
     6848        vertices = set(range(self.order()))
     6849   
     6850        value = []
     6851        pred = [-1]*self.order()
     6852   
     6853        add_element = (lambda y:value.append(id_inv[y])) if not reverse else (lambda y: value.insert(0,id_inv[y]))
     6854   
     6855        while vertices:
     6856            v = max(vertices,key=l)
     6857            vertices.remove(v)
     6858            vector = m.column(v)
     6859            for i in vertices:
     6860                code[i].append(vector[i])
     6861                if vector[i]:
     6862                    pred[i] = v
     6863            add_element(v)
     6864   
     6865        if tree:
     6866            g = DiGraph(sparse=True)
     6867            edges = [(id_inv[i], id_inv[pred[i]]) for i in range(self.order()) if pred[i]!=-1]
     6868            g.add_edges(edges)
     6869            return value, g
     6870
     6871        else:
     6872            return value
     6873   
    67186874    ### Constructors
    67196875
    67206876    def add_cycle(self, vertices):