Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tarjan_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
194#include <iostream>
195#include <iomanip>
196#include <string>
197#include <vector>
198#include <tpl_graph.H>
199#include <Tarjan.H>
200#include <tclap/CmdLine.h>
201
202using namespace std;
203using namespace Aleph;
204
205// Graph types
209
229{
230 SDigraph g;
231
232 // Main site pages (form one SCC)
233 auto home = g.insert_node("Homepage");
234 auto about = g.insert_node("About");
235 auto products = g.insert_node("Products");
236 auto services = g.insert_node("Services");
237 auto contact = g.insert_node("Contact");
238
239 // Blog pages (form another SCC)
240 auto blog = g.insert_node("Blog");
241 auto art1 = g.insert_node("Article1");
242 auto art2 = g.insert_node("Article2");
243 auto art3 = g.insert_node("Article3");
244
245 // Main site links (creates a cycle)
246 g.insert_arc(home, about);
247 g.insert_arc(about, home); // Back link
248 g.insert_arc(home, products);
249 g.insert_arc(about, services);
250 g.insert_arc(products, services);
251 g.insert_arc(services, contact);
252 g.insert_arc(contact, products); // Creates cycle
253
254 // Blog links (creates another cycle)
255 g.insert_arc(blog, art1);
256 g.insert_arc(art1, blog); // Back link
257 g.insert_arc(blog, art2);
258 g.insert_arc(art1, art3);
259 g.insert_arc(art3, art2);
260 g.insert_arc(art2, blog); // Creates cycle
261
262 return g;
263}
264
278{
279 SDigraph g;
280
281 // Core modules (SCC 1)
282 auto core = g.insert_node("Core");
283 auto utils = g.insert_node("Utils");
284
285 // Data modules (SCC 2)
286 auto db = g.insert_node("Database");
287 auto cache = g.insert_node("Cache");
288 auto logger = g.insert_node("Logger");
289
290 // Auth modules (SCC 3)
291 auto api = g.insert_node("API");
292 auto auth = g.insert_node("Auth");
293 auto session = g.insert_node("Session");
294
295 // Core dependencies (bidirectional = SCC)
296 g.insert_arc(core, utils);
297 g.insert_arc(utils, core);
298
299 // Data dependencies
300 g.insert_arc(core, db);
301 g.insert_arc(utils, cache);
302 g.insert_arc(db, cache);
303 g.insert_arc(cache, db); // Cycle
304 g.insert_arc(cache, logger);
305 g.insert_arc(logger, cache); // Cycle
306
307 // Auth dependencies
308 g.insert_arc(api, auth);
309 g.insert_arc(auth, session);
310 g.insert_arc(session, auth); // Cycle
311
312 return g;
313}
314
319{
320 SDigraph g;
321
322 auto a = g.insert_node("A");
323 auto b = g.insert_node("B");
324 auto c = g.insert_node("C");
325 auto d = g.insert_node("D");
326 auto e = g.insert_node("E");
327
328 g.insert_arc(a, b);
329 g.insert_arc(a, c);
330 g.insert_arc(b, d);
331 g.insert_arc(c, d);
332 g.insert_arc(d, e);
333
334 return g;
335}
336
340SDigraph::Node* find_node(SDigraph& g, const string& name)
341{
342 for (auto it = g.get_node_it(); it.has_curr(); it.next())
343 if (it.get_curr()->get_info() == name)
344 return it.get_curr();
345 return nullptr;
346}
347
351void print_graph(SDigraph& g, const string& title)
352{
353 cout << "\n=== " << title << " ===" << endl;
354 cout << "Nodes: " << g.get_num_nodes() << endl;
355 cout << "Edges: " << g.get_num_arcs() << endl;
356
357 cout << "\nAdjacency structure:" << endl;
358 for (auto nit = g.get_node_it(); nit.has_curr(); nit.next())
359 {
360 auto* node = nit.get_curr();
361 cout << " " << node->get_info() << " -> ";
362
363 bool first = true;
364 for (auto ait = g.get_out_it(node); ait.has_curr(); ait.next())
365 {
366 if (not first) cout << ", ";
367 cout << ait.get_tgt_node()->get_info();
368 first = false;
369 }
370 if (first) cout << "(none)";
371 cout << endl;
372 }
373}
374
378void demo_find_sccs(SDigraph& g, const string& description)
379{
380 cout << "\n--- Finding Strongly Connected Components ---" << endl;
381 cout << "Graph: " << description << endl;
382
384
385 // Get SCCs as lists of nodes
387 tarjan.connected_components(g, sccs);
388
389 cout << "\nFound " << sccs.size() << " strongly connected components:" << endl;
390
391 int scc_num = 1;
392 for (auto sit = sccs.get_it(); sit.has_curr(); sit.next(), ++scc_num)
393 {
394 auto& scc = sit.get_curr();
395 cout << "\n SCC " << scc_num << " (" << scc.size() << " node(s)): ";
396
397 bool first = true;
398 for (auto nit = scc.get_it(); nit.has_curr(); nit.next())
399 {
400 if (not first) cout << ", ";
401 cout << nit.get_curr()->get_info();
402 first = false;
403 }
404
405 if (scc.size() > 1)
406 cout << " [cycle exists]";
407 else
408 cout << " [single node]";
409 }
410 cout << endl;
411}
412
417{
418 cout << "\n--- Cycle Detection ---" << endl;
419 cout << "Graph: " << description << endl;
420
422
423 if (tarjan.has_cycle(g))
424 {
425 cout << "Result: Graph CONTAINS cycles" << endl;
426
427 // Find and display a cycle
429 tarjan.compute_cycle(g, cycle);
430
431 if (cycle.size() > 0)
432 {
433 cout << "A cycle found: ";
434 bool first = true;
435 for (auto it = cycle.get_it(); it.has_curr(); it.next())
436 {
437 if (not first) cout << " -> ";
438 cout << it.get_curr()->get_info();
439 first = false;
440 }
441 cout << " -> " << cycle.get_first_node()->get_info() << " (back to start)" << endl;
442 }
443 }
444 else
445 {
446 cout << "Result: Graph is a DAG (no cycles)" << endl;
447 cout << "This graph can be topologically sorted." << endl;
448 }
449}
450
455{
456 cout << "\n" << string(60, '=') << endl;
457 cout << "Example: Web Page Community Detection" << endl;
458 cout << string(60, '=') << endl;
459
461 print_graph(g, "Web Page Link Graph");
462
463 demo_find_sccs(g, "Web pages with hyperlinks");
464
465 cout << "\n--- Analysis ---" << endl;
466 cout << "Pages in the same SCC form a 'community' - they mutually" << endl;
467 cout << "link to each other (directly or through intermediate pages)." << endl;
468 cout << "This is useful for:" << endl;
469 cout << " - Detecting website structure" << endl;
470 cout << " - Finding related content clusters" << endl;
471 cout << " - SEO analysis" << endl;
472}
473
478{
479 cout << "\n" << string(60, '=') << endl;
480 cout << "Example: Software Module Dependency Analysis" << endl;
481 cout << string(60, '=') << endl;
482
484 print_graph(g, "Module Dependency Graph");
485
486 demo_find_sccs(g, "Software modules with dependencies");
487 demo_cycle_detection(g, "Software modules");
488
489 cout << "\n--- Analysis ---" << endl;
490 cout << "Modules in the same SCC have circular dependencies." << endl;
491 cout << "This indicates:" << endl;
492 cout << " - These modules must be built together" << endl;
493 cout << " - Changes to one may affect others" << endl;
494 cout << " - Consider refactoring to break cycles" << endl;
495}
496
501{
502 cout << "\n" << string(60, '=') << endl;
503 cout << "Example: DAG Detection" << endl;
504 cout << string(60, '=') << endl;
505
506 SDigraph g = build_dag();
507 print_graph(g, "Directed Acyclic Graph");
508
509 demo_find_sccs(g, "DAG structure");
510 demo_cycle_detection(g, "DAG (no cycles)");
511
512 cout << "\n--- Analysis ---" << endl;
513 cout << "Each SCC contains only one node, confirming this is a DAG." << endl;
514 cout << "DAGs can be topologically sorted and processed in order." << endl;
515}
516
517int main(int argc, char* argv[])
518{
519 try
520 {
521 TCLAP::CmdLine cmd("Tarjan's SCC Algorithm Example", ' ', "1.0");
522
523 TCLAP::SwitchArg webArg("w", "web",
524 "Show web community detection example", false);
525 TCLAP::SwitchArg modArg("m", "modules",
526 "Show module dependency analysis example", false);
527 TCLAP::SwitchArg dagArg("d", "dag",
528 "Show DAG detection example", false);
529 TCLAP::SwitchArg allArg("a", "all",
530 "Run all demos", false);
531
532 cmd.add(webArg);
533 cmd.add(modArg);
534 cmd.add(dagArg);
535 cmd.add(allArg);
536
537 cmd.parse(argc, argv);
538
539 bool runWeb = webArg.getValue();
540 bool runMod = modArg.getValue();
541 bool runDag = dagArg.getValue();
542 bool runAll = allArg.getValue();
543
545 runAll = true;
546
547 cout << "=== Tarjan's Algorithm: Strongly Connected Components ===" << endl;
548 cout << "An SCC is a maximal set where every vertex reaches every other." << endl;
549
550 if (runAll or runWeb)
552
553 if (runAll or runMod)
555
556 if (runAll or runDag)
558
559 cout << "\n=== Algorithm Summary ===" << endl;
560 cout << "Tarjan's Algorithm: O(V + E) time, single DFS pass" << endl;
561 cout << "Uses index (visit order) and lowlink (lowest reachable index)" << endl;
562 cout << "When lowlink[v] == index[v], v is root of an SCC" << endl;
563
564 return 0;
565 }
566 catch (TCLAP::ArgException& e)
567 {
568 cerr << "Error: " << e.error() << " for arg " << e.argId() << endl;
569 return 1;
570 }
571}
572
Tarjan's algorithm for strongly connected components.
int main()
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3848
typename BaseGraph::Node Node
Definition graph-dry.H:3851
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Path on a graph.
Definition tpl_graph.H:2669
Computes strongly connected components (SCCs) in a directed graph using Tarjan's algorithm.
Definition Tarjan.H:171
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
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.
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
void demo_web_communities()
Demonstrate practical application: web communities.
void demo_find_sccs(SDigraph &g, const string &description)
Demonstrate finding SCCs with Tarjan's algorithm.
SDigraph::Node * find_node(SDigraph &g, const string &name)
Find a node by name.
SDigraph build_module_graph()
Build a software module dependency graph.
void demo_dependency_analysis()
Demonstrate practical application: dependency analysis.
void print_graph(SDigraph &g, const string &title)
Print the graph structure.
void demo_dag_detection()
Demonstrate DAG detection.
void demo_cycle_detection(SDigraph &g, const string &description)
Demonstrate cycle detection.
SDigraph build_dag()
Build a simple graph with no cycles (DAG)
SDigraph build_web_graph()
Build a sample web page link graph.
Generic graph and digraph implementations.