def update_weight_node(self, node): """ update node as weighted or not """ if node.state == State.WEIGHT: progress_state(node, [self.start_node, self.finish_node], State.NORMAL, self.render_delay) elif node.state == State.NORMAL or node.state == State.WALL: self.render_weight(node, random_weight=False, current_weight=False)
def clear_walls_and_weights(self): """ clear all walls and weights from graph """ if self.is_solving: return self.solved = False for node in self.flat_nodes: if node.state == State.WALL or node.state == State.WEIGHT: progress_state(node, [], State.NORMAL, self.render_delay)
def update_wall_node(self, node): """ update node as wall or not """ if node.state == State.WALL: progress_state(node, [self.start_node, self.finish_node], State.NORMAL, self.render_delay) elif node.state == State.NORMAL or node.state == State.WEIGHT: progress_state(node, [self.start_node, self.finish_node], State.WALL, self.render_delay)
def clear_graph(self): """ reset node back to initial state """ if self.is_solving: return self.solved = False self.reset_local_nodes() for node in self.flat_nodes: progress_state(node, [], State.NORMAL, self.render_delay)
def backtrack(self): """ backtrack through path to finish node """ if self.recursive: for node in reversed(self.path): progress_state(node, self.state_consts, State.PATH, self.render_delay) else: for node in self.path: progress_state(node, self.state_consts, State.PATH, self.render_delay)
def update_finish_node(self, node): """ update finishing node """ if self.finish_node is not None: progress_state(self.finish_node, [self.start_node], State.NORMAL, self.render_delay) progress_state(node, [self.start_node], State.FINISH, self.render_delay) self.finish_node = node if self.solved: self.validate_graph(animate=False)
def dijkstra(self, node): """ dijkstra and a* algorithm implementation """ while self.finish_node != self.get_next_priority(): if node is None or node not in self.adjacency_list: return False progress_state(node, self.state_consts, State.VISITING, self.render_delay) self.priority_queue.pop(node, None) edges = self.adjacency_list[node] self.relaxation(node, edges) progress_state(node, self.state_consts, State.VISITED, self.render_delay) node = self.get_next_priority() return True
def clear_path(self): """ clear any nodes in last iteration """ if self.is_solving: return self.solved = False for node in self.flat_nodes: if 1 < node.weight < inf: self.render_weight(node, random_weight=False, current_weight=True) elif node.state == State.VISITED or \ node.state == State.VISITING or \ node.state == State.QUEUE or \ node.state == State.PATH: progress_state(node, [], State.NORMAL, self.render_delay)
def render_weight(self, node, random_weight, current_weight): if random_weight: w = random.randrange(50) elif current_weight: w = node.weight else: w = self.weight progress_state(node, [self.start_node, self.finish_node], State.WEIGHT, self.render_delay, weight=w) self.canvas.create_text(node.x1 + (self.node_size / 2), node.y1 + (self.node_size / 2), fill="#333333", font="Times 11 bold", text=node.weight)
def random_maze(self): """ generate a random maze """ if self.is_solving: return for node in self.flat_nodes: if random.uniform(0, 1) < self.wall_frequency: if random.uniform(0, 1) < 0.5: progress_state(node, [self.start_node, self.finish_node], State.WALL, self.render_delay) else: self.render_weight(node, random_weight=True, current_weight=False) else: progress_state(node, [self.start_node, self.finish_node], State.NORMAL, self.render_delay)
def dfs_recursive(self, node): """ depth first search recursive algorithm """ if node == self.finish_node: return True if node not in self.adjacency_list: return False progress_state(node, self.state_consts, State.VISITING, self.render_delay) edges = self.adjacency_list[node] for edge in edges: if edge.state == State.VISITED or edge.state == State.VISITING: continue if self.dfs_recursive(edge): self.path.append(edge) return True progress_state(node, self.state_consts, State.VISITED, self.render_delay) return False
def dfs(self, node): """ depth first search iterative solution """ stack = [node] while node != self.finish_node: node = stack[-1] pop_from_stack = True progress_state(node, self.state_consts, State.VISITING, self.render_delay) self.path.append(node) for edge in self.adjacency_list[node]: if edge.state == State.VISITED or edge.state == State.VISITING or edge.state == State.START: continue stack.append(edge) pop_from_stack = False break if pop_from_stack: progress_state(stack[-1], self.state_consts, State.VISITED, self.render_delay) stack.pop(-1) if not stack: return False self.path = [node for node in self.path if node.state != State.VISITED] return True
def config_nodes(self, event=None): """ configure all nodes on the graph """ if self.is_solving: return self.clean_canvas() self.reset_local_nodes() self.n_cols = int(self.graph_width // self.node_size) self.n_rows = int(self.graph_height // self.node_size) self.nodes = [[None for _ in range(0, self.n_cols)] for _ in range(0, self.n_rows)] idx = 0 for i, row in enumerate(self.nodes): y1 = i * self.node_size y2 = y1 + self.node_size for j, col in enumerate(row): x1 = j * self.node_size x2 = x1 + self.node_size node = Node(x1, y1, x2, y2, i, j, idx, self) progress_state(node, [], State.NORMAL, self.render_delay) self.nodes[i][j] = node idx += 1 self.flat_nodes = [node for row in self.nodes for node in row]
def bfs_recursive(self, node): """ breadth first search recursive - find shortest path """ if node == self.finish_node or node not in self.adjacency_list: return progress_state(node, self.state_consts, State.VISITING, self.render_delay) for edge in self.adjacency_list[node]: if edge.state == State.VISITED or edge in self.queue: continue self.queue.append(edge) progress_state(edge, self.state_consts, State.QUEUE, self.render_delay) self.prev[edge] = self.queue[0] progress_state(node, self.state_consts, State.VISITED, self.render_delay) self.queue.pop(0) if not self.queue: return self.bfs_recursive(self.queue[0])
def bfs(self): """ breadth first search iterative """ node = self.queue[-1] while node != self.finish_node and node in self.adjacency_list: progress_state(node, self.state_consts, State.VISITING, self.render_delay) for edge in self.adjacency_list[node]: if edge.state == State.VISITED or edge.state == State.QUEUE: continue self.prev[edge] = node self.queue.append(edge) progress_state(edge, self.state_consts, State.QUEUE, self.render_delay) self.queue.pop(0) progress_state(node, self.state_consts, State.VISITED, self.render_delay) if not self.queue: break node = self.queue[0]
def visualise_path(self): for node in reversed(self.path): progress_state(node, self.state_consts, State.PATH, self.render_delay)