Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_netcapgraph.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
71#ifndef TPL_NETCAPGRAPH_H
72#define TPL_NETCAPGRAPH_H
73
74#include <tpl_net.H>
75#include <ah-errors.H>
76
77namespace Aleph {
78
97template <typename Node_Info = Empty_Class, typename F_Type = double>
98class Net_Cap_Node : public Graph_Anode<Node_Info>
99{
101
102public:
105
107 using Node_Type = Node_Info;
108
111
114
117
121 {
122 // empty
123 }
124
132 explicit Net_Cap_Node(const Node_Info& node_info)
133 : Base(node_info),
135 {
136 // empty
137 }
138
143 explicit Net_Cap_Node(Node_Info&& node_info) noexcept
144 : Base(std::move(node_info)),
145 max_cap(std::numeric_limits<Flow_Type>::max())
146 {
147 // empty
148 }
149
157 : Base(node->get_info()),
158 max_cap(node->max_cap),
159 in_flow(node->in_flow),
160 out_flow(node->out_flow)
161 {
162 // empty
163 }
164
170 : Base(other),
174 {
175 // empty
176 }
177
184 {
185 if (this != &other)
186 {
188 max_cap = other.max_cap;
189 in_flow = other.in_flow;
190 out_flow = other.out_flow;
191 }
192 return *this;
193 }
194
200 {
201 return max_cap;
202 }
203
209 void set_max_cap(const Flow_Type& cap)
210 {
212 << "Node capacity cannot be negative";
213 max_cap = cap;
214 }
215};
216
217
265template <class NodeT = Net_Cap_Node<Empty_Class, double>,
266 class ArcT = Net_Arc<Empty_Class, double>>
267class Net_Cap_Graph : public Net_Graph<NodeT, ArcT>
268{
269public:
272
274 using Arc = ArcT;
275
277 using Node = NodeT;
278
280 using Flow_Type = typename Arc::Flow_Type;
281
283 using Node_Type = typename Node::Node_Type;
284
286 using Arc_Type = typename Arc::Arc_Type;
287
288 Node * insert_node(Node *p) override
289 {
290 return Net_Class::insert_node(p);
291 }
292
305 Node* insert_node(const Node_Type& node_info,
306 const Flow_Type& cap = std::numeric_limits<Flow_Type>::max())
307 {
309 << "Node capacity cannot be negative";
310
311 Node* p = Net_Class::insert_node(node_info);
312 p->max_cap = cap;
313 return p;
314 }
315
324 {
325 return insert_node(Node_Type{}, cap);
326 }
327
334 {
335 return insert_node(Node_Type{}, std::numeric_limits<Flow_Type>::max());
336 }
337
357
358private:
359 Aux_Net* aux_net = nullptr;
360
361public:
367 : Net_Class(), aux_net(nullptr)
368 {
369 // empty
370 }
371
379 {
380 // aux_net is not copied; must be recomputed if needed
381 }
382
388 : Net_Class(std::move(other)), aux_net(other.aux_net)
389 {
390 other.aux_net = nullptr;
391 }
392
400 {
401 if (this != &other)
402 {
403 if (aux_net != nullptr)
404 free_aux_net();
406 }
407 return *this;
408 }
409
416 {
417 if (this != &other)
418 {
419 if (aux_net != nullptr)
420 free_aux_net();
421 Net_Class::operator=(std::move(other));
422 aux_net = other.aux_net;
423 other.aux_net = nullptr;
424 }
425 return *this;
426 }
427
433 {
434 if (aux_net != nullptr)
435 {
437 delete aux_net;
438 aux_net = nullptr;
439 }
440 }
441
447 {
448 return aux_net;
449 }
450
456 {
457 return aux_net;
458 }
459
465 {
466 return aux_net != nullptr;
467 }
468
493 {
494 ah_domain_error_if(aux_net != nullptr)
495 << "Auxiliary network has already been computed";
496
497 aux_net = new Aux_Net;
498
499 try
500 {
501 // Phase 1: Create node pairs and capacity arcs
502 for (Node_Iterator<Net_Cap_Graph> it(*this); it.has_curr(); it.next_ne())
503 {
504 Node* p = it.get_curr();
505
506 // Create source and target nodes for this node
507 typename Aux_Net::Node* src = aux_net->insert_node();
508 typename Aux_Net::Node* tgt = aux_net->insert_node();
509
510 // Create arc representing node capacity
511 // info = true means this arc represents a node
512 typename Aux_Net::Arc* arc =
513 aux_net->insert_arc(src, tgt, p->max_cap, Flow_Type{0}, true);
514
515 // Establish bidirectional mapping
516 NODE_COOKIE(p) = arc;
517 ARC_COOKIE(arc) = p;
518 }
519
520 // Phase 2: Create arcs corresponding to original edges
521 for (Arc_Iterator<Net_Cap_Graph> it(*this); it.has_curr(); it.next_ne())
522 {
523 Arc* arc = it.get_curr();
524
525 // Get the auxiliary arcs for source and target nodes
526 typename Aux_Net::Arc* src_arc =
527 static_cast<typename Aux_Net::Arc*>(NODE_COOKIE(this->get_src_node(arc)));
528 typename Aux_Net::Arc* tgt_arc =
529 static_cast<typename Aux_Net::Arc*>(NODE_COOKIE(this->get_tgt_node(arc)));
530
531 // Connect tgt of src_arc to src of tgt_arc
532 // info = false means this arc represents an original edge
533 typename Aux_Net::Arc* a =
536 arc->cap, arc->flow, false);
537
538 // Establish bidirectional mapping
539 ARC_COOKIE(arc) = a;
540 ARC_COOKIE(a) = arc;
541 }
542
543 return aux_net;
544 }
545 catch (...)
546 {
547 // Clean up on failure
548 if (aux_net != nullptr)
549 {
551 delete aux_net;
552 aux_net = nullptr;
553 }
554 throw;
555 }
556 }
557
570 void update()
571 {
572 ah_domain_error_if(aux_net == nullptr)
573 << "Auxiliary network has not been computed";
574
575 for (typename Aux_Net::Arc_Iterator it(*aux_net); it.has_curr(); it.next_ne())
576 {
577 typename Aux_Net::Arc* arc = it.get_curr();
578
579 if (arc->get_info()) // This arc represents a node
580 {
581 Node* p = static_cast<Node*>(ARC_COOKIE(arc));
582 p->in_flow = arc->flow;
583 p->out_flow = arc->flow;
584 }
585 else // This arc represents an original edge
586 {
587 Arc* a = static_cast<Arc*>(ARC_COOKIE(arc));
588 a->flow = arc->flow;
589 }
590 }
591 }
592
601 {
602 ah_domain_error_if(aux_net == nullptr)
603 << "Auxiliary network has not been computed";
604
606 delete aux_net;
607 aux_net = nullptr;
608 }
609
621 {
622 ah_domain_error_if(aux_net == nullptr)
623 << "Auxiliary network has not been computed";
624
626 for (Node_Iterator<Net_Cap_Graph> it(*this); it.has_curr(); it.next_ne())
627 {
628 Node* p = it.get_curr();
629 total += p->in_flow;
630 }
631 return total;
632 }
633
642 {
643 for (Node_Iterator<Net_Cap_Graph> it(*this); it.has_curr(); it.next_ne())
644 {
645 Node* p = it.get_curr();
646 if (p->in_flow > p->max_cap || p->out_flow > p->max_cap)
647 return false;
648 }
649 return true;
650 }
651
657 {
658 // Reset arc flows
659 for (Arc_Iterator<Net_Cap_Graph> it(*this); it.has_curr(); it.next_ne())
660 it.get_curr()->flow = Flow_Type{0};
661
662 // Reset node flows
663 for (Node_Iterator<Net_Cap_Graph> it(*this); it.has_curr(); it.next_ne())
664 {
665 Node* p = it.get_curr();
666 p->in_flow = Flow_Type{0};
667 p->out_flow = Flow_Type{0};
668 }
669 }
670
676 [[nodiscard]] static Flow_Type get_node_cap(const Node* node) noexcept
677 {
678 return node->max_cap;
679 }
680
688 static void set_node_cap(Node* node, const Flow_Type& cap)
689 {
691 << "Node capacity cannot be negative";
692 ah_overflow_error_if(node->in_flow > cap || node->out_flow > cap)
693 << "Current flow exceeds new capacity";
694 node->max_cap = cap;
695 }
696};
697
698} // end namespace Aleph
699
700#endif // TPL_NETCAPGRAPH_H
Exception handling system with formatted messages for Aleph-w.
#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
Node of Array_Graph
Definition tpl_agraph.H:64
Graph_Anode & operator=(const Graph_Anode &node)
Definition tpl_agraph.H:109
Capacitated network with node capacity constraints.
Net_Cap_Graph & operator=(const Net_Cap_Graph &other)
Copy assignment operator.
static void set_node_cap(Node *node, const Flow_Type &cap)
Set the capacity of a node.
Net_Cap_Graph(const Net_Cap_Graph &other)
Copy constructor.
~Net_Cap_Graph()
Destructor.
bool has_aux_net() const noexcept
Check if auxiliary network has been computed.
const Aux_Net * get_aux_net() const noexcept
Get const pointer to the auxiliary network.
Aux_Net * get_aux_net() noexcept
Get pointer to the auxiliary network.
Node * insert_node(const Node_Type &node_info, const Flow_Type &cap=std::numeric_limits< Flow_Type >::max())
Insert a new capacitated node into the network.
typename Node::Node_Type Node_Type
Type of information stored in nodes.
Net_Cap_Graph & operator=(Net_Cap_Graph &&other) noexcept
Move assignment operator.
Node * insert_node(const Flow_Type &cap)
Insert a new node with default info and specified capacity.
static Flow_Type get_node_cap(const Node *node) noexcept
Get the capacity of a node.
typename Arc::Arc_Type Arc_Type
Type of information stored in arcs.
Net_Graph< Net_Node< Empty_Class >, Net_Arc< bool, Flow_Type > > Aux_Net
Auxiliary network type for solving node-capacitated networks.
Net_Cap_Graph(Net_Cap_Graph &&other) noexcept
Move constructor.
Node * insert_node()
Insert a new node with default info and unlimited capacity.
Net_Graph< NodeT, ArcT > Net_Class
Base network class type.
void free_aux_net()
Free the auxiliary network.
Flow_Type get_total_flow() const
Get the total flow value of the network.
void update()
Update flow values from auxiliary network to this network.
Node * insert_node(Node *p) override
bool check_node_capacities() const noexcept
Check if all node capacity constraints are satisfied.
void reset_flows() noexcept
Reset all flow values to zero.
Aux_Net * compute_aux_net()
Compute the equivalent arc-capacitated auxiliary network.
Net_Cap_Graph() noexcept
Default constructor.
typename Arc::Flow_Type Flow_Type
Type representing capacity and flow values.
Node with capacity constraint for flow networks.
F_Type Flow_Type
Type representing flow and capacity values.
Net_Cap_Node(const Net_Cap_Node &other)
Copy constructor.
void set_max_cap(const Flow_Type &cap)
Set the maximum capacity of this node.
Net_Cap_Node(Node_Info &&node_info) noexcept
Move constructor from node info.
Node_Info Node_Type
Type of information stored in the node.
Net_Cap_Node & operator=(const Net_Cap_Node &other)
Copy assignment operator.
Flow_Type in_flow
Tracked incoming flow (updated by update() after auxiliary net computation).
const Flow_Type & get_max_cap() const noexcept
Get the maximum capacity of this node.
Graph_Anode< Node_Info > Base
Flow_Type out_flow
Tracked outgoing flow (updated by update() after auxiliary net computation).
Net_Cap_Node(const Node_Info &node_info)
Construct a node with the given information.
Flow_Type max_cap
Maximum flow capacity that can pass through this node.
Net_Cap_Node() noexcept
Default constructor. Sets max_cap to the maximum possible value.
Net_Cap_Node(const Net_Cap_Node *node)
Copy constructor from another Net_Cap_Node.
NodeInfo node_info
Definition graph-dry.H:443
NodeInfo & get_info() noexcept
Return a modifiable reference to the data contained in the node.
Definition graph-dry.H:494
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
__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
#define ARC_COOKIE(p)
Return the arc cookie
#define NODE_COOKIE(p)
Return the node cookie
void clear_graph(GT &g) noexcept
Clean a graph: all its nodes and arcs are removed and freed.
Definition tpl_graph.H:3549
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Iterator over arcs of a graph.
Definition tpl_agraph.H:325
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
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
ArcT Arc
Arc type.
Definition tpl_net.H:272
Net_Graph & operator=(Net_Graph &&other) noexcept
Move-assign a network. O(1) operation.
Definition tpl_net.H:753
NodeT Node
Node type.
Definition tpl_net.H:275
Node * insert_node()
Insert a new node with default info.
Definition tpl_net.H:565
Network flow graph structures.