예제 #1
0
 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
예제 #2
0
    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
예제 #3
0
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
예제 #4
0
 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
예제 #5
0
    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()}
예제 #6
0
    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 = {}
예제 #7
0
 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)
예제 #8
0
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
예제 #9
0
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
예제 #10
0
 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
예제 #11
0
 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
예제 #12
0
 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
예제 #13
0
    # 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],
예제 #14
0
    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)
예제 #15
0
    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,
예제 #16
0
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)
예제 #17
0
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)
예제 #18
0
    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, [])
예제 #19
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
예제 #20
0
 def __merge_subtrees(subtrees):
     result = SuitabilityGraph()
     for subtree in subtrees:
         result.append_graph(subtree)
     return result
예제 #21
0
    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]
예제 #22
0
    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
예제 #23
0
    # 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:]])
예제 #24
0
    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:
예제 #25
0
 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
예제 #26
0
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
예제 #27
0
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
예제 #28
0
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
예제 #29
0
    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,
예제 #30
0
 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)