pub struct AssignmentBuilder { /* private fields */ }Expand description
Fluent builder for bipartite assignment COPs.
Construct via assignment() (preferred) or Default::default.
All setters consume self and return self, allowing chained
configuration. The terminal AssignmentBuilder::solve call
validates the configuration, materializes the underlying
Csp<CostFiniteDomain>, runs branch-and-bound, and returns an
AssignmentSolution (or an AssignmentError on
mis-configuration / infeasibility).
Implementations§
Source§impl AssignmentBuilder
impl AssignmentBuilder
Sourcepub fn cost(self, f: impl Fn(usize, usize) -> f64) -> Self
pub fn cost(self, f: impl Fn(usize, usize) -> f64) -> Self
Eagerly populate the row-major cost matrix.
Calls f(i, k) exactly once per (row, col) cell during this
method, stores the result in an internal Vec<f64>, and
returns self. No closure is retained, which keeps the
builder Send + Sync even when constructed from non-'static
captures.
§Panics
Panics if AssignmentBuilder::rows or
AssignmentBuilder::cols has not been called yet — both
dimensions are required to know how to walk f.
Sourcepub fn row_group(self, f: impl Fn(usize) -> u8) -> Self
pub fn row_group(self, f: impl Fn(usize) -> u8) -> Self
Tag each row with a u8 group identifier.
Rows in different groups are placed in independent
AllDifferentExcept scopes, and a row may only be assigned
to a column whose group identifier matches. Omitting the call
(or supplying |_| 0) puts every row in a single group, which
is the standard bipartite-assignment shape.
Sourcepub fn col_group(self, f: impl Fn(usize) -> u8) -> Self
pub fn col_group(self, f: impl Fn(usize) -> u8) -> Self
Tag each column with a u8 group identifier.
See AssignmentBuilder::row_group for the semantics.
Sourcepub fn pin(self, row: usize, col: i32) -> Self
pub fn pin(self, row: usize, col: i32) -> Self
Hard-pin row row to column col.
col may be SENTINEL to force the row unmatched. Multiple
pins are accumulated; conflicting pins on the same row are
detected at AssignmentBuilder::solve time as
AssignmentError::Infeasible.
Sourcepub fn unmatch_penalty(self, penalty: f64) -> Self
pub fn unmatch_penalty(self, penalty: f64) -> Self
Set the per-row cost paid when a row is assigned to
SENTINEL (left unmatched).
Sourcepub fn node_budget(self, budget: Option<u64>) -> Self
pub fn node_budget(self, budget: Option<u64>) -> Self
Override the underlying branch-and-bound node budget.
Passing None here is not the same as never calling this
method: None requests an unbounded search, while the default
(no call) installs a 1_000_000 node guard so a pathological
problem cannot hang the caller. See
crate::SolveConfig::node_budget.
Sourcepub fn solve(self) -> Result<AssignmentSolution, AssignmentError>
pub fn solve(self) -> Result<AssignmentSolution, AssignmentError>
Validate the configuration and solve for the minimum-cost assignment.
A group-free, pin-free instance is dispatched to the closed-form
Kuhn-Munkres LAP solver (always optimal, microsecond-scale, never
budget-blows). Grouped or pinned instances fall through to the general
branch-and-bound CSP path. See the module docs for the n≈15–18 B&B
ceiling; use solve_branch_and_bound to
force the CSP path on any shape.
Sourcepub fn solve_branch_and_bound(
self,
) -> Result<AssignmentSolution, AssignmentError>
pub fn solve_branch_and_bound( self, ) -> Result<AssignmentSolution, AssignmentError>
Force the branch-and-bound CSP path regardless of shape, bypassing the
closed-form LAP dispatch in solve.
Exists for benchmarking the general solver and for the node-count
invariance gate — a group-free/pin-free instance solved here exercises
the exact same B&B trajectory it did before the LAP dispatch landed, so
its nodes_explored / backtracks counts are a stable regression
tripwire. Prefer solve in production.