Theory MLSSmf_HF_Extras

theory MLSSmf_HF_Extras
  imports HereditarilyFinite.HF
begin

lemma union_hunion: "finite a  finite b  HF (a  b) = HF a  HF b"
  by (standard, standard, standard) auto

lemma inter_hinter: "finite a  finite b  HF (a  b) = HF a  HF b"
  by (standard, standard, standard) auto

lemma hdisjoint_iff[iff]: "A  B = 0  (x. x  A  x  B)"
  apply standard
   apply (metis hinter_iff hmem_hempty)
  apply blast
  done

lemma hcard_0E: "hcard s = 0  s = 0"
proof (rule ccontr)
  assume "s  0" "hcard s = 0"
  then have "hcard s > 0"
    using hcard_hinsert_if hcard_hdiff1_less by fastforce
  with hcard s = 0 show False by simp
qed

lemma hcard_1E: "hcard s = 1  c. s = 0  c"
proof (rule ccontr)
  assume "hcard s = 1" "c. s = 0  c"
  then obtain s' c where "s = s'  c" "s'  0" "c  s'"
    by (metis hcard_0 hf_cases zero_neq_one) 
  then have "hcard s = Suc (hcard s')"
    using hcard_hinsert_if by auto
  moreover
  from s'  0 have "hcard s' > 0"
    using hcard_0E by blast
  ultimately
  have "hcard s > 1" by simp
  with hcard s = 1 show False by presburger
qed

lemma singleton_nonempty_subset:
  assumes "s = HF {c}"
      and "t  s"
      and "t  0"
    shows "t = HF {c}"
proof -
  from t  s s = HF {c} have "c' = c" if "c'  t" for c'
    using that by force
  with t  0 show ?thesis by force
qed

lemma hsubset_hunion:
  "s  t  s  u  s  t  u"
  by (cases "s  t") auto

lemma mem_hsubset_HUnion:
  "finite S  s  S  s  HF S"
  by auto

lemma hinter_hdiff_hempty: "s  B  s  (A - B) = 0"
  by blast

lemma Hunion_nonempty: "finite S  HF S = HF {s  S. s  0}"
  by force

lemma hcard_Hunion_singletons:
  assumes "finite s"
      and f_s_singletons: "x  s. hcard (f x) = 1"
    shows "hcard (HF (f ` s))  card s"
  using assms
proof (induction s)
  case empty
  then show ?case using Zero_hf_def by auto
next
  case (insert x F)
  then have IH': "hcard (HF (f ` F))  card F" by blast
  from xinsert x F. hcard (f x) = 1 obtain a where "f x = HF {a}"
    using hcard_1E by fastforce
  then have Hunion_insert_a: "HF (f ` insert x F) = HF (insert (HF {a}) (f ` F))"
    by simp
  have "HF (insert (HF {a}) (f ` F)) = (HF (f ` F))  (HF {a})"
    by (simp add: hinsert_def insert.hyps(1))
  also have "... = HF {a}  (HF (f ` F))" by blast
  also have "... = (HF (f ` F))  a" by force
  finally have "HF (insert (HF {a}) (f ` F)) = HF (f ` F)  a" .
  with Hunion_insert_a have insert_hinsert:
    "HF (f ` insert x F) = HF (f ` F)  a"
    by argo
  
  have Suc_hcard_le: "hcard (HF (f ` F)  a)  Suc (hcard (HF (f ` F)))"
    apply (cases "a  HF (f ` F)")
    by (simp add: hcard_hinsert_if)+

  from x  F have Suc_card: "card (insert x F) = Suc (card F)"
    by (simp add: insert.hyps(1))

  from insert_hinsert Suc_hcard_le Suc_card IH'
  show ?case by presburger
qed

lemma hcard_Hunion_distinct_singletons:
  assumes "finite s"
      and f_distinct: "x  s. y  s. x  y  f x  f y"
      and f_s_singletons: "x  s. hcard (f x) = 1"
    shows "hcard (HF (f ` s)) = card s"
  using assms
proof (induction s)
  case empty
  then show ?case using Zero_hf_def by auto
