1use super::types::{
6 BoolReflect, DecidableCounter, Decision, DecisionChain, DecisionTable, EqDecision, FiniteSet,
7 FnPred, Interval, LeDecision, NamedDecision, Not,
8};
9use oxilean_kernel::Node;
10
11pub trait Decidable {
16 type Proof;
18 fn decide(&self) -> Decision<Self::Proof>;
20 fn is_decidably_true(&self) -> bool {
22 self.decide().is_true()
23 }
24}
25pub trait DecidablePred<A> {
29 fn decide_pred(&self, a: &A) -> Decision<()>;
31 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 fn any_slice(&self, xs: &[A]) -> bool {
39 xs.iter().any(|x| self.decide_pred(x).is_true())
40 }
41 fn all_slice(&self, xs: &[A]) -> bool {
43 xs.iter().all(|x| self.decide_pred(x).is_true())
44 }
45 fn count_slice(&self, xs: &[A]) -> usize {
47 xs.iter().filter(|x| self.decide_pred(x).is_true()).count()
48 }
49}
50pub trait DecidableRel<A> {
52 fn decide_rel(&self, a: &A, b: &A) -> Decision<()>;
54 fn holds(&self, a: &A, b: &A) -> bool {
56 self.decide_rel(a, b).is_true()
57 }
58}
59pub 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}
67pub 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}
75pub 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}
83pub 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}
91pub 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}
98pub 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}
106pub 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}
114pub 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}
122pub fn decision_and<P, Q>(dp: Decision<P>, dq: Decision<Q>) -> Decision<(P, Q)> {
124 dp.and(dq)
125}
126pub fn decision_or<P>(dp: Decision<P>, dq: Decision<P>) -> Decision<P> {
128 dp.or(dq)
129}
130pub fn decision_not<P: std::fmt::Debug>(dp: Decision<P>) -> Decision<String> {
132 dp.negate()
133}
134pub fn decision_implies<P, Q>(dp: Decision<P>, f: impl FnOnce(P) -> Decision<Q>) -> Decision<Q> {
136 dp.flat_map(f)
137}
138pub 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}
147pub 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}
158pub 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}
166pub 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}
174pub 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}
182pub 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}
351pub 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}
359pub 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}
367pub 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}
375pub 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}
383pub 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}
391pub 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}
399pub 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}
407pub 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}
419pub 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}
426pub fn decision_to_result(d: Decision<()>) -> Result<(), String> {
428 match d {
429 Decision::IsTrue(()) => Ok(()),
430 Decision::IsFalse(msg) => Err(msg),
431 }
432}
433pub 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}
492pub 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}
622pub 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}
630pub 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}
638pub 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}
646pub 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}