Theory Prelim

(*<*)
theory Prelim
imports Main
begin
(*>*)

section ‹Auxiliary Lemmas›

lemma Cons_eq_upt_conv: "x # xs = [m ..< n] ⟷ m < n ∧ x = m ∧ xs = [Suc m ..< n]"
  by (induct n arbitrary: xs) (force simp: Cons_eq_append_conv)+

lemma map_setE[elim_format]: "map f xs = ys ⟹ y ∈ set ys ⟹ ∃x∈set xs. f x = y"
  by (induct xs arbitrary: ys) auto

lemma set_Cons_eq: "set_Cons X XS = (⋃xs∈XS. (λx. x # xs) ` X)"
  by (auto simp: set_Cons_def)

lemma set_Cons_empty_iff: "set_Cons X XS = {} ⟷ (X = {} ∨ XS = {})"
  by (auto simp: set_Cons_eq)

lemma infinite_set_ConsI:
  "XS ≠ {} ⟹ infinite X ⟹ infinite (set_Cons X XS)"
  "X ≠ {} ⟹ infinite XS ⟹ infinite (set_Cons X XS)"
proof(unfold set_Cons_eq)
  assume "infinite X" and "XS ≠ {}"
  then obtain xs where "xs ∈ XS"
    by blast
  hence "inj (λx. x # xs)"
    by (clarsimp simp: inj_on_def)
  hence "infinite ((λx. x # xs) ` X)"
    using ‹infinite X› finite_imageD inj_on_def
    by blast
  moreover have "((λx. x # xs) ` X) ⊆ (⋃xs∈XS. (λx. x # xs) ` X)"
    using ‹xs ∈ XS› by auto
  ultimately show "infinite (⋃xs∈XS. (λx. x # xs) ` X)"
    by (simp add: infinite_super)
next
  assume "infinite XS" and "X ≠ {}"
  then show "infinite (⋃xs∈XS. (λx. x # xs) ` X)"
    by (elim contrapos_nn finite_surj[of _ _ tl]) (auto simp: image_iff)
qed

primrec fst_pos :: "'a list ⇒ 'a ⇒ nat option"
  where "fst_pos [] x = None"
  | "fst_pos (y#ys) x = (if x = y then Some 0 else
      (case fst_pos ys x of None ⇒ None | Some n ⇒ Some (Suc n)))"

lemma fst_pos_None_iff: "fst_pos xs x = None ⟷ x ∉ set xs"
  by (induct xs arbitrary: x; force split: option.splits)

lemma nth_fst_pos: "x ∈ set xs ⟹ xs ! (the (fst_pos xs x)) = x"
  by (induct xs arbitrary: x; fastforce simp: fst_pos_None_iff split: option.splits)

primrec positions :: "'a list ⇒ 'a ⇒ nat list"
  where "positions [] x = []"
  | "positions (y#ys) x = (λns. if x = y then 0 # ns else ns) (map Suc (positions ys x))"

lemma eq_positions_iff: "length xs = length ys
  ⟹ positions xs x = positions ys y ⟷ (∀n< length xs. xs ! n = x ⟷ ys ! n = y)"
  by (induct xs ys arbitrary: x y rule: list_induct2) (use less_Suc_eq_0_disj in auto)

lemma positions_eq_nil_iff: "positions xs x = [] ⟷ x ∉ set xs"
  by (induct xs) simp_all

lemma positions_nth: "n ∈ set (positions xs x) ⟹ xs ! n = x"
  by (induct xs arbitrary: n x)
    (auto simp: positions_eq_nil_iff[symmetric] split: if_splits)

lemma set_positions_eq: "set (positions xs x) = {n. xs ! n = x ∧ n < length xs}"
  by (induct xs arbitrary: x)
    (use less_Suc_eq_0_disj in ‹auto simp: positions_eq_nil_iff[symmetric] image_iff split: if_splits›)

lemma positions_length: "n ∈ set (positions xs x) ⟹ n < length xs"
  by (induct xs arbitrary: n x)
    (auto simp: positions_eq_nil_iff[symmetric] split: if_splits)

