AI Module2
AI Module2
AI Module2
Module 2
SOLVING PROBLEMS BY SEARCHING
3.1 PROBLEM-SOLVING AGENTS
Goal formulation: Goal formulation is the process of defining and structuring the objectives
that an individual, team, or organization aims to achieve. It involves clarifying what needs to
be accomplished, establishing criteria for success, and breaking down larger goals into
smaller, manageable tasks.
Unknown : It seems like you're referencing the word "unknown." In the context of problem-
solving or analysis, "unknown" typically refers to variables, factors, or aspects of a situation
that are not fully understood or identified. These unknowns can present challenges or
uncertainties that need to be addressed in order to effectively formulate and solve problems.
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.
observable: "Observable" refers to something that can be perceived or detected through the
senses or through instrumentation.
Deterministic: "Deterministic" refers to a system or process in which every state or outcome
is uniquely determined by its preceding state, without any randomness or uncertainty. In a
deterministic system, given the same initial conditions, the subsequent states or outcomes will
always be the same.
Search: 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.
Execution: Once a solution is found, the actions it recommends can be carried out. This is
called the execution phase.
Control theorists call this an open-loop system, because ignoring the percepts breaks the loop
between agent and environment.
The initial state that the agent starts in. For example, the initial state for our agent in
Romania might be described as In(Arad).
A description of the possible actions available to the agent. Given a particular state s,
ACTIONS ACTIONS(s) returns the set of actions that can be executed in s. We say
that each of these actions is applicable in s. For example, from the state In(Arad), the
applicable APPLICABLE actions are
{Go(Sibiu), Go(Timisoara), Go(Zerind)}.
A description of what each action does; the formal name for this is the transition
model, specified by a function RESULT(s, a) that returns the state that results from
TRANSITION MODEL doing action a in state s. We also use the term successor to refer to
any state reachable SUCCESSOR from a given state by a single action.2 For example, we
have
RESULT(In(Arad),Go(Zerind)) = In(Zerind) .
Together, the initial state, actions, and transition model implicitly define the state space of
the problem
Path in the state space is a sequence of states connected by a sequence of actions
The goal test, which determines whether a given state is a goal state. Sometimes the
goal is specified by an abstract property rather than an explicitly enumerated set of
states. For example, in chess, the goal is to reach a state called “checkmate,” where
the opponent’s king is under attack and can’t escape.
path cost function that assigns a numeric cost to each path. The problem-solving
agent chooses a cost function that reflects its own performance measure.
performance of algorithms.
real-world problem is one whose solutions people actually care about. Such problems tend
not to have a single agreed-upon description, but we can give the general flavor of their
formulations.
3.2.1 Toy problems
vacuum world
The first example we examine is the vacuum world first introduced in Chapter 2. (See
Figure 2.2.) This can be formulated as a problem as follows:
• States: The state is determined by both the agent location and the dirt locations. The agent
is in one of two locations, each of which might or might not contain dirt. Thus, there are
2 × 22 = 8 possible world states. A larger environment with n locations has n · 2n states.
• Initial state: Any state can be designated as the initial state.
• Actions: In this simple environment, each state has just three actions: Left, Right, and Suck.
Larger environments might also include Up and Down.
• Transition model: The actions have their expected effects, except that moving Left in the
leftmost square, moving Right in the rightmost square, and Sucking in a clean square have no
effect. The complete state space is shown in Figure 3.3.
• Goal test: This checks whether all the squares are clean.
• Path cost: Each step costs 1, so the path cost is the number of steps in the path.
The 8-puzzle:
The 8-puzzle, an instance of which is shown in Figure 3.4, consists of a 3×3 board with eight
numbered tiles and a blank space. A tile adjacent to the blank space can slide into the space. The
object is to reach a specified goal state, such as the one shown on the right of the figure. The standard
formulation is as follows:
States: A state description specifies the location of each of the eight tiles and the blank in one
of the nine squares.
• Initial state: Any state can be designated as the initial state. Note that any given goal can be
reached from exactly half of the possible initial states (Exercise 3.4).
• Actions: The simplest formulation defines the actions as movements of the blank space
Left, Right, Up, or Down. Different subsets of these are possible depending on where the
blank is.
• Transition model: Given a state and action, this returns the resulting state; for example, if
we apply Left to the start state in Figure 3.4, the resulting state has the 5 and the blank
switched.
• Goal test: This checks whether the state matches the goal configuration shown in Figure
3.4. (Other goal configurations are possible.)
• Path cost: Each step costs 1, so the path cost is the number of steps in the path.
The 8-puzzle belongs to the family of sliding-block puzzles, which are often used as test
problems for new search algorithms in AI. This family is known to be NP-complete, so one
does not expect to find methods significantly better in the worst case than the search
algorithms described in this chapter and the next. The 8-puzzle has 9!/2 = 181, 440 reachable
states and is easily solved. The 15-puzzle (on a 4×4 board) has around 1.3 trillion states, and
random instances can be solved optimally in a few milliseconds by the best search
algorithms. The 24-puzzle (on a 5 × 5 board) has around 1025 states, and random instances
take several hours to solve optimally.
8-queens problem
The goal of the 8-queens problem is to place eight queens on a chessboard such that no
queen attacks any other. (A queen attacks any piece in the same row, column or diagonal.)
Figure 3.5 shows an attempted solution that fails: the queen in the rightmost column is
attacked by the queen at the top left.
There are two main kinds of formulation. An incremental formulation involves operators
that augment the state description, starting with an empty state; for the 8-queens problem, this
means that each action adds a queen to the state. A complete-state formulation starts with
all 8 queens on the board and moves them around. In either case, the path cost is of no
interest because only the final state counts. The first incremental formulation one might try is
the following:
• States: Any arrangement of 0 to 8 queens on the board is a state.
• Initial state: No queens on the board.
• Actions: Add a queen to any empty square.
• Transition model: Returns the board with a queen added to the specified square.
• Goal test: 8 queens are on the board, none attacked.
In this formulation, we have 64 · 63 ··· 57 ≈ 1.8 × 1014 possible sequences to investigate. A
better formulation would prohibit placing a queen in any square that is already attacked:
• States: All possible arrangements of n queens (0 ≤ n ≤ 8), one per column in the
leftmost n columns, with no queen attacking another.
• Actions: Add a queen to any square in the leftmost empty column such that it is not
attacked by any other queen. This formulation reduces the 8-queens state space from 1.8 ×
1014 to just 2,057, and solutions are easy to find. On the other hand, for 100 queens the
reduction is from roughly 10400 states to about 1052 states (Exercise 3.5)—a big improvement,
but not enough to make the problem tractable. Section 4.1 describes the complete-state
formulation, and Chapter 6 gives a simple algorithm that solves even the million-queens
problem with ease.
Explanation:
To find a solution to the 8 Queen problem, which consists of placing 8 queens on a
chessboard in such a way that no two queens threaten each other.
The algorithm starts by placing a queen on the first column, then it proceeds to the next
column and places a queen in the first safe row of that column.
If the algorithm reaches the 8th column and all queens are placed in a safe position, it
prints the board and returns true. If the algorithm is unable to place a queen in a safe
position in a certain column, it backtracks to the previous column and tries a different
row.
The “isSafe” function checks if it is safe to place a queen on a certain row and column
by checking if there are any queens in the same row, diagonal or anti-diagonal.
It’s worth to notice that this is just a high-level pseudo code and it might need to be
adapted depending on the specific implementation and language you are using.
Knuth’s 4 problem
Our final toy problem was devised by Donald Knuth (1964) and illustrates how
infinite state spaces can arise. Knuth conjectured that, starting with the number 4, a
sequence of factorial, square root, and floor operations will reach any desired positive
integer. For example, we can reach 5 from 4 as follows:
States: Each state obviously includes a location (e.g., an airport) and the current time.
Furthermore, because the cost of an action (a flight segment) may depend on previous
segments, their fare bases, and their status as domestic or international, the state must record
extra information about these “historical” aspects.
• Initial state: This is specified by the user’s query.
• Actions: Take any flight from the current location, in any seat class, leaving after the
current time, leaving enough time for within-airport transfer if needed.
• Transition model: The state resulting from taking a flight will have the flight’s destination
as the current location and the flight’s arrival time as the current time.
• Goal test: Are we at the final destination specified by the user?
• Path cost: This depends on monetary cost, waiting time, flight time, customs and
immigration procedures, seat quality, time of day, type of airplane, frequent-flyer mileage
awards, and so on.
Touring problems are closely related to route-finding problems, but with an important
difference. Consider, for example, the problem “Visit every city in Figure 3.2 at least once,
starting and ending in Bucharest.” As with route finding, the actions correspond to trips
between adjacent cities. The state space, however, is quite different. Each state must include
not just the current location but also the set of cities the agent has visited. So the initial state
would be In(Bucharest), Visited({Bucharest}), a typical intermediate state would be
In(Vaslui), Visited({Bucharest, Urziceni, Vaslui}), and the goal test would check whether the
agent is in Bucharest and all 20 cities have been visited.
The travelling salesperson problem (TSP) is a touring problem in which each city must be
visited exactly once. The aim is to find the shortest tour. The problem is known to be NP-
hard, but an enormous amount of effort has been expended to improve the capabilities of TSP
algorithms. In addition to planning trips for travelling salespersons, these algorithms have
been used for tasks such as planning movements of automatic circuit-board drills and of
stocking machines on shop floors.
Eg: Consider the following graph with six cities and the distances between them
From the given graph, since the origin is already mentioned, the solution must always start
from that node. Among the edges leading from A, A → B has the shortest distance.
Then, B → C has the shortest and only edge between, therefore it is included in the output
graph.
There’s only one edge between C → D, therefore it is added to the output graph.
There’s two outward edges from D. Even though, D → B has lower distance than D → E, B
is already visited once and it would form a cycle if added to the output graph. Therefore, D
→ E is added into the output graph.
There’s only one edge from e, that is E → F. Therefore, it is added into the output graph.
Again, even though F → C has lower distance than F → A, F → A is added into the output
graph in order to avoid the cycle that would form and C is already visited once.
Even though, the cost of path could be decreased if it originates from other nodes but the
question is not raised with respect to that.
A VLSI layout problem requires positioning millions of components and connections on a chip to
minimize area, minimize circuit delays, minimize stray capacitances, and maximize manufacturing
yield. The layout problem comes after the logical design phase and is usually split into two parts: cell
layout and channel routing. In cell layout, the primitive components of the circuit are grouped into
cells, each of which performs some recognized function. Each cell has a fixed footprint (size and
shape) and requires a certain number of connections to each of the other cells. The aim is to place the
cells on the chip so that they do not overlap and so that there is room for the connecting wires to be
placed between the cells. Channel routing finds a specific route for each wire through the gaps
between the cells. These search problems are extremely complex, but definitely worth solving. Later
in this chapter, we present some algorithms capable of solving them.
This is the essence of search—following up one option now and putting the others aside for
later, in case the first choice does not lead to a solution. Suppose we choose Sibiu first. We
check to see whether it is a goal state (it is not) and then expand it to get In(Arad),
In(Fagaras), In(Oradea), and In(RimnicuVilcea). We can then choose any of these four or go
back and choose Timisoara or Zerind. Each of these six nodes is a leaf node, that is, a node
with no children in the tree. The set of all leaf nodes available for expansion at any given
point is called the frontier. (Many authors call it the open list, which is both geographically
less evocative and less accurate, because other data structures are better suited than a list.) In
Figure 3.6, the frontier of each tree consists of those nodes with bold outlines.
The process of expanding nodes on the frontier continues until either a solution is found or
there are no more states to expand. The general TREE-SEARCH algorithm is shown
informally in Figure 3.7. Search algorithms all share this basic structure; they vary primarily
according to how they choose which state to expand next—the so-called search strategy.
The eagle-eyed reader will notice one peculiar thing about the search tree shown in Figure
3.6: it includes the path from Arad to Sibiu and back to Arad again! We say that In(Arad) is a
repeated state in the search tree, generated in this case by a loopy path. Considering such
loopy paths means that the complete search tree for Romania is infinite because there is no
limit to how often one can traverse a loop. is no need to consider loopy paths. We can rely on
more than intuition for this: because path costs are additive and step costs are nonnegative, a loopy
path to any given state is never better than the same path with the loop removed.
Loopy paths are a special case of the more general concept of redundant paths, which exist
whenever there is more than one way to get from one state to another. Consider the paths
Arad–Sibiu (140 km long) and Arad–Zerind–Oradea–Sibiu (297 km long). Obviously, the
second path is redundant—it’s just a worse way to get to the same state. If you are concerned
about reaching the goal, there’s never any reason to keep more than one path to any given
state, because any goal state that is reachable by extending one path is also reachable by
extending the other.
In some cases, it is possible to define the problem itself so as to eliminate redundant paths.
For example, if we formulate the 8-queens problem (page 71) so that a queen can be placed in
any column, then each state with n queens can be reached by n! different paths; but if we
reformulate the problem so that each new queen is placed in the leftmost empty column, then
each state can be reached only through one path.
In other cases, redundant paths are unavoidable. This includes all problems where the actions
are reversible, such as route-finding problems and sliding-block puzzles. Route- finding on a
rectangular grid (like the one used later for Figure 3.9) is a particularly important example
in computer games. In such a grid, each state has four successors, so a search tree of depth d
that includes repeated states has 4d leaves; but there are only about 2d2 distinct states within
d steps of any given state. For d = 20, this means about a trillion nodes but only about 800
distinct states. Thus, following redundant paths can cause a tractable problem to become
intractable. This is true even for algorithms that know how to avoid infinite loops.
As the saying goes, algorithms that forget their history are doomed to repeat it. The
way to avoid exploring redundant paths is to remember where one has been. To do this, we
augment the TREE-SEARCH algorithm with a data structure called the explored set (also
known as the closed list), which remembers every expanded node. Newly generated nodes
that match previously generated nodes—ones in the explored set or the frontier—can be
discarded instead of being added to the frontier. The new algorithm, called GRAPH-
SEARCH, is shown informally in Figure 3.7. The specific algorithms in this chapter draw on
this general design.
Clearly, the search tree constructed by the GRAPH-SEARCH algorithm contains at
most one copy of each state, so we can think of it as growing a tree directly on the state-space
graph, state-space graph into the explored region and the unexplored region, so that every
path from the initial state to an unexplored state has to pass through a state in the frontier. (If
this seems completely obvious, try Exercise 3.13 now.) This property is illustrated in Figure
3.9. As every step moves a state from the frontier into the explored region while moving
some states from the unexplored region into the frontier, we see that the algorithm is
systematically examining the states in the state space, one by one, until it finds a solution.
Given the components for a parent node, it is easy to see how to compute the necessary
components for a child node. The function CHILD-NODE takes a parent node and an action
and returns the resulting child node:
The node data structure is depicted in Figure 3.10. Notice how the PARENT pointers string
the nodes together into a tree structure. These pointers also allow the solution path to be
extracted when a goal node is found; we use the SOLUTION function to return the sequence
of actions obtained by following parent pointers back to the root. Up to now, we have not
been very careful to distinguish between nodes and states, but in writing detailed algorithms
it’s important to make that distinction. A node is a bookkeeping data structure used to
represent the search tree. A state corresponds to a configuration of the world. Thus, nodes are
on particular paths, as defined by PARENT pointers, whereas states are not. Furthermore,
two different nodes can contain the same world state if that state is generated via two
different search paths.
Now that we have nodes, we need somewhere to put them. The frontier needs to be stored in
such a way that the search algorithm can easily choose the next node to expand according to
its preferred strategy. The appropriate data structure for this is a queue. The operations on a
queue are as follows:
• EMPTY?(queue) returns true only if there are no more elements in the queue.
• POP(queue) removes the first element of the queue and returns it.
• INSERT(element, queue) inserts an element and returns the resulting queue.
Queues are characterized by the order in which they store the inserted nodes. Three common variants
are the first-in, first-out or FIFO queue, which pops the oldest element of the queue; the last-in, first
out or LIFO queue (also known as a stack), which pops the newest element of the queue; and the
priority queue, which pops the element of the queue with the highest priority according to some
ordering function.
Thus, to compute the total cost, we have to add milliseconds and kilometres. There is
no “official exchange rate” between the two, but it might be reasonable in this case to convert
kilometres into milliseconds by using an estimate of the car’s average speed (because time is
what the agent cares about). This enables the agent to find an optimal tradeoffs point at which
further computation to find a shorter path becomes counterproductive.
3.4 UNINFORMED SEARCH STRATEGIES (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.
Pseudo code is given in Figure 3.11. Figure 3.12 shows the progress of the search on a simple
binary tree.
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 non decreasing 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. Then the total number of nodes generated is
b + b2 + b3 + ··· + bd = O(bd) .
(If the algorithm were to apply the goal test to nodes when selected for expansion, rather than
when generated, the whole layer of nodes at depth d would be expanded before the goal was
detected and the time complexity would be O(bd+1).)
As for space complexity: for any kind of graph search, which stores every expanded
node in the explored set, the space complexity is always within a factor of b of the time
complexity. For breadth-first graph search in particular, every node generated remains in
memory. There will be O(bd−1) nodes in the explored set and O(bd) nodes in the frontier,
so the space complexity is O(bd), i.e., it is dominated by the size of the frontier. Switching
to a tree search would not save much space, and in a state space with many redundant paths,
switching could cost a great deal of time.
An exponential complexity bound such as O(bd) is scary. Figure 3.13 shows why. It
lists, for various values of the solution depth d, the time and memory required for a breadth-
first search with branching factor b = 10. The table assumes that 1 million nodes can be
generated per second and that a node requires 1000 bytes of storage. Many search problems
fit roughly within these assumptions (give or take a factor of 100) when run on a modern
personal computer.
indeed any uninformed search) to find it. In general, exponential-complexity search problems
cannot be solved by uninformed methods for any but the smallest instances.
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.
Uniform-cost search does not care about the number of steps a path has, but only about their
total cost. Therefore, it will get stuck in an infinite loop if there is a path with an infinite
sequence of zero-cost actions—for example, a sequence of NoOp actions.6 Completeness is
guaranteed provided the cost of every step exceeds some small positive constant.
Uniform-cost search is guided by path costs rather than depths, so its complexity is
not easily characterized in terms of b and d. Instead, let C∗ be the cost of the optimal
solution, and assume that every action costs at least . Then the algorithm’s worst-case time
and space complexity is O(b1+ C∗/ ), which can be much greater than bd. This is because
uniform cost search can explore large trees of small steps before exploring paths involving
large and perhaps useful steps. When all step costs are equal, b1+ C∗/ is just bd+1. When all
step costs are the same, uniform-cost search is similar to breadth-first search, except that the
latter stops as soon as it generates a goal, whereas uniform-cost search examines all the nodes
at the goal’s depth to see if one has a lower cost; thus uniform-cost search does strictly more
work by expanding nodes at depth d unnecessarily.
3.4.3 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 selected.
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.
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.
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.
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).
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 generated d times. So the total number of nodes
generated in the worst case is
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 cantered 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 search.
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.
Consider the question of what we mean by “the goal” in searching “backward from
the goal.” For the 8-puzzle and for finding a route in Romania, there is just one goal state, so
the backward search is very much like the forward search. If there are several explicitly listed
goal states—for example, the two dirt-free goal states in Figure 3.3—then we can construct a
new dummy goal state whose immediate predecessors are all the actual goal states. But if the
goal is an abstract description, such as the goal that “no queen attacks another queen” in the
n-queens problem, then bidirectional search is difficult to use.
3.4.7 Comparing uninformed search strategies
Figure 3.21 compares search strategies in terms of the four evaluation criteria. 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.
SUMMARY
This chapter has introduced methods that an agent can use to select actions in environments
that are deterministic, observable, static, and completely known. In such cases, the agent can
construct sequences of actions that achieve its goals; this process is called search.
• Before an agent can start searching for solutions, a goal must be identified and a
welldefined problem must be formulated.
• A problem consists of five parts: the initial state, a set of actions, a transition model
describing the results of those actions, a goal test function, and a path cost function. The
environment of the problem is represented by a state space. A path through the state space
from the initial state to a goal state is a solution.
• Search algorithms treat states and actions as atomic: they do not consider any internal
structure they might possess.
• A general TREE-SEARCH algorithm considers all possible paths to find a solution,
whereas a GRAPH-SEARCH algorithm avoids consideration of redundant paths.
• Search algorithms are judged on the basis of completeness, optimality, time complexity,
and space complexity. Complexity depends on b, the branching factor in the state space, and
d, the depth of the shallowest solution.
• Uninformed search methods have access only to the problem definition. The basic
algorithms are as follows:
– Breadth-first search expands the shallowest nodes first; it is complete, optimal for unit
step costs, but has exponential space complexity.
– Uniform-cost search expands the node with lowest path cost, g(n), and is optimal for
general step costs.
– Depth-first search expands the deepest unexpanded node first. It is neither complete nor
optimal, but has linear space complexity. Depth-limited search adds a depth bound.
– Iterative deepening search calls depth-first search with increasing depth limits until a goal
is found. It is complete, optimal for unit step costs, has time complexity comparable to
breadth-first search, and has linear space complexity.
– Bidirectional search can enormously reduce time complexity, but it is not always
applicable and may require too much space.
EXERCISES
1. Explain why problem formulation must follow goal formulation.
Sol: Problem formulation is the process of clearly defining the issue or challenge that needs
to be addressed. It involves identifying the specific aspects of the situation that are causing
difficulty or concern. Goal formulation, on the other hand, is the process of establishing what
you want to achieve or accomplish.
It's essential for problem formulation to follow goal formulation because:
Clarity of Purpose: Establishing clear goals provides a direction for problem
formulation. When you know what you want to achieve, it becomes easier to identify
the obstacles or problems that stand in the way of reaching those goals.
Relevance: Problem formulation should be directly related to the goals you've set. By
formulating goals first, you ensure that the problems identified are relevant to the
objectives you're trying to accomplish. This prevents wasting time and resources on
solving issues that don't contribute to your desired outcomes.
Focus: Goals provide a focus for problem-solving efforts. They help you prioritize
which problems are most important to address, allowing you to allocate resources
effectively and avoid getting sidetracked by less significant issues.
Evaluation: Having clearly defined goals allows you to evaluate the effectiveness of
your problem formulation. By comparing the solutions generated against the desired
outcomes, you can assess whether the identified problems were accurately understood
and addressed.
Alignment: When problem formulation follows goal formulation, it ensures alignment
between the problems being tackled and the overarching objectives of the endeavor.
This alignment increases the likelihood of success because all efforts are directed
towards fulfilling the intended purpose.
2. Your goal is to navigate a robot out of a maze. The robot starts in the centre of the maze
facing north. You can turn the robot to face north, east, south, or west. You can direct
the robot to move forward a certain distance, although it will stop before hitting a wall.
a. Formulate this problem. How large is the state space?
b. In navigating a maze, the only place we need to turn is at the intersection of two or
more corridors. Reformulate this problem using this observation. How large is the state
space now?
c. From each point in the maze, we can move in any of the four directions until we reach
a turning point, and this is the only action we need to do. Reformulate the problem
using these actions. Do we need to keep track of the robot’s orientation now?
d. In our initial description of the problem we already abstracted from the real world,
restricting actions and removing details. List three such simplifications we made.
Sol: a. Original Problem Formulation:
- State Space: In the original problem, the state space consists of the position of the robot
(x, y coordinates) and its orientation (north, east, south, or west).
b. Reformulated Problem with Intersection Observation:
- In this reformulation, we only need to consider turning at intersections.
- State Space: The state space now consists of the position of the robot (x, y coordinates)
and the direction it needs to turn at intersections. Since there are four directions (north, east,
south, west) and three possible actions (turn left, go straight, turn right) at each intersection,
the state space is reduced to the position of the robot and one of three actions to take.
c. Reformulated Problem with Simplified Actions:
Solu: The 8-puzzle states can be divided into two disjoint sets based on their parity, namely
the "even" and "odd" states. This division is based on the number of inversions in the puzzle,
where an inversion occurs when a tile precedes another tile with a lower number but comes
after it in the goal state. For instance, in the goal state:
123
456
780
If we represent the puzzle as a 1D array, an inversion happens if a tile with a higher value
appears before a tile with a lower value.
To demonstrate:
- In the puzzle state `[1, 2, 3, 4, 5, 6, 7, 0, 8]`, there are no inversions.
- In the puzzle state `[1, 2, 3, 4, 5, 6, 0, 8, 7]`, there's one inversion (7 precedes 8).
- In the puzzle state `[1, 2, 3, 4, 5, 0, 7, 8, 6]`, there are four inversions (5 precedes 7, 5
precedes 8, 7 precedes 8, and 6 precedes 8).
The property of the 8-puzzle is such that only states with an even number of inversions are
solvable. Thus, we can divide the states into "even" and "odd" sets based on this property.
The goal state has zero inversions, making it an "even" state.
To decide which set a given state is in:
1. Count the number of inversions in the puzzle state.
2. If the number of inversions is even, the state belongs to the "even" set; otherwise, it
belongs to the "odd" set.
This method is useful for generating random states because:
1. It ensures that any random state generated is solvable. Since only states in the same parity
set are reachable from one another, generating a random state within a particular set
guarantees its solvability within that set.
2. It simplifies the process of generating random states by limiting the search space. Instead
of searching randomly through all possible states, we can focus on generating states within a
specific parity set, reducing the computational complexity of the task.
4. Consider the n-queens problem using the “efficient” incremental formulation Explain
why the state space has at least 3√ n! states and estimate the largest n for which
exhaustive exploration is feasible. (Hint: Derive a lower bound on the branching factor
by considering the maximum number of squares that a queen can attack in any
column.)
Solu: The n-queens problem is a classic puzzle where you have to place n queens on an n×n
chessboard such that no two queens attack each other. In the "efficient" incremental
formulation, you place one queen in each column, ensuring that no two queens share the
same row or diagonal.
To understand why the state space has at least 3√n! states, let's break it down:
1. Branching Factor: In the incremental formulation, each queen is placed in a column, and
we need to find a valid row for each queen. Let's denote the maximum number of squares that
a queen can attack in any column as k. In a column, there are n rows, but each queen can only
attack k squares in that column. So, the effective branching factor for each column is at most
n/k.
2. State Space Size: We have n columns to place n queens. Each column has a branching
factor of at most n/k. So, the total number of possible states can be estimated by multiplying
the branching factor of each column:
Total States ≥ (k/n)n
3. Lower Bound on k: The maximum number of squares that a queen can attack in any
column is equal to the number of rows in the column. So, k is at least n.
Substituting this lower bound for k into the equation for total states:
So, the largest n for which exhaustive exploration is feasible depends on the manageable limit
of states.
5. Give a complete problem formulation for each of the following. Choose a formulation
that is precise enough to be implemented.
a. Using only four colors, you have to color a planar map in such a way that no two
adjacent regions have the same color.
b. A 3-foot-tall monkey is in a room where some bananas are suspended from the 8-foot
ceiling. He would like to get the bananas. The room contains two stackable, movable,
climbable 3-foot-high crates.
c. You have a program that outputs the message “illegal input record” when fed a
certain file of input records. You know that processing of each record is independent of
the other records. You want to discover what record is illegal.
d. You have three jugs, measuring 12 gallons, 8 gallons, and 3 gallons, and a water
faucet. You can fill the jugs up or empty them out from one to another or onto the
ground. You need to measure out exactly one gallon.
Solu:
a. Problem Formulation for Coloring a Planar Map:
- Initial State:
- Planar map with regions and adjacency information.
- All regions uncolored.
- Actions:
- Choose a region.
- Assign one of the four colors to the chosen region, ensuring it doesn't conflict with
neighboring regions.
- Transition Model:
- Assigning a color to a region.
- Update the state by coloring the chosen region and checking if the coloring violates
adjacency constraints.
- Goal State:
- All regions are colored, and no two adjacent regions have the same color.
- Cost Function:
- Minimize the number of color changes or transitions between states.
- Constraints:
- The chosen colors must not violate the adjacency rule.
- The map must be planar.
b. Problem Formulation for the Monkey and Bananas Problem:
- Initial State:
- Monkey's position, banana's position, crate's position.
- Monkey is not holding anything.
- Actions:
- Move left.
- Move right.
- Climb up on crate.
- Climb down from crate.
- Grab banana (if reachable).
- Transition Model:
- Changing the monkey's position or state.
- Moving the crate's position.
- Updating the state based on the action taken.
- Goal State:
- Monkey successfully grabs the banana.
- Cost Function:
- Minimize the number of actions taken.
- Constraints:
- Monkey cannot reach bananas directly without climbing on crates.
- Cost Function:
- Minimize the number of moves (boat trips) required to reach the goal state.
- Constraints:
- Missionaries cannot be outnumbered by cannibals on either side of the river.
- The boat can only carry one or two people at a time.
Diagram of the Complete State Space:
Initial State:
[MMM CCC B] -> [--- --- ---]
Possible States:
[MMM CCC B] -> [--- --- ---] (Boat on original side)
[MM CC B] -> [MMM CCC ---] (Boat on original side)
[MM CC B] -> [--- --- MMM CCC] (Boat on opposite side)
[MMM CC B] -> [--- CC MMM] (Boat on original side)
[MMM B] -> [CCC MM ---] (Boat on original side)
[MMM B] -> [--- MM CCC] (Boat on opposite side)
[MM B] -> [M CCC MM] (Boat on original side)
[MM B] -> [--- CCC MMM] (Boat on opposite side)
[CCC B] -> [MMM --- CCC] (Boat on original side)
[CCC B] -> [MMM CCC ---] (Boat on opposite side)
[CCC MM B] -> [--- MM CCC] (Boat on original side)
[CC MM B] -> [M CCC MM] (Boat on original side)
[CC MM B] -> [--- CCC MMM] (Boat on opposite side)
[CC B] -> [MM CCC M] (Boat on original side)
[CC B] -> [--- CCC MMM] (Boat on opposite side)
[MMM B] -> [--- MM CCC] (Boat on original side)
[MMM B] -> [CCC MM ---] (Boat on opposite side)
[MM B] -> [--- CCC MM] (Boat on original side)
[MM B] -> [MM CCC ---] (Boat on opposite side)
[B] -> [MMM CCC ---] (Boat on original side)
b. To solve the problem optimally, you can use the Breadth-First Search (BFS) algorithm,
which guarantees finding the shortest path to the solution. Since the state space is relatively
small, repeated states can be checked without significant computational overhead. However,
in larger state spaces, checking for repeated states might become inefficient.
c. Despite the simplicity of the state space, people often find this puzzle challenging due to
the need to consider multiple constraints simultaneously. It requires careful planning and
systematic exploration of possible moves while ensuring that no group of missionaries is
outnumbered by cannibals on either side of the river. Additionally, the optimal solution might
not be immediately apparent, leading to trial and error for many people.
7. An action such as Go(Sibiu) really consists of a long sequence of finer-grained
actions: turn on the car, release the brake, accelerate forward, etc. Having composite
actions of this kind reduces the number of steps in a solution sequence, thereby
reducing the search time. Suppose we take this to the logical extreme, by making super-
composite actions out of every possible sequence of Go actions. Then every problem
instance is solved by a single supercomposite action, such as Go(Sibiu)Go(Rimnicu
Vilcea)Go(Pitesti)Go(Bucharest). Explain how search would work in this formulation.
Is this a practical approach for speeding up problem solving?
Solu:
In this extreme formulation where every possible sequence of "Go" actions is encapsulated
into a single super-composite action, the search process becomes significantly simplified.
Essentially, the search algorithm would treat each super-composite action as a single atomic
step. This means that instead of considering individual actions (like turning on the car,
releasing the brake, etc.), the algorithm directly evaluates the consequences of executing the
entire sequence of actions represented by the super-composite action.
Here's how the search would work in this formulation:
1. Initial State: The initial state of the problem.
2. Actions: The available super-composite actions, each representing a sequence of finer-
grained actions.
3. Transition Model: Executing a super-composite action results in a new state.
4. Goal State: The desired state that satisfies the problem's criteria.
5. Search Algorithm: The search algorithm, whether it's BFS, DFS, A*, etc., would operate
on these super-composite actions. It would explore the state space by applying these actions
and evaluating their consequences until a goal state is reached.
While this approach theoretically reduces the number of steps in the solution sequence,
making the search process more efficient, it has several practical limitations:
1. Complexity of Super-Composite Actions: Super-composite actions may encapsulate a
large number of finer-grained actions, making them complex and difficult to understand or
manage.
2. Loss of Flexibility: By predefining all possible sequences of actions, the system loses the
flexibility to adapt its behaviour based on changing circumstances or constraints.
3. Memory and Computational Resources: Storing and processing super-composite actions
for large state spaces can be memory-intensive and computationally expensive.
4. Optimality Concerns: Predefined super-composite actions may not always lead to the most
optimal solutions, especially in dynamic or uncertain environments.