Skip to main content

oxilean_std/decidable/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use super::types::{
6    BoolReflect, DecidableCounter, Decision, DecisionChain, DecisionTable, EqDecision, FiniteSet,
7    FnPred, Interval, LeDecision, NamedDecision, Not,
8};
9
10/// A type whose truth value is decidable.
11///
12/// Analogous to Lean 4's `Decidable` typeclass. Implementors produce a
13/// `Decision` when asked.
14pub trait Decidable {
15    /// The proof type when the proposition holds.
16    type Proof;
17    /// Decide the proposition, returning the decision.
18    fn decide(&self) -> Decision<Self::Proof>;
19    /// Shorthand: returns `true` iff the proposition holds.
20    fn is_decidably_true(&self) -> bool {
21        self.decide().is_true()
22    }
23}
24/// A decidable predicate `P : A → Prop`.
25///
26/// Given any `a : A`, can compute whether `P(a)` holds.
27pub trait DecidablePred<A> {
28    /// Decide whether the predicate holds for `a`.
29    fn decide_pred(&self, a: &A) -> Decision<()>;
30    /// Filter a slice, keeping elements satisfying the predicate.
31    fn filter_slice<'a>(&self, xs: &'a [A]) -> Vec<&'a A> {
32        xs.iter()
33            .filter(|x| self.decide_pred(x).is_true())
34            .collect()
35    }
36    /// Check whether any element of a slice satisfies the predicate.
37    fn any_slice(&self, xs: &[A]) -> bool {
38        xs.iter().any(|x| self.decide_pred(x).is_true())
39    }
40    /// Check whether all elements of a slice satisfy the predicate.
41    fn all_slice(&self, xs: &[A]) -> bool {
42        xs.iter().all(|x| self.decide_pred(x).is_true())
43    }
44    /// Count elements of a slice satisfying the predicate.
45    fn count_slice(&self, xs: &[A]) -> usize {
46        xs.iter().filter(|x| self.decide_pred(x).is_true()).count()
47    }
48}
49/// A decidable binary relation `R : A → A → Prop`.
50pub trait DecidableRel<A> {
51    /// Decide whether `R(a, b)` holds.
52    fn decide_rel(&self, a: &A, b: &A) -> Decision<()>;
53    /// Check whether `R(a, b)` holds.
54    fn holds(&self, a: &A, b: &A) -> bool {
55        self.decide_rel(a, b).is_true()
56    }
57}
58/// Decide equality of two `u32` values.
59pub fn decide_nat_eq(a: u32, b: u32) -> Decision<()> {
60    if a == b {
61        Decision::IsTrue(())
62    } else {
63        Decision::IsFalse(format!("{a} ≠ {b}"))
64    }
65}
66/// Decide `a ≤ b` for `u32` values.
67pub fn decide_nat_le(a: u32, b: u32) -> Decision<()> {
68    if a <= b {
69        Decision::IsTrue(())
70    } else {
71        Decision::IsFalse(format!("{a} > {b}"))
72    }
73}
74/// Decide `a < b` for `u32` values.
75pub fn decide_nat_lt(a: u32, b: u32) -> Decision<()> {
76    if a < b {
77        Decision::IsTrue(())
78    } else {
79        Decision::IsFalse(format!("{a} ≥ {b}"))
80    }
81}
82/// Decide equality of two string slices.
83pub fn decide_str_eq(a: &str, b: &str) -> Decision<()> {
84    if a == b {
85        Decision::IsTrue(())
86    } else {
87        Decision::IsFalse(format!("{a:?} ≠ {b:?}"))
88    }
89}
90/// Decide membership of `x` in a slice `xs`.
91pub fn decide_mem<T: PartialEq>(x: &T, xs: &[T]) -> Decision<usize> {
92    match xs.iter().position(|y| y == x) {
93        Some(idx) => Decision::IsTrue(idx),
94        None => Decision::IsFalse("not found".to_string()),
95    }
96}
97/// Decide whether `a` and `b` are equal for any `PartialEq` type.
98pub fn decide_eq<T: PartialEq>(a: &T, b: &T) -> Decision<()> {
99    if a == b {
100        Decision::IsTrue(())
101    } else {
102        Decision::IsFalse("not equal".to_string())
103    }
104}
105/// Decide `a ≤ b` for any `PartialOrd` type.
106pub fn decide_le<T: PartialOrd>(a: &T, b: &T) -> Decision<()> {
107    if a <= b {
108        Decision::IsTrue(())
109    } else {
110        Decision::IsFalse("not ≤".to_string())
111    }
112}
113/// Decide `a < b` for any `PartialOrd` type.
114pub fn decide_lt<T: PartialOrd>(a: &T, b: &T) -> Decision<()> {
115    if a < b {
116        Decision::IsTrue(())
117    } else {
118        Decision::IsFalse("not <".to_string())
119    }
120}
121/// Decide `P ∧ Q`.
122pub fn decision_and<P, Q>(dp: Decision<P>, dq: Decision<Q>) -> Decision<(P, Q)> {
123    dp.and(dq)
124}
125/// Decide `P ∨ Q` (left-biased).
126pub fn decision_or<P>(dp: Decision<P>, dq: Decision<P>) -> Decision<P> {
127    dp.or(dq)
128}
129/// Decide `¬P`.
130pub fn decision_not<P: std::fmt::Debug>(dp: Decision<P>) -> Decision<String> {
131    dp.negate()
132}
133/// Decide `P → Q` given a decision of `P` and a function producing a decision of `Q`.
134pub fn decision_implies<P, Q>(dp: Decision<P>, f: impl FnOnce(P) -> Decision<Q>) -> Decision<Q> {
135    dp.flat_map(f)
136}
137/// Decide a conjunction of a list of unit decisions.
138pub fn decide_all(ds: impl IntoIterator<Item = Decision<()>>) -> Decision<()> {
139    for d in ds {
140        if d.is_false() {
141            return d;
142        }
143    }
144    Decision::IsTrue(())
145}
146/// Decide a disjunction of a list of unit decisions.
147pub fn decide_any(ds: impl IntoIterator<Item = Decision<()>>) -> Decision<()> {
148    let mut last = Decision::IsFalse("no alternatives".to_string());
149    for d in ds {
150        if d.is_true() {
151            return d;
152        }
153        last = d;
154    }
155    last
156}
157/// Decide whether a `u32` lies in the range `[lo, hi)`.
158pub fn decide_range(x: u32, lo: u32, hi: u32) -> Decision<()> {
159    if x >= lo && x < hi {
160        Decision::IsTrue(())
161    } else {
162        Decision::IsFalse(format!("{x} not in [{lo}, {hi})"))
163    }
164}
165/// Decide whether a string slice starts with a prefix.
166pub fn decide_starts_with(s: &str, prefix: &str) -> Decision<()> {
167    if s.starts_with(prefix) {
168        Decision::IsTrue(())
169    } else {
170        Decision::IsFalse(format!("{s:?} does not start with {prefix:?}"))
171    }
172}
173/// Decide whether a string slice ends with a suffix.
174pub fn decide_ends_with(s: &str, suffix: &str) -> Decision<()> {
175    if s.ends_with(suffix) {
176        Decision::IsTrue(())
177    } else {
178        Decision::IsFalse(format!("{s:?} does not end with {suffix:?}"))
179    }
180}
181/// Decide whether a slice is non-empty.
182pub fn decide_non_empty<T>(xs: &[T]) -> Decision<()> {
183    if !xs.is_empty() {
184        Decision::IsTrue(())
185    } else {
186        Decision::IsFalse("slice is empty".to_string())
187    }
188}
189#[cfg(test)]
190mod tests {
191    use super::*;
192    #[test]
193    fn test_decision_is_true() {
194        let d: Decision<()> = Decision::IsTrue(());
195        assert!(d.is_true());
196        assert!(!d.is_false());
197    }
198    #[test]
199    fn test_decision_is_false() {
200        let d: Decision<()> = Decision::IsFalse("no".to_string());
201        assert!(d.is_false());
202        assert!(!d.is_true());
203    }
204    #[test]
205    fn test_decision_map() {
206        let d: Decision<u32> = Decision::IsTrue(5);
207        let d2 = d.map(|x| x * 2);
208        match d2 {
209            Decision::IsTrue(v) => assert_eq!(v, 10),
210            _ => panic!("expected IsTrue variant"),
211        };
212    }
213    #[test]
214    fn test_decision_and_both_true() {
215        let a: Decision<()> = Decision::IsTrue(());
216        let b: Decision<()> = Decision::IsTrue(());
217        assert!(a.and(b).is_true());
218    }
219    #[test]
220    fn test_decision_and_one_false() {
221        let a: Decision<()> = Decision::IsTrue(());
222        let b: Decision<()> = Decision::IsFalse("no".to_string());
223        assert!(a.and(b).is_false());
224    }
225    #[test]
226    fn test_decision_or_first_true() {
227        let a: Decision<()> = Decision::IsTrue(());
228        let b: Decision<()> = Decision::IsFalse("no".to_string());
229        assert!(a.or(b).is_true());
230    }
231    #[test]
232    fn test_decide_nat_eq() {
233        assert!(decide_nat_eq(5, 5).is_true());
234        assert!(decide_nat_eq(5, 6).is_false());
235    }
236    #[test]
237    fn test_decide_nat_le() {
238        assert!(decide_nat_le(3, 5).is_true());
239        assert!(decide_nat_le(5, 3).is_false());
240    }
241    #[test]
242    fn test_decide_str_eq() {
243        assert!(decide_str_eq("hello", "hello").is_true());
244        assert!(decide_str_eq("hello", "world").is_false());
245    }
246    #[test]
247    fn test_decide_mem() {
248        let xs = vec![1u32, 2, 3];
249        assert!(decide_mem(&2, &xs).is_true());
250        assert!(decide_mem(&5, &xs).is_false());
251    }
252    #[test]
253    fn test_finite_set_insert() {
254        let mut s: FiniteSet<u32> = FiniteSet::new();
255        assert!(s.insert(1));
256        assert!(!s.insert(1));
257        assert_eq!(s.len(), 1);
258    }
259    #[test]
260    fn test_finite_set_union() {
261        let mut a: FiniteSet<u32> = FiniteSet::new();
262        a.insert(1);
263        a.insert(2);
264        let mut b: FiniteSet<u32> = FiniteSet::new();
265        b.insert(2);
266        b.insert(3);
267        let u = a.union(&b);
268        assert_eq!(u.len(), 3);
269        assert!(u.contains(&3));
270    }
271    #[test]
272    fn test_finite_set_intersection() {
273        let a: FiniteSet<u32> = [1, 2, 3].iter().copied().collect();
274        let b: FiniteSet<u32> = [2, 3, 4].iter().copied().collect();
275        let inter = a.intersection(&b);
276        assert_eq!(inter.len(), 2);
277        assert!(inter.contains(&2));
278        assert!(inter.contains(&3));
279    }
280    #[test]
281    fn test_finite_set_difference() {
282        let a: FiniteSet<u32> = [1, 2, 3].iter().copied().collect();
283        let b: FiniteSet<u32> = [2, 3].iter().copied().collect();
284        let diff = a.difference(&b);
285        assert_eq!(diff.len(), 1);
286        assert!(diff.contains(&1));
287    }
288    #[test]
289    fn test_finite_set_subset() {
290        let a: FiniteSet<u32> = [1, 2].iter().copied().collect();
291        let b: FiniteSet<u32> = [1, 2, 3].iter().copied().collect();
292        assert!(a.is_subset(&b));
293        assert!(!b.is_subset(&a));
294    }
295    #[test]
296    fn test_bool_reflect() {
297        let d_true: Decision<()> = Decision::IsTrue(());
298        let d_false: Decision<()> = Decision::IsFalse("no".to_string());
299        assert!(BoolReflect::from_decision(&d_true).to_bool());
300        assert!(!BoolReflect::from_decision(&d_false).to_bool());
301    }
302    #[test]
303    fn test_decision_table() {
304        let mut table = DecisionTable::new();
305        table.insert("prop_a", Decision::IsTrue(()));
306        table.insert("prop_b", Decision::IsFalse("no".to_string()));
307        assert!(table
308            .lookup("prop_a")
309            .expect("lookup should succeed")
310            .is_true());
311        assert!(table
312            .lookup("prop_b")
313            .expect("lookup should succeed")
314            .is_false());
315        assert!(table.lookup("prop_c").is_none());
316    }
317    #[test]
318    fn test_decide_range() {
319        assert!(decide_range(5, 0, 10).is_true());
320        assert!(decide_range(10, 0, 10).is_false());
321        assert!(decide_range(0, 0, 10).is_true());
322    }
323    #[test]
324    fn test_decide_all() {
325        let ds: Vec<Decision<()>> = vec![Decision::IsTrue(()), Decision::IsTrue(())];
326        assert!(decide_all(ds).is_true());
327        let ds2: Vec<Decision<()>> = vec![Decision::IsTrue(()), Decision::IsFalse("n".to_string())];
328        assert!(decide_all(ds2).is_false());
329    }
330    #[test]
331    fn test_decide_any() {
332        let ds: Vec<Decision<()>> = vec![Decision::IsFalse("n".to_string()), Decision::IsTrue(())];
333        assert!(decide_any(ds).is_true());
334        let ds2: Vec<Decision<()>> = vec![
335            Decision::IsFalse("a".to_string()),
336            Decision::IsFalse("b".to_string()),
337        ];
338        assert!(decide_any(ds2).is_false());
339    }
340    #[test]
341    fn test_fn_pred() {
342        let pred = FnPred::new(|x: &u32| *x > 3);
343        assert!(pred.decide_pred(&5).is_true());
344        assert!(pred.decide_pred(&2).is_false());
345        let xs = vec![1u32, 2, 3, 4, 5];
346        let filtered = pred.filter_slice(&xs);
347        assert_eq!(filtered.len(), 2);
348    }
349}
350/// Decide equality for `Option<T>`.
351pub fn decide_option_eq<T: PartialEq>(a: &Option<T>, b: &Option<T>) -> Decision<()> {
352    if a == b {
353        Decision::IsTrue(())
354    } else {
355        Decision::IsFalse("options differ".to_string())
356    }
357}
358/// Decide whether an `Option<T>` is `Some`.
359pub fn decide_is_some<T>(a: &Option<T>) -> Decision<()> {
360    if a.is_some() {
361        Decision::IsTrue(())
362    } else {
363        Decision::IsFalse("is None".to_string())
364    }
365}
366/// Decide whether an `Option<T>` is `None`.
367pub fn decide_is_none<T>(a: &Option<T>) -> Decision<()> {
368    if a.is_none() {
369        Decision::IsTrue(())
370    } else {
371        Decision::IsFalse("is Some".to_string())
372    }
373}
374/// Decide equality for slices of `PartialEq` elements.
375pub fn decide_slice_eq<T: PartialEq>(a: &[T], b: &[T]) -> Decision<()> {
376    if a == b {
377        Decision::IsTrue(())
378    } else {
379        Decision::IsFalse(format!("slices differ (len {} vs {})", a.len(), b.len()))
380    }
381}
382/// Decide whether a slice has the given length.
383pub fn decide_len<T>(xs: &[T], expected: usize) -> Decision<()> {
384    if xs.len() == expected {
385        Decision::IsTrue(())
386    } else {
387        Decision::IsFalse(format!("length {} ≠ {expected}", xs.len()))
388    }
389}
390/// Decide whether an integer is even.
391pub fn decide_even(n: u32) -> Decision<()> {
392    if n % 2 == 0 {
393        Decision::IsTrue(())
394    } else {
395        Decision::IsFalse(format!("{n} is odd"))
396    }
397}
398/// Decide whether an integer is odd.
399pub fn decide_odd(n: u32) -> Decision<()> {
400    if n % 2 == 1 {
401        Decision::IsTrue(())
402    } else {
403        Decision::IsFalse(format!("{n} is even"))
404    }
405}
406/// Decide whether `n` is divisible by `d`.
407///
408/// Returns `IsFalse` if `d == 0`.
409pub fn decide_divisible(n: u32, d: u32) -> Decision<()> {
410    if d == 0 {
411        Decision::IsFalse("divisor is zero".to_string())
412    } else if n % d == 0 {
413        Decision::IsTrue(())
414    } else {
415        Decision::IsFalse(format!("{n} not divisible by {d}"))
416    }
417}
418/// Lift a `Result<(), E>` into a `Decision<()>`.
419pub fn decision_from_result<E: std::fmt::Display>(r: Result<(), E>) -> Decision<()> {
420    match r {
421        Ok(()) => Decision::IsTrue(()),
422        Err(e) => Decision::IsFalse(e.to_string()),
423    }
424}
425/// Convert a `Decision<()>` into a `Result<(), String>`.
426pub fn decision_to_result(d: Decision<()>) -> Result<(), String> {
427    match d {
428        Decision::IsTrue(()) => Ok(()),
429        Decision::IsFalse(msg) => Err(msg),
430    }
431}
432/// Run a series of named decisions and report the results.
433///
434/// Returns a list of all named decisions, and whether all passed.
435pub fn run_decisions(decisions: Vec<NamedDecision>) -> (Vec<NamedDecision>, bool) {
436    let all_pass = decisions.iter().all(|d| d.is_true());
437    (decisions, all_pass)
438}
439#[cfg(test)]
440mod extra_tests {
441    use super::*;
442    #[test]
443    fn test_decide_even_odd() {
444        assert!(decide_even(4).is_true());
445        assert!(decide_odd(3).is_true());
446        assert!(decide_even(3).is_false());
447        assert!(decide_odd(4).is_false());
448    }
449    #[test]
450    fn test_decide_divisible() {
451        assert!(decide_divisible(12, 4).is_true());
452        assert!(decide_divisible(12, 5).is_false());
453        assert!(decide_divisible(12, 0).is_false());
454    }
455    #[test]
456    fn test_decide_option() {
457        let a: Option<u32> = Some(5);
458        let b: Option<u32> = Some(5);
459        assert!(decide_option_eq(&a, &b).is_true());
460        assert!(decide_is_some(&a).is_true());
461        assert!(decide_is_none::<u32>(&None).is_true());
462    }
463    #[test]
464    fn test_decide_slice_eq() {
465        let a = vec![1u32, 2, 3];
466        let b = vec![1u32, 2, 3];
467        let c = vec![1u32, 2];
468        assert!(decide_slice_eq(&a, &b).is_true());
469        assert!(decide_slice_eq(&a, &c).is_false());
470    }
471    #[test]
472    fn test_named_decision() {
473        let nd = NamedDecision::new("prop_a", Decision::IsTrue(()));
474        assert!(nd.is_true());
475        let s = nd.summary();
476        assert!(s.contains("prop_a"));
477    }
478    #[test]
479    fn test_decision_from_result() {
480        let r: Result<(), String> = Ok(());
481        assert!(decision_from_result(r).is_true());
482        let r2: Result<(), String> = Err("err".to_string());
483        assert!(decision_from_result(r2).is_false());
484    }
485    #[test]
486    fn test_decision_to_result() {
487        assert!(decision_to_result(Decision::IsTrue(())).is_ok());
488        assert!(decision_to_result(Decision::IsFalse("no".to_string())).is_err());
489    }
490}
491/// Build the standard Decidable environment declarations.
492///
493/// Registers `Decidable`, `DecidableEq`, and common instances for
494/// `Nat`, `Bool`, `String`, `Unit`, `Char`, and compound types.
495pub fn build_decidable_env(env: &mut oxilean_kernel::Environment) -> Result<(), String> {
496    use oxilean_kernel::{BinderInfo as Bi, Declaration, Expr, Level, Name};
497    let mut add = |name: &str, ty: Expr| -> Result<(), String> {
498        match env.add(Declaration::Axiom {
499            name: Name::str(name),
500            univ_params: vec![],
501            ty,
502        }) {
503            Ok(()) | Err(_) => Ok(()),
504        }
505    };
506    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
507    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
508    let arr = |a: Expr, b: Expr| -> Expr {
509        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
510    };
511    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
512    let prop = || -> Expr { Expr::Sort(Level::zero()) };
513    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
514    let dec_eq_of = |ty: Expr| -> Expr { app(cst("DecidableEq"), ty) };
515    add("Decidable", arr(prop(), type1()))?;
516    add("DecidableEq", arr(type1(), type1()))?;
517    let is_true_ty = Expr::Pi(
518        Bi::Implicit,
519        Name::str("p"),
520        Box::new(prop()),
521        Box::new(arr(Expr::BVar(0), dec_of(Expr::BVar(1)))),
522    );
523    add("Decidable.isTrue", is_true_ty)?;
524    let is_false_ty = Expr::Pi(
525        Bi::Implicit,
526        Name::str("p"),
527        Box::new(prop()),
528        Box::new(arr(arr(Expr::BVar(0), cst("False")), dec_of(Expr::BVar(1)))),
529    );
530    add("Decidable.isFalse", is_false_ty)?;
531    add("instDecidableTrue", dec_of(cst("True")))?;
532    add("instDecidableFalse", dec_of(cst("False")))?;
533    let inst_dec_not_ty = Expr::Pi(
534        Bi::Implicit,
535        Name::str("p"),
536        Box::new(prop()),
537        Box::new(Expr::Pi(
538            Bi::InstImplicit,
539            Name::str("inst"),
540            Box::new(dec_of(Expr::BVar(0))),
541            Box::new(dec_of(app(cst("Not"), Expr::BVar(1)))),
542        )),
543    );
544    add("instDecidableNot", inst_dec_not_ty)?;
545    let inst_dec_and_ty = Expr::Pi(
546        Bi::Implicit,
547        Name::str("p"),
548        Box::new(prop()),
549        Box::new(Expr::Pi(
550            Bi::Implicit,
551            Name::str("q"),
552            Box::new(prop()),
553            Box::new(Expr::Pi(
554                Bi::InstImplicit,
555                Name::str("dp"),
556                Box::new(dec_of(Expr::BVar(1))),
557                Box::new(Expr::Pi(
558                    Bi::InstImplicit,
559                    Name::str("dq"),
560                    Box::new(dec_of(Expr::BVar(1))),
561                    Box::new(dec_of(app(app(cst("And"), Expr::BVar(3)), Expr::BVar(2)))),
562                )),
563            )),
564        )),
565    );
566    add("instDecidableAnd", inst_dec_and_ty)?;
567    let inst_dec_or_ty = Expr::Pi(
568        Bi::Implicit,
569        Name::str("p"),
570        Box::new(prop()),
571        Box::new(Expr::Pi(
572            Bi::Implicit,
573            Name::str("q"),
574            Box::new(prop()),
575            Box::new(Expr::Pi(
576                Bi::InstImplicit,
577                Name::str("dp"),
578                Box::new(dec_of(Expr::BVar(1))),
579                Box::new(Expr::Pi(
580                    Bi::InstImplicit,
581                    Name::str("dq"),
582                    Box::new(dec_of(Expr::BVar(1))),
583                    Box::new(dec_of(app(app(cst("Or"), Expr::BVar(3)), Expr::BVar(2)))),
584                )),
585            )),
586        )),
587    );
588    add("instDecidableOr", inst_dec_or_ty)?;
589    add("instDecidableEqNat", dec_eq_of(cst("Nat")))?;
590    add("instDecidableEqBool", dec_eq_of(cst("Bool")))?;
591    add("instDecidableEqString", dec_eq_of(cst("String")))?;
592    add("instDecidableEqUnit", dec_eq_of(cst("Unit")))?;
593    add("instDecidableEqChar", dec_eq_of(cst("Char")))?;
594    add("instDecidableEqInt", dec_eq_of(cst("Int")))?;
595    let inst_dec_eq_opt_ty = Expr::Pi(
596        Bi::Implicit,
597        Name::str("α"),
598        Box::new(type1()),
599        Box::new(Expr::Pi(
600            Bi::InstImplicit,
601            Name::str("inst"),
602            Box::new(dec_eq_of(Expr::BVar(0))),
603            Box::new(dec_eq_of(app(cst("Option"), Expr::BVar(1)))),
604        )),
605    );
606    add("instDecidableEqOption", inst_dec_eq_opt_ty)?;
607    let inst_dec_eq_list_ty = Expr::Pi(
608        Bi::Implicit,
609        Name::str("α"),
610        Box::new(type1()),
611        Box::new(Expr::Pi(
612            Bi::InstImplicit,
613            Name::str("inst"),
614            Box::new(dec_eq_of(Expr::BVar(0))),
615            Box::new(dec_eq_of(app(cst("List"), Expr::BVar(1)))),
616        )),
617    );
618    add("instDecidableEqList", inst_dec_eq_list_ty)?;
619    Ok(())
620}
621/// Decide membership in a `FiniteSet<T>`.
622pub fn decide_finite_set_mem<T: PartialEq>(x: &T, set: &FiniteSet<T>) -> Decision<()> {
623    if set.contains(x) {
624        Decision::IsTrue(())
625    } else {
626        Decision::IsFalse("not in set".to_string())
627    }
628}
629/// Decide whether a `FiniteSet` is a subset of another.
630pub fn decide_subset<T: PartialEq>(a: &FiniteSet<T>, b: &FiniteSet<T>) -> Decision<()> {
631    if a.is_subset(b) {
632        Decision::IsTrue(())
633    } else {
634        Decision::IsFalse("not a subset".to_string())
635    }
636}
637/// Decide whether an interval `[lo, hi]` is non-empty.
638pub fn decide_interval_non_empty(iv: &Interval) -> Decision<()> {
639    if !iv.is_empty() {
640        Decision::IsTrue(())
641    } else {
642        Decision::IsFalse("interval is empty".to_string())
643    }
644}
645/// Decide whether two intervals overlap.
646pub fn decide_intervals_overlap(a: &Interval, b: &Interval) -> Decision<()> {
647    if !a.intersect(b).is_empty() {
648        Decision::IsTrue(())
649    } else {
650        Decision::IsFalse(format!("{} and {} do not overlap", a, b))
651    }
652}
653#[cfg(test)]
654mod decidable_extra_tests {
655    use super::*;
656    #[test]
657    fn test_decidable_counter_record() {
658        let mut counter = DecidableCounter::new();
659        counter.record(&Decision::IsTrue(()));
660        counter.record(&Decision::IsTrue(()));
661        counter.record(&Decision::IsFalse("no".to_string()));
662        assert_eq!(counter.true_count, 2);
663        assert_eq!(counter.false_count, 1);
664        assert_eq!(counter.total(), 3);
665    }
666    #[test]
667    fn test_decidable_counter_true_rate() {
668        let mut counter = DecidableCounter::new();
669        counter.record(&Decision::IsTrue(()));
670        counter.record(&Decision::IsTrue(()));
671        assert!((counter.true_rate() - 100.0).abs() < 0.01);
672    }
673    #[test]
674    fn test_decidable_counter_all_true() {
675        let mut counter = DecidableCounter::new();
676        counter.record(&Decision::IsTrue(()));
677        assert!(counter.all_true());
678        counter.record(&Decision::IsFalse("n".to_string()));
679        assert!(!counter.all_true());
680    }
681    #[test]
682    fn test_decidable_counter_reset() {
683        let mut counter = DecidableCounter::new();
684        counter.record(&Decision::IsTrue(()));
685        counter.reset();
686        assert_eq!(counter.total(), 0);
687    }
688    #[test]
689    fn test_decision_chain_all_passed() {
690        let chain = DecisionChain::new()
691            .step("a", Decision::IsTrue(()))
692            .step("b", Decision::IsTrue(()));
693        assert!(chain.all_passed());
694        assert_eq!(chain.passed_count(), 2);
695        assert_eq!(chain.failed_count(), 0);
696    }
697    #[test]
698    fn test_decision_chain_first_failure() {
699        let chain = DecisionChain::new()
700            .step("a", Decision::IsTrue(()))
701            .step("b", Decision::IsFalse("no".to_string()))
702            .step("c", Decision::IsTrue(()));
703        assert!(!chain.all_passed());
704        assert_eq!(chain.first_failure(), Some("b"));
705    }
706    #[test]
707    fn test_decision_chain_empty() {
708        let chain = DecisionChain::new();
709        assert!(chain.is_empty());
710        assert_eq!(chain.len(), 0);
711    }
712    #[test]
713    fn test_interval_contains() {
714        let iv = Interval::new(3, 7);
715        assert!(iv.contains(3));
716        assert!(iv.contains(7));
717        assert!(iv.contains(5));
718        assert!(!iv.contains(2));
719        assert!(!iv.contains(8));
720    }
721    #[test]
722    fn test_interval_is_empty() {
723        let iv = Interval::new(5, 3);
724        assert!(iv.is_empty());
725        assert_eq!(iv.len(), 0);
726    }
727    #[test]
728    fn test_interval_len() {
729        let iv = Interval::new(2, 5);
730        assert_eq!(iv.len(), 4);
731    }
732    #[test]
733    fn test_interval_intersect() {
734        let a = Interval::new(1, 5);
735        let b = Interval::new(3, 8);
736        let inter = a.intersect(&b);
737        assert_eq!(inter.lo, 3);
738        assert_eq!(inter.hi, 5);
739    }
740    #[test]
741    fn test_interval_union() {
742        let a = Interval::new(1, 5);
743        let b = Interval::new(3, 8);
744        let u = a.union(&b);
745        assert_eq!(u.lo, 1);
746        assert_eq!(u.hi, 8);
747    }
748    #[test]
749    fn test_interval_decide_contains() {
750        let iv = Interval::new(0, 10);
751        assert!(iv.decide_contains(5).is_true());
752        assert!(iv.decide_contains(11).is_false());
753    }
754    #[test]
755    fn test_interval_display() {
756        let iv = Interval::new(-1, 3);
757        assert_eq!(format!("{}", iv), "[-1, 3]");
758    }
759    #[test]
760    fn test_eq_decision_true() {
761        let d = EqDecision::new(42u32, 42u32);
762        assert!(d.decide().is_true());
763        assert!(d.is_decidably_true());
764    }
765    #[test]
766    fn test_eq_decision_false() {
767        let d = EqDecision::new(1u32, 2u32);
768        assert!(d.decide().is_false());
769    }
770    #[test]
771    fn test_le_decision_true() {
772        let d = LeDecision::new(3u32, 5u32);
773        assert!(d.decide().is_true());
774    }
775    #[test]
776    fn test_le_decision_equal() {
777        let d = LeDecision::new(5u32, 5u32);
778        assert!(d.decide().is_true());
779    }
780    #[test]
781    fn test_le_decision_false() {
782        let d = LeDecision::new(6u32, 5u32);
783        assert!(d.decide().is_false());
784    }
785    #[test]
786    fn test_decide_finite_set_mem() {
787        let mut s: FiniteSet<u32> = FiniteSet::new();
788        s.insert(7);
789        assert!(decide_finite_set_mem(&7u32, &s).is_true());
790        assert!(decide_finite_set_mem(&8u32, &s).is_false());
791    }
792    #[test]
793    fn test_decide_subset() {
794        let a: FiniteSet<u32> = [1, 2].iter().copied().collect();
795        let b: FiniteSet<u32> = [1, 2, 3].iter().copied().collect();
796        assert!(decide_subset(&a, &b).is_true());
797        assert!(decide_subset(&b, &a).is_false());
798    }
799    #[test]
800    fn test_decide_interval_non_empty() {
801        let iv1 = Interval::new(1, 5);
802        let iv2 = Interval::new(5, 3);
803        assert!(decide_interval_non_empty(&iv1).is_true());
804        assert!(decide_interval_non_empty(&iv2).is_false());
805    }
806    #[test]
807    fn test_decide_intervals_overlap() {
808        let a = Interval::new(1, 5);
809        let b = Interval::new(4, 9);
810        let c = Interval::new(6, 9);
811        assert!(decide_intervals_overlap(&a, &b).is_true());
812        assert!(decide_intervals_overlap(&a, &c).is_false());
813    }
814}
815pub fn dcs_ext_decidable_typeclass(
816    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
817) -> Result<(), String> {
818    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
819    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
820    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
821    let arr = |a: Expr, b: Expr| -> Expr {
822        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
823    };
824    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
825    let prop = || -> Expr { Expr::Sort(Level::zero()) };
826    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
827    let decide_ty = Expr::Pi(
828        Bi::Implicit,
829        Name::str("p"),
830        Box::new(prop()),
831        Box::new(Expr::Pi(
832            Bi::InstImplicit,
833            Name::str("inst"),
834            Box::new(dec_of(Expr::BVar(0))),
835            Box::new(cst("Bool")),
836        )),
837    );
838    add("Decidable.decide", decide_ty)?;
839    let decide_iff_ty = Expr::Pi(
840        Bi::Implicit,
841        Name::str("p"),
842        Box::new(prop()),
843        Box::new(Expr::Pi(
844            Bi::InstImplicit,
845            Name::str("inst"),
846            Box::new(dec_of(Expr::BVar(0))),
847            Box::new(app(
848                app(
849                    cst("Iff"),
850                    app(
851                        app(cst("Eq"), app(cst("Decidable.decide"), Expr::BVar(1))),
852                        cst("Bool.true"),
853                    ),
854                ),
855                Expr::BVar(1),
856            )),
857        )),
858    );
859    add("Decidable.decide_eq_true_iff", decide_iff_ty)?;
860    let by_contra_ty = Expr::Pi(
861        Bi::Implicit,
862        Name::str("p"),
863        Box::new(prop()),
864        Box::new(Expr::Pi(
865            Bi::InstImplicit,
866            Name::str("inst"),
867            Box::new(dec_of(Expr::BVar(0))),
868            Box::new(arr(
869                arr(arr(Expr::BVar(1), cst("False")), cst("False")),
870                Expr::BVar(1),
871            )),
872        )),
873    );
874    add("Decidable.byContradiction", by_contra_ty)?;
875    let em_ty = Expr::Pi(
876        Bi::Implicit,
877        Name::str("p"),
878        Box::new(prop()),
879        Box::new(Expr::Pi(
880            Bi::InstImplicit,
881            Name::str("inst"),
882            Box::new(dec_of(Expr::BVar(0))),
883            Box::new(app(
884                app(cst("Or"), Expr::BVar(1)),
885                arr(Expr::BVar(1), cst("False")),
886            )),
887        )),
888    );
889    add("Decidable.em", em_ty)?;
890    let _ = type1();
891    Ok(())
892}
893pub fn dcs_ext_logical_connective_closure(
894    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
895) -> Result<(), String> {
896    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
897    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
898    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
899    let arr = |a: Expr, b: Expr| -> Expr {
900        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
901    };
902    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
903    let prop = || -> Expr { Expr::Sort(Level::zero()) };
904    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
905    let dec_implies_ty = Expr::Pi(
906        Bi::Implicit,
907        Name::str("p"),
908        Box::new(prop()),
909        Box::new(Expr::Pi(
910            Bi::Implicit,
911            Name::str("q"),
912            Box::new(prop()),
913            Box::new(Expr::Pi(
914                Bi::InstImplicit,
915                Name::str("hp"),
916                Box::new(dec_of(Expr::BVar(1))),
917                Box::new(Expr::Pi(
918                    Bi::InstImplicit,
919                    Name::str("hq"),
920                    Box::new(dec_of(Expr::BVar(1))),
921                    Box::new(dec_of(arr(Expr::BVar(3), Expr::BVar(2)))),
922                )),
923            )),
924        )),
925    );
926    add("instDecidableImplies", dec_implies_ty)?;
927    let dec_iff_ty = Expr::Pi(
928        Bi::Implicit,
929        Name::str("p"),
930        Box::new(prop()),
931        Box::new(Expr::Pi(
932            Bi::Implicit,
933            Name::str("q"),
934            Box::new(prop()),
935            Box::new(Expr::Pi(
936                Bi::InstImplicit,
937                Name::str("hp"),
938                Box::new(dec_of(Expr::BVar(1))),
939                Box::new(Expr::Pi(
940                    Bi::InstImplicit,
941                    Name::str("hq"),
942                    Box::new(dec_of(Expr::BVar(1))),
943                    Box::new(dec_of(app(app(cst("Iff"), Expr::BVar(3)), Expr::BVar(2)))),
944                )),
945            )),
946        )),
947    );
948    add("instDecidableIff", dec_iff_ty)?;
949    let dec_and_ty = Expr::Pi(
950        Bi::Implicit,
951        Name::str("p"),
952        Box::new(prop()),
953        Box::new(Expr::Pi(
954            Bi::Implicit,
955            Name::str("q"),
956            Box::new(prop()),
957            Box::new(arr(
958                dec_of(Expr::BVar(1)),
959                arr(
960                    dec_of(Expr::BVar(1)),
961                    dec_of(app(app(cst("And"), Expr::BVar(3)), Expr::BVar(2))),
962                ),
963            )),
964        )),
965    );
966    add("Decidable.and_of_dec", dec_and_ty)?;
967    let dec_or_ty = Expr::Pi(
968        Bi::Implicit,
969        Name::str("p"),
970        Box::new(prop()),
971        Box::new(Expr::Pi(
972            Bi::Implicit,
973            Name::str("q"),
974            Box::new(prop()),
975            Box::new(arr(
976                dec_of(Expr::BVar(1)),
977                arr(
978                    dec_of(Expr::BVar(1)),
979                    dec_of(app(app(cst("Or"), Expr::BVar(3)), Expr::BVar(2))),
980                ),
981            )),
982        )),
983    );
984    add("Decidable.or_of_dec", dec_or_ty)?;
985    let dec_not_ty = Expr::Pi(
986        Bi::Implicit,
987        Name::str("p"),
988        Box::new(prop()),
989        Box::new(arr(
990            dec_of(Expr::BVar(0)),
991            dec_of(arr(Expr::BVar(1), cst("False"))),
992        )),
993    );
994    add("Decidable.not_of_dec", dec_not_ty)?;
995    let _ = type1();
996    Ok(())
997}
998pub fn dcs_ext_decidable_eq_basic(
999    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1000) -> Result<(), String> {
1001    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1002    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1003    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1004    let arr = |a: Expr, b: Expr| -> Expr {
1005        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1006    };
1007    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1008    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
1009    add("instDecidableEqNat", app(cst("DecidableEq"), cst("Nat")))?;
1010    add("instDecidableEqInt", app(cst("DecidableEq"), cst("Int")))?;
1011    add("instDecidableEqBool", app(cst("DecidableEq"), cst("Bool")))?;
1012    add("instDecidableEqChar", app(cst("DecidableEq"), cst("Char")))?;
1013    add(
1014        "instDecidableEqString",
1015        app(cst("DecidableEq"), cst("String")),
1016    )?;
1017    add("instDecidableEqUnit", app(cst("DecidableEq"), cst("Unit")))?;
1018    let nat_dec_eq_ty = arr(
1019        cst("Nat"),
1020        arr(
1021            cst("Nat"),
1022            dec_of(app(app(cst("Eq"), Expr::BVar(1)), Expr::BVar(0))),
1023        ),
1024    );
1025    add("Nat.decEq", nat_dec_eq_ty)?;
1026    let int_dec_eq_ty = arr(
1027        cst("Int"),
1028        arr(
1029            cst("Int"),
1030            dec_of(app(app(cst("Eq"), Expr::BVar(1)), Expr::BVar(0))),
1031        ),
1032    );
1033    add("Int.decEq", int_dec_eq_ty)?;
1034    let bool_dec_eq_ty = arr(
1035        cst("Bool"),
1036        arr(
1037            cst("Bool"),
1038            dec_of(app(app(cst("Eq"), Expr::BVar(1)), Expr::BVar(0))),
1039        ),
1040    );
1041    add("Bool.decEq", bool_dec_eq_ty)?;
1042    let _ = (type1(), Bi::Default, Name::Anonymous);
1043    Ok(())
1044}
1045pub fn dcs_ext_decidable_eq_compound(
1046    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1047) -> Result<(), String> {
1048    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1049    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1050    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1051    let _arr = |a: Expr, b: Expr| -> Expr {
1052        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1053    };
1054    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1055    let dec_eq_list_ty = Expr::Pi(
1056        Bi::Implicit,
1057        Name::str("α"),
1058        Box::new(type1()),
1059        Box::new(Expr::Pi(
1060            Bi::InstImplicit,
1061            Name::str("inst"),
1062            Box::new(app(cst("DecidableEq"), Expr::BVar(0))),
1063            Box::new(app(cst("DecidableEq"), app(cst("List"), Expr::BVar(1)))),
1064        )),
1065    );
1066    add("instDecidableEqList", dec_eq_list_ty)?;
1067    let dec_eq_opt_ty = Expr::Pi(
1068        Bi::Implicit,
1069        Name::str("α"),
1070        Box::new(type1()),
1071        Box::new(Expr::Pi(
1072            Bi::InstImplicit,
1073            Name::str("inst"),
1074            Box::new(app(cst("DecidableEq"), Expr::BVar(0))),
1075            Box::new(app(cst("DecidableEq"), app(cst("Option"), Expr::BVar(1)))),
1076        )),
1077    );
1078    add("instDecidableEqOption", dec_eq_opt_ty)?;
1079    let dec_eq_prod_ty = Expr::Pi(
1080        Bi::Implicit,
1081        Name::str("α"),
1082        Box::new(type1()),
1083        Box::new(Expr::Pi(
1084            Bi::Implicit,
1085            Name::str("β"),
1086            Box::new(type1()),
1087            Box::new(Expr::Pi(
1088                Bi::InstImplicit,
1089                Name::str("ha"),
1090                Box::new(app(cst("DecidableEq"), Expr::BVar(1))),
1091                Box::new(Expr::Pi(
1092                    Bi::InstImplicit,
1093                    Name::str("hb"),
1094                    Box::new(app(cst("DecidableEq"), Expr::BVar(1))),
1095                    Box::new(app(
1096                        cst("DecidableEq"),
1097                        app(app(cst("Prod"), Expr::BVar(3)), Expr::BVar(2)),
1098                    )),
1099                )),
1100            )),
1101        )),
1102    );
1103    add("instDecidableEqProd", dec_eq_prod_ty)?;
1104    let dec_eq_sum_ty = Expr::Pi(
1105        Bi::Implicit,
1106        Name::str("α"),
1107        Box::new(type1()),
1108        Box::new(Expr::Pi(
1109            Bi::Implicit,
1110            Name::str("β"),
1111            Box::new(type1()),
1112            Box::new(Expr::Pi(
1113                Bi::InstImplicit,
1114                Name::str("ha"),
1115                Box::new(app(cst("DecidableEq"), Expr::BVar(1))),
1116                Box::new(Expr::Pi(
1117                    Bi::InstImplicit,
1118                    Name::str("hb"),
1119                    Box::new(app(cst("DecidableEq"), Expr::BVar(1))),
1120                    Box::new(app(
1121                        cst("DecidableEq"),
1122                        app(app(cst("Sum"), Expr::BVar(3)), Expr::BVar(2)),
1123                    )),
1124                )),
1125            )),
1126        )),
1127    );
1128    add("instDecidableEqSum", dec_eq_sum_ty)?;
1129    Ok(())
1130}
1131pub fn dcs_ext_linear_ordering(
1132    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1133) -> Result<(), String> {
1134    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1135    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1136    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1137    let arr = |a: Expr, b: Expr| -> Expr {
1138        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1139    };
1140    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1141    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
1142    add("DecidableLinearOrder", arr(type1(), type1()))?;
1143    add(
1144        "instDecidableLinearOrderNat",
1145        app(cst("DecidableLinearOrder"), cst("Nat")),
1146    )?;
1147    add(
1148        "instDecidableLinearOrderInt",
1149        app(cst("DecidableLinearOrder"), cst("Int")),
1150    )?;
1151    let nat_dec_lt_ty = arr(
1152        cst("Nat"),
1153        arr(
1154            cst("Nat"),
1155            dec_of(app(app(cst("Nat.lt"), Expr::BVar(1)), Expr::BVar(0))),
1156        ),
1157    );
1158    add("Nat.decLt", nat_dec_lt_ty)?;
1159    let nat_dec_le_ty = arr(
1160        cst("Nat"),
1161        arr(
1162            cst("Nat"),
1163            dec_of(app(app(cst("Nat.le"), Expr::BVar(1)), Expr::BVar(0))),
1164        ),
1165    );
1166    add("Nat.decLe", nat_dec_le_ty)?;
1167    let compare_ty = Expr::Pi(
1168        Bi::Implicit,
1169        Name::str("α"),
1170        Box::new(type1()),
1171        Box::new(Expr::Pi(
1172            Bi::InstImplicit,
1173            Name::str("inst"),
1174            Box::new(app(cst("DecidableLinearOrder"), Expr::BVar(0))),
1175            Box::new(arr(Expr::BVar(1), arr(Expr::BVar(2), cst("Ordering")))),
1176        )),
1177    );
1178    add("Decidable.compare", compare_ty)?;
1179    let min_ty = Expr::Pi(
1180        Bi::Implicit,
1181        Name::str("α"),
1182        Box::new(type1()),
1183        Box::new(Expr::Pi(
1184            Bi::InstImplicit,
1185            Name::str("inst"),
1186            Box::new(app(cst("DecidableLinearOrder"), Expr::BVar(0))),
1187            Box::new(arr(Expr::BVar(1), arr(Expr::BVar(2), Expr::BVar(3)))),
1188        )),
1189    );
1190    add("Decidable.min", min_ty)?;
1191    let max_ty = Expr::Pi(
1192        Bi::Implicit,
1193        Name::str("α"),
1194        Box::new(type1()),
1195        Box::new(Expr::Pi(
1196            Bi::InstImplicit,
1197            Name::str("inst"),
1198            Box::new(app(cst("DecidableLinearOrder"), Expr::BVar(0))),
1199            Box::new(arr(Expr::BVar(1), arr(Expr::BVar(2), Expr::BVar(3)))),
1200        )),
1201    );
1202    add("Decidable.max", max_ty)?;
1203    Ok(())
1204}
1205pub fn dcs_ext_bounded_quantifiers(
1206    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1207) -> Result<(), String> {
1208    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1209    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1210    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1211    let arr = |a: Expr, b: Expr| -> Expr {
1212        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1213    };
1214    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1215    let prop = || -> Expr { Expr::Sort(Level::zero()) };
1216    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
1217    let bool_ty = || -> Expr { cst("Bool") };
1218    let forall_finset_ty = Expr::Pi(
1219        Bi::Implicit,
1220        Name::str("α"),
1221        Box::new(type1()),
1222        Box::new(Expr::Pi(
1223            Bi::InstImplicit,
1224            Name::str("inst"),
1225            Box::new(app(cst("DecidableEq"), Expr::BVar(0))),
1226            Box::new(arr(
1227                arr(Expr::BVar(1), prop()),
1228                arr(
1229                    app(cst("Finset"), Expr::BVar(2)),
1230                    dec_of(Expr::Pi(
1231                        Bi::Default,
1232                        Name::str("x"),
1233                        Box::new(Expr::BVar(2)),
1234                        Box::new(arr(
1235                            app(app(cst("Finset.mem"), Expr::BVar(0)), Expr::BVar(2)),
1236                            app(Expr::BVar(2), Expr::BVar(0)),
1237                        )),
1238                    )),
1239                ),
1240            )),
1241        )),
1242    );
1243    add("Decidable.forallFinset", forall_finset_ty)?;
1244    let exists_finset_ty = Expr::Pi(
1245        Bi::Implicit,
1246        Name::str("α"),
1247        Box::new(type1()),
1248        Box::new(arr(
1249            arr(Expr::BVar(0), prop()),
1250            arr(
1251                app(cst("Finset"), Expr::BVar(1)),
1252                dec_of(app(
1253                    app(cst("Exists"), Expr::BVar(1)),
1254                    arr(
1255                        app(cst("Finset.mem"), Expr::BVar(0)),
1256                        app(Expr::BVar(1), Expr::BVar(0)),
1257                    ),
1258                )),
1259            ),
1260        )),
1261    );
1262    add("Decidable.existsFinset", exists_finset_ty)?;
1263    let forall_range_ty = arr(
1264        cst("Nat"),
1265        arr(
1266            arr(cst("Nat"), bool_ty()),
1267            dec_of(Expr::Pi(
1268                Bi::Default,
1269                Name::str("i"),
1270                Box::new(cst("Nat")),
1271                Box::new(arr(
1272                    app(app(cst("Nat.lt"), Expr::BVar(0)), Expr::BVar(2)),
1273                    app(
1274                        app(cst("Eq"), app(Expr::BVar(1), Expr::BVar(0))),
1275                        cst("Bool.true"),
1276                    ),
1277                )),
1278            )),
1279        ),
1280    );
1281    add("Decidable.forallRange", forall_range_ty)?;
1282    let exists_range_ty = arr(
1283        cst("Nat"),
1284        arr(
1285            arr(cst("Nat"), bool_ty()),
1286            dec_of(app(
1287                app(cst("Exists"), cst("Nat")),
1288                app(
1289                    app(
1290                        cst("And"),
1291                        app(app(cst("Nat.lt"), Expr::BVar(0)), Expr::BVar(2)),
1292                    ),
1293                    app(
1294                        app(cst("Eq"), app(Expr::BVar(1), Expr::BVar(0))),
1295                        cst("Bool.true"),
1296                    ),
1297                ),
1298            )),
1299        ),
1300    );
1301    add("Decidable.existsRange", exists_range_ty)?;
1302    Ok(())
1303}
1304pub fn dcs_ext_lem_boolean_reflection(
1305    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1306) -> Result<(), String> {
1307    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1308    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1309    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1310    let arr = |a: Expr, b: Expr| -> Expr {
1311        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1312    };
1313    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1314    let prop = || -> Expr { Expr::Sort(Level::zero()) };
1315    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
1316    let bool_ty = || -> Expr { cst("Bool") };
1317    let lem_dec_ty = Expr::Pi(
1318        Bi::Implicit,
1319        Name::str("p"),
1320        Box::new(prop()),
1321        Box::new(arr(
1322            dec_of(Expr::BVar(0)),
1323            app(
1324                app(cst("Or"), Expr::BVar(1)),
1325                arr(Expr::BVar(1), cst("False")),
1326            ),
1327        )),
1328    );
1329    add("LEM_from_Decidable", lem_dec_ty)?;
1330    let reflect_ty = Expr::Pi(
1331        Bi::Implicit,
1332        Name::str("p"),
1333        Box::new(prop()),
1334        Box::new(Expr::Pi(
1335            Bi::InstImplicit,
1336            Name::str("inst"),
1337            Box::new(dec_of(Expr::BVar(0))),
1338            Box::new(arr(
1339                bool_ty(),
1340                app(
1341                    app(
1342                        cst("Iff"),
1343                        app(app(cst("Eq"), Expr::BVar(0)), cst("Bool.true")),
1344                    ),
1345                    Expr::BVar(2),
1346                ),
1347            )),
1348        )),
1349    );
1350    add("Bool.reflect", reflect_ty)?;
1351    let decide_reflect_ty = Expr::Pi(
1352        Bi::Implicit,
1353        Name::str("p"),
1354        Box::new(prop()),
1355        Box::new(Expr::Pi(
1356            Bi::InstImplicit,
1357            Name::str("inst"),
1358            Box::new(dec_of(Expr::BVar(0))),
1359            Box::new(app(
1360                app(
1361                    cst("Iff"),
1362                    app(
1363                        app(cst("Eq"), app(cst("Decidable.decide"), Expr::BVar(1))),
1364                        cst("Bool.true"),
1365                    ),
1366                ),
1367                Expr::BVar(1),
1368            )),
1369        )),
1370    );
1371    add("Bool.decide_reflect", decide_reflect_ty)?;
1372    let prop_decidable_ty = Expr::Pi(
1373        Bi::Implicit,
1374        Name::str("p"),
1375        Box::new(prop()),
1376        Box::new(dec_of(Expr::BVar(0))),
1377    );
1378    add("Classical.propDecidable", prop_decidable_ty)?;
1379    let classical_em_ty = Expr::Pi(
1380        Bi::Default,
1381        Name::str("p"),
1382        Box::new(prop()),
1383        Box::new(app(
1384            app(cst("Or"), Expr::BVar(0)),
1385            arr(Expr::BVar(0), cst("False")),
1386        )),
1387    );
1388    add("Classical.em", classical_em_ty)?;
1389    let _ = type1();
1390    Ok(())
1391}
1392pub fn dcs_ext_semi_decidability(
1393    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1394) -> Result<(), String> {
1395    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1396    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1397    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1398    let arr = |a: Expr, b: Expr| -> Expr {
1399        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1400    };
1401    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1402    let prop = || -> Expr { Expr::Sort(Level::zero()) };
1403    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
1404    add("SemiDecidable", arr(prop(), type1()))?;
1405    let to_semi_ty = Expr::Pi(
1406        Bi::Implicit,
1407        Name::str("p"),
1408        Box::new(prop()),
1409        Box::new(arr(
1410            dec_of(Expr::BVar(0)),
1411            app(cst("SemiDecidable"), Expr::BVar(1)),
1412        )),
1413    );
1414    add("Decidable.toSemiDecidable", to_semi_ty)?;
1415    let semi_and_ty = Expr::Pi(
1416        Bi::Implicit,
1417        Name::str("p"),
1418        Box::new(prop()),
1419        Box::new(Expr::Pi(
1420            Bi::Implicit,
1421            Name::str("q"),
1422            Box::new(prop()),
1423            Box::new(arr(
1424                app(cst("SemiDecidable"), Expr::BVar(1)),
1425                arr(
1426                    app(cst("SemiDecidable"), Expr::BVar(1)),
1427                    app(
1428                        cst("SemiDecidable"),
1429                        app(app(cst("And"), Expr::BVar(3)), Expr::BVar(2)),
1430                    ),
1431                ),
1432            )),
1433        )),
1434    );
1435    add("SemiDecidable.and", semi_and_ty)?;
1436    let semi_or_ty = Expr::Pi(
1437        Bi::Implicit,
1438        Name::str("p"),
1439        Box::new(prop()),
1440        Box::new(Expr::Pi(
1441            Bi::Implicit,
1442            Name::str("q"),
1443            Box::new(prop()),
1444            Box::new(arr(
1445                app(cst("SemiDecidable"), Expr::BVar(1)),
1446                arr(
1447                    app(cst("SemiDecidable"), Expr::BVar(1)),
1448                    app(
1449                        cst("SemiDecidable"),
1450                        app(app(cst("Or"), Expr::BVar(3)), Expr::BVar(2)),
1451                    ),
1452                ),
1453            )),
1454        )),
1455    );
1456    add("SemiDecidable.or", semi_or_ty)?;
1457    let semi_nn_ty = Expr::Pi(
1458        Bi::Implicit,
1459        Name::str("p"),
1460        Box::new(prop()),
1461        Box::new(arr(
1462            app(cst("SemiDecidable"), Expr::BVar(0)),
1463            app(
1464                cst("SemiDecidable"),
1465                arr(arr(Expr::BVar(1), cst("False")), cst("False")),
1466            ),
1467        )),
1468    );
1469    add("SemiDecidable.not_not", semi_nn_ty)?;
1470    Ok(())
1471}
1472pub fn dcs_ext_undecidability_halting(
1473    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1474) -> Result<(), String> {
1475    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1476    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1477    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1478    let arr = |a: Expr, b: Expr| -> Expr {
1479        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1480    };
1481    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1482    let prop = || -> Expr { Expr::Sort(Level::zero()) };
1483    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
1484    let halting_ty = arr(
1485        arr(cst("Nat"), app(cst("Option"), cst("Nat"))),
1486        arr(cst("Nat"), prop()),
1487    );
1488    add("HaltingProblem", halting_ty)?;
1489    add("HaltingProblem.undecidable", prop())?;
1490    add("Rice.theorem", prop())?;
1491    add("Decidable.computability_implies_decidable", prop())?;
1492    let semi_dec_halting_ty = Expr::Pi(
1493        Bi::Default,
1494        Name::str("p"),
1495        Box::new(arr(cst("Nat"), app(cst("Option"), cst("Nat")))),
1496        Box::new(Expr::Pi(
1497            Bi::Default,
1498            Name::str("n"),
1499            Box::new(cst("Nat")),
1500            Box::new(app(
1501                cst("SemiDecidable"),
1502                app(app(cst("HaltingProblem"), Expr::BVar(1)), Expr::BVar(0)),
1503            )),
1504        )),
1505    );
1506    add("HaltingProblem.semi_decidable", semi_dec_halting_ty)?;
1507    add("Rice.corollary_extensional", prop())?;
1508    let _ = (type1(), dec_of(cst("P")));
1509    Ok(())
1510}
1511pub fn dcs_ext_presburger_arithmetic(
1512    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1513) -> Result<(), String> {
1514    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1515    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1516    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1517    let arr = |a: Expr, b: Expr| -> Expr {
1518        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1519    };
1520    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1521    let prop = || -> Expr { Expr::Sort(Level::zero()) };
1522    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
1523    add("PresburgerFormula", type1())?;
1524    let pres_decide_ty = arr(cst("PresburgerFormula"), cst("Bool"));
1525    add("Presburger.decide", pres_decide_ty)?;
1526    let pres_sound_ty = arr(
1527        cst("PresburgerFormula"),
1528        arr(
1529            app(
1530                app(cst("Eq"), app(cst("Presburger.decide"), Expr::BVar(0))),
1531                cst("Bool.true"),
1532            ),
1533            app(cst("PresburgerFormula.holds"), Expr::BVar(1)),
1534        ),
1535    );
1536    add("Presburger.decide_sound", pres_sound_ty)?;
1537    let pres_complete_ty = arr(
1538        cst("PresburgerFormula"),
1539        arr(
1540            app(cst("PresburgerFormula.holds"), Expr::BVar(0)),
1541            app(
1542                app(cst("Eq"), app(cst("Presburger.decide"), Expr::BVar(1))),
1543                cst("Bool.true"),
1544            ),
1545        ),
1546    );
1547    add("Presburger.decide_complete", pres_complete_ty)?;
1548    let pres_decidable_ty = arr(
1549        cst("PresburgerFormula"),
1550        dec_of(app(cst("PresburgerFormula.holds"), Expr::BVar(0))),
1551    );
1552    add("Presburger.decidable", pres_decidable_ty)?;
1553    let add_comm_dec_ty = arr(
1554        cst("Nat"),
1555        arr(
1556            cst("Nat"),
1557            dec_of(app(
1558                app(
1559                    cst("Eq"),
1560                    app(app(cst("Nat.add"), Expr::BVar(1)), Expr::BVar(0)),
1561                ),
1562                app(app(cst("Nat.add"), Expr::BVar(0)), Expr::BVar(1)),
1563            )),
1564        ),
1565    );
1566    add("Nat.add_comm_decidable", add_comm_dec_ty)?;
1567    let _ = prop();
1568    Ok(())
1569}
1570pub fn dcs_ext_dpll_procedure(
1571    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1572) -> Result<(), String> {
1573    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1574    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1575    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1576    let arr = |a: Expr, b: Expr| -> Expr {
1577        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1578    };
1579    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1580    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
1581    let bool_ty = || -> Expr { cst("Bool") };
1582    add("CNFFormula", type1())?;
1583    let dpll_solve_ty = arr(cst("CNFFormula"), bool_ty());
1584    add("DPLL.solve", dpll_solve_ty)?;
1585    let dpll_sound_ty = arr(
1586        cst("CNFFormula"),
1587        arr(
1588            app(
1589                app(cst("Eq"), app(cst("DPLL.solve"), Expr::BVar(0))),
1590                cst("Bool.true"),
1591            ),
1592            app(cst("CNFFormula.satisfiable"), Expr::BVar(1)),
1593        ),
1594    );
1595    add("DPLL.sound", dpll_sound_ty)?;
1596    let dpll_complete_ty = arr(
1597        cst("CNFFormula"),
1598        arr(
1599            app(cst("CNFFormula.satisfiable"), Expr::BVar(0)),
1600            app(
1601                app(cst("Eq"), app(cst("DPLL.solve"), Expr::BVar(1))),
1602                cst("Bool.true"),
1603            ),
1604        ),
1605    );
1606    add("DPLL.complete", dpll_complete_ty)?;
1607    let dpll_dec_ty = arr(
1608        cst("CNFFormula"),
1609        dec_of(app(cst("CNFFormula.satisfiable"), Expr::BVar(0))),
1610    );
1611    add("DPLL.decidable_sat", dpll_dec_ty)?;
1612    let tautology_ty = arr(cst("CNFFormula"), cst("Prop"));
1613    add("Propositional.Tautology", tautology_ty)?;
1614    let dec_taut_ty = arr(
1615        cst("CNFFormula"),
1616        dec_of(app(cst("Propositional.Tautology"), Expr::BVar(0))),
1617    );
1618    add("Propositional.decidable_tautology", dec_taut_ty)?;
1619    Ok(())
1620}
1621pub fn dcs_ext_constructive_markov(
1622    add: &mut impl FnMut(&str, oxilean_kernel::Expr) -> Result<(), String>,
1623) -> Result<(), String> {
1624    use super::functions::*;
1625    use oxilean_kernel::{BinderInfo as Bi, Expr, Level, Name};
1626    use std::fmt;
1627    let cst = |s: &str| -> Expr { Expr::Const(Name::str(s), vec![]) };
1628    let app = |f: Expr, a: Expr| -> Expr { Expr::App(Box::new(f), Box::new(a)) };
1629    let arr = |a: Expr, b: Expr| -> Expr {
1630        Expr::Pi(Bi::Default, Name::Anonymous, Box::new(a), Box::new(b))
1631    };
1632    let type1 = || -> Expr { Expr::Sort(Level::succ(Level::zero())) };
1633    let prop = || -> Expr { Expr::Sort(Level::zero()) };
1634    let dec_of = |p: Expr| -> Expr { app(cst("Decidable"), p) };
1635    let markov_ty = Expr::Pi(
1636        Bi::Default,
1637        Name::str("p"),
1638        Box::new(arr(cst("Nat"), cst("Bool"))),
1639        Box::new(arr(
1640            arr(
1641                arr(
1642                    app(
1643                        app(cst("Exists"), cst("Nat")),
1644                        app(
1645                            app(cst("Eq"), app(Expr::BVar(1), Expr::BVar(0))),
1646                            cst("Bool.true"),
1647                        ),
1648                    ),
1649                    cst("False"),
1650                ),
1651                cst("False"),
1652            ),
1653            app(
1654                app(cst("Exists"), cst("Nat")),
1655                app(
1656                    app(cst("Eq"), app(Expr::BVar(1), Expr::BVar(0))),
1657                    cst("Bool.true"),
1658                ),
1659            ),
1660        )),
1661    );
1662    add("Markov.principle", markov_ty)?;
1663    add("ChurchThesis", arr(arr(cst("Nat"), cst("Nat")), prop()))?;
1664    let church_ty = Expr::Pi(
1665        Bi::Default,
1666        Name::str("f"),
1667        Box::new(arr(cst("Nat"), cst("Nat"))),
1668        Box::new(app(
1669            app(cst("Exists"), cst("Nat")),
1670            app(app(cst("Computes"), Expr::BVar(0)), Expr::BVar(1)),
1671        )),
1672    );
1673    add("Church.thesis", church_ty)?;
1674    let cons_dec_finite_ty = Expr::Pi(
1675        Bi::Implicit,
1676        Name::str("α"),
1677        Box::new(type1()),
1678        Box::new(arr(
1679            app(cst("Finset"), Expr::BVar(0)),
1680            arr(
1681                arr(Expr::BVar(1), prop()),
1682                dec_of(Expr::Pi(
1683                    Bi::Default,
1684                    Name::str("x"),
1685                    Box::new(Expr::BVar(1)),
1686                    Box::new(arr(
1687                        app(app(cst("Finset.mem"), Expr::BVar(0)), Expr::BVar(2)),
1688                        app(Expr::BVar(2), Expr::BVar(0)),
1689                    )),
1690                )),
1691            ),
1692        )),
1693    );
1694    add("Constructive.decidable_finite", cons_dec_finite_ty)?;
1695    let witness_ty = Expr::Pi(
1696        Bi::Implicit,
1697        Name::str("p"),
1698        Box::new(arr(cst("Nat"), prop())),
1699        Box::new(arr(
1700            app(
1701                app(cst("Exists"), cst("Nat")),
1702                app(Expr::BVar(1), Expr::BVar(0)),
1703            ),
1704            app(
1705                app(cst("Sigma"), cst("Nat")),
1706                app(Expr::BVar(1), Expr::BVar(0)),
1707            ),
1708        )),
1709    );
1710    add("Constructive.witness_extraction", witness_ty)?;
1711    Ok(())
1712}