Title: Heuristic Search
1Heuristic Search
- CIS 479/579
- Bruce R. Maxim
- UM-Dearborn
2State Space Search
- Many AI problems can be conceptualized as
searching a well defined set of related problem
states - Puzzle solving
- Game playing
- Generate and test
- Genetic algorithms
- Scheduling algorithms
3Water Jug Problem
- Problem
- You have a four gallon jug and a three gallon jug
and the goal is to come up with exactly two
gallons of water. - Operations
- Dump bucket contents on the ground
- Dump bucket contents in other bucket
- Fill bucket to top with water
4Tree Representation
- (0,0)
-
-
- (4,0) (0,3)
- (0,3) (0,0) (4,3) (1,3) (3,0) (4,3) (0,0)
5Digraph Representation
- (0,0)
- (4,0) (0,3)
- (1,3) (4,3) (3,0)
6Adjacency List
- (0 0) ? ((4 0) (0 3))
- (4 0) ? (( 4 3) (0 0) (1 3) (0 3))
- (0 3) ? ((4 3) (3 0) (0 0))
- (1 3) ? ((1 0) (4 3) (4 0) (0 3))
7Good Knowledge Representations
- Important things made clear /explicit
- Expose natural constraints
- Must be complete
- Are concise
- Transparent (easily understood)
- Information can be retrieved stored quickly
- Detail suppressed (can be found as needed)
- Computable using existing procedures
8River Puzzle
- Problem
- There are four items a farmer, wolf, goose, and
corn. The farmer can only take one item across
the river at a time. - Constraints
- Wolf will eat the goose if left alone with it
- Goose will eat the corn if left alone with it
9Problem Analysis
- Each of the 4 problem elements can be considered
a Boolean variable based on its bank location - There are 24 or 16 possible states
- 6 of these states fail the no eat test
- That leaves 10 states to consider which could be
linked n C(10,2) 45 ways - However only 10 of these links can really be used
to connect states
10FFarmer WWolf GGoose CCorn River
- W F
- W
- F G
- F W F G G F
- W C W C C G F
- G C F W
- C F C F W W G
- G G G C C C
- F C
- W
- G W
11Solution
- Once graph is constructed finding solution is
easy (simply find a path) - AI programs would rarely construct the entire
graph explicitly before searching - AI programs would generate nodes as needed and
restrict the path search to the nodes generated - May use forward reasoning (initial to goal) or
backward reasoning (goal to initial)
12Rules
- Many time these state transitions are written as
rules - If ((Wolf Corn) (Farmer Goose))
- Then ((Wolf Corn Farmer) (Goose))
- Depending on which direction you are reasoning
you match either the left (if) or right (then)
part
13Potential Problems
- If you have more than one state to move to then
you need a procedure to choose one - Exact matches often do not occur in the real
world so you may need to measure how close you
are to an exact match
14Control Strategies
- A good control strategy causes motion (ideally
toward the goal state) - The control strategy should be systematic and not
allow repeated use of the same rule sequences (to
avoid infinite loops)
15Heuristics
- AI programming often relies on the use of
heuristics - Heuristics are techniques that improves
efficiency by trading speed for completeness
16Search Considerations
- Can the search algorithm work for the problem
space? - Is the search algorithm efficient?
- Is it easy to implement?
- Is search the best approach or is more knowledge
better?
17Example Graph
A
F
S
B
C
18Adjacency List
- (setf (get 's 'children) '(a b)) (setf (get
'a 'children) '(s b f)) (setf (get 'b
'children) '(s a c)) (setf (get 'c 'children)
'(b f)) (setf (get 'f 'children) '(a c))
19Any Path Search Algorithms
- Depth First Search
- Hill Climbing
- Best First Search
- Breadth First Search
- Beam Search
20Depth First Search
- Add root to queue of partial paths
- Until queue is empty or goal is attained
- If first queue element equals the goal then
- do nothing
- Else
- remove the first queue element
- add its children to the front of the queue of the
partial paths - If goal is attained then
- announce success
21Depth First Output
- gt (depth 's 'f)
- ((s))
- ((a s) (b s))
- ((b a s) (f a s) (b s))
- ((c b a s) (f a s) (b s))
- ((f c b a s) (f a s) (b s))
- (s a b c f)
22Depth First Weakness
- Depth first is not good for tall trees when it
is possible to over commit to a bad path early - In our example depth first missed a complete
solution because it focused on checking the first
partial path and did not test the others in the
queue
23Depth First Search
- (defun depth (start finish)
- (depth1 (list (list start)) finish))(defun
depth1 (queue finish) - (cond ((null queue) nil) ((equal
finish (caar queue)) - (print queue) (reverse
(car queue))) (t (print queue)
(depth1 (append (expand (car queue)) - (cdr queue)) finish))))
24expand
- (defun expand (path)
- kills cycles
- (remove-if (lambda (path)
- (member (car path) (cdr path))
- )
- (mapcar '(lambda (child)(cons child path))
- (get (car path) 'children)
- )
- )
- )
- gt (expand '(a s))
- ((b a s) (f a s))
25Recursive Depth First
- (defun simple-depth (tree goal)
- (cond (( (car tree) goal) tree)
- ((atom tree) nil)
- (t (cons (car tree)
- (or (simple-depth (cadr tree)
goal) - (simple-depth (caadr tree)
goal) - )
- )
- )
- )
- )
26Breadth First Search
- Add root to queue of partial paths
- Until queue is empty or goal is attained
- If first queue element equals the goal then
- do nothing
- Else
- remove the first queue element
- add its children to the rear of the queue of the
partial paths - If goal is attained then
- announce success
27Breadth First Output
- gt (breadth 's 'f)
- ((s))
- ((a s) (b s))
- ((b s) (b a s) (f a s))
- ((b a s) (f a s) (a b s) (c b s))
- ((f a s) (a b s) (c b s) (c b a s))
- (s a f)
28Breadth First Weakness
- Breadth first is not good for fat trees where
the nodes have high branching factors - Can also be bad choice when several partial paths
lead to the same node several levels down
(bottleneck) - Not always fast but it will never miss a complete
solution
29Breadth First Search
- (defun breadth (start finish)
- (breadth1 (list (list start)) finish))
- (defun breadth1 (queue finish)
- (cond ((null queue) nil) ((equal finish
(caar queue)) - (print queue)
- (reverse (car queue)))
(t (print queue) (breadth1 (append
(cdr queue) - (expand (car queue)))
- finish))))
-
30Improving Search
- We will need to add knowledge to our algorithms
to make them perform better - We will need to add some distance estimates, even
using best guesses would help - We will need to begin sorting part of the the
queue of partial paths
31Insertion Sort
- (defun insertion-sort (s predicate)
- insertion sort for lists (cond ((null s)
nil) (t (splice-in (car s) - (insertion-sort (cdr s) predicate)
predicate)))
32Insertion Sort Helper
- (defun splice-in (element s predicate)
- insert in order (cond ((null s) (list
element)) - end of s? ((funcall predicate
element (car s)) (cons element s)) - add here? (t (cons (car s)
- (splice-in element (cdr s)
predicate))) - try further down
- ))
33sort
- Common Lisp has a built in sort function that
allows you to sort any list using a predicate
capable of comparing two list elements - Examples
- gt (sort '(1 2 3 4 5) 'gt)
- (5 4 3 2 1)
- gt (sort '(5 4 3 2 1) 'lt)
- (1 2 3 4 5)
34closerp
- When could define a predicate function that
either retrieves or computes the distance to the
goal for the nodes - (defun closerp (x y)
- (lt (get (car x) 'distance)
- (get (car y) 'distance)
- )
- )
35Example Graph
1
A
0
2
F
S
B
C
1
2
36Using closerp
- gt (setf (get 's 'distance) 2)
- gt (setf (get 'a 'distance) 1)
- gt (setf (get 'b 'distance) 2)
- gt (setf (get 'c 'distance) 1)
- gt (setf (get 'f 'distance) 0)
- gt (sort '((b s) (b a s) (f a s)) 'closerp)
- ((f a s) (b s) (b a s))
37Euclidean Distance
- Distance could be computed based on properties of
the node instead - Another possibility
- (defun distance (n1 n2)
- (sqrt ( (expt (- (get n1 x) (get n2 x)) 2)
- (expt (- (get n1 y) (get n2 y)) 2)
- )
- )
- )
38Hill Climbing
- An improved depth first search
- Requires the ability to guess the distance to the
goal using an ordinal scale (does not require
exact distances) - Children are sorted before being added to the
front of the queue of partial paths
39Uses for Hill Climbing
- You must have adjustable (and reversible)
operations to control progress - Adjusting thermostat without numbers
- Adjusting fuzzy TV signal
- Mountain climbing in the fog using an altimeter
40Hill Climbing
- Add root to queue of partial paths
- Until queue is empty or goal is attained
- If first queue element equals the goal then
- do nothing
- Else
- remove the first queue element
- sort its children based on distance to goal
- add children to the front of the queue of the
partial paths - If goal is attained then
- announce success
41Hill Climbing Output
- gt (hill 's 'f)
- ((s))
- ((a s) (b s))
- ((f a s) (b a s) (b s))
- (s a f)
42Hill Climbing
- (defun hill (start finish)
- (hill1 (list (list start)) finish))
- (defun hill1 (queue finish)
- (cond ((null queue) nil)
- ((equal finish (caar queue))
- (print queue)
- (reverse (car queue)))
- (t (print queue) (hill1
- (append
- (sort (expand (car queue))
'closerp) (cdr queue) - ) finish))))
43Hill Climbing Weaknesses
- Foothill problem
- Local peaks attract procedures attention away
from trying to reach the top - Plateau problem
- Area flat so there is very little to attract
procedure to one path over another - Ridge problem
- Every step is down though not at a local minimum
(e.g. at the Northpole every step is south)
44Best First Search
- An improved hill climbing or depth first search
- Requires the ability to guess the distance to the
goal using an ordinal scale (does not require
exact distances) - Entire queue of partial path is sorted after it
is modified
45Best First Search
- Add root to queue of partial paths
- Until queue is empty or goal is attained
- If first queue element equals the goal then
- do nothing
- Else
- remove the first queue element
- add its children to the front of the queue of the
partial paths - sort the queue of partial paths
- If goal is attained then
- announce success
46Best First Output
- gt (best 's 'f)
- ((s))
- ((a s) (b s))
- ((f a s) (b a s) (b s))
- (s a f)
47Best First Search
- (defun best (start finish)
- (best1 (list (list start)) finish))
- (defun best1 (queue finish)
- (cond ((null queue) nil)
- ((equal finish (caar queue))
- (print queue)
- (reverse (car queue)))
- (t (print queue) (best1
- (sort
- (append
- (expand (car queue)) (cdr
queue)) 'closerp)
finish))))
48Best First Weaknesses
- Still requires the use of a natural distance
measure - Sorting takes time
- Tends to produce shorter paths than other depth
first search algorithms, but is not guaranteed to
produce the shortest path
49Beam First Search
- Improved version of breadth first search
- Good for fat trees
- Does not guarantee it will find shortest path
- Trades speed for completeness
50Beam First Search
- Add root to queue of partial paths
- Until queue is empty or goal is attained
- If first queue element equals the goal then
- do nothing
- Else
- If length (queue) gt then then
- take first queue elements as new queue
- remove the first queue element
- add its sorted children to the rear of the
queue of the partial paths - If goal is attained then announce success
51Beam First Output
- gt (beam 's 'f 3)
- ((s))
- ((a s) (b s))
- ((f a s) (a b s) (c b s) (b a s))
- (s a f)
52Beam First Search
- (defun beam (start finish width)
- (beam1 (list (list start)) finish width))
- (defun beam1 (queue finish width)
- (cond ((null queue) nil)
- ((equal finish (caar queue))
- (print queue) (reverse
(car queue))) (t (print queue)
(beam1 - (sort (apply 'nconc
- (mapcar 'expand
(if (lt (length queue) width)
queue (first-n queue width))))
'closerp) finish width)))
53first-n
- (defun first-n (l n) (cond ((zerop n) nil)
(t (cons (car l) - (first-n (cdr l) (1- n))))))
54Improving Things
- We would still like to find optimal paths faster
then breadth first search does - More knowledge should mean less search
- Dont try to tune the search efficiency,
improve understanding and try to remove the need
for search
55British Museum Search
- If enough monkeys had enough type writers and
enough time then they could recreate all the
knowledge housed in the British Museum - So we could compute every path by trial and error
then pick the shortest
56Branch and Bound
- An optimal depth first search
- Requires the ability to measure the distance
traveled so far using an ordinal scale (does
not require exact distances) - Entire queue of partial path is sorted after it
is modified
57Branch and Bound
- Add root to queue of partial paths
- Until queue is empty or goal is attained
- If first queue element equals the goal then
- do nothing
- Else
- remove the first queue element
- add its children to the front of the queue of the
partial paths - sort the queue of partial paths by distance
traveled - If goal is attained then announce success
58Branch and Bound Output
- gt (branch 's 'f)
- ((s))
- ((a s) (b s))
- ((b s) (b a s) (f a s))
- ((a b s) (c b s) (b a s) (f a s))
- ((c b s) (b a s) (f a s) (f a b s))
- ((b a s) (f a s) (f c b s) (f a b s))
- ((f a s) (c b a s) (f c b s) (f a b s))
- (s a f)
59Branch and Bound
- (defun branch (start finish)
- (branch1 (list (list start)) finish))
- (defun branch1 (queue finish)
- (cond ((null queue) nil)
- ((equal finish (caar queue))
- (print queue)
- (reverse (car queue)))
- (t (print queue) (branch1
- (sort new predicate
used - (append
- (expand (car queue)) (cdr
queue)) - 'shorterp) finish))))
60shorterp
- These distances should be computable for most
problem spaces - For this example using path length as the cost
of traveling so far - (defun shorterp (p1 p2)
- check path length
- (lt (length p1) (length p2)))
61 Branch and Bound Weaknesses
- Still requires the use of a natural distance
measure - Sorting takes time
- Produces shorter paths, but like many optimal
path algorithms it requires more work
62Branch and Bound with Underestimator
- If we can get a good estimate of the remaining
distance to the goal we could get a better
estimate of the real cost of traversing each
evolving path - It is essential that our estimate of the
remaining distance never exceed the actual
distance to the goal (to ensure the promise that
the algorithm return the shortest path)
63Branch and Bound with Underestimator
- Add root to queue of partial paths
- Until queue is empty or goal is attained
- If first queue element equals the goal then
- do nothing
- Else
- remove the first queue element
- add its children to the front of the queue of the
partial paths - sort the queue of partial paths by distance
traveled plus the estimate of the distance to the
goal - If goal is attained then announce success
64Branch and Bound with Underestimator Output
- gt (under 's 'f)
- ((s))
- ((a s) (b s))
- ((f a s) (b s) (b a s))
- (s a f)
65Branch and Bound with Underestimator
- (defun under (start finish)
- (under1 (list (list start)) finish))
- (defun under1 (queue finish)
- (cond ((null queue) nil)
- ((equal finish (caar queue))
- (print queue)
- (reverse (car queue)))
- (t (print queue)
- (under1
- (sort
- (append (expand (car queue))
- (cdr queue))
- 'betterp)
- finish))))
66betterp
- For this example using path length as the cost
of traveling so far - We are pretending the the distances are
underestimators of the distance to the goal - (defun betterp (p1 p2) (if (lt ( (length p1)
(get (car p1) 'distance)) ( (length p2)
(get (car p2) 'distance)) - )
- t nil))
67 Branch and Bound with Underestimator Weaknesses
- Still requires the use of a natural distance
measure - Underestimator is a guess as best
- Sorting takes time
- Allows redundant paths to evolve (like ordinary
branch and bound)
68Branch and Bound with Dynamic Programming
- If we can have tried to improve Branch and Bound
by eliminating redundant paths - We will not use an underestimator in this version
of the algorithm
69Branch and Bound with Dynamic Programming
- Add root to queue of partial paths
- Until queue is empty or goal is attained
- If first queue element equals the goal then
- do nothing
- Else
- remove the first queue element
- add its children to the front of the queue of the
partial paths - sort the queue of partial paths by distance
traveled - remove redundant paths
- If goal is attained then announce success
70Branch and Bound with Dynamic Programming Output
- gt (dynamic 's 'f)
- ((s))
- ((a s) (b s))
- ((b s) (f a s))
- ((a b s) (c b s) (f a s))
- ((c b s) (f a s))
- ((f a s))
- (s a f)
71Branch and Bound with Dynamic Programming
- (defun dynamic (start finish)
- (dynamic1 (list (list start)) finish))
- (defun dynamic1 (queue finish)
- (cond ((null queue) nil)
- ((equal finish (caar queue))
- (print queue)
- (reverse (car queue)))
- (t (print queue)
- (dynamic1
- (remove-dups
- (sort
- (append (expand (car
queue)) - (cdr queue))
- 'shorterp))
- finish))))
72remove-dups
- (defun remove-dups (queue)
- (do ((path (car queue) (cadr (member path
queue))) - (remd (cdr queue) (cdr (member path
queue))) - ) ((null remd) queue)
- drop any path reaching same node as first
path (dolist (path2 remd) - (if (equal (car path2) (car
path)) (setq queue (remove
path2 queue)) - )
- )
- )
- )
73 Branch and Bound with Dynamic Programming
Weaknesses
- Still requires the use of a natural distance
measure - I have seen some evidence of thrashing when
underestimator if not used - Sorting takes time
74A
- Makes use of both a cost and underestimator
- Removes redundant paths from the queue of partial
paths
75A
- Add root to queue of partial paths
- Until queue is empty or goal is attained
- If first queue element equals the goal then
- do nothing
- Else
- remove the first queue element
- add its children to the front of the queue of the
partial paths - sort the queue of partial paths by distance
traveled plus the estimate of distance to goal - remove redundant paths
- If goal is attained then announce success
76A
- gt (a 's 'f)
- ((s))
- ((a s) (b s))
- ((f a s) (b s))
- (s a f)
77A
- (defun a (start finish)
- (a1 (list (list start)) finish))
- (defun a1 (queue finish)
- (cond ((null queue) nil)
- ((equal finish (caar queue))
- (print queue)
- (reverse (car queue)))
- (t (print queue)
- (a1 (remove-dups
- (sort(append
- (expand (car queue))
- (cdr queue))
- 'betterp))
- finish))))
78A Weaknesses
- Still requires the use of a natural distance
measure - Underestimator is a guess as best
- Sorting takes time
- Removing paths takes time
79Summary
- British Museum
- only works for small search spaces
- Branch and Bound
- good for large search spaces if bad paths look
bad early - B B with Underestimator
- good if distance estimate is reliable
- B B with Dynamic Programming
- good when several paths reach the same state on
the way to a solution - A
- good whenever B B is good with underestimator
and dynamic programming