Exemple #1
0
def solve(G, T=None, cost=float('inf'), multiplier=1):
    """
    Args:
        G: networkx.Graph
        T: the best known dominating-set tree. None if unknown
        cost: the cost of the best known T

    Returns:
        T: networkx.Graph
    """
    tries, max_tries = 0, int(multiplier * len(list(G.nodes)))
    while tries < max_tries:
        if cost == 0:
            break
        nodes = list(G.nodes)
        random.shuffle(nodes)
        i = 0
        while not nx.is_dominating_set(G, nodes[:i]) or not nx.is_connected(
                G.subgraph(nodes[:i])):
            i += 1
        new_T, new_cost = min(
            (pick_leaves(G, t, utils.average_pairwise_distance_fast(t))
             for t in gen_candidates(G, nodes[:i])),
            key=lambda p: p[1])
        if new_cost < cost:
            T, cost = new_T, new_cost
            tries = 0
        else:
            tries += 1
    return T, cost
Exemple #2
0
def solve2(G):
    """
    Args:
        G: networkx.Graph

    Returns:
        T: networkx.Graph
    """
    pq = []  #min heap for Kruskals edge popping
    for e in G.edges:
        heappush(pq, (-G.edges[e]['weight'], e))
    T = copy.deepcopy(G)
    costpq = []  #min heap with minimal pairwise distance with its tree

    while pq:
        if (T.number_of_nodes() == 2):
            break
        node = heappop(pq)
        e = node[1]
        # print(e)
        w = node[0] * -1
        T.remove_edge(e[0], e[1])
        if T.degree(e[1]) == 0:
            T.remove_node(e[1])
        if T.degree(e[0]) == 0:
            T.remove_node(e[0])
        if nx.is_connected(T) and nx.is_dominating_set(G, T):
            if nx.is_tree(T):
                heappush(costpq, (average_pairwise_distance_fast(T), T))
                # cost = average_pairwise_distance_fast(T)
        else:
            T.add_edge(e[0], e[1], weight=w)

    return heappop(costpq)[1]
Exemple #3
0
def combine(folders):
    inputs = {}
    best_scores = {}
    best_outputs = {}

    for filename in os.listdir(INPUT_PATH):
        inputs[filename] = read_input_file(INPUT_PATH + filename)

    for folder in folders:
        for filename in os.listdir(folder):
            if filename != '.DS_Store':
                output_graph = read_output_file(folder + filename, inputs[filename.split('.')[0] + '.in'])
                if output_graph.number_of_nodes() == 1:
                    best_scores[filename] = 0
                    best_outputs[filename] = output_graph
                else:
                    score = average_pairwise_distance_fast(output_graph)
                    if filename not in best_scores:
                        best_scores[filename] = score
                        best_outputs[filename] = output_graph
                    elif filename in best_scores and score < best_scores[filename]:
                        best_scores[filename] = score
                        best_outputs[filename] = output_graph

    for id in best_outputs:
        write_output_file(best_outputs[id], OUTPUT_PATH + id)
Exemple #4
0
def pruneLeavesDesc(l, res, currentAvg):
	#VERY naive solution bc we repeat avg_pairwise_distance method on EVERY call
	leaves = l.values()
	#print(leaves)
	removedLeaves = []
	temp = res.copy()
	verticesRemoved = {}
	#start with the largest edge weight of leaves first
	for elem in reverse(leaves):
		temp.remove(elem)
		print(temp)
		#create new graph to recalculate avg pairwise distance w/o elem
		Tr = nx.Graph()
		Tr.add_weighted_edges_from(temp)
		new_avg = average_pairwise_distance_fast(Tr)
		#if better avg obtained w/o elem: remove it and update avg
		#else, add it back and move on to next leaf
		if new_avg <= currentAvg:
			removedLeaves.append(elem)
			verticesRemoved.add([elem[0], elem[1]]) #add vertices to this set
			currentAvg = new_avg
			print("removed:"+ str(new_avg))
		else:
			temp.add(elem)
			print("kept:"+ str(new_avg))

	return (removedLeaves, verticesRemoved)
