##// END OF EJS Templates
ancestor: improve docstring...
Sune Foldager -
r9915:806e6b6c default
parent child Browse files
Show More
@@ -1,85 +1,86 b''
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 return the least common ancestor of nodes a and b or None if there
13 is no such ancestor.
12 return a minimal-distance ancestor of nodes a and b, or None if there is no
13 such ancestor. Note that there can be several ancestors with the same
14 (minimal) distance, and the one returned is arbitrary.
14 15
15 pfunc must return a list of parent vertices
16 pfunc must return a list of parent vertices for a given vertex
16 17 """
17 18
18 19 if a == b:
19 20 return a
20 21
21 22 # find depth from root of all ancestors
22 23 parentcache = {}
23 24 visit = [a, b]
24 25 depth = {}
25 26 while visit:
26 27 vertex = visit[-1]
27 28 pl = pfunc(vertex)
28 29 parentcache[vertex] = pl
29 30 if not pl:
30 31 depth[vertex] = 0
31 32 visit.pop()
32 33 else:
33 34 for p in pl:
34 35 if p == a or p == b: # did we find a or b as a parent?
35 36 return p # we're done
36 37 if p not in depth:
37 38 visit.append(p)
38 39 if visit[-1] == vertex:
39 40 depth[vertex] = min([depth[p] for p in pl]) - 1
40 41 visit.pop()
41 42
42 43 # traverse ancestors in order of decreasing distance from root
43 44 def ancestors(vertex):
44 45 h = [(depth[vertex], vertex)]
45 46 seen = set()
46 47 while h:
47 48 d, n = heapq.heappop(h)
48 49 if n not in seen:
49 50 seen.add(n)
50 51 yield (d, n)
51 52 for p in parentcache[n]:
52 53 heapq.heappush(h, (depth[p], p))
53 54
54 55 def generations(vertex):
55 56 sg, s = None, set()
56 57 for g, v in ancestors(vertex):
57 58 if g != sg:
58 59 if sg:
59 60 yield sg, s
60 61 sg, s = g, set((v,))
61 62 else:
62 63 s.add(v)
63 64 yield sg, s
64 65
65 66 x = generations(a)
66 67 y = generations(b)
67 68 gx = x.next()
68 69 gy = y.next()
69 70
70 71 # increment each ancestor list until it is closer to root than
71 72 # the other, or they match
72 73 try:
73 74 while 1:
74 75 if gx[0] == gy[0]:
75 76 for v in gx[1]:
76 77 if v in gy[1]:
77 78 return v
78 79 gy = y.next()
79 80 gx = x.next()
80 81 elif gx[0] > gy[0]:
81 82 gy = y.next()
82 83 else:
83 84 gx = x.next()
84 85 except StopIteration:
85 86 return None
General Comments 0
You need to be logged in to leave comments. Login now