1use super::SolutionState;
21use crate::adjacencies::Adjacencies;
22use crate::collections::NodeVecMap;
23use crate::search::dfs;
24use crate::traits::{FiniteGraph, GraphType, IndexDigraph};
25use num_traits::{Bounded, FromPrimitive, NumAssign, NumCast, Signed, ToPrimitive, Zero};
26
27type ID = u32;
28
29pub enum Pricing {
30 RoundRobin,
31 Complete,
32 Block,
33 MultiplePartial,
34}
35
36pub struct NetworkSimplex<G, F> {
38 graph: G,
39
40 balances: Vec<F>,
41 potentials: Vec<F>,
42 subtrees: Vec<ID>,
43 parent_edges: Vec<ID>,
44 parent_nodes: Vec<ID>,
45
46 prev_preorder: Vec<ID>, next_preorder: Vec<ID>, last_preorder: Vec<ID>, sources: Vec<ID>,
51 sinks: Vec<ID>,
52 lower: Vec<F>,
53 upper: Vec<F>,
54 costs: Vec<F>,
55 caps: Vec<F>,
56 flows: Vec<F>,
57 state: Vec<i8>,
58
59 pub pricing: Pricing,
60 current_edge: ID,
61 block_size: usize,
62 pub zero: F,
64
65 niter: usize,
66 solution_state: SolutionState,
67 need_new_basis: bool,
68
69 pub artificial_cost: Option<F>,
75 pub infinite: F,
82}
83
84impl<G, F> NetworkSimplex<G, F>
85where
86 G: IndexDigraph,
87 F: Bounded + NumCast + NumAssign + PartialOrd + Copy + FromPrimitive + Signed,
88{
89 pub fn new(g: G) -> Self {
90 let n = FiniteGraph::num_nodes(&g);
91 let m = FiniteGraph::num_edges(&g);
92 let mut spx = NetworkSimplex {
93 graph: g,
94 balances: vec![F::zero(); n],
95 potentials: vec![F::zero(); n + 1],
96 subtrees: vec![0; n + 1],
97 parent_edges: vec![0; n + 1],
98 parent_nodes: vec![0; n + 1],
99
100 prev_preorder: vec![0; n + 1],
101 next_preorder: vec![0; n + 1],
102 last_preorder: vec![0; n + 1],
103
104 sources: vec![0; m + n],
105 sinks: vec![0; m + n],
106 lower: vec![F::zero(); m + n],
107 upper: vec![F::zero(); m + n],
108 costs: vec![F::zero(); m + n],
109 caps: vec![F::zero(); m + n],
110 flows: vec![F::zero(); m + n],
111 state: vec![0; m + n],
112
113 pricing: Pricing::Block,
114 current_edge: 0,
115 block_size: 0,
116 zero: F::zero(),
117
118 niter: 0,
119 solution_state: SolutionState::Unknown,
120 need_new_basis: true,
121
122 artificial_cost: None,
123 infinite: F::max_value(),
124 };
125 spx.init();
126 spx
127 }
128
129 pub fn as_graph(&self) -> &G {
130 &self.graph
131 }
132
133 pub fn balance(&self, u: <G as GraphType>::Node<'_>) -> F {
134 self.balances[self.graph.node_id(u)]
135 }
136
137 pub fn set_balance(&mut self, u: <G as GraphType>::Node<'_>, balance: F) {
138 self.need_new_basis = true;
139 self.balances[self.graph.node_id(u)] = balance;
140 }
141
142 pub fn set_balances<'a, Bs>(&'a mut self, balance: Bs)
143 where
144 Bs: Fn(<G as GraphType>::Node<'a>) -> F,
145 {
146 for u in self.graph.nodes() {
147 self.balances[self.graph.node_id(u)] = (balance)(u);
148 }
149 }
150
151 pub fn lower(&self, e: <G as GraphType>::Edge<'_>) -> F {
152 self.lower[self.graph.edge_id(e)]
153 }
154
155 pub fn set_lower(&mut self, e: <G as GraphType>::Edge<'_>, lb: F) {
156 self.need_new_basis = true;
157 self.lower[self.graph.edge_id(e)] = lb;
158 }
159
160 pub fn set_lowers<'a, Ls>(&'a mut self, lower: Ls)
161 where
162 Ls: Fn(<G as GraphType>::Edge<'a>) -> F,
163 {
164 for e in self.graph.edges() {
165 self.lower[self.graph.edge_id(e)] = (lower)(e);
166 }
167 }
168
169 pub fn upper(&self, e: <G as GraphType>::Edge<'_>) -> F {
170 self.upper[self.graph.edge_id(e)]
171 }
172
173 pub fn set_upper(&mut self, e: <G as GraphType>::Edge<'_>, ub: F) {
174 self.need_new_basis = true;
175 self.upper[self.graph.edge_id(e)] = ub;
176 }
177
178 pub fn set_uppers<'a, Us>(&'a mut self, upper: Us)
179 where
180 Us: Fn(<G as GraphType>::Edge<'a>) -> F,
181 {
182 for e in self.graph.edges() {
183 self.upper[self.graph.edge_id(e)] = (upper)(e);
184 }
185 }
186
187 pub fn cost(&self, e: <G as GraphType>::Edge<'_>) -> F {
188 self.costs[self.graph.edge_id(e)]
189 }
190
191 pub fn set_cost(&mut self, e: <G as GraphType>::Edge<'_>, cost: F) {
192 self.costs[self.graph.edge_id(e)] = cost;
193 }
194
195 pub fn set_costs<'a, Cs>(&'a mut self, cost: Cs)
196 where
197 Cs: Fn(<G as GraphType>::Edge<'a>) -> F,
198 {
199 for e in self.graph.edges() {
200 self.costs[self.graph.edge_id(e)] = (cost)(e);
201 }
202 }
203
204 pub fn value(&self) -> F {
206 let mut v = F::zero();
207 for e in FiniteGraph::edges(&self.graph) {
208 v += self.flow(e) * self.costs[self.graph.edge_id(e)];
209 }
210 v
211 }
212
213 pub fn flow(&self, a: <G as GraphType>::Edge<'_>) -> F {
215 let eid = self.graph.edge_id(a);
216 self.flows[eid] + self.lower[eid]
217 }
218
219 pub fn solve(&mut self) -> SolutionState {
221 self.niter = 0;
222 self.solution_state = SolutionState::Unknown;
223
224 if FiniteGraph::num_nodes(&self.graph).is_zero() {
226 self.solution_state = SolutionState::Optimal;
227 return self.solution_state;
228 }
229
230 if FiniteGraph::num_edges(&self.graph).is_zero() {
231 self.solution_state = if self.balances.iter().all(Zero::is_zero) {
233 SolutionState::Optimal
234 } else {
235 SolutionState::Infeasible
236 };
237 return self.solution_state;
238 }
239
240 self.initialize_pricing();
241
242 if self.need_new_basis && !self.prepare_initial_basis() {
243 self.solution_state = SolutionState::Infeasible;
244 return self.solution_state;
245 }
246
247 self.initialize_node_potentials();
248
249 if !self.compute_initial_pivots() {
251 self.solution_state = SolutionState::Unbounded;
252 return self.solution_state;
253 }
254
255 loop {
256 self.niter += 1;
257 if let Some(eid) = self.find_entering_edge() {
258 if !self.augment_cycle(eid) {
259 self.solution_state = SolutionState::Unbounded;
260 return self.solution_state;
261 }
262 } else {
263 break;
264 }
265 }
266
267 self.solution_state = if self.check_feasibility() {
268 SolutionState::Optimal
269 } else {
270 SolutionState::Infeasible
271 };
272
273 self.solution_state
274 }
275
276 pub fn solution_state(&self) -> SolutionState {
278 if self.need_new_basis {
279 SolutionState::Unknown
280 } else {
281 self.solution_state
282 }
283 }
284
285 fn init(&mut self) {
286 let m = self.graph.num_edges();
287 for eid in 0..m {
289 self.sources[eid] = NumCast::from(self.graph.node_id(self.graph.src(self.graph.id2edge(eid)))).unwrap();
290 self.sinks[eid] = NumCast::from(self.graph.node_id(self.graph.snk(self.graph.id2edge(eid)))).unwrap();
291 }
292
293 }
296
297 pub fn num_iterations(&self) -> usize {
298 self.niter
299 }
300
301 fn initialize_pricing(&mut self) {
302 match self.pricing {
303 Pricing::RoundRobin => self.current_edge = 0,
304 Pricing::Complete => (),
305 Pricing::Block => {
306 self.current_edge = 0;
307 self.block_size = ((self.graph.num_edges() as f64).sqrt() * 0.5)
310 .round()
311 .to_usize()
312 .unwrap()
313 .max(10);
314 }
315 Pricing::MultiplePartial => todo!(),
316 }
317 }
318
319 fn prepare_initial_basis(&mut self) -> bool {
320 let n = self.graph.num_nodes();
321 let m = self.graph.num_edges() * 2;
322 let uid = self.graph.num_nodes();
324
325 let mut balances = self.balances.clone();
327 balances.push(F::zero());
328
329 let artificial_cost = self.artificial_cost.unwrap_or_else(|| {
331 let mut value = F::zero();
332 for &c in &self.costs[0..self.graph.num_edges()] {
333 if c > value {
334 value = c;
335 }
336 }
337 F::from(n).unwrap() * (F::one() + value)
338 });
339
340 self.subtrees[uid] = n as ID + 1;
341 self.parent_edges[uid] = ID::max_value();
342 self.parent_nodes[uid] = ID::max_value();
343
344 self.prev_preorder[uid] = ID::max_value();
345 self.next_preorder[uid] = 0;
346 self.last_preorder[uid] = n as ID - 1;
347
348 for e in self.graph.edges() {
350 let eid = self.graph.edge_id(e);
351 let cap = self.upper[eid] - self.lower[eid];
353
354 if cap < self.zero {
356 return false;
357 }
358
359 let flw: F;
360 if self.costs[eid] >= F::zero() {
361 self.state[eid] = 1;
362 flw = F::zero();
363 } else {
364 self.state[eid] = -1;
365 flw = cap;
366 }
367
368 self.flows[eid] = flw;
369 self.caps[eid] = cap;
370
371 let flw = flw + self.lower[eid];
373 balances[self.graph.node_id(self.graph.src(e))] -= flw;
374 balances[self.graph.node_id(self.graph.snk(e))] += flw;
375 }
376
377 #[allow(clippy::needless_range_loop)]
379 for vid in 0..n {
380 self.subtrees[vid] = 1;
381 let eid = m + vid * 2;
383 let fid; let b; if balances[vid] >= F::zero() {
386 fid = eid ^ 1;
387 b = balances[vid];
388 self.costs[eid / 2] = F::zero();
389 self.sources[eid / 2] = ID::from_usize(eid - m).unwrap();
391 self.sinks[eid / 2] = ID::from_usize(n).unwrap();
392 } else {
393 fid = eid;
394 b = -balances[vid];
395 self.costs[eid / 2] = artificial_cost;
396 self.sources[eid / 2] = ID::from_usize(n).unwrap();
398 self.sinks[eid / 2] = ID::from_usize(eid - m).unwrap();
399 }
400
401 self.caps[eid / 2] = self.infinite;
402 self.flows[eid / 2] = b;
403 self.state[eid / 2] = 0;
404
405 self.parent_nodes[vid] = uid as ID;
406 self.parent_edges[vid] = fid as ID;
407 self.prev_preorder[vid] = if vid > 0 { vid as ID - 1 } else { n as ID };
408 self.next_preorder[vid] = if vid + 1 < n { vid as ID + 1 } else { ID::max_value() };
409 self.last_preorder[vid] = vid as ID; }
411
412 self.need_new_basis = false;
413
414 true
415 }
416
417 fn compute_initial_pivots(&mut self) -> bool {
421 let n = self.graph.num_nodes();
422 let mut supply_nodes = Vec::new();
423 let mut demand_nodes = Vec::new();
424 let mut total_supply = F::zero();
425 for uid in 0..n {
426 let b = self.balances[uid];
427 if b > F::zero() {
428 total_supply += b;
429 supply_nodes.push(uid);
430 } else if b < F::zero() {
431 demand_nodes.push(uid);
432 }
433 }
434
435 if total_supply.is_zero() {
437 return true;
438 }
439
440 let edges: Vec<usize> = if supply_nodes.len() == 1 && demand_nodes.len() == 1 {
441 let s = self.graph.id2node(supply_nodes[0]);
444 let t = self.graph.id2node(demand_nodes[0]);
445 let mut edges = Vec::new();
446 for (_, e) in dfs::start_with_data(
447 self.graph
448 .incoming()
449 .filter(|&(e, _)| self.caps[self.graph.edge_id(e)] >= total_supply && self.graph.snk(e) != s),
450 t,
451 (NodeVecMap::new(&self.graph), Vec::new()),
452 ) {
453 edges.push(self.graph.edge_id(e));
454 }
455 edges
456 } else {
457 demand_nodes
459 .iter()
460 .filter_map(|&vid| {
461 self.graph
462 .inedges(self.graph.id2node(vid))
463 .map(|(e, _)| self.graph.edge_id(e))
464 .min_by(|&eid, &fid| self.costs[eid].partial_cmp(&self.costs[fid]).unwrap())
465 })
466 .collect()
467 };
468
469 for eid in edges {
471 if self.reduced_cost(eid) >= F::zero() {
472 continue;
473 }
474 let eid = self.oriented_edge(eid);
475 if !self.augment_cycle(eid) {
476 return false;
477 }
478 }
479
480 true
481 }
482
483 fn initialize_node_potentials(&mut self) {
484 let rootid = self.graph.num_nodes();
485 self.potentials[rootid] = F::zero();
486
487 let mut uid = self.next_preorder[rootid] as usize;
488 while uid != ID::max_value() as usize {
489 let eid = self.parent_edges[uid] as usize;
490 let vid = self.parent_nodes[uid] as usize;
491 self.potentials[uid] = self.potentials[vid] + oriented_flow(eid, self.costs[eid / 2]);
492 uid = self.next_preorder[uid] as usize;
493 }
494 }
495
496 fn update_node_potentials(&mut self, uentering: usize) {
497 let eid = self.parent_edges[uentering] as usize;
498 let vid = self.parent_nodes[uentering] as usize;
499 let sigma = self.potentials[vid] - self.potentials[uentering] + oriented_flow(eid, self.costs[eid / 2]);
500 let uend = self.next_preorder[self.last_preorder[uentering] as usize] as usize;
501 let mut uid = uentering;
502 while uid != uend {
503 self.potentials[uid] += sigma;
504 uid = self.next_preorder[uid] as usize;
505 }
506 }
507
508 fn augment_cycle(&mut self, e_in: ID) -> bool {
509 let e_in = e_in as usize;
510
511 let (mut u_in, mut v_in) = if (e_in & 1) == 0 {
513 (self.sources[e_in / 2] as usize, self.sinks[e_in / 2] as usize)
514 } else {
515 (self.sinks[e_in / 2] as usize, self.sources[e_in / 2] as usize)
516 };
517
518 let mut d = self.caps[e_in / 2];
520
521 let mut v_out = None;
523 let mut e_out_fwd = true;
524 let mut uid = u_in;
525 let mut vid = v_in;
526 while uid != vid {
527 let fwd = self.subtrees[uid] < self.subtrees[vid];
528 let nodeid = if fwd { uid } else { vid };
531
532 let f = self.parent_edges[nodeid] as usize;
533
534 let flw = if ((f & 1) != 0) == fwd {
535 self.flows[f / 2]
536 } else if self.caps[f / 2] != self.infinite {
537 self.caps[f / 2] - self.flows[f / 2]
538 } else {
539 self.infinite
540 };
541
542 if flw < d {
543 d = flw;
544 v_out = Some(nodeid);
545 e_out_fwd = fwd;
546 }
547
548 if fwd {
549 uid = self.parent_nodes[uid] as usize
550 } else {
551 vid = self.parent_nodes[vid] as usize
552 };
553 }
554
555 if d >= self.infinite {
556 return false;
557 }
558
559 let ancestorid = vid;
562
563 self.flows[e_in / 2] = if self.state[e_in / 2] == 1 {
565 d
566 } else {
567 self.caps[e_in / 2] - d
568 };
569
570 let v_out = if let Some(m) = v_out {
572 m
573 } else {
574 self.state[e_in / 2] = -self.state[e_in / 2];
576 let mut uid = u_in;
578 let mut vid = v_in;
579 while uid != ancestorid {
580 let f = self.parent_edges[uid] as usize;
581 self.flows[f / 2] += oriented_flow(f, d);
582 uid = self.parent_nodes[uid] as usize;
583 }
584 while vid != ancestorid {
585 let f = self.parent_edges[vid] as usize;
586 self.flows[f / 2] -= oriented_flow(f, d);
587 vid = self.parent_nodes[vid] as usize;
588 }
589 return true;
591 };
592 let u_out = self.parent_nodes[v_out] as usize;
593
594 self.state[e_in / 2] = 0; let e_in = if e_out_fwd {
602 let e_out = self.parent_edges[v_out] as usize;
603 self.state[e_out / 2] = if (e_out & 1) == 0 { -1 } else { 1 };
604 e_in
605 } else {
606 let e_out = self.parent_edges[v_out] as usize;
607 self.state[e_out / 2] = if (e_out & 1) == 0 { 1 } else { -1 };
608 d = -d;
610 std::mem::swap(&mut u_in, &mut v_in);
611 e_in ^ 1
612 };
613
614 let mut uid = u_in;
615 let mut vid = v_in;
616 let orig_v_out_last = self.last_preorder[v_out];
617 let orig_v_out_prev = self.prev_preorder[v_out];
618 let orig_v_in_last = self.last_preorder[v_in];
619 let orig_ancestor_last = self.last_preorder[ancestorid];
620
621 if u_in == v_out && v_in == self.parent_nodes[v_out] as usize {
623 let fid = self.parent_edges[v_out] as usize;
624 self.flows[fid / 2] += oriented_flow(fid, d);
625 self.parent_edges[u_in] = e_in as ID ^ 1;
626 self.update_node_potentials(u_in);
627 return true;
628 }
629
630 let subtreediff = self.subtrees[v_out];
633 let mut childsubtree = 0;
634
635 let mut e_add = e_in;
651 let mut orig_u_last = self.last_preorder[u_in] as usize;
652 let mut orig_u_prev = self.prev_preorder[u_in] as usize;
653 while vid != v_out {
654 let wid = self.parent_nodes[uid] as usize;
655 let w_last = self.last_preorder[wid] as usize;
656 let w_prev = self.prev_preorder[wid] as usize;
657
658 if w_last == orig_u_last {
661 self.last_preorder[wid] = orig_u_prev as ID;
662 }
663
664 let u_last = self.last_preorder[uid] as usize;
666 let u_prev = self.prev_preorder[uid] as usize;
667 self.next_preorder[u_prev] = self.next_preorder[u_last];
668 if self.next_preorder[u_last] != ID::max_value() {
669 self.prev_preorder[self.next_preorder[u_last] as usize] = u_prev as ID;
670 }
671
672 self.prev_preorder[uid] = vid as ID;
674 self.next_preorder[u_last] = self.next_preorder[vid];
675 if self.next_preorder[vid] != ID::max_value() {
676 self.prev_preorder[self.next_preorder[vid] as usize] = u_last as ID;
677 }
678 self.next_preorder[vid] = uid as ID;
679
680 let e_del = self.parent_edges[uid] as usize;
681 self.parent_edges[uid] = e_add as ID ^ 1; self.parent_nodes[uid] = vid as ID;
683
684 self.flows[e_del / 2] += oriented_flow(e_del, d);
685
686 let usubtree = self.subtrees[uid];
689 self.subtrees[uid] = subtreediff - childsubtree;
690 childsubtree = usubtree;
691
692 vid = uid;
694 uid = wid;
695 orig_u_last = w_last;
696 orig_u_prev = w_prev;
697 e_add = e_del;
698 }
699
700 {
703 let mut vid = self.parent_nodes[v_out] as usize;
707 let mut last = self.last_preorder[v_out];
708 while vid != v_in {
709 if self.last_preorder[vid] as usize == vid {
713 self.last_preorder[vid] = last;
714 } else {
715 last = self.last_preorder[vid];
716 }
717 vid = self.parent_nodes[vid] as usize;
718 }
719 }
720
721 {
726 let mut uid = u_out;
727 while uid != ancestorid {
728 if self.last_preorder[uid] == orig_v_out_last {
729 self.last_preorder[uid] = orig_v_out_prev;
730 }
731 let eid = self.parent_edges[uid] as usize;
733 self.flows[eid / 2] += oriented_flow(eid, d);
734 self.subtrees[uid] -= subtreediff;
735 uid = self.parent_nodes[uid] as usize;
736 }
737 }
738
739 {
745 let u_in_last = self.last_preorder[u_in];
746 let bad_last = if v_in == orig_v_in_last as usize {
747 orig_v_in_last
748 } else {
749 ID::max_value() };
751 let mut vid = v_in;
752 while vid != ancestorid {
753 if self.last_preorder[vid] == bad_last {
754 self.last_preorder[vid] = u_in_last;
755 }
756 let eid = self.parent_edges[vid] as usize;
757 self.flows[eid / 2] -= oriented_flow(eid, d);
758 self.subtrees[vid] += subtreediff;
759 vid = self.parent_nodes[vid] as usize;
760 }
761 }
762
763 let (old, new) = if u_out == ancestorid && orig_ancestor_last == orig_v_out_last {
767 if orig_v_out_prev as usize == v_in {
770 self.last_preorder[ancestorid] = orig_ancestor_last;
771 (orig_v_out_last, self.last_preorder[u_in])
772 } else {
773 self.last_preorder[ancestorid] = orig_ancestor_last;
774 (orig_v_out_last, orig_v_out_prev)
775 }
776 } else if orig_ancestor_last == orig_v_out_last {
777 (orig_v_out_last, orig_v_out_prev)
778 } else if orig_ancestor_last == orig_v_in_last {
779 if u_out == ancestorid {
780 self.last_preorder[ancestorid] = orig_ancestor_last;
782 }
783 (orig_v_in_last, self.last_preorder[v_in])
784 } else {
785 (ID::max_value(), ID::max_value())
786 };
787
788 if old != ID::max_value() {
789 let mut uid = ancestorid;
790 while uid != ID::max_value() as usize && self.last_preorder[uid] == old {
791 self.last_preorder[uid] = new;
792 uid = self.parent_nodes[uid] as usize;
793 }
794 }
795
796 self.update_node_potentials(u_in);
798
799 true
800 }
801
802 fn check_feasibility(&mut self) -> bool {
803 self.flows[self.graph.num_edges()..].iter().all(|&x| x <= self.zero)
804 }
805
806 fn find_entering_edge(&mut self) -> Option<ID> {
807 match self.pricing {
808 Pricing::RoundRobin => self.round_robin_pricing(),
809 Pricing::Complete => self.complete_pricing(),
810 Pricing::Block => self.block_pricing(),
811 Pricing::MultiplePartial => self.multiple_partial_pricing(),
812 }
813 }
814
815 fn round_robin_pricing(&mut self) -> Option<ID> {
816 let mut eid = self.current_edge as usize;
817 loop {
818 if self.reduced_cost(eid) < F::zero() {
819 self.current_edge = eid as ID;
820 return Some(self.oriented_edge(eid));
821 }
822 eid = (eid + 1) % self.graph.num_edges();
823 if eid == self.current_edge as usize {
824 return None;
825 }
826 }
827 }
828
829 fn complete_pricing(&mut self) -> Option<ID> {
830 let mut min_cost = F::zero();
831 let mut min_edge = None;
832 for eid in 0..self.graph.num_edges() {
833 let c = self.reduced_cost(eid);
834 if c < min_cost {
835 min_cost = c;
836 min_edge = Some(eid);
837 }
838 }
839
840 min_edge.map(|eid| self.oriented_edge(eid))
841 }
842
843 fn block_pricing(&mut self) -> Option<ID> {
844 let mut end = self.graph.num_edges();
845 let mut eid = self.current_edge as usize % end;
846 let mut min_edge = None;
847 let mut min_cost = F::zero();
848 let mut m = (eid + self.block_size).min(end);
849 let mut cnt = self.block_size.min(end);
850
851 loop {
852 while eid < m {
853 let c = self.reduced_cost(eid);
854 if c < min_cost {
855 min_cost = c;
856 min_edge = Some(eid);
857 }
858 cnt -= 1;
859 eid += 1;
860 }
861
862 if cnt == 0 {
863 m = (eid + self.block_size).min(end);
865 cnt = self.block_size.min(end);
866 } else if eid != self.current_edge as usize {
867 end = self.current_edge as usize;
870 eid = 0;
871 m = cnt.min(end);
872 continue;
873 }
874
875 if let Some(enteringid) = min_edge {
876 self.current_edge = eid as ID;
877 return Some(self.oriented_edge(enteringid));
878 }
879
880 if eid == self.current_edge as usize {
881 return None;
882 }
883 }
884 }
885
886 fn multiple_partial_pricing(&mut self) -> Option<ID> {
887 todo!()
888 }
889
890 fn reduced_cost(&self, eid: usize) -> F {
891 unsafe {
892 F::from(*self.state.get_unchecked(eid)).unwrap()
893 * (*self.costs.get_unchecked(eid)
894 - *self.potentials.get_unchecked(*self.sinks.get_unchecked(eid) as usize)
895 + *self.potentials.get_unchecked(*self.sources.get_unchecked(eid) as usize))
896 }
897 }
898
899 fn oriented_edge(&self, eid: usize) -> ID {
900 let eid = if self.state[eid] == 1 { eid * 2 } else { (eid * 2) | 1 };
901 eid as ID
902 }
903}
904
905fn oriented_flow<F>(eid: usize, d: F) -> F
906where
907 F: NumAssign + NumCast,
908{
909 (F::one() - F::from((eid & 1) * 2).unwrap()) * d
910}
911
912pub fn network_simplex<G, F, Bs, Ls, Us, Cs>(
916 g: &G,
917 balances: Bs,
918 lower: Ls,
919 upper: Us,
920 costs: Cs,
921) -> Option<(F, Vec<(G::Edge<'_>, F)>)>
922where
923 G: IndexDigraph,
924 F: NumAssign + NumCast + FromPrimitive + Ord + Signed + Bounded + Copy,
925 Bs: Fn(G::Node<'_>) -> F,
926 Ls: Fn(G::Edge<'_>) -> F,
927 Us: Fn(G::Edge<'_>) -> F,
928 Cs: Fn(G::Edge<'_>) -> F,
929{
930 let mut spx = NetworkSimplex::new(g);
931 spx.set_balances(balances);
932 spx.set_lowers(lower);
933 spx.set_uppers(upper);
934 spx.set_costs(costs);
935 if spx.solve() == SolutionState::Optimal {
936 Some((spx.value(), g.edges().map(|e| (e, spx.flow(e))).collect()))
937 } else {
938 None
939 }
940}