-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstochastic_growth.py
125 lines (108 loc) · 3.49 KB
/
stochastic_growth.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
__author__ = ['Salvador Aguinaga', 'Rodrigo Palacios', 'David Chaing', 'Tim Weninger']
import random
import math
import networkx as nx
import net_metrics as metrics
def control_rod(choices, H, num_nodes):
newchoices = []
p = len(H) / float(num_nodes)
total = 0
for i in range(0, len(choices)):
n = float(choices[i][0].count('N'))
t = float(choices[i][0].count('T'))
# 2*(e^-x)-1
x = p
form = 2 * math.e ** (-x) - 1
wn = n * form
wt = t
ratio = max(0, wt + wn)
total += ratio
newchoices.append((choices[i][0], ratio))
r = random.uniform(0, total)
upto = 0
if total == 0:
random.shuffle(newchoices)
for c, w in newchoices:
if upto + w >= r:
return c
upto += w
assert False, "Shouldn't get here"
def try_combination(lhs, N):
lhs
for i in range(0, len(N)):
n = N[i]
if lhs[0] == "S":
break
if len(lhs) == len(n):
t = []
for i in n:
t.append(i)
random.shuffle(t)
return zip(t, lhs)
return []
def find_match(N, prod_rules):
if len(N) == 1 and ['S'] in N: return [('S', 'S')]
matching = {}
while True:
lhs = random.choice(prod_rules.keys()).lstrip("(").rstrip(")")
lhs = lhs.split(",")
c = try_combination(lhs, N)
if c: return c
def grow(prod_rules, n, diam=0):
D = list()
newD = diam
H = list()
N = list()
N.append(["S"]) # starting node
ttt = 0
# pick non terminal
num = 0
while len(N) > 0 and num < n:
lhs_match = find_match(N, prod_rules)
e = []
match = []
for tup in lhs_match:
match.append(tup[0])
e.append(tup[1])
lhs_str = "(" + ",".join(str(x) for x in sorted(e)) + ")"
new_idx = {}
n_rhs = str(control_rod(prod_rules[lhs_str].items(), H, n)).lstrip("(").rstrip(")")
# print lhs_str, "->", n_rhs
for x in n_rhs.split(")("):
new_he = []
he = x.split(":")[0]
term_symb = x.split(":")[1]
for y in he.split(","):
if y.isdigit(): # y is internal node
if y not in new_idx:
new_idx[y] = num
num += 1
if diam > 0 and num >= newD and len(H) > 0:
newD = newD + diam
newG = nx.Graph()
for e in H:
if (len(e) == 1):
newG.add_node(e[0])
else:
newG.add_edge(e[0], e[1])
D.append(metrics.bfs_eff_diam(newG, 20, 0.9))
new_he.append(new_idx[y])
else: # y is external node
for tup in lhs_match: # which external node?
if tup[1] == y:
new_he.append(tup[0])
break
# prod = "(" + ",".join(str(x) for x in new_he) + ")"
if term_symb == "N":
N.append(sorted(new_he))
elif term_symb == "T":
H.append(new_he)
match = sorted(match)
N.remove(match)
newG = nx.Graph()
for e in H:
if (len(e) == 1):
newG.add_node(e[0])
else:
newG.add_edge(e[0], e[1])
return newG, D