Theory HOLCF-Join

theory "HOLCF-Join"
imports HOLCF
begin

subsubsection ‹Binary Joins and compatibility›

context cpo
begin
definition join :: "'a => 'a => 'a" (infixl  80) where
  "x  y = (if  z. {x, y} <<| z then lub {x, y} else x)"

definition compatible :: "'a  'a  bool"
  where "compatible x y = ( z. {x, y} <<| z)"

lemma compatibleI:
  assumes "x  z"
  assumes "y  z"
  assumes " a.  x  a ; y  a   z  a"
  shows "compatible x y"
proof-
  from assms
  have "{x,y} <<| z"
    by (auto intro: is_lubI)
  thus ?thesis unfolding compatible_def by (metis)
qed

lemma is_joinI:
  assumes "x  z"
  assumes "y  z"
  assumes " a.  x  a ; y  a   z  a"
  shows "x  y = z"
proof-
  from assms
  have "{x,y} <<| z"
    by (auto intro: is_lubI)
  thus ?thesis unfolding join_def by (metis lub_eqI)
qed

lemma is_join_and_compatible:
  assumes "x  z"
  assumes "y  z"
  assumes " a.  x  a ; y  a   z  a"
  shows "compatible x y  x  y = z"
by (metis compatibleI is_joinI assms)

lemma compatible_sym: "compatible x y  compatible y x"
  unfolding compatible_def by (metis insert_commute)

lemma compatible_sym_iff: "compatible x y  compatible y x"
  unfolding compatible_def by (metis insert_commute)

lemma join_above1: "compatible x y  x  x  y"
  unfolding compatible_def join_def
  apply auto
  by (metis is_lubD1 is_ub_insert lub_eqI)  

lemma join_above2: "compatible x y  y  x  y"
  unfolding compatible_def join_def
  apply auto
  by (metis is_lubD1 is_ub_insert lub_eqI)  

lemma larger_is_join1: "y  x  x  y = x"
  unfolding join_def
  by (metis doubleton_eq_iff lub_bin)

lemma larger_is_join2: "x  y  x  y = y"
  unfolding join_def
  by (metis is_lub_bin lub_bin)

lemma join_self[simp]: "x  x = x"
  unfolding join_def  by auto
end

lemma join_commute:  "compatible x y  x  y = y  x"
  unfolding compatible_def unfolding join_def by (metis insert_commute)

lemma lub_is_join:
  "{x, y} <<| z  x  y = z"
unfolding join_def by (metis lub_eqI)

lemma compatible_refl[simp]: "compatible x x"
  by (rule compatibleI[OF below_refl below_refl])

lemma join_mono:
  assumes "compatible a b"
  and "compatible c d"
  and "a  c"
  and "b  d"
  shows "a  b  c  d"
proof-
  from assms obtain x y where "{a, b} <<| x" "{c, d} <<| y" unfolding compatible_def by auto
  with assms have "a  y" "b  y" by (metis below.r_trans is_lubD1 is_ub_insert)+
  with {a, b} <<| x have "x  y" by (metis is_lub_below_iff is_lub_singleton is_ub_insert)
  moreover
  from {a, b} <<| x {c, d} <<| y have "a  b = x" "c  d = y" by (metis lub_is_join)+
  ultimately
  show ?thesis by simp
qed

lemma
  assumes "compatible x y"
  shows join_above1: "x  x  y" and join_above2: "y  x  y"
proof-
  from assms obtain z where "{x,y} <<| z" unfolding compatible_def by auto
  hence  "x  y = z" and "x  z" and "y  z" apply (auto intro: lub_is_join) by (metis is_lubD1 is_ub_insert)+
  thus "x  x  y" and "y  x  y" by simp_all
qed

lemma
  assumes "compatible x y"
  shows compatible_above1: "compatible x (x  y)" and compatible_above2: "compatible y (x  y)"
proof-
  from assms obtain z where "{x,y} <<| z" unfolding compatible_def by auto
  hence  "x  y = z" and "x  z" and "y  z" apply (auto intro: lub_is_join) by (metis is_lubD1 is_ub_insert)+
  thus  "compatible x (x  y)" and  "compatible y (x  y)" by (metis below.r_refl compatibleI)+
qed

lemma join_below:
  assumes "compatible x y"
  and "x  a" and "y  a"
  shows "x  y  a"
proof-
  from assms obtain z where z: "{x,y} <<| z" unfolding compatible_def by auto
  with assms have "z  a" by (metis is_lub_below_iff is_ub_empty is_ub_insert)
  moreover
  from z have "x  y = z" by (rule lub_is_join) 
  ultimately show ?thesis by simp
qed

lemma join_below_iff:
  assumes "compatible x y"
  shows "x  y  a  (x  a  y  a)"
  by (metis assms below_trans cpo_class.join_above1 cpo_class.join_above2 join_below)