next
  case (insert x F)
  then have IH': "hcard (HF (f ` F)) = card F" by blast
  from xinsert x F. hcard (f x) = 1 obtain a where "f x = HF {a}"
    using hcard_1E by fastforce
  then have Hunion_insert_a: "HF (f ` insert x F) = HF (insert (HF {a}) (f ` F))"
    by simp
  have "HF (insert (HF {a}) (f ` F)) = (HF (f ` F))  (HF {a})"
    by (simp add: hinsert_def insert.hyps(1))
  also have "... = HF {a}  (HF (f ` F))" by blast
  also have "... = (HF (f ` F))  a" by force
  finally have "HF (insert (HF {a}) (f ` F)) = HF (f ` F)  a" .
  with Hunion_insert_a have insert_hinsert:
    "HF (f ` insert x F) = HF (f ` F)  a"
    by argo
  
  have "b  a" if "b  HF (f ` F)" for b
  proof -
    from that obtain y where "y  F" "b  f y" by auto
    with insert.prems(2) have "f y = HF {b}"
      using hcard_1E by force
    from y  F x  F insert.prems(1) have "f x  f y" by auto
    with f x = HF {a} f y = HF {b}
    show "b  a" by auto
  qed
  then have Suc_hcard: "hcard (HF (f ` F)  a) = Suc (hcard (HF (f ` F)))"
    by (metis hcard_hinsert_if)

  from x  F have Suc_card: "card (insert x F) = Suc (card F)"
    by (simp add: insert.hyps(1))

  from insert_hinsert Suc_hcard Suc_card IH'
  show ?case by presburger
qed

lemma singleton_mem_eq:
  assumes "HF {a} = HF {b}"
    shows "a = b"
  using assms
  by (metis HF_hfset hfset_0 hfset_hinsert singleton_insert_inj_eq') 

lemma hinter_HUnion_if_image_pairwise_disjoint:
  assumes "finite U"
      and "S  U"
      and "T  U"
      and image_pairwise_disjoint: "x  U. y  U. x  y  f x  f y = 0"
    shows "HF (f ` S)  HF (f ` T) = HF (f ` (S  T))"
proof (standard; standard)
  fix c assume "c  HF (f ` S)  HF (f ` T)"
  from assms have "finite S" "finite T"
    using finite_subset by blast+
  from c  HF (f ` S)  HF (f ` T)
  have "c  HF (f ` S)" "c  HF (f ` T)" by blast+
  then obtain x y where "x  S" "c  f x" "y  T" "c  f y"
    using finite S finite T by fastforce+
  with image_pairwise_disjoint have "x = y"
    using S  U T  U by blast
  with x  S y  T have "x  S  T" by blast
  with c  f x show "c  HF (f ` (S  T))"
    using finite S by auto
next
  fix c assume "c  HF (f ` (S  T))"
  then obtain x where "x  S  T" "c  f x"
    by auto
  then have "x  S" "x  T" by blast+
  from assms have "finite S" "finite T"
    using finite_subset by blast+
  from x  S c  f x have "c  HF (f ` S)" 
    using finite S by auto
  moreover
  from x  T c  f x have "c  HF (f ` T)" 
    using finite T by auto
  ultimately
  show "c  HF (f ` S)  HF (f ` T)" by blast
qed

lemma HUnion_hdiff_if_image_pairwise_disjoint:
  assumes "finite U"
      and "S  U"
      and "T  U"
      and image_pairwise_disjoint: "x  U. y  U. x  y  f x  f y = 0"
    shows "HF (f ` (S - T)) = HF (f ` S) - HF (f ` T)"
proof (standard; standard)
  fix c assume "c  HF (f ` (S - T))"
  then obtain x where "x  S - T" "c  f x"
    by auto
  then have "x  S" "x  T" by blast+
  from assms have "finite S" "finite T"
    using finite_subset by blast+
  from x  S c  f x have "c  HF (f ` S)" 
    using finite S by auto
  from image_pairwise_disjoint c  f x
  have "y  U. y  x  c  f y"
    using x  S S  U by auto
  with x  T have "y  T. c  f y"
    using T  U by fast
  then have "c  HF (f ` T)"
    using finite T by simp
  with c  HF (f ` S) show "c  HF (f ` S) - HF (f ` T)"
    by blast
next
  fix c assume "c  HF (f ` S) - HF (f ` T)"
  from assms have "finite S" "finite T"
    using finite_subset by blast+
  from c  HF (f ` S) - HF (f ` T)
  have "c  HF (f ` S)" "c  HF (f ` T)" by blast+
  then obtain x where "x  S" "x  T" "c  f x"
    using finite T by fastforce
  then show "c  HF (f ` (S - T))"
    using finite S by auto
qed

lemma hsubset_hcard:
  assumes "S  T"
  shows "hcard S  hcard T"
  using assms
  apply (induction T arbitrary: S)
   apply simp
  apply (smt (verit) hcard_hinsert_if less_eq_insert2_iff linorder_le_cases not_less_eq_eq)
  done

lemma HInter_singleton: "HF {x} = x"
  unfolding HInter_def by auto

lemma HF_nonempty: "finite S  S  {}  HF S  0"
  using hfset_HF by fastforce

lemma HF_insert_hinsert: "finite S  HF (insert x S) = HF S  x"
  unfolding hinsert_def by simp

lemma HUnion_empty: "s  S. f s = 0  HF (f ` S) = 0"
  by fastforce

lemma HUnion_eq: "x  S. f x = g x  HF (f ` S) = HF (g ` S)"
  by auto

end