Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
net_sup_dem_test.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
38#include <gtest/gtest.h>
39#include <tpl_net_sup_dem.H>
40#include <tpl_dynDlist.H>
41#include <string>
42
43using namespace Aleph;
44
45// =============================================================================
46// Type Aliases for Testing
47// =============================================================================
48
49// Simple network with int flow (use Empty_Class as node info to avoid ambiguity)
53
54// Network with string info and double flow
58
59// =============================================================================
60// Net_Sup_Dem_Node Tests
61// =============================================================================
62
63class NetSupDemNodeTest : public ::testing::Test
64{
65protected:
67};
68
70{
71 Node n;
72 EXPECT_EQ(n.supply_flow, 0);
73 EXPECT_EQ(n.get_supply_flow(), 0);
74}
75
77{
78 Node n("TestNode");
79 EXPECT_EQ(n.supply_flow, 0);
80}
81
83{
84 Node original("Original");
85 original.supply_flow = 42;
86
88 EXPECT_EQ(copy.supply_flow, 42);
89}
90
92{
93 Node n;
94 n.get_supply_flow() = 100;
95 EXPECT_EQ(n.supply_flow, 100);
96}
97
98// =============================================================================
99// Net_Sup_Dem_Graph Basic Tests
100// =============================================================================
101
102class NetSupDemGraphTest : public ::testing::Test
103{
104protected:
106};
107
109{
110 EXPECT_FALSE(net.exist_aux_net());
111 EXPECT_EQ(net.get_super_source(), nullptr);
112 EXPECT_EQ(net.get_super_sink(), nullptr);
113}
114
116{
117 auto* p = net.insert_node(100); // supply node
118 EXPECT_EQ(p->supply_flow, 100);
119 EXPECT_EQ(net.get_supply_flow(p), 100);
120}
121
123{
124 auto* p = net.insert_node(-50); // demand node
125 EXPECT_EQ(p->supply_flow, -50);
126 EXPECT_EQ(net.get_supply_flow(p), -50);
127}
128
130{
131 auto* p = net.insert_node(0); // transit node
132 EXPECT_EQ(p->supply_flow, 0);
133}
134
135// ==============================================================================
136// Supply/Demand Query Tests
137// =============================================================================
138
140{
141 net.insert_node(100); // supply
142 net.insert_node(50); // supply
143 net.insert_node(0); // transit
144 net.insert_node(-30); // demand
145
146 EXPECT_EQ(net.count_supply_nodes(), 2u);
147}
148
150{
151 net.insert_node(100); // supply
152 net.insert_node(-50); // demand
153 net.insert_node(-30); // demand
154 net.insert_node(-20); // demand
155
156 EXPECT_EQ(net.count_demand_nodes(), 3u);
157}
158
160{
161 net.insert_node(100);
162 net.insert_node(50);
163 net.insert_node(-30); // demand, not counted
164
165 EXPECT_EQ(net.total_supply(), 150);
166}
167
169{
170 net.insert_node(100); // supply, not counted
171 net.insert_node(-50);
172 net.insert_node(-30);
173
174 EXPECT_EQ(net.total_demand(), 80);
175}
176
178{
179 net.insert_node(100);
180 net.insert_node(-50);
181 net.insert_node(-50);
182
183 EXPECT_TRUE(net.is_balanced());
184}
185
187{
188 net.insert_node(100);
189 net.insert_node(-30);
190
191 EXPECT_FALSE(net.is_balanced());
192}
193
194// =============================================================================
195// Set Supply Flow Tests
196// =============================================================================
197
199{
200 auto* p = net.insert_node(0);
201 p->out_cap = 200; // Set output capacity
202
203 net.set_supply_flow(p, 150);
204 EXPECT_EQ(p->supply_flow, 150);
205}
206
208{
209 auto* p = net.insert_node(0);
210 p->in_cap = 100; // Set input capacity
211
212 net.set_supply_flow(p, -80);
213 EXPECT_EQ(p->supply_flow, -80);
214}
215
217{
218 auto* p = net.insert_node(0);
219 p->out_cap = 50;
220
221 EXPECT_THROW(net.set_supply_flow(p, 100), std::range_error);
222}
223
225{
226 auto* p = net.insert_node(0);
227 p->in_cap = 30;
228
229 EXPECT_THROW(net.set_supply_flow(p, -50), std::range_error);
230}
231
232// =============================================================================
233// Auxiliary Network Tests
234// =============================================================================
235
236class AuxNetTest : public ::testing::Test
237{
238protected:
240
241 void SetUp() override
242 {
243 // Create a simple supply-demand network
244 // Supply: 100 units
245 // Demand: 80 units (feasible)
246 auto* s1 = net.insert_node(50); // supply 50
247 auto* s2 = net.insert_node(50); // supply 50
248 auto* t1 = net.insert_node(0); // transit
249 auto* d1 = net.insert_node(-40); // demand 40
250 auto* d2 = net.insert_node(-40); // demand 40
251
252 // Set capacities for supply nodes
253 s1->out_cap = 100;
254 s2->out_cap = 100;
255
256 // Set capacities for demand nodes
257 d1->in_cap = 100;
258 d2->in_cap = 100;
259
260 // Create arcs with sufficient capacity
261 net.insert_arc(s1, t1, 100);
262 net.insert_arc(s2, t1, 100);
263 net.insert_arc(t1, d1, 100);
264 net.insert_arc(t1, d2, 100);
265 }
266};
267
269{
270 EXPECT_FALSE(net.exist_aux_net());
271
272 auto* result = net.compute_aux_net();
273
274 EXPECT_EQ(result, &net);
275 EXPECT_TRUE(net.exist_aux_net());
276 EXPECT_NE(net.get_super_source(), nullptr);
277 EXPECT_NE(net.get_super_sink(), nullptr);
278}
279
281{
282 net.compute_aux_net();
283
284 EXPECT_THROW(net.compute_aux_net(), std::domain_error);
285}
286
288{
289 EXPECT_EQ(net.get_aux_net(), nullptr);
290}
291
293{
294 net.compute_aux_net();
295 EXPECT_EQ(net.get_aux_net(), &net);
296}
297
299{
300 net.compute_aux_net();
301 EXPECT_TRUE(net.exist_aux_net());
302
303 net.free_aux_net();
304
305 EXPECT_FALSE(net.exist_aux_net());
306 EXPECT_EQ(net.get_super_source(), nullptr);
307 EXPECT_EQ(net.get_super_sink(), nullptr);
308}
309
311{
312 EXPECT_THROW(net.free_aux_net(), std::domain_error);
313}
314
316{
317 EXPECT_THROW((void)net.is_feasible(), std::domain_error);
318}
319
320// =============================================================================
321// Feasibility Tests
322// =============================================================================
323
324class FeasibilityTest : public ::testing::Test
325{
326protected:
328};
329
331{
332 // Network with no supply or demand (all transit nodes)
333 // Note: When there are no supply/demand nodes, compute_aux_net
334 // removes both super nodes, so exist_aux_net() returns false.
335 // This is correct behavior - there's nothing to check for feasibility.
336 auto* n1 = net.insert_node(0);
337 auto* n2 = net.insert_node(0);
338 net.insert_arc(n1, n2, 100);
339
340 // A network with no supply/demand is trivially balanced and feasible
341 EXPECT_TRUE(net.is_balanced());
342 EXPECT_EQ(net.total_supply(), 0);
343 EXPECT_EQ(net.total_demand(), 0);
344}
345
347{
348 auto* s = net.insert_node(100);
349 s->out_cap = 200;
350 s->out_flow = 100; // Simulate flow
351
352 net.compute_aux_net();
353 EXPECT_TRUE(net.is_feasible());
354}
355
357{
358 auto* s = net.insert_node(100);
359 s->out_cap = 200;
360 s->out_flow = 50; // Less than required
361
362 net.compute_aux_net();
363 EXPECT_FALSE(net.is_feasible());
364}
365
367{
368 auto* d = net.insert_node(-80);
369 d->in_cap = 100;
370 d->in_flow = 80; // Exactly meeting demand
371
372 net.compute_aux_net();
373 EXPECT_TRUE(net.is_feasible());
374}
375
377{
378 auto* d = net.insert_node(-80);
379 d->in_cap = 100;
380 d->in_flow = 50; // Less than required
381
382 net.compute_aux_net();
383 EXPECT_FALSE(net.is_feasible());
384}
385
387{
388 auto* s = net.insert_node(100);
389 auto* d = net.insert_node(-100);
390
391 s->out_cap = 150;
392 s->out_flow = 100;
393 d->in_cap = 150;
394 d->in_flow = 100;
395
396 net.insert_arc(s, d, 100);
397
398 net.compute_aux_net();
399 EXPECT_TRUE(net.is_feasible());
400}
401
403{
404 auto* s = net.insert_node(100);
405 auto* d = net.insert_node(-100);
406
407 s->out_cap = 150;
408 s->out_flow = 80; // Not enough
409 d->in_cap = 150;
410 d->in_flow = 80;
411
412 net.insert_arc(s, d, 100);
413
414 net.compute_aux_net();
415 EXPECT_FALSE(net.is_feasible());
416}
417
418// =============================================================================
419// Non-Feasible Nodes Tests
420// =============================================================================
421
423{
424 auto* s1 = net.insert_node(100);
425 auto* s2 = net.insert_node(50);
426
427 s1->out_cap = 200;
428 s1->out_flow = 60; // Not enough
429 s2->out_cap = 100;
430 s2->out_flow = 50; // OK
431
432 net.compute_aux_net();
433
435 net.non_feasible_nodes(supply_list, demand_list);
436
440}
441
443{
444 auto* d1 = net.insert_node(-100);
445 auto* d2 = net.insert_node(-50);
446
447 d1->in_cap = 200;
448 d1->in_flow = 80; // Not enough
449 d2->in_cap = 100;
450 d2->in_flow = 50; // OK
451
452 net.compute_aux_net();
453
455 net.non_feasible_nodes(supply_list, demand_list);
456
460}
461
463{
464 auto* s1 = net.insert_node(100);
465 auto* s2 = net.insert_node(80);
466 auto* d1 = net.insert_node(-60);
467 auto* d2 = net.insert_node(-70);
468
469 s1->out_cap = 200; s1->out_flow = 50; // Not enough
470 s2->out_cap = 200; s2->out_flow = 80; // OK
471 d1->in_cap = 200; d1->in_flow = 30; // Not enough
472 d2->in_cap = 200; d2->in_flow = 70; // OK
473
474 net.compute_aux_net();
475
477 net.non_feasible_nodes(supply_list, demand_list);
478
481}
482
483// =============================================================================
484// Capacity Validation Tests
485// =============================================================================
486
488{
489 auto* p = net.insert_node(0);
490 p->out_cap = 50;
491 p->supply_flow = 100; // Will exceed capacity
492
493 EXPECT_THROW(net.compute_aux_net(), std::range_error);
494}
495
497{
498 auto* p = net.insert_node(0);
499 p->in_cap = 30;
500 p->supply_flow = -50; // Demand exceeds in_cap
501
502 EXPECT_THROW(net.compute_aux_net(), std::range_error);
503}
504
505// =============================================================================
506// Edge Cases
507// =============================================================================
508
510{
511 auto* s1 = net.insert_node(100);
512 auto* s2 = net.insert_node(50);
513
514 s1->out_cap = 200;
515 s2->out_cap = 100;
516
517 net.compute_aux_net();
518
519 // Should have super-source but no super-sink
520 EXPECT_NE(net.get_super_source(), nullptr);
521 EXPECT_EQ(net.get_super_sink(), nullptr);
522}
523
525{
526 auto* d1 = net.insert_node(-100);
527 auto* d2 = net.insert_node(-50);
528
529 d1->in_cap = 200;
530 d2->in_cap = 100;
531
532 net.compute_aux_net();
533
534 // Should have super-sink but no super-source
535 EXPECT_EQ(net.get_super_source(), nullptr);
536 EXPECT_NE(net.get_super_sink(), nullptr);
537}
538
540{
541 net.insert_node(0);
542 net.insert_node(0);
543 net.insert_node(0);
544
545 net.compute_aux_net();
546
547 // Neither super-source nor super-sink needed
548 EXPECT_EQ(net.get_super_source(), nullptr);
549 EXPECT_EQ(net.get_super_sink(), nullptr);
550 // But auxiliary net is still "computed" (flag set)
551 EXPECT_FALSE(net.exist_aux_net()); // Both null means not "exist"
552}
553
555{
556 auto* p = net.insert_node(0);
557 EXPECT_EQ(p->supply_flow, 0);
558 EXPECT_EQ(net.count_supply_nodes(), 0u);
559 EXPECT_EQ(net.count_demand_nodes(), 0u);
560}
561
562// =============================================================================
563// String Network Tests (Different Types)
564// =============================================================================
565
566class StringNetTest : public ::testing::Test
567{
568protected:
570};
571
573{
574 auto* p = net.insert_node("Factory", 100.5);
575 EXPECT_EQ(p->get_info(), "Factory");
576 EXPECT_DOUBLE_EQ(p->supply_flow, 100.5);
577}
578
580{
581 auto* s = net.insert_node("Source", 100.5);
582 auto* d = net.insert_node("Sink", -50.25);
583
584 s->out_cap = 200.0;
585 d->in_cap = 100.0;
586
587 EXPECT_DOUBLE_EQ(net.total_supply(), 100.5);
588 EXPECT_DOUBLE_EQ(net.total_demand(), 50.25);
589}
590
591// =============================================================================
592// Destructor Tests
593// =============================================================================
594
596{
597 auto* net = new SimpleNet();
598 auto* s = net->insert_node(100);
599 auto* d = net->insert_node(-100);
600
601 s->out_cap = 200;
602 d->in_cap = 200;
603
604 net->compute_aux_net();
605 EXPECT_TRUE(net->exist_aux_net());
606
607 // Should not crash - destructor should handle cleanup
608 delete net;
609 SUCCEED();
610}
611
612// =============================================================================
613// Integration Test
614// =============================================================================
615
617{
618 SimpleNet net;
619
620 // Create a balanced network
621 auto* factory1 = net.insert_node(100);
622 auto* factory2 = net.insert_node(50);
623 auto* warehouse = net.insert_node(0);
624 auto* store1 = net.insert_node(-80);
625 auto* store2 = net.insert_node(-70);
626
627 // Set capacities
628 factory1->out_cap = 150;
629 factory2->out_cap = 100;
630 store1->in_cap = 100;
631 store2->in_cap = 100;
632
633 // Connect with arcs
634 net.insert_arc(factory1, warehouse, 100);
635 net.insert_arc(factory2, warehouse, 50);
636 net.insert_arc(warehouse, store1, 80);
637 net.insert_arc(warehouse, store2, 70);
638
639 // Check balance
640 EXPECT_EQ(net.total_supply(), 150);
641 EXPECT_EQ(net.total_demand(), 150);
642 EXPECT_TRUE(net.is_balanced());
643
644 // Compute auxiliary network
645 net.compute_aux_net();
646 EXPECT_TRUE(net.exist_aux_net());
647
648 // Simulate successful max-flow
649 factory1->out_flow = 100;
650 factory2->out_flow = 50;
651 store1->in_flow = 80;
652 store2->in_flow = 70;
653
654 // Check feasibility
655 EXPECT_TRUE(net.is_feasible());
656
657 // Get non-feasible nodes (should be empty)
659 net.non_feasible_nodes(supply_list, demand_list);
662
663 // Cleanup
664 net.free_aux_net();
665 EXPECT_FALSE(net.exist_aux_net());
666}
667
668int main(int argc, char** argv)
669{
670 ::testing::InitGoogleTest(&argc, argv);
671 return RUN_ALL_TESTS();
672}
int main()
WeightedDigraph::Node Node
Dynamic doubly linked list with O(1) size and bidirectional access.
T & get_first() const
Return the first item of the list.
Definition htlist.H:1675
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
Network graph with supply and demand nodes.
Node * insert_node(const Node_Type &node_info, const Flow_Type &supply=0)
Insert a node with info and supply/demand value.
Node with supply/demand flow value.
void SetUp() override
#define TEST(name)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
Definition ahAlgo.H:584
DynList< T > maps(const C &c, Op op)
Classic map operation.
TEST_F(NetSupDemNodeTest, DefaultConstructor)
Net_Sup_Dem_Graph< SimpleNode, SimpleArc > SimpleNet
Arc of a flow network implemented with adjacency lists.
Definition tpl_net.H:115
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
Dynamic doubly linked list implementation.
Supply-demand network flow algorithms.