Skip to main content

cairn_knowledge_graph/operations/selection/operators/
not.rs

1use once_cell::sync::Lazy;
2
3use graphblas_sparse_linear_algebra::operators::{
4    apply::{UnaryOperatorApplier, UnaryOperatorApplierTrait},
5    options::OperatorOptions,
6    unary_operator::LogicalNegation,
7};
8
9use crate::error::GraphComputingError;
10use crate::operations::selection::vertex_selection::VertexSelection;
11
12static DEFAULT_GRAPHBLAS_OPERATOR_OPTIONS_WITH_PRE_CLEARED_OUTPUT: Lazy<OperatorOptions> =
13    Lazy::new(|| OperatorOptions::new(true, false, false, false, false));
14
15static GRAPHBLAS_VECTOR_LOGICAL_NEGATION_OPERATOR: Lazy<UnaryOperatorApplier<bool>> =
16    Lazy::new(|| {
17        UnaryOperatorApplier::<bool>::new(
18            &LogicalNegation::<bool>::new(),
19            &DEFAULT_GRAPHBLAS_OPERATOR_OPTIONS_WITH_PRE_CLEARED_OUTPUT,
20            None,
21        )
22    });
23
24pub trait LogicalNegationOperator<RightHandSide = Self> {
25    type Output;
26    fn not(&self) -> Result<Self::Output, GraphComputingError>;
27    fn not_with_mask(&self, mask: &RightHandSide) -> Result<Self::Output, GraphComputingError>;
28}
29
30impl<'g> LogicalNegationOperator for VertexSelection<'g> {
31    type Output = VertexSelection<'g>;
32
33    fn not(&self) -> Result<Self, GraphComputingError> {
34        // TODO: Size checking
35
36        let mut resulting_vertex_selection = self.clone();
37        GRAPHBLAS_VECTOR_LOGICAL_NEGATION_OPERATOR.apply_to_vector(
38            &self.to_full_vertex_mask()?,
39            resulting_vertex_selection.vertex_mask_mut_ref(),
40        )?;
41        Ok(resulting_vertex_selection)
42    }
43
44    fn not_with_mask(&self, mask: &Self) -> Result<Self, GraphComputingError> {
45        // TODO: Size checking
46        let mask_vector = mask.vertex_mask_ref();
47        let mut resulting_vertex_selection = self.clone();
48        GRAPHBLAS_VECTOR_LOGICAL_NEGATION_OPERATOR.apply_to_vector_with_mask(
49            &self.to_full_vertex_mask_with_mask(mask_vector)?,
50            resulting_vertex_selection.vertex_mask_mut_ref(),
51            mask_vector,
52        )?;
53        Ok(resulting_vertex_selection)
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    use crate::graph::vertex::VertexValue;
62    use crate::operations::select_vertex::SelectVertex;
63
64    use crate::tests::standard_graph_for_testing::standard_graph_for_testing;
65
66    #[test]
67    fn test_not_operator_for_vertex_selection() {
68        let graph = standard_graph_for_testing();
69
70        let integer_selection = graph
71            .select_vertices_connected_to_vertex_by_key(String::from("is_a"), &"integer")
72            .unwrap();
73
74        let no_integer_selection = integer_selection.not().unwrap();
75        let mut no_integer = no_integer_selection.vertex_values_ref().unwrap();
76
77        no_integer.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());
78        no_integer.dedup();
79
80        println!("{:?}", no_integer);
81        assert_eq!(no_integer.len(), 10);
82        assert!(no_integer.contains(&&VertexValue::String(String::from("integer"))));
83        assert!(no_integer.contains(&&VertexValue::String(String::from("natural_number"))));
84        assert!(no_integer.contains(&&VertexValue::String(String::from("negative"))));
85        assert!(no_integer.contains(&&VertexValue::String(String::from("not_a_number"))));
86        assert!(no_integer.contains(&&VertexValue::String(String::from("real_number"))));
87        assert!(no_integer.contains(&&VertexValue::String(String::from("string"))));
88        assert!(no_integer.contains(&&VertexValue::String(String::from("positive"))));
89        assert!(no_integer.contains(&&VertexValue::FloatingPoint32Bit(-1.1)));
90        assert!(no_integer.contains(&&VertexValue::FloatingPoint32Bit(1.1)));
91        assert!(no_integer.contains(&&VertexValue::FloatingPoint32Bit(1.2)));
92    }
93
94    #[test]
95    fn test_not_operator_for_vertex_selection_with_mask() {
96        let graph = standard_graph_for_testing();
97
98        let integer_selection = graph
99            .select_vertices_connected_to_vertex_by_key(String::from("is_a"), &"integer")
100            .unwrap();
101        let number_selection = graph
102            .select_vertices_connected_to_vertex_by_key(String::from("is_a"), &"real_number")
103            .unwrap();
104
105        let no_integer_selection = integer_selection.not_with_mask(&number_selection).unwrap();
106        let mut no_integer = no_integer_selection.vertex_values_ref().unwrap();
107
108        no_integer.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());
109        no_integer.dedup();
110
111        println!("{:?}", no_integer);
112        assert_eq!(no_integer.len(), 3);
113        assert!(no_integer.contains(&&VertexValue::FloatingPoint32Bit(-1.1)));
114        assert!(no_integer.contains(&&VertexValue::FloatingPoint32Bit(1.1)));
115        assert!(no_integer.contains(&&VertexValue::FloatingPoint32Bit(1.2)));
116    }
117}