# HG changeset patch # User immler # Date 1572966129 18000 # Node ID ddd4aefc540f9f121c807711198014d089d199d9 # Parent bd3d4702b4f2998ba6607d5a9dc8a583c70284bf# Parent c1b63124245ca28d52af8273f9caeb8e4ecf4911 merged diff -r c1b63124245c -r ddd4aefc540f src/HOL/Decision_Procs/Approximation.thy --- a/src/HOL/Decision_Procs/Approximation.thy Tue Nov 05 14:57:41 2019 +0100 +++ b/src/HOL/Decision_Procs/Approximation.thy Tue Nov 05 10:02:09 2019 -0500 @@ -73,554 +73,93 @@ subsection "Implement approximation function" -fun lift_bin :: "(float * float) option \ (float * float) option \ (float \ float \ float \ float \ (float * float) option) \ (float * float) option" where -"lift_bin (Some (l1, u1)) (Some (l2, u2)) f = f l1 u1 l2 u2" | +fun lift_bin :: "(float interval) option \ (float interval) option \ (float interval \ float interval \ (float interval) option) \ (float interval) option" where +"lift_bin (Some ivl1) (Some ivl2) f = f ivl1 ivl2" | "lift_bin a b f = None" -fun lift_bin' :: "(float * float) option \ (float * float) option \ (float \ float \ float \ float \ (float * float)) \ (float * float) option" where -"lift_bin' (Some (l1, u1)) (Some (l2, u2)) f = Some (f l1 u1 l2 u2)" | +fun lift_bin' :: "(float interval) option \ (float interval) option \ (float interval \ float interval \ float interval) \ (float interval) option" where +"lift_bin' (Some ivl1) (Some ivl2) f = Some (f ivl1 ivl2)" | "lift_bin' a b f = None" -fun lift_un :: "(float * float) option \ (float \ float \ ((float option) * (float option))) \ (float * float) option" where -"lift_un (Some (l1, u1)) f = (case (f l1 u1) of (Some l, Some u) \ Some (l, u) - | t \ None)" | +fun lift_un :: "float interval option \ (float interval \ float interval option) \ float interval option" where +"lift_un (Some ivl) f = f ivl" | "lift_un b f = None" -fun lift_un' :: "(float * float) option \ (float \ float \ (float * float)) \ (float * float) option" where -"lift_un' (Some (l1, u1)) f = Some (f l1 u1)" | +lemma lift_un_eq:\ \TODO\ "lift_un x f = Option.bind x f" + by (cases x) auto + +fun lift_un' :: "(float interval) option \ (float interval \ (float interval)) \ (float interval) option" where +"lift_un' (Some ivl1) f = Some (f ivl1)" | "lift_un' b f = None" -definition bounded_by :: "real list \ (float \ float) option list \ bool" where - "bounded_by xs vs \ - (\ i < length vs. case vs ! i of None \ True - | Some (l, u) \ xs ! i \ { real_of_float l .. real_of_float u })" - +definition bounded_by :: "real list \ (float interval) option list \ bool" where + "bounded_by xs vs \ (\ i < length vs. case vs ! i of None \ True | Some ivl \ xs ! i \\<^sub>r ivl)" + lemma bounded_byE: assumes "bounded_by xs vs" shows "\ i. i < length vs \ case vs ! i of None \ True - | Some (l, u) \ xs ! i \ { real_of_float l .. real_of_float u }" - using assms bounded_by_def by blast + | Some ivl \ xs ! i \\<^sub>r ivl" + using assms + by (auto simp: bounded_by_def) lemma bounded_by_update: assumes "bounded_by xs vs" - and bnd: "xs ! i \ { real_of_float l .. real_of_float u }" - shows "bounded_by xs (vs[i := Some (l,u)])" -proof - - { - fix j - let ?vs = "vs[i := Some (l,u)]" - assume "j < length ?vs" - hence [simp]: "j < length vs" by simp - have "case ?vs ! j of None \ True | Some (l, u) \ xs ! j \ { real_of_float l .. real_of_float u }" - proof (cases "?vs ! j") - case (Some b) - thus ?thesis - proof (cases "i = j") - case True - thus ?thesis using \?vs ! j = Some b\ and bnd by auto - next - case False - thus ?thesis using \bounded_by xs vs\ unfolding bounded_by_def by auto - qed - qed auto - } - thus ?thesis unfolding bounded_by_def by auto -qed + and bnd: "xs ! i \\<^sub>r ivl" + shows "bounded_by xs (vs[i := Some ivl])" + using assms + by (cases "i < length vs") (auto simp: bounded_by_def nth_list_update split: option.splits) lemma bounded_by_None: "bounded_by xs (replicate (length xs) None)" unfolding bounded_by_def by auto -fun approx approx' :: "nat \ floatarith \ (float * float) option list \ (float * float) option" where -"approx' prec a bs = (case (approx prec a bs) of Some (l, u) \ Some (float_round_down prec l, float_round_up prec u) | None \ None)" | -"approx prec (Add a b) bs = - lift_bin' (approx' prec a bs) (approx' prec b bs) - (\ l1 u1 l2 u2. (float_plus_down prec l1 l2, float_plus_up prec u1 u2))" | -"approx prec (Minus a) bs = lift_un' (approx' prec a bs) (\ l u. (-u, -l))" | -"approx prec (Mult a b) bs = - lift_bin' (approx' prec a bs) (approx' prec b bs) (bnds_mult prec)" | -"approx prec (Inverse a) bs = lift_un (approx' prec a bs) (\ l u. if (0 < l \ u < 0) then (Some (float_divl prec 1 u), Some (float_divr prec 1 l)) else (None, None))" | -"approx prec (Cos a) bs = lift_un' (approx' prec a bs) (bnds_cos prec)" | -"approx prec Pi bs = Some (lb_pi prec, ub_pi prec)" | -"approx prec (Min a b) bs = lift_bin' (approx' prec a bs) (approx' prec b bs) (\ l1 u1 l2 u2. (min l1 l2, min u1 u2))" | -"approx prec (Max a b) bs = lift_bin' (approx' prec a bs) (approx' prec b bs) (\ l1 u1 l2 u2. (max l1 l2, max u1 u2))" | -"approx prec (Abs a) bs = lift_un' (approx' prec a bs) (\l u. (if l < 0 \ 0 < u then 0 else min \l\ \u\, max \l\ \u\))" | -"approx prec (Arctan a) bs = lift_un' (approx' prec a bs) (\ l u. (lb_arctan prec l, ub_arctan prec u))" | -"approx prec (Sqrt a) bs = lift_un' (approx' prec a bs) (\ l u. (lb_sqrt prec l, ub_sqrt prec u))" | -"approx prec (Exp a) bs = lift_un' (approx' prec a bs) (\ l u. (lb_exp prec l, ub_exp prec u))" | -"approx prec (Powr a b) bs = lift_bin (approx' prec a bs) (approx' prec b bs) (bnds_powr prec)" | -"approx prec (Ln a) bs = lift_un (approx' prec a bs) (\ l u. (lb_ln prec l, ub_ln prec u))" | -"approx prec (Power a n) bs = lift_un' (approx' prec a bs) (float_power_bnds prec n)" | -"approx prec (Floor a) bs = lift_un' (approx' prec a bs) (\ l u. (floor_fl l, floor_fl u))" | -"approx prec (Num f) bs = Some (f, f)" | -"approx prec (Var i) bs = (if i < length bs then bs ! i else None)" +fun approx approx' :: "nat \ floatarith \ (float interval) option list \ (float interval) option" + where + "approx' prec a bs = (case (approx prec a bs) of Some ivl \ Some (round_interval prec ivl) | None \ None)" | + "approx prec (Add a b) bs = lift_bin' (approx' prec a bs) (approx' prec b bs) (+)" | + "approx prec (Minus a) bs = lift_un' (approx' prec a bs) uminus" | + "approx prec (Mult a b) bs = lift_bin' (approx' prec a bs) (approx' prec b bs) (mult_float_interval prec)" | + "approx prec (Inverse a) bs = lift_un (approx' prec a bs) (inverse_float_interval prec)" | + "approx prec (Cos a) bs = lift_un' (approx' prec a bs) (cos_float_interval prec)" | + "approx prec Pi bs = Some (pi_float_interval prec)" | + "approx prec (Min a b) bs = lift_bin' (approx' prec a bs) (approx' prec b bs) (min_interval)" | + "approx prec (Max a b) bs = lift_bin' (approx' prec a bs) (approx' prec b bs) (max_interval)" | + "approx prec (Abs a) bs = lift_un' (approx' prec a bs) (abs_interval)" | + "approx prec (Arctan a) bs = lift_un' (approx' prec a bs) (arctan_float_interval prec)" | + "approx prec (Sqrt a) bs = lift_un' (approx' prec a bs) (sqrt_float_interval prec)" | + "approx prec (Exp a) bs = lift_un' (approx' prec a bs) (exp_float_interval prec)" | + "approx prec (Powr a b) bs = lift_bin (approx' prec a bs) (approx' prec b bs) (powr_float_interval prec)" | + "approx prec (Ln a) bs = lift_un (approx' prec a bs) (ln_float_interval prec)" | + "approx prec (Power a n) bs = lift_un' (approx' prec a bs) (power_float_interval prec n)" | + "approx prec (Floor a) bs = lift_un' (approx' prec a bs) (floor_float_interval)" | + "approx prec (Num f) bs = Some (interval_of f)" | + "approx prec (Var i) bs = (if i < length bs then bs ! i else None)" lemma approx_approx': - assumes Pa: "\l u. Some (l, u) = approx prec a vs \ - l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" - and approx': "Some (l, u) = approx' prec a vs" - shows "l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" -proof - - obtain l' u' where S: "Some (l', u') = approx prec a vs" - using approx' unfolding approx'.simps by (cases "approx prec a vs") auto - have l': "l = float_round_down prec l'" and u': "u = float_round_up prec u'" - using approx' unfolding approx'.simps S[symmetric] by auto - show ?thesis unfolding l' u' - using order_trans[OF Pa[OF S, THEN conjunct2] float_round_up[of u']] - using order_trans[OF float_round_down[of _ l'] Pa[OF S, THEN conjunct1]] by auto -qed - -lemma lift_bin_ex: - assumes lift_bin_Some: "Some (l, u) = lift_bin a b f" - shows "\ l1 u1 l2 u2. Some (l1, u1) = a \ Some (l2, u2) = b" -proof (cases a) - case None - hence "None = lift_bin a b f" - unfolding None lift_bin.simps .. - thus ?thesis - using lift_bin_Some by auto -next - case (Some a') - show ?thesis - proof (cases b) - case None - hence "None = lift_bin a b f" - unfolding None lift_bin.simps .. - thus ?thesis using lift_bin_Some by auto - next - case (Some b') - obtain la ua where a': "a' = (la, ua)" - by (cases a') auto - obtain lb ub where b': "b' = (lb, ub)" - by (cases b') auto - thus ?thesis - unfolding \a = Some a'\ \b = Some b'\ a' b' by auto - qed -qed - -lemma lift_bin_f: - assumes lift_bin_Some: "Some (l, u) = lift_bin (g a) (g b) f" - and Pa: "\l u. Some (l, u) = g a \ P l u a" - and Pb: "\l u. Some (l, u) = g b \ P l u b" - shows "\ l1 u1 l2 u2. P l1 u1 a \ P l2 u2 b \ Some (l, u) = f l1 u1 l2 u2" -proof - - obtain l1 u1 l2 u2 - where Sa: "Some (l1, u1) = g a" - and Sb: "Some (l2, u2) = g b" - using lift_bin_ex[OF assms(1)] by auto - have lu: "Some (l, u) = f l1 u1 l2 u2" - using lift_bin_Some[unfolded Sa[symmetric] Sb[symmetric] lift_bin.simps] by auto - thus ?thesis - using Pa[OF Sa] Pb[OF Sb] by auto -qed - -lemma lift_bin: - assumes lift_bin_Some: "Some (l, u) = lift_bin (approx' prec a bs) (approx' prec b bs) f" - and Pa: "\l u. Some (l, u) = approx prec a bs \ - real_of_float l \ interpret_floatarith a xs \ interpret_floatarith a xs \ real_of_float u" (is "\l u. _ = ?g a \ ?P l u a") - and Pb: "\l u. Some (l, u) = approx prec b bs \ - real_of_float l \ interpret_floatarith b xs \ interpret_floatarith b xs \ real_of_float u" - shows "\l1 u1 l2 u2. (real_of_float l1 \ interpret_floatarith a xs \ interpret_floatarith a xs \ real_of_float u1) \ - (real_of_float l2 \ interpret_floatarith b xs \ interpret_floatarith b xs \ real_of_float u2) \ - Some (l, u) = (f l1 u1 l2 u2)" -proof - - { fix l u assume "Some (l, u) = approx' prec a bs" - with approx_approx'[of prec a bs, OF _ this] Pa - have "l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" by auto } note Pa = this - { fix l u assume "Some (l, u) = approx' prec b bs" - with approx_approx'[of prec b bs, OF _ this] Pb - have "l \ interpret_floatarith b xs \ interpret_floatarith b xs \ u" by auto } note Pb = this - - from lift_bin_f[where g="\a. approx' prec a bs" and P = ?P, OF lift_bin_Some, OF Pa Pb] - show ?thesis by auto -qed - -lemma lift_bin'_ex: - assumes lift_bin'_Some: "Some (l, u) = lift_bin' a b f" - shows "\ l1 u1 l2 u2. Some (l1, u1) = a \ Some (l2, u2) = b" -proof (cases a) - case None - hence "None = lift_bin' a b f" - unfolding None lift_bin'.simps .. - thus ?thesis - using lift_bin'_Some by auto -next - case (Some a') - show ?thesis - proof (cases b) - case None - hence "None = lift_bin' a b f" - unfolding None lift_bin'.simps .. - thus ?thesis using lift_bin'_Some by auto - next - case (Some b') - obtain la ua where a': "a' = (la, ua)" - by (cases a') auto - obtain lb ub where b': "b' = (lb, ub)" - by (cases b') auto - thus ?thesis - unfolding \a = Some a'\ \b = Some b'\ a' b' by auto - qed -qed - -lemma lift_bin'_f: - assumes lift_bin'_Some: "Some (l, u) = lift_bin' (g a) (g b) f" - and Pa: "\l u. Some (l, u) = g a \ P l u a" - and Pb: "\l u. Some (l, u) = g b \ P l u b" - shows "\ l1 u1 l2 u2. P l1 u1 a \ P l2 u2 b \ l = fst (f l1 u1 l2 u2) \ u = snd (f l1 u1 l2 u2)" -proof - - obtain l1 u1 l2 u2 - where Sa: "Some (l1, u1) = g a" - and Sb: "Some (l2, u2) = g b" - using lift_bin'_ex[OF assms(1)] by auto - have lu: "(l, u) = f l1 u1 l2 u2" - using lift_bin'_Some[unfolded Sa[symmetric] Sb[symmetric] lift_bin'.simps] by auto - have "l = fst (f l1 u1 l2 u2)" and "u = snd (f l1 u1 l2 u2)" - unfolding lu[symmetric] by auto - thus ?thesis - using Pa[OF Sa] Pb[OF Sb] by auto -qed - -lemma lift_bin': - assumes lift_bin'_Some: "Some (l, u) = lift_bin' (approx' prec a bs) (approx' prec b bs) f" - and Pa: "\l u. Some (l, u) = approx prec a bs \ - l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" (is "\l u. _ = ?g a \ ?P l u a") - and Pb: "\l u. Some (l, u) = approx prec b bs \ - l \ interpret_floatarith b xs \ interpret_floatarith b xs \ u" - shows "\l1 u1 l2 u2. (l1 \ interpret_floatarith a xs \ interpret_floatarith a xs \ u1) \ - (l2 \ interpret_floatarith b xs \ interpret_floatarith b xs \ u2) \ - l = fst (f l1 u1 l2 u2) \ u = snd (f l1 u1 l2 u2)" + assumes Pa: "\ivl. approx prec a vs = Some ivl \ interpret_floatarith a xs \\<^sub>r ivl" + and approx': "approx' prec a vs = Some ivl" + shows "interpret_floatarith a xs \\<^sub>r ivl" proof - - { fix l u assume "Some (l, u) = approx' prec a bs" - with approx_approx'[of prec a bs, OF _ this] Pa - have "l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" by auto } note Pa = this - { fix l u assume "Some (l, u) = approx' prec b bs" - with approx_approx'[of prec b bs, OF _ this] Pb - have "l \ interpret_floatarith b xs \ interpret_floatarith b xs \ u" by auto } note Pb = this - - from lift_bin'_f[where g="\a. approx' prec a bs" and P = ?P, OF lift_bin'_Some, OF Pa Pb] - show ?thesis by auto -qed - -lemma lift_un'_ex: - assumes lift_un'_Some: "Some (l, u) = lift_un' a f" - shows "\ l u. Some (l, u) = a" -proof (cases a) - case None - hence "None = lift_un' a f" - unfolding None lift_un'.simps .. - thus ?thesis - using lift_un'_Some by auto -next - case (Some a') - obtain la ua where a': "a' = (la, ua)" - by (cases a') auto - thus ?thesis - unfolding \a = Some a'\ a' by auto -qed - -lemma lift_un'_f: - assumes lift_un'_Some: "Some (l, u) = lift_un' (g a) f" - and Pa: "\l u. Some (l, u) = g a \ P l u a" - shows "\ l1 u1. P l1 u1 a \ l = fst (f l1 u1) \ u = snd (f l1 u1)" -proof - - obtain l1 u1 where Sa: "Some (l1, u1) = g a" - using lift_un'_ex[OF assms(1)] by auto - have lu: "(l, u) = f l1 u1" - using lift_un'_Some[unfolded Sa[symmetric] lift_un'.simps] by auto - have "l = fst (f l1 u1)" and "u = snd (f l1 u1)" - unfolding lu[symmetric] by auto - thus ?thesis - using Pa[OF Sa] by auto -qed - -lemma lift_un': - assumes lift_un'_Some: "Some (l, u) = lift_un' (approx' prec a bs) f" - and Pa: "\l u. Some (l, u) = approx prec a bs \ - l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" - (is "\l u. _ = ?g a \ ?P l u a") - shows "\l1 u1. (l1 \ interpret_floatarith a xs \ interpret_floatarith a xs \ u1) \ - l = fst (f l1 u1) \ u = snd (f l1 u1)" -proof - - have Pa: "l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" - if "Some (l, u) = approx' prec a bs" for l u - using approx_approx'[of prec a bs, OF _ that] Pa - by auto - from lift_un'_f[where g="\a. approx' prec a bs" and P = ?P, OF lift_un'_Some, OF Pa] - show ?thesis by auto -qed - -lemma lift_un'_bnds: - assumes bnds: "\ (x::real) lx ux. (l, u) = f lx ux \ x \ { lx .. ux } \ l \ f' x \ f' x \ u" - and lift_un'_Some: "Some (l, u) = lift_un' (approx' prec a bs) f" - and Pa: "\l u. Some (l, u) = approx prec a bs \ - l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" - shows "real_of_float l \ f' (interpret_floatarith a xs) \ f' (interpret_floatarith a xs) \ real_of_float u" -proof - - from lift_un'[OF lift_un'_Some Pa] - obtain l1 u1 where "l1 \ interpret_floatarith a xs" - and "interpret_floatarith a xs \ u1" - and "l = fst (f l1 u1)" - and "u = snd (f l1 u1)" - by blast - hence "(l, u) = f l1 u1" and "interpret_floatarith a xs \ {l1 .. u1}" - by auto - thus ?thesis - using bnds by auto -qed - -lemma lift_un_ex: - assumes lift_un_Some: "Some (l, u) = lift_un a f" - shows "\l u. Some (l, u) = a" -proof (cases a) - case None - hence "None = lift_un a f" - unfolding None lift_un.simps .. - thus ?thesis - using lift_un_Some by auto -next - case (Some a') - obtain la ua where a': "a' = (la, ua)" - by (cases a') auto - thus ?thesis - unfolding \a = Some a'\ a' by auto -qed - -lemma lift_un_f: - assumes lift_un_Some: "Some (l, u) = lift_un (g a) f" - and Pa: "\l u. Some (l, u) = g a \ P l u a" - shows "\ l1 u1. P l1 u1 a \ Some l = fst (f l1 u1) \ Some u = snd (f l1 u1)" -proof - - obtain l1 u1 where Sa: "Some (l1, u1) = g a" - using lift_un_ex[OF assms(1)] by auto - have "fst (f l1 u1) \ None \ snd (f l1 u1) \ None" - proof (rule ccontr) - assume "\ (fst (f l1 u1) \ None \ snd (f l1 u1) \ None)" - hence or: "fst (f l1 u1) = None \ snd (f l1 u1) = None" by auto - hence "lift_un (g a) f = None" - proof (cases "fst (f l1 u1) = None") - case True - then obtain b where b: "f l1 u1 = (None, b)" - by (cases "f l1 u1") auto - thus ?thesis - unfolding Sa[symmetric] lift_un.simps b by auto - next - case False - hence "snd (f l1 u1) = None" - using or by auto - with False obtain b where b: "f l1 u1 = (Some b, None)" - by (cases "f l1 u1") auto - thus ?thesis - unfolding Sa[symmetric] lift_un.simps b by auto - qed - thus False - using lift_un_Some by auto - qed - then obtain a' b' where f: "f l1 u1 = (Some a', Some b')" - by (cases "f l1 u1") auto - from lift_un_Some[unfolded Sa[symmetric] lift_un.simps f] - have "Some l = fst (f l1 u1)" and "Some u = snd (f l1 u1)" - unfolding f by auto - thus ?thesis - unfolding Sa[symmetric] lift_un.simps using Pa[OF Sa] by auto -qed - -lemma lift_un: - assumes lift_un_Some: "Some (l, u) = lift_un (approx' prec a bs) f" - and Pa: "\l u. Some (l, u) = approx prec a bs \ - l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" - (is "\l u. _ = ?g a \ ?P l u a") - shows "\l1 u1. (l1 \ interpret_floatarith a xs \ interpret_floatarith a xs \ u1) \ - Some l = fst (f l1 u1) \ Some u = snd (f l1 u1)" -proof - - have Pa: "l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" - if "Some (l, u) = approx' prec a bs" for l u - using approx_approx'[of prec a bs, OF _ that] Pa by auto - from lift_un_f[where g="\a. approx' prec a bs" and P = ?P, OF lift_un_Some, OF Pa] - show ?thesis by auto -qed - -lemma lift_un_bnds: - assumes bnds: "\(x::real) lx ux. (Some l, Some u) = f lx ux \ x \ { lx .. ux } \ l \ f' x \ f' x \ u" - and lift_un_Some: "Some (l, u) = lift_un (approx' prec a bs) f" - and Pa: "\l u. Some (l, u) = approx prec a bs \ - l \ interpret_floatarith a xs \ interpret_floatarith a xs \ u" - shows "real_of_float l \ f' (interpret_floatarith a xs) \ f' (interpret_floatarith a xs) \ real_of_float u" -proof - - from lift_un[OF lift_un_Some Pa] - obtain l1 u1 where "l1 \ interpret_floatarith a xs" - and "interpret_floatarith a xs \ u1" - and "Some l = fst (f l1 u1)" - and "Some u = snd (f l1 u1)" - by blast - hence "(Some l, Some u) = f l1 u1" and "interpret_floatarith a xs \ {l1 .. u1}" - by auto - thus ?thesis - using bnds by auto + obtain ivl' where S: "approx prec a vs = Some ivl'" and ivl_def: "ivl = round_interval prec ivl'" + using approx' unfolding approx'.simps by (cases "approx prec a vs") auto + show ?thesis + by (auto simp: ivl_def intro!: in_round_intervalI Pa[OF S]) qed lemma approx: assumes "bounded_by xs vs" - and "Some (l, u) = approx prec arith vs" (is "_ = ?g arith") - shows "l \ interpret_floatarith arith xs \ interpret_floatarith arith xs \ u" (is "?P l u arith") - using \Some (l, u) = approx prec arith vs\ -proof (induct arith arbitrary: l u) - case (Add a b) - from lift_bin'[OF Add.prems[unfolded approx.simps]] Add.hyps - obtain l1 u1 l2 u2 where "l = float_plus_down prec l1 l2" - and "u = float_plus_up prec u1 u2" "l1 \ interpret_floatarith a xs" - and "interpret_floatarith a xs \ u1" "l2 \ interpret_floatarith b xs" - and "interpret_floatarith b xs \ u2" - unfolding fst_conv snd_conv by blast - thus ?case - unfolding interpret_floatarith.simps by (auto intro!: float_plus_up_le float_plus_down_le) -next - case (Minus a) - from lift_un'[OF Minus.prems[unfolded approx.simps]] Minus.hyps - obtain l1 u1 where "l = -u1" "u = -l1" - and "l1 \ interpret_floatarith a xs" "interpret_floatarith a xs \ u1" - unfolding fst_conv snd_conv by blast - thus ?case - unfolding interpret_floatarith.simps using minus_float.rep_eq by auto -next - case (Mult a b) - from lift_bin'[OF Mult.prems[unfolded approx.simps]] Mult.hyps - obtain l1 u1 l2 u2 - where l: "l = fst (bnds_mult prec l1 u1 l2 u2)" - and u: "u = snd (bnds_mult prec l1 u1 l2 u2)" - and a: "l1 \ interpret_floatarith a xs" "interpret_floatarith a xs \ u1" - and b: "l2 \ interpret_floatarith b xs" "interpret_floatarith b xs \ u2" unfolding fst_conv snd_conv by blast - from l u have lu: "(l, u) = bnds_mult prec l1 u1 l2 u2" by simp - from bnds_mult[OF lu] a b show ?case by simp -next - case (Inverse a) - from lift_un[OF Inverse.prems[unfolded approx.simps], unfolded if_distrib[of fst] if_distrib[of snd] fst_conv snd_conv] Inverse.hyps - obtain l1 u1 where l': "Some l = (if 0 < l1 \ u1 < 0 then Some (float_divl prec 1 u1) else None)" - and u': "Some u = (if 0 < l1 \ u1 < 0 then Some (float_divr prec 1 l1) else None)" - and l1: "l1 \ interpret_floatarith a xs" - and u1: "interpret_floatarith a xs \ u1" - by blast - have either: "0 < l1 \ u1 < 0" - proof (rule ccontr) - assume P: "\ (0 < l1 \ u1 < 0)" - show False - using l' unfolding if_not_P[OF P] by auto - qed - moreover have l1_le_u1: "real_of_float l1 \ real_of_float u1" - using l1 u1 by auto - ultimately have "real_of_float l1 \ 0" and "real_of_float u1 \ 0" - by auto - - have inv: "inverse u1 \ inverse (interpret_floatarith a xs) - \ inverse (interpret_floatarith a xs) \ inverse l1" - proof (cases "0 < l1") - case True - hence "0 < real_of_float u1" and "0 < real_of_float l1" "0 < interpret_floatarith a xs" - using l1_le_u1 l1 by auto - show ?thesis - unfolding inverse_le_iff_le[OF \0 < real_of_float u1\ \0 < interpret_floatarith a xs\] - inverse_le_iff_le[OF \0 < interpret_floatarith a xs\ \0 < real_of_float l1\] - using l1 u1 by auto - next - case False - hence "u1 < 0" - using either by blast - hence "real_of_float u1 < 0" and "real_of_float l1 < 0" "interpret_floatarith a xs < 0" - using l1_le_u1 u1 by auto - show ?thesis - unfolding inverse_le_iff_le_neg[OF \real_of_float u1 < 0\ \interpret_floatarith a xs < 0\] - inverse_le_iff_le_neg[OF \interpret_floatarith a xs < 0\ \real_of_float l1 < 0\] - using l1 u1 by auto - qed - - from l' have "l = float_divl prec 1 u1" - by (cases "0 < l1 \ u1 < 0") auto - hence "l \ inverse u1" - unfolding nonzero_inverse_eq_divide[OF \real_of_float u1 \ 0\] - using float_divl[of prec 1 u1] by auto - also have "\ \ inverse (interpret_floatarith a xs)" - using inv by auto - finally have "l \ inverse (interpret_floatarith a xs)" . - moreover - from u' have "u = float_divr prec 1 l1" - by (cases "0 < l1 \ u1 < 0") auto - hence "inverse l1 \ u" - unfolding nonzero_inverse_eq_divide[OF \real_of_float l1 \ 0\] - using float_divr[of 1 l1 prec] by auto - hence "inverse (interpret_floatarith a xs) \ u" - by (rule order_trans[OF inv[THEN conjunct2]]) - ultimately show ?case - unfolding interpret_floatarith.simps using l1 u1 by auto -next - case (Abs x) - from lift_un'[OF Abs.prems[unfolded approx.simps], unfolded fst_conv snd_conv] Abs.hyps - obtain l1 u1 where l': "l = (if l1 < 0 \ 0 < u1 then 0 else min \l1\ \u1\)" - and u': "u = max \l1\ \u1\" - and l1: "l1 \ interpret_floatarith x xs" - and u1: "interpret_floatarith x xs \ u1" - by blast - thus ?case - unfolding l' u' - by (cases "l1 < 0 \ 0 < u1") (auto simp add: real_of_float_min real_of_float_max) -next - case (Min a b) - from lift_bin'[OF Min.prems[unfolded approx.simps], unfolded fst_conv snd_conv] Min.hyps - obtain l1 u1 l2 u2 where l': "l = min l1 l2" and u': "u = min u1 u2" - and l1: "l1 \ interpret_floatarith a xs" and u1: "interpret_floatarith a xs \ u1" - and l1: "l2 \ interpret_floatarith b xs" and u1: "interpret_floatarith b xs \ u2" - by blast - thus ?case - unfolding l' u' by (auto simp add: real_of_float_min) -next - case (Max a b) - from lift_bin'[OF Max.prems[unfolded approx.simps], unfolded fst_conv snd_conv] Max.hyps - obtain l1 u1 l2 u2 where l': "l = max l1 l2" and u': "u = max u1 u2" - and l1: "l1 \ interpret_floatarith a xs" and u1: "interpret_floatarith a xs \ u1" - and l1: "l2 \ interpret_floatarith b xs" and u1: "interpret_floatarith b xs \ u2" - by blast - thus ?case - unfolding l' u' by (auto simp add: real_of_float_max) -next - case (Cos a) - with lift_un'_bnds[OF bnds_cos] show ?case by auto -next - case (Arctan a) - with lift_un'_bnds[OF bnds_arctan] show ?case by auto -next - case Pi - with pi_boundaries show ?case by auto -next - case (Sqrt a) - with lift_un'_bnds[OF bnds_sqrt] show ?case by auto -next - case (Exp a) - with lift_un'_bnds[OF bnds_exp] show ?case by auto -next - case (Powr a b) - from lift_bin[OF Powr.prems[unfolded approx.simps]] Powr.hyps - obtain l1 u1 l2 u2 where lu: "Some (l, u) = bnds_powr prec l1 u1 l2 u2" - and l1: "l1 \ interpret_floatarith a xs" and u1: "interpret_floatarith a xs \ u1" - and l2: "l2 \ interpret_floatarith b xs" and u2: "interpret_floatarith b xs \ u2" - by blast - from bnds_powr[OF lu] l1 u1 l2 u2 - show ?case by simp -next - case (Ln a) - with lift_un_bnds[OF bnds_ln] show ?case by auto -next - case (Power a n) - with lift_un'_bnds[OF bnds_power] show ?case by auto -next - case (Floor a) - from lift_un'[OF Floor.prems[unfolded approx.simps] Floor.hyps] - show ?case by (auto simp: floor_fl.rep_eq floor_mono) -next - case (Num f) - thus ?case by auto -next - case (Var n) - from this[symmetric] \bounded_by xs vs\[THEN bounded_byE, of n] - show ?case by (cases "n < length vs") auto -qed + and "approx prec arith vs = Some ivl" + shows "interpret_floatarith arith xs \\<^sub>r ivl" + using \approx prec arith vs = Some ivl\ + using \bounded_by xs vs\[THEN bounded_byE] + by (induct arith arbitrary: ivl) + (force split: option.splits if_splits + intro!: plus_in_float_intervalI mult_float_intervalI uminus_in_float_intervalI + inverse_float_interval_eqI abs_in_float_intervalI + min_intervalI max_intervalI + cos_float_intervalI + arctan_float_intervalI pi_float_interval sqrt_float_intervalI exp_float_intervalI + powr_float_interval_eqI ln_float_interval_eqI power_float_intervalI floor_float_intervalI + intro: in_round_intervalI)+ datatype form = Bound floatarith floatarith floatarith form | Assign floatarith floatarith form @@ -639,30 +178,32 @@ "interpret_form (Conj f g) vs \ interpret_form f vs \ interpret_form g vs" | "interpret_form (Disj f g) vs \ interpret_form f vs \ interpret_form g vs" -fun approx_form' and approx_form :: "nat \ form \ (float * float) option list \ nat list \ bool" where -"approx_form' prec f 0 n l u bs ss = approx_form prec f (bs[n := Some (l, u)]) ss" | -"approx_form' prec f (Suc s) n l u bs ss = - (let m = (l + u) * Float 1 (- 1) - in (if approx_form' prec f s n l m bs ss then approx_form' prec f s n m u bs ss else False))" | +fun approx_form' and approx_form :: "nat \ form \ (float interval) option list \ nat list \ bool" where +"approx_form' prec f 0 n ivl bs ss = approx_form prec f (bs[n := Some ivl]) ss" | +"approx_form' prec f (Suc s) n ivl bs ss = + (let (ivl1, ivl2) = split_float_interval ivl + in (if approx_form' prec f s n ivl1 bs ss then approx_form' prec f s n ivl2 bs ss else False))" | "approx_form prec (Bound (Var n) a b f) bs ss = (case (approx prec a bs, approx prec b bs) - of (Some (l, _), Some (_, u)) \ approx_form' prec f (ss ! n) n l u bs ss + of (Some ivl1, Some ivl2) \ approx_form' prec f (ss ! n) n (sup ivl1 ivl2) bs ss | _ \ False)" | "approx_form prec (Assign (Var n) a f) bs ss = (case (approx prec a bs) - of (Some (l, u)) \ approx_form' prec f (ss ! n) n l u bs ss + of (Some ivl) \ approx_form' prec f (ss ! n) n ivl bs ss | _ \ False)" | "approx_form prec (Less a b) bs ss = (case (approx prec a bs, approx prec b bs) - of (Some (l, u), Some (l', u')) \ float_plus_up prec u (-l') < 0 + of (Some ivl, Some ivl') \ float_plus_up prec (upper ivl) (-lower ivl') < 0 | _ \ False)" | "approx_form prec (LessEqual a b) bs ss = (case (approx prec a bs, approx prec b bs) - of (Some (l, u), Some (l', u')) \ float_plus_up prec u (-l') \ 0 + of (Some ivl, Some ivl') \ float_plus_up prec (upper ivl) (-lower ivl') \ 0 | _ \ False)" | "approx_form prec (AtLeastAtMost x a b) bs ss = (case (approx prec x bs, approx prec a bs, approx prec b bs) - of (Some (lx, ux), Some (l, u), Some (l', u')) \ float_plus_up prec u (-lx) \ 0 \ float_plus_up prec ux (-l') \ 0 + of (Some ivlx, Some ivl, Some ivl') \ + float_plus_up prec (upper ivl) (-lower ivlx) \ 0 \ + float_plus_up prec (upper ivlx) (-lower ivl') \ 0 | _ \ False)" | "approx_form prec (Conj a b) bs ss \ approx_form prec a bs ss \ approx_form prec b bs ss" | "approx_form prec (Disj a b) bs ss \ approx_form prec a bs ss \ approx_form prec b bs ss" | @@ -671,32 +212,32 @@ lemma lazy_conj: "(if A then B else False) = (A \ B)" by simp lemma approx_form_approx_form': - assumes "approx_form' prec f s n l u bs ss" - and "(x::real) \ { l .. u }" - obtains l' u' where "x \ { l' .. u' }" - and "approx_form prec f (bs[n := Some (l', u')]) ss" -using assms proof (induct s arbitrary: l u) + assumes "approx_form' prec f s n ivl bs ss" + and "(x::real) \\<^sub>r ivl" + obtains ivl' where "x \\<^sub>r ivl'" + and "approx_form prec f (bs[n := Some ivl']) ss" +using assms proof (induct s arbitrary: ivl) case 0 - from this(1)[of l u] this(2,3) + from this(1)[of ivl] this(2,3) show thesis by auto next case (Suc s) - - let ?m = "(l + u) * Float 1 (- 1)" - have "real_of_float l \ ?m" and "?m \ real_of_float u" - unfolding less_eq_float_def using Suc.prems by auto - - with \x \ { l .. u }\ - have "x \ { l .. ?m} \ x \ { ?m .. u }" by auto - thus thesis - proof (rule disjE) - assume *: "x \ { l .. ?m }" - with Suc.hyps[OF _ _ *] Suc.prems - show thesis by (simp add: Let_def lazy_conj) + then obtain ivl1 ivl2 where ivl_split: "split_float_interval ivl = (ivl1, ivl2)" + by (fastforce dest: split_float_intervalD) + from split_float_interval_realD[OF this \x \\<^sub>r ivl\] + consider "x \\<^sub>r ivl1" | "x \\<^sub>r ivl2" + by atomize_elim + then show thesis + proof cases + case *: 1 + from Suc.hyps[OF _ _ *] Suc.prems + show ?thesis + by (simp add: lazy_conj ivl_split split: prod.splits) next - assume *: "x \ { ?m .. u }" - with Suc.hyps[OF _ _ *] Suc.prems - show thesis by (simp add: Let_def lazy_conj) + case *: 2 + from Suc.hyps[OF _ _ *] Suc.prems + show ?thesis + by (simp add: lazy_conj ivl_split split: prod.splits) qed qed @@ -709,23 +250,24 @@ then obtain n where x_eq: "x = Var n" by (cases x) auto - with Bound.prems obtain l u' l' u - where l_eq: "Some (l, u') = approx prec a vs" - and u_eq: "Some (l', u) = approx prec b vs" - and approx_form': "approx_form' prec f (ss ! n) n l u vs ss" + with Bound.prems obtain ivl1 ivl2 + where l_eq: "approx prec a vs = Some ivl1" + and u_eq: "approx prec b vs = Some ivl2" + and approx_form': "approx_form' prec f (ss ! n) n (sup ivl1 ivl2) vs ss" by (cases "approx prec a vs", simp) (cases "approx prec b vs", auto) have "interpret_form f xs" if "xs ! n \ { interpret_floatarith a xs .. interpret_floatarith b xs }" proof - from approx[OF Bound.prems(2) l_eq] and approx[OF Bound.prems(2) u_eq] that - have "xs ! n \ { l .. u}" by auto + have "xs ! n \\<^sub>r (sup ivl1 ivl2)" + by (auto simp: set_of_eq sup_float_def max_def inf_float_def min_def) from approx_form_approx_form'[OF approx_form' this] - obtain lx ux where bnds: "xs ! n \ { lx .. ux }" - and approx_form: "approx_form prec f (vs[n := Some (lx, ux)]) ss" . + obtain ivlx where bnds: "xs ! n \\<^sub>r ivlx" + and approx_form: "approx_form prec f (vs[n := Some ivlx]) ss" . - from \bounded_by xs vs\ bnds have "bounded_by xs (vs[n := Some (lx, ux)])" + from \bounded_by xs vs\ bnds have "bounded_by xs (vs[n := Some ivlx])" by (rule bounded_by_update) with Bound.hyps[OF approx_form] show ?thesis by blast @@ -737,22 +279,22 @@ then obtain n where x_eq: "x = Var n" by (cases x) auto - with Assign.prems obtain l u - where bnd_eq: "Some (l, u) = approx prec a vs" + with Assign.prems obtain ivl + where bnd_eq: "approx prec a vs = Some ivl" and x_eq: "x = Var n" - and approx_form': "approx_form' prec f (ss ! n) n l u vs ss" + and approx_form': "approx_form' prec f (ss ! n) n ivl vs ss" by (cases "approx prec a vs") auto have "interpret_form f xs" if bnds: "xs ! n = interpret_floatarith a xs" proof - from approx[OF Assign.prems(2) bnd_eq] bnds - have "xs ! n \ { l .. u}" by auto + have "xs ! n \\<^sub>r ivl" by auto from approx_form_approx_form'[OF approx_form' this] - obtain lx ux where bnds: "xs ! n \ { lx .. ux }" - and approx_form: "approx_form prec f (vs[n := Some (lx, ux)]) ss" . + obtain ivlx where bnds: "xs ! n \\<^sub>r ivlx" + and approx_form: "approx_form prec f (vs[n := Some ivlx]) ss" . - from \bounded_by xs vs\ bnds have "bounded_by xs (vs[n := Some (lx, ux)])" + from \bounded_by xs vs\ bnds have "bounded_by xs (vs[n := Some ivlx])" by (rule bounded_by_update) with Assign.hyps[OF approx_form] show ?thesis by blast @@ -761,37 +303,38 @@ using interpret_form.simps x_eq and interpret_floatarith.simps by simp next case (Less a b) - then obtain l u l' u' - where l_eq: "Some (l, u) = approx prec a vs" - and u_eq: "Some (l', u') = approx prec b vs" - and inequality: "real_of_float (float_plus_up prec u (-l')) < 0" + then obtain ivl ivl' + where l_eq: "approx prec a vs = Some ivl" + and u_eq: "approx prec b vs = Some ivl'" + and inequality: "real_of_float (float_plus_up prec (upper ivl) (-lower ivl')) < 0" by (cases "approx prec a vs", auto, cases "approx prec b vs", auto) from le_less_trans[OF float_plus_up inequality] approx[OF Less.prems(2) l_eq] approx[OF Less.prems(2) u_eq] - show ?case by auto + show ?case by (auto simp: set_of_eq) next case (LessEqual a b) - then obtain l u l' u' - where l_eq: "Some (l, u) = approx prec a vs" - and u_eq: "Some (l', u') = approx prec b vs" - and inequality: "real_of_float (float_plus_up prec u (-l')) \ 0" + then obtain ivl ivl' + where l_eq: "approx prec a vs = Some ivl" + and u_eq: "approx prec b vs = Some ivl'" + and inequality: "real_of_float (float_plus_up prec (upper ivl) (-lower ivl')) \ 0" by (cases "approx prec a vs", auto, cases "approx prec b vs", auto) from order_trans[OF float_plus_up inequality] approx[OF LessEqual.prems(2) l_eq] approx[OF LessEqual.prems(2) u_eq] - show ?case by auto + show ?case by (auto simp: set_of_eq) next case (AtLeastAtMost x a b) - then obtain lx ux l u l' u' - where x_eq: "Some (lx, ux) = approx prec x vs" - and l_eq: "Some (l, u) = approx prec a vs" - and u_eq: "Some (l', u') = approx prec b vs" - and inequality: "real_of_float (float_plus_up prec u (-lx)) \ 0" "real_of_float (float_plus_up prec ux (-l')) \ 0" + then obtain ivlx ivl ivl' + where x_eq: "approx prec x vs = Some ivlx" + and l_eq: "approx prec a vs = Some ivl" + and u_eq: "approx prec b vs = Some ivl'" + and inequality: "real_of_float (float_plus_up prec (upper ivl) (-lower ivlx)) \ 0" + "real_of_float (float_plus_up prec (upper ivlx) (-lower ivl')) \ 0" by (cases "approx prec x vs", auto, cases "approx prec a vs", auto, cases "approx prec b vs", auto) from order_trans[OF float_plus_up inequality(1)] order_trans[OF float_plus_up inequality(2)] approx[OF AtLeastAtMost.prems(2) l_eq] approx[OF AtLeastAtMost.prems(2) u_eq] approx[OF AtLeastAtMost.prems(2) x_eq] - show ?case by auto + show ?case by (auto simp: set_of_eq) qed auto lemma approx_form: @@ -907,12 +450,12 @@ declare approx.simps[simp del] -fun isDERIV_approx :: "nat \ nat \ floatarith \ (float * float) option list \ bool" where +fun isDERIV_approx :: "nat \ nat \ floatarith \ (float interval) option list \ bool" where "isDERIV_approx prec x (Add a b) vs = (isDERIV_approx prec x a vs \ isDERIV_approx prec x b vs)" | "isDERIV_approx prec x (Mult a b) vs = (isDERIV_approx prec x a vs \ isDERIV_approx prec x b vs)" | "isDERIV_approx prec x (Minus a) vs = isDERIV_approx prec x a vs" | "isDERIV_approx prec x (Inverse a) vs = - (isDERIV_approx prec x a vs \ (case approx prec a vs of Some (l, u) \ 0 < l \ u < 0 | None \ False))" | + (isDERIV_approx prec x a vs \ (case approx prec a vs of Some ivl \ 0 < lower ivl \ upper ivl < 0 | None \ False))" | "isDERIV_approx prec x (Cos a) vs = isDERIV_approx prec x a vs" | "isDERIV_approx prec x (Arctan a) vs = isDERIV_approx prec x a vs" | "isDERIV_approx prec x (Min a b) vs = False" | @@ -920,15 +463,15 @@ "isDERIV_approx prec x (Abs a) vs = False" | "isDERIV_approx prec x Pi vs = True" | "isDERIV_approx prec x (Sqrt a) vs = - (isDERIV_approx prec x a vs \ (case approx prec a vs of Some (l, u) \ 0 < l | None \ False))" | + (isDERIV_approx prec x a vs \ (case approx prec a vs of Some ivl \ 0 < lower ivl | None \ False))" | "isDERIV_approx prec x (Exp a) vs = isDERIV_approx prec x a vs" | "isDERIV_approx prec x (Powr a b) vs = - (isDERIV_approx prec x a vs \ isDERIV_approx prec x b vs \ (case approx prec a vs of Some (l, u) \ 0 < l | None \ False))" | + (isDERIV_approx prec x a vs \ isDERIV_approx prec x b vs \ (case approx prec a vs of Some ivl \ 0 < lower ivl | None \ False))" | "isDERIV_approx prec x (Ln a) vs = - (isDERIV_approx prec x a vs \ (case approx prec a vs of Some (l, u) \ 0 < l | None \ False))" | + (isDERIV_approx prec x a vs \ (case approx prec a vs of Some ivl \ 0 < lower ivl | None \ False))" | "isDERIV_approx prec x (Power a 0) vs = True" | "isDERIV_approx prec x (Floor a) vs = - (isDERIV_approx prec x a vs \ (case approx prec a vs of Some (l, u) \ l > floor u \ u < ceiling l | None \ False))" | + (isDERIV_approx prec x a vs \ (case approx prec a vs of Some ivl \ lower ivl > floor (upper ivl) \ upper ivl < ceiling (lower ivl) | None \ False))" | "isDERIV_approx prec x (Power a (Suc n)) vs = isDERIV_approx prec x a vs" | "isDERIV_approx prec x (Num f) vs = True" | "isDERIV_approx prec x (Var n) vs = True" @@ -940,88 +483,65 @@ using isDERIV_approx proof (induct f) case (Inverse a) - then obtain l u where approx_Some: "Some (l, u) = approx prec a vs" - and *: "0 < l \ u < 0" + then obtain ivl where approx_Some: "approx prec a vs = Some ivl" + and *: "0 < lower ivl \ upper ivl < 0" by (cases "approx prec a vs") auto with approx[OF \bounded_by xs vs\ approx_Some] - have "interpret_floatarith a xs \ 0" by auto + have "interpret_floatarith a xs \ 0" by (auto simp: set_of_eq) thus ?case using Inverse by auto next case (Ln a) - then obtain l u where approx_Some: "Some (l, u) = approx prec a vs" - and *: "0 < l" + then obtain ivl where approx_Some: "approx prec a vs = Some ivl" + and *: "0 < lower ivl" by (cases "approx prec a vs") auto with approx[OF \bounded_by xs vs\ approx_Some] - have "0 < interpret_floatarith a xs" by auto + have "0 < interpret_floatarith a xs" by (auto simp: set_of_eq) thus ?case using Ln by auto next case (Sqrt a) - then obtain l u where approx_Some: "Some (l, u) = approx prec a vs" - and *: "0 < l" + then obtain ivl where approx_Some: "approx prec a vs = Some ivl" + and *: "0 < lower ivl" by (cases "approx prec a vs") auto with approx[OF \bounded_by xs vs\ approx_Some] - have "0 < interpret_floatarith a xs" by auto + have "0 < interpret_floatarith a xs" by (auto simp: set_of_eq) thus ?case using Sqrt by auto next case (Power a n) thus ?case by (cases n) auto next case (Powr a b) - from Powr obtain l1 u1 where a: "Some (l1, u1) = approx prec a vs" and pos: "0 < l1" + from Powr obtain ivl1 where a: "approx prec a vs = Some ivl1" + and pos: "0 < lower ivl1" by (cases "approx prec a vs") auto with approx[OF \bounded_by xs vs\ a] - have "0 < interpret_floatarith a xs" by auto + have "0 < interpret_floatarith a xs" by (auto simp: set_of_eq) with Powr show ?case by auto next case (Floor a) - then obtain l u where approx_Some: "Some (l, u) = approx prec a vs" - and "real_of_int \real_of_float u\ < real_of_float l" "real_of_float u < real_of_int \real_of_float l\" + then obtain ivl where approx_Some: "approx prec a vs = Some ivl" + and "real_of_int \real_of_float (upper ivl)\ < real_of_float (lower ivl)" + "real_of_float (upper ivl) < real_of_int \real_of_float (lower ivl)\" and "isDERIV x a xs" by (cases "approx prec a vs") auto with approx[OF \bounded_by xs vs\ approx_Some] le_floor_iff show ?case - by (force elim!: Ints_cases) + by (force elim!: Ints_cases simp: set_of_eq) qed auto lemma bounded_by_update_var: assumes "bounded_by xs vs" - and "vs ! i = Some (l, u)" - and bnd: "x \ { real_of_float l .. real_of_float u }" + and "vs ! i = Some ivl" + and bnd: "x \\<^sub>r ivl" shows "bounded_by (xs[i := x]) vs" -proof (cases "i < length xs") - case False - thus ?thesis - using \bounded_by xs vs\ by auto -next - case True - let ?xs = "xs[i := x]" - from True have "i < length ?xs" by auto - have "case vs ! j of None \ True | Some (l, u) \ ?xs ! j \ {real_of_float l .. real_of_float u}" - if "j < length vs" for j - proof (cases "vs ! j") - case None - then show ?thesis by simp - next - case (Some b) - thus ?thesis - proof (cases "i = j") - case True - thus ?thesis using \vs ! i = Some (l, u)\ Some and bnd \i < length ?xs\ - by auto - next - case False - thus ?thesis - using \bounded_by xs vs\[THEN bounded_byE, OF \j < length vs\] Some by auto - qed - qed - thus ?thesis - unfolding bounded_by_def by auto -qed + using assms + using nth_list_update + by (cases "i < length xs") + (force simp: bounded_by_def split: option.splits)+ lemma isDERIV_approx': assumes "bounded_by xs vs" - and vs_x: "vs ! x = Some (l, u)" - and X_in: "X \ {real_of_float l .. real_of_float u}" + and vs_x: "vs ! x = Some ivl" + and X_in: "X \\<^sub>r ivl" and approx: "isDERIV_approx prec x f vs" shows "isDERIV x f (xs[x := X])" proof - @@ -1033,14 +553,14 @@ assumes "n < length xs" and bnd: "bounded_by xs vs" and isD: "isDERIV_approx prec n f vs" - and app: "Some (l, u) = approx prec (DERIV_floatarith n f) vs" (is "_ = approx _ ?D _") - shows "\(x::real). l \ x \ x \ u \ + and app: "approx prec (DERIV_floatarith n f) vs = Some ivl" (is "approx _ ?D _ = _") + shows "\(x::real). x \\<^sub>r ivl \ DERIV (\ x. interpret_floatarith f (xs[n := x])) (xs!n) :> x" - (is "\ x. _ \ _ \ DERIV (?i f) _ :> _") -proof (rule exI[of _ "?i ?D (xs!n)"], rule conjI[OF _ conjI]) + (is "\ x. _ \ DERIV (?i f) _ :> _") +proof (rule exI[of _ "?i ?D (xs!n)"], rule conjI) let "?i f" = "\x. interpret_floatarith f (xs[n := x])" from approx[OF bnd app] - show "l \ ?i ?D (xs!n)" and "?i ?D (xs!n) \ u" + show "?i ?D (xs!n) \\<^sub>r ivl" using \n < length xs\ by auto from DERIV_floatarith[OF \n < length xs\, of f "xs!n"] isDERIV_approx[OF bnd isD] show "DERIV (?i f) (xs!n) :> (?i ?D (xs!n))" @@ -1048,11 +568,11 @@ qed lemma lift_bin_aux: - assumes lift_bin_Some: "Some (l, u) = lift_bin a b f" - obtains l1 u1 l2 u2 - where "a = Some (l1, u1)" - and "b = Some (l2, u2)" - and "f l1 u1 l2 u2 = Some (l, u)" + assumes lift_bin_Some: "lift_bin a b f = Some ivl" + obtains ivl1 ivl2 + where "a = Some ivl1" + and "b = Some ivl2" + and "f ivl1 ivl2 = Some ivl" using assms by (cases a, simp, cases b, simp, auto) @@ -1060,22 +580,22 @@ "approx_tse prec n 0 c k f bs = approx prec f bs" | "approx_tse prec n (Suc s) c k f bs = (if isDERIV_approx prec n f bs then - lift_bin (approx prec f (bs[n := Some (c,c)])) + lift_bin (approx prec f (bs[n := Some (interval_of c)])) (approx_tse prec n s c (Suc k) (DERIV_floatarith n f) bs) - (\ l1 u1 l2 u2. approx prec + (\ivl1 ivl2. approx prec (Add (Var 0) (Mult (Inverse (Num (Float (int k) 0))) (Mult (Add (Var (Suc (Suc 0))) (Minus (Num c))) - (Var (Suc 0))))) [Some (l1, u1), Some (l2, u2), bs!n]) + (Var (Suc 0))))) [Some ivl1, Some ivl2, bs!n]) else approx prec f bs)" lemma bounded_by_Cons: assumes bnd: "bounded_by xs vs" - and x: "x \ { real_of_float l .. real_of_float u }" - shows "bounded_by (x#xs) ((Some (l, u))#vs)" + and x: "x \\<^sub>r ivl" + shows "bounded_by (x#xs) ((Some ivl)#vs)" proof - - have "case ((Some (l,u))#vs) ! i of Some (l, u) \ (x#xs)!i \ { real_of_float l .. real_of_float u } | None \ True" - if *: "i < length ((Some (l, u))#vs)" for i + have "case ((Some ivl)#vs) ! i of Some ivl \ (x#xs)!i \\<^sub>r ivl | None \ True" + if *: "i < length ((Some ivl)#vs)" for i proof (cases i) case 0 with x show ?thesis by auto @@ -1093,25 +613,25 @@ assumes "bounded_by xs vs" and bnd_c: "bounded_by (xs[x := c]) vs" and "x < length vs" and "x < length xs" - and bnd_x: "vs ! x = Some (lx, ux)" - and ate: "Some (l, u) = approx_tse prec x s c k f vs" - shows "\ n. (\ m < n. \ (z::real) \ {lx .. ux}. + and bnd_x: "vs ! x = Some ivlx" + and ate: "approx_tse prec x s c k f vs = Some ivl" + shows "\ n. (\ m < n. \ (z::real) \ set_of (real_interval ivlx). DERIV (\ y. interpret_floatarith ((DERIV_floatarith x ^^ m) f) (xs[x := y])) z :> (interpret_floatarith ((DERIV_floatarith x ^^ (Suc m)) f) (xs[x := z]))) - \ (\ (t::real) \ {lx .. ux}. (\ i = 0.. j \ {k.. (\ (t::real) \ set_of (real_interval ivlx). (\ i = 0.. j \ {k.. j \ {k.. {l .. u})" (is "\ n. ?taylor f k l u n") + (xs!x - c)^n \\<^sub>r ivl)" (is "\ n. ?taylor f k ivl n") using ate -proof (induct s arbitrary: k f l u) +proof (induct s arbitrary: k f ivl) case 0 { - fix t::real assume "t \ {lx .. ux}" + fix t::real assume "t \\<^sub>r ivlx" note bounded_by_update_var[OF \bounded_by xs vs\ bnd_x this] from approx[OF this 0[unfolded approx_tse.simps]] - have "(interpret_floatarith f (xs[x := t])) \ {l .. u}" + have "(interpret_floatarith f (xs[x := t])) \\<^sub>r ivl" by (auto simp add: algebra_simps) } thus ?case by (auto intro!: exI[of _ 0]) @@ -1122,32 +642,32 @@ case False note ap = Suc.prems[unfolded approx_tse.simps if_not_P[OF False]] { - fix t::real assume "t \ {lx .. ux}" + fix t::real assume "t \\<^sub>r ivlx" note bounded_by_update_var[OF \bounded_by xs vs\ bnd_x this] from approx[OF this ap] - have "(interpret_floatarith f (xs[x := t])) \ {l .. u}" + have "(interpret_floatarith f (xs[x := t])) \\<^sub>r ivl" by (auto simp add: algebra_simps) } thus ?thesis by (auto intro!: exI[of _ 0]) next case True with Suc.prems - obtain l1 u1 l2 u2 - where a: "Some (l1, u1) = approx prec f (vs[x := Some (c,c)])" - and ate: "Some (l2, u2) = approx_tse prec x s c (Suc k) (DERIV_floatarith x f) vs" - and final: "Some (l, u) = approx prec + obtain ivl1 ivl2 + where a: "approx prec f (vs[x := Some (interval_of c)]) = Some ivl1" + and ate: "approx_tse prec x s c (Suc k) (DERIV_floatarith x f) vs = Some ivl2" + and final: "approx prec (Add (Var 0) (Mult (Inverse (Num (Float (int k) 0))) (Mult (Add (Var (Suc (Suc 0))) (Minus (Num c))) - (Var (Suc 0))))) [Some (l1, u1), Some (l2, u2), vs!x]" + (Var (Suc 0))))) [Some ivl1, Some ivl2, vs!x] = Some ivl" by (auto elim!: lift_bin_aux) from bnd_c \x < length xs\ - have bnd: "bounded_by (xs[x:=c]) (vs[x:= Some (c,c)])" + have bnd: "bounded_by (xs[x:=c]) (vs[x:= Some (interval_of c)])" by (auto intro!: bounded_by_update) from approx[OF this a] - have f_c: "interpret_floatarith ((DERIV_floatarith x ^^ 0) f) (xs[x := c]) \ { l1 .. u1 }" + have f_c: "interpret_floatarith ((DERIV_floatarith x ^^ 0) f) (xs[x := c]) \\<^sub>r ivl1" (is "?f 0 (real_of_float c) \ _") by auto @@ -1155,16 +675,16 @@ for f :: "'a \ 'a" and n :: nat and x :: 'a by (induct n) auto from Suc.hyps[OF ate, unfolded this] obtain n - where DERIV_hyp: "\m z. \ m < n ; (z::real) \ { lx .. ux } \ \ + where DERIV_hyp: "\m z. \ m < n ; (z::real) \\<^sub>r ivlx \ \ DERIV (?f (Suc m)) z :> ?f (Suc (Suc m)) z" - and hyp: "\t \ {real_of_float lx .. real_of_float ux}. + and hyp: "\t \ set_of (real_interval ivlx). (\ i = 0.. j \ {Suc k.. j \ {Suc k.. {l2 .. u2}" + inverse (real (\ j \ {Suc k..\<^sub>r ivl2" (is "\ t \ _. ?X (Suc k) f n t \ _") by blast have DERIV: "DERIV (?f m) z :> ?f (Suc m) z" - if "m < Suc n" and bnd_z: "z \ { lx .. ux }" for m and z::real + if "m < Suc n" and bnd_z: "z \\<^sub>r ivlx" for m and z::real proof (cases m) case 0 with DERIV_floatarith[OF \x < length xs\ @@ -1187,16 +707,16 @@ define C where "C = xs!x - c" { - fix t::real assume t: "t \ {lx .. ux}" + fix t::real assume t: "t \\<^sub>r ivlx" hence "bounded_by [xs!x] [vs!x]" using \bounded_by xs vs\[THEN bounded_byE, OF \x < length vs\] by (cases "vs!x", auto simp add: bounded_by_def) with hyp[THEN bspec, OF t] f_c - have "bounded_by [?f 0 c, ?X (Suc k) f n t, xs!x] [Some (l1, u1), Some (l2, u2), vs!x]" + have "bounded_by [?f 0 c, ?X (Suc k) f n t, xs!x] [Some ivl1, Some ivl2, vs!x]" by (auto intro!: bounded_by_Cons) from approx[OF this final, unfolded atLeastAtMost_iff[symmetric]] - have "?X (Suc k) f n t * (xs!x - real_of_float c) * inverse k + ?f 0 c \ {l .. u}" + have "?X (Suc k) f n t * (xs!x - real_of_float c) * inverse k + ?f 0 c \\<^sub>r ivl" by (auto simp add: algebra_simps) also have "?X (Suc k) f n t * (xs!x - real_of_float c) * inverse (real k) + ?f 0 c = (\ i = 0.. j \ {k.. {l .. u}" . + finally have "?T \\<^sub>r ivl" . } thus ?thesis using DERIV by blast qed @@ -1215,11 +735,11 @@ lemma approx_tse: assumes "bounded_by xs vs" - and bnd_x: "vs ! x = Some (lx, ux)" - and bnd_c: "real_of_float c \ {lx .. ux}" + and bnd_x: "vs ! x = Some ivlx" + and bnd_c: "real_of_float c \\<^sub>r ivlx" and "x < length vs" and "x < length xs" - and ate: "Some (l, u) = approx_tse prec x s c 1 f vs" - shows "interpret_floatarith f xs \ {l .. u}" + and ate: "approx_tse prec x s c 1 f vs = Some ivl" + shows "interpret_floatarith f xs \\<^sub>r ivl" proof - define F where [abs_def]: "F n z = interpret_floatarith ((DERIV_floatarith x ^^ n) f) (xs[x := z])" for n z @@ -1231,15 +751,15 @@ from approx_tse_generic[OF \bounded_by xs vs\ this bnd_x ate] obtain n - where DERIV: "\ m z. m < n \ real_of_float lx \ z \ z \ real_of_float ux \ DERIV (F m) z :> F (Suc m) z" - and hyp: "\ (t::real). t \ {lx .. ux} \ + where DERIV: "\ m z. m < n \ real_of_float (lower ivlx) \ z \ z \ real_of_float (upper ivlx) \ DERIV (F m) z :> F (Suc m) z" + and hyp: "\ (t::real). t \\<^sub>r ivlx \ (\ j = 0.. {l .. u}" (is "\ t. _ \ ?taylor t \ _") + \\<^sub>r ivl" (is "\ t. _ \ ?taylor t \ _") unfolding F_def atLeastAtMost_iff[symmetric] prod_fact - by blast + by (auto simp: set_of_eq Ball_def) - have bnd_xs: "xs ! x \ { lx .. ux }" + have bnd_xs: "xs ! x \\<^sub>r ivlx" using \bounded_by xs vs\[THEN bounded_byE, OF \x < length vs\] bnd_x by auto show ?thesis @@ -1257,8 +777,9 @@ by auto next case False - have "lx \ real_of_float c" "real_of_float c \ ux" "lx \ xs!x" "xs!x \ ux" - using Suc bnd_c \bounded_by xs vs\[THEN bounded_byE, OF \x < length vs\] bnd_x by auto + have "lower ivlx \ real_of_float c" "real_of_float c \ upper ivlx" "lower ivlx \ xs!x" "xs!x \ upper ivlx" + using Suc bnd_c \bounded_by xs vs\[THEN bounded_byE, OF \x < length vs\] bnd_x + by (auto simp: set_of_eq) from Taylor[OF zero_less_Suc, of F, OF F0 DERIV[unfolded Suc] this False] obtain t::real where t_bnd: "if xs ! x < c then xs ! x < t \ t < c else c < t \ t < xs ! x" and fl_eq: "interpret_floatarith f (xs[x := xs ! x]) = @@ -1266,12 +787,12 @@ F (Suc n') t / (fact (Suc n')) * (xs ! x - c) ^ Suc n'" unfolding atLeast0LessThan by blast - from t_bnd bnd_xs bnd_c have *: "t \ {lx .. ux}" - by (cases "xs ! x < c") auto + from t_bnd bnd_xs bnd_c have *: "t \\<^sub>r ivlx" + by (cases "xs ! x < c") (auto simp: set_of_eq) have "interpret_floatarith f (xs[x := xs ! x]) = ?taylor t" unfolding fl_eq Suc by (auto simp add: algebra_simps divide_inverse) - also have "\ \ {l .. u}" + also have "\ \\<^sub>r ivl" using * by (rule hyp) finally show ?thesis by simp @@ -1280,119 +801,122 @@ qed fun approx_tse_form' where -"approx_tse_form' prec t f 0 l u cmp = - (case approx_tse prec 0 t ((l + u) * Float 1 (- 1)) 1 f [Some (l, u)] - of Some (l, u) \ cmp l u | None \ False)" | -"approx_tse_form' prec t f (Suc s) l u cmp = - (let m = (l + u) * Float 1 (- 1) - in (if approx_tse_form' prec t f s l m cmp then - approx_tse_form' prec t f s m u cmp else False))" +"approx_tse_form' prec t f 0 ivl cmp = + (case approx_tse prec 0 t (mid ivl) 1 f [Some ivl] + of Some ivl \ cmp ivl | None \ False)" | +"approx_tse_form' prec t f (Suc s) ivl cmp = + (let (ivl1, ivl2) = split_float_interval ivl + in (if approx_tse_form' prec t f s ivl1 cmp then + approx_tse_form' prec t f s ivl2 cmp else False))" lemma approx_tse_form': fixes x :: real - assumes "approx_tse_form' prec t f s l u cmp" - and "x \ {l .. u}" - shows "\l' u' ly uy. x \ {l' .. u'} \ real_of_float l \ l' \ u' \ real_of_float u \ cmp ly uy \ - approx_tse prec 0 t ((l' + u') * Float 1 (- 1)) 1 f [Some (l', u')] = Some (ly, uy)" + assumes "approx_tse_form' prec t f s ivl cmp" + and "x \\<^sub>r ivl" + shows "\ivl' ivly. x \\<^sub>r ivl' \ ivl' \ ivl \ cmp ivly \ + approx_tse prec 0 t (mid ivl') 1 f [Some ivl'] = Some ivly" using assms -proof (induct s arbitrary: l u) +proof (induct s arbitrary: ivl) case 0 - then obtain ly uy - where *: "approx_tse prec 0 t ((l + u) * Float 1 (- 1)) 1 f [Some (l, u)] = Some (ly, uy)" - and **: "cmp ly uy" by (auto elim!: case_optionE) + then obtain ivly + where *: "approx_tse prec 0 t (mid ivl) 1 f [Some ivl] = Some ivly" + and **: "cmp ivly" by (auto elim!: case_optionE) with 0 show ?case by auto next case (Suc s) - let ?m = "(l + u) * Float 1 (- 1)" + let ?ivl1 = "fst (split_float_interval ivl)" + let ?ivl2 = "snd (split_float_interval ivl)" from Suc.prems - have l: "approx_tse_form' prec t f s l ?m cmp" - and u: "approx_tse_form' prec t f s ?m u cmp" + have l: "approx_tse_form' prec t f s ?ivl1 cmp" + and u: "approx_tse_form' prec t f s ?ivl2 cmp" by (auto simp add: Let_def lazy_conj) - have m_l: "real_of_float l \ ?m" and m_u: "?m \ real_of_float u" - unfolding less_eq_float_def using Suc.prems by auto - with \x \ { l .. u }\ consider "x \ { l .. ?m}" | "x \ {?m .. u}" - by atomize_elim auto - thus ?case + have subintervals: "?ivl1 \ ivl" "?ivl2 \ ivl" + using mid_le + by (auto simp: less_eq_interval_def split_float_interval_bounds) + + from split_float_interval_realD[OF _ \x \\<^sub>r ivl\] consider "x \\<^sub>r ?ivl1" | "x \\<^sub>r ?ivl2" + by (auto simp: prod_eq_iff) + then show ?case proof cases case 1 from Suc.hyps[OF l this] - obtain l' u' ly uy where - "x \ {l' .. u'} \ real_of_float l \ l' \ real_of_float u' \ ?m \ cmp ly uy \ - approx_tse prec 0 t ((l' + u') * Float 1 (- 1)) 1 f [Some (l', u')] = Some (ly, uy)" + obtain ivl' ivly where + "x \\<^sub>r ivl' \ ivl' \ fst (split_float_interval ivl) \ cmp ivly \ + approx_tse prec 0 t (mid ivl') 1 f [Some ivl'] = Some ivly" by blast - with m_u show ?thesis - by (auto intro!: exI) + then show ?thesis + using subintervals + by (auto) next case 2 from Suc.hyps[OF u this] - obtain l' u' ly uy where - "x \ { l' .. u' } \ ?m \ real_of_float l' \ u' \ real_of_float u \ cmp ly uy \ - approx_tse prec 0 t ((l' + u') * Float 1 (- 1)) 1 f [Some (l', u')] = Some (ly, uy)" + obtain ivl' ivly where + "x \\<^sub>r ivl' \ ivl' \ snd (split_float_interval ivl) \ cmp ivly \ + approx_tse prec 0 t (mid ivl') 1 f [Some ivl'] = Some ivly" by blast - with m_u show ?thesis - by (auto intro!: exI) + then show ?thesis + using subintervals + by (auto) qed qed lemma approx_tse_form'_less: fixes x :: real - assumes tse: "approx_tse_form' prec t (Add a (Minus b)) s l u (\ l u. 0 < l)" - and x: "x \ {l .. u}" + assumes tse: "approx_tse_form' prec t (Add a (Minus b)) s ivl (\ ivl. 0 < lower ivl)" + and x: "x \\<^sub>r ivl" shows "interpret_floatarith b [x] < interpret_floatarith a [x]" proof - from approx_tse_form'[OF tse x] - obtain l' u' ly uy - where x': "x \ {l' .. u'}" - and "real_of_float l \ real_of_float l'" - and "real_of_float u' \ real_of_float u" and "0 < ly" - and tse: "approx_tse prec 0 t ((l' + u') * Float 1 (- 1)) 1 (Add a (Minus b)) [Some (l', u')] = Some (ly, uy)" + obtain ivl' ivly + where x': "x \\<^sub>r ivl'" + and "ivl' \ ivl" and "0 < lower ivly" + and tse: "approx_tse prec 0 t (mid ivl') 1 (Add a (Minus b)) [Some ivl'] = Some ivly" by blast - hence "bounded_by [x] [Some (l', u')]" + hence "bounded_by [x] [Some ivl']" by (auto simp add: bounded_by_def) - from approx_tse[OF this _ _ _ _ tse[symmetric], of l' u'] x' - have "ly \ interpret_floatarith a [x] - interpret_floatarith b [x]" - by auto - from order_less_le_trans[OF _ this, of 0] \0 < ly\ show ?thesis + from approx_tse[OF this _ _ _ _ tse, of ivl'] x' mid_le + have "lower ivly \ interpret_floatarith a [x] - interpret_floatarith b [x]" + by (auto simp: set_of_eq) + from order_less_le_trans[OF _ this, of 0] \0 < lower ivly\ show ?thesis by auto qed lemma approx_tse_form'_le: fixes x :: real - assumes tse: "approx_tse_form' prec t (Add a (Minus b)) s l u (\ l u. 0 \ l)" - and x: "x \ {l .. u}" + assumes tse: "approx_tse_form' prec t (Add a (Minus b)) s ivl (\ ivl. 0 \ lower ivl)" + and x: "x \\<^sub>r ivl" shows "interpret_floatarith b [x] \ interpret_floatarith a [x]" proof - from approx_tse_form'[OF tse x] - obtain l' u' ly uy - where x': "x \ {l' .. u'}" - and "l \ real_of_float l'" - and "real_of_float u' \ u" and "0 \ ly" - and tse: "approx_tse prec 0 t ((l' + u') * Float 1 (- 1)) 1 (Add a (Minus b)) [Some (l', u')] = Some (ly, uy)" + obtain ivl' ivly + where x': "x \\<^sub>r ivl'" + and "ivl' \ ivl" and "0 \ lower ivly" + and tse: "approx_tse prec 0 t (mid ivl') 1 (Add a (Minus b)) [Some (ivl')] = Some ivly" by blast - hence "bounded_by [x] [Some (l', u')]" by (auto simp add: bounded_by_def) - from approx_tse[OF this _ _ _ _ tse[symmetric], of l' u'] x' - have "ly \ interpret_floatarith a [x] - interpret_floatarith b [x]" - by auto - from order_trans[OF _ this, of 0] \0 \ ly\ show ?thesis + hence "bounded_by [x] [Some ivl']" by (auto simp add: bounded_by_def) + from approx_tse[OF this _ _ _ _ tse, of ivl'] x' mid_le + have "lower ivly \ interpret_floatarith a [x] - interpret_floatarith b [x]" + by (auto simp: set_of_eq) + from order_trans[OF _ this, of 0] \0 \ lower ivly\ show ?thesis by auto qed fun approx_tse_concl where -"approx_tse_concl prec t (Less lf rt) s l u l' u' \ - approx_tse_form' prec t (Add rt (Minus lf)) s l u' (\ l u. 0 < l)" | -"approx_tse_concl prec t (LessEqual lf rt) s l u l' u' \ - approx_tse_form' prec t (Add rt (Minus lf)) s l u' (\ l u. 0 \ l)" | -"approx_tse_concl prec t (AtLeastAtMost x lf rt) s l u l' u' \ - (if approx_tse_form' prec t (Add x (Minus lf)) s l u' (\ l u. 0 \ l) then - approx_tse_form' prec t (Add rt (Minus x)) s l u' (\ l u. 0 \ l) else False)" | -"approx_tse_concl prec t (Conj f g) s l u l' u' \ - approx_tse_concl prec t f s l u l' u' \ approx_tse_concl prec t g s l u l' u'" | -"approx_tse_concl prec t (Disj f g) s l u l' u' \ - approx_tse_concl prec t f s l u l' u' \ approx_tse_concl prec t g s l u l' u'" | -"approx_tse_concl _ _ _ _ _ _ _ _ \ False" +"approx_tse_concl prec t (Less lf rt) s ivl ivl' \ + approx_tse_form' prec t (Add rt (Minus lf)) s (sup ivl ivl') (\ ivl. 0 < lower ivl)" | +"approx_tse_concl prec t (LessEqual lf rt) s ivl ivl' \ + approx_tse_form' prec t (Add rt (Minus lf)) s (sup ivl ivl') (\ ivl. 0 \ lower ivl)" | +"approx_tse_concl prec t (AtLeastAtMost x lf rt) s ivl ivl' \ + (if approx_tse_form' prec t (Add x (Minus lf)) s (sup ivl ivl') (\ ivl. 0 \ lower ivl) then + approx_tse_form' prec t (Add rt (Minus x)) s (sup ivl ivl') (\ ivl. 0 \ lower ivl) else False)" | +"approx_tse_concl prec t (Conj f g) s ivl ivl' \ + approx_tse_concl prec t f s ivl ivl' \ approx_tse_concl prec t g s ivl ivl'" | +"approx_tse_concl prec t (Disj f g) s ivl ivl' \ + approx_tse_concl prec t f s ivl ivl' \ approx_tse_concl prec t g s ivl ivl'" | +"approx_tse_concl _ _ _ _ _ _ \ False" definition "approx_tse_form prec t s f = @@ -1400,7 +924,7 @@ Bound x a b f \ x = Var 0 \ (case (approx prec a [None], approx prec b [None]) of - (Some (l, u), Some (l', u')) \ approx_tse_concl prec t f s l u l' u' + (Some ivl, Some ivl') \ approx_tse_concl prec t f s ivl ivl' | _ \ False) | _ \ False)" @@ -1409,9 +933,9 @@ shows "interpret_form f [x]" proof (cases f) case f_def: (Bound i a b f') - with assms obtain l u l' u' - where a: "approx prec a [None] = Some (l, u)" - and b: "approx prec b [None] = Some (l', u')" + with assms obtain ivl ivl' + where a: "approx prec a [None] = Some ivl" + and b: "approx prec b [None] = Some ivl'" unfolding approx_tse_form_def by (auto elim!: case_optionE) from f_def assms have "i = Var 0" @@ -1421,30 +945,31 @@ { let ?f = "\z. interpret_floatarith z [x]" assume "?f i \ { ?f a .. ?f b }" - with approx[OF _ a[symmetric], of "[x]"] approx[OF _ b[symmetric], of "[x]"] - have bnd: "x \ { l .. u'}" unfolding bounded_by_def i by auto + with approx[OF _ a, of "[x]"] approx[OF _ b, of "[x]"] + have bnd: "x \\<^sub>r sup ivl ivl'" unfolding bounded_by_def i + by (auto simp: set_of_eq sup_float_def inf_float_def min_def max_def) have "interpret_form f' [x]" using assms[unfolded f_def] proof (induct f') case (Less lf rt) with a b - have "approx_tse_form' prec t (Add rt (Minus lf)) s l u' (\ l u. 0 < l)" + have "approx_tse_form' prec t (Add rt (Minus lf)) s (sup ivl ivl') (\ ivl. 0 < lower ivl)" unfolding approx_tse_form_def by auto from approx_tse_form'_less[OF this bnd] show ?case using Less by auto next case (LessEqual lf rt) with f_def a b assms - have "approx_tse_form' prec t (Add rt (Minus lf)) s l u' (\ l u. 0 \ l)" + have "approx_tse_form' prec t (Add rt (Minus lf)) s (sup ivl ivl') (\ ivl. 0 \ lower ivl)" unfolding approx_tse_form_def by auto from approx_tse_form'_le[OF this bnd] show ?case using LessEqual by auto next case (AtLeastAtMost x lf rt) with f_def a b assms - have "approx_tse_form' prec t (Add rt (Minus x)) s l u' (\ l u. 0 \ l)" - and "approx_tse_form' prec t (Add x (Minus lf)) s l u' (\ l u. 0 \ l)" + have "approx_tse_form' prec t (Add rt (Minus x)) s (sup ivl ivl') (\ ivl. 0 \ lower ivl)" + and "approx_tse_form' prec t (Add x (Minus lf)) s (sup ivl ivl') (\ ivl. 0 \ lower ivl)" unfolding approx_tse_form_def lazy_conj by (auto split: if_split_asm) from approx_tse_form'_le[OF this(1) bnd] approx_tse_form'_le[OF this(2) bnd] show ?case using AtLeastAtMost by auto @@ -1455,14 +980,14 @@ text \\<^term>\approx_form_eval\ is only used for the {\tt value}-command.\ -fun approx_form_eval :: "nat \ form \ (float * float) option list \ (float * float) option list" where +fun approx_form_eval :: "nat \ form \ (float interval) option list \ (float interval) option list" where "approx_form_eval prec (Bound (Var n) a b f) bs = (case (approx prec a bs, approx prec b bs) - of (Some (l, _), Some (_, u)) \ approx_form_eval prec f (bs[n := Some (l, u)]) + of (Some ivl1, Some ivl2) \ approx_form_eval prec f (bs[n := Some (sup ivl1 ivl2)]) | _ \ bs)" | "approx_form_eval prec (Assign (Var n) a f) bs = (case (approx prec a bs) - of (Some (l, u)) \ approx_form_eval prec f (bs[n := Some (l, u)]) + of (Some ivl) \ approx_form_eval prec f (bs[n := Some ivl]) | _ \ bs)" | "approx_form_eval prec (Less a b) bs = bs @ [approx prec a bs, approx prec b bs]" | "approx_form_eval prec (LessEqual a b) bs = bs @ [approx prec a bs, approx prec b bs]" | @@ -1473,105 +998,71 @@ subsection \Implement proof method \texttt{approximation}\ -oracle approximation_oracle = \fn (thy, t) => -let - fun bad t = error ("Bad term: " ^ Syntax.string_of_term_global thy t); +ML \ +val _ = \ \Trusting the oracle \@{oracle_name "holds_by_evaluation"} +signature APPROXIMATION_COMPUTATION = sig +val approx_bool: Proof.context -> term -> term +val approx_arith: Proof.context -> term -> term +val approx_form_eval: Proof.context -> term -> term +val approx_conv: Proof.context -> conv +end + +structure Approximation_Computation : APPROXIMATION_COMPUTATION = struct + + fun approx_conv ctxt ct = + @{computation_check + terms: Trueprop + "0 :: nat" "1 :: nat" "2 :: nat" "3 :: nat" Suc + "(+)::nat\nat\nat" "(-)::nat\nat\nat" "(*)::nat\nat\nat" + "0 :: int" "1 :: int" "2 :: int" "3 :: int" "-1 :: int" + "(+)::int\int\int" "(-)::int\int\int" "(*)::int\int\int" "uminus::int\int" + "replicate :: _ \ (float interval) option \ _" + "interval_of::float\float interval" + approx' + approx_form + approx_tse_form + approx_form_eval + datatypes: bool + int + nat + integer + "nat list" + float + "(float interval) option list" + floatarith + form + } ctxt ct fun term_of_bool true = \<^term>\True\ | term_of_bool false = \<^term>\False\; val mk_int = HOLogic.mk_number \<^typ>\int\ o @{code integer_of_int}; - fun dest_int (\<^term>\int_of_integer\ $ j) = @{code int_of_integer} (snd (HOLogic.dest_number j)) - | dest_int i = @{code int_of_integer} (snd (HOLogic.dest_number i)); fun term_of_float (@{code Float} (k, l)) = \<^term>\Float\ $ mk_int k $ mk_int l; - fun term_of_float_float_option NONE = \<^term>\None :: (float \ float) option\ - | term_of_float_float_option (SOME ff) = \<^term>\Some :: float \ float \ _\ - $ HOLogic.mk_prod (apply2 term_of_float ff); - - val term_of_float_float_option_list = - HOLogic.mk_list \<^typ>\(float \ float) option\ o map term_of_float_float_option; - - fun nat_of_term t = @{code nat_of_integer} - (HOLogic.dest_nat t handle TERM _ => snd (HOLogic.dest_number t)); - - fun float_of_term (\<^term>\Float\ $ k $ l) = - @{code Float} (dest_int k, dest_int l) - | float_of_term t = bad t; + fun term_of_float_interval x = @{term "Interval::_\float interval"} $ + HOLogic.mk_prod + (apply2 term_of_float (@{code lowerF} x, @{code upperF} x)) - fun floatarith_of_term (\<^term>\Add\ $ a $ b) = @{code Add} (floatarith_of_term a, floatarith_of_term b) - | floatarith_of_term (\<^term>\Minus\ $ a) = @{code Minus} (floatarith_of_term a) - | floatarith_of_term (\<^term>\Mult\ $ a $ b) = @{code Mult} (floatarith_of_term a, floatarith_of_term b) - | floatarith_of_term (\<^term>\Inverse\ $ a) = @{code Inverse} (floatarith_of_term a) - | floatarith_of_term (\<^term>\Cos\ $ a) = @{code Cos} (floatarith_of_term a) - | floatarith_of_term (\<^term>\Arctan\ $ a) = @{code Arctan} (floatarith_of_term a) - | floatarith_of_term (\<^term>\Abs\ $ a) = @{code Abs} (floatarith_of_term a) - | floatarith_of_term (\<^term>\Max\ $ a $ b) = @{code Max} (floatarith_of_term a, floatarith_of_term b) - | floatarith_of_term (\<^term>\Min\ $ a $ b) = @{code Min} (floatarith_of_term a, floatarith_of_term b) - | floatarith_of_term \<^term>\Pi\ = @{code Pi} - | floatarith_of_term (\<^term>\Sqrt\ $ a) = @{code Sqrt} (floatarith_of_term a) - | floatarith_of_term (\<^term>\Exp\ $ a) = @{code Exp} (floatarith_of_term a) - | floatarith_of_term (\<^term>\Powr\ $ a $ b) = @{code Powr} (floatarith_of_term a, floatarith_of_term b) - | floatarith_of_term (\<^term>\Ln\ $ a) = @{code Ln} (floatarith_of_term a) - | floatarith_of_term (\<^term>\Power\ $ a $ n) = - @{code Power} (floatarith_of_term a, nat_of_term n) - | floatarith_of_term (\<^term>\Floor\ $ a) = @{code Floor} (floatarith_of_term a) - | floatarith_of_term (\<^term>\Var\ $ n) = @{code Var} (nat_of_term n) - | floatarith_of_term (\<^term>\Num\ $ m) = @{code Num} (float_of_term m) - | floatarith_of_term t = bad t; + fun term_of_float_interval_option NONE = \<^term>\None :: (float interval) option\ + | term_of_float_interval_option (SOME ff) = \<^term>\Some :: float interval \ _\ + $ (term_of_float_interval ff); + + val term_of_float_interval_option_list = + HOLogic.mk_list \<^typ>\(float interval) option\ o map term_of_float_interval_option; - fun form_of_term (\<^term>\Bound\ $ a $ b $ c $ p) = @{code Bound} - (floatarith_of_term a, floatarith_of_term b, floatarith_of_term c, form_of_term p) - | form_of_term (\<^term>\Assign\ $ a $ b $ p) = @{code Assign} - (floatarith_of_term a, floatarith_of_term b, form_of_term p) - | form_of_term (\<^term>\Less\ $ a $ b) = @{code Less} - (floatarith_of_term a, floatarith_of_term b) - | form_of_term (\<^term>\LessEqual\ $ a $ b) = @{code LessEqual} - (floatarith_of_term a, floatarith_of_term b) - | form_of_term (\<^term>\Conj\ $ a $ b) = @{code Conj} - (form_of_term a, form_of_term b) - | form_of_term (\<^term>\Disj\ $ a $ b) = @{code Disj} - (form_of_term a, form_of_term b) - | form_of_term (\<^term>\AtLeastAtMost\ $ a $ b $ c) = @{code AtLeastAtMost} - (floatarith_of_term a, floatarith_of_term b, floatarith_of_term c) - | form_of_term t = bad t; + val approx_bool = @{computation bool} + (fn _ => fn x => case x of SOME b => term_of_bool b + | NONE => error "Computation approx_bool failed.") + val approx_arith = @{computation "float interval option"} + (fn _ => fn x => case x of SOME ffo => term_of_float_interval_option ffo + | NONE => error "Computation approx_arith failed.") + val approx_form_eval = @{computation "float interval option list"} + (fn _ => fn x => case x of SOME ffos => term_of_float_interval_option_list ffos + | NONE => error "Computation approx_form_eval failed.") - fun float_float_option_of_term \<^term>\None :: (float \ float) option\ = NONE - | float_float_option_of_term (\<^term>\Some :: float \ float \ _\ $ ff) = - SOME (apply2 float_of_term (HOLogic.dest_prod ff)) - | float_float_option_of_term (\<^term>\approx'\ $ n $ a $ ffs) = @{code approx'} - (nat_of_term n) (floatarith_of_term a) (float_float_option_list_of_term ffs) - | float_float_option_of_term t = bad t - and float_float_option_list_of_term - (\<^term>\replicate :: _ \ (float \ float) option \ _\ $ n $ \<^term>\None :: (float \ float) option\) = - @{code replicate} (nat_of_term n) NONE - | float_float_option_list_of_term (\<^term>\approx_form_eval\ $ n $ p $ ffs) = - @{code approx_form_eval} (nat_of_term n) (form_of_term p) (float_float_option_list_of_term ffs) - | float_float_option_list_of_term t = map float_float_option_of_term - (HOLogic.dest_list t); - - val nat_list_of_term = map nat_of_term o HOLogic.dest_list ; - - fun bool_of_term (\<^term>\approx_form\ $ n $ p $ ffs $ ms) = @{code approx_form} - (nat_of_term n) (form_of_term p) (float_float_option_list_of_term ffs) (nat_list_of_term ms) - | bool_of_term (\<^term>\approx_tse_form\ $ m $ n $ q $ p) = - @{code approx_tse_form} (nat_of_term m) (nat_of_term n) (nat_of_term q) (form_of_term p) - | bool_of_term t = bad t; - - fun eval t = case fastype_of t - of \<^typ>\bool\ => - (term_of_bool o bool_of_term) t - | \<^typ>\(float \ float) option\ => - (term_of_float_float_option o float_float_option_of_term) t - | \<^typ>\(float \ float) option list\ => - (term_of_float_float_option_list o float_float_option_list_of_term) t - | _ => bad t; - - val normalize = eval o Envir.beta_norm o Envir.eta_long []; - -in Thm.global_cterm_of thy (Logic.mk_equals (t, normalize t)) end +end \ lemma intervalE: "a \ x \ x \ b \ \ x \ { a .. b } \ P\ \ P" diff -r c1b63124245c -r ddd4aefc540f src/HOL/Decision_Procs/Approximation_Bounds.thy --- a/src/HOL/Decision_Procs/Approximation_Bounds.thy Tue Nov 05 14:57:41 2019 +0100 +++ b/src/HOL/Decision_Procs/Approximation_Bounds.thy Tue Nov 05 10:02:09 2019 -0500 @@ -11,13 +11,15 @@ theory Approximation_Bounds imports Complex_Main - "HOL-Library.Float" + "HOL-Library.Interval_Float" Dense_Linear_Order begin declare powr_neg_one [simp] declare powr_neg_numeral [simp] +context includes interval.lifting begin + section "Horner Scheme" subsection \Define auxiliary helper \horner\ function\ @@ -193,6 +195,44 @@ l1 \ x ^ n \ x ^ n \ u1" using float_power_bnds by auto +lift_definition power_float_interval :: "nat \ nat \ float interval \ float interval" + is "\p n (l, u). float_power_bnds p n l u" + using float_power_bnds + by (auto simp: bnds_power dest!: float_power_bnds[OF sym]) + +lemma lower_power_float_interval: + "lower (power_float_interval p n x) = fst (float_power_bnds p n (lower x) (upper x))" + by transfer auto +lemma upper_power_float_interval: + "upper (power_float_interval p n x) = snd (float_power_bnds p n (lower x) (upper x))" + by transfer auto + +lemma power_float_intervalI: "x \\<^sub>r X \ x ^ n \\<^sub>r power_float_interval p n X" + using float_power_bnds[OF prod.collapse] + by (auto simp: set_of_eq lower_power_float_interval upper_power_float_interval) + +lemma power_float_interval_mono: + "set_of (power_float_interval prec n A) + \ set_of (power_float_interval prec n B)" + if "set_of A \ set_of B" +proof - + define la where "la = real_of_float (lower A)" + define ua where "ua = real_of_float (upper A)" + define lb where "lb = real_of_float (lower B)" + define ub where "ub = real_of_float (upper B)" + have ineqs: "lb \ la" "la \ ua" "ua \ ub" "lb \ ub" + using that lower_le_upper[of A] lower_le_upper[of B] + by (auto simp: la_def ua_def lb_def ub_def set_of_eq) + show ?thesis + using ineqs + by (simp add: set_of_subset_iff float_power_bnds_def max_def + power_down_fl.rep_eq power_up_fl.rep_eq + lower_power_float_interval upper_power_float_interval + la_def[symmetric] ua_def[symmetric] lb_def[symmetric] ub_def[symmetric]) + (auto intro!: power_down_mono power_up_mono intro: order_trans[where y=0]) +qed + + section \Approximation utility functions\ definition bnds_mult :: "nat \ float \ float \ float \ float \ float \ float" where @@ -220,6 +260,42 @@ ultimately show ?thesis by simp qed +lift_definition mult_float_interval::"nat \ float interval \ float interval \ float interval" + is "\prec. \(a1, a2). \(b1, b2). bnds_mult prec a1 a2 b1 b2" + by (auto dest!: bnds_mult[OF sym]) + +lemma lower_mult_float_interval: + "lower (mult_float_interval p x y) = fst (bnds_mult p (lower x) (upper x) (lower y) (upper y))" + by transfer auto +lemma upper_mult_float_interval: + "upper (mult_float_interval p x y) = snd (bnds_mult p (lower x) (upper x) (lower y) (upper y))" + by transfer auto + +lemma mult_float_interval: + "set_of (real_interval A) * set_of (real_interval B) \ + set_of (real_interval (mult_float_interval prec A B))" +proof - + let ?bm = "bnds_mult prec (lower A) (upper A) (lower B) (upper B)" + show ?thesis + using bnds_mult[of "fst ?bm" "snd ?bm", simplified, OF refl] + by (auto simp: set_of_eq set_times_def upper_mult_float_interval lower_mult_float_interval) +qed + +lemma mult_float_intervalI: + "x * y \\<^sub>r mult_float_interval prec A B" + if "x \\<^sub>i real_interval A" "y \\<^sub>i real_interval B" + using mult_float_interval[of A B] that + by (auto simp: ) + +lemma mult_float_interval_mono: + "set_of (mult_float_interval prec A B) \ set_of (mult_float_interval prec X Y)" + if "set_of A \ set_of X" "set_of B \ set_of Y" + using that + apply transfer + unfolding bnds_mult_def atLeastatMost_subset_iff float_plus_down.rep_eq float_plus_up.rep_eq + by (auto simp: float_plus_down.rep_eq float_plus_up.rep_eq mult_float_mono1 mult_float_mono2) + + definition map_bnds :: "(nat \ float \ float) \ (nat \ float \ float) \ nat \ (float \ float) \ (float \ float)" where "map_bnds lb ub prec = (\(l,u). (lb prec l, ub prec u))" @@ -456,6 +532,25 @@ show "sqrt x \ u" unfolding u using bnds_sqrt'[of ux prec] by auto qed +lift_definition sqrt_float_interval::"nat \ float interval \ float interval" + is "\prec. \(lx, ux). (lb_sqrt prec lx, ub_sqrt prec ux)" + using bnds_sqrt' + by auto (meson order_trans real_sqrt_le_iff) + +lemma lower_float_interval: "lower (sqrt_float_interval prec X) = lb_sqrt prec (lower X)" + by transfer auto + +lemma upper_float_interval: "upper (sqrt_float_interval prec X) = ub_sqrt prec (upper X)" + by transfer auto + +lemma sqrt_float_interval: + "sqrt ` set_of (real_interval X) \ set_of (real_interval (sqrt_float_interval prec X))" + using bnds_sqrt + by (auto simp: set_of_eq lower_float_interval upper_float_interval) + +lemma sqrt_float_intervalI: "sqrt x \\<^sub>r sqrt_float_interval p X" if "x \\<^sub>r X" + using sqrt_float_interval[of X p] that + by auto section "Arcus tangens and \" @@ -711,6 +806,18 @@ ultimately show ?thesis by auto qed +lift_definition pi_float_interval::"nat \ float interval" is "\prec. (lb_pi prec, ub_pi prec)" + using pi_boundaries + by (auto intro: order_trans) + +lemma lower_pi_float_interval: "lower (pi_float_interval prec) = lb_pi prec" + by transfer auto +lemma upper_pi_float_interval: "upper (pi_float_interval prec) = ub_pi prec" + by transfer auto +lemma pi_float_interval: "pi \ set_of (real_interval (pi_float_interval prec))" + using pi_boundaries + by (auto simp: set_of_eq lower_pi_float_interval upper_pi_float_interval) + subsection "Compute arcus tangens in the entire domain" @@ -1056,6 +1163,32 @@ qed qed +lemmas [simp del] = lb_arctan.simps ub_arctan.simps + +lemma lb_arctan: "arctan (real_of_float x) \ y \ real_of_float (lb_arctan prec x) \ y" + and ub_arctan: "y \ arctan x \ y \ ub_arctan prec x" + for x::float and y::real + using arctan_boundaries[of x prec] by auto + +lift_definition arctan_float_interval :: "nat \ float interval \ float interval" + is "\prec. \(lx, ux). (lb_arctan prec lx, ub_arctan prec ux)" + by (auto intro!: lb_arctan ub_arctan arctan_monotone') + +lemma lower_arctan_float_interval: "lower (arctan_float_interval p x) = lb_arctan p (lower x)" + by transfer auto +lemma upper_arctan_float_interval: "upper (arctan_float_interval p x) = ub_arctan p (upper x)" + by transfer auto + +lemma arctan_float_interval: + "arctan ` set_of (real_interval x) \ set_of (real_interval (arctan_float_interval p x))" + by (auto simp: set_of_eq lower_arctan_float_interval upper_arctan_float_interval + intro!: lb_arctan ub_arctan arctan_monotone') + +lemma arctan_float_intervalI: + "arctan x \\<^sub>r arctan_float_interval p X" if "x \\<^sub>r X" + using arctan_float_interval[of X p] that + by auto + section "Sinus and Cosinus" @@ -1794,6 +1927,31 @@ qed qed +lemma bnds_cos_lower: "\x. real_of_float xl \ x \ x \ real_of_float xu \ cos x \ y \ real_of_float (fst (bnds_cos prec xl xu)) \ y" + and bnds_cos_upper: "\x. real_of_float xl \ x \ x \ real_of_float xu \ y \ cos x \ y \ real_of_float (snd (bnds_cos prec xl xu))" + for xl xu::float and y::real + using bnds_cos[of "fst (bnds_cos prec xl xu)" "snd (bnds_cos prec xl xu)" prec] + by force+ + +lift_definition cos_float_interval :: "nat \ float interval \ float interval" + is "\prec. \(lx, ux). bnds_cos prec lx ux" + using bnds_cos + by auto (metis (full_types) order_refl order_trans) + +lemma lower_cos_float_interval: "lower (cos_float_interval p x) = fst (bnds_cos p (lower x) (upper x))" + by transfer auto +lemma upper_cos_float_interval: "upper (cos_float_interval p x) = snd (bnds_cos p (lower x) (upper x))" + by transfer auto + +lemma cos_float_interval: + "cos ` set_of (real_interval x) \ set_of (real_interval (cos_float_interval p x))" + by (auto simp: set_of_eq bnds_cos_lower bnds_cos_upper lower_cos_float_interval + upper_cos_float_interval) + +lemma cos_float_intervalI: "cos x \\<^sub>r cos_float_interval p X" if "x \\<^sub>r X" + using cos_float_interval[of X p] that + by auto + section "Exponential function" @@ -2137,6 +2295,31 @@ qed qed +lemmas [simp del] = lb_exp.simps ub_exp.simps + +lemma lb_exp: "exp x \ y \ lb_exp prec x \ y" + and ub_exp: "y \ exp x \ y \ ub_exp prec x" + for x::float and y::real using exp_boundaries[of x prec] by auto + +lift_definition exp_float_interval :: "nat \ float interval \ float interval" + is "\prec. \(lx, ux). (lb_exp prec lx, ub_exp prec ux)" + by (auto simp: lb_exp ub_exp) + +lemma lower_exp_float_interval: "lower (exp_float_interval p x) = lb_exp p (lower x)" + by transfer auto +lemma upper_exp_float_interval: "upper (exp_float_interval p x) = ub_exp p (upper x)" + by transfer auto + +lemma exp_float_interval: + "exp ` set_of (real_interval x) \ set_of (real_interval (exp_float_interval p x))" + using exp_boundaries + by (auto simp: set_of_eq lower_exp_float_interval upper_exp_float_interval lb_exp ub_exp) + +lemma exp_float_intervalI: + "exp x \\<^sub>r exp_float_interval p X" if "x \\<^sub>r X" + using exp_float_interval[of X p] that + by auto + section "Logarithm" @@ -2211,7 +2394,7 @@ also have "\ \ ?ub" unfolding power_Suc2 mult.assoc[symmetric] times_float.rep_eq sum_distrib_right[symmetric] unfolding mult.commute[of "real_of_float x"] od - using horner_bounds(2)[where G="\ i k. Suc k" and F="\x. x" and f="\x. x" and lb="\n i k x. lb_ln_horner prec n k x" and ub="\n i k x. ub_ln_horner prec n k x" and j'=1 and n="2*od+1", + using horner_bounds(2)[where G="\ i k. Suc k" and F="\x. x" and f="\x. x" and lb="\n i k x. lb_ln_horner prec n k x" and ub="\n i k x. ub_ln_horner prec n k x" and j'=1 and n="2 * od + 1", OF \0 \ real_of_float x\ refl lb_ln_horner.simps ub_ln_horner.simps] \0 \ real_of_float x\ unfolding real_of_float_power by (rule mult_right_mono) @@ -2703,6 +2886,46 @@ ultimately show "l \ ln x \ ln x \ u" .. qed +lemmas [simp del] = lb_ln.simps ub_ln.simps + +lemma lb_lnD: + "y \ ln x \ 0 < real_of_float x" if "lb_ln prec x = Some y" + using lb_ln[OF that[symmetric]] by auto + +lemma ub_lnD: + "ln x \ y\ 0 < real_of_float x" if "ub_ln prec x = Some y" + using ub_ln[OF that[symmetric]] by auto + +lift_definition(code_dt) ln_float_interval :: "nat \ float interval \ float interval option" + is "\prec. \(lx, ux). + Option.bind (lb_ln prec lx) (\l. + Option.bind (ub_ln prec ux) (\u. Some (l, u)))" + by (auto simp: pred_option_def bind_eq_Some_conv ln_le_cancel_iff[symmetric] + simp del: ln_le_cancel_iff dest!: lb_lnD ub_lnD) + +lemma ln_float_interval_eq_Some_conv: + "ln_float_interval p x = Some y \ + lb_ln p (lower x) = Some (lower y) \ ub_ln p (upper x) = Some (upper y)" + by transfer (auto simp: bind_eq_Some_conv) + +lemma ln_float_interval: "ln ` set_of (real_interval x) \ set_of (real_interval y)" + if "ln_float_interval p x = Some y" + using that lb_ln[of "lower y" p "lower x"] + ub_ln[of "lower y" p "lower x"] + apply (auto simp add: set_of_eq ln_float_interval_eq_Some_conv ln_le_cancel_iff) + apply (meson less_le_trans ln_less_cancel_iff not_le) + by (meson less_le_trans ln_less_cancel_iff not_le ub_lnD) + +lemma ln_float_intervalI: + "ln x \ set_of' (ln_float_interval p X)" if "x \\<^sub>r X" + using ln_float_interval[of p X] that + by (auto simp: set_of'_def split: option.splits) + +lemma ln_float_interval_eqI: + "ln x \\<^sub>r IVL" if "ln_float_interval p X = Some IVL" "x \\<^sub>r X" + using ln_float_intervalI[of x X p] that + by (auto simp: set_of'_def split: option.splits) + section \Real power function\ @@ -2719,8 +2942,6 @@ Some (map_bnds lb_exp ub_exp prec (bnds_mult prec (the (lb_ln prec l1)) (the (ub_ln prec u1)) l2 u2)))" -lemmas [simp del] = lb_exp.simps ub_exp.simps - lemma mono_exp_real: "mono (exp :: real \ real)" by (auto simp: mono_def) @@ -2798,4 +3019,29 @@ qed qed +lift_definition(code_dt) powr_float_interval :: "nat \ float interval \ float interval \ float interval option" + is "\prec. \(l1, u1). \(l2, u2). bnds_powr prec l1 u1 l2 u2" + by (auto simp: pred_option_def dest!: bnds_powr[OF sym]) + +lemma powr_float_interval: + "{x powr y | x y. x \ set_of (real_interval X) \ y \ set_of (real_interval Y)} + \ set_of (real_interval R)" + if "powr_float_interval prec X Y = Some R" + using that + by transfer (auto dest!: bnds_powr[OF sym]) + +lemma powr_float_intervalI: + "x powr y \ set_of' (powr_float_interval p X Y)" + if "x \\<^sub>r X" "y \\<^sub>r Y" + using powr_float_interval[of p X Y] that + by (auto simp: set_of'_def split: option.splits) + +lemma powr_float_interval_eqI: + "x powr y \\<^sub>r IVL" + if "powr_float_interval p X Y = Some IVL" "x \\<^sub>r X" "y \\<^sub>r Y" + using powr_float_intervalI[of x X y Y p] that + by (auto simp: set_of'_def split: option.splits) + end + +end \ No newline at end of file diff -r c1b63124245c -r ddd4aefc540f src/HOL/Decision_Procs/approximation.ML --- a/src/HOL/Decision_Procs/approximation.ML Tue Nov 05 14:57:41 2019 +0100 +++ b/src/HOL/Decision_Procs/approximation.ML Tue Nov 05 10:02:09 2019 -0500 @@ -10,7 +10,7 @@ val approximation_tac : int -> (string * int) list -> int option -> Proof.context -> int -> tactic end -structure Approximation: APPROXIMATION = +structure Approximation = struct fun reorder_bounds_tac ctxt prems i = @@ -42,18 +42,14 @@ fold prepend_prem order all_tac end -fun approximation_conv ctxt ct = - approximation_oracle (Proof_Context.theory_of ctxt, Thm.term_of ct); - -fun approximate ctxt t = - approximation_oracle (Proof_Context.theory_of ctxt, t) - |> Thm.prop_of |> Logic.dest_equals |> snd; - -(* Should be in HOL.thy ? *) -fun gen_eval_tac conv ctxt = - CONVERSION - (Object_Logic.judgment_conv ctxt (Conv.params_conv (~1) (K (Conv.concl_conv (~1) conv)) ctxt)) - THEN' resolve_tac ctxt [TrueI] +fun approximate ctxt t = case fastype_of t + of \<^typ>\bool\ => + Approximation_Computation.approx_bool ctxt t + | \<^typ>\(float interval) option\ => + Approximation_Computation.approx_arith ctxt t + | \<^typ>\(float interval) option list\ => + Approximation_Computation.approx_form_eval ctxt t + | _ => error ("Bad term: " ^ Syntax.string_of_term ctxt t); fun rewrite_interpret_form_tac ctxt prec splitting taylor i st = let fun lookup_splitting (Free (name, _)) = @@ -125,14 +121,16 @@ | dest_float t = raise TERM ("dest_float", [t]) -fun dest_ivl (Const (\<^const_name>\Some\, _) $ - (Const (\<^const_name>\Pair\, _) $ u $ l)) = SOME (dest_float u, dest_float l) +fun dest_ivl + (Const (\<^const_name>\Some\, _) $ + (Const (\<^const_name>\Interval\, _) $ ((Const (\<^const_name>\Pair\, _) $ u $ l)))) = + SOME (dest_float u, dest_float l) | dest_ivl (Const (\<^const_name>\None\, _)) = NONE | dest_ivl t = raise TERM ("dest_result", [t]) fun mk_approx' prec t = (\<^const>\approx'\ $ HOLogic.mk_number \<^typ>\nat\ prec - $ t $ \<^term>\[] :: (float * float) option list\) + $ t $ \<^term>\[] :: (float interval) option list\) fun mk_approx_form_eval prec t xs = (\<^const>\approx_form_eval\ $ HOLogic.mk_number \<^typ>\nat\ prec @@ -241,8 +239,8 @@ |> HOLogic.dest_Trueprop |> dest_interpret_form |> (fn (data, xs) => - mk_approx_form_eval prec data (HOLogic.mk_list \<^typ>\(float * float) option\ - (map (fn _ => \<^term>\None :: (float * float) option\) (HOLogic.dest_list xs))) + mk_approx_form_eval prec data (HOLogic.mk_list \<^typ>\(float interval) option\ + (map (fn _ => \<^term>\None :: (float interval) option\) (HOLogic.dest_list xs))) |> approximate ctxt |> HOLogic.dest_list |> curry ListPair.zip (HOLogic.dest_list xs @ calculated_subterms arith_term) @@ -286,10 +284,11 @@ (opt_modes -- Parse.term >> (fn (modes, t) => Toplevel.keep (approximate_cmd modes t))); -fun approximation_tac prec splitting taylor ctxt i = - prepare_form_tac ctxt i - THEN reify_form_tac ctxt i - THEN rewrite_interpret_form_tac ctxt prec splitting taylor i - THEN gen_eval_tac (approximation_conv ctxt) ctxt i +fun approximation_tac prec splitting taylor ctxt = + prepare_form_tac ctxt + THEN' reify_form_tac ctxt + THEN' rewrite_interpret_form_tac ctxt prec splitting taylor + THEN' CONVERSION (Approximation_Computation.approx_conv ctxt) + THEN' resolve_tac ctxt [TrueI] end; diff -r c1b63124245c -r ddd4aefc540f src/HOL/Decision_Procs/approximation_generator.ML --- a/src/HOL/Decision_Procs/approximation_generator.ML Tue Nov 05 14:57:41 2019 +0100 +++ b/src/HOL/Decision_Procs/approximation_generator.ML Tue Nov 05 10:02:09 2019 -0500 @@ -92,6 +92,10 @@ fun real_of_Float (@{code Float} (m, e)) = real_of_man_exp (@{code integer_of_int} m) (@{code integer_of_int} e) +fun term_of_int i = (HOLogic.mk_number @{typ int} (@{code integer_of_int} i)) + +fun term_of_Float (@{code Float} (m, e)) = @{term Float} $ term_of_int m $ term_of_int e + fun is_True \<^term>\True\ = true | is_True _ = false @@ -129,8 +133,8 @@ \<^const>\approx_form\ $ HOLogic.mk_number \<^typ>\nat\ prec $ e $ - (HOLogic.mk_list \<^typ>\(float * float) option\ - (map (fn t => mk_Some \<^typ>\float * float\ $ HOLogic.mk_prod (t, t)) ts)) $ + (HOLogic.mk_list \<^typ>\(float interval) option\ + (map (fn t => mk_Some \<^typ>\float interval\ $ (\<^term>\interval_of::float\_\ $ t)) ts)) $ \<^term>\[] :: nat list\ in (if @@ -142,7 +146,7 @@ | IEEEReal.Unordered => false then let - val ts = map (fn x => snd x ()) rs + val ts = map (fn x => term_of_Float (fst x)) rs val ts' = map (AList.lookup op = (map dest_Free xs ~~ ts) #> the_default Term.dummy diff -r c1b63124245c -r ddd4aefc540f src/HOL/Library/Float.thy --- a/src/HOL/Library/Float.thy Tue Nov 05 14:57:41 2019 +0100 +++ b/src/HOL/Library/Float.thy Tue Nov 05 10:02:09 2019 -0500 @@ -1104,6 +1104,201 @@ end +lemma truncate_up_nonneg_mono: + assumes "0 \ x" "x \ y" + shows "truncate_up prec x \ truncate_up prec y" +proof - + consider "\log 2 x\ = \log 2 y\" | "\log 2 x\ \ \log 2 y\" "0 < x" | "x \ 0" + by arith + then show ?thesis + proof cases + case 1 + then show ?thesis + using assms + by (auto simp: truncate_up_def round_up_def intro!: ceiling_mono) + next + case 2 + from assms \0 < x\ have "log 2 x \ log 2 y" + by auto + with \\log 2 x\ \ \log 2 y\\ + have logless: "log 2 x < log 2 y" + by linarith + have flogless: "\log 2 x\ < \log 2 y\" + using \\log 2 x\ \ \log 2 y\\ \log 2 x \ log 2 y\ by linarith + have "truncate_up prec x = + real_of_int \x * 2 powr real_of_int (int prec - \log 2 x\ )\ * 2 powr - real_of_int (int prec - \log 2 x\)" + using assms by (simp add: truncate_up_def round_up_def) + also have "\x * 2 powr real_of_int (int prec - \log 2 x\)\ \ (2 ^ (Suc prec))" + proof (simp only: ceiling_le_iff) + have "x * 2 powr real_of_int (int prec - \log 2 x\) \ + x * (2 powr real (Suc prec) / (2 powr log 2 x))" + using real_of_int_floor_add_one_ge[of "log 2 x"] assms + by (auto simp: algebra_simps simp flip: powr_diff intro!: mult_left_mono) + then show "x * 2 powr real_of_int (int prec - \log 2 x\) \ real_of_int ((2::int) ^ (Suc prec))" + using \0 < x\ by (simp add: powr_realpow powr_add) + qed + then have "real_of_int \x * 2 powr real_of_int (int prec - \log 2 x\)\ \ 2 powr int (Suc prec)" + by (auto simp: powr_realpow powr_add) + (metis power_Suc of_int_le_numeral_power_cancel_iff) + also + have "2 powr - real_of_int (int prec - \log 2 x\) \ 2 powr - real_of_int (int prec - \log 2 y\ + 1)" + using logless flogless by (auto intro!: floor_mono) + also have "2 powr real_of_int (int (Suc prec)) \ + 2 powr (log 2 y + real_of_int (int prec - \log 2 y\ + 1))" + using assms \0 < x\ + by (auto simp: algebra_simps) + finally have "truncate_up prec x \ + 2 powr (log 2 y + real_of_int (int prec - \log 2 y\ + 1)) * 2 powr - real_of_int (int prec - \log 2 y\ + 1)" + by simp + also have "\ = 2 powr (log 2 y + real_of_int (int prec - \log 2 y\) - real_of_int (int prec - \log 2 y\))" + by (subst powr_add[symmetric]) simp + also have "\ = y" + using \0 < x\ assms + by (simp add: powr_add) + also have "\ \ truncate_up prec y" + by (rule truncate_up) + finally show ?thesis . + next + case 3 + then show ?thesis + using assms + by (auto intro!: truncate_up_le) + qed +qed + +lemma truncate_up_switch_sign_mono: + assumes "x \ 0" "0 \ y" + shows "truncate_up prec x \ truncate_up prec y" +proof - + note truncate_up_nonpos[OF \x \ 0\] + also note truncate_up_le[OF \0 \ y\] + finally show ?thesis . +qed + +lemma truncate_down_switch_sign_mono: + assumes "x \ 0" + and "0 \ y" + and "x \ y" + shows "truncate_down prec x \ truncate_down prec y" +proof - + note truncate_down_le[OF \x \ 0\] + also note truncate_down_nonneg[OF \0 \ y\] + finally show ?thesis . +qed + +lemma truncate_down_nonneg_mono: + assumes "0 \ x" "x \ y" + shows "truncate_down prec x \ truncate_down prec y" +proof - + consider "x \ 0" | "\log 2 \x\\ = \log 2 \y\\" | + "0 < x" "\log 2 \x\\ \ \log 2 \y\\" + by arith + then show ?thesis + proof cases + case 1 + with assms have "x = 0" "0 \ y" by simp_all + then show ?thesis + by (auto intro!: truncate_down_nonneg) + next + case 2 + then show ?thesis + using assms + by (auto simp: truncate_down_def round_down_def intro!: floor_mono) + next + case 3 + from \0 < x\ have "log 2 x \ log 2 y" "0 < y" "0 \ y" + using assms by auto + with \\log 2 \x\\ \ \log 2 \y\\\ + have logless: "log 2 x < log 2 y" and flogless: "\log 2 x\ < \log 2 y\" + unfolding atomize_conj abs_of_pos[OF \0 < x\] abs_of_pos[OF \0 < y\] + by (metis floor_less_cancel linorder_cases not_le) + have "2 powr prec \ y * 2 powr real prec / (2 powr log 2 y)" + using \0 < y\ by simp + also have "\ \ y * 2 powr real (Suc prec) / (2 powr (real_of_int \log 2 y\ + 1))" + using \0 \ y\ \0 \ x\ assms(2) + by (auto intro!: powr_mono divide_left_mono + simp: of_nat_diff powr_add powr_diff) + also have "\ = y * 2 powr real (Suc prec) / (2 powr real_of_int \log 2 y\ * 2)" + by (auto simp: powr_add) + finally have "(2 ^ prec) \ \y * 2 powr real_of_int (int (Suc prec) - \log 2 \y\\ - 1)\" + using \0 \ y\ + by (auto simp: powr_diff le_floor_iff powr_realpow powr_add) + then have "(2 ^ (prec)) * 2 powr - real_of_int (int prec - \log 2 \y\\) \ truncate_down prec y" + by (auto simp: truncate_down_def round_down_def) + moreover have "x \ (2 ^ prec) * 2 powr - real_of_int (int prec - \log 2 \y\\)" + proof - + have "x = 2 powr (log 2 \x\)" using \0 < x\ by simp + also have "\ \ (2 ^ (Suc prec )) * 2 powr - real_of_int (int prec - \log 2 \x\\)" + using real_of_int_floor_add_one_ge[of "log 2 \x\"] \0 < x\ + by (auto simp flip: powr_realpow powr_add simp: algebra_simps powr_mult_base le_powr_iff) + also + have "2 powr - real_of_int (int prec - \log 2 \x\\) \ 2 powr - real_of_int (int prec - \log 2 \y\\ + 1)" + using logless flogless \x > 0\ \y > 0\ + by (auto intro!: floor_mono) + finally show ?thesis + by (auto simp flip: powr_realpow simp: powr_diff assms of_nat_diff) + qed + ultimately show ?thesis + by (metis dual_order.trans truncate_down) + qed +qed + +lemma truncate_down_eq_truncate_up: "truncate_down p x = - truncate_up p (-x)" + and truncate_up_eq_truncate_down: "truncate_up p x = - truncate_down p (-x)" + by (auto simp: truncate_up_uminus_eq truncate_down_uminus_eq) + +lemma truncate_down_mono: "x \ y \ truncate_down p x \ truncate_down p y" + apply (cases "0 \ x") + apply (rule truncate_down_nonneg_mono, assumption+) + apply (simp add: truncate_down_eq_truncate_up) + apply (cases "0 \ y") + apply (auto intro: truncate_up_nonneg_mono truncate_up_switch_sign_mono) + done + +lemma truncate_up_mono: "x \ y \ truncate_up p x \ truncate_up p y" + by (simp add: truncate_up_eq_truncate_down truncate_down_mono) + +lemma truncate_up_nonneg: "0 \ truncate_up p x" if "0 \ x" + by (simp add: that truncate_up_le) + +lemma truncate_up_pos: "0 < truncate_up p x" if "0 < x" + by (meson less_le_trans that truncate_up) + +lemma truncate_up_less_zero_iff[simp]: "truncate_up p x < 0 \ x < 0" +proof - + have f1: "\n r. truncate_up n r + truncate_down n (- 1 * r) = 0" + by (simp add: truncate_down_uminus_eq) + have f2: "(\v0 v1. truncate_up v0 v1 + truncate_down v0 (- 1 * v1) = 0) = (\v0 v1. truncate_up v0 v1 = - 1 * truncate_down v0 (- 1 * v1))" + by (auto simp: truncate_up_eq_truncate_down) + have f3: "\x1. ((0::real) < x1) = (\ x1 \ 0)" + by fastforce + have "(- 1 * x \ 0) = (0 \ x)" + by force + then have "0 \ x \ \ truncate_down p (- 1 * x) \ 0" + using f3 by (meson truncate_down_pos) + then have "(0 \ truncate_up p x) \ (\ 0 \ x)" + using f2 f1 truncate_up_nonneg by force + then show ?thesis + by linarith +qed + +lemma truncate_up_nonneg_iff[simp]: "truncate_up p x \ 0 \ x \ 0" + using truncate_up_less_zero_iff[of p x] truncate_up_nonneg[of x] + by linarith + +lemma truncate_down_less_zero_iff[simp]: "truncate_down p x < 0 \ x < 0" + by (metis le_less_trans not_less_iff_gr_or_eq truncate_down truncate_down_pos truncate_down_zero) + +lemma truncate_down_nonneg_iff[simp]: "truncate_down p x \ 0 \ x \ 0" + using truncate_down_less_zero_iff[of p x] truncate_down_nonneg[of x p] + by linarith + +lemma truncate_down_eq_zero_iff[simp]: "truncate_down prec x = 0 \ x = 0" + by (metis not_less_iff_gr_or_eq truncate_down_less_zero_iff truncate_down_pos truncate_down_zero) + +lemma truncate_up_eq_zero_iff[simp]: "truncate_up prec x = 0 \ x = 0" + by (metis not_less_iff_gr_or_eq truncate_up_less_zero_iff truncate_up_pos truncate_up_zero) + subsection \Approximation of positive rationals\ @@ -1324,109 +1519,6 @@ end -subsection \Approximate Power\ - -lemma div2_less_self[termination_simp]: "odd n \ n div 2 < n" for n :: nat - by (simp add: odd_pos) - -fun power_down :: "nat \ real \ nat \ real" -where - "power_down p x 0 = 1" -| "power_down p x (Suc n) = - (if odd n then truncate_down (Suc p) ((power_down p x (Suc n div 2))\<^sup>2) - else truncate_down (Suc p) (x * power_down p x n))" - -fun power_up :: "nat \ real \ nat \ real" -where - "power_up p x 0 = 1" -| "power_up p x (Suc n) = - (if odd n then truncate_up p ((power_up p x (Suc n div 2))\<^sup>2) - else truncate_up p (x * power_up p x n))" - -lift_definition power_up_fl :: "nat \ float \ nat \ float" is power_up - by (induct_tac rule: power_up.induct) simp_all - -lift_definition power_down_fl :: "nat \ float \ nat \ float" is power_down - by (induct_tac rule: power_down.induct) simp_all - -lemma power_float_transfer[transfer_rule]: - "(rel_fun pcr_float (rel_fun (=) pcr_float)) (^) (^)" - unfolding power_def - by transfer_prover - -lemma compute_power_up_fl[code]: - "power_up_fl p x 0 = 1" - "power_up_fl p x (Suc n) = - (if odd n then float_round_up p ((power_up_fl p x (Suc n div 2))\<^sup>2) - else float_round_up p (x * power_up_fl p x n))" - and compute_power_down_fl[code]: - "power_down_fl p x 0 = 1" - "power_down_fl p x (Suc n) = - (if odd n then float_round_down (Suc p) ((power_down_fl p x (Suc n div 2))\<^sup>2) - else float_round_down (Suc p) (x * power_down_fl p x n))" - unfolding atomize_conj by transfer simp - -lemma power_down_pos: "0 < x \ 0 < power_down p x n" - by (induct p x n rule: power_down.induct) - (auto simp del: odd_Suc_div_two intro!: truncate_down_pos) - -lemma power_down_nonneg: "0 \ x \ 0 \ power_down p x n" - by (induct p x n rule: power_down.induct) - (auto simp del: odd_Suc_div_two intro!: truncate_down_nonneg mult_nonneg_nonneg) - -lemma power_down: "0 \ x \ power_down p x n \ x ^ n" -proof (induct p x n rule: power_down.induct) - case (2 p x n) - have ?case if "odd n" - proof - - from that 2 have "(power_down p x (Suc n div 2)) ^ 2 \ (x ^ (Suc n div 2)) ^ 2" - by (auto intro: power_mono power_down_nonneg simp del: odd_Suc_div_two) - also have "\ = x ^ (Suc n div 2 * 2)" - by (simp flip: power_mult) - also have "Suc n div 2 * 2 = Suc n" - using \odd n\ by presburger - finally show ?thesis - using that by (auto intro!: truncate_down_le simp del: odd_Suc_div_two) - qed - then show ?case - by (auto intro!: truncate_down_le mult_left_mono 2 mult_nonneg_nonneg power_down_nonneg) -qed simp - -lemma power_up: "0 \ x \ x ^ n \ power_up p x n" -proof (induct p x n rule: power_up.induct) - case (2 p x n) - have ?case if "odd n" - proof - - from that even_Suc have "Suc n = Suc n div 2 * 2" - by presburger - then have "x ^ Suc n \ (x ^ (Suc n div 2))\<^sup>2" - by (simp flip: power_mult) - also from that 2 have "\ \ (power_up p x (Suc n div 2))\<^sup>2" - by (auto intro: power_mono simp del: odd_Suc_div_two) - finally show ?thesis - using that by (auto intro!: truncate_up_le simp del: odd_Suc_div_two) - qed - then show ?case - by (auto intro!: truncate_up_le mult_left_mono 2) -qed simp - -lemmas power_up_le = order_trans[OF _ power_up] - and power_up_less = less_le_trans[OF _ power_up] - and power_down_le = order_trans[OF power_down] - -lemma power_down_fl: "0 \ x \ power_down_fl p x n \ x ^ n" - by transfer (rule power_down) - -lemma power_up_fl: "0 \ x \ x ^ n \ power_up_fl p x n" - by transfer (rule power_up) - -lemma real_power_up_fl: "real_of_float (power_up_fl p x n) = power_up p x n" - by transfer simp - -lemma real_power_down_fl: "real_of_float (power_down_fl p x n) = power_down p x n" - by transfer simp - - subsection \Approximate Addition\ definition "plus_down prec x y = truncate_down prec (x + y)" @@ -1794,6 +1886,332 @@ end +lemma plus_down_mono: "plus_down p a b \ plus_down p c d" if "a + b \ c + d" + by (auto simp: plus_down_def intro!: truncate_down_mono that) + +lemma plus_up_mono: "plus_up p a b \ plus_up p c d" if "a + b \ c + d" + by (auto simp: plus_up_def intro!: truncate_up_mono that) + +subsection \Approximate Multiplication\ + +lemma mult_mono_nonpos_nonneg: "a * b \ c * d" + if "a \ c" "a \ 0" "0 \ d" "d \ b" for a b c d::"'a::ordered_ring" + by (meson dual_order.trans mult_left_mono_neg mult_right_mono that) + +lemma mult_mono_nonneg_nonpos: "b * a \ d * c" + if "a \ c" "c \ 0" "0 \ d" "d \ b" for a b c d::"'a::ordered_ring" + by (meson dual_order.trans mult_right_mono_neg mult_left_mono that) + +lemma mult_mono_nonpos_nonpos: "a * b \ c * d" + if "a \ c" "a \ 0" "b \ d" "d \ 0" for a b c d::real + by (meson dual_order.trans mult_left_mono_neg mult_right_mono_neg that) + +lemma mult_float_mono1: + notes mono_rules = plus_down_mono add_mono nprt_mono nprt_le_zero zero_le_pprt pprt_mono + shows "a \ b \ ab \ bb \ + aa \ a \ + b \ ba \ + ac \ ab \ + bb \ bc \ + plus_down prec (nprt aa * pprt bc) + (plus_down prec (nprt ba * nprt bc) + (plus_down prec (pprt aa * pprt ac) + (pprt ba * nprt ac))) + \ plus_down prec (nprt a * pprt bb) + (plus_down prec (nprt b * nprt bb) + (plus_down prec (pprt a * pprt ab) + (pprt b * nprt ab)))" + apply (rule order_trans) + apply (rule mono_rules | assumption)+ + apply (rule mult_mono_nonpos_nonneg) + apply (rule mono_rules | assumption)+ + apply (rule mult_mono_nonpos_nonpos) + apply (rule mono_rules | assumption)+ + apply (rule mult_mono) + apply (rule mono_rules | assumption)+ + apply (rule mult_mono_nonneg_nonpos) + apply (rule mono_rules | assumption)+ + by (rule order_refl)+ + +lemma mult_float_mono2: + notes mono_rules = plus_up_mono add_mono nprt_mono nprt_le_zero zero_le_pprt pprt_mono + shows "a \ b \ + ab \ bb \ + aa \ a \ + b \ ba \ + ac \ ab \ + bb \ bc \ + plus_up prec (pprt b * pprt bb) + (plus_up prec (pprt a * nprt bb) + (plus_up prec (nprt b * pprt ab) + (nprt a * nprt ab))) + \ plus_up prec (pprt ba * pprt bc) + (plus_up prec (pprt aa * nprt bc) + (plus_up prec (nprt ba * pprt ac) + (nprt aa * nprt ac)))" + apply (rule order_trans) + apply (rule mono_rules | assumption)+ + apply (rule mult_mono) + apply (rule mono_rules | assumption)+ + apply (rule mult_mono_nonneg_nonpos) + apply (rule mono_rules | assumption)+ + apply (rule mult_mono_nonpos_nonneg) + apply (rule mono_rules | assumption)+ + apply (rule mult_mono_nonpos_nonpos) + apply (rule mono_rules | assumption)+ + by (rule order_refl)+ + + +subsection \Approximate Power\ + +lemma div2_less_self[termination_simp]: "odd n \ n div 2 < n" for n :: nat + by (simp add: odd_pos) + +fun power_down :: "nat \ real \ nat \ real" +where + "power_down p x 0 = 1" +| "power_down p x (Suc n) = + (if odd n then truncate_down (Suc p) ((power_down p x (Suc n div 2))\<^sup>2) + else truncate_down (Suc p) (x * power_down p x n))" + +fun power_up :: "nat \ real \ nat \ real" +where + "power_up p x 0 = 1" +| "power_up p x (Suc n) = + (if odd n then truncate_up p ((power_up p x (Suc n div 2))\<^sup>2) + else truncate_up p (x * power_up p x n))" + +lift_definition power_up_fl :: "nat \ float \ nat \ float" is power_up + by (induct_tac rule: power_up.induct) simp_all + +lift_definition power_down_fl :: "nat \ float \ nat \ float" is power_down + by (induct_tac rule: power_down.induct) simp_all + +lemma power_float_transfer[transfer_rule]: + "(rel_fun pcr_float (rel_fun (=) pcr_float)) (^) (^)" + unfolding power_def + by transfer_prover + +lemma compute_power_up_fl[code]: + "power_up_fl p x 0 = 1" + "power_up_fl p x (Suc n) = + (if odd n then float_round_up p ((power_up_fl p x (Suc n div 2))\<^sup>2) + else float_round_up p (x * power_up_fl p x n))" + and compute_power_down_fl[code]: + "power_down_fl p x 0 = 1" + "power_down_fl p x (Suc n) = + (if odd n then float_round_down (Suc p) ((power_down_fl p x (Suc n div 2))\<^sup>2) + else float_round_down (Suc p) (x * power_down_fl p x n))" + unfolding atomize_conj by transfer simp + +lemma power_down_pos: "0 < x \ 0 < power_down p x n" + by (induct p x n rule: power_down.induct) + (auto simp del: odd_Suc_div_two intro!: truncate_down_pos) + +lemma power_down_nonneg: "0 \ x \ 0 \ power_down p x n" + by (induct p x n rule: power_down.induct) + (auto simp del: odd_Suc_div_two intro!: truncate_down_nonneg mult_nonneg_nonneg) + +lemma power_down: "0 \ x \ power_down p x n \ x ^ n" +proof (induct p x n rule: power_down.induct) + case (2 p x n) + have ?case if "odd n" + proof - + from that 2 have "(power_down p x (Suc n div 2)) ^ 2 \ (x ^ (Suc n div 2)) ^ 2" + by (auto intro: power_mono power_down_nonneg simp del: odd_Suc_div_two) + also have "\ = x ^ (Suc n div 2 * 2)" + by (simp flip: power_mult) + also have "Suc n div 2 * 2 = Suc n" + using \odd n\ by presburger + finally show ?thesis + using that by (auto intro!: truncate_down_le simp del: odd_Suc_div_two) + qed + then show ?case + by (auto intro!: truncate_down_le mult_left_mono 2 mult_nonneg_nonneg power_down_nonneg) +qed simp + +lemma power_up: "0 \ x \ x ^ n \ power_up p x n" +proof (induct p x n rule: power_up.induct) + case (2 p x n) + have ?case if "odd n" + proof - + from that even_Suc have "Suc n = Suc n div 2 * 2" + by presburger + then have "x ^ Suc n \ (x ^ (Suc n div 2))\<^sup>2" + by (simp flip: power_mult) + also from that 2 have "\ \ (power_up p x (Suc n div 2))\<^sup>2" + by (auto intro: power_mono simp del: odd_Suc_div_two) + finally show ?thesis + using that by (auto intro!: truncate_up_le simp del: odd_Suc_div_two) + qed + then show ?case + by (auto intro!: truncate_up_le mult_left_mono 2) +qed simp + +lemmas power_up_le = order_trans[OF _ power_up] + and power_up_less = less_le_trans[OF _ power_up] + and power_down_le = order_trans[OF power_down] + +lemma power_down_fl: "0 \ x \ power_down_fl p x n \ x ^ n" + by transfer (rule power_down) + +lemma power_up_fl: "0 \ x \ x ^ n \ power_up_fl p x n" + by transfer (rule power_up) + +lemma real_power_up_fl: "real_of_float (power_up_fl p x n) = power_up p x n" + by transfer simp + +lemma real_power_down_fl: "real_of_float (power_down_fl p x n) = power_down p x n" + by transfer simp + +lemmas [simp del] = power_down.simps(2) power_up.simps(2) + +lemmas power_down_simp = power_down.simps(2) +lemmas power_up_simp = power_up.simps(2) + +lemma power_down_even_nonneg: "even n \ 0 \ power_down p x n" + by (induct p x n rule: power_down.induct) + (auto simp: power_down_simp simp del: odd_Suc_div_two intro!: truncate_down_nonneg ) + +lemma power_down_eq_zero_iff[simp]: "power_down prec b n = 0 \ b = 0 \ n \ 0" +proof (induction n arbitrary: b rule: less_induct) + case (less x) + then show ?case + using power_down_simp[of _ _ "x - 1"] + by (cases x) (auto simp add: div2_less_self) +qed + +lemma power_down_nonneg_iff[simp]: + "power_down prec b n \ 0 \ even n \ b \ 0" +proof (induction n arbitrary: b rule: less_induct) + case (less x) + show ?case + using less(1)[of "x - 1" b] power_down_simp[of _ _ "x - 1"] + by (cases x) (auto simp: algebra_split_simps zero_le_mult_iff) +qed + +lemma power_down_neg_iff[simp]: + "power_down prec b n < 0 \ + b < 0 \ odd n" + using power_down_nonneg_iff[of prec b n] by (auto simp del: power_down_nonneg_iff) + +lemma power_down_nonpos_iff[simp]: + notes [simp del] = power_down_neg_iff power_down_eq_zero_iff + shows "power_down prec b n \ 0 \ b < 0 \ odd n \ b = 0 \ n \ 0" + using power_down_neg_iff[of prec b n] power_down_eq_zero_iff[of prec b n] + by auto + +lemma power_down_mono: + "power_down prec a n \ power_down prec b n" + if "((0 \ a \ a \ b)\(odd n \ a \ b) \ (even n \ a \ 0 \ b \ a))" + using that +proof (induction n arbitrary: a b rule: less_induct) + case (less i) + show ?case + proof (cases i) + case j: (Suc j) + note IH = less[unfolded j even_Suc not_not] + note [simp del] = power_down.simps + show ?thesis + proof cases + assume [simp]: "even j" + have "a * power_down prec a j \ b * power_down prec b j" + by (smt IH(1) IH(2) \even j\ lessI mult_mono' mult_mono_nonpos_nonneg power_down_even_nonneg) + then have "truncate_down (Suc prec) (a * power_down prec a j) \ truncate_down (Suc prec) (b * power_down prec b j)" + by (auto intro!: truncate_down_mono simp: abs_le_square_iff[symmetric] abs_real_def) + then show ?thesis + unfolding j + by (simp add: power_down_simp) + next + assume [simp]: "odd j" + have "power_down prec 0 (Suc (j div 2)) \ - power_down prec b (Suc (j div 2))" + if "b < 0" "even (j div 2)" + apply (rule order_trans[where y=0]) + using IH that by (auto simp: div2_less_self) + then have "truncate_down (Suc prec) ((power_down prec a (Suc (j div 2)))\<^sup>2) + \ truncate_down (Suc prec) ((power_down prec b (Suc (j div 2)))\<^sup>2)" + using IH + by (auto intro!: truncate_down_mono intro: order_trans[where y=0] + simp: abs_le_square_iff[symmetric] abs_real_def + div2_less_self) + then show ?thesis + unfolding j + by (simp add: power_down_simp) + qed + qed simp +qed + +lemma power_up_even_nonneg: "even n \ 0 \ power_up p x n" + by (induct p x n rule: power_up.induct) + (auto simp: power_up.simps simp del: odd_Suc_div_two intro!: ) + +lemma power_up_eq_zero_iff[simp]: "power_up prec b n = 0 \ b = 0 \ n \ 0" +proof (induction n arbitrary: b rule: less_induct) + case (less x) + then show ?case + using power_up_simp[of _ _ "x - 1"] + by (cases x) (auto simp: algebra_split_simps zero_le_mult_iff div2_less_self) +qed + +lemma power_up_nonneg_iff[simp]: + "power_up prec b n \ 0 \ even n \ b \ 0" +proof (induction n arbitrary: b rule: less_induct) + case (less x) + show ?case + using less(1)[of "x - 1" b] power_up_simp[of _ _ "x - 1"] + by (cases x) (auto simp: algebra_split_simps zero_le_mult_iff) +qed + +lemma power_up_neg_iff[simp]: + "power_up prec b n < 0 \ b < 0 \ odd n" + using power_up_nonneg_iff[of prec b n] by (auto simp del: power_up_nonneg_iff) + +lemma power_up_nonpos_iff[simp]: + notes [simp del] = power_up_neg_iff power_up_eq_zero_iff + shows "power_up prec b n \ 0 \ b < 0 \ odd n \ b = 0 \ n \ 0" + using power_up_neg_iff[of prec b n] power_up_eq_zero_iff[of prec b n] + by auto + +lemma power_up_mono: + "power_up prec a n \ power_up prec b n" + if "((0 \ a \ a \ b)\(odd n \ a \ b) \ (even n \ a \ 0 \ b \ a))" + using that +proof (induction n arbitrary: a b rule: less_induct) + case (less i) + show ?case + proof (cases i) + case j: (Suc j) + note IH = less[unfolded j even_Suc not_not] + note [simp del] = power_up.simps + show ?thesis + proof cases + assume [simp]: "even j" + have "a * power_up prec a j \ b * power_up prec b j" + by (smt IH(1) IH(2) \even j\ lessI mult_mono' mult_mono_nonpos_nonneg power_up_even_nonneg) + then have "truncate_up prec (a * power_up prec a j) \ truncate_up prec (b * power_up prec b j)" + by (auto intro!: truncate_up_mono simp: abs_le_square_iff[symmetric] abs_real_def) + then show ?thesis + unfolding j + by (simp add: power_up_simp) + next + assume [simp]: "odd j" + have "power_up prec 0 (Suc (j div 2)) \ - power_up prec b (Suc (j div 2))" + if "b < 0" "even (j div 2)" + apply (rule order_trans[where y=0]) + using IH that by (auto simp: div2_less_self) + then have "truncate_up prec ((power_up prec a (Suc (j div 2)))\<^sup>2) + \ truncate_up prec ((power_up prec b (Suc (j div 2)))\<^sup>2)" + using IH + by (auto intro!: truncate_up_mono intro: order_trans[where y=0] + simp: abs_le_square_iff[symmetric] abs_real_def + div2_less_self) + then show ?thesis + unfolding j + by (simp add: power_up_simp) + qed + qed simp +qed + subsection \Lemmas needed by Approximate\ @@ -1948,160 +2366,6 @@ "0 \ real_of_float x \ real_of_float y \ 0 \ real_of_float (float_divr prec x y) \ 0" by transfer (rule real_divr_nonneg_neg_upper_bound) -lemma truncate_up_nonneg_mono: - assumes "0 \ x" "x \ y" - shows "truncate_up prec x \ truncate_up prec y" -proof - - consider "\log 2 x\ = \log 2 y\" | "\log 2 x\ \ \log 2 y\" "0 < x" | "x \ 0" - by arith - then show ?thesis - proof cases - case 1 - then show ?thesis - using assms - by (auto simp: truncate_up_def round_up_def intro!: ceiling_mono) - next - case 2 - from assms \0 < x\ have "log 2 x \ log 2 y" - by auto - with \\log 2 x\ \ \log 2 y\\ - have logless: "log 2 x < log 2 y" - by linarith - have flogless: "\log 2 x\ < \log 2 y\" - using \\log 2 x\ \ \log 2 y\\ \log 2 x \ log 2 y\ by linarith - have "truncate_up prec x = - real_of_int \x * 2 powr real_of_int (int prec - \log 2 x\ )\ * 2 powr - real_of_int (int prec - \log 2 x\)" - using assms by (simp add: truncate_up_def round_up_def) - also have "\x * 2 powr real_of_int (int prec - \log 2 x\)\ \ (2 ^ (Suc prec))" - proof (simp only: ceiling_le_iff) - have "x * 2 powr real_of_int (int prec - \log 2 x\) \ - x * (2 powr real (Suc prec) / (2 powr log 2 x))" - using real_of_int_floor_add_one_ge[of "log 2 x"] assms - by (auto simp: algebra_simps simp flip: powr_diff intro!: mult_left_mono) - then show "x * 2 powr real_of_int (int prec - \log 2 x\) \ real_of_int ((2::int) ^ (Suc prec))" - using \0 < x\ by (simp add: powr_realpow powr_add) - qed - then have "real_of_int \x * 2 powr real_of_int (int prec - \log 2 x\)\ \ 2 powr int (Suc prec)" - by (auto simp: powr_realpow powr_add) - (metis power_Suc of_int_le_numeral_power_cancel_iff) - also - have "2 powr - real_of_int (int prec - \log 2 x\) \ 2 powr - real_of_int (int prec - \log 2 y\ + 1)" - using logless flogless by (auto intro!: floor_mono) - also have "2 powr real_of_int (int (Suc prec)) \ - 2 powr (log 2 y + real_of_int (int prec - \log 2 y\ + 1))" - using assms \0 < x\ - by (auto simp: algebra_simps) - finally have "truncate_up prec x \ - 2 powr (log 2 y + real_of_int (int prec - \log 2 y\ + 1)) * 2 powr - real_of_int (int prec - \log 2 y\ + 1)" - by simp - also have "\ = 2 powr (log 2 y + real_of_int (int prec - \log 2 y\) - real_of_int (int prec - \log 2 y\))" - by (subst powr_add[symmetric]) simp - also have "\ = y" - using \0 < x\ assms - by (simp add: powr_add) - also have "\ \ truncate_up prec y" - by (rule truncate_up) - finally show ?thesis . - next - case 3 - then show ?thesis - using assms - by (auto intro!: truncate_up_le) - qed -qed - -lemma truncate_up_switch_sign_mono: - assumes "x \ 0" "0 \ y" - shows "truncate_up prec x \ truncate_up prec y" -proof - - note truncate_up_nonpos[OF \x \ 0\] - also note truncate_up_le[OF \0 \ y\] - finally show ?thesis . -qed - -lemma truncate_down_switch_sign_mono: - assumes "x \ 0" - and "0 \ y" - and "x \ y" - shows "truncate_down prec x \ truncate_down prec y" -proof - - note truncate_down_le[OF \x \ 0\] - also note truncate_down_nonneg[OF \0 \ y\] - finally show ?thesis . -qed - -lemma truncate_down_nonneg_mono: - assumes "0 \ x" "x \ y" - shows "truncate_down prec x \ truncate_down prec y" -proof - - consider "x \ 0" | "\log 2 \x\\ = \log 2 \y\\" | - "0 < x" "\log 2 \x\\ \ \log 2 \y\\" - by arith - then show ?thesis - proof cases - case 1 - with assms have "x = 0" "0 \ y" by simp_all - then show ?thesis - by (auto intro!: truncate_down_nonneg) - next - case 2 - then show ?thesis - using assms - by (auto simp: truncate_down_def round_down_def intro!: floor_mono) - next - case 3 - from \0 < x\ have "log 2 x \ log 2 y" "0 < y" "0 \ y" - using assms by auto - with \\log 2 \x\\ \ \log 2 \y\\\ - have logless: "log 2 x < log 2 y" and flogless: "\log 2 x\ < \log 2 y\" - unfolding atomize_conj abs_of_pos[OF \0 < x\] abs_of_pos[OF \0 < y\] - by (metis floor_less_cancel linorder_cases not_le) - have "2 powr prec \ y * 2 powr real prec / (2 powr log 2 y)" - using \0 < y\ by simp - also have "\ \ y * 2 powr real (Suc prec) / (2 powr (real_of_int \log 2 y\ + 1))" - using \0 \ y\ \0 \ x\ assms(2) - by (auto intro!: powr_mono divide_left_mono - simp: of_nat_diff powr_add powr_diff) - also have "\ = y * 2 powr real (Suc prec) / (2 powr real_of_int \log 2 y\ * 2)" - by (auto simp: powr_add) - finally have "(2 ^ prec) \ \y * 2 powr real_of_int (int (Suc prec) - \log 2 \y\\ - 1)\" - using \0 \ y\ - by (auto simp: powr_diff le_floor_iff powr_realpow powr_add) - then have "(2 ^ (prec)) * 2 powr - real_of_int (int prec - \log 2 \y\\) \ truncate_down prec y" - by (auto simp: truncate_down_def round_down_def) - moreover have "x \ (2 ^ prec) * 2 powr - real_of_int (int prec - \log 2 \y\\)" - proof - - have "x = 2 powr (log 2 \x\)" using \0 < x\ by simp - also have "\ \ (2 ^ (Suc prec )) * 2 powr - real_of_int (int prec - \log 2 \x\\)" - using real_of_int_floor_add_one_ge[of "log 2 \x\"] \0 < x\ - by (auto simp flip: powr_realpow powr_add simp: algebra_simps powr_mult_base le_powr_iff) - also - have "2 powr - real_of_int (int prec - \log 2 \x\\) \ 2 powr - real_of_int (int prec - \log 2 \y\\ + 1)" - using logless flogless \x > 0\ \y > 0\ - by (auto intro!: floor_mono) - finally show ?thesis - by (auto simp flip: powr_realpow simp: powr_diff assms of_nat_diff) - qed - ultimately show ?thesis - by (metis dual_order.trans truncate_down) - qed -qed - -lemma truncate_down_eq_truncate_up: "truncate_down p x = - truncate_up p (-x)" - and truncate_up_eq_truncate_down: "truncate_up p x = - truncate_down p (-x)" - by (auto simp: truncate_up_uminus_eq truncate_down_uminus_eq) - -lemma truncate_down_mono: "x \ y \ truncate_down p x \ truncate_down p y" - apply (cases "0 \ x") - apply (rule truncate_down_nonneg_mono, assumption+) - apply (simp add: truncate_down_eq_truncate_up) - apply (cases "0 \ y") - apply (auto intro: truncate_up_nonneg_mono truncate_up_switch_sign_mono) - done - -lemma truncate_up_mono: "x \ y \ truncate_up p x \ truncate_up p y" - by (simp add: truncate_up_eq_truncate_down truncate_down_mono) - lemma Float_le_zero_iff: "Float a b \ 0 \ a \ 0" by (auto simp: zero_float_def mult_le_0_iff) diff -r c1b63124245c -r ddd4aefc540f src/HOL/Library/Interval.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Library/Interval.thy Tue Nov 05 10:02:09 2019 -0500 @@ -0,0 +1,854 @@ +(* Title: Interval + Author: Christoph Traut, TU Muenchen + Fabian Immler, TU Muenchen +*) +section \Interval Type\ +theory Interval + imports + Complex_Main + Lattice_Algebras + Set_Algebras +begin + +text \A type of non-empty, closed intervals.\ + +typedef (overloaded) 'a interval = + "{(a::'a::preorder, b). a \ b}" + morphisms bounds_of_interval Interval + by auto + +setup_lifting type_definition_interval + +lift_definition lower::"('a::preorder) interval \ 'a" is fst . + +lift_definition upper::"('a::preorder) interval \ 'a" is snd . + +lemma interval_eq_iff: "a = b \ lower a = lower b \ upper a = upper b" + by transfer auto + +lemma interval_eqI: "lower a = lower b \ upper a = upper b \ a = b" + by (auto simp: interval_eq_iff) + +lemma lower_le_upper[simp]: "lower i \ upper i" + by transfer auto + +lift_definition set_of :: "'a::preorder interval \ 'a set" is "\x. {fst x .. snd x}" . + +lemma set_of_eq: "set_of x = {lower x .. upper x}" + by transfer simp + +context notes [[typedef_overloaded]] begin + +lift_definition(code_dt) Interval'::"'a::preorder \ 'a::preorder \ 'a interval option" + is "\a b. if a \ b then Some (a, b) else None" + by auto + +lemma Interval'_split: + "P (Interval' a b) \ + (\ivl. a \ b \ lower ivl = a \ upper ivl = b \ P (Some ivl)) \ (\a\b \ P None)" + by transfer auto + +lemma Interval'_split_asm: + "P (Interval' a b) \ + \((\ivl. a \ b \ lower ivl = a \ upper ivl = b \ \P (Some ivl)) \ (\a\b \ \P None))" + unfolding Interval'_split + by auto + +lemmas Interval'_splits = Interval'_split Interval'_split_asm + +lemma Interval'_eq_Some: "Interval' a b = Some i \ lower i = a \ upper i = b" + by (simp split: Interval'_splits) + +end + +instantiation "interval" :: ("{preorder,equal}") equal +begin + +definition "equal_class.equal a b \ (lower a = lower b) \ (upper a = upper b)" + +instance proof qed (simp add: equal_interval_def interval_eq_iff) +end + +instantiation interval :: ("preorder") ord begin + +definition less_eq_interval :: "'a interval \ 'a interval \ bool" + where "less_eq_interval a b \ lower b \ lower a \ upper a \ upper b" + +definition less_interval :: "'a interval \ 'a interval \ bool" + where "less_interval x y = (x \ y \ \ y \ x)" + +instance proof qed +end + +instantiation interval :: ("lattice") semilattice_sup +begin + +lift_definition sup_interval :: "'a interval \ 'a interval \ 'a interval" + is "\(a, b) (c, d). (inf a c, sup b d)" + by (auto simp: le_infI1 le_supI1) + +lemma lower_sup[simp]: "lower (sup A B) = inf (lower A) (lower B)" + by transfer auto + +lemma upper_sup[simp]: "upper (sup A B) = sup (upper A) (upper B)" + by transfer auto + +instance proof qed (auto simp: less_eq_interval_def less_interval_def interval_eq_iff) +end + +lemma set_of_interval_union: "set_of A \ set_of B \ set_of (sup A B)" for A::"'a::lattice interval" + by (auto simp: set_of_eq) + +lemma interval_union_commute: "sup A B = sup B A" for A::"'a::lattice interval" + by (auto simp add: interval_eq_iff inf.commute sup.commute) + +lemma interval_union_mono1: "set_of a \ set_of (sup a A)" for A :: "'a::lattice interval" + using set_of_interval_union by blast + +lemma interval_union_mono2: "set_of A \ set_of (sup a A)" for A :: "'a::lattice interval" + using set_of_interval_union by blast + +lift_definition interval_of :: "'a::preorder \ 'a interval" is "\x. (x, x)" + by auto + +lemma lower_interval_of[simp]: "lower (interval_of a) = a" + by transfer auto + +lemma upper_interval_of[simp]: "upper (interval_of a) = a" + by transfer auto + +definition width :: "'a::{preorder,minus} interval \ 'a" + where "width i = upper i - lower i" + + +instantiation "interval" :: ("ordered_ab_semigroup_add") ab_semigroup_add +begin + +lift_definition plus_interval::"'a interval \ 'a interval \ 'a interval" + is "\(a, b). \(c, d). (a + c, b + d)" + by (auto intro!: add_mono) +lemma lower_plus[simp]: "lower (plus A B) = plus (lower A) (lower B)" + by transfer auto +lemma upper_plus[simp]: "upper (plus A B) = plus (upper A) (upper B)" + by transfer auto + +instance proof qed (auto simp: interval_eq_iff less_eq_interval_def ac_simps) +end + +instance "interval" :: ("{ordered_ab_semigroup_add, lattice}") ordered_ab_semigroup_add +proof qed (auto simp: less_eq_interval_def intro!: add_mono) + +instantiation "interval" :: ("{preorder,zero}") zero +begin + +lift_definition zero_interval::"'a interval" is "(0, 0)" by auto +lemma lower_zero[simp]: "lower 0 = 0" + by transfer auto +lemma upper_zero[simp]: "upper 0 = 0" + by transfer auto +instance proof qed +end + +instance "interval" :: ("{ordered_comm_monoid_add}") comm_monoid_add +proof qed (auto simp: interval_eq_iff) + +instance "interval" :: ("{ordered_comm_monoid_add,lattice}") ordered_comm_monoid_add .. + +instantiation "interval" :: ("{ordered_ab_group_add}") uminus +begin + +lift_definition uminus_interval::"'a interval \ 'a interval" is "\(a, b). (-b, -a)" by auto +lemma lower_uminus[simp]: "lower (- A) = - upper A" + by transfer auto +lemma upper_uminus[simp]: "upper (- A) = - lower A" + by transfer auto +instance .. +end + +instantiation "interval" :: ("{ordered_ab_group_add}") minus +begin + +definition minus_interval::"'a interval \ 'a interval \ 'a interval" + where "minus_interval a b = a + - b" +lemma lower_minus[simp]: "lower (minus A B) = minus (lower A) (upper B)" + by (auto simp: minus_interval_def) +lemma upper_minus[simp]: "upper (minus A B) = minus (upper A) (lower B)" + by (auto simp: minus_interval_def) + +instance .. +end + +instantiation "interval" :: (linordered_semiring) times +begin + +lift_definition times_interval :: "'a interval \ 'a interval \ 'a interval" + is "\(a1, a2). \(b1, b2). + (let x1 = a1 * b1; x2 = a1 * b2; x3 = a2 * b1; x4 = a2 * b2 + in (min x1 (min x2 (min x3 x4)), max x1 (max x2 (max x3 x4))))" + by (auto simp: Let_def intro!: min.coboundedI1 max.coboundedI1) + +lemma lower_times: + "lower (times A B) = Min {lower A * lower B, lower A * upper B, upper A * lower B, upper A * upper B}" + by transfer (auto simp: Let_def) + +lemma upper_times: + "upper (times A B) = Max {lower A * lower B, lower A * upper B, upper A * lower B, upper A * upper B}" + by transfer (auto simp: Let_def) + +instance .. +end + +lemma interval_eq_set_of_iff: "X = Y \ set_of X = set_of Y" for X Y::"'a::order interval" + by (auto simp: set_of_eq interval_eq_iff) + + +subsection \Membership\ + +abbreviation (in preorder) in_interval ("(_/ \\<^sub>i _)" [51, 51] 50) + where "in_interval x X \ x \ set_of X" + +lemma in_interval_to_interval[intro!]: "a \\<^sub>i interval_of a" + by (auto simp: set_of_eq) + +lemma plus_in_intervalI: + fixes x y :: "'a :: ordered_ab_semigroup_add" + shows "x \\<^sub>i X \ y \\<^sub>i Y \ x + y \\<^sub>i X + Y" + by (simp add: add_mono_thms_linordered_semiring(1) set_of_eq) + +lemma connected_set_of[intro, simp]: + "connected (set_of X)" for X::"'a::linear_continuum_topology interval" + by (auto simp: set_of_eq ) + +lemma ex_sum_in_interval_lemma: "\xa\{la .. ua}. \xb\{lb .. ub}. x = xa + xb" + if "la \ ua" "lb \ ub" "la + lb \ x" "x \ ua + ub" + "ua - la \ ub - lb" + for la b c d::"'a::linordered_ab_group_add" +proof - + define wa where "wa = ua - la" + define wb where "wb = ub - lb" + define w where "w = wa + wb" + define d where "d = x - la - lb" + define da where "da = max 0 (min wa (d - wa))" + define db where "db = d - da" + from that have nonneg: "0 \ wa" "0 \ wb" "0 \ w" "0 \ d" "d \ w" + by (auto simp add: wa_def wb_def w_def d_def add.commute le_diff_eq) + have "0 \ db" + by (auto simp: da_def nonneg db_def intro!: min.coboundedI2) + have "x = (la + da) + (lb + db)" + by (simp add: da_def db_def d_def) + moreover + have "x - la - ub \ da" + using that + unfolding da_def + by (intro max.coboundedI2) (auto simp: wa_def d_def diff_le_eq diff_add_eq) + then have "db \ wb" + by (auto simp: db_def d_def wb_def algebra_simps) + with \0 \ db\ that nonneg have "lb + db \ {lb..ub}" + by (auto simp: wb_def algebra_simps) + moreover + have "da \ wa" + by (auto simp: da_def nonneg) + then have "la + da \ {la..ua}" + by (auto simp: da_def wa_def algebra_simps) + ultimately show ?thesis + by force +qed + + +lemma ex_sum_in_interval: "\xa\la. xa \ ua \ (\xb\lb. xb \ ub \ x = xa + xb)" + if a: "la \ ua" and b: "lb \ ub" and x: "la + lb \ x" "x \ ua + ub" + for la b c d::"'a::linordered_ab_group_add" +proof - + from linear consider "ua - la \ ub - lb" | "ub - lb \ ua - la" + by blast + then show ?thesis + proof cases + case 1 + from ex_sum_in_interval_lemma[OF that 1] + show ?thesis by auto + next + case 2 + from x have "lb + la \ x" "x \ ub + ua" by (simp_all add: ac_simps) + from ex_sum_in_interval_lemma[OF b a this 2] + show ?thesis by auto + qed +qed + +lemma Icc_plus_Icc: + "{a .. b} + {c .. d} = {a + c .. b + d}" + if "a \ b" "c \ d" + for a b c d::"'a::linordered_ab_group_add" + using ex_sum_in_interval[OF that] + by (auto intro: add_mono simp: atLeastAtMost_iff Bex_def set_plus_def) + +lemma set_of_plus: + fixes A :: "'a::linordered_ab_group_add interval" + shows "set_of (A + B) = set_of A + set_of B" + using Icc_plus_Icc[of "lower A" "upper A" "lower B" "upper B"] + by (auto simp: set_of_eq) + +lemma plus_in_intervalE: + fixes xy :: "'a :: linordered_ab_group_add" + assumes "xy \\<^sub>i X + Y" + obtains x y where "xy = x + y" "x \\<^sub>i X" "y \\<^sub>i Y" + using assms + unfolding set_of_plus set_plus_def + by auto + +lemma set_of_uminus: "set_of (-X) = {- x | x. x \ set_of X}" + for X :: "'a :: ordered_ab_group_add interval" + by (auto simp: set_of_eq simp: le_minus_iff minus_le_iff + intro!: exI[where x="-x" for x]) + +lemma uminus_in_intervalI: + fixes x :: "'a :: ordered_ab_group_add" + shows "x \\<^sub>i X \ -x \\<^sub>i -X" + by (auto simp: set_of_uminus) + +lemma uminus_in_intervalD: + fixes x :: "'a :: ordered_ab_group_add" + shows "x \\<^sub>i - X \ - x \\<^sub>i X" + by (auto simp: set_of_uminus) + +lemma minus_in_intervalI: + fixes x y :: "'a :: ordered_ab_group_add" + shows "x \\<^sub>i X \ y \\<^sub>i Y \ x - y \\<^sub>i X - Y" + by (metis diff_conv_add_uminus minus_interval_def plus_in_intervalI uminus_in_intervalI) + +lemma set_of_minus: "set_of (X - Y) = {x - y | x y . x \ set_of X \ y \ set_of Y}" + for X Y :: "'a :: linordered_ab_group_add interval" + unfolding minus_interval_def set_of_plus set_of_uminus set_plus_def + by force + +lemma times_in_intervalI: + fixes x y::"'a::linordered_ring" + assumes "x \\<^sub>i X" "y \\<^sub>i Y" + shows "x * y \\<^sub>i X * Y" +proof - + define X1 where "X1 \ lower X" + define X2 where "X2 \ upper X" + define Y1 where "Y1 \ lower Y" + define Y2 where "Y2 \ upper Y" + from assms have assms: "X1 \ x" "x \ X2" "Y1 \ y" "y \ Y2" + by (auto simp: X1_def X2_def Y1_def Y2_def set_of_eq) + have "(X1 * Y1 \ x * y \ X1 * Y2 \ x * y \ X2 * Y1 \ x * y \ X2 * Y2 \ x * y) \ + (X1 * Y1 \ x * y \ X1 * Y2 \ x * y \ X2 * Y1 \ x * y \ X2 * Y2 \ x * y)" + proof (cases x "0::'a" rule: linorder_cases) + case x0: less + show ?thesis + proof (cases "y < 0") + case y0: True + from y0 x0 assms have "x * y \ X1 * y" by (intro mult_right_mono_neg, auto) + also from x0 y0 assms have "X1 * y \ X1 * Y1" by (intro mult_left_mono_neg, auto) + finally have 1: "x * y \ X1 * Y1". + show ?thesis proof(cases "X2 \ 0") + case True + with assms have "X2 * Y2 \ X2 * y" by (auto intro: mult_left_mono_neg) + also from assms y0 have "... \ x * y" by (auto intro: mult_right_mono_neg) + finally have "X2 * Y2 \ x * y". + with 1 show ?thesis by auto + next + case False + with assms have "X2 * Y1 \ X2 * y" by (auto intro: mult_left_mono) + also from assms y0 have "... \ x * y" by (auto intro: mult_right_mono_neg) + finally have "X2 * Y1 \ x * y". + with 1 show ?thesis by auto + qed + next + case False + then have y0: "y \ 0" by auto + from x0 y0 assms have "X1 * Y2 \ x * Y2" by (intro mult_right_mono, auto) + also from y0 x0 assms have "... \ x * y" by (intro mult_left_mono_neg, auto) + finally have 1: "X1 * Y2 \ x * y". + show ?thesis + proof(cases "X2 \ 0") + case X2: True + from assms y0 have "x * y \ X2 * y" by (intro mult_right_mono) + also from assms X2 have "... \ X2 * Y1" by (auto intro: mult_left_mono_neg) + finally have "x * y \ X2 * Y1". + with 1 show ?thesis by auto + next + case X2: False + from assms y0 have "x * y \ X2 * y" by (intro mult_right_mono) + also from assms X2 have "... \ X2 * Y2" by (auto intro: mult_left_mono) + finally have "x * y \ X2 * Y2". + with 1 show ?thesis by auto + qed + qed + next + case [simp]: equal + with assms show ?thesis by (cases "Y2 \ 0", auto intro:mult_sign_intros) + next + case x0: greater + show ?thesis + proof (cases "y < 0") + case y0: True + from x0 y0 assms have "X2 * Y1 \ X2 * y" by (intro mult_left_mono, auto) + also from y0 x0 assms have "X2 * y \ x * y" by (intro mult_right_mono_neg, auto) + finally have 1: "X2 * Y1 \ x * y". + show ?thesis + proof(cases "Y2 \ 0") + case Y2: True + from x0 assms have "x * y \ x * Y2" by (auto intro: mult_left_mono) + also from assms Y2 have "... \ X1 * Y2" by (auto intro: mult_right_mono_neg) + finally have "x * y \ X1 * Y2". + with 1 show ?thesis by auto + next + case Y2: False + from x0 assms have "x * y \ x * Y2" by (auto intro: mult_left_mono) + also from assms Y2 have "... \ X2 * Y2" by (auto intro: mult_right_mono) + finally have "x * y \ X2 * Y2". + with 1 show ?thesis by auto + qed + next + case y0: False + from x0 y0 assms have "x * y \ X2 * y" by (intro mult_right_mono, auto) + also from y0 x0 assms have "... \ X2 * Y2" by (intro mult_left_mono, auto) + finally have 1: "x * y \ X2 * Y2". + show ?thesis + proof(cases "X1 \ 0") + case True + with assms have "X1 * Y2 \ X1 * y" by (auto intro: mult_left_mono_neg) + also from assms y0 have "... \ x * y" by (auto intro: mult_right_mono) + finally have "X1 * Y2 \ x * y". + with 1 show ?thesis by auto + next + case False + with assms have "X1 * Y1 \ X1 * y" by (auto intro: mult_left_mono) + also from assms y0 have "... \ x * y" by (auto intro: mult_right_mono) + finally have "X1 * Y1 \ x * y". + with 1 show ?thesis by auto + qed + qed + qed + hence min:"min (X1 * Y1) (min (X1 * Y2) (min (X2 * Y1) (X2 * Y2))) \ x * y" + and max:"x * y \ max (X1 * Y1) (max (X1 * Y2) (max (X2 * Y1) (X2 * Y2)))" + by (auto simp:min_le_iff_disj le_max_iff_disj) + show ?thesis using min max + by (auto simp: Let_def X1_def X2_def Y1_def Y2_def set_of_eq lower_times upper_times) +qed + +lemma times_in_intervalE: + fixes xy :: "'a :: {linordered_semiring, real_normed_algebra, linear_continuum_topology}" + \ \TODO: linear continuum topology is pretty strong\ + assumes "xy \\<^sub>i X * Y" + obtains x y where "xy = x * y" "x \\<^sub>i X" "y \\<^sub>i Y" +proof - + let ?mult = "\(x, y). x * y" + let ?XY = "set_of X \ set_of Y" + have cont: "continuous_on ?XY ?mult" + by (auto intro!: tendsto_eq_intros simp: continuous_on_def split_beta') + have conn: "connected (?mult ` ?XY)" + by (rule connected_continuous_image[OF cont]) auto + have "lower (X * Y) \ ?mult ` ?XY" "upper (X * Y) \ ?mult ` ?XY" + by (auto simp: set_of_eq lower_times upper_times min_def max_def split: if_splits) + from connectedD_interval[OF conn this, of xy] assms + obtain x y where "xy = x * y" "x \\<^sub>i X" "y \\<^sub>i Y" by (auto simp: set_of_eq) + then show ?thesis .. +qed + +lemma set_of_times: "set_of (X * Y) = {x * y | x y. x \ set_of X \ y \ set_of Y}" + for X Y::"'a :: {linordered_ring, real_normed_algebra, linear_continuum_topology} interval" + by (auto intro!: times_in_intervalI elim!: times_in_intervalE) + +instance "interval" :: (linordered_idom) cancel_semigroup_add +proof qed (auto simp: interval_eq_iff) + +lemma interval_mul_commute: "A * B = B * A" for A B:: "'a::linordered_idom interval" + by (simp add: interval_eq_iff lower_times upper_times ac_simps) + +lemma interval_times_zero_right[simp]: "A * 0 = 0" for A :: "'a::linordered_ring interval" + by (simp add: interval_eq_iff lower_times upper_times ac_simps) + +lemma interval_times_zero_left[simp]: + "0 * A = 0" for A :: "'a::linordered_ring interval" + by (simp add: interval_eq_iff lower_times upper_times ac_simps) + +instantiation "interval" :: ("{preorder,one}") one +begin + +lift_definition one_interval::"'a interval" is "(1, 1)" by auto +lemma lower_one[simp]: "lower 1 = 1" + by transfer auto +lemma upper_one[simp]: "upper 1 = 1" + by transfer auto +instance proof qed +end + +instance interval :: ("{one, preorder, linordered_semiring}") power +proof qed + +lemma set_of_one[simp]: "set_of (1::'a::{one, order} interval) = {1}" + by (auto simp: set_of_eq) + +instance "interval" :: + ("{linordered_idom,linordered_ring, real_normed_algebra, linear_continuum_topology}") monoid_mult + apply standard + unfolding interval_eq_set_of_iff set_of_times + subgoal + by (auto simp: interval_eq_set_of_iff set_of_times; metis mult.assoc) + by auto + +lemma one_times_ivl_left[simp]: "1 * A = A" for A :: "'a::linordered_idom interval" + by (simp add: interval_eq_iff lower_times upper_times ac_simps min_def max_def) + +lemma one_times_ivl_right[simp]: "A * 1 = A" for A :: "'a::linordered_idom interval" + by (metis interval_mul_commute one_times_ivl_left) + +lemma set_of_power_mono: "a^n \ set_of (A^n)" if "a \ set_of A" + for a :: "'a::linordered_idom" + using that + by (induction n) (auto intro!: times_in_intervalI) + +lemma set_of_add_cong: + "set_of (A + B) = set_of (A' + B')" + if "set_of A = set_of A'" "set_of B = set_of B'" + for A :: "'a::linordered_ab_group_add interval" + unfolding set_of_plus that .. + +lemma set_of_add_inc_left: + "set_of (A + B) \ set_of (A' + B)" + if "set_of A \ set_of A'" + for A :: "'a::linordered_ab_group_add interval" + unfolding set_of_plus using that by (auto simp: set_plus_def) + +lemma set_of_add_inc_right: + "set_of (A + B) \ set_of (A + B')" + if "set_of B \ set_of B'" + for A :: "'a::linordered_ab_group_add interval" + using set_of_add_inc_left[OF that] + by (simp add: add.commute) + +lemma set_of_add_inc: + "set_of (A + B) \ set_of (A' + B')" + if "set_of A \ set_of A'" "set_of B \ set_of B'" + for A :: "'a::linordered_ab_group_add interval" + using set_of_add_inc_left[OF that(1)] set_of_add_inc_right[OF that(2)] + by auto + +lemma set_of_neg_inc: + "set_of (-A) \ set_of (-A')" + if "set_of A \ set_of A'" + for A :: "'a::ordered_ab_group_add interval" + using that + unfolding set_of_uminus + by auto + +lemma set_of_sub_inc_left: + "set_of (A - B) \ set_of (A' - B)" + if "set_of A \ set_of A'" + for A :: "'a::linordered_ab_group_add interval" + using that + unfolding set_of_minus + by auto + +lemma set_of_sub_inc_right: + "set_of (A - B) \ set_of (A - B')" + if "set_of B \ set_of B'" + for A :: "'a::linordered_ab_group_add interval" + using that + unfolding set_of_minus + by auto + +lemma set_of_sub_inc: + "set_of (A - B) \ set_of (A' - B')" + if "set_of A \ set_of A'" "set_of B \ set_of B'" + for A :: "'a::linordered_idom interval" + using set_of_sub_inc_left[OF that(1)] set_of_sub_inc_right[OF that(2)] + by auto + +lemma set_of_mul_inc_right: + "set_of (A * B) \ set_of (A * B')" + if "set_of B \ set_of B'" + for A :: "'a::linordered_ring interval" + using that + apply transfer + apply (clarsimp simp add: Let_def) + apply (intro conjI) + apply (metis linear min.coboundedI1 min.coboundedI2 mult_left_mono mult_left_mono_neg order_trans) + apply (metis linear min.coboundedI1 min.coboundedI2 mult_left_mono mult_left_mono_neg order_trans) + apply (metis linear min.coboundedI1 min.coboundedI2 mult_left_mono mult_left_mono_neg order_trans) + apply (metis linear min.coboundedI1 min.coboundedI2 mult_left_mono mult_left_mono_neg order_trans) + apply (metis linear max.coboundedI1 max.coboundedI2 mult_left_mono mult_left_mono_neg order_trans) + apply (metis linear max.coboundedI1 max.coboundedI2 mult_left_mono mult_left_mono_neg order_trans) + apply (metis linear max.coboundedI1 max.coboundedI2 mult_left_mono mult_left_mono_neg order_trans) + apply (metis linear max.coboundedI1 max.coboundedI2 mult_left_mono mult_left_mono_neg order_trans) + done + +lemma set_of_distrib_left: + "set_of (B * (A1 + A2)) \ set_of (B * A1 + B * A2)" + for A1 :: "'a::linordered_ring interval" + apply transfer + apply (clarsimp simp: Let_def distrib_left distrib_right) + apply (intro conjI) + apply (metis add_mono min.cobounded1 min.left_commute) + apply (metis add_mono min.cobounded1 min.left_commute) + apply (metis add_mono min.cobounded1 min.left_commute) + apply (metis add_mono min.assoc min.cobounded2) + apply (meson add_mono order.trans max.cobounded1 max.cobounded2) + apply (meson add_mono order.trans max.cobounded1 max.cobounded2) + apply (meson add_mono order.trans max.cobounded1 max.cobounded2) + apply (meson add_mono order.trans max.cobounded1 max.cobounded2) + done + +lemma set_of_distrib_right: + "set_of ((A1 + A2) * B) \ set_of (A1 * B + A2 * B)" + for A1 A2 B :: "'a::{linordered_ring, real_normed_algebra, linear_continuum_topology} interval" + unfolding set_of_times set_of_plus set_plus_def + apply clarsimp + subgoal for b a1 a2 + apply (rule exI[where x="a1 * b"]) + apply (rule conjI) + subgoal by force + subgoal + apply (rule exI[where x="a2 * b"]) + apply (rule conjI) + subgoal by force + subgoal by (simp add: algebra_simps) + done + done + done + +lemma set_of_mul_inc_left: + "set_of (A * B) \ set_of (A' * B)" + if "set_of A \ set_of A'" + for A :: "'a::{linordered_ring, real_normed_algebra, linear_continuum_topology} interval" + using that + unfolding set_of_times + by auto + +lemma set_of_mul_inc: + "set_of (A * B) \ set_of (A' * B')" + if "set_of A \ set_of A'" "set_of B \ set_of B'" + for A :: "'a::{linordered_ring, real_normed_algebra, linear_continuum_topology} interval" + using that unfolding set_of_times by auto + +lemma set_of_pow_inc: + "set_of (A^n) \ set_of (A'^n)" + if "set_of A \ set_of A'" + for A :: "'a::{linordered_idom, real_normed_algebra, linear_continuum_topology} interval" + using that + by (induction n, simp_all add: set_of_mul_inc) + +lemma set_of_distrib_right_left: + "set_of ((A1 + A2) * (B1 + B2)) \ set_of (A1 * B1 + A1 * B2 + A2 * B1 + A2 * B2)" + for A1 :: "'a::{linordered_idom, real_normed_algebra, linear_continuum_topology} interval" +proof- + have "set_of ((A1 + A2) * (B1 + B2)) \ set_of (A1 * (B1 + B2) + A2 * (B1 + B2))" + by (rule set_of_distrib_right) + also have "... \ set_of ((A1 * B1 + A1 * B2) + A2 * (B1 + B2))" + by (rule set_of_add_inc_left[OF set_of_distrib_left]) + also have "... \ set_of ((A1 * B1 + A1 * B2) + (A2 * B1 + A2 * B2))" + by (rule set_of_add_inc_right[OF set_of_distrib_left]) + finally show ?thesis + by (simp add: add.assoc) +qed + +lemma mult_bounds_enclose_zero1: + "min (la * lb) (min (la * ub) (min (lb * ua) (ua * ub))) \ 0" + "0 \ max (la * lb) (max (la * ub) (max (lb * ua) (ua * ub)))" + if "la \ 0" "0 \ ua" + for la lb ua ub:: "'a::linordered_idom" + subgoal by (metis (no_types, hide_lams) that eq_iff min_le_iff_disj mult_zero_left mult_zero_right + zero_le_mult_iff) + subgoal by (metis that le_max_iff_disj mult_zero_right order_refl zero_le_mult_iff) + done + +lemma mult_bounds_enclose_zero2: + "min (la * lb) (min (la * ub) (min (lb * ua) (ua * ub))) \ 0" + "0 \ max (la * lb) (max (la * ub) (max (lb * ua) (ua * ub)))" + if "lb \ 0" "0 \ ub" + for la lb ua ub:: "'a::linordered_idom" + using mult_bounds_enclose_zero1[OF that, of la ua] + by (simp_all add: ac_simps) + +lemma set_of_mul_contains_zero: + "0 \ set_of (A * B)" + if "0 \ set_of A \ 0 \ set_of B" + for A :: "'a::linordered_idom interval" + using that + by (auto simp: set_of_eq lower_times upper_times algebra_simps mult_le_0_iff + mult_bounds_enclose_zero1 mult_bounds_enclose_zero2) + +instance "interval" :: (linordered_semiring) mult_zero + apply standard + subgoal by transfer auto + subgoal by transfer auto + done + +lift_definition min_interval::"'a::linorder interval \ 'a interval \ 'a interval" is + "\(l1, u1). \(l2, u2). (min l1 l2, min u1 u2)" + by (auto simp: min_def) +lemma lower_min_interval[simp]: "lower (min_interval x y) = min (lower x) (lower y)" + by transfer auto +lemma upper_min_interval[simp]: "upper (min_interval x y) = min (upper x) (upper y)" + by transfer auto + +lemma min_intervalI: + "a \\<^sub>i A \ b \\<^sub>i B \ min a b \\<^sub>i min_interval A B" + by (auto simp: set_of_eq min_def) + +lift_definition max_interval::"'a::linorder interval \ 'a interval \ 'a interval" is + "\(l1, u1). \(l2, u2). (max l1 l2, max u1 u2)" + by (auto simp: max_def) +lemma lower_max_interval[simp]: "lower (max_interval x y) = max (lower x) (lower y)" + by transfer auto +lemma upper_max_interval[simp]: "upper (max_interval x y) = max (upper x) (upper y)" + by transfer auto + +lemma max_intervalI: + "a \\<^sub>i A \ b \\<^sub>i B \ max a b \\<^sub>i max_interval A B" + by (auto simp: set_of_eq max_def) + +lift_definition abs_interval::"'a::linordered_idom interval \ 'a interval" is + "(\(l,u). (if l < 0 \ 0 < u then 0 else min \l\ \u\, max \l\ \u\))" + by auto + +lemma lower_abs_interval[simp]: + "lower (abs_interval x) = (if lower x < 0 \ 0 < upper x then 0 else min \lower x\ \upper x\)" + by transfer auto +lemma upper_abs_interval[simp]: "upper (abs_interval x) = max \lower x\ \upper x\" + by transfer auto + +lemma in_abs_intervalI1: + "lx < 0 \ 0 < ux \ 0 \ xa \ xa \ max (- lx) (ux) \ xa \ abs ` {lx..ux}" + for xa::"'a::linordered_idom" + by (metis abs_minus_cancel abs_of_nonneg atLeastAtMost_iff image_eqI le_less le_max_iff_disj + le_minus_iff neg_le_0_iff_le order_trans) + +lemma in_abs_intervalI2: + "min (\lx\) \ux\ \ xa \ xa \ max \lx\ \ux\ \ lx \ ux \ 0 \ lx \ ux \ 0 \ + xa \ abs ` {lx..ux}" + for xa::"'a::linordered_idom" + by (force intro: image_eqI[where x="-xa"] image_eqI[where x="xa"]) + +lemma set_of_abs_interval: "set_of (abs_interval x) = abs ` set_of x" + by (auto simp: set_of_eq not_less intro: in_abs_intervalI1 in_abs_intervalI2 cong del: image_cong_simp) + +fun split_domain :: "('a::preorder interval \ 'a interval list) \ 'a interval list \ 'a interval list list" + where "split_domain split [] = [[]]" + | "split_domain split (I#Is) = ( + let S = split I; + D = split_domain split Is + in concat (map (\d. map (\s. s # d) S) D) + )" + +context notes [[typedef_overloaded]] begin +lift_definition(code_dt) split_interval::"'a::linorder interval \ 'a \ ('a interval \ 'a interval)" + is "\(l, u) x. ((min l x, max l x), (min u x, max u x))" + by (auto simp: min_def) +end + +lemma split_domain_nonempty: + assumes "\I. split I \ []" + shows "split_domain split I \ []" + using last_in_set assms + by (induction I, auto) + +lemma lower_split_interval1: "lower (fst (split_interval X m)) = min (lower X) m" + and lower_split_interval2: "lower (snd (split_interval X m)) = min (upper X) m" + and upper_split_interval1: "upper (fst (split_interval X m)) = max (lower X) m" + and upper_split_interval2: "upper (snd (split_interval X m)) = max (upper X) m" + subgoal by transfer auto + subgoal by transfer (auto simp: min.commute) + subgoal by transfer (auto simp: ) + subgoal by transfer (auto simp: ) + done + +lemma split_intervalD: "split_interval X x = (A, B) \ set_of X \ set_of A \ set_of B" + unfolding set_of_eq + by transfer (auto simp: min_def max_def split: if_splits) + +instantiation interval :: ("{topological_space, preorder}") topological_space +begin + +definition open_interval_def[code del]: "open (X::'a interval set) = + (\x\X. + \A B. + open A \ + open B \ + lower x \ A \ upper x \ B \ Interval ` (A \ B) \ X)" + +instance +proof + show "open (UNIV :: ('a interval) set)" + unfolding open_interval_def by auto +next + fix S T :: "('a interval) set" + assume "open S" "open T" + show "open (S \ T)" + unfolding open_interval_def + proof (safe) + fix x assume "x \ S" "x \ T" + from \x \ S\ \open S\ obtain Sl Su where S: + "open Sl" "open Su" "lower x \ Sl" "upper x \ Su" "Interval ` (Sl \ Su) \ S" + by (auto simp: open_interval_def) + from \x \ T\ \open T\ obtain Tl Tu where T: + "open Tl" "open Tu" "lower x \ Tl" "upper x \ Tu" "Interval ` (Tl \ Tu) \ T" + by (auto simp: open_interval_def) + + let ?L = "Sl \ Tl" and ?U = "Su \ Tu" + have "open ?L \ open ?U \ lower x \ ?L \ upper x \ ?U \ Interval ` (?L \ ?U) \ S \ T" + using S T by (auto simp add: open_Int) + then show "\A B. open A \ open B \ lower x \ A \ upper x \ B \ Interval ` (A \ B) \ S \ T" + by fast + qed +qed (unfold open_interval_def, fast) + +end + + +subsection \Quickcheck\ + +lift_definition Ivl::"'a \ 'a::preorder \ 'a interval" is "\a b. (min a b, b)" + by (auto simp: min_def) + +instantiation interval :: ("{exhaustive,preorder}") exhaustive +begin + +definition exhaustive_interval::"('a interval \ (bool \ term list) option) + \ natural \ (bool \ term list) option" + where + "exhaustive_interval f d = + Quickcheck_Exhaustive.exhaustive (\x. Quickcheck_Exhaustive.exhaustive (\y. f (Ivl x y)) d) d" + +instance .. + +end + +definition (in term_syntax) [code_unfold]: + "valtermify_interval x y = Code_Evaluation.valtermify (Ivl::'a::{preorder,typerep}\_) {\} x {\} y" + +instantiation interval :: ("{full_exhaustive,preorder,typerep}") full_exhaustive +begin + +definition full_exhaustive_interval:: + "('a interval \ (unit \ term) \ (bool \ term list) option) + \ natural \ (bool \ term list) option" where + "full_exhaustive_interval f d = + Quickcheck_Exhaustive.full_exhaustive + (\x. Quickcheck_Exhaustive.full_exhaustive (\y. f (valtermify_interval x y)) d) d" + +instance .. + +end + +instantiation interval :: ("{random,preorder,typerep}") random +begin + +definition random_interval :: + "natural + \ natural \ natural + \ ('a interval \ (unit \ term)) \ natural \ natural" where + "random_interval i = + scomp (Quickcheck_Random.random i) + (\man. scomp (Quickcheck_Random.random i) (\exp. Pair (valtermify_interval man exp)))" + +instance .. + +end + +lifting_update interval.lifting +lifting_forget interval.lifting + +end diff -r c1b63124245c -r ddd4aefc540f src/HOL/Library/Interval_Float.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Library/Interval_Float.thy Tue Nov 05 10:02:09 2019 -0500 @@ -0,0 +1,357 @@ +section \Approximate Operations on Intervals of Floating Point Numbers\ +theory Interval_Float + imports + Interval + Float +begin + +definition mid :: "float interval \ float" + where "mid i = (lower i + upper i) * Float 1 (-1)" + +lemma mid_in_interval: "mid i \\<^sub>i i" + using lower_le_upper[of i] + by (auto simp: mid_def set_of_eq powr_minus) + +lemma mid_le: "lower i \ mid i" "mid i \ upper i" + using mid_in_interval + by (auto simp: set_of_eq) + +definition centered :: "float interval \ float interval" + where "centered i = i - interval_of (mid i)" + +definition "split_float_interval x = split_interval x ((lower x + upper x) * Float 1 (-1))" + +lemma split_float_intervalD: "split_float_interval X = (A, B) \ set_of X \ set_of A \ set_of B" + by (auto dest!: split_intervalD simp: split_float_interval_def) + +lemma split_float_interval_bounds: + shows + lower_split_float_interval1: "lower (fst (split_float_interval X)) = lower X" + and lower_split_float_interval2: "lower (snd (split_float_interval X)) = mid X" + and upper_split_float_interval1: "upper (fst (split_float_interval X)) = mid X" + and upper_split_float_interval2: "upper (snd (split_float_interval X)) = upper X" + using mid_le[of X] + by (auto simp: split_float_interval_def mid_def[symmetric] min_def max_def real_of_float_eq + lower_split_interval1 lower_split_interval2 + upper_split_interval1 upper_split_interval2) + +lemmas float_round_down_le[intro] = order_trans[OF float_round_down] + and float_round_up_ge[intro] = order_trans[OF _ float_round_up] + +text \TODO: many of the lemmas should move to theories Float or Approximation + (the latter should be based on type @{type interval}.\ + +subsection "Intervals with Floating Point Bounds" + +context includes interval.lifting begin + +lift_definition round_interval :: "nat \ float interval \ float interval" + is "\p. \(l, u). (float_round_down p l, float_round_up p u)" + by (auto simp: intro!: float_round_down_le float_round_up_le) + +lemma lower_round_ivl[simp]: "lower (round_interval p x) = float_round_down p (lower x)" + by transfer auto +lemma upper_round_ivl[simp]: "upper (round_interval p x) = float_round_up p (upper x)" + by transfer auto + +lemma round_ivl_correct: "set_of A \ set_of (round_interval prec A)" + by (auto simp: set_of_eq float_round_down_le float_round_up_le) + +lift_definition truncate_ivl :: "nat \ real interval \ real interval" + is "\p. \(l, u). (truncate_down p l, truncate_up p u)" + by (auto intro!: truncate_down_le truncate_up_le) + +lemma lower_truncate_ivl[simp]: "lower (truncate_ivl p x) = truncate_down p (lower x)" + by transfer auto +lemma upper_truncate_ivl[simp]: "upper (truncate_ivl p x) = truncate_up p (upper x)" + by transfer auto + +lemma truncate_ivl_correct: "set_of A \ set_of (truncate_ivl prec A)" + by (auto simp: set_of_eq intro!: truncate_down_le truncate_up_le) + +lift_definition real_interval::"float interval \ real interval" + is "\(l, u). (real_of_float l, real_of_float u)" + by auto + +lemma lower_real_interval[simp]: "lower (real_interval x) = lower x" + by transfer auto +lemma upper_real_interval[simp]: "upper (real_interval x) = upper x" + by transfer auto + +definition "set_of' x = (case x of None \ UNIV | Some i \ set_of (real_interval i))" + +lemma real_interval_min_interval[simp]: + "real_interval (min_interval a b) = min_interval (real_interval a) (real_interval b)" + by (auto simp: interval_eq_set_of_iff set_of_eq real_of_float_min) + +lemma real_interval_max_interval[simp]: + "real_interval (max_interval a b) = max_interval (real_interval a) (real_interval b)" + by (auto simp: interval_eq_set_of_iff set_of_eq real_of_float_max) + +lemma in_intervalI: + "x \\<^sub>i X" if "lower X \ x" "x \ upper X" + using that by (auto simp: set_of_eq) + +abbreviation in_real_interval ("(_/ \\<^sub>r _)" [51, 51] 50) where + "x \\<^sub>r X \ x \\<^sub>i real_interval X" + +lemma in_real_intervalI: + "x \\<^sub>r X" if "lower X \ x" "x \ upper X" for x::real and X::"float interval" + using that + by (intro in_intervalI) auto + +subsection \intros for \real_interval\\ + +lemma in_round_intervalI: "x \\<^sub>r A \ x \\<^sub>r (round_interval prec A)" + by (auto simp: set_of_eq float_round_down_le float_round_up_le) + +lemma zero_in_float_intervalI: "0 \\<^sub>r 0" + by (auto simp: set_of_eq) + +lemma plus_in_float_intervalI: "a + b \\<^sub>r A + B" if "a \\<^sub>r A" "b \\<^sub>r B" + using that + by (auto simp: set_of_eq) + +lemma minus_in_float_intervalI: "a - b \\<^sub>r A - B" if "a \\<^sub>r A" "b \\<^sub>r B" + using that + by (auto simp: set_of_eq) + +lemma uminus_in_float_intervalI: "-a \\<^sub>r -A" if "a \\<^sub>r A" + using that + by (auto simp: set_of_eq) + +lemma real_interval_times: "real_interval (A * B) = real_interval A * real_interval B" + by (auto simp: interval_eq_iff lower_times upper_times min_def max_def) + +lemma times_in_float_intervalI: "a * b \\<^sub>r A * B" if "a \\<^sub>r A" "b \\<^sub>r B" + using times_in_intervalI[OF that] + by (auto simp: real_interval_times) + +lemma real_interval_abs: "real_interval (abs_interval A) = abs_interval (real_interval A)" + by (auto simp: interval_eq_iff min_def max_def) + +lemma abs_in_float_intervalI: "abs a \\<^sub>r abs_interval A" if "a \\<^sub>r A" + by (auto simp: set_of_abs_interval real_interval_abs intro!: imageI that) + +lemma interval_of[intro,simp]: "x \\<^sub>r interval_of x" + by (auto simp: set_of_eq) + +lemma split_float_interval_realD: "split_float_interval X = (A, B) \ x \\<^sub>r X \ x \\<^sub>r A \ x \\<^sub>r B" + by (auto simp: set_of_eq prod_eq_iff split_float_interval_bounds) + + +subsection \bounds for lists\ + +lemma lower_Interval: "lower (Interval x) = fst x" + and upper_Interval: "upper (Interval x) = snd x" + if "fst x \ snd x" + using that + by (auto simp: lower_def upper_def Interval_inverse split_beta') + +definition all_in_i :: "'a::preorder list \ 'a interval list \ bool" + (infix "(all'_in\<^sub>i)" 50) + where "x all_in\<^sub>i I = (length x = length I \ (\i < length I. x ! i \\<^sub>i I ! i))" + +definition all_in :: "real list \ float interval list \ bool" + (infix "(all'_in)" 50) + where "x all_in I = (length x = length I \ (\i < length I. x ! i \\<^sub>r I ! i))" + +definition all_subset :: "'a::order interval list \ 'a interval list \ bool" + (infix "(all'_subset)" 50) + where "I all_subset J = (length I = length J \ (\i < length I. set_of (I!i) \ set_of (J!i)))" + +lemmas [simp] = all_in_def all_subset_def + +lemma all_subsetD: + assumes "I all_subset J" + assumes "x all_in I" + shows "x all_in J" + using assms + by (auto simp: set_of_eq; fastforce) + +lemma round_interval_mono: "set_of (round_interval prec X) \ set_of (round_interval prec Y)" + if "set_of X \ set_of Y" + using that + by transfer + (auto simp: float_round_down.rep_eq float_round_up.rep_eq truncate_down_mono truncate_up_mono) + +lemma Ivl_simps[simp]: "lower (Ivl a b) = min a b" "upper (Ivl a b) = b" + subgoal by transfer simp + subgoal by transfer simp + done + +lemma set_of_subset_iff: "set_of X \ set_of Y \ lower Y \ lower X \ upper X \ upper Y" + for X Y::"'a::linorder interval" + by (auto simp: set_of_eq subset_iff) + +lemma bounds_of_interval_eq_lower_upper: + "bounds_of_interval ivl = (lower ivl, upper ivl)" if "lower ivl \ upper ivl" + using that + by (auto simp: lower.rep_eq upper.rep_eq) + +lemma real_interval_Ivl: "real_interval (Ivl a b) = Ivl a b" + by transfer (auto simp: min_def) + +lemma set_of_mul_contains_real_zero: + "0 \\<^sub>r (A * B)" if "0 \\<^sub>r A \ 0 \\<^sub>r B" + using that set_of_mul_contains_zero[of A B] + by (auto simp: set_of_eq) + +fun subdivide_interval :: "nat \ float interval \ float interval list" + where "subdivide_interval 0 I = [I]" + | "subdivide_interval (Suc n) I = ( + let m = mid I + in (subdivide_interval n (Ivl (lower I) m)) @ (subdivide_interval n (Ivl m (upper I))) + )" + +lemma subdivide_interval_length: + shows "length (subdivide_interval n I) = 2^n" + by(induction n arbitrary: I, simp_all add: Let_def) + +lemma lower_le_mid: "lower x \ mid x" "real_of_float (lower x) \ mid x" + and mid_le_upper: "mid x \ upper x" "real_of_float (mid x) \ upper x" + unfolding mid_def + subgoal by transfer (auto simp: powr_neg_one) + subgoal by transfer (auto simp: powr_neg_one) + subgoal by transfer (auto simp: powr_neg_one) + subgoal by transfer (auto simp: powr_neg_one) + done + +lemma subdivide_interval_correct: + "list_ex (\i. x \\<^sub>r i) (subdivide_interval n I)" if "x \\<^sub>r I" for x::real + using that +proof(induction n arbitrary: x I) + case 0 + then show ?case by simp +next + case (Suc n) + from \x \\<^sub>r I\ consider "x \\<^sub>r Ivl (lower I) (mid I)" | "x \\<^sub>r Ivl (mid I) (upper I)" + by (cases "x \ real_of_float (mid I)") + (auto simp: set_of_eq min_def lower_le_mid mid_le_upper) + from this[case_names lower upper] show ?case + by cases (use Suc.IH in \auto simp: Let_def\) +qed + +fun interval_list_union :: "'a::lattice interval list \ 'a interval" + where "interval_list_union [] = undefined" + | "interval_list_union [I] = I" + | "interval_list_union (I#Is) = sup I (interval_list_union Is)" + +lemma interval_list_union_correct: + assumes "S \ []" + assumes "i < length S" + shows "set_of (S!i) \ set_of (interval_list_union S)" + using assms +proof(induction S arbitrary: i) + case (Cons a S i) + thus ?case + proof(cases S) + fix b S' + assume "S = b # S'" + hence "S \ []" + by simp + show ?thesis + proof(cases i) + case 0 + show ?thesis + apply(cases S) + using interval_union_mono1 + by (auto simp add: 0) + next + case (Suc i_prev) + hence "i_prev < length S" + using Cons(3) by simp + + from Cons(1)[OF \S \ []\ this] Cons(1) + have "set_of ((a # S) ! i) \ set_of (interval_list_union S)" + by (simp add: \i = Suc i_prev\) + also have "... \ set_of (interval_list_union (a # S))" + using \S \ []\ + apply(cases S) + using interval_union_mono2 + by auto + finally show ?thesis . + qed + qed simp +qed simp + +lemma split_domain_correct: + fixes x :: "real list" + assumes "x all_in I" + assumes split_correct: "\x a I. x \\<^sub>r I \ list_ex (\i::float interval. x \\<^sub>r i) (split I)" + shows "list_ex (\s. x all_in s) (split_domain split I)" + using assms(1) +proof(induction I arbitrary: x) + case (Cons I Is x) + have "x \ []" + using Cons(2) by auto + obtain x' xs where x_decomp: "x = x' # xs" + using \x \ []\ list.exhaust by auto + hence "x' \\<^sub>r I" "xs all_in Is" + using Cons(2) + by auto + show ?case + using Cons(1)[OF \xs all_in Is\] + split_correct[OF \x' \\<^sub>r I\] + apply (auto simp add: list_ex_iff set_of_eq) + by (smt length_Cons less_Suc_eq_0_disj nth_Cons_0 nth_Cons_Suc x_decomp) +qed simp + + +lift_definition(code_dt) inverse_float_interval::"nat \ float interval \ float interval option" is + "\prec (l, u). if (0 < l \ u < 0) then Some (float_divl prec 1 u, float_divr prec 1 l) else None" + by (auto intro!: order_trans[OF float_divl] order_trans[OF _ float_divr] + simp: divide_simps) + +lemma inverse_float_interval_eq_Some_conv: + defines "one \ (1::float)" + shows + "inverse_float_interval p X = Some R \ + (lower X > 0 \ upper X < 0) \ + lower R = float_divl p one (upper X) \ + upper R = float_divr p one (lower X)" + by clarsimp (transfer fixing: one, force simp: one_def split: if_splits) + +lemma inverse_float_interval: + "inverse ` set_of (real_interval X) \ set_of (real_interval Y)" + if "inverse_float_interval p X = Some Y" + using that + apply (clarsimp simp: set_of_eq inverse_float_interval_eq_Some_conv) + by (intro order_trans[OF float_divl] order_trans[OF _ float_divr] conjI) + (auto simp: divide_simps) + +lemma inverse_float_intervalI: + "x \\<^sub>r X \ inverse x \ set_of' (inverse_float_interval p X)" + using inverse_float_interval[of p X] + by (auto simp: set_of'_def split: option.splits) + +lemma inverse_float_interval_eqI: "inverse_float_interval p X = Some IVL \ x \\<^sub>r X \ inverse x \\<^sub>r IVL" + using inverse_float_intervalI[of x X p] + by (auto simp: set_of'_def) + +lemma real_interval_abs_interval[simp]: + "real_interval (abs_interval x) = abs_interval (real_interval x)" + by (auto simp: interval_eq_set_of_iff set_of_eq real_of_float_max real_of_float_min) + +lift_definition floor_float_interval::"float interval \ float interval" is + "\(l, u). (floor_fl l, floor_fl u)" + by (auto intro!: floor_mono simp: floor_fl.rep_eq) + +lemma lower_floor_float_interval[simp]: "lower (floor_float_interval x) = floor_fl (lower x)" + by transfer auto +lemma upper_floor_float_interval[simp]: "upper (floor_float_interval x) = floor_fl (upper x)" + by transfer auto + +lemma floor_float_intervalI: "\x\ \\<^sub>r floor_float_interval X" if "x \\<^sub>r X" + using that by (auto simp: set_of_eq floor_fl_def floor_mono) + +end + + +subsection \constants for code generation\ + +definition lowerF::"float interval \ float" where "lowerF = lower" +definition upperF::"float interval \ float" where "upperF = upper" + + +end \ No newline at end of file diff -r c1b63124245c -r ddd4aefc540f src/HOL/Library/Library.thy --- a/src/HOL/Library/Library.thy Tue Nov 05 14:57:41 2019 +0100 +++ b/src/HOL/Library/Library.thy Tue Nov 05 10:02:09 2019 -0500 @@ -38,6 +38,8 @@ Groups_Big_Fun Indicator_Function Infinite_Set + Interval + Interval_Float IArray Landau_Symbols Lattice_Algebras