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