0% found this document useful (0 votes)
17 views87 pages

Unit - 2

Uploaded by

tituyadav3006
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views87 pages

Unit - 2

Uploaded by

tituyadav3006
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 87

PROBLEM SOLVING METHODS

UNIT - 2
Our discussion of problem solving begins with precise definitions of
problems and their solutions and give several examples to illustrate
these definitions. We will describe several general-purpose search
algorithms that can be used to solve these problems. We will see several
uninformed search algorithms—algorithms that are given no information
about the problem other than its definition. Although some of these
algorithms can solve any solvable problem, none of them can do so
efficiently. Informed search algorithms, on the other hand, can do quite
well given some guidance on where to look for solutions.
Uninformed search, also called blind search and naïve search, is a class
of general purpose search algorithms that operate in a bruteforce way.
These algorithms can be applied to a variety of search problems, but since
they don’t take into account the target problem, are inefficient. In contrast,
informed search methods use a heuristic to guide the search for the
problem at hand and are therefore much more efficient.
PROBLEM-SOLVING AGENTS

Intelligent agents are supposed to maximize their performance


measure.
In that case, it makes sense for the agent to adopt the goal, Goal
formulation, based on the current situation and the agent’s
performance measure, is the first step in problem solving. We will
consider a goal to be a set of world states—exactly those states in
which the goal is satisfied. The agent’s task is to find out how to
act, now and in the future, so that it reaches a goal state. Problem
formulation is the process of deciding what actions and states to
consider, given a goal.
In other words, the agent will not know which of its possible actions is
best, because it does not yet know enough about the state that results
from taking each action. If the agent has no additional information—i.e., if
the environment is unknown in the sense—then it is has no choice but to
try one of the actions at random. In general, an agent with several
immediate options of unknown value can decide what to do by first
examining future actions that eventually lead to states of known value.

To be more specific about what we mean by “examining future actions,”


