0% found this document useful (0 votes)
15 views

Lab8-Solution

The document contains multiple lab tasks that demonstrate the use of constraint satisfaction problems (CSP) and search algorithms in Python using the SimpleAI library. Each task includes the definition of variables, domains, constraints, and methods to solve problems such as coloring a graph, solving a sliding puzzle, and navigating a maze. The tasks illustrate various techniques like backtracking, A* search, and heuristics to find solutions efficiently.

Uploaded by

Mubeen Ahmed
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

Lab8-Solution

The document contains multiple lab tasks that demonstrate the use of constraint satisfaction problems (CSP) and search algorithms in Python using the SimpleAI library. Each task includes the definition of variables, domains, constraints, and methods to solve problems such as coloring a graph, solving a sliding puzzle, and navigating a maze. The tasks illustrate various techniques like backtracking, A* search, and heuristics to find solutions efficiently.

Uploaded by

Mubeen Ahmed
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 9

Lab task 1

from simpleai.search import CspProblem, backtrack, \


min_conflicts, MOST_CONSTRAINED_VARIABLE, \
HIGHEST_DEGREE_VARIABLE, LEAST_CONSTRAINING_VALUE

# Constraint that expects all the different variables


# to have different values
def constraint_unique(variables, values):
# Check if all the values are unique
return len(values) == len(set(values))

# Constraint that specifies that one variable


# should be bigger than other
def constraint_bigger(variables, values):
return values[0] > values[1]

# Constraint that specifies that there should be


# one odd and one even variables in the two variables
def constraint_odd_even(variables, values):
# If first variable is even, then second should
# be odd and vice versa
if values[0] % 2 == 0:
return values[1] % 2 == 1
else:
return values[1] % 2 == 0

if __name__=='__main__':
variables = ('John', 'Anna', 'Tom', 'Patricia')

domains = {
'John': [1, 2, 3],
'Anna': [1, 3],
'Tom': [2, 4],
'Patricia': [2, 3, 4],
}

constraints = [
(('John', 'Anna', 'Tom'), constraint_unique),
(('Tom', 'Anna'), constraint_bigger),
(('John', 'Patricia'), constraint_odd_even),
]

problem = CspProblem(variables, domains, constraints)


print('\nSolutions:\n\nNormal:', backtrack(problem))
print('\nMost constrained variable:', backtrack(problem,
variable_heuristic=MOST_CONSTRAINED_VARIABLE))
print('\nHighest degree variable:', backtrack(problem,
variable_heuristic=HIGHEST_DEGREE_VARIABLE))
print('\nLeast constraining value:', backtrack(problem,
value_heuristic=LEAST_CONSTRAINING_VALUE))
print('\nMost constrained variable and least constraining value:',
backtrack(problem, variable_heuristic=MOST_CONSTRAINED_VARIABLE,
value_heuristic=LEAST_CONSTRAINING_VALUE))
print('\nHighest degree and least constraining value:',
backtrack(problem, variable_heuristic=HIGHEST_DEGREE_VARIABLE,
value_heuristic=LEAST_CONSTRAINING_VALUE))
print('\nMinimum conflicts:', min_conflicts(problem))

Lab task 2
from simpleai.search import CspProblem, backtrack

# Define the function that imposes the constraint


# that neighbors should be different
def constraint_func(names, values):
return values[0] != values[1]

if __name__=='__main__':
# Specify the variables
names = ('Mark', 'Julia', 'Steve', 'Amanda', 'Brian',
'Joanne', 'Derek', 'Allan', 'Michelle', 'Kelly')

# Define the possible colors


colors = dict((name, ['red', 'green', 'blue', 'gray']) for name in names)

# Define the constraints


constraints = [
(('Mark', 'Julia'), constraint_func),
(('Mark', 'Steve'), constraint_func),
(('Julia', 'Steve'), constraint_func),
(('Julia', 'Amanda'), constraint_func),
(('Julia', 'Derek'), constraint_func),
(('Julia', 'Brian'), constraint_func),
(('Steve', 'Amanda'), constraint_func),
(('Steve', 'Allan'), constraint_func),
(('Steve', 'Michelle'), constraint_func),
(('Amanda', 'Michelle'), constraint_func),
(('Amanda', 'Joanne'), constraint_func),
(('Amanda', 'Derek'), constraint_func),
(('Brian', 'Derek'), constraint_func),
(('Brian', 'Kelly'), constraint_func),
(('Joanne', 'Michelle'), constraint_func),
(('Joanne', 'Amanda'), constraint_func),
(('Joanne', 'Derek'), constraint_func),
(('Joanne', 'Kelly'), constraint_func),
(('Derek', 'Kelly'), constraint_func),
]

# Solve the problem


problem = CspProblem(names, colors, constraints)

# Print the solution


output = backtrack(problem)
print('\nColor mapping:\n')
for k, v in output.items():
print(k, '==>', v)

Lab task 3

from simpleai.search import astar, SearchProblem

# Class containing methods to solve the puzzle


