git @ Cat's Eye Technologies Philomath / 0a2bfbf
Rename from "proof.c" to "theorem.c" because it defines theorems. Chris Pressey 1 year, 16 days ago
5 changed file(s) with 252 addition(s) and 250 deletion(s). Raw diff Collapse all Expand all
00 #!/bin/sh -ex
11
22 CC="gcc -ansi -pedantic"
3 for MODULE in assert formula assumptions proof; do
3 for MODULE in assert formula assumptions theorem; do
44 (cd src && ${CC} ${CFLAGS} -I../include -c $MODULE.c -o $MODULE.o)
55 done
0 /* proof.h */
0 #include "theorem.h"
11
2 #ifndef PROOF_H
3 #define PROOF_H 1
4
5 #include "formula.h"
6
7 struct theorem;
8
9 int proves(struct theorem *, struct formula *);
10
11 struct theorem *suppose(struct formula *, int);
12
13 struct theorem *conj_intro(struct theorem *, struct theorem *);
14 struct theorem *conj_elim_lhs(struct theorem *);
15 struct theorem *conj_elim_rhs(struct theorem *);
16
17 struct theorem *impl_intro(int, struct theorem *);
18 struct theorem *impl_elim(struct theorem *, struct theorem *);
19
20 struct theorem *disj_intro_lhs(struct formula *, struct theorem *);
21 struct theorem *disj_intro_rhs(struct theorem *, struct formula *);
22 struct theorem *disj_elim(struct theorem *, struct theorem *, int, struct theorem *, int);
23
24 struct theorem *conj_elim_lhs(struct theorem *);
25 struct theorem *conj_elim_rhs(struct theorem *);
26
27 struct theorem *neg_intro(int, struct theorem *);
28 struct theorem *neg_elim(struct theorem *, struct theorem *);
29
30 struct theorem *absr_elim(struct theorem *, struct formula *);
31 struct theorem *double_neg_elim(struct theorem *);
32
33 #endif /* ndef PROOF_H */
0 /* theorem.h */
1
2 #ifndef THEOREM_H
3 #define THEOREM_H 1
4
5 #include "formula.h"
6
7 struct theorem;
8
9 int proves(struct theorem *, struct formula *);
10
11 struct theorem *suppose(struct formula *, int);
12
13 struct theorem *conj_intro(struct theorem *, struct theorem *);
14 struct theorem *conj_elim_lhs(struct theorem *);
15 struct theorem *conj_elim_rhs(struct theorem *);
16
17 struct theorem *impl_intro(int, struct theorem *);
18 struct theorem *impl_elim(struct theorem *, struct theorem *);
19
20 struct theorem *disj_intro_lhs(struct formula *, struct theorem *);
21 struct theorem *disj_intro_rhs(struct theorem *, struct formula *);
22 struct theorem *disj_elim(struct theorem *, struct theorem *, int, struct theorem *, int);
23
24 struct theorem *conj_elim_lhs(struct theorem *);
25 struct theorem *conj_elim_rhs(struct theorem *);
26
27 struct theorem *neg_intro(int, struct theorem *);
28 struct theorem *neg_elim(struct theorem *, struct theorem *);
29
30 struct theorem *absr_elim(struct theorem *, struct formula *);
31 struct theorem *double_neg_elim(struct theorem *);
32
33 #endif /* ndef THEOREM_H */
+0
-216
src/proof.c less more
0 #include <stdio.h>
1 #include <stdlib.h>
2
3 #include "assert.h"
4 #include "formula.h"
5 #include "assumptions.h"
6 #include "proof.h"
7
8 struct theorem {
9 struct assumptions *assumptions;
10 struct formula *conclusion;
11 };
12
13 struct theorem *
14 mk_theorem(struct assumptions *assumptions, struct formula *conclusion) {
15 struct theorem *t = (struct theorem *)malloc(sizeof(struct theorem));
16 assert(t != NULL, "mk_theorem: could not allocate theorem object");
17 #ifdef DEBUG
18 fprintf(stdout, "-----------------------------------------\n");
19 fprintf(stdout, "Created theorem ");
20 formula_fprint(stdout, conclusion);
21 fprintf(stdout, " under assumptions:\n");
22 assumptions_fprint(stdout, assumptions);
23 fprintf(stdout, "-----------------------------------------\n\n");
24 #endif
25 t->assumptions = assumptions;
26 t->conclusion = conclusion;
27 return t;
28 }
29
30 int proves(struct theorem *t, struct formula *c) {
31 /* Asserts that the theorem t proves the formula c. If it does,
32 a successful system exit code (i.e. 0) is returned, with
33 which the process may exit. */
34 assert(t->assumptions == NULL, "proves: proof contains undischarged assumptions");
35 #ifdef DEBUG
36 if (!formula_eq(t->conclusion, c)) {
37 fprintf(stdout, "Claim: ");
38 formula_fprint(stdout, c);
39 fprintf(stdout, "\n");
40 fprintf(stdout, "Conclusion of proof: ");
41 formula_fprint(stdout, t->conclusion);
42 fprintf(stdout, "\n");
43 }
44 #endif
45 assert(formula_eq(t->conclusion, c), "proves: proof does not prove what is claimed");
46 return 0;
47 }
48
49 struct theorem *
50 suppose(struct formula *formula, int label) {
51 return mk_theorem(
52 assume(label, formula, NULL),
53 formula
54 );
55 }
56
57 struct theorem *
58 conj_intro(struct theorem *x, struct theorem *y) {
59 /* If x is a theorem, and y is a theorem, then x & y is a theorem. */
60 return mk_theorem(
61 merge(x->assumptions, y->assumptions),
62 conj(x->conclusion, y->conclusion)
63 );
64 }
65
66 struct theorem *
67 conj_elim_lhs(struct theorem *x) {
68 /* If x (of the form y & z) is a theorem, then y is a theorem. */
69 assert(x->conclusion->type == CONJ, "conj_elim_lhs: not a conjunction");
70 return mk_theorem(
71 x->assumptions,
72 x->conclusion->lhs
73 );
74 }
75
76 struct theorem *
77 conj_elim_rhs(struct theorem *x) {
78 /* If x (of the form y & z) is a theorem, then z is a theorem. */
79 assert(x->conclusion->type == CONJ, "conj_elim_rhs: not a conjunction");
80 return mk_theorem(
81 x->assumptions,
82 x->conclusion->rhs
83 );
84 }
85
86 struct theorem *
87 impl_intro(int label, struct theorem *y) {
88 /* If y is a theorem under the assumption x, then x -> y is a theorem. */
89 struct formula *f = lookup(label, y->assumptions);
90 struct assumptions *a = discharge(label, y->assumptions);
91 #ifdef DEBUG
92 if (f == NULL) {
93 fprintf(stdout, "Label %d not found in:", label);
94 assumptions_fprint(stdout, a);
95 fprintf(stdout, "\n");
96 }
97 #endif
98 assert(f != NULL, "impl_intro: label not found in assumptions");
99 return mk_theorem(
100 a,
101 impl(f, y->conclusion)
102 );
103 }
104
105 struct theorem *
106 impl_elim(struct theorem *x, struct theorem *y) {
107 /* If x is a theorem, and y (of the form x -> z) is a theorem, then z is a theorem. */
108 assert(y->conclusion->type == IMPL, "impl_elim: not an implication");
109 assert(formula_eq(y->conclusion->lhs, x->conclusion), "impl_elim: formula mismatch");
110 return mk_theorem(
111 merge(x->assumptions, y->assumptions),
112 y->conclusion->rhs
113 );
114 }
115
116 struct theorem *
117 disj_intro_lhs(struct formula *fx, struct theorem *y) {
118 /* If y is a theorem, then x v y is a theorem, for any x. */
119 return mk_theorem(
120 y->assumptions,
121 disj(fx, y->conclusion)
122 );
123 }
124
125 struct theorem *
126 disj_intro_rhs(struct theorem *x, struct formula *fy) {
127 /* If x is a theorem, then x v y is a theorem, for any y. */
128 return mk_theorem(
129 x->assumptions,
130 disj(x->conclusion, fy)
131 );
132 }
133
134 struct theorem *
135 disj_elim(struct theorem *z, struct theorem *x, int label1, struct theorem *y, int label2) {
136 /* If z is a theorem, and under the assumption labelled "1" x is a theorem, and under
137 the assumption labelled "2" y is a theorem, and x concludes the same as y,
138 and z (in the form "1" v "2") is a theorem, then x is a theorem. */
139 struct formula *f1, *f2;
140 struct assumptions *a_x, *a_y;
141
142 assert(z->conclusion->type == DISJ, "disj_elim: not a disjunction");
143
144 f1 = lookup(label1, x->assumptions);
145 a_x = discharge(label1, x->assumptions);
146
147 f2 = lookup(label2, y->assumptions);
148 a_y = discharge(label2, y->assumptions);
149
150 assert(formula_eq(x->conclusion, y->conclusion), "disj_elim: mismatched conclusions");
151 assert(formula_eq(z->conclusion->lhs, f1), "disj_elim: mismatched assumption on lhs");
152 assert(formula_eq(z->conclusion->rhs, f2), "disj_elim: mismatched assumption on rhs");
153
154 return mk_theorem(
155 merge(z->assumptions, merge(a_x, a_y)),
156 x->conclusion
157 );
158 }
159
160 struct theorem *
161 neg_intro(int label, struct theorem *x)
162 {
163 /* If x is absurdum and x is a theorem under the assumption y, then not-y is a theorem. */
164 struct formula *f = lookup(label, x->assumptions);
165 struct assumptions *a = discharge(label, x->assumptions);
166 assert(x->conclusion->type == ABSR, "neg_intro: not absurdum");
167 #ifdef DEBUG
168 if (f == NULL) {
169 fprintf(stdout, "Label %d not found in:", label);
170 assumptions_fprint(stdout, a);
171 fprintf(stdout, "\n");
172 }
173 #endif
174 assert(f != NULL, "neg_intro: label not found in assumptions");
175 return mk_theorem(
176 a,
177 neg(f)
178 );
179 }
180
181 struct theorem *
182 neg_elim(struct theorem *x, struct theorem *y)
183 {
184 /* If x has the form z and x is a theorem, and y has the form not-z and y is a theorem,
185 then absurdum is a theorem. */
186 assert(y->conclusion->type == NEG, "neg_elim: not a negation");
187 assert(formula_eq(x->conclusion, y->conclusion->rhs), "neg_elim: mismatched conclusions");
188 return mk_theorem(
189 merge(x->assumptions, y->assumptions),
190 absr()
191 );
192 }
193
194 struct theorem *
195 absr_elim(struct theorem *x, struct formula *fy)
196 {
197 /* If x is absurdum and x is a theorem, then y is a theorem for any y. */
198 assert(x->conclusion->type == ABSR, "absr_elim: not absurdum");
199 return mk_theorem(
200 x->assumptions,
201 fy
202 );
203 }
204
205 struct theorem *
206 double_neg_elim(struct theorem *x)
207 {
208 /* If x is a theorem and x is in the form not-not-y, then y is a theorem. */
209 assert(x->conclusion->type == NEG, "double_neg_elim: not a negation");
210 assert(x->conclusion->rhs->type == NEG, "double_neg_elim: not a double negation");
211 return mk_theorem(
212 x->assumptions,
213 x->conclusion->rhs->rhs
214 );
215 }
0 #include <stdio.h>
1 #include <stdlib.h>
2
3 #include "assert.h"
4 #include "formula.h"
5 #include "assumptions.h"
6 #include "proof.h"
7
8 struct theorem {
9 struct assumptions *assumptions;
10 struct formula *conclusion;
11 };
12
13 struct theorem *
14 mk_theorem(struct assumptions *assumptions, struct formula *conclusion) {
15 struct theorem *t = (struct theorem *)malloc(sizeof(struct theorem));
16 assert(t != NULL, "mk_theorem: could not allocate theorem object");
17 #ifdef DEBUG
18 fprintf(stdout, "-----------------------------------------\n");
19 fprintf(stdout, "Created theorem ");
20 formula_fprint(stdout, conclusion);
21 fprintf(stdout, " under assumptions:\n");
22 assumptions_fprint(stdout, assumptions);
23 fprintf(stdout, "-----------------------------------------\n\n");
24 #endif
25 t->assumptions = assumptions;
26 t->conclusion = conclusion;
27 return t;
28 }
29
30 int proves(struct theorem *t, struct formula *c) {
31 /* Asserts that the theorem t proves the formula c. If it does,
32 a successful system exit code (i.e. 0) is returned, with
33 which the process may exit. */
34 assert(t->assumptions == NULL, "proves: proof contains undischarged assumptions");
35 #ifdef DEBUG
36 if (!formula_eq(t->conclusion, c)) {
37 fprintf(stdout, "Claim: ");
38 formula_fprint(stdout, c);
39 fprintf(stdout, "\n");
40 fprintf(stdout, "Conclusion of proof: ");
41 formula_fprint(stdout, t->conclusion);
42 fprintf(stdout, "\n");
43 }
44 #endif
45 assert(formula_eq(t->conclusion, c), "proves: proof does not prove what is claimed");
46 return 0;
47 }
48
49 struct theorem *
50 suppose(struct formula *formula, int label) {
51 return mk_theorem(
52 assume(label, formula, NULL),
53 formula
54 );
55 }
56
57 struct theorem *
58 conj_intro(struct theorem *x, struct theorem *y) {
59 /* If x is a theorem, and y is a theorem, then x & y is a theorem. */
60 return mk_theorem(
61 merge(x->assumptions, y->assumptions),
62 conj(x->conclusion, y->conclusion)
63 );
64 }
65
66 struct theorem *
67 conj_elim_lhs(struct theorem *x) {
68 /* If x (of the form y & z) is a theorem, then y is a theorem. */
69 assert(x->conclusion->type == CONJ, "conj_elim_lhs: not a conjunction");
70 return mk_theorem(
71 x->assumptions,
72 x->conclusion->lhs
73 );
74 }
75
76 struct theorem *
77 conj_elim_rhs(struct theorem *x) {
78 /* If x (of the form y & z) is a theorem, then z is a theorem. */
79 assert(x->conclusion->type == CONJ, "conj_elim_rhs: not a conjunction");
80 return mk_theorem(
81 x->assumptions,
82 x->conclusion->rhs
83 );
84 }
85
86 struct theorem *
87 impl_intro(int label, struct theorem *y) {
88 /* If y is a theorem under the assumption x, then x -> y is a theorem. */
89 struct formula *f = lookup(label, y->assumptions);
90 struct assumptions *a = discharge(label, y->assumptions);
91 #ifdef DEBUG
92 if (f == NULL) {
93 fprintf(stdout, "Label %d not found in:", label);
94 assumptions_fprint(stdout, a);
95 fprintf(stdout, "\n");
96 }
97 #endif
98 assert(f != NULL, "impl_intro: label not found in assumptions");
99 return mk_theorem(
100 a,
101 impl(f, y->conclusion)
102 );
103 }
104
105 struct theorem *
106 impl_elim(struct theorem *x, struct theorem *y) {
107 /* If x is a theorem, and y (of the form x -> z) is a theorem, then z is a theorem. */
108 assert(y->conclusion->type == IMPL, "impl_elim: not an implication");
109 assert(formula_eq(y->conclusion->lhs, x->conclusion), "impl_elim: formula mismatch");
110 return mk_theorem(
111 merge(x->assumptions, y->assumptions),
112 y->conclusion->rhs
113 );
114 }
115
116 struct theorem *
117 disj_intro_lhs(struct formula *fx, struct theorem *y) {
118 /* If y is a theorem, then x v y is a theorem, for any x. */
119 return mk_theorem(
120 y->assumptions,
121 disj(fx, y->conclusion)
122 );
123 }
124
125 struct theorem *
126 disj_intro_rhs(struct theorem *x, struct formula *fy) {
127 /* If x is a theorem, then x v y is a theorem, for any y. */
128 return mk_theorem(
129 x->assumptions,
130 disj(x->conclusion, fy)
131 );
132 }
133
134 struct theorem *
135 disj_elim(struct theorem *z, struct theorem *x, int label1, struct theorem *y, int label2) {
136 /* If z is a theorem, and under the assumption labelled "1" x is a theorem, and under
137 the assumption labelled "2" y is a theorem, and x concludes the same as y,
138 and z (in the form "1" v "2") is a theorem, then x is a theorem. */
139 struct formula *f1, *f2;
140 struct assumptions *a_x, *a_y;
141
142 assert(z->conclusion->type == DISJ, "disj_elim: not a disjunction");
143
144 f1 = lookup(label1, x->assumptions);
145 a_x = discharge(label1, x->assumptions);
146
147 f2 = lookup(label2, y->assumptions);
148 a_y = discharge(label2, y->assumptions);
149
150 assert(formula_eq(x->conclusion, y->conclusion), "disj_elim: mismatched conclusions");
151 assert(formula_eq(z->conclusion->lhs, f1), "disj_elim: mismatched assumption on lhs");
152 assert(formula_eq(z->conclusion->rhs, f2), "disj_elim: mismatched assumption on rhs");
153
154 return mk_theorem(
155 merge(z->assumptions, merge(a_x, a_y)),
156 x->conclusion
157 );
158 }
159
160 struct theorem *
161 neg_intro(int label, struct theorem *x)
162 {
163 /* If x is absurdum and x is a theorem under the assumption y, then not-y is a theorem. */
164 struct formula *f = lookup(label, x->assumptions);
165 struct assumptions *a = discharge(label, x->assumptions);
166 assert(x->conclusion->type == ABSR, "neg_intro: not absurdum");
167 #ifdef DEBUG
168 if (f == NULL) {
169 fprintf(stdout, "Label %d not found in:", label);
170 assumptions_fprint(stdout, a);
171 fprintf(stdout, "\n");
172 }
173 #endif
174 assert(f != NULL, "neg_intro: label not found in assumptions");
175 return mk_theorem(
176 a,
177 neg(f)
178 );
179 }
180
181 struct theorem *
182 neg_elim(struct theorem *x, struct theorem *y)
183 {
184 /* If x has the form z and x is a theorem, and y has the form not-z and y is a theorem,
185 then absurdum is a theorem. */
186 assert(y->conclusion->type == NEG, "neg_elim: not a negation");
187 assert(formula_eq(x->conclusion, y->conclusion->rhs), "neg_elim: mismatched conclusions");
188 return mk_theorem(
189 merge(x->assumptions, y->assumptions),
190 absr()
191 );
192 }
193
194 struct theorem *
195 absr_elim(struct theorem *x, struct formula *fy)
196 {
197 /* If x is absurdum and x is a theorem, then y is a theorem for any y. */
198 assert(x->conclusion->type == ABSR, "absr_elim: not absurdum");
199 return mk_theorem(
200 x->assumptions,
201 fy
202 );
203 }
204
205 struct theorem *
206 double_neg_elim(struct theorem *x)
207 {
208 /* If x is a theorem and x is in the form not-not-y, then y is a theorem. */
209 assert(x->conclusion->type == NEG, "double_neg_elim: not a negation");
210 assert(x->conclusion->rhs->type == NEG, "double_neg_elim: not a double negation");
211 return mk_theorem(
212 x->assumptions,
213 x->conclusion->rhs->rhs
214 );
215 }