Theory Xor

theory Xor imports 
  "HOL-Algebra.Complete_Lattice" 
  "CryptHOL.Misc_CryptHOL" 
begin

unbundle no lattice_syntax

context bounded_lattice begin

lemma top_join [simp]: "x ∈ carrier L ⟹ ⊤ ⊔ x = ⊤"
  using eq_is_equal top_join by auto

lemma join_top [simp]: "x ∈ carrier L ⟹ x ⊔ ⊤ = ⊤"
  using le_iff_meet by blast

lemma bot_join [simp]: "x ∈ carrier L ⟹ ⊥ ⊔ x = x"
  using le_iff_meet by blast

lemma join_bot [simp]: "x ∈ carrier L ⟹ x ⊔ ⊥ = x"
  by (metis bot_join join_comm)

lemma bot_meet [simp]: "x ∈ carrier L ⟹ ⊥ ⊓ x = ⊥"
  using bottom_meet by auto

lemma meet_bot [simp]: "x ∈ carrier L ⟹ x ⊓ ⊥ = ⊥"
  by (metis bot_meet meet_comm)

lemma top_meet [simp]: "x ∈ carrier L ⟹ ⊤ ⊓ x = x"
  by (metis le_iff_join meet_comm top_closed top_higher)

lemma meet_top [simp]: "x ∈ carrier L ⟹ x ⊓ ⊤ = x"
  by (metis meet_comm top_meet)

lemma join_idem [simp]: "x ∈ carrier L ⟹ x ⊔ x = x"
  using le_iff_meet by blast

lemma meet_idem [simp]: "x ∈ carrier L ⟹ x ⊓ x = x"
  using le_iff_join le_refl by presburger

lemma meet_leftcomm: "x ⊓ (y ⊓ z) = y ⊓ (x ⊓ z)" if "x ∈ carrier L" "y ∈ carrier L" "z ∈ carrier L"
  by (metis meet_assoc meet_comm that)

lemma join_leftcomm: "x ⊔ (y ⊔ z) = y ⊔ (x ⊔ z)" if "x ∈ carrier L" "y ∈ carrier L" "z ∈ carrier L"
  by (metis join_assoc join_comm that)

lemmas meet_ac = meet_assoc meet_comm meet_leftcomm
lemmas join_ac = join_assoc join_comm join_leftcomm

end

record 'a boolean_algebra = "'a gorder" +
  compl :: "'a ⇒ 'a" (‹-ı› 1000)

definition xor :: "('a, 'b) boolean_algebra_scheme ⇒ 'a ⇒ 'a ⇒ 'a" (infixr ‹⊕ı› 100) where
  "x ⊕ y = (x ⊔ y) ⊓ (- (x ⊓ y))" for L (structure)

locale boolean_algebra = bounded_lattice L
  for L (structure) +
  assumes compl_closed [intro, simp]: "x ∈ carrier L ⟹ - x ∈ carrier L"
    and meet_compl_bot [simp]: "x ∈ carrier L ⟹ - x ⊓ x = ⊥"
    and join_compl_top [simp]: "x ∈ carrier L ⟹ - x ⊔ x = ⊤"
    and join_meet_distrib1: "⟦ x ∈ carrier L; y ∈ carrier L; z ∈ carrier L ⟧ ⟹ x ⊔ (y ⊓ z) = (x ⊔ y) ⊓ (x ⊔ z)"
begin

lemma join_meet_distrib2: "(y ⊓ z) ⊔ x = (y ⊔ x) ⊓ (z ⊔ x)"
  if "x ∈ carrier L" "y ∈ carrier L" "z ∈ carrier L"
  by (simp add: join_comm join_meet_distrib1 that)

lemma meet_join_distrib1: "x ⊓ (y ⊔ z) = (x ⊓ y) ⊔ (x ⊓ z)"
  if [simp]: "x ∈ carrier L" "y ∈ carrier L" "z ∈ carrier L"
proof -
  have "x ⊓ (y ⊔ z) = (x ⊓ (x ⊔ z)) ⊓ (y ⊔ z)"
    using join_left le_iff_join by auto
  also have "… = x ⊓ (z ⊔ (x ⊓ y))"
    by (simp add: join_comm join_meet_distrib1 meet_assoc)
  also have "… = ((x ⊓ y) ⊔ x) ⊓ ((x ⊓ y) ⊔ z)"
    by (metis join_comm le_iff_meet meet_closed meet_left that(1) that(2))
  also have "… = (x ⊓ y) ⊔ (x ⊓ z)"
    by (simp add: join_meet_distrib1)
  finally show ?thesis .
