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

Heuristic Search Algorithms

The document discusses various heuristic search algorithms including A*, breadth-first search (BFS), and depth-first search (DFS). It provides explanations of the algorithms along with Python code examples of implementing BFS and DFS on graphs. It also gives an example of using the simpleai library to solve a constraint satisfaction problem (CSP) by modeling a coloring problem with names and color constraints.

Uploaded by

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

Heuristic Search Algorithms

The document discusses various heuristic search algorithms including A*, breadth-first search (BFS), and depth-first search (DFS). It provides explanations of the algorithms along with Python code examples of implementing BFS and DFS on graphs. It also gives an example of using the simpleai library to solve a constraint satisfaction problem (CSP) by modeling a coloring problem with names and color constraints.

Uploaded by

faheemmahmood1
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

Heuristic Search Algorithms

Instructor:Faheem Mahmood
March 16, 2024

1 Heuristic Search Algorithms


1.1 The simpleai Library
This lib implements many of the artificial intelligence algorithms described on the book “Artificial
Intelligence, a Modern Approach”, from Stuart Russel and Peter Norvig. We strongly recommend
you to read the book, or at least the introductory chapters and the ones related to the components
you want to use, because we won’t explain the algorithms here.

[1]: # to check wheather simpleai is installed or not

import simpleai as sa

print(sa)

<module 'simpleai' from 'B:\\AI Spring22\\Lab


Manuals\\Lab06\\simpleai\\__init__.py'>
We will be using a package called simpleai throughout the code. It contains various rou-
tines that are useful in building solutions using heuristic search techniques. It’s available at
https://github.com/simpleai-team/simpleai.
Or we can also install it by pip. Just have a look to new cell.
So we’re going to install ‘simpleai’ library by typing ‘pip install simpleai’

[2]: pip install simpleai

Collecting simpleai
Downloading simpleai-0.8.3.tar.gz (94 kB)
Building wheels for collected packages: simpleai
Building wheel for simpleai (setup.py): started
Building wheel for simpleai (setup.py): finished with status 'done'
Created wheel for simpleai: filename=simpleai-0.8.3-py3-none-any.whl
size=101000
sha256=a5eafe893302e4e0eded26358acd6dcb29fbd74dc239abfd0d6885d8fc52a72e
Stored in directory: c:\users\ahmad\appdata\local\pip\cache\wheels\49\98\03\7b
d5011c19ca8909a0db02f6c8a536d339ac356a17cac01372
Successfully built simpleai
Installing collected packages: simpleai

1
Successfully installed simpleai-0.8.3
Note: you may need to restart the kernel to use updated packages.
Simple AI allows you to define problems and look for the solution with different strategies. Here
is an easiest problem which is familiar to you This problem tries to create the string “HELLO
WORLD” using the A* algorithm:

[3]: from simpleai.search import SearchProblem, astar

GOAL = 'HELLO WORLD'

class HelloProblem(SearchProblem):
def actions(self, state):
if len(state) < len(GOAL):
return list(' ABCDEFGHIJKLMNOPQRSTUVWXYZ')
else:
return []

def result(self, state, action):


return state + action

def is_goal(self, state):


return state == GOAL

def heuristic(self, state):


# how far are we from the goal?
wrong = sum([1 if state[i] != GOAL[i] else 0 for i in␣
,→range(len(state))])

missing = len(GOAL) - len(state)


return wrong + missing

problem = HelloProblem(initial_state='')
result = astar(problem)

print(result.state)
print(result.path())

