Uploaded by namblininambli

Lesson 04 Problem Solving by Searching

advertisement
Problem Solving by Searching
SCO113: Foundations of Artificial
Intelligence
Search
• Search plays a key role in many parts of AI. These algorithms
provide the conceptual backbone of almost every approach to the
systematic exploration of alternatives.
• There are four classes of search algorithms, which differ along
two dimensions:
– First, is the difference between uninformed (also known as blind)
search and then informed (also known as heuristic) searches.
• Informed searches have access to task-specific information that can be
used to make the search process more efficient.
– The other difference is between any solution searches and optimal
searches.
• Optimal searches are looking for the best possible solution while anypath searches will just settle for finding some solution.
Graphs
• Graphs are everywhere; E.g., think about road networks or airline
routes or computer networks.
• In all of these cases we might be interested in finding a path
through the graph that satisfies some property.
• It may be that any path will do or we may be interested in a path
having the fewest "hops" or a least cost path assuming the hops
are not all equivalent.
Romania graph
Formulating the problem
• On holiday in Romania; currently in Arad.
• Flight leaves tomorrow from Bucharest.
• Formulate goal:
– be in Bucharest
• Formulate problem:
– states: various cities
– actions: drive between cities
• Find solution:
– sequence of cities, e.g., Arad, Sibiu, Fagaras, Bucharest
Another graph example
• However, graphs can also be much more abstract.
• A path through such a graph (from a start node to a goal node) is
a "plan of action" to achieve some desired goal state from some
known starting state.
• It is this type of graph that is of more general interest in AI.
Problem solving
• One general approach to problem solving in AI is to reduce the
problem to be solved to one of searching a graph.
• To use this approach, we must specify what are the states, the
actions and the goal test.
• A state is supposed to be complete, that is, to represent all the
relevant aspects of the problem to be solved.
• We are assuming that the actions are deterministic, that is, we
know exactly the state after the action is performed.
Goal test
• In general, we need a test for the goal, not just one specific goal
state.
– So, for example, we might be interested in any city in Germany
rather than specifically Frankfurt.
• Or, when proving a theorem, all we care is about knowing one
fact in our current data base of facts.
– Any final set of facts that contains the desired fact is a proof.
Example Problems
“Toy” Problems: Simple, but useful for theory and analysis
Vacuum world, Sliding-block puzzles, N-Queens
Real Problems: The solutions are more useful, but not as
helpful to theory
Route-finding, touring, assembly sequencing, Internet
searching
Vacuum cleaner
Vacuum cleaner
Formally…
A problem is defined by four items:
1.
2.
initial state e.g., "at Arad"
actions and successor function S: = set of action-state tuples
–
3.
goal test, can be
–
–
–
4.
explicit, e.g., x = "at Bucharest"
implicit, e.g., Checkmate(x)
path cost (additive)
–
–
•
e.g., S(Arad) = {(goZerind, Zerind), (goTimisoara, Timisoara),
(goSilbiu, Silbiu)}
e.g., sum of distances, or number of actions executed, etc.
c(x,a,y) is the step cost, assumed to be ≥ 0
A solution is a sequence of actions leading from the initial state to a goal
state
Searching for Solutions
• State space can be represented as a search tree (or
graph) of search nodes
• Each node represents a state
– Many nodes can represent the same state
• Each arc represents a valid action from one state to
another
• A solution is a path from initial to goal nodes
Search Nodes
• A search node is a data structure that contains
–
–
–
–
–
The real-world state represented by the node
The parent node that generated it
The action that lead to it
The path cost to get to it (from the initial state)
Its depth (the number of steps to reach it from the initial state)
Searching for Solutions
• The search tree starts with just the root node, which
represents the initial state
• First, use the goal test to see if the root is a goal
• If not, expand this node, which generates new nodes
– Use successor function to apply valid actions. The results of
these actions lead to new states, represented by new nodes
• Nodes that are generated, but not yet expanded are in
the fringe, (physically a queue data structure)
Example: The 8-puzzle
•
•
•
•
states?
actions?
goal test?
path cost?
Example: The 8-puzzle
•
•
•
•
states? locations of tiles
actions? move blank left, right, up, down
goal test? = goal state (given)
path cost? 1 per move
Romania graph
Tree search example
Tree search example
Tree search example
Tree search algorithms
• Basic idea:
– Exploration of state space by generating successors of already-explored
states (i.e. expanding states)
(
Data type node:
components : STATE , PARENT_NODE , OPERATOR ,
DEPTH , PATH_COST
Function GENERAL-SEARCH ( problem ,QUEUING_FN ) returns
a solution or failure
nodes  MAKE_QUEUE (MAKE_NODE (INITIAL_STATE
[problem ] ))
Loop do
if nodes is empty then return failure
node  REMOVE_FRONT (nodes )
if GOAL_TEST [problem ] applied to STATE ( node ) succeeds
then return node
nodes  QUEUING_FN (nodes , EXPAND (node ,OPERATORS
[problem ] ))
End
Function SIMPLE-PROBLEM-SOLVING-AGENT(percept) returns an action
Inputs: percept , a percept
Static: seq , an action sequence , initially empty
state , some description of the current world state
goal , a goal , initially null
problem , a problem formulation
State ← UPDATE-STATE(state,percept)
If seq is empty then do
goal ← FORMULATE-GOAL(state)
problem ← FORMULATE-PROBLEM(state,goal)
seq ← SEARCH(problem)
action ← FIRST(seq)
seq ← REST(seq)
Return action
Function Tree-Search(problem,fringe) returns a solution, or failure
fringe←Insert(MAKE-NODE(INITIAL-STATE[problem]),fringe)
loop do
if Empty?(fringe) then return failure
node ← REMOVE-FIRST(fringe)
if GOAL-TEST[problem] applied to STATE[node] succeeds
then return SOLUTION(node)
fringe ← INSERT-ALL(EXPAND(node,problem),fringe)
Function EXPAND(node,problem) returns a set of nodes
successors ← the empty set
For each(action,result)in SUCCESSOR-FN[problem](STATE[node]) do
s ← a new node
STATE[s] ← result
PARENT-NODE[s] ← node
ACTION[s] ← action
PATH-COST[s] ← PATH-COST[node]+STEP-COST(node,action,s)
DEPTH[s] ← DEPTH[node]+1
add s to successors
return successors
Search strategies
• A search strategy is defined by picking the order of node
expansion
• Search algorithms (strategies) are evaluated/measured along the
following four dimensions:
– completeness: does it always find a solution if one exists?
– time complexity: number of nodes generated
– space complexity: maximum number of nodes in memory
– optimality: does it always find a least-cost solution?
• Time and space complexity are measured in terms of
– b: maximum branching factor of the search tree
– d: depth of the least-cost solution
– m: maximum depth of the state space
Categories of search strategies
• Uninformed search
– no information about the number of steps
– or the path cost from the current state to the goal
– search the state space blindly
• Informed search, or heuristic search
– a cleverer strategy that searches toward the goal,
– based on the information from the current state so far
Uninformed search strategies
• Uninformed do not use information relevant to the specific
problem.
•
•
•
•
•
•
Breadth-first search
Uniform-cost search
Depth-first search
Depth-limited search
Iterative deepening search
Bidirectional search
Breadth-first search
• Function BREADTH_FIRST_SEARCH ( problem ) return a
solution or failure
•
return GENERAL_SEARCH (problem ,ENQUEUE_AT_END
Breadth-first search
• TreeSearch(problem, FIFO-QUEUE()) results in a breadth-first
search.
• The FIFO queue puts all newly generated successors at the end of the
queue, which means that shallow nodes are expanded before deeper
nodes.
– I.e. Pick from the fringe to expand the shallowest unexpanded node
Breadth-first search
• Expand shallowest unexpanded node
• Implementation:
– fringe is a FIFO queue, i.e., new successors go at end
Breadth-first search
• Expand shallowest unexpanded node
• Implementation:
– fringe is a FIFO queue, i.e., new successors go at end
Breadth-first search
• Expand shallowest unexpanded node
• Implementation:
– fringe is a FIFO queue, i.e., new successors go at end
Breadth-First Search (BFS)
Breadth-first search
S
A
B
C
11
D
14
D
D
E
A
E
F
B
F
G
19
C
19
G
17
E
B
C
17
B
E
A
15
F
G 25
F
C
15
G
13
Performance of Breadth-First Search
• Good news
– It is complete
– It is optimal, as long as the path cost function is nondecreasing (e.g., if all actions have the same cost)
• Bad news
– Time and (especially) space complexity can be
prohibitively high
• Has to keep all nodes in memory: queue gets large
• If d is large, takes a long time to reach a goal
The Properties of breadth-first
search
• Complete?
– Yes (if b is finite)
• Time?
– 1+b+b2+b3+… +bd + b(bd-1) = O(bd+1)
• Space?
– O(bd+1) (keeps every node in memory)
• Optimal?
– Yes (if cost is a non-decreasing function of depth, e.g. when we
have 1 cost per step)
Uniform-cost search
•
•
•
Expand least-cost unexpanded node.
The algorithm expands nodes in order of increasing path cost.
Therefore, the first goal node selected for expansion is the optimal solution.
•
Implementation:
– fringe = queue ordered by path cost (priority queue)
•
Equivalent to breadth-first if step costs all equal
•
Complete? Yes, if step cost ≥ ε (I.e. not zero)
•
Time? number of nodes with g ≤ cost of optimal solution, O(bC*/ ε) where C* is the
cost of the optimal solution
•
Space? Number of nodes with g ≤ cost of optimal solution, O(bC*/ ε)
•
Optimal? Yes – nodes expanded in increasing order of g(n)
Uniform cost search
• the first found solution is guaranteed to be the cheapest
– least in depth
– But restrict to non-decreasing path cost
– Unsuitable for operators with negative cost
Depth-First Search (DFS)
• DFS expands the deepest node first
• Implemented in TREE-SEARCH using a last-in firstout (LIFO) queue
– State to consider is pulled from front of queue
– Generated states are added at the front of the queue
– Check first successor of the root node. Then check its
successor, etc.
– If a non-goal node is reached with no successors, back up
just until an unexpanded node is reached, then continue.
Depth-first search
• Expand deepest unexpanded node
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
Depth-first search
• Expand deepest unexpanded node
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
Depth-first search
• Expand deepest unexpanded node
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
Depth-first search
• Expand deepest unexpanded node
•
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
–
Depth-first search
• Expand deepest unexpanded node
•
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
–
Depth-first search
• Expand deepest unexpanded node
•
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
–
Depth-first search
• Expand deepest unexpanded node
•
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
–
Depth-first search
• Expand deepest unexpanded node
•
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
–
Depth-first search
• Expand deepest unexpanded node
•
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
–
Depth-first search
• Expand deepest unexpanded node
•
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
–
Depth-first search
• Expand deepest unexpanded node
•
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
–
Depth-first search
• Expand deepest unexpanded node
•
• Implementation:
– fringe = LIFO queue, i.e., put successors at front
–
Depth-first search
S
A
B
C
11
D
14
D
D
E
A
E
F
B
F
G
19
C G
19 17
E
B
C
17
B
E
A
15
F
G 25
F
C
15
G
13
Depth-first search (Analysis)
• Not complete
– because a path may be infinite or looping
– then the path will never fail and go back try another option
• Not optimal
– it doesn't guarantee the best solution
• It overcomes (Good NEWS)
– the time and space complexities
Properties of depth-first search
• Complete? No: fails in infinite-depth spaces, spaces with loops
– Modify to avoid repeated states along path
 complete in finite spaces
• Time? O(bm): terrible if m is much larger than d
– but if solutions are dense, may be much faster than breadth-first
• Space? O(bm), i.e., linear space!
• Optimal? No
Depth-Limited Search (DLS)
• DLS is DFS with a depth limit, L
– Nodes at depth limit are treated as leaves
– Depth limits can come from domain knowledge
• E.g., L = diameter of state space
• Implemented same as DFS, but with depth limit
• Performance
– Incomplete if L < d
– Nonoptimal if L > d
– Time and space complexity <= DFS
Depth-limited search
DepthLimitedSearch (int limit)
{
stackADT fringe;
insert root into the fringe
do {
if (Empty(fringe)) return NULL; /* Failure */
nodePT = Pop(fringe);
if (GoalTest(nodePT->state))
return nodePT;
/* Expand node and insert all the successors */
if (nodePT->depth < limit)
insert into the fringe Expand(nodePT)
} while (1);
}
Iterative Deepening Depth-First
Search (IDDFS)
• IDDFS performs DLS one or more times, each time
with a larger depth limit, l
– Start with l = 0, perform DLS
– If goal not found, repeat DLS with l = 1, and so on
• Performance
– Combines benefits of BFS (completeness, optimality) with
benefits of DFS (relatively low space complexity)
• Not as inefficient as it looks
– Repeating low-depth levels: these levels do not have many
nodes
Iterative deepening Search
Function ITERATIVE_DEEPING_SEARCH( problem ) returns a
solution sequence or failure
inputs: problem , a problem
for depth ← 0 to ∞ do
if DEPTH_LIMITED_SEARCH ( problem , depth ) succeeds
then return its result
end
return failure
Iterative deepening search l =0
Iterative deepening search l =1
Iterative deepening search l =2
Iterative deepening search l =3
Iterative deepening search
Iterative deepening search
(Analysis)
• optimal
• complete
• Time and space complexities
– reasonable
• suitable for the problem
– having a large search space
– and the depth of the solution is not known
Iterative deepening search
• Number of nodes generated in a breadth-first search to depth d
with branching factor b:
NBFS = b0 + b1 + b2 + … + bd-2 + bd-1 + bd
• Number of nodes generated in an iterative deepening search to
depth d with branching factor b:
NIDS = (d+1)b0 + d b1 + (d-1)b2 + … + 3bd-2 +2bd-1 + 1bd
• For b = 10, d = 5,
– NBFS = 1 + 10 + 100 + 1,000 + 10,000 + 100,000 = 111,111
–
– NIDS = 6 + 50 + 400 + 3,000 + 20,000 + 100,000 = 123,456
–
• Overhead = (123,456 - 111,111)/111,111 = 11%
•
•
•
•
Properties of iterative deepening
search
Complete? Yes
Time? (d+1)b0 + d b1 + (d-1)b2 + … + bd = O(bd)
Space? O(bd)
Optimal? Yes, if step cost = 1
Bidirectional Search
• Perform two searches simultaneously
– One search from the initial state to a goal state
– Another search from a goal state to the initial state
– Stop searching when either search reaches a state that is in
the fringe of the other state (i.e., when they “meet in the
middle”)
• Performance
– Complete and optimal if both searches are BFS
– Not easy to generate predecessors for some goals (e.g.,
checkmate)
Bidirectional Strategy
2 fringe queues: FRINGE1 and FRINGE2
Time and space complexity = O(bd/2) << O(bd)
Bidirectional
search
S
A
B
C
11
D
14
Forward
Backwards
D
D
E
A
E
F
B
F
G
19
C
19
G
17
E
B
C
17
B
E
A
15
F
G 25
F
C
15
G
13
Avoiding Repeated States
• Reaching a node with a repeated state means that there are at
least two paths to the same state
– Can lead to infinite loops
• Keep a list of all nodes expanded so far (called the closed list;
the fringe is the open list)
– If a generated node’s state matches a state in the closed list,
discard it rather than adding it to the fringe
Avoiding repeated states
• for all search strategies
– There is possibility of expanding states
• that have already been encountered and expanded before, on some
other path
– may cause the path to be infinite  loop forever
– Algorithms that forget their history
• are doomed to repeat it
Repeated states
• Failure to detect repeated states can turn a linear problem into an
exponential one!
Avoiding repeated states
• Three ways to deal with this possibility
– Do not return to the state it just came from
• Refuse generation of any successor same as its parent state
– Do not create paths with cycles
• Refuse generation of any successor same as its ancestor states
– Do not generate any generated state
• Not only its ancestor states, but also all other expanded states have to
be checked against
Avoiding repeated states
• We then define a data structure
– closed list:
a set storing every expanded node so far
– If the current node matches a node on the closed list, discard
it.
Which Direction Should We Search?
Our choices: Forward, backwards, or bidirectional
The issues:
How many start and goal states are there?
Branching factors in each direction
How much work is it to compare states?
Summary of algorithms
Criterion
Complete?
BreadthFirst
UniformCost
DepthFirst
Yes
Yes
No
Time
bd
bd
bm
Space
bd
bd
Optimal?
Yes
Yes
DepthLimited
Yes,
If l  d
Iterative
Deepening
Bidirectional
(if applicable)
Yes
Yes
bl
bd
bd/2
bm
bl
bd
bd/2
No
No
Yes
Yes
Comparing search strategies
Assignment
• Homework Assignment 3: problems 3.2, 3.3, 3.7 from
the textbook
More resources
• BFS: https://www.youtube.com/watch?v=GfgdWpgBJ0A
• DFS: https://www.youtube.com/watch?v=rmKOOxU4Gf4
• Depth Limited Search (DLS):
https://www.youtube.com/watch?v=rmKOOxU4Gf4
Download