liveBook · Manning

Frontier

As explained in Classic Computer Science Problems in Swift: Essential techniques for practicing programmers

A frontier is the collection of discovered search states that remain candidates for exploration.

A frontier holds discovered states that remain candidates for exploration. In a maze search, it begins with the start location. The search removes a node, tests its state against the goal, and adds eligible successors. A separate explored collection tracks states already encountered so the search does not circle back indefinitely. section 2.2

How the frontier removes nodes determines the search order:

  • Depth-first search uses a stack, taking the most recently added node and following a path deeper before backtracking. section 2.2
  • Breadth-first search uses a queue, taking the earliest added node to explore nearby locations first. section 2.2
  • A* uses a priority queue of nodes with costs and heuristics. section 2.2

Each node keeps its state and parent. When the goal is removed from the frontier, following parent links reconstructs the path. If the frontier empties first, there is nowhere left to search. section 2.2

func dfs<StateType:
 Hashable>(initialState: StateType, goalTestFn: (StateType)
 -> Bool, successorFn: (StateType) -> [StateType]) -> Node<StateType>? {
    // frontier is where we've yet to go
    let frontier: Stack<Node<StateType>> = Stack<Node<StateType>>()
    frontier.push(Node(state: initialState, parent: nil))
    // explored is where we've been
    var explored: Set<StateType> = Set<StateType>()
    explored.insert(initialState)

    // keep going while there is more to explore
    while !frontier.isEmpty {
        let currentNode = frontier.pop()
        let currentState = currentNode.state
        // if we found the goal, we're done
        if goalTestFn(currentState) { return currentNode }
        // check where we can go next and haven't explored
        for child in successorFn(currentState) where
         !explored.contains(child) {
            explored.insert(child)
            frontier.push(Node(state: child, parent: currentNode))
        }
    }
    return nil // never found the goal
}

The Swift depth-first search keeps its frontier as a stack of nodes and its explored states in a separate set. section 2.2

How Classic Computer Science Problems in Swift: Essential techniques for practicing programmers covers it

How deep it goes
Works through frontier initialization and search loops, then varies the container across three algorithms without a formal analysis.
Examples
Uses a grid maze and Swift search functions with stack, queue, and priority-queue frontiers.
What it assumes
Uses Swift generics and Hashable states while supplying simple stack and queue implementations.
What you can do after
Operate/configure a maze search by choosing a stack, queue, or priority queue as its frontier.
How it connects
Connects the frontier to stacks, queues, priority queues, explored states, goal tests, and path reconstruction.

Also explained in

Compare how 2 books explain frontier →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Classic Computer Science Problems in Swift: Essential techniques for practicing programmers. The section links point to the parts of the book it draws on.