Beispiel #1
0
def general_search(problem, queueing_function):

    num_expanded = 0 #Counts number of nodes expanded (excluding root)
    max_nodes_in_queue = 0 #Counts maximum number of nodes in queue
    PQueue = [] #List to be transformed into a priority queue
    visited = {} #Dictionary to keep track of visited nodes (Allows for O(1) searching)
    heapq.heapify(PQueue) #Heapify the list we made earlier
    puzzle = copy.deepcopy(problem) #Make a deep copy just in case so stuff doesn't break

    #Check for solvability in O(1) time
    if not checkSolvability(puzzle):
            print "\nPuzzle is not Solvable!\n"
            return ""

    #If puzzle is solvable, then calculate initial h(n)
    if queueing_function == "UniformCostSearch":
        puzzle.heuristicCost = 0

    elif queueing_function == "A_star_misplaced":
        puzzle.heuristicCost = calcMisplacedTilesDistance(puzzle)

    elif queueing_function == "A_star_manhattan":
        puzzle.heuristicCost = calcManhattanDistance(puzzle)

    #Push initial node onto priority queue
    heapq.heappush(PQueue,puzzle)

    #While queue is not empty
    #Values still exist in the queue which means search has not
    #been exhausted(backup in case solvability check fails)
    while len(PQueue) != 0:

        #Pop the node with lowest total cost from queue
        #(Overloaded <= operator in puzzle class)
        prevPuzzle = heapq.heappop(PQueue)

        #Check if the puzzle's state is equivalent to the goal state
        if prevPuzzle.checkIfFinished():
            #If true print out completion and the trace
            #for nodes expanded and maximum nodes in queue
            #print "\nGoal!!"
            #prevPuzzle.printPuzzle()
            #print "\nTo solve this problem the search algorithm expanded a total of", num_expanded, "nodes."
            #print "The maximum number of nodes in the queue at any one time was", max_nodes_in_queue,"."
            #print "The depth of the goal node was", prevPuzzle.depth , "."
            return prevPuzzle.moveString

        #Otherwise, print out trace for next best node to expand
        #print "\nThe best state to expand with a g(n) =",prevPuzzle.depth\
        #            ,"and h(n) =",prevPuzzle.heuristicCost,"is..."

        #Print out the node that we are expanding
        #prevPuzzle.printPuzzle()
        #print "\nExpanding this node..."

        #Generate all possible moves(children) for that node
        puzzle_tree = prevPuzzle.GenerateMoves()

        #For all the children of the current node popped
        for puzzle in puzzle_tree:
            
            #Generate a list and then convert it into a string
            #based off the puzzle's state
            #This will be our key in our dictionary for hashing
            puzzle_list = []
            for list in puzzle.startPuzzle:
                puzzle_list += list
            puzzle_key = ""
            for elem in puzzle_list:
                puzzle_key += str(elem)

            #If the key does not exist in our dictionary
            if puzzle_key not in visited:

                #Hash in the new node with its respective key
                #Must convert to tuple since lists are not hashable
                visited[puzzle_key] = tuple(puzzle_list)

                #Create the new puzzle to be pushed onto queue
                #and calculate its respective h(n) value
                nextPuzzle = Puzzle(puzzle.startPuzzle)
                nextPuzzle.heuristicCost = calcManhattanDistance(nextPuzzle)
                nextPuzzle.moveString = puzzle.moveString
                
                #Increment depth counter for children
                nextPuzzle.depth = prevPuzzle.depth+1
                #Push child onto priority queue
                heapq.heappush(PQueue,nextPuzzle)
                #Increment number of nodes expanded
                num_expanded += 1

            #If the current number of nodes in queue exceeds
            #current maximum counter, update maximum
            if len(PQueue) > max_nodes_in_queue:
                max_nodes_in_queue = len(PQueue)

    #Return failure if 2nd check trips
    #(Should not happen because solvability check should handle)
    print "This puzzle is not solvable! \n"
    return ""