##// END OF EJS Templates
ancestor: use set instead of dict
Benoit Boissinot -
r8465:23429ebd default
parent child Browse files
Show More
@@ -1,85 +1,85
1 1 # ancestor.py - generic DAG ancestor algorithm for mercurial
2 2 #
3 3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2, incorporated herein by reference.
7 7
8 8 import heapq
9 9
10 10 def ancestor(a, b, pfunc):
11 11 """
12 12 return the least common ancestor of nodes a and b or None if there
13 13 is no such ancestor.
14 14
15 15 pfunc must return a list of parent vertices
16 16 """
17 17
18 18 if a == b:
19 19 return a
20 20
21 21 # find depth from root of all ancestors
22 22 parentcache = {}
23 23 visit = [a, b]
24 24 depth = {}
25 25 while visit:
26 26 vertex = visit[-1]
27 27 pl = pfunc(vertex)
28 28 parentcache[vertex] = pl
29 29 if not pl:
30 30 depth[vertex] = 0
31 31 visit.pop()
32 32 else:
33 33 for p in pl:
34 34 if p == a or p == b: # did we find a or b as a parent?
35 35 return p # we're done
36 36 if p not in depth:
37 37 visit.append(p)
38 38 if visit[-1] == vertex:
39 39 depth[vertex] = min([depth[p] for p in pl]) - 1
40 40 visit.pop()
41 41
42 42 # traverse ancestors in order of decreasing distance from root
43 43 def ancestors(vertex):
44 44 h = [(depth[vertex], vertex)]
45 seen = {}
45 seen = set()
46 46 while h:
47 47 d, n = heapq.heappop(h)
48 48 if n not in seen:
49 seen[n] = 1
49 seen.add(n)
50 50 yield (d, n)
51 51 for p in parentcache[n]:
52 52 heapq.heappush(h, (depth[p], p))
53 53
54 54 def generations(vertex):
55 sg, s = None, {}
55 sg, s = None, set()
56 56 for g, v in ancestors(vertex):
57 57 if g != sg:
58 58 if sg:
59 59 yield sg, s
60 sg, s = g, {v:1}
60 sg, s = g, set((v,))
61 61 else:
62 s[v] = 1
62 s.add(v)
63 63 yield sg, s
64 64
65 65 x = generations(a)
66 66 y = generations(b)
67 67 gx = x.next()
68 68 gy = y.next()
69 69
70 70 # increment each ancestor list until it is closer to root than
71 71 # the other, or they match
72 72 try:
73 73 while 1:
74 74 if gx[0] == gy[0]:
75 75 for v in gx[1]:
76 76 if v in gy[1]:
77 77 return v
78 78 gy = y.next()
79 79 gx = x.next()
80 80 elif gx[0] > gy[0]:
81 81 gy = y.next()
82 82 else:
83 83 gx = x.next()
84 84 except StopIteration:
85 85 return None
General Comments 0
You need to be logged in to leave comments. Login now