🚀 DAGs 上級マスター

アルゴリズム実装・最適化・実践応用の完全ガイド

🔬 トポロジカルソート - 理論と実装

🎯 アルゴリズムの核心

トポロジカルソートは、DAGの頂点を線形順序に並べるアルゴリズムです。依存関係を満たす実行順序を決定する際の基礎となります。

📊 Kahn's Algorithm 実装

class DAG { constructor() { this.adjList = new Map(); this.inDegree = new Map(); } addVertex(vertex) { if (!this.adjList.has(vertex)) { this.adjList.set(vertex, []); this.inDegree.set(vertex, 0); } } addEdge(from, to) { this.addVertex(from); this.addVertex(to); this.adjList.get(from).push(to); this.inDegree.set(to, this.inDegree.get(to) + 1); } topologicalSort() { const result = []; const queue = []; const inDegreeCopy = new Map(this.inDegree); // 入次数0の頂点をキューに追加 for (let [vertex, degree] of inDegreeCopy) { if (degree === 0) { queue.push(vertex); } } while (queue.length > 0) { const current = queue.shift(); result.push(current); // 隣接頂点の入次数を減らす for (let neighbor of this.adjList.get(current)) { inDegreeCopy.set(neighbor, inDegreeCopy.get(neighbor) - 1); if (inDegreeCopy.get(neighbor) === 0) { queue.push(neighbor); } } } return result.length === this.adjList.size ? result : null; } } 

🎮 インタラクティブ・トポロジカルソート可視化

800ms
アルゴリズム実行ログがここに表示されます...
O(V + E)
時間計算量
O(V)
空間計算量
0
実行ステップ数

⚡ DAGにおける最長パス問題

🎯 動的プログラミング解法

DAGでは最長パス問題を多項式時間で解くことができます(一般グラフではNP困難)。

class LongestPath { constructor(dag) { this.dag = dag; this.memo = new Map(); } findLongestPath(start, end) { const topoOrder = this.dag.topologicalSort(); const dist = new Map(); const parent = new Map(); // 初期化 for (let vertex of topoOrder) { dist.set(vertex, vertex === start ? 0 : -Infinity); parent.set(vertex, null); } // トポロジカル順序で処理 for (let u of topoOrder) { if (dist.get(u) !== -Infinity) { for (let v of this.dag.adjList.get(u)) { if (dist.get(u) + 1 > dist.get(v)) { dist.set(v, dist.get(u) + 1); parent.set(v, u); } } } } return this.reconstructPath(start, end, parent, dist); } reconstructPath(start, end, parent, dist) { if (dist.get(end) === -Infinity) return null; const path = []; let current = end; while (current !== null) { path.unshift(current); current = parent.get(current); } return { path: path, length: dist.get(end), distance: dist.get(end) }; } } 

🔍 最長パス探索可視化

🏭 実世界応用:データパイプライン設計

💼 ETLパイプライン最適化

データ処理パイプラインにおけるDAGの活用例:依存関係管理、並列実行計画、障害復旧戦略

class DataPipeline { constructor() { this.tasks = new Map(); this.dependencies = new Map(); this.executionPlan = null; } addTask(taskId, processor, resources = {}) { this.tasks.set(taskId, { id: taskId, processor: processor, resources: resources, status: 'pending', startTime: null, endTime: null, error: null }); this.dependencies.set(taskId, []); } addDependency(taskId, dependsOn) { if (!this.dependencies.has(taskId)) { this.dependencies.set(taskId, []); } this.dependencies.get(taskId).push(dependsOn); } generateExecutionPlan() { // トポロジカルソートベースの実行計画 const dag = new DAG(); for (let taskId of this.tasks.keys()) { dag.addVertex(taskId); } for (let [taskId, deps] of this.dependencies) { for (let dep of deps) { dag.addEdge(dep, taskId); } } this.executionPlan = dag.topologicalSort(); return this.executionPlan; } async executeParallel() { const plan = this.generateExecutionPlan(); const executing = new Set(); const completed = new Set(); const canExecute = (taskId) => { return this.dependencies.get(taskId).every(dep => completed.has(dep)); }; while (completed.size < plan.length) { // 実行可能なタスクを特定 const ready = plan.filter(taskId => !executing.has(taskId) && !completed.has(taskId) && canExecute(taskId) ); // 並列実行 const promises = ready.map(async taskId => { executing.add(taskId); try { await this.executeTask(taskId); completed.add(taskId); } catch (error) { this.tasks.get(taskId).error = error; throw error; } finally { executing.delete(taskId); } }); await Promise.all(promises); } } async executeTask(taskId) { const task = this.tasks.get(taskId); task.status = 'running'; task.startTime = Date.now(); try { await task.processor(); task.status = 'completed'; } catch (error) { task.status = 'failed'; task.error = error; throw error; } finally { task.endTime = Date.now(); } } } 

📊 計算量分析とベンチマーク

アルゴリズム 時間計算量 空間計算量 特徴 適用場面
Kahn's Algorithm O(V + E) O(V) キュー使用、安定 一般的なトポソート
DFS-based TopSort O(V + E) O(V) 再帰、逆順出力 メモリ効率重視
Longest Path O(V + E) O(V) DP使用 スケジューリング
Critical Path O(V + E) O(V) 最早/最遅時刻計算 プロジェクト管理

🧠 上級者チャレンジ問題

問題1: 最適化問題

n個のタスクがあり、各タスクには実行時間t[i]が設定されています。DAGで表現された依存関係の下で、全タスクの完了時間を最小化する並列実行スケジュールを求めてください。

問題2: 理論問題

DAGにおいて、任意の2つの頂点間の到達可能性を前処理O(V²)で計算し、クエリをO(1)で答えるデータ構造を設計してください。

🎓 まとめと次のステップ

🏆 習得したスキル

  • 効率的なトポロジカルソートアルゴリズムの実装
  • DAGにおける最長パス問題の解法
  • 並列処理とスケジューリングの最適化
  • 実際のデータパイプライン設計での応用
  • 計算量分析と性能最適化

🚀 さらなる発展

  • 分散システム: Apache Airflow, Luigi等でのワークフロー管理
  • 機械学習: TensorFlow, PyTorchでの計算グラフ最適化
  • コンパイラ設計: 依存関係解析と最適化
  • ブロックチェーン: トランザクション順序付けと検証