Theory Repeat
theory Repeat
imports Main
begin
section "Repeat Function At Most N Times"
fun repeatatm :: "nat ⇒ ('a ⇒ 'b ⇒ bool) ⇒ ('a ⇒ 'b ⇒ 'a) ⇒ 'a ⇒ 'b ⇒ 'a"
where
"repeatatm 0 _ _ acc _ = acc" |
"repeatatm (Suc n) f g acc obsv = (if f acc obsv then acc else repeatatm n f g (g acc obsv) obsv)"
declare repeatatm.simps[simp del]
subsection "Step and early termination lemmas"
lemma repeatatm_step_stop_Suc:
"f (repeatatm n f g a b) b
⟹ repeatatm (Suc n) f g a b = repeatatm n f g a b"
proof (induct n arbitrary: a)
case 0
then show ?case
by (simp add: repeatatm.simps)
next
case (Suc n a)
note IH = this
show ?case
proof (cases "f a b")
assume "f a b"
then show ?case
by (simp add: repeatatm.simps)
next
assume "¬ f a b"
with IH(2)
have "f (repeatatm n f g (g a b) b) b"
by (simp add: repeatatm.simps)
with IH(1)
have "repeatatm (Suc n) f g (g a b) b = repeatatm n f g (g a b) b"
by blast
then show ?case
by (simp add: repeatatm.simps)
qed
qed
lemma repeatatm_step:
"¬f (repeatatm n f g a b) b
⟹ repeatatm (Suc n) f g a b = g (repeatatm n f g a b) b"
proof (induct n arbitrary: a)
case 0
then show ?case
by (simp add: repeatatm.simps)
next
case (Suc n a)
note IH = this
show ?case
proof (cases "f a b")
assume "f a b"
with IH(2)
show ?case
by (simp add: repeatatm.simps)
next
assume "¬ f a b"
with IH(2)
have "¬ f (repeatatm n f g (g a b) b) b"
by (simp add: repeatatm.simps)
with IH(1)
have "repeatatm (Suc n) f g (g a b) b = g (repeatatm n f g (g a b) b) b"
by blast
then show ?case
by (simp add: repeatatm.simps ‹¬ f a b›)
qed
qed
lemma repeatatm_step_forward:
"¬f a b ⟹ repeatatm (Suc n) f g a b = repeatatm n f g (g a b) b"
by (induct n arbitrary: a; simp add: repeatatm.simps)
lemma repeatatm_stop_Suc:
"⟦f (repeatatm n f g a b) b⟧ ⟹ f (repeatatm (Suc n) f g a b) b"
proof (induct n arbitrary: a)
case 0
then show ?case
by (simp add: repeatatm.simps)
next
case (Suc n a)
note IH = this
show ?case
proof (cases "f a b")
assume "f a b"
then show ?case
by (simp add: repeatatm.simps)
next
assume "¬ f a b"
with IH(2)
have "f (repeatatm n f g (g a b) b) b"
by (simp add: repeatatm.simps)
with IH(1)
have "f (repeatatm (Suc n) f g (g a b) b) b"
by blast
then show ?case
by (simp add: repeatatm.simps)
qed
qed
lemma repeatatm_stop:
"⟦f (repeatatm n f g a b) b; n ≤ m⟧ ⟹ f (repeatatm m f g a b) b"
proof (induct m arbitrary: a n)
case 0
then show ?case
by simp
next
case (Suc m a n)
note IH = this
show ?case
proof (cases "n ≤ m")
assume "n ≤ m"
with repeatatm_stop_Suc[of f m g a b] IH(1)[OF IH(2)]
show ?case
by simp
next
assume "¬ n ≤ m"
with IH(2,3)
show ?case
using le_Suc_eq by blast
qed
qed
lemma repeatatm_step_stop:
"⟦f (repeatatm n f g a b) b; n ≤ m⟧ ⟹ repeatatm m f g a b = repeatatm n f g a b"
proof (induct m arbitrary: a n)
case 0
then show ?case
by simp
next
case (Suc m a n)
note IH = this
show ?case
proof (cases "n ≤ m")
assume "n ≤ m"
with repeatatm_step_stop_Suc[of f m g a b] IH(2) IH(1)[OF IH(2)]
show ?case
by simp
next
assume "¬ n ≤ m"
then show ?case
using Suc.prems(2) le_SucE by blast
qed
qed
lemma repeatatm_not_stop_Suc:
"¬f (repeatatm (Suc n) f g a b) b ⟹ ¬f (repeatatm n f g a b) b"
apply (rule contrapos_nn[where Q = "f (repeatatm (Suc n) f g a b) b"]; simp)
using repeatatm_stop_Suc[of f n g a b] by simp
lemma repeatatm_maintain_inv:
assumes "⋀a. P a ⟹ P (g a b)"
shows "P a ⟹ P (repeatatm n f g a b)"
proof (induct n arbitrary: a)
case 0
then show ?case
by (simp add: repeatatm.simps)
next
case (Suc n a)
note IH = this
from IH(1)[OF IH(2)]
have "P (repeatatm n f g a b)"
by assumption
with `⋀a. P a ⟹ P (g a b)`
show ?case
by (metis repeatatm_step repeatatm_step_stop_Suc)
qed
section "Repeat Function N Times"
definition repeat :: "nat ⇒ ('a ⇒ 'b ⇒ 'a) ⇒ 'a ⇒ 'b ⇒ 'a"
where
"repeat n f a b = repeatatm n (λx y. False) f a b"
lemma repeat_0:
"repeat 0 f a b = a"
by (simp add: repeat_def repeatatm.simps(1))
lemma repeat_step:
"repeat (Suc n) f a b = f (repeat n f a b) b"
unfolding repeat_def
by (simp add: repeatatm_step)
lemma repeat_step_forward:
"repeat (Suc n) f a b = repeat n f (f a b) b"
unfolding repeat_def
by (simp add: repeatatm_step_forward)
lemma repeat_maintain_inv:
assumes "⋀a. P a ⟹ P (f a b)"
shows "P a ⟹ P (repeat n f a b)"
by (simp add: assms repeat_def repeatatm_maintain_inv)
lemma repeat_eq_fold:
"repeat n f a b = fold (λ_ a. f a b) [0..<n] a"
apply (induct n)
apply (simp add: repeat_def repeatatm.simps)
apply (subst repeat_step)
apply simp
done
end