🧠 AI Foundations · Lecture 6 of 24

Informed Search: Greedy Best-First and A* with Admissible Heuristics

Knowledge about where the goal lies transforms search. We derive A*, prove its optimality with admissible heuristics, and learn how to invent good heuristics by relaxing problems.

Blind search is honest but slow. A human planning a route from Dhaka to Chattogram does not consider roads heading towards Rajshahi, because they know roughly where Chattogram is. Today we give our search algorithms that kind of knowledge through a heuristic function, and we study the most celebrated algorithm in classical AI: A\*.

Heuristic functions#

A heuristic $h(n)$ estimates the cost of the cheapest path from node $n$ to a goal. For route finding, the straight-line distance is a natural choice. For the 8-puzzle, two classic heuristics are:

  • $h_1$ = number of misplaced tiles;
  • $h_2$ = sum of Manhattan distances of each tile from its goal position.

Greedy search expands the node with smallest $h(n)$ — whatever looks closest to the goal. It is often fast but neither optimal nor (in tree search) complete: it can be lured down a path that looks promising but is expensive or a dead end.

A* combines the cost already paid with the estimated cost remaining:

$$ f(n) = g(n) + h(n) $$

where $g(n)$ is the path cost from the start to $n$. A* expands the node with the lowest $f$ — the estimated cost of the cheapest solution through $n$.

python
import heapq, itertools

def a_star(start, is_goal, neighbors, h):
    counter = itertools.count()          # tie-breaker so states need not be comparable
    frontier = [(h(start), next(counter), 0, start)]
    g_best = {start: 0}
    parent = {start: None}
    while frontier:
        f, _, g, s = heapq.heappop(frontier)
        if is_goal(s):
            path = []
            while s is not None:
                path.append(s); s = parent[s]
            return g, path[::-1]
        if g > g_best[s]:
            continue
        for t, cost in neighbors(s):
            g2 = g + cost
            if g2 < g_best.get(t, float("inf")):
                g_best[t] = g2
                parent[t] = s
                heapq.heappush(frontier, (g2 + h(t), next(counter), g2, t))
    return None

Admissibility and consistency#

Every consistent heuristic is admissible (with $h(\text{goal}) = 0$), but not vice versa.

Why A* is optimal#

Theorem. With an admissible heuristic, A* tree search returns an optimal solution.

Proof sketch. Suppose A* selects a suboptimal goal $G_2$ for expansion, with $g(G_2) > C^*$. Let $n$ be a node on an optimal path that is still on the frontier (one always exists). Then

$$ f(n) = g(n) + h(n) \le g(n) + h^*(n) = C^* < g(G_2) = f(G_2) $$

so $n$ has a strictly smaller $f$ than $G_2$ and would have been expanded first — a contradiction. $\blacksquare$

With a consistent heuristic, $f$ values are non-decreasing along any path, which means that the first time A* expands a state it has found the optimal path to it — so graph search with a closed set remains optimal.

The quality of a heuristic#

If $h_2(n) \ge h_1(n)$ for all $n$ and both are admissible, we say $h_2$ dominates $h_1$, and A* with $h_2$ never expands more nodes. For the 8-puzzle, Manhattan distance dominates misplaced tiles. Typical results at solution depth 20:

HeuristicNodes generated (approx.)Effective branching factor
None (IDS)too many to run~2.8
$h_1$ misplaced tiles~ 39,000~1.47
$h_2$ Manhattan~ 1,600~1.28

Inventing heuristics by relaxation#

Where do good heuristics come from? The most powerful technique is problem relaxation: remove constraints from the problem, then solve the easier problem exactly. The cost of an optimal solution to a relaxed problem is an admissible heuristic for the original.

For the 8-puzzle, the rule is "a tile can move from A to B if A is adjacent to B and B is blank."

  • Drop both conditions → a tile can jump anywhere → $h_1$.
  • Drop "B is blank" → tiles slide through each other → $h_2$.

Other techniques include pattern databases (store exact costs for sub-problems) and learned heuristics, where a neural network predicts cost-to-go — the idea behind modern systems that combine search with learning.

Variants you should know#

  • Weighted A\*: $f = g + w\,h$ with $w > 1$ trades optimality (bounded by factor $w$) for speed.
  • IDA\*: iterative deepening on $f$-cost, using linear memory.
  • SMA\*: uses all available memory and drops the worst nodes when full.
JA
Written by

Janin A Apurba

B.Sc. in CSE, AUST · Advanced ICT Officer, CNRS-UNHCR. Teaching AI, ML and Deep Learning to the next generation of engineers and researchers.

Keep learning

Related lectures

🧠 AI Foundations

Uninformed Search: BFS, DFS, Uniform-Cost and Iterative Deepening

Many AI problems reduce to finding a path in a huge graph. We formalise search problems and analyse the classic blind strategies for completeness, optimality, time and space.

Beginner⏱ 5 min#005
🧠 AI Foundations

Adversarial Search: Minimax and Alpha–Beta Pruning

When an opponent is trying to defeat you, search must account for their choices. We derive minimax, prove alpha–beta pruning correct, and see how real game engines evaluate positions.

Intermediate⏱ 5 min#007
🧠 AI Foundations

Classical Planning: STRIPS, PDDL and Planning Graphs

Planning is search with structured, factored states. We represent actions with preconditions and effects, compare forward and backward planning, and see how domain-independent heuristics are derived automatically.

Intermediate⏱ 5 min#015