def plot_graph_and_tree(G, T, time): """ Plot a graph G and a tree T on top of it Assumes that G has an embedding in the plane, represented as a dictionary G.pos""" plt.clf() nx.draw_networkx_edges(G, G.pos, alpha=.75, width=.5, style='dotted') nx.draw_networkx_edges(T, G.pos, alpha=.5, width=2) X = np.array(list(G.pos.values())) plt.plot(X[:,0], X[:,1], 'bo', alpha=.5) plt.plot([G.pos[T.root][0]], [G.pos[T.root][1]], 'bo', ms=12, mew=4, alpha=.95) # display the most recently swapped edges P = models.my_path_graph(T.path) nx.draw_networkx_edges(P, G.pos, alpha=.25 + (1-time)*.5, width=4, edge_color='c') P = models.my_path_graph([T.u_new, T.v_new]) P.add_edge(T.u_old, T.v_old) nx.draw_networkx_edges(P, G.pos, alpha=.25 + (1-time)*.5, width=4, edge_color='y') # find and display the current longest path path = nx.shortest_path(T, T.root) furthest_leaf = max(path, key=lambda l: len(path[l])) P = models.my_path_graph(path[furthest_leaf]) if len(path[furthest_leaf]) <= T.k: col = 'g' else: col = 'r' nx.draw_networkx_edges(P, G.pos, alpha=.5, width=4, edge_color=col) plt.text(G.pos[furthest_leaf][0], G.pos[furthest_leaf][1], '%d hops from root'%len(path[furthest_leaf]), color=col, alpha=.8, fontsize=9) T.depth = len(path[furthest_leaf])
def hidden_image_maze(fname, style='jittery'): """ Supported styles: jittery, smooth, sketch""" H = models.image_grid_graph(fname) # get a subgraph of the grid corresponding to edges between black pixels G = H.base_graph # for every edge in H, make the corresponding edge in H have weight 0 for u,v in H.edges(): G[u][v]['weight'] = 0 # find a minimum spanning tree on G (which will include the maze solution) T = nx.minimum_spanning_tree(G) # find the maze solution in the spanning tree P = models.my_path_graph(nx.shortest_path(T, (0,0), max(H.nodes()))) # generate the dual graph, including edges not crossed by the spanning tree D = models.dual_grid(G, T) views.add_maze_boundary(D, max(G.nodes())) views.make_entry_and_exit(D, max(G.nodes())) pos = views.layout_maze(D, fast=(style == 'jittery')) views.plot_maze(D, pos, P, G.pos) # make it stylish if requested if style == 'sketch': plt.figure(1) D_pos = views.layout_maze(D, fast=True) nx.draw_networkx_edges(D, D_pos, width=1, edge_color='k') D_pos = views.layout_maze(D, fast=True) nx.draw_networkx_edges(D, D_pos, width=1, edge_color='k') # show the pixel colors loaded from the file, for "debugging" plt.figure(2) for v in G: plt.plot([G.pos[v][0]], [G.pos[v][1]], '.', alpha=.5, color=G.node[v]['color'])
def plot_graph_and_tree(G, T, time): """ Plot a graph G and a tree T on top of it Assumes that G has an embedding in the plane, represented as a dictionary G.pos""" plt.clf() nx.draw_networkx_edges(G, G.pos, alpha=.75, width=.5, style='dotted') nx.draw_networkx_edges(T, G.pos, alpha=.5, width=2) X = np.array(list(G.pos.values())) plt.plot(X[:, 0], X[:, 1], 'bo', alpha=.5) plt.plot([G.pos[T.root][0]], [G.pos[T.root][1]], 'bo', ms=12, mew=4, alpha=.95) # display the most recently swapped edges P = models.my_path_graph(T.path) nx.draw_networkx_edges(P, G.pos, alpha=.25 + (1 - time) * .5, width=4, edge_color='c') P = models.my_path_graph([T.u_new, T.v_new]) P.add_edge(T.u_old, T.v_old) nx.draw_networkx_edges(P, G.pos, alpha=.25 + (1 - time) * .5, width=4, edge_color='y') # find and display the current longest path path = nx.shortest_path(T, T.root) furthest_leaf = max(path, key=lambda l: len(path[l])) P = models.my_path_graph(path[furthest_leaf]) if len(path[furthest_leaf]) <= T.k: col = 'g' else: col = 'r' nx.draw_networkx_edges(P, G.pos, alpha=.5, width=4, edge_color=col) plt.text(G.pos[furthest_leaf][0], G.pos[furthest_leaf][1], '%d hops from root' % len(path[furthest_leaf]), color=col, alpha=.8, fontsize=9) T.depth = len(path[furthest_leaf])
def random_maze(n=25): G = models.my_grid_graph([n,n]) T = nx.minimum_spanning_tree(G) P = models.my_path_graph(nx.shortest_path(T, (0,0), (n-1, n-1))) D = models.dual_grid(G, T) views.add_maze_boundary(D, [n, n]) views.make_entry_and_exit(D, [n, n]) pos = views.layout_maze(D, fast=True) views.plot_maze(D, pos, P, G.pos)
def random_maze(n=25): G = models.my_grid_graph([n, n]) T = nx.minimum_spanning_tree(G) P = models.my_path_graph(nx.shortest_path(T, (0, 0), (n - 1, n - 1))) D = models.dual_grid(G, T) views.add_maze_boundary(D, [n, n]) views.make_entry_and_exit(D, [n, n]) pos = views.layout_maze(D, fast=True) views.plot_maze(D, pos, P, G.pos)
def test_graph_utils(self): P = model.my_path_graph(model.nx.shortest_path(self.G, (0,0), (4,4))) H = model.image_grid_graph('test.png') d = model.dual_grid_edge((0,0), (0,1)) assert d == ((-0.5, 0.5), (0.5, 0.5)), 'dual of integer lattice should be offset by .5s' D = model.dual_grid(H.base_graph, H) graphics.add_maze_boundary(D, [5,5]) graphics.make_entry_and_exit(D, [5,5]) HH = graphics.split_edges(H)
def test_graph_utils(self): P = model.my_path_graph(model.nx.shortest_path(self.G, (0, 0), (4, 4))) H = model.image_grid_graph('test.png') d = model.dual_grid_edge((0, 0), (0, 1)) assert d == ((-0.5, 0.5), (0.5, 0.5)), 'dual of integer lattice should be offset by .5s' D = model.dual_grid(H.base_graph, H) graphics.add_maze_boundary(D, [5, 5]) graphics.make_entry_and_exit(D, [5, 5]) HH = graphics.split_edges(H)
def border_maze(fname='test.png', fast=True): G = models.image_grid_graph( fname, colors=set([(255, 255, 255, 255), (0, 0, 0, 255)]) ) # get a subgraph of the grid corresponding to edges between black and white H = models.image_grid_graph( fname, colors=set([(0, 0, 0, 255)]) ) # get a subgraph of the grid corresponding to edges between black pixels # for every edge in H, make the corresponding edge in G have weight 0 for u, v in G.edges(): G[u][v]['weight'] = (H.has_edge(u, v) and .1) or (1. + G.base_graph[u][v]['weight']) # find a minimum spanning tree on G (which will include the maze solution) T = nx.minimum_spanning_tree(G) # add border edges to G B = models.image_grid_graph(fname, colors=set([(255, 255, 255, 255), (0, 0, 0, 255), (255, 0, 0, 255)])) for u, v in B.edges(): if not G.has_edge(u, v): G.add_edge(u, v) # find the maze solution in the spanning tree for u, v in G.edges(): if len(G[u]) < 4 and len(G[v]) < 4: G[u][v]['weight'] = 1 else: G[u][v]['weight'] = 1e6 for u, v in T.edges(): G[u][v]['weight'] = 0 P = models.my_path_graph( nx.shortest_path(G, (0, 0), max(G.nodes()), weight='weight')) G_pos = G.base_graph.pos # generate the dual graph, including edges not crossed by the spanning tree D = models.dual_grid(G, T) D = views.split_edges(D) pos = views.layout_maze(D, fast=fast) views.plot_maze(D, pos, P, G_pos) # show the pixel colors loaded from the file, for "debugging" plt.figure(2) for v in G: plt.plot([G_pos[v][0]], [G_pos[v][1]], '.', alpha=.5, color=G.base_graph.node[v]['color']) return dict(G=G, H=H, T=T, P=P, B=B)
def border_maze(fname='test.png', fast=True): G = models.image_grid_graph(fname, colors=set([(255,255,255,255), (0,0,0,255)])) # get a subgraph of the grid corresponding to edges between black and white H = models.image_grid_graph(fname, colors=set([(0,0,0,255)])) # get a subgraph of the grid corresponding to edges between black pixels # for every edge in H, make the corresponding edge in G have weight 0 for u,v in G.edges(): G[u][v]['weight'] = (H.has_edge(u,v) and .1) or (1.+G.base_graph[u][v]['weight']) # find a minimum spanning tree on G (which will include the maze solution) T = nx.minimum_spanning_tree(G) # add border edges to G B = models.image_grid_graph(fname, colors=set([(255,255,255,255), (0,0,0,255), (255,0,0,255)])) for u,v in B.edges(): if not G.has_edge(u, v): G.add_edge(u, v) # find the maze solution in the spanning tree for u,v in G.edges(): if len(G[u]) < 4 and len(G[v]) < 4: G[u][v]['weight'] = 1 else: G[u][v]['weight'] = 1e6 for u,v in T.edges(): G[u][v]['weight'] = 0 P = models.my_path_graph(nx.shortest_path(G, (0,0), max(G.nodes()), weight='weight')) G_pos = G.base_graph.pos # generate the dual graph, including edges not crossed by the spanning tree D = models.dual_grid(G, T) D = views.split_edges(D) pos = views.layout_maze(D, fast=fast) views.plot_maze(D, pos, P, G_pos) # show the pixel colors loaded from the file, for "debugging" plt.figure(2) for v in G: plt.plot([G_pos[v][0]], [G_pos[v][1]], '.', alpha=.5, color=G.base_graph.node[v]['color']) return dict(G=G, H=H, T=T, P=P, B=B)
def hidden_image_maze(fname, style='jittery'): """ Supported styles: jittery, smooth, sketch""" H = models.image_grid_graph( fname ) # get a subgraph of the grid corresponding to edges between black pixels G = H.base_graph # for every edge in H, make the corresponding edge in H have weight 0 for u, v in H.edges(): G[u][v]['weight'] = 0 # find a minimum spanning tree on G (which will include the maze solution) T = nx.minimum_spanning_tree(G) # find the maze solution in the spanning tree P = models.my_path_graph(nx.shortest_path(T, (0, 0), max(H.nodes()))) # generate the dual graph, including edges not crossed by the spanning tree D = models.dual_grid(G, T) views.add_maze_boundary(D, max(G.nodes())) views.make_entry_and_exit(D, max(G.nodes())) pos = views.layout_maze(D, fast=(style == 'jittery')) views.plot_maze(D, pos, P, G.pos) # make it stylish if requested if style == 'sketch': plt.figure(1) D_pos = views.layout_maze(D, fast=True) nx.draw_networkx_edges(D, D_pos, width=1, edge_color='k') D_pos = views.layout_maze(D, fast=True) nx.draw_networkx_edges(D, D_pos, width=1, edge_color='k') # show the pixel colors loaded from the file, for "debugging" plt.figure(2) for v in G: plt.plot([G.pos[v][0]], [G.pos[v][1]], '.', alpha=.5, color=G.node[v]['color'])
def ld_maze(n=25): """ having many low-degree vertices makes for hard mazes unfortunately, finding them is slow""" # start with an nxn square grid G = models.my_grid_graph([n,n]) # make a pymc model of a low-degree spanning tree on this T = models.LDST(G, beta=10) mod_mc = mc.MCMC([T]) mod_mc.use_step_method(models.STMetropolis, T) mod_mc.sample(100, burn=99) T = T.value P = models.my_path_graph(nx.shortest_path(T, (0,0), (n-1, n-1))) D = models.dual_grid(G, T) views.add_maze_boundary(D, [n,n]) views.make_entry_and_exit(D, [n,n]) D = views.split_edges(D) D = views.split_edges(D) D_pos = views.layout_maze(D, fast=False) views.plot_maze(D, D_pos, P, G.pos)
def ld_maze(n=25): """ having many low-degree vertices makes for hard mazes unfortunately, finding them is slow""" # start with an nxn square grid G = models.my_grid_graph([n, n]) # make a pymc model of a low-degree spanning tree on this T = models.LDST(G, beta=10) mod_mc = mc.MCMC([T]) mod_mc.use_step_method(models.STMetropolis, T) mod_mc.sample(100, burn=99) T = T.value P = models.my_path_graph(nx.shortest_path(T, (0, 0), (n - 1, n - 1))) D = models.dual_grid(G, T) views.add_maze_boundary(D, [n, n]) views.make_entry_and_exit(D, [n, n]) D = views.split_edges(D) D = views.split_edges(D) D_pos = views.layout_maze(D, fast=False) views.plot_maze(D, D_pos, P, G.pos)