src/HOL/Decision_Procs/Reflected_Multivariate_Polynomial.thy
changeset 56043 0b25c3d34b77
parent 56009 dda076a32aea
child 56066 cce36efe32eb
equal deleted inserted replaced
56042:d3c35a300433 56043:0b25c3d34b77
     8 imports Complex_Main Rat_Pair Polynomial_List
     8 imports Complex_Main Rat_Pair Polynomial_List
     9 begin
     9 begin
    10 
    10 
    11 subsection{* Datatype of polynomial expressions *}
    11 subsection{* Datatype of polynomial expressions *}
    12 
    12 
    13 datatype poly = C Num| Bound nat| Add poly poly|Sub poly poly
    13 datatype poly = C Num | Bound nat | Add poly poly | Sub poly poly
    14   | Mul poly poly| Neg poly| Pw poly nat| CN poly nat poly
    14   | Mul poly poly| Neg poly| Pw poly nat| CN poly nat poly
    15 
    15 
    16 abbreviation poly_0 :: "poly" ("0\<^sub>p") where "0\<^sub>p \<equiv> C (0\<^sub>N)"
    16 abbreviation poly_0 :: "poly" ("0\<^sub>p") where "0\<^sub>p \<equiv> C (0\<^sub>N)"
    17 abbreviation poly_p :: "int \<Rightarrow> poly" ("'((_)')\<^sub>p") where "(i)\<^sub>p \<equiv> C (i)\<^sub>N"
    17 abbreviation poly_p :: "int \<Rightarrow> poly" ("'((_)')\<^sub>p") where "(i)\<^sub>p \<equiv> C (i)\<^sub>N"
    18 
    18 
   140 definition polysub :: "poly \<Rightarrow> poly \<Rightarrow> poly" (infixl "-\<^sub>p" 60)
   140 definition polysub :: "poly \<Rightarrow> poly \<Rightarrow> poly" (infixl "-\<^sub>p" 60)
   141   where "p -\<^sub>p q = polyadd p (polyneg q)"
   141   where "p -\<^sub>p q = polyadd p (polyneg q)"
   142 
   142 
   143 fun polymul :: "poly \<Rightarrow> poly \<Rightarrow> poly" (infixl "*\<^sub>p" 60)
   143 fun polymul :: "poly \<Rightarrow> poly \<Rightarrow> poly" (infixl "*\<^sub>p" 60)
   144 where
   144 where
   145   "polymul (C c) (C c') = C (c*\<^sub>Nc')"
   145   "polymul (C c) (C c') = C (c *\<^sub>N c')"
   146 | "polymul (C c) (CN c' n' p') =
   146 | "polymul (C c) (CN c' n' p') =
   147     (if c = 0\<^sub>N then 0\<^sub>p else CN (polymul (C c) c') n' (polymul (C c) p'))"
   147     (if c = 0\<^sub>N then 0\<^sub>p else CN (polymul (C c) c') n' (polymul (C c) p'))"
   148 | "polymul (CN c n p) (C c') =
   148 | "polymul (CN c n p) (C c') =
   149     (if c' = 0\<^sub>N  then 0\<^sub>p else CN (polymul c (C c')) n (polymul p (C c')))"
   149     (if c' = 0\<^sub>N  then 0\<^sub>p else CN (polymul c (C c')) n (polymul p (C c')))"
   150 | "polymul (CN c n p) (CN c' n' p') =
   150 | "polymul (CN c n p) (CN c' n' p') =
   554     assume m: "m \<le> min n0 n1"
   554     assume m: "m \<le> min n0 n1"
   555     let ?d = "degreen (?cnp *\<^sub>p ?cnp') m"
   555     let ?d = "degreen (?cnp *\<^sub>p ?cnp') m"
   556     let ?d1 = "degreen ?cnp m"
   556     let ?d1 = "degreen ?cnp m"
   557     let ?d2 = "degreen ?cnp' m"
   557     let ?d2 = "degreen ?cnp' m"
   558     let ?eq = "?d = (if ?cnp = 0\<^sub>p \<or> ?cnp' = 0\<^sub>p then 0  else ?d1 + ?d2)"
   558     let ?eq = "?d = (if ?cnp = 0\<^sub>p \<or> ?cnp' = 0\<^sub>p then 0  else ?d1 + ?d2)"
   559     have "n'<n \<or> n < n' \<or> n' = n" by auto
   559     have "n' < n \<or> n < n' \<or> n' = n" by auto
   560     moreover
   560     moreover
   561     {
   561     {
   562       assume "n' < n \<or> n < n'"
   562       assume "n' < n \<or> n < n'"
   563       with "4.hyps"(3,6,18) np np' m have ?eq
   563       with "4.hyps"(3,6,18) np np' m have ?eq
   564         by auto
   564         by auto
   568       assume nn': "n' = n"
   568       assume nn': "n' = n"
   569       then have nn: "\<not> n' < n \<and> \<not> n < n'" by arith
   569       then have nn: "\<not> n' < n \<and> \<not> n < n'" by arith
   570       from "4.hyps"(16,18)[of n n' n]
   570       from "4.hyps"(16,18)[of n n' n]
   571         "4.hyps"(13,14)[of n "Suc n'" n]
   571         "4.hyps"(13,14)[of n "Suc n'" n]
   572         np np' nn'
   572         np np' nn'
   573       have norm: "isnpolyh ?cnp n" "isnpolyh c' (Suc n)" "isnpolyh (?cnp *\<^sub>p c') n"
   573       have norm:
   574         "isnpolyh p' n" "isnpolyh (?cnp *\<^sub>p p') n" "isnpolyh (CN 0\<^sub>p n (CN c n p *\<^sub>p p')) n"
   574         "isnpolyh ?cnp n"
   575         "(?cnp *\<^sub>p c' = 0\<^sub>p) = (c' = 0\<^sub>p)"
   575         "isnpolyh c' (Suc n)"
   576         "?cnp *\<^sub>p p' \<noteq> 0\<^sub>p" by (auto simp add: min_def)
   576         "isnpolyh (?cnp *\<^sub>p c') n"
       
   577         "isnpolyh p' n"
       
   578         "isnpolyh (?cnp *\<^sub>p p') n"
       
   579         "isnpolyh (CN 0\<^sub>p n (CN c n p *\<^sub>p p')) n"
       
   580         "?cnp *\<^sub>p c' = 0\<^sub>p \<longleftrightarrow> c' = 0\<^sub>p"
       
   581         "?cnp *\<^sub>p p' \<noteq> 0\<^sub>p"
       
   582         by (auto simp add: min_def)
   577       {
   583       {
   578         assume mn: "m = n"
   584         assume mn: "m = n"
   579         from "4.hyps"(17,18)[OF norm(1,4), of n]
   585         from "4.hyps"(17,18)[OF norm(1,4), of n]
   580           "4.hyps"(13,15)[OF norm(1,2), of n] norm nn' mn
   586           "4.hyps"(13,15)[OF norm(1,2), of n] norm nn' mn
   581         have degs:
   587         have degs:
   625   }
   631   }
   626   {
   632   {
   627     case (2 n0 n1)
   633     case (2 n0 n1)
   628     then have np: "isnpolyh ?cnp n0"
   634     then have np: "isnpolyh ?cnp n0"
   629       and np': "isnpolyh ?cnp' n1"
   635       and np': "isnpolyh ?cnp' n1"
   630       and m: "m \<le> min n0 n1" by simp_all
   636       and m: "m \<le> min n0 n1"
       
   637       by simp_all
   631     then have mn: "m \<le> n" by simp
   638     then have mn: "m \<le> n" by simp
   632     let ?c0p = "CN 0\<^sub>p n (?cnp *\<^sub>p p')"
   639     let ?c0p = "CN 0\<^sub>p n (?cnp *\<^sub>p p')"
   633     {
   640     {
   634       assume C: "?cnp *\<^sub>p c' +\<^sub>p ?c0p = 0\<^sub>p" "n' = n"
   641       assume C: "?cnp *\<^sub>p c' +\<^sub>p ?c0p = 0\<^sub>p" "n' = n"
   635       then have nn: "\<not> n' < n \<and> \<not> n < n'"
   642       then have nn: "\<not> n' < n \<and> \<not> n < n'"
   698 proof (cases "headconst p = 0\<^sub>N", simp_all add: headconst_zero[OF np])
   705 proof (cases "headconst p = 0\<^sub>N", simp_all add: headconst_zero[OF np])
   699   let ?h = "headconst p"
   706   let ?h = "headconst p"
   700   assume pz: "p \<noteq> 0\<^sub>p"
   707   assume pz: "p \<noteq> 0\<^sub>p"
   701   {
   708   {
   702     assume hz: "INum ?h = (0::'a)"
   709     assume hz: "INum ?h = (0::'a)"
   703     from headconst_isnormNum[OF np] have norm: "isnormNum ?h" "isnormNum 0\<^sub>N" by simp_all
   710     from headconst_isnormNum[OF np] have norm: "isnormNum ?h" "isnormNum 0\<^sub>N"
   704     from isnormNum_unique[where ?'a = 'a, OF norm] hz have "?h = 0\<^sub>N" by simp
   711       by simp_all
   705     with headconst_zero[OF np] have "p =0\<^sub>p" by blast with pz have "False" by blast}
   712     from isnormNum_unique[where ?'a = 'a, OF norm] hz have "?h = 0\<^sub>N"
   706   then show "INum (headconst p) = (0::'a) \<longrightarrow> \<lparr>p\<rparr>\<^sub>p\<^bsup>bs\<^esup> = 0" by blast
   713       by simp
       
   714     with headconst_zero[OF np] have "p = 0\<^sub>p"
       
   715       by blast
       
   716     with pz have False
       
   717       by blast
       
   718   }
       
   719   then show "INum (headconst p) = (0::'a) \<longrightarrow> \<lparr>p\<rparr>\<^sub>p\<^bsup>bs\<^esup> = 0"
       
   720     by blast
   707 qed
   721 qed
   708 
   722 
   709 
   723 
   710 text{* polyneg is a negation and preserves normal forms *}
   724 text{* polyneg is a negation and preserves normal forms *}
   711 
   725 
   753 
   767 
   754 lemma polypow[simp]:
   768 lemma polypow[simp]:
   755   "Ipoly bs (polypow n p) = (Ipoly bs p :: 'a::{field_char_0,field_inverse_zero}) ^ n"
   769   "Ipoly bs (polypow n p) = (Ipoly bs p :: 'a::{field_char_0,field_inverse_zero}) ^ n"
   756 proof (induct n rule: polypow.induct)
   770 proof (induct n rule: polypow.induct)
   757   case 1
   771   case 1
   758   then show ?case by simp
   772   then show ?case
       
   773     by simp
   759 next
   774 next
   760   case (2 n)
   775   case (2 n)
   761   let ?q = "polypow ((Suc n) div 2) p"
   776   let ?q = "polypow ((Suc n) div 2) p"
   762   let ?d = "polymul ?q ?q"
   777   let ?d = "polymul ?q ?q"
   763   have "odd (Suc n) \<or> even (Suc n)" by simp
   778   have "odd (Suc n) \<or> even (Suc n)"
       
   779     by simp
   764   moreover
   780   moreover
   765   { assume odd: "odd (Suc n)"
   781   {
       
   782     assume odd: "odd (Suc n)"
   766     have th: "(Suc (Suc (Suc 0) * (Suc n div Suc (Suc 0)))) = Suc n div 2 + Suc n div 2 + 1"
   783     have th: "(Suc (Suc (Suc 0) * (Suc n div Suc (Suc 0)))) = Suc n div 2 + Suc n div 2 + 1"
   767       by arith
   784       by arith
   768     from odd have "Ipoly bs (p ^\<^sub>p Suc n) = Ipoly bs (polymul p ?d)" by (simp add: Let_def)
   785     from odd have "Ipoly bs (p ^\<^sub>p Suc n) = Ipoly bs (polymul p ?d)"
   769     also have "\<dots> = (Ipoly bs p) * (Ipoly bs p)^(Suc n div 2)*(Ipoly bs p)^(Suc n div 2)"
   786       by (simp add: Let_def)
       
   787     also have "\<dots> = (Ipoly bs p) * (Ipoly bs p)^(Suc n div 2) * (Ipoly bs p)^(Suc n div 2)"
   770       using "2.hyps" by simp
   788       using "2.hyps" by simp
   771     also have "\<dots> = (Ipoly bs p) ^ (Suc n div 2 + Suc n div 2 + 1)"
   789     also have "\<dots> = (Ipoly bs p) ^ (Suc n div 2 + Suc n div 2 + 1)"
   772       by (simp only: power_add power_one_right) simp
   790       by (simp only: power_add power_one_right) simp
   773     also have "\<dots> = (Ipoly bs p) ^ (Suc (Suc (Suc 0) * (Suc n div Suc (Suc 0))))"
   791     also have "\<dots> = (Ipoly bs p) ^ (Suc (Suc (Suc 0) * (Suc n div Suc (Suc 0))))"
   774       by (simp only: th)
   792       by (simp only: th)
   775     finally have ?case
   793     finally have ?case
   776     using odd_nat_div_two_times_two_plus_one[OF odd, symmetric] by simp  }
   794     using odd_nat_div_two_times_two_plus_one[OF odd, symmetric] by simp
       
   795   }
   777   moreover
   796   moreover
   778   { assume even: "even (Suc n)"
   797   {
       
   798     assume even: "even (Suc n)"
   779     have th: "(Suc (Suc 0)) * (Suc n div Suc (Suc 0)) = Suc n div 2 + Suc n div 2"
   799     have th: "(Suc (Suc 0)) * (Suc n div Suc (Suc 0)) = Suc n div 2 + Suc n div 2"
   780       by arith
   800       by arith
   781     from even have "Ipoly bs (p ^\<^sub>p Suc n) = Ipoly bs ?d" by (simp add: Let_def)
   801     from even have "Ipoly bs (p ^\<^sub>p Suc n) = Ipoly bs ?d"
       
   802       by (simp add: Let_def)
   782     also have "\<dots> = (Ipoly bs p) ^ (Suc n div 2 + Suc n div 2)"
   803     also have "\<dots> = (Ipoly bs p) ^ (Suc n div 2 + Suc n div 2)"
   783       using "2.hyps" apply (simp only: power_add) by simp
   804       using "2.hyps" by (simp only: power_add) simp
   784     finally have ?case using even_nat_div_two_times_two[OF even] by (simp only: th)}
   805     finally have ?case using even_nat_div_two_times_two[OF even]
       
   806       by (simp only: th)
       
   807   }
   785   ultimately show ?case by blast
   808   ultimately show ?case by blast
   786 qed
   809 qed
   787 
   810 
   788 lemma polypow_normh:
   811 lemma polypow_normh:
   789   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
   812   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
   790   shows "isnpolyh p n \<Longrightarrow> isnpolyh (polypow k p) n"
   813   shows "isnpolyh p n \<Longrightarrow> isnpolyh (polypow k p) n"
   791 proof (induct k arbitrary: n rule: polypow.induct)
   814 proof (induct k arbitrary: n rule: polypow.induct)
       
   815   case 1
       
   816   then show ?case by auto
       
   817 next
   792   case (2 k n)
   818   case (2 k n)
   793   let ?q = "polypow (Suc k div 2) p"
   819   let ?q = "polypow (Suc k div 2) p"
   794   let ?d = "polymul ?q ?q"
   820   let ?d = "polymul ?q ?q"
   795   from 2 have th1:"isnpolyh ?q n" and th2: "isnpolyh p n" by blast+
   821   from 2 have th1: "isnpolyh ?q n" and th2: "isnpolyh p n"
   796   from polymul_normh[OF th1 th1] have dn: "isnpolyh ?d n" by simp
   822     by blast+
   797   from polymul_normh[OF th2 dn] have on: "isnpolyh (polymul p ?d) n" by simp
   823   from polymul_normh[OF th1 th1] have dn: "isnpolyh ?d n"
   798   from dn on show ?case by (simp add: Let_def)
   824     by simp
   799 qed auto
   825   from polymul_normh[OF th2 dn] have on: "isnpolyh (polymul p ?d) n"
       
   826     by simp
       
   827   from dn on show ?case
       
   828     by (simp add: Let_def)
       
   829 qed
   800 
   830 
   801 lemma polypow_norm:
   831 lemma polypow_norm:
   802   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
   832   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
   803   shows "isnpoly p \<Longrightarrow> isnpoly (polypow k p)"
   833   shows "isnpoly p \<Longrightarrow> isnpoly (polypow k p)"
   804   by (simp add: polypow_normh isnpoly_def)
   834   by (simp add: polypow_normh isnpoly_def)
   828   shows "isnpoly (shift1 p) "
   858   shows "isnpoly (shift1 p) "
   829   using pn pnz by (simp add: shift1_def isnpoly_def)
   859   using pn pnz by (simp add: shift1_def isnpoly_def)
   830 
   860 
   831 lemma shift1_nz[simp]:"shift1 p \<noteq> 0\<^sub>p"
   861 lemma shift1_nz[simp]:"shift1 p \<noteq> 0\<^sub>p"
   832   by (simp add: shift1_def)
   862   by (simp add: shift1_def)
   833 lemma funpow_shift1_isnpoly:
   863 
   834   "\<lbrakk> isnpoly p ; p \<noteq> 0\<^sub>p\<rbrakk> \<Longrightarrow> isnpoly (funpow n shift1 p)"
   864 lemma funpow_shift1_isnpoly: "isnpoly p \<Longrightarrow> p \<noteq> 0\<^sub>p \<Longrightarrow> isnpoly (funpow n shift1 p)"
   835   by (induct n arbitrary: p) (auto simp add: shift1_isnpoly funpow_swap1)
   865   by (induct n arbitrary: p) (auto simp add: shift1_isnpoly funpow_swap1)
   836 
   866 
   837 lemma funpow_isnpolyh:
   867 lemma funpow_isnpolyh:
   838   assumes f: "\<And> p. isnpolyh p n \<Longrightarrow> isnpolyh (f p) n"
   868   assumes f: "\<And>p. isnpolyh p n \<Longrightarrow> isnpolyh (f p) n"
   839     and np: "isnpolyh p n"
   869     and np: "isnpolyh p n"
   840   shows "isnpolyh (funpow k f p) n"
   870   shows "isnpolyh (funpow k f p) n"
   841   using f np by (induct k arbitrary: p) auto
   871   using f np by (induct k arbitrary: p) auto
   842 
   872 
   843 lemma funpow_shift1:
   873 lemma funpow_shift1:
   844   "(Ipoly bs (funpow n shift1 p) :: 'a :: {field_char_0,field_inverse_zero}) =
   874   "(Ipoly bs (funpow n shift1 p) :: 'a :: {field_char_0,field_inverse_zero}) =
   845     Ipoly bs (Mul (Pw (Bound 0) n) p)"
   875     Ipoly bs (Mul (Pw (Bound 0) n) p)"
   846   by (induct n arbitrary: p) (simp_all add: shift1_isnpoly shift1)
   876   by (induct n arbitrary: p) (simp_all add: shift1_isnpoly shift1)
   847 
   877 
   848 lemma shift1_isnpolyh: "isnpolyh p n0 \<Longrightarrow> p\<noteq> 0\<^sub>p \<Longrightarrow> isnpolyh (shift1 p) 0"
   878 lemma shift1_isnpolyh: "isnpolyh p n0 \<Longrightarrow> p \<noteq> 0\<^sub>p \<Longrightarrow> isnpolyh (shift1 p) 0"
   849   using isnpolyh_mono[where n="n0" and n'="0" and p="p"] by (simp add: shift1_def)
   879   using isnpolyh_mono[where n="n0" and n'="0" and p="p"] by (simp add: shift1_def)
   850 
   880 
   851 lemma funpow_shift1_1:
   881 lemma funpow_shift1_1:
   852   "(Ipoly bs (funpow n shift1 p) :: 'a :: {field_char_0,field_inverse_zero}) =
   882   "(Ipoly bs (funpow n shift1 p) :: 'a :: {field_char_0,field_inverse_zero}) =
   853     Ipoly bs (funpow n shift1 (1)\<^sub>p *\<^sub>p p)"
   883     Ipoly bs (funpow n shift1 (1)\<^sub>p *\<^sub>p p)"
   898   by (induct p) auto
   928   by (induct p) auto
   899 
   929 
   900 lemma decrpoly_normh: "isnpolyh p n0 \<Longrightarrow> polybound0 p \<Longrightarrow> isnpolyh (decrpoly p) (n0 - 1)"
   930 lemma decrpoly_normh: "isnpolyh p n0 \<Longrightarrow> polybound0 p \<Longrightarrow> isnpolyh (decrpoly p) (n0 - 1)"
   901   apply (induct p arbitrary: n0)
   931   apply (induct p arbitrary: n0)
   902   apply auto
   932   apply auto
   903   apply (atomize)
   933   apply atomize
   904   apply (erule_tac x = "Suc nat" in allE)
   934   apply (erule_tac x = "Suc nat" in allE)
   905   apply auto
   935   apply auto
   906   done
   936   done
   907 
   937 
   908 lemma head_polybound0: "isnpolyh p n0 \<Longrightarrow> polybound0 (head p)"
   938 lemma head_polybound0: "isnpolyh p n0 \<Longrightarrow> polybound0 (head p)"
   922   shows "Ipoly (b # bs) (polysubst0 a t) = Ipoly ((Ipoly (b' # bs) a) # bs) t"
   952   shows "Ipoly (b # bs) (polysubst0 a t) = Ipoly ((Ipoly (b' # bs) a) # bs) t"
   923   by (induct t) (simp_all add: polybound0_I[OF nb, where b="b" and b'="b'"])
   953   by (induct t) (simp_all add: polybound0_I[OF nb, where b="b" and b'="b'"])
   924 
   954 
   925 lemma decrpoly:
   955 lemma decrpoly:
   926   assumes nb: "polybound0 t"
   956   assumes nb: "polybound0 t"
   927   shows "Ipoly (x#bs) t = Ipoly bs (decrpoly t)"
   957   shows "Ipoly (x # bs) t = Ipoly bs (decrpoly t)"
   928   using nb by (induct t rule: decrpoly.induct) simp_all
   958   using nb by (induct t rule: decrpoly.induct) simp_all
   929 
   959 
   930 lemma polysubst0_polybound0:
   960 lemma polysubst0_polybound0:
   931   assumes nb: "polybound0 t"
   961   assumes nb: "polybound0 t"
   932   shows "polybound0 (polysubst0 t a)"
   962   shows "polybound0 (polysubst0 t a)"
   933   using nb by (induct a rule: poly.induct) auto
   963   using nb by (induct a rule: poly.induct) auto
   934 
   964 
   935 lemma degree0_polybound0: "isnpolyh p n \<Longrightarrow> degree p = 0 \<Longrightarrow> polybound0 p"
   965 lemma degree0_polybound0: "isnpolyh p n \<Longrightarrow> degree p = 0 \<Longrightarrow> polybound0 p"
   936   by (induct p arbitrary: n rule: degree.induct) (auto simp add: isnpolyh_polybound0)
   966   by (induct p arbitrary: n rule: degree.induct) (auto simp add: isnpolyh_polybound0)
   937 
   967 
   938 primrec maxindex :: "poly \<Rightarrow> nat" where
   968 primrec maxindex :: "poly \<Rightarrow> nat"
       
   969 where
   939   "maxindex (Bound n) = n + 1"
   970   "maxindex (Bound n) = n + 1"
   940 | "maxindex (CN c n p) = max  (n + 1) (max (maxindex c) (maxindex p))"
   971 | "maxindex (CN c n p) = max  (n + 1) (max (maxindex c) (maxindex p))"
   941 | "maxindex (Add p q) = max (maxindex p) (maxindex q)"
   972 | "maxindex (Add p q) = max (maxindex p) (maxindex q)"
   942 | "maxindex (Sub p q) = max (maxindex p) (maxindex q)"
   973 | "maxindex (Sub p q) = max (maxindex p) (maxindex q)"
   943 | "maxindex (Mul p q) = max (maxindex p) (maxindex q)"
   974 | "maxindex (Mul p q) = max (maxindex p) (maxindex q)"
   946 | "maxindex (C x) = 0"
   977 | "maxindex (C x) = 0"
   947 
   978 
   948 definition wf_bs :: "'a list \<Rightarrow> poly \<Rightarrow> bool"
   979 definition wf_bs :: "'a list \<Rightarrow> poly \<Rightarrow> bool"
   949   where "wf_bs bs p \<longleftrightarrow> length bs \<ge> maxindex p"
   980   where "wf_bs bs p \<longleftrightarrow> length bs \<ge> maxindex p"
   950 
   981 
   951 lemma wf_bs_coefficients: "wf_bs bs p \<Longrightarrow> \<forall> c \<in> set (coefficients p). wf_bs bs c"
   982 lemma wf_bs_coefficients: "wf_bs bs p \<Longrightarrow> \<forall>c \<in> set (coefficients p). wf_bs bs c"
   952 proof (induct p rule: coefficients.induct)
   983 proof (induct p rule: coefficients.induct)
   953   case (1 c p)
   984   case (1 c p)
   954   show ?case
   985   show ?case
   955   proof
   986   proof
   956     fix x
   987     fix x
   959       by simp
   990       by simp
   960     moreover
   991     moreover
   961     {
   992     {
   962       assume "x = c"
   993       assume "x = c"
   963       then have "wf_bs bs x"
   994       then have "wf_bs bs x"
   964         using "1.prems"  unfolding wf_bs_def by simp
   995         using "1.prems" unfolding wf_bs_def by simp
   965     }
   996     }
   966     moreover
   997     moreover
   967     {
   998     {
   968       assume H: "x \<in> set (coefficients p)"
   999       assume H: "x \<in> set (coefficients p)"
   969       from "1.prems" have "wf_bs bs p"
  1000       from "1.prems" have "wf_bs bs p"
   974     ultimately  show "wf_bs bs x"
  1005     ultimately  show "wf_bs bs x"
   975       by blast
  1006       by blast
   976   qed
  1007   qed
   977 qed simp_all
  1008 qed simp_all
   978 
  1009 
   979 lemma maxindex_coefficients: "\<forall>c\<in> set (coefficients p). maxindex c \<le> maxindex p"
  1010 lemma maxindex_coefficients: "\<forall>c \<in> set (coefficients p). maxindex c \<le> maxindex p"
   980   by (induct p rule: coefficients.induct) auto
  1011   by (induct p rule: coefficients.induct) auto
   981 
  1012 
   982 lemma wf_bs_I: "wf_bs bs p \<Longrightarrow> Ipoly (bs @ bs') p = Ipoly bs p"
  1013 lemma wf_bs_I: "wf_bs bs p \<Longrightarrow> Ipoly (bs @ bs') p = Ipoly bs p"
   983   unfolding wf_bs_def by (induct p) (auto simp add: nth_append)
  1014   unfolding wf_bs_def by (induct p) (auto simp add: nth_append)
   984 
  1015 
   990   let ?tbs = "take ?ip bs"
  1021   let ?tbs = "take ?ip bs"
   991   from wf have "length ?tbs = ?ip"
  1022   from wf have "length ?tbs = ?ip"
   992     unfolding wf_bs_def by simp
  1023     unfolding wf_bs_def by simp
   993   then have wf': "wf_bs ?tbs p"
  1024   then have wf': "wf_bs ?tbs p"
   994     unfolding wf_bs_def by  simp
  1025     unfolding wf_bs_def by  simp
   995   have eq: "bs = ?tbs @ (drop ?ip bs)"
  1026   have eq: "bs = ?tbs @ drop ?ip bs"
   996     by simp
  1027     by simp
   997   from wf_bs_I[OF wf', of "drop ?ip bs"] show ?thesis
  1028   from wf_bs_I[OF wf', of "drop ?ip bs"] show ?thesis
   998     using eq by simp
  1029     using eq by simp
   999 qed
  1030 qed
  1000 
  1031 
  1005   unfolding wf_bs_def by simp
  1036   unfolding wf_bs_def by simp
  1006 
  1037 
  1007 lemma wf_bs_insensitive': "wf_bs (x#bs) p = wf_bs (y#bs) p"
  1038 lemma wf_bs_insensitive': "wf_bs (x#bs) p = wf_bs (y#bs) p"
  1008   unfolding wf_bs_def by simp
  1039   unfolding wf_bs_def by simp
  1009 
  1040 
  1010 
       
  1011 
       
  1012 lemma wf_bs_coefficients': "\<forall>c \<in> set (coefficients p). wf_bs bs c \<Longrightarrow> wf_bs (x#bs) p"
  1041 lemma wf_bs_coefficients': "\<forall>c \<in> set (coefficients p). wf_bs bs c \<Longrightarrow> wf_bs (x#bs) p"
  1013   by (induct p rule: coefficients.induct) (auto simp add: wf_bs_def)
  1042   by (induct p rule: coefficients.induct) (auto simp add: wf_bs_def)
       
  1043 
  1014 lemma coefficients_Nil[simp]: "coefficients p \<noteq> []"
  1044 lemma coefficients_Nil[simp]: "coefficients p \<noteq> []"
  1015   by (induct p rule: coefficients.induct) simp_all
  1045   by (induct p rule: coefficients.induct) simp_all
  1016 
  1046 
  1017 
       
  1018 lemma coefficients_head: "last (coefficients p) = head p"
  1047 lemma coefficients_head: "last (coefficients p) = head p"
  1019   by (induct p rule: coefficients.induct) auto
  1048   by (induct p rule: coefficients.induct) auto
  1020 
  1049 
  1021 lemma wf_bs_decrpoly: "wf_bs bs (decrpoly p) \<Longrightarrow> wf_bs (x#bs) p"
  1050 lemma wf_bs_decrpoly: "wf_bs bs (decrpoly p) \<Longrightarrow> wf_bs (x#bs) p"
  1022   unfolding wf_bs_def by (induct p rule: decrpoly.induct) auto
  1051   unfolding wf_bs_def by (induct p rule: decrpoly.induct) auto
  1023 
  1052 
  1024 lemma length_le_list_ex: "length xs \<le> n \<Longrightarrow> \<exists> ys. length (xs @ ys) = n"
  1053 lemma length_le_list_ex: "length xs \<le> n \<Longrightarrow> \<exists>ys. length (xs @ ys) = n"
  1025   apply (rule exI[where x="replicate (n - length xs) z"])
  1054   apply (rule exI[where x="replicate (n - length xs) z"])
  1026   apply simp
  1055   apply simp
  1027   done
  1056   done
  1028 
  1057 
  1029 lemma isnpolyh_Suc_const:"isnpolyh p (Suc n) \<Longrightarrow> isconstant p"
  1058 lemma isnpolyh_Suc_const: "isnpolyh p (Suc n) \<Longrightarrow> isconstant p"
  1030   apply (cases p)
  1059   apply (cases p)
  1031   apply auto
  1060   apply auto
  1032   apply (case_tac "nat")
  1061   apply (case_tac "nat")
  1033   apply simp_all
  1062   apply simp_all
  1034   done
  1063   done
  1050 
  1079 
  1051 lemma wf_bs_polyneg: "wf_bs bs p \<Longrightarrow> wf_bs bs (~\<^sub>p p)"
  1080 lemma wf_bs_polyneg: "wf_bs bs p \<Longrightarrow> wf_bs bs (~\<^sub>p p)"
  1052   unfolding wf_bs_def by (induct p rule: polyneg.induct) auto
  1081   unfolding wf_bs_def by (induct p rule: polyneg.induct) auto
  1053 
  1082 
  1054 lemma wf_bs_polysub: "wf_bs bs p \<Longrightarrow> wf_bs bs q \<Longrightarrow> wf_bs bs (p -\<^sub>p q)"
  1083 lemma wf_bs_polysub: "wf_bs bs p \<Longrightarrow> wf_bs bs q \<Longrightarrow> wf_bs bs (p -\<^sub>p q)"
  1055   unfolding polysub_def split_def fst_conv snd_conv using wf_bs_polyadd wf_bs_polyneg by blast
  1084   unfolding polysub_def split_def fst_conv snd_conv
  1056 
  1085   using wf_bs_polyadd wf_bs_polyneg by blast
  1057 
  1086 
  1058 subsection{* Canonicity of polynomial representation, see lemma isnpolyh_unique*}
  1087 
       
  1088 subsection {* Canonicity of polynomial representation, see lemma isnpolyh_unique *}
  1059 
  1089 
  1060 definition "polypoly bs p = map (Ipoly bs) (coefficients p)"
  1090 definition "polypoly bs p = map (Ipoly bs) (coefficients p)"
  1061 definition "polypoly' bs p = map ((Ipoly bs o decrpoly)) (coefficients p)"
  1091 definition "polypoly' bs p = map (Ipoly bs \<circ> decrpoly) (coefficients p)"
  1062 definition "poly_nate bs p = map ((Ipoly bs o decrpoly)) (coefficients (polynate p))"
  1092 definition "poly_nate bs p = map (Ipoly bs \<circ> decrpoly) (coefficients (polynate p))"
  1063 
  1093 
  1064 lemma coefficients_normh: "isnpolyh p n0 \<Longrightarrow> \<forall> q \<in> set (coefficients p). isnpolyh q n0"
  1094 lemma coefficients_normh: "isnpolyh p n0 \<Longrightarrow> \<forall>q \<in> set (coefficients p). isnpolyh q n0"
  1065 proof (induct p arbitrary: n0 rule: coefficients.induct)
  1095 proof (induct p arbitrary: n0 rule: coefficients.induct)
  1066   case (1 c p n0)
  1096   case (1 c p n0)
  1067   have cp: "isnpolyh (CN c 0 p) n0"
  1097   have cp: "isnpolyh (CN c 0 p) n0"
  1068     by fact
  1098     by fact
  1069   then have norm: "isnpolyh c 0" "isnpolyh p 0" "p \<noteq> 0\<^sub>p" "n0 = 0"
  1099   then have norm: "isnpolyh c 0" "isnpolyh p 0" "p \<noteq> 0\<^sub>p" "n0 = 0"
  1070     by (auto simp add: isnpolyh_mono[where n'=0])
  1100     by (auto simp add: isnpolyh_mono[where n'=0])
  1071   from "1.hyps"[OF norm(2)] norm(1) norm(4) show ?case
  1101   from "1.hyps"[OF norm(2)] norm(1) norm(4) show ?case
  1072     by simp
  1102     by simp
  1073 qed auto
  1103 qed auto
  1074 
  1104 
  1075 lemma coefficients_isconst:
  1105 lemma coefficients_isconst: "isnpolyh p n \<Longrightarrow> \<forall>q \<in> set (coefficients p). isconstant q"
  1076   "isnpolyh p n \<Longrightarrow> \<forall>q\<in>set (coefficients p). isconstant q"
  1106   by (induct p arbitrary: n rule: coefficients.induct) (auto simp add: isnpolyh_Suc_const)
  1077   by (induct p arbitrary: n rule: coefficients.induct)
       
  1078     (auto simp add: isnpolyh_Suc_const)
       
  1079 
  1107 
  1080 lemma polypoly_polypoly':
  1108 lemma polypoly_polypoly':
  1081   assumes np: "isnpolyh p n0"
  1109   assumes np: "isnpolyh p n0"
  1082   shows "polypoly (x#bs) p = polypoly' bs p"
  1110   shows "polypoly (x # bs) p = polypoly' bs p"
  1083 proof-
  1111 proof -
  1084   let ?cf = "set (coefficients p)"
  1112   let ?cf = "set (coefficients p)"
  1085   from coefficients_normh[OF np] have cn_norm: "\<forall> q\<in> ?cf. isnpolyh q n0" .
  1113   from coefficients_normh[OF np] have cn_norm: "\<forall> q\<in> ?cf. isnpolyh q n0" .
  1086   {fix q assume q: "q \<in> ?cf"
  1114   {
  1087     from q cn_norm have th: "isnpolyh q n0" by blast
  1115     fix q
  1088     from coefficients_isconst[OF np] q have "isconstant q" by blast
  1116     assume q: "q \<in> ?cf"
  1089     with isconstant_polybound0[OF th] have "polybound0 q" by blast}
  1117     from q cn_norm have th: "isnpolyh q n0"
       
  1118       by blast
       
  1119     from coefficients_isconst[OF np] q have "isconstant q"
       
  1120       by blast
       
  1121     with isconstant_polybound0[OF th] have "polybound0 q"
       
  1122       by blast
       
  1123   }
  1090   then have "\<forall>q \<in> ?cf. polybound0 q" ..
  1124   then have "\<forall>q \<in> ?cf. polybound0 q" ..
  1091   then have "\<forall>q \<in> ?cf. Ipoly (x#bs) q = Ipoly bs (decrpoly q)"
  1125   then have "\<forall>q \<in> ?cf. Ipoly (x # bs) q = Ipoly bs (decrpoly q)"
  1092     using polybound0_I[where b=x and bs=bs and b'=y] decrpoly[where x=x and bs=bs]
  1126     using polybound0_I[where b=x and bs=bs and b'=y] decrpoly[where x=x and bs=bs]
  1093     by auto
  1127     by auto
  1094   then show ?thesis unfolding polypoly_def polypoly'_def by simp
  1128   then show ?thesis
       
  1129     unfolding polypoly_def polypoly'_def by simp
  1095 qed
  1130 qed
  1096 
  1131 
  1097 lemma polypoly_poly:
  1132 lemma polypoly_poly:
  1098   assumes np: "isnpolyh p n0"
  1133   assumes "isnpolyh p n0"
  1099   shows "Ipoly (x#bs) p = poly (polypoly (x#bs) p) x"
  1134   shows "Ipoly (x # bs) p = poly (polypoly (x # bs) p) x"
  1100   using np
  1135   using assms
  1101   by (induct p arbitrary: n0 bs rule: coefficients.induct) (auto simp add: polypoly_def)
  1136   by (induct p arbitrary: n0 bs rule: coefficients.induct) (auto simp add: polypoly_def)
  1102 
  1137 
  1103 lemma polypoly'_poly:
  1138 lemma polypoly'_poly:
  1104   assumes np: "isnpolyh p n0"
  1139   assumes "isnpolyh p n0"
  1105   shows "\<lparr>p\<rparr>\<^sub>p\<^bsup>x # bs\<^esup> = poly (polypoly' bs p) x"
  1140   shows "\<lparr>p\<rparr>\<^sub>p\<^bsup>x # bs\<^esup> = poly (polypoly' bs p) x"
  1106   using polypoly_poly[OF np, simplified polypoly_polypoly'[OF np]] .
  1141   using polypoly_poly[OF assms, simplified polypoly_polypoly'[OF assms]] .
  1107 
  1142 
  1108 
  1143 
  1109 lemma polypoly_poly_polybound0:
  1144 lemma polypoly_poly_polybound0:
  1110   assumes np: "isnpolyh p n0" and nb: "polybound0 p"
  1145   assumes "isnpolyh p n0"
       
  1146     and "polybound0 p"
  1111   shows "polypoly bs p = [Ipoly bs p]"
  1147   shows "polypoly bs p = [Ipoly bs p]"
  1112   using np nb unfolding polypoly_def
  1148   using assms
       
  1149   unfolding polypoly_def
  1113   apply (cases p)
  1150   apply (cases p)
  1114   apply auto
  1151   apply auto
  1115   apply (case_tac nat)
  1152   apply (case_tac nat)
  1116   apply auto
  1153   apply auto
  1117   done
  1154   done
  1118 
  1155 
  1119 lemma head_isnpolyh: "isnpolyh p n0 \<Longrightarrow> isnpolyh (head p) n0"
  1156 lemma head_isnpolyh: "isnpolyh p n0 \<Longrightarrow> isnpolyh (head p) n0"
  1120   by (induct p rule: head.induct) auto
  1157   by (induct p rule: head.induct) auto
  1121 
  1158 
  1122 lemma headn_nz[simp]: "isnpolyh p n0 \<Longrightarrow> (headn p m = 0\<^sub>p) = (p = 0\<^sub>p)"
  1159 lemma headn_nz[simp]: "isnpolyh p n0 \<Longrightarrow> headn p m = 0\<^sub>p \<longleftrightarrow> p = 0\<^sub>p"
  1123   by (cases p) auto
  1160   by (cases p) auto
  1124 
  1161 
  1125 lemma head_eq_headn0: "head p = headn p 0"
  1162 lemma head_eq_headn0: "head p = headn p 0"
  1126   by (induct p rule: head.induct) simp_all
  1163   by (induct p rule: head.induct) simp_all
  1127 
  1164 
  1128 lemma head_nz[simp]: "isnpolyh p n0 \<Longrightarrow> (head p = 0\<^sub>p) = (p = 0\<^sub>p)"
  1165 lemma head_nz[simp]: "isnpolyh p n0 \<Longrightarrow> head p = 0\<^sub>p \<longleftrightarrow> p = 0\<^sub>p"
  1129   by (simp add: head_eq_headn0)
  1166   by (simp add: head_eq_headn0)
  1130 
  1167 
  1131 lemma isnpolyh_zero_iff:
  1168 lemma isnpolyh_zero_iff:
  1132   assumes nq: "isnpolyh p n0"
  1169   assumes nq: "isnpolyh p n0"
  1133     and eq :"\<forall>bs. wf_bs bs p \<longrightarrow> \<lparr>p\<rparr>\<^sub>p\<^bsup>bs\<^esup> = (0::'a::{field_char_0,field_inverse_zero, power})"
  1170     and eq :"\<forall>bs. wf_bs bs p \<longrightarrow> \<lparr>p\<rparr>\<^sub>p\<^bsup>bs\<^esup> = (0::'a::{field_char_0,field_inverse_zero, power})"
  1267 lemma polymul_commute:
  1304 lemma polymul_commute:
  1268   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
  1305   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
  1269     and np: "isnpolyh p n0"
  1306     and np: "isnpolyh p n0"
  1270     and nq: "isnpolyh q n1"
  1307     and nq: "isnpolyh q n1"
  1271   shows "p *\<^sub>p q = q *\<^sub>p p"
  1308   shows "p *\<^sub>p q = q *\<^sub>p p"
  1272   using isnpolyh_unique[OF polymul_normh[OF np nq] polymul_normh[OF nq np], where ?'a = "'a::{field_char_0,field_inverse_zero, power}"]
  1309   using isnpolyh_unique[OF polymul_normh[OF np nq] polymul_normh[OF nq np],
       
  1310     where ?'a = "'a::{field_char_0,field_inverse_zero, power}"]
  1273   by simp
  1311   by simp
  1274 
  1312 
  1275 declare polyneg_polyneg [simp]
  1313 declare polyneg_polyneg [simp]
  1276 
  1314 
  1277 lemma isnpolyh_polynate_id [simp]:
  1315 lemma isnpolyh_polynate_id [simp]:
  1278   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
  1316   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
  1279     and np: "isnpolyh p n0"
  1317     and np: "isnpolyh p n0"
  1280   shows "polynate p = p"
  1318   shows "polynate p = p"
  1281   using isnpolyh_unique[where ?'a= "'a::{field_char_0,field_inverse_zero}", OF polynate_norm[of p, unfolded isnpoly_def] np] polynate[where ?'a = "'a::{field_char_0,field_inverse_zero}"]
  1319   using isnpolyh_unique[where ?'a= "'a::{field_char_0,field_inverse_zero}",
       
  1320       OF polynate_norm[of p, unfolded isnpoly_def] np]
       
  1321     polynate[where ?'a = "'a::{field_char_0,field_inverse_zero}"]
  1282   by simp
  1322   by simp
  1283 
  1323 
  1284 lemma polynate_idempotent[simp]:
  1324 lemma polynate_idempotent[simp]:
  1285   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
  1325   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
  1286   shows "polynate (polynate p) = polynate p"
  1326   shows "polynate (polynate p) = polynate p"
  1299 
  1339 
  1300 lemma degree_eq_degreen0: "degree p = degreen p 0"
  1340 lemma degree_eq_degreen0: "degree p = degreen p 0"
  1301   by (induct p rule: degree.induct) simp_all
  1341   by (induct p rule: degree.induct) simp_all
  1302 
  1342 
  1303 lemma degree_polyneg:
  1343 lemma degree_polyneg:
  1304   assumes n: "isnpolyh p n"
  1344   assumes "isnpolyh p n"
  1305   shows "degree (polyneg p) = degree p"
  1345   shows "degree (polyneg p) = degree p"
  1306   apply (induct p arbitrary: n rule: polyneg.induct)
  1346   apply (induct p rule: polyneg.induct)
  1307   using n apply simp_all
  1347   using assms
       
  1348   apply simp_all
  1308   apply (case_tac na)
  1349   apply (case_tac na)
  1309   apply auto
  1350   apply auto
  1310   done
  1351   done
  1311 
  1352 
  1312 lemma degree_polyadd:
  1353 lemma degree_polyadd:
  1313   assumes np: "isnpolyh p n0" and nq: "isnpolyh q n1"
  1354   assumes np: "isnpolyh p n0"
       
  1355     and nq: "isnpolyh q n1"
  1314   shows "degree (p +\<^sub>p q) \<le> max (degree p) (degree q)"
  1356   shows "degree (p +\<^sub>p q) \<le> max (degree p) (degree q)"
  1315   using degreen_polyadd[OF np nq, where m= "0"] degree_eq_degreen0 by simp
  1357   using degreen_polyadd[OF np nq, where m= "0"] degree_eq_degreen0 by simp
  1316 
  1358 
  1317 
  1359 
  1318 lemma degree_polysub:
  1360 lemma degree_polysub:
  1319   assumes np: "isnpolyh p n0"
  1361   assumes np: "isnpolyh p n0"
  1320     and nq: "isnpolyh q n1"
  1362     and nq: "isnpolyh q n1"
  1321   shows "degree (p -\<^sub>p q) \<le> max (degree p) (degree q)"
  1363   shows "degree (p -\<^sub>p q) \<le> max (degree p) (degree q)"
  1322 proof-
  1364 proof-
  1323   from nq have nq': "isnpolyh (~\<^sub>p q) n1" using polyneg_normh by simp
  1365   from nq have nq': "isnpolyh (~\<^sub>p q) n1"
  1324   from degree_polyadd[OF np nq'] show ?thesis by (simp add: polysub_def degree_polyneg[OF nq])
  1366     using polyneg_normh by simp
       
  1367   from degree_polyadd[OF np nq'] show ?thesis
       
  1368     by (simp add: polysub_def degree_polyneg[OF nq])
  1325 qed
  1369 qed
  1326 
  1370 
  1327 lemma degree_polysub_samehead:
  1371 lemma degree_polysub_samehead:
  1328   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
  1372   assumes "SORT_CONSTRAINT('a::{field_char_0,field_inverse_zero})"
  1329     and np: "isnpolyh p n0" and nq: "isnpolyh q n1" and h: "head p = head q"
  1373     and np: "isnpolyh p n0"
       
  1374     and nq: "isnpolyh q n1"
       
  1375     and h: "head p = head q"
  1330     and d: "degree p = degree q"
  1376     and d: "degree p = degree q"
  1331   shows "degree (p -\<^sub>p q) < degree p \<or> (p -\<^sub>p q = 0\<^sub>p)"
  1377   shows "degree (p -\<^sub>p q) < degree p \<or> (p -\<^sub>p q = 0\<^sub>p)"
  1332   unfolding polysub_def split_def fst_conv snd_conv
  1378   unfolding polysub_def split_def fst_conv snd_conv
  1333   using np nq h d
  1379   using np nq h d
  1334 proof (induct p q rule: polyadd.induct)
  1380 proof (induct p q rule: polyadd.induct)