def get_child_subtrees(root, minima, T): last = minima p = T.nodes[minima]['p'] run = 0 subtrees = [] while (last != p): neighbors = T[p] #Add all the subtrees with child saddle p for n in neighbors: #Check that n is a child and not an ancestor of minima if (n != last and f_(T.nodes[n]) < f_(T.nodes[p])): stree = sub_special(T, n) subtrees.append(stree) #We've traced back to the root if (p == root): return subtrees last = p #Update the last variable p = T.nodes[p]['p'] #Move to the next ancestor run += 1 return subtrees
def match_cost(U, V, mu, su, mv, sv): #m represents the minima #s represents the saddle cost = max(abs(f_(U.nodes[mu]) - f_(V.nodes[mv])), abs(f_(U.nodes[su]) - f_(V.nodes[sv]))) #print("Match cost: " + str(cost)) return cost
def compute_costs(A, root, costs=None): if (costs == None): costs = {} #Base removal cost #print("Saddle and Minima in tree: " + str(root in A and A.nodes[root]['p'] in A)) c = remove_cost(A, root, A.nodes[root]['p']) #Account for the necessary removal of descendants #Use memoization to speed things up f = f_(A.nodes[root]) neighbors = A[root] max_cost = c for nei in neighbors: #If nei is a child but its cost hasn't been computed... if (f_(A.nodes[nei]) < f): if (nei not in costs): costs[nei] = compute_costs(A, nei, costs)[nei] if (costs[nei] > max_cost): max_cost = costs[nei] costs[root] = max_cost return costs
def calc_set_distance(anc, i1, i2, M, distances): n = list(M.nodes) #The two nodes corresponding to the given indices. n1 = n[i1] node1 = M.nodes[n1] n2 = n[i2] node2 = M.nodes[n2] #Make sure node 1 doesn't have the greater function value if(f_(node1) > f_(node2)): n1, n2 = n2, n1 node1, node2 = node1, node2 #The ancestry lines of n1 and n2, respectively a1 = [n1] a1.list_append(anc[n1]) a2 = [n2] a2.list_append(anc[n2]) #Find the common ancestor for i in range(0, len(a2)): if(a2[i] in a1): f = f_(M.nodes[a2[i]]) distances[i1][i2] = f distances[i2][i1] = f return f
def on_level_neighbors(G, n): f = f_(G.nodes[n]) neighbors = G[n] on_lvl = [] for nei in neighbors: if(f_(G.nodes[nei]) == f): on_lvl.append(nei) return on_lvl
def add_node(n_, G, M): #The actual node n = G.nodes[n_] f = f_(n) #The node's value #Get all the children neighbors = G[n_] true_children = [] for nei in neighbors: if(f_(G.nodes[nei]) < f): #Is child true_children.append(nei) #No children => leaf if(len(true_children) == 0): M.add_node(n_) #Create a copy of n in M n['c'] = n_ #Own inferior M.nodes[n_]['p'] = n_ #Own superior M.nodes[n_]['value'] = f #Function value return #Get the roots of the children roots = [] min_root = find_c(true_children[0], G) for c in true_children: r = find_c(c, G) if(r not in roots): #Add the root if it is new roots.append(r) if(f_(G.nodes[r]) < f_(G.nodes[min_root])): #Update the min root min_root = r #1 child => just update inferior if(len(roots) == 1): n['c'] = roots[0] return #2 or MORE children => merge if(len(roots) >= 2): M.add_node(n_) #Create a copy of n in M M.nodes[n_]['p'] = n_ #Own parent M.nodes[n_]['value'] = f #Function value for r in roots: p = find_p(r, M) #What we connect to if(p != n_): #Add Edge M.add_edge(p, n_) M.nodes[p]['p'] = n_ #Update the superior if(f_(M.nodes[p]) == f): processed = {} collapse_neighbors(M, n_, processed, merge=True) #set c as the inferior of n and all other roots n['c'] = min_root for r in roots: G.nodes[r]['c'] = min_root
def median_f(M): nodes = listify_nodes(M) nodes.sort(key=f_) num = len(nodes) n1 = nodes[math.ceil((num-1)/2)] n2 = nodes[math.floor((num-1)/2)] med = (f_(n1)+f_(n2))/2 return med
def find_root(T): nodes = listify_nodes(T) max_ = f_(nodes[0]) max_node = nodes[0] for n in nodes: if(f_(n) > max_): max_ = f_(n) max_node = n return max_node['name']
def find_on_level(M, roots, f): for r in roots: p = find_p(r, M) if(f_(M.nodes[p]) == f): return p return None
def mean_f(M): nodes = listify_nodes(M) avg = 0 for n in nodes: avg += f_(n) return avg / len(nodes)
def get_child_subtrees_(root, minima, T, subtrees): last = minima p = T.nodes[minima]['p'] st = [] while (True): neighbors = T[p] #Add all the subtrees with child saddle p for n in neighbors: #Check that n is a child and not an ancestor of minima if (n != last and f_(T.nodes[n]) < f_(T.nodes[p])): st.append(subtrees[n]) #We've traced back to the root if (p == root): return st last = p #Update the last variable p = T.nodes[p]['p'] #Move to the next ancestor
def descendants_(G, n, des): if n in des: return des[n] #Add the current node d = [n] #Add all the children and their descendants neighbors = G[n] for nei in neighbors: #Check for child if (f_(G.nodes[nei]) < f_(G.nodes[n])): #memoize! if (nei not in des): des[nei] = descendants_(G, nei, des) list_append(d, des[nei]) des[n] = d return d
def remove_cost(A, u, v): return abs(f_(A.nodes[u]) - f_(A.nodes[v])) / 2