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}