Question

In: Computer Science

Question(on Python). There is a Python program what could solve the simple slide puzzles problem by...

Question(on Python). There is a Python program what could solve the simple slide puzzles problem by A* algorithm. Please fill in the body of the a_star() function.

In order to solve a specific problem, the a_star function needs to know the problem's start state, the desired goal state, and a function that expands a given node. To be precise, this function receives as its input the current state and the goal state and returns a list of pairs of the form (new_state, h'-score). There is exactly one such pair for each of the possible moves in the current state, with new_state being the state resulting from that move, paired with its h'-score. Note that this is not the f'-score but the h'-score, i.e., an (optimistic) estimate of the number of moves needed to reach the goal from the current state. The expand function does not know g’and therefore cannot compute f'; this has to be done by the a_star function.

The a_star function calls the expand function (in this context, slide_expand) in order to expand a node in the search tree, i.e., obtain the states that can be reached from the current one and their h’-scores. Again, please note that these are not f’-scores but h’-scores;
a_star needs to compute the h’-scores for sorting the list of open nodes. Also, note that slide_expand does not (and cannot) check whether it is creating a search cycle, i.e., whether it generates a state that is identical to one of its ancestors; this has to be done by a_star. The given slide_expand function uses the same scoring function as discussed in class – it simply counts the number of mismatched tiles (excluding the empty tile).

Please add code to the a_star function so that slide_solver can find an optimal solution for Example #1 and, in principle, for any slide puzzle. You are not allowed to modify any code outside of the a_star function. Hints: It is best to not use recursion in a_star but rather a loop that expands the next node, prevents any cycles in the search tree, sorts the list of open nodes by their scores, etc., until it finds a solution or determines that there is no solution. It is also a good idea to keep a list of ancestors for every node on the list, i.e., the list of states from the start that the algorithm went through in order to reach this node. When a goal state is reached, this list of ancestors for this node can be returned as the solution.

A_Star.py

import numpy as np

example_1_start = np.array([[2, 8, 3],
                           [1, 6, 4],
                           [7, 0, 5]])

example_1_goal = np.array([[1, 2, 3],
                           [8, 0, 4],
                           [7, 6, 5]])
 
example_2_start = np.array([[ 2,  6,  4,  8],
                            [ 5, 11,  3, 12],
                            [ 7,  0,  1, 15],
                            [10,  9, 13, 14]])

example_2_goal = np.array([[ 1,  2,  3,  4],
                           [ 5,  6,  7,  8],
                           [ 9, 10, 11, 12],
                           [13, 14, 15,  0]])

# For a given current state, move, and goal, compute the new state and its h'-score and return them as a pair. 
def make_node(state, row_from, col_from, row_to, col_to, goal):
    # Create the new state that results from playing the current move. 
    (height, width) = state.shape
    new_state = np.copy(state)
    new_state[row_to, col_to] = new_state[row_from, col_from]
    new_state[row_from, col_from] = 0
    
    # Count the mismatched numbers and use this value as the h'-score (estimated number of moves needed to reach the goal).
    mismatch_count = 0
    for i in range(height):
        for j in range(width):
            if new_state[i ,j] > 0 and new_state[i, j] != goal[i, j]:
                mismatch_count += 1
   
    return (new_state, mismatch_count)

# For given current state and goal state, create all states that can be reached from the current state
# (i.e., expand the current node in the search tree) and return a list that contains a pair (state, h'-score)
# for each of these states.   
def slide_expand(state, goal):
    node_list = []
    (height, width) = state.shape
    (empty_row, empty_col) = np.argwhere(state == 0)[0]     # Find the position of the empty tile
    
    # Based on the positin of the empty tile, find all possible moves and add a pair (new_state, h'-score)
    # for each of them.
    if empty_row > 0:
        node_list.append(make_node(state, empty_row - 1, empty_col, empty_row, empty_col, goal))
    if empty_row < height - 1:
        node_list.append(make_node(state, empty_row + 1, empty_col, empty_row, empty_col, goal))
    if empty_col > 0:
        node_list.append(make_node(state, empty_row, empty_col - 1, empty_row, empty_col, goal))
    if empty_col < width - 1:
        node_list.append(make_node(state, empty_row, empty_col + 1, empty_row, empty_col, goal))
    
    return node_list
  
# TO DO: Return either the solution as a list of states from start to goal or [] if there is no solution.               
def a_star(start, goal, expand):
    return []

