https://github.com/havelessbemore/munkres
A lightweight and efficient implementation of the Munkres (Hungarian) algorithm for optimal assignment.
https://github.com/havelessbemore/munkres
assignment-problem combinatorial-optimization hungarian-algorithm munkres-algorithm optimization
Last synced: 12 days ago
JSON representation
A lightweight and efficient implementation of the Munkres (Hungarian) algorithm for optimal assignment.
- Host: GitHub
- URL: https://github.com/havelessbemore/munkres
- Owner: havelessbemore
- License: mit
- Created: 2024-03-27T01:25:50.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-14T10:44:46.000Z (over 1 year ago)
- Last Synced: 2025-10-10T23:53:04.520Z (5 months ago)
- Topics: assignment-problem, combinatorial-optimization, hungarian-algorithm, munkres-algorithm, optimization
- Language: TypeScript
- Homepage:
- Size: 1.64 MB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
- Authors: AUTHORS
Awesome Lists containing this project
README
# Munkres
A lightweight and efficient implementation of the [Munkres (Hungarian) algorithm](https://en.wikipedia.org/wiki/Hungarian_algorithm) for optimal assignment.
[](https://www.npmjs.com/package/munkres)
[](https://jsr.io/@munkres/munkres)
[](https://github.com/havelessbemore/munkres/graphs/commit-activity)
[](https://github.com/havelessbemore/munkres/blob/master/LICENSE)
[](https://codecov.io/gh/havelessbemore/munkres)

## Features
1. Flexible
- Use `number` or `bigint` matrices.
- Use square (_NxN_) or rectangular (_MxN_) matrices.
- Works with any [MatrixLike](src/types/matrixLike.ts) input. Use arrays, typed arrays, custom objects, etc.
1. Fast ([benchmarks](#results))
- _O(M2N)_ when _M <= N_
- _O(MN2)_ when _M > N_
1. Efficient
- _O(M + N)_ memory
1. Robust
- Supports `-Infinity` and `Infinity` values.
- [Helper methods](#helpers) provided for creating and modifying matrices.
## Getting Started
### Install
NPM:
```bash
npm install munkres
```
Yarn:
```bash
yarn add munkres
```
JSR:
```bash
jsr add @munkres/munkres
```
## Usage
With a cost matrix:
```javascript
import munkres from "munkres";
// Create a cost matrix. Cell [y, x] is the cost
// of assigning the y-th worker to the x-th job.
const costMatrix = [
[1, 2, 3],
[2, 4, 6],
[3, 6, 9],
];
// Find a set of optimal assignments pairs (y, x).
const assignments = munkres(costMatrix);
console.log(assignments);
// Output: [[0, 2], [1, 1], [2, 0]]
```
With a profit matrix:
```javascript
import { munkres, copyMatrix, invertMatrix } from "munkres";
// Create a profit matrix. Cell [y, x] is the
// profit of assigning the y-th worker to the x-th job.
const profitMatrix = [
[9, 8, 7],
[8, 6, 4],
[7, 4, 1],
];
// Covert the profit matrix into a cost matrix.
const costMatrix = copyMatrix(profitMatrix);
invertMatrix(costMatrix);
// Find a set of optimal assignments pairs (y, x).
const assignments = munkres(costMatrix);
console.log(assignments);
// Output: [[0, 2], [1, 1], [2, 0]]
```
## API
- `munkres(costMatrix)`
Executes the Munkres algorithm on the given cost matrix and returns a set of optimal assignment pairs. Even if there are multiple optimal assignment sets, only one is returned.
### Types
- [`Matrix`](src/types/matrix.ts): A generic 2D matrix (i.e. `T[][]`).
- [`MatrixLike`](src/types/matrixLike.ts): A generic read-only 2D matrix.
- Can be made from any `ArrayLike` objects (i.e. any indexable object with a numeric `length` property). This
allows for more flexibility, such as matrices made with typed arrays or objects.
- [`Pair`](src/types/pair.ts): A generic pair (i.e. `[A, B]`).
### Helpers
1. `copyMatrix(matrix)`: Creates a copy of the given matrix.
1. `createMatrix(workers, jobs, callbackFn)`: Generates a matrix based on the given workers, jobs, and callback function.
1. `genMatrix(numRows, numCols, callbackFn)`: Generates a matrix based on the given dimensions and a callback function.
1. `getMatrixMax(matrix)`: Finds the maximum value in a given matrix.
1. `getMatrixMin(matrix)`: Finds the minimum value in a given matrix.
1. `invertMatrix(matrix, bigVal?)`: Inverts the values in the given matrix. Useful for converting between minimizing and maximizing problems. If `bigVal` is not given, the matrix's max value is used instead.
1. `negateMatrix(matrix)`: Negates all values in the given matrix. Useful for converting between minimizing and maximizing problems.
## Community and Support
Contributions are welcome!
- **Questions / Dicussions**: Please contact us via [GitHub discussions](https://github.com/havelessbemore/munkres/discussions).
- **Bug Reports**: Please use the [GitHub issue tracker](https://github.com/havelessbemore/munkres/issues) to report any bugs. Include a detailed description and any relevant code snippets or logs.
- **Feature Requests**: Please submit feature requests as issues, clearly describing the feature and its potential benefits.
- **Pull Requests**: Please ensure your code adheres to the existing style of the project and include any necessary tests and documentation.
For more information, check out the [contributor's guide](https://github.com/havelessbemore/munkres/CONTRIBUTING.md).
## Build
1. Clone the project from github
```bash
git clone git@github.com:havelessbemore/munkres.git
cd munkres
```
2. Install dependencies
```bash
npm install
```
3. Build the project
```bash
npm run build
```
This will output ECMAScript (`.mjs`) and CommonJS (`.js`) modules in the `dist/` directory.
## Format
To run the code linter:
```bash
npm run lint
```
To automatically fix linting issues, run:
```bash
npm run format
```
## Test
To run tests:
```bash
npm test
```
To run tests with a coverage report:
```bash
npm run test:coverage
```
A coverage report is generated at `./coverage/index.html`.
## Benchmarks
[Run benchmarks in your browser](https://jsbm.dev/QHoz2G2XHQknL).
To run locally:
```bash
npm run bench
```
### CI / CD
Benchmarks are integrated into our CI/CD pipeline and automatically run with each commit to the `main` branch. This helps monitor the performance impacts of development, preventing regressions and verifying changes maintain performance standards.
[View historical results](https://havelessbemore.github.io/munkres/dev/bench/).
Specs:
- Package version: latest
- Runtime: NodeJS v20
- Benchmarking Tool: tinybench v2.6.0
- OS: [ubuntu-latest](https://github.com/actions/runner-images)
### Results
Below are the latest results from running locally.
Specs:
- Package version: v2.0.2
- Runtime: NodeJS v20.12.2
- Benchmarking Tool: tinybench v2.6.0
- Machine:
- Model: MacBook Air
- Chip: Apple M2
- Memory: 8 GB
- OS: MacOS Sonoma
#### `number[][]`
| Dimensions | Min (ms) | Max (ms) | Avg (ms) | Samples |
| ---------- | ----------- | ----------- | ----------- | --------- |
| 2x2 | 0 | 0.92475 | 0.00014 | 3,611,437 |
| 4x4 | 0.00013 | 0.38683 | 0.00041 | 1,227,622 |
| 8x8 | 0.00062 | 0.2005 | 0.00134 | 372,763 |
| 16x16 | 0.002 | 0.26346 | 0.00487 | 102,720 |
| 32x32 | 0.009 | 0.06462 | 0.01874 | 26,678 |
| 64x64 | 0.04483 | 0.28279 | 0.07837 | 6,381 |
| 128x128 | 0.228 | 0.52058 | 0.34338 | 1,457 |
| 256x256 | 1.07725 | 2.37567 | 1.59139 | 315 |
| 512x512 | 5.86442 | 9.18546 | 7.71347 | 65 |
| 1024x1024 | 31.82083 | 45.471 | 38.12961 | 50 |
| 2048x2048 | 165.45792 | 245.93154 | 205.5154 | 50 |
| 4096x4096 | 905.25592 | 1,384.78808 | 1,129.78629 | 50 |
| 8192x8192 | 5,062.63533 | 7,561.39129 | 6,152.11964 | 50 |
#### `bigint[][]`
| Dimensions | Min (ms) | Max (ms) | Avg (ms) | Samples |
| ---------- | ------------ | ------------ | ------------ | --------- |
| 2x2 | 0.00004 | 1.45567 | 0.00018 | 2,763,520 |
| 4x4 | 0.00029 | 0.61792 | 0.00058 | 860,516 |
| 8x8 | 0.00121 | 0.63829 | 0.00246 | 203,435 |
| 16x16 | 0.0045 | 0.639 | 0.00994 | 50,320 |
| 32x32 | 0.02021 | 0.66221 | 0.04299 | 11,633 |
| 64x64 | 0.11575 | 1.00283 | 0.19514 | 2,563 |
| 128x128 | 0.53988 | 1.92654 | 0.9169 | 546 |
| 256x256 | 3.32492 | 6.38088 | 4.51322 | 112 |
| 512x512 | 15.75375 | 46.94746 | 25.27091 | 50 |
| 1024x1024 | 107.30771 | 171.37271 | 129.81464 | 50 |
| 2048x2048 | 546.04767 | 850.22892 | 689.95893 | 50 |
| 4096x4096 | 2,835.29229 | 4,583.96688 | 3,697.85205 | 50 |
| 8192x8192 | 18,069.79829 | 24,171.88267 | 21,107.47192 | 10 |
---
Made with ❤️ by [Michael Rojas](https://github.com/havelessbemore)