def small_graph_bruteforce_recursive(G, currG, costPQ):
    T = copy.deepcopy(currG)
    #for all edges in the current graph
    for e in T.edges:
        #BASE CASE: continue or don't continue
        if nx.is_connected(currG) and nx.is_dominating_set(G, currG):
            if nx.is_tree(currG):
                heappush(
                    costPQ,
                    (average_pairwise_distance_fast(currG), currG))  #records
                print(costPQ[0])
        else:
            #the current graph is not connected or dominating
            return

        e0 = e[0]
        e1 = e[1]
        w = G.get_edge_data(e0, e1)['weight']

        #remove then recursive
        currG.remove_edge(e[0], e[1])
        if currG.degree(e[1]) == 0:
            currG.remove_node(e[1])
        if currG.degree(e[0]) == 0:
            currG.remove_node(e[0])
        small_graph_bruteforce_recursive(G, currG, costPQ)  #recursive call

        #re-add what I just removed
        if e0 not in currG.nodes:
            currG.add_node(e0)
        if e1 not in currG.nodes:
            currG.add_node(e1)
        currG.add_edge(e0, e1, weight=w)
def solve(G):
    """
	Args:
		G: networkx.Graph

	Returns:
		T: networkx.Graph
	"""
    min_tree = nx.Graph()
    min_cost = float('inf')

    # if by luck there's a node connecting to all other verts, return it
    for node in G.nodes:
        if len(list(nx.neighbors(G, node))) == nx.number_of_nodes(G) - 1:
            min_tree.add_node(node)
            return min_tree

    start_vertices = starting_point(G)

    # run greedy alg on all starting vertex candidates
    for start_vertex in start_vertices:
        curr_tree = greedy_find_min_tree(G, start_vertex)
        curr_cost = average_pairwise_distance_fast(curr_tree)
        if curr_cost < min_cost:
            min_cost = curr_cost
            min_tree = curr_tree

    return min_tree
Exemple #7
0
def solve(G):
    """Approximates a connected dominating set across a graph input by selecting the optimal solution from many randomly generated candidate solutions.

    Parameters
    ----------
    G: NetworkX graph

    Returns
    -------
    T: A connected dominating set across G

    Notes
    -----
    This function was designed to be a randomized approximation algorithm. 
    This is an NP-hard problem which makes finding a correct solution computationally difficult.
    However, by employing probabilistic measures, this algorithm can ensure a solution T that approximates the optimal solution T'.

    """

    # initialize variables to track, and eventually return, best tree
    best_distance = float('inf')
    best_tree = G
    curr_tree = G

    # run loop 1000 times for each graph input to continually improve solution over time
    for i in range(1000):
        curr_tree = solve_computation(G)
        curr_distance = average_pairwise_distance_fast(curr_tree)
        if (curr_distance < best_distance):
            best_distance = curr_distance
            best_tree = curr_tree
    return best_tree
Exemple #8
0
def pruneLeavesAll(l, res, currentAvg, totalVs):
    prunedEdges = l.values()
    prunedVertices = l.keys()
    Tr = nx.Graph()
    Tr.add_weighted_edges_from([i for i in res if i not in prunedEdges])
    Tr.add_nodes_from([i for i in totalVs if i not in prunedVertices])
    avgAll = average_pairwise_distance_fast(Tr)
    return (prunedEdges, prunedVertices, avgAll)
Exemple #9
0
 def heuristic(edge):
     if edge[0] == edge[1]: return float('inf')
     T_copy = nx.Graph(T)
     T_copy.add_edge(edge[0], edge[1], weight=edge[2].get('weight', 1))
     T_copy.add_node(edge[0])
     T_copy.add_node(edge[1])
     if not nx.is_tree(T_copy): return float('inf')
     return average_pairwise_distance_fast(T_copy)
def brute_force(G, id):
    edges = list(G.edges)
    for i in range(1, len(edges)):
        print(i)
        lst = list(combinations(edges, i))
        print(len(lst))
        for edge_group in lst:
            T = nx.Graph()
            for edge in edge_group:
                T.add_edge(edge[0],
                           edge[1],
                           weight=G.get_edge_data(edge[0], edge[1])['weight'])
            if is_valid_network(
                    G,
                    T) and average_pairwise_distance_fast(T) < best_scores[id]:
                print(average_pairwise_distance_fast(T))
                update_best_graph(T, id, 'brute_force')
