def compare_complexity(max_size, iterations=10): size = [] d_time = [] f_time = [] for n in range(10, max_size, 10): nodes = n size.append(nodes) g = SmallWorldGraph(nodes, 4, 0.5) # Get Dijkstra time: start = etime() # Iterate to get a stable estimate of the time for it in range(iterations): nx.all_pairs_dijkstra_path_length(g) end = etime() d_time.append(end - start) # Get Floyd-Warshall time start = etime() # Iterate to get a stable estimate of the time for it in range(iterations): g.shortest_path_all_pairs() end = etime() f_time.append(end - start) pyplot.plot(size, d_time, 'rs') pyplot.plot(size, f_time, 'bo') pyplot.title("Floyd-Warshall (blue) vs Dijkstra (red)") pyplot.savefig("shortest_path_compare.png")
def test_all_pairs_dijkstra_path_length(self): cycle = nx.cycle_graph(7) pl = dict(nx.all_pairs_dijkstra_path_length(cycle)) assert_equal(pl[0], {0: 0, 1: 1, 2: 2, 3: 3, 4: 3, 5: 2, 6: 1}) cycle[1][2]['weight'] = 10 pl = dict(nx.all_pairs_dijkstra_path_length(cycle)) assert_equal(pl[0], {0: 0, 1: 1, 2: 5, 3: 4, 4: 3, 5: 2, 6: 1})
def compare(self, g1, g2, verbose=False): """ Compute the kernel value between the two graphs. """ djk1 = nx.Graph(nx.all_pairs_dijkstra_path_length(g1)) djk1.remove_edges_from(djk1.selfloop_edges()) djk2 = nx.all_pairs_dijkstra_path_length(g2) djk2.remove_edges_from(djk2.selfloop_edges())
def path_check(G,kG): pair = [] s1 = time.time() sp1 = nx.all_pairs_dijkstra_path_length(G) t1 = time.time() #print 'G %f sec' %(t1-s1) s2 = time.time() sp2 = nx.all_pairs_dijkstra_path_length(kG) t2 = time.time() #print 'kG %f sec' %(t2-s2) for u,v in kG.edges(): if sp1[u][v] != sp2[u][v]: pair.append((u,v,sp1[u][v],sp2[u][v])) print 'speed %f' %(float((t2-s2)-(t1-s1))/(t1-s1))
def shortest_path(graph): """ All-pairs shortest path on the graph of inverse weights. For each pair, calculates the sum of the weights on the shortest path (by weight) between each pair in the graph. Uses the inverse weights to calculate, and inverts the final weight, such that a higher score is considered better. Returns: An array of n arrays of length n, representing the weight of the shortest path between each pair of nodes on the graph of inverse weights. None is used for pairs where there is no path. """ num_nodes = graph.number_of_nodes() nx_dict = nx.all_pairs_dijkstra_path_length( graph, weight='inv_weight') # Convert from dict format to array format shortest_paths = np.zeros((num_nodes, num_nodes)) for i, d in nx_dict.iteritems(): for j in xrange(num_nodes): try: shortest_paths[i, j] = 1.0 / d[j] except (KeyError, ZeroDivisionError): shortest_paths[i, j] = np.inf return shortest_paths
def get_diameter(g): vertices = g.nodes() #pairs = get_pairs(vertices) dists = networkx.all_pairs_dijkstra_path_length(g) #for s in shortest_paths.keys(): # print s,shortest_paths[s] return max(get_vertices([x.values() for x in dists.values()]))
def diameter(g, weighted): if not weighted: return nx.diameter(g) else: ret = nx.all_pairs_dijkstra_path_length(g) return max(map(lambda perSourceDists: max(perSourceDists.values()), ret.values())) pass
def route_remaining_edges_simple(G, T, n2c): """The original routing function --- not used now""" #for u,v in G.edges_iter(): # if T.are_adjacent(n2c[u], n2c[v]): # print 'edge (%d,%d) at %d,%d good' % (u,v,n2c[u], n2c[v]) if G.number_of_edges() == 0: return [] H = construct_routing_graph(T, set(n2c.values())) SP = nx.all_pairs_dijkstra_path(H) SP_len = nx.all_pairs_dijkstra_path_length(H) nx.write_edgelist(H, "hex.graph") # for every remaining edge Routes = [] for u,v in G.edges_iter(): c = n2c[u] d = n2c[v] # find the combination of sides that gives the shortest path best = bestp = None for s1,s2 in itertools.product(T.hex_sides(),T.hex_sides()): source = T.side_name(c,s1) target = T.side_name(d,s2) if SP_len[source][target] < best or best is None: best = SP_len[source][target] bestp = SP[source][target] #print >>sys.stderr, "Route %d - %d (%g) %s" % (u, v, best, ",".join(bestp)) Routes.append(bestp) return Routes
def expand_road_network(road_network, discritization): """Discritize a simple road_network Takes a simple road network with nodes at features and intersections and edges with weights between nodes and add nodes along the edges """ rn_old = road_network df = discritization # nodes per unit weight # Find shortest paths and path lengths paths = nx.all_pairs_dijkstra_path(rn_old) path_lengths = nx.all_pairs_dijkstra_path_length(rn_old) # Create new graph rn = nx.Graph() rn.add_nodes_from(rn_old.nodes(data=True)) for old_edge in rn_old.edges(data=True): beg = old_edge[0] end = old_edge[1] if int(beg) > int(end): beg, end = end, beg num_nodes = int(round(old_edge[2]['weight'] * df) - 1) old_node_name = beg for node in range(num_nodes): new_node_name = '{}.{}.{}'.format(beg, end, node) if node == num_nodes - 1: rn.add_edge(new_node_name, end) rn.add_edge(old_node_name, new_node_name) old_node_name = new_node_name return rn, paths, path_lengths
def distances_to_tour(self): scaffolds = self.scaffolds distances = self.distances G = nx.DiGraph() for (a, b), v in distances.items(): d = self.weighted_mean(v) G.add_edge(a, b, weight=d) if a == START or b == END: continue G.add_edge(b, a, weight=d) logging.debug("Graph size: |V|={0}, |E|={1}.".format(len(G), G.size())) L = nx.all_pairs_dijkstra_path_length(G) for a, b in combinations(scaffolds, 2): if G.has_edge(a, b): continue l = L[a][b] G.add_edge(a, b, weight=l) G.add_edge(b, a, weight=l) edges = [] for a, b, d in G.edges(data=True): edges.append((a, b, d['weight'])) try: tour = hamiltonian(edges, directed=True, precision=2) assert tour[0] == START and tour[-1] == END tour = tour[1:-1] except: logging.debug("concorde-TSP failed. Use default scaffold ordering.") tour = scaffolds[:] return tour
def initialize_graph(size): points_x = [] points_y = [] terminals = [] for i in range(size): points_x.append(random.uniform(-100, 100)) points_y.append(random.uniform(-100, 100)) for i in range(size): if i % 2 == 0: terminals.append(i) h = nx.erdos_renyi_graph(size, 0.3) g = nx.Graph() for i in range(size): g.add_node(i) for i in range(size): for j in range(i, size): if h.has_edge(i, j): g.add_edge(i, j) # weight=manhattan_distance((points_x[i], points_y[i]), (points_x[j], points_y[j]))) length_shortest_paths = nx.all_pairs_dijkstra_path_length(g) shortest_paths = nx.all_pairs_shortest_path(g) metric_closure = nx.Graph() for i in range(size): metric_closure.add_node(i) for i in range(size): for j in range(size): metric_closure.add_edge(i, j, weight=length_shortest_paths[i][j]) print metric_closure return (terminals, shortest_paths, metric_closure, points_x, points_y, g)
def __init__(self, view, controller, metacaching, implementation='ideal', radius=4, **kwargs): """Constructor Parameters ---------- view : NetworkView An instance of the network view controller : NetworkController An instance of the network controller metacaching : str (LCE | LCD) Metacaching policy used implementation : str, optional The implementation of the nearest replica discovery. Currently on ideal routing is implemented, in which each node has omniscient knowledge of the location of each content. radius : int, optional Radius used by nodes to discover the location of a content. Not used by ideal routing. """ super(NearestReplicaRouting, self).__init__(view, controller) if metacaching not in ('LCE', 'LCD'): raise ValueError("Metacaching policy %s not supported" % metacaching) if implementation not in ('ideal', 'approx_1', 'approx_2'): raise ValueError("Implementation %s not supported" % implementation) self.metacaching = metacaching self.implementation = implementation self.radius = radius self.distance = dict(nx.all_pairs_dijkstra_path_length(self.view.topology(), weight='delay'))
def create_shortest_path_matrix(weighted=False, discount_highways=False): G = nx.DiGraph() logging.info("Loading graph to NetworkX from database...") c = connection.cursor() if discount_highways: c.execute("SELECT l.beg_node_id, l.end_node_id, (CASE WHEN l.link_type='1' THEN 0.5 WHEN l.link_type='2' THEN 0.5 ELSE 1.0 END) FROM microsim_link l") else: c.execute("SELECT l.beg_node_id, l.end_node_id, l.length/l.lane_count AS resistance FROM microsim_link l") G.add_weighted_edges_from(c.fetchall()) logging.debug("Road network is strongly connected: %s" % repr(nx.is_strongly_connected(G))) logging.info("Computing shortest paths...") if weighted: sp = nx.all_pairs_dijkstra_path_length(G) else: sp = nx.all_pairs_shortest_path_length(G) logging.info("Converting shortest paths into matrix...") c.execute("SELECT ROW_NUMBER() OVER (ORDER BY id), beg_node_id, end_node_id FROM microsim_link") links = c.fetchall() N_LINKS = len(links) shortest_paths = np.zeros((N_LINKS, N_LINKS)) for col_idx, _, col_end_node in links: for row_idx, _, row_end_node in links: if col_idx == row_idx: continue nodes = sp[col_end_node] if row_end_node not in nodes: shortest_paths[row_idx - 1, col_idx - 1] = float(N_LINKS) else: shortest_paths[row_idx - 1, col_idx - 1] = nodes[row_end_node] logging.info("Shortest path matrix complete.") return shortest_paths
def compareGraphToOptimum(self): shortestPathsWeights = nx.all_pairs_dijkstra_path_length(self.G) optimalSum = 0 graphSum = 0 mypath = 0 pathsNotFound = 0 for source, val in shortestPathsWeights.iteritems(): for destination, pathLenght in val.iteritems(): if source == destination: continue try: mypath = self.pathLenght(source, destination) graphSum += mypath optimalSum += pathLenght if not mypath == pathLenght: print 'different path from %s to %s with %d to %d' % (str(source), str(destination), mypath, pathLenght) except KeyError: print 'incomplete solultion! No path from %s to %s' % (str(source), str(destination)) pathsNotFound += 1 optimalSum += pathLenght graphSum += 2*pathLenght #return '','incomplete' error = (float(graphSum)-float(optimalSum))/float(optimalSum) print "Error of found paths: %f%%, Paths not found: %d" %(100*error,pathsNotFound) #print 'optimal shortest-paths sum: %s, graph shortest-path sum: %s.' % (str(optimalSum), str(graphSum)) return error, pathsNotFound
def getGroupMetrics(G, results): results.numEdges = len(G.edges()) results.numNodes = len(G.nodes()) pathLenghts = nx.all_pairs_dijkstra_path_length(G, weight="weight").values() results.averageShortestPathWeighted = np.average( [ x.values()[0] for x in pathLenghts]) results.maxShortestPathWeighted = np.max( [ x.values()[0] for x in pathLenghts]) pathLenghts = nx.all_pairs_shortest_path_length(G).values() results.averageShortestPath = np.average( [ x.values()[0] for x in pathLenghts]) results.maxShortestPath = np.max( [ x.values()[0] for x in pathLenghts]) cache = None runResB = {} runResC = {} for i in range(4,6): res = computeGroupMetrics(G, groupSize=i, weighted=True, cutoff = 2, shortestPathsCache=cache) cache = res[-1] runResB[i] = [res[0], res[1]] runResC[i] = [res[2], res[3]] results.groupMetrics['betweenness'] = runResB results.groupMetrics['closeness'] = runResC
def largearcs_connecting_heuristic( cycles, transport_graph, cost_label='cost' ) : APSP = nx.all_pairs_dijkstra_path( transport_graph, weight=cost_label ) APSPL = nx.all_pairs_dijkstra_path_length( transport_graph, weight=cost_label ) # Step 3(b): Form the inter-node distance from the original edge costs # d(ni,nj) = min { c'(u,v) | u \in Ri, v \in Rj }. # Associate with (ni,nj) the edge (u,v) yielding minimum cost. inter_node_distance = nx.Graph() for cycle in cycles : u = node() u.cycle = cycle # do we need this?... eh, it's cheap inter_node_distance.add_node( u ) # u.enroute, u.balance = cycle_edges( cycle ) # also want to store all nodes visited while *EMPTY* u.nodes = set() for x,y in u.balance.edges_iter() : u.nodes.update( APSP[x][y] ) #for x,y,key, data in u.graph.edges_iter( keys=True, data=True ) : #if not data.get( 'CONNECT_ONLY', False ) : continue #u.nodes.update( APSP[x][y] ) NODES = inter_node_distance.nodes() for u, v in itertools.combinations( NODES, 2 ) : options = [ ( APSPL[x][y] + APSPL[y][x], (x,y) ) for x,y in itertools.product( u.nodes, v.nodes ) ] # round trip cost cost, edge = min( options ) inter_node_distance.add_edge( u, v, cost=cost, edge=edge ) # Step 4: Find a minimum cost spanning tree on inter-node distance graph MST = nx.algorithms.minimum_spanning_tree( inter_node_distance, weight='cost' ) # Step 2: Initialize PRETOUR to be empty. For each edge in the matching, # associate a direction (from head to tail); insert into PRETOUR # (Also, insert the arcs...) eulerian = nx.MultiDiGraph() for u in NODES : for x,y, key in u.enroute.edges_iter( keys=True ) : eulerian.add_edge( x,y, key, SERVICE=True ) for u in NODES : for x,y in u.balance.edges_iter() : eulerian.add_edge( x, y ) for _,__,data in MST.edges_iter( data=True ) : x,y = data.get('edge') eulerian.add_edge( x, y ) eulerian.add_edge( y, x ) try : tour = [] for edge in eulerian_circuit_verbose( eulerian ) : if not eulerian.get_edge_data( *edge ).get('SERVICE', False ) : continue tour.append( edge ) return tour except : return eulerian
def roadnet_APSP( roadnet, length='length' ) : digraph = nx.MultiDiGraph() for i,j,key,data in roadnet.edges_iter( keys=True, data=True ) : edgelen = data.get( length, 1 ) digraph.add_edge( i,j,key, weight=edgelen ) if not data.get( 'oneway', False ) : digraph.add_edge( j,i,key, weight=edgelen ) return nx.all_pairs_dijkstra_path_length( digraph )
def calc_influence(DiG,cf): sp = nx.all_pairs_dijkstra_path_length(DiG,cf) for key in sp: d = sp[key] for idx in d: # add influence to expect node dd = d[idx]/cf G.node[idx]['density'] += (1.0-dd*dd)*3/4
def diam(self): #this is very, very, very inefficient! nodes = self.defects len = [] while nodes: v = nodes.pop() for u in nodes: len.append(nx.all_pairs_dijkstra_path_length(self.compl,v,u)) return max(len)
def dijkstra_path(G): """Return the shortest Dijkstra (weighted) path between all pairs of vertices (averaged twice) """ dijkstra_path = nx.all_pairs_dijkstra_path_length(G) summed_dpv = [sum(dpv.values()) for dpv in dijkstra_path.values()] average_dijkstra_path = sum(summed_dpv)/ (len(G.nodes())**2) return average_dijkstra_path
def _compute_all_pairs(self, graph, weight=None, normalize=False): lengths = nx.all_pairs_dijkstra_path_length(graph, weight=weight) max_length = max([max(lengths[i].values()) for i in lengths]) if normalize: for i in lengths: for j in lengths[i]: lengths[i][j] = float(lengths[i][j]) / max_length return lengths
def harmonic_centrality(G, distance=None): r"""Compute harmonic centrality for nodes. Harmonic centrality [1]_ of a node `u` is the sum of the reciprocal of the shortest path distances from all other nodes to `u` .. math:: C(u) = \sum_{v \neq u} \frac{1}{d(v, u)} where `d(v, u)` is the shortest-path distance between `v` and `u`. Notice that higher values indicate higher centrality. Parameters ---------- G : graph A NetworkX graph distance : edge attribute key, optional (default=None) Use the specified edge attribute as the edge distance in shortest path calculations. If `None`, then each edge will have distance equal to 1. Returns ------- nodes : dictionary Dictionary of nodes with harmonic centrality as the value. See Also -------- betweenness_centrality, load_centrality, eigenvector_centrality, degree_centrality, closeness_centrality Notes ----- If the 'distance' keyword is set to an edge attribute key then the shortest-path length will be computed using Dijkstra's algorithm with that edge attribute as the edge weight. References ---------- .. [1] Boldi, Paolo, and Sebastiano Vigna. "Axioms for centrality." Internet Mathematics 10.3-4 (2014): 222-262. """ if len(G) <= 1: return {singleton: 0.0 for singleton in G.nodes()} if G.is_directed(): G = G.reverse() if distance is not None: # use Dijkstra's algorithm with specified attribute as edge weight sp = nx.all_pairs_dijkstra_path_length(G, weight=distance) else: sp = nx.all_pairs_shortest_path_length(G) return {n: sum(1/d if d > 0 else 0 for d in dd.values()) for n, dd in sp}
def ordered_path(mst, combinations): length0=nx.all_pairs_dijkstra_path_length(mst) lMax=0 for f,t in combinations: lCur=length0[f][t] if lCur>lMax: lMax=lCur best=(f,t) return nx.dijkstra_path(mst,best[0],best[1])
def get_paths(data, edgeDict=None, graph=None, algorithm='Floyd', weights='aff', saveResults=False, filepathDist=None): ''' a function that computes all pairwise distances (shortest paths) and puts it into a dictionary. Input: graph with edges as distances OR (default) dict with pairwise affinities (not distances) Output: shortest paths in a dict of dicts. ''' unmatched = [] distGraph = nx.Graph() if weights == 'aff': print "computing 1/affinities..." for i in data: matched = 0 if i in edgeDict: distGraph.add_node(i) matched = 1 for j in edgeDict[i]: if edgeDict[i][j] == 0: distGraph.add_edge(i, j, weight='inf') else: distGraph.add_edge(i, j, weight=1.0 / edgeDict[i][j]) if matched == 0: unmatched.append(i) elif weights == 'dist': distGraph = graph else: print "Error: weight should be either 'aff' or 'dist'" return 1 print "number of unmatched nodes: ", len(unmatched) print unmatched if algorithm == 'Floyd': print "\ncomputing all shortest paths with Floyd-Warshall algorithm..." dist = nx.floyd_warshall(distGraph) print "pairwise distances obtained" elif algorithm == "Dijkstra": print "\ncomputing all shortest paths with Dijkstra algorithm..." dist = nx.all_pairs_dijkstra_path_length(distGraph) print "pairwise distances obtained" else: print "\nError: cannot recognize what algorithm to use" return 1 print "num of rows in dist matrix: ", len(dist.keys()) # print dist.keys() if saveResults: if filepathDist == None: #filepathDist = "/home/krybachuk/SHORTESTPATH_" + VersionTime filepathDist = "SHORTESTPATH_" + "latest" json.dump(dist, open(filepathDist, 'w')) print "shortest path dict saved\n\n" return dist
def get_mean_effdist(G, with_error=False, weight="weight", get_all=False): length = nx.all_pairs_dijkstra_path_length(G) res = [length[n][n2] for n in length.keys() for n2 in length[n].keys()] if get_all: return array(res) elif with_error: return mean(res), std(res) / sqrt(len(res) - 1) else: return mean(res)
def dijkstraDumpReport(G,printOnScreen=False): paths = nx.all_pairs_dijkstra_path_length(G, weight='weight') print type(paths) json.dump(paths, open("graph_dijkstra.json",'w')) print "Saving all the Dijkstra lengths to: ", "graph_dijkstra.json" if printOnScreen: for path in paths.keys(): print "------------------------------------------" print path, " ", paths[path] print "\n"
def mainfuntion(allrows): # global GG_S # global finger_S # global orignodelist_S # global allnodedist_S # is not use,add in here is clear global for next recall model. GTotal = madeG(allrows) GG.append(GTotal) allnodedist = nx.all_pairs_dijkstra_path_length(GG[0]) trunkui() #正式进入程序功能入口。
def __init__(self, data_path): with open(data_path, 'r') as graph_file: graph_data = json.load(graph_file) self.graph = json_graph.node_link_graph(graph_data, multigraph=False) self.name_node_map = {node[1]['name']: node[0] for node in self.graph.nodes(data=True)} self.all_paths = networkx.all_pairs_dijkstra_path(self.graph) self.all_costs = networkx.all_pairs_dijkstra_path_length(self.graph) # add blank houses set to each node for node in self.graph.nodes(): self.graph.node[node]['houses'] = []
def _load_nav_graphs(self): ''' Load connectivity graph for each scan, useful for reasoning about shortest paths ''' print 'Loading navigation graphs for %d scans' % len(self.scans) self.graphs = load_nav_graphs(self.scans) self.paths = {} for scan,G in self.graphs.iteritems(): # compute all shortest paths self.paths[scan] = dict(nx.all_pairs_dijkstra_path(G)) self.distances = {} for scan,G in self.graphs.iteritems(): # compute all shortest paths self.distances[scan] = dict(nx.all_pairs_dijkstra_path_length(G))
def calc_root(G): all_pairs_G=nx.all_pairs_dijkstra_path_length(G) root="" maxi=0 for x in all_pairs_G.keys(): for y in all_pairs_G[x].keys(): if(all_pairs_G[x][y] > maxi): maxi=all_pairs_G[x][y] root=y return root
Folder_to_load_from= '{}'.format(Folder_to_load_from) Folder_to_save_graphs=str(Folder_to_save_graphs) Name_of_stat_file='{}'.format(Name_of_stat_file) stats={} #create graph G=ox.save_load.load_graphml(Graphml_File_Name, folder=Folder_to_load_from) #average shortest path length of graph stats['average_shortest_path_length']=nx.average_shortest_path_length(G,weight='length') # find the all_pairs_dijkstra_path_length stats['all_pairs_dijkstra_path_length']=nx.all_pairs_dijkstra_path_length(G, cutoff=15000, weight='length') shortlengthsum={key: sum(value.itervalues()) for key, value in length.iteritems()} Total=sum(shortlengthsum.values()) N=G.number_of_nodes() Mean_length_shortest=float(Total)/N dict2 = {key:float(value)/Mean_length_shortest for key, value in shortlengthsum.items()} z=dict2.values() std=np.std(z)
args = parser.parse_args() name = args.name name = name \ .replace(' ', '-') \ .lower() \ .replace('č', 'c') \ .replace('š', 's') \ .replace('ž', 'z') g: nx.Graph = nx.read_pajek(f"../data/graphs/with_distances/{name}.net") nodes = {} centers = {center: [] for center in random.sample(g.nodes, args.k)} distances = dict(nx.all_pairs_dijkstra_path_length(g, weight=lambda u, v, d: int(d[0]['duration']))) # 1. compute the desired cluster size max_cluster_size = math.ceil(g.number_of_nodes() / args.k) # 2. Initialise means, preferably with k-means for i in range(0, 100): # for each node, find closest center for node in g.nodes: closest_center = -1 closest_distance = float('inf') for center in centers: distance = distances[center][node] if distance < closest_distance:
print "Pair for distance calc: %s" % x print "Pair for edge list: (%s,%s)" % (src, dest) if dist < 9: print("dist is less than 9") G.add_edge(int(src), int(dest)) new_edge = "%s \t %s" % (int(src), int(dest)) # write new edges to file edge_list_out = open('edge_list_out.dat', 'a') edge_list_out.write(new_edge) edge_list_out.write("\n") else: print("dist is greater than 9") print dist edge_list_out.close() # check that updated graph has expected num and list of edges and nodes newnumedges = G.number_of_edges() # store new number of edges newedges = G.edges() # store new list of edges print "The number of nodes in graph should not have changed: %s" % numnodes print "The number of edges currently in the graph: %s" % newnumedges print "The list of edges currently in the graph:\n%s" % newedges # calculate shortest paths and distances through shortest paths # calc shortest path from x to y #print(nx.shortest_path(G, x, y, 1)) # code vars or manually add x,y of interest # calc all shortest paths between all nodes in a weighted graph print(nx.all_pairs_dijkstra_path(G, 5, 1)) # cutoff=5, weight=1 # calc all shortest path lengths between all nodes in a weighted graph print(nx.all_pairs_dijkstra_path_length(G, 5, 1)) # cutoff=5, weight=1
def map(self): task_graph = self.process_graph processor_graph = nx.Graph( ) #create a topology graph using info about each node`s neighbours for elem in range(len(self.topology)): x, y, z = self.topology.to_xyz(elem) for neighbour in self.topology.neighbours(x, y, z): processor_graph.add_edge( elem, self.topology.to_idx(neighbour) ) #if two nodes are neighbours, we add an edge between them to our topo_graph dijkstra_path = dict( nx.all_pairs_dijkstra_path_length(processor_graph)) flag = False #false if without partition, true - with def find_new_start( C, s ): #we are lookong for the nearest node to s that is free for allocating, i.e. has C(s)>0 left, right = 0, 0 while True: if C[s - left] == 1: return s - left elif C[s + right] == 1: return s + right if s - left > 0: left += 1 if s + right < len(C) - 1: right += 1 def create_partition_graph( tgraph, pgraph ): #we create a partition of a given app_graph to len(graph)-chunks, #several tasks that communicate tightly are combined into one block, an edge between each block has weight equal to sum of all edges between all tasks in two different blocks # partition = nxmetis.partition(tgraph, len(pgraph), None, None, 'weight', None, None, None, True) partition_graph = nx.Graph() partition_graph.add_nodes_from(pgraph.nodes()) for i in range(len(partition[1])): for j in range(len(partition[1])): if j != i: val = 0 for elem_from_i in partition[1][i]: for elem_from_j in partition[1][j]: if tgraph.has_edge(elem_from_i, elem_from_j): val += tgraph.get_edge_data( elem_from_i, elem_from_j)['weight'] if val > 0: partition_graph.add_edge(i, j, weight=val) return partition, partition_graph def dijkstra_closest_vertex( C, start ): #here we are looking for the nearest node to our start position #that has C[s]>0 min_distance = float("inf") for elem in dijkstra_path[start]: if elem != start and C[elem] > 0: if dijkstra_path[start][elem] < min_distance: min_distance, min_index = dijkstra_path[start][ elem], elem return min_index def greedy_graph_embedding_algo(tgraph, pgraph): mapping = {} task_set = set(tgraph.nodes()) C = [1 for i in range(len(pgraph))] queue = [] start_node = list(pgraph.nodes())[len(pgraph.nodes()) // 2] #one from the center ID`s #here we sort all vertices according the weights of their out edges queue_of_heaviest_in_S = [ i[0] for i in sorted(tgraph.degree(None, 'weight'), key=lambda item: item[1], reverse=True) ] #queue_of_heaviest_in_S = [i[0] for i in sorted(tgraph.degree(None,'weight'),key=lambda item:item[1],reverse=True)] while len(task_set) != 0: vertex_m = queue_of_heaviest_in_S.pop(0) if C[start_node] == 0: start_node = find_new_start(C, start_node) mapping[vertex_m] = self.topology.to_xyz(start_node) task_set.remove(vertex_m) C[start_node] = 0 for u in tgraph[vertex_m]: if u in task_set: queue.append( (vertex_m, u, tgraph.get_edge_data(vertex_m, u))) #here we sort the queue according the weights of each edge queue = sorted(queue, key=lambda x: x[2]['weight'], reverse=True) while len(queue) != 0: heaviest_edge_in_Q = queue.pop(0) if C[start_node] == 0: start_node = dijkstra_closest_vertex(C, start_node) _, vertex_m = heaviest_edge_in_Q[0], heaviest_edge_in_Q[1] mapping[vertex_m] = self.topology.to_xyz(start_node) task_set.remove(vertex_m) queue_of_heaviest_in_S.remove(vertex_m) C[start_node] = 0 #here we have to check whether our u in task_set or not #if not, there can be a situation, when an edge with its neighbour is already added into queue, #hence we have to delete it from the queue in order not consider it in the future (because we already have allocated these two nodes onto topology nodes) for u in tgraph[vertex_m]: if u in task_set: queue.append((vertex_m, u, tgraph.get_edge_data(vertex_m, u))) elif (vertex_m, u, tgraph.get_edge_data( vertex_m, u)) in queue or (u, vertex_m, tgraph.get_edge_data( vertex_m, u)) in queue: try: queue.remove( (vertex_m, u, tgraph.get_edge_data(vertex_m, u))) except ValueError: queue.remove( (u, vertex_m, tgraph.get_edge_data(vertex_m, u))) queue = sorted(queue, key=lambda x: x[2]['weight'], reverse=True) return mapping if flag: partition, partition_graph = create_partition_graph( task_graph, processor_graph) maps = greedy_graph_embedding_algo(partition_graph, processor_graph) return_mapping = {} for i in range(len(maps)): for elem in partition[1][i]: return_mapping[elem] = maps[i] return return_mapping else: maps = greedy_graph_embedding_algo(task_graph, processor_graph) return maps
def optimal_median_cache_placement(topology, cache_budget, n_cache_nodes, hit_ratio, weight='delay', **kwargs): """Deploy caching nodes in locations that minimize overall latency assuming a partitioned strategy (a la Google Global Cache). According to this, in the network, a set of caching nodes are deployed and each receiver is mapped to one and only one caching node. Requests from this receiver are always sent to the designated caching node. In case of cache miss requests are forwarded to the original source. This placement problem can be mapped to the p-median location-allocation problem. This function solves this problem using the vertex substitution heuristic, which practically works like the k-medoid PAM algorithms, which is also similar to the k-means clustering algorithm. The result is not guaranteed to be globally optimal, only locally optimal. Notes ----- This placement assumes that all receivers have degree = 1 and are connected to an ICR candidate nodes. Also, it assumes that contents are uniformly assigned to sources. Parameters ---------- topology : Topology The topology object cache_budget : int The cumulative cache budget n_nodes : int The number of caching nodes to deploy hit_ratio : float The expected cache hit ratio of a single cache weight : str The weight attribute """ n_cache_nodes = int(n_cache_nodes) icr_candidates = topology.graph['icr_candidates'] if len(icr_candidates) < n_cache_nodes: raise ValueError("The number of ICR candidates (%d) is lower than " "the target number of caches (%d)" % (len(icr_candidates), n_cache_nodes)) elif len(icr_candidates) == n_cache_nodes: caches = list(icr_candidates) cache_assignment = { v: list(topology.adj[v].keys())[0] for v in topology.receivers() } else: # Need to optimally allocate caching nodes distances = dict( nx.all_pairs_dijkstra_path_length(topology, weight=weight)) sources = topology.sources() d = {u: {} for u in icr_candidates} for u in icr_candidates: source_dist = sum(distances[u][source] for source in sources) / len(sources) for v in icr_candidates: if v in d[u]: d[v][u] = d[u][v] else: d[v][u] = distances[v][u] + (hit_ratio * source_dist) allocation, caches, _ = compute_p_median(distances, n_cache_nodes) cache_assignment = { v: allocation[list(topology.adj[v].keys())[0]] for v in topology.receivers() } cache_size = iround(cache_budget / n_cache_nodes) if cache_size == 0: raise ValueError( "Cache budget is %d but it's too small to deploy it on %d nodes. " "Each node will have a zero-sized cache. " "Set a larger cache budget and try again" % (cache_budget, n_cache_nodes)) for v in caches: topology.node[v]['stack'][1]['cache_size'] = cache_size topology.graph['cache_assignment'] = cache_assignment
def shortest_path_length(G, source=None, target=None, weight=None): """Compute shortest path lengths in the graph. Parameters ---------- G : NetworkX graph source : node, optional Starting node for path. If not specified, compute shortest path lengths using all nodes as source nodes. target : node, optional Ending node for path. If not specified, compute shortest path lengths using all nodes as target nodes. weight : None or string, optional (default = None) If None, every edge has weight/distance/cost 1. If a string, use this edge attribute as the edge weight. Any edge attribute not present defaults to 1. Returns ------- length: int or iterator If the source and target are both specified, return the length of the shortest path from the source to the target. If only the source is specified, return a tuple (target, shortest path length) iterator, where shortest path lengths are the lengths of the shortest path from the source to one of the targets. If only the target is specified, return a tuple (source, shortest path length) iterator, where shortest path lengths are the lengths of the shortest path from one of the sources to the target. If neither the source nor target are specified, return a (source, dictionary) iterator with dictionary keyed by target and shortest path length as the key value. Raises ------ NetworkXNoPath If no path exists between source and target. Examples -------- >>> G=nx.path_graph(5) >>> nx.shortest_path_length(G,source=0,target=4) 4 >>> p=nx.shortest_path_length(G,source=0) # target not specified >>> dict(p)[4] 4 >>> p=nx.shortest_path_length(G,target=4) # source not specified >>> dict(p)[0] 4 >>> p=nx.shortest_path_length(G) # source,target not specified >>> dict(p)[0][4] 4 Notes ----- The length of the path is always 1 less than the number of nodes involved in the path since the length measures the number of edges followed. For digraphs this returns the shortest directed path length. To find path lengths in the reverse direction use G.reverse(copy=False) first to flip the edge orientation. See Also -------- all_pairs_shortest_path_length() all_pairs_dijkstra_path_length() single_source_shortest_path_length() single_source_dijkstra_path_length() """ if source is None: if target is None: ## Find paths between all pairs. if weight is None: paths = nx.all_pairs_shortest_path_length(G) else: paths = nx.all_pairs_dijkstra_path_length(G, weight=weight) else: ## Find paths from all nodes co-accessible to the target. with nx.utils.reversed(G): if weight is None: # We need to exhaust the iterator as Graph needs # to be reversed. paths = list( nx.single_source_shortest_path_length(G, target)) else: paths = nx.single_source_dijkstra_path_length( G, target, weight=weight) else: if target is None: ## Find paths to all nodes accessible from the source. if weight is None: paths = nx.single_source_shortest_path_length(G, source) else: paths = nx.single_source_dijkstra_path_length(G, source, weight=weight) else: ## Find shortest source-target path. if weight is None: p = nx.bidirectional_shortest_path(G, source, target) paths = len(p) - 1 else: paths = nx.dijkstra_path_length(G, source, target, weight) return paths