diff --git a/examples/set_join_semilattice.rs b/examples/set_join_semilattice.rs new file mode 100644 index 0000000..55a67b7 --- /dev/null +++ b/examples/set_join_semilattice.rs @@ -0,0 +1,72 @@ +use noether::{AssociativeJoin, CommutativeJoin, IdempotentJoin, Join, JoinSemiLattice}; +use std::collections::HashSet; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SetJoinSemilattice { + set: HashSet, +} +impl SetJoinSemilattice { + pub const fn new(set: HashSet) -> Self { + Self { set } + } +} +impl CommutativeJoin for SetJoinSemilattice {} +impl AssociativeJoin for SetJoinSemilattice {} + +impl IdempotentJoin for SetJoinSemilattice {} + +impl Join for SetJoinSemilattice { + fn join(self, other: &Self) -> Self { + let union: HashSet = self.set.union(&other.set).cloned().collect(); + Self { set: union } + } + + /// The identity element: an empty set. + /// Satisfies: a ⋁ {} == a + fn identity(&self) -> Self { + Self { + set: HashSet::new(), + } + } +} + +// // impl Join for {}; + +impl JoinSemiLattice for SetJoinSemilattice {} + +fn main() { + // Test 1: check join of different sets + let set_a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); + let set_b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); + + let semilattice_a = SetJoinSemilattice { set: set_a }; + let semilattice_b = SetJoinSemilattice { set: set_b }; + + // Perform the join operation (union) + let result: SetJoinSemilattice = semilattice_a.join(&semilattice_b); + println!("Resulting Set: {:?}", result.set); + + // Test 2: check join of same element + + let set_c: HashSet<_> = vec![1, 2, 3].into_iter().collect(); + let set_d: HashSet<_> = vec![1, 2, 3].into_iter().collect(); + + let semilattice_c = SetJoinSemilattice { set: set_c }; + let semilattice_d = SetJoinSemilattice { set: set_d }; + + let result_same_set: SetJoinSemilattice = semilattice_c.join(&semilattice_d); + println!("Resulting Same Set: {:?}", result_same_set.set); + + // Test 3: check join with identity element should return the same set + + let set_e: HashSet<_> = vec![1, 2, 4].into_iter().collect(); + + let semilattice_e = SetJoinSemilattice { set: set_e }; + let identity = semilattice_e.identity(); + + let result_identity: SetJoinSemilattice = semilattice_e.join(&identity); + println!( + "Resulting of join with identity should return same set {:?}", + result_identity.set + ); +} diff --git a/src/lib.rs b/src/lib.rs index e412b12..9ac657b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -607,6 +607,35 @@ impl Field for T {} // OrderedField impl OrderedField for T {} +// properties of Join in a semilattice +/// Ensures that the join operation satisfies associativity: +/// - For all a, b, c in the semilattice: +/// (a ⋁ b) ⋁ c == a ⋁ (b ⋁ c) +/// This property guarantees that grouping does not affect the result of joins. +pub trait IdempotentJoin {} +/// Ensures that the join operation satisfies commutativity: +/// - For all a, b in the semilattice: +/// a ⋁ b == b ⋁ a +/// This property allows the order of operands to be swapped without affecting the result. + +/// Ensures that the join operation satisfies idempotency: +/// - For all a in the semilattice: +/// a ⋁ a == a +/// This property means that joining an element with itself does not change the element. + +pub trait AssociativeJoin {} + +pub trait CommutativeJoin {} + +pub trait Join: AssociativeJoin + CommutativeJoin + IdempotentJoin { + fn join(self, other: &Self) -> Self; + /// Returns the identity element of the semilattice. + /// The identity must satisfy: a ⋁ e == a, where e is the identity element. + fn identity(&self) -> Self; +} + +pub trait JoinSemiLattice: Join {} + // RealField // Note: This cannot be implemented as a blanket impl because it requires knowledge about completeness