# HG changeset patch
# User Diego de Estrada
# Date 1315290554 10800
# Node ID 4a4d5218c2814646f948e002476e1c4173faed28
# Parent 2a2abbcad325ccca9399981ceddf5897eb467e64
Implementation of lex_BFS() in linear time.
diff r 2a2abbcad325 r 4a4d5218c281 sage/graphs/generic_graph.py
 a/sage/graphs/generic_graph.py Thu Aug 11 12:52:48 2011 +0000
+++ b/sage/graphs/generic_graph.py Tue Sep 06 03:29:14 2011 0300
@@ 9387,13 +9387,9 @@
for each vertex `v` the subgraph induces by its nondeleted neighbors,
then testing whether this graph is complete.
 This problem can be solved in `O(m)` [Rose75]_ ( where `m` is the number
 of edges in the graph ) but this implementation is not linear because of
 the complexity of Lex BFS. Improving Lex BFS to linear complexity would
 make this algorithm linear.

The complexity of this algorithm is equal to the complexity of the
 implementation of Lex BFS.
+ implementation of Lex BFS [Rose75]_, which is linear in the size of the
+ graph.
EXAMPLES:
@@ 11535,13 +11531,9 @@
vertex of maximal code ( according to the lexicographic
order ) is then removed, and the codes are updated.
 This algorithm runs in time `O(n^2)` ( where `n` is the
 number of vertices in the graph ), which is not optimal.
 An optimal algorithm would run in time `O(m)` ( where `m`
 is the number of edges in the graph ), and require the use
 of a doublylinked list which are not available in python
 and can not really be written efficiently. This could be
 done in Cython, though.
+ This algorithm runs in time `O(n+m)` ( where `n` is the
+ number of vertices in the graph and `m` is the number of
+ edges in the graph ).
EXAMPLE:
@@ 11571,48 +11563,57 @@
True
"""
 id_inv = dict([(i,v) for (v,i) in zip(self.vertices(),range(self.order()))])
 code = [[] for i in range(self.order())]
 m = self.am()

 l = lambda x : code[x]
 vertices = set(range(self.order()))

 value = []
 pred = [1]*self.order()

 add_element = (lambda y:value.append(id_inv[y])) if not reverse else (lambda y: value.insert(0,id_inv[y]))

 # Should we take care of the first vertex we pick ?
 first = True if initial_vertex is not None else False


 while vertices:

 if not first:
 v = max(vertices,key=l)
 else:
 v = self.vertices().index(initial_vertex)
 first = False

 vertices.remove(v)
 vector = m.column(v)
 for i in vertices:
 code[i].append(vector[i])
 if vector[i]:
 pred[i] = v
 add_element(v)

+ n = self.order()
+ perm_inv = self.vertices()
+ perm = dict(zip(perm_inv,range(n)))
+
+ if initial_vertex is not None:
+ i = perm[initial_vertex]
+ if i != 0:
+ v = perm_inv[0]
+ perm[initial_vertex], perm[v] = 0, i
+ perm_inv[i], perm_inv[0] = v, initial_vertex
+
+ slice_of = [0]*n
+ slice_head = [0]*n
+ subslice = [1]*n
+ pred = {}
+
+ k = 1
+ for i in range(n):
+ old_k = k
+ v = perm_inv[i]
+ for w in self.neighbors(v):
+ j = perm[w]
+ if j <= i:
+ continue
+ a = slice_of[j]
+ if slice_head[a] <= i:
+ slice_head[a] = i+1
+ l = slice_head[a]
+ if l < n1 and slice_of[l+1] != a:
+ continue
+ u = perm_inv[l]
+ if l != j:
+ perm[w], perm[u] = l, j
+ perm_inv[j], perm_inv[l] = u, w
+ slice_head[a] += 1
+ if subslice[a] < old_k:
+ subslice[a] = k
+ slice_head[k] = l
+ k += 1
+ slice_of[l] = subslice[a]
+ pred[u] = v
+
+ if reverse:
+ perm_inv.reverse()
if tree:
from sage.graphs.digraph import DiGraph
g = DiGraph(sparse=True)
 edges = [(id_inv[i], id_inv[pred[i]]) for i in range(self.order()) if pred[i]!=1]
 g.add_edges(edges)
 return value, g

 else:
 return value

+ g.add_edges(pred.items())
+ return perm_inv, g
+ return perm_inv
+
### Constructors
def add_cycle(self, vertices):