Algorithm Search⌘K

Proofs: Hungarian algorithm

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

The Hungarian algorithm returns a least-cost assignment full

This proof shows: correctness, termination.

Let CC be an n×mn \times m matrix with 1≤n≤m1 \le n \le m and finite entries. (The implementation replaces a missing entry by a large finite cost first; the last part of this proof covers that step.) Rows are 1…n1 \ldots n, columns are 1…m1 \ldots m, and column 0 is a dummy. For a row kk and a column j≥1j \ge 1, the reduced cost is cˉkj=ckj−uk−vj\bar c_{kj} = c_{kj} - u_k - v_j. A pair kjkj is tight if cˉkj=0\bar c_{kj} = 0. Column j≥1j \ge 1 is matched if p[j]≠0p[j] \ne 0, and free otherwise.

Round invariant (R). Before the round of row ii (line L3):

  1. pp restricted to the columns 1…m1 \ldots m is injective on its nonzero values, and its nonzero values are exactly the rows 1…i−11 \ldots i-1;
  2. cˉkj≥0\bar c_{kj} \ge 0 for each row k<ik < i and each column j≥1j \ge 1;
  3. vj≤0v_j \le 0 for each column j≥1j \ge 1, and vj=0v_j = 0 for each free column;
  4. each matched pair (p[j],j)(p[j], j) is tight;
  5. uk=0u_k = 0 for each row k≥ik \ge i.

Line L1 makes (R) true for i=1i = 1: there are no matched columns and no rows k<1k < 1.

Pass invariant (P). Fix a round ii. In this round, call a column used when its mark is true, and call the rows p[j]p[j] of the used columns jj the tree rows; p[0]=ip[0] = i, so row ii is a tree row as soon as column 0 is used. At the end of each pass (after line L12):

  1. every used column other than 0 is matched, and the tree rows are distinct;
  2. cˉkj≥0\bar c_{kj} \ge 0 for each row k≤ik \le i and each column j≥1j \ge 1;
  3. for each column j≥1j \ge 1 that is not used, minv[j]=min⁡{cˉkj:k a tree row}\text{minv}[j] = \min \{ \bar c_{kj} : k \text{ a tree row} \}, and way[j]\text{way}[j] is a used column with cˉp[way[j]],j=minv[j]\bar c_{p[\text{way}[j]], j} = \text{minv}[j];
  4. for each used column j≥1j \ge 1, the pairs (p[j],j)(p[j], j) and (p[way[j]],j)(p[\text{way}[j]], j) are tight, and way[j]\text{way}[j] was used before jj;
  5. (R3) and (R4) hold, and the column j1j_1 chosen at line L9 satisfies minv[j1]=0\text{minv}[j_1] = 0.

Proof that (P) holds after each pass. Consider a pass. At line L5, column j0j_0 becomes used and its row i0=p[j0]i_0 = p[j_0] becomes a tree row. In the first pass, j0=0j_0 = 0 and i0=ii_0 = i. In a later pass, j0j_0 is the column j1j_1 of the pass before, which is matched, since otherwise line L14 would have ended the loop; so i0i_0 is a row k<ik < i that is not yet a tree row, because pp is injective. This gives (P1).

Lines L6 to L8 lower minv[j]\text{minv}[j] to cˉi0j\bar c_{i_0 j} when that is smaller, and record way[j]=j0\text{way}[j] = j_0. So, before the shift, minv[j]\text{minv}[j] is the least reduced cost from a tree row to jj, for each column jj that is not used, and way[j]\text{way}[j] names a column whose row reaches it. Line L9 sets δ=min⁡{minv[j]:j not used}\delta = \min \{ \text{minv}[j] : j \text{ not used} \} and j1j_1 to a column that reaches it. There is at least one column that is not used, because the used columns other than 0 are matched and there are at most i−1<mi - 1 < m matched columns. So δ\delta is finite.

Lines L10 to L12 add δ\delta to uku_k for each tree row kk and subtract δ\delta from vjv_j for each used column jj. Look at the effect on cˉkj\bar c_{kj} for a row k≤ik \le i and a column j≥1j \ge 1:

  • kk a tree row and jj used: cˉkj\bar c_{kj} does not change.
  • kk a tree row and jj not used: cˉkj\bar c_{kj} drops by δ\delta. Before the shift cˉkj≥minv[j]≥δ\bar c_{kj} \ge \text{minv}[j] \ge \delta, so after it cˉkj≥0\bar c_{kj} \ge 0. Line L12 lowers minv[j]\text{minv}[j] by δ\delta too, so (P3) stays true, and minv[j1]=0\text{minv}[j_1] = 0.
  • kk not a tree row and jj used: cˉkj\bar c_{kj} grows by δ\delta. In the first pass no column j≥1j \ge 1 is used, so this case does not occur. In a later pass, δ≥0\delta \ge 0, because by (P2) and (P3) of the pass before, every minv[j]\text{minv}[j] is at least 0 before line L6 and line L6 only takes minima with reduced costs that are at least 0 by (P2). So cˉkj\bar c_{kj} stays at least 0.
  • kk not a tree row and jj not used: cˉkj\bar c_{kj} does not change.