we have to be more specific about properties of the environment. For now
we assume that the environment is observable, so the agent always
knows the current state. We also assume the environment is discrete, so
at any given state there are only finitely many actions to choose from. We
will assume the environment is known, so the agent knows which states
are reached by each action. Finally, we assume that the environment is
deterministic, so each action has exactly one outcome.
The process of looking for a sequence of actions that reaches the
goal is called search. A search algorithm takes a problem as
input and returns a solution in the form of an action sequence.
Once a solution is found, the actions it recommends can be
carried out. This is called the execution phase. Thus, we have a
simple “formulate, search, execute” design for the agent, as
shown in Figure 3.1. After formulating a goal and a problem to
solve, the agent calls a search procedure to solve it. It then uses
the solution to guide its actions, doing whatever the solution
recommends as the next thing to do—typically, the first action of
the sequence—and then removing that step from the sequence.
Once the solution has been executed, the agent will formulate a
new goal.
Notice that while the agent is executing the
solution sequence it ignores its percepts when
choosing an action because it knows in
advance what they will be. An agent that carries
out its plans with its eyes closed, so to speak,
must be quite certain of what is going OPEN-
LOOP on. Control theorists call this an open-
loop system, because ignoring the percepts
breaks the loop between agent and
environment.
SEARCH AND AI
Search is an important aspect of AI because in many
ways, problem solving in AI is fundamentally a search.
Search can be defined as a problem-solving technique
that enumerates a problem space from an initial position
in search of a goal position (or solution). The manner in
which the problem space is searched is defined by the
search algorithm or strategy. As search strategies offer
different ways to enumerate the search space, how well
a strategy works is based on the problem at hand.
Ideally, the search algorithm selected is one whose
characteristics match that of the problem at hand.
Measuring problem-solving performance
• Completeness: Is the algorithm guaranteed to find a solution
when there is one?
• Optimality: Does the strategy find the optimal solution, as defined
on page 68?
• Time complexity: How long does it take to find a solution?
• Space complexity: How much memory is needed to perform the
search?
GENERAL STATE SPACE SEARCH
Let’s begin our discussion of search by first understanding
what is meant by a search space. When solving a problem, it’s
convenient to think about the solution space in terms of a
number of actions that we can take, and the new state of the
environment as we perform those actions. As we take one of
multiple possible actions (each have their own cost), our
environment changes and opens up alternatives for new
actions. As is the case with many kinds of problem solving,
some paths lead to dead-ends where others lead to solutions.
And there may also be multiple solutions, some better than
others. The problem of search is to find a sequence of
operators that transition from the start to goal state. That
sequence of operators is the solution.
Search in a Physical Space
Let’s consider a simple search problem in physical space
(Figure 2.1). Our initial position is ‘A’ from which there are three
possible actions that lead to position ‘B,’ ‘C,’ or ‘D.’ Places, or
states, are marked by letters. At each place, there’s an
opportunity for a decision, or action. The action (also called an
operator) is simply a legal move between one place and another.
Implied in this exercise is a goal state, or a physical location
that we’re seeking. This search space (shown in Figure 2.1) can
be reduced to a tree structure as illustrated in Figure 2.2. The
search space has been minimized here to the necessary places
on the physical map (states) and the transitions that are
possible between the states (application of operators). Each
node in the tree is a physical location and the arcs between
nodes are the legal moves. The depth of the tree is the distance
Search in a Puzzle Space
The “Towers of Hanoi” puzzle is an interesting example of a
state space for solving a puzzle problem. The object of this
puzzle is to move a number of disks from one peg to another
(one at a time), with a number of constraints that must be met.
Each disk is of a unique size and it’s not legal for a larger disk
to sit on top of a smaller disk. The initial state of the puzzle is
such that all disks begin on one peg in increasing size order
(see Figure 2.2). Our goal (the solution) is to move all disks to
the last peg. As in many state spaces, there are potential
transitions that are not legal. For example, we can only move a
peg that has no object above it. Further, we can’t move a large
disk onto a smaller disk (though we can move any disk to an
empty peg). The space of possible operators is therefore constrained only
to legal moves.
For example, if we move a small disk from Peg A to Peg C,
moving the same disk back to Peg A could be defined as an
invalid transition. Not doing so would result in loops and an
infinitely deep tree.
Consider our initial position from Figure 2.3. The only disk
that may move is the small disk at the top of Peg A. For this
disk, only two legal moves are possible, from Peg A to Peg
B or C. From this state, there are three potential moves:

1. Move the small disk from Peg C to Peg B.


2. Move the small disk from Peg C to Peg A.
3. Move the medium disk from Peg A to Peg B.
The first move (small disk from Peg C to Peg B), while valid
is not a potential move, as we just moved this disk to Peg C
(an empty peg). Moving it a second time serves no purpose
(as this move could have been done during the prior
transition), so there’s no value in doing this now (a
heuristic).

A heuristic is a simple or efficient rule for solving a given