HELLO WORLD
[(None, ''), ('H', 'H'), ('E', 'HE'), ('L', 'HEL'), ('L', 'HELL'), ('O',
'HELLO'), (' ', 'HELLO '), ('W', 'HELLO W'), ('O', 'HELLO WO'), ('R', 'HELLO
WOR'), ('L', 'HELLO WORL'), ('D', 'HELLO WORLD')]

1.2 Breadth-first search (BFS)


Breadth-first search (BFS) is an algorithm used for tree traversal on graphs or tree data structures.
BFS can be easily implemented using recursion and data structures like dictionaries and lists.

2
The Algorithm: Pick any node, visit the adjacent unvisited vertex, mark it as visited, display it,
and insert it in a queue. If there are no remaining adjacent vertices left, remove the first vertex
from the queue. Repeat step 1 and step 2 until the queue is empty or the desired node is found.
Implementation Consider the graph, which is implemented in the code below:

3
[4]: graph = {
'A' : ['B','C'],
'B' : ['D', 'E'],
'C' : ['F'],
'D' : [],
'E' : ['F'],
'F' : []
}

visited = [] # List to keep track of visited nodes.


queue = [] #Initialize a queue

def bfs(visited, graph, node):


visited.append(node)
queue.append(node)

while queue:
s = queue.pop(0)
print (s, end = " ")

for neighbour in graph[s]:


if neighbour not in visited:
visited.append(neighbour)
queue.append(neighbour)

# Driver Code
bfs(visited, graph, 'A')

A B C D E F

1.2.1 Explanation
Lines 3-10: The illustrated graph is represented using an adjacency list. An easy way to do this
in Python is to use a dictionary data structure, where each vertex has a stored list of its adjacent
nodes.
Line 12: visited is a list that is used to keep track of visited nodes.
Line 13: queue is a list that is used to keep track of nodes currently in the queue.
Line 29: The arguments of the bfs function are the visited list, the graph in the form of a dictionary,
and the starting node A.
Lines 15-26: bfs follows the algorithm described above:
It checks and appends the starting node to the visited list and the queue. Then, while the queue
contains elements, it keeps taking out nodes from the queue, appends the neighbors of that node
to the queue if they are unvisited, and marks them as visited. This continues until the queue is
empty.

4
1.3 Depth-first search (DFS)
Depth-first search (DFS), is an algorithm for tree traversal on graph or tree data structures. It can
be implemented easily using recursion and data structures like dictionaries and sets.
The Algorithm: Pick any node. If it is unvisited, mark it as visited and recur on all its adjacent
nodes. Repeat until all the nodes are visited, or the node to be searched is found.
Implementation Consider this graph, implemented in the code below:

5
[5]: # Using a Python dictionary to act as an adjacency list
graph = {
'A' : ['B','C'],
'B' : ['D', 'E'],
'C' : ['F'],
'D' : [],
'E' : ['F'],
'F' : []
}

visited = set() # Set to keep track of visited nodes.

def dfs(visited, graph, node):


if node not in visited:
print (node)
visited.add(node)
for neighbour in graph[node]:
dfs(visited, graph, neighbour)

# Driver Code
dfs(visited, graph, 'A')

A
B
D
E
F
C

1.3.1 Explanation
Lines 2-9: The illustrated graph is represented using an adjacency list - an easy way to do it in
Python is to use a dictionary data structure. Each vertex has a list of its adjacent nodes stored.
Line 11: visited is a set that is used to keep track of visited nodes. Line 21: The dfs function
is called and is passed the visited set, the graph in the form of a dictionary, and A, which is the
starting node. Lines 13-18: dfs follows the algorithm described above: It first checks if the current
node is unvisited - if yes, it is appended in the visited set. Then for each neighbor of the current
node, the dfs function is invoked again. The base case is invoked when all the nodes are visited.
The function then returns.

1.4 Solving a Problem with Constraints


We have already discussed in class that how CSPs are formulated. Let’s apply them to a real-world
problem. In this problem, we have a list of names and each name can take a fixed set of values.
We also have a set of constraints between these people that needs to be satisfied. Let’s see how to
do it.

6
[6]: 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),

7
(('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)

Color mapping:

Mark ==> red


Julia ==> green
Steve ==> blue
Amanda ==> red
Brian ==> red
Joanne ==> green
Derek ==> blue
Allan ==> red
Michelle ==> gray
Kelly ==> gray

You might also like