23 (*-----------------------------------------------------------------*) |
26 (*-----------------------------------------------------------------*) |
24 (*cooper_pp: provefunction for the one-exstance quantifier elimination*) |
27 (*cooper_pp: provefunction for the one-exstance quantifier elimination*) |
25 (* Here still only one problem : The proof for the arithmetical transformations done on the dvd atomic formulae*) |
28 (* Here still only one problem : The proof for the arithmetical transformations done on the dvd atomic formulae*) |
26 (*-----------------------------------------------------------------*) |
29 (*-----------------------------------------------------------------*) |
27 |
30 |
28 val presburger_ss = simpset_of (theory "Presburger"); |
31 fun cooper_pp sg (fm as e$Abs(xn,xT,p)) = |
29 |
|
30 fun cooper_pp sg vrl (fm as e$Abs(xn,xT,p)) = |
|
31 let val (xn1,p1) = variant_abs (xn,xT,p) |
32 let val (xn1,p1) = variant_abs (xn,xT,p) |
32 in (CooperProof.cooper_prv sg (Free (xn1, xT)) p1 vrl) end; |
33 in (CooperProof.cooper_prv sg (Free (xn1, xT)) p1) end; |
33 |
34 |
34 fun mnnf_pp sg fm = CooperProof.proof_of_cnnf sg fm |
35 fun mnnf_pp sg fm = CooperProof.proof_of_cnnf sg fm |
35 (CooperProof.proof_of_evalc sg); |
36 (CooperProof.proof_of_evalc sg); |
36 |
37 |
37 fun mproof_of_int_qelim sg fm = |
38 fun tmproof_of_int_qelim sg fm = |
38 Qelim.proof_of_mlift_qelim sg CooperDec.is_arith_rel |
39 Qelim.tproof_of_mlift_qelim sg CooperDec.is_arith_rel |
39 (CooperProof.proof_of_linform sg) (mnnf_pp sg) (cooper_pp sg) fm; |
40 (CooperProof.proof_of_linform sg) (mnnf_pp sg) (cooper_pp sg) fm; |
|
41 |
40 |
42 |
41 (* Theorems to be used in this tactic*) |
43 (* Theorems to be used in this tactic*) |
42 |
44 |
43 val zdvd_int = thm "zdvd_int"; |
45 val zdvd_int = thm "zdvd_int"; |
44 val zdiff_int_split = thm "zdiff_int_split"; |
46 val zdiff_int_split = thm "zdiff_int_split"; |
61 | add_term_typed_consts (Abs (_, _, t), cs) = add_term_typed_consts (t, cs) |
63 | add_term_typed_consts (Abs (_, _, t), cs) = add_term_typed_consts (t, cs) |
62 | add_term_typed_consts (_, cs) = cs; |
64 | add_term_typed_consts (_, cs) = cs; |
63 |
65 |
64 fun term_typed_consts t = add_term_typed_consts(t,[]); |
66 fun term_typed_consts t = add_term_typed_consts(t,[]); |
65 |
67 |
|
68 (* put a term into eta long beta normal form *) |
|
69 fun eta_long Ts (Abs (s, T, t)) = Abs (s, T, eta_long (T :: Ts) t) |
|
70 | eta_long Ts t = (case strip_comb t of |
|
71 (Abs _, _) => eta_long Ts (Envir.beta_norm t) |
|
72 | (u, ts) => |
|
73 let |
|
74 val Us = binder_types (fastype_of1 (Ts, t)); |
|
75 val i = length Us |
|
76 in list_abs (map (pair "x") Us, |
|
77 list_comb (incr_boundvars i u, map (eta_long (rev Us @ Ts)) |
|
78 (map (incr_boundvars i) ts @ map Bound (i - 1 downto 0)))) |
|
79 end); |
|
80 |
66 (* Some Types*) |
81 (* Some Types*) |
67 val bT = HOLogic.boolT; |
82 val bT = HOLogic.boolT; |
68 val iT = HOLogic.intT; |
83 val iT = HOLogic.intT; |
69 val binT = HOLogic.binT; |
84 val binT = HOLogic.binT; |
70 val nT = HOLogic.natT; |
85 val nT = HOLogic.natT; |
92 ("op +", iT --> iT --> iT), |
107 ("op +", iT --> iT --> iT), |
93 ("op -", iT --> iT --> iT), |
108 ("op -", iT --> iT --> iT), |
94 ("op *", iT --> iT --> iT), |
109 ("op *", iT --> iT --> iT), |
95 ("HOL.abs", iT --> iT), |
110 ("HOL.abs", iT --> iT), |
96 ("uminus", iT --> iT), |
111 ("uminus", iT --> iT), |
97 ("HOL.max", iT --> iT --> iT), |
|
98 ("HOL.min", iT --> iT --> iT), |
|
99 |
112 |
100 ("op <=", nT --> nT --> bT), |
113 ("op <=", nT --> nT --> bT), |
101 ("op =", nT --> nT --> bT), |
114 ("op =", nT --> nT --> bT), |
102 ("op <", nT --> nT --> bT), |
115 ("op <", nT --> nT --> bT), |
103 ("Divides.op dvd", nT --> nT --> bT), |
116 ("Divides.op dvd", nT --> nT --> bT), |
105 ("Divides.op mod", nT --> nT --> nT), |
118 ("Divides.op mod", nT --> nT --> nT), |
106 ("op +", nT --> nT --> nT), |
119 ("op +", nT --> nT --> nT), |
107 ("op -", nT --> nT --> nT), |
120 ("op -", nT --> nT --> nT), |
108 ("op *", nT --> nT --> nT), |
121 ("op *", nT --> nT --> nT), |
109 ("Suc", nT --> nT), |
122 ("Suc", nT --> nT), |
110 ("HOL.max", nT --> nT --> nT), |
|
111 ("HOL.min", nT --> nT --> nT), |
|
112 |
123 |
113 ("Numeral.bin.Bit", binT --> bT --> binT), |
124 ("Numeral.bin.Bit", binT --> bT --> binT), |
114 ("Numeral.bin.Pls", binT), |
125 ("Numeral.bin.Pls", binT), |
115 ("Numeral.bin.Min", binT), |
126 ("Numeral.bin.Min", binT), |
116 ("Numeral.number_of", binT --> iT), |
127 ("Numeral.number_of", binT --> iT), |
117 ("Numeral.number_of", binT --> nT), |
128 ("Numeral.number_of", binT --> nT), |
118 ("0", nT), |
129 ("0", nT), |
119 ("0", iT), |
130 ("0", iT), |
120 ("1", nT), |
131 ("1", nT), |
121 ("1", iT), |
132 ("1", iT), |
122 |
|
123 ("False", bT), |
133 ("False", bT), |
124 ("True", bT)]; |
134 ("True", bT)]; |
125 |
|
126 (*returns true if the formula is relevant for presburger arithmetic tactic*) |
|
127 fun relevant ps t = (term_typed_consts t) subset allowed_consts andalso |
|
128 map (fn i => snd (nth_elem (i, ps))) (loose_bnos t) @ |
|
129 map (snd o dest_Free) (term_frees t) @ map (snd o dest_Var) (term_vars t) |
|
130 subset [iT, nT]; |
|
131 |
135 |
132 (* Preparation of the formula to be sent to the Integer quantifier *) |
136 (* Preparation of the formula to be sent to the Integer quantifier *) |
133 (* elimination procedure *) |
137 (* elimination procedure *) |
134 (* Transforms meta implications and meta quantifiers to object *) |
138 (* Transforms meta implications and meta quantifiers to object *) |
135 (* implications and object quantifiers *) |
139 (* implications and object quantifiers *) |
136 |
140 |
137 fun prepare_for_presburger q fm = |
141 |
|
142 (*==================================*) |
|
143 (* Abstracting on subterms ========*) |
|
144 (*==================================*) |
|
145 (* Returns occurences of terms that are function application of type int or nat*) |
|
146 |
|
147 fun getfuncs fm = case strip_comb fm of |
|
148 (Free (_, T), ts as _ :: _) => |
|
149 if body_type T mem [iT, nT] |
|
150 andalso not (ts = []) andalso forall (null o loose_bnos) ts |
|
151 then [fm] |
|
152 else foldl op union ([], map getfuncs ts) |
|
153 | (Var (_, T), ts as _ :: _) => |
|
154 if body_type T mem [iT, nT] |
|
155 andalso not (ts = []) andalso forall (null o loose_bnos) ts then [fm] |
|
156 else foldl op union ([], map getfuncs ts) |
|
157 | (Const (s, T), ts) => |
|
158 if (s, T) mem allowed_consts orelse not (body_type T mem [iT, nT]) |
|
159 then foldl op union ([], map getfuncs ts) |
|
160 else [fm] |
|
161 | (Abs (s, T, t), _) => getfuncs t |
|
162 | _ => []; |
|
163 |
|
164 |
|
165 fun abstract_pres sg fm = |
|
166 foldr (fn (t, u) => |
|
167 let val T = fastype_of t |
|
168 in all T $ Abs ("x", T, abstract_over (t, u)) end) |
|
169 (getfuncs fm, fm); |
|
170 |
|
171 |
|
172 |
|
173 (* hasfuncs_on_bounds dont care of the type of the functions applied! |
|
174 It returns true if there is a subterm coresponding to the application of |
|
175 a function on a bounded variable. |
|
176 |
|
177 Function applications are allowed only for well predefined functions a |
|
178 consts*) |
|
179 |
|
180 fun has_free_funcs fm = case strip_comb fm of |
|
181 (Free (_, T), ts as _ :: _) => |
|
182 if (body_type T mem [iT,nT]) andalso (not (T mem [iT,nT])) |
|
183 then true |
|
184 else exists (fn x => x) (map has_free_funcs ts) |
|
185 | (Var (_, T), ts as _ :: _) => |
|
186 if (body_type T mem [iT,nT]) andalso not (T mem [iT,nT]) |
|
187 then true |
|
188 else exists (fn x => x) (map has_free_funcs ts) |
|
189 | (Const (s, T), ts) => exists (fn x => x) (map has_free_funcs ts) |
|
190 | (Abs (s, T, t), _) => has_free_funcs t |
|
191 |_ => false; |
|
192 |
|
193 |
|
194 (*returns true if the formula is relevant for presburger arithmetic tactic |
|
195 The constants occuring in term t should be a subset of the allowed_consts |
|
196 There also should be no occurences of application of functions on bounded |
|
197 variables. Whenever this function will be used, it will be ensured that t |
|
198 will not contain subterms with function symbols that could have been |
|
199 abstracted over.*) |
|
200 |
|
201 fun relevant ps t = (term_typed_consts t) subset allowed_consts andalso |
|
202 map (fn i => snd (nth_elem (i, ps))) (loose_bnos t) @ |
|
203 map (snd o dest_Free) (term_frees t) @ map (snd o dest_Var) (term_vars t) |
|
204 subset [iT, nT] |
|
205 andalso not (has_free_funcs t); |
|
206 |
|
207 |
|
208 fun prepare_for_presburger sg q fm = |
138 let |
209 let |
139 val ps = Logic.strip_params fm |
210 val ps = Logic.strip_params fm |
140 val hs = map HOLogic.dest_Trueprop (Logic.strip_assums_hyp fm) |
211 val hs = map HOLogic.dest_Trueprop (Logic.strip_assums_hyp fm) |
141 val c = HOLogic.dest_Trueprop (Logic.strip_assums_concl fm) |
212 val c = HOLogic.dest_Trueprop (Logic.strip_assums_concl fm) |
142 val _ = if relevant (rev ps) c then () else raise CooperDec.COOPER |
213 val _ = if relevant (rev ps) c then () |
|
214 else (trace_msg ("Conclusion is not a presburger term:\n" ^ |
|
215 Sign.string_of_term sg c); raise CooperDec.COOPER) |
143 fun mk_all ((s, T), (P,n)) = |
216 fun mk_all ((s, T), (P,n)) = |
144 if 0 mem loose_bnos P then |
217 if 0 mem loose_bnos P then |
145 (HOLogic.all_const T $ Abs (s, T, P), n) |
218 (HOLogic.all_const T $ Abs (s, T, P), n) |
146 else (incr_boundvars ~1 P, n-1) |
219 else (incr_boundvars ~1 P, n-1) |
147 fun mk_all2 (v, t) = HOLogic.all_const (fastype_of v) $ lambda v t; |
220 fun mk_all2 (v, t) = HOLogic.all_const (fastype_of v) $ lambda v t; |
159 |
232 |
160 (* object implication to meta---*) |
233 (* object implication to meta---*) |
161 fun mp_step n th = if (n=0) then th else (mp_step (n-1) th) RS mp; |
234 fun mp_step n th = if (n=0) then th else (mp_step (n-1) th) RS mp; |
162 |
235 |
163 (* the presburger tactic*) |
236 (* the presburger tactic*) |
164 fun presburger_tac q i = ObjectLogic.atomize_tac i THEN (fn st => |
237 |
|
238 (* Parameters : q = flag for quantify ofer free variables ; |
|
239 a = flag for abstracting over function occurences |
|
240 i = subgoal *) |
|
241 |
|
242 fun presburger_tac q a i = ObjectLogic.atomize_tac i THEN (fn st => |
165 let |
243 let |
166 val g = BasisLibrary.List.nth (prems_of st, i - 1); |
244 val g = BasisLibrary.List.nth (prems_of st, i - 1) |
167 val sg = sign_of_thm st; |
245 val sg = sign_of_thm st |
|
246 (* The Abstraction step *) |
|
247 val g' = if a then abstract_pres sg g else g |
168 (* Transform the term*) |
248 (* Transform the term*) |
169 val (t,np,nh) = prepare_for_presburger q g |
249 val (t,np,nh) = prepare_for_presburger sg q g' |
170 (* Some simpsets for dealing with mod div abs and nat*) |
250 (* Some simpsets for dealing with mod div abs and nat*) |
171 |
|
172 val simpset0 = HOL_basic_ss |
251 val simpset0 = HOL_basic_ss |
173 addsimps [mod_div_equality', Suc_plus1] |
252 addsimps [mod_div_equality', Suc_plus1] |
174 addsplits [split_zdiv, split_zmod, split_div', split_min, split_max] |
253 addsplits [split_zdiv, split_zmod, split_div', split_min, split_max] |
175 (* Simp rules for changing (n::int) to int n *) |
254 (* Simp rules for changing (n::int) to int n *) |
176 val simpset1 = HOL_basic_ss |
255 val simpset1 = HOL_basic_ss |
181 |
260 |
182 val simpset2 = HOL_basic_ss |
261 val simpset2 = HOL_basic_ss |
183 addsimps [nat_0_le, all_nat, ex_nat, number_of1, number_of2, int_0, int_1] |
262 addsimps [nat_0_le, all_nat, ex_nat, number_of1, number_of2, int_0, int_1] |
184 addcongs [conj_le_cong, imp_le_cong] |
263 addcongs [conj_le_cong, imp_le_cong] |
185 (* simp rules for elimination of abs *) |
264 (* simp rules for elimination of abs *) |
186 |
|
187 val simpset3 = HOL_basic_ss addsplits [abs_split] |
265 val simpset3 = HOL_basic_ss addsplits [abs_split] |
188 |
|
189 val ct = cterm_of sg (HOLogic.mk_Trueprop t) |
266 val ct = cterm_of sg (HOLogic.mk_Trueprop t) |
190 |
|
191 (* Theorem for the nat --> int transformation *) |
267 (* Theorem for the nat --> int transformation *) |
192 val pre_thm = Seq.hd (EVERY |
268 val pre_thm = Seq.hd (EVERY |
193 [simp_tac simpset0 i, |
269 [simp_tac simpset0 1, |
194 TRY (simp_tac simpset1 i), TRY (simp_tac simpset2 i), |
270 TRY (simp_tac simpset1 1), TRY (simp_tac simpset2 1), |
195 TRY (simp_tac simpset3 i), TRY (simp_tac presburger_ss i)] |
271 TRY (simp_tac simpset3 1)] |
196 (trivial ct)) |
272 (trivial ct)) |
197 |
273 fun assm_tac i = REPEAT_DETERM_N nh (assume_tac i) |
198 fun assm_tac i = REPEAT_DETERM_N nh (assume_tac i); |
|
199 |
|
200 (* The result of the quantifier elimination *) |
274 (* The result of the quantifier elimination *) |
201 val (th, tac) = case (prop_of pre_thm) of |
275 val (th, tac) = case (prop_of pre_thm) of |
202 Const ("==>", _) $ (Const ("Trueprop", _) $ t1) $ _ => |
276 Const ("==>", _) $ (Const ("Trueprop", _) $ t1) $ _ => |
203 (trace_msg ("calling procedure with term:\n" ^ |
277 (trace_msg ("calling procedure with term:\n" ^ |
204 Sign.string_of_term sg t1); |
278 Sign.string_of_term sg t1); |
205 ((mproof_of_int_qelim sg (Pattern.eta_long [] t1) RS iffD2) RS pre_thm, |
279 ((tmproof_of_int_qelim sg (Pattern.eta_long [] t1) RS iffD2) RS pre_thm, |
206 assm_tac (i + 1) THEN (if q then I else TRY) (rtac TrueI i))) |
280 assm_tac (i + 1) THEN (if q then I else TRY) (rtac TrueI i))) |
207 | _ => (pre_thm, assm_tac i) |
281 | _ => (pre_thm, assm_tac i) |
208 in (rtac (((mp_step nh) o (spec_step np)) th) i THEN tac) st |
282 in (rtac (((mp_step nh) o (spec_step np)) th) i |
|
283 THEN tac) st |
209 end handle Subscript => no_tac st | CooperDec.COOPER => no_tac st); |
284 end handle Subscript => no_tac st | CooperDec.COOPER => no_tac st); |
210 |
285 |
211 fun presburger_args meth = |
286 fun presburger_args meth = |
212 Method.simple_args (Scan.optional (Args.$$$ "no_quantify" >> K false) true) |
287 let val parse_flag = |
213 (fn q => fn _ => meth q 1); |
288 Args.$$$ "no_quantify" >> K (apfst (K false)) |
214 |
289 || Args.$$$ "no_abs" >> K (apsnd (K false)); |
215 fun presburger_method q i = Method.METHOD (fn facts => |
290 in |
216 Method.insert_tac facts 1 THEN presburger_tac q i) |
291 Method.simple_args |
|
292 (Scan.optional (Args.$$$ "(" |-- Args.list1 parse_flag --| Args.$$$ ")") [] >> |
|
293 curry (foldl op |>) (true, true)) |
|
294 (fn (q,a) => fn _ => meth q a 1) |
|
295 end; |
|
296 |
|
297 fun presburger_method q a i = Method.METHOD (fn facts => |
|
298 Method.insert_tac facts 1 THEN presburger_tac q a i) |
217 |
299 |
218 val setup = |
300 val setup = |
219 [Method.add_method ("presburger", |
301 [Method.add_method ("presburger", |
220 presburger_args presburger_method, |
302 presburger_args presburger_method, |
221 "decision procedure for Presburger arithmetic"), |
303 "decision procedure for Presburger arithmetic"), |
222 ArithTheoryData.map (fn {splits, inj_consts, discrete, presburger} => |
304 ArithTheoryData.map (fn {splits, inj_consts, discrete, presburger} => |
223 {splits = splits, inj_consts = inj_consts, discrete = discrete, |
305 {splits = splits, inj_consts = inj_consts, discrete = discrete, |
224 presburger = Some (presburger_tac true)})]; |
306 presburger = Some (presburger_tac true true)})]; |
225 |
307 |
226 end; |
308 end; |
227 |
309 |
228 val presburger_tac = Presburger.presburger_tac true; |
310 val presburger_tac = Presburger.presburger_tac true true; |