def __build_steiner_forest(self): forest = SuitabilityGraph() dist = cost = occupancy = 0 for t, dest in self.__confirmed.iteritems(): if dest is None: dest = self.__medoids[t] self.__confirmed[t] = dest for t_ in self.__term_tree[t]: self.__detour[t_] += self.__graph.dist[tuple( sorted([t, dest]))] # # Print groups of terminals that travel together. # if dest in self.__pois: # print self.__term_tree[t] # print t, dest self.__graph.compute_dist_paths(origins=[t], destinations=[dest], recompute=True) try: forest.append_path( self.__graph.paths[tuple(sorted([t, dest]))], self.__graph) dist = self.__graph.dist[tuple(sorted([t, dest]))] cost += dist except KeyError: # pdb.set_trace() print 'key error:', t, dest # Who is driver? # if t in self.__terminals and (dist > max_wd or dest == self.__medoids[t]): # print "Driver:", t, "Meeting point:", dest occupancy += len(self.__term_tree[t]) * dist # print "Num. terms:", len(self.__term_tree[t]), "Shared distance:", dist return forest, cost, occupancy / cost
def steiner_tree(self): subtrees = [] _, paths = dijkstra(self.__graph, self.__poi, self.__terminals) for t in self.__terminals: path = paths[t] subtree = SuitabilityGraph() # j = 0 # for i in range(len(path_to_poi)): # if path_to_poi[i] in self.__graph.contracted_regions: # region_id = path_to_poi[i] # subtree.append_from_path(path_to_poi[j:i], self.__original_graph) # closest_node = self.__find_closest_node_to_poi_within_region(region_id) # path_endpoint_1 = self.__dist_paths_node_within_region_node[closest_node][1][path_to_poi[i - 1]] # subtree.append_from_path(path_endpoint_1, self.__original_graph) # path_endpoint_2 = self.__dist_paths_node_within_region_node[closest_node][1][path_to_poi[i + 1]] # subtree.append_from_path(path_endpoint_2, self.__original_graph) # j = i + 1 # subtree.append_from_path(path_to_poi[j:], self.__original_graph) subtree.append_path(path, self.__graph) subtrees.append(subtree) steiner_tree = self.__merge_subtrees(subtrees) self.__prune_steiner_tree(steiner_tree) if self.__contract_graph: self.__decontract_steiner_tree(steiner_tree) return steiner_tree
class Baltz: def __init__(self, graph): # Init some instance variables. self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) self.__edges = graph.get_edges() self.__congestion = {} l_G = float(0) for e, le in self.__edges.iteritems(): self.__congestion[e] = 0 l_G += le self.__costs = {e: le / l_G for e, le in self.__edges.iteritems()} def steiner_forest(self, requests, k=4): lambda_ = 1 MSTs = {} n = len(self.__graph) for i, r in enumerate(requests): self.__graph.update_edge_weights({ e: self.__costs[e] * n**(self.__congestion[e] / lambda_ - 1) for e in self.__edges }) mz = VST_RS(self.__graph) Ti, l, _, _, _, _, _ = mz.steiner_forest(r[1:], [r[0]], k, sys.maxint) MSTs[i] = (Ti, l) for e in Ti.get_edges(): self.__congestion[e] += 1 lambda_ = max(lambda_, self.__congestion[e]) iteration = 1 while iteration <= 100: for i, r in enumerate(requests): cmax = max(self.__congestion.values()) E_Ti = MSTs[i][0].get_edges() A = len(E_Ti) self.__graph.update_edge_weights({ e: self.__costs[e] * A**(self.__congestion[e] - cmax) for e in self.__edges }) self.__graph.update_edge_weights( {e: le / A for e, le in E_Ti.iteritems()}) mz = VST_RS(self.__graph) Ti_, l, _, _, _, _, _ = mz.steiner_forest( r[1:], [r[0]], k, sys.maxint) self.__graph.update_edge_weights( {e: le * A for e, le in E_Ti.iteritems()}) if MSTs[i][1] > l: for e in MSTs[i][0].get_edges(): self.__congestion[e] -= 1 for e in Ti_.get_edges(): self.__congestion[e] += 1 MSTs[i] = (Ti_, l) iteration += 1 return MSTs
def enclosing_region(self): enclosing = SuitabilityGraph() paths = [] paths.append(self.__paths[tuple(sorted([323287670, 2392803740]))]) paths.append(self.__paths[tuple(sorted([2392803740, 127578100]))]) paths.append(self.__paths[tuple(sorted([127578100, 3109398450]))]) paths.append(self.__paths[tuple(sorted([3109398450, 342909685]))]) paths.append(self.__paths[tuple(sorted([342909685, 323287670]))]) for path in paths: enclosing.append_path(path, self.__original_graph) return enclosing
def __init__(self, graph): # Init some instance variables. self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) self.__edges = graph.get_edges() self.__congestion = {} l_G = float(0) for e, le in self.__edges.iteritems(): self.__congestion[e] = 0 l_G += le self.__costs = {e: le / l_G for e, le in self.__edges.iteritems()}
def __init__(self, graph, terminals, contract_graph=True, contracted_graph=None, within_convex_hull=False, dist_paths=None, nodes=None, use_medoid=False): # Check whether graph is node-weighted. if not graph.is_node_weighted(): raise (ValueError, "Dreyfus with IMRs algorithm only works with node-weighted graphs.") # Extract POI from the terminals list. if len(terminals) > 0: self.__poi = terminals[0] else: return # Set object variables. generator = SuitableNodeWeightGenerator() self.__original_graph = graph self.__terminals = terminals self.__contract_graph = contract_graph self.__use_medoid = use_medoid # Contracted graph... if contract_graph: if contracted_graph is not None: self.__graph = contracted_graph.copy() else: self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) self.__graph.contract_suitable_regions(generator, excluded_nodes=terminals, get_centroid_medoid=use_medoid) else: self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) # if nodes is not None: self.__nodes = list(nodes) else: if within_convex_hull: pass # self.__nodes = self.__graph.get_suitable_nodes_within_convex_set(terminals, generator, dist_paths) else: self.__nodes = self.__graph.get_suitable_nodes(generator, excluded_nodes=terminals) # for t in terminals: self.__nodes.append(t) # print(self.__nodes) # self.__dist = {} self.__paths = {} if dist_paths is not None: self.__dist = dict(dist_paths[0]) self.__paths = dict(dist_paths[1]) else: self.__dist, self.__paths = self.__graph.get_dist_paths(origins=self.__nodes, destinations=self.__nodes) # self.__s_d = {}
def __init__(self, graph, terminals): # Check whether graph is node-weighted. if not graph.is_node_weighted(): raise ( ValueError, "Cluster-based algorithm only works with node-weighted graphs." ) # Extract POI from the terminals list. if len(terminals) > 0: self.__poi = terminals[0] else: return # generator = SuitableNodeWeightGenerator() # Set object variables. self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) self.__terminals = terminals # # self.__regions = self.__graph.get_suitable_regions(generator, excluded_nodes=terminals, # get_border_internal_nodes=True, get_centroid_medoid=True, # get_characteristic_nodes=True) self.__regions = self.__graph.get_suitable_regions( generator, excluded_nodes=terminals, get_border_internal_nodes=True, get_centroid_medoid=True) # self.__nodes = [] for id_r in self.__regions: # # characteristic_nodes = self.__regions[id_r][6] # self.__nodes.extend(characteristic_nodes) border_nodes = self.__regions[id_r][1] self.__nodes.extend(border_nodes) # # if len(characteristic_nodes) == 0: # medoid = self.__regions[id_r][4] # # print(medoid) # self.__nodes.append(medoid) for t in terminals: self.__nodes.append(t) # self.__dist, self.__paths = self.__graph.get_dist_paths( origins=self.__nodes, destinations=self.__nodes)
def get_suitability_graph_from_session(request): graph = request.session['graph'] suitability_graph = SuitabilityGraph() for node_id, (node_weight, adj_dict, data) in graph.iteritems(): new_adj_dict = {int(neighbour): edge_cost for neighbour, edge_cost in adj_dict.iteritems()} suitability_graph[int(node_id)] = (node_weight, new_adj_dict, data) dist = {} for k, v in request.session['dist'].iteritems(): k_ = k.split(",") dist[(long(k_[0]), long(k_[1]))] = v suitability_graph.dist = dist pairs = set() for k in request.session['pairs_dist_paths']: k_ = k.split(",") pairs.add((long(k_[0]), long(k_[1]))) suitability_graph.pairs_dist_paths = pairs return suitability_graph
def get_suitability_graph_from_session(request): graph = request.session['graph'] suitability_graph = SuitabilityGraph() for node_id, (node_weight, adj_dict, data) in graph.iteritems(): new_adj_dict = { int(neighbour): edge_cost for neighbour, edge_cost in adj_dict.iteritems() } suitability_graph[int(node_id)] = (node_weight, new_adj_dict, data) return suitability_graph
def __build_steiner_tree(self, node, subset): steiner_tree = SuitabilityGraph() next_node = self.__s_d[node][subset][0][3] print(node, self.__s_d[node][subset]) # pdb.set_trace() if next_node is not None: try: steiner_tree.append_path( self.__paths[tuple(sorted([node, next_node]))], self.__graph) except KeyError: _, paths = dijkstra(self.__graph, node, [next_node]) steiner_tree.append_path(paths[next_node], self.__graph) (set_e, set_f) = self.__s_d[node][subset][0][4] steiner_branch_e = SuitabilityGraph() if set_e is not None and set_e != [next_node]: steiner_branch_e = self.__build_steiner_tree(next_node, set_e) steiner_branch_f = SuitabilityGraph() if set_f is not None and set_f != [next_node] and len(set_f) > 0: steiner_branch_f = self.__build_steiner_tree(next_node, set_f) steiner_tree.append_graph(steiner_branch_e) steiner_tree.append_graph(steiner_branch_f) return steiner_tree
def __build_steiner_tree_bactracking(self, node, subset): steiner_tree = SuitabilityGraph() next_node = self.__steiner_distances[node][tuple(subset)][3] # pdb.set_trace() if next_node is not None: try: steiner_tree.append_path( self.__paths[tuple(sorted([node, next_node]))], self.__graph) except KeyError: _, paths = dijkstra(self.__graph, node, [next_node]) steiner_tree.append_path(paths[next_node], self.__graph) (best_e, best_f) = self.__steiner_distances[node][tuple(subset)][4] steiner_branch_e = SuitabilityGraph() if best_e is not None and best_e != [next_node]: steiner_branch_e = self.__build_steiner_tree_bactracking( next_node, best_e) steiner_branch_f = SuitabilityGraph() if best_f is not None and best_f != [next_node] and len(best_f) > 0: steiner_branch_f = self.__build_steiner_tree_bactracking( next_node, best_f) steiner_tree.append_graph(steiner_branch_e) steiner_tree.append_graph(steiner_branch_f) return steiner_tree
def __build_steiner_tree_bactracking(self, node, subset): steiner_tree = SuitabilityGraph() next_node = self.__s_d[node][tuple(subset)][1] if self.__contract_graph: print(node, self.__s_d[node][tuple(subset)]) # pdb.set_trace() if next_node is not None: steiner_tree.append_path(self.__paths[tuple(sorted([node, next_node]))], self.__graph) (best_e, best_f) = self.__s_d[node][tuple(subset)][2] # pdb.set_trace() steiner_branch_e = SuitabilityGraph() if best_e is not None and best_e != [next_node]: steiner_branch_e = self.__build_steiner_tree_bactracking(next_node, best_e) steiner_branch_f = SuitabilityGraph() if best_f is not None and best_f != [next_node] and len(best_f) > 0: steiner_branch_f = self.__build_steiner_tree_bactracking(next_node, best_f) steiner_tree.append_graph(steiner_branch_e) steiner_tree.append_graph(steiner_branch_f) return steiner_tree
# node_weights[401] = generator.weights['VERY_SUITABLE'][0] node_weights[405] = generator.weights['VERY_SUITABLE'][0] gh = GridDigraphGenerator() node_weighted = gh.generate( m, n, edge_weighted=False, node_weighted=True, # node_weight_generator=generator, node_weights=node_weights, seed=seed) terminals = [200, 760, 763, 766, 499] suitability_graph = SuitabilityGraph() suitability_graph.append_graph(node_weighted) dr = DreyfusIMR(suitability_graph, terminals, contract_graph=False, within_convex_hull=False) start_time = time.clock() steiner_tree = dr.steiner_tree(consider_terminals=False) elapsed_time = time.clock() - start_time cost, node_cost = steiner_tree.compute_total_weights(terminals) ngh = NetworkXGraphHelper(suitability_graph) ngh.draw_graph(nodes_1=terminals, subgraphs_2=[steiner_tree],
m = n = 40 gh = GridDigraphGenerator() graph = gh.generate( m, n, edge_weighted=False, node_weighted=True, node_weight_generator=generator, # node_weights=node_weights, seed=seed) terminals = [470, 388, 750, 1185, 1222, 739, 487, 850, 1299, 333] poi = 899 suitability_graph = SuitabilityGraph() suitability_graph.append_graph(graph) suitability_graph.extend_suitable_regions(seed, generator) suitability_graph.extend_suitable_regions(seed, generator) regions = suitability_graph.get_suitable_regions(generator) # suitability_graph.contract_suitable_regions(generator) # paths = [] # for t in terminals: # _, paths_t = dijkstra(suitability_graph, t, [poi], consider_node_weights=False) # paths.append(paths_t[poi]) # _, paths_poi = suitability_graph.compute_shortest(poi, terminals)
terminals = [23, 17, 65] # terminals = [703, 858, 668, 171, 628, 886, 240, 383, 268, 686] # terminals = [3381, 2580, 2655, 3622, 2161, 5247, 5073, 871, 4946, 1017] # terminals = [23, 45, 56, 289, 365] # terminals = [331, 356, 297] # poi = 294 # terminals = [197, 221] # poi = 74 # terminals = [123, 230, 310, 588, 625, 700] # poi = 464 suitability_graph = SuitabilityGraph() suitability_graph.append_graph(graph) # suitability_graph.extend_suitable_regions(seed, generator) # suitability_graph.extend_suitable_regions(seed, generator) # regions = suitability_graph.get_suitable_regions(generator) contract_graph = False within_convex_hull = False consider_terminals = True start_time = time.clock() dr = DreyfusIMR(suitability_graph, terminals, contract_graph=contract_graph,
from grid_digraph_generator import GridDigraphGenerator from suitability import SuitableNodeWeightGenerator, SuitabilityGraph if __name__ == '__main__': generator = SuitableNodeWeightGenerator() seed = 0 m = n = 30 gh = GridDigraphGenerator() node_weighted = gh.generate(m, n, edge_weighted=True, node_weighted=True, node_weight_generator=generator, seed=seed) suitability_graph = SuitabilityGraph() suitability_graph.append_graph(node_weighted) weights = {i: generator.weights["VERY_SUITABLE"][0] for i in range(m * n)} suitability_graph.update_node_weights(weights)
if __name__ == '__main__': generator = SuitableNodeWeightGenerator() seed = 10 m = n = 50 gh = GridDigraphGenerator() node_weighted = gh.generate(m, n, edge_weighted=True, node_weighted=True, node_weight_generator=generator, seed=seed) suitability_graph = SuitabilityGraph() suitability_graph.append_graph(node_weighted) # suitability_graph.extend_suitable_regions(seed, generator) hotspots = suitability_graph.get_suitable_nodes(generator) terminals = np.random.choice(a=m * n, size=30, replace=False) while set(hotspots).intersection(terminals) != set(): terminals = np.random.choice(a=m * n, size=30, replace=False) pois = terminals[:3] terminals = terminals[3:] regions = suitability_graph.get_suitable_regions(generator)
def __init__(self, graph, terminals, poi, max_level_attraction=2, contract_graph=True, contracted_graph=None, within_convex_hull=False, dist_paths_suitable_nodes=None): if not graph.is_node_weighted(): raise ( ValueError, "Gravitation algorithm only works with node-weighted graphs.") # Store class variables for future references. self.__original_graph = graph self.__terminals = terminals self.__poi = poi self.__contract_graph = contract_graph # terminals_poi = list(terminals) terminals_poi.append(poi) generator = SuitableNodeWeightGenerator() # Contracted graph... if contract_graph: if contracted_graph is not None: self.__graph = contracted_graph.copy() else: self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) self.__graph.contract_suitable_regions( generator, excluded_nodes=terminals_poi) else: self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) # # # ngh = NetworkXGraphHelper(self.__original_graph) # ngh.draw_graph(nodes_1=terminals, # nodes_2=[poi], # subgraphs_1=[r for _, (r, _, _) in self.__graph.contracted_regions.iteritems()], # node_weight_generator=generator, # node_size=25) # # # ngh = NetworkXGraphHelper(self.__graph) # ngh.draw_graph(node_weight_generator=generator, node_size=25, node_labels=True) # Copy distances and paths dictionary since it will be changed. dist_paths = None if dist_paths_suitable_nodes is not None: dist_paths = dict(dist_paths_suitable_nodes) for e in terminals_poi: dist_paths[e] = dijkstra(self.__graph, e) # Get the suitable nodes. if within_convex_hull: self.__suitable_nodes = self.__graph.get_suitable_nodes_within_convex_set( terminals_poi, generator, dist_paths) else: self.__suitable_nodes = self.__graph.get_suitable_nodes( generator, excluded_nodes=terminals_poi) # print(self.__suitable_nodes) # self.__dist_paths_node_node = {} if dist_paths is not None: self.__dist_paths_node_node = { n: dist_paths[n] for n in self.__suitable_nodes } else: self.__dist_paths_node_node = \ {n: dijkstra(self.__graph, n) for n in self.__suitable_nodes} for e in terminals_poi: if e not in self.__dist_paths_node_node: self.__dist_paths_node_node[e] = dijkstra(self.__graph, e) # max_distances = [ max(self.__dist_paths_node_node[n][0].values()) for n in self.__suitable_nodes if len(self.__dist_paths_node_node[n][0].values()) > 0 ] if len(max_distances) > 0: self.__max_dist = max(max_distances) else: self.__max_dist = 0 # # # max_level_attraction_poi = 0 # for t in terminals: # max_level_attraction_poi = max(max_level_attraction_poi, len(self.__dist_paths_node_node[poi][1][t])) # mass = self.__calculate_mass_suitable_node(poi) # self.__attract_nodes_to(poi, mass, poi, max_level_attraction_poi, 0, []) # dist_to_poi = {} for n in self.__suitable_nodes: try: dist_to_poi[n] = self.__dist_paths_node_node[n][0][poi] except KeyError: dist_to_poi[n] = sys.maxint # dist_to_poi = {n: self.__dist_paths_node_node[n][0][poi] for n in self.__suitable_nodes} # ord_suit_nodes = sorted(dist_to_poi.iteritems(), key=operator.itemgetter(1), reverse=True) ord_suit_nodes = sorted(dist_to_poi.iteritems(), key=operator.itemgetter(1)) for n, _ in ord_suit_nodes: mass = self.__calculate_mass_suitable_node(n) self.__attract_nodes_to(n, mass, n, max_level_attraction, 0, [])
class Gravitation: def __init__(self, graph, terminals, poi, max_level_attraction=2, contract_graph=True, contracted_graph=None, within_convex_hull=False, dist_paths_suitable_nodes=None): if not graph.is_node_weighted(): raise ( ValueError, "Gravitation algorithm only works with node-weighted graphs.") # Store class variables for future references. self.__original_graph = graph self.__terminals = terminals self.__poi = poi self.__contract_graph = contract_graph # terminals_poi = list(terminals) terminals_poi.append(poi) generator = SuitableNodeWeightGenerator() # Contracted graph... if contract_graph: if contracted_graph is not None: self.__graph = contracted_graph.copy() else: self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) self.__graph.contract_suitable_regions( generator, excluded_nodes=terminals_poi) else: self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) # # # ngh = NetworkXGraphHelper(self.__original_graph) # ngh.draw_graph(nodes_1=terminals, # nodes_2=[poi], # subgraphs_1=[r for _, (r, _, _) in self.__graph.contracted_regions.iteritems()], # node_weight_generator=generator, # node_size=25) # # # ngh = NetworkXGraphHelper(self.__graph) # ngh.draw_graph(node_weight_generator=generator, node_size=25, node_labels=True) # Copy distances and paths dictionary since it will be changed. dist_paths = None if dist_paths_suitable_nodes is not None: dist_paths = dict(dist_paths_suitable_nodes) for e in terminals_poi: dist_paths[e] = dijkstra(self.__graph, e) # Get the suitable nodes. if within_convex_hull: self.__suitable_nodes = self.__graph.get_suitable_nodes_within_convex_set( terminals_poi, generator, dist_paths) else: self.__suitable_nodes = self.__graph.get_suitable_nodes( generator, excluded_nodes=terminals_poi) # print(self.__suitable_nodes) # self.__dist_paths_node_node = {} if dist_paths is not None: self.__dist_paths_node_node = { n: dist_paths[n] for n in self.__suitable_nodes } else: self.__dist_paths_node_node = \ {n: dijkstra(self.__graph, n) for n in self.__suitable_nodes} for e in terminals_poi: if e not in self.__dist_paths_node_node: self.__dist_paths_node_node[e] = dijkstra(self.__graph, e) # max_distances = [ max(self.__dist_paths_node_node[n][0].values()) for n in self.__suitable_nodes if len(self.__dist_paths_node_node[n][0].values()) > 0 ] if len(max_distances) > 0: self.__max_dist = max(max_distances) else: self.__max_dist = 0 # # # max_level_attraction_poi = 0 # for t in terminals: # max_level_attraction_poi = max(max_level_attraction_poi, len(self.__dist_paths_node_node[poi][1][t])) # mass = self.__calculate_mass_suitable_node(poi) # self.__attract_nodes_to(poi, mass, poi, max_level_attraction_poi, 0, []) # dist_to_poi = {} for n in self.__suitable_nodes: try: dist_to_poi[n] = self.__dist_paths_node_node[n][0][poi] except KeyError: dist_to_poi[n] = sys.maxint # dist_to_poi = {n: self.__dist_paths_node_node[n][0][poi] for n in self.__suitable_nodes} # ord_suit_nodes = sorted(dist_to_poi.iteritems(), key=operator.itemgetter(1), reverse=True) ord_suit_nodes = sorted(dist_to_poi.iteritems(), key=operator.itemgetter(1)) for n, _ in ord_suit_nodes: mass = self.__calculate_mass_suitable_node(n) self.__attract_nodes_to(n, mass, n, max_level_attraction, 0, []) # # # ngh = NetworkXGraphHelper(self.__graph) # ngh.draw_graph(node_weight_generator=generator, node_size=25, node_labels=False) ''' ''' def __calculate_mass_suitable_node(self, node): hits = 0 for t in self.__terminals: p = self.__dist_paths_node_node[self.__poi][1][t] if node in p: hits += 10 mass = 0 if node in self.__graph.contracted_regions: region = self.__graph.contracted_regions[node][0] for n in region: mass += 1. / region[n][0] * 100 else: mass = 1. / self.__graph[node][0] * 100 return mass + hits ''' ''' def __calculate_adjusted_edge_cost(self, edge_cost, mass_attracting_node, distance_from_attracting_node): if self.__max_dist > 0: scaled_dist = float( distance_from_attracting_node) / self.__max_dist else: scaled_dist = 1 return edge_cost * scaled_dist / mass_attracting_node ''' ''' def __attract_nodes_to(self, attracting_node, mass_attracting_node, current_node, level_attraction, distance_so_far, already_affected_edges): if level_attraction < 1: return for neighbour in self.__graph[current_node][1]: edge = tuple(sorted([current_node, neighbour])) distance_from_attracting_node = self.__dist_paths_node_node[ attracting_node][0][neighbour] edge_cost = self.__graph[current_node][1][neighbour] if distance_so_far + edge_cost == distance_from_attracting_node and edge not in already_affected_edges: adjusted_edge_cost = \ self.__calculate_adjusted_edge_cost(edge_cost, mass_attracting_node, distance_from_attracting_node) self.__graph[current_node][1][neighbour] = adjusted_edge_cost self.__graph[neighbour][1][current_node] = adjusted_edge_cost already_affected_edges.append(edge) self.__attract_nodes_to(attracting_node, mass_attracting_node, neighbour, level_attraction - 1, distance_so_far + edge_cost, already_affected_edges) def __find_closest_node_to_node_within_region(self, node, region_id): region = self.__graph.contracted_regions[region_id][0] min_dist = sys.maxint closest_node = None distances, paths = dijkstra(self.__original_graph, node, region.keys()) for n in region: if distances[n] < min_dist: closest_node = n min_dist = distances[n] return closest_node, paths[closest_node] def __decontract_steiner_tree(self, steiner_tree): regions = [] paths = [] trees = [] for r in steiner_tree: if r in self.__graph.contracted_regions: regions.append(r) neighbors = steiner_tree[r][1].keys() new_terminals = [] for n in neighbors: closest_node_to_n, path = self.__find_closest_node_to_node_within_region( n, r) paths.append(path) new_terminals.append(closest_node_to_n) del steiner_tree[n][1][r] if len(new_terminals) > 1: region = self.__graph.contracted_regions[r][0] g = Gravitation(region, new_terminals[1:], new_terminals[0], contract_graph=False) st = g.steiner_tree() trees.append(st) for r in regions: del steiner_tree[r] for p in paths: steiner_tree.append_path(p, self.__original_graph) for st in trees: steiner_tree.append_graph(st) # Fix the edge costs. for v in steiner_tree: for w in steiner_tree[v][1]: steiner_tree[v][1][w] = self.__original_graph[v][1][w] @staticmethod def __merge_subtrees(subtrees): result = SuitabilityGraph() for subtree in subtrees: result.append_graph(subtree) return result def __prune_steiner_tree(self, steiner_tree): while True: keys_to_prune = [] for n in steiner_tree: if n not in self.__terminals and n != self.__poi: neighbours = steiner_tree[n][1].keys() if len(neighbours) == 1: neighbour = neighbours[0] del steiner_tree[neighbour][1][n] keys_to_prune.append(n) if len(keys_to_prune) == 0: break for n in keys_to_prune: del steiner_tree[n] def steiner_tree(self): subtrees = [] _, paths = dijkstra(self.__graph, self.__poi, self.__terminals) for t in self.__terminals: path = paths[t] subtree = SuitabilityGraph() # j = 0 # for i in range(len(path_to_poi)): # if path_to_poi[i] in self.__graph.contracted_regions: # region_id = path_to_poi[i] # subtree.append_from_path(path_to_poi[j:i], self.__original_graph) # closest_node = self.__find_closest_node_to_poi_within_region(region_id) # path_endpoint_1 = self.__dist_paths_node_within_region_node[closest_node][1][path_to_poi[i - 1]] # subtree.append_from_path(path_endpoint_1, self.__original_graph) # path_endpoint_2 = self.__dist_paths_node_within_region_node[closest_node][1][path_to_poi[i + 1]] # subtree.append_from_path(path_endpoint_2, self.__original_graph) # j = i + 1 # subtree.append_from_path(path_to_poi[j:], self.__original_graph) subtree.append_path(path, self.__graph) subtrees.append(subtree) steiner_tree = self.__merge_subtrees(subtrees) self.__prune_steiner_tree(steiner_tree) if self.__contract_graph: self.__decontract_steiner_tree(steiner_tree) return steiner_tree
def __merge_subtrees(subtrees): result = SuitabilityGraph() for subtree in subtrees: result.append_graph(subtree) return result
seed = 1 m = n = 50 gh = GridDigraphGenerator() node_weighted = gh.generate(m, n, edge_weighted=True, node_weighted=True, node_weight_generator=generator, seed=seed) # pois = [359, 834, 520, 378, 755, 616, 1, 435] # pois = [359, 834] # terminals = [123, 456, 463, 897, 506, 639, 343, 232, 564, 766, 138, 469, 800] suitability_graph = SuitabilityGraph() suitability_graph.append_graph(node_weighted) suitability_graph.extend_suitable_regions(seed, generator) suitability_graph.extend_suitable_regions(seed, generator) suitability_graph.extend_suitable_regions(seed, generator) suitability_graph.extend_suitable_regions(seed, generator) hotspots = suitability_graph.get_suitable_nodes(generator) terminals = np.random.choice(a=m * n, size=60, replace=False) while set(suitability_graph.keys()).intersection(terminals) != set( terminals) or set(hotspots).intersection(terminals) != set(): terminals = np.random.choice(a=m * n, size=60, replace=False) pois = terminals[:15]
seed = 5 m = n = 30 # m = n = 10 gh = GridDigraphGenerator() node_weighted = gh.generate(m, n, edge_weighted=True, node_weighted=True, node_weight_generator=generator, seed=seed) terminals = [288, 315, 231, 312, 111, 609, 645, 434, 654, 469, 186] # terminals = [36, 78, 28, 11] suitability_graph = SuitabilityGraph() suitability_graph.append_graph(node_weighted) suitability_graph.extend_suitable_regions(seed, generator) suitability_graph.extend_suitable_regions(seed, generator) regions = suitability_graph.get_suitable_regions(generator) start_time = time.clock() dr = DreyfusIMRV2(suitability_graph, terminals, contract_graph=True, within_convex_hull=False) steiner_tree = dr.steiner_tree(consider_terminals=False) elapsed_time = time.clock() - start_time
# node_weights[1221] = generator.weights['VERY_SUITABLE'][0] gh = GridDigraphGenerator() node_weighted = gh.generate( m, n, edge_weighted=True, node_weighted=True, node_weight_generator=generator, # node_weights=node_weights, seed=seed) terminals = [742, 870, 776, 578] suitability_graph = SuitabilityGraph() suitability_graph.append_graph(node_weighted) suitability_graph.extend_suitable_regions(seed, generator) suitability_graph.extend_suitable_regions(seed, generator) suitability_graph.extend_suitable_regions(seed, generator) suitability_graph.extend_suitable_regions(seed, generator) regions = suitability_graph.get_suitable_regions(generator) suitable_nodes = suitability_graph.get_suitable_nodes( generator, excluded_nodes=terminals) dist, _ = dijkstra(suitability_graph, terminals[0], terminals[1:]) upper_bound = sum([dist[t] for t in terminals[1:]])
results = [] generator = SuitableNodeWeightGenerator() # try: for seed in seeds: print("seed:", seed) for msns in range(len(ms)): print("nodes:", ms[msns] * ns[msns]) graph = GridDigraphGenerator().generate( ms[msns], ns[msns], node_weighted=True, node_weight_generator=generator, seed=seed) suitability_graph = SuitabilityGraph() suitability_graph.append_graph(graph) hotspots = suitability_graph.get_suitable_nodes(generator) start_time = time.clock() suitability_graph.compute_dist_paths(origins=hotspots, destinations=hotspots, compute_paths=False) print "compute", time.clock() - start_time, "# hotspots:", len( hotspots) for num_seats in capacity: # suitability_graph.extend_suitable_regions(seed, generator) # hotspots = suitability_graph.get_suitable_nodes(generator) # print i, "# hotspots:", len(hotspots) for num_terminals in nums_terminals:
def Ai(self, k, r, X, i): T = SuitabilityGraph() while k > 0: TBEST = SuitabilityGraph() for kprime in range(1, k + 1): for v in self.__nodes: if i > 1: Tprime = self.Ai(kprime, v, X, i - 1) p = self.__paths[tuple(sorted([r, v]))] Tprime.append_path(p, self.__graph) else: dists = {} for t in self.__terminals: dists[t] = self.__dist[tuple(sorted([v, t]))] ord_term = sorted(dists.iteritems(), key=operator.itemgetter(1)) Tprime = SuitabilityGraph() for j in range(kprime): p = self.__paths[tuple(sorted([v, ord_term[j][0]]))] Tprime.append_path(p, self.__graph) if self.d(TBEST) > self.d(Tprime): TBEST = Tprime T.append_graph(TBEST) k -= len(set(TBEST.keys()).intersection(X)) X = set(X).difference(TBEST.keys()) return T
class ClusterBased: def __init__(self, graph, terminals): # Check whether graph is node-weighted. if not graph.is_node_weighted(): raise ( ValueError, "Cluster-based algorithm only works with node-weighted graphs." ) # Extract POI from the terminals list. if len(terminals) > 0: self.__poi = terminals[0] else: return # generator = SuitableNodeWeightGenerator() # Set object variables. self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) self.__terminals = terminals # # self.__regions = self.__graph.get_suitable_regions(generator, excluded_nodes=terminals, # get_border_internal_nodes=True, get_centroid_medoid=True, # get_characteristic_nodes=True) self.__regions = self.__graph.get_suitable_regions( generator, excluded_nodes=terminals, get_border_internal_nodes=True, get_centroid_medoid=True) # self.__nodes = [] for id_r in self.__regions: # # characteristic_nodes = self.__regions[id_r][6] # self.__nodes.extend(characteristic_nodes) border_nodes = self.__regions[id_r][1] self.__nodes.extend(border_nodes) # # if len(characteristic_nodes) == 0: # medoid = self.__regions[id_r][4] # # print(medoid) # self.__nodes.append(medoid) for t in terminals: self.__nodes.append(t) # self.__dist, self.__paths = self.__graph.get_dist_paths( origins=self.__nodes, destinations=self.__nodes) ''' ''' def steiner_tree(self, consider_terminals=False): dr = DreyfusIMR(graph=self.__graph, terminals=self.__terminals, contract_graph=False, nodes=self.__nodes, dist_paths=(self.__dist, self.__paths)) if consider_terminals: steiner_tree = dr.steiner_tree(consider_terminals=True) else: steiner_tree = dr.steiner_tree(consider_terminals=False) # self.__refine_steiner_tree(steiner_tree) return steiner_tree ''' ''' def __refine_steiner_tree(self, steiner_tree): clusters = [] for id_r in self.__regions: region = self.__regions[id_r][0] for n in steiner_tree: if n in region: clusters.append(id_r) break print clusters
def generate_graph(results, generator, cost_type="distance", capacitated=False): graph = SuitabilityGraph(capacitated=capacitated) # prev_way_id = None prev_node_id = None hotspots = set() pois = set() for r in results: way_id = r[0] node_id = r[1] type_ = r[3] stype = r[4] poi_name = r[5] lat = float(r[6]) lon = float(r[7]) sa1_code = r[8] sa2_code = r[9] hw_type = r[10] if node_id not in graph: if type_ == "hotspot": graph[node_id] = (generator.weights["VERY_SUITABLE"][0], {}, {'lat': lat, 'lon': lon, 'sa1': sa1_code, 'sa2': sa2_code, 'subtype': stype}) hotspots.add(node_id) else: if type_ == "poi": pois.add(node_id) graph[node_id] = (generator.weights["WARNING"][0], {}, {'lat': lat, 'lon': lon, 'sa1': sa1_code, 'sa2': sa2_code, 'subtype': stype, 'name': poi_name}) if prev_way_id == way_id: prev_lat = graph[prev_node_id][2]['lat'] prev_lon = graph[prev_node_id][2]['lon'] # Cost estimation cost = 0 distance = haversine(lat, lon, prev_lat, prev_lon) if cost_type == "distance": cost = distance elif cost_type == "travel_time": cost = osm_avg(distance, hw_type) # graph[node_id][1][prev_node_id] = cost graph[prev_node_id][1][node_id] = cost prev_way_id = way_id prev_node_id = node_id # # pdb.set_trace() isolated = [] # Both dictionaries will INCLUDE HOT SPOTS AND POIs. nodes_by_sa1_code = {} nodes_by_sa2_code = {} # for node_id, info in graph.iteritems(): if len(info[1]) == 0 or (len(info[1]) == 1 and info[1].keys()[0] == node_id): isolated.append(node_id) else: sa1_code = info[2]['sa1'] sa2_code = info[2]['sa2'] if sa1_code in nodes_by_sa1_code: nodes_by_sa1_code[sa1_code].append(node_id) else: nodes_by_sa1_code[sa1_code] = [node_id] if sa2_code in nodes_by_sa2_code: nodes_by_sa2_code[sa2_code].append(node_id) else: nodes_by_sa2_code[sa2_code] = [node_id] for node_id in isolated: del graph[node_id] if node_id in hotspots: hotspots.remove(node_id) if node_id in pois: pois.remove(node_id) # print "h:", len(hotspots), "p:", len(pois) return graph, list(hotspots), list(pois), nodes_by_sa1_code, nodes_by_sa2_code
class LazySteinerTree: def __init__(self, graph, terminals, hot_spots=None, generator=None, distances=None): # Check whether graph is node-weighted. if not graph.is_node_weighted(): raise (ValueError, "Lazy Steiner Tree only works with node-weighted graphs.") # Extract POI from the terminals list. if len(terminals) > 0: self.__poi = terminals[0] else: return # Set object variables. self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) self.__terminals = terminals self.__hot_spots = None self.__nodes = None self.__s_d = {} self.__paths = {} self.__refs = {} # Set hot spots. if hot_spots is None: if generator is None: generator = SuitableNodeWeightGenerator() self.__hot_spots = self.__graph.get_suitable_nodes( generator, excluded_nodes=terminals) else: self.__hot_spots = list(hot_spots) # Set nodes = hot spots + terminals. self.__nodes = list(self.__hot_spots) for t in terminals: self.__nodes.append(t) # Set distances. if distances is None: len_hot_spots = len(self.__hot_spots) self.__distances = {} for t in self.__terminals: dist, paths = dijkstra(self.__graph, t, self.__nodes) for n in self.__nodes: try: self.__distances[tuple(sorted([t, n]))] = (dist[n], 'N') self.__paths[tuple(sorted([t, n]))] = paths[n] except KeyError: self.__distances[tuple(sorted([t, n]))] = (sys.maxint, 'N') self.__paths[tuple(sorted([t, n]))] = [] for h1 in self.__hot_spots: for i in range(self.__hot_spots.index(h1), len_hot_spots): h2 = self.__hot_spots[i] distance = 0 d_type = 'E' if h1 == h2: d_type = 'N' else: distance = haversine(self.__graph[h1][2]['lat'], self.__graph[h1][2]['lon'], self.__graph[h2][2]['lat'], self.__graph[h2][2]['lon']) self.__distances[tuple(sorted([h1, h2]))] = (distance, d_type) else: self.__distances = dict(distances) ''' ''' @staticmethod def __create_subsets_e(set_): sets_e = [tuple([set_[0]])] l_set = len(set_) for x in range(1, l_set - 1): for y in comb(set_[1:], x): t = [set_[0]] t.extend(y) sets_e.append(tuple(t)) return sets_e def steiner_tree(self, h_l_sd=20, h_l_hot_spots=3, consider_terminals=False): # set_c = tuple(sorted(self.__terminals[1:])) t_tuples = [tuple([t]) for t in set_c] # for j in self.__nodes: self.__s_d[j] = {} for t in t_tuples: dist, d_t = self.__distances[tuple(sorted([j, t[0]]))] self.__s_d[j][t] = [[ dist, 0, dist, t[0], (None, None), d_t, d_t, d_t, d_t, 0 ]] # for m in range(2, len(set_c)): # sets_d = [tuple(set_d) for set_d in comb(set_c, m)] for set_d in sets_d: # target_hot_spots = CandidatesList(h_l_hot_spots) for i in self.__nodes: self.__s_d[i][set_d] = CandidatesList(h_l_sd) # sets_e = self.__create_subsets_e(set_d) # for j in self.__nodes: u = sys.maxint sets_e_f = None d_ts = None for set_e in sets_e: set_f = tuple(sorted(list(set(set_d) - set(set_e)))) if len(set_f) > 0: s = self.__s_d[j][set_e][0][0] + self.__s_d[j][ set_f][0][0] else: s = self.__s_d[j][set_e][0][0] if s < u: u = s sets_e_f = (set_e, set_f) d_ts = (self.__s_d[j][set_e][0][5], self.__s_d[j][set_f][0][5]) for i in self.__nodes: try: dist, d_t = self.__distances[tuple(sorted([i, j]))] except KeyError: dist = sys.maxint d_t = 'N' if consider_terminals: cost = dist + u # if cost < self.__steiner_distances[i][set_d][0][0]: if cost < sys.maxint: dd_t = 'E' if d_t == 'N' and d_ts[0] == 'N' and d_ts[ 1] == 'N': dd_t = 'N' self.__s_d[i][set_d].append([ cost, u, dist, j, sets_e_f, dd_t, d_t, d_ts[0], d_ts[1], 0 ]) # dist_to_poi = self.__distances[tuple(sorted([self.__poi, i]))][0] # target_hot_spots.append([dist_to_poi + cost, i]) else: cost = dist + u # if cost < self.__steiner_distances[i][set_d][0][0] and j not in self.__terminals: if j not in self.__terminals and cost < sys.maxint: dd_t = 'E' if d_t == 'N' and d_ts[0] == 'N' and d_ts[ 1] == 'N': dd_t = 'N' self.__s_d[i][set_d].append([ cost, u, dist, j, sets_e_f, dd_t, d_t, d_ts[0], d_ts[1], 0 ]) # dist_to_poi = self.__distances[tuple(sorted([self.__poi, i]))][0] # target_hot_spots.append([dist_to_poi + cost, i]) target_hot_spots = CandidatesList(h_l_hot_spots) for i in self.__nodes: cost = self.__s_d[i][set_d][0][0] j = self.__s_d[i][set_d][0][3] set_e, set_f = self.__s_d[i][set_d][0][4] dist_to_poi = self.__distances[tuple( sorted([self.__poi, i]))][0] target_hot_spots.append([dist_to_poi + cost, i]) if j in self.__refs: if set_e in self.__refs[j]: self.__refs[j][set_e].add((i, set_d)) else: self.__refs[j][set_e] = {(i, set_d)} if set_f in self.__refs[j]: self.__refs[j][set_f].add((i, set_d)) else: self.__refs[j][set_f] = {(i, set_d)} else: self.__refs[j] = { set_e: {(i, set_d)}, set_f: {(i, set_d)} } # which is the best node for steiner tree between terminals in D and POI # print('-------------------------------------------------------') # print(set_d) # print('-------------------------------------------------------') # self.__print_target_hot_spots(target_hot_spots, set_d) # print('-------------------------------------------------------') # pdb.set_trace() self.__correct_i_s(target_hot_spots, set_d) self.__print_target_hot_spots(target_hot_spots, set_d) # print('-------------------------------------------------------') # sets_e = self.__create_subsets_e(set_c) # # cost = sys.maxint target_hot_spots = CandidatesList(h_l_hot_spots) self.__s_d[self.__poi][set_c] = CandidatesList(h_l_sd) for j in self.__nodes: u = sys.maxint sets_e_f = None d_ts = None for set_e in sets_e: set_f = tuple(sorted(list(set(set_c) - set(set_e)))) if len(set_f) > 0: s = self.__s_d[j][set_e][0][0] + self.__s_d[j][set_f][0][0] else: s = self.__s_d[j][set_e][0][0] if s < u: u = s sets_e_f = (set_e, set_f) d_ts = (self.__s_d[j][set_e][0][5], self.__s_d[j][set_f][0][5]) try: dist, d_t = self.__distances[tuple(sorted([self.__poi, j]))] except KeyError: dist = sys.maxint d_t = 'N' if consider_terminals: # if dist + u < cost: dd_t = 'E' if d_t == 'N' and d_ts[0] == 'N' and d_ts[1] == 'N': dd_t = 'N' cost = dist + u if cost < sys.maxint: self.__s_d[self.__poi][set_c].append([ cost, u, dist, j, sets_e_f, dd_t, d_t, d_ts[0], d_ts[1], 0 ]) target_hot_spots.append([cost, self.__poi]) else: cost = dist + u if j not in self.__terminals and cost < sys.maxint: dd_t = 'E' if d_t == 'N' and d_ts[0] == 'N' and d_ts[1] == 'N': dd_t = 'N' self.__s_d[self.__poi][set_c].append([ cost, u, dist, j, sets_e_f, dd_t, d_t, d_ts[0], d_ts[1], 0 ]) target_hot_spots.append([cost, self.__poi]) j = self.__s_d[self.__poi][set_c][0][3] set_e, set_f = self.__s_d[self.__poi][set_c][0][4] if j in self.__refs: if set_e in self.__refs[j]: self.__refs[j][set_e].add((self.__poi, set_c)) else: self.__refs[j][set_e] = {(self.__poi, set_c)} if set_f in self.__refs[j]: self.__refs[j][set_f].add((self.__poi, set_c)) else: self.__refs[j][set_f] = {(self.__poi, set_c)} else: self.__refs[j] = { set_e: {(self.__poi, set_c)}, set_f: {(self.__poi, set_c)} } # print('-------------------------------------------------------') # print(set_c) # print('-------------------------------------------------------') # self.__print_target_hotspots(target_hot_spots, set_c) # print('-------------------------------------------------------') # pdb.set_trace() # self.__print_target_hot_spots(target_hot_spots, set_c) # pdb.set_trace() self.__correct_i_s(target_hot_spots, set_c) # print('-------------------------------------------------------') # # # while True: # delta_cost = self.__steinerify(self.__poi, set_c) # if delta_cost == 0: # break # # Reconstruct the Steiner by backtracking steiner_tree = self.__build_steiner_tree(self.__poi, set_c) # return steiner_tree # def __correct_i_s(self, target_hot_spots, subset): # while len(target_hot_spots) > 0: # # pdb.set_trace() # i = target_hot_spots[0][1] # dd_t = self.__s_d[i][subset][0][5] # if dd_t == 'E': # self.__correct_j_s(i, subset) # target_hot_spots.pop(0) def __correct_i_s(self, target_hot_spots, subset): if len(target_hot_spots) > 0: # target_hot_spots.sort() i = target_hot_spots[0][1] dd_t = self.__s_d[i][subset][0][5] # while dd_t == 'E': # delta = self.__correct_j_s(i, subset) target_hot_spots[0][0] += delta # target_hot_spots.sort() i = target_hot_spots[0][1] dd_t = self.__s_d[i][subset][0][5] def __propagate(self, delta, j, subset): try: for i, subset_i in self.__refs[j][subset]: # if i == 552618963: # print(subset_i, self.__s_d[i][subset_i][0][0], delta, j, subset) self.__s_d[i][subset_i][0][0] += delta self.__s_d[i][subset_i][0][1] += delta self.__propagate(delta, i, subset_i) except KeyError: pass def __correct_j_s(self, i, subset): # # self.__s_d[i][subset].sort() j = self.__s_d[i][subset][0][3] old_j = j old_set_e, old_set_f = self.__s_d[i][subset][0][4] dd_t = self.__s_d[i][subset][0][5] count = 0 # while dd_t == 'E': # ---------------------------------------------------------------------------------------------------------- delta_dist = 0 d_t_1 = self.__s_d[i][subset][0][6] if d_t_1 == 'E': # i_j_tuple = tuple(sorted([i, j])) if self.__distances[i_j_tuple][1] == 'N': dist = self.__distances[i_j_tuple][0] else: try: distances, _ = dijkstra(self.__graph, i, [j]) dist = distances[j] self.__distances[i_j_tuple] = (dist, 'N') except KeyError: dist = sys.maxint old_dist = self.__s_d[i][subset][0][2] delta_dist = dist - old_dist # self.__s_d[i][subset][0][0] += delta_dist self.__s_d[i][subset][0][2] = dist self.__s_d[i][subset][0][6] = 'N' # ---------------------------------------------------------------------------------------------------------- delta_u = 0 d_t_2 = self.__s_d[i][subset][0][7] d_t_3 = self.__s_d[i][subset][0][8] if d_t_2 == 'E' or d_t_3 == 'E': # if i == 3073194802L and subset == (30287961, 313278858, 1011956802, 1655220587): # pdb.set_trace() u, set_e, set_f, delta_e, delta_f = self.__correct_e_f( j, subset) self.__s_d[i][subset][0][4] = (set_e, set_f) delta_u = delta_e + delta_f # if u != self.__s_d[i][subset][0][1]: delta_u = u - self.__s_d[i][subset][0][1] self.__s_d[i][subset][0][0] += delta_u self.__s_d[i][subset][0][1] += delta_u self.__s_d[i][subset][0][7] = 'N' self.__s_d[i][subset][0][8] = 'N' # ---------------------------------------------------------------------------------------------------------- d_t_1 = self.__s_d[i][subset][0][6] d_t_2 = self.__s_d[i][subset][0][7] d_t_3 = self.__s_d[i][subset][0][8] if d_t_1 == 'N' and d_t_2 == 'N' and d_t_3 == 'N': self.__s_d[i][subset][0][5] = 'N' # delta = delta_dist + delta_u self.__s_d[i][subset][0][9] = delta if delta > 0 and count == 0: self.__propagate(delta, i, subset) if self.__s_d[i][subset][0][5] == 'N': try: del self.__refs[i][subset] except KeyError: pass count += 1 # self.__s_d[i][subset].sort() j = self.__s_d[i][subset][0][3] dd_t = self.__s_d[i][subset][0][5] # Update refs j = self.__s_d[i][subset][0][3] set_e, set_f = self.__s_d[i][subset][0][4] if j != old_j or set_e != old_set_e or set_f != old_set_f: # try: self.__refs[old_j][old_set_e].remove((i, subset)) self.__refs[old_j][old_set_f].remove((i, subset)) except KeyError: pass # if j in self.__refs: if set_e in self.__refs[j]: self.__refs[j][set_e].add((i, subset)) else: self.__refs[j][set_e] = {(i, subset)} if set_f in self.__refs[j]: self.__refs[j][set_f].add((i, subset)) else: self.__refs[j][set_f] = {(i, subset)} else: self.__refs[j] = {set_e: {(i, subset)}, set_f: {(i, subset)}} return self.__s_d[i][subset][0][9] def __create_subsets_e_f(self, j, set_): subsets_e_f = [] sets_e = self.__create_subsets_e(set_) for set_e in sets_e: set_f = tuple(sorted(list(set(set_) - set(set_e)))) if len(set_f) > 0: s = self.__s_d[j][set_e][0][0] + self.__s_d[j][set_f][0][0] else: s = self.__s_d[j][set_e][0][0] subsets_e_f.append([s, set_e, set_f, 0, 0]) return subsets_e_f def __correct_e_f(self, j, set_): # subsets_e_f = self.__create_subsets_e_f(j, set_) # subsets_e_f.sort() set_e = subsets_e_f[0][1] set_f = subsets_e_f[0][2] dd_t_e = self.__s_d[j][set_e][0][5] dd_t_f = self.__s_d[j][set_f][0][5] while dd_t_e == 'E' or dd_t_f == 'E': # delta_e = self.__correct_j_s(j, set_e) delta_f = self.__correct_j_s(j, set_f) subsets_e_f[0][0] += delta_e + delta_f subsets_e_f[0][3] = delta_e subsets_e_f[0][4] = delta_f # subsets_e_f.sort() set_e = subsets_e_f[0][1] set_f = subsets_e_f[0][2] dd_t_e = self.__s_d[j][set_e][0][5] dd_t_f = self.__s_d[j][set_f][0][5] return subsets_e_f[0] def __print_target_hot_spots(self, target_hot_spots, subset): for th in target_hot_spots: dist_to_poi = th[0] i = th[1] j = self.__s_d[i][subset][0][3] dd_type = self.__s_d[i][subset][0][5] d_type_1 = self.__s_d[i][subset][0][6] d_type_2 = self.__s_d[i][subset][0][7] d_type_3 = self.__s_d[i][subset][0][8] print(dist_to_poi, i, j, dd_type, d_type_1, d_type_2, d_type_3) def __build_steiner_tree(self, node, subset): steiner_tree = SuitabilityGraph() next_node = self.__s_d[node][subset][0][3] print(node, self.__s_d[node][subset]) # pdb.set_trace() if next_node is not None: try: steiner_tree.append_path( self.__paths[tuple(sorted([node, next_node]))], self.__graph) except KeyError: _, paths = dijkstra(self.__graph, node, [next_node]) steiner_tree.append_path(paths[next_node], self.__graph) (set_e, set_f) = self.__s_d[node][subset][0][4] steiner_branch_e = SuitabilityGraph() if set_e is not None and set_e != [next_node]: steiner_branch_e = self.__build_steiner_tree(next_node, set_e) steiner_branch_f = SuitabilityGraph() if set_f is not None and set_f != [next_node] and len(set_f) > 0: steiner_branch_f = self.__build_steiner_tree(next_node, set_f) steiner_tree.append_graph(steiner_branch_e) steiner_tree.append_graph(steiner_branch_f) return steiner_tree
generator = SuitableNodeWeightGenerator() results = [] try: for seed in range(num_seeds): for size in sizes: graph = GridDigraphGenerator().generate( size, size, node_weighted=True, node_weight_generator=generator, seed=seed) suitability_graph = SuitabilityGraph() suitability_graph.append_graph(graph) total_num_suitable_nodes = len( suitability_graph.get_suitable_nodes(generator)) for num_terminals in nums_terminals: for sample in range(num_samples): line = [ seed, size * size, total_num_suitable_nodes, num_terminals, sample + 1 ] terminals = np.random.choice(a=size * size,
def __init__(self, graph, terminals, hot_spots=None, generator=None, distances=None): # Check whether graph is node-weighted. if not graph.is_node_weighted(): raise (ValueError, "Lazy Steiner Tree only works with node-weighted graphs.") # Extract POI from the terminals list. if len(terminals) > 0: self.__poi = terminals[0] else: return # Set object variables. self.__graph = SuitabilityGraph() self.__graph.append_graph(graph) self.__terminals = terminals self.__hot_spots = None self.__nodes = None self.__s_d = {} self.__paths = {} self.__refs = {} # Set hot spots. if hot_spots is None: if generator is None: generator = SuitableNodeWeightGenerator() self.__hot_spots = self.__graph.get_suitable_nodes( generator, excluded_nodes=terminals) else: self.__hot_spots = list(hot_spots) # Set nodes = hot spots + terminals. self.__nodes = list(self.__hot_spots) for t in terminals: self.__nodes.append(t) # Set distances. if distances is None: len_hot_spots = len(self.__hot_spots) self.__distances = {} for t in self.__terminals: dist, paths = dijkstra(self.__graph, t, self.__nodes) for n in self.__nodes: try: self.__distances[tuple(sorted([t, n]))] = (dist[n], 'N') self.__paths[tuple(sorted([t, n]))] = paths[n] except KeyError: self.__distances[tuple(sorted([t, n]))] = (sys.maxint, 'N') self.__paths[tuple(sorted([t, n]))] = [] for h1 in self.__hot_spots: for i in range(self.__hot_spots.index(h1), len_hot_spots): h2 = self.__hot_spots[i] distance = 0 d_type = 'E' if h1 == h2: d_type = 'N' else: distance = haversine(self.__graph[h1][2]['lat'], self.__graph[h1][2]['lon'], self.__graph[h2][2]['lat'], self.__graph[h2][2]['lon']) self.__distances[tuple(sorted([h1, h2]))] = (distance, d_type) else: self.__distances = dict(distances)