cairn_knowledge_graph/operations/selection/operators/
and.rs1use once_cell::sync::Lazy;
2
3use graphblas_sparse_linear_algebra::operators::{
4 element_wise_multiplication::ElementWiseVectorMultiplicationMonoidOperator, monoid::LogicalAnd,
5 options::OperatorOptions,
6};
7
8use crate::error::GraphComputingError;
9use crate::operations::selection::vertex_selection::VertexSelection;
10
11static DEFAULT_GRAPHBLAS_OPERATOR_OPTIONS: Lazy<OperatorOptions> =
12 Lazy::new(|| OperatorOptions::new_default());
13
14static GRAPHBLAS_VECTOR_AND_OPERATOR: Lazy<ElementWiseVectorMultiplicationMonoidOperator<bool>> =
15 Lazy::new(|| {
16 ElementWiseVectorMultiplicationMonoidOperator::<bool>::new(
17 &LogicalAnd::<bool>::new(),
18 &DEFAULT_GRAPHBLAS_OPERATOR_OPTIONS,
19 None,
20 )
21 });
22
23pub trait AndOperator<RightHandSide = Self> {
24 type Output;
25 fn and(&self, right_hand_side: &RightHandSide) -> Result<Self::Output, GraphComputingError>;
26 fn and_with_mask(
28 &self,
29 right_hand_side: &RightHandSide,
30 mask: &RightHandSide,
31 ) -> Result<Self::Output, GraphComputingError>;
32}
33
34impl<'g> AndOperator for VertexSelection<'g> {
35 type Output = VertexSelection<'g>;
36
37 fn and(&self, right_hand_side: &Self) -> Result<Self, GraphComputingError> {
38 let mut resulting_vertex_selection = self.clone();
41 GRAPHBLAS_VECTOR_AND_OPERATOR.apply(
42 self.vertex_mask_ref(),
43 right_hand_side.vertex_mask_ref(),
44 resulting_vertex_selection.vertex_mask_mut_ref(),
45 )?;
46 Ok(resulting_vertex_selection)
47 }
48
49 fn and_with_mask(
51 &self,
52 right_hand_side: &Self,
53 mask: &Self,
54 ) -> Result<Self, GraphComputingError> {
55 let mut resulting_vertex_selection = self.clone();
58 GRAPHBLAS_VECTOR_AND_OPERATOR.apply_with_mask(
59 mask.vertex_mask_ref(),
60 self.vertex_mask_ref(),
61 right_hand_side.vertex_mask_ref(),
62 resulting_vertex_selection.vertex_mask_mut_ref(),
63 )?;
64 Ok(resulting_vertex_selection)
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 use crate::graph::vertex::VertexValue;
73 use crate::operations::select_vertex::SelectVertex;
74
75 use crate::tests::standard_graph_for_testing::standard_graph_for_testing;
76
77 #[test]
78 fn test_and_operator_for_vertex_selection() {
79 let graph = standard_graph_for_testing();
80
81 let negative_selection = graph
82 .select_vertices_connected_to_vertex_by_key(String::from("sign"), &"negative")
83 .unwrap();
84 let integer_selection = graph
85 .select_vertices_connected_to_vertex_by_key(String::from("is_a"), &"integer")
86 .unwrap();
87
88 let negative_integer_selection = negative_selection.and(&integer_selection).unwrap();
89 let negative_integers = negative_integer_selection.vertex_values_ref().unwrap();
90
91 assert_eq!(negative_integers, vec!(&VertexValue::Integer8Bit(-1)));
92 }
93
94 #[test]
95 fn test_and_operator_for_vertex_selection_with_mask() {
96 let graph = standard_graph_for_testing();
97
98 let negative_selection = graph
99 .select_vertices_connected_to_vertex_by_key(String::from("sign"), &"negative")
100 .unwrap();
101 let integer_selection = graph
102 .select_vertices_connected_to_vertex_by_key(String::from("is_a"), &"integer")
103 .unwrap();
104 let real_number_selection = graph
105 .select_vertices_connected_to_vertex_by_key(String::from("is_a"), &"real_number")
106 .unwrap();
107
108 let selection_of_real_numbers_without_positive_integers = real_number_selection
109 .and_with_mask(&negative_selection, &integer_selection)
110 .unwrap();
111 let real_numbers_without_positive_integers =
112 selection_of_real_numbers_without_positive_integers
113 .vertex_values_ref()
114 .unwrap();
115
116 assert_eq!(real_numbers_without_positive_integers.len(), 4);
117 assert!(real_numbers_without_positive_integers.contains(&&VertexValue::Integer8Bit(-1)));
118 assert!(real_numbers_without_positive_integers
119 .contains(&&VertexValue::FloatingPoint32Bit(-1.1)));
120 assert!(
121 real_numbers_without_positive_integers.contains(&&VertexValue::FloatingPoint32Bit(1.1))
122 );
123 assert!(
124 real_numbers_without_positive_integers.contains(&&VertexValue::FloatingPoint32Bit(1.2))
125 );
126 }
127}