AA Applied Algorithms

Multilevel Local Search

Compress the problem, solve the small version, expand back, refine — like working with a zoomed-out then zoomed-in view.

Intuition

The big idea

For a 100-variable problem, a local-search swap touches only 1 variable at a time — that's tiny. If you instead group variables into clusters of 2 and toggle entire clusters, each "move" affects 2 variables. Group again into clusters of 4 — each move affects 4. This lets the search make large, coordinated moves at coarse levels (good for escaping local optima), then refine with small moves at the fine level.

The three phases

  1. Coarsening — Merge variables into clusters. Cluster of clusters at the next level. Repeat until the problem is small.
  2. Coarse optimization — Apply local search at the coarsest level (each "move" toggles an entire cluster).
  3. Uncoarsening + refinement — Project the solution back to the next finer level. Run local search again. Repeat until you reach the original (level 0).

Worked example (graph coloring with 100 variables)

Two colors: Black (B) or Green (G). Constraint: neighboring variables must have different colors.

Level 0 — original problem

100 indices, 100 individual variables.

Reduction → Level 1 (50 clusters of 2)

Cluster #1 = (var 1, var 4)
Cluster #2 = (var 2, var 17)
…
Cluster #50 = (var 6, var 36)

Now the "solution" assigns one color to each cluster (both variables in the cluster get that color). 50 decisions instead of 100.

Reduction → Level 2 (25 clusters of 4)

Cluster #1 = ((1,4) ∪ (5,27))    → 4 vars
Cluster #2 = ((2,17) ∪ (4,15))   → 4 vars
…
Cluster #25 = ((45,13) ∪ (21,3))

Optimize at level 2

Random initial coloring at the cluster level. Apply local search:

while (not stop):
    pick random cluster i
    flip its color
    if (solution improves) accept else revert

Get something like: R B B G R G … B for 25 clusters. Each cluster's color applies to all 4 of its variables.

Uncoarsen to level 1, refine

Now we have 50 clusters with colors inherited from level 2. Run local search at this level — flipping a 2-variable cluster's color.

Uncoarsen to level 0, refine

Each variable gets its color. Run local search per individual variable.

Pseudocode

MULTILEVEL_LS(initial_problem, num_levels):
    P[0] = initial_problem
    for L = 1 .. num_levels:
        P[L] = coarsen(P[L-1])     // merge pairs of clusters

    solution[num_levels] = random
    for L = num_levels down to 0:
        solution[L] = local_search(P[L], solution[L])
        if L > 0:
            solution[L-1] = project(solution[L])    // inherit colors

    return solution[0]

Why this works:

Exam tips

Frequently asked

  • "Describe coarsening" — random pairing of variables/clusters at each level.
  • "Why multilevel over plain local search?" — large coordinated moves at coarse levels escape local optima.
  • "What happens at the finest level?" — local search with single-variable moves (same as ordinary).
  • "Apply multilevel to CSP" — same recipe; the local search inside flips a cluster's color (or value) and re-counts violated constraints.