def test(adj_mat, elapsed_time, i): G = ntx.Graph(adj_mat) ntx.draw_networkx(G, pos=ntx.kamada_kawai_layout(G), node_size=50, with_labels=True, font_size=4, width=0.5) plt.savefig("graph"+i+".png", dpi=1000, quality=95) plt.show() t0 = time.perf_counter() ntx.floyd_warshall(G) elapsed_time[0].append(time.perf_counter() - t0) t0 = time.perf_counter() ntx.johnson(G) elapsed_time[1].append(time.perf_counter() - t0) print("finished_test") return elapsed_time
def test_negative_weights(self): G = nx.DiGraph() G.add_weighted_edges_from([('0', '3', 3), ('0', '1', -5), ('0', '2', 2), ('1', '2', 4), ('2', '3', 1)]) paths = nx.johnson(G) assert_equal( paths, { '1': { '1': ['1'], '3': ['1', '2', '3'], '2': ['1', '2'] }, '0': { '1': ['0', '1'], '0': ['0'], '3': ['0', '1', '2', '3'], '2': ['0', '1', '2'] }, '3': { '3': ['3'] }, '2': { '3': ['2', '3'], '2': ['2'] } }) paths = nx.johnson(G, new_weight='new_weight') assert_equal( paths, { '1': { '1': ['1'], '3': ['1', '2', '3'], '2': ['1', '2'] }, '0': { '1': ['0', '1'], '0': ['0'], '3': ['0', '1', '2', '3'], '2': ['0', '1', '2'] }, '3': { '3': ['3'] }, '2': { '3': ['2', '3'], '2': ['2'] } }) for u, v, w in G.edges(data=True): assert_true('new_weight' in w)
def test_negative_weights(self): G = nx.DiGraph() G.add_weighted_edges_from([("0", "3", 3), ("0", "1", -5), ("0", "2", 2), ("1", "2", 4), ("2", "3", 1)]) paths = nx.johnson(G) assert paths == { "1": { "1": ["1"], "3": ["1", "2", "3"], "2": ["1", "2"] }, "0": { "1": ["0", "1"], "0": ["0"], "3": ["0", "1", "2", "3"], "2": ["0", "1", "2"], }, "3": { "3": ["3"] }, "2": { "3": ["2", "3"], "2": ["2"] }, }
def shortest_paths(networkx_network): """ finds the all pairs shortest paths using Johnson Algo sets a dictionary, keyed by source and target, of all pairs shortest paths with path_delays in the network as an attr. key: (src, dest) , value: ([nodes_on_the_shortest_path], path_delay) path delays are the sum of individual edge_delays of the edges in the shortest path from source to destination """ # in-built implementation of Johnson Algo, just returns a list of shortest paths # returns a dict with : key: source, value: dict with key: dest and value: shortest path as list of nodes all_pair_shortest_paths = dict( nx.johnson(networkx_network, weight='weight')) # contains shortest paths with path_delays # key: (src, dest) , value: ([nodes_on_the_shortest_path], path_delay) shortest_paths_with_delays = {} for source, v in all_pair_shortest_paths.items(): for destination, shortest_path_list in v.items(): path_delay = 0 # only if the source and destination are different, path_delays need to be calculated, otherwise 0 if source != destination: # shortest_path_list only contains ordered nodes [node1,node2,node3....] in the shortest path # here we take ordered pair of nodes (src, dest) to cal. the path_delay of the edge between them for i in range(len(shortest_path_list) - 1): path_delay += networkx_network[shortest_path_list[i]][ shortest_path_list[i + 1]]['delay'] shortest_paths_with_delays[(source, destination)] = (shortest_path_list, path_delay) networkx_network.graph['shortest_paths'] = shortest_paths_with_delays
def test_negative_weights(self): G = nx.DiGraph() G.add_weighted_edges_from([('0', '3', 3), ('0', '1', -5), ('0', '2', 2), ('1', '2', 4), ('2', '3', 1)]) paths = nx.johnson(G) assert_equal( paths, { '1': { '1': ['1'], '3': ['1', '2', '3'], '2': ['1', '2'] }, '0': { '1': ['0', '1'], '0': ['0'], '3': ['0', '1', '2', '3'], '2': ['0', '1', '2'] }, '3': { '3': ['3'] }, '2': { '3': ['2', '3'], '2': ['2'] } })
def constraint_correct(G, C, P, w0): path = nx.johnson( G, weight='weight') # or nx.all_pairs_dijkstra_path_length(G) C_max_dist = 0 for i in range(1, len(P) + 1): if (i in C): continue else: min_dist = 1000 * 1000 min_idx = 0 for j in C: cur_dist = 0 for k in range(len(path[i][j]) - 1): cur_dist += G[path[i][j][k]][path[i][j][k + 1]]['weight'] if (cur_dist < min_dist): min_dist = cur_dist min_idx = j if (C_max_dist < min_dist): C_max_dist = min_dist C_max_v = (i, min_idx) max_path = path[C_max_v[0]][C_max_v[1]] max_edges = [] for i in range(len(max_path) - 1): max_edges.append([max_path[i], max_path[i + 1]]) if C_max_dist > w0: return False, max_edges else: return True, max_edges
def get_makespan(self): import networkx as nx G = nx.DiGraph() edg = tuple(set(unfold(self.A)) | set(unfold(self.E))) edg_weighted = [(x[0], x[1], -self.getD(x[0])) for x in edg] G.add_weighted_edges_from(edg_weighted) s = nx.johnson(G, weight='weight')[-1][self.N - 2] return sum([self.getD(x) for x in s])
def test_negative_weights(self): G = nx.DiGraph() G.add_weighted_edges_from([('0', '3', 3), ('0', '1', -5), ('0', '2', 2), ('1', '2', 4), ('2', '3', 1)]) paths = nx.johnson(G) assert_equal(paths, {'1': {'1': ['1'], '3': ['1', '2', '3'], '2': ['1', '2']}, '0': {'1': ['0', '1'], '0': ['0'], '3': ['0', '1', '2', '3'], '2': ['0', '1', '2']}, '3': {'3': ['3']}, '2': {'3': ['2', '3'], '2': ['2']}}) paths = nx.johnson(G, new_weight='new_weight') assert_equal(paths, {'1': {'1': ['1'], '3': ['1', '2', '3'], '2': ['1', '2']}, '0': {'1': ['0', '1'], '0': ['0'], '3': ['0', '1', '2', '3'], '2': ['0', '1', '2']}, '3': {'3': ['3']}, '2': {'3': ['2', '3'], '2': ['2']}}) for u, v, w in G.edges(data=True): assert_true('new_weight' in w)
def test_negative_weights(self): G = nx.DiGraph() G.add_weighted_edges_from([('0', '3', 3), ('0', '1', -5), ('0', '2', 2), ('1', '2', 4), ('2', '3', 1)]) paths = nx.johnson(G) assert_equal(paths, {'1': {'1': ['1'], '3': ['1', '2', '3'], '2': ['1', '2']}, '0': {'1': ['0', '1'], '0': ['0'], '3': ['0', '1', '2', '3'], '2': ['0', '1', '2']}, '3': {'3': ['3']}, '2': {'3': ['2', '3'], '2': ['2']}})
def test_graphs(self): validate_path(self.XG, 's', 'v', 9, nx.johnson(self.XG)['s']['v']) validate_path(self.MXG, 's', 'v', 9, nx.johnson(self.MXG)['s']['v']) validate_path(self.XG2, 1, 3, 4, nx.johnson(self.XG2)[1][3]) validate_path(self.XG3, 0, 3, 15, nx.johnson(self.XG3)[0][3]) validate_path(self.XG4, 0, 2, 4, nx.johnson(self.XG4)[0][2]) validate_path(self.MXG4, 0, 2, 4, nx.johnson(self.MXG4)[0][2])
def test_graphs(self): validate_path(self.XG, "s", "v", 9, nx.johnson(self.XG)["s"]["v"]) validate_path(self.MXG, "s", "v", 9, nx.johnson(self.MXG)["s"]["v"]) validate_path(self.XG2, 1, 3, 4, nx.johnson(self.XG2)[1][3]) validate_path(self.XG3, 0, 3, 15, nx.johnson(self.XG3)[0][3]) validate_path(self.XG4, 0, 2, 4, nx.johnson(self.XG4)[0][2]) validate_path(self.MXG4, 0, 2, 4, nx.johnson(self.MXG4)[0][2])
def test_unweighted_graph(self): with pytest.raises(nx.NetworkXError): G = nx.path_graph(5) nx.johnson(G)
def test_single_node_graph(self): with pytest.raises(nx.NetworkXError): G = nx.DiGraph() G.add_node(0) nx.johnson(G)
def fast_price_function(g, e, proportional, algorithm='johnson'): """ Fast function to find the optimal price for a given edge e. 1. Calculate the shortest path from all-to-all vertices without going through $C$ with either Floyd-Warshall or Johnson. Default is Johnson 2. Calculate shortest path from $C$ source to all explicitly going through $C$ with Dijkstra. 3. Compare difference between all-to-all cost with all-to-$V$-to-all, producing a cumulative summation over the difference. 4. Maximizing fee * cumulative difference. Plots the given fee * cumulative difference over fee curve. """ e_data = g.get_edge_data(e[0][0], e[0][1]) # Remove edge e g.remove_edge(e[0][0], e[0][1]) # Floyd or Johnson if algorithm == 'johnson': all_pair_shortest_path = nx.floyd_warshall(g, weight="price") else: all_pair_shortest_path = nx.johnson(g, weight="price") # remove all edges from e source, Add edge e edges = list(g.out_edges(e[0][0])) # get all edges of source edges_data = [] for rm in edges: edges_data.append(g.get_edge_data(rm[0], rm[1])) g.remove_edge(rm[0], rm[1]) temp_price = e_data["price"] e_data["price"] = proportional g.add_edge(e[0][0], e[0][1], **e_data) # Compute single source dijkstras from e source over e. edge_to_all = nx.single_source_dijkstra_path_length(g, e[0][0], weight="price") path_price_difference = [] for source in all_pair_shortest_path: for destination in all_pair_shortest_path[source]: # SOURCE TO V TO DESTINATION if source != destination != e[0][0]: #print("-----") #print(source) #print(destination) #print(all_pair_shortest_path[source][destination]) diff = (all_pair_shortest_path[source][e[0][0]] + edge_to_all[destination] ) - all_pair_shortest_path[source][destination] if diff < 0: # TODO: WHAT TO DO WITH TIES? path_price_difference.append(-diff) fee_range = range(10, 1350, 10) plot_list = [] e_data["price"] = temp_price for i, add in enumerate(edges): g.add_edge(add[0], add[1], **edges_data[i]) for r in fee_range: plot_list.append( len([p for p in path_price_difference if p >= r]) * r * proportional / 1000) #plot.plot_fee_curve(fee_range, plot_list) return plot_list
def test_unweighted_graph(self): G = nx.path_graph(5) nx.johnson(G)
def johnson(G, source, destination): return " -> ".join(nx.johnson(G)[source][destination])
def optimize(self): start_time = time.time() try: for s_idx, s_session in enumerate(self.sessions): session_start_time = time.time() tree = self._solution.get_tree(s_session) print "curr", s_idx #################################################################################### # # Algorithm 1 The construction of multilevel overlay directed network # #################################################################################### copy_graph = self.graph.copy() # Remove edge with insufficient residual capacity for link_id in set(self.app.links.items()) & set( copy_graph.edges()): if self.links[link_id].cap - ( self.links[link_id].used_cap + self.sessions[s_idx].bw) < 0: copy_graph.remove_edge(link_id[0], link_id[1]) # Calculate all shortest paths between each pair nodes in G apsp_length = dict( nx.all_pairs_dijkstra_path_length(copy_graph, weight='BandwidthCost')) apsp_path = nx.johnson(copy_graph, weight='BandwidthCost') # check if dst is reachable # Remove session which cannot reach to every destination try: if set(self.sessions[s_idx].dsts) - set( apsp_path[self.sessions[s_idx].src]): raise ResourceOverloaded except ResourceOverloaded: print "ResourceOverloaded!!!!!!!!!!!!!!" continue # Replicate all |V|=n nodes k times and place n*k nodes in a n x k grid, Each node can be denoted by v_n_k # Connect all nodes in i-th column to all nodes in i+1-th column with directed arrows # Set the edge cost between two nodes as the corresponding shortest path cost in G multilevel_graph = nx.DiGraph() for i, service in enumerate(self.service_chains[s_idx][:-1]): for head in self.service_nodes[service]: for tail in self.service_nodes[ self.service_chains[s_idx][i + 1]]: cost = apsp_length[head][tail] multilevel_graph.add_edge( str(service) + "_" + str(head), str(self.service_chains[s_idx][i + 1]) + "_" + str(tail), weight=cost) #################################################################################### # # Algorithm 2 The Modified Shortest-Path Algorithm (MSA) # #################################################################################### if len(self.service_chains[s_idx]) == 0: st = steiner_tree(copy_graph, [self.sessions[s_idx].src] + list(self.sessions[s_idx].dsts), weight='BandwidthCost') # Convert steiner_tree into directed graph s_tree = nx.DiGraph() for dst in self.sessions[s_idx].dsts: s_tree.add_edge(dst, "sink", weight=0) for h, t in st: s_tree.add_edge( t, h, weight=copy_graph[t][h]['BandwidthCost'] * self.sessions[s_idx].bw) st_edges = set() for path in nx.all_simple_paths( s_tree.to_undirected(), source=self.sessions[s_idx].src, target="sink"): for idx in range(len(path) - 2): st_edges.add((path[idx], path[idx + 1])) self._solution.add_path(self.sessions[s_idx], path[:-1], None) memo = defaultdict(float) # Update link usage try: for h, t in st_edges: self.links[(h, t)].used_cap += self.sessions[ s_idx].bw * self.links[(h, t)].bw_cost memo[(h, t)] += self.sessions[s_idx].bw * self.links[ (h, t)].bw_cost self.total_routing_cost += self.sessions[ s_idx].bw * self.links[(h, t)].bw_cost if self.links[(h, t)].used_cap > self.links[( h, t)].cap: raise ResourceOverloaded except ResourceOverloaded: print "ResourceOverloaded!!!!!!!!!!!!!!" for link_id, v in memo.items(): self.links[link_id].used_cap -= v continue curr_time = time.time() - session_start_time self.update_session_cost(solution=self._solution, session=self.sessions[s_idx], links=st_edges, time=curr_time) self.solution_tree[s_idx] = s_tree self.session_completed += 1 continue # Divide each nodes in G' into two parts, and connect theses two parts with cost y_l_k_u for service in self.service_chains[s_idx]: for node in self.service_nodes[service]: fst_half, snd_half = str(service) + "_" + str( node), '_' + str(service) + "_" + str(node) for h, t in list(multilevel_graph.out_edges(fst_half)): multilevel_graph.add_edge( snd_half, t, weight=multilevel_graph[h][t]['weight']) multilevel_graph.remove_edge(h, t) multilevel_graph.add_edge( fst_half, snd_half, weight=self.sessions[s_idx].res[service]['cpu']) # Add the source node S into G' # Connect S to all nodes of the first column in G' and set the cost as corresponding shortest path first_service = self.service_chains[s_idx][0] for tail in self.service_nodes[first_service]: multilevel_graph.add_edge( self.sessions[s_idx].src, str(first_service) + "_" + str(tail), weight=apsp_length[self.sessions[s_idx].src][tail]) feasible_solution = (float('inf'), [], []) last_service = self.service_chains[s_idx][-1] for v in self.service_nodes[last_service]: if self.nodes[v].services[last_service].resources_cap['cpu'] - \ (self.nodes[v].services[last_service].used_cap['cpu'] + self.sessions[s_idx].res[last_service]['cpu']) < 0: continue # Find the shortest path y from S to v in G' and get [w_l_n_u] last_node_v = "_" + str(last_service) + "_" + str(v) # Build a Steiner tree to cover v and all destinations st = steiner_tree(copy_graph, [v] + list(self.sessions[s_idx].dsts), weight='BandwidthCost') # Convert steiner_tree into directed graph s_tree = nx.DiGraph() s_tree_path = set() for dst in self.sessions[s_idx].dsts: s_tree.add_edge(dst, "sink", weight=0) for h, t in st: s_tree.add_edge( h, t, weight=copy_graph[h][t]['BandwidthCost'] * self.sessions[s_idx].bw) s_tree.add_edge( t, h, weight=copy_graph[t][h]['BandwidthCost'] * self.sessions[s_idx].bw) for path in nx.all_simple_paths(s_tree, source=v, target="sink"): for i, n in enumerate(path[:-2]): s_tree_path.add((n, path[i + 1])) # steiner_tree cost accum_cost = 0 for h, t in s_tree_path: accum_cost += copy_graph[h][t][ 'BandwidthCost'] * self.sessions[s_idx].bw shortest_path = nx.dijkstra_path(multilevel_graph, self.sessions[s_idx].src, last_node_v, weight='weight')[1:] candidate_solution = [self.sessions[s_idx].src] for i, service in enumerate( self.service_chains[s_idx][:-1]): # Check where l_j is deployed in an overloaded node, if so, # find a new node with the minimum sum of setup cost and connection cost to deploy l_j node = int(shortest_path[i * 2][len(str(service)) + 1:]) if self.nodes[node].services[service].resources_cap['cpu'] - \ (self.nodes[node].services[service].used_cap['cpu'] + self.sessions[s_idx].res[service]['cpu']) < 0: other_nodes_cost = [] for other_node in set( self.service_nodes[service]) - {node}: if self.nodes[other_node].services[service].resources_cap['cpu'] - \ (self.nodes[other_node].services[service].used_cap['cpu'] + self.sessions[s_idx].res[service]['cpu']) < 0: continue prev_service = "_" + self.service_chains[s_idx][i - 1] + "_" + str(candidate_solution[-1]) \ if i != 0 else candidate_solution[-1] next_service = self.service_chains[s_idx][ i + 1] + "_" + shortest_path[ (i + 1) * 2][len(str(service)) + 1:] vk = multilevel_graph[prev_service][ str(service) + "_" + str(other_node)]['weight'] vm = multilevel_graph[ "_" + str(service) + "_" + str(other_node)][next_service]['weight'] other_nodes_cost.append( (self.sessions[s_idx].res[service]['cpu'] + vk + vm, other_node)) if not other_nodes_cost: # print ">>>>>Cannot find solution!solution!!!!" break _, best_candidate = max(other_nodes_cost) candidate_solution.append(best_candidate) else: candidate_solution.append(node) candidate_solution.append(v) # add last node # Cannot find solution with v!!!!! if len(candidate_solution) < 1 + len( self.service_chains[s_idx]): continue # source to last VNF cost for i, node in enumerate(candidate_solution[:-1]): accum_cost += apsp_length[node][candidate_solution[i + 1]] if accum_cost < feasible_solution[0]: feasible_solution = (accum_cost, candidate_solution, s_tree_path) # Cannot find solution!!!!! try: if len(feasible_solution[1]) < 1 + len( self.service_chains[s_idx]): raise ResourceOverloaded except ResourceOverloaded: print "ResourceOverloaded!!!!!!!!!!!!!!" continue traversed_edges = defaultdict(int) # Build tree from feasible solution feasible_solution_tree = nx.DiGraph() for node_id, node in enumerate(feasible_solution[1][:-1]): path = nx.shortest_path( copy_graph, source=node, target=feasible_solution[1][node_id + 1], weight='BandwidthCost') for i, h in enumerate(path[:-1]): traversed_edges[(h, path[i + 1])] += 1 feasible_solution_tree.add_edge( h, path[i + 1], weight=copy_graph[h][path[i + 1]]['BandwidthCost'] * self.sessions[s_idx].bw) for h, t in feasible_solution[2]: traversed_edges[(h, t)] += 1 feasible_solution_tree.add_edge( h, t, weight=copy_graph[h][t]['BandwidthCost'] * self.sessions[s_idx].bw) #################################################################################### # # Algorithm 3 The Optimize Phase Algorithm (OPA) # #################################################################################### _, candidate_solution, s_tree_path = feasible_solution # print "self.sessions[s_idx]", self.sessions[s_idx] curr_service_node = [] for s_id, service_node in enumerate(candidate_solution[1:]): curr_service_node.append( (self.service_chains[s_idx][s_id], service_node)) # Find all connection nodes in X_0 connection_nodes = set(self.sessions[s_idx].dsts) for dst in self.sessions[s_idx].dsts: connection_nodes -= set( nx.descendants(feasible_solution_tree, dst)) for j, service in reversed( list(enumerate(self.service_chains[s_idx]))): for connection_node in list(connection_nodes): connection_nodes.remove(connection_node) for other_node in set(self.service_nodes[service]) - { connection_node }: # if l_j can be deployed in other nodes according to the rule in Section IV-C then if self.nodes[other_node].services[service].resources_cap['cpu'] - \ (self.nodes[other_node].services[service].used_cap['cpu'] + self.sessions[s_idx].res[service]['cpu']) < 0: continue old_cost = apsp_length[candidate_solution[ j + 1]][connection_node] new_cost = apsp_length[candidate_solution[j]][other_node] + \ apsp_length[other_node][connection_node] + 0 if new_cost < old_cost: curr_service_node.append((service, other_node)) # Old link from VNF to connection node old_path = apsp_path[candidate_solution[ j + 1]][connection_node] for i, t in reversed( list(enumerate(old_path[1:]))): if feasible_solution_tree.has_edge( old_path[i], t ) and feasible_solution_tree.edges( old_path[i] ) <= 1 and feasible_solution_tree.edges( t) <= 1: feasible_solution_tree.remove_edge( old_path[i], t) traversed_edges[(old_path[i], t)] -= 1 if feasible_solution_tree.has_node( old_path[i]) and len( feasible_solution_tree.edges( old_path[i])) > 1: break # New link from new VNF to connection node new_path = apsp_path[other_node][ connection_node] for i, h in enumerate(new_path[:-1]): try: feasible_solution_tree.add_edge( h, new_path[i + 1], weight=copy_graph[h][new_path[ i + 1]]['BandwidthCost'] * self.sessions[s_idx].bw) except: print "i, h", i, h for hh, tt in copy_graph.edges(): print hh, tt traversed_edges[(h, new_path[i + 1])] += 1 # New link from previous VNF to new VNF new_path = apsp_path[ candidate_solution[j]][other_node] for i, h in enumerate(new_path[:-1]): feasible_solution_tree.add_edge( h, new_path[i + 1], weight=copy_graph[h][new_path[ i + 1]]['BandwidthCost'] * self.sessions[s_idx].bw) traversed_edges[(h, new_path[i + 1])] += 1 connection_nodes.add(other_node) break # Add link from source to connection nodes for connection_node in connection_nodes: new_path = apsp_path[ self.sessions[s_idx].src][connection_node] for i, h in enumerate(new_path[:-1]): feasible_solution_tree.add_edge( h, new_path[i + 1], weight=copy_graph[h][new_path[i + 1]]['BandwidthCost'] * self.sessions[s_idx].bw) traversed_edges[(h, new_path[i + 1])] += 1 print "self.sessions[s_idx]", self.sessions[s_idx].addr memo = defaultdict(float) try: # Update service used_cap for service, node in curr_service_node: print "service, node", service, node self.nodes[node].services[service].used_cap[ 'cpu'] += self.sessions[s_idx].res[service]['cpu'] memo[service] += self.sessions[s_idx].res[service][ 'cpu'] if self.nodes[node].services[service].used_cap[ 'cpu'] > self.nodes[node].services[ service].resources_cap['cpu']: raise ResourceOverloaded except ResourceOverloaded: print "ResourceOverloaded!!!!!!!!!!!!!!" for service, v in memo.items(): node = curr_service_node[service] self.nodes[node].services[service].used_cap['cpu'] -= v continue memo = defaultdict(float) # Update link usage try: print traversed_edges.items() curr_cost = 0 sess_links = [] for l, count_link in traversed_edges.items(): for _ in range(count_link): h, t = l print h, t sess_links.append((h, t)) self.links[(h, t)].used_cap += self.sessions[ s_idx].bw * self.links[(h, t)].bw_cost memo[(h, t)] += self.sessions[s_idx].bw * self.links[ (h, t)].bw_cost if self.links[(h, t)].used_cap > self.links[( h, t)].cap: raise ResourceOverloaded curr_cost += self.sessions[s_idx].bw * self.links[ (h, t)].bw_cost self.total_routing_cost += self.sessions[ s_idx].bw * self.links[(h, t)].bw_cost print self.sessions[s_idx].addr, "curr_cost", curr_cost except ResourceOverloaded: print "ResourceOverloaded!!!!!!!!!!!!!!" for link_id, v in memo.items(): self.links[link_id].used_cap -= v continue # # Update the flow tcam # for node, num_traverse in traversed_edges.items(): # h, t = node # self.nodes[h].services['sdn_router'].used_cap['tcam'] = self.sessions[s_idx].res[service]['tcam'] * num_traverse # self.nodes[t].services['sdn_router'].used_cap['tcam'] = self.sessions[s_idx].res[service]['tcam'] * num_traverse # num_undirected_traversed_edges = defaultdict(int) # for h, t in traversed_edges.keys(): # # h, t = key # if (h, t) in num_undirected_traversed_edges or (t, h) in num_undirected_traversed_edges: # continue # num_undirected_traversed_edges[(h, t)] = traversed_edges[(h, t)] + traversed_edges[(t, h)] curr_time = time.time() - session_start_time self.update_session_cost(solution=self._solution, session=self.sessions[s_idx], links=sess_links, time=curr_time) self.session_completed += 1 except Exception as e: raise e finally: print 'All DONE:', str(self.session_completed / len(self.sessions)) total_time = time.time() - start_time print "Optimization time = ", str(total_time), " sec" self._solution.total_time = total_time return self._solution
def compute_all_pair_shortest_path(graphs_single_robot, trees_single_robot): all_pairs_shortest_paths_per_robot = [] all_pairs_shortest_paths_per_robot_b = [ dict() for i in range(len(graphs_single_robot)) ] subgraph_nodes = [0] * len(graphs_single_robot) for i in range(len(graphs_single_robot)): all_pairs_shortest_paths_per_robot.append( \ nx.johnson(graphs_single_robot[i], weight='weight')) subgraph_nodes[i] = random.sample( graphs_single_robot[i].nodes, math.ceil(len(graphs_single_robot[i].nodes) / 10)) if len( subgraph_nodes[i] ) == 1: # single_source_bellman_ford gets stuck on single node graph, so this is an edge case all_pairs_shortest_paths_per_robot_b[i][subgraph_nodes[i] [0]] = dict() all_pairs_shortest_paths_per_robot_b[i][subgraph_nodes[i][0]][ subgraph_nodes[i][0]] = [subgraph_nodes[i][0]] else: for j in range(len(subgraph_nodes[i])): all_pairs_shortest_paths_per_robot_b[i][ subgraph_nodes[i][j]] = nx.single_source_bellman_ford( graphs_single_robot[i], subgraph_nodes[i][j], target=None, weight='weight')[1] while len(all_pairs_shortest_paths_per_robot_b[i]) < len( graphs_single_robot[i].nodes): for node in list(all_pairs_shortest_paths_per_robot_b[i].keys()): N = drrt_ao.adj(graphs_single_robot[i], node) for neighbor in N: if neighbor in all_pairs_shortest_paths_per_robot_b[i]: continue else: all_pairs_shortest_paths_per_robot_b[i][ neighbor] = dict() for key in all_pairs_shortest_paths_per_robot_b[i][ node].keys(): all_pairs_shortest_paths_per_robot_b[ i][neighbor][key] = list( all_pairs_shortest_paths_per_robot_b[i] [node][key] ) # attaching copy of the list of the neighbor all_pairs_shortest_paths_per_robot_b[i][neighbor][ key].insert(0, neighbor) if key == neighbor: all_pairs_shortest_paths_per_robot_b[i][neighbor][ key] = all_pairs_shortest_paths_per_robot_b[ i][neighbor][key][:1] for i in range( len(graphs_single_robot) ): # A check to see the johnson and bellman ford dictionaries are equal for key in all_pairs_shortest_paths_per_robot[i].keys(): if key not in all_pairs_shortest_paths_per_robot_b[i]: print("check out") else: for inkey in all_pairs_shortest_paths_per_robot[i][key].keys(): if inkey not in all_pairs_shortest_paths_per_robot_b[i][ key]: print("check in") return all_pairs_shortest_paths_per_robot_b
G.add_edge(t[0] + 1, t[1] + 1, weight=euclidean(t[0], t[1])) G.add_edge(t[1] + 1, t[2] + 1, weight=euclidean(t[1], t[2])) G.add_edge(t[0] + 1, t[2] + 1, weight=euclidean(t[0], t[2])) # Cycle check for i in range(len(C) - 1): e = [C[i], C[i + 1]] if (e in G.edges()): # cycle edge on DG CE_IN.append(e) else: CE_OUT.append(e) C_length += euclidean(C[i] - 1, C[i + 1] - 1) if (len(CE_OUT) > 0): C_valid = 0 # Calculate ditance between vertices and cycle path = nx.johnson(G, weight='weight') # or nx.all_pairs_dijkstra_path_length(G) print("1. All Shortest Path (v-->cycle)") print("vertex -- cycle_vertex ==> distance [path]") for i in range(1, len(P) + 1): if (i in C): continue else: min_dist = 1000 * 1000 min_idx = 0 for j in C: cur_dist = 0 for k in range(len(path[i][j]) - 1): cur_dist += G[path[i][j][k]][path[i][j][k + 1]]['weight'] if cur_dist < min_dist: min_dist = cur_dist min_idx = j print(" ", i, "--", min_idx, "==>", round(min_dist, 3),
def all_pairs_paths(G): print "Computing all pairs paths..." paths = nx.johnson(G, weight="weight") return paths
def johnson_explored(G, source, destination): return " -> ".join(nx.johnson(G)[source])
def test_single_node_graph(self): G = nx.DiGraph() G.add_node(0) nx.johnson(G)
if eg[0] in cost_dict: if eg[1] in cost_dict[eg[0]]: eg[2]['negative_weight'] = -1 * eg[2]['weight'] idcs = np.random.choice(len(gp.nodes()), int(5 * 5 * 0.2), replace=False) # print idcs # スタート・ゴール・障害物を設定する st, gl, obs = (0, 0), (30, 60), [list(gp.nodes())[i] for i in idcs[2:]] # st, gl, obs = (0,0), (np.random.randint(g_dim[0]),np.random.randint(g_dim[1])), [list(gp.nodes())[i] for i in idcs[2:]] obs = [list(gp.nodes())[i] for i in idcs[2:]] path = nx.astar_path(gp, st, gl, cost) length = nx.astar_path_length(gp, st, gl, cost) path2 = nx.johnson(gp, weight='negative_weight') print('johnson: {0}'.format(path2[st][gl])) for p in path2[st][gl]: if gp.node[p].get('color', '') == 'black': print('Invalid path') continue gp.node[p]['color'] = 'orange' previous_nd = st longest_length = 0 for nd in path2[st][gl][:]: if not (previous_nd == st and nd == st): # longest_length += cost_dict[previous_nd][nd] longest_length += gp[previous_nd][nd]['weight'] # print ('{0}-[{1}]→{2}'.format(previous_nd,cost_dict[previous_nd][nd],nd))
def optimize(self): start_time = time.time() ############################ # Multi-Tree Routing Phase ############################ copy_graph = self.graph.copy() # Sort the multicast tress according to their data rates in ascending order self.sessions = sorted(self.app.get_sessions(), key=lambda session: session.bw) for s_idx, s_session in enumerate(self.sessions): for link_id in set(self.app.links.items()) & set( copy_graph.edges()): if self.links[link_id].cap - (self.links[link_id].used_cap + s_session.bw) < 0: copy_graph.remove_edge(link_id[0], link_id[1]) # All to All node shortest distance apsp = nx.johnson(copy_graph, weight='BandwidthCost') # Remove session which cannot reach to every destination if set(s_session.dsts) - set(apsp[s_session.src]): continue # Shortest path trees session_tree = nx.DiGraph() # DAG - multicast tree counted_link = set() for dst in s_session.dsts: for i, head_edge in enumerate( apsp[s_session.src][dst][:-1]): # path tail_edge = apsp[s_session.src][dst][i + 1] session_tree.add_edge(head_edge, tail_edge, weight=self.graph[head_edge] [tail_edge]['BandwidthCost'] * s_session.bw) # Add link usage if (head_edge, tail_edge) not in counted_link: self.links[(head_edge, tail_edge)].used_cap += s_session.bw counted_link.add((head_edge, tail_edge)) # # Add flow table self.node_capacity[head_edge] |= {s_idx} self.node_capacity[tail_edge] |= {s_idx} # Find branching nodes if len(session_tree.edges(head_edge)) > 1: self.session_branch_nodes[s_idx].add(head_edge) self.sessions_tree[s_idx] = session_tree # Try to reroute all branch node for s_idx, nodes in self.session_branch_nodes.items(): for node in list(nodes): self.reroute(s_idx, node) # self.reassess_tcam_cost() # max_tcam = 0 # for node, sessions in self.node_capacity.items(): # if len(sessions)>max_tcam: # max_tcam = len(sessions) total_c = 0 for link_id, link in self.links.items(): total_c += link.used_cap # print "max_tcam", max_tcam print "self.sessions_tree", len(self.sessions_tree) print "self.app.get_sessions()", len(self.app.get_sessions()) print 'All DONE:', len(self.app.get_sessions()) - len( self.sessions_tree) == 0 # ############################ # # State-Node Assignment Phase # ############################ # # print "State-Node Assignment Phase" # # # Greedy Assigning Stage # self.branch_state_node_sessions = defaultdict(set) # Reset sessions_branch_state_nodes # self.session_branch_state_nodes = defaultdict(set) # a = defaultdict(set) # curr__a_cost = {s_idx: self.cost_t_a(s_idx, set()) for s_idx, _ in self.sessions_tree.items()} # cost_t_a_cache = dict() # for s_idx, _ in self.sessions_tree.items(): # cost_t_a_cache[s_idx] = defaultdict(float) # # Find max x # while True: # max_x_cost, max_x_node, max_x_s_idx = -float('inf'), None, None # for s_idx, _ in self.sessions_tree.items(): # for branch_node in self.session_branch_nodes[s_idx] - a[s_idx]: # if len(self.branch_state_node_sessions[branch_node]) + 1 <= self.nodes[branch_node].services['sdn_router'].resources_cap['tcam']: # if tuple({branch_node} | a[s_idx]) not in cost_t_a_cache[s_idx]: # cost_t_a_cache[s_idx][tuple({branch_node} | a[s_idx])] = \ # self.cost_t_a(s_idx, {branch_node} | a[s_idx]) # reduced_cost = curr__a_cost[s_idx] - cost_t_a_cache[s_idx][tuple({branch_node} | a[s_idx])] # if reduced_cost > max_x_cost: # max_x_cost, max_x_node, max_x_s_idx = reduced_cost, branch_node, s_idx # # if max_x_cost == -float('inf'): # break # a[max_x_s_idx].add(max_x_node) # AU{x} # curr__a_cost[max_x_s_idx] -= max_x_cost # z(A) # self.branch_state_node_sessions[max_x_node].add(max_x_s_idx) # self.session_branch_state_nodes[max_x_s_idx].add(max_x_node) # # self.reassess_cost() # # total_c = 0 # for link_id, link in self.links.items(): # total_c += link.used_cap # # print "total_c", total_c # # # # Local Search Stage # # print "Local Search Stage" # # # Identify the overloaded nodes # overloaded_branch_state_nodes = defaultdict(set) # for s_idx, branch_nodes in self.session_branch_nodes.items(): # for branch_node in branch_nodes: # overloaded_branch_state_nodes[branch_node].add(s_idx) # if len(overloaded_branch_state_nodes[branch_node]) > \ # self.nodes[branch_node].services['sdn_router'].resources_cap['tcam']: # self.overloaded_set.add(branch_node) # # # Choose set of session in branch state node that reduce z_cost # for u in self.overloaded_set: # cost_no_overloaded_node = [(self.cost_t_a(s_idx, a[s_idx] - {u}) - self.cost_t_a(s_idx, a[s_idx] | {u}), # s_idx) for s_idx in overloaded_branch_state_nodes[u]] # cost_no_overloaded_node.sort() # # # Remove overloaded node from branch state # self.branch_state_node_sessions[u] = set() # for s_idx in self.session_branch_state_nodes: # if u in self.session_branch_state_nodes[s_idx]: # self.session_branch_state_nodes[s_idx].remove(u) # # for _ in range(self.nodes[u].services['sdn_router'].resources_cap['tcam']): # _, best_t = cost_no_overloaded_node.pop() # self.branch_state_node_sessions[u].add(best_t) # self.session_branch_state_nodes[best_t].add(u) # self.reassess_cost() # # for _, s_idx in cost_no_overloaded_node: # # Reroute the rest tree # self.reroute(s_idx, u) # # # If the amount of multicast flows in any edge exceeds the capacity constraint, # # we also reroute its closest upstream state node u in a tree Ti # # to w, such that the new path from w to v follows the link # # capacity constraint. # overloaded_links = {link_id for link_id, link in self.links.items() if link.used_cap > link.cap} # for s_idx, s_session in self.sessions_tree.items(): # for h, t in list(overloaded_links): # if (h, t) in s_session.edges(): # # find downstream # down_streams = [t] # while len(down_streams) > 0: # v = down_streams.pop(0) # if v in set(self.session_branch_nodes[s_idx]) | set(self.sessions[s_idx].dsts): # # find downstream # if self.reroute_path(s_idx, h, v): # overloaded_links.remove((h, t)) # break # else: # down_streams += list(s_session.neighbors(v)) # # # Remove session until link constraint is meant # while len(overloaded_links) > 0: # overloaded_link = overloaded_links.pop() # for s_idx in reversed(list(self.sessions_tree)): # if overloaded_link in self.sessions_tree[s_idx].edges(): # del self.sessions_tree[s_idx] # self.reassess_cost() # if self.links[overloaded_link].used_cap <= self.links[overloaded_link].cap: # break # total_c = 0 # for link_id, link in self.links.items(): # total_c += link.used_cap # # print "total_c", total_c # print "total mtrsa session", len(self.sessions_tree) # print "total session", len(self.app.get_sessions()) # print "unicast tunneling", self.max_count_unicast_tunneling() # # for id, node in self.nodes.items(): # print "used cam", id, node.services['sdn_router'].used_cap['tcam'] # Convert networkx to Solution for s_idx, s_session in self.sessions_tree.items(): self._solution.get_tree(self.sessions[s_idx]) self.update_session_cost(solution=self._solution, session=self.sessions[s_idx], links=self.sessions_tree[s_idx].edges()) total_time = time.time() - start_time self._solution.total_time = total_time return self._solution
def use_johnson(self,s,t): path = nx.johnson(self.G, source=s, target=t) return path