Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Worked examples

Short illustrations of ideas from AIMA (search, heuristics, logic-style checks). The same page is used for print and PDF exports (code appears as static listings) and for the website: when this project is built with project.jupyter (AI Dialogic), {code-cell} blocks become live in the browser via Thebe + Binder so students can re-run and edit them.

Search: explicit graph and goal test

Static listing (readable in any export):

"""Tiny directed graph: states are labels; expand by following edges."""
SUCCESSORS = {
    "START": ["A", "B"],
    "A": ["GOAL"],
    "B": ["A"],
    "GOAL": [],
}

def is_goal(state: str) -> bool:
    return state == "GOAL"

Live cell — includes the graph so it runs on its own in Thebe (static {code} blocks above are not executed):

SUCCESSORS = {
    "START": ["A", "B"],
    "A": ["GOAL"],
    "B": ["A"],
    "GOAL": [],
}

def is_goal(state: str) -> bool:
    return state == "GOAL"

start = "START"
frontier = [start]
visited = set()
while frontier:
    s = frontier.pop(0)
    if is_goal(s):
        print("Found GOAL from", start)
        break
    visited.add(s)
    for nxt in SUCCESSORS.get(s, []):
        if nxt not in visited:
            frontier.append(nxt)
else:
    print("No path (this tiny graph always reaches GOAL from START).")

Heuristic: Manhattan distance on a grid

Static intuition (no execution required):

def manhattan(a: tuple[int, int], b: tuple[int, int]) -> int:
    """Admissible for grid pathfinding with unit cost."""
    return abs(a[0] - b[0]) + abs(a[1] - b[1])

Live playground (definition repeated so the cell is self-contained for execution):

def manhattan(a: tuple[int, int], b: tuple[int, int]) -> int:
    return abs(a[0] - b[0]) + abs(a[1] - b[1])

start, goal = (0, 0), (3, 2)
h = manhattan(start, goal)
print("h(start, goal) =", h)

Propositional-style check (Python bool)

def implies(p: bool, q: bool) -> bool:
    return (not p) or q

P, Q = True, False
print("P -> Q when P=T, Q=F:", implies(P, Q))
print("P -> Q when P=F, Q=F:", implies(False, False))

Where this shows up elsewhere