munkres
v2.1.1
Published
A lightweight and efficient implementation of the Munkres (Hungarian) algorithm for optimal assignment in square and rectangular matrices.
Maintainers
Readme
Munkres
Optimally pair up two sets (workers to jobs, drivers to riders, bids to items) to minimize total cost.
Given a cost matrix where matrix[y][x] is the cost of pairing item y with item x, munkres returns the one-to-one assignment with the lowest possible total cost. It's a fast, dependency-free implementation of the Munkres (Hungarian) algorithm.
Reach for it whenever you have a table of pairing costs (or profits) and need the optimal matching rather than a greedy guess.
Features
- Flexible:
numberorbigintcosts; square (NxN) or rectangular (MxN) matrices; anyMatrixLikeinput (arrays, typed arrays, custom indexables). - Fast: O(M²N) time when M ≤ N (O(MN²) otherwise) and only O(M + N) extra memory. Benchmarks below.
- Typed & dependency-free: first-class TypeScript types, zero runtime dependencies, ships both ESM and CommonJS.
- Robust: force an assignment with
-Infinityor avoid one withInfinity; built-in helpers for building and transforming matrices.
Install
npm install munkres
yarn add munkres
pnpm add munkres
jsr add @munkres/munkresUsage
import { munkres } from "munkres";
// matrix[y][x] = cost of assigning worker y to job x
const costMatrix = [
[1, 2, 3],
[2, 4, 6],
[3, 6, 9],
];
const assignments = munkres(costMatrix);
// → [[0, 2], [1, 1], [2, 0]] (worker 0 → job 2, worker 1 → job 1, worker 2 → job 0)Each result is a [y, x] pair (row, then column). The result has min(rows, cols) pairs; if there are more workers than jobs (or vice versa), the unmatched ones are simply absent.
Maximizing instead of minimizing? Convert your profit matrix to a cost matrix first:
import { munkres, copyMatrix, invertMatrix } from "munkres";
const profitMatrix = [
[9, 8, 7],
[8, 6, 4],
[7, 4, 1],
];
const costMatrix = copyMatrix(profitMatrix);
invertMatrix(costMatrix); // flip profits into costs
const assignments = munkres(costMatrix);
// → [[0, 2], [1, 1], [2, 0]]API
munkres(costMatrix, options?)
Runs the algorithm and returns a set of optimal [y, x] assignment pairs. If several optimal assignments exist, one is returned.
costMatrix: aMatrixLike<number>orMatrixLike<bigint>wherecostMatrix[y][x]is the cost of assigning workeryto jobx. Costs are minimized, so use-Infinityto force an assignment (chosen whenever possible) andInfinityto avoid one (used only as a last resort, when no finite alternative exists).options.finite(boolean, defaultfalse): promise the matrix is all-finite and in-range, skipping input validation for a small speedup on large matrices. If the promise is broken, the result is undefined (it won't throw). SeeMunkresOptions.
Returns Pair<number>[], an array of [y, x] pairs, length min(rows, cols).
Throws
TypeError: anumbermatrix containsNaN. (UseInfinityto avoid an assignment instead.)RangeError: anumbermatrix's value range (max - min) exceedsNumber.MAX_VALUE / 2and could overflow. Scale the matrix down, or usebigint.
Precision: the
numberpath uses 64-bit floats. For integer costs that need an exact optimum (especially near or beyondNumber.MAX_SAFE_INTEGER), use abigintmatrix for arbitrary precision.
Types
Matrix<T>: a 2D matrix,T[][].MatrixLike<T>: a read-only 2D matrix accepting anyArrayLike(arrays, typed arrays, custom indexables).Pair<A, B = A>: a[A, B]tuple.MunkresOptions: the options object formunkres().
Helpers
Utilities for building and transforming cost matrices:
| Helper | Description |
| --- | --- |
| copyMatrix(matrix) | Copy a matrix. |
| createMatrix(workers, jobs, callbackFn) | Build a matrix from worker/job lists and a cost function. |
| genMatrix(numRows, numCols, callbackFn) | Build a matrix from dimensions and a callback. |
| getMatrixMax(matrix) / getMatrixMin(matrix) | Find the max / min value. |
| invertMatrix(matrix, bigVal?) | Invert values (max → min); converts between minimizing and maximizing. Uses the matrix max if bigVal is omitted. |
| negateMatrix(matrix) | Negate all values; another way to swap minimizing and maximizing. |
Benchmarks
Performance is tracked automatically on every release and every commit to main:
- Release-over-release trend →: how performance changes across published versions.
- Per-commit history →: fine-grained regression tracking.
- Run it in your browser →: try it on your own inputs.
- Run locally →: See the contributing guide.
As a ballpark (Apple M2, v2.1.1):
| Matrix Size | number | bigint |
| --- | --- | --- |
| 64x64 | ~0.07ms | ~0.17ms |
| 256x256 | ~1.2ms | ~3.7ms |
| 1024x1024 | ~26ms | ~110ms |
| 4096x4096 | ~0.73s | ~3.8s |
Contributing
Contributions are welcome. See the contributing guide for local setup, tests, and the style guide.
- Questions / discussion: GitHub Discussions
- Bugs: Issue tracker
- Feature requests: open an issue describing the feature and its benefit.