Exemple #11
0
def dijkstra_two_solve(G, params=DEFAULT_PARAMS, k=2, all_trees=False):
    """
	Wrapper method that generats solutions using dijkstra_two
	Args:
		G: nx.Graph()
		params: allows Dijkstras to account for several properties of edges
		k: tries upto k source vertices if k distinct vertices exist
		all_trees: Flags whether to return best tree or all of them
	Returns:
		If all_trees, then it returns an array of all the generated trees.
		Else, it returns the single best shortest path tree.
	"""
    n = len(G.nodes())
    k = min(n, k)
    #Trivial cases that otherwise error
    if n == 1:
        return G
    elif n == 2:
        T = nx.Graph()
        T.add_node(0)
        return T
    #Uses dijkstras to find metric closure distances
    D = [[0 for u in G.nodes()] for v in G.nodes()]
    all_paths_iter = nx.all_pairs_dijkstra(G)
    for u, (distance, path) in all_paths_iter:
        for v in distance:
            D[u][v] = distance[v]
    avgD = [mean(d) for d in D]
    starts = sorted(G.nodes(), key=lambda v: avgD[v])[0:k]
    if all_trees:
        Trees = []
        for s in starts:
            T = dijkstra_two(G, s, D=D, params=params)
            cost = average_pairwise_distance_fast(T)
            Trees.append(T)
        return Trees
    else:
        minval, mintree = 1000000, None
        for s in starts:
            T = dijkstra_two(G, s, D=D, params=params)
            cost = average_pairwise_distance_fast(T)
            if cost < minval:
                minval = cost
                mintree = T
        return mintree
Exemple #12
0
def scorer(filename):
    input = INPUT_PATH + filename
    print(input)
    out_filename = filename.split('.')[0] + '.out'
    print(OUTPUT_PATH + out_filename)
    if os.path.isfile(OUTPUT_PATH + out_filename):
        output_graph = read_output_file(OUTPUT_PATH + out_filename,
                                        read_input_file(input))
        print(average_pairwise_distance_fast(output_graph))
Exemple #13
0
def remove_leaves(G, tree):
    all_leaves = []
    new_leaves = find_new_leaves(tree, [], all_leaves)
    for leaf in new_leaves:
        cost_with_leaf = average_pairwise_distance_fast(tree)
        for neighbor in tree.neighbors(leaf):
            neighbor_leaf = neighbor
        tree.remove_node(leaf)
        cost_without_leaf = average_pairwise_distance_fast(tree)
        if (nx.is_dominating_set(G, tree.nodes())):
            if cost_with_leaf <= cost_without_leaf:
                edge_weight = G[neighbor_leaf][leaf]['weight']
                tree.add_edge(neighbor_leaf, leaf, weight=edge_weight)
        else:
            edge_weight = G[neighbor_leaf][leaf]['weight']
            tree.add_edge(leaf, neighbor_leaf, weight=edge_weight)
        new_leaves.remove(leaf)
        new_leaves = find_new_leaves(tree, new_leaves, all_leaves)
    return tree
Exemple #14
0
def solveTree(G):
    """ solve for tree 
    - evaluating whether a leaf is worth adding to T
    
    """
    nonleaf = [v for v in G.nodes() if G.degree[v] > 1]
    T = G.subgraph(nonleaf).copy()
    avg = average_pairwise_distance_fast(T)
    leafs = [v for v in G.nodes() if G.degree[v] == 1]
    for v in leafs:
        u = G.neighbors(v)
        weight = G.get_edge_data(v, u, default=0)
        if weight < avg and weight != 0:
            T.add_node(v)
            tempAvg = average_pairwise_distance_fast(T)
            if tempAvg > avgv:
                T.remove_node(v)
            else:
                avg = tempAvg
    return T