qed

lemma meet_join_distrib2: "(y ⊔ z) ⊓ x = (y ⊓ x) ⊔ (z ⊓ x)"
  if [simp]: "x ∈ carrier L" "y ∈ carrier L" "z ∈ carrier L"
  by (simp add: meet_comm meet_join_distrib1)

lemmas join_meet_distrib = join_meet_distrib1 join_meet_distrib2

lemmas meet_join_distrib = meet_join_distrib1 meet_join_distrib2

lemmas distrib = join_meet_distrib meet_join_distrib

lemma meet_compl2_bot [simp]: "x ∈ carrier L ⟹ x ⊓ - x = ⊥"
  by (metis meet_comm meet_compl_bot)

lemma join_compl2_top [simp]: "x ∈ carrier L ⟹ x ⊔ - x = ⊤"
  by (metis join_comm join_compl_top)

lemma compl_unique:
  assumes "x ⊓ y = ⊥"
    and "x ⊔ y = ⊤"
    and [simp]: "x ∈ carrier L" "y ∈ carrier L"
  shows "- x = y"
proof -
  have "(x ⊓ - x) ⊔ (- x ⊓ y) = (x ⊓ y) ⊔ (- x ⊓ y)"
    using inf_compl_bot assms(1) by simp
  then have "(- x ⊓ x) ⊔ (- x ⊓ y) = (y ⊓ x) ⊔ (y ⊓ - x)"
    by (simp add: meet_comm)
  then have "- x ⊓ (x ⊔ y) = y ⊓ (x ⊔ - x)"
    using assms(3) assms(4) compl_closed meet_join_distrib1 by presburger
  then have "- x ⊓ ⊤ = y ⊓ ⊤"
    by (simp add: assms(2))
  then show "- x = y"
    using le_iff_join top_higher by auto
qed

lemma double_compl [simp]: "- (- x) = x" if [simp]: "x ∈ carrier L"
  by(rule compl_unique)(simp_all)

lemma compl_eq_compl_iff [simp]: "- x = - y ⟷ x = y" if "x ∈ carrier L" "y ∈ carrier L"
  by (metis double_compl that that)

lemma compl_bot_eq [simp]: "- ⊥ = ⊤"
  using le_iff_join le_iff_meet local.compl_unique top_higher by auto

lemma compl_top_eq [simp]: "- ⊤ = ⊥"
  by (metis bottom_closed compl_bot_eq double_compl)

lemma compl_inf [simp]: "- (x ⊓ y) = - x ⊔ - y" if [simp]: "x ∈ carrier L" "y ∈ carrier L"
proof (rule compl_unique)
  have "(x ⊓ y) ⊓ (- x ⊔ - y) = (y ⊓ (x ⊓ - x)) ⊔ (x ⊓ (y ⊓ - y))"
    by (smt compl_closed meet_assoc meet_closed meet_comm meet_join_distrib1 that)
  then show "(x ⊓ y) ⊓ (- x ⊔ - y) = ⊥"
    by (metis bottom_closed bottom_lower le_iff_join le_iff_meet meet_comm meet_compl2_bot that)
next
  have "(x ⊓ y) ⊔ (- x ⊔ - y) = (- y ⊔ (x ⊔ - x)) ⊓ (- x ⊔ (y ⊔ - y))"
    by (smt compl_closed join_meet_distrib2 join_assoc join_comm local.boolean_algebra_axioms that join_closed)
  then show "(x ⊓ y) ⊔ (- x ⊔ - y) = ⊤"
    by (metis compl_closed join_compl2_top join_right le_iff_join le_iff_meet that top_closed)
qed simp_all

lemma compl_sup [simp]: "- (x ⊔ y) = - x ⊓ - y" if "x ∈ carrier L" "y ∈ carrier L"
  by (metis compl_closed compl_inf double_compl meet_closed that)

lemma compl_mono:
  assumes "x ⊑ y"
    and "x ∈ carrier L" "y ∈ carrier L"
  shows "- y ⊑ - x"
  by (metis assms(1) assms(2) assms(3) compl_closed join_comm le_iff_join le_iff_meet compl_inf)

lemma compl_le_compl_iff [simp]: "- x ⊑ - y ⟷ y ⊑ x" if "x ∈ carrier L" "y ∈ carrier L"
  using that by (auto dest: compl_mono)

