예제 #1
0
 def g(cls, parentnode: Node, action, childnode: Node):
     return len(childnode.path())
예제 #2
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
    (instance of basicsearch_lib02.representation.Problem or derived class),
    attempt to solve the problem.
    
    If debug is True, debugging information will be displayed.
    
    if verbose is True, the following information will be displayed:
        
        Number of moves to solution
        List of moves and resulting puzzle states
        Example:
        
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
        
        If no solution were found (not possible with the puzzles we
        are using), we would display:
        
            No solution found
    
    Returns a tuple (path, nodes_explored) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    """
    rootNode = Node(problem, problem.initial)
    frontier = PriorityQueue()
    frontier.append(rootNode)
    frontierHash = {}
    frontierHash[hash(rootNode)] = rootNode
    done = found = False
    exploredNodes = Explored()

    while not done:
        node = frontier.pop()
        frontierHash.pop(hash(node), None)
        #print(node)
        exploredNodes.add(node)
        if node.problem.goal_test(node.state):
            found = done = True
            #print("finished with solution")
        else:
            nodes = []
            for n in node.expand(node.problem):
                #may need to come back and compare boards instead of nodes
                if (hash(n) not in frontierHash or frontierHash[hash(n)] != n
                    ) and exploredNodes.exists(n) == False:
                    #print("adding to the frontier")
                    nodes.append(n)
            for n in nodes:
                frontier.append(n)
                frontierHash[hash(n)] = n
            if len(frontier) == 0:
                print("finished, no solution")
                done = True

    if verbose == True:
        #print the path to the solution
        if found:
            path = node.path()
            solution = node.solution()
            print("Solution in ", len(solution), "moves")
            print("Initial state")
            counter = 1
            for item in path:
                print(item.state)
                if counter <= len(solution):
                    print("Move ", counter, " - ", solution[counter - 1])
                counter = counter + 1
        else:
            print("No solution found")

    if found == True:
        return (node.solution(), len(node.path()))
    else:
        return (None, None)
예제 #3
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
    (instance of basicsearch_lib02.representation.Problem or derived class),
    attempt to solve the problem.
    
    If debug is True, debugging information will be displayed.
    
    if verbose is True, the following information will be displayed:
        
        Number of moves to solution
        List of moves and resulting puzzle states
        Example:
        
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
        
        If no solution were found (not possible with the puzzles we
        are using), we would display:
        
            No solution found
    
    Returns a tuple (path, nodes_explored, elapsed_s) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    elapsed_s is the elapsed wall clock time performing the search
    """
    # Start the timer:
    timer = Timer()

    # Create a hashtable to store all explored states
    exploredStates = Explored()
    # Create a PriorityQueue to store all current states
    frontier = PriorityQueue(f=lambda node: node.g + node.h)
    # Initialize the frontier with the first Node
    frontier.append(Node(problem, problem.initial))

    # Loop until the solution is found or the state space is exhausted
    while frontier.__len__() != 0:

        # Pop a node from the frontier
        node = frontier.pop()

        if problem.goal_test(node.state):
            alpha = node.path()
            actions = node.solution()

            # If verbose is True, display all moves
            if verbose:
                print(f'Solution in {len(actions)} moves')
                for i in range(len(actions)):
                    print(f'Move {i + 1} - {actions[i]}')
                    print(alpha[i + 1].state, end='\n\n')

            # Return a Tuple contains:
            # - List of actions to solve the problem,
            # - Number of nodes explored,
            # - elapsed_s in seconds
            return alpha, len(exploredStates.exploredStates), timer.elapsed_s()

        else:
            # Explore the children of current node
            for child in node.expand(problem):

                child_tuple = child.state.state_tuple()

                # if we haven't explored this child yet
                # Load it into frontier and explore set
                if not exploredStates.exists(child_tuple):
                    exploredStates.add(child_tuple)
                    frontier.append(child)

    # If no solution found, return None
    return None
