Theory List_util
theory List_util
imports Main
begin
inductive same_length :: "'a list ⇒ 'b list ⇒ bool" where
same_length_Nil: "same_length [] []" |
same_length_Cons: "same_length xs ys ⟹ same_length (x # xs) (y # ys)"
code_pred same_length .
lemma same_length_iff_eq_lengths: "same_length xs ys ⟷ length xs = length ys"
proof
assume "same_length xs ys"
then show "length xs = length ys"
by (induction xs ys rule: same_length.induct) simp_all
next
assume "length xs = length ys"
then show "same_length xs ys"
proof (induction xs arbitrary: ys)
case Nil
then show ?case
by (simp add: same_length_Nil)
next
case (Cons x xs)
then show ?case
by (metis length_Suc_conv same_length_Cons)
qed
qed
lemma same_length_Cons:
"same_length (x # xs) ys ⟹ ∃y ys'. ys = y # ys'"
"same_length xs (y # ys) ⟹ ∃x xs'. xs = x # xs'"
proof -
assume "same_length (x # xs) ys"
then show "∃y ys'. ys = y # ys'"
by (induction "x # xs" ys rule: same_length.induct) simp
next
assume "same_length xs (y # ys)"
then show "∃x xs'. xs = x # xs'"
by (induction xs "y # ys" rule: same_length.induct) simp
qed
section ‹nth\_opt›
fun nth_opt where
"nth_opt (x # _) 0 = Some x" |
"nth_opt (_ # xs) (Suc n) = nth_opt xs n" |
"nth_opt _ _ = None"
lemma nth_opt_eq_Some_conv: "nth_opt xs n = Some x ⟷ n < length xs ∧ xs ! n = x"
by (induction xs n rule: nth_opt.induct; simp)
lemmas nth_opt_eq_SomeD[dest] = nth_opt_eq_Some_conv[THEN iffD1]
section ‹Generic lemmas›
lemma list_rel_imp_pred1:
assumes
"list_all2 R xs ys" and
"⋀x y. (x, y) ∈ set (zip xs ys) ⟹ R x y ⟹ P x"
shows "list_all P xs"
using assms
by (induction xs ys rule: list.rel_induct) auto
lemma list_rel_imp_pred2:
assumes
"list_all2 R xs ys" and
"⋀x y. (x, y) ∈ set (zip xs ys) ⟹ R x y ⟹ P y"
shows "list_all P ys"
using assms
by (induction xs ys rule: list.rel_induct) auto
lemma eq_append_conv_conj: "(zs = xs @ ys) = (xs = take (length xs) zs ∧ ys = drop (length xs) zs)"
by (metis append_eq_conv_conj)
lemma list_all_list_updateI: "list_all P xs ⟹ P x ⟹ list_all P (list_update xs n x)"
by (induction xs arbitrary: n) (auto simp add: nat.split_sels(2))
lemmas list_all2_update1_cong = list_all2_update_cong[of _ _ ys _ "ys ! i" i for ys i, simplified]
lemmas list_all2_update2_cong = list_all2_update_cong[of _ xs _ "xs ! i" _ i for xs i, simplified]
lemma map_list_update_id:
"f (xs ! pc) = f instr ⟹ map f (xs[pc := instr]) = map f xs"
using list_update_id map_update by metis
lemma list_all_eq_const_imp_replicate:
assumes "list_all (λx. x = y) xs"
shows "xs = replicate (length xs) y"
using assms
by (induction xs; simp)
lemma list_all_eq_const_imp_replicate':
assumes "list_all ((=) y) xs"
shows "xs = replicate (length xs) y"
using assms
by (induction xs; simp)
lemma list_all_eq_const_replicate_lhs[intro]:
"list_all (λx. y = x) (replicate n y)"
by (simp add: list_all_length)
lemma list_all_eq_const_replicate_rhs[intro]:
"list_all (λx. x = y) (replicate n y)"
by (simp add: list_all_length)
lemma list_all_eq_const_replicate[simp]: "list_all ((=) c) (replicate n c)"
by (simp add: list_all_length)
lemma replicate_eq_map:
assumes "n = length xs" and "⋀y. y ∈ set xs ⟹ f y = x"
shows "replicate n x = map f xs"
using assms
proof (induction xs arbitrary: n)
case Nil
thus ?case by simp
next
case (Cons x xs)
thus ?case by (cases n; auto)
qed
lemma replicate_eq_impl_Ball_eq:
shows "replicate n c = xs ⟹ (∀x ∈ set xs. x = c)"
by (meson in_set_replicate)
lemma rel_option_map_of:
assumes "list_all2 (rel_prod (=) R) xs ys"
shows "rel_option R (map_of xs l) (map_of ys l)"
using assms
proof (induction xs ys rule: list.rel_induct)
case Nil
thus ?case by simp
next
case (Cons x xs y ys)
from Cons.hyps have "fst x = fst y" and "R (snd x) (snd y)"
by (simp_all add: rel_prod_sel)
show ?case
proof (cases "l = fst y")
case True
then show ?thesis
by (simp add: ‹fst x = fst y› ‹R (snd x) (snd y)›)
next
case False
then show ?thesis
using Cons.IH
by (simp add: ‹fst x = fst y› )
qed
qed
lemma list_all2_rel_prod_nth:
assumes "list_all2 (rel_prod R1 R2) xs ys" and "n < length xs"
shows "R1 (fst (xs ! n)) (fst (ys ! n)) ∧ R2 (snd (xs ! n)) (snd (ys ! n))"
using assms
proof (induction n arbitrary: xs ys)
case 0
then show ?case
using assms(1,2)
by (auto elim: list.rel_cases)
next
case (Suc n)
then obtain x xs' y ys' where xs_def[simp]: "xs = x # xs'" and ys_def[simp]: "ys = y # ys'"
by (auto elim: list.rel_cases)
show ?case
using Suc.prems Suc.IH[of xs' ys']
by force
qed
lemma list_all2_rel_prod_fst_hd:
assumes "list_all2 (rel_prod R1 R2) xs ys" and "xs ≠ [] ∨ ys ≠ []"
shows "R1 (fst (hd xs)) (fst (hd ys)) ∧ R2 (snd (hd xs)) (snd (hd ys))"
using assms
by (auto simp: rel_prod_sel elim: list.rel_cases)
lemma list_all2_rel_prod_fst_last:
assumes "list_all2 (rel_prod R1 R2) xs ys" and "xs ≠ [] ∨ ys ≠ []"
shows "R1 (fst (last xs)) (fst (last ys)) ∧ R2 (snd (last xs)) (snd (last ys))"
proof -
have "xs ≠ []" and "ys ≠ []"
using assms by (auto elim: list.rel_cases)
moreover have "length xs = length ys"
by (rule assms(1)[THEN list_all2_lengthD])
ultimately show ?thesis
using list_all2_rel_prod_nth[OF assms(1)]
by (simp add: last_conv_nth)
qed
lemma list_all_nthD[intro]: "list_all P xs ⟹ n < length xs ⟹ P (xs ! n)"
by (simp add: list_all_length)
lemma "list_all P xs ⟹ ∀x∈ set xs. P x"
using list_all_iff list.pred_set
by (simp add: list_all_iff)
lemma list_all_map_of_SomeD:
assumes "list_all P kvs" and "map_of kvs k = Some v"
shows "P (k, v)"
using assms
unfolding list.pred_set
by (auto dest: map_of_SomeD)
lemma list_all_not_nthD:"list_all P xs ⟹ ¬ P (xs ! n) ⟹ length xs ≤ n"
proof (induction xs arbitrary: n)
case Nil
then show ?case
by simp
next
case (Cons x xs)
then show ?case
by (cases n) simp_all
qed
lemma list_all_butlast_not_nthD: "list_all P (butlast xs) ⟹ ¬ P (xs ! n) ⟹ length xs ≤ Suc n"
using list_all_not_nthD[of _ "butlast xs" for xs, simplified]
by (smt (z3) One_nat_def Suc_pred le_Suc_eq length_butlast length_greater_0_conv less_Suc_eq list.pred_inject(1) list_all_not_nthD not_le nth_butlast)
lemma list_all_replicateI[intro]: "P x ⟹ list_all P (replicate n x)"
unfolding list.pred_set
by simp
lemma map_eq_append_replicate_conv:
assumes "map f xs = replicate n x @ ys"
shows "map f (take n xs) = replicate n x"
using assms
by (metis append_eq_conv_conj length_replicate take_map)
lemma map_eq_replicate_imp_list_all_const:
"map f xs = replicate n x ⟹ n = length xs ⟹ list_all (λy. f y = x) xs"
by (induction xs arbitrary: n) simp_all
lemma map_eq_replicateI: "length xs = n ⟹ (⋀x. x ∈ set xs ⟹ f x = c) ⟹ map f xs = replicate n c"
by (induction xs arbitrary: n) auto
lemma list_all_dropI[intro]: "list_all P xs ⟹ list_all P (drop n xs)"
by (metis append_take_drop_id list_all_append)
section ‹Non-empty list›
type_synonym 'a nlist = "'a × 'a list"
end