problem or making a decision.
UNINFORMED SEARCH STRATEGIES
This section covers several search strategies that come under the
heading of uninformed search (also called blind search). The term
means that the strategies have no additional information about states
beyond that provided in the problem definition. All they can do is
generate successors and distinguish a goal state from a non-goal
state. All search strategies are distinguished by the order in which
nodes are expanded. Strategies that know whether one non-goal
state is “more promising” than another are called informed search or
heuristic search strategies.
Breadth-first search is a simple strategy in which the root node is
expanded first, then all the successors of the root node are expanded
next, then their successors, and so on. In general, all the nodes are
expanded at a given depth in the search tree before any nodes at the
next level are expanded.
Breadth-first search is an instance of the general graph-search
algorithm (Figure 3.7) in which the shallowest unexpanded node is
chosen for expansion. This is achieved very simply by using a FIFO
queue for the frontier. Thus, new nodes (which are always deeper
than their parents) go to the back of the queue, and old nodes, which
are shallower than the new nodes, get expanded first. There is one
slight tweak on the general graph-search algorithm, which is that the
goal test is applied to each node when it is generated rather than
when it is selected for
expansion. This decision is explained below, where we discuss time
complexity. Note also that the algorithm, following the general
template for graph search, discards any new path to a state already
in the frontier or explored set; it is easy to see that any such path
must be at least as deep as the one already found. Thus, breadth-
first search always has the shallowest path to every node on the
frontier.
How does breadth-first search rate according to the four criteria
from the previous section?
We can easily see that it is complete—if the shallowest goal node
is at some finite depth d, breadth-first search will eventually find it
after generating all shallower nodes (provided the branching
factor b is finite). Note that as soon as a goal node is generated,
we know it is the shallowest goal node because all shallower
nodes must have been generated already and failed the goal test.
Now, the shallowest goal node is not necessarily the optimal one;
technically, breadth-first search is optimal if the path cost is a
nondecreasing function of the depth of the node. The most
common such scenario is that all actions have the same cost.
So far, the news about breadth-first search has been good.
The news about time and space is not so good. Imagine
searching a uniform tree where every state has b successors.
The root of the search tree generates b nodes at the first level,
each of which generates b more nodes, for a total of b2 at the
second level. Each of these generates b more nodes, yielding
b3 nodes at the third level, and so on. Now suppose that the
solution is at depth d. In the worst case, it is the last node
generated at that level.
Uniform-cost search
When all step costs are equal, breadth-first search is optimal
because it always expands the shallowest unexpanded node. By
a simple extension, we can find an algorithm that is optimal with
any step-cost function. Instead of expanding the shallowest node,
uniform-cost search expands the node n with the lowest path
cost g(n). This is done by storing the frontier as a priority queue
ordered by g. The algorithm is shown in Figure 3.14.
In addition to the ordering of the queue by path cost, there are
two other significant differences from breadth-first search. The
first is that the goal test is applied to a node when it is selected
for expansion (as in the generic graph-search algorithm shown in
Figure 3.7) rather than when it is first generated. The reason is
may be on a suboptimal path. The second difference is that a test is
added in case a better path is found to a node currently on the
frontier.
Both of these modifications come into play in the example shown in
Figure 3.15, where the problem is to get from Sibiu to Bucharest.
The successors of Sibiu are Rimnicu Vilcea and Fagaras, with costs
80 and 99, respectively. The least-cost node, Rimnicu Vilcea, is
expanded next, adding Pitesti with cost 80 + 97=177. The least-cost
node is now Fagaras, so it is expanded, adding Bucharest with cost
99+211=310. Now a goal node has been generated, but uniform-
cost search keeps going, choosing Pitesti for expansion and adding
a second path to Bucharest with cost 80+97+101= 278. Now the
algorithm checks to see if this new path is better than the old one; it
is, so the old one is discarded.
Bucharest, now with g-cost 278, is selected for expansion and
the solution is returned. It is easy to see that uniform-cost
search is optimal in general. First, we observe that whenever
uniform-cost search selects a node n for expansion, the
optimal path to that node has been found. (Were this not the
case, there would have to be another frontier node n on the
optimal path from the start node to n, by the graph separation
property of Figure 3.9; by definition, n would have lower g-
cost than n and would have been selected first.) Then,
because step costs are nonnegative, paths never get shorter
as nodes are added. These two facts together imply that
uniform-cost search expands nodes in order of their optimal
path cost. Hence, the first goal node selected for expansion
Depth-first search
Depth-first search always expands the deepest node in the
current frontier of the search tree. The progress of the search is
illustrated in Figure 3.16. The search proceeds immediately to the
deepest level of the search tree, where the nodes have no
successors. As those nodes are expanded, they are dropped from
the frontier, so then the search “backs up” to the next deepest node
that still has unexplored successors. The depth-first search
algorithm is an instance of the graph-search algorithm in Figure
3.7; whereas breadth-first-search uses a FIFO queue, depth-first
search uses a LIFO queue. A LIFO queue means that the most
recently generated node is chosen for expansion. This must be the
deepest unexpanded node because it is one deeper than its parent—
which, in turn, was the deepest unexpanded node when it was
As an alternative to the GRAPH-SEARCH-style implementation,
it is common to implement depth-first search with a recursive
function that calls itself on each of its children in turn. (A
recursive depth-first algorithm incorporating a depth limit is
shown in Figure 3.17.) The properties of depth-first search
depend strongly on whether the graph-search or tree-search
version is used. The graph-search version, which avoids
repeated states and redundant paths, is complete in finite state
spaces because it will eventually expand every node. The tree-
search version, on the other hand, is not complete—for example,
in Figure 3.6 the algorithm will follow the Arad–Sibiu–Arad–Sibiu
loop forever.
Depth-first tree search can be modified at no extra memory cost
so that it checks new states against those on the path from the
root to the current node; this avoids infinite loops in finite state
spaces but does not avoid the proliferation of redundant paths.
In infinite state spaces, both versions fail if an infinite non-goal
path is encountered. For example, in Knuth’s 4 problem, depth-
first search would keep applying the factorial operator forever.
For similar reasons, both versions are non optimal. For example,
in Figure 3.16, depth first search will explore the entire left sub
tree even if node C is a goal node. If node J were also a goal
node, then depth-first search would return it as a solution instead
of C, which would be a better solution; hence, depth-first search
is not optimal.
The time complexity of depth-first graph search is bounded by the
size of the state space (which may be infinite, of course). A depth-
first tree search, on the other hand, may generate all of the O (bm)
nodes in the search tree, where m is the maximum depth of any
node; this can be much greater than the size of the state space.
Note that m itself can be much larger than d (the depth of the
shallowest solution) and is infinite if the tree is unbounded. So far,
depth-first search seems to have no clear advantage over
breadth-first search, so why do we include it? The reason is the
space complexity. For a graph search, there is no advantage, but
a depth-first tree search needs to store only a single path from the
root to a leaf node,
along with the remaining unexpanded sibling nodes for each
node on the path. Once a node has been expanded, it can be
removed from memory as soon as all its descendants have
been fully explored. For a state space with branching factor b
and maximum depth m, depth-first search requires storage of
only O(bm) nodes. Using the same assumptions as for Figure
3.13 and assuming that nodes at the same depth as the goal
node have no successors, we find that depth-first search would
require 156 kilobytes instead of 10 exabytes at depth d = 16, a
factor of 7 trillion times less space. This has led to the adoption
of depth-first tree search as the basic workhorse of many areas
of AI, including constraint satisfaction, propositional satisfiability,
and logic programming. For the remainder of this section, we
focus primarily on the tree search version of depth-first search.
A variant of depth-first search called backtracking search uses
still less memory. In backtracking, only one successor is
generated at a time rather than all successors; each partially
expanded node remembers which successor to generate next. In
this way, only O(m) memory is needed rather than O(bm).
Backtracking search facilitates yet another memory-saving (and
time-saving) trick: the idea of generating a successor by
modifying the current state description directly rather than
copying it first. This reduces the memory requirements to just
one state description and O(m) actions. For this to work, we must
be able to undo each modification when we go back to generate
the next successor. For problems with large state descriptions,
such as robotic assembly, these techniques are critical to
success.
Depth-limited search
The embarrassing failure of depth-first search in infinite state
spaces can be alleviated by supplying depth-first search with a
predetermined depth limit . That is, nodes at depth are treated as
if they have no successors. This approach is called depth-
limited search. The depth limit solves the infinite-path problem.
Unfortunately, it also introduces an additional source of
incompleteness if we choose < d, that is, the shallowest goal is
beyond the depth limit. (This is likely when d is unknown.) Depth-
limited search will also be non optimal if we choose > d. Its time
complexity is O(b) and its space complexity is O(b). Depth-first
search can be viewed as a special case of depth-limited search
with =∞.
Sometimes, depth limits can be based on knowledge of the
problem. For example, on the map of Romania there are 20 cities.
Therefore, we know that if there is a solution, it must be of length
19 at the longest, so = 19 is a possible choice. But in fact if we
studied the map carefully, we would discover that any city can be
reached from any other city in at most 9 steps. This number,
known as the diameter of the state space, gives us a better depth
limit, which leads to a more efficient depth-limited search. For
most problems, however, we will not know a good depth limit until
we have solved the problem. Depth-limited search can be
implemented as a simple modification to the general tree or
graph-search algorithm. Notice that depth-limited search can terminate
with two kinds of failure: the standard failure value indicates no
solution; the cutoff value indicates no solution within the depth limit.
Iterative deepening depth-first search
Iterative deepening search (or iterative deepening depth-first
search) is a general strategy, often used in combination with
depth-first tree search, that finds the best depth limit. It does this
by gradually increasing the limit—first 0, then 1, then 2, and so
on—until a goal is found. This will occur when the depth limit
reaches d, the depth of the shallowest goal node. The algorithm
is shown in Figure 3.18. Iterative deepening combines the
benefits of depth-first and breadth-first search. Like depth-first
search, its memory requirements are modest: O(bd) to be
precise. Like breadth-first search, it is complete when the
branching factor is finite and optimal when the path cost is a non
decreasing function of the depth of the node.
Figure 3.19 shows four iterations of ITERATIVE-
DEEPENING-SEARCH on a binary search tree, where the
solution is found on the fourth iteration. Iterative
deepening search may seem wasteful because states are
generated multiple times. It turns out this is not too costly.
The reason is that in a search tree with the same (or nearly
the same) branching factor at each level, most of the
nodes are in the bottom level, so it does not matter much
that the upper levels are generated multiple times. In an
iterative deepening search, the nodes on the bottom level
(depth d) are generated once, those on the next-to-bottom
level are generated twice, and so on, up to the children of the root,
which are generated d times.
If you are really concerned about repeating the
repetition, you can use a hybrid approach that runs
breadth-first search until almost all the available
memory is consumed, and then runs iterative
deepening from all the nodes in the frontier. In
general, iterative deepening is the preferred
uninformed search method when the search space is
large and the depth of the solution is not known.
Iterative deepening search is analogous to breadth-
first search in that it explores a complete layer of new
nodes at each iteration before going on to the next
layer.
It would seem worthwhile to develop an iterative
analog to uniform-cost search, inheriting the latter
algorithm’s optimality guarantees while avoiding its
memory requirements. The idea is to use increasing
path-cost limits instead of increasing depth limits.
The resulting algorithm, called iterative lengthening
search. It turns out, unfortunately, that iterative
lengthening incurs substantial overhead compared to
uniform-cost search.
Bidirectional search
The idea behind bidirectional search is to run two simultaneous
searches—one forward from the initial state and the other
backward from the goal—hoping that the two searches meet in the
middle (Figure 3.20). The motivation is that bd/2 + bd/2 is much
less than bd, or in the figure, the area of the two small circles is
less than the area of one big circle centered on the start and
reaching to the goal. Bidirectional search is implemented by
replacing the goal test with a check to see whether the frontiers of
the two searches intersect; if they do, a solution has been found.
(It is important to realize that the first such solution found may not
be optimal, even if the two searches are both breadth-first; some
additional search is required to make sure there isn’t another
short-cut across the gap.)
The check can be done when each node is generated or selected for
expansion and, with a hash table, will take constant time. For
example, if a problem has solution depth d=6, and each direction
runs breadth-first search one node at a time, then in the worst case
the two searches meet when they have generated all of the nodes at
depth 3. For b=10, this means a total of 2,220 node generations,
compared with 1,111,110 for a standard breadth-first search. Thus,
the time complexity of bidirectional search using breadth-first
searches in both directions is O(bd/2). The space complexity is also
O(bd/2). We can reduce this by roughly half if one of the two searches
is done by iterative deepening, but at least one of the frontiers must
be kept in memory so that the intersection check can be done. This
space requirement is the most significant weakness of bidirectional
The reduction in time complexity makes bidirectional search
attractive, but how do we search backward? This is not as easy
as it sounds. Let the predecessors of a state x be all those
states that have x as a successor. Bidirectional search requires a
method for computing predecessors. When all the actions in the
state space are reversible, the predecessors of x are just its
successors. Other cases may require substantial ingenuity.

