Skip to main content

oxilean_std/ord/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use super::functions::*;
6/// Approximates the least fixpoint of a monotone function on a finite ordered set
7/// by iterative ascent from the bottom element.
8#[allow(dead_code)]
9pub struct FixpointIterator<T: Ord + Clone + Eq> {
10    current: T,
11    bottom: T,
12    max_iters: usize,
13}
14impl<T: Ord + Clone + Eq> FixpointIterator<T> {
15    /// Create a new fixpoint iterator starting from `bottom`.
16    pub fn new(bottom: T, max_iters: usize) -> Self {
17        Self {
18            current: bottom.clone(),
19            bottom,
20            max_iters,
21        }
22    }
23    /// Compute the fixpoint of `f` starting from `bottom`.
24    /// Returns `Some(fp)` if converged within `max_iters`, `None` otherwise.
25    pub fn compute<F: Fn(&T) -> T>(&mut self, f: &F) -> Option<T> {
26        self.current = self.bottom.clone();
27        for _ in 0..self.max_iters {
28            let next = f(&self.current);
29            if next == self.current {
30                return Some(self.current.clone());
31            }
32            self.current = next;
33        }
34        None
35    }
36    /// Current approximation.
37    pub fn current(&self) -> &T {
38        &self.current
39    }
40    /// Reset to the bottom element.
41    pub fn reset(&mut self) {
42        self.current = self.bottom.clone();
43    }
44}
45/// A closed interval `[lo, hi]` over an ordered type with membership and operations.
46#[allow(dead_code)]
47#[derive(Clone, Debug, PartialEq, Eq)]
48pub struct BoundedRange<T: Ord + Clone> {
49    lo: T,
50    hi: T,
51}
52impl<T: Ord + Clone> BoundedRange<T> {
53    /// Create a new `BoundedRange`. Panics if `lo > hi`.
54    pub fn new(lo: T, hi: T) -> Self {
55        assert!(lo <= hi, "BoundedRange: lo must be <= hi");
56        Self { lo, hi }
57    }
58    /// Try to create a `BoundedRange`, returning `None` if `lo > hi`.
59    pub fn try_new(lo: T, hi: T) -> Option<Self> {
60        if lo <= hi {
61            Some(Self { lo, hi })
62        } else {
63            None
64        }
65    }
66    /// Check if `val` lies in this closed interval.
67    pub fn contains(&self, val: &T) -> bool {
68        val >= &self.lo && val <= &self.hi
69    }
70    /// The lower bound.
71    pub fn lo(&self) -> &T {
72        &self.lo
73    }
74    /// The upper bound.
75    pub fn hi(&self) -> &T {
76        &self.hi
77    }
78    /// Clamp `val` to this interval.
79    pub fn clamp(&self, val: T) -> T {
80        if val < self.lo {
81            self.lo.clone()
82        } else if val > self.hi {
83            self.hi.clone()
84        } else {
85            val
86        }
87    }
88    /// Compute the intersection of two ranges, returning `None` if disjoint.
89    pub fn intersect(&self, other: &Self) -> Option<Self> {
90        let lo = if self.lo >= other.lo {
91            self.lo.clone()
92        } else {
93            other.lo.clone()
94        };
95        let hi = if self.hi <= other.hi {
96            self.hi.clone()
97        } else {
98            other.hi.clone()
99        };
100        Self::try_new(lo, hi)
101    }
102    /// Check if two ranges overlap.
103    pub fn overlaps(&self, other: &Self) -> bool {
104        self.lo <= other.hi && other.lo <= self.hi
105    }
106    /// Check if `other` is entirely contained in `self`.
107    pub fn includes(&self, other: &Self) -> bool {
108        self.lo <= other.lo && other.hi <= self.hi
109    }
110}
111/// The three possible ordering outcomes, mirroring Lean 4's `Ordering`.
112#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
113pub enum OrdResult {
114    /// First argument is less than the second.
115    Less,
116    /// Both arguments are equal.
117    Equal,
118    /// First argument is greater than the second.
119    Greater,
120}
121impl OrdResult {
122    /// Swap the ordering: `Less ↔ Greater`, `Equal` stays `Equal`.
123    pub fn swap(self) -> Self {
124        match self {
125            OrdResult::Less => OrdResult::Greater,
126            OrdResult::Equal => OrdResult::Equal,
127            OrdResult::Greater => OrdResult::Less,
128        }
129    }
130    /// Lexicographic "then": if `self` is `Equal`, return `other`; otherwise `self`.
131    pub fn then(self, other: OrdResult) -> Self {
132        match self {
133            OrdResult::Equal => other,
134            _ => self,
135        }
136    }
137    /// `true` iff the result is `Less`.
138    pub fn is_lt(self) -> bool {
139        self == OrdResult::Less
140    }
141    /// `true` iff the result is `Equal`.
142    pub fn is_eq(self) -> bool {
143        self == OrdResult::Equal
144    }
145    /// `true` iff the result is `Greater`.
146    pub fn is_gt(self) -> bool {
147        self == OrdResult::Greater
148    }
149    /// `true` iff the result is `Less` or `Equal`.
150    pub fn is_le(self) -> bool {
151        self != OrdResult::Greater
152    }
153    /// `true` iff the result is `Greater` or `Equal`.
154    pub fn is_ge(self) -> bool {
155        self != OrdResult::Less
156    }
157    /// Convert to a signed integer: -1, 0, or 1.
158    pub fn to_signum(self) -> i32 {
159        match self {
160            OrdResult::Less => -1,
161            OrdResult::Equal => 0,
162            OrdResult::Greater => 1,
163        }
164    }
165    /// Convert from a `std::cmp::Ordering`.
166    pub fn from_std(o: std::cmp::Ordering) -> Self {
167        match o {
168            std::cmp::Ordering::Less => OrdResult::Less,
169            std::cmp::Ordering::Equal => OrdResult::Equal,
170            std::cmp::Ordering::Greater => OrdResult::Greater,
171        }
172    }
173    /// Convert to a `std::cmp::Ordering`.
174    pub fn to_std(self) -> std::cmp::Ordering {
175        match self {
176            OrdResult::Less => std::cmp::Ordering::Less,
177            OrdResult::Equal => std::cmp::Ordering::Equal,
178            OrdResult::Greater => std::cmp::Ordering::Greater,
179        }
180    }
181}
182/// A sorted `Vec`-based set.
183#[derive(Clone, Debug, Default)]
184pub struct SortedSet<T: Ord> {
185    items: Vec<T>,
186}
187impl<T: Ord> SortedSet<T> {
188    /// Create an empty `SortedSet`.
189    pub fn new() -> Self {
190        Self { items: Vec::new() }
191    }
192    /// Insert `item` (no-op if already present).
193    pub fn insert(&mut self, item: T) {
194        match self.items.binary_search(&item) {
195            Ok(_) => {}
196            Err(i) => self.items.insert(i, item),
197        }
198    }
199    /// `true` if `item` is in the set.
200    pub fn contains(&self, item: &T) -> bool {
201        self.items.binary_search(item).is_ok()
202    }
203    /// Remove `item`, returning `true` if it was present.
204    pub fn remove(&mut self, item: &T) -> bool {
205        match self.items.binary_search(item) {
206            Ok(i) => {
207                self.items.remove(i);
208                true
209            }
210            Err(_) => false,
211        }
212    }
213    /// Number of items.
214    pub fn len(&self) -> usize {
215        self.items.len()
216    }
217    /// `true` if empty.
218    pub fn is_empty(&self) -> bool {
219        self.items.is_empty()
220    }
221    /// Iterate over items in order.
222    pub fn iter(&self) -> std::slice::Iter<'_, T> {
223        self.items.iter()
224    }
225    /// Set union.
226    pub fn union(&self, other: &Self) -> Self
227    where
228        T: Clone,
229    {
230        let mut result = self.clone();
231        for item in &other.items {
232            result.insert(item.clone());
233        }
234        result
235    }
236    /// Set intersection.
237    pub fn intersection(&self, other: &Self) -> Self
238    where
239        T: Clone,
240    {
241        let mut result = Self::new();
242        for item in &self.items {
243            if other.contains(item) {
244                result.insert(item.clone());
245            }
246        }
247        result
248    }
249    /// Set difference (`self \ other`).
250    pub fn difference(&self, other: &Self) -> Self
251    where
252        T: Clone,
253    {
254        let mut result = Self::new();
255        for item in &self.items {
256            if !other.contains(item) {
257                result.insert(item.clone());
258            }
259        }
260        result
261    }
262}
263/// A simple sorted `Vec`-based map for small collections.
264///
265/// Keys are kept in sorted order; lookups are O(log n) via binary search.
266#[derive(Clone, Debug)]
267pub struct SortedMap<K: Ord, V> {
268    entries: Vec<(K, V)>,
269}
270impl<K: Ord, V> SortedMap<K, V> {
271    /// Create an empty `SortedMap`.
272    pub fn new() -> Self {
273        Self {
274            entries: Vec::new(),
275        }
276    }
277    /// Insert or replace the value for `key`.
278    pub fn insert(&mut self, key: K, value: V) {
279        match self.entries.binary_search_by(|(k, _)| k.cmp(&key)) {
280            Ok(i) => self.entries[i].1 = value,
281            Err(i) => self.entries.insert(i, (key, value)),
282        }
283    }
284    /// Look up the value for `key`.
285    pub fn get(&self, key: &K) -> Option<&V> {
286        self.entries
287            .binary_search_by(|(k, _)| k.cmp(key))
288            .ok()
289            .map(|i| &self.entries[i].1)
290    }
291    /// Remove the entry for `key`, returning the old value if present.
292    pub fn remove(&mut self, key: &K) -> Option<V> {
293        self.entries
294            .binary_search_by(|(k, _)| k.cmp(key))
295            .ok()
296            .map(|i| self.entries.remove(i).1)
297    }
298    /// `true` if `key` is in the map.
299    pub fn contains_key(&self, key: &K) -> bool {
300        self.entries.binary_search_by(|(k, _)| k.cmp(key)).is_ok()
301    }
302    /// Number of entries.
303    pub fn len(&self) -> usize {
304        self.entries.len()
305    }
306    /// `true` if the map is empty.
307    pub fn is_empty(&self) -> bool {
308        self.entries.is_empty()
309    }
310    /// Iterate over `(key, value)` pairs in key order.
311    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
312        self.entries.iter().map(|(k, v)| (k, v))
313    }
314    /// Return all keys in order.
315    pub fn keys(&self) -> impl Iterator<Item = &K> {
316        self.entries.iter().map(|(k, _)| k)
317    }
318    /// Return all values in key order.
319    pub fn values(&self) -> impl Iterator<Item = &V> {
320        self.entries.iter().map(|(_, v)| v)
321    }
322}
323/// A concrete representation of a Galois connection between two ordered sets.
324///
325/// A Galois connection is a pair of monotone functions `l : A → B` and `r : B → A`
326/// such that for all `a ∈ A` and `b ∈ B`: `l(a) ≤ b ↔ a ≤ r(b)`.
327#[allow(dead_code)]
328pub struct GaloisPair<A, B, L, R>
329where
330    A: Ord,
331    B: Ord,
332    L: Fn(&A) -> B,
333    R: Fn(&B) -> A,
334{
335    left_adjoint: L,
336    right_adjoint: R,
337    _phantom: std::marker::PhantomData<(A, B)>,
338}
339impl<A, B, L, R> GaloisPair<A, B, L, R>
340where
341    A: Ord,
342    B: Ord,
343    L: Fn(&A) -> B,
344    R: Fn(&B) -> A,
345{
346    /// Construct a new Galois pair from left and right adjoints.
347    pub fn new(left_adjoint: L, right_adjoint: R) -> Self {
348        Self {
349            left_adjoint,
350            right_adjoint,
351            _phantom: std::marker::PhantomData,
352        }
353    }
354    /// Apply the left adjoint (lower adjoint) to an element.
355    pub fn left(&self, a: &A) -> B {
356        (self.left_adjoint)(a)
357    }
358    /// Apply the right adjoint (upper adjoint) to an element.
359    pub fn right(&self, b: &B) -> A {
360        (self.right_adjoint)(b)
361    }
362    /// Check the Galois condition: `l(a) ≤ b ↔ a ≤ r(b)` for given `a` and `b`.
363    pub fn check_galois_condition(&self, a: &A, b: &B) -> bool {
364        let la = self.left(a);
365        let rb = self.right(b);
366        (la <= *b) == (*a <= rb)
367    }
368    /// The closure operator `a ↦ r(l(a))` is a closure operator on `A`.
369    pub fn closure(&self, a: &A) -> A {
370        let la = self.left(a);
371        self.right(&la)
372    }
373    /// The kernel operator `b ↦ l(r(b))` is a kernel operator on `B`.
374    pub fn kernel(&self, b: &B) -> B {
375        let rb = self.right(b);
376        self.left(&rb)
377    }
378}
379/// A permutation of indices `0..n`.
380#[derive(Clone, Debug, PartialEq, Eq)]
381pub struct Permutation {
382    pub perm: Vec<usize>,
383}
384impl Permutation {
385    /// Create the identity permutation of size `n`.
386    pub fn identity(n: usize) -> Self {
387        Self {
388            perm: (0..n).collect(),
389        }
390    }
391    /// Create a permutation from a sorted-order vector.
392    ///
393    /// `perm[i] = j` means that position `i` in the sorted order
394    /// came from position `j` in the original.
395    pub fn from_sort_order<T: Ord>(v: &[T]) -> Self {
396        let mut indices: Vec<usize> = (0..v.len()).collect();
397        indices.sort_by(|&a, &b| v[a].cmp(&v[b]));
398        Self { perm: indices }
399    }
400    /// Apply the permutation to a slice, returning a new Vec.
401    pub fn apply<T: Clone>(&self, v: &[T]) -> Vec<T> {
402        self.perm.iter().map(|&i| v[i].clone()).collect()
403    }
404    /// Compute the inverse permutation.
405    pub fn inverse(&self) -> Self {
406        let n = self.perm.len();
407        let mut inv = vec![0usize; n];
408        for (i, &j) in self.perm.iter().enumerate() {
409            inv[j] = i;
410        }
411        Self { perm: inv }
412    }
413    /// Compose two permutations (`self` after `other`).
414    pub fn compose(&self, other: &Self) -> Self {
415        assert_eq!(self.perm.len(), other.perm.len());
416        let perm = other.perm.iter().map(|&i| self.perm[i]).collect();
417        Self { perm }
418    }
419    /// Size of the permutation.
420    pub fn len(&self) -> usize {
421        self.perm.len()
422    }
423    /// Check if empty.
424    pub fn is_empty(&self) -> bool {
425        self.perm.is_empty()
426    }
427    /// Check if this is the identity permutation.
428    pub fn is_identity(&self) -> bool {
429        self.perm.iter().enumerate().all(|(i, &j)| i == j)
430    }
431}
432/// A chain in a partial order: a totally ordered subset tracked as a sorted Vec.
433#[allow(dead_code)]
434pub struct MonotoneChain<T: Ord + Clone> {
435    elements: Vec<T>,
436}
437impl<T: Ord + Clone> MonotoneChain<T> {
438    /// Create an empty chain.
439    pub fn new() -> Self {
440        Self {
441            elements: Vec::new(),
442        }
443    }
444    /// Try to extend the chain with `elem`. Returns `true` if successful
445    /// (i.e., `elem` is greater than the last element).
446    pub fn push(&mut self, elem: T) -> bool {
447        if self.elements.is_empty()
448            || *self
449                .elements
450                .last()
451                .expect("elements is non-empty: checked by is_empty")
452                < elem
453        {
454            self.elements.push(elem);
455            true
456        } else {
457            false
458        }
459    }
460    /// Length of the chain.
461    pub fn len(&self) -> usize {
462        self.elements.len()
463    }
464    /// Whether the chain is empty.
465    pub fn is_empty(&self) -> bool {
466        self.elements.is_empty()
467    }
468    /// The minimum element of the chain.
469    pub fn min_elem(&self) -> Option<&T> {
470        self.elements.first()
471    }
472    /// The maximum element of the chain.
473    pub fn max_elem(&self) -> Option<&T> {
474        self.elements.last()
475    }
476    /// Iterate over chain elements in order.
477    pub fn iter(&self) -> std::slice::Iter<'_, T> {
478        self.elements.iter()
479    }
480    /// Build the longest increasing subsequence from a slice (patience sorting).
481    pub fn lis_from_slice(v: &[T]) -> Self {
482        let mut tails: Vec<T> = Vec::new();
483        for x in v {
484            let pos = tails.partition_point(|t| t < x);
485            if pos == tails.len() {
486                tails.push(x.clone());
487            } else {
488                tails[pos] = x.clone();
489            }
490        }
491        let mut chain = Self::new();
492        for t in tails {
493            chain.elements.push(t);
494        }
495        chain
496    }
497}
498/// A max-heap backed by a `Vec`, supporting arbitrary `Ord` elements.
499#[allow(dead_code)]
500pub struct OrderedHeap<T: Ord> {
501    data: Vec<T>,
502}
503impl<T: Ord> OrderedHeap<T> {
504    /// Create an empty heap.
505    pub fn new() -> Self {
506        Self { data: Vec::new() }
507    }
508    /// Push an element onto the heap.
509    pub fn push(&mut self, val: T) {
510        self.data.push(val);
511        self.sift_up(self.data.len() - 1);
512    }
513    /// Pop the maximum element.
514    pub fn pop(&mut self) -> Option<T> {
515        if self.data.is_empty() {
516            return None;
517        }
518        let n = self.data.len();
519        self.data.swap(0, n - 1);
520        let max = self.data.pop();
521        if !self.data.is_empty() {
522            self.sift_down(0);
523        }
524        max
525    }
526    /// Peek at the maximum element without removing it.
527    pub fn peek(&self) -> Option<&T> {
528        self.data.first()
529    }
530    /// Number of elements.
531    pub fn len(&self) -> usize {
532        self.data.len()
533    }
534    /// Whether the heap is empty.
535    pub fn is_empty(&self) -> bool {
536        self.data.is_empty()
537    }
538    fn sift_up(&mut self, mut i: usize) {
539        while i > 0 {
540            let parent = (i - 1) / 2;
541            if self.data[i] > self.data[parent] {
542                self.data.swap(i, parent);
543                i = parent;
544            } else {
545                break;
546            }
547        }
548    }
549    fn sift_down(&mut self, mut i: usize) {
550        let n = self.data.len();
551        loop {
552            let left = 2 * i + 1;
553            let right = 2 * i + 2;
554            let mut largest = i;
555            if left < n && self.data[left] > self.data[largest] {
556                largest = left;
557            }
558            if right < n && self.data[right] > self.data[largest] {
559                largest = right;
560            }
561            if largest == i {
562                break;
563            }
564            self.data.swap(i, largest);
565            i = largest;
566        }
567    }
568    /// Build a heap from a Vec (heapify).
569    pub fn from_vec(mut v: Vec<T>) -> Self {
570        let n = v.len();
571        let mut heap = Self {
572            data: std::mem::take(&mut v),
573        };
574        if n > 1 {
575            let start = (n - 2) / 2;
576            for i in (0..=start).rev() {
577                heap.sift_down(i);
578            }
579        }
580        heap
581    }
582}