# HG changeset patch # User paulson # Date 1712956760 -3600 # Node ID c06c95576ea954652282baa3e4876d3e8be4c6cc # Parent 83fa23ca40e55c7a8f5e4d539b55ac103d1391dd Tidied some messy proofs diff -r 83fa23ca40e5 -r c06c95576ea9 src/HOL/Decision_Procs/Parametric_Ferrante_Rackoff.thy --- a/src/HOL/Decision_Procs/Parametric_Ferrante_Rackoff.thy Fri Apr 12 09:58:53 2024 +0100 +++ b/src/HOL/Decision_Procs/Parametric_Ferrante_Rackoff.thy Fri Apr 12 22:19:20 2024 +0100 @@ -208,7 +208,7 @@ and nb: "tmbound m t" and nle: "m \ length bs" shows "Itm vs (removen m bs) (decrtm m t) = Itm vs bs t" - using bnd nb nle by (induct t rule: tm.induct) (auto simp add: removen_nth) + using bnd nb nle by (induct t rule: tm.induct) (auto simp: removen_nth) primrec tmsubst0:: "tm \ tm \ tm" where @@ -276,25 +276,33 @@ | "tmadd a b = Add a b" lemma tmadd [simp]: "Itm vs bs (tmadd t s) = Itm vs bs (Add t s)" - apply (induct t s rule: tmadd.induct) - apply (simp_all add: Let_def) - apply (case_tac "c1 +\<^sub>p c2 = 0\<^sub>p") - apply (case_tac "n1 \ n2") - apply simp_all - apply (case_tac "n1 = n2") - apply (simp_all add: algebra_simps) - apply (simp only: distrib_left [symmetric] polyadd [symmetric]) - apply simp - done +proof (induct t s rule: tmadd.induct) + case (1 n1 c1 r1 n2 c2 r2) + show ?case + proof (cases "c1 +\<^sub>p c2 = 0\<^sub>p") + case 0: True + show ?thesis + proof (cases "n1 \ n2") + case True + with 0 show ?thesis + apply (simp add: 1) + by (metis INum_int(2) Ipoly.simps(1) comm_semiring_class.distrib mult_eq_0_iff polyadd) + qed (use 0 1 in auto) + next + case False + then show ?thesis + using 1 comm_semiring_class.distrib by auto + qed +qed auto lemma tmadd_nb0[simp]: "tmbound0 t \ tmbound0 s \ tmbound0 (tmadd t s)" - by (induct t s rule: tmadd.induct) (auto simp add: Let_def) + by (induct t s rule: tmadd.induct) (auto simp: Let_def) lemma tmadd_nb[simp]: "tmbound n t \ tmbound n s \ tmbound n (tmadd t s)" - by (induct t s rule: tmadd.induct) (auto simp add: Let_def) + by (induct t s rule: tmadd.induct) (auto simp: Let_def) lemma tmadd_blt[simp]: "tmboundslt n t \ tmboundslt n s \ tmboundslt n (tmadd t s)" - by (induct t s rule: tmadd.induct) (auto simp add: Let_def) + by (induct t s rule: tmadd.induct) (auto simp: Let_def) lemma tmadd_allpolys_npoly[simp]: "allpolys isnpoly t \ allpolys isnpoly s \ allpolys isnpoly (tmadd t s)" @@ -316,7 +324,7 @@ by (induct t arbitrary: n rule: tmmul.induct) auto lemma tmmul_blt[simp]: "tmboundslt n t \ tmboundslt n (tmmul t i)" - by (induct t arbitrary: i rule: tmmul.induct) (auto simp add: Let_def) + by (induct t arbitrary: i rule: tmmul.induct) (auto simp: Let_def) lemma tmmul_allpolys_npoly[simp]: assumes "SORT_CONSTRAINT('a::field_char_0)" @@ -381,21 +389,19 @@ lemma polynate_stupid: assumes "SORT_CONSTRAINT('a::field_char_0)" shows "polynate t = 0\<^sub>p \ Ipoly bs t = (0::'a)" - apply (subst polynate[symmetric]) - apply simp - done + by (metis INum_int(2) Ipoly.simps(1) polynate) lemma simptm_ci[simp]: "Itm vs bs (simptm t) = Itm vs bs t" - by (induct t rule: simptm.induct) (auto simp add: Let_def polynate_stupid) + by (induct t rule: simptm.induct) (auto simp: Let_def polynate_stupid) lemma simptm_tmbound0[simp]: "tmbound0 t \ tmbound0 (simptm t)" - by (induct t rule: simptm.induct) (auto simp add: Let_def) + by (induct t rule: simptm.induct) (auto simp: Let_def) lemma simptm_nb[simp]: "tmbound n t \ tmbound n (simptm t)" - by (induct t rule: simptm.induct) (auto simp add: Let_def) + by (induct t rule: simptm.induct) (auto simp: Let_def) lemma simptm_nlt[simp]: "tmboundslt n t \ tmboundslt n (simptm t)" - by (induct t rule: simptm.induct) (auto simp add: Let_def) + by (induct t rule: simptm.induct) (auto simp: Let_def) lemma [simp]: "isnpoly 0\<^sub>p" and [simp]: "isnpoly (C (1, 1))" @@ -404,7 +410,7 @@ lemma simptm_allpolys_npoly[simp]: assumes "SORT_CONSTRAINT('a::field_char_0)" shows "allpolys isnpoly (simptm p)" - by (induct p rule: simptm.induct) (auto simp add: Let_def) + by (induct p rule: simptm.induct) (auto simp: Let_def) declare let_cong[fundef_cong del] @@ -422,24 +428,15 @@ declare let_cong[fundef_cong] lemma split0_stupid[simp]: "\x y. (x, y) = split0 p" - apply (rule exI[where x="fst (split0 p)"]) - apply (rule exI[where x="snd (split0 p)"]) - apply simp - done + using prod.collapse by blast lemma split0: "tmbound 0 (snd (split0 t)) \ Itm vs bs (CNP 0 (fst (split0 t)) (snd (split0 t))) = Itm vs bs t" - apply (induct t rule: split0.induct) - apply simp - apply (simp add: Let_def split_def field_simps) - apply (simp add: Let_def split_def field_simps) - apply (simp add: Let_def split_def field_simps) - apply (simp add: Let_def split_def field_simps) - apply (simp add: Let_def split_def field_simps) - apply (simp add: Let_def split_def mult.assoc distrib_left[symmetric]) - apply (simp add: Let_def split_def field_simps) - apply (simp add: Let_def split_def field_simps) - done +proof (induct t rule: split0.induct) + case (7 c t) + then show ?case + by (simp add: Let_def split_def mult.assoc flip: distrib_left) +qed (auto simp: Let_def split_def field_simps) lemma split0_ci: "split0 t = (c',t') \ Itm vs bs t = Itm vs bs (CNP 0 c' t')" proof - @@ -472,21 +469,21 @@ lemma split0_nb: assumes nb: "tmbound n t" shows "tmbound n (snd (split0 t))" - using nb by (induct t rule: split0.induct) (auto simp add: Let_def split_def) + using nb by (induct t rule: split0.induct) (auto simp: Let_def split_def) lemma split0_blt: assumes nb: "tmboundslt n t" shows "tmboundslt n (snd (split0 t))" - using nb by (induct t rule: split0.induct) (auto simp add: Let_def split_def) + using nb by (induct t rule: split0.induct) (auto simp: Let_def split_def) lemma tmbound_split0: "tmbound 0 t \ Ipoly vs (fst (split0 t)) = 0" - by (induct t rule: split0.induct) (auto simp add: Let_def split_def) + by (induct t rule: split0.induct) (auto simp: Let_def split_def) lemma tmboundslt_split0: "tmboundslt n t \ Ipoly vs (fst (split0 t)) = 0 \ n > 0" - by (induct t rule: split0.induct) (auto simp add: Let_def split_def) + by (induct t rule: split0.induct) (auto simp: Let_def split_def) lemma tmboundslt0_split0: "tmboundslt 0 t \ Ipoly vs (fst (split0 t)) = 0" - by (induct t rule: split0.induct) (auto simp add: Let_def split_def) + by (induct t rule: split0.induct) (auto simp: Let_def split_def) lemma allpolys_split0: "allpolys isnpoly p \ allpolys isnpoly (snd (split0 p))" by (induct p rule: split0.induct) (auto simp add: isnpoly_def Let_def split_def) @@ -764,7 +761,7 @@ from A(1)[OF bnd nb nle] show ?thesis . qed then show ?case by auto -qed (auto simp add: decrtm removen_nth) +qed (auto simp: decrtm removen_nth) primrec subst0 :: "tm \ fm \ fm" where @@ -849,7 +846,7 @@ by (simp add: incrtm0[where x="x" and bs="bs" and t="t"]) qed then show ?case by simp -qed (auto simp add: tmsubst) +qed (auto simp: tmsubst) lemma subst_nb: assumes "tmbound m t" @@ -926,36 +923,38 @@ where "evaldjf f ps \ foldr (djf f) ps F" lemma djf_Or: "Ifm vs bs (djf f p q) = Ifm vs bs (Or (f p) q)" - apply (cases "q = T") - apply (simp add: djf_def) - apply (cases "q = F") - apply (simp add: djf_def) - apply (cases "f p") - apply (simp_all add: Let_def djf_def) - done + by (cases "f p") (simp_all add: Let_def djf_def) lemma evaldjf_ex: "Ifm vs bs (evaldjf f ps) \ (\p \ set ps. Ifm vs bs (f p))" by (induct ps) (simp_all add: evaldjf_def djf_Or) lemma evaldjf_bound0: - assumes "\x\ set xs. bound0 (f x)" + assumes "\x \ set xs. bound0 (f x)" shows "bound0 (evaldjf f xs)" using assms - apply (induct xs) - apply (auto simp add: evaldjf_def djf_def Let_def) - apply (case_tac "f a") - apply auto - done +proof (induct xs) + case Nil + then show ?case + by (simp add: evaldjf_def) +next + case (Cons a xs) + then show ?case + by (cases "f a") (simp_all add: evaldjf_def djf_def Let_def) +qed lemma evaldjf_qf: assumes "\x\ set xs. qfree (f x)" shows "qfree (evaldjf f xs)" using assms - apply (induct xs) - apply (auto simp add: evaldjf_def djf_def Let_def) - apply (case_tac "f a") - apply auto - done +proof (induct xs) + case Nil + then show ?case + by (simp add: evaldjf_def) +next + case (Cons a xs) + then show ?case + by (cases "f a") (simp_all add: evaldjf_def djf_def Let_def) +qed fun disjuncts :: "fm \ fm list" where @@ -1100,71 +1099,32 @@ definition "neq p = not (eq p)" lemma lt: "allpolys isnpoly p \ Ifm vs bs (lt p) = Ifm vs bs (Lt p)" - apply (simp add: lt_def) - apply (cases p) - apply simp_all - apply (rename_tac poly, case_tac poly) - apply (simp_all add: isnpoly_def) - done + by (auto simp: lt_def isnpoly_def split: tm.split poly.split) lemma le: "allpolys isnpoly p \ Ifm vs bs (le p) = Ifm vs bs (Le p)" - apply (simp add: le_def) - apply (cases p) - apply simp_all - apply (rename_tac poly, case_tac poly) - apply (simp_all add: isnpoly_def) - done + by (auto simp: le_def isnpoly_def split: tm.split poly.split) lemma eq: "allpolys isnpoly p \ Ifm vs bs (eq p) = Ifm vs bs (Eq p)" - apply (simp add: eq_def) - apply (cases p) - apply simp_all - apply (rename_tac poly, case_tac poly) - apply (simp_all add: isnpoly_def) - done + by (auto simp: eq_def isnpoly_def split: tm.split poly.split) lemma neq: "allpolys isnpoly p \ Ifm vs bs (neq p) = Ifm vs bs (NEq p)" by (simp add: neq_def eq) lemma lt_lin: "tmbound0 p \ islin (lt p)" - apply (simp add: lt_def) - apply (cases p) - apply simp_all - apply (rename_tac poly, case_tac poly) - apply simp_all - apply (rename_tac nat a b, case_tac nat) - apply simp_all - done + using islin_stupid + by(auto simp: lt_def isnpoly_def split: tm.split poly.split) lemma le_lin: "tmbound0 p \ islin (le p)" - apply (simp add: le_def) - apply (cases p) - apply simp_all - apply (rename_tac poly, case_tac poly) - apply simp_all - apply (rename_tac nat a b, case_tac nat) - apply simp_all - done + using islin_stupid + by(auto simp: le_def isnpoly_def split: tm.split poly.split) lemma eq_lin: "tmbound0 p \ islin (eq p)" - apply (simp add: eq_def) - apply (cases p) - apply simp_all - apply (rename_tac poly, case_tac poly) - apply simp_all - apply (rename_tac nat a b, case_tac nat) - apply simp_all - done + using islin_stupid + by(auto simp: eq_def isnpoly_def split: tm.split poly.split) lemma neq_lin: "tmbound0 p \ islin (neq p)" - apply (simp add: neq_def eq_def) - apply (cases p) - apply simp_all - apply (rename_tac poly, case_tac poly) - apply simp_all - apply (rename_tac nat a b, case_tac nat) - apply simp_all - done + using islin_stupid + by(auto simp: neq_def eq_def isnpoly_def split: tm.split poly.split) definition "simplt t = (let (c,s) = split0 (simptm t) in if c= 0\<^sub>p then lt s else Lt (CNP 0 c s))" definition "simple t = (let (c,s) = split0 (simptm t) in if c= 0\<^sub>p then le s else Le (CNP 0 c s))" @@ -1176,7 +1136,7 @@ shows "islin (simplt t)" unfolding simplt_def using split0_nb0' - by (auto simp add: lt_lin Let_def split_def isnpoly_fst_split0[OF simptm_allpolys_npoly] + by (auto simp: lt_lin Let_def split_def isnpoly_fst_split0[OF simptm_allpolys_npoly] islin_stupid allpolys_split0[OF simptm_allpolys_npoly]) lemma simple_islin [simp]: @@ -1184,7 +1144,7 @@ shows "islin (simple t)" unfolding simple_def using split0_nb0' - by (auto simp add: Let_def split_def isnpoly_fst_split0[OF simptm_allpolys_npoly] + by (auto simp: Let_def split_def isnpoly_fst_split0[OF simptm_allpolys_npoly] islin_stupid allpolys_split0[OF simptm_allpolys_npoly] le_lin) lemma simpeq_islin [simp]: @@ -1192,7 +1152,7 @@ shows "islin (simpeq t)" unfolding simpeq_def using split0_nb0' - by (auto simp add: Let_def split_def isnpoly_fst_split0[OF simptm_allpolys_npoly] + by (auto simp: Let_def split_def isnpoly_fst_split0[OF simptm_allpolys_npoly] islin_stupid allpolys_split0[OF simptm_allpolys_npoly] eq_lin) lemma simpneq_islin [simp]: @@ -1200,7 +1160,7 @@ shows "islin (simpneq t)" unfolding simpneq_def using split0_nb0' - by (auto simp add: Let_def split_def isnpoly_fst_split0[OF simptm_allpolys_npoly] + by (auto simp: Let_def split_def isnpoly_fst_split0[OF simptm_allpolys_npoly] islin_stupid allpolys_split0[OF simptm_allpolys_npoly] neq_lin) lemma really_stupid: "\ (\c1 s'. (c1, s') \ split0 s)" @@ -1213,7 +1173,7 @@ and "allpolys isnpoly (snd (split0 t))" using * by (induct t rule: split0.induct) - (auto simp add: Let_def split_def polyadd_norm polymul_norm polyneg_norm + (auto simp: Let_def split_def polyadd_norm polymul_norm polyneg_norm polysub_norm really_stupid) lemma simplt[simp]: "Ifm vs bs (simplt t) = Ifm vs bs (Lt t)" @@ -1291,44 +1251,24 @@ qed lemma lt_nb: "tmbound0 t \ bound0 (lt t)" - apply (simp add: lt_def) - apply (cases t) - apply auto - apply (rename_tac poly, case_tac poly) - apply auto - done + by(auto simp: lt_def split: tm.split poly.split) lemma le_nb: "tmbound0 t \ bound0 (le t)" - apply (simp add: le_def) - apply (cases t) - apply auto - apply (rename_tac poly, case_tac poly) - apply auto - done + by(auto simp: le_def split: tm.split poly.split) lemma eq_nb: "tmbound0 t \ bound0 (eq t)" - apply (simp add: eq_def) - apply (cases t) - apply auto - apply (rename_tac poly, case_tac poly) - apply auto - done + by(auto simp: eq_def split: tm.split poly.split) lemma neq_nb: "tmbound0 t \ bound0 (neq t)" - apply (simp add: neq_def eq_def) - apply (cases t) - apply auto - apply (rename_tac poly, case_tac poly) - apply auto - done - + by(auto simp: neq_def eq_def split: tm.split poly.split) + +(*THE FOLLOWING PROOFS MIGHT BE COMBINED*) lemma simplt_nb[simp]: - assumes "SORT_CONSTRAINT('a::field_char_0)" - shows "tmbound0 t \ bound0 (simplt t)" + assumes "SORT_CONSTRAINT('a::field_char_0)" and t: "tmbound0 t" + shows "bound0 (simplt t)" proof (simp add: simplt_def Let_def split_def) - assume "tmbound0 t" - then have *: "tmbound0 (simptm t)" - by simp + have *: "tmbound0 (simptm t)" + using t by simp let ?c = "fst (split0 (simptm t))" from tmbound_split0[OF *[unfolded tmbound0_tmbound_iff[symmetric]]] have th: "\bs. Ipoly bs ?c = Ipoly bs 0\<^sub>p" @@ -1344,12 +1284,11 @@ qed lemma simple_nb[simp]: - assumes "SORT_CONSTRAINT('a::field_char_0)" - shows "tmbound0 t \ bound0 (simple t)" + assumes "SORT_CONSTRAINT('a::field_char_0)" and t: "tmbound0 t" + shows "bound0 (simple t)" proof(simp add: simple_def Let_def split_def) - assume "tmbound0 t" - then have *: "tmbound0 (simptm t)" - by simp + have *: "tmbound0 (simptm t)" + using t by simp let ?c = "fst (split0 (simptm t))" from tmbound_split0[OF *[unfolded tmbound0_tmbound_iff[symmetric]]] have th: "\bs. Ipoly bs ?c = Ipoly bs 0\<^sub>p" @@ -1365,12 +1304,11 @@ qed lemma simpeq_nb[simp]: - assumes "SORT_CONSTRAINT('a::field_char_0)" - shows "tmbound0 t \ bound0 (simpeq t)" + assumes "SORT_CONSTRAINT('a::field_char_0)" and t: "tmbound0 t" + shows "bound0 (simpeq t)" proof (simp add: simpeq_def Let_def split_def) - assume "tmbound0 t" - then have *: "tmbound0 (simptm t)" - by simp + have *: "tmbound0 (simptm t)" + using t by simp let ?c = "fst (split0 (simptm t))" from tmbound_split0[OF *[unfolded tmbound0_tmbound_iff[symmetric]]] have th: "\bs. Ipoly bs ?c = Ipoly bs 0\<^sub>p" @@ -1386,12 +1324,11 @@ qed lemma simpneq_nb[simp]: - assumes "SORT_CONSTRAINT('a::field_char_0)" - shows "tmbound0 t \ bound0 (simpneq t)" + assumes "SORT_CONSTRAINT('a::field_char_0)" and t: "tmbound0 t" + shows "bound0 (simpneq t)" proof (simp add: simpneq_def Let_def split_def) - assume "tmbound0 t" - then have *: "tmbound0 (simptm t)" - by simp + have *: "tmbound0 (simptm t)" + using t by simp let ?c = "fst (split0 (simptm t))" from tmbound_split0[OF *[unfolded tmbound0_tmbound_iff[symmetric]]] have th: "\bs. Ipoly bs ?c = Ipoly bs 0\<^sub>p" @@ -1419,35 +1356,30 @@ where "list_disj ps \ foldr disj ps F" lemma list_conj: "Ifm vs bs (list_conj ps) = (\p\ set ps. Ifm vs bs p)" - by (induct ps) (auto simp add: list_conj_def) + by (induct ps) (auto simp: list_conj_def) lemma list_conj_qf: " \p\ set ps. qfree p \ qfree (list_conj ps)" - by (induct ps) (auto simp add: list_conj_def) + by (induct ps) (auto simp: list_conj_def) lemma list_disj: "Ifm vs bs (list_disj ps) = (\p\ set ps. Ifm vs bs p)" - by (induct ps) (auto simp add: list_disj_def) + by (induct ps) (auto simp: list_disj_def) lemma conj_boundslt: "boundslt n p \ boundslt n q \ boundslt n (conj p q)" unfolding conj_def by auto lemma conjs_nb: "bound n p \ \q\ set (conjs p). bound n q" - apply (induct p rule: conjs.induct) - apply (unfold conjs.simps) - apply (unfold set_append) - apply (unfold ball_Un) - apply (unfold bound.simps) - apply auto - done +proof (induct p rule: conjs.induct) + case (1 p q) + then show ?case + unfolding conjs.simps bound.simps by fastforce +qed auto lemma conjs_boundslt: "boundslt n p \ \q\ set (conjs p). boundslt n q" - apply (induct p rule: conjs.induct) - apply (unfold conjs.simps) - apply (unfold set_append) - apply (unfold ball_Un) - apply (unfold boundslt.simps) - apply blast - apply simp_all - done +proof (induct p rule: conjs.induct) + case (1 p q) + then show ?case + unfolding conjs.simps bound.simps by fastforce +qed auto lemma list_conj_boundslt: " \p\ set ps. boundslt n p \ boundslt n (list_conj ps)" by (induct ps) (auto simp: list_conj_def) @@ -1503,7 +1435,7 @@ also fix y have "\ = (\x. (Ifm vs (y#bs) ?cyes) \ (Ifm vs (x#bs) ?cno))" using bound0_I[OF yes_nb, where bs="bs" and b'="y"] by blast also have "\ = (Ifm vs bs (decr0 ?cyes) \ Ifm vs bs (E ?cno))" - by (auto simp add: decr0[OF yes_nb] simp del: partition_filter_conv) + by (auto simp: decr0[OF yes_nb] simp del: partition_filter_conv) also have "\ = (Ifm vs bs (conj (decr0 ?cyes) (qe ?cno)))" using qe[rule_format, OF no_qf] by auto finally have "Ifm vs bs (E p) = Ifm vs bs (CJNB qe p)" @@ -1546,25 +1478,13 @@ by (induct p rule: simpfm.induct) auto lemma lt_qf[simp]: "qfree (lt t)" - apply (cases t) - apply (auto simp add: lt_def) - apply (rename_tac poly, case_tac poly) - apply auto - done + by(auto simp: lt_def split: tm.split poly.split) lemma le_qf[simp]: "qfree (le t)" - apply (cases t) - apply (auto simp add: le_def) - apply (rename_tac poly, case_tac poly) - apply auto - done + by(auto simp: le_def split: tm.split poly.split) lemma eq_qf[simp]: "qfree (eq t)" - apply (cases t) - apply (auto simp add: eq_def) - apply (rename_tac poly, case_tac poly) - apply auto - done + by(auto simp: eq_def split: tm.split poly.split) lemma neq_qf[simp]: "qfree (neq t)" by (simp add: neq_def) @@ -1671,19 +1591,19 @@ shows "\z. \x < z. Ifm vs (x#bs) (minusinf p) \ Ifm vs (x#bs) p" using assms proof (induct p rule: minusinf.induct) - case 1 + case (1 p q) + then obtain zp zq where zp: "\xxxxz. \x > z. Ifm vs (x#bs) (plusinf p) \ Ifm vs (x#bs) p" using assms proof (induct p rule: plusinf.induct) - case 1 + case (1 p q) + then obtain zp zq where zp: "\x>zp. Ifm vs (x # bs) (plusinf p) = Ifm vs (x # bs) p" + and zq: "\x>zq. Ifm vs (x # bs) (plusinf q) = Ifm vs (x # bs) q" + by force then show ?case - apply auto - apply (rule_tac x="max z za" in exI) - apply auto - done + by (rule_tac x="max zp zq" in exI) auto next - case 2 + case (2 p q) + then obtain zp zq where zp: "\x>zp. Ifm vs (x # bs) (plusinf p) = Ifm vs (x # bs) p" + and zq: "\x>zq. Ifm vs (x # bs) (plusinf q) = Ifm vs (x # bs) q" + by force then show ?case - apply auto - apply (rule_tac x="max z za" in exI) - apply auto - done + by (rule_tac x="max zp zq" in exI) auto next case (3 c e) then have nbe: "tmbound0 e" @@ -2072,10 +1992,10 @@ qed auto lemma minusinf_nb: "islin p \ bound0 (minusinf p)" - by (induct p rule: minusinf.induct) (auto simp add: eq_nb lt_nb le_nb) + by (induct p rule: minusinf.induct) (auto simp: eq_nb lt_nb le_nb) lemma plusinf_nb: "islin p \ bound0 (plusinf p)" - by (induct p rule: minusinf.induct) (auto simp add: eq_nb lt_nb le_nb) + by (induct p rule: minusinf.induct) (auto simp: eq_nb lt_nb le_nb) lemma minusinf_ex: assumes lp: "islin p" @@ -2140,16 +2060,14 @@ Ipoly vs c < 0 \ Ipoly vs c * x \ - Itm vs (x#bs) s \ Ipoly vs c > 0 \ Ipoly vs c * x \ - Itm vs (x#bs) s" using lp nmi ex - apply (induct p rule: minusinf.induct) - apply (auto simp add: eq le lt polyneg_norm) - apply (auto simp add: linorder_not_less order_le_less) - done + by (induct p rule: minusinf.induct) + (auto simp: eq le lt polyneg_norm linorder_not_less order_le_less) then obtain c s where csU: "(c, s) \ set (uset p)" and x: "(Ipoly vs c < 0 \ Ipoly vs c * x \ - Itm vs (x#bs) s) \ (Ipoly vs c > 0 \ Ipoly vs c * x \ - Itm vs (x#bs) s)" by blast then have "x \ (- Itm vs (x#bs) s) / Ipoly vs c" using divide_le_eq[of "- Itm vs (x#bs) s" "Ipoly vs c" x] - by (auto simp add: mult.commute) + by (auto simp: mult.commute) then show ?thesis using csU by auto qed @@ -2183,10 +2101,8 @@ Ipoly vs c < 0 \ Ipoly vs c * x \ - Itm vs (x#bs) s \ Ipoly vs c > 0 \ Ipoly vs c * x \ - Itm vs (x#bs) s" using lp nmi ex - apply (induct p rule: minusinf.induct) - apply (auto simp add: eq le lt polyneg_norm) - apply (auto simp add: linorder_not_less order_le_less) - done + by (induct p rule: minusinf.induct) + (auto simp: eq le lt polyneg_norm linorder_not_less order_le_less) then obtain c s where c_s: "(c, s) \ set (uset p)" and "Ipoly vs c < 0 \ Ipoly vs c * x \ - Itm vs (x#bs) s \ @@ -2194,7 +2110,7 @@ by blast then have "x \ (- Itm vs (x#bs) s) / Ipoly vs c" using le_divide_eq[of x "- Itm vs (x#bs) s" "Ipoly vs c"] - by (auto simp add: mult.commute) + by (auto simp: mult.commute) then show ?thesis using c_s by auto qed @@ -2248,7 +2164,7 @@ case N: 2 from px pos_less_divide_eq[OF N, where a="x" and b="-?Nt x s"] have px': "x < - ?Nt x s / ?N c" - by (auto simp add: not_less field_simps) + by (auto simp: not_less field_simps) from ycs show ?thesis proof assume y: "y < - ?Nt x s / ?N c" @@ -2272,7 +2188,7 @@ case N: 3 from px neg_divide_less_eq[OF N, where a="x" and b="-?Nt x s"] have px': "x > - ?Nt x s / ?N c" - by (auto simp add: not_less field_simps) + by (auto simp: not_less field_simps) from ycs show ?thesis proof assume y: "y > - ?Nt x s / ?N c" @@ -2449,7 +2365,7 @@ show ?thesis by (simp add: field_simps tmbound0_I[OF lin(3), of vs x bs y] sum_eq[symmetric]) qed -qed (auto simp add: tmbound0_I[where vs=vs and bs="bs" and b="y" and b'="x"] +qed (auto simp: tmbound0_I[where vs=vs and bs="bs" and b="y" and b'="x"] bound0_I[where vs=vs and bs="bs" and b="y" and b'="x"]) lemma inf_uset: @@ -3261,7 +3177,7 @@ Ifm vs (((- Itm vs (x#bs) t / Ipoly vs c + - Itm vs (x#bs) s / Ipoly vs d) /2)#bs) p" using lp by (induct p rule: islin.induct) - (auto simp add: tmbound0_I + (auto simp: tmbound0_I [where b = "(- (Itm vs (x # bs) t / \c\\<^sub>p\<^bsup>vs\<^esup>) - (Itm vs (x # bs) s / \d\\<^sub>p\<^bsup>vs\<^esup>)) / 2" and b' = x and bs = bs and vs = vs] msubsteq msubstneq msubstlt [OF nc nd] msubstle [OF nc nd]) @@ -3272,7 +3188,7 @@ and "tmbound0 s" shows "bound0 (msubst p ((c,t),(d,s)))" using assms - by (induct p rule: islin.induct) (auto simp add: msubsteq_nb msubstneq_nb msubstlt_nb msubstle_nb) + by (induct p rule: islin.induct) (auto simp: msubsteq_nb msubstneq_nb msubstlt_nb msubstle_nb) lemma fr_eq_msubst: assumes lp: "islin p" @@ -3315,7 +3231,7 @@ lemma simpfm_lin: assumes "SORT_CONSTRAINT('a::field_char_0)" shows "qfree p \ islin (simpfm p)" - by (induct p rule: simpfm.induct) (auto simp add: conj_lin disj_lin) + by (induct p rule: simpfm.induct) (auto simp: conj_lin disj_lin) definition "ferrack p \ let @@ -3395,10 +3311,7 @@ by simp also have "\ \ ?rhs" using decr0[OF th1, of vs x bs] - apply (simp add: ferrack_def Let_def) - apply (cases "?mp = T \ ?pp = T") - apply auto - done + by (cases "?mp = T \ ?pp = T") (auto simp: ferrack_def Let_def) finally show ?thesis using thqf by blast qed @@ -3468,11 +3381,8 @@ case z: 4 from z have ?F using ct - apply - - apply (rule bexI[where x = "(c,t)"]) - apply simp_all - apply (rule bexI[where x = "(d,s)"]) - apply simp_all + apply (intro bexI[where x = "(c,t)"]; simp) + apply (intro bexI[where x = "(d,s)"]; simp) done then show ?thesis by blast qed @@ -3553,7 +3463,7 @@ Ifm vs (Itm vs (x#bs) t / Ipoly vs c #bs) p" using lp pos by (induct p rule: islin.induct) - (auto simp add: msubsteq2 msubstltpos[OF pos] msubstlepos[OF pos] + (auto simp: msubsteq2 msubstltpos[OF pos] msubstlepos[OF pos] tmbound0_I[of _ vs "Itm vs (x # bs) t / \c\\<^sub>p\<^bsup>vs\<^esup>" bs x] bound0_I[of _ vs "Itm vs (x # bs) t / \c\\<^sub>p\<^bsup>vs\<^esup>" bs x] field_simps) @@ -3573,7 +3483,7 @@ shows "Ifm vs (x#bs) (msubstneg p c t) = Ifm vs (Itm vs (x#bs) t / Ipoly vs c #bs) p" using lp pos by (induct p rule: islin.induct) - (auto simp add: msubsteq2 msubstltneg[OF pos] msubstleneg[OF pos] + (auto simp: msubsteq2 msubstltneg[OF pos] msubstleneg[OF pos] tmbound0_I[of _ vs "Itm vs (x # bs) t / \c\\<^sub>p\<^bsup>vs\<^esup>" bs x] bound0_I[of _ vs "Itm vs (x # bs) t / \c\\<^sub>p\<^bsup>vs\<^esup>" bs x] field_simps) @@ -3596,12 +3506,12 @@ case c: 1 from c msubstneg_I[OF lp c, of x bs t] lt[OF anc(1), of vs "x#bs"] lt[OF anc(2), of vs "x#bs"] show ?thesis - by (auto simp add: msubst2_def) + by (auto simp: msubst2_def) next case c: 2 from c msubstpos_I[OF lp c, of x bs t] lt[OF anc(1), of vs "x#bs"] lt[OF anc(2), of vs "x#bs"] show ?thesis - by (auto simp add: msubst2_def) + by (auto simp: msubst2_def) qed qed @@ -3624,7 +3534,7 @@ shows "bound0 (msubstpos p c t)" using lp tnb by (induct p c t rule: msubstpos.induct) - (auto simp add: msubsteq2_nb msubstltpos_nb msubstlepos_nb) + (auto simp: msubsteq2_nb msubstltpos_nb msubstlepos_nb) lemma msubstneg_nb: assumes "SORT_CONSTRAINT('a::field_char_0)" @@ -3633,7 +3543,7 @@ shows "bound0 (msubstneg p c t)" using lp tnb by (induct p c t rule: msubstneg.induct) - (auto simp add: msubsteq2_nb msubstltneg_nb msubstleneg_nb) + (auto simp: msubsteq2_nb msubstltneg_nb msubstleneg_nb) lemma msubst2_nb: assumes "SORT_CONSTRAINT('a::field_char_0)" @@ -3652,7 +3562,7 @@ by simp lemma islin_qf: "islin p \ qfree p" - by (induct p rule: islin.induct) (auto simp add: bound0_qf) + by (induct p rule: islin.induct) (auto simp: bound0_qf) lemma fr_eq_msubst2: assumes lp: "islin p" @@ -3689,7 +3599,7 @@ by (simp add: polyneg_norm nn) then have nn2: "\n *\<^sub>p(C (-2,1)) \\<^sub>p\<^bsup>vs\<^esup> \ 0" "\n \\<^sub>p\<^bsup>vs\<^esup> \ 0" using H(2) nn' nn - by (auto simp add: msubst2_def lt zero_less_mult_iff mult_less_0_iff) + by (auto simp: msubst2_def lt zero_less_mult_iff mult_less_0_iff) from msubst2[OF lp nn nn2(1), of x bs t] have "\n\\<^sub>p\<^bsup>vs\<^esup> \ 0 \ Ifm vs (- Itm vs (x # bs) t / (\n\\<^sub>p\<^bsup>vs\<^esup> * 2) # bs) p" using H(2) nn2 by (simp add: mult_minus2_right) @@ -3731,7 +3641,7 @@ by (simp_all add: polyneg_norm nn) have nn': "\(C (-2, 1) *\<^sub>p c*\<^sub>p d)\\<^sub>p\<^bsup>vs\<^esup> \ 0" "\c\\<^sub>p\<^bsup>vs\<^esup> \ 0" "\d\\<^sub>p\<^bsup>vs\<^esup> \ 0" using H(3) - by (auto simp add: msubst2_def lt[OF stupid(1)] + by (auto simp: msubst2_def lt[OF stupid(1)] lt[OF stupid(2)] zero_less_mult_iff mult_less_0_iff) from msubst2[OF lp nn nn'(1), of x bs ] H(3) nn' have "\c\\<^sub>p\<^bsup>vs\<^esup> \ 0 \ \d\\<^sub>p\<^bsup>vs\<^esup> \ 0 \ @@ -3862,7 +3772,7 @@ proof assume H: ?lhs then have z: "\C (-2, 1) *\<^sub>p b *\<^sub>p d\\<^sub>p\<^bsup>vs\<^esup> \ 0" "\C (-2, 1) *\<^sub>p d *\<^sub>p b\\<^sub>p\<^bsup>vs\<^esup> \ 0" - by (auto simp add: msubst2_def lt[OF stupid(3)] lt[OF stupid(1)] + by (auto simp: msubst2_def lt[OF stupid(3)] lt[OF stupid(1)] mult_less_0_iff zero_less_mult_iff) from msubst2[OF lq norm2(1) z(1), of x bs] msubst2[OF lq norm2(2) z(2), of x bs] H show ?rhs @@ -3870,7 +3780,7 @@ next assume H: ?rhs then have z: "\C (-2, 1) *\<^sub>p b *\<^sub>p d\\<^sub>p\<^bsup>vs\<^esup> \ 0" "\C (-2, 1) *\<^sub>p d *\<^sub>p b\\<^sub>p\<^bsup>vs\<^esup> \ 0" - by (auto simp add: msubst2_def lt[OF stupid(4)] lt[OF stupid(2)] + by (auto simp: msubst2_def lt[OF stupid(4)] lt[OF stupid(2)] mult_less_0_iff zero_less_mult_iff) from msubst2[OF lq norm2(1) z(1), of x bs] msubst2[OF lq norm2(2) z(2), of x bs] H show ?lhs @@ -3898,13 +3808,16 @@ also have "\ \ ?I ?R" by (simp add: list_disj_def evaldjf_ex split_def) also have "\ \ ?rhs" - unfolding ferrack2_def - apply (cases "?mp = T") - apply (simp add: list_disj_def) - apply (cases "?pp = T") - apply (simp add: list_disj_def) - apply (simp_all add: Let_def decr0[OF nb]) - done + proof (cases "?mp = T \ ?pp = T") + case True + then show ?thesis + unfolding ferrack2_def + by (force simp add: ferrack2_def list_disj_def) + next + case False + then show ?thesis + by (simp add: ferrack2_def Let_def decr0[OF nb]) + qed finally show ?thesis using decr0_qf[OF nb] by (simp add: ferrack2_def Let_def) qed @@ -3915,7 +3828,7 @@ have this: "\bs p. qfree p \ qfree (ferrack2 p) \ Ifm vs bs (ferrack2 p) = Ifm vs bs (E p)" by blast from qelim[OF this, of "prep p" bs] show ?thesis - unfolding frpar2_def by (auto simp add: prep) + unfolding frpar2_def by (auto simp: prep) qed oracle frpar_oracle = @@ -4092,57 +4005,9 @@ \ "parametric QE for linear Arithmetic over fields, Version 2" lemma "\(x::'a::linordered_field). y \ -1 \ (y + 1) * x < 0" - apply (frpar type: 'a pars: y) - apply (simp add: field_simps) - apply (rule spec[where x=y]) - apply (frpar type: 'a pars: "z::'a") - apply simp - done + by (metis mult.commute neg_less_0_iff_less nonzero_divide_eq_eq sum_eq zero_less_two) lemma "\(x::'a::linordered_field). y \ -1 \ (y + 1)*x < 0" - apply (frpar2 type: 'a pars: y) - apply (simp add: field_simps) - apply (rule spec[where x=y]) - apply (frpar2 type: 'a pars: "z::'a") - apply simp - done - -text \Collins/Jones Problem\ -(* -lemma "\(r::'a::{linordered_field, number_ring}). 0 < r \ r < 1 \ 0 < (2 - 3*r) *(a^2 + b^2) + (2*a)*r \ (2 - 3*r) *(a^2 + b^2) + 4*a*r - 2*a - r < 0" -proof - - have "(\(r::'a::{linordered_field, number_ring}). 0 < r \ r < 1 \ 0 < (2 - 3*r) *(a^2 + b^2) + (2*a)*r \ (2 - 3*r) *(a^2 + b^2) + 4*a*r - 2*a - r < 0) \ (\(r::'a::{linordered_field, number_ring}). 0 < r \ r < 1 \ 0 < 2 *(a^2 + b^2) - (3*(a^2 + b^2)) * r + (2*a)*r \ 2*(a^2 + b^2) - (3*(a^2 + b^2) - 4*a + 1)*r - 2*a < 0)" (is "?lhs \ ?rhs") -by (simp add: field_simps) -have "?rhs" - - apply (frpar type: "'a::{linordered_field, number_ring}" pars: "a::'a::{linordered_field, number_ring}" "b::'a::{linordered_field, number_ring}") - apply (simp add: field_simps) -oops -*) -(* -lemma "ALL (x::'a::{linordered_field, number_ring}) y. (1 - t)*x \ (1+t)*y \ (1 - t)*y \ (1+t)*x --> 0 \ y" -apply (frpar type: "'a::{linordered_field, number_ring}" pars: "t::'a::{linordered_field, number_ring}") -oops -*) - -text \Collins/Jones Problem\ - -(* -lemma "\(r::'a::{linordered_field, number_ring}). 0 < r \ r < 1 \ 0 < (2 - 3*r) *(a^2 + b^2) + (2*a)*r \ (2 - 3*r) *(a^2 + b^2) + 4*a*r - 2*a - r < 0" -proof - - have "(\(r::'a::{linordered_field, number_ring}). 0 < r \ r < 1 \ 0 < (2 - 3*r) *(a^2 + b^2) + (2*a)*r \ (2 - 3*r) *(a^2 + b^2) + 4*a*r - 2*a - r < 0) \ (\(r::'a::{linordered_field, number_ring}). 0 < r \ r < 1 \ 0 < 2 *(a^2 + b^2) - (3*(a^2 + b^2)) * r + (2*a)*r \ 2*(a^2 + b^2) - (3*(a^2 + b^2) - 4*a + 1)*r - 2*a < 0)" (is "?lhs \ ?rhs") -by (simp add: field_simps) -have "?rhs" - apply (frpar2 type: "'a::{linordered_field, number_ring}" pars: "a::'a::{linordered_field, number_ring}" "b::'a::{linordered_field, number_ring}") - apply simp -oops -*) - -(* -lemma "ALL (x::'a::{linordered_field, number_ring}) y. (1 - t)*x \ (1+t)*y \ (1 - t)*y \ (1+t)*x --> 0 \ y" -apply (frpar2 type: "'a::{linordered_field, number_ring}" pars: "t::'a::{linordered_field, number_ring}") -apply (simp add: field_simps linorder_neq_iff[symmetric]) -apply ferrack -oops -*) + by (metis mult.right_neutral mult_minus1_right neg_0_le_iff_le nle_le not_less sum_eq) + end diff -r 83fa23ca40e5 -r c06c95576ea9 src/HOL/Decision_Procs/Polynomial_List.thy --- a/src/HOL/Decision_Procs/Polynomial_List.thy Fri Apr 12 09:58:53 2024 +0100 +++ b/src/HOL/Decision_Procs/Polynomial_List.thy Fri Apr 12 22:19:20 2024 +0100 @@ -5,7 +5,8 @@ section \Univariate Polynomials as lists\ theory Polynomial_List -imports Complex_Main + imports Complex_Main + begin text \Application of polynomial as a function.\ @@ -264,13 +265,9 @@ by blast have "r = 0" using p0 by (simp only: Cons qr poly_mult poly_add) simp - with Cons qr show ?thesis - apply - - apply (rule exI[where x = q]) - apply auto - apply (cases q) - apply auto - done + with Cons qr have "p = [- a, 1] *** q" + by (simp add: local.padd_commut) + then show ?thesis .. qed ultimately show ?thesis using Cons by blast qed @@ -344,11 +341,8 @@ by blast from y have "y = a \ poly q y = 0" by (simp only: q poly_mult_eq_zero_disj poly_add) (simp add: algebra_simps) - with i[of y] y(1) y(2) show ?thesis - apply auto - apply (erule_tac x = "m" in allE) - apply auto - done + with i[of y] y show ?thesis + using le_Suc_eq by auto qed then show ?case by blast qed @@ -360,12 +354,7 @@ lemma (in idom) poly_roots_finite_lemma1: "poly p x \ poly [] x \ \N i. \x. poly p x = 0 \ (\n::nat. n < N \ x = i n)" - apply (drule poly_roots_index_length) - apply safe - apply (rule_tac x = "Suc (length p)" in exI) - apply (rule_tac x = i in exI) - apply (simp add: less_Suc_eq_le) - done + by (metis le_imp_less_Suc poly_roots_index_length) lemma (in idom) idom_finite_lemma: assumes "\x. P x \ (\n. n < length j \ x = j!n)" @@ -379,15 +368,8 @@ lemma (in idom) poly_roots_finite_lemma2: "poly p x \ poly [] x \ \i. \x. poly p x = 0 \ x \ set i" - apply (drule poly_roots_index_length) - apply safe - apply (rule_tac x = "map (\n. i n) [0 ..< Suc (length p)]" in exI) - apply (auto simp add: image_iff) - apply (erule_tac x="x" in allE) - apply clarsimp - apply (case_tac "n = length p") - apply (auto simp add: order_le_less) - done + using poly_roots_index_length atMost_iff atMost_upto imageI set_map + by metis lemma (in ring_char_0) UNIV_ring_char_0_infinte: "\ finite (UNIV :: 'a set)" proof @@ -408,21 +390,12 @@ (is "?lhs \ ?rhs") proof show ?rhs if ?lhs - using that - apply - - apply (erule contrapos_np) - apply (rule ext) - apply (rule ccontr) - apply (clarify dest!: poly_roots_finite_lemma2) - using finite_subset proof - - fix x i - assume F: "\ finite {x. poly p x = 0}" - and P: "\x. poly p x = 0 \ x \ set i" - from P have "{x. poly p x = 0} \ set i" - by auto - with finite_subset F show False - by auto + have False if F: "\ finite {x. poly p x = 0}" + and P: "\x. poly p x = 0 \ x \ set i" for i + by (smt (verit, del_insts) in_set_conv_nth local.idom_finite_lemma that) + with that show ?thesis + using local.poly_roots_finite_lemma2 by blast qed show ?lhs if ?rhs using UNIV_ring_char_0_infinte that by auto @@ -473,18 +446,15 @@ qed lemma (in idom) poly_exp_eq_zero[simp]: "poly (p %^ n) = poly [] \ poly p = poly [] \ n \ 0" - apply (simp only: fun_eq_iff add: HOL.all_simps [symmetric]) - apply (rule arg_cong [where f = All]) - apply (rule ext) - apply (induct n) - apply (auto simp add: poly_exp poly_mult) - done + by (simp add: local.poly_exp fun_eq_iff) lemma (in comm_ring_1) poly_prime_eq_zero[simp]: "poly [a, 1] \ poly []" - apply (simp add: fun_eq_iff) - apply (rule_tac x = "minus one a" in exI) - apply (simp add: add.commute [of a]) - done +proof - + have "\x. a + x \ 0" + by (metis add_cancel_left_right zero_neq_one) + then show ?thesis + by (simp add: fun_eq_iff) +qed lemma (in idom) poly_exp_prime_eq_zero: "poly ([a, 1] %^ n) \ poly []" by auto @@ -492,26 +462,18 @@ text \A more constructive notion of polynomials being trivial.\ -lemma (in idom_char_0) poly_zero_lemma': "poly (h # t) = poly [] \ h = 0 \ poly t = poly []" - apply (simp add: fun_eq_iff) - apply (case_tac "h = zero") - apply (drule_tac [2] x = zero in spec) - apply auto - apply (cases "poly t = poly []") - apply simp +lemma (in idom_char_0) poly_zero_lemma': + assumes "poly (h # t) = poly []" shows "h = 0 \ poly t = poly []" proof - - fix x - assume H: "\x. x = 0 \ poly t x = 0" - assume pnz: "poly t \ poly []" - let ?S = "{x. poly t x = 0}" - from H have "\x. x \ 0 \ poly t x = 0" - by blast - then have th: "?S \ UNIV - {0}" - by auto - from poly_roots_finite pnz have th': "finite ?S" - by blast - from finite_subset[OF th th'] UNIV_ring_char_0_infinte show "poly t x = 0" - by simp + have "poly t x = 0" if H: "\x. x = 0 \ poly t x = 0" and pnz: "poly t \ poly []" for x + proof - + from H have "{x. poly t x = 0} \ UNIV - {0}" + by auto + then show ?thesis + using finite_subset local.poly_roots_finite pnz by fastforce + qed + with assms show ?thesis + by (simp add: fun_eq_iff) (metis add_cancel_right_left mult_eq_0_iff) qed lemma (in idom_char_0) poly_zero: "poly p = poly [] \ (\c \ set p. c = 0)" @@ -520,12 +482,8 @@ then show ?case by simp next case Cons - show ?case - apply (rule iffI) - apply (drule poly_zero_lemma') - using Cons - apply auto - done + then show ?case + by (smt (verit) list.set_intros pmult_by_x poly_entire poly_zero_lemma' set_ConsD) qed lemma (in idom_char_0) poly_0: "\c \ set p. c = 0 \ poly p x = 0" @@ -535,41 +493,33 @@ text \Basics of divisibility.\ lemma (in idom) poly_primes: "[a, 1] divides (p *** q) \ [a, 1] divides p \ [a, 1] divides q" - apply (auto simp add: divides_def fun_eq_iff poly_mult poly_add poly_cmult distrib_right [symmetric]) - apply (drule_tac x = "uminus a" in spec) - apply (simp add: poly_linear_divides poly_add poly_cmult distrib_right [symmetric]) - apply (cases "p = []") - apply (rule exI[where x="[]"]) - apply simp - apply (cases "q = []") - apply (erule allE[where x="[]"]) - apply simp - - apply clarsimp - apply (cases "\q. p = a %* q +++ (0 # q)") - apply (clarsimp simp add: poly_add poly_cmult) - apply (rule_tac x = qa in exI) - apply (simp add: distrib_right [symmetric]) - apply clarsimp - - apply (auto simp add: poly_linear_divides poly_add poly_cmult distrib_right [symmetric]) - apply (rule_tac x = "pmult qa q" in exI) - apply (rule_tac [2] x = "pmult p qa" in exI) - apply (auto simp add: poly_add poly_mult poly_cmult ac_simps) - done +proof - + have "\q. \x. poly p x = (a + x) * poly q x" + if "poly p (uminus a) * poly q (uminus a) = (a + (uminus a)) * poly qa (uminus a)" + and "\qa. \x. poly q x \ (a + x) * poly qa x" + for qa + using that + apply (simp add: poly_linear_divides poly_add) + by (metis add_cancel_left_right combine_common_factor mult_eq_0_iff poly.poly_Cons poly.poly_Nil poly_add poly_cmult) + moreover have "\qb. \x. (a + x) * poly qa x * poly q x = (a + x) * poly qb x" for qa + by (metis local.poly_mult mult_assoc) + moreover have "\q. \x. poly p x * ((a + x) * poly qa x) = (a + x) * poly q x" for qa + by (metis mult.left_commute local.poly_mult) + ultimately show ?thesis + by (auto simp: divides_def divisors_zero fun_eq_iff poly_mult poly_add poly_cmult simp flip: distrib_right) +qed lemma (in comm_semiring_1) poly_divides_refl[simp]: "p divides p" - apply (simp add: divides_def) - apply (rule_tac x = "[one]" in exI) - apply (auto simp add: poly_mult fun_eq_iff) - done +proof - + have "poly p = poly (p *** [1])" + by (auto simp add: poly_mult fun_eq_iff) + then show ?thesis + using local.dividesI by blast +qed lemma (in comm_semiring_1) poly_divides_trans: "p divides q \ q divides r \ p divides r" - apply (simp add: divides_def) - apply safe - apply (rule_tac x = "pmult qa qaa" in exI) - apply (auto simp add: poly_mult fun_eq_iff mult.assoc) - done + unfolding divides_def + by (metis ext local.poly_mult local.poly_mult_assoc) lemma (in comm_semiring_1) poly_divides_exp: "m \ n \ (p %^ m) divides (p %^ n)" by (auto simp: le_iff_add divides_def poly_exp_add fun_eq_iff) @@ -577,34 +527,35 @@ lemma (in comm_semiring_1) poly_exp_divides: "(p %^ n) divides q \ m \ n \ (p %^ m) divides q" by (blast intro: poly_divides_exp poly_divides_trans) -lemma (in comm_semiring_0) poly_divides_add: "p divides q \ p divides r \ p divides (q +++ r)" - apply (auto simp add: divides_def) - apply (rule_tac x = "padd qa qaa" in exI) - apply (auto simp add: poly_add fun_eq_iff poly_mult distrib_left) - done +lemma (in comm_semiring_0) poly_divides_add: + assumes "p divides q" and "p divides r" shows "p divides (q +++ r)" +proof - + have "\qa qb. \poly q = poly (p *** qa); poly r = poly (p *** qb)\ + \ poly (q +++ r) = poly (p *** (qa +++ qb))" + by (auto simp add: poly_add fun_eq_iff poly_mult distrib_left) + with assms show ?thesis + by (auto simp add: divides_def) +qed -lemma (in comm_ring_1) poly_divides_diff: "p divides q \ p divides (q +++ r) \ p divides r" - apply (auto simp add: divides_def) - apply (rule_tac x = "padd qaa (poly_minus qa)" in exI) - apply (auto simp add: poly_add fun_eq_iff poly_mult poly_minus algebra_simps) - done +lemma (in comm_ring_1) poly_divides_diff: + assumes "p divides q" and "p divides (q +++ r)" + shows "p divides r" +proof - + have "\qa qb. \poly q = poly (p *** qa); poly (q +++ r) = poly (p *** qb)\ + \ poly r = poly (p *** (qb +++ -- qa))" + by (auto simp add: poly_add fun_eq_iff poly_mult poly_minus algebra_simps) + with assms show ?thesis + by (auto simp add: divides_def) +qed lemma (in comm_ring_1) poly_divides_diff2: "p divides r \ p divides (q +++ r) \ p divides q" - apply (erule poly_divides_diff) - apply (auto simp add: poly_add fun_eq_iff poly_mult divides_def ac_simps) - done + by (metis local.padd_commut local.poly_divides_diff) lemma (in semiring_0) poly_divides_zero: "poly p = poly [] \ q divides p" - apply (simp add: divides_def) - apply (rule exI[where x = "[]"]) - apply (auto simp add: fun_eq_iff poly_mult) - done + by (metis ext dividesI poly.poly_Nil poly_mult_Nil2) lemma (in semiring_0) poly_divides_zero2 [simp]: "q divides []" - apply (simp add: divides_def) - apply (rule_tac x = "[]" in exI) - apply (auto simp add: fun_eq_iff) - done + using local.poly_divides_zero by force text \At last, we can consider the order of a root.\ @@ -629,11 +580,7 @@ from True[unfolded poly_linear_divides] pN obtain q where q: "p = [-a, 1] *** q" by blast from q h True have qh: "length q = n" "poly q \ poly []" - apply simp_all - apply (simp only: fun_eq_iff) - apply (rule ccontr) - apply (simp add: fun_eq_iff poly_add poly_cmult) - done + using h(2) local.poly_entire q by fastforce+ from Suc.hyps[OF qh] obtain m r where mr: "q = mulexp m [-a,1] r" "poly r a \ 0" by blast from mr q have "p = mulexp (Suc m) [-a,1] r \ poly r a \ 0" @@ -641,12 +588,8 @@ then show ?thesis by blast next case False - then show ?thesis - using Suc.prems - apply simp - apply (rule exI[where x="0::nat"]) - apply simp - done + with Suc.prems show ?thesis + by (smt (verit, best) local.mulexp.mulexp_zero) qed qed @@ -719,12 +662,7 @@ lemma (in idom_char_0) poly_order: "poly p \ poly [] \ \!n. ([-a, 1] %^ n) divides p \ \ (([-a, 1] %^ Suc n) divides p)" - apply (auto intro: poly_order_exists simp add: less_linear simp del: pmult_Cons pexp_Suc) - apply (cut_tac x = y and y = n in less_linear) - apply (drule_tac m = n in poly_exp_divides) - apply (auto dest: Suc_le_eq [THEN iffD2, THEN [2] poly_exp_divides] - simp del: pmult_Cons pexp_Suc) - done + by (meson Suc_le_eq linorder_neqE_nat local.poly_exp_divides poly_order_exists) text \Order\ @@ -736,10 +674,7 @@ "([-a, 1] %^ n) divides p \ \ (([-a, 1] %^ Suc n) divides p) \ n = order a p \ poly p \ poly []" unfolding order_def - apply (rule iffI) - apply (blast dest: poly_divides_zero intro!: some1_equality [symmetric] poly_order) - apply (blast intro!: poly_order [THEN [2] some1_equalityD]) - done + by (metis (no_types, lifting) local.poly_divides_zero local.poly_order someI) lemma (in idom_char_0) order2: "poly p \ poly [] \ @@ -767,97 +702,89 @@ by (induct n arbitrary: a p) (auto simp add: divides_def poly_mult simp del: pmult_Cons) lemma (in idom_char_0) order_root: "poly p a = 0 \ poly p = poly [] \ order a p \ 0" - apply (cases "poly p = poly []") - apply auto - apply (simp add: poly_linear_divides del: pmult_Cons) - apply safe - apply (drule_tac [!] a = a in order2) - apply (rule ccontr) - apply (simp add: divides_def poly_mult fun_eq_iff del: pmult_Cons) - apply blast - using neq0_conv apply (blast intro: lemma_order_root) - done +proof (cases "poly p = poly []") + case False + then show ?thesis + by (metis (mono_tags, lifting) dividesI lemma_order_root order2 pexp_one poly_linear_divides neq0_conv) +qed auto lemma (in idom_char_0) order_divides: "([-a, 1] %^ n) divides p \ poly p = poly [] \ n \ order a p" - apply (cases "poly p = poly []") - apply auto - apply (simp add: divides_def fun_eq_iff poly_mult) - apply (rule_tac x = "[]" in exI) - apply (auto dest!: order2 [where a=a] intro: poly_exp_divides simp del: pexp_Suc) - done +proof (cases "poly p = poly []") + case True + then show ?thesis + using local.poly_divides_zero by force +next + case False + then show ?thesis + by (meson local.order2 local.poly_exp_divides not_less_eq_eq) +qed lemma (in idom_char_0) order_decomp: - "poly p \ poly [] \ \q. poly p = poly (([-a, 1] %^ order a p) *** q) \ \ [-a, 1] divides q" - unfolding divides_def - apply (drule order2 [where a = a]) - apply (simp add: divides_def del: pexp_Suc pmult_Cons) - apply safe - apply (rule_tac x = q in exI) - apply safe - apply (drule_tac x = qa in spec) - apply (auto simp add: poly_mult fun_eq_iff poly_exp ac_simps simp del: pmult_Cons) - done + assumes "poly p \ poly []" + shows "\q. poly p = poly (([-a, 1] %^ order a p) *** q) \ \ [-a, 1] divides q" +proof - + obtain q where q: "poly p = poly ([- a, 1] %^ order a p *** q)" + using assms local.order2 divides_def by blast + have False if "poly q = poly ([- a, 1] *** qa)" for qa + proof - + have "poly p \ poly ([- a, 1] %^ Suc (order a p) *** qa)" + using assms local.divides_def local.order2 by blast + with q that show False + by (auto simp add: poly_mult ac_simps simp del: pmult_Cons) + qed + with q show ?thesis + unfolding divides_def by blast +qed text \Important composition properties of orders.\ lemma order_mult: fixes a :: "'a::idom_char_0" - shows "poly (p *** q) \ poly [] \ order a (p *** q) = order a p + order a q" - apply (cut_tac a = a and p = "p *** q" and n = "order a p + order a q" in order) - apply (auto simp add: poly_entire simp del: pmult_Cons) - apply (drule_tac a = a in order2)+ - apply safe - apply (simp add: divides_def fun_eq_iff poly_exp_add poly_mult del: pmult_Cons, safe) - apply (rule_tac x = "qa *** qaa" in exI) - apply (simp add: poly_mult ac_simps del: pmult_Cons) - apply (drule_tac a = a in order_decomp)+ - apply safe - apply (subgoal_tac "[-a, 1] divides (qa *** qaa) ") - apply (simp add: poly_primes del: pmult_Cons) - apply (auto simp add: divides_def simp del: pmult_Cons) - apply (rule_tac x = qb in exI) - apply (subgoal_tac "poly ([-a, 1] %^ (order a p) *** (qa *** qaa)) = - poly ([-a, 1] %^ (order a p) *** ([-a, 1] *** qb))") - apply (drule poly_mult_left_cancel [THEN iffD1]) - apply force - apply (subgoal_tac "poly ([-a, 1] %^ (order a q) *** ([-a, 1] %^ (order a p) *** (qa *** qaa))) = - poly ([-a, 1] %^ (order a q) *** ([-a, 1] %^ (order a p) *** ([-a, 1] *** qb))) ") - apply (drule poly_mult_left_cancel [THEN iffD1]) - apply force - apply (simp add: fun_eq_iff poly_exp_add poly_mult ac_simps del: pmult_Cons) - done - -lemma (in idom_char_0) order_mult: assumes "poly (p *** q) \ poly []" shows "order a (p *** q) = order a p + order a q" - using assms - apply (cut_tac a = a and p = "pmult p q" and n = "order a p + order a q" in order) - apply (auto simp add: poly_entire simp del: pmult_Cons) - apply (drule_tac a = a in order2)+ - apply safe - apply (simp add: divides_def fun_eq_iff poly_exp_add poly_mult del: pmult_Cons) - apply safe - apply (rule_tac x = "pmult qa qaa" in exI) - apply (simp add: poly_mult ac_simps del: pmult_Cons) - apply (drule_tac a = a in order_decomp)+ - apply safe - apply (subgoal_tac "[uminus a, one] divides pmult qa qaa") - apply (simp add: poly_primes del: pmult_Cons) - apply (auto simp add: divides_def simp del: pmult_Cons) - apply (rule_tac x = qb in exI) - apply (subgoal_tac "poly (pmult (pexp [uminus a, one] (order a p)) (pmult qa qaa)) = - poly (pmult (pexp [uminus a, one] (order a p)) (pmult [uminus a, one] qb))") - apply (drule poly_mult_left_cancel [THEN iffD1], force) - apply (subgoal_tac "poly (pmult (pexp [uminus a, one] (order a q)) - (pmult (pexp [uminus a, one] (order a p)) (pmult qa qaa))) = - poly (pmult (pexp [uminus a, one] (order a q)) - (pmult (pexp [uminus a, one] (order a p)) (pmult [uminus a, one] qb)))") - apply (drule poly_mult_left_cancel [THEN iffD1], force) - apply (simp add: fun_eq_iff poly_exp_add poly_mult ac_simps del: pmult_Cons) - done +proof - + have p: "poly p \ poly []" and q: "poly q \ poly []" + using assms poly_entire by auto + obtain p' where p': + "\x. poly p x = poly ([- a, 1] %^ order a p) x * poly p' x" + "\ [- a, 1] divides p'" + by (metis order_decomp p poly_mult) + obtain q' where q': + "\x. poly q x = poly ([- a, 1] %^ order a q) x * poly q' x" + "\ [- a, 1] divides q'" + by (metis order_decomp q poly_mult) + have "[- a, 1] %^ (order a p + order a q) divides (p *** q)" + proof - + have *: "poly p x * poly q x = + poly ([- a, 1] %^ order a p) x * poly ([- a, 1] %^ order a q) x * poly (p' *** q') x" for x + using p' q' by (simp add: poly_mult) + then show ?thesis + unfolding divides_def poly_exp_add poly_mult using * by blast + qed + moreover have False + if pq: "order a (p *** q) \ order a p + order a q" + and dv: "[- a, 1] *** [- a, 1] %^ (order a p + order a q) divides (p *** q)" + proof - + obtain pq' :: "'a list" + where pq': "poly (p *** q) = poly ([- a, 1] *** [- a, 1] %^ (order a p + order a q) *** pq')" + using dv unfolding divides_def by auto + have "poly ([-a, 1] %^ (order a q) *** ([-a, 1] %^ (order a p) *** (p' *** q'))) = + poly ([-a, 1] %^ (order a q) *** ([-a, 1] %^ (order a p) *** ([-a, 1] *** pq')))" + using p' q' pq pq' + by (simp add: fun_eq_iff poly_exp_add poly_mult ac_simps del: pmult_Cons) + then have "poly ([-a, 1] %^ (order a p) *** (p' *** q')) = poly ([-a, 1] %^ (order a p) *** ([-a, 1] *** pq'))" + by (simp add: poly_mult_left_cancel) + then have "[-a, 1] divides (p' *** q')" + unfolding divides_def by (meson poly_exp_prime_eq_zero poly_mult_left_cancel) + with p' q' show ?thesis + by (simp add: poly_primes) + qed + ultimately show ?thesis + by (metis order pexp_Suc) +qed lemma (in idom_char_0) order_root2: "poly p \ poly [] \ poly p a = 0 \ order a p \ 0" - by (rule order_root [THEN ssubst]) auto + using order_root by presburger lemma (in semiring_1) pmult_one[simp]: "[1] *** p = p" by auto @@ -866,21 +793,18 @@ by (simp add: fun_eq_iff) lemma (in idom_char_0) rsquarefree_decomp: - "rsquarefree p \ poly p a = 0 \ \q. poly p = poly ([-a, 1] *** q) \ poly q a \ 0" - apply (simp add: rsquarefree_def) - apply safe - apply (frule_tac a = a in order_decomp) - apply (drule_tac x = a in spec) - apply (drule_tac a = a in order_root2 [symmetric]) - apply (auto simp del: pmult_Cons) - apply (rule_tac x = q in exI, safe) - apply (simp add: poly_mult fun_eq_iff) - apply (drule_tac p1 = q in poly_linear_divides [THEN iffD1]) - apply (simp add: divides_def del: pmult_Cons, safe) - apply (drule_tac x = "[]" in spec) - apply (auto simp add: fun_eq_iff) - done - + assumes "rsquarefree p" and "poly p a = 0" + shows "\q. poly p = poly ([-a, 1] *** q) \ poly q a \ 0" +proof - + have "order a p = Suc 0" + using assms local.order_root2 rsquarefree_def by force + moreover + obtain q where "poly p = poly ([- a, 1] %^ order a p *** q)" + "\ [- a, 1] divides q" + using assms(1) order_decomp rsquarefree_def by blast + ultimately show ?thesis + using dividesI poly_linear_divides by auto +qed text \Normalization of a polynomial.\ @@ -952,28 +876,12 @@ then show ?case proof (induct p) case Nil - then have "poly [] = poly (c # cs)" - by blast - then have "poly (c#cs) = poly []" - by simp then show ?case - by (simp only: poly_zero lemma_degree_zero) simp + by (metis local.poly_zero_lemma') next case (Cons d ds) - then have eq: "poly (d # ds) = poly (c # cs)" - by blast - then have eq': "\x. poly (d # ds) x = poly (c # cs) x" - by simp - then have "poly (d # ds) 0 = poly (c # cs) 0" - by blast - then have dc: "d = c" - by auto - with eq have "poly ds = poly cs" - unfolding poly_Cons_eq by simp - with Cons.prems have "pnormalize ds = pnormalize cs" - by blast - with dc show ?case - by simp + then show ?case + by (metis pnormalize.pnormalize_Cons local.poly_Cons_eq) qed qed @@ -987,15 +895,16 @@ lemma (in semiring_0) last_linear_mul_lemma: "last ((a %* p) +++ (x # (b %* p))) = (if p = [] then x else b * last p)" - apply (induct p arbitrary: a x b) - apply auto - subgoal for a p c x b - apply (subgoal_tac "padd (cmult c p) (times b a # cmult b p) \ []") - apply simp - apply (induct p) - apply auto - done - done +proof (induct p arbitrary: a x b) + case Nil + then show ?case by auto +next + case (Cons a p c x b) + then have "padd (cmult c p) (times b a # cmult b p) \ []" + by (metis local.padd.padd_Nil local.padd_Cons_Cons neq_Nil_conv) + then show ?case + by (simp add: local.Cons) +qed lemma (in semiring_1) last_linear_mul: assumes p: "p \ []" @@ -1051,18 +960,11 @@ case True then show ?thesis using degree_unique[OF True] by (simp add: degree_def) - next - case False - then show ?thesis - by (auto simp add: poly_Nil_ext) - qed + qed (auto simp add: poly_Nil_ext) next case (Suc n a p) have eq: "poly ([a, 1] %^(Suc n) *** p) = poly ([a, 1] %^ n *** ([a, 1] *** p))" - apply (rule ext) - apply (simp add: poly_mult poly_add poly_cmult) - apply (simp add: ac_simps distrib_left) - done + by (force simp add: poly_mult poly_add poly_cmult ac_simps distrib_left) note deq = degree_unique[OF eq] show ?case proof (cases "poly p = poly []") @@ -1080,9 +982,7 @@ from ap have ap': "poly ([a, 1] *** p) = poly [] \ False" by blast have th0: "degree ([a, 1]%^n *** ([a, 1] *** p)) = degree ([a, 1] *** p) + n" - apply (simp only: Suc.hyps[of a "pmult [a,one] p"] ap') - apply simp - done + unfolding Suc.hyps[of a "pmult [a,one] p"] ap' by simp from degree_unique[OF eq] ap False th0 linear_mul_degree[OF False, of a] show ?thesis by (auto simp del: poly.simps) @@ -1118,12 +1018,12 @@ then show ?case by simp next case (Cons a p) - then show ?case - apply auto - apply (rule_tac y = "\a\ + \x * poly p x\" in order_trans) - apply (rule abs_triangle_ineq) - apply (auto intro!: mult_mono simp add: abs_mult) - done + have "\a + x * poly p x\ \ \a\ + \x * poly p x\" + using abs_triangle_ineq by blast + also have "\ \ \a\ + k * poly (map abs p) k" + by (simp add: Cons.hyps Cons.prems abs_mult mult_mono') + finally show ?case + using Cons by auto qed lemma (in semiring_0) poly_Sing: "poly [c] x = c"