Measuring problem-solving performance


• 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?
Comparing uninformed search strategies
Figure 3.21 compares search strategies in terms of the four
evaluation criteria set forth as
Completeness
Optimality
Time complexity
Space complexity.
This comparison is for tree-search versions. For graph searches,
the main differences are that depth-first search is complete for
finite state spaces and that the space and time complexities are
bounded by the size of the state space.
INFORMED (HEURISTIC) SEARCH STRATEGIES
This section shows how an informed search strategy—one that
uses problem-specific knowledge beyond the definition of the
problem itself—can find solutions more efficiently than can an
uninformed strategy. The general approach we consider is called
best-first search. Best-first search is an instance of the general
TREE-SEARCH or GRAPH-SEARCH algorithm in which a node
is selected for expansion based on an evaluation function, f(n).
The evaluation function is construed as a cost estimate, so the
node with the lowest evaluation is expanded first. The
implementation of best-first graph search is identical to that for
uniform-cost search (Figure 3.14), except for the use of f instead
of g to order the priority queue.
The choice of f determines the search strategy. Most
best-first algorithms include as a component of f a
heuristic function, denoted h(n):
h(n) = estimated cost of the cheapest path from the state
at node n to a goal state.
Heuristic functions are the most common form in which
additional knowledge of the problem is imparted to the search
algorithm.
Greedy best-first search
Greedy best-first search tries to expand the node that is closest
to the goal, on the grounds that this is likely to lead to a solution
quickly. Thus, it evaluates nodes by using just the heuristic
function; that is, f(n) = h(n).
Let us see how this works for route-finding problems in Romania;
we use the straight line distance heuristic, which we will call
hSLD. If the goal is Bucharest, we need to know the straight-line
distances to Bucharest, which are shown in Figure 3.22. For
example, hSLD(In(Arad))=366. Notice that the values of hSLD
cannot be computed from the problem description itself.
Moreover, it takes a certain amount of experience to know that
hSLD is correlated with actual road distances and is, therefore, a
useful heuristic.
Figure 3.23 shows the progress of a 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
Romania with step costs in km
•Evaluation function f(n) = h(n) (heuristic)

