1#[derive(Debug, Clone)]
31pub struct MaxFlowResult {
32 pub flow: i64,
34 pub steps: usize,
36 pub edge_flow: Vec<i64>,
38}
39
40#[derive(Debug, Clone, Default)]
42pub struct PhaseTiming {
43 pub relabel_us: u64,
45 pub pull_us: u64,
47 pub push_us: u64,
49 pub convergence_us: u64,
51 pub relabel_skipped: usize,
53}
54
55#[derive(Debug, Clone)]
57pub struct TimedMaxFlowResult {
58 pub result: MaxFlowResult,
60 pub timing: PhaseTiming,
62}
63
64struct TideState {
70 n: usize,
71 source: usize,
72 sink: usize,
73
74 head: Vec<usize>,
77 adj_edges: Vec<usize>,
80 fwd_end: Vec<usize>,
83
84 to: Vec<usize>,
87 cap: Vec<i64>,
89 flow: Vec<i64>,
91
92 height: Vec<i32>,
95 excess: Vec<i64>,
97 #[allow(dead_code)]
99 level: Vec<i32>,
100
101 max_level: usize,
104 level_buckets: Vec<Vec<usize>>,
106
107 bfs_cur: Vec<usize>,
110 bfs_next: Vec<usize>,
111 dist_buf1: Vec<i32>,
113 dist_buf2: Vec<i32>,
114
115 topology_changed: bool,
117 steps: usize,
118}
119
120impl TideState {
121 fn new(n: usize, source: usize, sink: usize, edges: &[(usize, usize, i64)]) -> Self {
122 let m = edges.len();
123 let total = 2 * m;
124
125 let mut to = vec![0usize; total];
126 let mut cap = vec![0i64; total];
127
128 for (i, &(u, v, c)) in edges.iter().enumerate() {
129 let fwd = 2 * i;
130 let rev = 2 * i + 1;
131 to[fwd] = v;
132 to[rev] = u;
133 cap[fwd] = c;
134 cap[rev] = 0;
135 }
136
137 let mut fwd_deg = vec![0u32; n];
140 let mut rev_deg = vec![0u32; n];
141 for (i, &(u, v, _)) in edges.iter().enumerate() {
142 let _ = i;
143 fwd_deg[u] += 1;
144 rev_deg[v] += 1;
145 }
146
147 let mut head = vec![0usize; n + 1];
149 let mut fwd_end = vec![0usize; n];
150 for v in 0..n {
151 head[v + 1] = head[v] + (fwd_deg[v] + rev_deg[v]) as usize;
152 fwd_end[v] = head[v] + fwd_deg[v] as usize;
153 }
154 let total_adj = head[n];
155 let mut adj_edges = vec![0usize; total_adj];
156
157 let mut fwd_pos: Vec<usize> = (0..n).map(|v| head[v]).collect();
160 let mut rev_pos: Vec<usize> = fwd_end.clone();
161
162 for (i, &(u, v, _)) in edges.iter().enumerate() {
163 let fwd = 2 * i;
164 let rev = 2 * i + 1;
165 adj_edges[fwd_pos[u]] = fwd;
166 fwd_pos[u] += 1;
167 adj_edges[rev_pos[v]] = rev;
168 rev_pos[v] += 1;
169 }
170 drop(fwd_deg);
171 drop(rev_deg);
172 drop(fwd_pos);
173 drop(rev_pos);
174
175 let flow = vec![0i64; total];
176 let height = vec![0i32; n];
177 let excess = vec![0i64; n];
178
179 let mut level = vec![-1i32; n];
181 level[source] = 0;
182 let mut bfs_cur = vec![source];
183 let mut bfs_next = Vec::new();
184 while !bfs_cur.is_empty() {
185 for &v in &bfs_cur {
186 for idx in head[v]..fwd_end[v] {
188 let e = adj_edges[idx];
189 let w = to[e];
190 if level[w] == -1 {
191 level[w] = level[v] + 1;
192 bfs_next.push(w);
193 }
194 }
195 }
196 std::mem::swap(&mut bfs_cur, &mut bfs_next);
197 bfs_next.clear();
198 }
199
200 let max_level = level.iter().copied().filter(|&l| l >= 0).max().unwrap_or(0) as usize;
202 let mut level_buckets: Vec<Vec<usize>> = vec![Vec::new(); max_level + 1];
203 for v in 0..n {
204 if v != source && v != sink && level[v] >= 0 {
205 level_buckets[level[v] as usize].push(v);
206 }
207 }
208
209 let dist_buf1 = vec![-1i32; n];
210 let dist_buf2 = vec![-1i32; n];
211
212 TideState {
213 n,
214 source,
215 sink,
216 head,
217 adj_edges,
218 fwd_end,
219 to,
220 cap,
221 flow,
222 height,
223 excess,
224 level,
225 max_level,
226 level_buckets,
227 bfs_cur,
228 bfs_next,
229 dist_buf1,
230 dist_buf2,
231 topology_changed: true,
232 steps: 0,
233 }
234 }
235
236 fn initialize(&mut self) {
238 let source = self.source;
239 for idx in self.head[source]..self.fwd_end[source] {
240 let e = self.adj_edges[idx]; let c = self.cap[e];
242 if c > 0 {
243 self.flow[e] = c;
244 self.flow[e ^ 1] = -c;
245 let v = self.to[e];
246 self.excess[v] += c;
247 self.excess[source] -= c;
248 }
249 }
250 self.height[source] = self.n as i32;
251 }
252
253 fn global_relabel(&mut self) {
256 let n = self.n;
257 let source = self.source;
258 let sink = self.sink;
259
260 let dist_sink = &mut self.dist_buf1;
262 for x in dist_sink.iter_mut() {
263 *x = -1;
264 }
265 dist_sink[sink] = 0;
266
267 self.bfs_cur.clear();
305 self.bfs_cur.push(sink);
306 let mut reached = 1usize;
307
308 while !self.bfs_cur.is_empty() {
309 self.bfs_next.clear();
310 for i in 0..self.bfs_cur.len() {
311 let v = self.bfs_cur[i];
312 let d_next = dist_sink[v] + 1;
313 for idx in self.head[v]..self.head[v + 1] {
314 let e = self.adj_edges[idx];
315 let w = self.to[e];
316 let rev = e ^ 1;
317 if dist_sink[w] == -1 && self.cap[rev] - self.flow[rev] > 0 {
318 dist_sink[w] = d_next;
319 self.bfs_next.push(w);
320 reached += 1;
321 }
322 }
323 }
324 std::mem::swap(&mut self.bfs_cur, &mut self.bfs_next);
325 }
326
327 let need_source_bfs = reached < n;
329 if need_source_bfs {
330 let dist_source = &mut self.dist_buf2;
331 for x in dist_source.iter_mut() {
332 *x = -1;
333 }
334 dist_source[source] = 0;
335
336 self.bfs_cur.clear();
337 self.bfs_cur.push(source);
338
339 while !self.bfs_cur.is_empty() {
340 self.bfs_next.clear();
341 for i in 0..self.bfs_cur.len() {
342 let v = self.bfs_cur[i];
343 let d_next = dist_source[v] + 1;
344 for idx in self.head[v]..self.head[v + 1] {
345 let e = self.adj_edges[idx];
346 let w = self.to[e];
347 if dist_source[w] == -1 && self.cap[e] - self.flow[e] > 0 {
348 dist_source[w] = d_next;
349 self.bfs_next.push(w);
350 }
351 }
352 }
353 std::mem::swap(&mut self.bfs_cur, &mut self.bfs_next);
354 }
355 }
356
357 let n_i32 = n as i32;
359 for v in 0..n {
360 if v == source {
361 self.height[v] = n_i32;
362 } else if v == sink {
363 self.height[v] = 0;
364 } else if self.dist_buf1[v] >= 0 {
365 self.height[v] = self.dist_buf1[v];
366 } else if need_source_bfs && self.dist_buf2[v] >= 0 {
367 self.height[v] = n_i32 + self.dist_buf2[v];
368 }
369 }
370 }
371
372 fn global_push(&mut self) {
375 for lvl in 0..=self.max_level {
376 for i in 0..self.level_buckets[lvl].len() {
377 let v = self.level_buckets[lvl][i];
378 if self.excess[v] <= 0 {
379 continue;
380 }
381 let h_target = self.height[v] - 1;
382 for idx in self.head[v]..self.fwd_end[v] {
383 let e = self.adj_edges[idx]; let w = self.to[e];
385 let res_cap = self.cap[e] - self.flow[e];
386 if self.height[w] == h_target && res_cap > 0 {
387 let delta = self.excess[v].min(res_cap);
388
389 let old_bwd = self.cap[e ^ 1] - self.flow[e ^ 1] > 0;
390
391 self.flow[e] += delta;
392 self.flow[e ^ 1] -= delta;
393 self.excess[v] -= delta;
394 self.excess[w] += delta;
395
396 let new_fwd = self.cap[e] - self.flow[e] > 0;
397 let new_bwd = self.cap[e ^ 1] - self.flow[e ^ 1] > 0;
398 if !new_fwd || (old_bwd != new_bwd) {
399 self.topology_changed = true;
400 }
401
402 if self.excess[v] <= 0 {
403 break;
404 }
405 }
406 }
407 }
408 }
409 }
410
411 fn global_pull(&mut self) {
414 for lvl in (0..=self.max_level).rev() {
415 for i in 0..self.level_buckets[lvl].len() {
416 let v = self.level_buckets[lvl][i];
417 if self.excess[v] <= 0 {
418 continue;
419 }
420 let h_target = self.height[v] - 1;
421 for idx in self.fwd_end[v]..self.head[v + 1] {
422 let e = self.adj_edges[idx]; let fwd = e ^ 1; let u = self.to[e]; let res_cap = self.cap[e] - self.flow[e]; if self.height[u] == h_target && res_cap > 0 {
428 let delta = self.excess[v].min(res_cap);
429
430 let old_fwd = self.cap[fwd] - self.flow[fwd] > 0;
431
432 self.flow[e] += delta;
433 self.flow[fwd] -= delta;
434 self.excess[v] -= delta;
435 self.excess[u] += delta;
436
437 let new_fwd = self.cap[fwd] - self.flow[fwd] > 0;
438 let new_bwd = self.cap[e] - self.flow[e] > 0;
439 if (old_fwd != new_fwd) || !new_bwd {
440 self.topology_changed = true;
441 }
442
443 if self.excess[v] <= 0 {
444 break;
445 }
446 }
447 }
448 }
449 }
450 }
451
452 #[inline]
455 fn local_relabel(&self, v: usize) -> Option<i32> {
456 let mut min_h = i32::MAX;
457
458 for idx in self.head[v]..self.fwd_end[v] {
460 let e = self.adj_edges[idx];
461 if self.cap[e] - self.flow[e] > 0 {
462 min_h = min_h.min(self.height[self.to[e]]);
463 }
464 }
465 for idx in self.fwd_end[v]..self.head[v + 1] {
467 let e = self.adj_edges[idx];
468 if self.cap[e] - self.flow[e] > 0 {
469 min_h = min_h.min(self.height[self.to[e]]);
470 }
471 }
472
473 if min_h == i32::MAX {
474 None
475 } else {
476 Some(min_h + 1)
477 }
478 }
479
480 fn global_pull_relabel(&mut self) {
482 for lvl in (0..=self.max_level).rev() {
483 for i in 0..self.level_buckets[lvl].len() {
484 let v = self.level_buckets[lvl][i];
485 if self.excess[v] <= 0 {
486 continue;
487 }
488
489 let h_target = self.height[v] - 1;
490 let mut pulled = false;
491 for idx in self.fwd_end[v]..self.head[v + 1] {
492 let e = self.adj_edges[idx];
493 let fwd = e ^ 1;
494 let u = self.to[e];
495 let res_cap = self.cap[e] - self.flow[e];
496 if self.height[u] == h_target && res_cap > 0 {
497 let delta = self.excess[v].min(res_cap);
498 let old_fwd = self.cap[fwd] - self.flow[fwd] > 0;
499 self.flow[e] += delta;
500 self.flow[fwd] -= delta;
501 self.excess[v] -= delta;
502 self.excess[u] += delta;
503 let new_fwd = self.cap[fwd] - self.flow[fwd] > 0;
504 let new_bwd = self.cap[e] - self.flow[e] > 0;
505 if (old_fwd != new_fwd) || !new_bwd {
506 self.topology_changed = true;
507 }
508 pulled = true;
509 if self.excess[v] <= 0 {
510 break;
511 }
512 }
513 }
514
515 if !pulled && self.excess[v] > 0 {
516 if let Some(new_h) = self.local_relabel(v) {
517 if new_h > self.height[v] {
518 self.height[v] = new_h;
519 let h_target = new_h - 1;
520 for idx in self.fwd_end[v]..self.head[v + 1] {
521 let e = self.adj_edges[idx];
522 let fwd = e ^ 1;
523 let u = self.to[e];
524 let res_cap = self.cap[e] - self.flow[e];
525 if self.height[u] == h_target && res_cap > 0 {
526 let delta = self.excess[v].min(res_cap);
527 let old_fwd = self.cap[fwd] - self.flow[fwd] > 0;
528 self.flow[e] += delta;
529 self.flow[fwd] -= delta;
530 self.excess[v] -= delta;
531 self.excess[u] += delta;
532 let new_fwd = self.cap[fwd] - self.flow[fwd] > 0;
533 let new_bwd = self.cap[e] - self.flow[e] > 0;
534 if (old_fwd != new_fwd) || !new_bwd {
535 self.topology_changed = true;
536 }
537 if self.excess[v] <= 0 {
538 break;
539 }
540 }
541 }
542 }
543 }
544 }
545 }
546 }
547 }
548
549 fn global_push_relabel(&mut self) {
551 for lvl in 0..=self.max_level {
552 for i in 0..self.level_buckets[lvl].len() {
553 let v = self.level_buckets[lvl][i];
554 if self.excess[v] <= 0 {
555 continue;
556 }
557
558 let h_target = self.height[v] - 1;
559 let mut pushed = false;
560 for idx in self.head[v]..self.fwd_end[v] {
561 let e = self.adj_edges[idx];
562 let w = self.to[e];
563 let res_cap = self.cap[e] - self.flow[e];
564 if self.height[w] == h_target && res_cap > 0 {
565 let delta = self.excess[v].min(res_cap);
566 let old_bwd = self.cap[e ^ 1] - self.flow[e ^ 1] > 0;
567 self.flow[e] += delta;
568 self.flow[e ^ 1] -= delta;
569 self.excess[v] -= delta;
570 self.excess[w] += delta;
571 let new_fwd = self.cap[e] - self.flow[e] > 0;
572 let new_bwd = self.cap[e ^ 1] - self.flow[e ^ 1] > 0;
573 if !new_fwd || (old_bwd != new_bwd) {
574 self.topology_changed = true;
575 }
576 pushed = true;
577 if self.excess[v] <= 0 {
578 break;
579 }
580 }
581 }
582
583 if !pushed && self.excess[v] > 0 {
584 if let Some(new_h) = self.local_relabel(v) {
585 if new_h > self.height[v] {
586 self.height[v] = new_h;
587 let h_target = new_h - 1;
588 for idx in self.head[v]..self.fwd_end[v] {
589 let e = self.adj_edges[idx];
590 let w = self.to[e];
591 let res_cap = self.cap[e] - self.flow[e];
592 if self.height[w] == h_target && res_cap > 0 {
593 let delta = self.excess[v].min(res_cap);
594 let old_bwd = self.cap[e ^ 1] - self.flow[e ^ 1] > 0;
595 self.flow[e] += delta;
596 self.flow[e ^ 1] -= delta;
597 self.excess[v] -= delta;
598 self.excess[w] += delta;
599 let new_fwd = self.cap[e] - self.flow[e] > 0;
600 let new_bwd = self.cap[e ^ 1] - self.flow[e ^ 1] > 0;
601 if !new_fwd || (old_bwd != new_bwd) {
602 self.topology_changed = true;
603 }
604 if self.excess[v] <= 0 {
605 break;
606 }
607 }
608 }
609 }
610 }
611 }
612 }
613 }
614 }
615
616 fn tide_hybrid(&mut self) -> MaxFlowResult {
622 self.initialize();
623
624 let step_budget = 10 * self.n * self.n;
628 let mut bfs_stall_count = 0u32;
629
630 loop {
631 let (old_flow, old_hash) = self.convergence_state();
633 self.global_relabel();
634 self.topology_changed = false;
635 self.global_pull();
636 self.global_push();
637 self.steps += 1;
638
639 let (bfs_flow, bfs_hash) = self.convergence_state();
640
641 if bfs_flow == old_flow && bfs_hash == old_hash {
643 break;
644 }
645
646 if bfs_flow <= old_flow {
648 bfs_stall_count += 1;
649 if bfs_stall_count >= 3 {
650 break;
652 }
653 } else {
654 bfs_stall_count = 0;
655 }
656
657 if self.steps > step_budget {
659 continue; }
661
662 let mut prev_flow = bfs_flow;
665 let mut stall_count = 0u32;
666 loop {
667 let (_, old_hash2) = self.convergence_state();
668 self.topology_changed = false;
669 self.global_pull_relabel();
670 self.global_push_relabel();
671 self.steps += 1;
672
673 let (new_flow2, new_hash2) = self.convergence_state();
674
675 if new_flow2 == prev_flow && new_hash2 == old_hash2 {
677 break;
678 }
679
680 if new_flow2 > prev_flow {
681 prev_flow = new_flow2;
683 stall_count = 0;
684 } else {
685 stall_count += 1;
687 if stall_count >= 2 {
688 break;
689 }
690 }
691 }
692 }
693
694 loop {
697 let (old_flow, old_hash) = self.convergence_state();
698 self.global_relabel();
699 self.topology_changed = false;
700 self.global_pull();
701 self.global_push();
702 self.steps += 1;
703 let (new_flow, new_hash) = self.convergence_state();
704 if new_flow == old_flow && new_hash == old_hash {
705 break;
706 }
707 }
708
709 let (flow, _) = self.convergence_state();
710 MaxFlowResult {
711 flow,
712 steps: self.steps,
713 edge_flow: self.flow.clone(),
714 }
715 }
716
717 fn tide_hybrid_timed(&mut self) -> TimedMaxFlowResult {
719 use std::time::Instant;
720 self.initialize();
721 let mut timing = PhaseTiming::default();
722 let step_budget = 10 * self.n * self.n;
723 let mut bfs_stall_count = 0u32;
724
725 loop {
726 let tc0 = Instant::now();
728 let (old_flow, old_hash) = self.convergence_state();
729 let tc1 = Instant::now();
730 timing.convergence_us += tc1.duration_since(tc0).as_micros() as u64;
731
732 let tb0 = Instant::now();
733 self.global_relabel();
734 let tb1 = Instant::now();
735 timing.relabel_us += tb1.duration_since(tb0).as_micros() as u64;
736 self.topology_changed = false;
737
738 let tp0 = Instant::now();
739 self.global_pull();
740 let tp1 = Instant::now();
741 timing.pull_us += tp1.duration_since(tp0).as_micros() as u64;
742
743 let ts0 = Instant::now();
744 self.global_push();
745 let ts1 = Instant::now();
746 timing.push_us += ts1.duration_since(ts0).as_micros() as u64;
747 self.steps += 1;
748
749 let tc2 = Instant::now();
750 let (bfs_flow, bfs_hash) = self.convergence_state();
751 let tc3 = Instant::now();
752 timing.convergence_us += tc3.duration_since(tc2).as_micros() as u64;
753
754 if bfs_flow == old_flow && bfs_hash == old_hash {
755 break;
756 }
757
758 if bfs_flow <= old_flow {
759 bfs_stall_count += 1;
760 if bfs_stall_count >= 3 {
761 break;
762 }
763 } else {
764 bfs_stall_count = 0;
765 }
766
767 if self.steps > step_budget {
768 continue;
769 }
770
771 let mut prev_flow = bfs_flow;
773 let mut stall_count = 0u32;
774 loop {
775 let tc4 = Instant::now();
776 let (_, old_hash2) = self.convergence_state();
777 let tc5 = Instant::now();
778 timing.convergence_us += tc5.duration_since(tc4).as_micros() as u64;
779 timing.relabel_skipped += 1;
780 self.topology_changed = false;
781
782 let t2 = Instant::now();
783 self.global_pull_relabel();
784 let t3 = Instant::now();
785 timing.pull_us += t3.duration_since(t2).as_micros() as u64;
786
787 let t4 = Instant::now();
788 self.global_push_relabel();
789 let t5 = Instant::now();
790 timing.push_us += t5.duration_since(t4).as_micros() as u64;
791 self.steps += 1;
792
793 let tc6 = Instant::now();
794 let (new_flow2, new_hash2) = self.convergence_state();
795 let tc7 = Instant::now();
796 timing.convergence_us += tc7.duration_since(tc6).as_micros() as u64;
797
798 if new_flow2 == prev_flow && new_hash2 == old_hash2 {
799 break;
800 }
801
802 if new_flow2 > prev_flow {
803 prev_flow = new_flow2;
804 stall_count = 0;
805 } else {
806 stall_count += 1;
807 if stall_count >= 2 {
808 break;
809 }
810 }
811 }
812 }
813
814 loop {
816 let tc0 = Instant::now();
817 let (old_flow, old_hash) = self.convergence_state();
818 let tc1 = Instant::now();
819 timing.convergence_us += tc1.duration_since(tc0).as_micros() as u64;
820
821 let tb0 = Instant::now();
822 self.global_relabel();
823 let tb1 = Instant::now();
824 timing.relabel_us += tb1.duration_since(tb0).as_micros() as u64;
825 self.topology_changed = false;
826
827 let tp0 = Instant::now();
828 self.global_pull();
829 let tp1 = Instant::now();
830 timing.pull_us += tp1.duration_since(tp0).as_micros() as u64;
831
832 let ts0 = Instant::now();
833 self.global_push();
834 let ts1 = Instant::now();
835 timing.push_us += ts1.duration_since(ts0).as_micros() as u64;
836 self.steps += 1;
837
838 let tc2 = Instant::now();
839 let (new_flow, new_hash) = self.convergence_state();
840 let tc3 = Instant::now();
841 timing.convergence_us += tc3.duration_since(tc2).as_micros() as u64;
842
843 if new_flow == old_flow && new_hash == old_hash {
844 break;
845 }
846 }
847
848 let (flow, _) = self.convergence_state();
849 TimedMaxFlowResult {
850 result: MaxFlowResult {
851 flow,
852 steps: self.steps,
853 edge_flow: self.flow.clone(),
854 },
855 timing,
856 }
857 }
858
859 fn convergence_state(&self) -> (i64, u64) {
862 let mut flow = 0i64;
864 for idx in self.fwd_end[self.sink]..self.head[self.sink + 1] {
865 let e = self.adj_edges[idx]; flow += self.flow[e ^ 1]; }
868
869 let mut hash = 0u64;
871 for v in 0..self.n {
872 if v != self.source && v != self.sink && self.excess[v] > 0 {
873 hash ^= (v as u64).wrapping_mul(0x9E3779B97F4A7C15)
874 ^ (self.excess[v] as u64).wrapping_mul(0x517CC1B727220A95);
875 }
876 }
877
878 (flow, hash)
879 }
880
881 fn tide_adaptive(&mut self) -> MaxFlowResult {
890 const WARMUP: usize = 5;
891 self.initialize();
892
893 for _ in 0..WARMUP {
895 let (old_flow, old_hash) = self.convergence_state();
896 if self.topology_changed {
897 self.global_relabel();
898 }
899 self.topology_changed = false;
900 self.global_pull();
901 self.global_push();
902 self.steps += 1;
903 let (new_flow, new_hash) = self.convergence_state();
904 if new_flow == old_flow && new_hash == old_hash {
905 let (flow, _) = self.convergence_state();
906 return MaxFlowResult {
907 flow,
908 steps: self.steps,
909 edge_flow: self.flow.clone(),
910 };
911 }
912 }
913
914 let step_budget = 10 * self.n * self.n;
916 let mut bfs_stall_count = 0u32;
917
918 loop {
919 let (old_flow, old_hash) = self.convergence_state();
921 self.global_relabel();
922 self.topology_changed = false;
923 self.global_pull();
924 self.global_push();
925 self.steps += 1;
926
927 let (bfs_flow, bfs_hash) = self.convergence_state();
928 if bfs_flow == old_flow && bfs_hash == old_hash {
929 break;
930 }
931
932 if bfs_flow <= old_flow {
933 bfs_stall_count += 1;
934 if bfs_stall_count >= 3 {
935 break;
936 }
937 } else {
938 bfs_stall_count = 0;
939 }
940
941 if self.steps > step_budget {
942 continue;
943 }
944
945 let mut prev_flow = bfs_flow;
947 let mut stall_count = 0u32;
948 loop {
949 let (_, old_hash2) = self.convergence_state();
950 self.topology_changed = false;
951 self.global_pull_relabel();
952 self.global_push_relabel();
953 self.steps += 1;
954
955 let (new_flow2, new_hash2) = self.convergence_state();
956 if new_flow2 == prev_flow && new_hash2 == old_hash2 {
957 break;
958 }
959 if new_flow2 > prev_flow {
960 prev_flow = new_flow2;
961 stall_count = 0;
962 } else {
963 stall_count += 1;
964 if stall_count >= 2 {
965 break;
966 }
967 }
968 }
969 }
970
971 loop {
973 let (old_flow, old_hash) = self.convergence_state();
974 self.global_relabel();
975 self.topology_changed = false;
976 self.global_pull();
977 self.global_push();
978 self.steps += 1;
979 let (new_flow, new_hash) = self.convergence_state();
980 if new_flow == old_flow && new_hash == old_hash {
981 break;
982 }
983 }
984
985 let (flow, _) = self.convergence_state();
986 MaxFlowResult {
987 flow,
988 steps: self.steps,
989 edge_flow: self.flow.clone(),
990 }
991 }
992
993 fn tide_adaptive_timed(&mut self) -> TimedMaxFlowResult {
995 use std::time::Instant;
996 const WARMUP: usize = 5;
997 self.initialize();
998 let mut timing = PhaseTiming::default();
999
1000 for _ in 0..WARMUP {
1002 let t0 = Instant::now();
1003 let (old_flow, old_hash) = self.convergence_state();
1004 let t1 = Instant::now();
1005 timing.convergence_us += t1.duration_since(t0).as_micros() as u64;
1006
1007 if self.topology_changed {
1008 let t2 = Instant::now();
1009 self.global_relabel();
1010 let t3 = Instant::now();
1011 timing.relabel_us += t3.duration_since(t2).as_micros() as u64;
1012 } else {
1013 timing.relabel_skipped += 1;
1014 }
1015 self.topology_changed = false;
1016
1017 let t4 = Instant::now();
1018 self.global_pull();
1019 let t5 = Instant::now();
1020 timing.pull_us += t5.duration_since(t4).as_micros() as u64;
1021
1022 let t6 = Instant::now();
1023 self.global_push();
1024 let t7 = Instant::now();
1025 timing.push_us += t7.duration_since(t6).as_micros() as u64;
1026 self.steps += 1;
1027
1028 let t8 = Instant::now();
1029 let (new_flow, new_hash) = self.convergence_state();
1030 let t9 = Instant::now();
1031 timing.convergence_us += t9.duration_since(t8).as_micros() as u64;
1032
1033 if new_flow == old_flow && new_hash == old_hash {
1034 let (flow, _) = self.convergence_state();
1035 return TimedMaxFlowResult {
1036 result: MaxFlowResult {
1037 flow,
1038 steps: self.steps,
1039 edge_flow: self.flow.clone(),
1040 },
1041 timing,
1042 };
1043 }
1044 }
1045
1046 let step_budget = 10 * self.n * self.n;
1048 let mut bfs_stall_count = 0u32;
1049
1050 loop {
1051 let tc0 = Instant::now();
1052 let (old_flow, old_hash) = self.convergence_state();
1053 let tc1 = Instant::now();
1054 timing.convergence_us += tc1.duration_since(tc0).as_micros() as u64;
1055
1056 let tb0 = Instant::now();
1057 self.global_relabel();
1058 let tb1 = Instant::now();
1059 timing.relabel_us += tb1.duration_since(tb0).as_micros() as u64;
1060 self.topology_changed = false;
1061
1062 let tp0 = Instant::now();
1063 self.global_pull();
1064 let tp1 = Instant::now();
1065 timing.pull_us += tp1.duration_since(tp0).as_micros() as u64;
1066
1067 let ts0 = Instant::now();
1068 self.global_push();
1069 let ts1 = Instant::now();
1070 timing.push_us += ts1.duration_since(ts0).as_micros() as u64;
1071 self.steps += 1;
1072
1073 let tc2 = Instant::now();
1074 let (bfs_flow, bfs_hash) = self.convergence_state();
1075 let tc3 = Instant::now();
1076 timing.convergence_us += tc3.duration_since(tc2).as_micros() as u64;
1077
1078 if bfs_flow == old_flow && bfs_hash == old_hash {
1079 break;
1080 }
1081
1082 if bfs_flow <= old_flow {
1083 bfs_stall_count += 1;
1084 if bfs_stall_count >= 3 {
1085 break;
1086 }
1087 } else {
1088 bfs_stall_count = 0;
1089 }
1090
1091 if self.steps > step_budget {
1092 continue;
1093 }
1094
1095 let mut prev_flow = bfs_flow;
1097 let mut stall_count = 0u32;
1098 loop {
1099 let tc4 = Instant::now();
1100 let (_, old_hash2) = self.convergence_state();
1101 let tc5 = Instant::now();
1102 timing.convergence_us += tc5.duration_since(tc4).as_micros() as u64;
1103 timing.relabel_skipped += 1;
1104 self.topology_changed = false;
1105
1106 let t2 = Instant::now();
1107 self.global_pull_relabel();
1108 let t3 = Instant::now();
1109 timing.pull_us += t3.duration_since(t2).as_micros() as u64;
1110
1111 let t4 = Instant::now();
1112 self.global_push_relabel();
1113 let t5 = Instant::now();
1114 timing.push_us += t5.duration_since(t4).as_micros() as u64;
1115 self.steps += 1;
1116
1117 let tc6 = Instant::now();
1118 let (new_flow2, new_hash2) = self.convergence_state();
1119 let tc7 = Instant::now();
1120 timing.convergence_us += tc7.duration_since(tc6).as_micros() as u64;
1121
1122 if new_flow2 == prev_flow && new_hash2 == old_hash2 {
1123 break;
1124 }
1125 if new_flow2 > prev_flow {
1126 prev_flow = new_flow2;
1127 stall_count = 0;
1128 } else {
1129 stall_count += 1;
1130 if stall_count >= 2 {
1131 break;
1132 }
1133 }
1134 }
1135 }
1136
1137 loop {
1139 let tc0 = Instant::now();
1140 let (old_flow, old_hash) = self.convergence_state();
1141 let tc1 = Instant::now();
1142 timing.convergence_us += tc1.duration_since(tc0).as_micros() as u64;
1143
1144 let tb0 = Instant::now();
1145 self.global_relabel();
1146 let tb1 = Instant::now();
1147 timing.relabel_us += tb1.duration_since(tb0).as_micros() as u64;
1148 self.topology_changed = false;
1149
1150 let tp0 = Instant::now();
1151 self.global_pull();
1152 let tp1 = Instant::now();
1153 timing.pull_us += tp1.duration_since(tp0).as_micros() as u64;
1154
1155 let ts0 = Instant::now();
1156 self.global_push();
1157 let ts1 = Instant::now();
1158 timing.push_us += ts1.duration_since(ts0).as_micros() as u64;
1159 self.steps += 1;
1160
1161 let tc2 = Instant::now();
1162 let (new_flow, new_hash) = self.convergence_state();
1163 let tc3 = Instant::now();
1164 timing.convergence_us += tc3.duration_since(tc2).as_micros() as u64;
1165
1166 if new_flow == old_flow && new_hash == old_hash {
1167 break;
1168 }
1169 }
1170
1171 let (flow, _) = self.convergence_state();
1172 TimedMaxFlowResult {
1173 result: MaxFlowResult {
1174 flow,
1175 steps: self.steps,
1176 edge_flow: self.flow.clone(),
1177 },
1178 timing,
1179 }
1180 }
1181
1182 fn tide(&mut self) -> MaxFlowResult {
1184 self.initialize();
1185
1186 loop {
1187 let (old_flow, old_hash) = self.convergence_state();
1188
1189 if self.topology_changed {
1190 self.global_relabel();
1191 }
1192 self.topology_changed = false;
1193
1194 self.global_pull();
1195 self.global_push();
1196 self.steps += 1;
1197
1198 let (new_flow, new_hash) = self.convergence_state();
1199
1200 if new_flow == old_flow && new_hash == old_hash {
1201 break;
1202 }
1203 }
1204
1205 let (flow, _) = self.convergence_state();
1206 MaxFlowResult {
1207 flow,
1208 steps: self.steps,
1209 edge_flow: self.flow.clone(),
1210 }
1211 }
1212
1213 fn tide_timed(&mut self) -> TimedMaxFlowResult {
1215 use std::time::Instant;
1216
1217 self.initialize();
1218 let mut timing = PhaseTiming::default();
1219
1220 loop {
1221 let t0 = Instant::now();
1222 let (old_flow, old_hash) = self.convergence_state();
1223 let t1 = Instant::now();
1224 timing.convergence_us += t1.duration_since(t0).as_micros() as u64;
1225
1226 if self.topology_changed {
1227 let t2 = Instant::now();
1228 self.global_relabel();
1229 let t3 = Instant::now();
1230 timing.relabel_us += t3.duration_since(t2).as_micros() as u64;
1231 } else {
1232 timing.relabel_skipped += 1;
1233 }
1234 self.topology_changed = false;
1235
1236 let t4 = Instant::now();
1237 self.global_pull();
1238 let t5 = Instant::now();
1239 timing.pull_us += t5.duration_since(t4).as_micros() as u64;
1240
1241 let t6 = Instant::now();
1242 self.global_push();
1243 let t7 = Instant::now();
1244 timing.push_us += t7.duration_since(t6).as_micros() as u64;
1245
1246 self.steps += 1;
1247
1248 let t8 = Instant::now();
1249 let (new_flow, new_hash) = self.convergence_state();
1250 let t9 = Instant::now();
1251 timing.convergence_us += t9.duration_since(t8).as_micros() as u64;
1252
1253 if new_flow == old_flow && new_hash == old_hash {
1254 break;
1255 }
1256 }
1257
1258 let (flow, _) = self.convergence_state();
1259 TimedMaxFlowResult {
1260 result: MaxFlowResult {
1261 flow,
1262 steps: self.steps,
1263 edge_flow: self.flow.clone(),
1264 },
1265 timing,
1266 }
1267 }
1268}
1269
1270pub fn max_flow(
1288 n: usize,
1289 source: usize,
1290 sink: usize,
1291 edges: &[(usize, usize, i64)],
1292) -> MaxFlowResult {
1293 let mut state = TideState::new(n, source, sink, edges);
1294 state.tide()
1295}
1296
1297pub fn max_flow_timed(
1302 n: usize,
1303 source: usize,
1304 sink: usize,
1305 edges: &[(usize, usize, i64)],
1306) -> TimedMaxFlowResult {
1307 let mut state = TideState::new(n, source, sink, edges);
1308 state.tide_timed()
1309}
1310
1311pub fn max_flow_hybrid(
1317 n: usize,
1318 source: usize,
1319 sink: usize,
1320 edges: &[(usize, usize, i64)],
1321) -> MaxFlowResult {
1322 let mut state = TideState::new(n, source, sink, edges);
1323 state.tide_hybrid()
1324}
1325
1326pub fn max_flow_adaptive(
1332 n: usize,
1333 source: usize,
1334 sink: usize,
1335 edges: &[(usize, usize, i64)],
1336) -> MaxFlowResult {
1337 let mut state = TideState::new(n, source, sink, edges);
1338 state.tide_adaptive()
1339}
1340
1341pub fn max_flow_adaptive_timed(
1343 n: usize,
1344 source: usize,
1345 sink: usize,
1346 edges: &[(usize, usize, i64)],
1347) -> TimedMaxFlowResult {
1348 let mut state = TideState::new(n, source, sink, edges);
1349 state.tide_adaptive_timed()
1350}
1351
1352pub fn max_flow_hybrid_timed(
1354 n: usize,
1355 source: usize,
1356 sink: usize,
1357 edges: &[(usize, usize, i64)],
1358) -> TimedMaxFlowResult {
1359 let mut state = TideState::new(n, source, sink, edges);
1360 state.tide_hybrid_timed()
1361}
1362
1363#[cfg(test)]
1364mod tests {
1365 use super::*;
1366
1367 #[test]
1368 fn test_simple_path() {
1369 let result = max_flow(3, 0, 2, &[(0, 1, 10), (1, 2, 5)]);
1370 assert_eq!(result.flow, 5);
1371 }
1372
1373 #[test]
1374 fn test_parallel_paths() {
1375 let result = max_flow(4, 0, 3, &[(0, 1, 10), (1, 3, 10), (0, 2, 15), (2, 3, 15)]);
1376 assert_eq!(result.flow, 25);
1377 }
1378
1379 #[test]
1380 fn test_diamond() {
1381 let result = max_flow(
1382 4,
1383 0,
1384 3,
1385 &[(0, 1, 10), (0, 2, 10), (1, 2, 1), (1, 3, 10), (2, 3, 10)],
1386 );
1387 assert_eq!(result.flow, 20);
1388 }
1389
1390 #[test]
1391 fn test_bottleneck() {
1392 let result = max_flow(4, 0, 3, &[(0, 1, 100), (1, 2, 1), (2, 3, 100)]);
1393 assert_eq!(result.flow, 1);
1394 }
1395
1396 #[test]
1397 fn test_no_path() {
1398 let result = max_flow(4, 0, 3, &[(0, 1, 10), (2, 3, 10)]);
1399 assert_eq!(result.flow, 0);
1400 }
1401
1402 #[test]
1403 fn test_single_edge() {
1404 let result = max_flow(2, 0, 1, &[(0, 1, 42)]);
1405 assert_eq!(result.flow, 42);
1406 }
1407
1408 #[test]
1409 fn test_multiple_paths_shared_edge() {
1410 let result = max_flow(
1411 5,
1412 0,
1413 4,
1414 &[(0, 1, 10), (0, 2, 10), (1, 3, 10), (2, 3, 10), (3, 4, 15)],
1415 );
1416 assert_eq!(result.flow, 15);
1417 }
1418
1419 #[test]
1420 fn test_layered_graph() {
1421 let mut edges = Vec::new();
1422 for i in 0..3 {
1423 edges.push((0, i + 1, 10));
1424 }
1425 for i in 0..3 {
1426 for j in 0..3 {
1427 edges.push((i + 1, j + 4, 5));
1428 }
1429 }
1430 for j in 0..3 {
1431 edges.push((j + 4, 7, 10));
1432 }
1433 let result = max_flow(8, 0, 7, &edges);
1434 assert_eq!(result.flow, 30);
1435 }
1436
1437 #[test]
1438 fn test_clrs() {
1439 let result = max_flow(
1440 6,
1441 0,
1442 5,
1443 &[
1444 (0, 1, 16),
1445 (0, 2, 13),
1446 (1, 2, 10),
1447 (1, 3, 12),
1448 (2, 1, 4),
1449 (2, 4, 14),
1450 (3, 2, 9),
1451 (3, 5, 20),
1452 (4, 3, 7),
1453 (4, 5, 4),
1454 ],
1455 );
1456 assert_eq!(result.flow, 23);
1457 }
1458}