/
rusht.py
181 lines (153 loc) · 5.49 KB
/
rusht.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# vim: tabstop=4 shiftwidth=4 softtabstop=4 et
import collections
import gv
import pdb
LEAF, INTER = ("LEAF", "INTER")
class Node:
def __init__(self, flavor, identity, weight):
self.flavor = flavor
self.identity = identity
self.weight = weight
def string(self):
return bin(self.identity)[2:]
#self.root[0] => [node0]
#self.root[1] => [node1, node2]
#self.root[2] => [node3, node4, node5, node6]
class RushTree:
def __init__(self):
self.root = collections.deque()
self.root.append([Node(LEAF, 1, 1)])
self.depth = 1
#point to the last inserted
self.last = 0
#for draw
self.G = gv.digraph("G")
gv.setv(self.G, 'nodesep', '0.05')
gv.setv(self.G, 'rankdir', 'TB')
N = gv.protonode(self.G)
gv.setv(N, 'shape', 'record')
E = gv.protoedge(self.G)
gv.setv(E, 'side', 'left')
def insert_node(self):
#get last line
if len(self.root[self.depth-1]) < 2 ** (self.depth - 1):
#use the slot
#generate intermedia nodes
pos = self.last + 1
self.generate_parents_and_increate_weight(pos, self.depth, 1)
identity = self.calc_identity(pos, self.depth)
self.root[self.depth-1].append(Node(LEAF, identity, 1))
self.last += 1
#let all index node add new weight
#need new root node
else:
left_child_weight = self.root[0][0].weight
self.root.appendleft([Node(INTER, self.root[0][0].identity << 1 ,left_child_weight)])
self.depth += 1
self.insert_node()
#pos,depth is current node's parameter, its parents would be pos/2, depth-1
def generate_parents_and_increate_weight(self, pos, depth, weight):
if depth == 1:
return
parent = pos/2
parent_depth = depth - 1
if self.is_exist(parent_depth, parent) == True:
node = self.root[parent_depth-1][parent]
node.weight += weight
else:
#create new parent
v = self.calc_identity(parent, parent_depth)
self.root[parent_depth-1].append(Node(INTER, v, weight))
self.generate_parents_and_increate_weight(parent, parent_depth, weight)
def calc_identity(self, pos, depth):
#copy from the left tree and add 1 to left side
current_value = self.root[depth -1][pos - (2 ** (depth - 1))/2].identity + (1 << self.depth - 1)
return current_value
def is_exist(self, depth, pos):
try:
self.root[depth-1][pos]
except:
return False
return True
def print_me(self):
i = 0
print "total objects:%d" % (self.last + 1)
while i < self.depth:
print "depth %d" % (i)
for j in self.root[i]:
print "%s" % (j)
i += 1
def get_leftchild(self, depth, pos):
if depth + 1 > self.depth:
return None
try:
self.root[depth][2*pos]
except:
return None
return (depth+1, 2*pos)
def get_rightchild(self,depth,pos):
if depth + 1 > self.depth:
return None
try:
#depth + 1 is next depth
#depth + 1 - 1 is for offset
self.root[depth][2*pos + 1]
except:
return None
return (depth+1, 2*pos + 1)
def get_node(self,depth,pos):
return self.root[depth-1][pos]
def iterate_LHR(self,depth,pos):
left_child = self.get_leftchild(depth,pos)
if left_child:
for i in self.iterate_LHR(*left_child):
yield i
yield self.get_node(depth, pos)
right_child = self.get_rightchild(depth,pos)
if right_child:
for i in self.iterate_LHR(*right_child):
yield i
def iterate_LHR_N(self, depth, pos):
parent_nodes = []
n = (depth, pos)
while len(parent_nodes) > 0 or n != None:
if n != None:
parent_nodes.append(n)
n = self.get_leftchild(n[0], n[1])
else:
n = parent_nodes.pop()
yield self.get_node(n[0],n[1])
n = self.get_rightchild(n[0], n[1])
def out_graph(self):
if self.depth > 1:
self.generate_graph(1,0)
else:
first_node = self.get_node(1,0)
n = gv.node(self.G, first_node.string())
gv.setv(n, "label", "%s|%d" % (first_node.string(), first_node.weight))
gv.layout(self.G, 'dot')
#gv.render(self.G, 'xlib')
gv.write(self.G, "tree.dot")
def generate_graph(self,depth,pos):
left_child = self.get_leftchild(depth,pos)
if left_child:
self.add_edge(self.get_node(depth,pos), self.get_node(*left_child))
self.generate_graph(*left_child)
right_child = self.get_rightchild(depth,pos)
if right_child:
self.add_edge(self.get_node(depth,pos), self.get_node(*right_child))
self.generate_graph(*right_child)
def add_edge(self,a,b):
nodea = gv.node(self.G, a.string())
gv.setv(nodea, "label", "%s|%d" % (a.string(), a.weight))
nodeb = gv.node(self.G, b.string())
gv.setv(nodeb, "label", "%s|%d" % (b.string(), b.weight))
gv.edge(nodea, nodeb)
t = RushTree()
i = 0
while i < 4:
t.insert_node()
i += 1
#t.out_graph()
for i in t.iterate_LHR_N(1,0):
print i.string()