author | wenzelm |
Sat, 30 Nov 2024 16:01:58 +0100 | |
changeset 81513 | d11ed1bf0ad2 |
parent 80639 | 3322b6ae6b19 |
child 81954 | 6f2bcdfa9a19 |
permissions | -rw-r--r-- |
55239 | 1 |
(* Title: HOL/Tools/cnf.ML |
17618 | 2 |
Author: Alwen Tiu, QSL Team, LORIA (http://qsl.loria.fr) |
29265
5b4247055bd7
moved old add_term_vars, add_term_frees etc. to structure OldTerm;
wenzelm
parents:
26341
diff
changeset
|
3 |
Author: Tjark Weber, TU Muenchen |
17618 | 4 |
|
32960
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
5 |
FIXME: major overlaps with the code in meson.ML |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
6 |
|
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
7 |
Functions and tactics to transform a formula into Conjunctive Normal |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
8 |
Form (CNF). |
24958 | 9 |
|
32960
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
10 |
A formula in CNF is of the following form: |
17618 | 11 |
|
32960
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
12 |
(x11 | x12 | ... | x1n) & ... & (xm1 | xm2 | ... | xmk) |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
13 |
False |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
14 |
True |
17618 | 15 |
|
32960
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
16 |
where each xij is a literal (a positive or negative atomic Boolean |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
17 |
term), i.e. the formula is a conjunction of disjunctions of literals, |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
18 |
or "False", or "True". |
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
19 |
|
32960
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
20 |
A (non-empty) disjunction of literals is referred to as "clause". |
17618 | 21 |
|
32960
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
22 |
For the purpose of SAT proof reconstruction, we also make use of |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
23 |
another representation of clauses, which we call the "raw clauses". |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
24 |
Raw clauses are of the form |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
25 |
|
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
26 |
[..., x1', x2', ..., xn'] |- False , |
17618 | 27 |
|
32960
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
28 |
where each xi is a literal, and each xi' is the negation normal form |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
29 |
of ~xi. |
19236
150e8b0fb991
clauses now use (meta-)hyps instead of (meta-)implications; significant speedup
webertj
parents:
17809
diff
changeset
|
30 |
|
32960
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
31 |
Literals are successively removed from the hyps of raw clauses by |
69916a850301
eliminated hard tabulators, guessing at each author's individual tab-width;
wenzelm
parents:
32740
diff
changeset
|
32 |
resolution during SAT proof reconstruction. |
17618 | 33 |
*) |
34 |
||
35 |
signature CNF = |
|
36 |
sig |
|
41447 | 37 |
val is_atom: term -> bool |
38 |
val is_literal: term -> bool |
|
39 |
val is_clause: term -> bool |
|
40 |
val clause_is_trivial: term -> bool |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
41 |
|
59498
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
42 |
val clause2raw_thm: Proof.context -> thm -> thm |
80638 | 43 |
val make_nnf_thm: Proof.context -> term -> thm |
17618 | 44 |
|
58963
26bf09b95dda
proper context for assume_tac (atac remains as fall-back without context);
wenzelm
parents:
58839
diff
changeset
|
45 |
val weakening_tac: Proof.context -> int -> tactic (* removes the first hypothesis of a subgoal *) |
17618 | 46 |
|
42335 | 47 |
val make_cnf_thm: Proof.context -> term -> thm |
48 |
val make_cnfx_thm: Proof.context -> term -> thm |
|
41447 | 49 |
val cnf_rewrite_tac: Proof.context -> int -> tactic (* converts all prems of a subgoal to CNF *) |
50 |
val cnfx_rewrite_tac: Proof.context -> int -> tactic |
|
51 |
(* converts all prems of a subgoal to (almost) definitional CNF *) |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
52 |
end; |
17618 | 53 |
|
55239 | 54 |
structure CNF : CNF = |
17618 | 55 |
struct |
56 |
||
80637 | 57 |
fun is_atom \<^Const_>\<open>False\<close> = false |
58 |
| is_atom \<^Const_>\<open>True\<close> = false |
|
59 |
| is_atom \<^Const_>\<open>conj for _ _\<close> = false |
|
60 |
| is_atom \<^Const_>\<open>disj for _ _\<close> = false |
|
61 |
| is_atom \<^Const_>\<open>implies for _ _\<close> = false |
|
62 |
| is_atom \<^Const_>\<open>HOL.eq \<^Type>\<open>bool\<close> for _ _\<close> = false |
|
63 |
| is_atom \<^Const_>\<open>Not for _\<close> = false |
|
41447 | 64 |
| is_atom _ = true; |
17618 | 65 |
|
80637 | 66 |
fun is_literal \<^Const_>\<open>Not for x\<close> = is_atom x |
41447 | 67 |
| is_literal x = is_atom x; |
17618 | 68 |
|
80637 | 69 |
fun is_clause \<^Const_>\<open>disj for x y\<close> = is_clause x andalso is_clause y |
41447 | 70 |
| is_clause x = is_literal x; |
17618 | 71 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
72 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
73 |
(* clause_is_trivial: a clause is trivially true if it contains both an atom *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
74 |
(* and the atom's negation *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
75 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
76 |
|
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
77 |
fun clause_is_trivial c = |
41447 | 78 |
let |
80637 | 79 |
fun dual \<^Const_>\<open>Not for x\<close> = x |
80 |
| dual x = \<^Const>\<open>Not for x\<close> |
|
41447 | 81 |
fun has_duals [] = false |
82 |
| has_duals (x::xs) = member (op =) xs (dual x) orelse has_duals xs |
|
83 |
in |
|
84 |
has_duals (HOLogic.disjuncts c) |
|
85 |
end; |
|
17618 | 86 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
87 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
88 |
(* clause2raw_thm: translates a clause into a raw clause, i.e. *) |
20440
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
webertj
parents:
19236
diff
changeset
|
89 |
(* [...] |- x1 | ... | xn *) |
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
90 |
(* (where each xi is a literal) is translated to *) |
20440
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
webertj
parents:
19236
diff
changeset
|
91 |
(* [..., x1', ..., xn'] |- False , *) |
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
webertj
parents:
19236
diff
changeset
|
92 |
(* where each xi' is the negation normal form of ~xi *) |
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
93 |
(* ------------------------------------------------------------------------- *) |
17618 | 94 |
|
59498
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
95 |
fun clause2raw_thm ctxt clause = |
41447 | 96 |
let |
97 |
(* eliminates negated disjunctions from the i-th premise, possibly *) |
|
98 |
(* adding new premises, then continues with the (i+1)-th premise *) |
|
99 |
fun not_disj_to_prem i thm = |
|
59582 | 100 |
if i > Thm.nprems_of thm then |
41447 | 101 |
thm |
102 |
else |
|
59498
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents:
58963
diff
changeset
|
103 |
not_disj_to_prem (i+1) |
70486 | 104 |
(Seq.hd (REPEAT_DETERM (resolve_tac ctxt @{thms cnf.clause2raw_not_disj} i) thm)) |
41447 | 105 |
(* moves all premises to hyps, i.e. "[...] |- A1 ==> ... ==> An ==> B" *) |
106 |
(* becomes "[..., A1, ..., An] |- B" *) |
|
107 |
fun prems_to_hyps thm = |
|
108 |
fold (fn cprem => fn thm' => |
|
109 |
Thm.implies_elim thm' (Thm.assume cprem)) (cprems_of thm) thm |
|
110 |
in |
|
111 |
(* [...] |- ~(x1 | ... | xn) ==> False *) |
|
70486 | 112 |
(@{thm cnf.clause2raw_notE} OF [clause]) |
41447 | 113 |
(* [...] |- ~x1 ==> ... ==> ~xn ==> False *) |
114 |
|> not_disj_to_prem 1 |
|
115 |
(* [...] |- x1' ==> ... ==> xn' ==> False *) |
|
70486 | 116 |
|> Seq.hd o TRYALL (resolve_tac ctxt @{thms cnf.clause2raw_not_not}) |
41447 | 117 |
(* [..., x1', ..., xn'] |- False *) |
118 |
|> prems_to_hyps |
|
119 |
end; |
|
17618 | 120 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
121 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
122 |
(* inst_thm: instantiates a theorem with a list of terms *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
123 |
(* ------------------------------------------------------------------------- *) |
17618 | 124 |
|
80638 | 125 |
fun inst_thm ctxt ts thm = |
126 |
Thm.instantiate' [] (map (SOME o Thm.cterm_of ctxt) ts) thm; |
|
17618 | 127 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
128 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
129 |
(* Naive CNF transformation *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
130 |
(* ------------------------------------------------------------------------- *) |
17618 | 131 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
132 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
133 |
(* make_nnf_thm: produces a theorem of the form t = t', where t' is the *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
134 |
(* negation normal form (i.e. negation only occurs in front of atoms) *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
135 |
(* of t; implications ("-->") and equivalences ("=" on bool) are *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
136 |
(* eliminated (possibly causing an exponential blowup) *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
137 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
138 |
|
80638 | 139 |
fun make_nnf_thm ctxt \<^Const_>\<open>conj for x y\<close> = |
41447 | 140 |
let |
80638 | 141 |
val thm1 = make_nnf_thm ctxt x |
142 |
val thm2 = make_nnf_thm ctxt y |
|
41447 | 143 |
in |
70486 | 144 |
@{thm cnf.conj_cong} OF [thm1, thm2] |
41447 | 145 |
end |
80638 | 146 |
| make_nnf_thm ctxt \<^Const_>\<open>disj for x y\<close> = |
41447 | 147 |
let |
80638 | 148 |
val thm1 = make_nnf_thm ctxt x |
149 |
val thm2 = make_nnf_thm ctxt y |
|
41447 | 150 |
in |
70486 | 151 |
@{thm cnf.disj_cong} OF [thm1, thm2] |
41447 | 152 |
end |
80638 | 153 |
| make_nnf_thm ctxt \<^Const_>\<open>implies for x y\<close> = |
41447 | 154 |
let |
80638 | 155 |
val thm1 = make_nnf_thm ctxt \<^Const>\<open>Not for x\<close> |
156 |
val thm2 = make_nnf_thm ctxt y |
|
41447 | 157 |
in |
70486 | 158 |
@{thm cnf.make_nnf_imp} OF [thm1, thm2] |
41447 | 159 |
end |
80638 | 160 |
| make_nnf_thm ctxt \<^Const_>\<open>HOL.eq \<^Type>\<open>bool\<close> for x y\<close> = |
41447 | 161 |
let |
80638 | 162 |
val thm1 = make_nnf_thm ctxt x |
163 |
val thm2 = make_nnf_thm ctxt \<^Const>\<open>Not for x\<close> |
|
164 |
val thm3 = make_nnf_thm ctxt y |
|
165 |
val thm4 = make_nnf_thm ctxt \<^Const>\<open>Not for y\<close> |
|
41447 | 166 |
in |
70486 | 167 |
@{thm cnf.make_nnf_iff} OF [thm1, thm2, thm3, thm4] |
41447 | 168 |
end |
80637 | 169 |
| make_nnf_thm _ \<^Const_>\<open>Not for \<^Const_>\<open>False\<close>\<close> = |
70486 | 170 |
@{thm cnf.make_nnf_not_false} |
80637 | 171 |
| make_nnf_thm _ \<^Const_>\<open>Not for \<^Const_>\<open>True\<close>\<close> = |
70486 | 172 |
@{thm cnf.make_nnf_not_true} |
80638 | 173 |
| make_nnf_thm ctxt \<^Const_>\<open>Not for \<^Const_>\<open>conj for x y\<close>\<close> = |
41447 | 174 |
let |
80638 | 175 |
val thm1 = make_nnf_thm ctxt \<^Const>\<open>Not for x\<close> |
176 |
val thm2 = make_nnf_thm ctxt \<^Const>\<open>Not for y\<close> |
|
41447 | 177 |
in |
70486 | 178 |
@{thm cnf.make_nnf_not_conj} OF [thm1, thm2] |
41447 | 179 |
end |
80638 | 180 |
| make_nnf_thm ctxt \<^Const_>\<open>Not for \<^Const_>\<open>disj for x y\<close>\<close> = |
41447 | 181 |
let |
80638 | 182 |
val thm1 = make_nnf_thm ctxt \<^Const>\<open>Not for x\<close> |
183 |
val thm2 = make_nnf_thm ctxt \<^Const>\<open>Not for y\<close> |
|
41447 | 184 |
in |
70486 | 185 |
@{thm cnf.make_nnf_not_disj} OF [thm1, thm2] |
41447 | 186 |
end |
80638 | 187 |
| make_nnf_thm ctxt \<^Const_>\<open>Not for \<^Const_>\<open>implies for x y\<close>\<close> = |
41447 | 188 |
let |
80638 | 189 |
val thm1 = make_nnf_thm ctxt x |
190 |
val thm2 = make_nnf_thm ctxt \<^Const>\<open>Not for y\<close> |
|
41447 | 191 |
in |
70486 | 192 |
@{thm cnf.make_nnf_not_imp} OF [thm1, thm2] |
41447 | 193 |
end |
80638 | 194 |
| make_nnf_thm ctxt \<^Const_>\<open>Not for \<^Const_>\<open>HOL.eq \<^Type>\<open>bool\<close> for x y\<close>\<close> = |
41447 | 195 |
let |
80638 | 196 |
val thm1 = make_nnf_thm ctxt x |
197 |
val thm2 = make_nnf_thm ctxt \<^Const>\<open>Not for x\<close> |
|
198 |
val thm3 = make_nnf_thm ctxt y |
|
199 |
val thm4 = make_nnf_thm ctxt \<^Const>\<open>Not for y\<close> |
|
41447 | 200 |
in |
70486 | 201 |
@{thm cnf.make_nnf_not_iff} OF [thm1, thm2, thm3, thm4] |
41447 | 202 |
end |
80638 | 203 |
| make_nnf_thm ctxt \<^Const_>\<open>Not for \<^Const_>\<open>Not for x\<close>\<close> = |
41447 | 204 |
let |
80638 | 205 |
val thm1 = make_nnf_thm ctxt x |
41447 | 206 |
in |
70486 | 207 |
@{thm cnf.make_nnf_not_not} OF [thm1] |
41447 | 208 |
end |
80638 | 209 |
| make_nnf_thm ctxt t = inst_thm ctxt [t] @{thm cnf.iff_refl}; |
17618 | 210 |
|
42335 | 211 |
fun make_under_quantifiers ctxt make t = |
212 |
let |
|
213 |
fun conv ctxt ct = |
|
59582 | 214 |
(case Thm.term_of ct of |
45511
9b0f8ca4388e
continued implementation of lambda-lifting in Metis
blanchet
parents:
44121
diff
changeset
|
215 |
Const _ $ Abs _ => Conv.comb_conv (conv ctxt) ct |
42335 | 216 |
| Abs _ => Conv.abs_conv (conv o snd) ctxt ct |
217 |
| Const _ => Conv.all_conv ct |
|
67710
cc2db3239932
added HOLogic.mk_obj_eq convenience and eliminated some clones;
wenzelm
parents:
67149
diff
changeset
|
218 |
| t => make t RS @{thm eq_reflection}) |
cc2db3239932
added HOLogic.mk_obj_eq convenience and eliminated some clones;
wenzelm
parents:
67149
diff
changeset
|
219 |
in HOLogic.mk_obj_eq (conv ctxt (Thm.cterm_of ctxt t)) end |
42335 | 220 |
|
221 |
fun make_nnf_thm_under_quantifiers ctxt = |
|
80638 | 222 |
make_under_quantifiers ctxt (make_nnf_thm ctxt) |
42335 | 223 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
224 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
225 |
(* simp_True_False_thm: produces a theorem t = t', where t' is equivalent to *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
226 |
(* t, but simplified wrt. the following theorems: *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
227 |
(* (True & x) = x *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
228 |
(* (x & True) = x *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
229 |
(* (False & x) = False *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
230 |
(* (x & False) = False *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
231 |
(* (True | x) = True *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
232 |
(* (x | True) = True *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
233 |
(* (False | x) = x *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
234 |
(* (x | False) = x *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
235 |
(* No simplification is performed below connectives other than & and |. *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
236 |
(* Optimization: The right-hand side of a conjunction (disjunction) is *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
237 |
(* simplified only if the left-hand side does not simplify to False *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
238 |
(* (True, respectively). *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
239 |
(* ------------------------------------------------------------------------- *) |
17618 | 240 |
|
80638 | 241 |
fun simp_True_False_thm ctxt \<^Const_>\<open>conj for x y\<close> = |
41447 | 242 |
let |
80638 | 243 |
val thm1 = simp_True_False_thm ctxt x |
59582 | 244 |
val x'= (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1 |
41447 | 245 |
in |
80637 | 246 |
if x' = \<^Const>\<open>False\<close> then |
70486 | 247 |
@{thm cnf.simp_TF_conj_False_l} OF [thm1] (* (x & y) = False *) |
41447 | 248 |
else |
249 |
let |
|
80638 | 250 |
val thm2 = simp_True_False_thm ctxt y |
59582 | 251 |
val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2 |
41447 | 252 |
in |
80637 | 253 |
if x' = \<^Const>\<open>True\<close> then |
70486 | 254 |
@{thm cnf.simp_TF_conj_True_l} OF [thm1, thm2] (* (x & y) = y' *) |
80637 | 255 |
else if y' = \<^Const>\<open>False\<close> then |
70486 | 256 |
@{thm cnf.simp_TF_conj_False_r} OF [thm2] (* (x & y) = False *) |
80637 | 257 |
else if y' = \<^Const>\<open>True\<close> then |
70486 | 258 |
@{thm cnf.simp_TF_conj_True_r} OF [thm1, thm2] (* (x & y) = x' *) |
41447 | 259 |
else |
70486 | 260 |
@{thm cnf.conj_cong} OF [thm1, thm2] (* (x & y) = (x' & y') *) |
41447 | 261 |
end |
262 |
end |
|
80638 | 263 |
| simp_True_False_thm ctxt \<^Const_>\<open>disj for x y\<close> = |
41447 | 264 |
let |
80638 | 265 |
val thm1 = simp_True_False_thm ctxt x |
59582 | 266 |
val x' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1 |
41447 | 267 |
in |
80637 | 268 |
if x' = \<^Const>\<open>True\<close> then |
70486 | 269 |
@{thm cnf.simp_TF_disj_True_l} OF [thm1] (* (x | y) = True *) |
41447 | 270 |
else |
271 |
let |
|
80638 | 272 |
val thm2 = simp_True_False_thm ctxt y |
59582 | 273 |
val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2 |
41447 | 274 |
in |
80637 | 275 |
if x' = \<^Const>\<open>False\<close> then |
70486 | 276 |
@{thm cnf.simp_TF_disj_False_l} OF [thm1, thm2] (* (x | y) = y' *) |
80637 | 277 |
else if y' = \<^Const>\<open>True\<close> then |
70486 | 278 |
@{thm cnf.simp_TF_disj_True_r} OF [thm2] (* (x | y) = True *) |
80637 | 279 |
else if y' = \<^Const>\<open>False\<close> then |
70486 | 280 |
@{thm cnf.simp_TF_disj_False_r} OF [thm1, thm2] (* (x | y) = x' *) |
41447 | 281 |
else |
70486 | 282 |
@{thm cnf.disj_cong} OF [thm1, thm2] (* (x | y) = (x' | y') *) |
41447 | 283 |
end |
284 |
end |
|
80638 | 285 |
| simp_True_False_thm ctxt t = inst_thm ctxt [t] @{thm cnf.iff_refl}; (* t = t *) |
17618 | 286 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
287 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
288 |
(* make_cnf_thm: given any HOL term 't', produces a theorem t = t', where t' *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
289 |
(* is in conjunction normal form. May cause an exponential blowup *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
290 |
(* in the length of the term. *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
291 |
(* ------------------------------------------------------------------------- *) |
17618 | 292 |
|
42335 | 293 |
fun make_cnf_thm ctxt t = |
41447 | 294 |
let |
80637 | 295 |
fun make_cnf_thm_from_nnf \<^Const_>\<open>conj for x y\<close> = |
41447 | 296 |
let |
297 |
val thm1 = make_cnf_thm_from_nnf x |
|
298 |
val thm2 = make_cnf_thm_from_nnf y |
|
299 |
in |
|
70486 | 300 |
@{thm cnf.conj_cong} OF [thm1, thm2] |
41447 | 301 |
end |
80637 | 302 |
| make_cnf_thm_from_nnf \<^Const_>\<open>disj for x y\<close> = |
41447 | 303 |
let |
304 |
(* produces a theorem "(x' | y') = t'", where x', y', and t' are in CNF *) |
|
80637 | 305 |
fun make_cnf_disj_thm \<^Const_>\<open>conj for x1 x2\<close> y' = |
41447 | 306 |
let |
307 |
val thm1 = make_cnf_disj_thm x1 y' |
|
308 |
val thm2 = make_cnf_disj_thm x2 y' |
|
309 |
in |
|
70486 | 310 |
@{thm cnf.make_cnf_disj_conj_l} OF [thm1, thm2] (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *) |
41447 | 311 |
end |
80637 | 312 |
| make_cnf_disj_thm x' \<^Const_>\<open>conj for y1 y2\<close> = |
41447 | 313 |
let |
314 |
val thm1 = make_cnf_disj_thm x' y1 |
|
315 |
val thm2 = make_cnf_disj_thm x' y2 |
|
316 |
in |
|
70486 | 317 |
@{thm cnf.make_cnf_disj_conj_r} OF [thm1, thm2] (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *) |
41447 | 318 |
end |
319 |
| make_cnf_disj_thm x' y' = |
|
80638 | 320 |
inst_thm ctxt [\<^Const>\<open>disj for x' y'\<close>] @{thm cnf.iff_refl} (* (x' | y') = (x' | y') *) |
41447 | 321 |
val thm1 = make_cnf_thm_from_nnf x |
322 |
val thm2 = make_cnf_thm_from_nnf y |
|
59582 | 323 |
val x' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1 |
324 |
val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2 |
|
70486 | 325 |
val disj_thm = @{thm cnf.disj_cong} OF [thm1, thm2] (* (x | y) = (x' | y') *) |
41447 | 326 |
in |
70486 | 327 |
@{thm cnf.iff_trans} OF [disj_thm, make_cnf_disj_thm x' y'] |
41447 | 328 |
end |
80638 | 329 |
| make_cnf_thm_from_nnf t = inst_thm ctxt [t] @{thm cnf.iff_refl} |
41447 | 330 |
(* convert 't' to NNF first *) |
42335 | 331 |
val nnf_thm = make_nnf_thm_under_quantifiers ctxt t |
332 |
(*### |
|
80638 | 333 |
val nnf_thm = make_nnf_thm ctxt t |
42335 | 334 |
*) |
59582 | 335 |
val nnf = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) nnf_thm |
41447 | 336 |
(* then simplify wrt. True/False (this should preserve NNF) *) |
80638 | 337 |
val simp_thm = simp_True_False_thm ctxt nnf |
59582 | 338 |
val simp = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) simp_thm |
41447 | 339 |
(* finally, convert to CNF (this should preserve the simplification) *) |
42335 | 340 |
val cnf_thm = make_under_quantifiers ctxt make_cnf_thm_from_nnf simp |
341 |
(* ### |
|
41447 | 342 |
val cnf_thm = make_cnf_thm_from_nnf simp |
42335 | 343 |
*) |
41447 | 344 |
in |
70486 | 345 |
@{thm cnf.iff_trans} OF [@{thm cnf.iff_trans} OF [nnf_thm, simp_thm], cnf_thm] |
41447 | 346 |
end; |
17618 | 347 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
348 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
349 |
(* CNF transformation by introducing new literals *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
350 |
(* ------------------------------------------------------------------------- *) |
17618 | 351 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
352 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
353 |
(* make_cnfx_thm: given any HOL term 't', produces a theorem t = t', where *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
354 |
(* t' is almost in conjunction normal form, except that conjunctions *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
355 |
(* and existential quantifiers may be nested. (Use e.g. 'REPEAT_DETERM *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
356 |
(* (etac exE i ORELSE etac conjE i)' afterwards to normalize.) May *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
357 |
(* introduce new (existentially bound) literals. Note: the current *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
358 |
(* implementation calls 'make_nnf_thm', causing an exponential blowup *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
359 |
(* in the case of nested equivalences. *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
360 |
(* ------------------------------------------------------------------------- *) |
17618 | 361 |
|
42335 | 362 |
fun make_cnfx_thm ctxt t = |
41447 | 363 |
let |
364 |
val var_id = Unsynchronized.ref 0 (* properly initialized below *) |
|
365 |
fun new_free () = |
|
80637 | 366 |
Free ("cnfx_" ^ string_of_int (Unsynchronized.inc var_id), \<^Type>\<open>bool\<close>) |
367 |
fun make_cnfx_thm_from_nnf \<^Const_>\<open>conj for x y\<close> = |
|
41447 | 368 |
let |
369 |
val thm1 = make_cnfx_thm_from_nnf x |
|
370 |
val thm2 = make_cnfx_thm_from_nnf y |
|
371 |
in |
|
70486 | 372 |
@{thm cnf.conj_cong} OF [thm1, thm2] |
41447 | 373 |
end |
80637 | 374 |
| make_cnfx_thm_from_nnf \<^Const_>\<open>disj for x y\<close> = |
41447 | 375 |
if is_clause x andalso is_clause y then |
80638 | 376 |
inst_thm ctxt [\<^Const>\<open>disj for x y\<close>] @{thm cnf.iff_refl} |
41447 | 377 |
else if is_literal y orelse is_literal x then |
378 |
let |
|
379 |
(* produces a theorem "(x' | y') = t'", where x', y', and t' are *) |
|
380 |
(* almost in CNF, and x' or y' is a literal *) |
|
80637 | 381 |
fun make_cnfx_disj_thm \<^Const_>\<open>conj for x1 x2\<close> y' = |
41447 | 382 |
let |
383 |
val thm1 = make_cnfx_disj_thm x1 y' |
|
384 |
val thm2 = make_cnfx_disj_thm x2 y' |
|
385 |
in |
|
70486 | 386 |
@{thm cnf.make_cnf_disj_conj_l} OF [thm1, thm2] (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *) |
41447 | 387 |
end |
80637 | 388 |
| make_cnfx_disj_thm x' \<^Const_>\<open>conj for y1 y2\<close> = |
41447 | 389 |
let |
390 |
val thm1 = make_cnfx_disj_thm x' y1 |
|
391 |
val thm2 = make_cnfx_disj_thm x' y2 |
|
392 |
in |
|
70486 | 393 |
@{thm cnf.make_cnf_disj_conj_r} OF [thm1, thm2] (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *) |
41447 | 394 |
end |
80637 | 395 |
| make_cnfx_disj_thm \<^Const_>\<open>Ex \<^Type>\<open>bool\<close> for x'\<close> y' = |
41447 | 396 |
let |
80638 | 397 |
val thm1 = inst_thm ctxt [x', y'] @{thm cnf.make_cnfx_disj_ex_l} (* ((Ex x') | y') = (Ex (x' | y')) *) |
41447 | 398 |
val var = new_free () |
399 |
val thm2 = make_cnfx_disj_thm (betapply (x', var)) y' (* (x' | y') = body' *) |
|
80638 | 400 |
val thm3 = Thm.forall_intr (Thm.cterm_of ctxt var) thm2 (* !!v. (x' | y') = body' *) |
41447 | 401 |
val thm4 = Thm.strip_shyps (thm3 COMP allI) (* ALL v. (x' | y') = body' *) |
70486 | 402 |
val thm5 = Thm.strip_shyps (thm4 RS @{thm cnf.make_cnfx_ex_cong}) (* (EX v. (x' | y')) = (EX v. body') *) |
41447 | 403 |
in |
70486 | 404 |
@{thm cnf.iff_trans} OF [thm1, thm5] (* ((Ex x') | y') = (Ex v. body') *) |
41447 | 405 |
end |
80637 | 406 |
| make_cnfx_disj_thm x' \<^Const_>\<open>Ex \<^Type>\<open>bool\<close> for y'\<close> = |
41447 | 407 |
let |
80638 | 408 |
val thm1 = inst_thm ctxt [x', y'] @{thm cnf.make_cnfx_disj_ex_r} (* (x' | (Ex y')) = (Ex (x' | y')) *) |
41447 | 409 |
val var = new_free () |
410 |
val thm2 = make_cnfx_disj_thm x' (betapply (y', var)) (* (x' | y') = body' *) |
|
80638 | 411 |
val thm3 = Thm.forall_intr (Thm.cterm_of ctxt var) thm2 (* !!v. (x' | y') = body' *) |
41447 | 412 |
val thm4 = Thm.strip_shyps (thm3 COMP allI) (* ALL v. (x' | y') = body' *) |
70486 | 413 |
val thm5 = Thm.strip_shyps (thm4 RS @{thm cnf.make_cnfx_ex_cong}) (* (EX v. (x' | y')) = (EX v. body') *) |
41447 | 414 |
in |
70486 | 415 |
@{thm cnf.iff_trans} OF [thm1, thm5] (* (x' | (Ex y')) = (EX v. body') *) |
41447 | 416 |
end |
417 |
| make_cnfx_disj_thm x' y' = |
|
80638 | 418 |
inst_thm ctxt [\<^Const>\<open>disj for x' y'\<close>] @{thm cnf.iff_refl} (* (x' | y') = (x' | y') *) |
41447 | 419 |
val thm1 = make_cnfx_thm_from_nnf x |
420 |
val thm2 = make_cnfx_thm_from_nnf y |
|
59582 | 421 |
val x' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1 |
422 |
val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2 |
|
70486 | 423 |
val disj_thm = @{thm cnf.disj_cong} OF [thm1, thm2] (* (x | y) = (x' | y') *) |
41447 | 424 |
in |
70486 | 425 |
@{thm cnf.iff_trans} OF [disj_thm, make_cnfx_disj_thm x' y'] |
41447 | 426 |
end |
427 |
else |
|
428 |
let (* neither 'x' nor 'y' is a literal: introduce a fresh variable *) |
|
80638 | 429 |
val thm1 = inst_thm ctxt [x, y] @{thm cnf.make_cnfx_newlit} (* (x | y) = EX v. (x | v) & (y | ~v) *) |
41447 | 430 |
val var = new_free () |
80637 | 431 |
val body = \<^Const>\<open>conj for \<^Const>\<open>disj for x var\<close> \<^Const>\<open>disj for y \<^Const>\<open>Not for var\<close>\<close>\<close> |
41447 | 432 |
val thm2 = make_cnfx_thm_from_nnf body (* (x | v) & (y | ~v) = body' *) |
80638 | 433 |
val thm3 = Thm.forall_intr (Thm.cterm_of ctxt var) thm2 (* !!v. (x | v) & (y | ~v) = body' *) |
41447 | 434 |
val thm4 = Thm.strip_shyps (thm3 COMP allI) (* ALL v. (x | v) & (y | ~v) = body' *) |
70486 | 435 |
val thm5 = Thm.strip_shyps (thm4 RS @{thm cnf.make_cnfx_ex_cong}) (* (EX v. (x | v) & (y | ~v)) = (EX v. body') *) |
41447 | 436 |
in |
70486 | 437 |
@{thm cnf.iff_trans} OF [thm1, thm5] |
41447 | 438 |
end |
80638 | 439 |
| make_cnfx_thm_from_nnf t = inst_thm ctxt [t] @{thm cnf.iff_refl} |
41447 | 440 |
(* convert 't' to NNF first *) |
42335 | 441 |
val nnf_thm = make_nnf_thm_under_quantifiers ctxt t |
442 |
(* ### |
|
80638 | 443 |
val nnf_thm = make_nnf_thm ctxt t |
42335 | 444 |
*) |
59582 | 445 |
val nnf = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) nnf_thm |
41447 | 446 |
(* then simplify wrt. True/False (this should preserve NNF) *) |
80638 | 447 |
val simp_thm = simp_True_False_thm ctxt nnf |
59582 | 448 |
val simp = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) simp_thm |
41447 | 449 |
(* initialize var_id, in case the term already contains variables of the form "cnfx_<int>" *) |
80639 | 450 |
val _ = (var_id := Frees.fold (fn ((name, _), _) => fn max => |
41447 | 451 |
let |
452 |
val idx = |
|
80639 | 453 |
(case try (unprefix "cnfx_") name of |
454 |
SOME s => Int.fromString s |
|
455 |
| NONE => NONE) |
|
41447 | 456 |
in |
457 |
Int.max (max, the_default 0 idx) |
|
80639 | 458 |
end) (Frees.build (Frees.add_frees simp)) 0) |
41447 | 459 |
(* finally, convert to definitional CNF (this should preserve the simplification) *) |
42335 | 460 |
val cnfx_thm = make_under_quantifiers ctxt make_cnfx_thm_from_nnf simp |
461 |
(*### |
|
41447 | 462 |
val cnfx_thm = make_cnfx_thm_from_nnf simp |
42335 | 463 |
*) |
41447 | 464 |
in |
70486 | 465 |
@{thm cnf.iff_trans} OF [@{thm cnf.iff_trans} OF [nnf_thm, simp_thm], cnfx_thm] |
41447 | 466 |
end; |
17618 | 467 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
468 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
469 |
(* Tactics *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
470 |
(* ------------------------------------------------------------------------- *) |
17618 | 471 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
472 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
473 |
(* weakening_tac: removes the first hypothesis of the 'i'-th subgoal *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
474 |
(* ------------------------------------------------------------------------- *) |
17618 | 475 |
|
58963
26bf09b95dda
proper context for assume_tac (atac remains as fall-back without context);
wenzelm
parents:
58839
diff
changeset
|
476 |
fun weakening_tac ctxt i = |
70486 | 477 |
dresolve_tac ctxt @{thms cnf.weakening_thm} i THEN assume_tac ctxt (i+1); |
17618 | 478 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
479 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
480 |
(* cnf_rewrite_tac: converts all premises of the 'i'-th subgoal to CNF *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
481 |
(* (possibly causing an exponential blowup in the length of each *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
482 |
(* premise) *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
483 |
(* ------------------------------------------------------------------------- *) |
17618 | 484 |
|
32232 | 485 |
fun cnf_rewrite_tac ctxt i = |
41447 | 486 |
(* cut the CNF formulas as new premises *) |
60696 | 487 |
Subgoal.FOCUS (fn {prems, context = ctxt', ...} => |
41447 | 488 |
let |
60696 | 489 |
val cnf_thms = map (make_cnf_thm ctxt' o HOLogic.dest_Trueprop o Thm.prop_of) prems |
70486 | 490 |
val cut_thms = map (fn (th, pr) => @{thm cnf.cnftac_eq_imp} OF [th, pr]) (cnf_thms ~~ prems) |
41447 | 491 |
in |
492 |
cut_facts_tac cut_thms 1 |
|
493 |
end) ctxt i |
|
494 |
(* remove the original premises *) |
|
495 |
THEN SELECT_GOAL (fn thm => |
|
496 |
let |
|
59582 | 497 |
val n = Logic.count_prems ((Term.strip_all_body o fst o Logic.dest_implies o Thm.prop_of) thm) |
41447 | 498 |
in |
58963
26bf09b95dda
proper context for assume_tac (atac remains as fall-back without context);
wenzelm
parents:
58839
diff
changeset
|
499 |
PRIMITIVE (funpow (n div 2) (Seq.hd o weakening_tac ctxt 1)) thm |
41447 | 500 |
end) i; |
17618 | 501 |
|
17809
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
502 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
503 |
(* cnfx_rewrite_tac: converts all premises of the 'i'-th subgoal to CNF *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
504 |
(* (possibly introducing new literals) *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
505 |
(* ------------------------------------------------------------------------- *) |
195045659c06
Tactics sat and satx reimplemented, several improvements
webertj
parents:
17618
diff
changeset
|
506 |
|
32232 | 507 |
fun cnfx_rewrite_tac ctxt i = |
41447 | 508 |
(* cut the CNF formulas as new premises *) |
60696 | 509 |
Subgoal.FOCUS (fn {prems, context = ctxt', ...} => |
41447 | 510 |
let |
60696 | 511 |
val cnfx_thms = map (make_cnfx_thm ctxt' o HOLogic.dest_Trueprop o Thm.prop_of) prems |
70486 | 512 |
val cut_thms = map (fn (th, pr) => @{thm cnf.cnftac_eq_imp} OF [th, pr]) (cnfx_thms ~~ prems) |
41447 | 513 |
in |
514 |
cut_facts_tac cut_thms 1 |
|
515 |
end) ctxt i |
|
516 |
(* remove the original premises *) |
|
517 |
THEN SELECT_GOAL (fn thm => |
|
518 |
let |
|
59582 | 519 |
val n = Logic.count_prems ((Term.strip_all_body o fst o Logic.dest_implies o Thm.prop_of) thm) |
41447 | 520 |
in |
58963
26bf09b95dda
proper context for assume_tac (atac remains as fall-back without context);
wenzelm
parents:
58839
diff
changeset
|
521 |
PRIMITIVE (funpow (n div 2) (Seq.hd o weakening_tac ctxt 1)) thm |
41447 | 522 |
end) i; |
17618 | 523 |
|
41447 | 524 |
end; |