Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_net.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
50# ifndef TPL_NET_H
51# define TPL_NET_H
52
53# include <limits>
54# include <set>
55# include <tuple>
56# include <type_traits>
57# include <utility>
58
59# include <tpl_dynDlist.H>
60# include <tpl_dynListStack.H>
61# include <tpl_dynBinHeap.H>
62# include <tpl_dynSetTree.H>
63# include <tpl_dynSetHash.H>
64# include <tpl_random_queue.H>
65# include <tpl_graph_utils.H>
66# include <tpl_find_path.H>
67# include <graph-traverse.H>
68# include <ah-errors.H>
69
70
71namespace Aleph
72{
73 using std::get;
74
82 template <typename Arc_Info, typename Flow_Type>
83 struct Net_Arc_Info : public Arc_Info
84 {
87
90
92 Net_Arc_Info() = default;
93
100 };
101
113 template <typename Arc_Info, typename F_Type = double>
114 struct Net_Arc : public Graph_Aarc<Arc_Info> // Arc type for flow networks.
115 {
117
119
122
125
127 bool check_arc() const noexcept { return flow >= 0 and flow <= cap; }
128
131 : Base(info)
132 { /* empty */
133 }
134
136 Net_Arc(const Net_Arc & arc)
137 : Base(arc.arc_info), cap(arc.cap), flow(arc.flow)
138 {
139 // empty
140 }
141
144 { /* empty */
145 }
146
149 {
150 if (this == &arc)
151 return *this;
152
153 *static_cast<Base *>(this) = arc;
154 cap = arc.cap;
155 flow = arc.flow;
156
157 return *this;
158 }
159 };
160
161
163 template <class Net>
164 bool is_residual(typename Net::Node *src, typename Net::Arc *a) noexcept
165 {
166 assert(a->src_node == src or a->tgt_node == src);
167 return a->tgt_node == src;
168 }
169
174 template <class Net>
175 struct Net_Filt
176 {
177 typename Net::Node *p = nullptr;
178
179 void *cookie = nullptr;
180
182 void set_cookie(void *__cookie) noexcept { cookie = __cookie; }
183
185 Net_Filt(typename Net::Node *s = nullptr) noexcept
186 : p(s)
187 { /* empty */
188 }
189
191 bool operator ()(typename Net::Arc *a) const noexcept
192 {
193 assert(p);
194 assert(a->src_node == p or a->tgt_node == p);
195 auto src = static_cast<typename Net::Node *>(a->src_node);
196 if (src == p)
197 return a->cap - a->flow > 0; // normal arc
198
200 return a->flow > 0; // residual arc
201 }
202
204 bool operator ()(const Net &, typename Net::Arc *arc) noexcept
205 {
206 return (*this)(arc);
207 }
208
210 typename Net::Node * get_node(typename Net::Arc *a) const noexcept
211 {
212 assert(p);
213 assert(a->src_node == p or a->tgt_node == p);
214 return static_cast<typename Net::Node *>(a->src_node == p ? a->tgt_node : a->src_node);
215 }
216 };
217
218
219 template <class Net>
221
223 template <class Net, class Show_Arc = Dft_Show_Arc<Net>>
226
227
235 template <class Net>
236 typename Net::Flow_Type
237 remaining_flow(typename Net::Node *src, typename Net::Arc *a) noexcept
238 {
239 return is_residual<Net>(src, a) ? a->flow : a->cap - a->flow;
240 }
241
243 template <typename Node_Info = Empty_Class>
245
246
258 template <class NodeT = Net_Node<Empty_Class>,
259 class ArcT = Net_Arc<Empty_Class, double>>
260 struct Net_Graph : public Array_Graph<NodeT, ArcT>
261 {
263
265
266 using Base::Base;
267 using Base::insert_node;
268
269 using Graph = Base;
270
272 using Arc = ArcT;
273
275 using Node = NodeT;
276
278 using Flow_Type = typename Arc::Flow_Type;
279
281 using Node_Type = typename Node::Node_Type;
282
284 using Arc_Type = typename Arc::Arc_Type;
285
287
289 DynList<Arc *> out_arcs(Node *p) const noexcept
290 {
292 }
293
295 DynList<Node *> out_nodes(Node *p) const noexcept
296 {
297 return out_pairs<Net_Graph>(p).template maps<Node *>
298 ([](const ArcPair<Net_Graph> & p) { return get<1>(p); });
299 }
300
302 DynList<Arc *> in_arcs(Node *p) const noexcept
303 {
305 }
306
308 DynList<Node *> in_nodes(Node *p) const noexcept
309 {
310 return in_pairs<Net_Graph>(p).template maps<Node *>
311 ([](const ArcPair<Net_Graph> & p) { return get<1>(p); });
312 }
313
315 [[nodiscard]] Flow_Type get_in_cap(Node *node) const noexcept
316 {
318 for (_In_Iterator<Net_Graph> it(node); it.has_curr(); it.next_ne())
319 sum += it.get_curr()->cap;
320 return sum;
321 }
322
324 [[nodiscard]] Flow_Type get_out_cap(Node *node) const noexcept
325 {
327 for (_Out_Iterator<Net_Graph> it(node); it.has_curr(); it.next_ne())
328 sum += it.get_curr()->cap;
329 return sum;
330 }
331
333 size_t get_in_degree(Node *p) const noexcept
334 {
335 return this->in_degree(p);
336 }
337
339 size_t get_out_degree(Node *p) const noexcept
340 {
341 return this->out_degree(p);
342 }
343
345 [[nodiscard]] Flow_Type get_out_flow(Node *node) const noexcept
346 {
348 for (_Out_Iterator<Net_Graph> it(node); it.has_curr(); it.next_ne())
349 sum += it.get_curr()->flow;
350 return sum;
351 }
352
354 [[nodiscard]] Flow_Type get_in_flow(Node *node) const noexcept
355 {
357 for (_In_Iterator<Net_Graph> it(node); it.has_curr(); it.next_ne())
358 sum += it.get_curr()->flow;
359 return sum;
360 }
361
363 bool is_source(Node *node) const noexcept { return src_nodes.contains(node); }
364
366 bool is_sink(Node *node) const noexcept { return sink_nodes.contains(node); }
367
369 [[nodiscard]] constexpr bool is_single_source() const noexcept { return src_nodes.size() == 1; }
370
372 [[nodiscard]] constexpr bool is_single_sink() const noexcept { return sink_nodes.size() == 1; }
373
375 bool is_connected(Node *p) const noexcept
376 {
377 return get_in_degree(p) != 0 or get_out_degree(p) != 0;
378 }
379
381 bool check_node(Node *node) const noexcept
382 {
383 if (not is_connected(node))
384 return false;
385
386 auto out_flow = get_out_flow(node);
387 auto in_flow = get_in_flow(node);
388
389 // Use tolerance for floating-point comparison
390 const auto eps = std::max(std::abs(out_flow), std::abs(in_flow)) * 1e-9;
391 const auto nearly_zero = [eps](auto x) { return std::abs(x) <= eps; };
392 const auto nearly_equal = [eps](auto a, auto b) { return std::abs(a - b) <= eps; };
393
394 if (is_sink(node))
395 return nearly_zero(out_flow) and in_flow >= -eps;
396
397 if (is_source(node))
398 return nearly_zero(in_flow) and out_flow >= -eps;
399
400 return nearly_equal(out_flow, in_flow);
401 }
402
403 private:
406
409 {
411 for (typename DynSetTree<Node *>::Iterator it(src_nodes);
412 it.has_curr(); it.next_ne())
413 sum += get_out_flow(it.get_curr());
414 return sum;
415 }
416
419 {
422 it.has_curr(); it.next_ne())
423 sum += get_in_flow(it.get_curr());
424 return sum;
425 }
426
429 {
430 try
431 {
432 src_nodes.insert(p);
434 }
435 catch (...)
436 {
437 src_nodes.remove(p);
440 throw;
441 }
442 return p;
443 }
444
445 public:
448
454
455 public:
459 {
460 if (src_nodes.size() == 1)
461 return;
462
464 << "network has no source nodes (it has cycles)";
465
466 DynList<Node *> sources;
467 for (typename DynSetTree<Node *>::Iterator it(src_nodes);
468 it.has_curr(); it.next_ne())
469 sources.append(it.get_curr());
470
471 Node *super_source = insert_node();
472 for (typename DynList<Node *>::Iterator it(sources);
473 it.has_curr(); it.next_ne())
474 insert_arc(super_source, it.get_curr(), get_out_cap(it.get_curr()));
475
476 with_super_source = true;
477 }
478
481 {
483 return;
484
485 assert(src_nodes.size() == 1);
486
488 with_super_source = false;
489 }
490
494 {
495 if (sink_nodes.size() == 1)
496 return;
497
499 << "network has no sink nodes (it has cycles)";
500
503 it.has_curr(); it.next_ne())
504 sinks.append(it.get_curr());
505
506 Node *super_sink = insert_node();
507 for (typename DynList<Node *>::Iterator it(sinks);
508 it.has_curr(); it.next_ne())
509 insert_arc(it.get_curr(), super_sink, get_in_cap(it.get_curr()));
510 with_super_sink = true;
511 }
512
515 {
517 return;
518
519 assert(sink_nodes.size() == 1);
520
522 with_super_sink = false;
523 }
524
527 {
529 try
530 {
532 }
533 catch (const std::bad_alloc &)
534 {
536 throw;
537 }
538 }
539
546
548 Node * get_source() const { return src_nodes.get_item(); }
549
551 Node * get_sink() const { return sink_nodes.get_item(); }
552
559 Node * insert_node(const Node_Type & node_info)
560 {
561 return register_node(Graph::insert_node(node_info));
562 }
563
569
572 {
573 return register_node(Graph::insert_node(std::move(info)));
574 }
575
577 template <typename... Args>
579 {
580 return insert_node(Node_Type(args...));
581 }
582
583
591 {
593 return register_node(p);
594 }
595
607 Arc * insert_arc(Node *src_node, Node *tgt_node,
608 const Flow_Type & cap, const Flow_Type & flow,
609 const typename Arc::Arc_Type & arc_info = Arc_Type())
610 { // base insertion
611 auto arc = Graph::insert_arc(src_node, tgt_node, arc_info);
612
613 src_nodes.remove(tgt_node); // update sources/sinks
614 sink_nodes.remove(src_node);
615
616 arc->cap = cap;
617 arc->flow = flow;
618
619 ah_overflow_error_if(not arc->check_arc()) << "flow is greater than capacity";
620
621 return arc;
622 }
623
624 template <typename... Args>
626 Arc * emplace_arc(Node *src_node, Node *tgt_node,
627 const Flow_Type & cap, const Flow_Type & flow,
628 Args &&... args)
629 {
630 return insert_arc(src_node, tgt_node, cap, flow, Arc_Type(args...));
631 }
632
642 {
644
645 auto src = this->get_src_node(arc);
646 auto tgt = this->get_tgt_node(arc);
647
648 src_nodes.remove(tgt); // target is no longer a source
649 sink_nodes.remove(src); // source is no longer a sink
650
651 return arc;
652 }
653
655 Arc * insert_arc(Node *src_node, Node *tgt_node, const Flow_Type & cap)
656 {
657 return insert_arc(src_node, tgt_node, cap, 0, Arc_Type());
658 }
659
667 Arc * insert_arc(Node *src_node, Node *tgt_node,
668 const Arc_Type & arc_info = Arc_Type())
669 requires (not std::is_same_v<Arc_Type, Flow_Type> and
670 not std::is_arithmetic_v<Arc_Type>)
671 {
672 return insert_arc(src_node, tgt_node, 0, 0, arc_info);
673 }
674
676 void remove_arc(Arc *arc) override
677 {
678 auto src = this->get_src_node(arc);
679 auto tgt = this->get_tgt_node(arc);
680 if (get_in_degree(tgt) == 1)
681 src_nodes.insert(tgt); // target becomes a source
682
683 Graph::remove_arc(arc); // base removal
684
685 if (get_out_degree(src) == 0)
686 sink_nodes.insert(src); // source becomes a sink
687 }
688
690 void disconnect_arc(Arc *arc) noexcept
691 {
692 auto src = this->get_src_node(arc);
693 auto tgt = this->get_tgt_node(arc);
694 if (get_in_degree(tgt) == 1)
695 src_nodes.insert(tgt); // target becomes a source
696
697 Graph::disconnect_arc(arc); // base disconnection
698
699 if (get_out_degree(src) == 0)
700 sink_nodes.insert(src); // source becomes a sink
701 }
702
704 void remove_node(Node *p) noexcept override
705 {
706 Graph::remove_node(p); // base removal
707 src_nodes.remove(p);
709 }
710
712 Net_Graph(const Net_Graph & net)
717 {
718 copy_graph(*this, net, false); // copy without mapping
719
720 using Pair = std::pair<typename Net_Graph::Arc *, typename Net_Graph::Arc *>;
721 zip(this->arcs(), net.arcs()).for_each([](const Pair & p)
722 {
723 auto atgt = p.first;
724 auto asrc = p.second;
725 atgt->cap = asrc->cap;
726 atgt->flow = asrc->flow;
727 });
728 }
729
731 void swap(Net_Graph & other) noexcept
732 {
733 Graph::common_swap(other); // swap num_nodes, num_arcs, digraph, cookie
734 Graph::get_node_dlink().swap(other.get_node_dlink());
735 Graph::get_arc_dlink().swap(other.get_arc_dlink());
736 src_nodes.swap(other.src_nodes);
737 sink_nodes.swap(other.sink_nodes);
738 std::swap(Infinity, other.Infinity);
739 std::swap(with_super_source, other.with_super_source);
740 std::swap(with_super_sink, other.with_super_sink);
741 }
742
745 : Infinity(std::numeric_limits<typename Arc::Flow_Type>::max()),
747 {
748 swap(other);
749 }
750
753 {
754 if (this != &other)
755 swap(other);
756 return *this;
757 }
758
761 {
762 if (this == &net)
763 return *this;
764
765 Net_Graph tmp(net); // copy construct
766 swap(tmp); // swap with copy
767 return *this;
768 }
769
771 void set_cap(Arc *arc, const Flow_Type & cap)
772 {
773 ah_out_of_range_error_if(cap < arc->flow) << "capacity value is smaller than flow";
774
775 arc->cap = cap;
776 }
777
779 void set_flow(Arc *arc, const Flow_Type & flow)
780 {
781 ah_out_of_range_error_if(flow > arc->cap) << "flow value is greater than capacity";
782
783 arc->flow = flow;
784 }
785
787 const Flow_Type &get_flow(Arc *arc) const noexcept { return arc->flow; }
788
790 const Flow_Type &get_cap(Arc *arc) const noexcept { return arc->cap; }
791
793 void reset()
794 {
795 for (Arc_Iterator<Net_Graph> it(*this); it.has_curr(); it.next_ne())
796 it.get_curr()->flow = 0;
797 }
798
803 bool check_network() const
804 {
806 return false;
807
808 const auto total_out = total_source_out_flow();
809 const auto total_in = total_sink_in_flow();
810
811 // Use tolerance for floating-point comparison
812 const auto eps = std::max(std::abs(total_out), std::abs(total_in)) * 1e-9;
813 const bool flow_balanced = std::abs(total_out - total_in) <= eps;
814
815 return this->nodes().all([this](Node *p) { return check_node(p); }) and
816 this->arcs().all([](Arc *a) { return a->check_arc(); }) and
818 }
819
822 {
824 << "network has no source or sink nodes";
825
826 const auto total_out = total_source_out_flow();
827 const auto total_in = total_sink_in_flow();
828
829 (void)total_in; // May be unused when NDEBUG disables assert().
831 return total_out;
832 }
833
836
839
846
848 friend std::ostream &operator <<(std::ostream & s, const Path<Net_Graph> & path)
849 {
850 if (path.is_empty())
851 return s << "Path is Empty";
852
853 const Net_Graph & net = path.get_graph();
854 typename Path<Net_Graph>::Iterator it(path);
855 s << it.get_current_node()->get_info();
856 for (; it.has_current_arc(); it.next_ne())
857 {
858 typename Net_Graph::Arc *a = it.get_current_arc_ne();
859 s << "(" << a->cap << "," << a->flow << ")"
860 << net.get_connected_node(a, it.get_current_node_ne())->get_info();
861 }
862 return s;
863 }
864 };
865
872 template <class Net>
873 using Parc = std::tuple<typename Net::Arc *, bool>; // second field marks forward.
874
882 template <class Net>
883 using SemiPath = std::tuple<bool, typename Net::Flow_Type, DynList<Parc<Net>>>;
884
886 template <class Net>
887 inline void print(const DynList<Parc<Net>> & sp)
888 {
889 if (sp.is_empty())
890 {
891 std::cout << "Semi path is Empty";
892 return;
893 }
894
895 for (typename DynList<Parc<Net>>::Iterator it(sp); it.has_curr();
896 it.next_ne())
897 {
898 const Parc<Net> & pa = it.get_curr();
899 auto a = get<0>(pa);
900 auto s = static_cast<typename Net::Node *>(a->src_node);
901 auto t = static_cast<typename Net::Node *>(a->tgt_node);
902 std::cout << s->get_info() << "(" << a->flow << "," << a->cap << ")"
903 << t->get_info() << " " << (get<1>(pa) ? "Normal" : "Reduced")
904 << '\n';
905 }
906 }
907
916 template <class Net>
917 typename Net::Flow_Type increase_flow(Net & net, const Path<Net> & path)
918 {
919 typename Net::Flow_Type slack = net.Infinity; // bottleneck
920 using Tuple = std::tuple<typename Net::Node *, typename Net::Arc *>;
921
922 // Compute the bottleneck of the augmenting path.
923 for (typename Path<Net>::Iterator it(path); it.has_current_arc();
924 it.next_ne())
925 {
926 Tuple t = it.get_tuple_ne();
927 auto p = get<0>(t);
928 auto arc = get<1>(t);
929 const auto w = remaining_flow<Net>(p, arc);
930 if (w < slack)
931 slack = w;
932 }
933
934 // Increase flow along the augmenting path.
935 for (typename Path<Net>::Iterator it(path); it.has_current_arc(); it.next_ne())
936 {
937 auto t = it.get_tuple_ne();
938 auto p = get<0>(t);
939 auto arc = get<1>(t);
940
941 if (is_residual<Net>(p, arc))
942 arc->flow -= slack;
943 else
944 arc->flow += slack;
945
946 assert(arc->check_arc());
947 }
948
949 return slack;
950 }
951
952
961 template <class Net>
962 void increase_flow(Net & net,
963 const DynList<Parc<Net>> & semi_path,
964 const typename Net::Flow_Type slack)
965 {
966 (void)net; // May be unused when NDEBUG disables assert().
967
968 // Increase flow along the semi-path.
969 for (typename DynList<Parc<Net>>::Iterator it(semi_path); it.has_curr();
970 it.next_ne())
971 {
972 auto p = it.get_curr();
973 auto arc = get<0>(p);
974 if (get<1>(p)) // forward arc
975 arc->flow += slack;
976 else
977 arc->flow -= slack;
978
979 assert(arc->check_arc());
980 }
981 assert(net.check_network());
982 }
983
995 template <class Net>
996 void decrease_flow(Net & net, const DynList<Parc<Net>> & semi_path,
997 const typename Net::Flow_Type slack)
998 {
999 (void)net;
1000
1001 // Decrease flow: reverse the direction logic from increase_flow
1002 for (typename DynList<Parc<Net>>::Iterator it(semi_path); it.has_curr();
1003 it.next_ne())
1004 {
1005 auto p = it.get_curr();
1006 auto arc = get<0>(p);
1007 if (get<1>(p)) // forward arc: decrease instead of increase
1008 arc->flow -= slack;
1009 else // residual arc: increase instead of decrease
1010 arc->flow += slack;
1011
1012 assert(arc->check_arc());
1013 }
1014 }
1015
1016
1023 template <class Net, template <typename T> class Q>
1025 {
1026 const Net & net;
1027
1028 // Return end node if a path is found.
1029 typename Net::Node * search(typename Net::Node *start,
1030 typename Net::Node *end,
1031 typename Net::Flow_Type min_slack)
1032 {
1033 using Itor = Net_Iterator<Net>;
1034 net.reset_nodes();
1035 net.reset_arcs();
1036
1037 start->set_state(Processed);
1039 for (Itor it(start); it.has_curr(); it.next_ne())
1040 {
1041 auto a = it.get_curr();
1042 if (remaining_flow<Net>(start, a) < min_slack)
1043 continue;
1044 auto tgt = net.get_connected_node(a, start);
1045 tgt->set_state(Processing);
1046 a->set_state(Processing);
1047 q.put(a);
1048 }
1049
1050 typename Net::Node *curr = nullptr;
1051 while (not q.is_empty())
1052 {
1053 auto arc = q.get();
1054 assert(arc->state() == Processing);
1055 arc->set_state(Processed);
1056
1057 auto s = net.get_src_node(arc);
1058 auto t = net.get_tgt_node(arc);
1059
1060 if (s->state() == Processed and t->state() == Processed)
1061 continue;
1062
1063 curr = s->state() == Processed ? t : s;
1064 assert(curr->state() == Processing);
1065 curr->set_state(Processed);
1066 NODE_COOKIE(curr) = net.get_connected_node(arc, curr);
1067
1068 if (curr == end)
1069 return curr;
1070
1071 for (Itor it(curr); it.has_curr(); it.next_ne())
1072 {
1073 auto a = it.get_curr();
1074
1075 // Skip arcs already processed or already in queue
1076 if (a->state() != Unprocessed)
1077 continue;
1078
1079 if (remaining_flow<Net>(curr, a) < min_slack)
1080 continue;
1081
1082 auto tgt = net.get_connected_node(a, curr);
1083 if (tgt->state() == Processed)
1084 {
1085 a->set_state(Processed);
1086 continue;
1087 }
1088
1089 a->set_state(Processing);
1090 q.put(a);
1091 tgt->set_state(Processing);
1092 }
1093 } // end while
1094
1095 return nullptr;
1096 }
1097
1099 Path<Net> find(typename Net::Node *start, typename Net::Node *end,
1100 const typename Net::Flow_Type & min_slack = typename Net::Flow_Type{0})
1101 {
1102 auto curr = search(start, end, min_slack);
1103
1104 Path<Net> ret(net);
1105 if (not curr)
1106 return ret;
1107
1108 assert(curr == end);
1109
1110 while (curr != start)
1111 {
1112 ret.insert(curr);
1113 curr = static_cast<typename Net::Node *>(NODE_COOKIE(curr));
1114 }
1115 ret.insert(start);
1116
1117 return ret;
1118 }
1119
1122 typename Net::Node *end,
1123 typename Net::Flow_Type min_slack = typename Net::Flow_Type{0})
1124 {
1125 auto t = search(start, end, min_slack);
1126 if (not t)
1127 return std::make_tuple(false, typename Net::Flow_Type{0}, DynList<Parc<Net>>());
1128
1129 assert(t == end);
1130
1132 auto m = std::numeric_limits<typename Net::Flow_Type>::max();
1133 while (t != start)
1134 {
1135 auto s = static_cast<typename Net::Node *>(NODE_COOKIE(t));
1136 // Find arc connecting s and t with positive residual capacity.
1137 // With parallel arcs, we must pick one that can carry flow.
1138 typename Net::Arc *a = nullptr;
1139 typename Net::Arc *fallback = nullptr;
1140 for (Node_Arc_Iterator<Net> it(t); it.has_curr(); it.next_ne())
1141 {
1142 auto arc = it.get_curr();
1143 if ((arc->src_node == s and arc->tgt_node == t) or
1144 (arc->src_node == t and arc->tgt_node == s))
1145 {
1146 if (fallback == nullptr)
1147 fallback = arc; // Keep first match as fallback
1148 // Prefer arc with positive residual capacity
1149 if (remaining_flow<Net>(s, arc) > 0)
1150 {
1151 a = arc;
1152 break;
1153 }
1154 }
1155 }
1156 if (a == nullptr)
1157 a = fallback; // Use fallback if no arc with residual capacity
1158 assert(a != nullptr);
1159 bool normal = a->tgt_node == t;
1160 auto slack = normal ? a->cap - a->flow : a->flow;
1161 m = std::min(m, slack);
1162 semi_path.insert(std::make_tuple(a, normal));
1163 t = s;
1164 }
1165
1166 return std::make_tuple(true, m, std::move(semi_path));
1167 }
1168
1169 public:
1175
1181
1184 {
1185 // empty
1186 }
1187
1190 typename Net::Node *end,
1191 typename Net::Flow_Type min_slack = 0)
1192 {
1193 return find(start, end, min_slack);
1194 }
1195
1201
1206 typename Net::Flow_Type
1207 semi_path(typename Net::Node *start,
1208 typename Net::Node *end,
1210 const typename Net::Flow_Type & min_slack = 0)
1211 {
1212 semi_path.empty();
1213
1214 auto result = find_path(start, end, min_slack);
1215 if (not get<0>(result))
1216 return typename Net::Flow_Type{};
1217
1218 semi_path = std::move(get<2>(result));
1219 return get<1>(result);
1220 }
1221 };
1222
1224 template <class Net>
1226
1227
1229 template <class Net>
1231
1232
1240 template <class Net, template <typename T> class Q>
1242 const typename Net::Flow_Type & min_slack)
1243 {
1244 auto s = net.get_source();
1245 auto t = net.get_sink();
1246 return Find_Aumenting_Path<Net, Q>(net)(s, t, min_slack);
1247 }
1248
1249
1251 template <class Net>
1253 const typename Net::Flow_Type & min_slack)
1254 {
1256 }
1257
1258
1260 template <class Net>
1262 const typename Net::Flow_Type & min_slack)
1263 {
1265 }
1266
1267
1276 template <class Net, template <typename T> class Q>
1278 const typename Net::Flow_Type & slack)
1279 {
1280 return Find_Aumenting_Path<Net, Q>(net).find_aum_path(slack);
1281 }
1282
1283
1285 template <class Net>
1288 const typename Net::Flow_Type & slack)
1289 {
1291 }
1292
1293
1295 template <class Net>
1298 const typename Net::Flow_Type & slack)
1299 {
1301 }
1302
1303
1312 template <class Net, template <typename T> class Q>
1315 const typename Net::Flow_Type & slack)
1316 {
1317 return Find_Aumenting_Path<Net, Q>(net).find_dec_path(slack);
1318 }
1319
1320
1322 template <class Net>
1325 const typename Net::Flow_Type & slack)
1326 {
1328 }
1329
1330
1332 template <class Net>
1335 const typename Net::Flow_Type & slack)
1336 {
1338 }
1339
1340
1342 template <class Net>
1343 struct PP_Res_Node : public Net_Node<Empty_Class>
1344 {
1346
1349
1352
1355
1358 };
1359
1360 template <class Net>
1361 struct __Res_Arc : public Net_Arc<Empty_Class, typename Net::Flow_Type>
1362 {
1364
1365 typename Net::Arc *img = nullptr; // nullptr indicates residual arc
1366 __Res_Arc *dup = nullptr;
1367
1370
1373
1376
1378 bool is_residual() const { return img == nullptr; }
1379 };
1380
1381
1383 template <class Net>
1385
1387 template <class Net>
1389
1391 template <class Net>
1392 inline
1394 typename Net::Arc *a)
1395 {
1396 using Rnet = PP_Res_Net<Net>;
1397 auto s = net.get_src_node(a);
1398 auto t = net.get_tgt_node(a);
1399
1401
1402 auto src = static_cast<typename Rnet::Node *>(NODE_COOKIE(s));
1403 auto tgt = static_cast<typename Rnet::Node *>(NODE_COOKIE(t));
1404
1405 auto arc = rnet.insert_arc(src, tgt);
1406 auto dup = rnet.insert_arc(tgt, src);
1407
1408 arc->img = a; // mark it as not residual
1409 arc->cap = a->cap;
1410 arc->flow = a->flow;
1411 arc->dup = dup;
1412
1413 dup->cap = arc->cap;
1414 dup->flow = arc->cap - arc->flow;
1415 dup->dup = arc;
1416 }
1417
1419 template <class Rnet>
1420 struct Res_F
1421 {
1422 Res_F(typename Rnet::Node *) noexcept {}
1424
1425 bool operator ()(typename Rnet::Arc *a) const
1426 {
1427 return a->cap > a->flow;
1428 }
1429 };
1430
1435 template <class Net>
1436 inline
1437 std::tuple<PP_Res_Net<Net>, typename PP_Res_Net<Net>::Node *,
1438 typename PP_Res_Net<Net>::Node *>
1440 {
1441 using Rnet = PP_Res_Net<Net>;
1442 net.reset_nodes();
1443 Rnet rnet;
1444
1445 for (typename Net::Node_Iterator it(net); it.has_curr(); it.next_ne())
1446 {
1447 auto p = it.get_curr();
1448 auto q = rnet.insert_node();
1449 q->in_flow = net.get_in_flow(p);
1450 q->out_flow = net.get_out_flow(p);
1451 // Directly store pointers in cookies using reinterpret_cast to
1452 // preserve exact addresses without multiple inheritance adjustment
1453 NODE_COOKIE(p) = reinterpret_cast<void*>(q);
1454 NODE_COOKIE(q) = reinterpret_cast<void*>(p);
1455 }
1456
1457 for (typename Net::Arc_Iterator it(net); it.has_curr(); it.next_ne())
1458 create_residual_arc(net, rnet, it.get_curr());
1459
1460 return std::make_tuple(std::move(rnet),
1461 static_cast<typename Rnet::Node *>(NODE_COOKIE(net.get_source())),
1462 static_cast<typename Rnet::Node *>(NODE_COOKIE(net.get_sink())));
1463 }
1464
1466 template <class Rnet>
1467 inline
1468 void update_flow(const Rnet & rnet)
1469 {
1470 for (typename Rnet::Arc_Iterator it(rnet); it.has_curr(); it.next_ne())
1471 {
1472 auto arc = it.get_curr();
1473 auto img = arc->img;
1474 if (img == nullptr)
1475 continue;
1476 img->flow = arc->flow;
1477 }
1478 }
1479
1487 template <class Net,
1488 template <class> class Find_Path>
1490 {
1492 << "Network is not single source and single sink";
1493
1494 while (true) // while an augmenting path exists
1495 {
1496 SemiPath<Net> semi_path = Find_Path<Net>(net)();
1497 if (not get<0>(semi_path))
1498 break;
1499
1500 // Skip paths with zero slack.
1501 // This can happen with parallel arcs where one arc is saturated
1502 // but the path finder still finds a path through it.
1503 auto slack = get<1>(semi_path);
1504 if (slack <= typename Net::Flow_Type{0})
1505 break;
1506
1507 increase_flow<Net>(net, get<2>(semi_path), slack);
1508 }
1509
1510 return net.get_out_flow(net.get_source());
1511 }
1512
1513
1521 template <class Net>
1526
1527
1532 template <class Net>
1534 {
1536 typename Net::Flow_Type operator ()(Net & net) const
1537 {
1538 return ford_fulkerson_maximum_flow(net);
1539 }
1540 };
1541
1549 template <class Net>
1554
1555
1560 template <class Net>
1562 {
1564 typename Net::Flow_Type operator ()(Net & net) const
1565 {
1567 }
1568 };
1569
1571 template <class Net>
1572 static inline
1573 bool is_node_active(const Net & net, typename Net::Node *p)
1574 {
1575 return net.get_in_flow(p) != net.get_out_flow(p);
1576 }
1577
1579 template <class Rnet>
1580 static inline
1581 bool is_node_active(typename Rnet::Node *p)
1582 {
1583 return p->in_flow != p->out_flow;
1584 }
1585
1586
1588 template <class Net>
1589 static inline
1590 long &node_height(typename Net::Node *p) { return NODE_COUNTER(p); }
1591
1592
1594 template <class Net>
1595 static inline
1597 {
1599 exec(net.get_sink(),
1600 [&net](typename Net::Node *p, typename Net::Arc *a)
1601 {
1602 if (a)
1604 return true;
1605 });
1606 }
1607
1608
1610 template <class Q_Type>
1611 static inline
1612 void put_in_active_queue(Q_Type & q, typename Q_Type::Item_Type & p)
1613 {
1614 if (NODE_BITS(p).get_bit(Aleph::Maximum_Flow))
1615 return; // the node is already into the queue
1616 NODE_BITS(p).set_bit(Aleph::Maximum_Flow, true);
1617 q.put(p);
1618 }
1619
1620
1622 template <class Q_Type>
1623 static inline
1624 typename Q_Type::Item_Type get_from_active_queue(Q_Type & q)
1625 {
1626 auto p = q.get();
1628 NODE_BITS(p).set_bit(Aleph::Maximum_Flow, false);
1629 return p;
1630 }
1631
1632
1634 template <class Q_Type>
1635 static inline
1636 void remove_from_active_queue(Q_Type & q, typename Q_Type::Item_Type & p)
1637 {
1639 NODE_BITS(p).set_bit(Aleph::Maximum_Flow, false);
1640 q.remove(p);
1641 }
1642
1643
1658 template <class Net, class Q_Type>
1659 typename Net::Flow_Type
1661 {
1663 << "Network is not single source and single sink";
1664
1665 net.reset_nodes(); // especially assures that counters are in zero
1666 init_height_in_nodes(net); // set height to minimum distance in nodes to sink
1667
1668 auto source = net.get_source();
1669 auto sink = net.get_sink();
1670 node_height<Net>(source) = net.vsize(); // except the source
1671 constexpr auto Max = std::numeric_limits<long>::max();
1672
1673 using Itor = __Net_Iterator<Net>;
1674 Q_Type q;
1675 for (Itor it(source); it.has_curr(); it.next_ne()) // initial preflow
1676 {
1677 auto arc = it.get_curr();
1678 arc->flow = arc->cap; // saturate arc
1679 auto tgt = net.get_tgt_node(arc);
1680 put_in_active_queue(q, tgt);
1681 }
1682
1683 while (not q.is_empty()) // while there are active nodes
1684 {
1685 auto src = get_from_active_queue(q);
1686 auto excess = net.get_in_flow(src) - net.get_out_flow(src);
1687 long m = Max;
1688 bool was_eligible_arc = false;
1689 for (Itor it(src); it.has_curr() and excess > 0; it.next_ne())
1690 {
1691 auto arc = it.get_curr();
1692 auto tgt = net.get_connected_node(arc, src);
1693 if (node_height<Net>(src) != node_height<Net>(tgt) + 1)
1694 {
1695 m = std::min(m, node_height<Net>(tgt));
1696 continue;
1697 }
1698
1699 was_eligible_arc = true;
1701 if (is_residual<Net>(src, arc))
1702 {
1703 flow_to_push = std::min(arc->flow, excess);
1704 arc->flow -= flow_to_push;
1705 }
1706 else
1707 {
1708 flow_to_push = std::min(arc->cap - arc->flow, excess);
1709 arc->flow += flow_to_push;
1710 }
1711 excess -= flow_to_push;
1712 if (tgt != source and tgt != sink)
1713 {
1714 assert(is_node_active(net, tgt));
1715 put_in_active_queue(q, tgt);
1716 }
1717 }
1718
1719 if (excess > 0) // is src still active
1720 {
1722 node_height<Net>(src) = m + 1;
1723 put_in_active_queue(q, src);
1724 }
1725 }
1726
1727 assert(net.check_network());
1728
1729 return net.flow_value();
1730 }
1731
1732
1734 template <class Rnet>
1735 inline
1736 void init_height_in_nodes(Rnet & rnet, typename Rnet::Node *sink)
1737 {
1739 exec(sink, [&rnet](typename Rnet::Node *p, typename Rnet::Arc *a)
1740 {
1741 if (a)
1742 node_height<Rnet>(p) = node_height<Rnet>(rnet.get_src_node(a)) + 1;
1743 return true;
1744 });
1745 }
1746
1747
1755 template <class Net>
1756 typename Net::Flow_Type
1758 {
1759 using Node = typename Net::Node;
1761 <Net, DynListQueue<Node *>>(net);
1762 }
1763
1768 template <class Net>
1770 {
1772 typename Net::Flow_Type
1773 operator ()(Net & net) const
1774 {
1775 return fifo_preflow_maximum_flow(net);
1776 }
1777 };
1778
1779
1781 template <class Net>
1783 {
1784 bool operator ()(typename Net::Node *n1, typename Net::Node *n2) const
1785 {
1786 return node_height<Net>(n1) > node_height<Net>(n2);
1787 }
1788 };
1789
1797 template <class Net>
1798 typename Net::Flow_Type
1805
1810 template <class Net>
1812 {
1814 typename Net::Flow_Type operator ()(Net & net) const
1815 {
1816 return heap_preflow_maximum_flow(net);
1817 }
1818 };
1819
1827 template <class Net>
1828 typename Net::Flow_Type
1834
1835
1840 template <class Net>
1842 {
1844 typename Net::Flow_Type operator ()(Net & net) const
1845 {
1846 return random_preflow_maximum_flow(net);
1847 }
1848 };
1849
1850
1862 template <class Net, template <class> class Maxflow>
1868 {
1869 Maxflow<Net>()(net); // compute max flow
1870
1871 typename Net::Node *source = net.get_source();
1872
1873 // Traverse the residual network from source: reachable nodes go to vs.
1875 (source, [&vs](typename Net::Node *p)
1876 {
1877 vs.insert(p);
1878 return true;
1879 });
1880
1881 // Compute vt by complement.
1882 const size_t size_vt = net.get_num_nodes() - vs.size();
1883 for (Node_Iterator<Net> it(net); it.has_curr() and
1884 vt.size() < size_vt; it.next_ne())
1885 {
1886 if (auto p = it.get_curr(); p->state() == Unprocessed)
1887 vt.insert(p);
1888 }
1889
1890 for (Arc_Iterator<Net> it(net); it.has_curr(); it.next_ne())
1891 {
1892 auto arc = it.get_curr();
1893 if (arc->flow == 0) // residual candidate
1894 if (vt.contains(net.get_src_node(arc)) and // vt -> vs
1895 vs.contains(net.get_tgt_node(arc)))
1896 {
1897 cutt.insert(arc);
1898 continue;
1899 }
1900
1901 if (arc->flow == arc->cap) // saturated candidate
1902 if (vs.contains(net.get_src_node(arc)) and // vs -> vt
1903 vt.contains(net.get_tgt_node(arc)))
1904 cuts.insert(arc);
1905 }
1906
1907 return net.flow_value();
1908 }
1909
1910
1915 template <class Net,
1916 template <class> class Maxflow = Heap_Preflow_Maximum_Flow>
1929} // end namespace Aleph
1930
1931# endif // TPL_NET_H
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:584
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:468
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
WeightedDigraph::Node Node
long double w
Definition btreepic.C:153
virtual void remove_arc(Arc *a)
Definition tpl_agraph.H:492
virtual Node * insert_node(Node *p)
Definition tpl_agraph.H:393
Arc * disconnect_arc(Arc *arc)
Definition tpl_agraph.H:477
Dlink & get_arc_dlink() noexcept
Returns reference to internal arc Dlink for sorting operations.
Definition tpl_agraph.H:303
virtual void remove_node(Node *p)
Definition tpl_agraph.H:497
Arc * insert_arc(Node *src, Node *tgt, void *a)
Definition tpl_agraph.H:456
Arc * connect_arc(Arc *arc)
Definition tpl_agraph.H:449
Dlink & get_node_dlink() noexcept
Returns reference to internal node Dlink for sorting operations.
Definition tpl_agraph.H:300
Filtered iterator on directed graphs.
Definition tpl_graph.H:1690
GT::Arc * get_curr() const
Return the current arc.
Definition tpl_graph.H:1733
bool has_curr() const noexcept
Return true the iterator has an current arc.
Definition tpl_graph.H:1726
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3960
typename BaseGraph::Node Node
Definition graph-dry.H:3963
Dynamic heap of elements of type T ordered by a comparison functor.
void next_ne() noexcept
Move the iterator one position forward guaranteeing no exception.
Dynamic queue of elements of generic type T based on single linked list.
Iterator on the items of list.
Definition htlist.H:1420
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
Dynamic set backed by balanced binary search trees with automatic memory management.
const Key & get_item() const
Returns any element of the set.
const size_t & size() const
Returns the cardinality of the set.
Key * insert(const Key &key)
Inserts a key into the dynamic set.
void swap(DynSetTree &dset) noexcept(noexcept(tree.swap(dset.tree)) and noexcept(std::swap(num_nodes, dset.num_nodes)) and noexcept(std::swap(arena_allocator, dset.arena_allocator)))
Exchange all elements of this set with dset in constant time (and extremely fast).
size_t remove(const Key &key)
Removes a key from the dynamic set.
bool contains(const Key &key) const
Checks if a key exists in the set.
bool is_empty() const
returns true if the set is empty
Generic filter iterator wrapper.
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
Augmenting-path search over a directed network.
Definition tpl_net.H:1025
Path< Net > operator()(typename Net::Node *start, typename Net::Node *end, typename Net::Flow_Type min_slack=0)
Find a concrete Path with at least min_slack.
Definition tpl_net.H:1189
Find_Aumenting_Path(const Net &__g)
Construct a finder for net.
Definition tpl_net.H:1183
Net::Flow_Type semi_path(typename Net::Node *start, typename Net::Node *end, DynList< Parc< Net > > &semi_path, const typename Net::Flow_Type &min_slack=0)
Fill semi_path and return the slack value.
Definition tpl_net.H:1207
Path< Net > find(typename Net::Node *start, typename Net::Node *end, const typename Net::Flow_Type &min_slack=typename Net::Flow_Type{0})
Build a Path from start to end with minimum slack.
Definition tpl_net.H:1099
SemiPath< Net > find_dec_path(typename Net::Flow_Type min_slack=0.0)
Find a decrementing semi-path with at least min_slack.
Definition tpl_net.H:1177
SemiPath< Net > find_aum_path(typename Net::Flow_Type min_slack=0.0)
Find an augmenting semi-path with at least min_slack.
Definition tpl_net.H:1171
SemiPath< Net > find_path(typename Net::Node *start, typename Net::Node *end, typename Net::Flow_Type min_slack=typename Net::Flow_Type{0})
Build a SemiPath from start to end with minimum slack.
Definition tpl_net.H:1121
Net::Node * search(typename Net::Node *start, typename Net::Node *end, typename Net::Flow_Type min_slack)
Definition tpl_net.H:1029
bool has_curr() const noexcept
Definition htlist.H:930
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1207
Iterator on nodes and arcs of a path.
Definition tpl_graph.H:3311
Node * get_current_node_ne() const noexcept
Definition tpl_graph.H:3337
Node * get_current_node() const
Return the current node of a path.
Definition tpl_graph.H:3332
Arc * get_current_arc_ne() const noexcept
Definition tpl_graph.H:3359
bool has_current_arc() const noexcept
Return true if iterator has current arc.
Definition tpl_graph.H:3418
Path on a graph.
Definition tpl_graph.H:2772
bool is_empty() const noexcept
Return true if the path is empty.
Definition tpl_graph.H:2916
const GT & get_graph() const noexcept
Get a constant reference to the graph.
Definition tpl_graph.H:2844
void reset_arcs() const
Reset all the arcs of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:975
Container< Arc * > arcs() const
Return a container with all the arcs of the graph.
Definition graph-dry.H:2844
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:779
std::tuple< Arc *, Node * > ArcPair
Pair of arc and node (topologically related)
Definition graph-dry.H:3295
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:737
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
Definition graph-dry.H:820
void common_swap(GT &g) noexcept
Definition graph-dry.H:683
size_t out_degree(Node *p) const noexcept
Compute the output degree of a node.
Definition graph-dry.H:3379
constexpr size_t vsize() const noexcept
Definition graph-dry.H:746
void reset_nodes() const
Reset all the nodes of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:968
size_t in_degree(Node *p) const noexcept
Compute the input degree of a node.
Definition graph-dry.H:3356
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:785
Container< Node * > nodes() const
Return a container with all the nodes of the graph.
Definition graph-dry.H:2826
Traverse a graph depth-first or breadth-first and execute a visit function.
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4121
Graph traversal algorithms (DFS, BFS).
const unsigned char Processed
The node or arc has already been processed.
Definition aleph-graph.C:39
const unsigned char Processing
The node are being processed; probably it is inside a queue, stack or heap.
Definition aleph-graph.C:38
#define NODE_COUNTER(p)
Get the counter of a node.
#define NODE_COOKIE(p)
Return the node cookie
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
const unsigned char Unprocessed
The node have not bees processed.
Definition aleph-graph.C:37
#define NODE_BITS(p)
Get the control bits of a node.
void copy_graph(GT &gtgt, const GT &gsrc, bool cookie_map=false)
Explicit copy of graph.
Definition tpl_graph.H:3677
@ Maximum_Flow
Definition aleph-graph.H:78
@ Find_Path
Definition aleph-graph.H:76
Net_Graph< Net_Node< string >, Net_Arc< Empty_Class, FlowType > > Net
double Flow_Type
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
SemiPath< Net > find_aumenting_semi_path_dfs(const Net &net, const typename Net::Flow_Type &slack)
Find an augmenting semi-path using DFS.
Definition tpl_net.H:1287
static void remove_from_active_queue(Q_Type &q, typename Q_Type::Item_Type &p)
Remove a node from the active queue and clear its queue mark.
Definition tpl_net.H:1636
Net::Flow_Type remaining_flow(typename Net::Node *src, typename Net::Arc *a) noexcept
Return the remaining flow of a as seen from src.
Definition tpl_net.H:237
void decrease_flow(Net &net, const DynList< Parc< Net > > &semi_path, const typename Net::Flow_Type slack)
Decrease flow along a semi-path by a given slack.
Definition tpl_net.H:996
Net::Flow_Type edmonds_karp_maximum_flow(Net &net)
Maximize flow using the Edmonds-Karp algorithm.
Definition tpl_net.H:1550
Net::Flow_Type generic_preflow_vertex_push_maximum_flow(Net &net)
Generic preflow-push maximum flow (vertex-oriented).
Definition tpl_net.H:1660
bool is_residual(typename Net::Node *src, typename Net::Arc *a) noexcept
Return true if arc a is residual with respect to src.
Definition tpl_net.H:164
Net::Flow_Type random_preflow_maximum_flow(Net &net)
Preflow-push maximum flow using a random active-node queue.
Definition tpl_net.H:1829
Path< Net > find_aumenting_path_dfs(const Net &net, const typename Net::Flow_Type &min_slack)
Find an augmenting path using DFS.
Definition tpl_net.H:1252
SemiPath< Net > find_decrementing_path(const Net &net, const typename Net::Flow_Type &slack)
Find a decrementing semi-path using DFS or BFS based on Q.
Definition tpl_net.H:1314
Net::Flow_Type heap_preflow_maximum_flow(Net &net)
Preflow-push maximum flow using a height-ordered heap.
Definition tpl_net.H:1799
SemiPath< Net > find_aumenting_semi_path_bfs(const Net &net, const typename Net::Flow_Type &slack)
Find an augmenting semi-path using BFS.
Definition tpl_net.H:1297
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zip(const Container1 &a, const Container2 &b)
Zip two containers into a list of pairs.
and
Check uniqueness with explicit hash + equality functors.
static Q_Type::Item_Type get_from_active_queue(Q_Type &q)
Dequeue an active node and clear its queue mark.
Definition tpl_net.H:1624
Net::Flow_Type increase_flow(Net &net, const Path< Net > &path)
Increase flow along an augmenting path.
Definition tpl_net.H:917
SemiPath< Net > find_decrementing_path_dfs(const Net &net, const typename Net::Flow_Type &slack)
Find a decrementing semi-path using DFS.
Definition tpl_net.H:1324
void create_residual_arc(const Net &net, PP_Res_Net< Net > &rnet, typename Net::Arc *a)
Create residual arcs for a in the residual network.
Definition tpl_net.H:1393
std::tuple< PP_Res_Net< Net >, typename PP_Res_Net< Net >::Node *, typename PP_Res_Net< Net >::Node * > preflow_create_residual_net(Net &net)
Build the residual network for preflow-push algorithms.
Definition tpl_net.H:1439
Path< Net > find_aumenting_path_bfs(const Net &net, const typename Net::Flow_Type &min_slack)
Find an augmenting path using BFS.
Definition tpl_net.H:1261
static long & node_height(typename Net::Node *p)
Access the height label stored in NODE_COUNTER.
Definition tpl_net.H:1590
std::tuple< bool, typename Net::Flow_Type, DynList< Parc< Net > > > SemiPath
Semi-path tuple:
Definition tpl_net.H:883
SemiPath< Net > find_aumenting_semi_path(const Net &net, const typename Net::Flow_Type &slack)
Find an augmenting semi-path using DFS or BFS based on Q.
Definition tpl_net.H:1277
Net::Flow_Type fifo_preflow_maximum_flow(Net &net)
Preflow-push maximum flow using a FIFO queue of active nodes.
Definition tpl_net.H:1757
Path< Net > find_aumenting_path(const Net &net, const typename Net::Flow_Type &min_slack)
Find an augmenting path using DFS or BFS based on Q.
Definition tpl_net.H:1241
static bool is_node_active(const Net &net, typename Net::Node *p)
Return true if p has excess flow in net.
Definition tpl_net.H:1573
Net::Flow_Type ford_fulkerson_maximum_flow(Net &net)
Maximize flow using the Ford-Fulkerson algorithm.
Definition tpl_net.H:1522
static void init_height_in_nodes(Net &net)
Initialize node heights with BFS distance to the sink.
Definition tpl_net.H:1596
SemiPath< Net > find_decrementing_path_bfs(const Net &net, const typename Net::Flow_Type &slack)
Find a decrementing semi-path using BFS.
Definition tpl_net.H:1334
void update_flow(const Rnet &rnet)
Propagate residual arc flows back to their original arcs.
Definition tpl_net.H:1468
static void put_in_active_queue(Q_Type &q, typename Q_Type::Item_Type &p)
Enqueue an active node if it is not already enqueued.
Definition tpl_net.H:1612
Net::Flow_Type aumenting_path_maximum_flow(Net &net)
Maximize flow using repeated augmenting-path searches.
Definition tpl_net.H:1489
Net::Flow_Type min_cut(Net &net, DynSetTree< typename Net::Node * > &vs, DynSetTree< typename Net::Node * > &vt, DynList< typename Net::Arc * > &cuts, DynList< typename Net::Arc * > &cutt)
Compute max flow and the corresponding minimum cut.
Definition tpl_net.H:1863
std::tuple< typename Net::Arc *, bool > Parc
Arc entry for a semi-path.
Definition tpl_net.H:873
@ Tuple
Tuple type such as (Int, Bool).
void print(const DynList< Parc< Net > > &sp)
Print a semi-path to stdout.
Definition tpl_net.H:887
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
STL namespace.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1165
Iterator over arcs of a graph.
Definition tpl_agraph.H:325
Compare nodes by height (higher first).
Definition tpl_net.H:1783
bool operator()(typename Net::Node *n1, typename Net::Node *n2) const
Definition tpl_net.H:1784
Functor wrapper for edmonds_karp_maximum_flow().
Definition tpl_net.H:1562
Net::Flow_Type operator()(Net &net) const
Invoke edmonds_karp_maximum_flow().
Definition tpl_net.H:1564
Empty placeholder class with no data members.
Definition ahDefs.H:107
Functor wrapper for fifo_preflow_maximum_flow().
Definition tpl_net.H:1770
Net::Flow_Type operator()(Net &net) const
Invoke fifo_preflow_maximum_flow().
Definition tpl_net.H:1773
Functor wrapper for ford_fulkerson_maximum_flow().
Definition tpl_net.H:1534
Net::Flow_Type operator()(Net &net) const
Invoke ford_fulkerson_maximum_flow().
Definition tpl_net.H:1536
Functor wrapper for heap_preflow_maximum_flow().
Definition tpl_net.H:1812
Net::Flow_Type operator()(Net &net) const
Invoke heap_preflow_maximum_flow().
Definition tpl_net.H:1814
Functor wrapper for min_cut().
Definition tpl_net.H:1918
Net::Flow_Type operator()(Net &net, DynSetTree< typename Net::Node * > &vs, DynSetTree< typename Net::Node * > &vt, DynList< typename Net::Arc * > &cuts, DynList< typename Net::Arc * > &cutt)
Invoke min_cut().
Definition tpl_net.H:1920
Arc info extension that stores capacity and flow values.
Definition tpl_net.H:84
Net_Arc_Info(const Arc_Info &info, Flow_Type __cap, Flow_Type __flow)
Construct from base info, capacity and flow.
Definition tpl_net.H:95
Flow_Type flow
Flow value.
Definition tpl_net.H:89
Flow_Type cap
Capacity value.
Definition tpl_net.H:86
Net_Arc_Info()=default
Default constructor.
Arc of a flow network implemented with adjacency lists.
Definition tpl_net.H:115
bool check_arc() const noexcept
Return true if flow satisfies 0 <= flow <= cap.
Definition tpl_net.H:127
Net_Arc()
Default constructor.
Definition tpl_net.H:143
Flow_Type cap
Capacity value.
Definition tpl_net.H:121
Net_Arc(const Arc_Info &info)
Construct from arc info.
Definition tpl_net.H:130
Net_Arc & operator=(const Net_Arc &arc)
Copy assignment.
Definition tpl_net.H:148
Flow_Type flow
Flow value.
Definition tpl_net.H:124
F_Type Flow_Type
Definition tpl_net.H:118
Net_Arc(const Net_Arc &arc)
Copy constructor.
Definition tpl_net.H:136
Arc filter for residual traversal in flow networks.
Definition tpl_net.H:176
Net::Node * get_node(typename Net::Arc *a) const noexcept
Return the opposite endpoint of arc a with respect to p.
Definition tpl_net.H:210
Net_Filt(typename Net::Node *s=nullptr) noexcept
Build a filter rooted at node s.
Definition tpl_net.H:185
void set_cookie(void *__cookie) noexcept
Store an opaque cookie for compatibility with other iterators.
Definition tpl_net.H:182
bool operator()(typename Net::Arc *a) const noexcept
Return true if arc a has residual capacity with respect to p.
Definition tpl_net.H:191
Net::Node * p
Definition tpl_net.H:177
void * cookie
Definition tpl_net.H:179
Flow network implemented with adjacency lists.
Definition tpl_net.H:261
void unmake_super_source() noexcept
Restore a super-source network to its original multi-source form.
Definition tpl_net.H:480
Flow_Type get_out_flow(Node *node) const noexcept
Return total outgoing flow of node.
Definition tpl_net.H:345
typename Arc::Arc_Type Arc_Type
Arc info type.
Definition tpl_net.H:284
Node * insert_node(const Node_Type &node_info)
Insert a new node by copying node_info.
Definition tpl_net.H:559
void set_cap(Arc *arc, const Flow_Type &cap)
Set the capacity of an arc.
Definition tpl_net.H:771
const DynSetTree< Node * > & get_sink_nodes() const noexcept
Return the set of sink nodes.
Definition tpl_net.H:450
Node * insert_node(Node_Type &&info)
Insert a new node by moving info.
Definition tpl_net.H:571
Net_Graph & operator=(const Net_Graph &net)
Copy-assign a network. Throws bad_alloc on allocation failure.
Definition tpl_net.H:760
bool check_network() const
Validate flow-conservation and capacity constraints.
Definition tpl_net.H:803
bool is_connected(Node *p) const noexcept
Return true if p is connected (used for validation).
Definition tpl_net.H:375
bool with_super_sink
True if the network has a super-sink.
Definition tpl_net.H:838
const DynSetTree< Node * > & get_src_nodes() const noexcept
Return the set of source nodes.
Definition tpl_net.H:447
typename Node::Node_Type Node_Type
Node info type.
Definition tpl_net.H:281
Arc * connect_arc(Arc *arc)
Connect a previously disconnected arc.
Definition tpl_net.H:641
Net_Graph()
Default constructor.
Definition tpl_net.H:841
Net_Graph(const Net_Graph &net)
Copy-construct a network. Throws bad_alloc on allocation failure.
Definition tpl_net.H:712
Node * emplace_node(Args &&... args)
Construct a node in-place and insert it into the network.
Definition tpl_net.H:578
void unmake_super_sink() noexcept
Restore a super-sink network to its original multi-sink form.
Definition tpl_net.H:514
void remove_arc(Arc *arc) override
Remove arc arc from the network.
Definition tpl_net.H:676
void set_flow(Arc *arc, const Flow_Type &flow)
Set the flow of an arc. Throws if flow exceeds capacity.
Definition tpl_net.H:779
Node * insert_node(Node *p)
Insert a node by copying another node.
Definition tpl_net.H:590
void make_super_source()
Convert a multi-source network into a single super-source network.
Definition tpl_net.H:458
void make_super_sink()
Convert a multi-sink network into a single super-sink network.
Definition tpl_net.H:493
size_t get_out_degree(Node *p) const noexcept
Return the out-degree of p (number of outgoing arcs).
Definition tpl_net.H:339
Array_Graph< NodeT, ArcT > Base
Definition tpl_net.H:264
constexpr bool is_single_source() const noexcept
Return true if the network has a single source.
Definition tpl_net.H:369
Node * register_node(Node *p)
Insert p into source/sink sets with rollback on failure.
Definition tpl_net.H:428
Flow_Type total_sink_in_flow() const
Return total incoming flow to all sinks.
Definition tpl_net.H:418
bool is_source(Node *node) const noexcept
Return true if node is a source.
Definition tpl_net.H:363
Node * get_source() const
Return an arbitrary source node.
Definition tpl_net.H:548
friend std::ostream & operator<<(std::ostream &s, const Path< Net_Graph > &path)
Stream a path with arc (cap,flow) tuples.
Definition tpl_net.H:848
Flow_Type get_out_cap(Node *node) const noexcept
Return total outgoing capacity of node.
Definition tpl_net.H:324
Arc * insert_arc(Node *src_node, Node *tgt_node, const Flow_Type &cap, const Flow_Type &flow, const typename Arc::Arc_Type &arc_info=Arc_Type())
Insert a capacitated arc with an initial flow.
Definition tpl_net.H:607
DynSetTree< Node * > src_nodes
Definition tpl_net.H:404
void disconnect_arc(Arc *arc) noexcept
Disconnect arc arc from the graph without deleting it.
Definition tpl_net.H:690
bool with_super_source
True if the network has a super-source.
Definition tpl_net.H:835
Arc * insert_arc(Node *src_node, Node *tgt_node, const Flow_Type &cap)
Insert an arc with capacity cap and zero flow.
Definition tpl_net.H:655
DynList< Node * > out_nodes(Node *p) const noexcept
Return nodes reachable from p through outgoing arcs.
Definition tpl_net.H:295
void unmake_super_nodes()
Restore a super-source/super-sink network to its original form.
Definition tpl_net.H:541
Flow_Type Infinity
Definition tpl_net.H:286
ArcT Arc
Arc type.
Definition tpl_net.H:272
DynList< Arc * > out_arcs(Node *p) const noexcept
Return arcs outgoing from p (as a DynList).
Definition tpl_net.H:289
Flow_Type total_source_out_flow() const
Return total outgoing flow from all sources.
Definition tpl_net.H:408
Flow_Type get_in_cap(Node *node) const noexcept
Return total incoming capacity of node.
Definition tpl_net.H:315
Flow_Type get_in_flow(Node *node) const noexcept
Return total incoming flow of node.
Definition tpl_net.H:354
Node * get_sink() const
Return an arbitrary sink node.
Definition tpl_net.H:551
bool is_sink(Node *node) const noexcept
Return true if node is a sink.
Definition tpl_net.H:366
Flow_Type flow_value() const
Return the total flow value of the network.
Definition tpl_net.H:821
typename Arc::Flow_Type Flow_Type
Capacity/flow numeric type.
Definition tpl_net.H:278
void remove_node(Node *p) noexcept override
Remove node p and all its arcs from the network.
Definition tpl_net.H:704
constexpr bool is_single_sink() const noexcept
Return true if the network has a single sink.
Definition tpl_net.H:372
Net_Graph & operator=(Net_Graph &&other) noexcept
Move-assign a network. O(1) operation.
Definition tpl_net.H:752
Arc * emplace_arc(Node *src_node, Node *tgt_node, const Flow_Type &cap, const Flow_Type &flow, Args &&... args)
Construct arc info in-place and insert the arc.
Definition tpl_net.H:626
void make_super_nodes()
Convert a multi-source/multi-sink network into super-source/super-sink.
Definition tpl_net.H:526
DynSetTree< Node * > sink_nodes
Definition tpl_net.H:405
DynList< Node * > in_nodes(Node *p) const noexcept
Return nodes that can reach p through incoming arcs.
Definition tpl_net.H:308
Net_Graph(Net_Graph &&other) noexcept
Move-construct a network. O(1) operation.
Definition tpl_net.H:744
NodeT Node
Node type.
Definition tpl_net.H:275
const Flow_Type & get_cap(Arc *arc) const noexcept
Return the capacity value of an arc.
Definition tpl_net.H:790
const Flow_Type & get_flow(Arc *arc) const noexcept
Return the flow value of an arc.
Definition tpl_net.H:787
DynList< Arc * > in_arcs(Node *p) const noexcept
Return arcs incoming to p (as a DynList).
Definition tpl_net.H:302
Node * insert_node()
Insert a new node with default info.
Definition tpl_net.H:565
void reset()
Reset all arc flows to zero.
Definition tpl_net.H:793
bool check_node(Node *node) const noexcept
Return true if node satisfies flow conservation constraints.
Definition tpl_net.H:381
size_t get_in_degree(Node *p) const noexcept
Return the in-degree of p (number of incoming arcs).
Definition tpl_net.H:333
void swap(Net_Graph &other) noexcept
Swap contents with another network. O(1) operation.
Definition tpl_net.H:731
Arc * insert_arc(Node *src_node, Node *tgt_node, const Arc_Type &arc_info=Arc_Type())
Insert an arc with zero capacity and flow.
Definition tpl_net.H:667
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1120
Residual node used by preflow-push algorithms.
Definition tpl_net.H:1344
PP_Res_Node()
Default constructor.
Definition tpl_net.H:1351
Net::Flow_Type out_flow
Definition tpl_net.H:1348
Net::Flow_Type in_flow
Definition tpl_net.H:1347
PP_Res_Node(const Empty_Class &info)
Constructor from node info.
Definition tpl_net.H:1354
PP_Res_Node(Empty_Class &&info)
Move constructor from node info.
Definition tpl_net.H:1357
Functor wrapper for random_preflow_maximum_flow().
Definition tpl_net.H:1842
Net::Flow_Type operator()(Net &net) const
Invoke random_preflow_maximum_flow().
Definition tpl_net.H:1844
Residual arc filter: keep arcs with residual capacity.
Definition tpl_net.H:1421
Res_F(typename Rnet::Node *) noexcept
Definition tpl_net.H:1422
Res_F() noexcept
Definition tpl_net.H:1423
bool operator()(typename Rnet::Arc *a) const
Definition tpl_net.H:1425
__Res_Arc(const Empty_Class &info)
Constructor from arc info.
Definition tpl_net.H:1372
__Res_Arc * dup
Definition tpl_net.H:1366
bool is_residual() const
Return true if this is a residual arc.
Definition tpl_net.H:1378
__Res_Arc(Empty_Class &&info)
Move constructor from arc info
Definition tpl_net.H:1375
Net::Arc * img
Definition tpl_net.H:1365
__Res_Arc()
Default constructor.
Definition tpl_net.H:1369
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
Dynamic binary heap with node-based storage.
Dynamic doubly linked list implementation.
Dynamic stack implementation based on linked lists.
Dynamic set implementations based on hash tables.
Dynamic set implementations based on balanced binary search trees.
Path finding algorithms in graphs.
Utility algorithms and operations for graphs.
Random access queue (bag) with O(1) random pop.