lemma join_assoc:
  assumes "compatible x y"
  assumes "compatible x (y  z)"
  assumes "compatible y z"
  shows "(x  y)  z = x  (y  z)"
  apply (rule is_joinI)
  apply (rule join_mono[OF assms(1) assms(2) below_refl join_above1[OF assms(3)]])
  apply (rule below_trans[OF join_above2[OF assms(3)] join_above2[OF assms(2)]])
  apply (rule join_below[OF assms(2)])
  apply (erule rev_below_trans)
  apply (rule join_above1[OF assms(1)])
  apply (rule join_below[OF assms(3)])
  apply (erule rev_below_trans)
  apply (rule join_above2[OF assms(1)])
  apply assumption
  done

lemma join_idem[simp]: "compatible x y  x  (x  y) = x  y"
  apply (subst join_assoc[symmetric])
  apply (rule compatible_refl)
  apply (erule compatible_above1)
  apply assumption
  apply (subst join_self)
  apply rule
  done

lemma join_bottom[simp]: "x   = x" "  x = x"
  by (auto intro: is_joinI)

lemma compatible_adm2:
  shows "adm (λ y. compatible x y)"
proof(rule admI)
  fix Y
  assume c: "chain Y" and "i.  compatible x (Y i)"
  hence a: " i. compatible x (Y i)" by auto
  show "compatible x ( i. Y i)"
  proof(rule compatibleI)
    have c2: "chain (λi. x  Y i)"
      apply (rule chainI)
      apply (rule join_mono[OF a a below_refl chainE[OF chain Y]])
      done
    show "x  ( i. x  Y i)"
      by (auto intro: admD[OF _ c2] join_above1[OF a])
    show "( i. Y i)  ( i. x  Y i)"
      by (auto intro: admD[OF _ c] below_lub[OF c2 join_above2[OF a]])
    fix a
    assume "x  a" and "( i. Y i)  a"
    show "( i. x  Y i)  a"
      apply (rule lub_below[OF c2])
      apply (rule join_below[OF a x  a])
      apply (rule below_trans[OF is_ub_thelub[OF c] ( i. Y i)  a])
      done
  qed
qed

lemma compatible_adm1: "adm (λ x. compatible x y)"
  by (subst compatible_sym_iff, rule compatible_adm2)

lemma join_cont1:
  assumes "chain Y"
  assumes compat: " i. compatible (Y i) y"
  shows "(i. Y i)  y = ( i. Y i  y)"
proof-
  have c: "chain (λi. Y i  y)"
    apply (rule chainI)
    apply (rule join_mono[OF compat compat chainE[OF chain Y] below_refl])
    done

  show ?thesis
    apply (rule is_joinI)
    apply (rule lub_mono[OF chain Y c join_above1[OF compat]])
    apply (rule below_lub[OF c join_above2[OF compat]])
    apply (rule lub_below[OF c])
    apply (rule join_below[OF compat])
    apply (metis lub_below_iff[OF chain Y])
    apply assumption
    done
qed

lemma join_cont2:
  assumes "chain Y"
  assumes compat: " i. compatible x (Y i)"
  shows "x  (i. Y i) = ( i. x  Y i)"
proof-
  have c: "chain (λi. x  Y i)"
    apply (rule chainI)
    apply (rule join_mono[OF compat compat below_refl chainE[OF chain Y]])
    done

  show ?thesis
    apply (rule is_joinI)
    apply (rule below_lub[OF c join_above1[OF compat]])
    apply (rule lub_mono[OF chain Y c join_above2[OF compat]])
    apply (rule lub_below[OF c])
    apply (rule join_below[OF compat])
    apply assumption
    apply (metis lub_below_iff[OF chain Y])
    done
qed

lemma join_cont12:
  assumes "chain Y" and "chain Z"
  assumes compat: " i j. compatible (Y i) (Z j)"
  shows "(i. Y i)  (i. Z i) = ( i. Y i   Z i)"
proof-
  have "(i. Y i)  (i. Z i) = (i. Y i  (j. Z j))"
    by (rule join_cont1[OF chain Y admD[OF compatible_adm2 chain Z compat]])
  also have "... = (i j. Y i  Z j)"
    by (subst join_cont2[OF chain Z compat], rule)
  also have "... = (i. Y i  Z i)"
    apply (rule diag_lub)
    apply (rule chainI, rule join_mono[OF compat compat chainE[OF chain Y] below_refl])
    apply (rule chainI, rule join_mono[OF compat compat below_refl chainE[OF chain Z]])
    done
  finally show ?thesis.
qed

context pcpo
begin
  lemma bot_compatible[simp]:
    "compatible x " "compatible  x"
    unfolding compatible_def by (metis insert_commute is_lub_bin minimal)+
end

end