02 Uninformed Search
02 Uninformed Search
Kalev Kask
• Goal-Test:
– Do goal-test when node inserted into Frontier?
– Do goal-test when node removed?
12
Tree-Search vs. Graph-Search
❑ Example : Assemble 5 objects {a, b, c, d, e}
❑ A state is a bit-vector (length 5), 1=object in assembly, 0= not in assembly
• 11010 = a=1, b=1, c=0, d=1, e=0
• ⇒ a, b, d in assembly; c, e not in assembly
❑ State space:
• Number of states = 25 = 32
• Number of undirected edges = 25 ∙5∙½ = 80
❑ Tree search space:
• Number of nodes = number of paths = 5! = 120
• States can be reached in multiple ways
➢ 11010 can be reached by a+b+d or by a+d+b or by … etc.
• Often requires much more time, but much less space, than graph search
❑ Graph search space:
• Number of nodes = choose(5,0) + choose(5,1) + choose(5,2) + choose(5,3) +
choose(5,4) + choose(5,5) = 1 + 5 + 10 + 10 + 5 + 1 = 32
• States are reached in only one way, redundant paths are pruned
➢ Question: What if a better path is found to a state that already has been explored?
• Often requires much more space, but much less time, than tree search
Checking for identical nodes (1)
Check if a node is already in frontier
• It is “easy” to check if a node is already in the frontier (recall
frontier = fringe = open = queue)
o Keep a hash table holding all frontier nodes
• Hash size is same O(.) as priority queue, so hash does not increase overall space O(.)
• Hash time is O(1), so hash does not increase overall time O(.)
o When a node is expanded, remove it from hash table (it is no
longer in the frontier)
o For each resulting child of the expanded node:
• If child is not in hash table, add it to queue (frontier) and hash table
• Else if an old lower- or equal-cost node is in hash, discard the new higher-
or equal-cost child
• Else remove and discard the old higher-cost node from queue (frontier) and
hash, and add the new lower-cost child to queue (frontier) and hash
Checking for identical nodes (2)
Check if a node is in reached/explored/expanded
• It is memory-intensive [ O(bd) or O(bm) ]to check if a node is
in reached/explored/expanded
o Keep a hash table holding all explored/expanded nodes (hash
table may be HUGE!!)
• When a node is reached, add it to hash (reached)
• For each resulting child of the expanded node:
o If child is not in hash table or in frontier, then add it to the
queue (frontier) and process normally (BFS normal processing
differs from UCS normal processing, but the ideas behind
checking a node for being in reached/explored/expanded are
the same).
o Else discard any redundant node.
Checking for identical nodes (3)
Quick check for search being in a loop
• It is “moderately easy” to check for the search being
in a loop
o When a node is expanded, for each child:
• Trace back through parent pointers from child to root
• If an ancestor state is identical to the child, search is looping
➢ Discard child and fail on that branch
• Time complexity of child loop check is O( depth(child) )
• Memory consumption is zero
➢ Assuming good garbage collection
• Does NOT solve the general problem of repeated
nodes – only the specific problem of looping
• For quizzes and exams, we will follow your textbook
and NOT perform this loop check
Breath First Search
R&N 3.4.1
Breadth-first graph search
Breadth-First Search
• Expand shallowest unexpanded node
• Frontier: nodes waiting in a queue to be explored
– also called Fringe or OPEN
• Implementation:
– Frontier is a first-in-first-out (FIFO) queue, i.e., new successors go
at end of the queue. Future= green dotted circles
Frontier=white nodes
– Goal test when inserted Expanded/active=gray nodes
Forgotten/reclaimed= black nodes
Initial state = A
Is A a goal state?
Expand A to B,C
Is B or C a goal state?
Expand B to D,E
Is D or E a goal state?
Expand C to F, G
Is F or G a goal state?
Frontier = [E,F,G]
Breadth-first search
• Expand shallowest unexpanded node
• Frontier: nodes waiting in a queue to be explored
– also called Fringe, or OPEN
• Implementation:
– Frontier is a first-in-first-out (FIFO) queue (new successors go at end)
– Goal test when inserted
Future= green dotted circles
Frontier=white nodes
Expand E; no children Expanded/active=gray nodes
Forget E; B Forgotten/reclaimed= black nodes
Frontier = [F,G]
Example
BFS for
8-puzzle
Breadth-First Search
Properties of breadth-first search
• Complete? Yes, it always reaches a goal (if b is finite)
• Time? 1 + b + b2 + b3 + … + bd = O(bd)
(this is the number of nodes we generate)
• Space? O(bd)
(keeps every node in memory, either in frontier or on a path to frontier).
• Optimal? No, for general cost functions.
Yes, if cost is a non-decreasing function only of depth.
– With f(d) ≥ f(d-1), e.g., step-cost = constant:
• All optimal goal nodes occur on the same level
• Optimal goals are always shallower than non-optimal goals
• An optimal goal will be found before any non-optimal goal
Depth of Nodes
Solution Expanded Time Memory
Uniform-cost Search:
Expand node with smallest path cost g(n).
• Frontier is a priority queue, i.e., new successors are merged into
the queue sorted by g(n).
– Can remove successors already on queue w/higher g(n).
• Saves memory, costs time; another space-time trade-off.
• Goal-Test when node is popped off queue.
Uniform Cost Search
A B C
g=1 g=5 g=15
Ex: Uniform-cost search (Search tree version)
This early A B C
expensive goal g=1 g=5 g=15
node will go
back onto the G
queue until after g=11
the later
cheaper goal is
found.
Ex: Uniform-cost search (Search tree version)
A B C
g=1 g=5 g=15
G G
g=11 g=10
A B C
g=1 g=5 g=15
G G
g=11 g=10
Expanded:
Next:
Children:
Queue: S/g=0
Ex: Uniform-cost search (Virtual queue version)
Expanded: S/g=0
Next: S/g=0
Children: A/g=1, B/g=5, C/g=15
Queue: S/g=0, A/g=1, B/g=5, C/g=15
Ex: Uniform-cost search (Virtual queue version)
D
...
G is the only goal
node in the search No return from this branch.
space. G will never be popped.
Depth First Search
R&N 3.4.3
DLS Fig 3.12 p.81
• Depth-First Search is a special case of Depth-
Limited Search, when depth limit l=∞
Depth-first search (LIFO version)
• Expand deepest unexpanded node
• Frontier = Last In First Out (LIFO) queue (stack), i.e., new nodes go
at the front of the queue.
• Goal-Test when popped.
Future= green dotted circles
Initial state = A Frontier=white nodes
Expanded/active=gray nodes
PUSH(A) Forgotten/reclaimed= black nodes
frontier = [A]
POP(frontier)->A
frontier=[]
Is A goal? (NO)
…
Depth-first search
• Expand deepest unexpanded node
– Frontier = LIFO queue, i.e., put successors at front
Future= green dotted circles
Frontier=white nodes
Expanded/active=gray nodes
Expand A to B, C – Forgotten/reclaimed= black nodes
generate and PUSH
frontier = [B,C]
POP(frontier)->B
frontier=[C]
Is B goal? (NO)
POP(frontier)->D
frontier=[E,C]
Is D goal? (NO)
Depth-first search
• Expand deepest unexpanded node
– Frontier = LIFO queue, i.e., put successors at front
POP(frontier)->H
frontier=[I,E,C]
Is H goal? (NO)
Depth-first search
• Expand deepest unexpanded node
– Frontier = LIFO queue, i.e., put successors at front
POP(frontier)->I
frontier=[E,C]
Is I goal? (NO)
Depth-first search
• Expand deepest unexpanded node
– Frontier = LIFO queue, i.e., put successors at front
Expand I to no children
frontier = [E,C] Future= green dotted circles
Frontier=white nodes
Forget I, D. Expanded/active=gray nodes
Forgotten/reclaimed= black nodes
POP(frontier)->E
frontier=[C]
Is E goal? (NO)
Depth-first search
• Expand deepest unexpanded node
– Frontier = LIFO queue, i.e., put successors at front
POP(frontier)->J
frontier=[K,C]
Is J goal? (NO)
Depth-first search
• Expand deepest unexpanded node
– Frontier = LIFO queue, i.e., put successors at front
POP(frontier)->K
frontier=[C]
Is K goal? (NO)
Depth-first search
• Expand deepest unexpanded node
– Frontier = LIFO queue, i.e., put successors at front
POP(frontier)->C
frontier=[]
Is C goal? (NO)
Depth-first search
• Expand deepest unexpanded node
– Frontier = LIFO queue, i.e., put successors at front
POP(frontier)->F
frontier=[G]
Is F goal? (NO)
Properties of depth-first search A
• Complete? No: fails in infinite-depth spaces
– IS-CYCLE(node) check avoids loops/repeated states along path
B C
• Time? O(bd)
• Space? O(bd)
• Complexity
– time complexity is best: O(2 b(d/2)) = O(b (d/2))
– memory complexity is the same
Bi-Directional Search
Summary of algorithms
Criterion Breadth- Uniform- Depth- Depth- Iterative Bidirectional
First Cost First Limited Deepening (if applicable)
DLS
Complete? Yes[a] Yes[a,b] No No Yes[a] Yes[a,d]
Time O(bd) O(b1+C*/ε) O(bm) O(bl) O(bd) O(bd/2)
Space O(bd) O(b1+C*/ε) O(bm) O(bl) O(bd) O(bd/2)
Optimal? Yes[c] Yes No No Yes[c] Yes[c,d]
• Iterative deepening search uses only linear space and not much
more time than other uninformed algorithms
http://www.cs.rmit.edu.au/AI-Search/Product/
http://aima.cs.berkeley.edu/demos.html (for more demos)