Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
network_flow_example.C
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
132#include <iostream>
133#include <iomanip>
134#include <string>
135#include <vector>
136#include <tpl_net.H>
137#include <tclap/CmdLine.h>
138
139using namespace std;
140using namespace Aleph;
141
142// Node info type
143using NodeInfo = string;
144
145// Arc info type (empty - capacity/flow handled by Net_Arc)
147
148// Flow type
149using FlowType = int;
150
151// Network type
153
172{
173 FlowNet net;
174
175 // Create nodes
176 auto source = net.insert_node("Source");
177 auto b = net.insert_node("PumpB");
178 auto c = net.insert_node("PumpC");
179 auto d = net.insert_node("PumpD");
180 auto sink = net.insert_node("Sink");
181
182 // Add edges with capacities (in liters/second)
183 // Note: In Net_Graph, source/sink status is automatic based on topology
184 // - Source will have no incoming arcs
185 // - Sink will have no outgoing arcs
186
187 // From source
188 net.insert_arc(source, b, 10);
189 net.insert_arc(source, c, 8);
190
191 // Internal
192 net.insert_arc(b, d, 4);
193 net.insert_arc(c, d, 5);
194
195 // To sink
196 net.insert_arc(b, sink, 8);
197 net.insert_arc(c, sink, 2);
198 net.insert_arc(d, sink, 6);
199
200 return net;
201}
202
207{
208 FlowNet net;
209
210 auto source = net.insert_node("Source");
211 auto r1 = net.insert_node("Router1");
212 auto r2 = net.insert_node("Router2");
213 auto r3 = net.insert_node("Router3");
214 auto r4 = net.insert_node("Router4");
215 auto s1 = net.insert_node("Switch1");
216 auto s2 = net.insert_node("Switch2");
217 auto sink = net.insert_node("Sink");
218
219 // Source connections
220 net.insert_arc(source, r1, 15);
221 net.insert_arc(source, s1, 20);
222
223 // Internal connections
224 net.insert_arc(r1, r2, 5);
225 net.insert_arc(r1, r3, 10);
226 net.insert_arc(r2, s1, 7);
227 net.insert_arc(r3, r4, 8);
228 net.insert_arc(s1, s2, 6);
229 net.insert_arc(s2, r4, 9);
230
231 // Sink connections
232 net.insert_arc(r3, sink, 12);
233 net.insert_arc(r4, sink, 15);
234
235 return net;
236}
237
241void print_network(FlowNet& net, const string& title)
242{
243 cout << "\n=== " << title << " ===" << endl;
244 cout << "Nodes: " << net.get_num_nodes() << endl;
245 cout << "Arcs: " << net.get_num_arcs() << endl;
246
247 // Show source and sink
248 cout << "Source: " << net.get_source()->get_info() << endl;
249 cout << "Sink: " << net.get_sink()->get_info() << endl;
250
251 cout << "\nEdge flows (flow/capacity):" << endl;
252
254 FlowType total_in = 0;
255
256 for (auto it = net.get_arc_it(); it.has_curr(); it.next())
257 {
258 auto* arc = it.get_curr();
259 auto* src = net.get_src_node(arc);
260 auto* tgt = net.get_tgt_node(arc);
261
262 cout << " " << setw(10) << left << src->get_info()
263 << " ---> " << setw(10) << left << tgt->get_info()
264 << right << " : " << setw(3) << arc->flow
265 << " / " << setw(3) << arc->cap;
266
267 // Show utilization
268 if (arc->cap > 0)
269 {
270 double util = 100.0 * arc->flow / arc->cap;
271 cout << " (" << fixed << setprecision(0) << util << "%)";
272 if (arc->flow == arc->cap)
273 cout << " [SATURATED]";
274 }
275 cout << endl;
276
277 if (net.is_source(src))
278 total_out += arc->flow;
279 if (net.is_sink(tgt))
280 total_in += arc->flow;
281 }
282
283 cout << "\nFlow out of source: " << total_out << endl;
284 cout << "Flow into sink: " << total_in << endl;
285}
286
291{
292 cout << "\n=== Min-Cut (Dual of Max-Flow) ===" << endl;
293 cout << "\nBy the Max-Flow Min-Cut Theorem:" << endl;
294 cout << " Maximum flow value = Minimum cut capacity" << endl;
295
296 cout << "\nSaturated edges (part of min-cut):" << endl;
297
298 for (auto it = net.get_arc_it(); it.has_curr(); it.next())
299 {
300 auto* arc = it.get_curr();
301 if (arc->flow == arc->cap && arc->cap > 0)
302 {
303 auto* src = net.get_src_node(arc);
304 auto* tgt = net.get_tgt_node(arc);
305 cout << " " << src->get_info() << " -> "
306 << tgt->get_info() << " (capacity " << arc->cap << ")" << endl;
307 }
308 }
309
310 cout << "\nNote: The min-cut separates source from sink." << endl;
311 cout << "Cutting these edges disconnects source from sink." << endl;
312}
313
318{
319 cout << "\n=== Bipartite Matching via Max-Flow ===" << endl;
320
321 cout << "\nProblem: Assign workers to jobs (each worker can do some jobs)" << endl;
322
323 // Build bipartite matching network
324 FlowNet net;
325
326 auto source = net.insert_node("Source");
327
328 // Workers
329 auto alice = net.insert_node("Alice");
330 auto bob = net.insert_node("Bob");
331 auto carol = net.insert_node("Carol");
332
333 // Jobs
334 auto coding = net.insert_node("Coding");
335 auto design = net.insert_node("Design");
336 auto testing = net.insert_node("Testing");
337
338 auto sink = net.insert_node("Sink");
339
340 // Each worker can be assigned to at most 1 job (capacity 1 from source)
341 net.insert_arc(source, alice, 1);
342 net.insert_arc(source, bob, 1);
343 net.insert_arc(source, carol, 1);
344
345 // Worker-job compatibility (edges with capacity 1)
346 net.insert_arc(alice, coding, 1); // Alice can code
347 net.insert_arc(alice, design, 1); // Alice can design
348 net.insert_arc(bob, coding, 1); // Bob can code
349 net.insert_arc(bob, testing, 1); // Bob can test
350 net.insert_arc(carol, design, 1); // Carol can design
351 net.insert_arc(carol, testing, 1); // Carol can test
352
353 // Each job needs at most 1 worker (capacity 1 to sink)
354 net.insert_arc(coding, sink, 1);
355 net.insert_arc(design, sink, 1);
356 net.insert_arc(testing, sink, 1);
357
358 cout << "\nWorker skills:" << endl;
359 cout << " Alice: Coding, Design" << endl;
360 cout << " Bob: Coding, Testing" << endl;
361 cout << " Carol: Design, Testing" << endl;
362
363 // Compute max flow = max matching using Ford-Fulkerson
365
366 cout << "\nMaximum matching size: " << max_matching << endl;
367 cout << "\nOptimal assignment:" << endl;
368
369 for (auto it = net.get_arc_it(); it.has_curr(); it.next())
370 {
371 auto* arc = it.get_curr();
372 auto* src = net.get_src_node(arc);
373 auto* tgt = net.get_tgt_node(arc);
374
375 // Skip source and sink edges
376 if (net.is_source(src) || net.is_sink(tgt))
377 continue;
378
379 if (arc->flow == 1)
380 {
381 cout << " " << src->get_info() << " -> "
382 << tgt->get_info() << endl;
383 }
384 }
385}
386
387int main(int argc, char* argv[])
388{
389 try
390 {
391 TCLAP::CmdLine cmd("Network Flow Example", ' ', "1.0");
392
393 TCLAP::SwitchArg simpleArg("s", "simple",
394 "Use simple water network", false);
395 TCLAP::SwitchArg complexArg("c", "complex",
396 "Use complex datacenter network", false);
397 TCLAP::SwitchArg matchArg("m", "matching",
398 "Demonstrate bipartite matching", false);
399 TCLAP::SwitchArg allArg("a", "all",
400 "Run all demos", false);
401 TCLAP::SwitchArg verboseArg("v", "verbose",
402 "Show detailed output", false);
403
404 cmd.add(simpleArg);
405 cmd.add(complexArg);
406 cmd.add(matchArg);
407 cmd.add(allArg);
408 cmd.add(verboseArg);
409
410 cmd.parse(argc, argv);
411
412 bool runSimple = simpleArg.getValue();
413 bool runComplex = complexArg.getValue();
414 bool runMatch = matchArg.getValue();
415 bool runAll = allArg.getValue();
416 (void)verboseArg.getValue(); // Unused but available
417
418 // Default: run all demos
419 if (!runSimple && !runComplex && !runMatch)
420 runAll = true;
421
422 cout << "=== Maximum Flow Problem ===" << endl;
423 cout << "Algorithm used: Ford-Fulkerson (DFS augmenting paths)" << endl;
424
425 if (runAll || runSimple)
426 {
427 cout << "\n" << string(50, '=') << endl;
428 cout << "Water Distribution Network" << endl;
429 cout << string(50, '=') << endl;
430
432 print_network(water, "Initial Network (zero flow)");
433
434 cout << "\n--- Computing Maximum Flow ---" << endl;
436
437 print_network(water, "After Max-Flow Computation");
438 cout << "\n*** MAXIMUM FLOW: " << max_flow << " units ***" << endl;
439
441 }
442
443 if (runAll || runComplex)
444 {
445 cout << "\n" << string(50, '=') << endl;
446 cout << "Data Center Network" << endl;
447 cout << string(50, '=') << endl;
448
450 print_network(dc, "Initial Network (zero flow)");
451
452 cout << "\n--- Computing Maximum Flow ---" << endl;
454
455 print_network(dc, "After Max-Flow Computation");
456 cout << "\n*** MAXIMUM FLOW: " << max_flow << " units ***" << endl;
457 }
458
459 if (runAll || runMatch)
460 {
461 cout << "\n" << string(50, '=') << endl;
463 }
464
465 cout << "\n=== Algorithm Summary ===" << endl;
466 cout << "Ford-Fulkerson: O(E * max_flow)" << endl;
467 cout << "Edmonds-Karp: O(V * E²) - uses BFS" << endl;
468 cout << "Dinic: O(V² * E) - uses level graphs" << endl;
469
470 return 0;
471 }
472 catch (TCLAP::ArgException& e)
473 {
474 cerr << "Error: " << e.error() << " for arg " << e.argId() << endl;
475 return 1;
476 }
477}
int main()
auto get_arc_it() const noexcept
Obtains an iterator to the arc of graph.
Definition graph-dry.H:2802
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:778
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
double FlowType
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Net::Flow_Type ford_fulkerson_maximum_flow(Net &net)
Maximize flow using the Ford-Fulkerson algorithm.
Definition tpl_net.H:1523
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
FlowNet build_datacenter_network()
Build a more complex network.
void demonstrate_min_cut(FlowNet &net)
Demonstrate min-cut (dual of max-flow)
string NodeInfo
void print_network(FlowNet &net, const string &title)
Print network structure and flow.
void demonstrate_bipartite_matching()
Demonstrate bipartite matching as max-flow.
FlowNet build_water_network()
Build a sample flow network.
Empty placeholder class with no data members.
Definition ahDefs.H:105
Arc of a flow network implemented with adjacency lists.
Definition tpl_net.H:115
Flow network implemented with adjacency lists.
Definition tpl_net.H:261
Node * insert_node(const Node_Type &node_info)
Insert a new node by copying node_info.
Definition tpl_net.H:559
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
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
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
Network flow graph structures.