Theory C-restr

theory C-restr
imports C-Meet HOLCF-Utils
theory "C-restr"
imports C "C-Meet" "HOLCF-Utils"
begin

subsubsection {* The demand of a $C$-function *}

text {*
The demand is the least amount of resources required to produce a non-bottom element,
if at all.
*}

definition demand :: "(C → 'a::pcpo) ⇒ C" where
  "demand f = (if f⋅C ≠ ⊥ then C(LEAST n. f⋅Cn ≠ ⊥) else C)"

text {*
Because of continuity, a non-bottom value can always be obtained with finite resources.
*}

lemma finite_resources_suffice:
  assumes "f⋅C ≠ ⊥"
  obtains n where "f⋅Cn ≠ ⊥"
proof-
  {
  assume "∀n. f⋅(Cn) = ⊥"
  hence "f⋅C ⊑ ⊥"
    by (auto intro: lub_below[OF ch2ch_Rep_cfunR[OF chain_iterate]]
             simp add: Cinf_def fix_def2 contlub_cfun_arg[OF chain_iterate])
  with assms have False by simp
  }
  thus ?thesis using that by blast
qed

text {*
Because of monotonicity, a non-bottom value can always be obtained with more resources.
*}


lemma more_resources_suffice:
  assumes "f⋅r ≠ ⊥" and "r ⊑ r'"
  shows "f⋅r' ≠ ⊥"
  using assms(1) monofun_cfun_arg[OF assms(2), where  f = f]
  by auto

lemma infinite_resources_suffice:
  shows "f⋅r ≠ ⊥ ⟹ f⋅C ≠ ⊥"
  by (erule more_resources_suffice[OF _ below_Cinf])

lemma demand_suffices:
  assumes "f⋅C ≠ ⊥"
  shows "f⋅(demand f) ≠ ⊥"
  apply (simp add: assms demand_def)
  apply (rule finite_resources_suffice[OF assms])
  apply (rule LeastI)
  apply assumption
  done

lemma not_bot_demand:
  "f⋅r ≠ ⊥ ⟷ demand f ≠ C ∧ demand f ⊑ r"
proof(intro iffI)
  assume "f⋅r ≠ ⊥"
  thus "demand f ≠ C ∧ demand f ⊑ r"
    apply (cases r rule:C_cases)
    apply (auto intro: Least_le simp add: demand_def dest: infinite_resources_suffice)
    done
next
  assume *: "demand f ≠ C  ∧ demand f ⊑ r"
  then have "f⋅C ≠ ⊥" by (auto intro: Least_le simp add: demand_def dest: infinite_resources_suffice)
  hence "f⋅(demand f) ≠ ⊥" by (rule demand_suffices)
  moreover from * have "demand f ⊑ r"..
  ultimately
  show "f⋅r ≠ ⊥" by (rule more_resources_suffice)
qed

lemma infinity_bot_demand:
  "f⋅C = ⊥ ⟷ demand f = C"
  by (metis below_Cinf not_bot_demand)

lemma demand_suffices':
  assumes "demand f = Cn"
  shows "f⋅(demand f) ≠ ⊥"
  by (metis C_eq_Cinf assms demand_suffices infinity_bot_demand)

lemma demand_Suc_Least:
  assumes [simp]: "f⋅⊥ = ⊥"
  assumes "demand f ≠ C"
  shows "demand f = C(Suc (LEAST n. f⋅CSuc n ≠ ⊥))"
