Theory Powerset

section ‹Powerset›
theory Powerset
  imports
    Main
    n_Sequences
    Common_Lemmas
    Filter_Bool_List
begin

subsection"Definition"

text "Pow A"
text "Cardinality: 2 ^ card A›"
text "Example: Pow {0,1} = {{}, {1}, {0}, {0, 1}}›"

subsection"Algorithm"

fun all_bool_lists :: "nat  bool list list" where
  "all_bool_lists 0 = [[]]"
| "all_bool_lists (Suc x) = concat [[False#xs, True#xs] . xs  all_bool_lists x]"

fun powerset_enum where
  "powerset_enum xs = [(filter_bool_list x xs) . x  all_bool_lists (length xs)]"

subsection"Verification"

text "First we show the relevant theorems for all_bool_lists›, then we'll transfer the
results to the enumeration algorithm for powersets."

lemma distinct_concat_aux: "distinct xs  distinct (concat (map (λxs. [False # xs, True # xs]) xs))"
  by (induct xs) auto

lemma distinct_all_bool_lists : "distinct (all_bool_lists x)"
  by (induct x) (auto simp add: distinct_concat_aux)

lemma all_bool_lists_correct: "set (all_bool_lists x) = {xs. length xs = x}"
proof(standard)
  show "set (all_bool_lists x)  {xs. length xs = x}"
    by (induct x) auto
next
  show "{xs. length xs = x}  set (all_bool_lists x)"
  proof(induct x)
    case 0
    then show ?case by simp
  next
    case (Suc x)
    have "length ys = Suc x  xs. ys = False # xs  ys = True # xs" for ys
      by (metis (full_types) Suc_length_conv)
    then show ?case using Suc
      by fastforce
  qed
qed

subsubsection"Correctness"

theorem powerset_enum_correct: "set (map set (powerset_enum xs)) = Pow (set xs)"
proof(standard)
  show "set (map set (powerset_enum xs))  Pow (set xs)"
    using filter_bool_list_not_elem by fastforce
next
  have "x. x  set xs  x  (λx. set (filter_bool_list x xs)) ` {zs. length zs = length xs}"
    unfolding image_def using filter_bool_list_exist_length image_def by auto
  then show "Pow (set xs)  set (map set (powerset_enum xs))"
    using all_bool_lists_correct by auto
qed
  
subsubsection"Distinctness"

theorem powerset_enum_distinct_elem: "distinct xs  ys  set (powerset_enum xs)  distinct ys"
  using filter_bool_list_distinct by auto 

theorem powerset_enum_distinct: "distinct xs  distinct (powerset_enum xs)"
proof -
  assume dis: "distinct xs"
  then have " distinct (map (λx. filter_bool_list x xs) (all_bool_lists (length xs)))"
    using distinct_map filter_bool_list_inj distinct_all_bool_lists
    by (metis all_bool_lists_correct)
  then show ?thesis
    using dis by simp
qed

subsubsection"Cardinality"

text "Cardinality for powersets is already shown in @{thm [source] card_Pow}."

subsection"Alternative algorithm with n_sequence_enum›"

fun all_bool_lists2 :: "nat  bool list list" where
  "all_bool_lists2 n = n_sequence_enum [True, False] n"

lemma all_bool_lists2_distinct: "distinct (all_bool_lists2 n)"
  by (auto simp add: n_sequence_enum_distinct)

lemma all_bool_lists2_correct: "set (all_bool_lists n) = set (all_bool_lists2 n)"
  by (auto simp: all_bool_lists_correct n_sequence_enum_correct n_sequences_def)

end