Exemple #15
0
def simulatedAnnealing(G):
    vertices = list(G.nodes)
    edges = list(G.edges.data('weight'))
    #generating random start vertex
    v = vertices[random.randint(0,len(vertices) - 1)]
    #starting our current tree with start vertex
    solution_T = nx.Graph()
    solution_T.add_node(v)

    curr_pairwise_dist = float("inf")
    totalTimeSteps = 10000

    # timesteps > 0 or until we've added all the vertices to the tree
    while (totalTimeSteps > 0  or len(list(solution_T.nodes)) < len(vertices)):
        # getting the minimum outgoing edge
        #outgoing_Edges = {4: {'weight': 25.643}, 1: {'weight': 54.048}}
        outgoing_edges = [(n, nbrdict) for n, nbrdict in G.adjacency() if n == v][0][1]
        degree_One = ()
        #outgoing_Edges = {(0,4):  25.643, (0,1): 54.048}
        outgoing_edges = {(v,x):y['weight'] for x,y in outgoing_edges.items()}
        #min_edge = (0,4)
        min_edge = min(outgoing_edges.keys(), key=(lambda k: outgoing_edges[k]))
        #(min_edge, outgoing_edges[min_edge]) = ((0,4), 25)
        min_edge = (min_edge, outgoing_edges[min_edge])
        # end vertex of min edge
        u = min_edge[0][1]

        temp = solution_T.copy()
        print(totalTimeSteps)
        print(list(temp.edges))
        temp.add_node(u)
        temp.add_edge(v, u, weight=min_edge[1])
        print(list(temp.edges))
        temp_pairwise_distance = average_pairwise_distance_fast(temp)

        if(temp_pairwise_distance < curr_pairwise_dist or ):
            try:
                nx.find_cycle(temp)
            except:
                solution_T.add_node(u)
                solution_T.add_edge(v, u, weight=min_edge[1])
                v = u
                curr_pairwise_dist = temp_pairwise_distance
        elif(math.exp((curr_pairwise_dist - temp_pairwise_distance) / totalTimeSteps) < random.uniform(0,1)):
            try:
                nx.find_cycle(temp)
            except:
                solution_T.add_node(u)
                solution_T.add_edge(v, u, weight=min_edge[1])
                v = u
                curr_pairwise_dist = temp_pairwise_distance

        totalTimeSteps *= 1-(0.003);
    return solution_T
Exemple #16
0
def heuristic_avg_cost(params):
    """
	Loss function of average cost over training graphs.
	"""
    total_cost, count = 0, 0
    for input in os.listdir('training/'):
        G = read_input_file('training/' + input)
        T = dijkstra_two_solve(G, [p1, p2, p3, p4])
        assert is_valid_network(G, T)
        total_cost += average_pairwise_distance_fast(T)
        count += 1
    return total_cost / count
Exemple #17
0
def removeLeaves2(leaves, MST, G):
    """Remove leaves in LEAVES from an MST until MST is no 
    longer a dominating set of G AND the average pairwise 
    distance is decreased."""
    num_removed_leaves = 0
    impt_vertices = []
    for leaf in leaves:
        if (leaf and list(MST.edges(leaf, data='weight'))):
            e = list(MST.edges(leaf, data='weight'))[0]
            cost = average_pairwise_distance_fast(MST)
            #Test removing an edge and finding new avg pairwise dist. 
            MST.remove_node(leaf)
            new_cost = average_pairwise_distance_fast(MST)
            if (new_cost > cost or not nx.is_dominating_set(G, MST.nodes)):
                #Put the leaf node and edge back. 
                MST.add_node(leaf)
                MST.add_edge(e[0], e[1], weight=e[2])
                #print("Leaf kept")
                impt_vertices.append(leaf)
            else:
                num_removed_leaves += 1
    return MST, impt_vertices, num_removed_leaves
Exemple #18
0
def prune_leaves_cost(leaves, min_tree):
    removed = 0
    kept_leaves = []
    for leaf in leaves:
        if (leaf):
            e = list(min_tree.edges(leaf, data='weight'))[0]
            #print("leaf: " + str(leaf))
            #print("leaf edge: " + str(e))
            cost = average_pairwise_distance_fast(min_tree)
            min_tree.remove_node(leaf)
            new_cost = average_pairwise_distance_fast(min_tree)
            if (new_cost > cost
                    or not nx.is_dominating_set(G, min_tree.nodes)):
                min_tree.add_node(leaf)
                min_tree.add_edge(e[0], e[1], weight=e[2])
                #print("Leaf kept")
                kept_leaves.append(leaf)
            else:
                removed += 1
    #if (removed):
    #print("(Cost) We removed " + str(removed) + " leaves in this iter")
    return min_tree, kept_leaves, removed
Exemple #19
0
def solve(G):
    """
    Args:
        G: networkx.Graph

    Returns:
        T: networkx.Graph
    """
    pq = []
    for e in G.edges:
        heappush(pq, (-G.edges[e]['weight'], e))
    
    T = copy.deepcopy(G)
    print(T == G)
    print(type(T))
    costpq = []
    
    while pq:
        node = heappop(pq)
        e = node[1]
        print(e)
        w = node[0]
        T.remove_edge(e[0], e[1])
        if T.degree(e[1]) == 0:
            T.remove_node(e[1])
        if T.degree(e[0]) == 0:
            T.remove_node(e[0])
        # print("CONNECT")
        # print()
        if nx.is_connected(T) and nx.is_dominating_set(G, T):
            print("SDFSDF")
            if nx.is_tree(T):
                heappush(costpq, (average_pairwise_distance_fast(T), T))
                cost = average_pairwise_distance_fast(T)
        else:
            T.add_edge(e[0], e[1], weight=w)
    # return 0
    return heappop(costpq)[0]
