# HG changeset patch
# User Vincent Delecroix <20100.delecroix at gmail.com>
# Date 1286705749 7200
# Node ID 4b23c26b5c30da957eba2e4d848c2614d16d9c73
# Parent 7ae7b5175304fea5b08c9ee313c372a3936baa1e
#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 7ae7b5175304 r 4b23c26b5c30 sage/graphs/generic_graph.py
a

b


7185  7185  
7186  7186  def edges(self, labels=True, sort=True, key=None): 
7187  7187  r""" 
7188   Return a list of the edges of the graph as triples (u,v,l) 
7189   where u and v are vertices and l is a label. 
 7188  Return a list of edges. 
 7189  
 7190  Each edge is a triple (u,v,l) where u and v are vertices and l is a 
 7191  label. If the parameter ``labels`` is False then a list of couple (u,v) 
 7192  is returned where u and v are vertices. 
7190  7193  
7191  7194  INPUT: 
7192  7195  
… 
… 

7269  7272  L.sort(key=key) 
7270  7273  return L 
7271  7274  
7272   def edge_boundary(self, vertices1, vertices2=None, labels=True): 
 7275  def edge_boundary(self, vertices1, vertices2=None, labels=True, sort=True): 
7273  7276  """ 
7274  7277  Returns a list of edges `(u,v,l)` with `u` in ``vertices1`` 
7275  7278  and `v` in ``vertices2``. If ``vertices2`` is ``None``, then 
… 
… 

7314  7317  sage: G = graphs.DiamondGraph() 
7315  7318  sage: G.edge_boundary([0,1]) 
7316  7319  [(0, 2, {}), (1, 2, {}), (1, 3, {})] 
7317   sage: G = graphs.PetersenGraph() 
7318  7320  sage: G.edge_boundary([0], [0]) 
7319  7321  [] 
7320   
7321   """ 
7322   vertices1 = [v for v in vertices1 if v in self] 
7323   output = [] 
7324   if self._directed: 
7325   output.extend(self.outgoing_edge_iterator(vertices1,labels=labels)) 
 7322  sage: G.edge_boundary([2], [0]) 
 7323  [(0, 2, {})] 
 7324  """ 
 7325  vertices1 = set([v for v in vertices1 if v in self]) 
 7326  if self._directed: 
7326  7327  if vertices2 is not None: 
7327   output = [e for e in output if e[1] in vertices2] 
7328   else: 
7329   output = [e for e in output if e[1] not in vertices1] 
7330   return output 
7331   else: 
7332   output.extend(self.edge_iterator(vertices1,labels=labels)) 
7333   output2 = [] 
 7328  vertices2 = set([v for v in vertices2 if v in self]) 
 7329  output = [e for e in self.outgoing_edge_iterator(vertices1,labels=labels) 
 7330  if e[1] in vertices2] 
 7331  else: 
 7332  output = [e for e in self.outgoing_edge_iterator(vertices1,labels=labels) 
 7333  if e[1] not in vertices1] 
 7334  else: 
7334  7335  if vertices2 is not None: 
7335   for e in output: 
7336   if e[0] in vertices1: 
7337   if e[1] in vertices2: 
7338   output2.append(e) 
7339   elif e[0] in vertices2: # e[1] in vertices1 
7340   output2.append(e) 
7341   else: 
7342   for e in output: 
7343   if e[0] in vertices1: 
7344   if e[1] not in vertices1: 
7345   output2.append(e) 
7346   elif e[0] not in vertices1: # e[1] in vertices1 
7347   output2.append(e) 
7348   return output2 
 7336  vertices2 = set([v for v in vertices2 if v in self]) 
 7337  output = [e for e in self.edge_iterator(vertices1,labels=labels) 
 7338  if (e[0] in vertices1 and e[1] in vertices2) or 
 7339  (e[1] in vertices1 and e[0] in vertices2)] 
 7340  else: 
 7341  output = [e for e in self.edge_iterator(vertices1,labels=labels) 
 7342  if e[1] not in vertices1 or e[0] not in vertices1] 
 7343  if sort: 
 7344  output.sort() 
 7345  return output 
