Theory Imperative_Loops

theory Imperative_Loops
  imports 
    "Refine_Imperative_HOL.Sepref_HOL_Bindings"
    "Refine_Imperative_HOL.Pf_Mono_Prover"
    "Refine_Imperative_HOL.Pf_Add"
begin

section ‹Imperative Loops›

text "An auxiliary while rule provided by Peter Lammich."

lemma heap_WHILET_rule:
  assumes
    "wf R"
    "P ⟹A I s"
    "⋀s. <I s * true> bi s <λr. I s * ↑(r ⟷ b s)>t"
    "⋀s. b s ⟹ <I s * true> f s <λs'. I s' * ↑((s', s) ∈ R)>t"
    "⋀s. ¬ b s ⟹ I s ⟹A Q s"
  shows "<P * true> heap_WHILET bi f s <Q>t"
proof -
  have "<I s * true> heap_WHILET bi f s <λs'. I s' * ↑(¬ b s')>t"
    using assms(1)
  proof (induction arbitrary:)
    case (less s)
    show ?case
    proof (cases "b s")
      case True
      then show ?thesis
        by (subst heap_WHILET_unfold) (sep_auto heap: assms(3,4) less)
    next
      case False
      then show ?thesis
        by (subst heap_WHILET_unfold) (sep_auto heap: assms(3))
    qed
  qed
  then show ?thesis
    apply (rule cons_rule[rotated 2])
     apply (intro ent_star_mono assms(2) ent_refl)
    apply clarsimp
    apply (intro ent_star_mono assms(5) ent_refl)
    .
qed


lemma heap_WHILET_rule':
  assumes
    "wf R"
    "P ⟹A I s si * F"
    "⋀si s. <I s si * F> bi si <λr. I s si * F * ↑(r ⟷ b s)>t"
    "⋀si s. b s ⟹ <I s si * F> f si <λsi'. ∃As'. I s' si' * F * ↑((s', s) ∈ R)>t"
    "⋀si s. ¬ b s ⟹ I s si * F ⟹A Q s si"
  shows "<P> heap_WHILET bi f si <λsi. ∃As. Q s si>t"
proof -
  have "<I s si * F> heap_WHILET bi f si <λsi'. ∃As'. I s' si' * F * ↑(¬ b s')>t"
    using assms(1)
  proof (induction arbitrary: si)
    case (less s)
    show ?case
    proof (cases "b s")
      case True
      then show ?thesis
        apply (subst heap_WHILET_unfold)
        apply (sep_auto heap: assms(3,4) less)
        done
    next
      case False
      then show ?thesis
        by (subst heap_WHILET_unfold) (sep_auto heap: assms(3))
    qed
  qed
  then show ?thesis
    apply (rule cons_rule[rotated 2])
     apply (intro ent_star_mono assms(2) ent_refl)
    apply clarsimp
    apply (sep_auto )
    apply (erule ent_frame_fwd[OF assms(5)])
     apply frame_inference
    by sep_auto

qed

(* Added by NM, just a technicality since this rule fits our use case better *)

text "I derived my own version,
simply because it was a better fit to my use case."

corollary heap_WHILET_rule'':
  assumes
    "wf R"
    "P ⟹A I s"
    "⋀s. <I s * true> bi s <λr. I s * ↑(r ⟷ b s)>t"
    "⋀s. b s ⟹ <I s * true> f s <λs'. I s' * ↑((s', s) ∈ R)>t"
    "⋀s. ¬ b s ⟹ I s ⟹A Q s"
  shows "<P> heap_WHILET bi f s <Q>t"
  supply R = heap_WHILET_rule'[of R P "λs si. ↑(s = si) * I s" s _ true bi b f "λs si.↑(s = si) * Q s * true"]
  thm R
  using assms ent_true_drop apply(sep_auto heap: R assms)
  done
    (*
explicit proof:

proof -
  have "<I s * true> heap_WHILET bi f s <λs'. I s' * ↑(¬ b s')>t"
    using assms(1)
  proof (induction arbitrary:)
    case (less s)
    show ?case
    proof (cases "b s")
      case True
      then show ?thesis
        by (subst heap_WHILET_unfold) (sep_auto heap: assms(3,4) less)
    next
      case False
      then show ?thesis
        by (subst heap_WHILET_unfold) (sep_auto heap: assms(3))
    qed
  qed
  then show ?thesis
    apply (rule cons_rule[rotated 2])
     apply (intro ent_true_drop assms(2) ent_refl)
    apply clarsimp
    apply(intro ent_star_mono assms(5) ent_refl)
    .
qed
*)

end