예제 #4
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
    (instance of basicsearch_lib02.representation.Problem or derived class),
    attempt to solve the problem.
    
    If debug is True, debugging information will be displayed.
    
    if verbose is True, the following information will be displayed:
        
        Number of moves to solution
        List of moves and resulting puzzle states
        Example:
        
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
        
        If no solution were found (not possible with the puzzles we
        are using), we would display:
        
            No solution found
    
    Returns a tuple (path, nodes_explored) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    """
    #Initial tileboard for testing
    tb = problem.initial
    #Create first node and test if node passes goal
    node0 = Node(problem, tb)
    if problem.goal_test(node0.state) == True:
        return node0.solution()
    #define frontier set as priority queue and the explored set
    pq = PriorityQueue()
    pq.append(node0)
    new_nodes = []
    exploredSet = Explored()
    frontier = Explored()
    frontier.add(node0)
    nodesExpanded = 0

    #Expand the search tree until the goal state is found
    found = False
    #time.sleep(2)
    while (not found):
        #Check if the frontier is empty signifying failure
        if pq.__len__() == 0:
            print("No solution found")
            break
        #Take the next node from the priority queue and add it to explored set
        node = pq.pop()
        exploredSet.add(node)
        #Check if the goal state has been found
        if problem.goal_test(node.state) == True:
            path = node.path()
            solution = node.solution()
            steps = len(path) - 1
            found = True
            if verbose == True:
                verboseFunc(solution, steps, tb, path)
        else:
            #Expand the search tree and check if the nodes have been explored
            new_nodes = node.expand(problem)
        for j in range(len(new_nodes)):
            if exploredSet.exists(new_nodes[j].state) or frontier.exists(
                    new_nodes[j].state):
                continue
            else:
                #Add one to the number of nodes explored
                nodesExpanded += 1
                pq.append(new_nodes[j])  #Add the nodes to the priority queue
                frontier.add(
                    new_nodes[j])  #use hashed set to decrease lookup time
                if debug == True:
                    debugFunc(debug, pq)
    return (steps, nodesExpanded)
예제 #5
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
    (instance of basicsearch_lib02.representation.Problem or derived class),
    attempt to solve the problem.
    
    If debug is True, debugging information will be displayed.
    
    if verbose is True, the following information will be displayed:
        
        Number of moves to solution
        List of moves and resulting puzzle states
        Example:
        
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
        
        If no solution were found (not possible with the puzzles we
        are using), we would display:
        
            No solution found
    
    Returns a tuple (path, nodes_explored) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    """

    frontierNodes = PriorityQueue(min, Node.get_f)
    node = Node(problem, problem.getInitialBoardState())
    nodesExplored = 0

    exploredStates = Explored()  #hash table to store states
    exploredStates.add(node)

    for node in node.expand(problem):
        if not exploredStates.exists(node):  #its not a duplicate in explored
            frontierNodes.append(node)  #get initial frontier nodes

    done = found = False

    while not done:
        node = frontierNodes.pop()  #loop thru frontier states
        nodesExplored += 1
        exploredStates.add(node)

        if problem.goal_test(node.state):  #if found, set true
            found = done = True

        else:  #if not, then add the new frontier states to the queue
            for node in node.expand(problem):
                if not exploredStates.exists(
                        node):  #its not a duplicate in explored
                    #if not frontierNodes.__contains__(node): #not a duplicate in frontier, slow!
                    frontierNodes.append(node)

            if (frontierNodes.__len__ == 0
                ):  #if we run thru all frontier, search complete
                done = True

    if found:
        if (verbose):
            print("Moves to solution: ", node.path().__len__())
            print("Nodes Expanded: ", nodesExplored)

            move = 0
            solutionList = node.solution()
            boardList = []

            for node in node.path():
                boardList.append(problem.generateDebugBoard(node.state))

            print("Initial State")
            for board in boardList:
                counter = move + 1
                print(board)
                print()
                if (move < boardList.__len__() - 1):
                    print("Move ", counter, " ", solutionList[move])
                move += 1

        if (debug):
            print()
            print("Debug Info:")
            print(print_nodes(node.path()))
            print()

        return (node.solution(), nodesExplored
                )  #returns solution node's path/solution
    else:
        if (verbose | debug):
            print("No solution found")
        return ("No solution found", nodesExplored)
