Theory Valid_List
theory Valid_List
  imports Main "../util/List_Util"
begin
section ‹Valid List›
definition 
  valid_list :: "('a :: {linorder, order_bot}) list ⇒ bool"
where
  "valid_list s = (length s > 0 ∧ (∀i < length s - 1. s ! i ≠ bot) ∧ last s = bot)"
lemma valid_list_ex_def:
  fixes s ::"('a :: {linorder, order_bot}) list"
  shows "(valid_list s) = 
           (∃xs. s = xs @ [bot] ∧ 
                 (∀i < length xs. xs ! i ≠ bot))"
unfolding valid_list_def
proof safe
  assume 
    "s ≠ []" 
    "∀i<length s - 1. s ! i ≠ bot" 
    "last s = bot"
  then 
  show "∃xs. s = xs @ [bot] ∧ 
             (∀i<length xs. xs ! i ≠ bot)"
    by (metis append_butlast_last_id length_butlast nth_butlast)
qed (simp add: nth_append)+
lemma valid_list_iff_butlast_app_last:
  fixes s :: "('a :: {linorder, order_bot}) list"
  shows "valid_list s ⟷ 
            s ≠ [] ∧ 
            (∀x ∈ set (butlast s). x ≠ bot) ∧ 
            last s = bot"
  by (metis append_butlast_last_id butlast_snoc in_set_conv_nth 
            valid_list_def valid_list_ex_def length_greater_0_conv)
lemma valid_list_consI:
  fixes s :: "('a :: {linorder, order_bot}) list"
  fixes a :: 'a
  assumes "valid_list s"
  and "a ≠ bot" 
  shows "valid_list (a # s)"
  using assms 
  by (simp add: valid_list_iff_butlast_app_last)
lemma valid_list_consD:
  fixes s :: "('a :: {linorder, order_bot}) list"
  fixes a :: 'a
  assumes "valid_list (a # s)"
  assumes "s ≠ []"
  shows "valid_list s"
  using assms
  by (simp add: valid_list_iff_butlast_app_last)
lemma Min_valid_list:
  fixes s :: "('a :: {linorder, order_bot}) list"
  assumes "valid_list s"
  shows "Min (set s) = bot"
  by (metis assms List.finite_set Min.in_idem last_in_set min_bot valid_list_iff_butlast_app_last)
lemma valid_list_length:
  fixes s :: "('a :: {linorder, order_bot}) list"
  assumes "valid_list s"
  shows "length s > 0"
  using assms
  by (clarsimp simp: valid_list_ex_def)
lemma valid_list_length_ex:
  fixes s :: "('a :: {linorder, order_bot}) list"
  assumes "valid_list s"
  shows "∃n. length s = Suc n"
  using assms
  by (clarsimp simp: valid_list_ex_def)
lemma valid_list_not_nil:
  fixes s :: "('a :: {linorder, order_bot}) list"
  assumes "valid_list s"
  shows "s ≠ []"
  using assms by (simp add: valid_list_def)
lemma valid_list_Suc_mapping:
  fixes f :: "'a ⇒ nat"
  fixes s :: "'a list"
  shows "valid_list ((map (λx. Suc (f x)) s) @ [bot])"
proof (induct s)
  case (Cons a s)
  note IH = this
  have "map (λx. Suc (f x)) (a # s) = (Suc (f a)) # map (λx. Suc (f x)) s"
    by simp
  moreover
  have "Suc (f a) ≠ bot"
    by (simp add: bot_nat_def)
  hence "valid_list ((Suc (f a)) # (map (λx. Suc (f x)) s) @ [bot])"
    by (simp add: IH valid_list_consI)
  ultimately 
  show ?case
    by simp
qed (simp add: valid_list_ex_def)
lemma valid_list_app:
  assumes "valid_list (xs @ y # ys)"
  shows "valid_list (y # ys)"
  using assms
  by (induct xs) (simp add: valid_list_consD)+
lemma not_valid_list_app:
  assumes "valid_list (xs @ y # ys)"
  shows "¬valid_list xs"
  using assms
proof (induct xs)
  case Nil
  then show ?case
    using valid_list_not_nil by auto
next
  case (Cons a xs)
  then show ?case
    by (metis Groups.add_ac(2) Nil_is_append_conv One_nat_def add_diff_cancel_left' append_Cons
              last_ConsL list.discI list.size(4) nth_Cons_0 valid_list_consD valid_list_def)
qed
lemma valid_list_neqE:
  assumes "valid_list xs" "valid_list ys" "xs ≠ ys"
  shows "∃x y as bs cs. xs = as @ x # bs ∧ ys = as @ y # cs ∧ x ≠ y"
proof -
  note cases = list_neq_fc[OF assms(3)]
  moreover
  have "¬(∃z zs. xs = ys @ z # zs)"
    using assms(1) assms(2) not_valid_list_app by blast
  moreover
  have "¬(∃z zs. ys = xs @ z # zs)"
    using assms(1) assms(2) not_valid_list_app by blast
  ultimately show ?thesis
    by blast
qed
end