Skip to main content

cvx_graph/
relation.rs

1//! Typed relations (edges) in the knowledge graph.
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6use crate::EntityId;
7
8/// Relation type label.
9#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub enum RelationType {
11    /// Step A must precede step B in a plan.
12    Precedes,
13    /// Task requires this action/step.
14    Requires,
15    /// Object is located at a location.
16    LocatedAt,
17    /// Action uses an appliance.
18    Uses,
19    /// Entity A is similar to entity B.
20    SimilarTo,
21    /// Entity A is a sub-type of entity B.
22    IsA,
23    /// Task produces/achieves a state.
24    Produces,
25    /// Custom relation.
26    Custom(String),
27}
28
29/// A directed relation (edge) between two entities.
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct Relation {
32    /// Source entity.
33    pub source: EntityId,
34    /// Target entity.
35    pub target: EntityId,
36    /// Relation type.
37    pub relation_type: RelationType,
38    /// Weight / confidence (0.0 - 1.0).
39    pub weight: f32,
40    /// Arbitrary properties.
41    pub properties: HashMap<String, String>,
42}
43
44impl Relation {
45    /// Create a new relation.
46    pub fn new(
47        source: EntityId,
48        target: EntityId,
49        relation_type: RelationType,
50        weight: f32,
51    ) -> Self {
52        Self {
53            source,
54            target,
55            relation_type,
56            weight,
57            properties: HashMap::new(),
58        }
59    }
60
61    /// Add a property.
62    pub fn with_property(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
63        self.properties.insert(key.into(), value.into());
64        self
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn relation_creation() {
74        let r = Relation::new(1, 2, RelationType::Precedes, 1.0).with_property("order", "1");
75
76        assert_eq!(r.source, 1);
77        assert_eq!(r.target, 2);
78        assert_eq!(r.relation_type, RelationType::Precedes);
79    }
80}