Problem Solving: Uninformed Search

Problem Solving: Uninformed Search
References
●
●
Russell and Norvig, Artificial Intelligence: A modern approach, 2nd ed.
Prentice Hall, 2003 (chapter 3)
Nilsson, Artificial intelligence: A New synthesis. McGraw Hill, 2001
Outline
 Basic uninformed-search algorithms
 Breadth-first
search
 Uniform-cost search
 Depth-first search
 Depth limited search
 Iterative deepening
 Bidirectional search
 More on uninformed search
 Avoiding
repeated states
Uninformed (Blind) Search
or “blind”
uninformed
non-adversary
search
informed
adversary
or “heuristic”
Uninformed (Blind) Search
 Uninformed --or blind-- search strategies use
only the information available in the problem
definition
 Recall that blind search assumes that f(x) ≡ g(x)
Uninformed search
 Breadth-first search
 Uniform-cost search
 Depth-first search
 Depth-limited search
 Iterative deepening
 Bidirectional search
Breadth-first search
 Idea: explore the search space “horizontally”, i.e.
expanding all nodes at level k before taking into
account nodes at level k+1
Breadth-first search
 Implementation: The intended behavior can be
ensured by using a LIFO policy for storing
expanded nodes
defun BREADTH-FIRST-SEARCH(problem) returns solution
return TREE-SEARCH ( problem, queue )
Breadth-first search
 Node expansion:
 Expand
the shallowest unexpanded node
 Implementation:
 fringe
is a FIFO queue, i.e. new successors go at end
Breadth-first search: properties
 Completeness:
 Yes,
it is complete (if b is finite)
 Time complexity:
 O(bd)
exponential in d (depth of least cost solution)
 Space complexity:
 O(bd)
(keeps every node in memory)
 Optimality:
 NOT
optimal in general
 It is optimal only if the actual cost of any step is 1
Breadth-first search: properties
 Space is the major problem: at a rate of 10.000
nodes/sec (easy), with 10KB/node, generates
860GB in 24 hrs
 If b=10, d=10 it needs 1011 nodes = 129 days
Uninformed search
 Breadth-first search
 Uniform-cost search
 Depth-first search
 Depth-limited search
 Iterative deepening
 Bidirectional search
Uniform-cost search
 Idea: explore the search space according to the
cost g(x) spent to get the node x
 Note that breath-first search is a special case
of uniform-cost search in which g(x) = DEPTH(x)
Uniform-cost search
 Implementation: The intended behavior can be
ensured by using an ordered queue in which
nodes are inserted according to the function
f(x) = g(x)
defun UNIFORM-COST-SEARCH(problem) returns solution
return TREE-SEARCH ( problem, ordered-queue )
Uniform-cost search
 Node expansion:
 Expands
least-cost unexpanded node
 Implementation:
 Fringe
is a queue ordered by path cost
 Completeness:
 Yes,
it is complete, provided that –at each step– the
corresponding cost is ≥ ε
 Optimality:
 Yes,
it is optimal
 Nodes are expanded in increasing order of g(n)
Uninformed search
 Breadth-first search
 Uniform-cost search
 Depth-first search
 Depth-limited search
 Iterative deepening
 Bidirectional search
Depth-first search
 Idea: explore the search space “vertically”
according to a “left-to-right” ordering
Depth-first search
 Implementation: The intended behavior can be
ensured by using a FIFO policy while storing
expanded nodes
defun DEPTH-FIRST-SEARCH(problem) returns solution
return TREE-SEARCH ( problem, stack )
Depth-first search
 Node expansion:
 Expands
the deepest unexpanded node
 Implementation:
 Fringe
is a LIFO queue (i.e. a stack), put successors at front
Depth-first search - continued
Depth-first search: properties
 Completeness:
 No,
in general it is NOT complete (it fails in infinite-depth
spaces --e.g., spaces with state loops)
 It is complete in finite spaces, provided that it is able to
avoid repeated states along paths
 Time complexity:
 O(bm):
terrible if m is much greater than d
 On the other hand, if solutions are dense, it may be much
faster than breadth-first
 Space complexity:
 O(bm)
--- i.e. linear (great!)
 Optimality:
 NOT
optimal
Uninformed search
 Breadth-first search
 Uniform-cost search
 Depth-first search
 Depth-limited search
 Iterative deepening
 Bidirectional search
Depth-limited search
 Idea: avoid the pitfalls of depth-first search by
imposing a cutoff on the maximum depth of a
path
Depth-limited search
 Implementation: perform a depth-first search on
the part of the search tree that fulfills the
constraint imposed by the given limit
 There are three possible outcomes:
 The
