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. """ # We define a queue == breadth-first search queue = QueueFrontier() exploredSet = list() # We're going to look neighbors node = Node(source, None, None) exploredSet.append(source) neighbors = neighbors_for_person(source) # If doesn't has any neighbor, return None (there are people that has done just one movie of 1 actor) if len(neighbors) == 0: return None # For each neighbor, add to the queue each possible action (walk through the movie) for i in neighbors: node = Node(state = i[1], parent = None, action = i[0]) queue.add(node) # Check if we found the target if queue.contains_state(target): node = queue.search_state(target) return [(node.getAction(), target)] # took out an element from the queue and walk through the neighboors while not queue.empty(): parent = queue.remove() """ This is not necesary, because i found an eficient implementation checking if we reached the target when we add a node, and not when we remove it... if parent.getState() == target: # Once we have the target, go backwards. FIFO will be useful to do the path till the target result = StackFrontier() # Add the target element and go backward till the beginning through the parents result.add(parent) node = parent.getParent() while node != None: result.add(node) node = node.getParent() # build the return list in the correct order taking out every stack element r = list() while not result.empty(): node = result.remove() movie = node.getAction() person = node.getState() r.append([movie, person]) return r """ # Add the node to the explore dataset because we don't want to walk through the same way that we came exploredSet.append(parent.getState()) # expand the node and find neighbors neighbors = neighbors_for_person(parent.getState()) # remember state == person # For each neighbor we have the name of the neighbor i[1] and the movie i[0] shared with the parent of the neighbor for i in neighbors: node = Node(state=i[1], parent=parent, action=i[0]) # action == movies # If we have been in this neighbor before (this person), continue and don't expand this node again if queue.contains_state(node.getState()) or node.getState() in exploredSet: continue queue.add(node) # Check if this node has the target if node.getState() == target: # Once we have the target, go backwards. FIFO will be useful for this result = StackFrontier() # add the target element and go backward till the beginning through the parents result.add(node) node = node.getParent() while node != None: result.add(node) node = node.getParent() # build the return list in the correct order taking out every stack element r = list() while not result.empty(): node = result.remove() movie = node.getAction() person = node.getState() r.append([movie, person]) return r # raise NotImplementedError return None