Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_net_sup_dem.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
96#ifndef TPL_NET_SUP_DEM_H
97#define TPL_NET_SUP_DEM_H
98
99#include <tpl_net.H>
100#include <ah-errors.H>
101
102namespace Aleph
103{
104
118template <typename Node_Info, typename F_Type = long>
119class Net_Sup_Dem_Node : public Graph_Anode<Node_Info>
120{
121public:
124
127
130
133
136
139
142
148
154 {
155 return supply_flow;
156 }
157
160
169 explicit Net_Sup_Dem_Node(const Node_Info& node_info)
170 : Base(node_info)
171 {}
172
181 : Base(*node),
183 out_cap(node->out_cap),
184 in_cap(node->in_cap),
185 out_flow(node->out_flow),
186 in_flow(node->in_flow)
187 {}
188};
189
190
221template <class NodeT = Net_Sup_Dem_Node<Empty_Class, double>,
222 class ArcT = Net_Arc<Empty_Class, double>>
223class Net_Sup_Dem_Graph : public Net_Graph<NodeT, ArcT>
224{
225public:
229 using Arc = ArcT;
231 using Node = NodeT;
233 using Flow_Type = typename Arc::Flow_Type;
235 using Node_Type = typename Node::Node_Type;
237 using Arc_Type = typename Arc::Arc_Type;
240
241private:
242 Node* super_source = nullptr;
243 Node* super_sink = nullptr;
244
245public:
248
250 Net_Sup_Dem_Graph() = default;
251
254 {
255 if (exist_aux_net())
256 free_aux_net();
257 }
258
260
261 // Bring base class insert_node overloads into scope
263
266
278 Node* insert_node(const Node_Type& node_info, const Flow_Type& supply = 0)
279 {
280 Node* p = Net_Class::insert_node(node_info);
281 p->supply_flow = supply;
282 return p;
283 }
284
296 {
297 return insert_node(Node_Type(), supply);
298 }
299
301
304
310 {
311 return super_source != nullptr or super_sink != nullptr;
312 }
313
330 {
332 << "Auxiliary net is already computed";
333
334 super_source = insert_node(0); // auxiliary source
335 super_sink = insert_node(0); // auxiliary sink
336
337 // Connect super-source/sink based on supply/demand values
338 for (Node_Iterator<Net_Sup_Dem_Graph> it(*this); it.has_curr(); it.next_ne())
339 {
340 Node* p = it.get_curr();
341 if (p->supply_flow > 0) // supply node?
342 {
343 ah_range_error_if(p->out_cap < p->supply_flow)
344 << "Supply flow in node at " << static_cast<void*>(p)
345 << " is greater than out capacity";
346 this->insert_arc(super_source, p, p->supply_flow);
347 }
348 else if (p->supply_flow < 0) // demand node?
349 {
350 ah_range_error_if(p->in_cap < -p->supply_flow)
351 << "Supply flow in node at " << static_cast<void*>(p)
352 << " is smaller than in capacity";
353 this->insert_arc(p, super_sink, -p->supply_flow);
354 }
355 }
356
357 // Remove super-source if no supply nodes
358 if (this->get_out_degree(super_source) == 0)
359 {
360 this->remove_node(super_source);
361 super_source = nullptr;
362 }
363
364 // Remove super-sink if no demand nodes
365 if (this->get_in_degree(super_sink) == 0)
366 {
367 this->remove_node(super_sink);
368 super_sink = nullptr;
369 }
370
371 return this;
372 }
373
379 {
380 return exist_aux_net() ? this : nullptr;
381 }
382
388
394
404 {
406 << "Auxiliary net has not been computed";
407
408 if (super_source != nullptr)
409 {
410 this->remove_node(super_source);
411 super_source = nullptr;
412 }
413
414 if (super_sink != nullptr)
415 {
416 this->remove_node(super_sink);
417 super_sink = nullptr;
418 }
419 }
420
422
425
438 [[nodiscard]] bool is_feasible() const
439 {
441 << "Auxiliary net has not been computed";
442
443 for (Node_Iterator<Net_Sup_Dem_Graph> it(*this); it.has_curr(); it.next_ne())
444 {
445 Node* p = it.get_curr();
446 const Flow_Type& supply_flow = p->supply_flow;
447
448 if (supply_flow == 0)
449 continue;
450
451 if (supply_flow > 0 and p->out_flow < supply_flow)
452 return false; // Supply node not providing enough flow
453
454 if (supply_flow < 0 and p->in_flow < -supply_flow)
455 return false; // Demand node not receiving enough flow
456 }
457
458 return true;
459 }
460
473 {
474 for (Node_Iterator<Net_Sup_Dem_Graph> it(*this); it.has_curr(); it.next_ne())
475 {
476 Node* p = it.get_curr();
477 const Flow_Type& supply_flow = p->supply_flow;
478
479 if (supply_flow == 0)
480 continue;
481
482 if (supply_flow > 0 and p->out_flow < supply_flow)
484 else if (supply_flow < 0 and p->in_flow < -supply_flow)
486 }
487 }
488
490
493
507 {
508 ah_range_error_if(supply > 0 and p->out_cap < supply)
509 << "Supply flow in node at " << static_cast<void*>(p)
510 << " is greater than out capacity";
512 << "Supply flow in node at " << static_cast<void*>(p)
513 << " is smaller than in capacity";
514
515 p->supply_flow = supply;
516 }
517
525 {
526 return p->supply_flow;
527 }
528
530
533
539 {
540 size_t count = 0;
541 for (Node_Iterator<Net_Sup_Dem_Graph> it(*this); it.has_curr(); it.next_ne())
542 if (it.get_curr()->supply_flow > 0)
543 ++count;
544 return count;
545 }
546
552 {
553 size_t count = 0;
554 for (Node_Iterator<Net_Sup_Dem_Graph> it(*this); it.has_curr(); it.next_ne())
555 if (it.get_curr()->supply_flow < 0)
556 ++count;
557 return count;
558 }
559
565 {
566 Flow_Type total = 0;
567 for (Node_Iterator<Net_Sup_Dem_Graph> it(*this); it.has_curr(); it.next_ne())
568 {
569 const Flow_Type& sf = it.get_curr()->supply_flow;
570 if (sf > 0)
571 total += sf;
572 }
573 return total;
574 }
575
581 {
582 Flow_Type total = 0;
583 for (Node_Iterator<Net_Sup_Dem_Graph> it(*this); it.has_curr(); it.next_ne())
584 {
585 const Flow_Type& sf = it.get_curr()->supply_flow;
586 if (sf < 0)
587 total -= sf; // Add absolute value
588 }
589 return total;
590 }
591
600 {
601 return total_supply() == total_demand();
602 }
603
605};
606
607} // end namespace Aleph
608
609#endif // TPL_NET_SUP_DEM_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_range_error_if(C)
Throws std::range_error if condition holds.
Definition ah-errors.H:207
Dynamic doubly linked list with O(1) size and bidirectional access.
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
Node of Array_Graph
Definition tpl_agraph.H:64
Network graph with supply and demand nodes.
void non_feasible_nodes(DynDlist< Node * > &supply_list, DynDlist< Node * > &demand_list)
Get lists of nodes with unsatisfied supply/demand.
typename Node::Node_Type Node_Type
Type of information stored in nodes.
Node * get_super_sink() const noexcept
Get the super-sink node.
Node * super_sink
Super-sink for auxiliary network.
Node * get_super_source() const noexcept
Get the super-source node.
bool exist_aux_net() const noexcept
Check if the auxiliary network has been computed.
void free_aux_net()
Free the auxiliary network structures.
bool is_feasible() const
Check if the current flow is feasible.
typename Arc::Arc_Type Arc_Type
Type of information stored in arcs.
Node * super_source
Super-source for auxiliary network.
Flow_Type total_demand() const noexcept
Calculate total demand in the network.
Node * insert_node(const Flow_Type &supply)
Insert a node with supply/demand value only.
Net_Sup_Dem_Graph()=default
Default constructor.
typename Arc::Flow_Type Flow_Type
Type representing capacity and flow values.
Flow_Type get_supply_flow(Node *p) const noexcept
Get the supply/demand value for a node.
bool is_balanced() const noexcept
Check if the network is balanced.
~Net_Sup_Dem_Graph()
Destructor. Frees auxiliary network if it exists.
Net_Sup_Dem_Graph * compute_aux_net()
Compute the auxiliary capacitated network.
size_t count_demand_nodes() const noexcept
Count the number of demand nodes.
size_t count_supply_nodes() const noexcept
Count the number of supply nodes.
void set_supply_flow(Node *p, const Flow_Type &supply)
Set the supply/demand value for a node.
Flow_Type total_supply() const noexcept
Calculate total supply in the network.
Node * insert_node()
Insert a new node with default info.
Definition tpl_net.H:565
Node * insert_node(const Node_Type &node_info, const Flow_Type &supply=0)
Insert a node with info and supply/demand value.
Net_Sup_Dem_Graph * get_aux_net() noexcept
Get the auxiliary network if it exists.
Node with supply/demand flow value.
const Flow_Type & get_supply_flow() const noexcept
Get the supply/demand flow value (const version).
Flow_Type & get_supply_flow() noexcept
Get the supply/demand flow value.
Net_Sup_Dem_Node(const Node_Info &node_info)
Construct node with info.
Flow_Type out_flow
Tracked outgoing flow.
Flow_Type in_flow
Tracked incoming flow.
Net_Sup_Dem_Node(Net_Sup_Dem_Node *node)
Copy constructor from pointer.
Flow_Type out_cap
Outgoing capacity constraint.
Flow_Type supply_flow
Supply flow value: positive = supply, negative = demand, zero = transit.
Flow_Type in_cap
Incoming capacity constraint.
F_Type Flow_Type
Type representing flow values.
Net_Sup_Dem_Node()
Default constructor. Initializes all values to zero.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
Flow network implemented with adjacency lists.
Definition tpl_net.H:261
size_t get_out_degree(Node *p) const noexcept
Return the out-degree of p (number of outgoing arcs).
Definition tpl_net.H:339
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
void remove_node(Node *p) noexcept override
Remove node p and all its arcs from the network.
Definition tpl_net.H:705
Node * insert_node()
Insert a new node with default info.
Definition tpl_net.H:565
size_t get_in_degree(Node *p) const noexcept
Return the in-degree of p (number of incoming arcs).
Definition tpl_net.H:333
Network flow graph structures.