Algorithm Search⌘K

Proofs: Brandes' algorithm

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

Brandes' algorithm computes betweenness centrality full

This proof shows: correctness, termination.

Let G=(V,E)G = (V, E) be a directed graph; an undirected graph is the directed graph with both arcs (u,v)(u, v) and (v,u)(v, u) for each edge. Each arc has a length ℓ(u,v)>0\ell(u, v) > 0, and ℓ≡1\ell \equiv 1 in the form without weights. Fix a source ss. Let d(w)=dG(s,w)d(w) = d_G(s, w), with d(w)=∞d(w) = \infty if ww is not reachable, and let σsw\sigma_{sw} be the number of shortest paths from ss to ww, with σss=1\sigma_{ss} = 1 and σsw=0\sigma_{sw} = 0 for unreachable ww. The predecessor set is Ps(w)={v:(v,w)∈E, d(v)+ℓ(v,w)=d(w)<∞}P_s(w) = \{v : (v, w) \in E,\ d(v) + \ell(v, w) = d(w) < \infty\}.

Termination. Line L2 runs nn times. In one run, each vertex enters the queue at most once (line L8 enqueues ww only when d[w]=∞d[w] = \infty and makes it finite), so lines L5 to L9 run at most nn times and scan finite lists. Line L11 pops exactly the vertices pushed at line L6. So the algorithm stops. The Dijkstra form settles each vertex once and stops in the same way.

Lemma 1 (Bellman criterion). A vertex vv lies on a shortest path from ss to tt if and only if d(v)+dG(v,t)=d(t)<∞d(v) + d_G(v, t) = d(t) < \infty. Every shortest path to w≠sw \ne s ends with an arc (v,w)(v, w) with v∈Ps(w)v \in P_s(w), and its part up to vv is a shortest path to vv. Hence σsw=∑v∈Ps(w)σsv\sigma_{sw} = \sum_{v \in P_s(w)} \sigma_{sv} for w≠sw \ne s.

Proof. A subpath of a shortest path is a shortest path, since a shorter subpath could replace it. So the first statement holds, and a shortest path s…vws \ldots v w has d(v)+ℓ(v,w)=d(w)d(v) + \ell(v, w) = d(w), so v∈Ps(w)v \in P_s(w). Conversely, for v∈Ps(w)v \in P_s(w), each shortest path to vv followed by (v,w)(v, w) has length d(w)d(w). This is a bijection between the shortest paths to ww and the pairs (a predecessor vv, a shortest path to vv), which gives the sum. □\square

Lemma 2 (the search). After lines L4 to L9 (or their Dijkstra form) for the source ss: d[w]=d(w)d[w] = d(w), σ[w]=σsw\sigma[w] = \sigma_{sw} and P[w]=Ps(w)P[w] = P_s(w) for every ww, and SS holds the reachable vertices with dd non-decreasing from the bottom to the top.

Proof. Without weights, lines L4 to L8 are the breadth-first search, which sets d[w]=d(w)d[w] = d(w) and dequeues the vertices in non-decreasing order of dd; line L6 pushes them in that order. Line L9 runs once for each arc (v,w)(v, w) out of a reachable vv, after d[w]d[w] is final (either ww was discovered before, or line L8 just set it), and it appends vv to P[w]P[w] exactly when d(w)=d(v)+1d(w) = d(v) + 1, that is when v∈Ps(w)v \in P_s(w). So P[w]=Ps(w)P[w] = P_s(w). When vv is dequeued, all its predecessors have smaller dd and were dequeued before, so all their contributions to σ[v]\sigma[v] were made, and by Lemma 1 and induction on dd, σ[v]=σsv\sigma[v] = \sigma_{sv} when vv passes it on. The final σ[w]\sigma[w] is the sum over all v∈Ps(w)v \in P_s(w), which is σsw\sigma_{sw} by Lemma 1.

With positive lengths, Dijkstra's algorithm settles the vertices in non-decreasing order of dd and with d[v]=d(v)d[v] = d(v) at settling. Every v∈Ps(w)v \in P_s(w) has d(v)<d(w)d(v) < d(w), since ℓ>0\ell > 0, so it is settled before ww, and when it scans (v,w)(v, w) the test either makes vv the first predecessor found with the current best value or adds it to a list of equal value. Values found later that are smaller reset the list and the count; at the time ww is settled, d[w]=d(w)d[w] = d(w), and the list holds exactly the settled vv with d(v)+ℓ(v,w)=d(w)d(v) + \ell(v, w) = d(w), which are all of Ps(w)P_s(w), and by induction σ[w]=∑v∈Ps(w)σsv=σsw\sigma[w] = \sum_{v \in P_s(w)} \sigma_{sv} = \sigma_{sw}. □\square

Lemma 3 (the dependency recursion). For each vv,

