Skip to main content

relmath/core/
carrier.rs

1//! Deterministic explicit finite carrier foundations.
2
3use std::collections::BTreeSet;
4
5use super::UnaryRelation;
6
7/// A deterministic explicit finite carrier.
8///
9/// `FiniteCarrier<T>` is the first executable G7 carrier boundary. It records
10/// admissible values explicitly, even when some values are disconnected from
11/// the support of stored tuples. This keeps an explicit carrier semantically
12/// distinct from exact support inferred from relations such as
13/// [`crate::BinaryRelation::carrier`].
14/// Empty and singleton carriers are ordinary first-class values rather than
15/// special cases hidden behind relation support.
16///
17/// The starter implementation stores carrier members in a `BTreeSet`, so
18/// membership and iteration are deterministic.
19///
20/// # Examples
21///
22/// ```rust
23/// use relmath::{BinaryRelation, FiniteCarrier};
24///
25/// let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
26/// let step = BinaryRelation::from_pairs([("Draft", "Review")]);
27///
28/// assert!(states.contains(&"Archived"));
29/// assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
30/// assert_eq!(step.carrier().to_vec(), vec!["Draft", "Review"]);
31/// ```
32#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct FiniteCarrier<T: Ord> {
34    values: BTreeSet<T>,
35}
36
37impl<T: Ord> FiniteCarrier<T> {
38    /// Creates an empty explicit finite carrier.
39    #[must_use]
40    pub fn new() -> Self {
41        Self {
42            values: BTreeSet::new(),
43        }
44    }
45
46    /// Creates an explicit finite carrier from the provided values.
47    ///
48    /// Duplicate values are coalesced into one stored member.
49    #[must_use]
50    pub fn from_values<I>(values: I) -> Self
51    where
52        I: IntoIterator<Item = T>,
53    {
54        values.into_iter().collect()
55    }
56
57    /// Creates an explicit finite carrier containing exactly one value.
58    #[must_use]
59    pub fn singleton(value: T) -> Self {
60        let mut values = BTreeSet::new();
61        values.insert(value);
62        Self { values }
63    }
64
65    /// Returns the number of values in the explicit carrier.
66    #[must_use]
67    pub fn len(&self) -> usize {
68        self.values.len()
69    }
70
71    /// Returns `true` when the explicit carrier contains no values.
72    #[must_use]
73    pub fn is_empty(&self) -> bool {
74        self.values.is_empty()
75    }
76
77    /// Inserts a value into the explicit carrier.
78    ///
79    /// Returns `true` when the value was not already present.
80    pub fn insert(&mut self, value: T) -> bool {
81        self.values.insert(value)
82    }
83
84    /// Returns `true` when the explicit carrier contains the given value.
85    #[must_use]
86    pub fn contains(&self, value: &T) -> bool {
87        self.values.contains(value)
88    }
89
90    /// Returns an iterator over carrier values in deterministic order.
91    pub fn iter(&self) -> impl Iterator<Item = &T> {
92        self.values.iter()
93    }
94
95    /// Materializes this explicit carrier as a unary relation.
96    ///
97    /// This is an explicit bridge to the published exact APIs and generic code
98    /// paths that still take `UnaryRelation<T>` carrier arguments, such as
99    /// [`crate::BinaryRelation::identity`] and older call sites of
100    /// [`crate::BinaryRelation::reflexive_transitive_closure`].
101    ///
102    /// The conversion is intentionally explicit because it forgets the
103    /// semantic distinction between an explicitly declared carrier and ordinary
104    /// unary relation support. For direct carrier-aware exact operations, prefer
105    /// methods such as [`crate::BinaryRelation::identity_on`] and
106    /// [`crate::BinaryRelation::reflexive_transitive_closure_on`].
107    ///
108    /// # Examples
109    ///
110    /// ```rust
111    /// use relmath::{BinaryRelation, FiniteCarrier};
112    ///
113    /// let step = BinaryRelation::from_pairs([("Draft", "Review")]);
114    /// let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
115    ///
116    /// assert_eq!(
117    ///     step.reflexive_transitive_closure(&states.to_unary_relation())
118    ///         .to_vec(),
119    ///     step.reflexive_transitive_closure_on(&states).to_vec()
120    /// );
121    /// ```
122    #[must_use]
123    pub fn to_unary_relation(&self) -> UnaryRelation<T>
124    where
125        T: Clone,
126    {
127        self.values.iter().cloned().collect()
128    }
129
130    /// Converts the explicit carrier into a sorted vector of values.
131    #[must_use]
132    pub fn to_vec(&self) -> Vec<T>
133    where
134        T: Clone,
135    {
136        self.values.iter().cloned().collect()
137    }
138}
139
140impl<T: Ord> Default for FiniteCarrier<T> {
141    fn default() -> Self {
142        Self::new()
143    }
144}
145
146impl<T: Ord> FromIterator<T> for FiniteCarrier<T> {
147    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
148        Self {
149            values: iter.into_iter().collect(),
150        }
151    }
152}
153
154impl<T: Ord> Extend<T> for FiniteCarrier<T> {
155    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
156        self.values.extend(iter);
157    }
158}
159
160impl<T: Ord> IntoIterator for FiniteCarrier<T> {
161    type Item = T;
162    type IntoIter = std::collections::btree_set::IntoIter<T>;
163
164    fn into_iter(self) -> Self::IntoIter {
165        self.values.into_iter()
166    }
167}
168
169impl<'a, T: Ord> IntoIterator for &'a FiniteCarrier<T> {
170    type Item = &'a T;
171    type IntoIter = std::collections::btree_set::Iter<'a, T>;
172
173    fn into_iter(self) -> Self::IntoIter {
174        self.values.iter()
175    }
176}