Before the first pass, (R2) gives cˉkj≥0\bar c_{kj} \ge 0 for k<ik < i. Row ii is a tree row from the first pass on, so the second case covers it. This proves (P2).

(R3): only used columns change vjv_j. A used column j≥1j \ge 1 was used in a pass after the first, where δ≥0\delta \ge 0, so vjv_j only goes down, and vj≤0v_j \le 0 stays true. A free column is never used, by (P1), so its vjv_j stays 0. (R4): a matched pair (p[j],j)(p[j], j) has both ends in the tree or both outside, because the tree rows are exactly the rows of used columns, and row ii is not matched. So its reduced cost does not change, and it stays tight.

(P4): when a column jj becomes used, it was j1j_1 in the pass before, so the pair (p[way[j]],j)(p[\text{way}[j]], j) became tight at that time, and (p[j],j)(p[j], j) is tight by (R4). Later shifts do not change pairs with both ends in the tree, and line L8 does not change way[j]\text{way}[j] for a used column. □\square

Each round ends. Each pass makes one more column used. By (P1), the used columns other than 0 are matched, and at most i−1i - 1 columns are matched. So after at most ii passes, the column j1j_1 of line L13 is free and line L14 ends the loop.

The augmentation keeps (R). When the loop ends, j0j_0 is a free column with minv[j0]=0\text{minv}[j_0] = 0, and (p[way[j0]],j0)(p[\text{way}[j_0]], j_0) is tight by (P3). Line L15 follows the chain j0,way[j0],way[way[j0]],…j_0, \text{way}[j_0], \text{way}[\text{way}[j_0]], \ldots, which reaches 0, because each way\text{way} value is a column used strictly before (P4), and sets p[j]←p[way[j]]p[j] \leftarrow p[\text{way}[j]] for each column jj on the chain other than 0. So each row on the chain moves from its column way[j]\text{way}[j] to the next column jj; row i=p[0]i = p[0] moves to the first column after 0; and the free column j0j_0 gets a row. The new pairs are the pairs (p[way[j]],j)(p[\text{way}[j]], j), which are tight by (P3) and (P4). After the round, the matched rows are 1…i1 \ldots i, pp is still injective, and (R2) to (R4) hold for i+1i + 1 by (P2) and (P5). Row i+1i + 1 was not a tree row, so ui+1=0u_{i+1} = 0. So (R) holds before the round of row i+1i + 1.

Theorem. HUNGARIAN stops, and the pairs of line L16 form an assignment of all rows to distinct columns of least total cost.

Proof. Each of the nn rounds ends, and by (R) after the last round, every row has its own column. Let σ\sigma be the result and τ\tau any assignment of rows to distinct columns. By (R2), ckτ(k)≥uk+vτ(k)c_{k\tau(k)} \ge u_k + v_{\tau(k)} for each kk, so

∑kckτ(k)≥∑kuk+∑kvτ(k)≥∑kuk+∑j=1mvj,\sum_k c_{k\tau(k)} \ge \sum_k u_k + \sum_k v_{\tau(k)} \ge \sum_k u_k + \sum_{j=1}^{m} v_j,

where the second step uses vj≤0v_j \le 0 for the columns that τ\tau does not use (R3). For σ\sigma both steps are equalities: each pair (k,σ(k))(k, \sigma(k)) is tight by (R4), and the columns that σ\sigma does not use are free, with vj=0v_j = 0 by (R3). So ∑kckσ(k)=∑kuk+∑jvj≤∑kckτ(k)\sum_k c_{k\sigma(k)} = \sum_k u_k + \sum_j v_j \le \sum_k c_{k\tau(k)}. ■\blacksquare

Missing entries. Let FF be the set of finite entries, with least value aa and largest value bb, and let B>n(b−a)+∣a∣B > n(b - a) + |a| replace each missing entry. An assignment that uses only finite entries costs at most nbnb. An assignment that uses at least one replaced entry costs at least B+(n−1)a>n(b−a)+a+(n−1)a=nbB + (n - 1)a > n(b - a) + a + (n - 1)a = nb. So if some assignment avoids the missing entries, every optimal assignment of the new matrix avoids them too, and it is optimal for the old matrix. If no assignment avoids them, the optimal assignment of the new matrix uses one, and the implementation reports that there is none.

Back to Hungarian algorithm