merged
authorwenzelm
Mon, 24 Feb 2014 22:41:08 +0100
changeset 55729 3244957ca236
parent 55724 7572fc374f80 (diff)
parent 55728 aaf024d63b35 (current diff)
child 55730 97ff9276e12d
merged
--- a/src/HOL/Fields.thy	Mon Feb 24 20:42:08 2014 +0100
+++ b/src/HOL/Fields.thy	Mon Feb 24 22:41:08 2014 +0100
@@ -1156,6 +1156,12 @@
   apply (simp add: order_less_imp_le)
 done
 
+lemma zero_le_divide_abs_iff [simp]: "(0 \<le> a / abs b) = (0 \<le> a | b = 0)" 
+by (auto simp: zero_le_divide_iff)
+
+lemma divide_le_0_abs_iff [simp]: "(a / abs b \<le> 0) = (a \<le> 0 | b = 0)" 
+by (auto simp: divide_le_0_iff)
+
 lemma field_le_mult_one_interval:
   assumes *: "\<And>z. \<lbrakk> 0 < z ; z < 1 \<rbrakk> \<Longrightarrow> z * x \<le> y"
   shows "x \<le> y"
--- a/src/HOL/Power.thy	Mon Feb 24 20:42:08 2014 +0100
+++ b/src/HOL/Power.thy	Mon Feb 24 22:41:08 2014 +0100
@@ -610,6 +610,11 @@
 
 subsection {* Miscellaneous rules *}
 
+lemma self_le_power:
+  fixes x::"'a::linordered_semidom" 
+  shows "1 \<le> x \<Longrightarrow> 0 < n \<Longrightarrow> x \<le> x ^ n"
+  by (metis gr_implies_not0 le_eq_less_or_eq less_one nat_le_linear power_increasing power_one_right)
+
 lemma power_eq_if: "p ^ m = (if m=0 then 1 else p * (p ^ (m - 1)))"
   unfolding One_nat_def by (cases m) simp_all
 
--- a/src/HOL/Real_Vector_Spaces.thy	Mon Feb 24 20:42:08 2014 +0100
+++ b/src/HOL/Real_Vector_Spaces.thy	Mon Feb 24 22:41:08 2014 +0100
@@ -385,7 +385,7 @@
 apply (erule nonzero_of_real_inverse [symmetric])
 done
 
-lemma Reals_inverse [simp]:
+lemma Reals_inverse:
   fixes a :: "'a::{real_div_algebra, division_ring_inverse_zero}"
   shows "a \<in> Reals \<Longrightarrow> inverse a \<in> Reals"
 apply (auto simp add: Reals_def)
@@ -393,6 +393,11 @@
 apply (rule of_real_inverse [symmetric])
 done
 
+lemma Reals_inverse_iff [simp]: 
+  fixes x:: "'a :: {real_div_algebra, division_ring_inverse_zero}"
+  shows "inverse x \<in> \<real> \<longleftrightarrow> x \<in> \<real>"
+by (metis Reals_inverse inverse_inverse_eq)
+
 lemma nonzero_Reals_divide:
   fixes a b :: "'a::real_field"
   shows "\<lbrakk>a \<in> Reals; b \<in> Reals; b \<noteq> 0\<rbrakk> \<Longrightarrow> a / b \<in> Reals"
@@ -427,6 +432,24 @@
   then show thesis ..
 qed
 
+lemma setsum_in_Reals: assumes "\<And>i. i \<in> s \<Longrightarrow> f i \<in> \<real>" shows "setsum f s \<in> \<real>"
+proof (cases "finite s")
+  case True then show ?thesis using assms
+    by (induct s rule: finite_induct) auto
+next
+  case False then show ?thesis using assms
+    by (metis Reals_0 setsum_infinite)
+qed
+
+lemma setprod_in_Reals: assumes "\<And>i. i \<in> s \<Longrightarrow> f i \<in> \<real>" shows "setprod f s \<in> \<real>"
+proof (cases "finite s")
+  case True then show ?thesis using assms
+    by (induct s rule: finite_induct) auto
+next
+  case False then show ?thesis using assms
+    by (metis Reals_1 setprod_infinite)
+qed
+
 lemma Reals_induct [case_names of_real, induct set: Reals]:
   "q \<in> \<real> \<Longrightarrow> (\<And>r. P (of_real r)) \<Longrightarrow> P q"
   by (rule Reals_cases) auto
@@ -719,6 +742,11 @@
   finally show ?thesis .
 qed
 
+lemma norm_triangle_mono: 
+  fixes a b :: "'a::real_normed_vector"
+  shows "\<lbrakk>norm a \<le> r; norm b \<le> s\<rbrakk> \<Longrightarrow> norm (a + b) \<le> r + s"
+by (metis add_mono_thms_linordered_semiring(1) norm_triangle_ineq order.trans)
+
 lemma abs_norm_cancel [simp]:
   fixes a :: "'a::real_normed_vector"
   shows "\<bar>norm a\<bar> = norm a"
