equal
deleted
inserted
replaced
1 (* Title: HOL/Presburger.thy |
1 (* Title: HOL/Presburger.thy |
2 Author: Amine Chaieb, TU Muenchen |
2 Author: Amine Chaieb, TU Muenchen |
3 *) |
3 *) |
4 |
4 |
5 section {* Decision Procedure for Presburger Arithmetic *} |
5 section \<open>Decision Procedure for Presburger Arithmetic\<close> |
6 |
6 |
7 theory Presburger |
7 theory Presburger |
8 imports Groebner_Basis Set_Interval |
8 imports Groebner_Basis Set_Interval |
9 keywords "try0" :: diag |
9 keywords "try0" :: diag |
10 begin |
10 begin |
11 |
11 |
12 ML_file "Tools/Qelim/qelim.ML" |
12 ML_file "Tools/Qelim/qelim.ML" |
13 ML_file "Tools/Qelim/cooper_procedure.ML" |
13 ML_file "Tools/Qelim/cooper_procedure.ML" |
14 |
14 |
15 subsection{* The @{text "-\<infinity>"} and @{text "+\<infinity>"} Properties *} |
15 subsection\<open>The @{text "-\<infinity>"} and @{text "+\<infinity>"} Properties\<close> |
16 |
16 |
17 lemma minf: |
17 lemma minf: |
18 "\<lbrakk>\<exists>(z ::'a::linorder).\<forall>x<z. P x = P' x; \<exists>z.\<forall>x<z. Q x = Q' x\<rbrakk> |
18 "\<lbrakk>\<exists>(z ::'a::linorder).\<forall>x<z. P x = P' x; \<exists>z.\<forall>x<z. Q x = Q' x\<rbrakk> |
19 \<Longrightarrow> \<exists>z.\<forall>x<z. (P x \<and> Q x) = (P' x \<and> Q' x)" |
19 \<Longrightarrow> \<exists>z.\<forall>x<z. (P x \<and> Q x) = (P' x \<and> Q' x)" |
20 "\<lbrakk>\<exists>(z ::'a::linorder).\<forall>x<z. P x = P' x; \<exists>z.\<forall>x<z. Q x = Q' x\<rbrakk> |
20 "\<lbrakk>\<exists>(z ::'a::linorder).\<forall>x<z. P x = P' x; \<exists>z.\<forall>x<z. Q x = Q' x\<rbrakk> |
57 apply (auto elim!: dvdE simp add: algebra_simps) |
57 apply (auto elim!: dvdE simp add: algebra_simps) |
58 unfolding mult.assoc [symmetric] distrib_right [symmetric] left_diff_distrib [symmetric] |
58 unfolding mult.assoc [symmetric] distrib_right [symmetric] left_diff_distrib [symmetric] |
59 unfolding dvd_def mult.commute [of d] |
59 unfolding dvd_def mult.commute [of d] |
60 by auto |
60 by auto |
61 |
61 |
62 subsection{* The A and B sets *} |
62 subsection\<open>The A and B sets\<close> |
63 lemma bset: |
63 lemma bset: |
64 "\<lbrakk>\<forall>x.(\<forall>j \<in> {1 .. D}. \<forall>b\<in>B. x \<noteq> b + j)\<longrightarrow> P x \<longrightarrow> P(x - D) ; |
64 "\<lbrakk>\<forall>x.(\<forall>j \<in> {1 .. D}. \<forall>b\<in>B. x \<noteq> b + j)\<longrightarrow> P x \<longrightarrow> P(x - D) ; |
65 \<forall>x.(\<forall>j\<in>{1 .. D}. \<forall>b\<in>B. x \<noteq> b + j)\<longrightarrow> Q x \<longrightarrow> Q(x - D)\<rbrakk> \<Longrightarrow> |
65 \<forall>x.(\<forall>j\<in>{1 .. D}. \<forall>b\<in>B. x \<noteq> b + j)\<longrightarrow> Q x \<longrightarrow> Q(x - D)\<rbrakk> \<Longrightarrow> |
66 \<forall>x.(\<forall>j\<in>{1 .. D}. \<forall>b\<in>B. x \<noteq> b + j) \<longrightarrow> (P x \<and> Q x) \<longrightarrow> (P(x - D) \<and> Q (x - D))" |
66 \<forall>x.(\<forall>j\<in>{1 .. D}. \<forall>b\<in>B. x \<noteq> b + j) \<longrightarrow> (P x \<and> Q x) \<longrightarrow> (P(x - D) \<and> Q (x - D))" |
67 "\<lbrakk>\<forall>x.(\<forall>j\<in>{1 .. D}. \<forall>b\<in>B. x \<noteq> b + j)\<longrightarrow> P x \<longrightarrow> P(x - D) ; |
67 "\<lbrakk>\<forall>x.(\<forall>j\<in>{1 .. D}. \<forall>b\<in>B. x \<noteq> b + j)\<longrightarrow> P x \<longrightarrow> P(x - D) ; |
174 {fix x assume H: "\<not>(d dvd x + t)" with d have "\<not>d dvd (x + D) + t" |
174 {fix x assume H: "\<not>(d dvd x + t)" with d have "\<not>d dvd (x + D) + t" |
175 by (clarsimp simp add: dvd_def,erule_tac x= "ka - k" in allE,simp add: algebra_simps)} |
175 by (clarsimp simp add: dvd_def,erule_tac x= "ka - k" in allE,simp add: algebra_simps)} |
176 thus "\<forall>(x::int).(\<forall>j\<in>{1 .. D}. \<forall>b\<in>A. x \<noteq> b - j)\<longrightarrow> (\<not>d dvd x+t) \<longrightarrow> (\<not>d dvd (x + D) + t)" by auto |
176 thus "\<forall>(x::int).(\<forall>j\<in>{1 .. D}. \<forall>b\<in>A. x \<noteq> b - j)\<longrightarrow> (\<not>d dvd x+t) \<longrightarrow> (\<not>d dvd (x + D) + t)" by auto |
177 qed blast |
177 qed blast |
178 |
178 |
179 subsection{* Cooper's Theorem @{text "-\<infinity>"} and @{text "+\<infinity>"} Version *} |
179 subsection\<open>Cooper's Theorem @{text "-\<infinity>"} and @{text "+\<infinity>"} Version\<close> |
180 |
180 |
181 subsubsection{* First some trivial facts about periodic sets or predicates *} |
181 subsubsection\<open>First some trivial facts about periodic sets or predicates\<close> |
182 lemma periodic_finite_ex: |
182 lemma periodic_finite_ex: |
183 assumes dpos: "(0::int) < d" and modd: "ALL x k. P x = P(x - k*d)" |
183 assumes dpos: "(0::int) < d" and modd: "ALL x k. P x = P(x - k*d)" |
184 shows "(EX x. P x) = (EX j : {1..d}. P j)" |
184 shows "(EX x. P x) = (EX j : {1..d}. P j)" |
185 (is "?LHS = ?RHS") |
185 (is "?LHS = ?RHS") |
186 proof |
186 proof |
207 qed |
207 qed |
208 ultimately show ?RHS .. |
208 ultimately show ?RHS .. |
209 qed |
209 qed |
210 qed auto |
210 qed auto |
211 |
211 |
212 subsubsection{* The @{text "-\<infinity>"} Version*} |
212 subsubsection\<open>The @{text "-\<infinity>"} Version\<close> |
213 |
213 |
214 lemma decr_lemma: "0 < (d::int) \<Longrightarrow> x - (abs(x-z)+1) * d < z" |
214 lemma decr_lemma: "0 < (d::int) \<Longrightarrow> x - (abs(x-z)+1) * d < z" |
215 by(induct rule: int_gr_induct,simp_all add:int_distrib) |
215 by(induct rule: int_gr_induct,simp_all add:int_distrib) |
216 |
216 |
217 lemma incr_lemma: "0 < (d::int) \<Longrightarrow> z < x + (abs(x-z)+1) * d" |
217 lemma incr_lemma: "0 < (d::int) \<Longrightarrow> z < x + (abs(x-z)+1) * d" |
275 with periodic_finite_ex[OF dp pd] |
275 with periodic_finite_ex[OF dp pd] |
276 have "?R1" by blast} |
276 have "?R1" by blast} |
277 ultimately show ?thesis by blast |
277 ultimately show ?thesis by blast |
278 qed |
278 qed |
279 |
279 |
280 subsubsection {* The @{text "+\<infinity>"} Version*} |
280 subsubsection \<open>The @{text "+\<infinity>"} Version\<close> |
281 |
281 |
282 lemma plusinfinity: |
282 lemma plusinfinity: |
283 assumes dpos: "(0::int) < d" and |
283 assumes dpos: "(0::int) < d" and |
284 P1eqP1: "\<forall>x k. P' x = P'(x - k*d)" and ePeqP1: "\<exists> z. \<forall> x>z. P x = P' x" |
284 P1eqP1: "\<forall>x k. P' x = P'(x - k*d)" and ePeqP1: "\<exists> z. \<forall> x>z. P x = P' x" |
285 shows "(\<exists> x. P' x) \<longrightarrow> (\<exists> x. P x)" |
285 shows "(\<exists> x. P' x) \<longrightarrow> (\<exists> x. P x)" |
370 lemma uminus_dvd_conv: |
370 lemma uminus_dvd_conv: |
371 fixes d t :: int |
371 fixes d t :: int |
372 shows "d dvd t \<equiv> - d dvd t" and "d dvd t \<equiv> d dvd - t" |
372 shows "d dvd t \<equiv> - d dvd t" and "d dvd t \<equiv> d dvd - t" |
373 by simp_all |
373 by simp_all |
374 |
374 |
375 text {* \bigskip Theorems for transforming predicates on nat to predicates on @{text int}*} |
375 text \<open>\bigskip Theorems for transforming predicates on nat to predicates on @{text int}\<close> |
376 |
376 |
377 lemma zdiff_int_split: "P (int (x - y)) = |
377 lemma zdiff_int_split: "P (int (x - y)) = |
378 ((y \<le> x \<longrightarrow> P (int x - int y)) \<and> (x < y \<longrightarrow> P 0))" |
378 ((y \<le> x \<longrightarrow> P (int x - int y)) \<and> (x < y \<longrightarrow> P 0))" |
379 by (cases "y \<le> x") (simp_all add: zdiff_int) |
379 by (cases "y \<le> x") (simp_all add: zdiff_int) |
380 |
380 |
381 text {* |
381 text \<open> |
382 \medskip Specific instances of congruence rules, to prevent |
382 \medskip Specific instances of congruence rules, to prevent |
383 simplifier from looping. *} |
383 simplifier from looping.\<close> |
384 |
384 |
385 theorem imp_le_cong: |
385 theorem imp_le_cong: |
386 "\<lbrakk>x = x'; 0 \<le> x' \<Longrightarrow> P = P'\<rbrakk> \<Longrightarrow> (0 \<le> (x::int) \<longrightarrow> P) = (0 \<le> x' \<longrightarrow> P')" |
386 "\<lbrakk>x = x'; 0 \<le> x' \<Longrightarrow> P = P'\<rbrakk> \<Longrightarrow> (0 \<le> (x::int) \<longrightarrow> P) = (0 \<le> x' \<longrightarrow> P')" |
387 by simp |
387 by simp |
388 |
388 |
390 "\<lbrakk>x = x'; 0 \<le> x' \<Longrightarrow> P = P'\<rbrakk> \<Longrightarrow> (0 \<le> (x::int) \<and> P) = (0 \<le> x' \<and> P')" |
390 "\<lbrakk>x = x'; 0 \<le> x' \<Longrightarrow> P = P'\<rbrakk> \<Longrightarrow> (0 \<le> (x::int) \<and> P) = (0 \<le> x' \<and> P')" |
391 by (simp cong: conj_cong) |
391 by (simp cong: conj_cong) |
392 |
392 |
393 ML_file "Tools/Qelim/cooper.ML" |
393 ML_file "Tools/Qelim/cooper.ML" |
394 |
394 |
395 method_setup presburger = {* |
395 method_setup presburger = \<open> |
396 let |
396 let |
397 fun keyword k = Scan.lift (Args.$$$ k -- Args.colon) >> K () |
397 fun keyword k = Scan.lift (Args.$$$ k -- Args.colon) >> K () |
398 fun simple_keyword k = Scan.lift (Args.$$$ k) >> K () |
398 fun simple_keyword k = Scan.lift (Args.$$$ k) >> K () |
399 val addN = "add" |
399 val addN = "add" |
400 val delN = "del" |
400 val delN = "del" |
406 Scan.optional (keyword addN |-- thms) [] -- |
406 Scan.optional (keyword addN |-- thms) [] -- |
407 Scan.optional (keyword delN |-- thms) [] >> |
407 Scan.optional (keyword delN |-- thms) [] >> |
408 (fn ((elim, add_ths), del_ths) => fn ctxt => |
408 (fn ((elim, add_ths), del_ths) => fn ctxt => |
409 SIMPLE_METHOD' (Cooper.tac elim add_ths del_ths ctxt)) |
409 SIMPLE_METHOD' (Cooper.tac elim add_ths del_ths ctxt)) |
410 end |
410 end |
411 *} "Cooper's algorithm for Presburger arithmetic" |
411 \<close> "Cooper's algorithm for Presburger arithmetic" |
412 |
412 |
413 declare dvd_eq_mod_eq_0 [symmetric, presburger] |
413 declare dvd_eq_mod_eq_0 [symmetric, presburger] |
414 declare mod_1 [presburger] |
414 declare mod_1 [presburger] |
415 declare mod_0 [presburger] |
415 declare mod_0 [presburger] |
416 declare mod_by_1 [presburger] |
416 declare mod_by_1 [presburger] |
488 lemma [presburger]: |
488 lemma [presburger]: |
489 "even n \<longleftrightarrow> even (int n)" |
489 "even n \<longleftrightarrow> even (int n)" |
490 using even_int_iff [of n] by simp |
490 using even_int_iff [of n] by simp |
491 |
491 |
492 |
492 |
493 subsection {* Nice facts about division by @{term 4} *} |
493 subsection \<open>Nice facts about division by @{term 4}\<close> |
494 |
494 |
495 lemma even_even_mod_4_iff: |
495 lemma even_even_mod_4_iff: |
496 "even (n::nat) \<longleftrightarrow> even (n mod 4)" |
496 "even (n::nat) \<longleftrightarrow> even (n mod 4)" |
497 by presburger |
497 by presburger |
498 |
498 |
503 lemma even_mod_4_div_2: |
503 lemma even_mod_4_div_2: |
504 "n mod 4 = (1::nat) \<Longrightarrow> even ((n - 1) div 2)" |
504 "n mod 4 = (1::nat) \<Longrightarrow> even ((n - 1) div 2)" |
505 by presburger |
505 by presburger |
506 |
506 |
507 |
507 |
508 subsection {* Try0 *} |
508 subsection \<open>Try0\<close> |
509 |
509 |
510 ML_file "Tools/try0.ML" |
510 ML_file "Tools/try0.ML" |
511 |
511 |
512 end |
512 end |