예제 #1
0
def search_trials():
    """
    For randomly constructed NxN mazes, compute efficiency of searching strategies
    on 512 random mazes, as N grows from 4x4 to 128x128
    """
    import random
    from ch07.maze import to_networkx, distance_to

    tbl = DataTable([8,8,8,8],['N', 'BFS', 'DS', 'GS'], decimals=2)
    for N in [4, 8, 16, 32, 64, 128]:
        num_bfs = 0
        num_dfs = 0
        num_gs = 0
        for i in range(512):
            random.seed(i)
            m = Maze(N,N)
            G = to_networkx(m)

            num_bfs += annotated_bfs_search(G, m.start(), m.end())
            num_dfs += annotated_dfs_search(G, m.start(), m.end())
            num_gs += annotated_guided_search(G, m.start(), m.end(), distance_to)

        tbl.row([N, num_bfs/512, num_dfs/512, num_gs/512])

    tbl = DataTable([8,8,8,8],['N', 'BFS', 'DS', 'GS'], decimals=2)
    for N in [4, 8, 16, 32, 64, 128]:
        m = maze_to_defeat_guided_search(N)
        G = to_networkx(m)

        num_bfs = annotated_bfs_search(G, m.start(), m.end())
        num_dfs = annotated_dfs_search(G, m.start(), m.end())
        num_gs = annotated_guided_search(G, m.start(), m.end(), distance_to)

        tbl.row([N, num_bfs, num_dfs, num_gs])
예제 #2
0
    def test_maze(self):
        from ch07.maze import Maze, to_networkx
        import random
        random.seed(15)
        m = Maze(3, 5)
        self.assertEqual((0, 2), m.start())
        self.assertEqual((2, 2), m.end())

        G = to_networkx(m)
        self.assertEqual([(0, 1), (0, 3), (1, 2)], sorted(list(G[(0, 2)])))
예제 #3
0
    def __init__(self, master, maze, size, refresh_rate=0.01, stop_end=False):
        self.master = master
        self.viewer = Viewer(maze, size)
        self.marked = {}
        self.node_from = {}

        self.g = to_networkx(maze)
        self.start = maze.start()
        self.end = maze.end()
        self.stop_end = stop_end

        self.refresh_rate = refresh_rate

        master.after(0, self.animate)
        self.canvas = self.viewer.view(master)
예제 #4
0
def output_adjacency_list():
    """Output adjacency list for example maze."""
    random.seed(15)
    m = Maze(3, 5)
    g = to_networkx(m)
    N = g.number_of_nodes()
    tbl = DataTable([8] + [3] * N,
                    ['node'] + ['n{}'.format(i) for i in range(N)])
    tbl.format('node', 's')
    for i in range(N):
        tbl.format('n{}'.format(i), 's')

    for r in g.nodes():
        row = [str(r)]
        for c in g[r]:
            row.append(str(c))
        tbl.row(row)
예제 #5
0
def output_adjacency_matrix():
    """Output adjacency matrix for example maze."""
    random.seed(15)
    m = Maze(3, 5)
    g = to_networkx(m)
    N = g.number_of_nodes()
    count = 0
    for r in g.nodes():
        row = [str(r)]
        for c in g.nodes():
            if c in g[r]:
                row.append('1')
                count += 1
            else:
                row.append('')
        print('\t'.join(row))
    print(count / (N * N))
예제 #6
0
    def test_guided_search(self):
        from ch07.maze import Maze, to_networkx, solution_graph, distance_to
        from ch07.search import guided_search, path_to, node_from_field
        import random
        random.seed(15)
        m = Maze(3, 5)
        G = to_networkx(m)

        # BFS search solution
        node_from = guided_search(G, m.start(), m.end(), distance_to)
        self.assertEqual((1, 2), node_from[(2, 2)])

        # Create graph resulting from the BFS search results
        F = node_from_field(G, node_from)
        self.assertEqual(14, len(list(F.edges())))

        # The actual solution is a two-edge, three node straight path
        H = solution_graph(G, path_to(node_from, m.start(), m.end()))
        self.assertEqual(2, len(list(H.edges())))
예제 #7
0
    a designated target vertex; in the second graph the node_from dictionary
    is visualized.
    """
    if plt_error:
        return
    import matplotlib.pyplot as plt

    H = solution_graph(G, path_to(field, src, target))
    F = node_from_field(G, field)

    _, axes = plt.subplots(nrows=1, ncols=2, figsize=figsize)
    ax = axes.flatten()

    # get original positional location from original graph
    pos_h = nx.get_node_attributes(H, 'pos')
    nx.draw(H, pos_h, with_labels = True, node_color='w', font_size=8, ax=ax[0])
    pos_f = nx.get_node_attributes(F, 'pos')
    nx.draw(F, pos_f, with_labels = True, node_color='w', font_size=8, ax=ax[1])

#######################################################################
if __name__ == '__main__':
    random.seed(15)
    m = Maze(3,5)    # Anything bigger and these are too small to read
    graph = to_networkx(m)

    # Choose whether to use dfs_search, bfs_search, or guided_search
    draw_solution(graph, bfs_search(graph, m.start()), m.start(), m.end())

    import matplotlib.pyplot as plt
    plt.show()
예제 #8
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()