@@ -802,6 +830,17 @@
   shows "norm (x ^ n) = norm x ^ n"
 by (induct n) (simp_all add: norm_mult)
 
+lemma setprod_norm:
+  fixes f :: "'a \<Rightarrow> 'b::{comm_semiring_1,real_normed_div_algebra}"
+  shows "setprod (\<lambda>x. norm(f x)) A = norm (setprod f A)"
+proof (cases "finite A")
+  case True then show ?thesis 
+    by (induct A rule: finite_induct) (auto simp: norm_mult)
+next
+  case False then show ?thesis
+    by (metis norm_one setprod.infinite) 
+qed
+
 
 subsection {* Metric spaces *}
 
--- a/src/HOL/Set_Interval.thy	Mon Feb 24 20:42:08 2014 +0100
+++ b/src/HOL/Set_Interval.thy	Mon Feb 24 22:41:08 2014 +0100
@@ -1459,6 +1459,14 @@
   finally show ?case .
 qed
 
+lemma setsum_last_plus: "n \<noteq> 0 \<Longrightarrow> (\<Sum>i = 0..n. f i) = f n + (\<Sum>i = 0..n - Suc 0. f i)"
+  using atLeastAtMostSuc_conv [of 0 "n - 1"]
+  by auto
+
+lemma nested_setsum_swap:
+     "(\<Sum>i = 0..n. (\<Sum>j = 0..<i. a i j)) = (\<Sum>j = 0..<n. \<Sum>i = Suc j..n. a i j)"
+  by (induction n) (auto simp: setsum_addf)
+
 
 subsection {* The formula for geometric sums *}
 
@@ -1565,6 +1573,14 @@
   show ?case by simp
 qed
 
+lemma nat_diff_setsum_reindex:
+  fixes x :: "'a::{comm_ring,monoid_mult}"
+  shows "(\<Sum>i=0..<n. f (n - Suc i)) = (\<Sum>i=0..<n. f i)"
+apply (subst setsum_reindex_cong [of "%i. n - Suc i" "{0..< n}"])
+apply (auto simp: inj_on_def)
+apply (rule_tac x="n - Suc x" in image_eqI, auto)
+done
+
 subsection {* Products indexed over intervals *}
 
 syntax
@@ -1649,4 +1665,15 @@
     by auto
 qed
 
+lemma setprod_power_distrib:
+  fixes f :: "'a \<Rightarrow> 'b::comm_semiring_1"
+  shows "setprod f A ^ n = setprod (\<lambda>x. (f x)^n) A"
+proof (cases "finite A") 
+  case True then show ?thesis 
+    by (induct A rule: finite_induct) (auto simp add: power_mult_distrib)
+next
+  case False then show ?thesis 
+    by (metis setprod_infinite power_one)
+qed
+
 end
--- a/src/HOL/Tools/Lifting/lifting_def.ML	Mon Feb 24 20:42:08 2014 +0100
+++ b/src/HOL/Tools/Lifting/lifting_def.ML	Mon Feb 24 22:41:08 2014 +0100
@@ -265,7 +265,7 @@
     val unabs_def = unabs_all_def ctxt unfolded_def
   in  
     if body_type rty = body_type qty then 
-      SOME (simplify_code_eq ctxt unabs_def)
+      SOME (simplify_code_eq ctxt (unabs_def RS @{thm meta_eq_to_obj_eq}))
     else 
       let
         val thy = Proof_Context.theory_of ctxt
@@ -324,68 +324,74 @@
     simplify_code_eq ctxt abs_eq
   end
 
-fun define_code_using_abs_eq abs_eq_thm lthy =
-  if null (Logic.strip_imp_prems(prop_of abs_eq_thm)) then
-    (snd oo Local_Theory.note) ((Binding.empty, [Code.add_default_eqn_attrib]), [abs_eq_thm]) lthy
-  else
-    lthy
-  
-fun define_code_using_rep_eq opt_rep_eq_thm lthy = 
-  case opt_rep_eq_thm of
-    SOME rep_eq_thm =>   
-      let
-        val add_abs_eqn_attribute = 
-          Thm.declaration_attribute (fn thm => Context.mapping (Code.add_abs_eqn thm) I)
-        val add_abs_eqn_attrib = Attrib.internal (K add_abs_eqn_attribute);
-      in
-        (snd oo Local_Theory.note) ((Binding.empty, [add_abs_eqn_attrib]), [rep_eq_thm]) lthy
-      end
-    | NONE => lthy
 
-fun has_constr ctxt quot_thm =
+fun register_code_eq_thy abs_eq_thm opt_rep_eq_thm (rty, qty) thy =
   let