Exemple #20
0
def makeAllOutputFiles():
    for file in os.listdir("inputs"):
        if file.endswith(".in"):
            print(os.path.join("inputs", file))  #input file
            input_path = os.path.join("inputs", file)
            G = read_input_file(input_path)
            try:
                T = solve(G)
            except:
                print("ERRORED OUT. CONTINUE ANYWAY")
                T = G
            assert is_valid_network(G, T)

            #randomization optimization
            if len(T) > 2:
                print("Trying randomization to find better result..")
                try:
                    betterT = maes_randomization_alg(
                        G, T, 100)  #50 iterations of randomness
                except:
                    print("ERRORED OUT. CONTINUE ANYWAY")
                    betterT = G
                assert is_valid_network(G, betterT)

                if average_pairwise_distance_fast(
                        betterT) < average_pairwise_distance_fast(T):
                    print("BETTER TREE FOUND.")
                    T = betterT
                else:
                    print("No improvements.")
                    #nothing happens

            #print("Average pairwise distance: {}".format(average_pairwise_distance_fast(T)))
            outname = os.path.splitext(file)[0] + '.out'
            output_path = os.path.join("outputs", outname)
            print(output_path + "\n")
            write_output_file(T, output_path)
            assert validate_file(output_path) == True
def random_edges(G, id):
    T = nx.Graph()
    edges = list(np.random.permutation(G.edges))
    for edge in edges:
        T.add_edge(edge[0],
                   edge[1],
                   weight=G.get_edge_data(edge[0], edge[1])['weight'])
        if not nx.is_tree(T):
            T.remove_edge(edge[0], edge[1])
        if is_valid_network(G, T):
            score = average_pairwise_distance_fast(T)
            print(score - best_scores[id])
            update_best_graph(T, id, 'random edges')
            break
Exemple #22
0
def helper(G):
	T = None
	if G.size() == len(G) - 1:
		all_nodes = G.nodes()
		T = G.copy()
		for n in all_nodes():
			cost = average_pairwise_distance_fast(G)
			if G.degree(n) == 1:
				original_graph = T.copy()
				T.remove_node(n)
				temp_cost = average_pairwise_distance_fast(T)
				if temp_cost > cost:
					T = original_graph
				else:
					cost = temp_cost
	el = list(G.edges)
	el.sort()
	if el == [(0, 2), (1, 3), (1, 4), (2, 1), (2, 3)]:
		T = G.copy()
		T.remove_node(0)
		T.remove_node(4)
		T.remove_node(3)
		# all_nodes = G.nodes
		# for n in all_nodes():
		# 	cost = average_pairwise_distance_fast(G)
		# 	if G.degree(n) == 1 or G.degree(n) == 2:
		# 		original_graph = T.copy()
		# 		T.remove_node(n)
		# 		temp_cost =average_pairwise_distance_fast(T)
		# 		if temp_cost > cost:
		# 			T = original_graph
		# 		else:
		# 			cost = temp_cost
	if T is not None and is_valid_network(G, T):
		return T
	else:
		return None
Exemple #23
0
def prune(T, G, leaves):
    score = average_pairwise_distance_fast(T)

    while leaves:
        l = leaves.popleft()
        parent = list(T.neighbors(l))[0]
        edge_weight = T.get_edge_data(parent, l)['weight']
        T.remove_node(l)
        if nx.is_dominating_set(G, T.nodes):
            new_score = average_pairwise_distance_fast(T)
            p = np.random.random()
            if new_score > score and p > 0.5:
                T.add_node(l)
                T.add_edge(l, parent, weight=edge_weight)
            else:
                score = new_score
                #append new leaves
                if T.degree(parent) == 1:
                    leaves.append(parent)
        else:
            T.add_node(l)
            T.add_edge(l, parent, weight=edge_weight)

    return T
