kotoba_graph/graph/
graph.rs

1//! グラフデータ構造(列指向)
2
3use serde::{Deserialize, Serialize};
4use std::collections::{HashMap, HashSet};
5use parking_lot::RwLock;
6use kotoba_core::types::*;
7use kotoba_core::prelude::{Cid, GraphCore, GraphInstance, Node, Edge, GraphKind};
8use kotoba_cid::CidManager;
9use sha2::{Sha256, Digest};
10
11/// 頂点データ
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
13pub struct VertexData {
14    pub id: VertexId,
15    pub labels: Vec<Label>,
16    pub props: Properties,
17}
18
19impl VertexData {
20    pub fn to_node(&self) -> Node {
21        let mut hasher = Sha256::new();
22        hasher.update(self.id.to_string().as_bytes());
23        let hash: [u8; 32] = hasher.finalize().into();
24
25        Node {
26            cid: Cid(hash),
27            labels: self.labels.clone(),
28            r#type: "node".to_string(),
29            ports: Vec::new(),
30            attrs: Some(self.props.clone()),
31            component_ref: None,
32        }
33    }
34}
35
36/// エッジデータ
37#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
38pub struct EdgeData {
39    pub id: EdgeId,
40    pub src: VertexId,
41    pub dst: VertexId,
42    pub label: Label,
43    pub props: Properties,
44}
45
46impl EdgeData {
47    pub fn to_edge(&self) -> Edge {
48        let mut hasher = Sha256::new();
49        hasher.update(self.id.to_string().as_bytes());
50        let hash: [u8; 32] = hasher.finalize().into();
51
52        Edge {
53            cid: Cid(hash),
54            label: Some(self.label.clone()),
55            src: self.src.to_string(),
56            tgt: self.dst.to_string(),
57            attrs: Some(self.props.clone()),
58            r#type: "edge".to_string(),
59        }
60    }
61}
62
63/// グラフ(列指向表現)
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct Graph {
66    /// 頂点データ(ID→データ)
67    pub vertices: HashMap<VertexId, VertexData>,
68
69    /// エッジデータ(ID→データ)
70    pub edges: HashMap<EdgeId, EdgeData>,
71
72    /// 外向き隣接リスト(src→[dst])
73    pub adj_out: HashMap<VertexId, HashSet<VertexId>>,
74
75    /// 内向き隣接リスト(dst→[src])
76    pub adj_in: HashMap<VertexId, HashSet<VertexId>>,
77
78    /// ラベル別頂点インデックス(ラベル→[頂点ID])
79    pub vertex_labels: HashMap<Label, HashSet<VertexId>>,
80
81    /// ラベル別エッジインデックス(ラベル→[エッジID])
82    pub edge_labels: HashMap<Label, HashSet<EdgeId>>,
83}
84
85impl Graph {
86    /// 空のグラフを作成
87    pub fn empty() -> Self {
88        Self {
89            vertices: HashMap::new(),
90            edges: HashMap::new(),
91            adj_out: HashMap::new(),
92            adj_in: HashMap::new(),
93            vertex_labels: HashMap::new(),
94            edge_labels: HashMap::new(),
95        }
96    }
97
98    /// 頂点を追加
99    pub fn add_vertex(&mut self, vertex: VertexData) -> VertexId {
100        let id = vertex.id;
101        for label in &vertex.labels {
102            self.vertex_labels.entry(label.clone()).or_default().insert(id);
103        }
104        self.vertices.insert(id, vertex);
105        id
106    }
107
108    /// エッジを追加
109    pub fn add_edge(&mut self, edge: EdgeData) -> EdgeId {
110        let id = edge.id;
111        let src = edge.src;
112        let dst = edge.dst;
113
114        // 隣接リスト更新
115        self.adj_out.entry(src).or_default().insert(dst);
116        self.adj_in.entry(dst).or_default().insert(src);
117
118        // ラベルインデックス更新
119        self.edge_labels.entry(edge.label.clone()).or_default().insert(id);
120
121        self.edges.insert(id, edge);
122        id
123    }
124
125    /// 頂点を取得
126    pub fn get_vertex(&self, id: &VertexId) -> Option<&VertexData> {
127        self.vertices.get(id)
128    }
129
130    /// エッジを取得
131    pub fn get_edge(&self, id: &EdgeId) -> Option<&EdgeData> {
132        self.edges.get(id)
133    }
134
135    /// 頂点を削除
136    pub fn remove_vertex(&mut self, id: &VertexId) -> bool {
137        if let Some(vertex) = self.vertices.remove(id) {
138            // ラベルインデックスから削除
139            for label in &vertex.labels {
140                if let Some(vertices) = self.vertex_labels.get_mut(label) {
141                    vertices.remove(id);
142                    if vertices.is_empty() {
143                        self.vertex_labels.remove(label);
144                    }
145                }
146            }
147
148            // 関連エッジを削除
149            let mut edges_to_remove = Vec::new();
150            for (edge_id, edge) in &self.edges {
151                if edge.src == *id || edge.dst == *id {
152                    edges_to_remove.push(*edge_id);
153                }
154            }
155            for edge_id in edges_to_remove {
156                self.remove_edge(&edge_id);
157            }
158
159            // 隣接リストから削除
160            self.adj_out.remove(id);
161            self.adj_in.remove(id);
162
163            // 他の頂点の隣接リストから削除
164            for adj in self.adj_out.values_mut() {
165                adj.remove(id);
166            }
167            for adj in self.adj_in.values_mut() {
168                adj.remove(id);
169            }
170
171            true
172        } else {
173            false
174        }
175    }
176
177    /// エッジを削除
178    pub fn remove_edge(&mut self, id: &EdgeId) -> bool {
179        if let Some(edge) = self.edges.remove(id) {
180            // 隣接リスト更新
181            if let Some(out) = self.adj_out.get_mut(&edge.src) {
182                out.remove(&edge.dst);
183                if out.is_empty() {
184                    self.adj_out.remove(&edge.src);
185                }
186            }
187            if let Some(in_) = self.adj_in.get_mut(&edge.dst) {
188                in_.remove(&edge.src);
189                if in_.is_empty() {
190                    self.adj_in.remove(&edge.dst);
191                }
192            }
193
194            // ラベルインデックス更新
195            if let Some(edges) = self.edge_labels.get_mut(&edge.label) {
196                edges.remove(id);
197                if edges.is_empty() {
198                    self.edge_labels.remove(&edge.label);
199                }
200            }
201
202            true
203        } else {
204            false
205        }
206    }
207
208    /// ラベル別頂点を取得
209    pub fn vertices_by_label(&self, label: &Label) -> HashSet<VertexId> {
210        self.vertex_labels.get(label).cloned().unwrap_or_default()
211    }
212
213    /// ラベル別エッジを取得
214    pub fn edges_by_label(&self, label: &Label) -> HashSet<EdgeId> {
215        self.edge_labels.get(label).cloned().unwrap_or_default()
216    }
217
218    /// 頂点の次数を取得
219    pub fn degree(&self, id: &VertexId) -> usize {
220        let out_degree = self.adj_out.get(id).map(|s| s.len()).unwrap_or(0);
221        let in_degree = self.adj_in.get(id).map(|s| s.len()).unwrap_or(0);
222        out_degree + in_degree
223    }
224
225    /// 頂点数を取得
226    pub fn vertex_count(&self) -> usize {
227        self.vertices.len()
228    }
229
230    /// エッジ数を取得
231    pub fn edge_count(&self) -> usize {
232        self.edges.len()
233    }
234
235    pub fn to_graph_core(&self) -> GraphCore {
236        GraphCore {
237            nodes: self.vertices.values().map(|v| v.to_node()).collect(),
238            edges: self.edges.values().map(|e| e.to_edge()).collect(),
239            boundary: None,
240            attrs: None,
241        }
242    }
243}
244
245/// スレッドセーフなグラフ参照
246#[derive(Debug, Clone)]
247pub struct GraphRef {
248    inner: std::sync::Arc<RwLock<Graph>>,
249}
250
251impl GraphRef {
252    pub fn new(graph: Graph) -> Self {
253        Self {
254            inner: std::sync::Arc::new(RwLock::new(graph)),
255        }
256    }
257
258    pub fn read(&self) -> parking_lot::RwLockReadGuard<'_, Graph> {
259        self.inner.read()
260    }
261
262    pub fn write(&self) -> parking_lot::RwLockWriteGuard<'_, Graph> {
263        self.inner.write()
264    }
265
266    pub fn to_graph_instance_with_cid(&self, cid_manager: &mut CidManager) -> Result<GraphInstance> {
267        let core_graph = self.read().to_graph_core();
268        let cid = cid_manager.compute_graph_cid(&core_graph)?;
269
270        Ok(GraphInstance {
271            cid,
272            kind: GraphKind::Graph,
273            core: core_graph,
274            typing: None, // Simplified
275        })
276    }
277}