-    val thy = Proof_Context.theory_of ctxt
-    val abs_fun = quot_thm_abs quot_thm
-  in
-    if is_Const abs_fun then
-      Code.is_constr thy ((fst o dest_Const) abs_fun)
-    else
-      false
-  end
+    fun no_abstr (t $ u) = no_abstr t andalso no_abstr u
+      | no_abstr (Abs (_, _, t)) = no_abstr t
+      | no_abstr (Const (name, _)) = not (Code.is_abstr thy name)
+      | no_abstr _ = true
+    fun is_valid_eq eqn = can (Code.assert_eqn thy) (mk_meta_eq eqn, true) 
+      andalso no_abstr (prop_of eqn)
+    fun is_valid_abs_eq abs_eq = can (Code.assert_abs_eqn thy NONE) (mk_meta_eq abs_eq)
 
-fun has_abstr ctxt quot_thm =
-  let
-    val thy = Proof_Context.theory_of ctxt
-    val abs_fun = quot_thm_abs quot_thm
   in
-    if is_Const abs_fun then
-      Code.is_abstr thy ((fst o dest_Const) abs_fun)
+    if is_valid_eq abs_eq_thm then
+      Code.add_default_eqn abs_eq_thm thy
     else
-      false
-  end
-
-fun define_code abs_eq_thm opt_rep_eq_thm (rty, qty) lthy =
-  let
-    val (rty_body, qty_body) = get_body_types (rty, qty)
-  in
-    if rty_body = qty_body then
-      if null (Logic.strip_imp_prems(prop_of abs_eq_thm)) then
-        (snd oo Local_Theory.note) ((Binding.empty, [Code.add_default_eqn_attrib]), [abs_eq_thm]) lthy
-      else
-        (snd oo Local_Theory.note) ((Binding.empty, [Code.add_default_eqn_attrib]), [the opt_rep_eq_thm]) lthy
-    else
-      let 
-        val body_quot_thm = Lifting_Term.prove_quot_thm lthy (rty_body, qty_body)
+      let
+        val (rty_body, qty_body) = get_body_types (rty, qty)
       in
-        if has_constr lthy body_quot_thm then
-          define_code_using_abs_eq abs_eq_thm lthy
-        else if has_abstr lthy body_quot_thm then
-          define_code_using_rep_eq opt_rep_eq_thm lthy
+        if rty_body = qty_body then
+         Code.add_default_eqn (the opt_rep_eq_thm) thy
         else
-          lthy
+          if is_some opt_rep_eq_thm andalso is_valid_abs_eq (the opt_rep_eq_thm)
+          then
+            Code.add_abs_eqn (the opt_rep_eq_thm) thy
+          else
+            thy
       end
   end
 
