converge_optimization/packs/network_flow/
mod.rs1mod solver;
6mod types;
7
8pub use solver::*;
9pub use types::*;
10
11use crate::packs::{InvariantDef, InvariantResult, Pack, PackSolveResult, default_gate_evaluation};
12use converge_pack::gate::GateResult as Result;
13use converge_pack::gate::{KernelTraceLink, ProblemSpec, PromotionGate, ProposedPlan};
14
15pub struct NetworkFlowPack;
16
17impl Pack for NetworkFlowPack {
18 fn name(&self) -> &'static str {
19 "network-flow"
20 }
21
22 fn version(&self) -> &'static str {
23 "1.0.0"
24 }
25
26 fn validate_inputs(&self, inputs: &serde_json::Value) -> Result<()> {
27 let input: NetworkFlowInput = serde_json::from_value(inputs.clone())
28 .map_err(|e| converge_pack::GateError::invalid_input(format!("Invalid input: {e}")))?;
29 input.validate()
30 }
31
32 fn invariants(&self) -> &[InvariantDef] {
33 &[]
34 }
35
36 fn solve(&self, spec: &ProblemSpec) -> Result<PackSolveResult> {
37 let input: NetworkFlowInput = spec.inputs_as()?;
38 input.validate()?;
39
40 let solver = MinCostFlowSolver;
41 let (output, report) = solver.solve(&input, spec)?;
42
43 let trace = KernelTraceLink::audit_only(format!("trace-{}", spec.problem_id));
44 let confidence = if output.total_flow >= input.demand - 1e-9 {
45 0.9
46 } else {
47 0.3
48 };
49
50 let plan = ProposedPlan::from_payload(
51 format!("plan-{}", spec.problem_id),
52 self.name(),
53 output.summary(),
54 &output,
55 confidence,
56 trace,
57 )?;
58
59 Ok(PackSolveResult::new(plan, report))
60 }
61
62 fn check_invariants(&self, _plan: &ProposedPlan) -> Result<Vec<InvariantResult>> {
63 Ok(vec![])
64 }
65
66 fn evaluate_gate(
67 &self,
68 _plan: &ProposedPlan,
69 invariant_results: &[InvariantResult],
70 ) -> PromotionGate {
71 default_gate_evaluation(invariant_results, self.invariants())
72 }
73}