Skip to main content

oxilean_std/ordering/
functions.rs

1//! Auto-generated module
2//!
3//! πŸ€– Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8    DedekindCutQ, FiniteLinearOrder, FinitePartialOrder, OrderedRange, OrderedTable, Ordering,
9    OrderingBuilder, OrdinalCnf, WqoInstance,
10};
11
12/// Build Ordering type in the environment.
13pub fn build_ordering_env(env: &mut Environment) -> Result<(), String> {
14    let type1 = Expr::Sort(Level::succ(Level::zero()));
15    env.add(Declaration::Axiom {
16        name: Name::str("Ordering"),
17        univ_params: vec![],
18        ty: type1.clone(),
19    })
20    .map_err(|e| e.to_string())?;
21    env.add(Declaration::Axiom {
22        name: Name::str("Ordering.less"),
23        univ_params: vec![],
24        ty: Expr::Const(Name::str("Ordering"), vec![]),
25    })
26    .map_err(|e| e.to_string())?;
27    env.add(Declaration::Axiom {
28        name: Name::str("Ordering.equal"),
29        univ_params: vec![],
30        ty: Expr::Const(Name::str("Ordering"), vec![]),
31    })
32    .map_err(|e| e.to_string())?;
33    env.add(Declaration::Axiom {
34        name: Name::str("Ordering.greater"),
35        univ_params: vec![],
36        ty: Expr::Const(Name::str("Ordering"), vec![]),
37    })
38    .map_err(|e| e.to_string())?;
39    let is_le_ty = Expr::Pi(
40        oxilean_kernel::BinderInfo::Default,
41        Name::str("o"),
42        Box::new(Expr::Const(Name::str("Ordering"), vec![])),
43        Box::new(Expr::Const(Name::str("Bool"), vec![])),
44    );
45    env.add(Declaration::Axiom {
46        name: Name::str("Ordering.isLE"),
47        univ_params: vec![],
48        ty: is_le_ty,
49    })
50    .map_err(|e| e.to_string())?;
51    let is_ge_ty = Expr::Pi(
52        oxilean_kernel::BinderInfo::Default,
53        Name::str("o"),
54        Box::new(Expr::Const(Name::str("Ordering"), vec![])),
55        Box::new(Expr::Const(Name::str("Bool"), vec![])),
56    );
57    env.add(Declaration::Axiom {
58        name: Name::str("Ordering.isGE"),
59        univ_params: vec![],
60        ty: is_ge_ty,
61    })
62    .map_err(|e| e.to_string())?;
63    let reverse_ty = Expr::Pi(
64        oxilean_kernel::BinderInfo::Default,
65        Name::str("o"),
66        Box::new(Expr::Const(Name::str("Ordering"), vec![])),
67        Box::new(Expr::Const(Name::str("Ordering"), vec![])),
68    );
69    env.add(Declaration::Axiom {
70        name: Name::str("Ordering.reverse"),
71        univ_params: vec![],
72        ty: reverse_ty,
73    })
74    .map_err(|e| e.to_string())?;
75    let then_ty = Expr::Pi(
76        oxilean_kernel::BinderInfo::Default,
77        Name::str("o1"),
78        Box::new(Expr::Const(Name::str("Ordering"), vec![])),
79        Box::new(Expr::Pi(
80            oxilean_kernel::BinderInfo::Default,
81            Name::str("o2"),
82            Box::new(Expr::Const(Name::str("Ordering"), vec![])),
83            Box::new(Expr::Const(Name::str("Ordering"), vec![])),
84        )),
85    );
86    env.add(Declaration::Axiom {
87        name: Name::str("Ordering.then"),
88        univ_params: vec![],
89        ty: then_ty,
90    })
91    .map_err(|e| e.to_string())?;
92    Ok(())
93}
94#[cfg(test)]
95mod tests {
96    use super::*;
97    fn setup_env() -> Environment {
98        let mut env = Environment::new();
99        let type1 = Expr::Sort(Level::succ(Level::zero()));
100        env.add(Declaration::Axiom {
101            name: Name::str("Bool"),
102            univ_params: vec![],
103            ty: type1,
104        })
105        .expect("operation should succeed");
106        env
107    }
108    #[test]
109    fn test_build_ordering_env() {
110        let mut env = setup_env();
111        assert!(build_ordering_env(&mut env).is_ok());
112        assert!(env.get(&Name::str("Ordering")).is_some());
113        assert!(env.get(&Name::str("Ordering.less")).is_some());
114        assert!(env.get(&Name::str("Ordering.equal")).is_some());
115        assert!(env.get(&Name::str("Ordering.greater")).is_some());
116    }
117    #[test]
118    fn test_ordering_is_le() {
119        let mut env = setup_env();
120        build_ordering_env(&mut env).expect("build_ordering_env should succeed");
121        let decl = env
122            .get(&Name::str("Ordering.isLE"))
123            .expect("declaration 'Ordering.isLE' should exist in env");
124        assert!(matches!(decl, Declaration::Axiom { .. }));
125    }
126    #[test]
127    fn test_ordering_is_ge() {
128        let mut env = setup_env();
129        build_ordering_env(&mut env).expect("build_ordering_env should succeed");
130        let decl = env
131            .get(&Name::str("Ordering.isGE"))
132            .expect("declaration 'Ordering.isGE' should exist in env");
133        assert!(matches!(decl, Declaration::Axiom { .. }));
134    }
135    #[test]
136    fn test_ordering_reverse() {
137        let mut env = setup_env();
138        build_ordering_env(&mut env).expect("build_ordering_env should succeed");
139        let decl = env
140            .get(&Name::str("Ordering.reverse"))
141            .expect("declaration 'Ordering.reverse' should exist in env");
142        assert!(matches!(decl, Declaration::Axiom { .. }));
143    }
144    #[test]
145    fn test_ordering_then() {
146        let mut env = setup_env();
147        build_ordering_env(&mut env).expect("build_ordering_env should succeed");
148        let decl = env
149            .get(&Name::str("Ordering.then"))
150            .expect("declaration 'Ordering.then' should exist in env");
151        assert!(matches!(decl, Declaration::Axiom { .. }));
152    }
153}
154/// Compare two `Ord` values and return an `Ordering`.
155pub fn cmp<T: std::cmp::Ord>(a: &T, b: &T) -> Ordering {
156    Ordering::from_std(a.cmp(b))
157}
158/// Compare using a key function.
159pub fn cmp_by_key<T, K: std::cmp::Ord, F: Fn(&T) -> K>(a: &T, b: &T, key: F) -> Ordering {
160    Ordering::from_std(key(a).cmp(&key(b)))
161}
162/// Compare two slices lexicographically.
163pub fn cmp_slices<T: std::cmp::Ord>(a: &[T], b: &[T]) -> Ordering {
164    Ordering::from_std(a.cmp(b))
165}
166/// Chain a sequence of `Ordering` values (first non-`Equal` wins).
167pub fn ordering_chain(items: impl IntoIterator<Item = Ordering>) -> Ordering {
168    for item in items {
169        if item != Ordering::Equal {
170            return item;
171        }
172    }
173    Ordering::Equal
174}
175/// Return a sorted copy of a slice.
176pub fn sorted<T: std::cmp::Ord + Clone>(v: &[T]) -> Vec<T> {
177    let mut result = v.to_vec();
178    result.sort();
179    result
180}
181/// Return a sorted copy using a key function.
182pub fn sorted_by_key<T: Clone, K: std::cmp::Ord, F: Fn(&T) -> K>(v: &[T], key: F) -> Vec<T> {
183    let mut result = v.to_vec();
184    result.sort_by_key(key);
185    result
186}
187/// Return a reverse-sorted copy of a slice.
188pub fn sorted_desc<T: std::cmp::Ord + Clone>(v: &[T]) -> Vec<T> {
189    let mut result = v.to_vec();
190    result.sort_by(|a, b| b.cmp(a));
191    result
192}
193/// Merge two sorted slices into a sorted `Vec`.
194pub fn merge_sorted<T: std::cmp::Ord + Clone>(a: &[T], b: &[T]) -> Vec<T> {
195    let mut result = Vec::with_capacity(a.len() + b.len());
196    let (mut i, mut j) = (0, 0);
197    while i < a.len() && j < b.len() {
198        if a[i] <= b[j] {
199            result.push(a[i].clone());
200            i += 1;
201        } else {
202            result.push(b[j].clone());
203            j += 1;
204        }
205    }
206    result.extend_from_slice(&a[i..]);
207    result.extend_from_slice(&b[j..]);
208    result
209}
210/// `true` if a slice is sorted in non-decreasing order.
211pub fn is_sorted<T: std::cmp::Ord>(s: &[T]) -> bool {
212    s.windows(2).all(|w| w[0] <= w[1])
213}
214/// `true` if a slice is sorted in non-increasing order.
215pub fn is_sorted_desc<T: std::cmp::Ord>(s: &[T]) -> bool {
216    s.windows(2).all(|w| w[0] >= w[1])
217}
218/// Find the lower bound index for `target` in a sorted slice.
219///
220/// Returns the index of the first element `β‰₯ target`.
221pub fn lower_bound<T: std::cmp::Ord>(s: &[T], target: &T) -> usize {
222    let mut lo = 0;
223    let mut hi = s.len();
224    while lo < hi {
225        let mid = lo + (hi - lo) / 2;
226        if s[mid] < *target {
227            lo = mid + 1;
228        } else {
229            hi = mid;
230        }
231    }
232    lo
233}
234/// Find the upper bound index for `target` in a sorted slice.
235///
236/// Returns the index of the first element `> target`.
237pub fn upper_bound<T: std::cmp::Ord>(s: &[T], target: &T) -> usize {
238    let mut lo = 0;
239    let mut hi = s.len();
240    while lo < hi {
241        let mid = lo + (hi - lo) / 2;
242        if s[mid] <= *target {
243            lo = mid + 1;
244        } else {
245            hi = mid;
246        }
247    }
248    lo
249}
250#[cfg(test)]
251mod ordering_extra_tests {
252    use super::*;
253    #[test]
254    fn test_ordering_reverse() {
255        assert_eq!(Ordering::Less.reverse(), Ordering::Greater);
256        assert_eq!(Ordering::Greater.reverse(), Ordering::Less);
257        assert_eq!(Ordering::Equal.reverse(), Ordering::Equal);
258    }
259    #[test]
260    fn test_ordering_then() {
261        assert_eq!(Ordering::Equal.then(Ordering::Less), Ordering::Less);
262        assert_eq!(Ordering::Less.then(Ordering::Greater), Ordering::Less);
263        assert_eq!(Ordering::Greater.then(Ordering::Less), Ordering::Greater);
264    }
265    #[test]
266    fn test_ordering_predicates() {
267        assert!(Ordering::Less.is_lt());
268        assert!(Ordering::Less.is_le());
269        assert!(!Ordering::Less.is_ge());
270        assert!(Ordering::Equal.is_eq());
271        assert!(Ordering::Equal.is_le());
272        assert!(Ordering::Equal.is_ge());
273        assert!(Ordering::Greater.is_gt());
274        assert!(Ordering::Greater.is_ge());
275        assert!(!Ordering::Greater.is_le());
276    }
277    #[test]
278    fn test_ordering_signum() {
279        assert_eq!(Ordering::Less.to_signum(), -1);
280        assert_eq!(Ordering::Equal.to_signum(), 0);
281        assert_eq!(Ordering::Greater.to_signum(), 1);
282        assert_eq!(Ordering::from_signum(-5), Ordering::Less);
283        assert_eq!(Ordering::from_signum(0), Ordering::Equal);
284        assert_eq!(Ordering::from_signum(3), Ordering::Greater);
285    }
286    #[test]
287    fn test_ordering_std_roundtrip() {
288        let o = Ordering::Less;
289        assert_eq!(Ordering::from_std(o.to_std()), o);
290    }
291    #[test]
292    fn test_ordering_display() {
293        assert_eq!(Ordering::Less.to_string(), "lt");
294        assert_eq!(Ordering::Equal.to_string(), "eq");
295        assert_eq!(Ordering::Greater.to_string(), "gt");
296    }
297    #[test]
298    fn test_cmp() {
299        assert_eq!(cmp(&1, &2), Ordering::Less);
300        assert_eq!(cmp(&2, &2), Ordering::Equal);
301        assert_eq!(cmp(&3, &2), Ordering::Greater);
302    }
303    #[test]
304    fn test_ordering_chain() {
305        let result = ordering_chain([Ordering::Equal, Ordering::Equal, Ordering::Less]);
306        assert_eq!(result, Ordering::Less);
307        let all_eq = ordering_chain([Ordering::Equal, Ordering::Equal]);
308        assert_eq!(all_eq, Ordering::Equal);
309    }
310    #[test]
311    fn test_ordering_builder() {
312        let result = OrderingBuilder::new()
313            .field(&1u32, &1u32)
314            .field(&2u32, &3u32)
315            .build();
316        assert_eq!(result, Ordering::Less);
317    }
318    #[test]
319    fn test_sorted() {
320        let v = vec![3, 1, 4, 1, 5, 9, 2, 6];
321        let s = sorted(&v);
322        assert!(is_sorted(&s));
323    }
324    #[test]
325    fn test_sorted_desc() {
326        let v = vec![3, 1, 4, 1, 5];
327        let s = sorted_desc(&v);
328        assert!(is_sorted_desc(&s));
329    }
330    #[test]
331    fn test_merge_sorted() {
332        let a = vec![1, 3, 5];
333        let b = vec![2, 4, 6];
334        let merged = merge_sorted(&a, &b);
335        assert_eq!(merged, vec![1, 2, 3, 4, 5, 6]);
336        assert!(is_sorted(&merged));
337    }
338    #[test]
339    fn test_lower_upper_bound() {
340        let v = vec![1, 2, 2, 3, 4, 5];
341        assert_eq!(lower_bound(&v, &2), 1);
342        assert_eq!(upper_bound(&v, &2), 3);
343        assert_eq!(lower_bound(&v, &6), 6);
344        assert_eq!(upper_bound(&v, &0), 0);
345    }
346    #[test]
347    fn test_is_sorted_is_sorted_desc() {
348        assert!(is_sorted(&[1, 2, 3, 3]));
349        assert!(!is_sorted(&[1, 3, 2]));
350        assert!(is_sorted_desc(&[5, 4, 3, 1]));
351        assert!(!is_sorted_desc(&[1, 2]));
352    }
353    #[test]
354    fn test_cmp_slices() {
355        assert_eq!(cmp_slices(&[1, 2, 3], &[1, 2, 4]), Ordering::Less);
356        assert_eq!(cmp_slices::<i32>(&[], &[]), Ordering::Equal);
357    }
358    #[test]
359    fn test_cmp_by_key() {
360        let a = ("hello", 10);
361        let b = ("world", 5);
362        assert_eq!(cmp_by_key(&a, &b, |x| x.1), Ordering::Greater);
363    }
364}
365/// Build a richer Ordering environment: add the `Ord` typeclass plus the
366/// `Ordering` comparators that depend on `Bool`.
367#[allow(dead_code)]
368pub fn build_full_ordering_env(env: &mut Environment) -> Result<(), String> {
369    build_ordering_env(env)?;
370    let decide_ty = Expr::Pi(
371        BinderInfo::Default,
372        Name::str("o1"),
373        Box::new(Expr::Const(Name::str("Ordering"), vec![])),
374        Box::new(Expr::Pi(
375            BinderInfo::Default,
376            Name::str("o2"),
377            Box::new(Expr::Const(Name::str("Ordering"), vec![])),
378            Box::new(Expr::Const(Name::str("Bool"), vec![])),
379        )),
380    );
381    env.add(Declaration::Axiom {
382        name: Name::str("Ordering.beq"),
383        univ_params: vec![],
384        ty: decide_ty,
385    })
386    .map_err(|e| e.to_string())?;
387    Ok(())
388}
389/// Compare two `&str` values using the `Ordering` type.
390#[allow(dead_code)]
391pub fn str_cmp(a: &str, b: &str) -> Ordering {
392    Ordering::from_std(a.cmp(b))
393}
394/// Compare two `bool` values (false < true).
395#[allow(dead_code)]
396pub fn bool_cmp(a: bool, b: bool) -> Ordering {
397    Ordering::from_std(a.cmp(&b))
398}
399/// Compare two `usize` values.
400#[allow(dead_code)]
401pub fn usize_cmp(a: usize, b: usize) -> Ordering {
402    Ordering::from_std(a.cmp(&b))
403}
404/// Compare two `i64` values.
405#[allow(dead_code)]
406pub fn i64_cmp(a: i64, b: i64) -> Ordering {
407    Ordering::from_std(a.cmp(&b))
408}
409/// Compare two `f64` values (NaN is treated as Equal to itself, Less than everything else).
410#[allow(dead_code)]
411pub fn f64_cmp(a: f64, b: f64) -> Ordering {
412    match a.partial_cmp(&b) {
413        Some(o) => Ordering::from_std(o),
414        None => Ordering::Equal,
415    }
416}
417/// `true` if `a < b` (using `Ordering`).
418#[allow(dead_code)]
419pub fn ordering_lt<T: std::cmp::Ord>(a: &T, b: &T) -> bool {
420    cmp(a, b).is_lt()
421}
422/// `true` if `a <= b`.
423#[allow(dead_code)]
424pub fn ordering_le<T: std::cmp::Ord>(a: &T, b: &T) -> bool {
425    cmp(a, b).is_le()
426}
427/// `true` if `a > b`.
428#[allow(dead_code)]
429pub fn ordering_gt<T: std::cmp::Ord>(a: &T, b: &T) -> bool {
430    cmp(a, b).is_gt()
431}
432/// `true` if `a >= b`.
433#[allow(dead_code)]
434pub fn ordering_ge<T: std::cmp::Ord>(a: &T, b: &T) -> bool {
435    cmp(a, b).is_ge()
436}
437/// Lexicographic order on `Option<T>`: `None < Some(x)` for all `x`.
438#[allow(dead_code)]
439pub fn option_cmp<T: std::cmp::Ord>(a: &Option<T>, b: &Option<T>) -> Ordering {
440    match (a, b) {
441        (None, None) => Ordering::Equal,
442        (None, Some(_)) => Ordering::Less,
443        (Some(_), None) => Ordering::Greater,
444        (Some(x), Some(y)) => cmp(x, y),
445    }
446}
447/// Lexicographic order on `Result<T, E>`: `Err < Ok` for distinct constructors.
448#[allow(dead_code)]
449pub fn result_cmp<T: std::cmp::Ord, E: std::cmp::Ord>(
450    a: &Result<T, E>,
451    b: &Result<T, E>,
452) -> Ordering {
453    match (a, b) {
454        (Err(e1), Err(e2)) => cmp(e1, e2),
455        (Err(_), Ok(_)) => Ordering::Less,
456        (Ok(_), Err(_)) => Ordering::Greater,
457        (Ok(x), Ok(y)) => cmp(x, y),
458    }
459}
460#[cfg(test)]
461mod ordering_extra_tests2 {
462    use super::*;
463    #[test]
464    fn test_build_full_ordering_env() {
465        let mut env = Environment::new();
466        env.add(Declaration::Axiom {
467            name: Name::str("Bool"),
468            univ_params: vec![],
469            ty: Expr::Sort(Level::succ(Level::zero())),
470        })
471        .expect("operation should succeed");
472        assert!(build_full_ordering_env(&mut env).is_ok());
473        assert!(env.get(&Name::str("Ordering.beq")).is_some());
474    }
475    #[test]
476    fn test_str_cmp() {
477        assert_eq!(str_cmp("abc", "abd"), Ordering::Less);
478        assert_eq!(str_cmp("z", "a"), Ordering::Greater);
479        assert_eq!(str_cmp("x", "x"), Ordering::Equal);
480    }
481    #[test]
482    fn test_bool_cmp() {
483        assert_eq!(bool_cmp(false, true), Ordering::Less);
484        assert_eq!(bool_cmp(true, false), Ordering::Greater);
485        assert_eq!(bool_cmp(true, true), Ordering::Equal);
486    }
487    #[test]
488    fn test_numeric_cmp() {
489        assert_eq!(usize_cmp(3, 5), Ordering::Less);
490        assert_eq!(i64_cmp(-1, 1), Ordering::Less);
491        assert_eq!(f64_cmp(1.5, 1.5), Ordering::Equal);
492        assert_eq!(f64_cmp(2.0, 1.0), Ordering::Greater);
493    }
494    #[test]
495    fn test_ordering_predicates_via_cmp() {
496        assert!(ordering_lt(&1, &2));
497        assert!(ordering_le(&2, &2));
498        assert!(ordering_gt(&5, &3));
499        assert!(ordering_ge(&3, &3));
500    }
501    #[test]
502    fn test_option_cmp() {
503        let a: Option<u32> = None;
504        let b = Some(5u32);
505        assert_eq!(option_cmp(&a, &b), Ordering::Less);
506        assert_eq!(option_cmp(&b, &a), Ordering::Greater);
507        assert_eq!(option_cmp(&a, &a), Ordering::Equal);
508        assert_eq!(option_cmp(&Some(3u32), &Some(5u32)), Ordering::Less);
509    }
510    #[test]
511    fn test_result_cmp() {
512        let ok1: Result<u32, u32> = Ok(1);
513        let ok2: Result<u32, u32> = Ok(2);
514        let err1: Result<u32, u32> = Err(1);
515        assert_eq!(result_cmp(&err1, &ok1), Ordering::Less);
516        assert_eq!(result_cmp(&ok1, &ok2), Ordering::Less);
517    }
518    #[test]
519    fn test_ordering_then_with() {
520        let result = Ordering::Equal.then_with(|| Ordering::Greater);
521        assert_eq!(result, Ordering::Greater);
522        let result2 = Ordering::Less.then_with(|| Ordering::Greater);
523        assert_eq!(result2, Ordering::Less);
524    }
525    #[test]
526    fn test_ordering_builder_chained() {
527        let result = OrderingBuilder::new()
528            .field(&1u32, &1u32)
529            .field(&1u32, &1u32)
530            .field(&5u32, &10u32)
531            .build();
532        assert_eq!(result, Ordering::Less);
533    }
534    #[test]
535    fn test_sorted_by_key() {
536        let v = vec!["banana", "apple", "cherry"];
537        let sorted = sorted_by_key(&v, |s| s.len());
538        assert_eq!(sorted[0], "apple");
539    }
540}
541/// Return the maximum of two values according to `Ordering`.
542#[allow(dead_code)]
543pub fn ordering_max<T: std::cmp::Ord + Clone>(a: T, b: T) -> T {
544    if cmp(&a, &b).is_ge() {
545        a
546    } else {
547        b
548    }
549}
550/// Return the minimum of two values according to `Ordering`.
551#[allow(dead_code)]
552pub fn ordering_min<T: std::cmp::Ord + Clone>(a: T, b: T) -> T {
553    if cmp(&a, &b).is_le() {
554        a
555    } else {
556        b
557    }
558}
559#[cfg(test)]
560mod ordering_min_max_tests {
561    use super::*;
562    #[test]
563    fn test_ordering_max() {
564        assert_eq!(ordering_max(3u32, 5u32), 5);
565    }
566    #[test]
567    fn test_ordering_min() {
568        assert_eq!(ordering_min(3u32, 5u32), 3);
569    }
570}
571/// Select the k-th smallest element from a slice (0-indexed).
572///
573/// Returns `None` if `k >= v.len()`.
574#[allow(dead_code)]
575pub fn kth_smallest<T: std::cmp::Ord + Clone>(v: &[T], k: usize) -> Option<T> {
576    if k >= v.len() {
577        return None;
578    }
579    let mut sorted = v.to_vec();
580    sorted.sort();
581    Some(sorted[k].clone())
582}
583/// Select the k-th largest element from a slice (0-indexed).
584#[allow(dead_code)]
585pub fn kth_largest<T: std::cmp::Ord + Clone>(v: &[T], k: usize) -> Option<T> {
586    if k >= v.len() {
587        return None;
588    }
589    let mut sorted = v.to_vec();
590    sorted.sort_by(|a, b| b.cmp(a));
591    Some(sorted[k].clone())
592}
593/// Return the top-n largest elements of a slice, in decreasing order.
594#[allow(dead_code)]
595pub fn top_n<T: std::cmp::Ord + Clone>(v: &[T], n: usize) -> Vec<T> {
596    let mut sorted = sorted_desc(v);
597    sorted.truncate(n);
598    sorted
599}
600/// Return the bottom-n smallest elements of a slice, in increasing order.
601#[allow(dead_code)]
602pub fn bottom_n<T: std::cmp::Ord + Clone>(v: &[T], n: usize) -> Vec<T> {
603    let mut s = sorted(v);
604    s.truncate(n);
605    s
606}
607/// Compute the sorted intersection of two sorted slices.
608#[allow(dead_code)]
609pub fn sorted_intersection<T: std::cmp::Ord + Clone>(a: &[T], b: &[T]) -> Vec<T> {
610    let mut result = Vec::new();
611    let (mut i, mut j) = (0, 0);
612    while i < a.len() && j < b.len() {
613        match a[i].cmp(&b[j]) {
614            std::cmp::Ordering::Equal => {
615                result.push(a[i].clone());
616                i += 1;
617                j += 1;
618            }
619            std::cmp::Ordering::Less => i += 1,
620            std::cmp::Ordering::Greater => j += 1,
621        }
622    }
623    result
624}
625/// Compute the sorted difference (a minus b) of two sorted slices.
626#[allow(dead_code)]
627pub fn sorted_difference<T: std::cmp::Ord + Clone>(a: &[T], b: &[T]) -> Vec<T> {
628    let mut result = Vec::new();
629    let (mut i, mut j) = (0, 0);
630    while i < a.len() {
631        if j >= b.len() {
632            result.push(a[i].clone());
633            i += 1;
634        } else {
635            match a[i].cmp(&b[j]) {
636                std::cmp::Ordering::Equal => {
637                    i += 1;
638                    j += 1;
639                }
640                std::cmp::Ordering::Less => {
641                    result.push(a[i].clone());
642                    i += 1;
643                }
644                std::cmp::Ordering::Greater => j += 1,
645            }
646        }
647    }
648    result
649}
650/// Compute the sorted union of two sorted slices (no duplicates).
651#[allow(dead_code)]
652pub fn sorted_union<T: std::cmp::Ord + Clone>(a: &[T], b: &[T]) -> Vec<T> {
653    let mut merged = merge_sorted(a, b);
654    merged.dedup();
655    merged
656}
657#[cfg(test)]
658mod ordered_table_tests {
659    use super::*;
660    #[test]
661    fn test_ordered_table_insert_get() {
662        let mut t = OrderedTable::new();
663        t.insert("b", 2u32);
664        t.insert("a", 1u32);
665        t.insert("c", 3u32);
666        assert_eq!(t.get(&"a"), Some(&1));
667        assert_eq!(t.get(&"c"), Some(&3));
668        assert_eq!(t.get(&"d"), None);
669        assert_eq!(t.len(), 3);
670    }
671    #[test]
672    fn test_ordered_table_remove() {
673        let mut t = OrderedTable::new();
674        t.insert(1u32, "one");
675        t.insert(2u32, "two");
676        assert_eq!(t.remove(&1), Some("one"));
677        assert_eq!(t.len(), 1);
678        assert_eq!(t.remove(&99), None);
679    }
680    #[test]
681    fn test_ordered_table_keys_sorted() {
682        let mut t = OrderedTable::new();
683        t.insert(3u32, ());
684        t.insert(1u32, ());
685        t.insert(2u32, ());
686        let keys: Vec<_> = t.keys().into_iter().copied().collect();
687        assert_eq!(keys, vec![1, 2, 3]);
688    }
689    #[test]
690    fn test_kth_smallest() {
691        let v = vec![5, 3, 1, 4, 2];
692        assert_eq!(kth_smallest(&v, 0), Some(1));
693        assert_eq!(kth_smallest(&v, 2), Some(3));
694        assert_eq!(kth_smallest(&v, 10), None);
695    }
696    #[test]
697    fn test_kth_largest() {
698        let v = vec![5, 3, 1, 4, 2];
699        assert_eq!(kth_largest(&v, 0), Some(5));
700        assert_eq!(kth_largest(&v, 2), Some(3));
701    }
702    #[test]
703    fn test_top_n() {
704        let v = vec![3, 1, 4, 1, 5, 9, 2, 6];
705        assert_eq!(top_n(&v, 3), vec![9, 6, 5]);
706    }
707    #[test]
708    fn test_bottom_n() {
709        let v = vec![3, 1, 4, 1, 5, 9, 2, 6];
710        assert_eq!(bottom_n(&v, 3), vec![1, 1, 2]);
711    }
712    #[test]
713    fn test_sorted_intersection() {
714        let a = vec![1, 2, 3, 4, 5];
715        let b = vec![2, 4, 6];
716        assert_eq!(sorted_intersection(&a, &b), vec![2, 4]);
717    }
718    #[test]
719    fn test_sorted_difference() {
720        let a = vec![1, 2, 3, 4, 5];
721        let b = vec![2, 4];
722        assert_eq!(sorted_difference(&a, &b), vec![1, 3, 5]);
723    }
724    #[test]
725    fn test_sorted_union() {
726        let a = vec![1, 2, 3];
727        let b = vec![2, 3, 4];
728        assert_eq!(sorted_union(&a, &b), vec![1, 2, 3, 4]);
729    }
730    #[test]
731    fn test_ordered_table_contains_key() {
732        let mut t: OrderedTable<u32, &str> = OrderedTable::new();
733        t.insert(1, "one");
734        assert!(t.contains_key(&1));
735        assert!(!t.contains_key(&2));
736    }
737    #[test]
738    fn test_ordered_table_is_empty() {
739        let t: OrderedTable<u32, u32> = OrderedTable::new();
740        assert!(t.is_empty());
741    }
742    #[test]
743    fn test_ordered_table_values() {
744        let mut t = OrderedTable::new();
745        t.insert(1u32, "a");
746        t.insert(2u32, "b");
747        let vals = t.values();
748        assert_eq!(vals, vec![&"a", &"b"]);
749    }
750}
751/// Helper: build `Ξ± β†’ Ξ²` as a Pi with anonymous binder.
752pub fn ord_ext_arrow(a: Expr, b: Expr) -> Expr {
753    Expr::Pi(
754        BinderInfo::Default,
755        Name::Anonymous,
756        Box::new(a),
757        Box::new(b),
758    )
759}
760/// Type of `WQO.carrier`: the carrier type of a well-quasi-order.
761/// `WQO.carrier : WQO β†’ Type`
762#[allow(dead_code)]
763pub fn axiom_wqo_carrier_ty() -> Expr {
764    ord_ext_arrow(
765        Expr::Const(Name::str("WQO"), vec![]),
766        Expr::Sort(Level::succ(Level::zero())),
767    )
768}
769/// Type of `WQO.le`: the quasi-order relation.
770/// `WQO.le : (w : WQO) β†’ WQO.carrier w β†’ WQO.carrier w β†’ Prop`
771#[allow(dead_code)]
772pub fn axiom_wqo_le_ty() -> Expr {
773    let wqo = Expr::Const(Name::str("WQO"), vec![]);
774    let carrier_w = Expr::App(
775        Box::new(Expr::Const(Name::str("WQO.carrier"), vec![])),
776        Box::new(Expr::BVar(0)),
777    );
778    Expr::Pi(
779        BinderInfo::Default,
780        Name::str("w"),
781        Box::new(wqo),
782        Box::new(Expr::Pi(
783            BinderInfo::Default,
784            Name::str("a"),
785            Box::new(carrier_w.clone()),
786            Box::new(Expr::Pi(
787                BinderInfo::Default,
788                Name::str("b"),
789                Box::new(carrier_w),
790                Box::new(Expr::Sort(Level::zero())),
791            )),
792        )),
793    )
794}
795/// Type of `WQO.wf`: every infinite sequence has a good pair.
796/// `WQO.wf : (w : WQO) β†’ βˆ€ (f : Nat β†’ WQO.carrier w), βˆƒ i j, i < j ∧ WQO.le w (f i) (f j)`
797#[allow(dead_code)]
798pub fn axiom_wqo_wf_ty() -> Expr {
799    ord_ext_arrow(
800        Expr::Const(Name::str("WQO"), vec![]),
801        Expr::Const(Name::str("WQO.goodPair"), vec![]),
802    )
803}
804/// Type of `Dickson.lemma`: the product of WQOs is a WQO.
805/// `Dickson.lemma : WQO β†’ WQO β†’ WQO`
806#[allow(dead_code)]
807pub fn axiom_dickson_lemma_ty() -> Expr {
808    ord_ext_arrow(
809        Expr::Const(Name::str("WQO"), vec![]),
810        ord_ext_arrow(
811            Expr::Const(Name::str("WQO"), vec![]),
812            Expr::Const(Name::str("WQO"), vec![]),
813        ),
814    )
815}
816/// Type of `Dickson.nat_wqo`: (Nat, ≀) is a WQO.
817/// `Dickson.nat_wqo : WQO`
818#[allow(dead_code)]
819pub fn axiom_dickson_nat_wqo_ty() -> Expr {
820    Expr::Const(Name::str("WQO"), vec![])
821}
822/// Type of `Higman.lemma`: finite words over a WQO form a WQO under embedding.
823/// `Higman.lemma : WQO β†’ WQO`
824#[allow(dead_code)]
825pub fn axiom_higman_lemma_ty() -> Expr {
826    ord_ext_arrow(
827        Expr::Const(Name::str("WQO"), vec![]),
828        Expr::Const(Name::str("WQO"), vec![]),
829    )
830}
831/// Type of `Kruskal.treeThm`: finite rooted trees over a WQO form a WQO under topological embedding.
832/// `Kruskal.treeThm : WQO β†’ WQO`
833#[allow(dead_code)]
834pub fn axiom_kruskal_tree_thm_ty() -> Expr {
835    ord_ext_arrow(
836        Expr::Const(Name::str("WQO"), vec![]),
837        Expr::Const(Name::str("WQO"), vec![]),
838    )
839}
840/// Type of `Ordinal`: the type of ordinals.
841/// `Ordinal : Type 1`
842#[allow(dead_code)]
843pub fn axiom_ordinal_type_ty() -> Expr {
844    Expr::Sort(Level::succ(Level::succ(Level::zero())))
845}
846/// Type of `Ordinal.zero`: the ordinal zero.
847/// `Ordinal.zero : Ordinal`
848#[allow(dead_code)]
849pub fn axiom_ordinal_zero_ty() -> Expr {
850    Expr::Const(Name::str("Ordinal"), vec![])
851}
852/// Type of `Ordinal.succ`: successor ordinal.
853/// `Ordinal.succ : Ordinal β†’ Ordinal`
854#[allow(dead_code)]
855pub fn axiom_ordinal_succ_ty() -> Expr {
856    ord_ext_arrow(
857        Expr::Const(Name::str("Ordinal"), vec![]),
858        Expr::Const(Name::str("Ordinal"), vec![]),
859    )
860}
861/// Type of `Ordinal.add`: ordinal addition.
862/// `Ordinal.add : Ordinal β†’ Ordinal β†’ Ordinal`
863#[allow(dead_code)]
864pub fn axiom_ordinal_add_ty() -> Expr {
865    ord_ext_arrow(
866        Expr::Const(Name::str("Ordinal"), vec![]),
867        ord_ext_arrow(
868            Expr::Const(Name::str("Ordinal"), vec![]),
869            Expr::Const(Name::str("Ordinal"), vec![]),
870        ),
871    )
872}
873/// Type of `Ordinal.mul`: ordinal multiplication.
874/// `Ordinal.mul : Ordinal β†’ Ordinal β†’ Ordinal`
875#[allow(dead_code)]
876pub fn axiom_ordinal_mul_ty() -> Expr {
877    ord_ext_arrow(
878        Expr::Const(Name::str("Ordinal"), vec![]),
879        ord_ext_arrow(
880            Expr::Const(Name::str("Ordinal"), vec![]),
881            Expr::Const(Name::str("Ordinal"), vec![]),
882        ),
883    )
884}
885/// Type of `Ordinal.pow`: ordinal exponentiation.
886/// `Ordinal.pow : Ordinal β†’ Ordinal β†’ Ordinal`
887#[allow(dead_code)]
888pub fn axiom_ordinal_pow_ty() -> Expr {
889    ord_ext_arrow(
890        Expr::Const(Name::str("Ordinal"), vec![]),
891        ord_ext_arrow(
892            Expr::Const(Name::str("Ordinal"), vec![]),
893            Expr::Const(Name::str("Ordinal"), vec![]),
894        ),
895    )
896}
897/// Type of `Ordinal.omega`: the first infinite ordinal Ο‰.
898/// `Ordinal.omega : Ordinal`
899#[allow(dead_code)]
900pub fn axiom_ordinal_omega_ty() -> Expr {
901    Expr::Const(Name::str("Ordinal"), vec![])
902}
903/// Type of `Ordinal.epsilon0`: the ordinal Ξ΅β‚€ = sup{Ο‰, Ο‰^Ο‰, Ο‰^(Ο‰^Ο‰), ...}.
904/// `Ordinal.epsilon0 : Ordinal`
905#[allow(dead_code)]
906pub fn axiom_ordinal_epsilon0_ty() -> Expr {
907    Expr::Const(Name::str("Ordinal"), vec![])
908}
909/// Type of `Ordinal.churchKleene`: the Church-Kleene ordinal ω₁^CK.
910/// `Ordinal.churchKleene : Ordinal`
911#[allow(dead_code)]
912pub fn axiom_ordinal_church_kleene_ty() -> Expr {
913    Expr::Const(Name::str("Ordinal"), vec![])
914}
915/// Type of `Ordinal.lt`: strict ordering on ordinals.
916/// `Ordinal.lt : Ordinal β†’ Ordinal β†’ Prop`
917#[allow(dead_code)]
918pub fn axiom_ordinal_lt_ty() -> Expr {
919    ord_ext_arrow(
920        Expr::Const(Name::str("Ordinal"), vec![]),
921        ord_ext_arrow(
922            Expr::Const(Name::str("Ordinal"), vec![]),
923            Expr::Sort(Level::zero()),
924        ),
925    )
926}
927/// Type of `Ordinal.le`: weak ordering on ordinals.
928/// `Ordinal.le : Ordinal β†’ Ordinal β†’ Prop`
929#[allow(dead_code)]
930pub fn axiom_ordinal_le_ty() -> Expr {
931    ord_ext_arrow(
932        Expr::Const(Name::str("Ordinal"), vec![]),
933        ord_ext_arrow(
934            Expr::Const(Name::str("Ordinal"), vec![]),
935            Expr::Sort(Level::zero()),
936        ),
937    )
938}
939/// Type of `Ordinal.isLimit`: predicate for limit ordinals.
940/// `Ordinal.isLimit : Ordinal β†’ Prop`
941#[allow(dead_code)]
942pub fn axiom_ordinal_is_limit_ty() -> Expr {
943    ord_ext_arrow(
944        Expr::Const(Name::str("Ordinal"), vec![]),
945        Expr::Sort(Level::zero()),
946    )
947}
948/// Type of `Ordinal.comparability`: any two ordinals are comparable.
949/// `Ordinal.comparability : βˆ€ Ξ± Ξ² : Ordinal, Ξ± < Ξ² ∨ Ξ± = Ξ² ∨ Ξ² < Ξ±`
950#[allow(dead_code)]
951pub fn axiom_ordinal_comparability_ty() -> Expr {
952    let ord = Expr::Const(Name::str("Ordinal"), vec![]);
953    Expr::Pi(
954        BinderInfo::Default,
955        Name::str("alpha"),
956        Box::new(ord.clone()),
957        Box::new(Expr::Pi(
958            BinderInfo::Default,
959            Name::str("beta"),
960            Box::new(ord),
961            Box::new(Expr::Const(Name::str("Ordinal.trichotomy"), vec![])),
962        )),
963    )
964}
965/// Type of `Suslin.problem`: is every dense linear order without endpoints
966/// satisfying the countable chain condition isomorphic to the reals?
967/// `Suslin.problem : Prop`
968#[allow(dead_code)]
969pub fn axiom_suslin_problem_ty() -> Expr {
970    Expr::Sort(Level::zero())
971}
972/// Type of `LinearOrder`: a type equipped with a total order.
973/// `LinearOrder : Type β†’ Type 1`
974#[allow(dead_code)]
975pub fn axiom_linear_order_ty() -> Expr {
976    ord_ext_arrow(
977        Expr::Sort(Level::succ(Level::zero())),
978        Expr::Sort(Level::succ(Level::succ(Level::zero()))),
979    )
980}
981/// Type of `DenseLinearOrder`: a dense linear order without endpoints.
982/// `DenseLinearOrder : Type β†’ Prop`
983#[allow(dead_code)]
984pub fn axiom_dense_linear_order_ty() -> Expr {
985    ord_ext_arrow(
986        Expr::Sort(Level::succ(Level::zero())),
987        Expr::Sort(Level::zero()),
988    )
989}
990/// Type of `Hausdorff.scatteredOrder`: a scattered linear order embeds no dense suborder.
991/// `Hausdorff.scatteredOrder : Type β†’ Prop`
992#[allow(dead_code)]
993pub fn axiom_hausdorff_scattered_ty() -> Expr {
994    ord_ext_arrow(
995        Expr::Sort(Level::succ(Level::zero())),
996        Expr::Sort(Level::zero()),
997    )
998}
999/// Type of `Hausdorff.theorem`: every linear order decomposes into a scattered and a dense part.
1000/// `Hausdorff.theorem : LinearOrder β†’ Prop`
1001#[allow(dead_code)]
1002pub fn axiom_hausdorff_theorem_ty() -> Expr {
1003    ord_ext_arrow(
1004        Expr::Const(Name::str("LinearOrder"), vec![]),
1005        Expr::Sort(Level::zero()),
1006    )
1007}
1008/// Type of `Ramsey.orderThm`: infinite Ramsey theorem for order relations.
1009/// `Ramsey.orderThm : Nat β†’ Nat β†’ Prop`
1010#[allow(dead_code)]
1011pub fn axiom_ramsey_order_thm_ty() -> Expr {
1012    ord_ext_arrow(
1013        Expr::Const(Name::str("Nat"), vec![]),
1014        ord_ext_arrow(
1015            Expr::Const(Name::str("Nat"), vec![]),
1016            Expr::Sort(Level::zero()),
1017        ),
1018    )
1019}
1020/// Type of `Rationals.universalLinearOrder`: the rationals form a universal homogeneous
1021/// countable dense linear order without endpoints.
1022/// `Rationals.universalLinearOrder : Prop`
1023#[allow(dead_code)]
1024pub fn axiom_rationals_universal_linear_order_ty() -> Expr {
1025    Expr::Sort(Level::zero())
1026}
1027/// Type of `DedekindCut`: a Dedekind cut in an ordered field.
1028/// `DedekindCut : Type β†’ Type`
1029#[allow(dead_code)]
1030pub fn axiom_dedekind_cut_ty() -> Expr {
1031    ord_ext_arrow(
1032        Expr::Sort(Level::succ(Level::zero())),
1033        Expr::Sort(Level::succ(Level::zero())),
1034    )
1035}
1036/// Type of `DedekindCut.completeness`: every Dedekind cut has a supremum.
1037/// `DedekindCut.completeness : βˆ€ F : Type, DedekindCut F β†’ F`
1038#[allow(dead_code)]
1039pub fn axiom_dedekind_completeness_ty() -> Expr {
1040    Expr::Pi(
1041        BinderInfo::Default,
1042        Name::str("F"),
1043        Box::new(Expr::Sort(Level::succ(Level::zero()))),
1044        Box::new(ord_ext_arrow(
1045            Expr::App(
1046                Box::new(Expr::Const(Name::str("DedekindCut"), vec![])),
1047                Box::new(Expr::BVar(0)),
1048            ),
1049            Expr::BVar(1),
1050        )),
1051    )
1052}
1053/// Type of `Cantor.backAndForth`: any two countable dense linear orders
1054/// without endpoints are isomorphic.
1055/// `Cantor.backAndForth : Prop`
1056#[allow(dead_code)]
1057pub fn axiom_cantor_back_and_forth_ty() -> Expr {
1058    Expr::Sort(Level::zero())
1059}
1060/// Type of `Fraisse.limit`: the FraΓ―ssΓ© limit of a class of finite structures.
1061/// `Fraisse.limit : StructureClass β†’ Structure`
1062#[allow(dead_code)]
1063pub fn axiom_fraisse_limit_ty() -> Expr {
1064    ord_ext_arrow(
1065        Expr::Const(Name::str("StructureClass"), vec![]),
1066        Expr::Const(Name::str("Structure"), vec![]),
1067    )
1068}
1069/// Type of `OrderedField`: a field with a compatible total order.
1070/// `OrderedField : Type β†’ Prop`
1071#[allow(dead_code)]
1072pub fn axiom_ordered_field_ty() -> Expr {
1073    ord_ext_arrow(
1074        Expr::Sort(Level::succ(Level::zero())),
1075        Expr::Sort(Level::zero()),
1076    )
1077}
1078/// Type of `OrderedField.archimedean`: an ordered field is Archimedean
1079/// if for every x > 0, there exists n : Nat with n > x.
1080/// `OrderedField.archimedean : βˆ€ F, OrderedField F β†’ Prop`
1081#[allow(dead_code)]
1082pub fn axiom_ordered_field_archimedean_ty() -> Expr {
1083    Expr::Pi(
1084        BinderInfo::Default,
1085        Name::str("F"),
1086        Box::new(Expr::Sort(Level::succ(Level::zero()))),
1087        Box::new(ord_ext_arrow(
1088            Expr::App(
1089                Box::new(Expr::Const(Name::str("OrderedField"), vec![])),
1090                Box::new(Expr::BVar(0)),
1091            ),
1092            Expr::Sort(Level::zero()),
1093        )),
1094    )
1095}
1096/// Type of `WellOrder.induction`: transfinite induction for well-orders.
1097/// `WellOrder.induction : βˆ€ Ξ±, WellOrder Ξ± β†’ (βˆ€ x, (βˆ€ y, y < x β†’ P y) β†’ P x) β†’ βˆ€ x, P x`
1098#[allow(dead_code)]
1099pub fn axiom_well_order_induction_ty() -> Expr {
1100    ord_ext_arrow(
1101        Expr::Const(Name::str("WellOrder"), vec![]),
1102        Expr::Const(Name::str("WellOrder.inductionPrinciple"), vec![]),
1103    )
1104}
1105/// Type of `WellOrder.isomorphism`: any two well-orders of the same ordinal are isomorphic.
1106/// `WellOrder.isomorphism : WellOrder β†’ WellOrder β†’ Prop`
1107#[allow(dead_code)]
1108pub fn axiom_well_order_isomorphism_ty() -> Expr {
1109    ord_ext_arrow(
1110        Expr::Const(Name::str("WellOrder"), vec![]),
1111        ord_ext_arrow(
1112            Expr::Const(Name::str("WellOrder"), vec![]),
1113            Expr::Sort(Level::zero()),
1114        ),
1115    )
1116}
1117/// Type of `Ordinal.sup`: supremum of a set of ordinals.
1118/// `Ordinal.sup : (Nat β†’ Ordinal) β†’ Ordinal`
1119#[allow(dead_code)]
1120pub fn axiom_ordinal_sup_ty() -> Expr {
1121    ord_ext_arrow(
1122        ord_ext_arrow(
1123            Expr::Const(Name::str("Nat"), vec![]),
1124            Expr::Const(Name::str("Ordinal"), vec![]),
1125        ),
1126        Expr::Const(Name::str("Ordinal"), vec![]),
1127    )
1128}
1129/// Type of `Ordinal.cnfNF`: Cantor Normal Form of an ordinal.
1130/// `Ordinal.cnfNF : Ordinal β†’ List (Ordinal Γ— Nat)`
1131#[allow(dead_code)]
1132pub fn axiom_ordinal_cnf_ty() -> Expr {
1133    ord_ext_arrow(
1134        Expr::Const(Name::str("Ordinal"), vec![]),
1135        Expr::App(
1136            Box::new(Expr::Const(Name::str("List"), vec![])),
1137            Box::new(Expr::App(
1138                Box::new(Expr::App(
1139                    Box::new(Expr::Const(Name::str("Prod"), vec![])),
1140                    Box::new(Expr::Const(Name::str("Ordinal"), vec![])),
1141                )),
1142                Box::new(Expr::Const(Name::str("Nat"), vec![])),
1143            )),
1144        ),
1145    )
1146}
1147/// Type of `PartialOrder.antisymmetry`: a partial order is antisymmetric.
1148/// `PartialOrder.antisymmetry : βˆ€ {Ξ±} [PartialOrder Ξ±] (a b : Ξ±), a ≀ b β†’ b ≀ a β†’ a = b`
1149#[allow(dead_code)]
1150pub fn axiom_partial_order_antisymmetry_ty() -> Expr {
1151    Expr::Pi(
1152        BinderInfo::Implicit,
1153        Name::str("alpha"),
1154        Box::new(Expr::Sort(Level::succ(Level::zero()))),
1155        Box::new(Expr::Const(
1156            Name::str("PartialOrder.antisymmetryStatement"),
1157            vec![],
1158        )),
1159    )
1160}
1161/// Type of `TotalOrder.linearExtension`: every partial order extends to a total order.
1162/// `TotalOrder.linearExtension : PartialOrder β†’ TotalOrder`
1163#[allow(dead_code)]
1164pub fn axiom_total_order_linear_extension_ty() -> Expr {
1165    ord_ext_arrow(
1166        Expr::Const(Name::str("PartialOrder"), vec![]),
1167        Expr::Const(Name::str("TotalOrder"), vec![]),
1168    )
1169}
1170/// Register all extended ordering/ordinal axioms in the environment.
1171#[allow(dead_code)]
1172pub fn register_ordering_extended(env: &mut Environment) -> Result<(), String> {
1173    let type2 = Expr::Sort(Level::succ(Level::succ(Level::zero())));
1174    let type1 = Expr::Sort(Level::succ(Level::zero()));
1175    let prop = Expr::Sort(Level::zero());
1176    let prereqs: &[(&str, Expr)] = &[
1177        ("WQO", type1.clone()),
1178        ("Ordinal", type1.clone()),
1179        ("LinearOrder", type2.clone()),
1180        ("PartialOrder", type1.clone()),
1181        ("TotalOrder", type1.clone()),
1182        ("WellOrder", type1.clone()),
1183        ("StructureClass", type1.clone()),
1184        ("Structure", type1.clone()),
1185        ("Nat", type1.clone()),
1186        ("List", ord_ext_arrow(type1.clone(), type1.clone())),
1187        (
1188            "Prod",
1189            ord_ext_arrow(type1.clone(), ord_ext_arrow(type1.clone(), type1.clone())),
1190        ),
1191        ("WQO.goodPair", prop.clone()),
1192        ("Ordinal.trichotomy", prop.clone()),
1193        ("WellOrder.inductionPrinciple", prop.clone()),
1194        ("PartialOrder.antisymmetryStatement", prop.clone()),
1195        (
1196            "WQO.carrier",
1197            ord_ext_arrow(Expr::Const(Name::str("WQO"), vec![]), type1.clone()),
1198        ),
1199    ];
1200    for (name, ty) in prereqs {
1201        if !env.contains(&Name::str(*name)) {
1202            env.add(Declaration::Axiom {
1203                name: Name::str(*name),
1204                univ_params: vec![],
1205                ty: ty.clone(),
1206            })
1207            .map_err(|e| e.to_string())?;
1208        }
1209    }
1210    let axioms: &[(&str, Expr)] = &[
1211        ("WQO.le", axiom_wqo_le_ty()),
1212        ("WQO.wf", axiom_wqo_wf_ty()),
1213        ("Dickson.lemma", axiom_dickson_lemma_ty()),
1214        ("Dickson.nat_wqo", axiom_dickson_nat_wqo_ty()),
1215        ("Higman.lemma", axiom_higman_lemma_ty()),
1216        ("Kruskal.treeThm", axiom_kruskal_tree_thm_ty()),
1217        ("Ordinal.zero", axiom_ordinal_zero_ty()),
1218        ("Ordinal.succ", axiom_ordinal_succ_ty()),
1219        ("Ordinal.add", axiom_ordinal_add_ty()),
1220        ("Ordinal.mul", axiom_ordinal_mul_ty()),
1221        ("Ordinal.pow", axiom_ordinal_pow_ty()),
1222        ("Ordinal.omega", axiom_ordinal_omega_ty()),
1223        ("Ordinal.epsilon0", axiom_ordinal_epsilon0_ty()),
1224        ("Ordinal.churchKleene", axiom_ordinal_church_kleene_ty()),
1225        ("Ordinal.lt", axiom_ordinal_lt_ty()),
1226        ("Ordinal.le", axiom_ordinal_le_ty()),
1227        ("Ordinal.isLimit", axiom_ordinal_is_limit_ty()),
1228        ("Ordinal.comparability", axiom_ordinal_comparability_ty()),
1229        ("Suslin.problem", axiom_suslin_problem_ty()),
1230        ("DenseLinearOrder", axiom_dense_linear_order_ty()),
1231        ("Hausdorff.scatteredOrder", axiom_hausdorff_scattered_ty()),
1232        ("Hausdorff.theorem", axiom_hausdorff_theorem_ty()),
1233        ("Ramsey.orderThm", axiom_ramsey_order_thm_ty()),
1234        (
1235            "Rationals.universalLinearOrder",
1236            axiom_rationals_universal_linear_order_ty(),
1237        ),
1238        ("DedekindCut", axiom_dedekind_cut_ty()),
1239        ("DedekindCut.completeness", axiom_dedekind_completeness_ty()),
1240        ("Cantor.backAndForth", axiom_cantor_back_and_forth_ty()),
1241        ("Fraisse.limit", axiom_fraisse_limit_ty()),
1242        ("OrderedField", axiom_ordered_field_ty()),
1243        (
1244            "OrderedField.archimedean",
1245            axiom_ordered_field_archimedean_ty(),
1246        ),
1247        ("WellOrder.induction", axiom_well_order_induction_ty()),
1248        ("WellOrder.isomorphism", axiom_well_order_isomorphism_ty()),
1249        ("Ordinal.sup", axiom_ordinal_sup_ty()),
1250        ("Ordinal.cnfNF", axiom_ordinal_cnf_ty()),
1251        (
1252            "PartialOrder.antisymmetry",
1253            axiom_partial_order_antisymmetry_ty(),
1254        ),
1255        (
1256            "TotalOrder.linearExtension",
1257            axiom_total_order_linear_extension_ty(),
1258        ),
1259    ];
1260    for (name, ty) in axioms {
1261        env.add(Declaration::Axiom {
1262            name: Name::str(*name),
1263            univ_params: vec![],
1264            ty: ty.clone(),
1265        })
1266        .map_err(|e| e.to_string())?;
1267    }
1268    Ok(())
1269}
1270#[cfg(test)]
1271mod extended_ordering_tests {
1272    use super::*;
1273    #[test]
1274    fn test_wqo_instance_reflexive() {
1275        let w = WqoInstance::new(vec![0, 1, 2], |a, b| a <= b);
1276        assert!(w.is_reflexive());
1277    }
1278    #[test]
1279    fn test_wqo_instance_transitive() {
1280        let w = WqoInstance::new(vec![0, 1, 2], |a, b| a <= b);
1281        assert!(w.is_transitive());
1282    }
1283    #[test]
1284    fn test_wqo_good_pair() {
1285        let w = WqoInstance::new(vec![0, 1, 2], |a, b| a <= b);
1286        let seq = vec![2usize, 0, 1];
1287        assert!(w.has_good_pair(&seq));
1288    }
1289    #[test]
1290    fn test_wqo_find_good_pair() {
1291        let w = WqoInstance::new(vec![0, 1, 2], |a, b| a <= b);
1292        let seq = vec![0usize, 1, 2];
1293        let pair = w.find_good_pair(&seq);
1294        assert!(pair.is_some());
1295    }
1296    #[test]
1297    fn test_ordinal_cnf_zero() {
1298        let z = OrdinalCnf::zero();
1299        assert!(z.is_zero());
1300        assert!(z.is_finite());
1301        assert_eq!(z.as_finite(), Some(0));
1302    }
1303    #[test]
1304    fn test_ordinal_cnf_finite() {
1305        let three = OrdinalCnf::finite(3);
1306        assert!(!three.is_zero());
1307        assert!(three.is_finite());
1308        assert_eq!(three.as_finite(), Some(3));
1309    }
1310    #[test]
1311    fn test_ordinal_cnf_omega() {
1312        let w = OrdinalCnf::omega();
1313        assert!(!w.is_finite());
1314        assert!(!w.is_zero());
1315    }
1316    #[test]
1317    fn test_ordinal_cnf_add() {
1318        let a = OrdinalCnf::finite(2);
1319        let b = OrdinalCnf::finite(3);
1320        let sum = a.add(&b);
1321        assert_eq!(sum.as_finite(), Some(3));
1322    }
1323    #[test]
1324    fn test_ordinal_cnf_cmp() {
1325        let a = OrdinalCnf::finite(1);
1326        let b = OrdinalCnf::omega();
1327        assert_eq!(a.ord_cmp(&b), Ordering::Less);
1328        assert_eq!(b.ord_cmp(&a), Ordering::Greater);
1329        assert_eq!(a.ord_cmp(&a), Ordering::Equal);
1330    }
1331    #[test]
1332    fn test_dedekind_cut_in_lower_upper() {
1333        let cut = DedekindCutQ::new(1, 2);
1334        assert!(cut.in_lower(0, 1));
1335        assert!(cut.in_upper(1, 1));
1336        assert!(!cut.in_lower(1, 1));
1337    }
1338    #[test]
1339    fn test_dedekind_cut_cmp() {
1340        let a = DedekindCutQ::new(1, 3);
1341        let b = DedekindCutQ::new(1, 2);
1342        assert_eq!(a.cut_cmp(&b), Ordering::Less);
1343        assert_eq!(b.cut_cmp(&a), Ordering::Greater);
1344        assert_eq!(a.cut_cmp(&a), Ordering::Equal);
1345    }
1346    #[test]
1347    fn test_dedekind_mediant() {
1348        let a = DedekindCutQ::new(1, 3);
1349        let b = DedekindCutQ::new(1, 2);
1350        let m = a.mediant(&b);
1351        assert_eq!(m.numerator, 2);
1352        assert_eq!(m.denominator, 5);
1353    }
1354    #[test]
1355    fn test_finite_linear_order_identity() {
1356        let o = FiniteLinearOrder::identity(4);
1357        assert_eq!(o.size, 4);
1358        assert_eq!(o.rank(0), Some(0));
1359        assert_eq!(o.rank(3), Some(3));
1360        assert_eq!(o.min_elem(), Some(0));
1361        assert_eq!(o.max_elem(), Some(3));
1362    }
1363    #[test]
1364    fn test_finite_linear_order_compare() {
1365        let o = FiniteLinearOrder::identity(3);
1366        assert_eq!(o.compare(0, 1), Ordering::Less);
1367        assert_eq!(o.compare(2, 1), Ordering::Greater);
1368        assert_eq!(o.compare(1, 1), Ordering::Equal);
1369    }
1370    #[test]
1371    fn test_finite_linear_order_reverse() {
1372        let o = FiniteLinearOrder::identity(3);
1373        let r = o.reverse_order();
1374        assert_eq!(r.order, vec![2, 1, 0]);
1375        assert_eq!(r.min_elem(), Some(2));
1376    }
1377    #[test]
1378    fn test_finite_partial_order_discrete() {
1379        let p = FinitePartialOrder::discrete(3);
1380        assert!(p.is_valid());
1381        assert!(!p.is_total());
1382    }
1383    #[test]
1384    fn test_finite_partial_order_chain() {
1385        let mut le = vec![vec![false; 3]; 3];
1386        for i in 0..3usize {
1387            for j in i..3usize {
1388                le[i][j] = true;
1389            }
1390        }
1391        let p = FinitePartialOrder { size: 3, le };
1392        assert!(p.is_valid());
1393        assert!(p.is_total());
1394        assert_eq!(p.maximal_elements(), vec![2]);
1395    }
1396    #[test]
1397    fn test_transitive_closure() {
1398        let mut le = vec![vec![false; 3]; 3];
1399        le[0][0] = true;
1400        le[1][1] = true;
1401        le[2][2] = true;
1402        le[0][1] = true;
1403        le[1][2] = true;
1404        let p = FinitePartialOrder { size: 3, le };
1405        let cl = p.transitive_closure();
1406        assert!(cl.le[0][2]);
1407    }
1408    #[test]
1409    fn test_axiom_wqo_carrier_ty() {
1410        let ty = axiom_wqo_carrier_ty();
1411        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1412    }
1413    #[test]
1414    fn test_axiom_ordinal_zero_ty() {
1415        let ty = axiom_ordinal_zero_ty();
1416        assert_eq!(ty, Expr::Const(Name::str("Ordinal"), vec![]));
1417    }
1418    #[test]
1419    fn test_axiom_ordinal_add_ty() {
1420        let ty = axiom_ordinal_add_ty();
1421        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1422    }
1423    #[test]
1424    fn test_register_ordering_extended() {
1425        let mut env = Environment::new();
1426        assert!(register_ordering_extended(&mut env).is_ok());
1427        assert!(env.contains(&Name::str("Ordinal.zero")));
1428        assert!(env.contains(&Name::str("Ordinal.omega")));
1429        assert!(env.contains(&Name::str("Dickson.lemma")));
1430        assert!(env.contains(&Name::str("Higman.lemma")));
1431        assert!(env.contains(&Name::str("Kruskal.treeThm")));
1432        assert!(env.contains(&Name::str("Cantor.backAndForth")));
1433    }
1434}
1435/// Type of `BoundedLattice`: a lattice with top and bottom elements.
1436/// `BoundedLattice : Type β†’ Type 1`
1437#[allow(dead_code)]
1438pub fn axiom_bounded_lattice_ty() -> Expr {
1439    ord_ext_arrow(
1440        Expr::Sort(Level::succ(Level::zero())),
1441        Expr::Sort(Level::succ(Level::succ(Level::zero()))),
1442    )
1443}
1444/// Type of `CompleteLattice.sup`: supremum of an arbitrary set.
1445/// `CompleteLattice.sup : βˆ€ {L : Type} [CompleteLattice L], (L β†’ Prop) β†’ L`
1446#[allow(dead_code)]
1447pub fn axiom_complete_lattice_sup_ty() -> Expr {
1448    Expr::Pi(
1449        BinderInfo::Implicit,
1450        Name::str("L"),
1451        Box::new(Expr::Sort(Level::succ(Level::zero()))),
1452        Box::new(ord_ext_arrow(
1453            ord_ext_arrow(Expr::BVar(0), Expr::Sort(Level::zero())),
1454            Expr::BVar(1),
1455        )),
1456    )
1457}
1458/// Type of `GaloisConnection`: a Galois connection between two posets.
1459/// `GaloisConnection : βˆ€ (P Q : Type) [PartialOrder P] [PartialOrder Q], (P β†’ Q) β†’ (Q β†’ P) β†’ Prop`
1460#[allow(dead_code)]
1461pub fn axiom_galois_connection_ty() -> Expr {
1462    Expr::Pi(
1463        BinderInfo::Default,
1464        Name::str("P"),
1465        Box::new(Expr::Sort(Level::succ(Level::zero()))),
1466        Box::new(Expr::Pi(
1467            BinderInfo::Default,
1468            Name::str("Q"),
1469            Box::new(Expr::Sort(Level::succ(Level::zero()))),
1470            Box::new(ord_ext_arrow(
1471                ord_ext_arrow(Expr::BVar(1), Expr::BVar(0)),
1472                ord_ext_arrow(
1473                    ord_ext_arrow(Expr::BVar(1), Expr::BVar(2)),
1474                    Expr::Sort(Level::zero()),
1475                ),
1476            )),
1477        )),
1478    )
1479}
1480/// Type of `Antichain.maximal`: a maximal antichain in a partial order.
1481/// `Antichain.maximal : PartialOrder β†’ Type`
1482#[allow(dead_code)]
1483pub fn axiom_antichain_maximal_ty() -> Expr {
1484    ord_ext_arrow(
1485        Expr::Const(Name::str("PartialOrder"), vec![]),
1486        Expr::Sort(Level::succ(Level::zero())),
1487    )
1488}
1489/// Type of `Dilworth.theorem`: in any finite partial order, the minimum
1490/// number of chains needed to cover all elements equals the maximum antichain size.
1491/// `Dilworth.theorem : PartialOrder β†’ Prop`
1492#[allow(dead_code)]
1493pub fn axiom_dilworth_theorem_ty() -> Expr {
1494    ord_ext_arrow(
1495        Expr::Const(Name::str("PartialOrder"), vec![]),
1496        Expr::Sort(Level::zero()),
1497    )
1498}
1499/// Type of `Mirsky.theorem`: the minimum number of antichains covering a
1500/// partial order equals the length of the longest chain.
1501/// `Mirsky.theorem : PartialOrder β†’ Prop`
1502#[allow(dead_code)]
1503pub fn axiom_mirsky_theorem_ty() -> Expr {
1504    ord_ext_arrow(
1505        Expr::Const(Name::str("PartialOrder"), vec![]),
1506        Expr::Sort(Level::zero()),
1507    )
1508}
1509/// Type of `OrderIso`: an order isomorphism between two ordered sets.
1510/// `OrderIso : Type β†’ Type β†’ Type 1`
1511#[allow(dead_code)]
1512pub fn axiom_order_iso_ty() -> Expr {
1513    Expr::Pi(
1514        BinderInfo::Default,
1515        Name::str("A"),
1516        Box::new(Expr::Sort(Level::succ(Level::zero()))),
1517        Box::new(Expr::Pi(
1518            BinderInfo::Default,
1519            Name::str("B"),
1520            Box::new(Expr::Sort(Level::succ(Level::zero()))),
1521            Box::new(Expr::Sort(Level::succ(Level::succ(Level::zero())))),
1522        )),
1523    )
1524}
1525/// Type of `OrderEmbedding`: an order embedding (injective order homomorphism).
1526/// `OrderEmbedding : Type β†’ Type β†’ Type 1`
1527#[allow(dead_code)]
1528pub fn axiom_order_embedding_ty() -> Expr {
1529    Expr::Pi(
1530        BinderInfo::Default,
1531        Name::str("A"),
1532        Box::new(Expr::Sort(Level::succ(Level::zero()))),
1533        Box::new(Expr::Pi(
1534            BinderInfo::Default,
1535            Name::str("B"),
1536            Box::new(Expr::Sort(Level::succ(Level::zero()))),
1537            Box::new(Expr::Sort(Level::succ(Level::succ(Level::zero())))),
1538        )),
1539    )
1540}
1541/// Type of `CofinalSubset`: a subset S of a poset is cofinal if every element
1542/// has an upper bound in S.
1543/// `CofinalSubset : βˆ€ {P : Type} [PartialOrder P], (P β†’ Prop) β†’ Prop`
1544#[allow(dead_code)]
1545pub fn axiom_cofinal_subset_ty() -> Expr {
1546    Expr::Pi(
1547        BinderInfo::Implicit,
1548        Name::str("P"),
1549        Box::new(Expr::Sort(Level::succ(Level::zero()))),
1550        Box::new(ord_ext_arrow(
1551            ord_ext_arrow(Expr::BVar(0), Expr::Sort(Level::zero())),
1552            Expr::Sort(Level::zero()),
1553        )),
1554    )
1555}
1556/// Type of `Cofinality.ordinal`: the cofinality of an ordinal.
1557/// `Cofinality.ordinal : Ordinal β†’ Ordinal`
1558#[allow(dead_code)]
1559pub fn axiom_cofinality_ordinal_ty() -> Expr {
1560    ord_ext_arrow(
1561        Expr::Const(Name::str("Ordinal"), vec![]),
1562        Expr::Const(Name::str("Ordinal"), vec![]),
1563    )
1564}
1565/// Type of `RegularCardinal`: a cardinal equal to its own cofinality.
1566/// `RegularCardinal : Ordinal β†’ Prop`
1567#[allow(dead_code)]
1568pub fn axiom_regular_cardinal_ty() -> Expr {
1569    ord_ext_arrow(
1570        Expr::Const(Name::str("Ordinal"), vec![]),
1571        Expr::Sort(Level::zero()),
1572    )
1573}
1574#[cfg(test)]
1575mod ordered_range_tests {
1576    use super::*;
1577    #[test]
1578    fn test_ordered_range_contains() {
1579        let r = OrderedRange::new(1u32, 10u32);
1580        assert!(r.contains(&5));
1581        assert!(r.contains(&1));
1582        assert!(r.contains(&10));
1583        assert!(!r.contains(&0));
1584        assert!(!r.contains(&11));
1585    }
1586    #[test]
1587    fn test_ordered_range_contains_range() {
1588        let outer = OrderedRange::new(0u32, 100u32);
1589        let inner = OrderedRange::new(10u32, 50u32);
1590        assert!(outer.contains_range(&inner));
1591        assert!(!inner.contains_range(&outer));
1592    }
1593    #[test]
1594    fn test_ordered_range_overlaps() {
1595        let r1 = OrderedRange::new(1u32, 5u32);
1596        let r2 = OrderedRange::new(4u32, 8u32);
1597        let r3 = OrderedRange::new(6u32, 10u32);
1598        assert!(r1.overlaps(&r2));
1599        assert!(!r1.overlaps(&r3));
1600    }
1601    #[test]
1602    fn test_axiom_dilworth_theorem_ty() {
1603        let ty = axiom_dilworth_theorem_ty();
1604        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1605    }
1606    #[test]
1607    fn test_axiom_galois_connection_ty() {
1608        let ty = axiom_galois_connection_ty();
1609        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1610    }
1611    #[test]
1612    fn test_axiom_cofinality_ordinal_ty() {
1613        let ty = axiom_cofinality_ordinal_ty();
1614        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1615    }
1616    #[test]
1617    fn test_axiom_order_iso_ty() {
1618        let ty = axiom_order_iso_ty();
1619        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1620    }
1621    #[test]
1622    fn test_axiom_bounded_lattice_ty() {
1623        let ty = axiom_bounded_lattice_ty();
1624        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1625    }
1626    #[test]
1627    fn test_axiom_complete_lattice_sup_ty() {
1628        let ty = axiom_complete_lattice_sup_ty();
1629        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1630    }
1631    #[test]
1632    fn test_axiom_antichain_maximal_ty() {
1633        let ty = axiom_antichain_maximal_ty();
1634        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1635    }
1636    #[test]
1637    fn test_axiom_mirsky_theorem_ty() {
1638        let ty = axiom_mirsky_theorem_ty();
1639        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1640    }
1641    #[test]
1642    fn test_axiom_cofinal_subset_ty() {
1643        let ty = axiom_cofinal_subset_ty();
1644        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1645    }
1646    #[test]
1647    fn test_axiom_regular_cardinal_ty() {
1648        let ty = axiom_regular_cardinal_ty();
1649        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1650    }
1651    #[test]
1652    fn test_axiom_order_embedding_ty() {
1653        let ty = axiom_order_embedding_ty();
1654        assert!(matches!(ty, Expr::Pi(_, _, _, _)));
1655    }
1656}