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
96 : Arc_Info(info), cap(__cap), flow(__flow)
97 {
98 // empty
99 }
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
130 Net_Arc(const Arc_Info & info)
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
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 template <typename T = Arc_Type,
668 typename = std::enable_if_t<!std::is_same<T, Flow_Type>::value &&
669 !std::is_arithmetic_v<T>>>
670 Arc * insert_arc(Node *src_node, Node *tgt_node,
671 const T & arc_info = Arc_Type())
672 {
673 return insert_arc(src_node, tgt_node, 0, 0, arc_info);
674 }
675
677 void remove_arc(Arc *arc) override
678 {
679 auto src = this->get_src_node(arc);
680 auto tgt = this->get_tgt_node(arc);
681 if (get_in_degree(tgt) == 1)
682 src_nodes.insert(tgt); // target becomes a source
683
684 Graph::remove_arc(arc); // base removal
685
686 if (get_out_degree(src) == 0)
687 sink_nodes.insert(src); // source becomes a sink
688 }
689
691 void disconnect_arc(Arc *arc) noexcept
692 {
693 auto src = this->get_src_node(arc);
694 auto tgt = this->get_tgt_node(arc);
695 if (get_in_degree(tgt) == 1)
696 src_nodes.insert(tgt); // target becomes a source
697
698 Graph::disconnect_arc(arc); // base disconnection
699
700 if (get_out_degree(src) == 0)
701 sink_nodes.insert(src); // source becomes a sink
702 }
703
705 void remove_node(Node *p) noexcept override
706 {
707 Graph::remove_node(p); // base removal
708 src_nodes.remove(p);
710 }
711
713 Net_Graph(const Net_Graph & net)
718 {
719 copy_graph(*this, net, false); // copy without mapping
720
721 using Pair = std::pair<typename Net_Graph::Arc *, typename Net_Graph::Arc *>;
722 zip(this->arcs(), net.arcs()).for_each([](const Pair & p)
723 {
724 auto atgt = p.first;
725 auto asrc = p.second;
726 atgt->cap = asrc->cap;
727 atgt->flow = asrc->flow;
728 });
729 }
730
732 void swap(Net_Graph & other) noexcept
733 {
734 Graph::common_swap(other); // swap num_nodes, num_arcs, digraph, cookie
735 Graph::get_node_dlink().swap(other.get_node_dlink());
736 Graph::get_arc_dlink().swap(other.get_arc_dlink());
737 src_nodes.swap(other.src_nodes);
738 sink_nodes.swap(other.sink_nodes);
739 std::swap(Infinity, other.Infinity);
740 std::swap(with_super_source, other.with_super_source);
741 std::swap(with_super_sink, other.with_super_sink);
742 }
743
746 : Infinity(std::numeric_limits<typename Arc::Flow_Type>::max()),
748 {
749 swap(other);
750 }
751
754 {
755 if (this != &other)
756 swap(other);
757 return *this;
758 }
759
762 {
763 if (this == &net)
764 return *this;
765
766 Net_Graph tmp(net); // copy construct
767 swap(tmp); // swap with copy
768 return *this;
769 }
770
772 void set_cap(Arc *arc, const Flow_Type & cap)
773 {
774 ah_out_of_range_error_if(cap < arc->flow) << "capacity value is smaller than flow";
775
776 arc->cap = cap;
777 }
778
780 void set_flow(Arc *arc, const Flow_Type & flow)
781 {
782 ah_out_of_range_error_if(flow > arc->cap) << "flow value is greater than capacity";
783
784 arc->flow = flow;
785 }
786
788 const Flow_Type &get_flow(Arc *arc) const noexcept { return arc->flow; }
789
791 const Flow_Type &get_cap(Arc *arc) const noexcept { return arc->cap; }
792
794 void reset()
795 {
796 for (Arc_Iterator<Net_Graph> it(*this); it.has_curr(); it.next_ne())
797 it.get_curr()->flow = 0;
798 }
799
804 bool check_network() const
805 {
807 return false;
808
809 const auto total_out = total_source_out_flow();
810 const auto total_in = total_sink_in_flow();
811
812 // Use tolerance for floating-point comparison
813 const auto eps = std::max(std::abs(total_out), std::abs(total_in)) * 1e-9;
814 const bool flow_balanced = std::abs(total_out - total_in) <= eps;
815
816 return this->nodes().all([this](Node *p) { return check_node(p); }) and
817 this->arcs().all([](Arc *a) { return a->check_arc(); }) and
819 }
820
823 {
825 << "network has no source or sink nodes";
826
827 const auto total_out = total_source_out_flow();
828 const auto total_in = total_sink_in_flow();
829
830 (void)total_in; // May be unused when NDEBUG disables assert().
832 return total_out;
833 }
834
837
840
847
849 friend std::ostream &operator <<(std::ostream & s, const Path<Net_Graph> & path)
850 {
851 if (path.is_empty())
852 return s << "Path is Empty";
853
854 const Net_Graph & net = path.get_graph();
855 typename Path<Net_Graph>::Iterator it(path);
856 s << it.get_current_node()->get_info();
857 for (; it.has_current_arc(); it.next_ne())
858 {
859 typename Net_Graph::Arc *a = it.get_current_arc_ne();
860 s << "(" << a->cap << "," << a->flow << ")"
861 << net.get_connected_node(a, it.get_current_node_ne())->get_info();
862 }
863 return s;
864 }
865 };
866
873 template <class Net>
874 using Parc = std::tuple<typename Net::Arc *, bool>; // second field marks forward.
875
883 template <class Net>
884 using SemiPath = std::tuple<bool, typename Net::Flow_Type, DynList<Parc<Net>>>;
885
887 template <class Net>
888 inline void print(const DynList<Parc<Net>> & sp)
889 {
890 if (sp.is_empty())
891 {
892 std::cout << "Semi path is Empty";
893 return;
894 }
895
896 for (typename DynList<Parc<Net>>::Iterator it(sp); it.has_curr();
897 it.next_ne())
898 {
899 const Parc<Net> & pa = it.get_curr();
900 auto a = get<0>(pa);
901 auto s = static_cast<typename Net::Node *>(a->src_node);
902 auto t = static_cast<typename Net::Node *>(a->tgt_node);
903 std::cout << s->get_info() << "(" << a->flow << "," << a->cap << ")"
904 << t->get_info() << " " << (get<1>(pa) ? "Normal" : "Reduced")
905 << '\n';
906 }
907 }
908
917 template <class Net>
918 typename Net::Flow_Type increase_flow(Net & net, const Path<Net> & path)
919 {
920 typename Net::Flow_Type slack = net.Infinity; // bottleneck
921 using Tuple = std::tuple<typename Net::Node *, typename Net::Arc *>;
922
923 // Compute the bottleneck of the augmenting path.
924 for (typename Path<Net>::Iterator it(path); it.has_current_arc();
925 it.next_ne())
926 {
927 Tuple t = it.get_tuple_ne();
928 auto p = get<0>(t);
929 auto arc = get<1>(t);
930 const auto w = remaining_flow<Net>(p, arc);
931 if (w < slack)
932 slack = w;
933 }
934
935 // Increase flow along the augmenting path.
936 for (typename Path<Net>::Iterator it(path); it.has_current_arc(); it.next_ne())
937 {
938 auto t = it.get_tuple_ne();
939 auto p = get<0>(t);
940 auto arc = get<1>(t);
941
942 if (is_residual<Net>(p, arc))
943 arc->flow -= slack;
944 else
945 arc->flow += slack;
946
947 assert(arc->check_arc());
948 }
949
950 return slack;
951 }
952
953
962 template <class Net>
963 void increase_flow(Net & net,
964 const DynList<Parc<Net>> & semi_path,
965 const typename Net::Flow_Type slack)
966 {
967 (void)net; // May be unused when NDEBUG disables assert().
968
969 // Increase flow along the semi-path.
970 for (typename DynList<Parc<Net>>::Iterator it(semi_path); it.has_curr();
971 it.next_ne())
972 {
973 auto p = it.get_curr();
974 auto arc = get<0>(p);
975 if (get<1>(p)) // forward arc
976 arc->flow += slack;
977 else
978 arc->flow -= slack;
979
980 assert(arc->check_arc());
981 }
982 assert(net.check_network());
983 }
984
996 template <class Net>
997 void decrease_flow(Net & net, const DynList<Parc<Net>> & semi_path,
998 const typename Net::Flow_Type slack)
999 {
1000 (void)net;
1001
1002 // Decrease flow: reverse the direction logic from increase_flow
1003 for (typename DynList<Parc<Net>>::Iterator it(semi_path); it.has_curr();
1004 it.next_ne())
1005 {
1006 auto p = it.get_curr();
1007 auto arc = get<0>(p);
1008 if (get<1>(p)) // forward arc: decrease instead of increase
1009 arc->flow -= slack;
1010 else // residual arc: increase instead of decrease
1011 arc->flow += slack;
1012
1013 assert(arc->check_arc());
1014 }
1015 }
1016
1017
1024 template <class Net, template <typename T> class Q>
1026 {
1027 const Net & net;
1028
1029 // Return end node if a path is found.
1030 typename Net::Node * search(typename Net::Node *start,
1031 typename Net::Node *end,
1032 typename Net::Flow_Type min_slack)
1033 {
1034 using Itor = Net_Iterator<Net>;
1035 net.reset_nodes();
1036 net.reset_arcs();
1037
1038 start->set_state(Processed);
1040 for (Itor it(start); it.has_curr(); it.next_ne())
1041 {
1042 auto a = it.get_curr();
1043 if (remaining_flow<Net>(start, a) < min_slack)
1044 continue;
1045 auto tgt = net.get_connected_node(a, start);
1046 tgt->set_state(Processing);
1047 a->set_state(Processing);
1048 q.put(a);
1049 }
1050
1051 typename Net::Node *curr = nullptr;
1052 while (not q.is_empty())
1053 {
1054 auto arc = q.get();
1055 assert(arc->state() == Processing);
1056 arc->set_state(Processed);
1057
1058 auto s = net.get_src_node(arc);
1059 auto t = net.get_tgt_node(arc);
1060
1061 if (s->state() == Processed and t->state() == Processed)
1062 continue;
1063
1064 curr = s->state() == Processed ? t : s;
1065 assert(curr->state() == Processing);
1066 curr->set_state(Processed);
1067 NODE_COOKIE(curr) = net.get_connected_node(arc, curr);
1068
1069 if (curr == end)
1070 return curr;
1071
1072 for (Itor it(curr); it.has_curr(); it.next_ne())
1073 {
1074 auto a = it.get_curr();
1075
1076 // Skip arcs already processed or already in queue
1077 if (a->state() != Unprocessed)
1078 continue;
1079
1080 if (remaining_flow<Net>(curr, a) < min_slack)
1081 continue;
1082
1083 auto tgt = net.get_connected_node(a, curr);
1084 if (tgt->state() == Processed)
1085 {
1086 a->set_state(Processed);
1087 continue;
1088 }
1089
1090 a->set_state(Processing);
1091 q.put(a);
1092 tgt->set_state(Processing);
1093 }
1094 } // end while
1095
1096 return nullptr;
1097 }
1098
1100 Path<Net> find(typename Net::Node *start, typename Net::Node *end,
1101 const typename Net::Flow_Type & min_slack = typename Net::Flow_Type{0})
1102 {
1103 auto curr = search(start, end, min_slack);
1104
1105 Path<Net> ret(net);
1106 if (not curr)
1107 return ret;
1108
1109 assert(curr == end);
1110
1111 while (curr != start)
1112 {
1113 ret.insert(curr);
1114 curr = static_cast<typename Net::Node *>(NODE_COOKIE(curr));
1115 }
1116 ret.insert(start);
1117
1118 return ret;
1119 }
1120
1123 typename Net::Node *end,
1124 typename Net::Flow_Type min_slack = typename Net::Flow_Type{0})
1125 {
1126 auto t = search(start, end, min_slack);
1127 if (not t)
1128 return std::make_tuple(false, typename Net::Flow_Type{0}, DynList<Parc<Net>>());
1129
1130 assert(t == end);
1131
1133 auto m = std::numeric_limits<typename Net::Flow_Type>::max();
1134 while (t != start)
1135 {
1136 auto s = static_cast<typename Net::Node *>(NODE_COOKIE(t));
1137 // Find arc connecting s and t with positive residual capacity.
1138 // With parallel arcs, we must pick one that can carry flow.
1139 typename Net::Arc *a = nullptr;
1140 typename Net::Arc *fallback = nullptr;
1141 for (Node_Arc_Iterator<Net> it(t); it.has_curr(); it.next_ne())
1142 {
1143 auto arc = it.get_curr();
1144 if ((arc->src_node == s and arc->tgt_node == t) or
1145 (arc->src_node == t and arc->tgt_node == s))
1146 {
1147 if (fallback == nullptr)
1148 fallback = arc; // Keep first match as fallback
1149 // Prefer arc with positive residual capacity
1150 if (remaining_flow<Net>(s, arc) > 0)
1151 {
1152 a = arc;
1153 break;
1154 }
1155 }
1156 }
1157 if (a == nullptr)
1158 a = fallback; // Use fallback if no arc with residual capacity
1159 assert(a != nullptr);
1160 bool normal = a->tgt_node == t;
1161 auto slack = normal ? a->cap - a->flow : a->flow;
1162 m = std::min(m, slack);
1163 semi_path.insert(std::make_tuple(a, normal));
1164 t = s;
1165 }
1166
1167 return std::make_tuple(true, m, std::move(semi_path));
1168 }
1169
1170 public:
1176
1182
1185 {
1186 // empty
1187 }
1188
1191 typename Net::Node *end,
1192 typename Net::Flow_Type min_slack = 0)
1193 {
1194 return find(start, end, min_slack);
1195 }
1196
1202
1207 typename Net::Flow_Type
1208 semi_path(typename Net::Node *start,
1209 typename Net::Node *end,
1211 const typename Net::Flow_Type & min_slack = 0)
1212 {
1213 semi_path.empty();
1214
1215 auto result = find_path(start, end, min_slack);
1216 if (not get<0>(result))
1217 return typename Net::Flow_Type{};
1218
1219 semi_path = std::move(get<2>(result));
1220 return get<1>(result);
1221 }
1222 };
1223
1225 template <class Net>
1227
1228
1230 template <class Net>
1232
1233
1241 template <class Net, template <typename T> class Q>
1243 const typename Net::Flow_Type & min_slack)
1244 {
1245 auto s = net.get_source();
1246 auto t = net.get_sink();
1247 return Find_Aumenting_Path<Net, Q>(net)(s, t, min_slack);
1248 }
1249
1250
1252 template <class Net>
1254 const typename Net::Flow_Type & min_slack)
1255 {
1257 }
1258
1259
1261 template <class Net>
1263 const typename Net::Flow_Type & min_slack)
1264 {
1266 }
1267
1268
1277 template <class Net, template <typename T> class Q>
1279 const typename Net::Flow_Type & slack)
1280 {
1281 return Find_Aumenting_Path<Net, Q>(net).find_aum_path(slack);
1282 }
1283
1284
1286 template <class Net>
1289 const typename Net::Flow_Type & slack)
1290 {
1292 }
1293
1294
1296 template <class Net>
1299 const typename Net::Flow_Type & slack)
1300 {
1302 }
1303
1304
1313 template <class Net, template <typename T> class Q>
1316 const typename Net::Flow_Type & slack)
1317 {
1318 return Find_Aumenting_Path<Net, Q>(net).find_dec_path(slack);
1319 }
1320
1321
1323 template <class Net>
1326 const typename Net::Flow_Type & slack)
1327 {
1329 }
1330
1331
1333 template <class Net>
1336 const typename Net::Flow_Type & slack)
1337 {
1339 }
1340
1341
1343 template <class Net>
1344 struct PP_Res_Node : public Net_Node<Empty_Class>
1345 {
1347
1350
1353
1356
1359 };
1360
1361 template <class Net>
1362 struct __Res_Arc : public Net_Arc<Empty_Class, typename Net::Flow_Type>
1363 {
1365
1366 typename Net::Arc *img = nullptr; // nullptr indicates residual arc
1367 __Res_Arc *dup = nullptr;
1368
1371
1374
1377
1379 bool is_residual() const { return img == nullptr; }
1380 };
1381
1382
1384 template <class Net>
1386
1388 template <class Net>
1390
1392 template <class Net>
1393 inline
1395 typename Net::Arc *a)
1396 {
1397 using Rnet = PP_Res_Net<Net>;
1398 auto s = net.get_src_node(a);
1399 auto t = net.get_tgt_node(a);
1400
1402
1403 auto src = static_cast<typename Rnet::Node *>(NODE_COOKIE(s));
1404 auto tgt = static_cast<typename Rnet::Node *>(NODE_COOKIE(t));
1405
1406 auto arc = rnet.insert_arc(src, tgt);
1407 auto dup = rnet.insert_arc(tgt, src);
1408
1409 arc->img = a; // mark it as not residual
1410 arc->cap = a->cap;
1411 arc->flow = a->flow;
1412 arc->dup = dup;
1413
1414 dup->cap = arc->cap;
1415 dup->flow = arc->cap - arc->flow;
1416 dup->dup = arc;
1417 }
1418
1420 template <class Rnet>
1421 struct Res_F
1422 {
1423 Res_F(typename Rnet::Node *) noexcept {}
1425
1426 bool operator ()(typename Rnet::Arc *a) const
1427 {
1428 return a->cap > a->flow;
1429 }
1430 };
1431
1436 template <class Net>
1437 inline
1438 std::tuple<PP_Res_Net<Net>, typename PP_Res_Net<Net>::Node *,
1439 typename PP_Res_Net<Net>::Node *>
1441 {
1442 using Rnet = PP_Res_Net<Net>;
1443 net.reset_nodes();
1444 Rnet rnet;
1445
1446 for (typename Net::Node_Iterator it(net); it.has_curr(); it.next_ne())
1447 {
1448 auto p = it.get_curr();
1449 auto q = rnet.insert_node();
1450 q->in_flow = net.get_in_flow(p);
1451 q->out_flow = net.get_out_flow(p);
1452 // Directly store pointers in cookies using reinterpret_cast to
1453 // preserve exact addresses without multiple inheritance adjustment
1454 NODE_COOKIE(p) = reinterpret_cast<void*>(q);
1455 NODE_COOKIE(q) = reinterpret_cast<void*>(p);
1456 }
1457
1458 for (typename Net::Arc_Iterator it(net); it.has_curr(); it.next_ne())
1459 create_residual_arc(net, rnet, it.get_curr());
1460
1461 return std::make_tuple(std::move(rnet),
1462 static_cast<typename Rnet::Node *>(NODE_COOKIE(net.get_source())),
1463 static_cast<typename Rnet::Node *>(NODE_COOKIE(net.get_sink())));
1464 }
1465
1467 template <class Rnet>
1468 inline
1469 void update_flow(const Rnet & rnet)
1470 {
1471 for (typename Rnet::Arc_Iterator it(rnet); it.has_curr(); it.next_ne())
1472 {
1473 auto arc = it.get_curr();
1474 auto img = arc->img;
1475 if (img == nullptr)
1476 continue;
1477 img->flow = arc->flow;
1478 }
1479 }
1480
1488 template <class Net,
1489 template <class> class Find_Path>
1491 {
1493 << "Network is not single source and single sink";
1494
1495 while (true) // while an augmenting path exists
1496 {
1497 SemiPath<Net> semi_path = Find_Path<Net>(net)();
1498 if (not get<0>(semi_path))
1499 break;
1500
1501 // Skip paths with zero slack.
1502 // This can happen with parallel arcs where one arc is saturated
1503 // but the path finder still finds a path through it.
1504 auto slack = get<1>(semi_path);
1505 if (slack <= typename Net::Flow_Type{0})
1506 break;
1507
1508 increase_flow<Net>(net, get<2>(semi_path), slack);
1509 }
1510
1511 return net.get_out_flow(net.get_source());
1512 }
1513
1514
1522 template <class Net>
1527
1528
1533 template <class Net>
1535 {
1537 typename Net::Flow_Type operator ()(Net & net) const
1538 {
1539 return ford_fulkerson_maximum_flow(net);
1540 }
1541 };
1542
1550 template <class Net>
1555
1556
1561 template <class Net>
1563 {
1565 typename Net::Flow_Type operator ()(Net & net) const
1566 {
1568 }
1569 };
1570
1572 template <class Net>
1573 static inline
1574 bool is_node_active(const Net & net, typename Net::Node *p)
1575 {
1576 return net.get_in_flow(p) != net.get_out_flow(p);
1577 }
1578
1580 template <class Rnet>
1581 static inline
1582 bool is_node_active(typename Rnet::Node *p)
1583 {
1584 return p->in_flow != p->out_flow;
1585 }
1586
1587
1589 template <class Net>
1590 static inline
1591 long &node_height(typename Net::Node *p) { return NODE_COUNTER(p); }
1592
1593
1595 template <class Net>
1596 static inline
1598 {
1600 exec(net.get_sink(),
1601 [&net](typename Net::Node *p, typename Net::Arc *a)
1602 {
1603 if (a)
1605 return true;
1606 });
1607 }
1608
1609
1611 template <class Q_Type>
1612 static inline
1613 void put_in_active_queue(Q_Type & q, typename Q_Type::Item_Type & p)
1614 {
1615 if (NODE_BITS(p).get_bit(Aleph::Maximum_Flow))
1616 return; // the node is already into the queue
1617 NODE_BITS(p).set_bit(Aleph::Maximum_Flow, true);
1618 q.put(p);
1619 }
1620
1621
1623 template <class Q_Type>
1624 static inline
1625 typename Q_Type::Item_Type get_from_active_queue(Q_Type & q)
1626 {
1627 auto p = q.get();
1629 NODE_BITS(p).set_bit(Aleph::Maximum_Flow, false);
1630 return p;
1631 }
1632
1633
1635 template <class Q_Type>
1636 static inline
1637 void remove_from_active_queue(Q_Type & q, typename Q_Type::Item_Type & p)
1638 {
1640 NODE_BITS(p).set_bit(Aleph::Maximum_Flow, false);
1641 q.remove(p);
1642 }
1643
1644
1659 template <class Net, class Q_Type>
1660 typename Net::Flow_Type
1662 {
1664 << "Network is not single source and single sink";
1665
1666 net.reset_nodes(); // especially assures that counters are in zero
1667 init_height_in_nodes(net); // set height to minimum distance in nodes to sink
1668
1669 auto source = net.get_source();
1670 auto sink = net.get_sink();
1671 node_height<Net>(source) = net.vsize(); // except the source
1672 constexpr auto Max = std::numeric_limits<long>::max();
1673
1674 using Itor = __Net_Iterator<Net>;
1675 Q_Type q;
1676 for (Itor it(source); it.has_curr(); it.next_ne()) // initial preflow
1677 {
1678 auto arc = it.get_curr();
1679 arc->flow = arc->cap; // saturate arc
1680 auto tgt = net.get_tgt_node(arc);
1681 put_in_active_queue(q, tgt);
1682 }
1683
1684 while (not q.is_empty()) // while there are active nodes
1685 {
1686 auto src = get_from_active_queue(q);
1687 auto excess = net.get_in_flow(src) - net.get_out_flow(src);
1688 long m = Max;
1689 bool was_eligible_arc = false;
1690 for (Itor it(src); it.has_curr() and excess > 0; it.next_ne())
1691 {
1692 auto arc = it.get_curr();
1693 auto tgt = net.get_connected_node(arc, src);
1694 if (node_height<Net>(src) != node_height<Net>(tgt) + 1)
1695 {
1696 m = std::min(m, node_height<Net>(tgt));
1697 continue;
1698 }
1699
1700 was_eligible_arc = true;
1702 if (is_residual<Net>(src, arc))
1703 {
1704 flow_to_push = std::min(arc->flow, excess);
1705 arc->flow -= flow_to_push;
1706 }
1707 else
1708 {
1709 flow_to_push = std::min(arc->cap - arc->flow, excess);
1710 arc->flow += flow_to_push;
1711 }
1712 excess -= flow_to_push;
1713 if (tgt != source and tgt != sink)
1714 {
1715 assert(is_node_active(net, tgt));
1716 put_in_active_queue(q, tgt);
1717 }
1718 }
1719
1720 if (excess > 0) // is src still active
1721 {
1723 node_height<Net>(src) = m + 1;
1724 put_in_active_queue(q, src);
1725 }
1726 }
1727
1728 assert(net.check_network());
1729
1730 return net.flow_value();
1731 }
1732
1733
1735 template <class Rnet>
1736 inline
1737 void init_height_in_nodes(Rnet & rnet, typename Rnet::Node *sink)
1738 {
1740 exec(sink, [&rnet](typename Rnet::Node *p, typename Rnet::Arc *a)
1741 {
1742 if (a)
1743 node_height<Rnet>(p) = node_height<Rnet>(rnet.get_src_node(a)) + 1;
1744 return true;
1745 });
1746 }
1747
1748
1756 template <class Net>
1757 typename Net::Flow_Type
1759 {
1760 using Node = typename Net::Node;
1762 <Net, DynListQueue<Node *>>(net);
1763 }
1764
1769 template <class Net>
1771 {
1773 typename Net::Flow_Type
1774 operator ()(Net & net) const
1775 {
1776 return fifo_preflow_maximum_flow(net);
1777 }
1778 };
1779
1780
1782 template <class Net>
1784 {
1785 bool operator ()(typename Net::Node *n1, typename Net::Node *n2) const
1786 {
1787 return node_height<Net>(n1) > node_height<Net>(n2);
1788 }
1789 };
1790
1798 template <class Net>
1799 typename Net::Flow_Type
1806
1811 template <class Net>
1813 {
1815 typename Net::Flow_Type operator ()(Net & net) const
1816 {
1817 return heap_preflow_maximum_flow(net);
1818 }
1819 };
1820
1828 template <class Net>
1829 typename Net::Flow_Type
1835
1836
1841 template <class Net>
1843 {
1845 typename Net::Flow_Type operator ()(Net & net) const
1846 {
1847 return random_preflow_maximum_flow(net);
1848 }
1849 };
1850
1851
1863 template <class Net, template <class> class Maxflow>
1869 {
1870 Maxflow<Net>()(net); // compute max flow
1871
1872 typename Net::Node *source = net.get_source();
1873
1874 // Traverse the residual network from source: reachable nodes go to vs.
1876 (source, [&vs](typename Net::Node *p)
1877 {
1878 vs.insert(p);
1879 return true;
1880 });
1881
1882 // Compute vt by complement.
1883 const size_t size_vt = net.get_num_nodes() - vs.size();
1884 for (Node_Iterator<Net> it(net); it.has_curr() and
1885 vt.size() < size_vt; it.next_ne())
1886 {
1887 if (auto p = it.get_curr(); p->state() == Unprocessed)
1888 vt.insert(p);
1889 }
1890
1891 for (Arc_Iterator<Net> it(net); it.has_curr(); it.next_ne())
1892 {
1893 auto arc = it.get_curr();
1894 if (arc->flow == 0) // residual candidate
1895 if (vt.contains(net.get_src_node(arc)) and // vt -> vs
1896 vs.contains(net.get_tgt_node(arc)))
1897 {
1898 cutt.insert(arc);
1899 continue;
1900 }
1901
1902 if (arc->flow == arc->cap) // saturated candidate
1903 if (vs.contains(net.get_src_node(arc)) and // vs -> vt
1904 vt.contains(net.get_tgt_node(arc)))
1905 cuts.insert(arc);
1906 }
1907
1908 return net.flow_value();
1909 }
1910
1911
1916 template <class Net,
1917 template <class> class Maxflow = Heap_Preflow_Maximum_Flow>
1930} // end namespace Aleph
1931
1932# 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:579
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:463
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
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
bool has_curr() const noexcept
Return true the iterator has current node.
Filtered iterator on directed graphs.
Definition tpl_graph.H:1609
bool has_curr() const noexcept
Return true the iterator has an current arc.
Definition tpl_graph.H:1645
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3848
typename BaseGraph::Node Node
Definition graph-dry.H:3851
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:1714
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
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
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:1026
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:1190
Find_Aumenting_Path(const Net &__g)
Construct a finder for net.
Definition tpl_net.H:1184
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:1208
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:1100
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:1178
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:1172
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:1122
Net::Node * search(typename Net::Node *start, typename Net::Node *end, typename Net::Flow_Type min_slack)
Definition tpl_net.H:1030
bool has_curr() const noexcept
Return true if iterator has current item.
Definition htlist.H:1150
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1206
Iterator on nodes and arcs of a path.
Definition tpl_graph.H:3201
Node * get_current_node_ne() const noexcept
Definition tpl_graph.H:3227
Node * get_current_node() const
Return the current node of a path.
Definition tpl_graph.H:3222
Arc * get_current_arc_ne() const noexcept
Definition tpl_graph.H:3249
bool has_current_arc() const noexcept
Return true if iterator has current arc.
Definition tpl_graph.H:3308
Path on a graph.
Definition tpl_graph.H:2669
bool is_empty() const noexcept
Return true if the path is empty.
Definition tpl_graph.H:2813
const GT & get_graph() const noexcept
Get a constant reference to the graph.
Definition tpl_graph.H:2741
bool all(Operation &operation) const
Check if all the elements of container satisfy a condition.
Definition ah-dry.H:816
void reset_arcs() const
Reset all the arcs of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:927
Container< Arc * > arcs() const
Return a container with all the arcs of the graph.
Definition graph-dry.H:2738
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
std::tuple< Arc *, Node * > ArcPair
Pair of arc and node (topologically related)
Definition graph-dry.H:3189
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
Definition graph-dry.H:772
void common_swap(GT &g) noexcept
Definition graph-dry.H:641
size_t out_degree(Node *p) const noexcept
Compute the output degree of a node.
Definition graph-dry.H:3273
constexpr size_t vsize() const noexcept
Definition graph-dry.H:698
void reset_nodes() const
Reset all the nodes of graph (the control bits, the state, the counter and the cookie)
Definition graph-dry.H:920
size_t in_degree(Node *p) const noexcept
Compute the input degree of a node.
Definition graph-dry.H:3250
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
Container< Node * > nodes() const
Return a container with all the nodes of the graph.
Definition graph-dry.H:2720
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:4110
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
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:3567
@ 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:1288
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:1637
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:997
Net::Flow_Type edmonds_karp_maximum_flow(Net &net)
Maximize flow using the Edmonds-Karp algorithm.
Definition tpl_net.H:1551
Net::Flow_Type generic_preflow_vertex_push_maximum_flow(Net &net)
Generic preflow-push maximum flow (vertex-oriented).
Definition tpl_net.H:1661
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:1830
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:1253
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:1315
Net::Flow_Type heap_preflow_maximum_flow(Net &net)
Preflow-push maximum flow using a height-ordered heap.
Definition tpl_net.H:1800
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:1298
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.
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:1625
Net::Flow_Type increase_flow(Net &net, const Path< Net > &path)
Increase flow along an augmenting path.
Definition tpl_net.H:918
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
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:1325
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:1394
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:1440
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:1262
static long & node_height(typename Net::Node *p)
Access the height label stored in NODE_COUNTER.
Definition tpl_net.H:1591
std::tuple< bool, typename Net::Flow_Type, DynList< Parc< Net > > > SemiPath
Semi-path tuple:
Definition tpl_net.H:884
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:1278
Net::Flow_Type fifo_preflow_maximum_flow(Net &net)
Preflow-push maximum flow using a FIFO queue of active nodes.
Definition tpl_net.H:1758
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:1242
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:1574
Net::Flow_Type ford_fulkerson_maximum_flow(Net &net)
Maximize flow using the Ford-Fulkerson algorithm.
Definition tpl_net.H:1523
static void init_height_in_nodes(Net &net)
Initialize node heights with BFS distance to the sink.
Definition tpl_net.H:1597
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:1335
void update_flow(const Rnet &rnet)
Propagate residual arc flows back to their original arcs.
Definition tpl_net.H:1469
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:1613
Net::Flow_Type aumenting_path_maximum_flow(Net &net)
Maximize flow using repeated augmenting-path searches.
Definition tpl_net.H:1490
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:1864
std::tuple< typename Net::Arc *, bool > Parc
Arc entry for a semi-path.
Definition tpl_net.H:874
DynList< T > maps(const C &c, Op op)
Classic map operation.
void print(const DynList< Parc< Net > > &sp)
Print a semi-path to stdout.
Definition tpl_net.H:888
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:1164
Iterator over arcs of a graph.
Definition tpl_agraph.H:325
Compare nodes by height (higher first).
Definition tpl_net.H:1784
bool operator()(typename Net::Node *n1, typename Net::Node *n2) const
Definition tpl_net.H:1785
Functor wrapper for edmonds_karp_maximum_flow().
Definition tpl_net.H:1563
Net::Flow_Type operator()(Net &net) const
Invoke edmonds_karp_maximum_flow().
Definition tpl_net.H:1565
Empty placeholder class with no data members.
Definition ahDefs.H:105
Functor wrapper for fifo_preflow_maximum_flow().
Definition tpl_net.H:1771
Net::Flow_Type operator()(Net &net) const
Invoke fifo_preflow_maximum_flow().
Definition tpl_net.H:1774
Functor wrapper for ford_fulkerson_maximum_flow().
Definition tpl_net.H:1535
Net::Flow_Type operator()(Net &net) const
Invoke ford_fulkerson_maximum_flow().
Definition tpl_net.H:1537
Functor wrapper for heap_preflow_maximum_flow().
Definition tpl_net.H:1813
Net::Flow_Type operator()(Net &net) const
Invoke heap_preflow_maximum_flow().
Definition tpl_net.H:1815
Functor wrapper for min_cut().
Definition tpl_net.H:1919
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:1921
Arc info extension that stores capacity and flow values.
Definition tpl_net.H:84
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
Ftype Flow_Type
Type representing flow, capacity, and cost values.
Definition tpl_netcost.H:98
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:772
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:761
bool check_network() const
Validate flow-conservation and capacity constraints.
Definition tpl_net.H:804
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:839
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:842
Net_Graph(const Net_Graph &net)
Copy-construct a network. Throws bad_alloc on allocation failure.
Definition tpl_net.H:713
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:677
void set_flow(Arc *arc, const Flow_Type &flow)
Set the flow of an arc. Throws if flow exceeds capacity.
Definition tpl_net.H:780
Node * insert_node(Node *p)
Insert a node by copying another node.
Definition tpl_net.H:590
Arc * insert_arc(Node *src_node, Node *tgt_node, const T &arc_info=Arc_Type())
Insert an arc with zero capacity and flow.
Definition tpl_net.H:670
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:849
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:691
bool with_super_source
True if the network has a super-source.
Definition tpl_net.H:836
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:822
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:705
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:753
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:745
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:791
const Flow_Type & get_flow(Arc *arc) const noexcept
Return the flow value of an arc.
Definition tpl_net.H:788
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:794
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:732
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1119
Residual node used by preflow-push algorithms.
Definition tpl_net.H:1345
PP_Res_Node()
Default constructor.
Definition tpl_net.H:1352
Net::Flow_Type out_flow
Definition tpl_net.H:1349
Net::Flow_Type in_flow
Definition tpl_net.H:1348
PP_Res_Node(const Empty_Class &info)
Constructor from node info.
Definition tpl_net.H:1355
PP_Res_Node(Empty_Class &&info)
Move constructor from node info.
Definition tpl_net.H:1358
Functor wrapper for random_preflow_maximum_flow().
Definition tpl_net.H:1843
Net::Flow_Type operator()(Net &net) const
Invoke random_preflow_maximum_flow().
Definition tpl_net.H:1845
Residual arc filter: keep arcs with residual capacity.
Definition tpl_net.H:1422
Res_F(typename Rnet::Node *) noexcept
Definition tpl_net.H:1423
Res_F() noexcept
Definition tpl_net.H:1424
bool operator()(typename Rnet::Arc *a) const
Definition tpl_net.H:1426
__Res_Arc(const Empty_Class &info)
Constructor from arc info.
Definition tpl_net.H:1373
__Res_Arc * dup
Definition tpl_net.H:1367
bool is_residual() const
Return true if this is a residual arc.
Definition tpl_net.H:1379
__Res_Arc(Empty_Class &&info)
Move constructor from arc info
Definition tpl_net.H:1376
Net::Arc * img
Definition tpl_net.H:1366
__Res_Arc()
Default constructor.
Definition tpl_net.H:1370
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.