harness_space/
set.rs

1//! # Set Module
2//!
3//! This module provides traits for abstracting over collection types and partially
4//! ordered sets (posets).
5//!
6//! The core traits defined are:
7//! - [`Collection`]: For types that represent a collection of items, supporting basic operations
8//!   like checking for containment and emptiness.
9//! - [`Poset`]: Extends [`Collection`] for sets that also define a partial order relation among
10//!   their items, along with related poset operations like finding upsets, downsets,
11//!   minimal/maximal elements, etc.
12//!
13//! Implementations of [`Collection`] are provided for standard library types such as
14//! [`HashSet`], [`BTreeSet`], and [`Vec`].
15
16use std::{
17  collections::{BTreeSet, HashSet},
18  hash::{BuildHasher, Hash},
19};
20
21/// A trait for collections that support basic set operations.
22///
23/// This trait defines fundamental operations applicable to various collection types,
24/// focusing on item containment and checking for emptiness.
25///
26/// # Type Parameters
27///
28/// * `Item`: The type of elements contained within the collection.
29///
30/// # Implementations
31///
32/// Implementations are provided for:
33/// * [`HashSet<T, S>`]: Where `T: Hash + Eq + Clone` and `S: BuildHasher + Default`.
34/// * [`BTreeSet<T>`]: Where `T: Ord + Clone`.
35/// * [`Vec<T>`]: Where `T: PartialEq`.
36pub trait Collection {
37  /// The type of elements stored in the collection.
38  type Item;
39
40  /// Checks if an item is present in the collection.
41  ///
42  /// # Arguments
43  ///
44  /// * `point`: A reference to the item to check for containment.
45  ///
46  /// # Returns
47  ///
48  /// `true` if the item is found in the collection, `false` otherwise.
49  fn contains(&self, point: &Self::Item) -> bool;
50
51  /// Determines if the collection is empty.
52  ///
53  /// # Returns
54  ///
55  /// * `true` if the collection contains no items.
56  /// * `false` if the collection contains one or more items.
57  fn is_empty(&self) -> bool;
58}
59
60/// A trait for sets that support partial order relations, building upon [`Collection`].
61///
62/// This trait extends the basic [`Collection`] operations with methods specific to
63/// partially ordered sets (posets). This includes checking the partial order
64/// relation (`leq`), and computing various poset-specific subsets and elements.
65///
66/// # Type Parameters
67///
68/// * `Item`: The type of elements contained in the set, which are subject to the partial order.
69pub trait Poset: Collection {
70  /// Tests if one item is less than or equal to another according to the partial order.
71  ///
72  /// The `leq` relation (often denoted as $\le$) must satisfy reflexivity, antisymmetry,
73  /// and transitivity.
74  ///
75  /// # Arguments
76  ///
77  /// * `a`: A reference to the first item.
78  /// * `b`: A reference to the second item.
79  ///
80  /// # Returns
81  ///
82  /// * `Some(true)` if `a` is less than or equal to `b` ($a \le b$).
83  /// * `Some(false)` if `a` is not less than or equal to `b` (and both are comparable in the set).
84  /// * `None` if the relation cannot be determined (e.g., if one or both items are not considered
85  ///   part of the poset for comparison, or if the specific poset implementation cannot compare
86  ///   them).
87  fn leq(&self, a: &Self::Item, b: &Self::Item) -> Option<bool>;
88
89  /// Computes the upset of an item `a`.
90  ///
91  /// The upset of `a`, denoted $\uparrow a$, is the set of all items `x` in the poset
92  /// such that $a \le x$.
93  ///
94  /// # Arguments
95  ///
96  /// * `a`: The item whose upset is to be computed.
97  ///
98  /// # Returns
99  ///
100  /// A `HashSet` containing all items `x` such that `a` is less than or equal to `x`.
101  fn upset(&self, a: Self::Item) -> HashSet<Self::Item>;
102
103  /// Computes the downset of an item `a`.
104  ///
105  /// The downset of `a`, denoted $\downarrow a$, is the set of all items `x` in the poset
106  /// such that $x \le a$.
107  ///
108  /// # Arguments
109  ///
110  /// * `a`: The item whose downset is to be computed.
111  ///
112  /// # Returns
113  ///
114  /// A `HashSet` containing all items `x` such that `x` is less than or equal to `a`.
115  fn downset(&self, a: Self::Item) -> HashSet<Self::Item>;
116
117  /// Finds all minimal elements of the poset.
118  ///
119  /// An item `m` is minimal if there is no other item `x` in the poset such that $x < m$
120  /// (i.e., $x \le m$ and $x \neq m$).
121  ///
122  /// # Returns
123  ///
124  /// A `HashSet` containing all minimal elements of the poset.
125  fn minimal_elements(&self) -> HashSet<Self::Item>;
126
127  /// Finds all maximal elements of the poset.
128  ///
129  /// An item `m` is maximal if there is no other item `x` in the poset such that $m < x$
130  /// (i.e., $m \le x$ and $m \neq x$).
131  ///
132  /// # Returns
133  ///
134  /// A `HashSet` containing all maximal elements of the poset.
135  fn maximal_elements(&self) -> HashSet<Self::Item>;
136
137  /// Computes the join (least upper bound) of two items `a` and `b`, if it exists.
138  ///
139  /// The join $a \lor b$ is an item `j` such that $a \le j$ and $b \le j$, and for any
140  /// other item `k` with $a \le k$ and $b \le k$, it holds that $j \le k$.
141  ///
142  /// # Arguments
143  ///
144  /// * `a`: The first item.
145  /// * `b`: The second item.
146  ///
147  /// # Returns
148  ///
149  /// * `Some(join_element)` if the join of `a` and `b` exists.
150  /// * `None` if the join does not exist or is not unique.
151  fn join(&self, a: Self::Item, b: Self::Item) -> Option<Self::Item>;
152
153  /// Computes the meet (greatest lower bound) of two items `a` and `b`, if it exists.
154  ///
155  /// The meet $a \land b$ is an item `m` such that $m \le a$ and $m \le b$, and for any
156  /// other item `k` with $k \le a$ and $k \le b$, it holds that $k \le m$.
157  ///
158  /// # Arguments
159  ///
160  /// * `a`: The first item.
161  /// * `b`: The second item.
162  ///
163  /// # Returns
164  ///
165  /// * `Some(meet_element)` if the meet of `a` and `b` exists.
166  /// * `None` if the meet does not exist or is not unique.
167  fn meet(&self, a: Self::Item, b: Self::Item) -> Option<Self::Item>;
168
169  /// Finds all direct successors (covers) of an item `a`.
170  ///
171  /// An item `s` is a direct successor of `a` if $a < s$ (i.e., $a \le s$ and $a \neq s$)
172  /// and there is no item `x` such that $a < x < s$.
173  ///
174  /// # Arguments
175  ///
176  /// * `a`: The item whose successors are to be found.
177  ///
178  /// # Returns
179  ///
180  /// A `HashSet` containing all direct successors of `a`.
181  fn successors(&self, a: Self::Item) -> HashSet<Self::Item>;
182
183  /// Finds all direct predecessors of an item `a`.
184  ///
185  /// An item `p` is a direct predecessor of `a` if $p < a$ (i.e., $p \le a$ and $p \neq a$)
186  /// and there is no item `x` such that $p < x < a$.
187  ///
188  /// # Arguments
189  ///
190  /// * `a`: The item whose predecessors are to be found.
191  ///
192  /// # Returns
193  ///
194  /// A `HashSet` containing all direct predecessors of `a`.
195  fn predecessors(&self, a: Self::Item) -> HashSet<Self::Item>;
196}
197
198impl<T: Hash + Eq + Clone, S: BuildHasher + Default> Collection for HashSet<T, S> {
199  type Item = T;
200
201  /// Checks if the `HashSet` contains the specified item.
202  /// This is a direct wrapper around [`HashSet::contains`].
203  fn contains(&self, point: &Self::Item) -> bool { Self::contains(self, point) }
204
205  /// Checks if the `HashSet` is empty.
206  /// This is a direct wrapper around [`HashSet::is_empty`].
207  fn is_empty(&self) -> bool { Self::is_empty(self) }
208}
209
210impl<T: Ord + Clone> Collection for BTreeSet<T> {
211  type Item = T;
212
213  /// Checks if the `BTreeSet` contains the specified item.
214  /// This is a direct wrapper around [`BTreeSet::contains`].
215  fn contains(&self, point: &Self::Item) -> bool { Self::contains(self, point) }
216
217  /// Checks if the `BTreeSet` is empty.
218  /// This is a direct wrapper around [`BTreeSet::is_empty`].
219  fn is_empty(&self) -> bool { Self::is_empty(self) }
220}
221
222impl<T: PartialEq> Collection for Vec<T> {
223  type Item = T;
224
225  /// Checks if the `Vec` contains the specified item by iterating through its elements.
226  fn contains(&self, point: &Self::Item) -> bool { self.iter().any(|p| p == point) }
227
228  /// Checks if the `Vec` is empty.
229  /// This is a direct wrapper around [`Vec::is_empty`].
230  fn is_empty(&self) -> bool { self.is_empty() }
231}