1use super::types::{
6 BoolReflect, DecidableCounter, Decision, DecisionChain, DecisionTable, EqDecision, FiniteSet,
7 FnPred, Interval, LeDecision, NamedDecision, Not,
8};
9
10pub trait Decidable {
15 type Proof;
17 fn decide(&self) -> Decision<Self::Proof>;
19 fn is_decidably_true(&self) -> bool {
21 self.decide().is_true()
22 }
23}
24pub trait DecidablePred<A> {
28 fn decide_pred(&self, a: &A) -> Decision<()>;
30 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 fn any_slice(&self, xs: &[A]) -> bool {
38 xs.iter().any(|x| self.decide_pred(x).is_true())
39 }
40 fn all_slice(&self, xs: &[A]) -> bool {
42 xs.iter().all(|x| self.decide_pred(x).is_true())
43 }
44 fn count_slice(&self, xs: &[A]) -> usize {
46 xs.iter().filter(|x| self.decide_pred(x).is_true()).count()
47 }
48}
49pub trait DecidableRel<A> {
51 fn decide_rel(&self, a: &A, b: &A) -> Decision<()>;
53 fn holds(&self, a: &A, b: &A) -> bool {
55 self.decide_rel(a, b).is_true()
56 }
57}
58pub 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}
66pub 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}
74pub 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}
82pub 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}
90pub 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}
97pub 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}
105pub 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}
113pub 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}
121pub fn decision_and<P, Q>(dp: Decision<P>, dq: Decision<Q>) -> Decision<(P, Q)> {
123 dp.and(dq)
124}
125pub fn decision_or<P>(dp: Decision<P>, dq: Decision<P>) -> Decision<P> {
127 dp.or(dq)
128}
129pub fn decision_not<P: std::fmt::Debug>(dp: Decision<P>) -> Decision<String> {
131 dp.negate()
132}
133pub fn decision_implies<P, Q>(dp: Decision<P>, f: impl FnOnce(P) -> Decision<Q>) -> Decision<Q> {
135 dp.flat_map(f)
136}
137pub 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}
146pub 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}
157pub 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}
165pub 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}
173pub 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}
181pub 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}
350pub 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}
358pub 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}
366pub 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}
374pub 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}
382pub 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}
390pub 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}
398pub 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}
406pub 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}
418pub 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}
425pub fn decision_to_result(d: Decision<()>) -> Result<(), String> {
427 match d {
428 Decision::IsTrue(()) => Ok(()),
429 Decision::IsFalse(msg) => Err(msg),
430 }
431}
432pub 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}
491pub 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}
621pub 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}
629pub 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}
637pub 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}
645pub 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}