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}