# Find and print a solution for a given slide puzzle, i.e., the states we need to go through 
# in order to get from the start state to the goal state.
def slide_solver(start, goal):
    solution = a_star(start, goal, slide_expand)
    if not solution:
        print('This puzzle has no solution. Please stop trying to fool me.')
        return
        
    (height, width) = start.shape
    if height * width >= 10:            # If numbers can have two digits, more space is needed for printing
        digits = 2
    else:
        digits = 1
    horizLine = ('+' + '-' * (digits + 2)) * width + '+'
    for step in range(len(solution)):
        state = solution[step]
        for row in range(height):
            print(horizLine)
            for col in range(width):
                print('| %*d'%(digits, state[row, col]), end=' ')
            print('|')
        print(horizLine)
        if step < len(solution) - 1:
            space = ' ' * (width * (digits + 3) // 2)
            print(space + '|')
            print(space + 'V')

slide_solver(example_1_start, example_1_goal)       # Find solution to example_1

Solutions

Expert Solution

Code:

import numpy as np

example_1_start = np.array([[2, 8, 3],
                           [1, 6, 4],
                           [7, 0, 5]])

example_1_goal = np.array([[1, 2, 3],
                           [8, 0, 4],
                           [7, 6, 5]])

example_2_start = np.array([[ 2,  6,  4,  8],
                            [ 5, 11,  3, 12],
                            [ 7,  0,  1, 15],
                            [10,  9, 13, 14]])

example_2_goal = np.array([[ 1,  2,  3,  4],
                           [ 5,  6,  7,  8],
                           [ 9, 10, 11, 12],
                           [13, 14, 15,  0]])

# For a given current state, move, and goal, compute the new state and its h'-score and return them as a pair. 
def make_node(state, row_from, col_from, row_to, col_to, goal):
    # Create the new state that results from playing the current move. 
    (height, width) = state.shape
    new_state = np.copy(state)
    new_state[row_to, col_to] = new_state[row_from, col_from]
    new_state[row_from, col_from] = 0
    
    # Count the mismatched numbers and use this value as the h'-score (estimated number of moves needed to reach the goal).
    mismatch_count = 0
    for i in range(height):
        for j in range(width):
            if new_state[i ,j] > 0 and new_state[i, j] != goal[i, j]:
                mismatch_count += 1
   
    return (new_state, mismatch_count)

# For given current state and goal state, create all states that can be reached from the current state
# (i.e., expand the current node in the search tree) and return a list that contains a pair (state, h'-score)
# for each of these states.   
def slide_expand(state, goal):
    node_list = []
    (height, width) = state.shape
    (empty_row, empty_col) = np.argwhere(state == 0)[0]     # Find the position of the empty tile
    
    # Based on the positin of the empty tile, find all possible moves and add a pair (new_state, h'-score)
    # for each of them.
    if empty_row > 0:
        node_list.append(make_node(state, empty_row - 1, empty_col, empty_row, empty_col, goal))
    if empty_row < height - 1:
        node_list.append(make_node(state, empty_row + 1, empty_col, empty_row, empty_col, goal))
    if empty_col > 0:
        node_list.append(make_node(state, empty_row, empty_col - 1, empty_row, empty_col, goal))
    if empty_col < width - 1:
        node_list.append(make_node(state, empty_row, empty_col + 1, empty_row, empty_col, goal))
    
    return node_list
  
# TO DO: Return either the solution as a list of states from start to goal or [] if there is no solution.               
def a_star(start, goal, expand):
    #calculate h'-score of start state
    (height, width) = start.shape
    mismatch_count = 0
    #save start state and its h'-score into open_list
    open_list = [([start],mismatch_count)]
    #compare start state and goal
    compare_array = np.array_equal(open_list[0][0][-1], goal)
    #check whether reach the goal state
    while not compare_array:
        #create all states that can be reached from the current state and return state and h'-score
        node_list = expand(open_list[0][0][-1], goal) 
        #check new states and delete same states as ancestors to avoid a search cycle
        node_list_del = []
        for i in range(len(node_list)):
            for j in range(len(open_list[0][0])):
                if np.array_equal(node_list[i][0],open_list[0][0][j]):
                    node_list_del.append(i)
        for i in sorted(node_list_del,reverse=True):
            del node_list[i] 
        # if node_list is empty, which means all the new states are same as ancestors, then delete first element of open_list
        if len(node_list) == 0:
            del open_list[0]
        # if node_list is not empty, add all the children states and their f'-scores(current_depth + h'-score) in open_list
        else:
            for i in range(len(node_list)):
                # copy open_list 
                ancestor = open_list[0][0].copy()
                ancestor.append(node_list[i][0])
                #save each new state and its ancestors into a list, and calculate its f'-score
                node_list_sub=(ancestor,node_list[i][1]+len(open_list[0][0]))
                open_list.append(node_list_sub)
            # remove the expanded node
            del open_list[0]
            #sort f'-score of the list of open_list
            for i in range(0, len(open_list)):           
                for j in range(0, len(open_list)-i-1):  
                    if (open_list[j][1] > open_list[j + 1][1]):  
                        a = open_list[j]  
                        open_list[j]= open_list[j + 1]  
                        open_list[j + 1]= a 
        #if open_list is empty, which means that the problem does not have a solution, return empty list
        if len(open_list) == 0:
            return []
        # choose the smallest f'-score for next round
        compare_array = np.array_equal(open_list[0][0][-1], goal)
    return open_list[0][0]

# Find and print a solution for a given slide puzzle, i.e., the states we need to go through 
# in order to get from the start state to the goal state.
def slide_solver(start, goal):
    solution = a_star(start, goal, slide_expand)
    if not solution:
        print('This puzzle has no solution. Please stop trying to fool me.')
        return
        
    (height, width) = start.shape
    if height * width >= 10:            # If numbers can have two digits, more space is needed for printing
        digits = 2
    else:
        digits = 1
    horizLine = ('+' + '-' * (digits + 2)) * width + '+'
    for step in range(len(solution)):
        state = solution[step]
        for row in range(height):
            print(horizLine)
            for col in range(width):
                print('| %*d'%(digits, state[row, col]), end=' ')
            print('|')
        print(horizLine)
        if step < len(solution) - 1:
            space = ' ' * (width * (digits + 3) // 2)
            print(space + '|')
            print(space + 'V')

#slide_solver(example_1_start, example_1_goal)       # Find solution to example_1




# For a given current state, move, and goal, compute the new state and its h'-score and return them as a pair. 
def make_node_improved(state, row_from, col_from, row_to, col_to, goal):
    # Create the new state that results from playing the current move. 
    (height, width) = state.shape
    new_state = np.copy(state)
    new_state[row_to, col_to] = new_state[row_from, col_from]
    new_state[row_from, col_from] = 0
    
    # Count the mismatched numbers and use this value as the h'-score (estimated number of moves needed to reach the goal).
    distance_sum = 0
    new_state_list = list(new_state.flatten())
    goal_state_list = list(goal.flatten())
    for i in new_state_list:
        new_index = new_state_list.index(i)
        goal_index = goal_state_list.index(i)
        new_i, new_j = new_index // int(np.sqrt(len(new_state_list))), new_index % int(np.sqrt(len(new_state_list)))
        goal_i, goal_j = goal_index // int(np.sqrt(len(goal_state_list))), goal_index % int(np.sqrt(len(goal_state_list)))
        distance_sum += abs(new_i - goal_i) + abs(new_j- goal_j)
    return (new_state, distance_sum)

# For given current state and goal state, create all states that can be reached from the current state
# (i.e., expand the current node in the search tree) and return a list that contains a pair (state, h'-score)
# for each of these states.   
def slide_expand_improved(state, goal):
    node_list = []
    (height, width) = state.shape
    (empty_row, empty_col) = np.argwhere(state == 0)[0]     # Find the position of the empty tile
    
    # Based on the positin of the empty tile, find all possible moves and add a pair (new_state, h'-score)
    # for each of them.
    if empty_row > 0:
        node_list.append(make_node_improved(state, empty_row - 1, empty_col, empty_row, empty_col, goal))
    if empty_row < height - 1:
        node_list.append(make_node_improved(state, empty_row + 1, empty_col, empty_row, empty_col, goal))
    if empty_col > 0:
        node_list.append(make_node_improved(state, empty_row, empty_col - 1, empty_row, empty_col, goal))
    if empty_col < width - 1:
        node_list.append(make_node_improved(state, empty_row, empty_col + 1, empty_row, empty_col, goal))
    
    return node_list


# Find and print a solution for a given slide puzzle, i.e., the states we need to go through 
# in order to get from the start state to the goal state.
def slide_solver_improved(start, goal):
    solution = a_star(start, goal, slide_expand_improved)
    if not solution:
        print('This puzzle has no solution. Please stop trying to fool me.')
        return
        
    (height, width) = start.shape
    if height * width >= 10:            # If numbers can have two digits, more space is needed for printing
        digits = 2
    else:
        digits = 1
    horizLine = ('+' + '-' * (digits + 2)) * width + '+'
    for step in range(len(solution)):
        state = solution[step]
        for row in range(height):
            print(horizLine)
            for col in range(width):
                print('| %*d'%(digits, state[row, col]), end=' ')
            print('|')
        print(horizLine)
        if step < len(solution) - 1:
            space = ' ' * (width * (digits + 3) // 2)
            print(space + '|')
            print(space + 'V')


slide_solver_improved(example_1_start, example_1_goal)

Screenshots:

-------------------------END---------------------

Please give a thumbs up(upvote) if you liked the answer.


Related Solutions

PYTHON PROBLEM: Goal: Design and implement a Python program to solve the following problem. Scientists measure...
PYTHON PROBLEM: Goal: Design and implement a Python program to solve the following problem. Scientists measure an object’s mass in kilograms and weight in newtons. If you know the amount of mass of an object in kilograms, you can calculate its weight in newtons with the following formula: [Note: Use or test any random numbers to check whether the weight is heavy, can be lifted or light] ????h? = ???? × 9.8 Write a program that asks the user to...
Write a complete and syntactically correct Python program to solve the following problem: Write a program...
Write a complete and syntactically correct Python program to solve the following problem: Write a program for your professor that allows him to keep a record of the students’ average grade in his class. The program must be written in accordance with the following specs: 1. The input must be interactive from the keyboard. You will take input for 12 students. 2. You will input the students’ name and an average grade. The student cannot enter an average below zero...
Write a complete and syntactically correct Python program to solve the following problem: You are the...
Write a complete and syntactically correct Python program to solve the following problem: You are the payroll manager for SoftwarePirates Inc. You have been charged with writing a package that calculates the monthly paycheck for the salespeople. Salespeople at SoftwarePirates get paid a base salary of $2000 per month. Beyond the base salary, each salesperson earns commission on the following scale: Sales Commission Rate Bonus <$10000 0% 0 $10000 – $100,000 2% 0 $100,001 - $500,000 15% $1000 $500,001 -...
Write a Python program in a file called consonants.py, to solve the following problem using a...
Write a Python program in a file called consonants.py, to solve the following problem using a nested loop. For each input word, replace each consonant in the word with a question mark (?). Your program should print the original word and a count of the number of consonants replaced. Assume that the number of words to be processed is not known, hence a sentinel value (maybe "zzz") should be used. Sample input/output: Please enter a word or zzz to quit:...
Write a Python program to solve the 8-puzzle problem (and its natural generalizations) using the A*...
Write a Python program to solve the 8-puzzle problem (and its natural generalizations) using the A* search algorithm. The problem. The 8-puzzle problem is a puzzle invented and popularized by Noyes Palmer Chapman in the 1870s. It is played on a 3-by-3 grid with 8 square blocks labeled 1 through 8 and a blank square. Your goal is to rearrange the blocks so that they are in order, using as few moves as possible. You are permitted to slide blocks...
Python Problem Problem 1: In this problem you are asked to write a Python program to...
Python Problem Problem 1: In this problem you are asked to write a Python program to find the greatest and smallest elements in the list. The user gives the size of the list and its elements (positive and negative integers) as the input. Sample Output: Enter size of the list: 7 Enter element: 2 Enter element: 3 Enter element: 4 Enter element: 6 Enter element: 8 Enter element: 10 Enter element: 12 Greatest element in the list is: 12 Smallest...
Please write simple python program with explanation Problem statement: Stock markets are venues where buyers and...
Please write simple python program with explanation Problem statement: Stock markets are venues where buyers and sellers of shares meet and decide on a price to trade.Eddard is very interested in trading in stock market and he started gathering information of one stock.He has projected market prices for that share over the next n months.Eddard wants to purchase and resell the share to earn profits.He is much worried about the loss that might occur so he wanted to calculate "Minimum...
please answer this in a simple python code 1. Write a Python program to construct the...
please answer this in a simple python code 1. Write a Python program to construct the following pattern (with alphabets in the reverse order). It will print the following if input is 5 that is, print z one time, y two times … v five times. The maximum value of n is 26. z yy xxx wwww vvvvvv
PYTHON Program Problem Statement: Write a Python program that processes information related to a rectangle and...
PYTHON Program Problem Statement: Write a Python program that processes information related to a rectangle and prints/displays the computed values. The program will behave as in the following example. Note that in the two lines, Enter length and Enter width, the program does not display 10.0 or 8.0. They are values typed in by the user and read in by the program. The first two lines are text displayed by the program informing the user what the program does. This...
What could happen if you are analyzing some data to solve an engineering problem, but the...
What could happen if you are analyzing some data to solve an engineering problem, but the data was not taken correctly and does not represent the population size?
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT