200#include <unordered_map>
201#include <unordered_set>
204#include <tclap/CmdLine.h>
207using namespace Aleph;
220 std::unordered_map<TaskGraph::Node*, size_t> pos;
224 for (
auto it =
order.
get_it(); it.has_curr(); it.next(), ++i)
231 for (
auto nit = g.get_node_it();
nit.has_curr();
nit.next_ne())
233 auto * n =
nit.get_curr();
234 if (pos.find(n) == pos.end())
239 for (
auto ait = g.get_arc_it();
ait.has_curr();
ait.next_ne())
241 auto * a =
ait.get_curr();
242 auto * u = g.get_src_node(a);
243 auto * v = g.get_tgt_node(a);
245 const auto it_u = pos.find(u);
246 const auto it_v = pos.find(v);
262 cout <<
"Missing nodes (not produced by the algorithm): ";
266 if (!first)
cout <<
", ";
267 cout << n->get_info();
297 auto config_h = g.insert_node(
"config.h");
298 auto utils_h = g.insert_node(
"utils.h");
301 auto utils_o = g.insert_node(
"utils.o");
302 auto parser_o = g.insert_node(
"parser.o");
303 auto lexer_o = g.insert_node(
"lexer.o");
304 auto main_o = g.insert_node(
"main.o");
305 auto test_o = g.insert_node(
"test.o");
308 auto program = g.insert_node(
"program");
309 auto test_suite = g.insert_node(
"test_suite");
345 auto math101 = g.insert_node(
"Math101");
346 auto math201 = g.insert_node(
"Math201");
347 auto math301 = g.insert_node(
"Math301");
350 auto cs101 = g.insert_node(
"CS101");
351 auto cs102 = g.insert_node(
"CS102");
352 auto cs201 = g.insert_node(
"CS201");
353 auto cs301 = g.insert_node(
"CS301");
354 auto cs302 = g.insert_node(
"CS302");
375 for (
auto it = g.get_node_it(); it.has_curr(); it.next())
376 if (it.get_curr()->get_info() == name)
377 return it.get_curr();
387 cout <<
"Tasks: " << g.get_num_nodes() <<
endl;
388 cout <<
"Dependencies: " << g.get_num_arcs() <<
endl;
390 cout <<
"\nDependency structure:" <<
endl;
391 for (
auto nit = g.get_node_it();
nit.has_curr();
nit.next())
393 auto* node =
nit.get_curr();
394 cout <<
" " << node->get_info() <<
" depends on: ";
398 for (
auto ait = g.get_arc_it();
ait.has_curr();
ait.next())
400 auto* arc =
ait.get_curr();
401 if (g.get_tgt_node(arc) == node)
404 cout << g.get_src_node(arc)->get_info();
408 if (first)
cout <<
"(none - root task)";
418 cout <<
"\n--- DFS-based Topological Sort ---" <<
endl;
419 cout <<
"Algorithm: Post-order DFS traversal" <<
endl;
426 cout <<
"\nExecution order:" <<
endl;
430 auto* node = it.get_curr();
434 std::vector<TaskGraph::Node*>
missing;
438 cout <<
"\n[Warning] The produced order is not a valid topological ordering.\n";
439 cout <<
"This usually means the input graph is not a DAG (has a cycle) or the order is incomplete.\n";
446 cout <<
"\nVerification: Each task appears after all its dependencies." <<
endl;
455 cout <<
"\n--- BFS-based Topological Sort (Kahn's Algorithm) ---" <<
endl;
456 cout <<
"Algorithm: Iteratively remove source nodes (in-degree 0)" <<
endl;
463 cout <<
"\nExecution order:" <<
endl;
467 auto* node = it.get_curr();
471 std::vector<TaskGraph::Node*>
missing;
475 cout <<
"\n[Warning] Kahn's algorithm did not produce a complete valid ordering.\n";
476 cout <<
"If output size < V, the graph contains a cycle (not a DAG).\n";
483 cout <<
"\nParallel execution ranks:" <<
endl;
489 std::unordered_set<TaskGraph::Node*>
seen;
490 seen.reserve(g.get_num_nodes());
494 auto * n =
nit.get_curr();
502 cout <<
"\n[Warning] Rank-based output is incomplete/invalid (cycle or missing nodes).\n";
509 cout <<
" Level " <<
rank_num <<
" (can run in parallel): ";
510 auto& rank =
rit.get_curr();
515 cout <<
nit.get_curr()->get_info();
528 cout <<
"\n" << string(60,
'=') <<
endl;
529 cout <<
"Example: Build System Dependencies" <<
endl;
535 cout <<
"\n--- Computing Build Order ---" <<
endl;
542 cout <<
"\nBuild order (satisfies all dependencies):" <<
endl;
547 if (
not first)
cout <<
" && make ";
548 cout << it.get_curr()->get_info();
559 cout <<
"\n" << string(60,
'=') <<
endl;
560 cout <<
"Example: University Course Prerequisites" <<
endl;
566 cout <<
"\n--- Computing Course Order ---" <<
endl;
571 cout <<
"\nSuggested course schedule:" <<
endl;
581 cout <<
cit.get_curr()->get_info();
594 TCLAP::CmdLine
cmd(
"Topological Sort Example",
' ',
"1.0");
596 TCLAP::SwitchArg
buildArg(
"b",
"build",
597 "Show build system example",
false);
598 TCLAP::SwitchArg
courseArg(
"c",
"courses",
599 "Show course scheduling example",
false);
600 TCLAP::SwitchArg
allArg(
"a",
"all",
601 "Run all demos",
false);
603 "Show detailed output",
false);
620 cout <<
"=== Topological Sort: Task Ordering with Dependencies ===" <<
endl;
635 cout <<
"\n=== Algorithm Summary ===" <<
endl;
636 cout <<
"DFS-based: O(V + E), post-order traversal" <<
endl;
637 cout <<
"BFS-based: O(V + E), Kahn's algorithm (removes sources)" <<
endl;
638 cout <<
"Requirement: Input must be a DAG (no cycles)" <<
endl;
642 catch (TCLAP::ArgException& e)
644 cerr <<
"Error: " << e.error() <<
" for arg " << e.argId() <<
endl;
Generic directed graph (digraph) wrapper template.
typename BaseGraph::Node Node
Dynamic doubly linked list with O(1) size and bidirectional access.
T & insert(const T &item)
Insert a new item by copy.
T & append(const T &item)
Append a new item by copy.
void empty() noexcept
empty the list
size_t size() const noexcept
Count the number of elements of the list.
Computes topological ordering using breadth-first search (Kahn's algorithm).
Computes topological ordering using depth-first search.
void emplace(Args &&... args)
Appends a new element into the container by constructing it in-place with the given args.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
iterator end() noexcept
Return an STL-compatible end iterator.
Main namespace for Aleph-w library functions.
Array< size_t > ranks(const Array< T > &array)
Computes the rank of each element in an Array.
bool verbose
Flag enabling verbose output.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Arc of graph implemented with double-linked adjacency lists.
Node belonging to a graph implemented with a double linked adjacency list.
Topological sorting algorithms for directed acyclic graphs (DAGs).
void print_graph(TaskGraph &g, const string &title)
Print the graph structure.
TaskGraph build_courses_graph()
Build a course prerequisites graph.
void demo_build_order()
Demonstrate practical application: build order.
TaskGraph::Node * find_task(TaskGraph &g, const string &name)
Find a node by name.
TaskGraph build_project_graph()
Build a sample build system dependency graph.
void demo_course_scheduling()
Demonstrate practical application: course scheduling.
void demo_bfs_topological_sort(TaskGraph &g, bool verbose)
Demonstrate BFS-based topological sort (Kahn's algorithm)
void demo_dfs_topological_sort(TaskGraph &g, bool verbose)
Demonstrate DFS-based topological sort.
Generic graph and digraph implementations.