•= estimate of cost from n to goal

•e.g., hSLD(n) = straight-line distance from n to Bucharest

•Greedy best-first search expands the node that appears


to be closest to goal
Greedy best-first search example
Properties of greedy best-first search
• Complete? No – can get stuck in loops, e.g., Iasi  Neamt 
Iasi  Neamt 

• Time? O(bm), but a good heuristic can give dramatic


improvement

• Space? O(bm) -- keeps all nodes in memory

• Optimal? No
A* search: Minimizing the total estimated solution cost
The most widely known form of best-first search is called A∗ A
search (pronounced “A-star search”). 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) .
Since g(n) gives the path cost from the start node to node n, and
h(n) is the estimated cost of the cheapest path from n to the goal,
we have
f(n) = estimated cost of the cheapest solution through n .
Thus, if we are trying to find the cheapest solution, a reasonable
thing to try first is the node with the lowest value of g(n) + h(n).
It turns out that this strategy is more than just reasonable: provided
that the heuristic function h(n) satisfies certain conditions, A∗
search is both complete and optimal. The algorithm is identical to
UNIFORM-COST-SEARCH except that A∗ uses g + h instead of g.
A* search
• Idea: avoid expanding paths that are already expensive

• Evaluation function f(n) = g(n) + h(n)

• g(n) = cost so far to reach n

