deep_causality/traits/contextuable_graph/mod.rs
1/*
2 * SPDX-License-Identifier: MIT
3 * Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
4 */
5
6use crate::errors::ContextIndexError;
7use crate::traits::contextuable::space_temporal::SpaceTemporal;
8use crate::traits::contextuable::spatial::Spatial;
9use crate::traits::contextuable::temporal::Temporal;
10use crate::{Contextoid, ContextoidId, Datable, RelationKind, Symbolic};
11
12/// Trait for graph containing context-aware nodes.
13///
14/// D: Datable trait object
15/// S: Spatial trait object
16/// T: Temporable trait object
17/// ST: SpaceTemporal trait object
18/// V: Numeric type for dimension values
19///
20/// Provides methods for:
21/// - Adding/removing nodes and edges
22/// - Checking if nodes/edges exist
23/// - Getting node references
24/// - Getting graph size and counts
25///
26/// Nodes are Contextoid objects implementing required traits.
27/// Edges have a relation kind weight.
28///
29/// Methods return Result or Option types for error handling.
30///
31#[allow(clippy::type_complexity)]
32pub trait ContextuableGraph<D, S, T, ST, SYM, VS, VT>
33where
34 D: Datable + Clone,
35 S: Spatial<VS> + Clone,
36 T: Temporal<VT> + Clone,
37 ST: SpaceTemporal<VS, VT> + Clone,
38 SYM: Symbolic + Clone,
39 VS: Clone,
40 VT: Clone,
41{
42 fn add_node(
43 &mut self,
44 value: Contextoid<D, S, T, ST, SYM, VS, VT>,
45 ) -> Result<usize, ContextIndexError>;
46 fn contains_node(&self, index: usize) -> bool;
47 fn get_node(&self, index: usize) -> Option<&Contextoid<D, S, T, ST, SYM, VS, VT>>;
48 fn remove_node(&mut self, node_id: ContextoidId) -> Result<(), ContextIndexError>;
49 fn update_node(
50 &mut self,
51 node_id: ContextoidId,
52 new_node: Contextoid<D, S, T, ST, SYM, VS, VT>,
53 ) -> Result<(), ContextIndexError>;
54 fn add_edge(
55 &mut self,
56 a: usize,
57 b: usize,
58 weight: RelationKind,
59 ) -> Result<(), ContextIndexError>;
60 fn contains_edge(&self, a: usize, b: usize) -> bool;
61 fn remove_edge(&mut self, a: usize, b: usize) -> Result<(), ContextIndexError>;
62 fn size(&self) -> usize;
63 fn is_empty(&self) -> bool;
64 // Corrected method names
65 fn number_of_nodes(&self) -> usize;
66 fn number_of_edges(&self) -> usize;
67}
68
69/// Trait for poly-contextuable causal graphs.
70/// By default, the context graph is assumed to be a single-context graph.
71///
72/// This trait supports multiple contexts by extending the ContextuableGraph trait.
73///
74/// Extends ContextuableGraph trait with methods for:
75///
76/// - Creating and managing additional "contexts"
77/// - Setting a current context ID
78/// - Context-specific node/edge methods
79///
80/// Provides methods for:
81///
82/// - Creating new contexts
83/// - Checking if a context ID exists
84/// - Getting/setting current context ID
85/// - Context-specific node and edge methods
86///
87/// Nodes are Contextoid objects implementing required traits.
88/// Edges have a relation kind weight.
89///
90/// Methods return Result or Option types for error handling.
91///
92#[allow(clippy::type_complexity)]
93pub trait ExtendableContextuableGraph<D, S, T, ST, SYM, VS, VT>
94where
95 D: Datable + Clone,
96 S: Spatial<VS> + Clone,
97 T: Temporal<VT> + Clone,
98 ST: SpaceTemporal<VS, VT> + Clone,
99 SYM: Symbolic + Clone,
100 VS: Clone,
101 VT: Clone,
102{
103 /// Creates a new, empty "extra" context and adds it to the collection.
104 ///
105 /// This method generates a unique ID for the new context internally.
106 ///
107 /// # Parameters
108 /// - `capacity`: The initial storage capacity to pre-allocate for the new context's graph.
109 /// - `default`: If `true`, the newly created context is immediately set as the
110 /// currently active context for subsequent `extra_ctx_*` operations.
111 ///
112 /// # Returns
113 /// The unique `u64` ID assigned to the newly created context.
114 fn extra_ctx_add_new(&mut self, capacity: usize, default: bool) -> u64;
115
116 /// Creates a new extra context with a specific, user-provided ID.
117 ///
118 /// This is useful for scenarios where context IDs need to be deterministic,
119 /// such as when reconstructing a state from a saved configuration.
120 ///
121 /// # Parameters
122 /// - `id`: The user-defined `u64` ID for the new context.
123 /// - `capacity`: The initial storage capacity for the new context's graph.
124 /// - `default`: If `true`, this new context is set as the currently active one.
125 ///
126 /// # Returns
127 /// - `Ok(())` if the context was created successfully.
128 ///
129 /// # Errors
130 /// - `ContextIndexError` if a context with the provided `id` already exists.
131 fn extra_ctx_add_new_with_id(
132 &mut self,
133 id: u64,
134 capacity: usize,
135 default: bool,
136 ) -> Result<(), ContextIndexError>;
137
138 /// Checks if an extra context with the given ID exists.
139 ///
140 /// # Parameters
141 /// - `idx`: The `u64` ID of the context to check for.
142 ///
143 /// # Returns
144 /// `true` if a context with the specified ID exists, `false` otherwise.
145 fn extra_ctx_check_exists(&self, idx: u64) -> bool;
146
147 /// Gets the ID of the currently active extra context.
148 ///
149 /// By convention, an ID of `0` indicates that no extra context is currently active,
150 /// and operations will target the primary context.
151 ///
152 /// # Returns
153 /// The `u64` ID of the active context.
154 fn extra_ctx_get_current_id(&self) -> u64;
155
156 /// Sets the active extra context to the one identified by the given ID.
157 ///
158 /// All subsequent `extra_ctx_*` operations will be directed to this context
159 /// until it is changed or unset.
160 ///
161 /// # Parameters
162 /// - `idx`: The `u64` ID of the context to set as active.
163 ///
164 /// # Returns
165 /// - `Ok(())` on success.
166 ///
167 /// # Errors
168 /// - `ContextIndexError` if no context with the specified `idx` exists.
169 fn extra_ctx_set_current_id(&mut self, idx: u64) -> Result<(), ContextIndexError>;
170
171 /// Unsets the currently active extra context.
172 ///
173 /// After this operation, `extra_ctx_get_current_id` will return `0`,
174 /// indicating that no extra context is active.
175 ///
176 /// # Returns
177 /// - `Ok(())` if a context was active and has now been unset.
178 ///
179 /// # Errors
180 /// - `ContextIndexError` if no extra context was active to begin with.
181 fn extra_ctx_unset_current_id(&mut self) -> Result<(), ContextIndexError>;
182
183 /// Adds a `Contextoid` node to the currently active extra context.
184 ///
185 /// This operation is directed to the context set by `extra_ctx_set_current_id`.
186 ///
187 /// # Parameters
188 /// - `value`: The `Contextoid` instance to add to the graph.
189 ///
190 /// # Returns
191 /// - `Ok(usize)` containing the unique index of the newly added node within the active context's graph.
192 ///
193 /// # Errors
194 /// - `ContextIndexError` if no extra context is currently active.
195 fn extra_ctx_add_node(
196 &mut self,
197 value: Contextoid<D, S, T, ST, SYM, VS, VT>,
198 ) -> Result<usize, ContextIndexError>;
199
200 /// Checks if a node with the given index exists in the currently active extra context.
201 ///
202 /// This operation is directed to the context set by `extra_ctx_set_current_id`.
203 ///
204 /// # Parameters
205 /// - `index`: The index of the node to check for.
206 ///
207 /// # Returns
208 /// - `true` if a node with the specified index exists in the active context.
209 /// - `false` if the node does not exist or if no extra context is currently active.
210 fn extra_ctx_contains_node(&self, index: usize) -> bool;
211
212 /// Retrieves an immutable reference to a `Contextoid` from the currently active extra context.
213 ///
214 /// This operation is directed to the context set by `extra_ctx_set_current_id`.
215 ///
216 /// # Parameters
217 /// - `index`: The index of the node to retrieve.
218 ///
219 /// # Returns
220 /// - `Ok(&Contextoid<...>)` containing a reference to the node if found.
221 ///
222 /// # Errors
223 /// - `ContextIndexError` if no extra context is active or if the `index` is out of bounds for the active context's graph.
224 fn extra_ctx_get_node(
225 &self,
226 index: usize,
227 ) -> Result<&Contextoid<D, S, T, ST, SYM, VS, VT>, ContextIndexError>;
228
229 /// Removes a node by its index from the currently active extra context.
230 ///
231 /// This operation is directed to the context set by `extra_ctx_set_current_id`.
232 /// Note that this will also remove all edges connected to the specified node.
233 ///
234 /// # Parameters
235 /// - `index`: The index of the node to remove.
236 ///
237 /// # Returns
238 /// - `Ok(())` if the node was successfully removed.
239 ///
240 /// # Errors
241 /// - `ContextIndexError` if no extra context is active or if the `index` is out of bounds.
242 fn extra_ctx_remove_node(&mut self, index: usize) -> Result<(), ContextIndexError>;
243
244 /// Adds a directed edge between two nodes in the currently active extra context.
245 ///
246 /// The edge is created from node `a` to node `b`. This operation is directed
247 /// to the context set by `extra_ctx_set_current_id`.
248 ///
249 /// # Parameters
250 /// - `a`: The index of the source node.
251 /// - `b`: The index of the target node.
252 /// - `weight`: The `RelationKind` that describes the relationship between the nodes.
253 ///
254 /// # Returns
255 /// - `Ok(())` if the edge was successfully added.
256 ///
257 /// # Errors
258 /// - `ContextIndexError` if no extra context is active or if either `a` or `b` are invalid node indices.
259 fn extra_ctx_add_edge(
260 &mut self,
261 a: usize,
262 b: usize,
263 weight: RelationKind,
264 ) -> Result<(), ContextIndexError>;
265
266 /// Checks if a directed edge exists between two nodes in the currently active extra context.
267 ///
268 /// The check is for an edge from node `a` to node `b`. This operation is directed
269 /// to the context set by `extra_ctx_set_current_id`.
270 ///
271 /// # Parameters
272 /// - `a`: The index of the source node.
273 /// - `b`: The index of the target node.
274 ///
275 /// # Returns
276 /// - `true` if a directed edge from `a` to `b` exists in the active context.
277 /// - `false` if the edge does not exist, if either index is invalid, or if no
278 /// extra context is currently active.
279 fn extra_ctx_contains_edge(&self, a: usize, b: usize) -> bool;
280
281 /// Removes a directed edge between two nodes in the currently active extra context.
282 ///
283 /// This operation is directed to the context set by `extra_ctx_set_current_id`.
284 ///
285 /// # Parameters
286 /// - `a`: The index of the source node of the edge to remove.
287 /// - `b`: The index of the target node of the edge to remove.
288 ///
289 /// # Returns
290 /// - `Ok(())` if the edge was successfully removed.
291 ///
292 /// # Errors
293 /// - `ContextIndexError` if no extra context is active or if the edge does not exist.
294 fn extra_ctx_remove_edge(&mut self, a: usize, b: usize) -> Result<(), ContextIndexError>;
295
296 /// Returns the number of nodes in the currently active extra context's graph.
297 ///
298 /// This operation is directed to the context set by `extra_ctx_set_current_id`.
299 ///
300 /// # Returns
301 /// - `Ok(usize)` containing the total number of nodes in the active context's graph.
302 ///
303 /// # Errors
304 /// - `ContextIndexError` if no extra context is currently active.
305 fn extra_ctx_size(&self) -> Result<usize, ContextIndexError>;
306
307 /// Checks if the currently active extra context's graph is empty (contains no nodes).
308 ///
309 /// This operation is directed to the context set by `extra_ctx_set_current_id`.
310 ///
311 /// # Returns
312 /// - `Ok(true)` if the active context's graph has zero nodes.
313 /// - `Ok(false)` if it contains one or more nodes.
314 ///
315 /// # Errors
316 /// - `ContextIndexError` if no extra context is currently active.
317 fn extra_ctx_is_empty(&self) -> Result<bool, ContextIndexError>;
318
319 /// Returns the total number of nodes in the currently active extra context's graph.
320 ///
321 /// This operation is directed to the context set by `extra_ctx_set_current_id`.
322 ///
323 /// # Returns
324 /// - `Ok(usize)` containing the count of nodes in the active context's graph.
325 ///
326 /// # Errors
327 /// - `ContextIndexError` if no extra context is currently active.
328 fn extra_ctx_node_count(&self) -> Result<usize, ContextIndexError>;
329
330 /// Returns the total number of edges in the currently active extra context's graph.
331 ///
332 /// This operation is directed to the context set by `extra_ctx_set_current_id`.
333 ///
334 /// # Returns
335 /// - `Ok(usize)` containing the count of edges in the active context's graph.
336 ///
337 /// # Errors
338 /// - `ContextIndexError` if no extra context is currently active.
339 fn extra_ctx_edge_count(&self) -> Result<usize, ContextIndexError>;
340}