Пример #1
0
def generate_guided_search_figure(G, positions, src, target):
    """Generate Guided Search solution .. ultimately omitted from book."""
    if plt_error:
        return None
    import matplotlib.pyplot as plt

    (G, positions, _) = tmg_load(highway_map())
    plt.clf()
    plot_gps(positions)
    plot_highways(positions, G.edges())

    def distance_gps(from_cell, to_cell):
        """These ids are indexed into positions to get GPS coordinates."""
        return abs(positions[from_cell][0] -
                   positions[to_cell][0]) + abs(positions[from_cell][1] -
                                                positions[to_cell][1])

    node_from = guided_search(G, src, target, distance=distance_gps)
    total = compute_distance(positions, node_from, src, target)

    plot_node_from(positions, src, target, node_from, color='purple')
    print(
        '{0} total steps for Guided Search with distance={1:.1f} miles'.format(
            len(path_to(node_from, src, target)) - 1, total))
    plt.axis('off')
    output_file = image_file('figure-mass-highway-guided.svg')
    plt.savefig(output_file, format="svg")
    print(output_file)
    plt.clf()
    return output_file
Пример #2
0
def generate_bfs_and_dijkstra_figure(src, target):
    """Generate BFS solution overlaying Massachusetts highway."""
    if plt_error:
        return None
    import matplotlib.pyplot as plt

    (G, positions, _) = tmg_load(highway_map())
    (dist_to, edge_to) = dijkstra_sp(G, src)
    print('Dijkstra shortest distance is {} total steps with distance={:.1f}'.
          format(
              len(edges_path_to(edge_to, src, target)) - 1, dist_to[target]))
    path = edges_path_to(edge_to, src, target)
    plt.clf()
    plot_gps(positions)
    plot_highways(positions, G.edges())
    plot_path(positions, path)
    node_from = bfs_search(G, src)
    total = compute_distance(positions, node_from, src, target)

    plot_node_from(positions, src, target, node_from, color='purple')
    print(
        '{0} total steps for Breadth First Search with distance={1:.1f} miles'.
        format(len(path_to(node_from, src, target)) - 1, total))
    plt.axis('off')
    output_file = image_file('figure-mass-highway-bfs.svg')
    plt.savefig(output_file, format="svg")
    print(output_file)
    plt.clf()
    return output_file
Пример #3
0
def chained_dijkstra():
    """Generate Chained Dijkstra results with MA highway data."""
    from ch07.tmg_load import tmg_load, highway_map
    from ch07.dependencies import plt_error
    from ch07.single_source_sp import dijkstra_sp

    if not plt_error:
        (G, positions, _) = tmg_load(highway_map())

        start_time = time.time()
        longest_so_far = 0
        start = -1
        end = -1
        for i in range(G.number_of_nodes()):
            (dist_to, _) = dijkstra_sp(G, i)
            for j in range(i + 1, G.number_of_nodes()):
                if dist_to[j] > longest_so_far:
                    longest_so_far = dist_to[j]
                    start = i
                    end = j

        end_time = time.time()
        print(
            'start {} to end {} in longest shortest distance {} in time {:.3f} seconds'
            .format(positions[start], positions[end], longest_so_far,
                    end_time - start_time))
Пример #4
0
 def test_bounding(self):
     from ch07.tmg_load import tmg_load, highway_map, bounding_ids
     (_, positions, _) = tmg_load(highway_map())
     (NORTH, EAST, SOUTH, WEST) = bounding_ids(positions)
     self.assertTrue(positions[NORTH][0] >
                     positions[SOUTH][0])  # LAT Is higher for north
     self.assertTrue(
         positions[EAST][1] > positions[WEST][1])  # LONG is higher for east
Пример #5
0
    def test_generate_guided_search_figure(self):
        from ch07.book import generate_guided_search_figure
        from ch07.tmg_load import tmg_load, highway_map, bounding_ids
        from ch07.dependencies import plt_error

        if not plt_error:
            (G, positions, _) = tmg_load(highway_map())
            (_, EAST, _, WEST) = bounding_ids(positions)
            output_file = generate_guided_search_figure(
                G, positions, WEST, EAST)
            self.assertTrue(path.isfile(output_file))
