Ejemplo n.º 1
0
def test_merge_nearby_nodes():
    """                       
         --2                    2
        /                      /
      --                      /
     /                       /
    1                       /
     \                     /
      0-----------5   =>  0------------5
     / 
    3 
    |
    4

    """

    coords = [[ 0,  0],
              [-1,  1],
              [ 2,  6],
              [-1, -1],
              [-1, -2],
              [ 5,  0]]

    edges = [(0, 1), (1, 2), (0, 3), (3, 4), (0, 5)]

    geo = GeoGraph(coords=dict(enumerate(coords)), data=edges)
    geo.merge_nearby_nodes(radius=2.0)
    assert geo.edges() == [(0, 2), (0, 5)],\
        "nodes were not merged correctly"
Ejemplo n.º 2
0
def build_network(demand_nodes, 
                    existing=None, 
                    min_node_count=2,
                    single_network=True,
                    network_algorithm='mod_boruvka',
                    one_based=False 
                    ):
    """
    project demand nodes onto optional existing supply network and
    return the 'optimized' network

    Args:
        demand_nodes:  GeoGraph of demand nodes
        existing:  GeoGraph of existing grid (assumes node ids
            don't conflict with demand_nodes
        min_node_count:  minimum number of nodes allowed in a subgraph
            of the result
        network_algorithm:  Algorithm from ALGOS to run
        one_based:  Whether result GeoGraph's nodes should be one_based
            (if not, they are 0 based)

    Returns:
        msf: GeoGraph of minimum spanning forest proposed by the chosen
            network algorithm
        existing: The existing grid GeoGraph (None if it doesn't exist) 
        
    """
    geo_graph = subgraphs = rtree = None

    if existing:
        log.info("merging network and nodes")
        geo_graph, subgraphs, rtree = \
            merge_network_and_nodes(existing, demand_nodes, 
                single_network=single_network)
    else:
        geo_graph = demand_nodes

    log.info("running {} on {} demand nodes and {} total nodes".format(
              network_algorithm, len(demand_nodes), len(geo_graph)))

    # now run the selected algorithm
    network_algo = NetworkerRunner.ALGOS[network_algorithm]
    result_geo_graph = network_algo(geo_graph, subgraphs=subgraphs,
                                    rtree=rtree)

    # TODO: Remove unreferenced fake nodes?

    # now filter out subnetworks via minimum node count
    # TODO:  update union_all to support GeoGraph?
    filtered_graph = nx.union_all(filter(
        lambda sub: len(sub.node) >= min_node_count,
        nx.connected_component_subgraphs(result_geo_graph)))

    # map coords back to geograph
    # NOTE:  explicit relabel to int as somewhere in filtering above, some
    # node ids are set to numpy types which screws up comparisons to tuples
    # in write op
    # NOTE:  relabeling nodes in-place here drops node attributes for some
    #   reason so create a copy for now
    def id_label(i): 
        id = int(i+1) if one_based else int(i)
        return id

    msf = None
    if filtered_graph:
        coords = {id_label(i): result_geo_graph.coords[i]
                    for i in filtered_graph}
        relabeled = nx.relabel_nodes(filtered_graph, {i: id_label(i)
            for i in filtered_graph}, copy=True)
        msf = GeoGraph(result_geo_graph.srs, coords=coords, data=relabeled)

    log.info("filtered result has {} nodes and {} edges".format(
              len(msf.nodes()), len(msf.edges())))

    return msf
Ejemplo n.º 3
0
def build_network(demand_nodes,
                  existing=None,
                  min_node_count=2,
                  single_network=True,
                  network_algorithm='mod_boruvka',
                  spherical_accuracy=False,
                  one_based=False):
    """
    project demand nodes onto optional existing supply network and
    return the 'optimized' network

    Args:
        demand_nodes:  GeoGraph of demand nodes
        existing:  GeoGraph of existing grid (assumes node ids
            don't conflict with demand_nodes
        min_node_count:  minimum number of nodes allowed in a subgraph
            of the result
        network_algorithm:  Algorithm from ALGOS to run
        spherical_accuracy:  Whether to connect nodes to network on a sphere
        one_based:  Whether result GeoGraph's nodes should be one_based
            (if not, they are 0 based)

    Returns:
        msf: GeoGraph of minimum spanning forest proposed by the chosen
            network algorithm
        existing: The existing grid GeoGraph (None if it doesn't exist)

    """
    geo_graph = subgraphs = rtree = None

    if existing:
        log.info("merging network and nodes")
        geo_graph, subgraphs, rtree = \
            merge_network_and_nodes(existing, demand_nodes,
                                    single_network=single_network,
                                    spherical_accuracy=spherical_accuracy)
    else:
        geo_graph = demand_nodes

    log.info("running {} on {} demand nodes and {} total nodes".format(
              network_algorithm, len(demand_nodes), len(geo_graph)))

    # now run the selected algorithm
    network_algo = NetworkerRunner.ALGOS[network_algorithm]
    result_geo_graph = network_algo(geo_graph, subgraphs=subgraphs,
                                    rtree=rtree)

    filtered_graph = filter_min_node_subnetworks(result_geo_graph,
                                                 min_node_count)

    # map coords back to geograph
    # NOTE:  explicit relabel to int as somewhere in filtering above, some
    # node ids are set to numpy types which screws up comparisons to tuples
    # in write op
    # NOTE:  relabeling nodes in-place here drops node attributes for some
    #   reason so create a copy for now
    def id_label(i):
        id = int(i+1) if one_based else int(i)
        return id

    msf = GeoGraph(result_geo_graph.srs)
    if filtered_graph:
        coords = {id_label(i): result_geo_graph.coords[i]
                  for i in filtered_graph}
        relabeled = nx.relabel_nodes(filtered_graph, {i: id_label(i)
                                                      for i in filtered_graph},
                                     copy=True)
        msf = GeoGraph(result_geo_graph.srs, coords=coords, data=relabeled)

    log.info("filtered result has {} nodes and {} edges".format(
        len(msf.nodes()), len(msf.edges())))
    return msf