Suppose every worker can do every job, every pairing has a cost, and we need the globally cheapest one-to-one assignment. The Hungarian method is the classic teaching algorithm, but high-performance software often uses a different shortest-augmenting-path family. Jonker–Volgenant is one of its best-known representatives and remains practically important decades after its 1987 publication.
This Learning Hall article develops the algorithm from the linear assignment problem through primal assignments, dual potentials, reduced costs, alternating trees and shortest augmenting paths. It then explains the original initialization ideas, rectangular adaptations, modern SciPy practice, testing and the professional decision between Hungarian, Auction and Jonker–Volgenant approaches.
Quick Read
- The linear assignment problem chooses at most one entry from each row and column to minimize total cost.
- A feasible complete assignment is a perfect matching in a weighted bipartite graph.
- Dual variables attach potentials to rows and columns.
- Reduced cost measures how much an unmatched edge would cost after accounting for those potentials.
- Edges with zero reduced cost are compatible with complementary-slackness optimality.
- If a row is free, an augmenting path can connect it to a free column while alternating unmatched and matched edges.
- Jonker–Volgenant uses a shortest-augmenting-path strategy with carefully engineered initialization and scans.
- The original work addresses both dense and sparse linear assignment.
- Modern SciPy documents its dense linear_sum_assignment solver as a modified Jonker–Volgenant algorithm with no initialization.
- The professional lesson is that two algorithms with the same broad polynomial complexity can behave very differently because of initialization, scan order, memory layout and rectangular handling.
1. Beginner Level: The Cost Matrix
Let rows represent workers and columns represent jobs. Entry C[i,j] is the cost of assigning worker i to job j.
job0 job1 job2
worker0 4 1 3
worker1 2 0 5
worker2 3 2 2
We want one column per row and one row per column so the selected costs sum to a minimum. For this matrix, choosing (worker0,job1), (worker1,job0), (worker2,job2) gives cost 1+2+2=5.
2. Assignment as Bipartite Matching
Build a bipartite graph with row vertices on one side and column vertices on the other. Every allowable assignment is an edge weighted by its cost. A complete solution is a minimum-weight perfect matching when the matrix is square and all assignments are allowed.
For the classical matrix-reduction view, see our Hungarian Algorithm article. The present page owns the Jonker–Volgenant shortest-augmenting-path implementation family.
3. Primal and Dual Views
The primal problem chooses assignment edges. The dual assigns a row potential u[i] and a column potential v[j] subject to:
u[i] + v[j] ≤ C[i,j]
The reduced cost is:
r[i,j] = C[i,j] - u[i] - v[j]
Dual feasibility means reduced costs are nonnegative. In an optimal assignment, matched edges can be maintained at zero reduced cost. This is the complementary-slackness bridge between local arithmetic and global optimality.
4. Why an Augmenting Path?
Suppose most rows are already assigned but row r is free. We could assign r directly to a free column if one suitable edge exists. More often, the cheapest route goes through columns already occupied by other rows.
free row
→ unmatched edge to column
→ matched edge back to its row
→ unmatched edge to another column
→ ...
→ free column
Flip matched/unmatched status along this alternating path. The matching grows by one row without violating one-to-one assignment.
5. The Path Has a Cost
Under the current dual variables, unmatched edges have nonnegative reduced costs while matched zero-reduced-cost edges can be traversed back without increasing the path metric in the primal-dual search. Finding the best augmentation becomes a shortest-path problem in a specially structured alternating graph.
This is why Jonker and Volgenant describe their method as a shortest augmenting path algorithm rather than primarily as matrix row/column reduction.
6. Dijkstra-Like Search Without Building a Huge Graph
A dense implementation does not explicitly construct a general residual graph. It stores tentative distances to columns, tracks predecessor rows, and repeatedly selects the unscanned column with smallest tentative reduced-cost distance.
dist[j] = best reduced-cost path from free row to column j
pred[j] = row that currently gives dist[j]
If the chosen column is free, the augmenting path has been found. If it is assigned, follow its matched row and relax all outgoing row-to-column alternatives. This is Dijkstra’s logic specialized to the assignment structure.
7. Dual Updates Keep Reduced Costs Valid
When the shortest-path scan advances by a distance delta, adjust row and column potentials so the newly reached edges become tight while all reduced costs remain nonnegative. The exact bookkeeping differs by implementation, but the invariant is stable:
- dual feasibility is preserved;
- already selected shortest-path relationships stay valid;
- the final augmenting path consists of tight edges after the update;
- matched edges remain compatible with complementary slackness.
8. Augment by Reversing the Chain
Once a free column is reached, use predecessor information to reconstruct the alternating path backward. Reassign each column to the row that preceded it until the originally free row becomes assigned.
j = free_column
while true:
i = predecessor_row[j]
old_j = assigned_column[i]
assign i → j
if i == starting_free_row:
break
j = old_j
The path reconstruction is simple only because the shortest-path phase carefully stored one predecessor for each reached column.
9. What Jonker–Volgenant Added
The 1987 Jonker–Volgenant work is not merely “run Dijkstra repeatedly.” It combines a shortest augmenting-path core with initialization and reduction routines engineered to produce a strong partial assignment and useful dual variables before the expensive augmentation stage.
- column reduction creates initial tight edges;
- reduction transfer and augmenting-row-reduction phases improve the partial assignment and potentials;
- the shortest augmenting-path phase completes the remaining unmatched rows;
- dense and sparse cases use different data-management considerations.
Those details matter because solving several easy assignments early can reduce the number and difficulty of full shortest-path searches.
10. Modern SciPy Uses a Modified Variant
Current SciPy documentation states that scipy.optimize.linear_sum_assignment uses a modified Jonker–Volgenant algorithm with no initialization, following implementation work on two-dimensional rectangular assignment. That is a useful warning against treating “JV” as one immutable code listing.
A production library may retain the shortest-augmenting-path structure while changing initialization, rectangular handling, indexing and memory layout. When comparing performance, compare actual implementations, not only algorithm family names.
11. Rectangular Assignment
If there are more workers than jobs, or more jobs than workers, not every vertex on the larger side can be matched. A rectangular LAP solver must define the required cardinality and adapt its free-row/free-column handling accordingly.
Padding with dummy rows or columns is mathematically possible but may waste work or complicate numerical scaling. Modern implementations often solve the rectangular form directly.
12. Safe High-Level Pseudocode
JV_ASSIGN(C):
initialize assignment and dual variables
optionally run reduction / fast augmentation phases
for each remaining free row r:
initialize column distances from r
initialize predecessor information
while no free column has been finalized:
j = unscanned column with minimum tentative distance
apply required dual-distance update
if j is free:
terminal = j
break
i = row currently assigned to j
relax candidate columns through row i
reverse predecessor chain from terminal
augment matching by one
return assignment, total_cost
This skeleton explains the algorithmic job boundaries. A production implementation should follow the exact potential-update formulas of a trusted reference, because one sign error in reduced-cost arithmetic can silently break optimality.
13. Complexity
For dense n×n assignment, shortest-augmenting-path methods have cubic-order worst-case work in standard implementations. Jonker–Volgenant was designed to be exceptionally efficient in practical dense and sparse cases through careful reductions and scan organization.
Do not reduce performance evaluation to the O(n³) label. Matrix density, rectangular shape, number of initially free rows, cost distribution, cache layout and implementation language can dominate observed runtime.
14. Jonker–Volgenant vs Hungarian
- Hungarian: excellent pedagogical route to duality, zero reduced costs and augmenting structure.
- Jonker–Volgenant: shortest-path-centered implementation family designed for high practical efficiency.
- Both: are exact algorithms for linear assignment and can be understood through primal-dual invariants.
The right learning order is often Hungarian first, then JV. The Hungarian method makes the dual geometry visible; JV shows how that geometry is engineered into a fast solver.
15. Jonker–Volgenant vs Auction
The Auction Algorithm interprets assignment as bidders competing through prices and ε-complementary slackness. It can be attractive for parallel and distributed execution. JV is more naturally a centralized shortest-augmenting-path solver.
Neither dominates every workload. Exact tolerance, parallel hardware, sparse structure and repeated-solve patterns all affect the engineering decision.
16. Numerical and Data-Type Issues
- Integer costs can overflow when potentials and path distances are added or subtracted.
- Floating costs need careful handling of infinities, NaNs and near-equality.
- Forbidden assignments should use a representation that cannot accidentally become attractive after arithmetic.
- Subtracting very large nearly equal floating potentials can lose precision.
- If maximizing rather than minimizing, transform or support the objective explicitly instead of relying on an unsafe negation for extreme integer values.
17. Failure Modes
- Confusing shortest original-cost edges with shortest reduced-cost augmenting paths. Potentials are part of the search state.
- Breaking dual feasibility during updates. Negative reduced costs invalidate the Dijkstra-like reasoning.
- Forgetting matched-edge direction in the alternating graph. Path reconstruction depends on reversing assignments correctly.
- Reusing stale predecessor or distance arrays across augmentations. Each free-row search needs correctly reset state.
- Assuming the original JV initialization is required by every JV-family implementation. SciPy documents a no-initialization modified variant.
- Treating rectangular problems as square without defining dummy costs carefully.
- Benchmarking only random dense matrices. Structured costs can behave very differently.
18. Professional Testing Strategy
- Brute-force every assignment for very small square matrices and compare optimum cost.
- Compare with SciPy or another trusted LAP solver on random rectangular matrices.
- Test duplicate optimal assignments and verify cost, not one specific permutation.
- Use negative, zero and large positive costs if the implementation contract allows them.
- Test all-equal matrices, diagonal-dominant matrices and adversarial near-ties.
- After each augmentation, assert every assigned row and column has degree one.
- At termination, verify dual feasibility and complementary slackness on matched edges.
- Measure scans, augmentations and memory traffic separately from wall-clock time.
19. How to Learn It Efficiently
Start with a 3×3 cost matrix and give the learner the dual potentials. Ask them to compute the reduced-cost matrix and mark zero edges. Next provide a partial assignment and ask for one augmenting path. Only then introduce tentative distances and the Dijkstra-like scan.
Use subgoal labels: maintain duals → find shortest augmenting path → update potentials → reverse assignment chain → verify complementary slackness. Worked examples, tracing and faded scaffolds are more appropriate than beginning with a highly optimized LAPJV implementation full of index arrays.
20. Professional Applications
- Multi-object tracking and detection-to-track association.
- Robotics and sensor/data association.
- Scheduling and workforce assignment.
- Matching predicted and observed structures in computer vision.
- Evaluation metrics that require optimal bipartite matching.
- Resource allocation with one-to-one constraints.
- Subproblems inside ranked-assignment methods such as Murty’s algorithm.
Our Murty’s Algorithm article is a natural next step: Murty repeatedly solves assignment subproblems to enumerate multiple best solutions.
21. Practice Problems
- Solve a 3×3 assignment by brute force, then by a primal-dual method.
- Given u and v potentials, calculate every reduced cost and test dual feasibility.
- Trace one shortest augmenting-path search from a free row to a free column.
- Reverse the alternating path and update the assignment arrays by hand.
- Create a rectangular 3×5 example and define the exact matching cardinality required.
- Compare SciPy linear_sum_assignment with a simple Hungarian implementation on increasing matrix sizes.
- Use the solver inside one iteration of Murty’s k-best assignment algorithm and identify which data can be reused safely.
22. Sources and Further Reading
- R. Jonker and A. Volgenant, A Shortest Augmenting Path Algorithm for Dense and Sparse Linear Assignment Problems, Computing, 1987.
- SciPy linear_sum_assignment documentation — modified Jonker–Volgenant algorithm and rectangular assignment.
- SciPy optimization tutorial — linear sum assignment example.
- D. F. Crouse, On Implementing 2D Rectangular Assignment Algorithms, IEEE Transactions on Aerospace and Electronic Systems, 2016.
- Muldner, Jennings and Chiarelli, A Review of Worked Examples in Programming Activities, ACM TOCE, 2023.
Final idea: Jonker–Volgenant is a masterclass in turning optimization theory into an engineered search. Dual variables do not merely certify the final answer; they reshape costs so a shortest-path routine can discover the next useful augmentation efficiently. The algorithm succeeds by keeping three stories consistent at once: the current assignment, the current prices, and the shortest route to repair what remains unmatched.