Exemple #24
0
    def _search(self, steps):
        """
        Performs one iteration of local search and returns a possible T.
        """
        self._start()
        transitions = 0
        for i in range(steps):
            neighbors = [
                n for n in self._neighbors()
                if len(n.nodes) > 0 and is_valid_network(self.graph, n)
            ]

            if neighbors == []:
                continue
            else:
                neighbor = min(neighbors, key=average_pairwise_distance_fast)

            # If the neighbor is invalid, ignore it.
            if neighbor.nodes and is_valid_network(self.graph, neighbor):
                f = average_pairwise_distance_fast(self.network)
                f_p = average_pairwise_distance_fast(neighbor)

                delta = f_p - f
                prob = self._prob_sched(transitions + 1, delta)

                # Transition?
                if delta < 0:
                    # print(f_p)
                    transitions += 1
                    self.network = neighbor
                elif np.random.random() <= prob:
                    # print(f_p, prob)
                    transitions += 1
                    self.network = neighbor

        return self.network
def heuristics(G):
    """
    :param G: Given a graph G
    :return: the estimated cost of choosing each vertex.
    """
    res = []
    degree = G.degree()
    deg_para = 10000 / G.number_of_edges()
    wei_para = -100 / average_pairwise_distance_fast(G)
    for i in range(0, G.number_of_nodes()):
        total_weight = 0
        for neighbour in G.neighbors(i):
            total_weight += G.get_edge_data(i, neighbour).get('weight')
        res.append(deg_para * degree[i] + wei_para * total_weight)
    return res
Exemple #26
0
    def scout(self, init: bool = False) -> None:
        # has some chance to use best SPT
        if not init and random.random() < SPT_RATE:
            init = True
        self.solution = randomDominatingTree(self.G, init=init)
        self.unimprovedTimes = 0
        if len(self.solution) == 1:
            self.currentCost = 0
        else:
            self.currentCost = average_pairwise_distance_fast(self.solution)
        self.leaves = []

        # find leaves in the tree
        for v in self.solution.nodes:
            if len(self.solution[v]) == 1:
                self.leaves.append(v)
Exemple #27
0
def solve(G):
    """
    Args:
        G: networkx.Graph

    Returns:
        T: networkx.Graph + the algorithm used to produce it.
    """
    # Base Case: If no edges, we return the graph itself.
    if len(G.edges()) == 0:
        return G, None, 0
    #Algorithm Candidate 1: Cut ALL Leaf Nodes off MST. 
    pruned_MST1 = alg1(G)
    #Algorithm Candidate 2: Cut ALL Leaf Nodes off MST by edge weight consideration.
    pruned_MST2 = alg2(G)
    # Algorithm Candidate 3: Dominating Set Weight3
    DS_MST3 = alg3(G, 3)
    # Algorithm Candidate 4: Dominating Set Weight1
    DS_MST1 = alg3(G, 1)
    # Algorithm Candidate 5: Dominating Set Weight2
    DS_MST2 = alg3(G, 2)
    # # Algorithm Candidate 5: Dominating Set Weight0
    # DS_MST0 = alg3(G, 0)
    DS_MST4 = alg4(G)


    # Print out results: Attach name of algorithm with distance and the subgraph. 

    if DS_MST1:
        dsMST1 = ["Dominating Set MST 1", average_pairwise_distance_fast(DS_MST1), DS_MST1]
    else:
        dsMST1 = ['none', float('inf'), None]
    if DS_MST2:
        dsMST2 = ["Dominating Set MST 2", average_pairwise_distance_fast(DS_MST2), DS_MST2]
    else:
        dsMST2 = ['none', float('inf'), None]
    if DS_MST3:
        dsMST3 = ["Dominating Set MST 3", average_pairwise_distance_fast(DS_MST3), DS_MST3]
    else:
        dsMST3 = ['none', float('inf'), None]
    if DS_MST4:
        dsMST4 = ["Dominating Set MST 4", average_pairwise_distance_fast(DS_MST4), DS_MST4]
    else:
        dsMST4 = ['none', float('inf'), None]

    mst1 = ["Pruned MST 1", average_pairwise_distance_fast(pruned_MST1), pruned_MST1]
    mst2 = ["Pruned MST 2", average_pairwise_distance_fast(pruned_MST2), pruned_MST2]
 
    best_algorithm = min([dsMST1, dsMST2, dsMST3, dsMST4, mst1, mst2], key=lambda x: x[1])#Find best algorithm by minkey on avg pairwise dist.
    best_alg_name = best_algorithm[0]
    best_alg_avg_dist = best_algorithm[1]
    best_alg_avg_subgraph = best_algorithm[2]
    #print(best_alg_name + 'optimal')
    #Return optimal subgraph + name of producing algorithm 
    return best_alg_avg_subgraph, best_alg_name, best_alg_avg_dist