+local
+  fun encode_code_eq thy abs_eq opt_rep_eq (rty, qty) = 
+    let
+      fun mk_type typ = typ |> Logic.mk_type |> cterm_of thy |> Drule.mk_term
+    in
+      Conjunction.intr_balanced [abs_eq, (the_default TrueI opt_rep_eq), mk_type rty, mk_type qty]
+    end
+  
+  fun decode_code_eq thm =
+    let
+      val [abs_eq, rep_eq, rty, qty] = Conjunction.elim_balanced 4 thm
+      val opt_rep_eq = if Thm.eq_thm_prop (rep_eq, TrueI) then NONE else SOME rep_eq
+      fun dest_type typ = typ |> Drule.dest_term |> term_of |> Logic.dest_type
+    in
+      (abs_eq, opt_rep_eq, (dest_type rty, dest_type qty)) 
+    end
+  
+  fun register_encoded_code_eq thm thy =
+    let
+      val (abs_eq_thm, opt_rep_eq_thm, (rty, qty)) = decode_code_eq thm
+    in
+      register_code_eq_thy abs_eq_thm opt_rep_eq_thm (rty, qty) thy
+    end
+  
+  val register_code_eq_attribute = Thm.declaration_attribute
+    (fn thm => Context.mapping (register_encoded_code_eq thm) I)
+  val register_code_eq_attrib = Attrib.internal (K register_code_eq_attribute)
+in
+
+fun register_code_eq abs_eq_thm opt_rep_eq_thm (rty, qty) lthy =
+  let
+    val thy = Proof_Context.theory_of lthy
+    val encoded_code_eq = encode_code_eq thy abs_eq_thm opt_rep_eq_thm (rty, qty)
+  in
+    (snd oo Local_Theory.note) ((Binding.empty, [register_code_eq_attrib]), 
+      [encoded_code_eq]) lthy
+  end
+end
+            
 (*
   Defines an operation on an abstract type in terms of a corresponding operation 
     on a representation type.
@@ -434,7 +440,7 @@
       |> (case opt_rep_eq_thm of 
             SOME rep_eq_thm => (snd oo Local_Theory.note) ((rep_eq_thm_name, []), [rep_eq_thm])
             | NONE => I)
-      |> define_code abs_eq_thm opt_rep_eq_thm (rty_forced, qty)
+      |> register_code_eq abs_eq_thm opt_rep_eq_thm (rty_forced, qty)
   end
 
 fun mk_readable_rsp_thm_eq tm lthy =
--- a/src/HOL/Transcendental.thy	Mon Feb 24 20:42:08 2014 +0100
+++ b/src/HOL/Transcendental.thy	Mon Feb 24 22:41:08 2014 +0100
@@ -60,6 +60,23 @@
   apply (metis atLeastLessThan_iff diff_diff_cancel diff_less_Suc imageI le0 less_Suc_eq_le)
   done
 
+lemma power_diff_1_eq:
+  fixes x :: "'a::{comm_ring,monoid_mult}"
+  shows "n \<noteq> 0 \<Longrightarrow> x^n - 1 = (x - 1) * (\<Sum>i=0..<n. (x^i))"
+using lemma_realpow_diff_sumr2 [of x _ 1] 
+  by (cases n) auto
+
+lemma one_diff_power_eq':
+  fixes x :: "'a::{comm_ring,monoid_mult}"
+  shows "n \<noteq> 0 \<Longrightarrow> 1 - x^n = (1 - x) * (\<Sum>i=0..<n. x^(n - Suc i))"
+using lemma_realpow_diff_sumr2 [of 1 _ x] 
+  by (cases n) auto
+
+lemma one_diff_power_eq:
+  fixes x :: "'a::{comm_ring,monoid_mult}"
+  shows "n \<noteq> 0 \<Longrightarrow> 1 - x^n = (1 - x) * (\<Sum>i=0..<n. x^i)"
+by (metis one_diff_power_eq' [of n x] nat_diff_setsum_reindex)
+
 text{*Power series has a `circle` of convergence, i.e. if it sums for @{term
   x}, then it sums absolutely for @{term z} with @{term "\<bar>z\<bar> < \<bar>x\<bar>"}.*}
 
--- a/src/Pure/Isar/code.ML	Mon Feb 24 20:42:08 2014 +0100
+++ b/src/Pure/Isar/code.ML	Mon Feb 24 22:41:08 2014 +0100
@@ -24,6 +24,7 @@
   val mk_eqn: theory -> thm * bool -> thm * bool
   val mk_eqn_liberal: theory -> thm -> (thm * bool) option
   val assert_eqn: theory -> thm * bool -> thm * bool
+  val assert_abs_eqn: theory -> string option -> thm -> thm * string
   val const_typ_eqn: theory -> thm -> string * typ
   val expand_eta: theory -> int -> thm -> thm
   type cert
@@ -47,6 +48,8 @@
   val add_eqn: thm -> theory -> theory
   val add_nbe_eqn: thm -> theory -> theory
   val add_abs_eqn: thm -> theory -> theory
+  val add_abs_eqn_attribute: attribute
+  val add_abs_eqn_attrib: Attrib.src
   val add_default_eqn: thm -> theory -> theory
   val add_default_eqn_attribute: attribute
   val add_default_eqn_attrib: Attrib.src
@@ -546,7 +549,7 @@
       else error ("Type arguments do not satisfy sort constraints of abstype certificate.");
   in (thm, tyco) end;
 
-fun assert_eqn thy = error_thm (gen_assert_eqn thy true) thy;
+fun assert_eqn thy = gen_assert_eqn thy true;
 
 fun meta_rewrite thy = Local_Defs.meta_rewrite_rule (Proof_Context.init_global thy);
 
@@ -750,7 +753,7 @@
       let
         val thy = Proof_Context.theory_of ctxt;
         val eqns = burrow_fst (canonize_thms thy) raw_eqns;
-        val _ = map (assert_eqn thy) eqns;
+        val _ = map (error_thm (assert_eqn thy) thy) eqns;
         val (thms, propers) = split_list eqns;
         val _ = map (fn thm => if c = const_eqn thy thm then ()
           else error ("Wrong head of code equation,\nexpected constant "
@@ -1121,6 +1124,10 @@
 
 fun add_abs_eqn raw_thm thy = gen_add_abs_eqn (mk_abs_eqn thy raw_thm) thy;
 
+val add_abs_eqn_attribute = Thm.declaration_attribute
+  (fn thm => Context.mapping (add_abs_eqn thm) I);
+val add_abs_eqn_attrib = Attrib.internal (K add_abs_eqn_attribute);
+
 fun add_eqn_maybe_abs thm thy =
   case mk_eqn_maybe_abs thy thm
    of SOME (eqn, NONE) => gen_add_eqn false eqn thy