예제 #6
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
    (instance of basicsearch_lib02.representation.Problem or derived class),
    attempt to solve the problem.
    
    If debug is True, debugging information will be displayed.
    
    if verbose is True, the following information will be displayed:
        
        Number of moves to solution
        List of moves and resulting puzzle states
        Example:
        
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
        
        If no solution were found (not possible with the puzzles we
        are using), we would display:
        
            No solution found
    
    Returns a tuple (path, nodes_explored) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    """
    start = time.time()

    initial_node = Node(problem, problem.initial)
    node_queue = PriorityQueue(f=lambda x: x.get_f())
    explore = Explored()
    explore.add(initial_node.state)
    node_num = 1
    node = initial_node
    board = problem.initial
    solved = board.solved()
    while (not solved):
        newNodes = node.expand(problem)
        #Insert all new nodes into queues and explored
        for newNode in newNodes:
            if (not explore.exists(newNode.state)):
                explore.add(newNode.state)
                node_queue.append(newNode)
                node_num += 1
                if newNode.state.solved():
                    node = newNode
                    solved = newNode.state.solved()
        if len(node_queue) == 0:
            break

        if not solved:
            node = node_queue.pop()
            board = newNode.state

    second = (time.time() - start)
    actions = [a_node.action for a_node in node.path() if a_node.action]
    return (actions, node_num, second)
예제 #7
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
    (instance of basicsearch_lib02.representation.Problem or derived class),
    attempt to solve the problem.
    
    If debug is True, debugging information will be displayed.
    
    if verbose is True, the following information will be displayed:
        
        Number of moves to solution
        List of moves and resulting puzzle states
        Example:
        
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
        
        If no solution were found (not possible with the puzzles we
        are using), we would display:
        
            No solution found
    
    Returns a tuple (path, nodes_explored) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    """

    #generate initial state, no parent/actions
    #based off of graph search example on slides
    node = Node(problem, problem.initial)
    if (problem.g == DepthFirst.g and problem.h == DepthFirst.h):
        frontierset = PriorityQueue(node.get_f())
    else:
        frontierset = PriorityQueue()
    frontierset.append(node)
    done = False
    exploredset = Explored()
    expanded = 0  #number of expansions
    while not done:
        node = frontierset.pop()
        #print(node.__repr__())
        exploredset.add(node.state)
        if problem.goal_test(node.state):
            done = True
        else:
            for nextaction in node.expand(problem):
                expanded += 1
                if not exploredset.exists(nextaction.state):
                    frontierset.append(nextaction)
                done = frontierset.__len__() == 0
    if verbose:
        if (len(node.solution()) == 0):  #No solutions found
            print("No solution found")
        else:
            print("Solution in ", len(node.solution()), " moves")
            print("Initial State")
            print(problem.initial)
            tempboard = problem.initial
            for i in range(0, len(node.solution())):
                print("Move ", i + 1, " - ", node.solution()[i])
                tempboard = tempboard.move(node.solution()[i])
                print(tempboard.__repr__())
    return (node.solution(), expanded)
