kotoba_core/graph/
algorithms.rs

1//! グラフアルゴリズム実装
2//!
3//! このモジュールはグラフ構造に対する基本的なアルゴリズムを提供します。
4
5use std::collections::{HashMap, HashSet, VecDeque};
6use crate::graph::Graph;
7use crate::types::VertexId;
8use crate::types::*;
9
10/// グラフトラバーサルアルゴリズム
11pub struct GraphTraversal<'a> {
12    graph: &'a Graph,
13    visited: HashSet<VertexId>,
14    queue: VecDeque<VertexId>,
15    stack: Vec<VertexId>,
16}
17
18impl<'a> GraphTraversal<'a> {
19    /// 新しいトラバーサルを作成
20    pub fn new(graph: &'a Graph) -> Self {
21        Self {
22            graph,
23            visited: HashSet::new(),
24            queue: VecDeque::new(),
25            stack: Vec::new(),
26        }
27    }
28
29    /// BFS (Breadth-First Search) を実行
30    pub fn bfs(&mut self, start: VertexId) -> Vec<VertexId> {
31        self.visited.clear();
32        self.queue.clear();
33        let mut result = Vec::new();
34
35        self.visited.insert(start);
36        self.queue.push_back(start);
37
38        while let Some(current) = self.queue.pop_front() {
39            result.push(current);
40
41            // 隣接頂点を探索
42            if let Some(neighbors) = self.graph.adj_out.get(&current) {
43                for &neighbor in neighbors {
44                    if !self.visited.contains(&neighbor) {
45                        self.visited.insert(neighbor);
46                        self.queue.push_back(neighbor);
47                    }
48                }
49            }
50        }
51
52        result
53    }
54
55    /// DFS (Depth-First Search) を実行
56    pub fn dfs(&mut self, start: VertexId) -> Vec<VertexId> {
57        self.visited.clear();
58        self.stack.clear();
59        let mut result = Vec::new();
60
61        self.stack.push(start);
62
63        while let Some(current) = self.stack.pop() {
64            if !self.visited.contains(&current) {
65                self.visited.insert(current);
66                result.push(current);
67
68                // 隣接頂点をスタックに積む(逆順)
69                if let Some(neighbors) = self.graph.adj_out.get(&current) {
70                    let neighbors_vec: Vec<_> = neighbors.iter().collect();
71                    for &neighbor in neighbors_vec.iter().rev() {
72                        if !self.visited.contains(&neighbor) {
73                            self.stack.push(*neighbor);
74                        }
75                    }
76                }
77            }
78        }
79
80        result
81    }
82
83    /// 接続成分を検出
84    pub fn connected_components(&mut self) -> Vec<Vec<VertexId>> {
85        self.visited.clear();
86        let mut components = Vec::new();
87
88        for &vertex_id in self.graph.vertices.keys() {
89            if !self.visited.contains(&vertex_id) {
90                let component = self.bfs(vertex_id);
91                components.push(component);
92            }
93        }
94
95        components
96    }
97}
98
99/// グラフアルゴリズムのユーティリティ関数
100pub struct GraphAlgorithms;
101
102impl GraphAlgorithms {
103    /// 頂点間の最短経路を計算(BFS使用)
104    pub fn shortest_path(graph: &Graph, start: VertexId, end: VertexId) -> Option<Vec<VertexId>> {
105        if start == end {
106            return Some(vec![start]);
107        }
108
109        let mut visited = HashSet::new();
110        let mut queue = VecDeque::new();
111        let mut parent = HashMap::new();
112
113        visited.insert(start);
114        queue.push_back(start);
115
116        while let Some(current) = queue.pop_front() {
117            if let Some(neighbors) = graph.adj_out.get(&current) {
118                for &neighbor in neighbors {
119                    if !visited.contains(&neighbor) {
120                        visited.insert(neighbor);
121                        parent.insert(neighbor, current);
122                        queue.push_back(neighbor);
123
124                        if neighbor == end {
125                            // パスを再構築
126                            let mut path = vec![end];
127                            let mut current_vertex = end;
128                            while let Some(&parent_vertex) = parent.get(&current_vertex) {
129                                path.push(parent_vertex);
130                                current_vertex = parent_vertex;
131                                if parent_vertex == start {
132                                    break;
133                                }
134                            }
135                            path.reverse();
136                            return Some(path);
137                        }
138                    }
139                }
140            }
141        }
142
143        None // パスが見つからない
144    }
145
146    /// グラフのトポロジカルソート
147    pub fn topological_sort(graph: &Graph) -> Result<Vec<VertexId>> {
148        let mut in_degree = HashMap::new();
149        let mut queue = VecDeque::new();
150        let mut result = Vec::new();
151
152        // 入次数を計算
153        for &vertex_id in graph.vertices.keys() {
154            in_degree.insert(vertex_id, 0);
155        }
156
157        for neighbors in graph.adj_in.values() {
158            for &neighbor in neighbors {
159                if let Some(degree) = in_degree.get_mut(&neighbor) {
160                    *degree += 1;
161                }
162            }
163        }
164
165        // 入次数が0の頂点をキューに追加
166        for (&vertex_id, &degree) in &in_degree {
167            if degree == 0 {
168                queue.push_back(vertex_id);
169            }
170        }
171
172        while let Some(current) = queue.pop_front() {
173            result.push(current);
174
175            if let Some(neighbors) = graph.adj_out.get(&current) {
176                for &neighbor in neighbors {
177                    if let Some(degree) = in_degree.get_mut(&neighbor) {
178                        *degree -= 1;
179                        if *degree == 0 {
180                            queue.push_back(neighbor);
181                        }
182                    }
183                }
184            }
185        }
186
187        // サイクル検出
188        if result.len() != graph.vertices.len() {
189            return Err(kotoba_errors::KotobaError::Validation("Graph contains a cycle".to_string()));
190        }
191
192        Ok(result)
193    }
194
195    /// 強連結成分を検出(Kosarajuのアルゴリズム)
196    pub fn strongly_connected_components(graph: &Graph) -> Vec<Vec<VertexId>> {
197        // 簡易実装:現在は接続成分として扱う
198        let mut traversal = GraphTraversal::new(graph);
199        traversal.connected_components()
200    }
201
202    /// 頂点の次数を計算
203    pub fn degrees(graph: &Graph) -> HashMap<VertexId, (usize, usize)> {
204        let mut degrees = HashMap::new();
205
206        for &vertex_id in graph.vertices.keys() {
207            let out_degree = graph.adj_out.get(&vertex_id).map(|s| s.len()).unwrap_or(0);
208            let in_degree = graph.adj_in.get(&vertex_id).map(|s| s.len()).unwrap_or(0);
209            degrees.insert(vertex_id, (in_degree, out_degree));
210        }
211
212        degrees
213    }
214
215    /// グラフの密度を計算
216    pub fn density(graph: &Graph) -> f64 {
217        let n = graph.vertices.len() as f64;
218        let m = graph.edges.len() as f64;
219
220        if n <= 1.0 {
221            0.0
222        } else {
223            2.0 * m / (n * (n - 1.0))
224        }
225    }
226
227    /// グラフが連結かどうかを判定
228    pub fn is_connected(graph: &Graph) -> bool {
229        if graph.vertices.is_empty() {
230            return true;
231        }
232
233        let start = *graph.vertices.keys().next().unwrap();
234        let mut traversal = GraphTraversal::new(graph);
235        let reachable = traversal.bfs(start);
236
237        reachable.len() == graph.vertices.len()
238    }
239
240    /// グラフにサイクルが存在するかどうかを判定
241    pub fn has_cycle(graph: &Graph) -> bool {
242        Self::topological_sort(graph).is_err()
243    }
244}