competitive/graph/
network_simplex.rs

1use super::{One, Zero};
2use std::{
3    mem::swap,
4    ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign},
5};
6
7#[derive(Debug, Clone)]
8pub struct NetworkSimplex<F, C> {
9    n: usize,
10    edges: Vec<Edge<F, C>>,
11    lowers: Vec<F>,
12    dss: Vec<F>,
13    bucket_size: Option<usize>,
14    minor_limit: Option<usize>,
15}
16
17impl<F, C> NetworkSimplex<F, C>
18where
19    F: Copy + PartialOrd + Zero + Add<Output = F> + Sub<Output = F> + AddAssign + SubAssign,
20    C: Copy
21        + PartialOrd
22        + Zero
23        + One
24        + Add<Output = C>
25        + Sub<Output = C>
26        + AddAssign
27        + SubAssign
28        + Neg<Output = C>
29        + Mul<Output = C>
30        + From<F>,
31{
32    pub fn new(n: usize) -> Self {
33        Self {
34            n,
35            edges: vec![],
36            lowers: vec![],
37            dss: vec![F::zero(); n],
38            bucket_size: None,
39            minor_limit: None,
40        }
41    }
42
43    /// Add demand
44    pub fn add_demand(&mut self, vid: usize, demand: F) {
45        assert!(vid < self.n);
46        assert!(demand >= F::zero());
47        self.dss[vid] -= demand;
48    }
49
50    /// Add supply
51    pub fn add_supply(&mut self, vid: usize, supply: F) {
52        assert!(vid < self.n);
53        assert!(supply >= F::zero());
54        self.dss[vid] += supply;
55    }
56
57    /// Add demand/supply (positive for supply, negative for demand)
58    pub fn add_demand_supply(&mut self, vid: usize, ds: F) {
59        assert!(vid < self.n);
60        self.dss[vid] += ds;
61    }
62
63    /// Add edge with lower/upper capacity and cost
64    pub fn add_edge(&mut self, from: usize, to: usize, lower: F, upper: F, cost: C) {
65        assert!(from < self.n);
66        assert!(to < self.n);
67        assert!(lower <= upper);
68        self.edges.push(Edge {
69            to,
70            cap: upper - lower,
71            cost,
72        });
73        self.edges.push(Edge {
74            to: from,
75            cap: F::zero(),
76            cost: -cost,
77        });
78        self.lowers.push(lower);
79        self.dss[from] -= lower;
80        self.dss[to] += lower;
81    }
82
83    pub fn set_bucket_size(&mut self, size: usize) {
84        self.bucket_size = Some(size);
85    }
86
87    pub fn set_minor_limit(&mut self, limit: usize) {
88        self.minor_limit = Some(limit);
89    }
90
91    pub fn solve_minimize(self) -> Option<NetworkSimplexSolution<F, C>> {
92        NetworkSimplexSolver::build(self).solve()
93    }
94}
95
96#[derive(Debug, Clone)]
97struct Edge<F, C> {
98    to: usize,
99    cap: F,
100    cost: C,
101}
102
103#[derive(Debug, Clone)]
104struct Parent<F> {
105    par: usize,
106    eid: usize,
107    up: F,
108    down: F,
109}
110
111#[derive(Debug)]
112pub struct NetworkSimplexSolution<F, C> {
113    pub cost: C,
114    pub flows: Vec<F>,
115    pub potentials: Vec<C>,
116}
117
118#[derive(Debug)]
119struct NetworkSimplexSolver<F, C> {
120    n: usize,
121    m: usize,
122    edges: Vec<Edge<F, C>>, // forward/backward edges interleaved
123    lowers: Vec<F>,         // for each original edge (forward index/2)
124    dss: Vec<F>,            // demand/supply for each node
125
126    bucket_size: usize,
127    minor_limit: usize,
128    potentials: Vec<C>,      // potentials for nodes (size n)
129    parents: Vec<Parent<F>>, // size n (exclude super node)
130    depth: Vec<usize>,       // size n+1, depth[super]=0
131    next: Vec<usize>,        // euler-tour linked list for dynamic tree
132    prev: Vec<usize>,
133    candidates: Vec<usize>,
134}
135
136impl<F, C> NetworkSimplexSolver<F, C>
137where
138    F: Copy + PartialOrd + Zero + Add<Output = F> + Sub<Output = F> + AddAssign + SubAssign,
139    C: Copy
140        + PartialOrd
141        + Zero
142        + One
143        + Add<Output = C>
144        + Sub<Output = C>
145        + AddAssign
146        + SubAssign
147        + Neg<Output = C>
148        + Mul<Output = C>
149        + From<F>,
150{
151    fn connect(&mut self, a: usize, b: usize) {
152        self.next[a] = b;
153        self.prev[b] = a;
154    }
155
156    fn build(ns: NetworkSimplex<F, C>) -> Self {
157        let NetworkSimplex {
158            n,
159            mut edges,
160            lowers,
161            dss,
162            bucket_size,
163            minor_limit,
164        } = ns;
165
166        let m = edges.len();
167        let bucket_size =
168            bucket_size.unwrap_or_else(|| (((m as f64).sqrt() * 0.2) as usize).max(10));
169        let minor_limit =
170            minor_limit.unwrap_or_else(|| (((bucket_size as f64) * 0.1) as usize).max(3));
171
172        let mut potentials = vec![C::zero(); n + 1];
173        let mut parents = vec![
174            Parent {
175                par: 0,
176                eid: 0,
177                up: F::zero(),
178                down: F::zero(),
179            };
180            n
181        ];
182        let inf_cost = edges.iter().step_by(2).fold(C::one(), |acc, edge| {
183            acc + if edge.cost >= C::zero() {
184                edge.cost
185            } else {
186                -edge.cost
187            }
188        });
189        edges.reserve(m + n * 2);
190        let super_node = n;
191        for v in 0..n {
192            let eid = edges.len();
193            if dss[v] >= F::zero() {
194                edges.push(Edge {
195                    to: super_node,
196                    cap: F::zero(),
197                    cost: inf_cost,
198                });
199                edges.push(Edge {
200                    to: v,
201                    cap: dss[v],
202                    cost: -inf_cost,
203                });
204                potentials[v] = -inf_cost;
205            } else {
206                edges.push(Edge {
207                    to: super_node,
208                    cap: F::zero() - dss[v],
209                    cost: -inf_cost,
210                });
211                edges.push(Edge {
212                    to: v,
213                    cap: F::zero(),
214                    cost: inf_cost,
215                });
216                potentials[v] = inf_cost;
217            }
218            parents[v] = Parent {
219                par: super_node,
220                eid,
221                up: edges[eid].cap,
222                down: edges[eid ^ 1].cap,
223            };
224        }
225
226        let mut depth = vec![1; n + 1];
227        depth[super_node] = 0;
228
229        let mut this = NetworkSimplexSolver {
230            n,
231            m,
232            edges,
233            lowers,
234            dss,
235            bucket_size,
236            minor_limit,
237            parents,
238            depth,
239            next: vec![0; (n + 1) * 2],
240            prev: vec![0; (n + 1) * 2],
241            candidates: Vec::with_capacity(bucket_size),
242            potentials,
243        };
244        for v in 0..=n {
245            this.connect(v * 2, v * 2 + 1);
246        }
247        for v in 0..n {
248            this.connect(v * 2 + 1, this.next[super_node * 2]);
249            this.connect(super_node * 2, v * 2);
250        }
251        this
252    }
253
254    fn solve(mut self) -> Option<NetworkSimplexSolution<F, C>> {
255        let mut eid = 0usize;
256        loop {
257            for _ in 0..self.minor_limit {
258                if !self.minor() {
259                    break;
260                }
261            }
262            let mut best = C::zero();
263            let mut best_eid: Option<usize> = None;
264            self.candidates.clear();
265            for _ in 0..self.edges.len() {
266                if !self.edges[eid].cap.is_zero() {
267                    let clen = self.edges[eid].cost + self.potentials[self.edges[eid ^ 1].to]
268                        - self.potentials[self.edges[eid].to];
269                    if clen < C::zero() {
270                        if best_eid.is_none() || clen < best {
271                            best = clen;
272                            best_eid = Some(eid);
273                        }
274                        self.candidates.push(eid);
275                        if self.candidates.len() == self.bucket_size {
276                            break;
277                        }
278                    }
279                }
280                eid += 1;
281                if eid == self.edges.len() {
282                    eid = 0;
283                }
284            }
285            if self.candidates.is_empty() {
286                break;
287            }
288            if let Some(be) = best_eid {
289                self.push_flow(be);
290            }
291        }
292        for i in 0..self.n {
293            let eid = self.parents[i].eid;
294            self.edges[eid].cap = self.parents[i].up;
295            self.edges[eid ^ 1].cap = self.parents[i].down;
296        }
297        self.generate_solution()
298    }
299
300    fn minor(&mut self) -> bool {
301        if self.candidates.is_empty() {
302            return false;
303        }
304        let mut best = C::zero();
305        let mut best_eid: Option<usize> = None;
306        let mut i = 0usize;
307        while i < self.candidates.len() {
308            let eid = self.candidates[i];
309            if self.edges[eid].cap.is_zero() {
310                self.candidates.swap_remove(i);
311                continue;
312            }
313            let clen = self.edges[eid].cost + self.potentials[self.edges[eid ^ 1].to]
314                - self.potentials[self.edges[eid].to];
315            if clen >= C::zero() {
316                self.candidates.swap_remove(i);
317                continue;
318            }
319            if best_eid.is_none() || clen < best {
320                best = clen;
321                best_eid = Some(eid);
322            }
323            i += 1;
324        }
325        if let Some(best_eid) = best_eid {
326            self.push_flow(best_eid);
327            true
328        } else {
329            false
330        }
331    }
332
333    fn get_lca(
334        &self,
335        mut u: usize,
336        mut v: usize,
337        flow: &mut F,
338        del_u_side: &mut bool,
339        del_u: &mut usize,
340    ) -> usize {
341        if self.depth[u] >= self.depth[v] {
342            for _ in 0..self.depth[u] - self.depth[v] {
343                if self.parents[u].down < *flow {
344                    *flow = self.parents[u].down;
345                    *del_u = u;
346                    *del_u_side = true;
347                }
348                u = self.parents[u].par;
349            }
350        } else {
351            for _ in 0..self.depth[v] - self.depth[u] {
352                if self.parents[v].up <= *flow {
353                    *flow = self.parents[v].up;
354                    *del_u = v;
355                    *del_u_side = false;
356                }
357                v = self.parents[v].par;
358            }
359        }
360        while u != v {
361            if self.parents[u].down < *flow {
362                *flow = self.parents[u].down;
363                *del_u = u;
364                *del_u_side = true;
365            }
366            u = self.parents[u].par;
367            if self.parents[v].up <= *flow {
368                *flow = self.parents[v].up;
369                *del_u = v;
370                *del_u_side = false;
371            }
372            v = self.parents[v].par;
373        }
374        u
375    }
376
377    fn push_flow(&mut self, eid: usize) {
378        let u0 = self.edges[eid ^ 1].to;
379        let v0 = self.edges[eid].to;
380        let mut del_u = v0;
381        let mut flow = self.edges[eid].cap;
382        let mut del_u_side = true;
383        let lca = self.get_lca(u0, v0, &mut flow, &mut del_u_side, &mut del_u);
384        if !flow.is_zero() {
385            let mut u = u0;
386            let mut v = v0;
387            while u != lca {
388                self.parents[u].up += flow;
389                self.parents[u].down -= flow;
390                u = self.parents[u].par;
391            }
392            while v != lca {
393                self.parents[v].up -= flow;
394                self.parents[v].down += flow;
395                v = self.parents[v].par;
396            }
397        }
398        let mut u = u0;
399        let mut par = v0;
400        let mut p_caps = (self.edges[eid].cap - flow, self.edges[eid ^ 1].cap + flow);
401        let mut p_diff = -(self.edges[eid].cost + self.potentials[u0] - self.potentials[v0]);
402        if !del_u_side {
403            swap(&mut u, &mut par);
404            swap(&mut p_caps.0, &mut p_caps.1);
405            p_diff = -p_diff;
406        }
407        let mut par_eid = eid ^ if del_u_side { 0 } else { 1 };
408        while par != del_u {
409            let mut d = self.depth[par];
410            let mut idx = u * 2;
411            while idx != u * 2 + 1 {
412                if idx % 2 == 0 {
413                    d += 1;
414                    self.potentials[idx / 2] += p_diff;
415                    self.depth[idx / 2] = d;
416                } else {
417                    d -= 1;
418                }
419                idx = self.next[idx];
420            }
421            self.connect(self.prev[u * 2], self.next[u * 2 + 1]);
422            self.connect(u * 2 + 1, self.next[par * 2]);
423            self.connect(par * 2, u * 2);
424            swap(&mut self.parents[u].eid, &mut par_eid);
425            par_eid ^= 1;
426            swap(&mut self.parents[u].up, &mut p_caps.0);
427            swap(&mut self.parents[u].down, &mut p_caps.1);
428            swap(&mut p_caps.0, &mut p_caps.1);
429            let next_u = self.parents[u].par;
430            self.parents[u].par = par;
431            par = u;
432            u = next_u;
433        }
434        self.edges[par_eid].cap = p_caps.0;
435        self.edges[par_eid ^ 1].cap = p_caps.1;
436    }
437
438    fn generate_solution(mut self) -> Option<NetworkSimplexSolution<F, C>> {
439        for v in 0..self.n {
440            if self.dss[v] >= F::zero() {
441                if !self.edges[self.m + v * 2 + 1].cap.is_zero() {
442                    return None;
443                }
444            } else if !self.edges[self.m + v * 2].cap.is_zero() {
445                return None;
446            }
447        }
448        let mut cost = C::zero();
449        let mut flows = Vec::with_capacity(self.m / 2);
450        for eid in (0..self.m).step_by(2) {
451            let f = self.lowers[eid / 2] + self.edges[eid ^ 1].cap;
452            flows.push(f);
453            cost += C::from(f) * self.edges[eid].cost;
454        }
455        self.potentials.pop();
456        Some(NetworkSimplexSolution {
457            cost,
458            flows,
459            potentials: self.potentials,
460        })
461    }
462}
463
464#[cfg(test)]
465mod tests {
466    use super::*;
467
468    #[test]
469    fn test_feasible_b_flow() {
470        let mut ns = NetworkSimplex::<i32, i32>::new(3);
471        ns.add_supply(0, 5);
472        ns.add_demand(1, 5);
473        ns.add_edge(0, 2, 0, 10, -1);
474        ns.add_edge(2, 1, 0, 10, -1);
475        ns.add_edge(0, 1, 0, 10, 10);
476        let sol = ns.solve_minimize();
477        assert!(sol.is_some(), "should be feasible");
478        let sol = sol.unwrap();
479        assert_eq!(sol.cost, -10);
480        assert_eq!(sol.flows, vec![5, 5, 0]);
481    }
482
483    #[test]
484    fn test_infeasible_b_flow() {
485        let mut ns = NetworkSimplex::<i32, i32>::new(2);
486        ns.add_demand(0, 5);
487        ns.add_supply(1, 5);
488        ns.add_edge(0, 1, 0, 3, 2);
489        let sol = ns.solve_minimize();
490        assert!(sol.is_none(), "should be infeasible");
491    }
492}