Exemple #28
0
def greedy(G, weight='weight'):
    from random import choice

    T = G.__class__()
    if len(G) == 1:
        return G
    node = choice(list(G.nodes()))
    next_edges = list(G.edges(node, data=True))
    T.add_node(node)

    def heuristic(edge):
        if edge[0] == edge[1]: return float('inf')
        T_copy = nx.Graph(T)
        T_copy.add_edge(edge[0], edge[1], weight=edge[2].get('weight', 1))
        T_copy.add_node(edge[0])
        T_copy.add_node(edge[1])
        if not nx.is_tree(T_copy): return float('inf')
        return average_pairwise_distance_fast(T_copy)

    while True:
        curr_avg = average_pairwise_distance_fast(T)
        min_edge = min(next_edges, key=heuristic)
        min_new_avg = heuristic(min_edge)
        if is_valid_network(G, T) and min_new_avg > curr_avg:
            break
        else:
            if T.has_node(min_edge[0]):
                T.add_node(min_edge[1])
                T.add_edge(min_edge[0],
                           min_edge[1],
                           weight=min_edge[2].get('weight', 1))
                next_edges = next_edges + (list(G.edges(min_edge[1],
                                                        data=True)))
            elif T.has_node(min_edge[1]):
                T.add_node(min_edge[0])
                T.add_edge(min_edge[0],
                           min_edge[1],
                           weight=min_edge[2].get('weight', 1))
                next_edges = next_edges + (list(G.edges(min_edge[0],
                                                        data=True)))
            next_edges = list(
                filter(
                    lambda e: not (e[0] == min_edge[0] and e[1] == min_edge[1])
                    and not (e[0] == min_edge[1] and e[1] == min_edge[0]),
                    next_edges))

    return T
Exemple #29
0
 def pick_leaves_helper(G, T, edges, i):
     if not utils.is_valid_network(G, T):
         return float("inf"), []
     leafset = set(leaf for leaf, neighbor in edges)
     new_leaf_edges = [(n, list(T[n])[0]) for n in T.nodes
                       if n not in leafset and len(T[n]) == 1]
     edges = edges + new_leaf_edges
     cost, nodes_to_remove = utils.average_pairwise_distance_fast(T), []
     for k in range(i, len(edges)):
         leaf, neighbor = edges[k]
         w = T[leaf][neighbor]['weight']
         T.remove_node(leaf)
         new_cost, additional_nodes = pick_leaves_helper(G, T, edges, k + 1)
         if new_cost < cost:
             cost, nodes_to_remove = new_cost, [leaf] + additional_nodes
         T.add_edge(leaf, neighbor, weight=w)
     return cost, nodes_to_remove
Exemple #30
0
def solve(G):
    """
    Args:
        G: networkx.Graph

    Returns:
        T: networkx.Graph
    """
    #hard code methods
    #greedy2
    #greedy2_more_edges (only small and median)
    #trimMST
    #ds_spt

    #compute the cost only if not none

    min_cost = float('inf')
    min_tree = None

    tree_greedy1 = solver_greedy1.solve(G)
    if average_pairwise_distance_fast(tree_greedy1) < min_cost:
        min_cost = average_pairwise_distance_fast(tree_greedy1)
        min_tree = tree_greedy1

    if (nx.number_of_nodes(G) == 25 or nx.number_of_nodes(G) == 50):
        tree_greedy2 = solver_greedy2.solve(G)
        if average_pairwise_distance_fast(tree_greedy2) < min_cost:
            min_cost = average_pairwise_distance_fast(tree_greedy2)
            min_tree = tree_greedy2

    tree_mst = solver_mst.solve(G)
    if average_pairwise_distance_fast(tree_mst) < min_cost:
        min_cost = average_pairwise_distance_fast(tree_mst)
        min_tree = tree_mst

    tree_spt = solver_spt.solve(G)
    if average_pairwise_distance_fast(tree_spt) < min_cost:
        min_cost = average_pairwise_distance_fast(tree_spt)
        min_tree = tree_spt

    return min_tree