예제 #8
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
    attempt to solve the problem.

    Returns a tuple (path, nodes_explored) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    """

    frontier = PriorityQueue()
    root = Node(problem, problem.initial)
    frontier.append(root)
    node = frontier.pop()
    pop = True  # for right pop left pop for BFS

    if node.expand(node.problem)[0].g < 0:
        # DFS which has the negative depth
        # since start from the deepest node
        frontier = deque()
        frontier.append(root)
    elif node.expand(node.problem)[0].h == 2:
        # BFS
        pop = False
        frontier = deque()
        frontier.append(root)
    else:
        # Manhattan
        frontier.append(node)

    DONE = False
    nodes_explored = 0
    explored_set = Explored()
    while not DONE:
        if pop:
            node = frontier.pop()  # DFS A*
        else:
            node = frontier.popleft()  # BFS
        if debug:
            print("Next decision is:", str(node))

        explored_set.add(node.state.state_tuple())
        nodes_explored += 1

        if problem.goal_test(node.state):
            solved_path = node.path()
            if debug:
                print("Puzzle solved")
                #  print("path:", str(node.path()))
            DONE = True
            # if Verbose True display the info stats in requirement
            if verbose:
                print("Solution in %d moves" % (len(solved_path) - 1))
                print("Initial State")
                print(solved_path[0])

                for i in range(1, len(solved_path)):
                    print("Move %d - %s" % (i, solved_path[i].action))
                    print(solved_path[i].state)

            return solved_path, nodes_explored
        # Not solved yet
        else:
            for child in node.expand(node.problem):
                # add new child to frontier set
                if not explored_set.exists(child.state.state_tuple()):
                    frontier.append(child)
                    explored_set.add(child)
            # finish when there is no node in the queue
            # if debug:
            #    print("Num node in quenue:", str(len(frontier)))
            DONE = len(frontier) == 0

    if verbose:
        print("No solution found")
    return None, nodes_explored
예제 #9
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
      (instance of basicsearch_lib02.representation.Problem or derived class),
      attempt to solve the problem.
      
      If debug is True, debugging information will be displayed.
      
      if verbose is True, the following information will be displayed:
      
      Number of moves to solution
      List of moves and resulting puzzle states
      Example:
      
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
      
      If no solution were found (not possible with the puzzles we
      are using), we would display:
      
      No solution found

      Returns a tuple (path, nodes_explored) where:
      path - list of actions to solve the problem or None if no solution was found
      nodes_explored - Number of nodes explored (dequeued from frontier)
      """
    # Create explored set and initialize variable to track nodes expanded
    explored = Explored()
    frontier = Explored()
    frontierQ = PriorityQueue()
    nodes_expanded = 0

    # Create initial node as starting point and add to frontier
    initial_node = Node(problem, problem.puzzle.state_tuple())
    frontierQ.append(initial_node)
    frontier.add(initial_node.state)
    node = None

    # Run while loop until graph search is complete
    done = found = False
    while not done:
        # Pop next node from frontier priority queue
        node = frontierQ.pop()
        if debug:
            print("Node:", node, "Action", node.action)  # View node for debugging purposes
        # Add current node state to explored set
        state = node.state
        explored.add(state)

        if problem.goal_test(state):
            # If goal found, exit while loop and return
            found = done = True
        else:
            # If goal not found, loop through possible actions depending on state
            for act in problem.actions(state):
                next_state = problem.result(state, act)
                next_node = node.child_node(act)
                # Check if next node after action is in frontier queue or explored set
                if not explored.exists(next_state) and not frontier.exists(next_state):
                    # If not, add to frontier and track the node as expanded
                    frontier.add(next_state)
                    frontierQ.append(next_node)
                    nodes_expanded += 1

        if not found:
            done = len(frontierQ) <= -1  # Exit loop if frontier is empty

    if not found:
        print("No solution found.")
        # This should not happen, we check if board is solvable in Tileboard class
    else:
        if verbose:
            # If verbose, print puzzle states and actions in path to solution
            print("Solution in", len(node.solution()), "moves")
            print(problem.puzzle)

            # Loop through each action in path
            for i, act in enumerate(node.solution()):
                problem.puzzle = problem.puzzle.move(act)
                # Display move taken and resulting puzzle board
                print("Move", i + 1, "-", act)
                print(problem.puzzle)

        if debug:
            print("*" * 10, "Win")  # Divider for visualization during debugging

        return node.solution(), nodes_expanded
