cairn_knowledge_graph/operations/selection/operators/
not.rs1use 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 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 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}