lemma compl_le_swap1:
  assumes "y ⊑ - x" "x ∈ carrier L" "y ∈ carrier L"
  shows "x ⊑ - y"
  by (metis assms compl_closed compl_le_compl_iff double_compl)

lemma compl_le_swap2:
  assumes "- y ⊑ x" "x ∈ carrier L" "y ∈ carrier L"
  shows "- x ⊑ y"
  by (metis assms compl_closed compl_le_compl_iff double_compl)

lemma join_compl_top_left1 [simp]: "- x ⊔ (x ⊔ y) = ⊤" if [simp]: "x ∈ carrier L" "y ∈ carrier L"
  by (simp add: join_assoc[symmetric])

lemma join_compl_top_left2 [simp]: "x ⊔ (- x ⊔ y) = ⊤" if [simp]: "x ∈ carrier L" "y ∈ carrier L"
  using join_compl_top_left1[of "- x" y] by simp

lemma meet_compl_bot_left1 [simp]: "- x ⊓ (x ⊓ y) = ⊥" if [simp]: "x ∈ carrier L" "y ∈ carrier L"
  by (simp add: meet_assoc[symmetric])

lemma meet_compl_bot_left2 [simp]: "x ⊓ (- x ⊓ y) = ⊥" if [simp]: "x ∈ carrier L" "y ∈ carrier L"
  using meet_compl_bot_left1[of "- x" y] by simp

lemma meet_compl_bot_right [simp]: "x ⊓ (y ⊓ - x) = ⊥" if [simp]: "x ∈ carrier L" "y ∈ carrier L"
  by (metis meet_compl_bot_left2 meet_comm that)

lemma xor_closed [intro, simp]: "⟦ x ∈ carrier L; y ∈ carrier L ⟧ ⟹ x ⊕ y ∈ carrier L"
  by(simp add: xor_def)

lemma xor_comm: "⟦ x ∈ carrier L; y ∈ carrier L ⟧ ⟹ x ⊕ y = y ⊕ x"
  by(simp add: xor_def meet_join_distrib join_comm)

lemma xor_assoc: "(x ⊕ y) ⊕ z = x ⊕ (y ⊕ z)"
  if [simp]: "x ∈ carrier L" "y ∈ carrier L" "z ∈ carrier L"
  by(simp add: xor_def)(simp add: meet_join_distrib meet_ac join_ac)

lemma xor_left_comm: "x ⊕ (y ⊕ z) = y ⊕ (x ⊕ z)" if "x ∈ carrier L" "y ∈ carrier L" "z ∈ carrier L"
  using that xor_assoc xor_comm by auto

lemma [simp]:
  assumes "x ∈ carrier L"
  shows xor_bot: "x ⊕ ⊥ = x"
  and bot_xor: "⊥ ⊕ x = x"
  and xor_top: "x ⊕ ⊤ = - x"
  and top_xor: "⊤ ⊕ x = - x"
  by(simp_all add: xor_def assms)

lemma xor_inverse [simp]: "x ⊕ x = ⊥" if "x ∈ carrier L"
  by(simp add: xor_def that)

lemma xor_left_inverse [simp]: "x ⊕ x ⊕ y = y" if "x ∈ carrier L" "y ∈ carrier L"
  using that xor_assoc by fastforce

lemmas xor_ac = xor_assoc xor_comm xor_left_comm

lemma inj_on_xor: "inj_on ((⊕) x) (carrier L)" if "x ∈ carrier L"
  by(rule inj_onI)(metis that xor_left_inverse)

lemma surj_xor: "(⊕) x ` carrier L = carrier L" if [simp]: "x ∈ carrier L"
proof(rule Set.set_eqI, rule iffI)
  fix y
  assume [simp]: "y ∈ carrier L"
  have "x ⊕ y ∈ carrier L" by(simp)
  moreover have "y = x ⊕ (x ⊕ y)" by simp
  ultimately show "y ∈ (⊕) x ` carrier L" by(rule rev_image_eqI)
qed auto

lemma one_time_pad: "map_spmf ((⊕) x) (spmf_of_set (carrier L)) = spmf_of_set (carrier L)"
  if "x ∈ carrier L"
  apply(subst map_spmf_of_set_inj_on)
   apply(rule inj_on_xor[OF that])
  by(simp add: surj_xor that)

end

end