31 end |
31 end |
32 |
32 |
33 structure Z3_Proof_Literals: Z3_PROOF_LITERALS = |
33 structure Z3_Proof_Literals: Z3_PROOF_LITERALS = |
34 struct |
34 struct |
35 |
35 |
36 structure U = SMT_Utils |
|
37 structure T = Z3_Proof_Tools |
|
38 |
|
39 |
36 |
40 |
37 |
41 (* literal table *) |
38 (* literal table *) |
42 |
39 |
43 type littab = thm Termtab.table |
40 type littab = thm Termtab.table |
44 |
41 |
45 fun make_littab thms = fold (Termtab.update o `U.prop_of) thms Termtab.empty |
42 fun make_littab thms = |
46 |
43 fold (Termtab.update o `SMT_Utils.prop_of) thms Termtab.empty |
47 fun insert_lit thm = Termtab.update (`U.prop_of thm) |
44 |
48 fun delete_lit thm = Termtab.delete (U.prop_of thm) |
45 fun insert_lit thm = Termtab.update (`SMT_Utils.prop_of thm) |
|
46 fun delete_lit thm = Termtab.delete (SMT_Utils.prop_of thm) |
49 fun lookup_lit lits = Termtab.lookup lits |
47 fun lookup_lit lits = Termtab.lookup lits |
50 fun get_first_lit f = |
48 fun get_first_lit f = |
51 Termtab.get_first (fn (t, thm) => if f t then SOME thm else NONE) |
49 Termtab.get_first (fn (t, thm) => if f t then SOME thm else NONE) |
52 |
50 |
53 |
51 |
91 (* proof tools *) |
89 (* proof tools *) |
92 |
90 |
93 (** explosion of conjunctions and disjunctions **) |
91 (** explosion of conjunctions and disjunctions **) |
94 |
92 |
95 local |
93 local |
|
94 val precomp = Z3_Proof_Tools.precompose2 |
|
95 |
96 fun destc ct = Thm.dest_binop (Thm.dest_arg ct) |
96 fun destc ct = Thm.dest_binop (Thm.dest_arg ct) |
97 val dest_conj1 = T.precompose2 destc @{thm conjunct1} |
97 val dest_conj1 = precomp destc @{thm conjunct1} |
98 val dest_conj2 = T.precompose2 destc @{thm conjunct2} |
98 val dest_conj2 = precomp destc @{thm conjunct2} |
99 fun dest_conj_rules t = |
99 fun dest_conj_rules t = |
100 dest_conj_term t |> Option.map (K (dest_conj1, dest_conj2)) |
100 dest_conj_term t |> Option.map (K (dest_conj1, dest_conj2)) |
101 |
101 |
102 fun destd f ct = f (Thm.dest_binop (Thm.dest_arg (Thm.dest_arg ct))) |
102 fun destd f ct = f (Thm.dest_binop (Thm.dest_arg (Thm.dest_arg ct))) |
103 val dn1 = apfst Thm.dest_arg and dn2 = apsnd Thm.dest_arg |
103 val dn1 = apfst Thm.dest_arg and dn2 = apsnd Thm.dest_arg |
104 val dest_disj1 = T.precompose2 (destd I) @{lemma "~(P | Q) ==> ~P" by fast} |
104 val dest_disj1 = precomp (destd I) @{lemma "~(P | Q) ==> ~P" by fast} |
105 val dest_disj2 = T.precompose2 (destd dn1) @{lemma "~(~P | Q) ==> P" by fast} |
105 val dest_disj2 = precomp (destd dn1) @{lemma "~(~P | Q) ==> P" by fast} |
106 val dest_disj3 = T.precompose2 (destd I) @{lemma "~(P | Q) ==> ~Q" by fast} |
106 val dest_disj3 = precomp (destd I) @{lemma "~(P | Q) ==> ~Q" by fast} |
107 val dest_disj4 = T.precompose2 (destd dn2) @{lemma "~(P | ~Q) ==> Q" by fast} |
107 val dest_disj4 = precomp (destd dn2) @{lemma "~(P | ~Q) ==> Q" by fast} |
108 |
108 |
109 fun dest_disj_rules t = |
109 fun dest_disj_rules t = |
110 (case dest_disj_term' is_neg t of |
110 (case dest_disj_term' is_neg t of |
111 SOME (true, true) => SOME (dest_disj2, dest_disj4) |
111 SOME (true, true) => SOME (dest_disj2, dest_disj4) |
112 | SOME (true, false) => SOME (dest_disj2, dest_disj3) |
112 | SOME (true, false) => SOME (dest_disj2, dest_disj3) |
113 | SOME (false, true) => SOME (dest_disj1, dest_disj4) |
113 | SOME (false, true) => SOME (dest_disj1, dest_disj4) |
114 | SOME (false, false) => SOME (dest_disj1, dest_disj3) |
114 | SOME (false, false) => SOME (dest_disj1, dest_disj3) |
115 | NONE => NONE) |
115 | NONE => NONE) |
116 |
116 |
117 fun destn ct = [Thm.dest_arg (Thm.dest_arg (Thm.dest_arg ct))] |
117 fun destn ct = [Thm.dest_arg (Thm.dest_arg (Thm.dest_arg ct))] |
118 val dneg_rule = T.precompose destn @{thm notnotD} |
118 val dneg_rule = Z3_Proof_Tools.precompose destn @{thm notnotD} |
119 in |
119 in |
120 |
120 |
121 (* |
121 (* |
122 explode a term into literals and collect all rules to be able to deduce |
122 explode a term into literals and collect all rules to be able to deduce |
123 particular literals afterwards |
123 particular literals afterwards |
160 let |
160 let |
161 val dest_rules = if is_conj then dest_conj_rules else dest_disj_rules |
161 val dest_rules = if is_conj then dest_conj_rules else dest_disj_rules |
162 val tab = fold (Termtab.update o rpair ()) stop_lits Termtab.empty |
162 val tab = fold (Termtab.update o rpair ()) stop_lits Termtab.empty |
163 |
163 |
164 fun explode1 thm = |
164 fun explode1 thm = |
165 if Termtab.defined tab (U.prop_of thm) then cons thm |
165 if Termtab.defined tab (SMT_Utils.prop_of thm) then cons thm |
166 else |
166 else |
167 (case dest_rules (U.prop_of thm) of |
167 (case dest_rules (SMT_Utils.prop_of thm) of |
168 SOME (rule1, rule2) => |
168 SOME (rule1, rule2) => |
169 explode2 rule1 thm #> |
169 explode2 rule1 thm #> |
170 explode2 rule2 thm #> |
170 explode2 rule2 thm #> |
171 keep_intermediate ? cons thm |
171 keep_intermediate ? cons thm |
172 | NONE => cons thm) |
172 | NONE => cons thm) |
173 |
173 |
174 and explode2 dest_rule thm = |
174 and explode2 dest_rule thm = |
175 if full orelse exists_lit is_conj (Termtab.defined tab) (U.prop_of thm) |
175 if full orelse |
176 then explode1 (T.compose dest_rule thm) |
176 exists_lit is_conj (Termtab.defined tab) (SMT_Utils.prop_of thm) |
177 else cons (T.compose dest_rule thm) |
177 then explode1 (Z3_Proof_Tools.compose dest_rule thm) |
|
178 else cons (Z3_Proof_Tools.compose dest_rule thm) |
178 |
179 |
179 fun explode0 thm = |
180 fun explode0 thm = |
180 if not is_conj andalso is_dneg (U.prop_of thm) |
181 if not is_conj andalso is_dneg (SMT_Utils.prop_of thm) |
181 then [T.compose dneg_rule thm] |
182 then [Z3_Proof_Tools.compose dneg_rule thm] |
182 else explode1 thm [] |
183 else explode1 thm [] |
183 |
184 |
184 in explode0 end |
185 in explode0 end |
185 |
186 |
186 end |
187 end |
193 fun on_cprem i f thm = f (Thm.cprem_of thm i) |
194 fun on_cprem i f thm = f (Thm.cprem_of thm i) |
194 fun on_cprop f thm = f (Thm.cprop_of thm) |
195 fun on_cprop f thm = f (Thm.cprop_of thm) |
195 fun precomp2 f g thm = (on_cprem 1 f thm, on_cprem 2 g thm, f, g, thm) |
196 fun precomp2 f g thm = (on_cprem 1 f thm, on_cprem 2 g thm, f, g, thm) |
196 fun comp2 (cv1, cv2, f, g, rule) thm1 thm2 = |
197 fun comp2 (cv1, cv2, f, g, rule) thm1 thm2 = |
197 Thm.instantiate ([], [(cv1, on_cprop f thm1), (cv2, on_cprop g thm2)]) rule |
198 Thm.instantiate ([], [(cv1, on_cprop f thm1), (cv2, on_cprop g thm2)]) rule |
198 |> T.discharge thm1 |> T.discharge thm2 |
199 |> Z3_Proof_Tools.discharge thm1 |> Z3_Proof_Tools.discharge thm2 |
199 |
200 |
200 fun d1 ct = Thm.dest_arg ct and d2 ct = Thm.dest_arg (Thm.dest_arg ct) |
201 fun d1 ct = Thm.dest_arg ct and d2 ct = Thm.dest_arg (Thm.dest_arg ct) |
201 |
202 |
202 val conj_rule = precomp2 d1 d1 @{thm conjI} |
203 val conj_rule = precomp2 d1 d1 @{thm conjI} |
203 fun comp_conj ((_, thm1), (_, thm2)) = comp2 conj_rule thm1 thm2 |
204 fun comp_conj ((_, thm1), (_, thm2)) = comp2 conj_rule thm1 thm2 |
217 |
218 |
218 val neg = (fn @{const Not} $ t => (true, t) | t => (false, @{const Not} $ t)) |
219 val neg = (fn @{const Not} $ t => (true, t) | t => (false, @{const Not} $ t)) |
219 fun dest_disj (@{const Not} $ (@{const HOL.disj} $ t $ u)) = (neg t, neg u) |
220 fun dest_disj (@{const Not} $ (@{const HOL.disj} $ t $ u)) = (neg t, neg u) |
220 | dest_disj t = raise TERM ("dest_disj", [t]) |
221 | dest_disj t = raise TERM ("dest_disj", [t]) |
221 |
222 |
222 val dnegE = T.precompose (single o d2 o d1) @{thm notnotD} |
223 val precomp = Z3_Proof_Tools.precompose |
223 val dnegI = T.precompose (single o d1) @{lemma "P ==> ~~P" by fast} |
224 val dnegE = precomp (single o d2 o d1) @{thm notnotD} |
|
225 val dnegI = precomp (single o d1) @{lemma "P ==> ~~P" by fast} |
224 fun as_dneg f t = f (@{const Not} $ (@{const Not} $ t)) |
226 fun as_dneg f t = f (@{const Not} $ (@{const Not} $ t)) |
225 |
227 |
|
228 val precomp2 = Z3_Proof_Tools.precompose2 |
226 fun dni f = apsnd f o Thm.dest_binop o f o d1 |
229 fun dni f = apsnd f o Thm.dest_binop o f o d1 |
227 val negIffE = T.precompose2 (dni d1) @{lemma "~(P = (~Q)) ==> Q = P" by fast} |
230 val negIffE = precomp2 (dni d1) @{lemma "~(P = (~Q)) ==> Q = P" by fast} |
228 val negIffI = T.precompose2 (dni I) @{lemma "P = Q ==> ~(Q = (~P))" by fast} |
231 val negIffI = precomp2 (dni I) @{lemma "P = Q ==> ~(Q = (~P))" by fast} |
229 val iff_const = @{const HOL.eq (bool)} |
232 val iff_const = @{const HOL.eq (bool)} |
230 fun as_negIff f (@{const HOL.eq (bool)} $ t $ u) = |
233 fun as_negIff f (@{const HOL.eq (bool)} $ t $ u) = |
231 f (@{const Not} $ (iff_const $ u $ (@{const Not} $ t))) |
234 f (@{const Not} $ (iff_const $ u $ (@{const Not} $ t))) |
232 | as_negIff _ _ = NONE |
235 | as_negIff _ _ = NONE |
233 in |
236 in |
239 |
242 |
240 val lookup = lookup_lit littab |
243 val lookup = lookup_lit littab |
241 |
244 |
242 fun lookup_rule t = |
245 fun lookup_rule t = |
243 (case t of |
246 (case t of |
244 @{const Not} $ (@{const Not} $ t) => (T.compose dnegI, lookup t) |
247 @{const Not} $ (@{const Not} $ t) => |
|
248 (Z3_Proof_Tools.compose dnegI, lookup t) |
245 | @{const Not} $ (@{const HOL.eq (bool)} $ t $ (@{const Not} $ u)) => |
249 | @{const Not} $ (@{const HOL.eq (bool)} $ t $ (@{const Not} $ u)) => |
246 (T.compose negIffI, lookup (iff_const $ u $ t)) |
250 (Z3_Proof_Tools.compose negIffI, lookup (iff_const $ u $ t)) |
247 | @{const Not} $ ((eq as Const (@{const_name HOL.eq}, _)) $ t $ u) => |
251 | @{const Not} $ ((eq as Const (@{const_name HOL.eq}, _)) $ t $ u) => |
248 let fun rewr lit = lit COMP @{thm not_sym} |
252 let fun rewr lit = lit COMP @{thm not_sym} |
249 in (rewr, lookup (@{const Not} $ (eq $ u $ t))) end |
253 in (rewr, lookup (@{const Not} $ (eq $ u $ t))) end |
250 | _ => |
254 | _ => |
251 (case as_dneg lookup t of |
255 (case as_dneg lookup t of |
252 NONE => (T.compose negIffE, as_negIff lookup t) |
256 NONE => (Z3_Proof_Tools.compose negIffE, as_negIff lookup t) |
253 | x => (T.compose dnegE, x))) |
257 | x => (Z3_Proof_Tools.compose dnegE, x))) |
254 |
258 |
255 fun join1 (s, t) = |
259 fun join1 (s, t) = |
256 (case lookup t of |
260 (case lookup t of |
257 SOME lit => (s, lit) |
261 SOME lit => (s, lit) |
258 | NONE => |
262 | NONE => |
301 |
305 |
302 val falseE_v = Thm.dest_arg (Thm.dest_arg (Thm.cprop_of @{thm FalseE})) |
306 val falseE_v = Thm.dest_arg (Thm.dest_arg (Thm.cprop_of @{thm FalseE})) |
303 fun contra_right ct = Thm.instantiate ([], [(falseE_v, ct)]) @{thm FalseE} |
307 fun contra_right ct = Thm.instantiate ([], [(falseE_v, ct)]) @{thm FalseE} |
304 in |
308 in |
305 fun contradict conj ct = |
309 fun contradict conj ct = |
306 iff_intro (T.under_assumption (contra_left conj) ct) (contra_right ct) |
310 iff_intro (Z3_Proof_Tools.under_assumption (contra_left conj) ct) |
|
311 (contra_right ct) |
307 end |
312 end |
308 |
313 |
309 |
314 |
310 local |
315 local |
311 fun prove_eq l r (cl, cr) = |
316 fun prove_eq l r (cl, cr) = |
312 let |
317 let |
313 fun explode' is_conj = explode is_conj true (l <> r) [] |
318 fun explode' is_conj = explode is_conj true (l <> r) [] |
314 fun make_tab is_conj thm = make_littab (true_thm :: explode' is_conj thm) |
319 fun make_tab is_conj thm = make_littab (true_thm :: explode' is_conj thm) |
315 fun prove is_conj ct tab = join is_conj tab (Thm.term_of ct) |
320 fun prove is_conj ct tab = join is_conj tab (Thm.term_of ct) |
316 |
321 |
317 val thm1 = T.under_assumption (prove r cr o make_tab l) cl |
322 val thm1 = Z3_Proof_Tools.under_assumption (prove r cr o make_tab l) cl |
318 val thm2 = T.under_assumption (prove l cl o make_tab r) cr |
323 val thm2 = Z3_Proof_Tools.under_assumption (prove l cl o make_tab r) cr |
319 in iff_intro thm1 thm2 end |
324 in iff_intro thm1 thm2 end |
320 |
325 |
321 datatype conj_disj = CONJ | DISJ | NCON | NDIS |
326 datatype conj_disj = CONJ | DISJ | NCON | NDIS |
322 fun kind_of t = |
327 fun kind_of t = |
323 if is_conj t then SOME CONJ |
328 if is_conj t then SOME CONJ |