Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
cut_nodes_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
116#include <iostream>
117#include <iomanip>
118#include <string>
119#include <vector>
120#include <tpl_graph.H>
121#include <tpl_cut_nodes.H>
122#include <tclap/CmdLine.h>
123
124using namespace std;
125using namespace Aleph;
126
127// Graph types
131
144{
145 Graph g;
146
147 auto a = g.insert_node("A");
148 auto b = g.insert_node("B");
149 auto c = g.insert_node("C");
150 auto d = g.insert_node("D");
151 auto e = g.insert_node("E");
152 auto f = g.insert_node("F");
153 auto gg = g.insert_node("G");
154 auto h = g.insert_node("H");
155
156 g.insert_arc(a, b);
157 g.insert_arc(b, c);
158 g.insert_arc(a, d);
159 g.insert_arc(b, e);
160 g.insert_arc(d, e);
161 g.insert_arc(e, f);
162 g.insert_arc(f, gg);
163 g.insert_arc(f, h);
164 g.insert_arc(gg, h);
165
166 return g;
167}
168
183{
184 Graph g;
185
186 auto a = g.insert_node("A");
187 auto b = g.insert_node("B");
188 auto c = g.insert_node("C");
189 auto d = g.insert_node("D");
190 auto e = g.insert_node("E");
191 auto f = g.insert_node("F");
192 auto gg = g.insert_node("G");
193
194 // Main cycle
195 g.insert_arc(a, b);
196 g.insert_arc(b, c);
197 g.insert_arc(c, f);
198 g.insert_arc(f, d);
199 g.insert_arc(d, e);
200 g.insert_arc(e, a);
201
202 // Cross connections
203 g.insert_arc(a, d);
204 g.insert_arc(b, f);
205
206 // Pendant node
207 g.insert_arc(f, gg);
208
209 return g;
210}
211
224{
225 Graph g;
226
227 auto server1 = g.insert_node("Server1");
228 auto server2 = g.insert_node("Server2");
229 auto router1 = g.insert_node("Router1");
230 auto router2 = g.insert_node("Router2");
231 auto switch1 = g.insert_node("Switch1");
232 auto switch2 = g.insert_node("Switch2");
233 auto switch3 = g.insert_node("Switch3");
234 auto pc1 = g.insert_node("PC1");
235 auto pc2 = g.insert_node("PC2");
236 auto pc3 = g.insert_node("PC3");
237
248
249 return g;
250}
251
255Graph::Node* find_node(Graph& g, const string& name)
256{
257 for (auto it = g.get_node_it(); it.has_curr(); it.next())
258 if (it.get_curr()->get_info() == name)
259 return it.get_curr();
260 return nullptr;
261}
262
266void print_graph(Graph& g, const string& title)
267{
268 cout << "\n=== " << title << " ===" << endl;
269 cout << "Nodes: " << g.get_num_nodes() << endl;
270 cout << "Edges: " << g.get_num_arcs() << endl;
271
272 cout << "\nConnections:" << endl;
273 for (auto nit = g.get_node_it(); nit.has_curr(); nit.next())
274 {
275 auto* node = nit.get_curr();
276 cout << " " << node->get_info() << " -- ";
277
278 bool first = true;
279 for (Node_Arc_Iterator<Graph> ait(node); ait.has_curr(); ait.next())
280 {
281 auto* arc = ait.get_curr();
282 auto* neighbor = g.get_connected_node(arc, node);
283 if (not first) cout << ", ";
284 cout << neighbor->get_info();
285 first = false;
286 }
287 cout << endl;
288 }
289}
290
294void demo_cut_nodes(Graph& g, const string& description)
295{
296 cout << "\n--- Finding Cut Nodes (Articulation Points) ---" << endl;
297 cout << "Graph: " << description << endl;
298
299 Compute_Cut_Nodes<Graph> compute(g);
300 DynDlist<Graph::Node*> cut_nodes;
301
302 compute(g.get_first_node(), cut_nodes);
303
304 if (cut_nodes.is_empty())
305 {
306 cout << "\nNo cut nodes found - graph is biconnected!" << endl;
307 cout << "Removing any single node won't disconnect the graph." << endl;
308 }
309 else
310 {
311 cout << "\nCut nodes found: " << cut_nodes.size() << endl;
312 cout << "Cut nodes: ";
313 bool first = true;
314 for (auto it = cut_nodes.get_it(); it.has_curr(); it.next())
315 {
316 if (not first) cout << ", ";
317 cout << it.get_curr()->get_info();
318 first = false;
319 }
320 cout << endl;
321
322 cout << "\nImpact: Removing any of these nodes disconnects the graph." << endl;
323 }
324}
325
330{
331 cout << "\n" << string(60, '=') << endl;
332 cout << "Practical Example: Network Vulnerability Analysis" << endl;
333 cout << string(60, '=') << endl;
334
336 print_graph(g, "Computer Network");
337
338 Compute_Cut_Nodes<Graph> compute(g);
339 DynDlist<Graph::Node*> cut_nodes;
340
341 compute(g.get_first_node(), cut_nodes);
342
343 cout << "\n--- Vulnerability Analysis ---" << endl;
344
345 if (cut_nodes.is_empty())
346 {
347 cout << "Network is fully redundant - no single point of failure!" << endl;
348 }
349 else
350 {
351 cout << "Single points of failure identified:" << endl;
352 for (auto it = cut_nodes.get_it(); it.has_curr(); it.next())
353 {
354 auto* node = it.get_curr();
355 cout << "\n * " << node->get_info() << endl;
356
357 // Count connections
358 int connections = 0;
359 for (Node_Arc_Iterator<Graph> ait(node); ait.has_curr(); ait.next())
360 ++connections;
361
362 cout << " Connections: " << connections << endl;
363 cout << " Risk: CRITICAL - failure would partition the network" << endl;
364 }
365 }
366
367 cout << "\n--- Recommendations ---" << endl;
368 cout << "1. Add redundant links to eliminate cut nodes" << endl;
369 cout << "2. Prioritize backup for critical equipment" << endl;
370 cout << "3. Monitor cut nodes for failures" << endl;
371}
372
377{
378 cout << "\n" << string(60, '=') << endl;
379 cout << "Biconnected Components" << endl;
380 cout << string(60, '=') << endl;
381
383 print_graph(g, "Network Graph");
384
385 Compute_Cut_Nodes<Graph> compute(g);
386 DynDlist<Graph::Node*> cut_nodes;
387
388 compute(g.get_first_node(), cut_nodes);
389
390 cout << "\nCut nodes: ";
391 for (auto it = cut_nodes.get_it(); it.has_curr(); it.next())
392 cout << it.get_curr()->get_info() << " ";
393 cout << endl;
394
395 // Paint subgraphs (components)
396 long num_colors = compute.paint_subgraphs();
397
398 cout << "\n--- Biconnected Components ---" << endl;
399 cout << "Number of components: " << num_colors << endl;
400
401 cout << "\nNodes by component (color):" << endl;
402 for (long color = 1; color <= num_colors; ++color)
403 {
404 cout << " Component " << color << ": ";
405 bool first = true;
406 for (auto nit = g.get_node_it(); nit.has_curr(); nit.next())
407 {
408 auto* node = nit.get_curr();
409 if (g.get_counter(node) == color)
410 {
411 if (not first) cout << ", ";
412 cout << node->get_info();
413 first = false;
414 }
415 }
416 cout << endl;
417 }
418
419 cout << "\n--- Analysis ---" << endl;
420 cout << "A biconnected component has no cut nodes within it." << endl;
421 cout << "Components are connected through cut nodes." << endl;
422}
423
428{
429 cout << "\n" << string(60, '=') << endl;
430 cout << "Network Resilience Comparison" << endl;
431 cout << string(60, '=') << endl;
432
433 // Fragile network (tree-like)
434 cout << "\n--- Fragile Network (Tree-like) ---" << endl;
436 print_graph(fragile, "Fragile Network");
437
438 {
440 DynDlist<Graph::Node*> cut_nodes;
441 compute(fragile.get_first_node(), cut_nodes);
442
443 cout << "Cut nodes: " << cut_nodes.size() << " out of "
444 << fragile.get_num_nodes() << " nodes" << endl;
445 double fragility = 100.0 * cut_nodes.size() / fragile.get_num_nodes();
446 cout << "Fragility score: " << fixed << setprecision(1) << fragility << "%" << endl;
447 }
448
449 // Resilient network (with cycles)
450 cout << "\n--- Resilient Network (With Cycles) ---" << endl;
452 print_graph(resilient, "Resilient Network");
453
454 {
456 DynDlist<Graph::Node*> cut_nodes;
457 compute(resilient.get_first_node(), cut_nodes);
458
459 cout << "Cut nodes: " << cut_nodes.size() << " out of "
460 << resilient.get_num_nodes() << " nodes" << endl;
461 double fragility = 100.0 * cut_nodes.size() / resilient.get_num_nodes();
462 cout << "Fragility score: " << fixed << setprecision(1) << fragility << "%" << endl;
463 }
464
465 cout << "\n--- Key Insight ---" << endl;
466 cout << "Adding redundant connections (creating cycles) reduces fragility" << endl;
467 cout << "by eliminating articulation points." << endl;
468}
469
474{
475 cout << "\n" << string(60, '=') << endl;
476 cout << "Fixing Network Vulnerabilities" << endl;
477 cout << string(60, '=') << endl;
478
480
481 cout << "\n--- Before: Original Network ---" << endl;
482
483 {
484 Compute_Cut_Nodes<Graph> compute(g);
485 DynDlist<Graph::Node*> cut_nodes;
486 compute(g.get_first_node(), cut_nodes);
487
488 cout << "Cut nodes: ";
489 for (auto it = cut_nodes.get_it(); it.has_curr(); it.next())
490 cout << it.get_curr()->get_info() << " ";
491 cout << endl;
492 }
493
494 cout << "\n--- Adding Redundant Links ---" << endl;
495
496 // Add redundant links to eliminate cut nodes
497 auto* c = find_node(g, "C");
498 auto* d = find_node(g, "D");
499 auto* a = find_node(g, "A");
500 auto* f = find_node(g, "F");
501
502 cout << "Adding link: C -- D" << endl;
503 g.insert_arc(c, d);
504
505 cout << "Adding link: A -- F" << endl;
506 g.insert_arc(a, f);
507
508 cout << "\n--- After: Reinforced Network ---" << endl;
509
510 {
511 Compute_Cut_Nodes<Graph> compute(g);
512 DynDlist<Graph::Node*> cut_nodes;
513 compute(g.get_first_node(), cut_nodes);
514
515 if (cut_nodes.is_empty())
516 cout << "No cut nodes! Network is now more resilient." << endl;
517 else
518 {
519 cout << "Remaining cut nodes: ";
520 for (auto it = cut_nodes.get_it(); it.has_curr(); it.next())
521 cout << it.get_curr()->get_info() << " ";
522 cout << endl;
523 }
524 }
525
526 cout << "\n--- Lesson ---" << endl;
527 cout << "Strategic addition of edges can eliminate articulation points" << endl;
528 cout << "and improve network reliability." << endl;
529}
530
531int main(int argc, char* argv[])
532{
533 try
534 {
535 TCLAP::CmdLine cmd("Cut Nodes (Articulation Points) Example", ' ', "1.0");
536
537 TCLAP::SwitchArg basicArg("b", "basic",
538 "Show basic cut nodes demo", false);
539 TCLAP::SwitchArg netArg("n", "network",
540 "Show network vulnerability analysis", false);
541 TCLAP::SwitchArg biconArg("c", "biconnected",
542 "Show biconnected components", false);
543 TCLAP::SwitchArg compareArg("r", "resilience",
544 "Compare network resilience", false);
545 TCLAP::SwitchArg fixArg("f", "fix",
546 "Show fixing vulnerabilities", false);
547 TCLAP::SwitchArg allArg("a", "all",
548 "Run all demos", false);
549
550 cmd.add(basicArg);
551 cmd.add(netArg);
552 cmd.add(biconArg);
553 cmd.add(compareArg);
554 cmd.add(fixArg);
555 cmd.add(allArg);
556
557 cmd.parse(argc, argv);
558
559 bool runBasic = basicArg.getValue();
560 bool runNet = netArg.getValue();
561 bool runBicon = biconArg.getValue();
562 bool runCompare = compareArg.getValue();
563 bool runFix = fixArg.getValue();
564 bool runAll = allArg.getValue();
565
568 runAll = true;
569
570 cout << "=== Cut Nodes (Articulation Points) and Biconnected Components ===" << endl;
571 cout << "A cut node's removal disconnects the graph." << endl;
572
573 if (runAll or runBasic)
574 {
576 print_graph(g, "Sample Network");
577 demo_cut_nodes(g, "Sample network");
578 }
579
580 if (runAll or runNet)
582
583 if (runAll or runBicon)
585
586 if (runAll or runCompare)
588
589 if (runAll or runFix)
591
592 cout << "\n=== Summary ===" << endl;
593 cout << "Cut nodes are critical points in network topology." << endl;
594 cout << "Uses: Network reliability, infrastructure planning, graph analysis" << endl;
595 cout << "Algorithm: DFS with low-link values, O(V + E)" << endl;
596
597 return 0;
598 }
599 catch (TCLAP::ArgException& e)
600 {
601 cerr << "Error: " << e.error() << " for arg " << e.argId() << endl;
602 return 1;
603 }
604}
605
int main()
WeightedDigraph::Node Node
WeightedDigraph::Arc Arc
long double h
Definition btreepic.C:154
Computation of cut nodes (articulation points) of a graph.
long paint_subgraphs()
Paints the connected components around the cut nodes.
Dynamic doubly linked list with O(1) size and bidirectional access.
const size_t & size() const noexcept
Return the number of elements (constant time)
Node * get_first_node() const
Return any node in the graph.
Definition tpl_graph.H:576
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Node Node
The graph type.
Definition tpl_graph.H:432
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
Definition graph-dry.H:772
long & get_counter(Node *node) const noexcept
Get a modifiable reference to the counter of node
Definition graph-dry.H:867
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:778
auto get_node_it() const noexcept
Obtains an iterator to the nodes of graph.
Definition graph-dry.H:2780
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
Graph build_computer_network()
Build a graph representing a computer network.
Graph build_network_graph()
Build a network with clear cut nodes.
void demo_biconnected_components()
Demonstrate biconnected components.
void print_graph(Graph &g, const string &title)
Print graph structure.
Graph build_cyclic_graph()
Build a cyclic graph with fewer cut nodes.
void demo_fixing_vulnerabilities()
Demonstrate fixing network vulnerabilities.
void demo_network_vulnerability()
Practical example: Network vulnerability analysis.
void demo_resilience_comparison()
Compare resilient vs fragile networks.
Graph::Node * find_node(Graph &g, const string &name)
Find a node by name.
void demo_cut_nodes(Graph &g, const string &description)
Demonstrate finding cut nodes.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
static long & color(typename GT::Node *p)
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Node belonging to a graph implemented with a double linked adjacency list.
Definition tpl_graph.H:121
Filtered iterator of adjacent arcs of a node.
Definition tpl_graph.H:1119
Articulation points (cut nodes) and bridges.
Generic graph and digraph implementations.