Theory Set_System

theory Set_System
  imports Main
begin

section ‹AI-Authored proof formalization via independence systems›

subsection ‹Independence Systems›

text ‹
  An independence system consists of a finite ground set termE and a family termF
  of subsets satisfying: (1) the empty set is in termF, and (2) termF is hereditary
  (downward closed under subsets).
›

locale indep_system =
  fixes E :: "'a set" and indep :: "'a set  bool"
  assumes finite_E: "finite E"
  assumes empty_indep: "indep {}"
  assumes indep_subset_carrier: "F. indep F  F  E"
  assumes hereditary: "F F'. indep F  F'  F  indep F'"

text ‹
  A maximal independent set is one where no element can be added while preserving independence.
›

definition (in indep_system) maximal :: "'a set  bool" where
  "maximal F  indep F  (e  E - F. ¬ indep (F  {e}))"

lemma (in indep_system) maximalI:
  assumes "indep F" "e. e  E - F  ¬ indep (F  {e})"
  shows "maximal F"
  unfolding maximal_def using assms by blast

lemma (in indep_system) maximalD:
  assumes "maximal F"
  shows "indep F" "e. e  E - F  ¬ indep (F  {e})"
  using assms unfolding maximal_def by blast+

subsection ‹Best-In-Greedy Algorithm›

text ‹
  The Best-In-Greedy algorithm processes elements of termE in a given order, 
  greedily adding each element if independence is preserved.
  We model it as a fold over a list.
›

definition greedy_step :: "('a set  bool)  'a  'a set  'a set" where
  "greedy_step indep e F = (if indep (F  {e}) then F  {e} else F)"

definition best_in_greedy :: "('a set  bool)  'a list  'a set" where
  "best_in_greedy indep es = foldl (λF e. greedy_step indep e F) {} es"

text ‹
  We define the sequence of intermediate sets produced by the greedy algorithm.
›

fun greedy_partial :: "('a set  bool)  'a list  nat  'a set" where
  "greedy_partial indep es 0 = {}" |
  "greedy_partial indep es (Suc i) = 
    greedy_step indep (es ! i) (greedy_partial indep es i)"


text ‹The final result equals the partial result after processing all elements.›

lemma best_in_greedy_foldl_partial:
  assumes "n  length es"
  shows "foldl (λF e. greedy_step indep e F) {} (take n es) = greedy_partial indep es n" 
  using assms
proof (induction n)
  case 0
  then show ?case by simp
next
  case (Suc n)
  thus ?case
    by (simp add: take_Suc_conv_app_nth)
qed

lemma best_in_greedy_eq_partial:
  "best_in_greedy indep es = greedy_partial indep es (length es)"
  unfolding best_in_greedy_def
  using best_in_greedy_foldl_partial[of "length es" es indep]
  by simp

subsubsection ‹Properties of termgreedy_partial

text ‹The partial result is monotonically increasing.›

lemma greedy_partial_mono:
  "i  j  greedy_partial indep es i  greedy_partial indep es j"
proof (induction j)
  case 0
  then show ?case by simp
next
  case (Suc j)
  then show ?case
    by (cases "i = Suc j") (auto simp: greedy_step_def)
qed

text ‹If an element was skipped at step termj, adding it to F\_{j-1} was not independent.›

lemma greedy_partial_skip:
  assumes "j < length es" "es ! j  greedy_partial indep es (Suc j)"
  shows "¬ indep (greedy_partial indep es j  {es ! j})"
  using assms by (simp add: greedy_step_def split: if_splits)

text ‹The partial set is always contained in the first i elements.›

lemma greedy_partial_subset:
  assumes "i  length es"
  shows "greedy_partial indep es i  set (take i es)"
  using assms
proof (induction i)
  case 0
  then show ?case by simp
next
  case (Suc i)
  then have "greedy_partial indep es i  set (take i es)" by simp
  moreover have "set (take i es)  set (take (Suc i) es)"
    by (simp add: set_take_subset_set_take)
  moreover have "es ! i  set (take (Suc i) es)"
    using Suc.prems by (simp add: take_Suc_conv_app_nth)
  ultimately show ?case 
    by (auto simp: greedy_step_def)
qed


subsubsection ‹Theorem: Best-In-Greedy returns a maximal independent set›

text ‹
  Theorem 2.1 of larry2.tex (Theorem 13.9 of Korte-Vygen).
  If (E, indep) is an independence system and es is a permutation of E,
  then the Best-In-Greedy output is a maximal independent set.
  
  First we show the greedy output is independent, by induction.
›

lemma (in indep_system) greedy_partial_indep:
  assumes "i  length es" "set es  E"
  shows "indep (greedy_partial indep es i)"
  using assms
proof (induction i)
  case 0
  then show ?case using empty_indep by simp
next
  case (Suc i)
  then have IH: "indep (greedy_partial indep es i)" by simp
  show ?case
  proof (cases "indep (greedy_partial indep es i  {es ! i})")
    case True
    then show ?thesis by (simp add: greedy_step_def)
  next
    case False
    then show ?thesis using IH by (simp add: greedy_step_def)
  qed
qed

text ‹Now the main theorem.›

theorem (in indep_system) best_in_greedy_maximal:
  assumes perm: "set es = E" and distinct: "distinct es"
  shows "maximal (best_in_greedy indep es)"
proof (rule maximalI)
  have set_es: "set es  E" using perm by simp

  show indep_result: "indep (best_in_greedy indep es)"
    unfolding best_in_greedy_eq_partial
    using greedy_partial_indep[of "length es" es] set_es by simp

  fix e assume e_outside: "e  E - best_in_greedy indep es"
  show "¬ indep (best_in_greedy indep es  {e})"
  proof -
    from e_outside perm have "e  set es" by simp
    then obtain j where j: "j < length es" "es ! j = e" 
      by (metis in_set_conv_nth)
    from e_outside have "e  greedy_partial indep es (length es)"
      unfolding best_in_greedy_eq_partial by simp
    then have "e  greedy_partial indep es (Suc j)"
      using greedy_partial_mono[of "Suc j" "length es" indep es] j by auto
    then have not_indep_j: "¬ indep (greedy_partial indep es j  {e})"
      using greedy_partial_skip[of j es indep] j by simp
    have sub: "greedy_partial indep es j  {e}  best_in_greedy indep es  {e}"
      unfolding best_in_greedy_eq_partial 
      using greedy_partial_mono[of j "length es" indep es] j by auto
    show "¬ indep (best_in_greedy indep es  {e})"
    proof 
      assume "indep (best_in_greedy indep es  {e})"
      then show False using hereditary[OF _ sub] not_indep_j by blast
    qed
  qed
qed


end