| |
| |
| |
|
|
| #include "dag_engine.h" |
| #include <algorithm> |
| #include <queue> |
| #include <unordered_set> |
| #include <iostream> |
|
|
| 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<std::mutex> lock(mutex_); |
| index_[node.id] = nodes_.size(); |
| nodes_.push_back(node); |
| } |
|
|
| size_t DAGEngine::node_count() const { |
| std::lock_guard<std::mutex> lock(mutex_); |
| return nodes_.size(); |
| } |
|
|
| void DAGEngine::clear() { |
| std::lock_guard<std::mutex> lock(mutex_); |
| nodes_.clear(); |
| index_.clear(); |
| } |
|
|
| bool DAGEngine::validate() const { |
| std::lock_guard<std::mutex> lock(mutex_); |
|
|
| |
| std::unordered_map<std::string, int> 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<std::string> 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++; |
|
|
| |
| 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() { |
| |
| 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; |
| } |
|
|
| } |
|
|