converge_optimization/packs/assignment_pack/
solver.rs1use super::types::*;
7use crate::assignment::{self, AssignmentProblem};
8use converge_pack::gate::GateResult as Result;
9use converge_pack::gate::{ProblemSpec, ReplayEnvelope, SolverReport};
10
11pub struct HungarianAssignmentSolver;
13
14impl HungarianAssignmentSolver {
15 pub fn solve(
16 &self,
17 input: &AssignmentInput,
18 spec: &ProblemSpec,
19 ) -> Result<(AssignmentOutput, SolverReport)> {
20 let n = input.cost_matrix.len();
21
22 let scale = 1000i64;
25 let int_costs: Vec<Vec<i64>> = input
26 .cost_matrix
27 .iter()
28 .map(|row| {
29 row.iter()
30 .map(|&c| (c * scale as f64).round() as i64)
31 .collect()
32 })
33 .collect();
34
35 let problem = AssignmentProblem::from_costs(int_costs);
36 let solution = assignment::solve(&problem)
37 .map_err(|e| converge_pack::GateError::invalid_input(e.to_string()))?;
38
39 let assignments: Vec<(usize, usize)> = solution
41 .assignments
42 .iter()
43 .enumerate()
44 .filter(|&(agent, _)| agent < n)
45 .map(|(agent, &task)| (agent, task))
46 .collect();
47
48 let total_cost: f64 = assignments
49 .iter()
50 .map(|&(a, t)| input.cost_matrix[a][t])
51 .sum();
52
53 let output = AssignmentOutput {
54 assignments,
55 total_cost,
56 };
57
58 let replay = ReplayEnvelope::minimal(spec.seed());
59 let report = SolverReport::optimal("hungarian-assignment-v1", total_cost, replay);
60
61 Ok((output, report))
62 }
63}