use super::types::*;
use crate::assignment::{self, AssignmentProblem};
use converge_pack::gate::GateResult as Result;
use converge_pack::gate::{ProblemSpec, ReplayEnvelope, SolverReport};
pub struct HungarianAssignmentSolver;
impl HungarianAssignmentSolver {
pub fn solve(
&self,
input: &AssignmentInput,
spec: &ProblemSpec,
) -> Result<(AssignmentOutput, SolverReport)> {
let n = input.cost_matrix.len();
let scale = 1000i64;
let int_costs: Vec<Vec<i64>> = input
.cost_matrix
.iter()
.map(|row| {
row.iter()
.map(|&c| (c * scale as f64).round() as i64)
.collect()
})
.collect();
let problem = AssignmentProblem::from_costs(int_costs);
let solution = assignment::solve(&problem)
.map_err(|e| converge_pack::GateError::invalid_input(e.to_string()))?;
let assignments: Vec<(usize, usize)> = solution
.assignments
.iter()
.enumerate()
.filter(|&(agent, _)| agent < n)
.map(|(agent, &task)| (agent, task))
.collect();
let total_cost: f64 = assignments
.iter()
.map(|&(a, t)| input.cost_matrix[a][t])
.sum();
let output = AssignmentOutput {
assignments,
total_cost,
};
let replay = ReplayEnvelope::minimal(spec.seed());
let report = SolverReport::optimal("hungarian-assignment-v1", total_cost, replay);
Ok((output, report))
}
}