lemma positions_nth_cong:
  "m ∈ set (positions xs x) ⟹ n ∈ set (positions xs x) ⟹ xs ! n = xs ! m"
  using positions_nth[of _ xs x] by simp

lemma fst_pos_in_positions: "x ∈ set xs ⟹ the (fst_pos xs x) ∈ set (positions xs x)"
  by (induct xs arbitrary: x, simp)
    (fastforce simp: hd_map fst_pos_None_iff split: option.splits)

lemma hd_positions_eq_fst_pos: "x ∈ set xs ⟹ hd (positions xs x) = the (fst_pos xs x)"
  by (induct xs arbitrary: x)
    (auto simp: hd_map fst_pos_None_iff positions_eq_nil_iff split: option.splits)

lemma sorted_positions: "sorted (positions xs x)"
  by (induct xs arbitrary: x) (auto simp add: sorted_iff_nth_Suc nth_Cons' gr0_conv_Suc)

lemma Min_sorted_list: "sorted xs ⟹ xs ≠ [] ⟹ Min (set xs) = hd xs"
  by (induct xs)
    (auto simp: Min_insert2)

lemma Min_positions: "x ∈ set xs ⟹ Min (set (positions xs x)) = the (fst_pos xs x)"
  by (auto simp: Min_sorted_list[OF sorted_positions]
      positions_eq_nil_iff hd_positions_eq_fst_pos)

lemma subset_positions_map_fst: "set (positions tXs tX) ⊆ set (positions (map fst tXs) (fst tX))"
  by (induct tXs arbitrary: tX)
    (auto simp: subset_eq)

lemma subset_positions_map_snd: "set (positions tXs tX) ⊆ set (positions (map snd tXs) (snd tX))"
  by (induct tXs arbitrary: tX)
    (auto simp: subset_eq)

lemma Max_eqI: "finite A ⟹ A ≠ {} ⟹ (⋀a. a ∈ A ⟹ a ≤ b) ⟹ ∃a∈A. b ≤ a ⟹ Max A = b"
  by (rule antisym[OF Max.boundedI Max_ge_iff[THEN iffD2]]; clarsimp)

lemma Max_Suc: "X ≠ {} ⟹ finite X ⟹ Max (Suc ` X) = Suc (Max X)"
  using Max_ge Max_in
  by (intro Max_eqI) blast+

lemma Max_insert0: "X ≠ {} ⟹ finite X ⟹ Max (insert (0::nat) X) = Max X"
  using Max_ge Max_in
  by (intro Max_eqI) blast+

lemma positions_Cons_notin_tail: "x ∉ set xs ⟹ positions (x # xs) x = [0::nat]"
  by (cases xs) (auto simp: positions_eq_nil_iff)

lemma Max_set_positions_Cons_hd:
  "x ∉ set xs ⟹ Max (set (positions (x # xs) x)) = 0"
  by (subst positions_Cons_notin_tail) simp_all

lemma Max_set_positions_Cons_tl:
  "y ∈ set xs ⟹ Max (set (positions (x # xs) y)) = Suc (Max (set (positions xs y)))"
  by (auto simp: Max_Suc positions_eq_nil_iff)

lemma max_aux: "finite X ⟹ Suc j ∈ X ⟹ Max (insert (Suc j) (X - {j})) = Max (insert j X)"
  by (smt (verit) max.orderI Max.insert_remove Max_ge Max_insert empty_iff insert_Diff_single
      insert_absorb insert_iff max_def not_less_eq_eq)

lemma ball_swap: "(∀x ∈ A. ∀y ∈ B. P x y) = (∀y ∈ B. ∀x ∈ A. P x y)"
  by auto

lemma ball_triv_nonempty: "A ≠ {} ⟹ (∀x ∈ A. P) = P"
  by auto

lemma ball_if_distrib: "(∀x ∈ B. if p then f x else g x) ⟷ (if p then (∀x ∈ B. f x) else (∀x ∈ B. g x))"
  by simp

(*<*)
end
(*>*)