• h(n) = estimated cost from n to goal

• f(n) = estimated total cost of path through n to goal


A* search example
Admissible heuristics
• A heuristic h(n) is admissible if for every node n,
h(n) ≤ h*(n), where h*(n) is the true cost to reach the goal state
from n.
An admissible heuristic never overestimates the cost to reach
the goal, i.e., it is optimistic
Example: hSLD(n) (never overestimates the actual road distance)
Theorem: If h(n) is admissible, A* using TREE-SEARCH is
optimal
Conditions for optimality: Admissibility and consistency
The first condition we require for optimality is that h(n ) be an
admissible heuristic. An admissible heuristic is one that never
overestimates the cost to reach the goal. Because g(n) is the
actual cost to reach n along the current path, and f(n)=g(n) + h(n),
we have as an immediate consequence that f(n) never
overestimates the true cost of a solution along the current path
through n. Admissible heuristics are by nature optimistic because
they think the cost of solving the problem is less than it actually is.
An obvious example of an admissible heuristic is the straight-line
distance hSLD that we used in getting to Bucharest. Straight-line
distance is admissible because the shortest path between any
two points is a straight line,
A second, slightly stronger condition called consistency (or
sometimes monotonicity) is required only for applications of A∗
to graph search.9 A heuristic h(n) is consistent if, for every node n
and every successor n of n generated by any action a, the
estimated cost of reaching the goal from n is no greater than the
step cost of getting to n plus the estimated cost of reaching the
goal from n :