예제 #10
0
def graph_search(problem: Problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
    (instance of basicsearch_lib02.representation.Problem or derived class),
    attempt to solve the problem.
    
    If debug is True, debugging information will be displayed.
    
    if verbose is True, the following information will be displayed:
        
        Number of moves to solution
        List of moves and resulting puzzle states
        Example:
        
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
        
        If no solution were found (not possible with the puzzles we
        are using), we would display:
        
            No solution found
    
    Returns a tuple (path, nodes_explored) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    """

    # Establish frontier set and nodes
    frontier = PriorityQueue()
    frontier.append(Node(problem, problem.initial))
    node = frontier.pop()
    popping = True

    if node.expand(node.problem)[0].g < 0:
        # Depth First Search
        frontier = deque()
        frontier.append(Node(problem, problem.initial))
    elif node.expand(node.problem)[0].h < 2:
        # Breadth First Search
        popping = False
        frontier = deque()
        frontier.append(Node(problem, problem.initial))
    else:
        # Manhattan Search
        frontier.append(node)

    # Working with the hash
    frontier_hash = Explored()
    frontier_hash.add(problem.initial.state_tuple())
    finished = False
    nodes_explored = 0
    explored = Explored()
    while not finished:
        if popping:
            node = frontier.pop()  # Manhattan and DFS
        else:
            node = frontier.popleft()  # BFS

        if debug:
            print("Node popped:", str(node))

        explored.add(node.state.state_tuple())
        nodes_explored += 1

        if node.state.solved():
            if debug:
                print("Solution found!")
            solution_path = node.path()
            finished = True
            if verbose:
                print_solution(solution_path)
            return solution_path, nodes_explored
        else:
            for child in node.expand(node.problem):
                if not explored.exists(child.state.state_tuple(
                )) and not frontier_hash.exists(child.state.state_tuple()):
                    frontier.append(child)
                    frontier_hash.add(child)
                elif debug:
                    print("Skipping...", child)
                    pass
            finished = len(frontier) == 0
        if debug:
            print("")
    if verbose:
        print("No solution found")
    return None, nodes_explored
예제 #11
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) --
    Given a problem representation (instance of basicsearch_lib02.representation.
    Problem or derived class), attempt to solve the problem.
    
    If debug is True, debugging information will be displayed.
    
    if verbose is True, the following information will be displayed:
        
        Number of moves to solution
        List of moves and resulting puzzle states
        Example:
        
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
        
        If no solution were found (not possible with the puzzles we
        are using), we would display:
        
            No solution found
    
    Returns a tuple (path, nodes_explored) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    """

    # PriorityQueue should be used to maintain the order of the queue.
    frontier = PriorityQueue()

    frontier.append(Node(problem, problem.initial))

    current_node = frontier.pop()

    p = True
    #depth first search
    if current_node.expand(current_node.problem)[0].g < 0:

        frontier = deque()
        frontier.append(Node(problem, problem.initial))
    #breadth first search
    elif current_node.expand(current_node.problem)[0].h < 2:

        p = False
        frontier = deque()
        frontier.append(Node(problem, problem.initial))
    #manhattan
    else:

        frontier.append(current_node)

    f_hash = Explored()
    f_hash.add(problem.initial.state_tuple())
    done = False
    n_explored = 0
    explored = Explored()

    #graph_search
    while not done:

        if p:
            current_node = frontier.pop()
        else:
            current_node = frontier.popleft()
        explored.add(current_node.state.state_tuple())
        n_explored = n_explored + 1  #inc the number of explored nodes

        if current_node.state.solved():
            path = current_node.path()
            done = True
            return path, n_explored
        #if not found in the tree return none and number of nodes explored
        else:

            for child in current_node.expand(current_node.problem):
                if not explored.exists(child.state.state_tuple()) and not \
                        f_hash.exists(child.state.state_tuple()):
                    frontier.append(child)
                    f_hash.add(child)
            done = len(frontier) == 0

    return None, n_explored
예제 #12
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
      (instance of basicsearch_lib02.representation.Problem or derived class),
      attempt to solve the problem.

      If debug is True, debugging information will be displayed.

      if verbose is True, the following information will be displayed:

      Number of moves to solution
      List of moves and resulting puzzle states
      Example:

            Solution in 25 moves
            Initial state
                  0        1        2
            0     4        8        7
            1     5        .        2
            2     3        6        1
            Move 1 -  [0, -1]
                  0        1        2
            0     4        8        7
            1     .        5        2
            2     3        6        1
            Move 2 -  [1, 0]
                  0        1        2
            0     4        8        7
            1     3        5        2
            2     .        6        1

            ... more moves ...

                  0        1        2
            0     1        3        5
            1     4        2        .
            2     6        7        8
            Move 22 -  [-1, 0]
                  0        1        2
            0     1        3        .
            1     4        2        5
            2     6        7        8
            Move 23 -  [0, -1]
                  0        1        2
            0     1        .        3
            1     4        2        5
            2     6        7        8
            Move 24 -  [1, 0]
                  0        1        2
            0     1        2        3
            1     4        .        5
            2     6        7        8

      If no solution were found (not possible with the puzzles we
      are using), we would display:

      No solution found

      Returns a tuple (path, nodes_explored, elapsed_s) where:
      path - list of actions to solve the problem or None if no solution was found
      nodes_explored - Number of nodes explored (dequeued from frontier)
      elapsed_s is the elapsed wall clock time performing the search
      """
    """
      uses a priority queue for the frontier and an instance of the Explored class for
      the explored set
      """

    # list of actions to solution
    t = Timer()  # starts the timer
    frontier = PriorityQueue(
    )  # we are always going to have a frontier and we always need to put in to priority queue
    explored = Explored()  # explored set, NOT REALLY A SET, it is a dictionary
    frontier.append(Node(problem,
                         problem.initial))  # add initial node to the frontier
    solution = None
    i = 0  # used for debug and verbose purposes
    while (frontier.__len__() > 0):

        current = frontier.pop()  # Dequeue current node

        if (debug == True and i % 100000 == 0):
            print("############# %d #################" %
                  i)  # display iteration number
            print(current.state)  # display current node
            print("nodes in frontier",
                  frontier.__len__())  # display lenght of frontier set
            print("time elapsed %dmin %dsec" %
                  (t.elapsed_s() / 60,
                   t.elapsed_s() % 60))  # display time elapsed

        explored.add(current.state)  # add current state to explored

        if problem.goal_test(
                current.state):  # if the current state is the goal

            if debug:  # used for debugging
                print(
                    "###goal found, i = %d ###" % i
                )  # display the iteration number for when the goal was found
                print(current.state)  # display current node
                print("length",
                      len(current.path()))  # display current node path length
                print("time elapsed %dmin %dsec" %
                      (t.elapsed_s() / 60,
                       t.elapsed_s() % 60))  # display time elapsed

            solution = current  # found goal and end loop
            break

        else:
            child_nodes = current.expand(
                problem)  # expand the state to find child nodes

            for child in child_nodes:
                if not explored.exists(
                        child.state
                ):  # if we haven't encountered the states yet
                    frontier.append(child)  # add it to the frontier
                    explored.add(
                        child.state
                    )  # add to explored to prevent duplication in frontier

        i = i + 1  # used for debug and verbose purposes

    if solution != None and verbose == True:  # if we found a solution and want more detail
        solution_path = solution.path()  # create list of nodes to solution
        num_moves = len(solution_path) - 1  # number of moves to goal
        print("############# %d #################" % i)
        print("Solution in ", num_moves, " moves.\n")  # heading of detail
        print("Intial state")
        print(solution_path[0])  # first state printed
        print("time elapsed %dmin %dsec" %
              (t.elapsed_s() / 60, t.elapsed_s() % 60))  # display time elapsed
        for i in range(1, len(solution_path)):  # print each move in order
            print("\nMove ", i, "")  # display move number
            print(solution_path[i])  # display move

    if solution == None:  # no solution found
        print("no solution found")
        path = []  # if no solution found return empty list
        return (
            path, len(explored.explored_set), t.elapsed_s()
        )  # return empty path, number of nodes explored and time elapsed
    else:  # solution found
        return (solution.path(), len(explored.explored_set), t.elapsed_s()
                )  # return solution path, number of nodes expanded and time
예제 #13
0
def graph_search(problem, verbose=False, debug=False):
    """graph_search(problem, verbose, debug) - Given a problem representation
    (instance of basicsearch_lib02.representation.Problem or derived class),
    attempt to solve the problem.
    
    If debug is True, debugging information will be displayed.
    
    if verbose is True, the following information will be displayed:
        
        Number of moves to solution
        List of moves and resulting puzzle states
        Example:
        
            Solution in 25 moves        
            Initial state
                  0        1        2    
            0     4        8        7    
            1     5        .        2    
            2     3        6        1    
            Move 1 -  [0, -1]
                  0        1        2    
            0     4        8        7    
            1     .        5        2    
            2     3        6        1    
            Move 2 -  [1, 0]
                  0        1        2    
            0     4        8        7    
            1     3        5        2    
            2     .        6        1    
            
            ... more moves ...
            
                  0        1        2    
            0     1        3        5    
            1     4        2        .    
            2     6        7        8    
            Move 22 -  [-1, 0]
                  0        1        2    
            0     1        3        .    
            1     4        2        5    
            2     6        7        8    
            Move 23 -  [0, -1]
                  0        1        2    
            0     1        .        3    
            1     4        2        5    
            2     6        7        8    
            Move 24 -  [1, 0]
                  0        1        2    
            0     1        2        3    
            1     4        .        5    
            2     6        7        8    
        
        If no solution were found (not possible with the puzzles we
        are using), we would display:
        
            No solution found
    
    Returns a tuple (path, nodes_explored) where:
    path - list of actions to solve the problem or None if no solution was found
    nodes_explored - Number of nodes explored (dequeued from frontier)
    """

    path = []
    nodes_explored = 0
    return_tuple = ()

    node = Node(problem, problem.initial)  # root node

    frontier = PriorityQueue(order=min,
                             f=lambda x: x.get_f())  # todo Sort this out
    explored = Explored()
    frontier.append(node)

    if problem.goal_test(node.state):
        path = node.solution()
        return_tuple = (path, nodes_explored)
        return return_tuple

    counter = 0

    while True:
        if frontier.__len__() == 0:
            path = node.solution()
            nodes_explored = counter
            return_tuple = (path, nodes_explored)
            return return_tuple
        node = frontier.pop()
        if problem.goal_test(node.state):
            break
        child_nodes = node.expand(problem)
        if explored.add(node.state):
            counter = counter + 1
        for child_node in child_nodes:
            if child_node not in frontier and not explored.exists(
                    child_node.state):
                frontier.append(child_node)

    path = node.solution()
    node_path = node.path()
    if verbose:
        print("Solution in " + str(len(node_path) - 1) + " moves.")
        i = 0
        for sol in node_path:
            if i is 0:
                print("Initial state")
                print(sol.state)
                i = i + 1
                continue
            print("Move " + str(i) + " - " + str(path[i - 1]))
            print(sol.state)
            i = i + 1
    nodes_explored = counter
    return_tuple = (path, nodes_explored)
    return return_tuple