Ticket #9581: trac_9581-edge_incident.patch

File trac_9581-edge_incident.patch, 10.0 KB (added by vdelecroix, 10 years ago)

apply only this patch which takes care of Nathan remark

  • sage/graphs/generic_graph.py

    # HG changeset patch
    # User Vincent Delecroix <20100.delecroix at gmail.com>
    # Date 1286705749 -7200
    # Node ID 00006287cba84791d416da68764b00a5ce4ab96e
    # Parent  de197be456daa35faa368faeb11e4a711cd41200
    #9581: edges_incident does not return the right answer
    
    This patch correct edges_incident, add a sort option to many edge function and
    improve many algorithms which involve iteration.
    
    diff -r de197be456da -r 00006287cba8 sage/graphs/generic_graph.py
    a b  
    67626762
    67636763    def edges(self, labels=True, sort=True):
    67646764        """
    6765         Return a list of edges. Each edge is a triple (u,v,l) where u and v
    6766         are vertices and l is a label.
    6767        
    6768         INPUT:
    6769        
    6770        
    6771         -  ``labels`` - (bool; default: True) if False, each
    6772            edge is a tuple (u,v) of vertices.
    6773        
    6774         -  ``sort`` - (bool; default: True) if True, ensure
    6775            that the list of edges is sorted.
     6765        Return a list of edges.
     6766       
     6767        Each edge is a triple (u,v,l) where u and v are vertices and l is a
     6768        label. If the parameter ``labels`` is False then a list of couple (u,v)
     6769        is returned where u and v are vertices.
     6770       
     6771        INPUT:
     6772       
     6773       
     6774        -  ``labels`` - (bool; default: True) if False, each edge is a tuple
     6775           (u,v) of vertices.
     6776       
     6777        -  ``sort`` - (bool; default: True) if True, ensure that the list of
     6778           edges is sorted.
    67766779       
    67776780       
    67786781        OUTPUT: A list of tuples. It is safe to change the returned list.
     
    67956798            sage: D.edges(labels = False)
    67966799            [(0, 1), (0, 10), (0, 19), (1, 0), (1, 2), (1, 8), (2, 1), (2, 3), (2, 6), (3, 2), (3, 4), (3, 19), (4, 3), (4, 5), (4, 17), (5, 4), (5, 6), (5, 15), (6, 2), (6, 5), (6, 7), (7, 6), (7, 8), (7, 14), (8, 1), (8, 7), (8, 9), (9, 8), (9, 10), (9, 13), (10, 0), (10, 9), (10, 11), (11, 10), (11, 12), (11, 18), (12, 11), (12, 13), (12, 16), (13, 9), (13, 12), (13, 14), (14, 7), (14, 13), (14, 15), (15, 5), (15, 14), (15, 16), (16, 12), (16, 15), (16, 17), (17, 4), (17, 16), (17, 18), (18, 11), (18, 17), (18, 19), (19, 0), (19, 3), (19, 18)]
    67976800        """
    6798         L = list(self.edge_iterator(labels=labels))
    67996801        if sort:
    6800             L.sort()
    6801         return L
    6802 
    6803     def edge_boundary(self, vertices1, vertices2=None, labels=True):
    6804         """
    6805         Returns a list of edges `(u,v,l)` with `u` in ``vertices1``
     6802            return sorted(self.edge_iterator(labels=labels))
     6803        return list(self.edge_iterator(labels=labels))
     6804
     6805    def edge_boundary(self, vertices1, vertices2=None, labels=True, sort=True):
     6806        """
     6807        Returns a list of edges in the boundary of some vertices.
     6808
     6809        Returns the list of edges `(u,v,l)` with `u` in ``vertices1``
    68066810        and `v` in ``vertices2``. If ``vertices2`` is ``None``, then
    68076811        it is set to the complement of ``vertices1``.
    68086812       
    6809         In a digraph, the external boundary of a vertex `v` are those
    6810         vertices `u` with an arc `(v, u)`.
    6811        
    6812         INPUT:
    6813        
    6814        
    6815         -  ``labels`` - if ``False``, each edge is a tuple `(u,v)` of
    6816            vertices.
     6813        In a digraph, the external boundary of a vertex `u` are the
     6814        vertices `v` with an arc `(u, v)`.
     6815       
     6816        INPUT:
     6817       
     6818        -  ``labels`` - bool (default: True) - if ``False``, each edge is a
     6819           tuple `(u,v)` of  vertices.
     6820
     6821        - ``sort`` - bool (default: True) - sort the returned list.
    68176822       
    68186823       
    68196824        EXAMPLES::
     
    68456850            sage: G = graphs.DiamondGraph()
    68466851            sage: G.edge_boundary([0,1])
    68476852            [(0, 2, {}), (1, 2, {}), (1, 3, {})]
    6848             sage: G = graphs.PetersenGraph()
    68496853            sage: G.edge_boundary([0], [0])
    68506854            []
    6851 
    6852         """
    6853         vertices1 = [v for v in vertices1 if v in self]
    6854         output = []
    6855         if self._directed:
    6856             output.extend(self.outgoing_edge_iterator(vertices1,labels=labels))
     6855            sage: G.edge_boundary([2], [0])
     6856            [(0, 2, {})]
     6857        """
     6858        vertices1 = set([v for v in vertices1 if v in self])
     6859        if self._directed:
    68576860            if vertices2 is not None:
    6858                 output = [e for e in output if e[1] in vertices2]
    6859             else:
    6860                 output = [e for e in output if e[1] not in vertices1]
    6861             return output
    6862         else:
    6863             output.extend(self.edge_iterator(vertices1,labels=labels))
    6864             output2 = []
     6861                vertices2 = set([v for v in vertices2 if v in self])
     6862                output = [e for e in self.outgoing_edge_iterator(vertices1,labels=labels)
     6863                            if e[1] in vertices2]
     6864            else:
     6865                output = [e for e in self.outgoing_edge_iterator(vertices1,labels=labels)
     6866                            if e[1] not in vertices1]
     6867        else:
    68656868            if vertices2 is not None:
    6866                 for e in output:
    6867                     if e[0] in vertices1:
    6868                         if e[1] in vertices2:
    6869                             output2.append(e)
    6870                     elif e[0] in vertices2: # e[1] in vertices1
    6871                         output2.append(e)
    6872             else:
    6873                 for e in output:
    6874                     if e[0] in vertices1:
    6875                         if e[1] not in vertices1:
    6876                             output2.append(e)
    6877                     elif e[0] not in vertices1: # e[1] in vertices1
    6878                         output2.append(e)
    6879             return output2
     6869                vertices2 = set([v for v in vertices2 if v in self])
     6870                output = [e for e in self.edge_iterator(vertices1,labels=labels)
     6871                            if (e[0] in vertices1 and e[1] in vertices2) or
     6872                            (e[1] in vertices1 and e[0] in vertices2)]
     6873            else:
     6874                output = [e for e in self.edge_iterator(vertices1,labels=labels)
     6875                            if e[1] not in vertices1 or e[0] not in vertices1]
     6876        if sort:
     6877            output.sort()
     6878        return output
    68806879
    68816880    def edge_iterator(self, vertices=None, labels=True, ignore_direction=False):
    68826881        """
    6883         Returns an iterator over the edges incident with any vertex given.
    6884         If the graph is directed, iterates over edges going out only. If
    6885         vertices is None, then returns an iterator over all edges. If self
    6886         is directed, returns outgoing edges only.
    6887        
    6888         INPUT:
    6889        
     6882        Returns an iterator over edges.
     6883
     6884        The iterator returned is over the edges incident with any vertex given
     6885        in the parameter ``vertices``. If the graph is directed, iterates over
     6886        edges going out only. If vertices is None, then returns an iterator over
     6887        all edges. If self is directed, returns outgoing edges only.
     6888       
     6889        INPUT:
     6890       
     6891        - ``vertices`` - (default: None) a vertex, a list of vertices or None
    68906892       
    68916893        -  ``labels`` - if False, each edge is a tuple (u,v) of
    68926894           vertices.
    68936895       
    6894         -  ``ignore_direction`` - (default False) only applies
     6896        -  ``ignore_direction`` - bool (default: False) - only applies
    68956897           to directed graphs. If True, searches across edges in either
    68966898           direction.
    68976899       
     
    69306932        else:
    69316933            vertices = [v for v in vertices if v in self]
    69326934        if ignore_direction and self._directed:
    6933             for e in self._backend.iterator_out_edges(vertices, labels):
    6934                 yield e
    6935             for e in self._backend.iterator_in_edges(vertices, labels):
    6936                 yield e
     6935            from itertools import chain
     6936            return chain(self._backend.iterator_out_edges(vertices, labels),
     6937                         self._backend.iterator_in_edges(vertices, labels))
    69376938        elif self._directed:
    6938             for e in self._backend.iterator_out_edges(vertices, labels):
    6939                 yield e
    6940         else:
    6941             for e in self._backend.iterator_edges(vertices, labels):
    6942                 yield e
    6943 
    6944     def edges_incident(self, vertices=None, labels=True):
    6945         """
    6946         Returns a list of edges incident with any vertex given. If vertices
     6939            return self._backend.iterator_out_edges(vertices, labels)
     6940        else:
     6941            return self._backend.iterator_edges(vertices, labels)
     6942
     6943    def edges_incident(self, vertices=None, labels=True, sort=True):
     6944        """
     6945        Returns incident edges to some vertices.
     6946
     6947        If ``vertices` is a vertex, then it returns the list of edges incident to
     6948        that vertex. If ``vertices`` is a list of vertices then it returns the
     6949        list of all edges adjacent to those vertices. If ``vertices``
    69476950        is None, returns a list of all edges in graph. For digraphs, only
    69486951        lists outward edges.
    69496952       
    69506953        INPUT:
    6951        
    6952        
    6953         -  ``label`` - if False, each edge is a tuple (u,v) of
    6954            vertices.
     6954
     6955        - ``vertices`` - object (default: None) - a vertex, a list of vertices
     6956          or None.
     6957       
     6958        -  ``labels`` - bool (default: True) - if False, each edge is a tuple
     6959           (u,v) of vertices.
     6960
     6961        - ``sort`` - bool (default: True) - if True the returned list is sorted.
    69556962       
    69566963       
    69576964        EXAMPLES::
     
    69636970            [(0, 1, None)]
    69646971            sage: D.edges_incident([1])
    69656972            []
     6973
     6974        TESTS::
     6975
     6976            sage: G = Graph({0:[0]}, loops=True)  # ticket 9581
     6977            sage: G.edges_incident(0)
     6978            [(0, 0, None)]
    69666979        """
    69676980        if vertices in self:
    69686981            vertices = [vertices]
    6969         v = list(self.edge_boundary(vertices, labels=labels))
    6970         v.sort()   
    6971         return v
     6982
     6983        if sort:
     6984            return sorted(self.edge_iterator(vertices=vertices,labels=labels))
     6985        return list(self.edge_iterator(vertices=vertices,labels=labels))
    69726986
    69736987    def edge_label(self, u, v=None):
    69746988        """