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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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']
Exemple #9
0
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
Exemple #10
0
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