proof-
  from assms
  have "demand f = C(LEAST n. f⋅Cn ≠ ⊥)" by (auto simp add: demand_def)
  also
  then obtain n where "f⋅Cn ≠ ⊥" by (metis  demand_suffices')
  hence "(LEAST n. f⋅Cn ≠ ⊥) = Suc (LEAST n. f⋅CSuc n ≠ ⊥)"
    apply (rule Least_Suc) by simp
  finally show ?thesis.
qed

lemma demand_C_case[simp]: "demand (C_case⋅f) = C ⋅ (demand f)"
proof(cases "demand (C_case⋅f) = C")
  case True
  then have "C_case⋅f⋅C = ⊥"
    by (metis infinity_bot_demand)
  with True
  show ?thesis apply auto by (metis infinity_bot_demand)
next
  case False
  hence "demand (C_case⋅f) = CSuc (LEAST n. (C_case⋅f)⋅CSuc n ≠ ⊥)"
    by (rule demand_Suc_Least[OF C.case_rews(1)])
  also have "… = C⋅CLEAST n. f⋅Cn ≠ ⊥" by simp
  also have "… = C⋅(demand  f)"
    using False unfolding demand_def by auto
  finally show ?thesis.
qed

lemma demand_contravariant:
  assumes "f ⊑ g"
  shows "demand g ⊑ demand f"
proof(cases "demand f" rule:C_cases)
  fix n
  assume "demand f = Cn"
  hence "f⋅(demand f) ≠ ⊥" by (metis demand_suffices')
  also note monofun_cfun_fun[OF assms]
  finally have "g⋅(demand f) ≠ ⊥" by this (intro cont2cont)
  thus "demand g ⊑ demand f" unfolding not_bot_demand by auto
qed auto

subsubsection {* Restricting functions with domain C *}

fixrec C_restr :: "C → (C → 'a::pcpo) → (C → 'a)"
  where "C_restr⋅r⋅f⋅r' = (f⋅(r ⊓ r'))" 

abbreviation C_restr_syn :: "(C → 'a::pcpo) ⇒ C ⇒ (C → 'a)" ( "_|_" [111,110] 110)
  where "f|r ≡ C_restr⋅r⋅f"

lemma [simp]: "⊥|r = ⊥" by fixrec_simp
lemma [simp]: "f⋅⊥ = ⊥ ⟹ f| = ⊥"  by fixrec_simp

lemma C_restr_C_restr[simp]: "(v|r')|r = v|(r' ⊓ r)"
  by (rule cfun_eqI) simp

lemma C_restr_eqD:
  assumes "f|r = g|r"
  assumes "r' ⊑ r"
  shows "f⋅r' = g⋅r'"
by (metis C_restr.simps assms below_refl is_meetI)

lemma C_restr_eq_lower:
  assumes "f|r = g|r"
  assumes "r' ⊑ r"
  shows "f|r' = g|r'"
by (metis C_restr_C_restr assms below_refl is_meetI)

lemma C_restr_below[intro, simp]:
  "x|r ⊑ x"
  apply (rule cfun_belowI)
  apply simp
  by (metis below_refl meet_below2 monofun_cfun_arg)
  

lemma C_restr_below_cong:
  "(⋀ r'. r' ⊑ r ⟹ f ⋅ r' ⊑ g ⋅ r') ⟹ f|r ⊑ g|r"
  apply (rule cfun_belowI)
  apply simp
  by (metis below_refl meet_below1)

lemma C_restr_cong:
  "(⋀ r'. r' ⊑ r ⟹ f ⋅ r' = g ⋅ r') ⟹ f|r = g|r"
  apply (intro below_antisym C_restr_below_cong )
  by (metis below_refl)+

lemma C_restr_C_cong:
  "(⋀ r'. r' ⊑ r ⟹ f ⋅ (C⋅r') = g ⋅ (C⋅r')) ⟹ f⋅⊥=g⋅⊥ ⟹ f|C⋅r = g|C⋅r"
  apply (rule C_restr_cong)
  by (case_tac r', auto)

lemma C_restr_C_case[simp]:
  "(C_case⋅f)|C⋅r = C_case⋅(f|r)"
  apply (rule cfun_eqI)
  apply simp
  apply (case_tac x)
  apply simp
  apply simp
  done

lemma C_restr_bot_demand:
  assumes "C⋅r ⊑ demand f"
  shows "f|r = ⊥"
proof(rule cfun_eqI)
  fix r'
  have "f⋅(r ⊓ r') = ⊥"
  proof(rule classical)
    have "r ⊑ C ⋅ r" by (rule below_C)
    also
    note assms
    also
    assume *: "f⋅(r ⊓ r') ≠ ⊥"
    hence "demand f ⊑ (r ⊓ r')" unfolding not_bot_demand by auto
    hence "demand f ⊑ r"  by (metis below_refl meet_below1 below_trans)
    finally (below_antisym) have "r = demand f" by this (intro cont2cont)
    with assms
    have "demand f = C" by (cases "demand f" rule:C_cases) (auto simp add: iterate_Suc[symmetric] simp del: iterate_Suc)
    thus "f⋅(r ⊓ r') = ⊥" by (metis not_bot_demand)
  qed
  thus "(f|r)⋅r' = ⊥⋅r'" by simp
qed

subsubsection {* Restricting maps of C-ranged functions *}

definition env_C_restr :: "C → ('var::type ⇒ (C → 'a::pcpo)) → ('var ⇒ (C → 'a))" where
  "env_C_restr = (Λ r f.  cfun_comp⋅(C_restr⋅r)⋅f)"

abbreviation env_C_restr_syn :: "('var::type ⇒ (C → 'a::pcpo)) ⇒ C ⇒  ('var ⇒ (C → 'a))" ( "_|_" [111,110] 110)
  where "f|r ≡ env_C_restr⋅r⋅f"


lemma env_C_restr_upd[simp]: "(ρ(x := v))|r = (ρ|r)(x := v|r)"
  unfolding env_C_restr_def by simp

lemma env_C_restr_lookup[simp]: "(ρ|r) v = ρ v|r"
  unfolding env_C_restr_def by simp

lemma env_C_restr_bot[simp]: " ⊥|r = ⊥"
  unfolding env_C_restr_def by auto

lemma env_C_restr_restr_below[intro]: "ρ|r ⊑ ρ"
  by (auto intro: fun_belowI)

lemma env_C_restr_env_C_restr[simp]: "(v|r')|r = v|(r' ⊓ r)"
  unfolding env_C_restr_def by auto

lemma env_C_restr_cong:
  "(⋀ x r'. r' ⊑ r ⟹ f x ⋅ r' = g x ⋅ r') ⟹ f|r = g|r"
  unfolding env_C_restr_def
  by (rule ext) (auto intro: C_restr_cong)

end