GOAL-TEST? function succeeded somewhere within
the part of the search tree that has been explored (i.e. a
solution has been found)
 The imposed limit has been reached somewhere,
meaning that a solution might still be found although NOT
within the given limit (see the pseudo-code: *CUTOFF*)
 A failure occurred, meaning that no solution can be found,
even if the limit constraint is relaxed (see the pseudocode: *FAILURE*)
DLS: an implementation
Depth-limited search
defun DEPTH-LIMITED-SEARCH (problem, limit) returns solution
node ← MAKE-NODE(INITIAL-STATE(problem))
return RECURSIVE-DLS(problem, node, limit)
defun RECURSIVE-DLS (problem, node, limit) returns solution
cutoff? : boolean --- flag used to remember whether cutoff occurred
if problem.GOAL-TEST?(STATE(node)) then return SOLUTION(node)
if DEPTH(node) = limit then return *CUTOFF*
cutoff? ← false
for each succ in problem.EXPAND(node) do
result ← RECURSIVE-DLS(problem, succ, limit)
if result = *CUTOFF* then cutoff? ← true
else if result <> *FAILURE* then return result
if cutoff? then return *CUTOFF* else return *FAILURE*
Uninformed search
 Breadth-first search
 Uniform-cost search
 Depth-first search
 Depth-limited search
 Iterative deepening
 Bidirectional search
Iterative deepening search
 Idea: iteratively perform depth-limited searches
with incremental cutoffs, until a goal state is
found
Iterative deepening search
 Implementation: repeatedly calls a DLS
algorithm, with different (i.e., increasing) depth
limits
IDS: an implementation
Iterative deepening search
defun ITERATIVE-DEEPENING-SEARCH (problem) returns solution
limit ← 0
loop do --- the loop may not terminate ...
result ← DEPTH-LIMITED-SEARCH(problem,limit)
if result <> *CUTOFF* then return result
limit ← limit + 1
Iterative deepening search
Iterative deepening search
Iterative deepening search
Iterative deepening search
Iterative deepening search
 Completeness:
 Yes,
it is complete
 Time complexity:
 (d+1)⋅
b0 + d⋅ b1 + (d-1)⋅ b2 + … + bd = O(bd)
 Space complexity:
 O(b⋅
d)
 Optimality:
 NOT
optimal in general
 It is optimal only if the actual step cost is 1
It can be adapted to use uniform cost; in this case the algorithm is optimal!
Iterative deepening search
 Numerical comparison for b=10 and d=5, with
solution at the far right end of the search tree:
 N(IDS)
= 50 + 400 + 3,000 + 20,000 + 100,000 = 123,450
 N(BFS)
= 10 + 100 + 1,000 + 10,000 + 100,000 + 999,990 = 1,111,100
DLS: an implementation
Summary (uninformed search)
 Problem formulation usually demands abstracting
away real-world details in order to define a state
space that can feasibly be explored.
 There is a variety of uninformed (blind) search
strategies
 Iterative deepening search grants an optimal
solution (in the version adapted to use uniform
cost) with a reasonable amount of time and space
Bidirectional search
 Breadth-first search
 Uniform-cost search
 Depth-first search
 Depth-limited search
 Iterative deepening
 Bidirectional search
Bidirectional search
 Idea: save time by searching from both the
initial state (forward) and the final state
(backward)
Bidirectional search
 Stop when both searches meet bd/2+ bd/2 << bd
 To avoid repetitions, one search (or both) must
check –for each node to be expanded– whether
the corresponding state is in the fringe of the
other tree
Bidirectional search
 Space complexity:
 O(bd/2),
because at least one of the trees must be kept in
memory
 Difficulties:
 Can
we compute “predecessor(n)” efficiently?
 What is the initial state for backward search if the overall
goal is defined by a goal condition (e.g.. “checkmate”)?
More on Uninformed Search
Repeated states
 Failure to detect repeated states can turn a
linear problem into an exponential one!
Dealing with repeated states
 Introduce a CLOSED list that stores every
expanded node
 If
the current node is in the CLOSED list, discard it instead
of expanding it
 Keeping each node in memory increases space
complexity
 The fringe of unexpanded nodes is frequently
called the OPEN list
Tree Search with OPEN-CLOSED lists
defun GRAPH-SEARCH (problem, fringe) returns solution
closed ← {} --- a set of CLOSED nodes (actually states), initially empty
fringe.insert(MAKE-NODE(problem.initial-state))
while not ISEMPTY?(fringe) do
node ← fringe.remove()
if problem.GOAL-TEST?(STATE(node))
then return SOLUTION(node)
if not closed.member(STATE(node)) then
closed.add(STATE(node))
children ← problem.EXPAND(node)
for each child in children do fringe.insert(child)
return *FAILURE*