Theory Interval_Division_Non_Zero
chapter‹Basic Properties of Interval Division›
theory
Interval_Division_Non_Zero
imports
Interval_Utilities
begin
text ‹
The theory @{theory "HOL-Library.Interval"} does not define a division operation on intervals.
In the following we define a locale capturing the core properties of division by an interval that
does not contain zero. ›
section‹Preliminaries›
lemma division_leq_neg:
fixes x :: "'a::{linordered_field}"
assumes "0 < x" and "y < 0" and "z < 0" and "y ≤ z"
shows "x / z ≤ x / y"
proof -
have "x * y ≤ x * z" using assms by simp
hence "(x * y) / (y * z) ≤ (x * z) / (y * z)"
using assms
by (simp add: divide_right_mono zero_less_mult_iff neg_divide_le_eq)
thus ?thesis using assms by auto[1]
qed
lemma division_leq:
fixes x :: "'a::{linordered_field}"
assumes "0 < x" and "y ≤ z" and ‹y ≠ 0 ∧ z ≠ 0› and ‹(y < 0 ∧ z < 0) ∨ (0 < y ∧ 0 < z) ›
shows "x / z ≤ x / y"
proof (cases ‹(y < 0 ∧ z < 0)›)
case True
then show ?thesis using assms division_leq_neg by blast
next
case False
have ‹(0 < y ∧ 0 < z)› using assms False by blast
then show ?thesis
using assms
by (simp add: frac_le)
qed
lemma upper_leq_lower_div:
fixes Y :: "'a::{linordered_field} interval"
assumes ‹lower Y ≤ upper Y› and ‹¬ 0 ∈⇩i Y›
shows ‹1 / upper Y ≤ 1 / lower Y›
using assms division_leq frac_le
by (metis atLeastAtMost_iff inverse_eq_divide le_imp_inverse_le
le_imp_inverse_le_neg linorder_not_less set_of_eq)
section‹A Locale for Interval Division Where the Quotient-Interval does not Contain Zero›
locale interval_division = inverse +
constrains inverse :: ‹'a::{linordered_field, real_normed_algebra,linear_continuum_topology} interval ⇒ 'a interval›
and divide :: ‹'a::{linordered_field, real_normed_algebra,linear_continuum_topology} interval ⇒ 'a interval ⇒ 'a interval›
assumes inverse_left: ‹¬ 0 ∈⇩i x ⟹ 1 ≤ (inverse x) * x›
and divide: ‹¬ 0 ∈⇩i y ⟹ x ≤ (divide x y) * y›
begin
end
lemma interval_non_zero_eq:
‹¬ 0 ∈⇩i (i::'a::{linorder, zero} interval) = (lower i < 0 ∧ upper i < 0) ∨ (lower i > 0 ∧ upper i > 0)›
by (metis in_bounds in_intervalI linorder_not_less lower_le_upper order_le_less_trans)
lemma inverse_includes_one:
assumes ‹¬ 0 ∈⇩i (i::'a::{division_ring,linordered_ring} interval)›
shows ‹1 ∈⇩i (mk_interval (1 / upper i, 1 / lower i)) * i›
using assms interval_non_zero_eq[of i]
apply(simp add: set_of_eq)
apply(safe, simp_all)
by (metis in_bounds lower_in_interval mk_interval_upper nonzero_eq_divide_eq times_in_intervalI
upper_in_interval)+
lemma inverse_includes_one':
assumes ‹¬ 0 ∈⇩i (i::'a::{division_ring,linordered_ring} interval)›
shows ‹1 ≤ (mk_interval (1 / upper i, 1 / lower i)) * i›
by (simp add: assms in_bounds inverse_includes_one less_eq_interval_def)
locale interval_division_inverse = inverse +
constrains inverse :: ‹'a::{linordered_field, real_normed_algebra,linear_continuum_topology} interval ⇒ 'a interval›
and divide :: ‹'a::{linordered_field, real_normed_algebra,linear_continuum_topology} interval ⇒ 'a interval ⇒ 'a interval›
assumes inverse_non_zero_def: ‹¬ 0 ∈⇩i x ⟹ (inverse x) = mk_interval(1 / (upper x), 1 / (lower x))›
and divide_non_zero_def: ‹¬ 0 ∈⇩i y ⟹ (divide x y) = inverse y * x›
begin
sublocale interval_division divide inverse
apply(standard)
subgoal
by (simp add: inverse_includes_one' inverse_non_zero_def)
subgoal
by (metis (no_types, opaque_lifting) divide_non_zero_def interval_mul_commute inverse_includes_one' inverse_non_zero_def mult.assoc one_times_ivl_right times_interval_right)
done
lemma inverse_left_ge_one:
assumes ‹¬ 0 ∈⇩i x›
shows ‹1 ≤ (inverse x) * x›
proof -
have lower_ne_zero: ‹lower x ≠ 0›
using assms lower_in_interval by metis
have upper_ne_zero: ‹lower x ≠ 0›
using assms lower_in_interval by metis
have ‹1 ≤ (mk_interval ( 1 / (upper x), 1 / (lower x))) * x›
proof(cases "1 / upper x ≤ 1 / lower x")
case True note * = this
then show ?thesis
proof(cases "upper x = lower x")
case True
then show ?thesis
using upper_times[of "mk_interval (1 / upper x, 1 / lower x)" x]
lower_times[of "mk_interval (1 / upper x, 1 / lower x)" x]
interval_eq_iff[of "mk_interval (1 / upper x, 1 / lower x) * x" 1]
lower_ne_zero upper_ne_zero
unfolding mk_interval'
by simp
next
case False
then show ?thesis
using interval_eq_iff[of "mk_interval (1 / upper x, 1 / lower x) * x" 1]
upper_times[of "mk_interval (1 / upper x, 1 / lower x)" x]
lower_times[of "mk_interval (1 / upper x, 1 / lower x)" x]
proof -
have "1 / lower x = upper (mk_interval (1 / upper x, 1 / lower x))"
by (simp add: "*")
then show ?thesis
by (metis (no_types) in_bounds less_eq_interval_def lower_in_interval lower_one
nonzero_divide_eq_eq times_in_intervalI upper_in_interval upper_ne_zero upper_one)
qed
qed
next
case False
then show ?thesis
using interval_eq_iff[of "mk_interval (1 / upper x, 1 / lower x) * x" 1]
upper_times[of "mk_interval (1 / upper x, 1 / lower x)" x]
lower_times[of "mk_interval (1 / upper x, 1 / lower x)" x]
using assms lower_le_upper upper_leq_lower_div by blast
qed
then show ?thesis
by (simp add: assms inverse_non_zero_def)
qed
lemma division_right_ge_refl:
assumes ‹¬ 0 ∈⇩i y›
shows ‹x ≤ x * ((inverse y) * y)›
proof -
have a1: ‹set_of 1 ⊆ set_of ((inverse y) * y)›
using inverse_left_ge_one[of y, simplified assms, simplified]
by (simp add: interval_set_leq_eq)
show ?thesis
using set_of_mul_inc_right[of 1 "mk_interval (1 / upper y, 1 / lower y) * y" x,
simplified one_times_ivl_right[of x] a1, simplified]
by (metis a1 interval_set_leq_eq one_times_ivl_right times_interval_right)
qed
lemma division_right_ge_refl':
assumes ‹¬ 0 ∈⇩i y›
shows ‹x ≤ x * inverse y * y›
by (simp add: assms division_right_ge_refl mult.assoc)
lemma interval_div_constant:
assumes ‹0 ∉ set_of Y› and ‹0 ≤ x›
shows ‹divide (interval_of x) Y = Interval( x / upper Y, x / lower Y)›
proof -
have l: ‹lower Y ≤ upper Y› using lower_le_upper by simp
have ‹1 / upper Y ≤ 1 / lower Y› using assms l
by (metis divide_left_mono frac_le in_intervalI linorder_not_less mult_neg_neg order_less_le
zero_less_one_class.zero_le_one)
then show ?thesis
using
interval_of.abs_eq[of x]
assms divide_non_zero_def[of Y "interval_of x", simplified assms, simplified]
inverse_non_zero_def[of Y, simplified assms, simplified]
interval_times_scalar_pos_l interval_times_scalar_pos_r by fastforce
qed
lemma interval_of_width:
assumes ‹¬ 0 ∈⇩i Y›
shows ‹interval_of(width (divide (interval_of 1) Y)) = Interval( 1 / lower Y - 1 / upper Y, 1 / lower Y - 1 / upper Y) ›
proof(cases "Y" rule:interval_linorder_case_split[of _ 0 "λ Y. interval_of(width (divide (interval_of 1) Y))
= Interval( 1 / lower Y - 1 / upper Y, 1 / lower Y - 1 / upper Y)" ])
case LeftOf
have ‹1 / upper Y ≤ 1 / lower Y›
using assms division_leq_neg LeftOf
by (simp add: le_divide_eq)
then show ?case
using interval_div_constant upper_bounds lower_bounds assms
unfolding width_def interval_of_def by fastforce
next
case Including
then show ?case using assms by simp
next
case RightOf
have ‹1 / upper Y ≤ 1 / lower Y›
by (simp add: assms upper_leq_lower_div)
then show ?case
using interval_div_constant upper_bounds lower_bounds assms
unfolding width_def interval_of_def by fastforce
qed
lemma abs_pos:
assumes ‹0 < lower Y › and ‹¬ 0 ∈⇩i Y›
shows ‹abs_interval(divide (interval_of 1) Y) = Interval( 1 / upper Y, 1 / lower Y)›
proof -
have l: ‹lower Y ≤ upper Y› using lower_le_upper by simp
have ‹0 < 1 / upper Y ›
by (metis assms(1) l dual_order.strict_trans1 zero_less_divide_1_iff)
moreover have ‹ 0 < 1 / lower Y›
by (metis assms(1) zero_less_divide_1_iff)
moreover have ‹1 / upper Y ≤ 1 / lower Y›
using assms by (simp add: frac_le)
moreover have ‹divide (interval_of 1) Y = Interval( 1 / upper Y, 1 / lower Y)›
using assms interval_div_constant[of Y 1] by simp
ultimately show ?thesis
unfolding abs_interval_def by (simp add: bounds_of_interval_eq_lower_upper)
qed
lemma abs_neg:
assumes ‹upper Y < 0 › and ‹¬ 0 ∈⇩i Y›
shows ‹abs_interval(divide (interval_of 1) Y) = Interval(1 / ¦lower Y¦, 1 / ¦upper Y¦)›
proof -
have l: ‹lower Y ≤ upper Y› using lower_le_upper by simp
have i0: ‹ 1 / upper Y < 0 › and i1: ‹ 1 / lower Y < 0›
using assms by (simp, meson assms(1) divide_less_0_1_iff lower_le_upper order_le_less_trans)
moreover have i2: ‹¦upper Y¦ ≤ ¦lower Y¦›
using assms l by linarith
then have i3: ‹¦1 / lower Y¦ ≤ ¦1 / upper Y¦›
using assms division_leq_neg i1
by (simp add: division_leq)
moreover have ‹divide (interval_of 1) Y = Interval( 1 / upper Y, 1 / lower Y)›
using assms interval_div_constant[of Y 1] by simp
moreover have ‹abs_interval(Interval( 1 / upper Y, 1 / lower Y)) = Interval(¦1 / lower Y¦, ¦1 / upper Y¦)›
using assms i0 i1 i2 i3 unfolding abs_interval_def min_def max_def
by (simp add: bounds_of_interval_eq_lower_upper)
moreover have ‹... = Interval(1 / ¦lower Y¦, 1 / ¦upper Y¦)›
by auto[1]
ultimately show ?thesis
using assms interval_div_constant by force
qed
end
end