1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8 Clause, Combinator, CutEliminator, Formula, HerbrandInstance, HerbrandInstanceGenerator,
9 HerbrandTerm, LKNode, LKRule, NDTerm, ResolutionProver, Sequent, SequentCalculusProof,
10};
11
12pub(super) fn app(f: Expr, a: Expr) -> Expr {
13 Expr::App(Box::new(f), Box::new(a))
14}
15pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
16 app(app(f, a), b)
17}
18pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
19 app(app2(f, a, b), c)
20}
21pub fn cst(s: &str) -> Expr {
22 Expr::Const(Name::str(s), vec![])
23}
24pub fn prop() -> Expr {
25 Expr::Sort(Level::zero())
26}
27pub fn type0() -> Expr {
28 Expr::Sort(Level::succ(Level::zero()))
29}
30pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
31 Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
32}
33pub fn arrow(a: Expr, b: Expr) -> Expr {
34 pi(BinderInfo::Default, "_", a, b)
35}
36pub fn impl_pi(name: &str, dom: Expr, body: Expr) -> Expr {
37 pi(BinderInfo::Implicit, name, dom, body)
38}
39pub fn bvar(n: u32) -> Expr {
40 Expr::BVar(n)
41}
42pub fn nat_ty() -> Expr {
43 cst("Nat")
44}
45pub fn bool_ty() -> Expr {
46 cst("Bool")
47}
48pub fn list_ty(elem: Expr) -> Expr {
49 app(cst("List"), elem)
50}
51pub fn sequent_ty() -> Expr {
53 type0()
54}
55pub fn derivation_ty() -> Expr {
57 arrow(sequent_ty(), type0())
58}
59pub fn cut_rule_ty() -> Expr {
61 let seq = sequent_ty();
62 arrow(seq.clone(), arrow(seq.clone(), arrow(seq, prop())))
63}
64pub fn natural_deduction_ty() -> Expr {
66 type0()
67}
68pub fn lambda_term_ty() -> Expr {
70 arrow(type0(), type0())
71}
72pub fn normal_form_ty() -> Expr {
74 arrow(type0(), prop())
75}
76pub fn cut_elimination_ty() -> Expr {
79 let seq = cst("Sequent");
80 impl_pi(
81 "seq",
82 seq.clone(),
83 arrow(
84 app(cst("Derivable"), bvar(0)),
85 app(cst("CutFreeDerivable"), bvar(1)),
86 ),
87 )
88}
89pub fn subformula_property_ty() -> Expr {
92 let seq = cst("Sequent");
93 impl_pi(
94 "seq",
95 seq.clone(),
96 arrow(
97 app(cst("CutFreeDerivable"), bvar(0)),
98 app(cst("SubformulasClosed"), bvar(1)),
99 ),
100 )
101}
102pub fn normalization_ty() -> Expr {
105 impl_pi(
106 "t",
107 cst("LambdaTerm"),
108 arrow(
109 app(cst("WellTyped"), bvar(0)),
110 app(cst("StronglyNormalizing"), bvar(1)),
111 ),
112 )
113}
114pub fn consistency_ty() -> Expr {
117 arrow(app(cst("Provable"), cst("FalseFormula")), cst("False"))
118}
119pub fn completeness_propositional_ty() -> Expr {
122 impl_pi(
123 "f",
124 cst("Formula"),
125 arrow(
126 app(cst("Tautology"), bvar(0)),
127 app(cst("Provable"), bvar(1)),
128 ),
129 )
130}
131pub fn curry_howard_ty() -> Expr {
134 impl_pi(
135 "P",
136 prop(),
137 app2(
138 cst("Iff"),
139 app(cst("Proof"), bvar(0)),
140 app2(
141 cst("Exists"),
142 cst("LambdaTerm"),
143 app(cst("HasType"), bvar(1)),
144 ),
145 ),
146 )
147}
148pub fn lk_derivable_ty() -> Expr {
151 arrow(cst("Sequent"), prop())
152}
153pub fn lj_derivable_ty() -> Expr {
156 arrow(cst("Sequent"), prop())
157}
158pub fn lk_init_ty() -> Expr {
161 impl_pi(
162 "A",
163 cst("Formula"),
164 app(cst("LKDerivable"), app(cst("AxiomSeq"), bvar(0))),
165 )
166}
167pub fn lk_left_contraction_ty() -> Expr {
170 impl_pi(
171 "s",
172 cst("Sequent"),
173 impl_pi(
174 "t",
175 cst("Sequent"),
176 arrow(
177 app(cst("LKDerivable"), bvar(1)),
178 app(cst("LKDerivable"), bvar(1)),
179 ),
180 ),
181 )
182}
183pub fn lk_right_weakening_ty() -> Expr {
186 impl_pi(
187 "s",
188 cst("Sequent"),
189 impl_pi(
190 "A",
191 cst("Formula"),
192 arrow(
193 app(cst("LKDerivable"), bvar(1)),
194 app(
195 cst("LKDerivable"),
196 app2(cst("WeakenRight"), bvar(2), bvar(0)),
197 ),
198 ),
199 ),
200 )
201}
202pub fn lk_and_left1_ty() -> Expr {
205 impl_pi(
206 "s",
207 cst("Sequent"),
208 impl_pi(
209 "t",
210 cst("Sequent"),
211 arrow(
212 app(cst("LKDerivable"), bvar(1)),
213 app(cst("LKDerivable"), bvar(1)),
214 ),
215 ),
216 )
217}
218pub fn lk_and_right_ty() -> Expr {
221 impl_pi(
222 "s1",
223 cst("Sequent"),
224 impl_pi(
225 "s2",
226 cst("Sequent"),
227 impl_pi(
228 "s3",
229 cst("Sequent"),
230 arrow(
231 app(cst("LKDerivable"), bvar(2)),
232 arrow(
233 app(cst("LKDerivable"), bvar(2)),
234 app(cst("LKDerivable"), bvar(1)),
235 ),
236 ),
237 ),
238 ),
239 )
240}
241pub fn lk_cut_ty() -> Expr {
244 impl_pi(
245 "s1",
246 cst("Sequent"),
247 impl_pi(
248 "s2",
249 cst("Sequent"),
250 impl_pi(
251 "s3",
252 cst("Sequent"),
253 impl_pi(
254 "A",
255 cst("Formula"),
256 arrow(
257 app(cst("LKDerivable"), bvar(3)),
258 arrow(
259 app(cst("LKDerivable"), bvar(3)),
260 app(cst("LKDerivable"), bvar(2)),
261 ),
262 ),
263 ),
264 ),
265 ),
266 )
267}
268pub fn lj_imp_left_ty() -> Expr {
271 impl_pi(
272 "s1",
273 cst("Sequent"),
274 impl_pi(
275 "s2",
276 cst("Sequent"),
277 impl_pi(
278 "s3",
279 cst("Sequent"),
280 arrow(
281 app(cst("LJDerivable"), bvar(2)),
282 arrow(
283 app(cst("LJDerivable"), bvar(2)),
284 app(cst("LJDerivable"), bvar(1)),
285 ),
286 ),
287 ),
288 ),
289 )
290}
291pub fn lj_imp_right_ty() -> Expr {
294 impl_pi(
295 "s",
296 cst("Sequent"),
297 impl_pi(
298 "t",
299 cst("Sequent"),
300 arrow(
301 app(cst("LJDerivable"), bvar(1)),
302 app(cst("LJDerivable"), bvar(1)),
303 ),
304 ),
305 )
306}
307pub fn nd_imp_intro_ty() -> Expr {
310 impl_pi(
311 "A",
312 cst("Formula"),
313 impl_pi(
314 "B",
315 cst("Formula"),
316 arrow(
317 app2(
318 cst("NDDerivable"),
319 app2(cst("Cons"), bvar(1), cst("EmptyCtx")),
320 bvar(1),
321 ),
322 app2(
323 cst("NDDerivable"),
324 cst("EmptyCtx"),
325 app2(cst("ImpForm"), bvar(2), bvar(1)),
326 ),
327 ),
328 ),
329 )
330}
331pub fn nd_imp_elim_ty() -> Expr {
335 impl_pi(
336 "ctx",
337 cst("Context"),
338 impl_pi(
339 "A",
340 cst("Formula"),
341 impl_pi(
342 "B",
343 cst("Formula"),
344 arrow(
345 app2(
346 cst("NDDerivable"),
347 bvar(2),
348 app2(cst("ImpForm"), bvar(1), bvar(0)),
349 ),
350 arrow(
351 app2(cst("NDDerivable"), bvar(3), bvar(2)),
352 app2(cst("NDDerivable"), bvar(4), bvar(2)),
353 ),
354 ),
355 ),
356 ),
357 )
358}
359pub fn nd_and_intro_ty() -> Expr {
363 impl_pi(
364 "ctx",
365 cst("Context"),
366 impl_pi(
367 "A",
368 cst("Formula"),
369 impl_pi(
370 "B",
371 cst("Formula"),
372 arrow(
373 app2(cst("NDDerivable"), bvar(2), bvar(1)),
374 arrow(
375 app2(cst("NDDerivable"), bvar(3), bvar(1)),
376 app2(
377 cst("NDDerivable"),
378 bvar(4),
379 app2(cst("AndForm"), bvar(2), bvar(1)),
380 ),
381 ),
382 ),
383 ),
384 ),
385 )
386}
387pub fn nd_and_elim_left_ty() -> Expr {
391 impl_pi(
392 "ctx",
393 cst("Context"),
394 impl_pi(
395 "A",
396 cst("Formula"),
397 impl_pi(
398 "B",
399 cst("Formula"),
400 arrow(
401 app2(
402 cst("NDDerivable"),
403 bvar(2),
404 app2(cst("AndForm"), bvar(1), bvar(0)),
405 ),
406 app2(cst("NDDerivable"), bvar(3), bvar(2)),
407 ),
408 ),
409 ),
410 )
411}
412pub fn nd_or_intro_left_ty() -> Expr {
416 impl_pi(
417 "ctx",
418 cst("Context"),
419 impl_pi(
420 "A",
421 cst("Formula"),
422 impl_pi(
423 "B",
424 cst("Formula"),
425 arrow(
426 app2(cst("NDDerivable"), bvar(2), bvar(1)),
427 app2(
428 cst("NDDerivable"),
429 bvar(3),
430 app2(cst("OrForm"), bvar(2), bvar(1)),
431 ),
432 ),
433 ),
434 ),
435 )
436}
437pub fn ordinal_ty() -> Expr {
439 type0()
440}
441pub fn epsilon_zero_ty() -> Expr {
444 cst("Ordinal")
445}
446pub fn proof_theoretic_ordinal_ty() -> Expr {
449 arrow(cst("ProofSystem"), cst("Ordinal"))
450}
451pub fn pa_ordinal_epsilon_zero_ty() -> Expr {
454 app3(
455 cst("Eq"),
456 cst("Ordinal"),
457 app(cst("ProofTheoreticOrdinal"), cst("PA")),
458 cst("EpsilonZero"),
459 )
460}
461pub fn ordinal_induction_epsilon_zero_ty() -> Expr {
467 impl_pi(
468 "P",
469 arrow(cst("Ordinal"), prop()),
470 arrow(
471 impl_pi(
472 "alpha",
473 cst("Ordinal"),
474 arrow(
475 impl_pi(
476 "beta",
477 cst("Ordinal"),
478 arrow(app2(cst("OrdLt"), bvar(0), bvar(1)), app(bvar(3), bvar(1))),
479 ),
480 app(bvar(2), bvar(1)),
481 ),
482 ),
483 impl_pi(
484 "alpha",
485 cst("Ordinal"),
486 arrow(
487 app2(cst("OrdLt"), bvar(0), cst("EpsilonZero")),
488 app(bvar(3), bvar(1)),
489 ),
490 ),
491 ),
492 )
493}
494pub fn gentzen_consistency_ty() -> Expr {
497 app(cst("ConsistentSystem"), cst("PA"))
498}
499pub fn gentzen_hauptsatz_ty() -> Expr {
502 impl_pi(
503 "s",
504 cst("Sequent"),
505 arrow(
506 app(cst("LKDerivable"), bvar(0)),
507 app(cst("CutFreeLKDerivable"), bvar(1)),
508 ),
509 )
510}
511pub fn godel_first_incompleteness_ty() -> Expr {
515 impl_pi(
516 "S",
517 cst("ConsistentRecEnum"),
518 app2(
519 cst("Exists"),
520 cst("Sentence"),
521 app2(
522 cst("And"),
523 app2(cst("NotProvable"), bvar(1), bvar(0)),
524 app2(cst("NotProvable"), bvar(2), app(cst("NegForm"), bvar(1))),
525 ),
526 ),
527 )
528}
529pub fn godel_second_incompleteness_ty() -> Expr {
532 arrow(
533 app2(cst("ProvableIn"), cst("PA"), cst("ConPa")),
534 cst("False"),
535 )
536}
537pub fn rosser_sentence_ty() -> Expr {
540 impl_pi(
541 "S",
542 cst("ConsistentRecEnum"),
543 app2(
544 cst("Exists"),
545 cst("Sentence"),
546 app2(
547 cst("And"),
548 arrow(app2(cst("ProvableIn"), bvar(1), bvar(0)), cst("False")),
549 arrow(
550 app2(cst("ProvableIn"), bvar(2), app(cst("NegForm"), bvar(1))),
551 cst("False"),
552 ),
553 ),
554 ),
555 )
556}
557pub fn diagonal_lemma_ty() -> Expr {
561 impl_pi(
562 "phi",
563 arrow(cst("Formula"), cst("Formula")),
564 app2(
565 cst("Exists"),
566 cst("Sentence"),
567 app2(
568 cst("ProvableIn"),
569 cst("PA"),
570 app2(
571 cst("IffForm"),
572 bvar(0),
573 app(bvar(2), app(cst("GodelNum"), bvar(1))),
574 ),
575 ),
576 ),
577 )
578}
579pub fn tarski_undefinability_ty() -> Expr {
582 arrow(
583 app2(
584 cst("Exists"),
585 arrow(cst("Formula"), bool_ty()),
586 impl_pi(
587 "psi",
588 cst("Sentence"),
589 app2(
590 cst("Iff"),
591 app2(
592 cst("BoolEq"),
593 app(bvar(1), app(cst("GodelNum"), bvar(0))),
594 cst("BoolTrue"),
595 ),
596 app2(cst("TrueIn"), cst("StandardModel"), bvar(1)),
597 ),
598 ),
599 ),
600 cst("False"),
601 )
602}
603pub fn godel_completeness_ty() -> Expr {
607 impl_pi(
608 "T",
609 cst("Theory"),
610 impl_pi(
611 "phi",
612 cst("Formula"),
613 arrow(
614 app2(cst("Entails"), bvar(1), bvar(0)),
615 app2(cst("ProvableIn"), bvar(2), bvar(1)),
616 ),
617 ),
618 )
619}
620pub fn henkin_completeness_ty() -> Expr {
623 impl_pi(
624 "T",
625 cst("Theory"),
626 arrow(
627 app(cst("ConsistentTheory"), bvar(0)),
628 app2(cst("Exists"), cst("Model"), app(cst("ModelOf"), bvar(1))),
629 ),
630 )
631}
632pub fn compactness_ty() -> Expr {
637 impl_pi(
638 "T",
639 cst("Theory"),
640 arrow(
641 impl_pi(
642 "Delta",
643 cst("Theory"),
644 arrow(
645 app2(cst("FiniteSubset"), bvar(0), bvar(1)),
646 app2(cst("Exists"), cst("Model"), app(cst("ModelOf"), bvar(1))),
647 ),
648 ),
649 app2(cst("Exists"), cst("Model"), app(cst("ModelOf"), bvar(1))),
650 ),
651 )
652}
653pub fn herbrand_theorem_ty() -> Expr {
657 impl_pi(
658 "T",
659 cst("UniversalTheory"),
660 app2(
661 cst("Iff"),
662 arrow(app(cst("Satisfiable"), bvar(0)), cst("False")),
663 app2(
664 cst("Exists"),
665 cst("HerbrandInstance"),
666 app(app(cst("Refutes"), bvar(0)), bvar(2)),
667 ),
668 ),
669 )
670}
671pub fn craig_interpolation_ty() -> Expr {
676 impl_pi(
677 "A",
678 cst("Formula"),
679 impl_pi(
680 "B",
681 cst("Formula"),
682 arrow(
683 app(cst("Tautology"), app2(cst("ImpForm"), bvar(1), bvar(0))),
684 app2(
685 cst("Exists"),
686 cst("Formula"),
687 app3(
688 cst("And3"),
689 app2(cst("SubformAtoms"), bvar(0), bvar(3)),
690 app2(cst("SubformAtoms"), bvar(1), bvar(2)),
691 app2(
692 cst("And"),
693 app(cst("Tautology"), app2(cst("ImpForm"), bvar(3), bvar(1))),
694 app(cst("Tautology"), app2(cst("ImpForm"), bvar(1), bvar(2))),
695 ),
696 ),
697 ),
698 ),
699 ),
700 )
701}
702pub fn lyndon_interpolation_ty() -> Expr {
707 impl_pi(
708 "A",
709 cst("Formula"),
710 impl_pi(
711 "B",
712 cst("Formula"),
713 arrow(
714 app(cst("Tautology"), app2(cst("ImpForm"), bvar(1), bvar(0))),
715 app2(
716 cst("Exists"),
717 cst("Formula"),
718 app3(cst("LyndonInterpolant"), bvar(2), bvar(1), bvar(0)),
719 ),
720 ),
721 ),
722 )
723}
724pub fn beth_definability_ty() -> Expr {
729 impl_pi(
730 "T",
731 cst("Theory"),
732 impl_pi(
733 "P",
734 cst("Predicate"),
735 arrow(
736 app2(cst("ImplicitlyDefines"), bvar(1), bvar(0)),
737 app2(
738 cst("Exists"),
739 cst("Formula"),
740 app3(cst("ExplicitlyDefines"), bvar(2), bvar(2), bvar(0)),
741 ),
742 ),
743 ),
744 )
745}
746pub fn resolution_completeness_ty() -> Expr {
750 impl_pi(
751 "Phi",
752 cst("ClauseSet"),
753 app2(
754 cst("Iff"),
755 arrow(app(cst("Satisfiable"), bvar(0)), cst("False")),
756 app(cst("ResolutionRefutable"), bvar(1)),
757 ),
758 )
759}
760pub fn frege_system_ty() -> Expr {
763 arrow(cst("ProofSystem"), prop())
764}
765pub fn ef_simulates_frege_ty() -> Expr {
769 impl_pi(
770 "f",
771 cst("FregeProof"),
772 app2(
773 cst("Exists"),
774 cst("ExtFregeProof"),
775 app3(
776 cst("SimulatesWithBound"),
777 bvar(1),
778 bvar(0),
779 cst("Polynomial"),
780 ),
781 ),
782 )
783}
784pub fn cook_reckhow_ty() -> Expr {
788 impl_pi(
789 "F1",
790 cst("ProofSystem"),
791 impl_pi(
792 "F2",
793 cst("ProofSystem"),
794 arrow(
795 app(cst("FregeSystem"), bvar(1)),
796 arrow(
797 app(cst("FregeSystem"), bvar(1)),
798 app2(cst("PSimulate"), bvar(3), bvar(2)),
799 ),
800 ),
801 ),
802 )
803}
804pub fn takeuti_conjecture_ty() -> Expr {
807 impl_pi(
808 "seq",
809 cst("HOSequent"),
810 arrow(
811 app(cst("HODerivable"), bvar(0)),
812 app(cst("CutFreeHODerivable"), bvar(1)),
813 ),
814 )
815}
816pub fn weak_normalization_ty() -> Expr {
819 impl_pi(
820 "t",
821 cst("LambdaTerm"),
822 arrow(
823 app(cst("WellTyped"), bvar(0)),
824 app2(
825 cst("Exists"),
826 cst("LambdaTerm"),
827 app2(
828 cst("And"),
829 app(cst("NormalForm"), bvar(0)),
830 app2(cst("BetaReducesTo"), bvar(2), bvar(1)),
831 ),
832 ),
833 ),
834 )
835}
836pub fn church_rosser_ty() -> Expr {
841 impl_pi(
842 "t",
843 cst("LambdaTerm"),
844 impl_pi(
845 "s1",
846 cst("LambdaTerm"),
847 impl_pi(
848 "s2",
849 cst("LambdaTerm"),
850 arrow(
851 app2(cst("BetaReducesTo"), bvar(2), bvar(1)),
852 arrow(
853 app2(cst("BetaReducesTo"), bvar(3), bvar(1)),
854 app2(
855 cst("Exists"),
856 cst("LambdaTerm"),
857 app2(
858 cst("And"),
859 app2(cst("BetaReducesTo"), bvar(4), bvar(0)),
860 app2(cst("BetaReducesTo"), bvar(4), bvar(1)),
861 ),
862 ),
863 ),
864 ),
865 ),
866 ),
867 )
868}
869pub fn build_proof_theory_env(env: &mut Environment) {
871 let axioms: &[(&str, Expr)] = &[
872 ("Sequent", sequent_ty()),
873 ("Derivation", derivation_ty()),
874 ("CutRule", cut_rule_ty()),
875 ("NaturalDeduction", natural_deduction_ty()),
876 ("LambdaTerm", lambda_term_ty()),
877 ("NormalForm", normal_form_ty()),
878 ("Ordinal", ordinal_ty()),
879 ("Formula", type0()),
880 ("Derivable", arrow(cst("Sequent"), prop())),
881 ("CutFreeDerivable", arrow(cst("Sequent"), prop())),
882 ("SubformulasClosed", arrow(cst("Sequent"), prop())),
883 ("WellTyped", arrow(type0(), prop())),
884 ("StronglyNormalizing", arrow(type0(), prop())),
885 ("Provable", arrow(cst("Formula"), prop())),
886 ("Tautology", arrow(cst("Formula"), prop())),
887 ("Proof", arrow(prop(), type0())),
888 ("HasType", arrow(cst("LambdaTerm"), arrow(prop(), prop()))),
889 ("FalseFormula", cst("Formula")),
890 ("LKDerivable", lk_derivable_ty()),
891 ("LJDerivable", lj_derivable_ty()),
892 ("AxiomSeq", arrow(cst("Formula"), cst("Sequent"))),
893 (
894 "WeakenRight",
895 arrow(cst("Sequent"), arrow(cst("Formula"), cst("Sequent"))),
896 ),
897 ("CutFreeLKDerivable", arrow(cst("Sequent"), prop())),
898 ("Context", type0()),
899 ("EmptyCtx", cst("Context")),
900 (
901 "Cons",
902 arrow(cst("Formula"), arrow(cst("Context"), cst("Context"))),
903 ),
904 (
905 "NDDerivable",
906 arrow(cst("Context"), arrow(cst("Formula"), prop())),
907 ),
908 (
909 "ImpForm",
910 arrow(cst("Formula"), arrow(cst("Formula"), cst("Formula"))),
911 ),
912 (
913 "AndForm",
914 arrow(cst("Formula"), arrow(cst("Formula"), cst("Formula"))),
915 ),
916 (
917 "OrForm",
918 arrow(cst("Formula"), arrow(cst("Formula"), cst("Formula"))),
919 ),
920 ("NegForm", arrow(cst("Formula"), cst("Formula"))),
921 (
922 "IffForm",
923 arrow(cst("Formula"), arrow(cst("Formula"), cst("Formula"))),
924 ),
925 (
926 "OrdLt",
927 arrow(cst("Ordinal"), arrow(cst("Ordinal"), prop())),
928 ),
929 ("EpsilonZero", epsilon_zero_ty()),
930 ("ProofSystem", type0()),
931 ("ProofTheoreticOrdinal", proof_theoretic_ordinal_ty()),
932 ("PA", cst("ProofSystem")),
933 ("ConsistentSystem", arrow(cst("ProofSystem"), prop())),
934 ("Sentence", type0()),
935 ("ConsistentRecEnum", type0()),
936 (
937 "NotProvable",
938 arrow(cst("ConsistentRecEnum"), arrow(cst("Sentence"), prop())),
939 ),
940 (
941 "ProvableIn",
942 arrow(cst("ProofSystem"), arrow(cst("Formula"), prop())),
943 ),
944 ("ConPa", cst("Formula")),
945 ("GodelNum", arrow(cst("Sentence"), cst("Formula"))),
946 (
947 "TrueIn",
948 arrow(cst("Model"), arrow(cst("Sentence"), prop())),
949 ),
950 ("StandardModel", cst("Model")),
951 ("BoolEq", arrow(bool_ty(), arrow(bool_ty(), prop()))),
952 ("BoolTrue", bool_ty()),
953 ("Theory", type0()),
954 (
955 "Entails",
956 arrow(cst("Theory"), arrow(cst("Formula"), prop())),
957 ),
958 ("ConsistentTheory", arrow(cst("Theory"), prop())),
959 ("Model", type0()),
960 ("ModelOf", arrow(cst("Model"), arrow(cst("Theory"), prop()))),
961 (
962 "FiniteSubset",
963 arrow(cst("Theory"), arrow(cst("Theory"), prop())),
964 ),
965 ("UniversalTheory", type0()),
966 ("Satisfiable", arrow(cst("UniversalTheory"), prop())),
967 ("HerbrandInstance", type0()),
968 (
969 "Refutes",
970 arrow(
971 cst("HerbrandInstance"),
972 arrow(cst("UniversalTheory"), prop()),
973 ),
974 ),
975 (
976 "SubformAtoms",
977 arrow(cst("Formula"), arrow(cst("Formula"), prop())),
978 ),
979 ("And3", arrow(prop(), arrow(prop(), arrow(prop(), prop())))),
980 (
981 "LyndonInterpolant",
982 arrow(
983 cst("Formula"),
984 arrow(cst("Formula"), arrow(cst("Formula"), prop())),
985 ),
986 ),
987 ("Predicate", type0()),
988 (
989 "ImplicitlyDefines",
990 arrow(cst("Theory"), arrow(cst("Predicate"), prop())),
991 ),
992 (
993 "ExplicitlyDefines",
994 arrow(
995 cst("Theory"),
996 arrow(cst("Predicate"), arrow(cst("Formula"), prop())),
997 ),
998 ),
999 ("ClauseSet", type0()),
1000 ("ResolutionRefutable", arrow(cst("ClauseSet"), prop())),
1001 ("FregeProof", type0()),
1002 ("ExtFregeProof", type0()),
1003 (
1004 "SimulatesWithBound",
1005 arrow(
1006 cst("FregeProof"),
1007 arrow(cst("ExtFregeProof"), arrow(cst("Bound"), prop())),
1008 ),
1009 ),
1010 ("Bound", type0()),
1011 ("Polynomial", cst("Bound")),
1012 (
1013 "PSimulate",
1014 arrow(cst("ProofSystem"), arrow(cst("ProofSystem"), prop())),
1015 ),
1016 ("HOSequent", type0()),
1017 ("HODerivable", arrow(cst("HOSequent"), prop())),
1018 ("CutFreeHODerivable", arrow(cst("HOSequent"), prop())),
1019 (
1020 "BetaReducesTo",
1021 arrow(cst("LambdaTerm"), arrow(cst("LambdaTerm"), prop())),
1022 ),
1023 ("cut_elimination", cut_elimination_ty()),
1024 ("subformula_property", subformula_property_ty()),
1025 ("normalization", normalization_ty()),
1026 ("consistency", consistency_ty()),
1027 (
1028 "completeness_propositional",
1029 completeness_propositional_ty(),
1030 ),
1031 ("curry_howard", curry_howard_ty()),
1032 ("lk_init", lk_init_ty()),
1033 ("lk_left_contraction", lk_left_contraction_ty()),
1034 ("lk_right_weakening", lk_right_weakening_ty()),
1035 ("lk_and_left1", lk_and_left1_ty()),
1036 ("lk_and_right", lk_and_right_ty()),
1037 ("lk_cut", lk_cut_ty()),
1038 ("lj_imp_left", lj_imp_left_ty()),
1039 ("lj_imp_right", lj_imp_right_ty()),
1040 ("nd_imp_intro", nd_imp_intro_ty()),
1041 ("nd_imp_elim", nd_imp_elim_ty()),
1042 ("nd_and_intro", nd_and_intro_ty()),
1043 ("nd_and_elim_left", nd_and_elim_left_ty()),
1044 ("nd_or_intro_left", nd_or_intro_left_ty()),
1045 ("pa_ordinal_epsilon_zero", pa_ordinal_epsilon_zero_ty()),
1046 (
1047 "ordinal_induction_epsilon_zero",
1048 ordinal_induction_epsilon_zero_ty(),
1049 ),
1050 ("gentzen_consistency", gentzen_consistency_ty()),
1051 ("gentzen_hauptsatz", gentzen_hauptsatz_ty()),
1052 (
1053 "godel_first_incompleteness",
1054 godel_first_incompleteness_ty(),
1055 ),
1056 (
1057 "godel_second_incompleteness",
1058 godel_second_incompleteness_ty(),
1059 ),
1060 ("rosser_sentence", rosser_sentence_ty()),
1061 ("diagonal_lemma", diagonal_lemma_ty()),
1062 ("tarski_undefinability", tarski_undefinability_ty()),
1063 ("godel_completeness", godel_completeness_ty()),
1064 ("henkin_completeness", henkin_completeness_ty()),
1065 ("compactness", compactness_ty()),
1066 ("herbrand_theorem", herbrand_theorem_ty()),
1067 ("craig_interpolation", craig_interpolation_ty()),
1068 ("lyndon_interpolation", lyndon_interpolation_ty()),
1069 ("beth_definability", beth_definability_ty()),
1070 ("resolution_completeness", resolution_completeness_ty()),
1071 ("frege_system", frege_system_ty()),
1072 ("ef_simulates_frege", ef_simulates_frege_ty()),
1073 ("cook_reckhow", cook_reckhow_ty()),
1074 ("takeuti_conjecture", takeuti_conjecture_ty()),
1075 ("weak_normalization", weak_normalization_ty()),
1076 ("church_rosser", church_rosser_ty()),
1077 ];
1078 for (name, ty) in axioms {
1079 env.add(Declaration::Axiom {
1080 name: Name::str(*name),
1081 univ_params: vec![],
1082 ty: ty.clone(),
1083 })
1084 .ok();
1085 }
1086}
1087pub fn eval(f: &Formula, assignment: &std::collections::HashMap<String, bool>) -> bool {
1089 match f {
1090 Formula::Atom(s) => *assignment.get(s).unwrap_or(&false),
1091 Formula::True_ => true,
1092 Formula::False_ => false,
1093 Formula::Neg(inner) => !eval(inner, assignment),
1094 Formula::And(a, b) => eval(a, assignment) && eval(b, assignment),
1095 Formula::Or(a, b) => eval(a, assignment) || eval(b, assignment),
1096 Formula::Implies(a, b) => !eval(a, assignment) || eval(b, assignment),
1097 Formula::Iff(a, b) => eval(a, assignment) == eval(b, assignment),
1098 }
1099}
1100pub fn truth_table(f: &Formula) -> Vec<(std::collections::HashMap<String, bool>, bool)> {
1103 let atoms = f.atoms();
1104 let n = atoms.len();
1105 let mut rows = Vec::with_capacity(1 << n);
1106 for mask in 0u64..(1u64 << n) {
1107 let mut assignment = std::collections::HashMap::new();
1108 for (i, atom) in atoms.iter().enumerate() {
1109 assignment.insert(atom.clone(), (mask >> i) & 1 == 1);
1110 }
1111 let val = eval(f, &assignment);
1112 rows.push((assignment, val));
1113 }
1114 rows
1115}
1116pub fn dpll_sat(clauses: &[Vec<i32>]) -> Option<Vec<i32>> {
1122 let mut assignment = Vec::new();
1123 if dpll_inner(&clauses.to_vec(), &mut assignment) {
1124 Some(assignment)
1125 } else {
1126 None
1127 }
1128}
1129pub fn dpll_inner(clauses: &Vec<Vec<i32>>, assignment: &mut Vec<i32>) -> bool {
1130 let mut clauses = clauses.clone();
1131 loop {
1132 let unit = clauses.iter().find(|c| c.len() == 1).map(|c| c[0]);
1133 match unit {
1134 None => break,
1135 Some(lit) => {
1136 assignment.push(lit);
1137 clauses = propagate(&clauses, lit);
1138 }
1139 }
1140 }
1141 if clauses.iter().any(|c| c.is_empty()) {
1142 return false;
1143 }
1144 if clauses.is_empty() {
1145 return true;
1146 }
1147 let lit = clauses[0][0];
1148 let mut pos_clauses = propagate(&clauses, lit);
1149 let mut pos_assign = assignment.clone();
1150 pos_assign.push(lit);
1151 if dpll_inner(&pos_clauses, &mut pos_assign) {
1152 assignment.clear();
1153 assignment.extend(pos_assign);
1154 return true;
1155 }
1156 let neg_lit = -lit;
1157 pos_clauses = propagate(&clauses, neg_lit);
1158 let mut neg_assign = assignment.clone();
1159 neg_assign.push(neg_lit);
1160 if dpll_inner(&pos_clauses, &mut neg_assign) {
1161 assignment.clear();
1162 assignment.extend(neg_assign);
1163 return true;
1164 }
1165 false
1166}
1167pub fn propagate(clauses: &[Vec<i32>], lit: i32) -> Vec<Vec<i32>> {
1168 let mut result = Vec::new();
1169 for clause in clauses {
1170 if clause.contains(&lit) {
1171 continue;
1172 }
1173 let new_clause: Vec<i32> = clause.iter().filter(|&&l| l != -lit).copied().collect();
1174 result.push(new_clause);
1175 }
1176 result
1177}
1178pub fn to_cnf(f: &Formula) -> Vec<Vec<i32>> {
1182 let atoms = f.atoms();
1183 let atom_idx: std::collections::HashMap<String, i32> = atoms
1184 .iter()
1185 .enumerate()
1186 .map(|(i, s)| (s.clone(), (i + 1) as i32))
1187 .collect();
1188 let mut clauses = Vec::new();
1189 to_cnf_inner(f, &atom_idx, &mut clauses, true);
1190 clauses
1191}
1192pub fn to_cnf_inner(
1193 f: &Formula,
1194 idx: &std::collections::HashMap<String, i32>,
1195 clauses: &mut Vec<Vec<i32>>,
1196 polarity: bool,
1197) {
1198 match f {
1199 Formula::Atom(s) => {
1200 let lit = *idx.get(s).unwrap_or(&1);
1201 clauses.push(vec![if polarity { lit } else { -lit }]);
1202 }
1203 Formula::True_ => {
1204 if !polarity {
1205 clauses.push(vec![]);
1206 }
1207 }
1208 Formula::False_ => {
1209 if polarity {
1210 clauses.push(vec![]);
1211 }
1212 }
1213 Formula::Neg(inner) => {
1214 to_cnf_inner(inner, idx, clauses, !polarity);
1215 }
1216 Formula::And(a, b) => {
1217 if polarity {
1218 to_cnf_inner(a, idx, clauses, true);
1219 to_cnf_inner(b, idx, clauses, true);
1220 } else {
1221 to_cnf_inner(a, idx, clauses, false);
1222 to_cnf_inner(b, idx, clauses, false);
1223 }
1224 }
1225 Formula::Or(a, b) => {
1226 if polarity {
1227 to_cnf_inner(a, idx, clauses, true);
1228 to_cnf_inner(b, idx, clauses, true);
1229 } else {
1230 to_cnf_inner(a, idx, clauses, false);
1231 to_cnf_inner(b, idx, clauses, false);
1232 }
1233 }
1234 Formula::Implies(a, b) => {
1235 to_cnf_inner(
1236 &Formula::or(Formula::neg(*a.clone()), *b.clone()),
1237 idx,
1238 clauses,
1239 polarity,
1240 );
1241 }
1242 Formula::Iff(a, b) => {
1243 to_cnf_inner(
1244 &Formula::and(
1245 Formula::implies(*a.clone(), *b.clone()),
1246 Formula::implies(*b.clone(), *a.clone()),
1247 ),
1248 idx,
1249 clauses,
1250 polarity,
1251 );
1252 }
1253 }
1254}
1255pub fn is_provable_propositional(seq: &Sequent) -> bool {
1258 let premise = seq
1259 .antecedent
1260 .iter()
1261 .cloned()
1262 .reduce(Formula::and)
1263 .unwrap_or(Formula::True_);
1264 let conclusion = seq
1265 .succedent
1266 .iter()
1267 .cloned()
1268 .reduce(Formula::or)
1269 .unwrap_or(Formula::False_);
1270 Formula::implies(premise, conclusion).is_tautology()
1271}
1272#[cfg(test)]
1273mod tests {
1274 use super::*;
1275 #[test]
1276 fn test_formula_tautology() {
1277 let a = Formula::atom("A");
1278 let f = Formula::implies(a.clone(), a);
1279 assert!(f.is_tautology());
1280 }
1281 #[test]
1282 fn test_formula_not_tautology() {
1283 let a = Formula::atom("A");
1284 assert!(!a.is_tautology());
1285 }
1286 #[test]
1287 fn test_formula_satisfiable() {
1288 let a = Formula::atom("A");
1289 assert!(a.is_satisfiable());
1290 assert!(!Formula::False_.is_satisfiable());
1291 }
1292 #[test]
1293 fn test_formula_contradiction() {
1294 assert!(Formula::False_.is_contradiction());
1295 assert!(!Formula::atom("A").is_contradiction());
1296 }
1297 #[test]
1298 fn test_formula_atoms() {
1299 let f = Formula::and(Formula::atom("A"), Formula::atom("B"));
1300 let atoms = f.atoms();
1301 assert!(atoms.contains(&"A".to_string()));
1302 assert!(atoms.contains(&"B".to_string()));
1303 assert_eq!(atoms.len(), 2);
1304 }
1305 #[test]
1306 fn test_formula_depth() {
1307 let a = Formula::atom("A");
1308 assert_eq!(a.depth(), 0);
1309 let ab = Formula::and(Formula::atom("A"), Formula::atom("B"));
1310 assert_eq!(ab.depth(), 1);
1311 }
1312 #[test]
1313 fn test_sequent_is_axiom() {
1314 let a = Formula::atom("A");
1315 let seq = Sequent::new(vec![a.clone()], vec![a]);
1316 assert!(seq.is_axiom());
1317 let seq2 = Sequent::new(vec![Formula::atom("A")], vec![Formula::atom("B")]);
1318 assert!(!seq2.is_axiom());
1319 }
1320 #[test]
1321 fn test_dpll_sat_simple() {
1322 let result = dpll_sat(&[vec![1]]);
1323 assert!(result.is_some());
1324 let result2 = dpll_sat(&[vec![1], vec![-1]]);
1325 assert!(result2.is_none());
1326 let result3 = dpll_sat(&[vec![1, -1]]);
1327 assert!(result3.is_some());
1328 }
1329 #[test]
1330 fn test_combinator_i_reduce() {
1331 let ix = Combinator::app(Combinator::I, Combinator::K);
1332 let reduced = ix.reduce_step().expect("I x should reduce");
1333 assert!(matches!(reduced, Combinator::K));
1334 }
1335 #[test]
1336 fn test_combinator_k_reduce() {
1337 let kxy = Combinator::app(Combinator::app(Combinator::K, Combinator::I), Combinator::S);
1338 let reduced = kxy.reduce_step().expect("K x y should reduce");
1339 assert!(matches!(reduced, Combinator::I));
1340 }
1341 #[test]
1342 fn test_build_proof_theory_env() {
1343 let mut env = oxilean_kernel::Environment::new();
1344 build_proof_theory_env(&mut env);
1345 }
1346 #[test]
1347 fn test_formula_to_nnf_double_neg() {
1348 let a = Formula::atom("A");
1349 let nn_a = Formula::neg(Formula::neg(a.clone()));
1350 let nnf = nn_a.to_nnf();
1351 assert_eq!(nnf, a);
1352 }
1353 #[test]
1354 fn test_formula_to_nnf_de_morgan() {
1355 let a = Formula::atom("A");
1356 let b = Formula::atom("B");
1357 let f = Formula::neg(Formula::and(a.clone(), b.clone()));
1358 let nnf = f.to_nnf();
1359 assert_eq!(nnf, Formula::or(Formula::neg(a), Formula::neg(b)));
1360 }
1361 #[test]
1362 fn test_sequent_calculus_proof_valid() {
1363 let a = Formula::atom("A");
1364 let seq = Sequent::new(vec![a.clone()], vec![a]);
1365 let proof = SequentCalculusProof::new(LKNode::axiom(seq));
1366 assert!(proof.is_valid());
1367 assert!(proof.is_cut_free());
1368 assert_eq!(proof.size(), 1);
1369 }
1370 #[test]
1371 fn test_lk_node_cut_free() {
1372 let a = Formula::atom("A");
1373 let seq = Sequent::new(vec![a.clone()], vec![a.clone()]);
1374 let leaf = LKNode::axiom(seq.clone());
1375 let parent = LKNode::unary(seq, LKRule::LeftWeaken, leaf);
1376 assert!(parent.is_cut_free());
1377 }
1378 #[test]
1379 fn test_lk_node_not_cut_free() {
1380 let a = Formula::atom("A");
1381 let seq = Sequent::new(vec![a.clone()], vec![a.clone()]);
1382 let leaf1 = LKNode::axiom(seq.clone());
1383 let leaf2 = LKNode::axiom(seq.clone());
1384 let cut_node = LKNode::binary(seq, LKRule::Cut(a.clone()), leaf1, leaf2);
1385 assert!(!cut_node.is_cut_free());
1386 }
1387 #[test]
1388 fn test_nd_term_beta_reduction() {
1389 let id = NDTerm::Lam(
1390 "x".to_string(),
1391 Box::new(Formula::atom("A")),
1392 Box::new(NDTerm::Var("x".to_string())),
1393 );
1394 let applied = NDTerm::App(Box::new(id), Box::new(NDTerm::Var("K".to_string())));
1395 let reduced = applied.reduce_step().expect("beta-redex should reduce");
1396 assert_eq!(reduced, NDTerm::Var("K".to_string()));
1397 }
1398 #[test]
1399 fn test_nd_term_fst_reduction() {
1400 let pair = NDTerm::Pair(
1401 Box::new(NDTerm::Var("a".to_string())),
1402 Box::new(NDTerm::Var("b".to_string())),
1403 );
1404 let fst = NDTerm::Fst(Box::new(pair));
1405 let reduced = fst.reduce_step().expect("fst should reduce");
1406 assert_eq!(reduced, NDTerm::Var("a".to_string()));
1407 }
1408 #[test]
1409 fn test_nd_term_subst() {
1410 let lam = NDTerm::Lam(
1411 "y".to_string(),
1412 Box::new(Formula::atom("T")),
1413 Box::new(NDTerm::Var("y".to_string())),
1414 );
1415 let result = lam.subst("x", &NDTerm::Var("K".to_string()));
1416 assert_eq!(result, lam);
1417 }
1418 #[test]
1419 fn test_cut_eliminator_verify() {
1420 let a = Formula::atom("A");
1421 let seq = Sequent::new(vec![a.clone()], vec![a]);
1422 let proof = SequentCalculusProof::new(LKNode::axiom(seq));
1423 assert!(CutEliminator::verify(&proof));
1424 }
1425 #[test]
1426 fn test_resolution_prover_unsat() {
1427 let clauses = vec![Clause::new(&[1]), Clause::new(&[-1])];
1428 let prover = ResolutionProver::new(clauses);
1429 assert!(prover.refute(100));
1430 }
1431 #[test]
1432 fn test_resolution_prover_sat() {
1433 let clauses = vec![Clause::new(&[1])];
1434 let prover = ResolutionProver::new(clauses);
1435 assert!(!prover.refute(100));
1436 }
1437 #[test]
1438 fn test_clause_resolve() {
1439 let c1 = Clause::new(&[1, 2]);
1440 let c2 = Clause::new(&[-1, 3]);
1441 let resolvent = Clause::resolve(&c1, &c2, 1).expect("should resolve");
1442 assert!(resolvent.0.contains(&2));
1443 assert!(resolvent.0.contains(&3));
1444 assert!(!resolvent.0.contains(&1));
1445 }
1446 #[test]
1447 fn test_herbrand_terms_depth_zero() {
1448 let gen = HerbrandInstanceGenerator::new(vec!["a".to_string(), "b".to_string()], vec![]);
1449 let terms = gen.terms_up_to_depth(0);
1450 assert_eq!(terms.len(), 2);
1451 }
1452 #[test]
1453 fn test_herbrand_instance_bind() {
1454 let mut inst = HerbrandInstance::new();
1455 inst.bind("x", HerbrandTerm::constant("a"));
1456 assert_eq!(inst.lookup("x"), Some(&HerbrandTerm::constant("a")));
1457 }
1458 #[test]
1459 fn test_herbrand_instance_generator_next() {
1460 let mut gen =
1461 HerbrandInstanceGenerator::new(vec!["a".to_string()], vec![("f".to_string(), 1)]);
1462 let instances = gen.next_instances(&["x".to_string()]);
1463 assert!(!instances.is_empty());
1464 }
1465 #[test]
1466 fn test_is_provable_propositional() {
1467 let a = Formula::atom("A");
1468 let seq = Sequent::new(vec![], vec![Formula::implies(a.clone(), a)]);
1469 assert!(is_provable_propositional(&seq));
1470 }
1471 #[test]
1472 fn test_herbrand_term_display() {
1473 let t = HerbrandTerm::fun("f", vec![HerbrandTerm::constant("a")]);
1474 assert_eq!(t.to_string(), "f(a)");
1475 }
1476 #[test]
1477 fn test_clause_display_empty() {
1478 let c = Clause::new(&[]);
1479 assert_eq!(c.to_string(), "β‘");
1480 }
1481}