Algorithm Search⌘K

Proofs: Wilson's algorithm

These are the human proofs of Wilson's algorithm, at full length.

Wilson's algorithm returns each spanning tree with probability proportional to the product of its weights full

This proof shows: correctness, termination.

Claim. Let G=(V,E)G = (V, E) be a finite connected undirected multigraph with n≥1n \ge 1 vertices and a weight ce>0c_e > 0 on each edge; parallel edges and self-loops are allowed. For each root rr and each order of the vertices in line L2, WILSON stops with probability 1, and its output TT satisfies

Pr⁡[T=t]=c(t)Z,c(t)=∏e∈tce,Z=∑t′c(t′),\Pr[T = t] = \frac{c(t)}{Z}, \qquad c(t) = \prod_{e \in t} c_e, \qquad Z = \sum_{t'} c(t'),

for each spanning tree tt, the sum over all spanning trees t′t'. With all weights 1, Pr⁡[T=t]=1/τ(G)\Pr[T = t] = 1 / \tau(G).

Setup

For a vertex xx, let c(x)c(x) be the sum of cec_e over the edges at xx, with a self-loop counted twice. A step at xx chooses an edge ee at xx with probability ce/c(x)c_e / c(x) (a self-loop with probability 2ce/c(x)2 c_e / c(x)) and moves to its other end. An arrow at xx is an edge at xx read as pointing from xx to its other end.

A rooted spanning tree at rr is a choice of one arrow a(x)a(x) at each x≠rx \ne r such that following arrows from any vertex reaches rr. Forgetting the directions gives a bijection between rooted spanning trees at rr and spanning trees tt of GG: in a spanning tree, each x≠rx \ne r has exactly one edge on its path to rr, and that edge must be a(x)a(x). So it is enough to show Pr⁡[arrows=a]∝∏x≠rca(x)\Pr[\text{arrows} = a] \propto \prod_{x \ne r} c_{a(x)}, because ∏x≠rca(x)=c(t)\prod_{x \ne r} c_{a(x)} = c(t).

Termination

Each walk of lines L4 to L6 is a random walk on a finite connected graph, and it stops when it reaches a vertex in the tree, which contains rr. From any vertex, some path of at most n−1n - 1 steps reaches rr, and the walk follows it with probability at least some δ>0\delta > 0. So the probability that a walk has not stopped after j(n−1)j(n-1) steps is at most (1−δ)j→0(1 - \delta)^j \to 0. There are at most nn walks, so the algorithm stops with probability 1.

The stack model

Before the run, attach to each vertex x≠rx \ne r an infinite stack Sx=(Sx1,Sx2,…)S_x = (S_x^1, S_x^2, \ldots) of arrows at xx, all independent, each with the law of a step at xx. Let line L5 at vertex uu use the next unused entry of SuS_u. The run is then a function of the stacks, and it has the same law as before, since each use of line L5 gets a fresh independent step.

At each time, the visible graph has, for each x≠rx \ne r, the topmost unused entry of SxS_x as its arrow. Each x≠rx \ne r has out-degree 1 and rr has out-degree 0. So the visible graph is either a rooted spanning tree at rr, or it has a directed cycle; a self-loop arrow is a cycle of length 1. Popping a visible cycle marks the top entry of each vertex on it as used, so the next entry of each of these stacks becomes visible.

A colored cycle is a cycle together with the level of the stack entry at each of its vertices. Popping makes sense for colored cycles: the colored cycle CC is poppable when each of its entries is at the top of its stack and they form a cycle.

Step 1: the run pops cycles

Lemma 1. The run of WILSON on fixed stacks is a sequence of cycle pops, and when no cycle is visible the arrows of the tree it returns are the visible graph.

Proof. We keep the invariant: at the start of each pass of line L2, the visible arrows of the tree vertices other than rr are the arrows Next\text{Next} that the tree uses, and they lead to rr.

During a walk from ii, keep the current loop-erased path u0=i,u1,…,uku_0 = i, u_1, \ldots, u_k of distinct vertices not in the tree, where each uj→uj+1u_j \to u_{j+1} is the visible arrow of uju_j. The walk stands at uku_k, and line L5 reads the visible arrow of uku_k. If it leads to a vertex in the tree, the walk stops. If it leads to a new vertex, that vertex is appended to the path. If it leads to a vertex uju_j of the path (with j=kj = k for a self-loop), the visible arrows of uj,…,uku_j, \ldots, u_k form a cycle; we pop it at once. The walk now stands at uju_j, the path becomes u0,…,uju_0, \ldots, u_j, and the visible arrow of uju_j is the next entry of its stack, which is exactly the entry that line L5 reads at the next step. The entries of uj+1,…,uku_{j+1}, \ldots, u_k are popped too; if the walk comes back to one of them later, line L5 reads its next entry, which is again the visible one. So the walk with these pops reads the same entries as line L5, and each read entry is visible when it is read.

When the walk reaches the tree, the visible arrows of u0,…,uku_0, \ldots, u_k lead into the tree, and they equal Next[u0],…,Next[uk]\text{Next}[u_0], \ldots, \text{Next}[u_k], since Next[u]\text{Next}[u] always holds the last entry read at uu. Lines L8 to L11 add exactly these vertices with these arrows. A vertex that was on an erased loop and not on the final path stays out of the tree, and its visible arrow is an entry not yet read. So the invariant holds after the pass. When the run ends, every vertex is in the tree, so the visible graph is the returned tree, which has no cycle, and the run was a sequence of pops of visible colored cycles. □\square

