def shortest_path(source, target): """ Returns the shortest list of (movie_id, person_id) pairs that connect the source to the target. If no possible path, returns None. """ # Make the initial state a node sourceNode = Node(source) targetNode = Node(target) # Add initial state node to frontier (using QueueFrontier for BFS) frontier = QueueFrontier() frontier.add(sourceNode) state_frontier = [sourceNode.get_state()] # Keep track of explored state explored = [] while True: # If the frontier is empty, return None if frontier.empty(): return None # Check if the goal state is in the frontier if targetNode.get_state() in state_frontier: consideredNode = frontier.target_found(targetNode) explored.append(consideredNode.get_state()) # List for the path path = [] # Trace back the path while consideredNode.get_parent() is not None: temp = (consideredNode.get_action(), consideredNode.get_state()) path.append(temp) consideredNode = consideredNode.get_parent() # Reverse the path and return it path.reverse() return path # Move one node in frontier to explored node (this node will now be considered) consideredNode = frontier.removeNode() explored.append(consideredNode.get_state()) # Find the neighbour of the considered node that hasn't been explored and add them to the frontier for movie, neighbour in neighbors_for_person( consideredNode.get_state()): if not frontier.contains_state( neighbour) and neighbour not in explored: neighbourNode = Node(neighbour, consideredNode, movie) frontier.add(neighbourNode) state_frontier.append(neighbourNode.get_state()) if neighbour == targetNode.get_state(): targetNode = neighbourNode
def shortest_path(source, target): """ Returns the shortest list of (movie_id, person_id) pairs that connect the source to the target. If no possible path, returns None. """ global num_explored # Initialize starting node and frontier start = Node(state=source, parent=None, action=None) frontier = QueueFrontier() frontier.add(start) # initialize set for explored nodes explored = set() # Loop until solution found while True: # If nothing left in frontier, then there is no connection if frontier.empty(): return None # Take the node from the frontier node = frontier.remove() num_explored += 1 # Mark node as explored explored.add(node.get_state()) # Add neighbors to the frontier for action, state in neighbors_for_person(node.get_state()): if not frontier.contains_state(state) and state not in explored: child = Node(state, node, action) frontier.add(child) # If the node is the target, then there is connection if child.get_state() == target: connections = [] while child.get_parent() is not None: connections.append((child.get_action(), child.get_state())) child = child.get_parent() connections.reverse() return connections