Source code for combalg.rooted_tree
'''
rooted_tree.py
==============
Rooted Tree Algorithms. Well, only random selection. I believe there is
enough material in chapter 13 of [NW1978]_ to implement an enumerated
sequence (interesting challenge).
Members
~~~~~~~
'''
import random as rng
rooted_tree_count = {}
[docs]def random(nn):
'''
Returns a random rooted tree on nn vertices
:param nn: number of vertices in the output tree.
:type nn: int
:return: a random rooted tree
:rtype: list
The returned list is in `Prufer Code <https://en.wikipedia.org/wiki/Pr%C3%BCfer_sequence>`_.
You can convert the result to an edge list by zipping it with the
sequence [0,1,..,nn] and discarding the initial entry, which is always (0,0).
>>> result = rooted_tree.random(7)
>>> edge_list = list(zip(result, range(len(result))))[1:]
'''
def tc(n):
if n not in rooted_tree_count:
if n <= 2:
rooted_tree_count[n] = 1
else:
sum = 0
for m in range(1,n):
inner = 0
term = tc(n-m)
for d in range(1,m+1):
if m % d == 0:
inner += d * tc(d)
sum += term * inner
rooted_tree_count[n] = sum / (n-1)
return rooted_tree_count[n]
def select_jd(n):
tn = tc(n)
rho = rng.random()
sum = 0
for j in range(1,n+1):
for d in range(1,n+1):
if n - j*d > 0:
prob = float(d)*tc(n-j*d)*tc(d)/((n-1)*tn)
sum += prob
if sum > rho:
return j,d
# begin random rooted tree
stack = []
tree = []
t = 0
tm1 = -1
k = 0
r = 0
n = nn
done = False
while not done:
if n <= 2:
tm1 = t
t = len(tree)
for i in range(0,n):
tree.append(t)
k += n
else:
j,d = select_jd(n)
stack.append((j,d))
n = n - j*d
continue
while len(stack) > 0:
j,d = stack.pop()
if d > 0:
stack.append((j,0))
n = d
break
else:
lt = len(tree)
for i in range(0,j-1):
save = tree[t]
for j in range(t,lt):
if tree[j] != save:
k += 1
tree.append(k)
for j in range(t,len(tree)):
if tree[j] == j:
tree[j] = tm1
t = tm1
if tm1 > 0:
tm1 -= 1
while tm1 > 0 and tree[tm1] != tm1:
tm1 -= 1
done = len(stack) == 0
return tree