Theory Percentage
theory Percentage
imports HOL.Real
begin
section‹Implementation Detail: Percentage Type›
typedef percentage = ‹{0..(1::real)}›
morphisms real_of_percentage Abs_percentage
by auto
setup_lifting type_definition_percentage
instantiation percentage :: ‹zero›
begin
lift_definition zero_percentage :: ‹percentage› is ‹0 :: real›
by auto
instance ..
end
instantiation percentage :: ‹monoid_mult›
begin
lift_definition one_percentage :: ‹percentage› is ‹1 :: real›
by auto
lift_definition times_percentage :: ‹percentage ⇒ percentage ⇒ percentage› is ‹(*) :: real ⇒ _›
by (auto simp: mult_le_one)
instance
by standard (transfer; simp; fail)+
end
text‹A \<^term>‹Abs_percentage 0.1› would give a "Abstraction violation" in a value command.
So here is some magic to make code work.›
definition percentage :: ‹real ⇒ percentage› where
‹percentage p ≡ if p ≤ 0 then 0 else if p ≥ 1 then 1 else Abs_percentage p›
lemma percentage_code [code abstract]:
‹real_of_percentage (percentage p) = (if p ≤ 0 then 0 else if p ≥ 1 then 1 else p)›
unfolding percentage_def
by (simp add: Abs_percentage_inverse one_percentage.rep_eq zero_percentage.rep_eq)
value[code] ‹percentage 0.1›
lemma ‹real_of_percentage (percentage 0.1) * (25::real) = 2.5› by eval
lemma ‹(25::real) * real_of_percentage (percentage 0.1) = 2.5› by eval
text‹And now we get rid of explicit calls to \<^const>‹real_of_percentage››
declare [[coercion ‹real_of_percentage :: percentage ⇒ real›]]
lemma ‹(percentage 0.1) * (25::real) = 2.5› by eval
lemma ‹(25::real) * (percentage 0.1) = 2.5› by eval
lemma ‹(percentage 0.1) * (25::nat) = 2.5› by eval
lemma ‹(25::nat) * (percentage 0.1) = 2.5› by eval
lemma percentage_range:
fixes p :: ‹percentage›
shows ‹0 ≤ p ∧ p ≤ 1›
using real_of_percentage by auto
lemma real_of_percentage_range:
‹0 ≤ real_of_percentage p›
‹real_of_percentage p ≤ 1›
by(simp add: percentage_range)+
lemma percentage_min_max_simps:
‹real_of_percentage p = min 1 p›
‹real_of_percentage p = max 0 p›
by (simp add: percentage_range)+
lemma real_of_percentage_mult:
‹real a * real_of_percentage p ≤ a›
‹real_of_percentage p * real a ≤ a›
by (simp add: mult.commute mult_left_le percentage_range)+
lemma percentage_percentage_mult_right:
fixes a p ::‹percentage›
shows ‹a * p ≤ a›
by (simp add: mult_right_le_one_le real_of_percentage_range times_percentage.rep_eq)
lemma percentage_percentage_mult_left:
fixes a p ::‹percentage›
shows ‹p * a ≤ a›
by (simp add: mult.commute percentage_percentage_mult_right mult_right_le_one_le percentage_range times_percentage.rep_eq)
lemma percentage_real_pos_mult_right:
‹a ≥ 0 ⟹ a * real_of_percentage p ≤ a›
by (simp add: mult_left_le percentage_range)
lemma percentage_real_pos_mult_left:
‹a ≥ 0 ⟹ real_of_percentage p * a ≤ a›
by (simp add: mult_left_le_one_le percentage_range)
lemma percentage_mult_right_mono:
fixes a b p :: ‹percentage›
shows ‹a ≤ b ⟹ a * p ≤ b * p›
by transfer (simp add: mult_right_mono)
lemma percentage_real_mult_right_mono:
fixes p :: ‹percentage› and a b :: ‹real›
shows ‹a ≤ b ⟹ a * p ≤ b * p›
by transfer (simp add: mult_right_mono)
lemma percentage_real_diff_mult_right_mono:
‹a ≤ b ⟹ a - a * (real_of_percentage p) ≤ b - b * (real_of_percentage p)›
proof -
assume a: ‹a ≤ b›
have ‹0 ≤ b - a› by (simp add: a)
hence ‹(b - a) * real_of_percentage p ≤ b - a›
by (simp add: percentage_real_pos_mult_right)
with a show ‹?thesis›
by (simp add: a left_diff_distrib')
qed
lemma percentage_nat_diff_mult_right_mono:
fixes p :: ‹percentage› and a b :: ‹nat›
shows ‹(a :: nat) ≤ b ⟹ a - a * p ≤ b - b * p›
by (simp add: percentage_real_diff_mult_right_mono)
lemma percentage_add_limit_helper:
‹a ≥ 0 ⟹ b ≤ c - a ⟹ a * real_of_percentage prozent + b ≤ c›
by (metis add.commute le_diff_eq order_trans percentage_real_pos_mult_right)
end