AIML Unit 1 Chapter 3
AIML Unit 1 Chapter 3
States: A state description specifies the location of each of the eight tiles and the
blank in one of the nine squares.
Initial state: Any state can be designated as the initial state.
Actions: Left, Right, Up, or Down.
Transition model: Given a state and action, this returns the resulting state; for
example, if we apply Left to the start state in Figure 3.4, the resulting state has
the 5 and the blank switched.
Goal test: This checks whether the state matches the goal configuration (Other
goal configurations are possible.)
Path cost: Each step costs 1, so the path cost is the number of steps in the path
8-puzzle
8-queens problem
• States: Any arrangement of 0 to 8 queens on the board is a state.
Initial state: No queens on the board.
Actions: Add a queen to any empty square.
Transition model: Returns the board with a queen added to the
specified square.
Goal test: 8 queens are on the board, none attacked.
Real-world problems
1. Route finding problems
• GPS based navigation systems GMAP
2. Touring Problems
• TSP
3.VLSI Layout Problem: millions of components and connections on a chip to minimize
area, minimize circuit delays, minimize stray capacitances. cell layout and channel routing
4. Robot Navigation Problem
5.Automatic assembly sequencing :
6.Internet Searching
7.Searching paths in metabolic networks in bioinformatics : protein design,
in which the goal is to find a sequence of amino acids that will fold into a three-dimensional
protein with the right properties to cure some disease.
SEARCHING FOR SOLUTIONS
• A solution is an action sequence, so search algorithms work
by considering various possible action sequences.
• The possible action sequences starting at the initial state
form a search tree with the initial state at the root .
• a route from Arad to Bucharest.
• The root node of the tree initial state, In(Arad).
• The first step is to test whether this is a goal state.
• Do this by expanding the current state; thereby generating
a new set of states
• Add three branches from the parent node In(Arad) leading to
three new child nodes: In(Sibiu), In(Timisoara), and In(Zerind).
• Suppose we choose Sibiu first.
• Whether it is a goal state (it is not) and then expand it to get
In(Arad), In(Fagaras), In(Oradea), and In(RimnicuVilcea).
• Choose any of these four or go back and choose Timisoara or
Zerind.
• Each of these six nodes is a leaf node, that is, a node with no
children in the tree.
• The set of all leaf nodes available for expansion at any given
point is called the frontier.
• Loopy paths are a special case redundant paths
whenever there is more than one way to get from one
state to another.
• Consider the paths Arad–Sibiu (140 km long) and
Arad–Zerind–Oradea–Sibiu (297 km long).
• second path is redundant
Infrastructure for search
algorithms
• Search algorithms require a data structure for the search tree. Each node n
of the tree, a structure has four components
n.STATE: the state in the state space to which the node
corresponds;
n.PARENT: the node in the search tree that generated this
node;
n.ACTION: the action that was applied to the parent to
generate the node;
n.PATH-COST: the cost by g(n), of the path from the initial
state to the node, as indicated by the parent pointers.
• The appropriate data structure for this is a queue.
• The operations on a queue are as follows:
EMPTY?(queue) returns true only if there are no more elements in
the queue.
POP(queue) removes the first element of the queue and returns it.
INSERT(element, queue) inserts an element and returns the
resulting queue.
Queues are characterized by the order in which
they store the inserted nodes.
first-in, first-out or FIFO queue, pops the oldest
element of the queue;
last-in, first-out or LIFO queue (also known as a
stack),pops the newest element of the queue;
priority queue, pops the element of the queue with
the highest priority according to some ordering
function.
Measuring problem-solving
performance
design of specific search algorithms
Completeness: Is the algorithm guaranteed to find a
solution when there is one?
Optimality: Does the strategy find the optimal solution
Time complexity: How long does it take to find a solution?
Space complexity: How much memory is needed to perform
the search?
• size of the state space graph, |V | + |E|, where V is the set of
vertices (nodes) of the graph and E is the set of edges (links).
complexity is expressed in three quantities:
• b:Maximum branch factor of the search tree
• d:depth of the least cost solution to reach the goal
• m:maximum depth of the state space
•search cost—
• can use the total cost, which combines the search cost and
the path cost of the solution found.
• Ex:For the problem of finding a route from Arad to
Bucharest, the search cost is the amount of time taken by
the search and the solution cost is the total length of the
path in kilometers.
• to compute the total cost, to add milliseconds and
kilometers
UNINFORMED SEARCH
STRATEGIES
• Blind search.
• No additional information about states except the one provided in
the problem definition.
• All they can do is generate successors and distinguish a goal state
from a non-goal state.
• search strategies -by the order in which nodes are expanded.
• Strategies that know -goal state informed search or heuristic search
strategies;
BFS
DFS
Breadth First Search(BFS)
• The root node is expanded first
• Then all the successors of the root node are expanded.
• Then all their successors and so on.
• All the of a given depth are expanded before any node of the next
depth is expanded.
• Uses a standard queue FIFO as a data structure .
BFS
• BFS is complete(always finds goal if one exists)
• BFS finds the shallowest path to any goal node,if multiple goal nodes
exist ,BFS finds the shortest path
• If the shallowest solution is at depth ‘d’ and the goal test is done when each
node is generated then BFS generates b+b2+b3 ….+bd =O(bd) nodes that has
time complexity of O(bd)
• If the goal test is done when each node is expanded the time complexity of
BFS is O(bd+1)
• The space complexity (frontier size)is also O(bd) .This is the biggest drawback
of BFS
Limitations of BFS
• memory requirements are a bigger problem for breadth-
first search than is the execution time.
• Time is still a major factor.
Breadth-First Strategy
New nodes are inserted at the end of FRINGE
2 3 FRINGE = (1)
4 5 6 7
Breadth-First Strategy
New nodes are inserted at the end of FRINGE
2 3 FRINGE = (2, 3)
4 5 6 7
Breadth-First Strategy
New nodes are inserted at the end of FRINGE
2 3 FRINGE = (3, 4, 5)
4 5 6 7
Breadth-First Strategy
New nodes are inserted at the end of FRINGE
2 3 FRINGE = (4, 5, 6, 7)
4 5 6 7
import collections
def bfs(graph, root):
visited, queue = set(), collections.deque([root])
visited.add(root)
while queue:
# Dequeue a vertex from queue
vertex = queue.popleft()
print(str(vertex) + " ", end="")
# If not visited, mark it as visited, and enqueue it
for neighbour in graph[vertex]:
if neighbour not in visited:
visited.add(neighbour)
queue.append(neighbour)
if __name__ == '__main__':
graph = {0: [1, 2], 1: [2], 2: [3], 3: [1, 2]}
print("Following is Breadth First Traversal: ")
bfs(graph, 0)
Depth-first search
• Expands the deepest node in the current frontier of the
search tree.
• It uses Stack (LIFO queue),means that the most recently
generated node is chosen for expansion
• DFS is frequently programmed recursively.
graph = {
'0':['1', '2'], '1':['2'],'2':['3'],'3':['1', '2']
}
visited =set()
def dfs(visited,graph,root):
if root not in visited:
print(root)
visited.add(root)
for neighbour in graph[root]:
dfs(visited,graph,neighbour)
dfs(visited,graph,'0')
INFORMED (HEURISTIC) SEARCH
STRATEGIES
• uses problem-specific knowledge -can find solutions more efficiently than can
an uninformed strategy.
• General approach is best-first search.
• Best-first search is an instance of TREE-SEARCH or GRAPH-SEARCH algorithm
in which a node is selected for expansion based on an evaluation function,
f(n).
INFORMED (HEURISTIC) SEARCH
STRATEGIES
• The evaluation function is construed as a cost estimate, so the
node with the lowest evaluation is expanded first
• Informed search algorithms include a heuristic function h(n) as a
part of f(n)
• f(n)=g(n)+h(n) g(n) the cost to reach the node
• h(n)=estimate of the cheapest cost form the state at node n to a
goal state;
• h(goal)=0
Greedy best-first search
• GFS tries to expand the node that it estimates as being closest to the goal.
• likely to lead to a solution quickly
• It uses only the heuristic function h(n).
• f(n)=h(n).
• Use a straight line distance(SLD) heuristic hSLD for the route finding in Romania to the goal
Bucharest.
• hSLD(In(Arad))=366. values of hSLD cannot be computed from the problem description
itself.
• It takes a certain amount of experience to know that hSLD is correlated with actual road
distances and is, therefore, a useful heuristic.
• greedy best-first search using hSLD to find a path from Arad to
Bucharest.
• The first node to be expanded from Arad will be Sibiu because it is
closer to Bucharest than either Zerind or Timisoara.
• The next node to be expanded will be Fagaras because it is closest.
Fagaras in turn generates Bucharest, which is the goal.
• For this particular problem, greedy best-first search using hSLD finds a
solution without ever expanding a node that is not on the solution
path; hence, its search cost is minimal.
• It is not optimal, however: the path via Sibiu and Fagaras to Bucharest
is 32 kilometers longer than the path through Rimnicu Vilcea and
Pitesti. “greedy”—at each step it tries to get as close to the goal as
it can.
The algorithm is called greedy because in each step the algorithm
greedily tries to get as close to the goal as possible.
time and space complexity for the tree version is O(bm),
Suggestion for improvement :use the accumulated path distance g(n)
plus a heuristic h(n) as cost function f(n).This leads to A*
• Consider the problem of getting from Iasi to Fagaras.
• The heuristic suggests that Neamt be expanded first because it is
closest to Fagaras, but it is a dead end.
• The solution is to go first to Vaslui—a step that is actually farther from
the goal according to the heuristic—and then to continue to Urziceni,
Bucharest, and Fagaras.
• The algorithm will never find this solution, however, because
expanding Neamt puts Iasi back into the frontier, Iasi is closer to
Fagaras than Vaslui is, and so Iasi will be expanded again, leading to
an infinite loop.
• The worst-case time and space complexity for the tree version is
O(bm), where m is the maximum depth of the search space.
A* search: Minimizing the total estimated
solution cost
• It evaluates nodes by combining g(n), the cost to reach the node, and
h(n), the cost to get from the node to the goal:
• f(n) = g(n) + h(n) .
• g(n) gives the path cost from the start node to node n,
• h(n) is the estimated cost to reach the goal.
• f(n) = estimated cost of the cheapest solution through n .
• Under certain conditions A∗ search is both complete and optimal.
Graph_nodes = {
'A': [('B', 6), ('F', 3)],
'B': [('C', 3), ('D', 2)],
'C': [('D', 1), ('E', 5)],
'D': [('C', 1), ('E', 8)],
'E': [('I', 5), ('J', 5)],
'F': [('G', 1),('H', 7)] ,
'G': [('I', 3)],
'H': [('I', 2)],
'I': [('E', 5), ('J', 3)],
def get_neighbors(v):
if v in Graph_nodes:
return Graph_nodes[v]
else:
return None
def h(n):
H_dist = {
'A': 10,
'B': 8,
'C': 5,
'D': 7,
'E': 3,
'F': 6,
'G': 5,
'H': 3,
'I': 1,
'J': 0
}
return H_dist[n]
def aStarAlgo(start_node, stop_node):
open_set = set(start_node)
closed_set = set()
g = {}
parents = {}
g[start_node] = 0
parents[start_node] = start_node
while len(open_set) > 0:
n = None
for v in open_set:
if n == None or g[v] + h(v) < g[n] + h(n):
n = v
if n == stop_node or Graph_nodes[n] == None:
pass
else:
for (m, weight) in get_neighbors(n):
if m not in open_set and m not in closed_set:
open_set.add(m)
parents[m] = n
g[m] = g[n] + weight
else:
if g[m] > g[n] + weight:
g[m] = g[n] + weight
parents[m] = n
if m in closed_set:
closed_set.remove(m)
open_set.add(m)
if n == None:
print('Path does not
exist!')
return None
if n == stop_node:
path = []
while parents[n] != n:
path.append(n)
n = parents[n]
path.append(start_node)
path.reverse()
print('Path found: {}'.format(path))
return path
open_set.remove(n)
closed_set.add(n)