class PuzzleSolver(SearchProblem):
# Action method to get the list of the possible
# numbers that can be moved in to the empty space
def actions(self, cur_state):
rows = string_to_list(cur_state)
row_empty, col_empty = get_location(rows, 'e')

actions = []
if row_empty > 0:
actions.append(rows[row_empty - 1][col_empty])
if row_empty < 2:
actions.append(rows[row_empty + 1][col_empty])
if col_empty > 0:
actions.append(rows[row_empty][col_empty - 1])
if col_empty < 2:
actions.append(rows[row_empty][col_empty + 1])

return actions

# Return the resulting state after moving a piece to the empty space
def result(self, state, action):
rows = string_to_list(state)
row_empty, col_empty = get_location(rows, 'e')
row_new, col_new = get_location(rows, action)

rows[row_empty][col_empty], rows[row_new][col_new] = \
rows[row_new][col_new], rows[row_empty][col_empty]

return list_to_string(rows)

# Returns true if a state is the goal state


def is_goal(self, state):
return state == GOAL

# Returns an estimate of the distance from a state to


# the goal using the manhattan distance
def heuristic(self, state):
rows = string_to_list(state)

distance = 0

for number in '12345678e':


row_new, col_new = get_location(rows, number)
row_new_goal, col_new_goal = goal_positions[number]

distance += abs(row_new - row_new_goal) + abs(col_new - col_new_goal)


return distance

# Convert list to string


def list_to_string(input_list):
return '\n'.join(['-'.join(x) for x in input_list])

# Convert string to list


def string_to_list(input_string):
return [x.split('-') for x in input_string.split('\n')]

# Find the 2D location of the input element


def get_location(rows, input_element):
for i, row in enumerate(rows):
for j, item in enumerate(row):
if item == input_element:
return i, j

# Final result that we want to achieve


GOAL = '''1-2-3
4-5-6
7-8-e'''

# Starting point
INITIAL = '''1-e-2
6-3-4
7-5-8'''

# Create a cache for the goal position of each piece


goal_positions = {}
rows_goal = string_to_list(GOAL)
for number in '12345678e':
goal_positions[number] = get_location(rows_goal, number)

# Create the solver object


result = astar(PuzzleSolver(INITIAL))

# Print the results


for i, (action, state) in enumerate(result.path()):
print()
if action == None:
print('Initial configuration')
elif i == len(result.path()) - 1:
print('After moving', action, 'into the empty space. Goal achieved!')
else:
print('After moving', action, 'into the empty space')

print(state)

Lab task 4

import math
from simpleai.search import SearchProblem, astar

# Class containing the methods to solve the maze


class MazeSolver(SearchProblem):
# Initialize the class
def __init__(self, board):
self.board = board
self.goal = (0, 0)

for y in range(len(self.board)):
for x in range(len(self.board[y])):
if self.board[y][x].lower() == "o":
self.initial = (x, y)
elif self.board[y][x].lower() == "x":
self.goal = (x, y)

super(MazeSolver, self).__init__(initial_state=self.initial)

# Define the method that takes actions


# to arrive at the solution
def actions(self, state):
actions = []
for action in COSTS.keys():
newx, newy = self.result(state, action)
if self.board[newy][newx] != "#":
actions.append(action)

return actions

# Update the state based on the action


def result(self, state, action):
x, y = state

if action.count("up"):
y -= 1
if action.count("down"):
y += 1
if action.count("left"):
x -= 1
if action.count("right"):
x += 1

new_state = (x, y)

return new_state

# Check if we have reached the goal


def is_goal(self, state):
return state == self.goal

# Compute the cost of taking an action


def cost(self, state, action, state2):
return COSTS[action]

# Heuristic that we use to arrive at the solution


def heuristic(self, state):
x, y = state
gx, gy = self.goal

return math.sqrt((x - gx) ** 2 + (y - gy) ** 2)

if __name__ == "__main__":
# Define the map
MAP = """
##############################
# # # #
# #### ######## # #
# o# # # #
# ### ##### ###### #
# # ### # #
# # # # # # ###
# ##### # # # x #
# # # #
##############################
"""

# Convert map to a list


print(MAP)
MAP = [list(x) for x in MAP.split("\n") if x]

# Define cost of moving around the map


cost_regular = 1.0
cost_diagonal = 1.7

# Create the cost dictionary


COSTS = {
"up": cost_regular,
"down": cost_regular,
"left": cost_regular,
"right": cost_regular,
"up left": cost_diagonal,
"up right": cost_diagonal,
"down left": cost_diagonal,
"down right": cost_diagonal,
}

# Create maze solver object


problem = MazeSolver(MAP)

# Run the solver


result = astar(problem, graph_search=True)

# Extract the path


path = [x[1] for x in result.path()]

# Print the result


print()
for y in range(len(MAP)):
for x in range(len(MAP[y])):
if (x, y) == problem.initial:
print('o', end='')
elif (x, y) == problem.goal:
print('x', end='')
elif (x, y) in path:
print('·', end='')
else:
print(MAP[y][x], end='')

print()

You might also like