Skip to main content

Module assignment

Module assignment 

Source
Expand description

Bipartite assignment COP builder.

Tests: tests/assignment_builder.rs, tests/assignment_proptest.rs.

Fluent API for the common pattern of “assign N source rows to M target columns with per-cell costs, role-based AllDifferent groups, and optional hard pin constraints.”

§Two solve paths

AssignmentBuilder::solve dispatches on the shape:

  • Group-free / pin-free instances are a pure linear assignment problem, solved in closed form by Kuhn-Munkres (the hungarian crate) in O(n³) — microseconds even at n=200. This path is always proven-optimal and never budget-blows.
  • Grouped or pinned instances go through the general CSP: a Csp<CostFiniteDomain> with one variable per row, an AllDifferentExcept per row-group, and -1 as the unmatched sentinel, driven by branch-and-bound via Csp::solve_optimized (OptimizationMode::MinimizeCost + Pruning::Ac3).

The B&B path is only proven-optimal to roughly n ≈ 15–18; past that it exhausts its node budget and returns a best-so-far assignment with SolveStats::budget_exceeded set (n=20 budget-blows at ~1 M nodes). The closed-form dispatch exists precisely to keep the common group-free/pin-free shape off that cliff. AssignmentBuilder::solve_branch_and_bound forces the CSP path regardless of shape (benchmarking / the B&B node-count gate).

§Example

use csp_solver::assignment;

let sol = assignment()
    .rows(3)
    .cols(3)
    .cost(|i, k| if i == k { 0.0 } else { 10.0 })
    .unmatch_penalty(100.0)
    .solve()
    .expect("solvable");

assert_eq!(sol.assign, vec![0, 1, 2]);
assert_eq!(sol.cost, 0.0);

Structs§

AssignmentBuilder
Fluent builder for bipartite assignment COPs.
AssignmentSolution
Result of a successful AssignmentBuilder::solve call.

Enums§

AssignmentError
Errors from AssignmentBuilder::solve.

Constants§

SENTINEL
Sentinel value used in AssignmentSolution::assign to denote an unmatched row.

Functions§

assignment
Top-level constructor for an empty AssignmentBuilder.