7349  7346  
7350  7347  def edge_iterator(self, vertices=None, labels=True, ignore_direction=False): 
7351  7348  """ 
7352   Returns an iterator over the edges incident with any vertex given. 
7353   If the graph is directed, iterates over edges going out only. If 
7354   vertices is None, then returns an iterator over all edges. If self 
7355   is directed, returns outgoing edges only. 
7356   
7357   INPUT: 
7358   
 7349  Returns an iterator over edges. 
 7350  
 7351  The iterator returned is over the edges incident with any vertex given 
 7352  in the parameter ``vertices``. If the graph is directed, iterates over 
 7353  edges going out only. If vertices is None, then returns an iterator over 
 7354  all edges. If self is directed, returns outgoing edges only. 
 7355  
 7356  INPUT: 
 7357  
 7358   ``vertices``  (default: None) a vertex, a list of vertices or None 
7359  7359  
7360  7360   ``labels``  if False, each edge is a tuple (u,v) of 
7361  7361  vertices. 
7362  7362  
7363    ``ignore_direction``  (default False) only applies 
 7363   ``ignore_direction``  bool (default: False)  only applies 
7364  7364  to directed graphs. If True, searches across edges in either 
7365  7365  direction. 
7366  7366  
… 
… 

7399  7399  else: 
7400  7400  vertices = [v for v in vertices if v in self] 
7401  7401  if ignore_direction and self._directed: 
7402   for e in self._backend.iterator_out_edges(vertices, labels): 
7403   yield e 
7404   for e in self._backend.iterator_in_edges(vertices, labels): 
7405   yield e 
 7402  from itertools import chain 
 7403  return chain(self._backend.iterator_out_edges(vertices, labels), 
 7404  self._backend.iterator_in_edges(vertices, labels)) 
7406  7405  elif self._directed: 
7407   for e in self._backend.iterator_out_edges(vertices, labels): 
7408   yield e 
7409   else: 
7410   for e in self._backend.iterator_edges(vertices, labels): 
7411   yield e 
7412   
7413   def edges_incident(self, vertices=None, labels=True): 
7414   """ 
7415   Returns a list of edges incident with any vertex given. If vertices 
 7406  return self._backend.iterator_out_edges(vertices, labels) 
 7407  else: 
 7408  return self._backend.iterator_edges(vertices, labels) 
 7409  
 7410  def edges_incident(self, vertices=None, labels=True, sort=True): 
 7411  """ 
 7412  Returns incident edges to some vertices. 
 7413  
 7414  If ``vertices` is a vertex, then it returns the list of edges incident to 
 7415  that vertex. If ``vertices`` is a list of vertices then it returns the 
 7416  list of all edges adjacent to those vertices. If ``vertices`` 
7416  7417  is None, returns a list of all edges in graph. For digraphs, only 
7417  7418  lists outward edges. 
7418  7419  
7419  7420  INPUT: 
7420   
7421   
7422    ``label``  if False, each edge is a tuple (u,v) of 
7423   vertices. 
 7421  
 7422   ``vertices``  object (default: None)  a vertex, a list of vertices 
 7423  or None. 
 7424  
 7425   ``labels``  bool (default: True)  if False, each edge is a tuple 
 7426  (u,v) of vertices. 
 7427  
 7428   ``sort``  bool (default: True)  if True the returned list is sorted. 
7424  7429  
7425  7430  
7426  7431  EXAMPLES:: 
… 
… 

7432  7437  [(0, 1, None)] 
7433  7438  sage: D.edges_incident([1]) 
7434  7439  [] 
 7440  
 7441  TESTS:: 
 7442  
 7443  sage: G = Graph({0:[0]}, loops=True) # ticket 9581 
 7444  sage: G.edges_incident(0) 
 7445  [(0, 0, None)] 
7435  7446  """ 
7436  7447  if vertices in self: 
7437  7448  vertices = [vertices] 
7438   v = list(self.edge_boundary(vertices, labels=labels)) 
7439   v.sort() 
7440   return v 
 7449  
 7450  if sort: 
 7451  return sorted(self.edge_iterator(vertices=vertices,labels=labels)) 
 7452  return list(self.edge_iterator(vertices=vertices,labels=labels)) 
7441  7453  
7442  7454  def edge_label(self, u, v=None): 
7443  7455  """ 