Пример #6
0
def avoid_interstate_90():
    """Find shortest path from westernmost-MA to easternmost-MA that avoids I-90."""
    if plt_error:
        return None
    import matplotlib.pyplot as plt
    from ch07.single_source_sp import dijkstra_sp, edges_path_to
    from ch07.tmg_load import tmg_load, plot_gps, plot_highways, bounding_ids
    from resources.highway import highway_map
    from ch07.plot_map import plot_path
    from algs.output import image_file
    (G,positions,labels) = tmg_load(highway_map())

    # Since graph is undirected, we will visit each edge twice. Make sure to
    # only remove when u < v to avoid deleting same edge twice
    edges_to_remove = []
    destination = None
    for u in G.nodes():
        if labels[u] == 'I-90@134&I-93@20&MA3@20(93)&US1@I-93(20)':       # SPECIAL LABEL in BOSTON
            destination = u
        for v in G.adj[u]:
            if 'I-90' in labels[u] and 'I-90' in labels[v] and u < v:
                edges_to_remove.append((u,v))

    (_,_,_,WEST) = bounding_ids(positions)
    (dist_to, edge_to) = dijkstra_sp(G, WEST)
    print('Original Dijkstra shortest distance is {} total steps with distance={:.1f}'.format(len(edges_path_to(edge_to, WEST, destination))-1, dist_to[destination]))

    print('num edges:', G.number_of_edges())
    for e in edges_to_remove:
        G.remove_edge(e[0], e[1])
    print('num edges:', G.number_of_edges())

    # create a new graph whose edges are not wholly on I-90
    (_,_,_,WEST) = bounding_ids(positions)
    (dist_to, edge_to) = dijkstra_sp(G, WEST)
    print('Dijkstra shortest distance avoiding I-90 is {} total steps with distance={:.1f}'.format(len(edges_path_to(edge_to, WEST, destination))-1, dist_to[destination]))
    path = edges_path_to(edge_to,WEST, destination)
    plt.clf()
    plot_gps(positions)
    plot_highways(positions, G.edges())
    plot_path(positions, path)

    output_file = image_file('figure-mass-no-I-90-dijkstra.svg')
    plt.savefig(output_file, format="svg")
    print(output_file)
    plt.clf()
    return output_file
Пример #7
0
def floyd_warshall_highway():
    """Generate Floyd-Warshall results with MA highway data."""
    from ch07.tmg_load import tmg_load, highway_map
    from ch07.dependencies import plt_error

    if not plt_error:
        (G, positions, _) = tmg_load(highway_map())
        from networkx.algorithms.shortest_paths.dense import floyd_warshall
        print('This might take awhile')
        start_fw_time = time.time()
        dist_to = floyd_warshall(G, weight='weight')
        longest_so_far = 0
        start = -1
        end = -1
        for i in range(G.number_of_nodes()):
            for j in range(i + 1, G.number_of_nodes()):
                if dist_to[i][j] > longest_so_far:
                    longest_so_far = dist_to[i][j]
                    start = i
                    end = j
        end_fw_time = time.time()
        print(
            'start {} to end {} in longest shortest distance {} in time {:.3f} seconds'
            .format(positions[start], positions[end], longest_so_far,
                    end_fw_time - start_fw_time))

        # so much faster since graph is sparse
        from networkx.algorithms.shortest_paths.weighted import all_pairs_dijkstra_path_length
        start_time = time.time()
        dist_to = dict(all_pairs_dijkstra_path_length(G))

        longest_so_far = 0
        start = -1
        end = -1
        for i in range(G.number_of_nodes()):
            for j in range(i + 1, G.number_of_nodes()):
                if dist_to[i][j] > longest_so_far:
                    longest_so_far = dist_to[i][j]
                    start = i
                    end = j
        end_time = time.time()
        print(
            'start {} to end {} in longest shortest distance {} in time {:.3f} seconds'
            .format(positions[start], positions[end], longest_so_far,
                    end_time - start_time))
Пример #8
0
def generate_dfs_figure(src, target):
    """Generate DFS solution overlaying Massachusetts highway."""
    if plt_error:
        return None
    import matplotlib.pyplot as plt

    (G, positions, _) = tmg_load(highway_map())
    plt.clf()
    plot_gps(positions)
    plot_highways(positions, G.edges())

    node_from = dfs_search_recursive(G, src)
    total = compute_distance(positions, node_from, src, target)

    plot_node_from(positions, src, target, node_from, color='purple')
    print('{0} total steps for Depth First Search with distance={1:.1f} miles'.
          format(len(path_to(node_from, src, target)) - 1, total))
    plt.axis('off')
    output_file = image_file('figure-mass-highway-dfs.svg')
    plt.savefig(output_file, format="svg")
    print(output_file)
    plt.clf()
    return output_file