This is a form of the general triangle inequality, which stipulates


that each side of a triangle cannot be longer than the sum of the
other two sides. Here, the triangle is formed by n, n-, and the goal
Gn closest to n.
Memory-bounded heuristic search
The simplest way to reduce memory requirements for A∗ is to
adapt the idea of iterative deepening to the heuristic search
context, resulting in the iterative-deepening A∗ (IDA∗) algorithm.
The main difference between IDA∗ and standard iterative
deepening is that the cutoff used is the f-cost (g+h) rather than
the depth; at each iteration, the cutoff value is the smallest f-cost
of any node that exceeded the cutoff on the previous iteration.
IDA∗ is practical for many problems with unit step costs and
avoids the substantial overhead associated with keeping a sorted
queue of nodes. Unfortunately, it suffers from the same difficulties
with real valued costs as does the iterative version of uniform-cost
search
Recursive best-first search (RBFS) is a simple recursive
algorithm that attempts to mimic the operation of standard best-
first search, but using only linear space. The algorithm is shown in
Figure 3.26. Its structure is similar to that of a recursive depth-first
search, but rather than continuing indefinitely down the current
path, it uses the f limit variable to keep track of the f-value of the
best alternative path available from any ancestor of the current
node. If the current node exceeds this limit, the recursion unwinds
back to the alternative path. As the recursion unwinds, RBFS
replaces the f-value of each node along the path with a backed-
up value—the best f-value of its children. In this way, RBFS
remembers the f-value of the best leaf in the forgotten sub tree and can
therefore decide whether it’s worth re expanding the sub tree at some
later time. Figure 3.27 shows how RBFS reaches Bucharest.
Stages in an RBFS search for the shortest route to
Bucharest. The f-limit value for each recursive call is
shown on top of each current node, and every node is
labeled with its f-cost.
(a) The path via Rimnicu Vilcea is followed until the
current best leaf (Pitesti) has a value that is worse
than the best alternative path (Fagaras).
(b) The recursion unwinds and the best leaf
value of the forgotten subtree (417) is
backed up to Rimnicu Vilcea; then Fagaras is
expanded, revealing a best leaf value of 450.
(c) The recursion unwinds and the best leaf value
of the forgotten subtree (450) is backed up to
Fagaras; then Rimnicu Vilcea is expanded. This
time, because the best alternative path (through
Timisoara) costs at least 447, the expansion
continues to Bucharest.
RBFS is somewhat more efficient than IDA∗, but still suffers from
excessive node regeneration. In the example in Figure 3.27,
RBFS follows the path via Rimnicu Vilcea, then “changes its mind”
and tries Fagaras, and then changes its mind back again. These
mind changes occur because every time the current best path is
extended, its f-value is likely to increase—h is usually less
optimistic for nodes closer to the goal. When this happens, the
second-best path might become the best path, so the search has
to backtrack to follow it. Each mind change corresponds to an
iteration of IDA∗ and could require many re expansions of
forgotten nodes to recreate the best path and extend it one more
node.

You might also like