/** * AutoForge DAG Engine — Implementation */ #include "dag_engine.h" #include #include #include #include namespace autoforge { DAGEngine::DAGEngine() = default; DAGEngine::~DAGEngine() = default; std::string DAGEngine::version() { return "0.1.0"; } void DAGEngine::add_node(const DAGNode& node) { std::lock_guard lock(mutex_); index_[node.id] = nodes_.size(); nodes_.push_back(node); } size_t DAGEngine::node_count() const { std::lock_guard lock(mutex_); return nodes_.size(); } void DAGEngine::clear() { std::lock_guard lock(mutex_); nodes_.clear(); index_.clear(); } bool DAGEngine::validate() const { std::lock_guard lock(mutex_); // Kahn's algorithm for cycle detection std::unordered_map in_degree; for (const auto& node : nodes_) { if (in_degree.find(node.id) == in_degree.end()) { in_degree[node.id] = 0; } for (const auto& dep : node.deps) { in_degree[node.id]++; } } std::queue ready; for (const auto& [id, deg] : in_degree) { if (deg == 0) { ready.push(id); } } size_t processed = 0; while (!ready.empty()) { auto current = ready.front(); ready.pop(); processed++; // Find nodes that depend on current for (const auto& node : nodes_) { for (const auto& dep : node.deps) { if (dep == current) { in_degree[node.id]--; if (in_degree[node.id] == 0) { ready.push(node.id); } } } } } return processed == nodes_.size(); } bool DAGEngine::execute() { // Phase 2: actual concurrent task execution if (!validate()) { std::cerr << "[DAGEngine] Invalid DAG — contains cycles" << std::endl; return false; } std::cout << "[DAGEngine] DAG validated. Execution not yet implemented (Phase 2)." << std::endl; return true; } } // namespace autoforge