Пример #9
0
def generate_ch07():
    """Generate Tables and Figures for chapter 07."""
    chapter = 7

    with FigureNum(23) as figure_number:
        description = 'Initialize dist_to[][] and node_from[][] based on G'
        label = caption(chapter, figure_number)
        DG_TABLE = nx.DiGraph()
        DG_TABLE.add_edge('a', 'b', weight=4)
        DG_TABLE.add_edge('b', 'a', weight=2)
        DG_TABLE.add_edge('a', 'c', weight=3)
        DG_TABLE.add_edge('b', 'd', weight=5)
        DG_TABLE.add_edge('c', 'b', weight=6)
        DG_TABLE.add_edge('d', 'b', weight=1)
        DG_TABLE.add_edge('d', 'c', weight=7)
        visualize_results_floyd_warshall_just_initialize(DG_TABLE)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(24) as figure_number:
        description = 'Changes to node_from[][] and dist_to[][] after k processes a and b'
        label = caption(chapter, figure_number)
        DG_TABLE = nx.DiGraph()
        DG_TABLE.add_edge('a', 'b', weight=4)
        DG_TABLE.add_edge('b', 'a', weight=2)
        DG_TABLE.add_edge('a', 'c', weight=3)
        DG_TABLE.add_edge('b', 'd', weight=5)
        DG_TABLE.add_edge('c', 'b', weight=6)
        DG_TABLE.add_edge('d', 'b', weight=1)
        DG_TABLE.add_edge('d', 'c', weight=7)
        visualize_results_floyd_warshall_two_steps(DG_TABLE)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(1) as figure_number:
        description = 'Modeling different problems using graphs'
        print('by hand')
        label = caption(chapter, figure_number)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(2) as figure_number:
        description = 'An undirected graph of 12 vertices and 12 edges'
        make_sample_graph()
        label = caption(chapter, figure_number)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(3) as figure_number:
        description = 'A graph modeling a rectangular maze'
        label = caption(chapter, figure_number)
        from ch07.viewer import Viewer

        random.seed(15)
        m = Maze(3, 5)
        g = to_networkx(m)

        postscript_output = '{}-graph.ps'.format(label)
        if tkinter_error:
            print('unable to generate {}'.format(postscript_output))
        else:
            root = tkinter.Tk()
            canvas = Viewer(m, 50).view(root)
            tkinter_register_snapshot(root, canvas, postscript_output)
            root.mainloop()

        # For obscure reasons, this must come AFTER root.mainloop()
        if plt_error:
            pass
        else:
            import matplotlib.pyplot as plt
            pos = nx.get_node_attributes(g, 'pos')
            nx.draw(g, pos, with_labels=True, node_color='w', font_size=8)
            output_file = image_file('{}-graph.svg'.format(label))
            plt.savefig(output_file, format="svg")
            print('created {}'.format(output_file))

        print('{}. {}'.format(label, description))
        print()

    with FigureNum(4) as figure_number:
        description = 'Hitting a dead end while exploring a maze'
        print('Hand drawn overlay to Figure 7-2.')
        label = caption(chapter, figure_number)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(5) as figure_number:
        from ch07.search import dfs_search, draw_solution

        description = 'Depth First Search locates target if reachable from source'
        label = caption(chapter, figure_number)
        random.seed(15)
        m = Maze(3, 5)
        graph = to_networkx(m)

        if plt_error:
            print('unable to draw graph')
        else:
            draw_solution(graph, dfs_search(graph, m.start()), m.start(),
                          m.end())
            output_file = image_file('{}-graph.svg'.format(label))
            plt.savefig(output_file, format="svg")
            print('created {}'.format(output_file))

        print('{}. {}'.format(label, description))
        print()

    with FigureNum(6) as figure_number:
        description = 'Breadth First Search will locate shortest path to target, if reachable from source'
        print('Hand drawn overlay to Figure 7-2.')
        label = caption(chapter, figure_number)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(7) as figure_number:
        description = 'Breadth First Search finds shortest path to each node'
        label = caption(chapter, figure_number)
        random.seed(15)
        m = Maze(3, 5)
        graph = to_networkx(m)

        if plt_error:
            print('unable to draw graph')
        else:
            draw_solution(graph, bfs_search(graph, m.start()), m.start(),
                          m.end())
            output_file = image_file('{}-graph.svg'.format(label))
            plt.savefig(output_file, format="svg")
            print('created {}'.format(output_file))
            print('{}. {}'.format(label, description))
            print()

    with FigureNum(8) as figure_number:
        description = 'Comparing Depth First Search, Breadth First Search, and Guided Search'
        label = caption(chapter, figure_number)

        from ch07.solver_bfs import BreadthFirstSearchSolver
        from ch07.solver_dfs import DepthFirstSearchSolver
        from ch07.solver_guided import GuidedSearchSolver

        random.seed(15)
        m = Maze(13, 13)
        if tkinter_error:
            print('unable to generate {}'.format(postscript_output))
        else:
            root = tkinter.Tk()
            bfs = BreadthFirstSearchSolver(root,
                                           m,
                                           15,
                                           refresh_rate=0,
                                           stop_end=True)
            tkinter_register_snapshot(root, bfs.canvas,
                                      '{}-BFS.ps'.format(label))
            root.mainloop()

            root = tkinter.Tk()
            dfs = DepthFirstSearchSolver(root,
                                         m,
                                         15,
                                         refresh_rate=0,
                                         stop_end=True)
            tkinter_register_snapshot(root, dfs.canvas,
                                      '{}-DFS.ps'.format(label))
            root.mainloop()

            root = tkinter.Tk()
            sfs = GuidedSearchSolver(root,
                                     m,
                                     15,
                                     refresh_rate=0,
                                     stop_end=True)
            tkinter_register_snapshot(root, sfs.canvas,
                                      '{}-Guided.ps'.format(label))
            root.mainloop()
            print(
                'Generated BFS, DFS and Guided Postscript files for {}'.format(
                    label))

        print('{}. {}'.format(label, description))
        print()

    with FigureNum(9) as figure_number:
        description = 'Adjacency Matrix vs. Adjacency List representation'
        label = caption(chapter, figure_number)
        output_adjacency_matrix()
        output_adjacency_list()
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(10) as figure_number:
        description = 'Sample directed graph with 12 nodes and 14 edges.'
        label = caption(chapter, figure_number)
        make_sample_directed_graph()
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(11) as figure_number:
        description = 'Sample spreadsheet with underlying directed graph.'
        label = caption(chapter, figure_number)
        print('Screen shots from Excel, together with graph from Figure 7-9')
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(12) as figure_number:
        description = 'Visualizing execution of Depth First Search for Cycle Detection.'
        label = caption(chapter, figure_number)
        print('Done by hand.')
        print('{}. {}'.format(label, description))
        print()

    # In-text linear ordering
    print_sample_linear_ordering()
    print('Linear ordering of spreadsheet cells after Figure 12.')
    print()

    with FigureNum(13) as figure_number:
        description = 'Visualizing execution of Depth First Search for Topological Sort.'
        label = caption(chapter, figure_number)
        print('Done by hand.')
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(14) as figure_number:
        description = 'Modeling highway infrastructure in Massachusetts.'
        label = caption(chapter, figure_number)
        (_, mapPositions, _) = tmg_load(highway_map())
        (_, EAST, _, WEST) = bounding_ids(mapPositions)
        output_file = generate_bfs_and_dijkstra_figure(WEST, EAST)
        print('Generated {}'.format(output_file))
        print('Augmented by hand in SVG')
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(15) as figure_number:
        description = 'Modeling highway infrastructure in Massachusetts.'
        label = caption(chapter, figure_number)
        (_, mapPositions, _) = tmg_load(highway_map())
        (_, EAST, _, WEST) = bounding_ids(mapPositions)
        output_file = generate_dfs_figure(WEST, EAST)
        print('Generated {}'.format(output_file))
        print('Augmented by hand in SVG')
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(16) as figure_number:
        description = 'The shortest path from a to c has accumulated total of 8'
        label = caption(chapter, figure_number)
        print('Done by hand.')
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(17) as figure_number:
        description = "Executing Dijkstra's algorithm on small graph"
        label = caption(chapter, figure_number)
        DG_GOOD = nx.DiGraph()
        DG_GOOD.add_edge('a', 'b', weight=3)
        DG_GOOD.add_edge('a', 'c', weight=9)
        DG_GOOD.add_edge('b', 'c', weight=4)
        DG_GOOD.add_edge('b', 'd', weight=2)
        DG_GOOD.add_edge('d', 'c', weight=1)
        visualize_dijkstra_small_graph(DG_GOOD)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(18) as figure_number:
        description = "A negative edge weight in the wrong place breaks Dijkstra's algorithm"
        label = caption(chapter, figure_number)
        DG_GOOD = nx.DiGraph()
        DG_GOOD.add_edge('a', 'b', weight=3)
        DG_GOOD.add_edge('a', 'c', weight=1)
        DG_GOOD.add_edge('b', 'd', weight=-2)  # THIS BREAKS IT
        DG_GOOD.add_edge('c', 'd', weight=1)
        try:
            visualize_dijkstra_small_graph(DG_GOOD)
            print('WARNING: ValueError should have occurred! WARNING WARNING!')
        except ValueError:
            print('Unable to relax from final "b" node')

        print('{}. {}'.format(label, description))
        print()

    with FigureNum(19) as figure_number:
        description = 'Two graphs with negative edge weights, but only one has a negative cycle'
        label = caption(chapter, figure_number)
        DG_GOOD = nx.DiGraph()
        DG_GOOD.add_edge('a', 'b', weight=1)
        DG_GOOD.add_edge('b', 'd', weight=-3)
        DG_GOOD.add_edge('d', 'c', weight=5)
        DG_GOOD.add_edge('c', 'b', weight=-1)

        (dist_to, _) = bellman_ford(DG_GOOD, 'a')
        print('Good Graph: shortest distance from a to b is {}'.format(
            dist_to['b']))

        DG_BAD = nx.DiGraph()
        DG_BAD.add_edge('a', 'b', weight=1)
        DG_BAD.add_edge('b', 'd', weight=-3)
        DG_BAD.add_edge('d', 'c', weight=5)
        DG_BAD.add_edge('c', 'b', weight=-4)

        try:
            (dist_to, _) = bellman_ford(DG_BAD, 'a')
            print(
                'WARNING: RuntimeError should have occurred! WARNING WARNING!')
        except RuntimeError:
            print('Bad Graph: Negative cycle exists in the graph.')

        print('Done by hand.')
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(20) as figure_number:
        description = 'Example for all-pairs shortest path problem'
        label = caption(chapter, figure_number)
        DG_AP = nx.DiGraph()
        DG_AP.add_edge('a', 'b', weight=4)
        DG_AP.add_edge('b', 'a', weight=2)
        DG_AP.add_edge('a', 'c', weight=3)
        DG_AP.add_edge('b', 'd', weight=5)
        DG_AP.add_edge('c', 'b', weight=6)
        DG_AP.add_edge('d', 'b', weight=1)
        DG_AP.add_edge('d', 'c', weight=7)
        print(DG_AP.nodes())
        print(DG_AP.edges(data=True))
        print('Done by hand.')
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(21) as figure_number:
        description = 'Intuition behind the all-pairs shortest path problem'
        label = caption(chapter, figure_number)
        print('by hand')
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(22) as figure_number:
        description = 'dist_to, node_from, and actual shortest paths for graph in Figure 7-20'
        label = caption(chapter, figure_number)
        DG_TABLE = nx.DiGraph()
        DG_TABLE.add_edge('a', 'b', weight=4)
        DG_TABLE.add_edge('b', 'a', weight=2)
        DG_TABLE.add_edge('a', 'c', weight=3)
        DG_TABLE.add_edge('b', 'd', weight=5)
        DG_TABLE.add_edge('c', 'b', weight=6)
        DG_TABLE.add_edge('d', 'b', weight=1)
        DG_TABLE.add_edge('d', 'c', weight=7)
        visualize_results_floyd_warshall(DG_TABLE)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(23) as figure_number:
        description = 'Initialize dist_to[][] and node_from[][] based on G'
        label = caption(chapter, figure_number)
        DG_TABLE = nx.DiGraph()
        DG_TABLE.add_edge('a', 'b', weight=4)
        DG_TABLE.add_edge('b', 'a', weight=2)
        DG_TABLE.add_edge('a', 'c', weight=3)
        DG_TABLE.add_edge('b', 'd', weight=5)
        DG_TABLE.add_edge('c', 'b', weight=6)
        DG_TABLE.add_edge('d', 'b', weight=1)
        DG_TABLE.add_edge('d', 'c', weight=7)
        visualize_results_floyd_warshall_just_initialize(DG_TABLE)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(24) as figure_number:
        description = 'Changes to node_from[][] and dist_to[][] after k processes a and b'
        label = caption(chapter, figure_number)
        DG_TABLE = nx.DiGraph()
        DG_TABLE.add_edge('a', 'b', weight=4)
        DG_TABLE.add_edge('b', 'a', weight=2)
        DG_TABLE.add_edge('a', 'c', weight=3)
        DG_TABLE.add_edge('b', 'd', weight=5)
        DG_TABLE.add_edge('c', 'b', weight=6)
        DG_TABLE.add_edge('d', 'b', weight=1)
        DG_TABLE.add_edge('d', 'c', weight=7)
        visualize_results_floyd_warshall_two_steps(DG_TABLE)
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(25) as figure_number:
        description = 'Sample Maze to defeat Guided Search'
        label = caption(chapter, figure_number)
        print('Done by hand.')
        print('{}. {}'.format(label, description))
        print()

    with FigureNum(26) as figure_number:
        description = 'Sample directed, acyclic graph for single-source, shortest path optimization'
        label = caption(chapter, figure_number)
        print('Done by hand.')
        print('{}. {}'.format(label, description))
        print()