Theory C-restr

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 fC   then C⇗(LEAST n. fC⇗n )else C)"

text ‹
Because of continuity, a non-bottom value can always be obtained with finite resources.
›

lemma finite_resources_suffice:
  assumes "fC  "
  obtains n where "fC⇗n "
proof-
  {
  assume "n. f(C⇗n) = "
  hence "fC  "
    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 "fr  " and "r  r'"
  shows "fr'  "
  using assms(1) monofun_cfun_arg[OF assms(2), where  f = f]
  by auto

lemma infinite_resources_suffice:
  shows "fr    fC  "
  by (erule more_resources_suffice[OF _ below_Cinf])

lemma demand_suffices:
  assumes "fC  "
  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:
  "fr    demand f  C  demand f  r"
proof(intro iffI)
  assume "fr  "
  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 "fC  " 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 "fr  " by (rule more_resources_suffice)
qed

lemma infinity_bot_demand:
  "fC =   demand f = C"
  by (metis below_Cinf not_bot_demand)

lemma demand_suffices':
  assumes "demand f = C⇗n⇖"
  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. fC⇗Suc n ))⇖"
proof-
  from assms
  have "demand f = C⇗(LEAST n. fC⇗n )⇖" by (auto simp add: demand_def)
  also
  then obtain n where "fC⇗n " by (metis  demand_suffices')
  hence "(LEAST n. fC⇗n ) = Suc (LEAST n. fC⇗Suc n )"
    apply (rule Least_Suc) by simp
  finally show ?thesis.
qed

lemma demand_C_case[simp]: "demand (C_casef) = C  (demand f)"
proof(cases "demand (C_casef) = C")
  case True
  then have "C_casefC = "
    by (metis infinity_bot_demand)
  with True
  show ?thesis apply auto by (metis infinity_bot_demand)
next
  case False
  hence "demand (C_casef) = C⇗Suc (LEAST n. (C_casef)C⇗Suc n )⇖"
    by (rule demand_Suc_Least[OF C.case_rews(1)])
  also have " = CC⇗LEAST n. fC⇗n ⇖" 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 = C⇗n⇖"
  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_restrrfr' = (f(r  r'))" 

abbreviation C_restr_syn :: "(C  'a::pcpo)  C  (C  'a)" ( ‹_|⇘_ [111,110] 110)
  where "f|⇘r C_restrrf"

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 "fr' = gr'"
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  (Cr') = g  (Cr'))  f=g  f|⇘Cr= g|⇘Cr⇙"
  apply (rule C_restr_cong)
  by (case_tac r', auto)

lemma C_restr_C_case[simp]:
  "(C_casef)|⇘Cr= 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 "Cr  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_restrr)f)"

abbreviation env_C_restr_syn :: "('var::type  (C  'a::pcpo))  C   ('var  (C  'a))" ( ‹_|_ [111,110] 110)
  where "f|r env_C_restrrf"


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