Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
mincost_flow_example.cc
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
212#include <iostream>
213#include <iomanip>
214#include <vector>
215#include <string>
216#include <cstring>
217#include <tpl_netcost.H>
218#include <tpl_mincost.H>
219
220using namespace std;
221using namespace Aleph;
222
223static void usage(const char* prog)
224{
225 cout << "Usage: " << prog << " [--compare] [--network <logistics|assignment|transportation|all>] [--help]\n";
226 cout << "\nIf no flags are given, all demos are executed.\n";
227}
228
229static bool has_flag(int argc, char* argv[], const char* flag)
230{
231 for (int i = 1; i < argc; ++i)
232 if (std::strcmp(argv[i], flag) == 0)
233 return true;
234 return false;
235}
236
237static const char* get_opt_value(int argc, char* argv[], const char* opt)
238{
239 for (int i = 1; i + 1 < argc; ++i)
240 if (std::strcmp(argv[i], opt) == 0)
241 return argv[i + 1];
242 return nullptr;
243}
244
245// Type definitions
250
255{
256 CostNet net;
257
258 auto s = net.insert_node("Source");
259 auto a = net.insert_node("A");
260 auto b = net.insert_node("B");
261 auto t = net.insert_node("Sink");
262
263 // insert_arc(src, tgt, cap, cost)
264 net.insert_arc(s, a, 10, 2.0); // cap=10, cost=2
265 net.insert_arc(s, b, 8, 3.0); // cap=8, cost=3
266 net.insert_arc(a, b, 5, 1.0); // cap=5, cost=1
267 net.insert_arc(a, t, 7, 4.0); // cap=7, cost=4
268 net.insert_arc(b, t, 10, 2.0); // cap=10, cost=2
269
270 return net;
271}
272
274{
275 cout << "\n" << string(60, '=') << endl;
276 cout << "Comparison: Cycle Canceling vs Network Simplex (Logistics Network)" << endl;
277 cout << string(60, '=') << endl;
278
279 {
282 auto flow = net.get_out_flow(net.get_source());
283 auto cost = net.flow_cost();
284 cout << "Cycle canceling:\n";
285 cout << " Max flow: " << flow << "\n";
286 cout << " Total cost: $" << fixed << setprecision(2) << cost << "\n";
287 cout << " Cycles cancelled: " << get<0>(r) << "\n";
288 }
289
290 {
292 size_t pivots = max_flow_min_cost_by_network_simplex(net);
293 auto flow = net.get_out_flow(net.get_source());
294 auto cost = net.flow_cost();
295 cout << "Network simplex:\n";
296 cout << " Max flow: " << flow << "\n";
297 cout << " Total cost: $" << fixed << setprecision(2) << cost << "\n";
298 cout << " Pivots: " << pivots << "\n";
299 }
300}
301
305void print_cost_network(CostNet& net, const string& title)
306{
307 cout << "\n=== " << title << " ===" << endl;
308 cout << "Nodes: " << net.get_num_nodes() << ", Arcs: " << net.get_num_arcs() << endl;
309
310 Flow_Type total_cost = 0;
311 Flow_Type total_flow = 0;
312
313 cout << "\nArc flows:" << endl;
314
315 for (auto it = net.get_arc_it(); it.has_curr(); it.next())
316 {
317 auto* arc = it.get_curr();
318 auto* src = net.get_src_node(arc);
319 auto* tgt = net.get_tgt_node(arc);
320
321 Flow_Type arc_cost = arc->flow * arc->cost;
322 total_cost += arc_cost;
323
324 if (net.is_source(src))
325 total_flow += arc->flow;
326
327 cout << " " << setw(8) << left << src->get_info()
328 << " -> " << setw(8) << left << tgt->get_info()
329 << right << " : " << setw(4) << arc->flow
330 << " / " << setw(4) << arc->cap
331 << " @ $" << arc->cost << endl;
332 }
333
334 cout << "\nTotal flow: " << total_flow << endl;
335 cout << "Total cost: $" << fixed << setprecision(2) << total_cost << endl;
336}
337
342{
343 cout << "\n" << string(60, '=') << endl;
344 cout << "Example 2: Assignment Problem" << endl;
345 cout << string(60, '=') << endl;
346
347 cout << "\nProblem: Assign 3 workers to 3 jobs minimizing total cost." << endl;
348 cout << "\nCost matrix:" << endl;
349 cout << " Job1 Job2 Job3" << endl;
350 cout << "Worker1: $9 $2 $7" << endl;
351 cout << "Worker2: $6 $4 $3" << endl;
352 cout << "Worker3: $5 $8 $1" << endl;
353
355 {9, 2, 7}, // Worker 1
356 {6, 4, 3}, // Worker 2
357 {5, 8, 1} // Worker 3
358 };
359
360 auto result = solve_assignment<double>(costs);
361
362 cout << "\nOptimal assignment:" << endl;
363
364 if (result.feasible)
365 {
366 for (auto it = result.assignments.get_it(); it.has_curr(); it.next())
367 {
368 auto [w, j] = it.get_curr();
369 cout << " Worker" << (w+1) << " -> Job" << (j+1)
370 << " (cost = $" << costs[w][j] << ")" << endl;
371 }
372 cout << "\nMinimum total cost: $" << result.total_cost << endl;
373 }
374 else
375 {
376 cout << "No feasible assignment found." << endl;
377 }
378}
379
384{
385 cout << "\n" << string(60, '=') << endl;
386 cout << "Example 3: Transportation Problem" << endl;
387 cout << string(60, '=') << endl;
388
389 cout << "\nProblem: Ship goods from 2 warehouses to 3 stores." << endl;
390
391 vector<double> supply = {30, 20};
392 vector<double> demand = {15, 20, 15};
394 {4, 8, 8}, // Warehouse 1 to stores
395 {6, 2, 4} // Warehouse 2 to stores
396 };
397
398 auto result = solve_transportation<double>(supply, demand, costs);
399
400 if (result.feasible)
401 {
402 cout << "\nOptimal shipments:" << endl;
403 for (size_t i = 0; i < result.shipments.size(); ++i)
404 {
405 cout << " Warehouse" << (i+1) << ": ";
406 for (size_t j = 0; j < result.shipments[i].size(); ++j)
407 cout << setw(6) << result.shipments[i][j] << " ";
408 cout << endl;
409 }
410 cout << "\nMinimum cost: $" << result.total_cost << endl;
411 }
412 else
413 {
414 cout << "No feasible solution found." << endl;
415 }
416}
417
422{
423 cout << "\n" << string(60, '=') << endl;
424 cout << "Example 1: Min-Cost Max-Flow" << endl;
425 cout << string(60, '=') << endl;
426
428
429 print_cost_network(net, "Initial Network");
430
431 cout << "\n--- Computing Min-Cost Max-Flow ---" << endl;
432
433 // Using cycle canceling
434 auto result = max_flow_min_cost_by_cycle_canceling(net);
435 auto flow = net.get_out_flow(net.get_source());
436 auto cost = net.flow_cost();
437
438 print_cost_network(net, "After Optimization");
439
440 cout << "\n*** Results ***" << endl;
441 cout << "Maximum flow: " << flow << endl;
442 cout << "Minimum cost: $" << fixed << setprecision(2) << cost << endl;
443 cout << "Cycles cancelled: " << get<0>(result) << endl;
444}
445
446int main(int argc, char* argv[])
447{
448 cout << "=== Minimum Cost Maximum Flow ===" << endl;
449 cout << "Optimize flow networks with costs per unit\n" << endl;
450
451 if (has_flag(argc, argv, "--help"))
452 {
453 usage(argv[0]);
454 return 0;
455 }
456
457 const bool compare = has_flag(argc, argv, "--compare");
458 const char* network = get_opt_value(argc, argv, "--network");
459 const string sel = network ? string(network) : string("all");
460
461 if (compare)
462 {
464 return 0;
465 }
466
467 if (argc == 1 || sel == "all" || sel == "logistics")
469 if (argc == 1 || sel == "all" || sel == "assignment")
471 if (argc == 1 || sel == "all" || sel == "transportation")
473
474 if (!(argc == 1 || sel == "all" || sel == "logistics" || sel == "assignment" || sel == "transportation"))
475 {
476 cout << "Unknown --network value: " << sel << "\n";
477 usage(argv[0]);
478 return 1;
479 }
480
481 cout << "\n" << string(60, '=') << endl;
482 cout << "Summary" << endl;
483 cout << string(60, '=') << endl;
484
485 cout << R"(
486Min-Cost Max-Flow Problem:
487
488 Given: Network with capacities and per-unit costs
489 Find: Flow maximizing total flow at minimum cost
490
491Algorithms:
492 - Cycle Canceling: Simple, cancel negative-cost cycles
493 - Network Simplex: Efficient, maintains spanning tree
494
495Applications:
496 - Transportation: Ship goods at minimum cost
497 - Assignment: Match entities minimizing total cost
498 - Supply Chain: Optimize logistics networks
499)" << endl;
500
501 return 0;
502}
int main()
WeightedDigraph::Node Node
WeightedDigraph::Arc Arc
long double w
Definition btreepic.C:153
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
CostNet build_simple_network()
Build a simple logistics network.
void demo_mincost_maxflow()
Demonstrate min-cost max-flow.
void demo_assignment_problem()
Demonstrate the assignment problem.
void print_cost_network(CostNet &net, const string &title)
Print network with flows and costs.
static void usage(const char *prog)
void demo_transportation_problem()
Demonstrate the transportation problem.
static void demo_compare_algorithms_on_logistics()
double Flow_Type
static bool has_flag(int argc, char *argv[], const char *flag)
static const char * get_opt_value(int argc, char *argv[], const char *opt)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::tuple< size_t, double > max_flow_min_cost_by_cycle_canceling(Net &net, double it_factor=0.4, size_t step=10)
Compute maximum flow at minimum cost using cycle canceling.
size_t max_flow_min_cost_by_network_simplex(Net &net)
Compute maximum flow at minimum cost using Network Simplex.
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Arc type for maximum flow minimum cost networks.
Definition tpl_netcost.H:93
Capacitated flow network with costs associated to arcs.
Flow_Type flow_cost() const
Compute the total cost of flow circulating through the network.
NodeT Node
Node type.
virtual Arc * insert_arc(Node *src_node, Node *tgt_node, const Flow_Type &cap, const Flow_Type &__cost)
Create and insert an arc in a flow network with costs.
Flow_Type get_out_flow(Node *node) const noexcept
Return total outgoing flow of node.
Definition tpl_net.H:345
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
Advanced minimum cost flow algorithms.
Maximum flow minimum cost network algorithms.