Skip to main content

relmath/core/
unary.rs

1//! Deterministic exact unary relation foundations.
2
3use std::collections::BTreeSet;
4
5use crate::traits::FiniteRelation;
6
7/// A finite unary relation.
8///
9/// `UnaryRelation<T>` remains the exact unary relation surface. Current
10/// carrier-sensitive exact APIs still accept `UnaryRelation<T>` arguments for
11/// compatibility, but G7 introduces [`crate::FiniteCarrier`] as the explicit
12/// carrier boundary when a declared domain should stay distinct from support
13/// inferred from stored tuples.
14///
15/// The starter implementation uses `BTreeSet` so iteration order is
16/// deterministic.
17///
18/// # Examples
19///
20/// ```rust
21/// use relmath::{FiniteRelation, UnaryRelation};
22///
23/// let mut xs = UnaryRelation::new();
24/// assert!(xs.is_empty());
25///
26/// xs.insert(3);
27/// xs.insert(1);
28/// xs.insert(2);
29/// xs.insert(2);
30///
31/// let ys = UnaryRelation::singleton(3);
32/// let zs = UnaryRelation::from_values([2, 3, 4]);
33///
34/// assert!(xs.contains(&1));
35/// assert_eq!(xs.iter().copied().collect::<Vec<_>>(), vec![1, 2, 3]);
36/// assert_eq!(xs.union(&ys).to_vec(), vec![1, 2, 3]);
37/// assert_eq!(xs.intersection(&zs).to_vec(), vec![2, 3]);
38/// assert_eq!(xs.difference(&zs).to_vec(), vec![1]);
39/// assert!(ys.is_subset(&xs));
40/// ```
41#[derive(Clone, Debug, PartialEq, Eq)]
42pub struct UnaryRelation<T: Ord> {
43    values: BTreeSet<T>,
44}
45
46impl<T: Ord> UnaryRelation<T> {
47    /// Creates an empty unary relation.
48    #[must_use]
49    pub fn new() -> Self {
50        Self {
51            values: BTreeSet::new(),
52        }
53    }
54
55    /// Creates a unary relation from the provided values.
56    ///
57    /// Duplicate values are coalesced into a single stored element.
58    #[must_use]
59    pub fn from_values<I>(values: I) -> Self
60    where
61        I: IntoIterator<Item = T>,
62    {
63        values.into_iter().collect()
64    }
65
66    /// Creates a unary relation containing exactly one value.
67    #[must_use]
68    pub fn singleton(value: T) -> Self {
69        let mut values = BTreeSet::new();
70        values.insert(value);
71        Self { values }
72    }
73
74    /// Inserts a value into the unary relation.
75    ///
76    /// Returns `true` when the value was not already present.
77    pub fn insert(&mut self, value: T) -> bool {
78        self.values.insert(value)
79    }
80
81    /// Returns `true` when the unary relation contains the given value.
82    #[must_use]
83    pub fn contains(&self, value: &T) -> bool {
84        self.values.contains(value)
85    }
86
87    /// Returns an iterator over the values in deterministic order.
88    ///
89    /// Iteration order follows `T: Ord`.
90    pub fn iter(&self) -> impl Iterator<Item = &T> {
91        self.values.iter()
92    }
93
94    /// Returns the union of `self` and `other`.
95    #[must_use]
96    pub fn union(&self, other: &Self) -> Self
97    where
98        T: Clone,
99    {
100        self.values.union(&other.values).cloned().collect()
101    }
102
103    /// Returns the intersection of `self` and `other`.
104    #[must_use]
105    pub fn intersection(&self, other: &Self) -> Self
106    where
107        T: Clone,
108    {
109        self.values.intersection(&other.values).cloned().collect()
110    }
111
112    /// Returns the set difference `self \ other`.
113    #[must_use]
114    pub fn difference(&self, other: &Self) -> Self
115    where
116        T: Clone,
117    {
118        self.values.difference(&other.values).cloned().collect()
119    }
120
121    /// Returns `true` when every element of `self` also appears in `other`.
122    #[must_use]
123    pub fn is_subset(&self, other: &Self) -> bool {
124        self.values.is_subset(&other.values)
125    }
126
127    /// Converts the unary relation into a sorted vector.
128    #[must_use]
129    pub fn to_vec(&self) -> Vec<T>
130    where
131        T: Clone,
132    {
133        self.values.iter().cloned().collect()
134    }
135}
136
137impl<T: Ord> Default for UnaryRelation<T> {
138    fn default() -> Self {
139        Self::new()
140    }
141}
142
143impl<T: Ord> FiniteRelation for UnaryRelation<T> {
144    fn len(&self) -> usize {
145        self.values.len()
146    }
147}
148
149impl<T: Ord> FromIterator<T> for UnaryRelation<T> {
150    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
151        Self {
152            values: iter.into_iter().collect(),
153        }
154    }
155}
156
157impl<T: Ord> Extend<T> for UnaryRelation<T> {
158    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
159        self.values.extend(iter);
160    }
161}
162
163impl<T: Ord> IntoIterator for UnaryRelation<T> {
164    type Item = T;
165    type IntoIter = std::collections::btree_set::IntoIter<T>;
166
167    fn into_iter(self) -> Self::IntoIter {
168        self.values.into_iter()
169    }
170}
171
172impl<'a, T: Ord> IntoIterator for &'a UnaryRelation<T> {
173    type Item = &'a T;
174    type IntoIter = std::collections::btree_set::Iter<'a, T>;
175
176    fn into_iter(self) -> Self::IntoIter {
177        self.values.iter()
178    }
179}