|
1 | 1 | # Auction Algorithm Scala |
2 | 2 |
|
3 | | -This is a repo contains a `Scala` implementation of [Bertsekas's Auction Algorithm](http://dspace.mit.edu/bitstream/handle/1721.1/3233/P-2064-24690022.pdf?sequence=1). The algorithm solves the problem of optimally assigning M objects to N people given the preferences specified in a given cost matrix. |
| 3 | +A Scala 3 implementation of [Bertsekas' auction algorithm](http://dspace.mit.edu/bitstream/handle/1721.1/3233/P-2064-24690022.pdf?sequence=1) for the n-by-n assignment problem: optimally assigning n objects to n people given a cost matrix. Sibling of [AuctionAlgorithmCPP](https://github.com/EvanOman/AuctionAlgorithmCPP) — same algorithm, same problem-file format, interchangeable CLIs. |
4 | 4 |
|
5 | | -After a bit of optimization, this implementation can solve a size 500 assignment problem in ~.125 seconds. I have also implemented a parallel version, which seems to outperform the sequential version once the problem size is over 5000. This implementation is still being optimized. |
| 5 | +[](https://github.com/EvanOman/AuctionAlgorithmScala/actions/workflows/ci.yml) |
| 6 | + |
| 7 | +Originally written in 2016 (Scala 2.11 + Breeze); rewritten in 2026. The old implementation had the same epsilon-scaling termination bug as the original C++ version (the final scaling phase ran too coarse, so tie-heavy instances came back suboptimal — its own test harness literally printed "Percentage correct"), and its fixed starting epsilon of 0.3 meant it produced **no assignment at all** for n ≤ 2. Full bug taxonomy in the [C++ repo's docs/BUGS.md](https://github.com/EvanOman/AuctionAlgorithmCPP/blob/master/docs/BUGS.md); the old source is preserved at `legacy/`. |
| 8 | + |
| 9 | +## What's here |
| 10 | + |
| 11 | +- **`Auction.solve(costs, n, options)`** — the solver. Row-major `IndexedSeq[Long]` costs, `Minimize` (default) or `Maximize`, exact optimality for integer costs (the final scaling phase runs with n·ε < 1). An optional **parallel bidding mode** (`Options(parallel = true)`) computes each round's bids concurrently with deterministic results — the feature that distinguished the 2016 version, kept and made correct. |
| 12 | +- **`Problem`** — parser/formatter for the text problem format shared with the C++ repo. |
| 13 | +- **CLI** — `solve` / `generate` subcommands mirroring the C++ `auction` binary. |
| 14 | +- **Tests** — munit suite: brute-force cross-checks over hundreds of random instances, Machol–Wien closed-form cases, the tie-heavy regression instance, n ≤ 2 regressions, parallel-equals-sequential. |
| 15 | + |
| 16 | +## Usage |
| 17 | + |
| 18 | +Requires JDK 11+ and [sbt](https://www.scala-sbt.org/) ([just](https://github.com/casey/just) optional but recommended). |
| 19 | + |
| 20 | +```bash |
| 21 | +just test # run the test suite |
| 22 | +just solve problem.apf # solve a problem file |
| 23 | +just generate 10 --seed 42 # emit a random 10x10 instance |
| 24 | +``` |
| 25 | + |
| 26 | +Problem file format (`#` comments and blank lines ignored; `objective` defaults to `min`): |
| 27 | + |
| 28 | +``` |
| 29 | +objective min |
| 30 | +n 3 |
| 31 | +4 1 3 |
| 32 | +2 0 5 |
| 33 | +3 2 2 |
| 34 | +``` |
| 35 | + |
| 36 | +Output: |
| 37 | + |
| 38 | +``` |
| 39 | +objective: min |
| 40 | +n: 3 |
| 41 | +total_cost: 5 |
| 42 | +phases: 3 |
| 43 | +rounds: 7 |
| 44 | +assignment: |
| 45 | + 0 -> 1 |
| 46 | + 1 -> 0 |
| 47 | + 2 -> 2 |
| 48 | +``` |
| 49 | + |
| 50 | +Add `--json` for machine-readable output, `--parallel` for parallel bidding. |
| 51 | + |
| 52 | +As a library: |
| 53 | + |
| 54 | +```scala |
| 55 | +import com.evan.auctionalgorithm.* |
| 56 | + |
| 57 | +val costs = Vector[Long](4, 1, 3, 2, 0, 5, 3, 2, 2) |
| 58 | +val result = Auction.solve(costs, 3) // minimize by default |
| 59 | +// result.assignment == Vector(1, 0, 2), result.totalCost == 5 |
| 60 | +``` |
| 61 | + |
| 62 | +## Development |
| 63 | + |
| 64 | +`just fc` before committing (format + tests). CI runs `scalafmtCheckAll` and the test suite on every push. Compiler warnings are fatal (`-Werror`). |
0 commit comments