Step 2: the order of popping does not matter

Lemma 2. Fix the stacks. Suppose some sequence of pops, each of a poppable colored cycle, ends with no visible cycle after kk pops. Then every sequence of pops of poppable colored cycles ends after exactly kk pops, pops the same set of colored cycles, and leaves the same visible tree.

Proof. Two different cycles visible at the same time share no vertex, since each vertex has one visible arrow. A colored cycle CC, once poppable, stays poppable until one of its vertices has its top entry used, and the only pop that uses the top entry of a vertex of CC while CC is visible is the pop of CC itself.

Induction on kk. If k=0k = 0, no cycle is visible, so no pop is possible, and the claim holds. Let k≥1k \ge 1 and let C1,…,CkC_1, \ldots, C_k be the given sequence. Let CC be any poppable colored cycle at the start. The cycle CC is visible at the start and the sequence ends with no visible cycle, so some CjC_j uses an entry of CC; take the least such jj. Before step jj, no pop touched CC, so CC was still visible, and CjC_j shares a vertex with CC, so Cj=CC_j = C. The cycles C1,…,Cj−1C_1, \ldots, C_{j-1} are disjoint from CC, so popping CC first does not change whether they are poppable. Hence C,C1,…,Cj−1,Cj+1,…,CkC, C_1, \ldots, C_{j-1}, C_{j+1}, \ldots, C_k is also a valid sequence that ends with no visible cycle, with the same set of colored cycles. After popping CC, the rest has k−1k - 1 pops, so by induction every sequence from that state has k−1k - 1 pops, the same set, and the same final tree. Each sequence starts with some poppable CC, so the claim holds for all sequences. □\square

Step 3: the law of the tree

The run stops with probability 1, so by Lemma 1, with probability 1 the stacks admit a finite popping sequence. Call the set C\mathcal{C} of colored cycles popped and the final tree aa the outcome. By Lemma 2 the outcome depends only on the stacks.

Fix a finite set C\mathcal{C} of colored cycles that occurs as the popped set for some stacks with positive probability, and fix a rooted spanning tree aa. For each vertex xx, let ℓx\ell_x be the number of cycles in C\mathcal{C} through xx. The outcome is (C,a)(\mathcal{C}, a) if and only if

  1. for each colored cycle in C\mathcal{C}, the stack entries at its positions are the arrows of the cycle, and
  2. for each x≠rx \ne r, the entry Sxℓx+1S_x^{\ell_x + 1} is a(x)a(x).

Only if is clear: after popping C\mathcal{C}, the top of SxS_x is the entry at level ℓx+1\ell_x + 1, and it is the arrow of the final tree. If: since C\mathcal{C} occurs for some stacks, its colored cycles can be popped in some order when the entries of condition 1 hold, because poppability depends only on these entries. After these pops, the visible graph is aa, which has no cycle. So this is a popping sequence that ends, and by Lemma 2 the outcome is (C,a)(\mathcal{C}, a).

The two conditions fix different stack entries, which are independent. Writing px(e)=ce/c(x)p_x(e) = c_e / c(x) for the probability of an arrow (with the factor 2 for a self-loop), we get

Pr⁡[outcome=(C,a)]=(∏C∈C∏(x,e)∈Cpx(e))⋅∏x≠rpx(a(x))=Ψ(C)⋅∏x≠rca(x)∏x≠rc(x).\Pr[\text{outcome} = (\mathcal{C}, a)] = \Big( \prod_{C \in \mathcal{C}} \prod_{(x, e) \in C} p_x(e) \Big) \cdot \prod_{x \ne r} p_x(a(x)) = \Psi(\mathcal{C}) \cdot \frac{\prod_{x \ne r} c_{a(x)}}{\prod_{x \ne r} c(x)}.

Tree arrows are never self-loops, so the factor 2 does not appear in the second product. The first factor depends only on C\mathcal{C}, and the set of possible C\mathcal{C} does not depend on aa, since condition 1 alone decides whether C\mathcal{C} can be popped. Summing over C\mathcal{C},

Pr⁡[arrows=a]=(∑CΨ(C))⋅1∏x≠rc(x)⋅∏x≠rca(x).\Pr[\text{arrows} = a] = \Big( \sum_{\mathcal{C}} \Psi(\mathcal{C}) \Big) \cdot \frac{1}{\prod_{x \ne r} c(x)} \cdot \prod_{x \ne r} c_{a(x)}.

The first two factors do not depend on aa, so Pr⁡[arrows=a]∝∏x≠rca(x)=c(t)\Pr[\text{arrows} = a] \propto \prod_{x \ne r} c_{a(x)} = c(t) for the spanning tree tt of aa. The probabilities sum to 1 over all spanning trees, so Pr⁡[T=t]=c(t)/Z\Pr[T = t] = c(t) / Z.

The order of the vertices in line L2 changes only the order of popping, so by Lemma 2 it does not change the outcome for fixed stacks, and the law is the same for every order.

Disconnected graphs

The implementation picks a root in each component. A walk never leaves its component, so the runs in different components use disjoint stacks and are independent, and each gives a tree of its component with the law above. The forest FF then has probability proportional to ∏e∈Fce\prod_{e \in F} c_e among the spanning forests with one tree in each component, and with all weights 1 it is uniform among them. ■\blacksquare

Back to Wilson's algorithm