δs∙(v)=∑w : v∈Ps(w)σsvσsw(1+δs∙(w)),\delta_{s\bullet}(v) = \sum_{w \,:\, v \in P_s(w)} \frac{\sigma_{sv}}{\sigma_{sw}} \bigl(1 + \delta_{s\bullet}(w)\bigr),

where δs∙(v)=∑t≠s,vσst(v)/σst\delta_{s\bullet}(v) = \sum_{t \ne s, v} \sigma_{st}(v) / \sigma_{st}, with the sum over reachable tt.

Proof. Fix a reachable t≠vt \ne v with σst(v)>0\sigma_{st}(v) > 0. Each shortest path from ss to tt through vv leaves vv along exactly one arc (v,w)(v, w), and by Lemma 1, v∈Ps(w)v \in P_s(w) and ww is on the path. So σst(v)=∑w:v∈Ps(w)σst(v,w)\sigma_{st}(v) = \sum_{w : v \in P_s(w)} \sigma_{st}(v, w), where σst(v,w)\sigma_{st}(v, w) counts the shortest ss-tt paths that use the arc (v,w)(v, w).

Count σst(v,w)\sigma_{st}(v, w). If t=wt = w, it is σsv\sigma_{sv}: a shortest path to vv followed by the arc. If t≠wt \ne w, a path that uses (v,w)(v, w) is a shortest path to vv, the arc, and a shortest path from ww to tt, so σst(v,w)=σsv⋅σwt\sigma_{st}(v, w) = \sigma_{sv} \cdot \sigma_{wt}. The number of shortest ss-tt paths through ww is σst(w)=σswσwt\sigma_{st}(w) = \sigma_{sw} \sigma_{wt}, so σst(v,w)=σsvσswσst(w)\sigma_{st}(v, w) = \frac{\sigma_{sv}}{\sigma_{sw}} \sigma_{st}(w). Hence

σst(v,w)σst=σsvσsw⋅{1t=w,σst(w)/σstt≠w.\frac{\sigma_{st}(v, w)}{\sigma_{st}} = \frac{\sigma_{sv}}{\sigma_{sw}} \cdot \begin{cases} 1 & t = w, \\ \sigma_{st}(w) / \sigma_{st} & t \ne w. \end{cases}

Sum over tt and over ww, and exchange the two sums. For a fixed ww, the term t=wt = w gives σsvσsw\frac{\sigma_{sv}}{\sigma_{sw}}, and the terms t≠wt \ne w give σsvσswδs∙(w)\frac{\sigma_{sv}}{\sigma_{sw}} \delta_{s\bullet}(w). Pairs (t,w)(t, w) with σst(v,w)=0\sigma_{st}(v, w) = 0 contribute 0 on both sides, since then σst(w)=0\sigma_{st}(w) = 0 or tt is not reachable. This gives the formula. □\square

Lemma 4 (the accumulation). After lines L10 to L14 for the source ss, δ[v]=δs∙(v)\delta[v] = \delta_{s\bullet}(v) for every reachable vv, and the values added to CBC_B are δs∙(w)\delta_{s\bullet}(w) for w≠sw \ne s.

Proof. If v∈Ps(w)v \in P_s(w), then d(v)<d(w)d(v) < d(w), so vv is below ww in SS by Lemma 2 and is popped after ww. When ww is popped, every xx with w∈Ps(x)w \in P_s(x) is further from ss and was popped before, and each such pop added σswσsx(1+δ[x])\frac{\sigma_{sw}}{\sigma_{sx}}(1 + \delta[x]) to δ[w]\delta[w] at line L13. Line L13 adds to δ[w]\delta[w] only at these pops. By induction on the order of pops, each δ[x]\delta[x] used was already final and equal to δs∙(x)\delta_{s\bullet}(x), so by Lemma 3, δ[w]=δs∙(w)\delta[w] = \delta_{s\bullet}(w) when ww is popped. It is not changed later, since later pops only add to their predecessors, which are closer to ss. Line L14 then adds it for w≠sw \ne s. Unreachable vertices are never pushed and get no addition, which is right since δs∙(v)=0\delta_{s\bullet}(v) = 0 for them. □\square

Theorem. BRANDES(G)(G) returns CB(v)=∑s≠v≠tσst(v)/σstC_B(v) = \sum_{s \ne v \ne t} \sigma_{st}(v) / \sigma_{st} for every vv in the directed case, and half of it in the undirected case.

Proof. By Lemma 4, after the loop of line L2, CB[v]=∑s≠vδs∙(v)=∑s≠v∑t≠s,vσst(v)/σstC_B[v] = \sum_{s \ne v} \delta_{s\bullet}(v) = \sum_{s \ne v} \sum_{t \ne s, v} \sigma_{st}(v) / \sigma_{st}, which is the sum over ordered pairs. For an undirected graph, the pairs (s,t)(s, t) and (t,s)(t, s) have the same shortest paths reversed and give equal terms, so line L15 turns the sum into one over unordered pairs. ■\blacksquare

Back to Brandes' algorithm