Theory LemExtraDefs
chapter ‹Auxiliary Definitions needed by Lem›
theory "LemExtraDefs"
imports
Main
"HOL-Combinatorics.List_Permutation"
"HOL-Library.While_Combinator"
begin
hide_const (open) sign
subsection ‹General›
consts :: " 'a ⇒ 'b"
subsection ‹Lists›
:: " 'a list ⇒ nat ⇒ 'a option " where
"index [] n = None"
| "index (x # xs) 0 = Some x"
| "index (x # xs) (Suc n) = index xs n"
lemma [simp]:
"index l n = Some x ⟷ (n < length l ∧ (x = l ! n))"
proof (induct l arbitrary: n x)
case Nil thus ?case by simp
next
case (Cons e es n x)
note ind_hyp = this
show ?case
proof (cases n)
case 0 thus ?thesis by auto
next
case (Suc n')
with ind_hyp show ?thesis by simp
qed
qed
lemma [simp]:
"index l n = None ⟷ length l ≤ n"
by (rule iffD1[OF Not_eq_iff]) auto
lemma [simp]:
"length l ≤ n ⟹ index l n = None"
"n < length l ⟹ index l n = Some (l ! n)"
by (simp_all)
:: "('a ⇒ bool) ⇒ 'a list ⇒ nat list" where
"find_indices P [] = []"
| "find_indices P (x # xs) = (if P x then 0 # (map Suc (find_indices P xs)) else (map Suc (find_indices P xs)))"
lemma :
"length (find_indices P l) ≤ length l"
by (induct l) auto
lemma :
"sorted l ⟹ sorted (map Suc l)"
by (induct l) (simp_all)
lemma :
"sorted (find_indices P xs)"
proof (induct xs)
case Nil thus ?case by simp
next
case (Cons x xs)
from sorted_map_suc[OF this]
show ?case
by (simp)
qed
lemma [simp] :
"set (find_indices P l) = {i. i < length l ∧ P (l ! i)}"
proof (intro set_eqI)
fix i
show "i ∈ set (find_indices P l) ⟷ (i ∈ {i. i < length l ∧ P (l ! i)})"
proof (induct l arbitrary: i)
case Nil thus ?case by simp
next
case (Cons x l' i)
note ind_hyp = this
show ?case
proof (cases i)
case 0 thus ?thesis by auto
next
case (Suc i') with ind_hyp[of i'] show ?thesis by auto
qed
qed
qed
where
"find_index P xs = (case find_indices P xs of
[] ⇒ None
| i # _ ⇒ Some i)"
lemma [simp] :
"(find_index P xs = Some ii) ⟷ (ii < length xs ∧ P (xs ! ii) ∧ (∀i' < ii. ¬(P (xs ! i'))))"
(is "?lhs = ?rhs")
proof (cases "find_indices P xs")
case Nil
with find_indices_set[of P xs]
show ?thesis
unfolding find_index_def by auto
next
case (Cons i il) note find_indices_eq = this
from sorted_find_indices[of P xs] find_indices_eq
have "sorted (i # il)" by simp
hence i_leq: "⋀i'. i' ∈ set (i # il) ⟹ i ≤ i'" by auto
from find_indices_set[of P xs, unfolded find_indices_eq]
have set_i_il_eq:"⋀i'. i' ∈ set (i # il) = (i' < length xs ∧ P (xs ! i'))"
by simp
have lhs_eq: "find_index P xs = Some i"
unfolding find_index_def find_indices_eq by simp
show ?thesis
proof (intro iffI)
assume ?lhs
with lhs_eq have ii_eq[simp]: "ii = i" by simp
from set_i_il_eq[of i] i_leq[unfolded set_i_il_eq]
show ?rhs by auto (metis leD less_trans)
next
assume ?rhs
with set_i_il_eq[of ii]
have "ii ∈ set (i # il) ∧ (ii ≤ i)"
by (metis leI length_pos_if_in_set nth_Cons_0 nth_mem set_i_il_eq)
with i_leq [of ii] have "i = ii" by simp
thus ?lhs unfolding lhs_eq by simp
qed
qed
lemma [simp] :
"(find_index P xs = None) ⟷ (∀x ∈ set xs. ¬(P x))" (is "?lhs = ?rhs")
proof (rule iffD1[OF Not_eq_iff], intro iffI)
assume "¬ ?lhs"
then obtain i where "find_index P xs = Some i" by auto
hence "i < length xs ∧ P (xs ! i)" by simp
thus "¬ ?rhs" by auto
next
let ?p = "(λi. i < length xs ∧ P(xs ! i))"
assume "¬ ?rhs"
then obtain i where "?p i"
by (metis in_set_conv_nth)
from LeastI [of ?p, OF ‹?p i›]
have "?p (Least ?p)" .
hence "find_index P xs = Some (Least ?p)"
by (subst find_index_eq_some) (metis (mono_tags) less_trans not_less_Least)
thus "¬ ?lhs" by blast
qed
where
"genlist f n = map f (upt 0 n)"
lemma [simp] :
"length (genlist f n) = n"
unfolding genlist_def by simp
lemma [simp]:
"genlist f 0 = []"
"genlist f (Suc n) = genlist f n @ [f n]"
unfolding genlist_def by auto
where
"split_at n l = (take n l, drop n l)"
:: "('a ⇒ bool) ⇒ 'a list ⇒ ('a list) option " where
"delete_first P [] = None"
| "delete_first P (x # xs) =
(if (P x) then Some xs else
map_option (λxs'. x # xs') (delete_first P xs))"
declare delete_first.simps [simp del]
lemma [simp] :
"delete_first P [] = None"
"P x ⟹ delete_first P (x # xs) = Some xs"
"¬(P x) ⟹ delete_first P (x # xs) = map_option (λxs'. x # xs') (delete_first P xs)"
unfolding delete_first.simps by auto
lemmas = delete_first.simps(2)
lemma [simp] :
"delete_first P l = None ⟷ (∀x ∈ set l. ¬ (P x))"
by (induct l) (auto simp add: delete_first_unroll)
lemma :
"delete_first P l = (Some l') ⟷ (∃l1 x l2. P x ∧ (∀x ∈ set l1. ¬(P x)) ∧ (l = l1 @ (x # l2)) ∧ (l' = l1 @ l2))"
(is "?lhs l l' = (∃l1 x l2. ?rhs_body l1 x l2 l l')")
proof (induct l arbitrary: l')
case Nil thus ?case by simp
next
case (Cons e l l')
note ind_hyp = this
show ?case
proof (cases "P e")
case True
show ?thesis
proof (rule iffI)
assume "?lhs (e # l) l'"
with ‹P e› have "l = l'" by simp
with ‹P e› have "?rhs_body [] e l' (e # l) l'" by simp
thus "∃l1 x l2. ?rhs_body l1 x l2 (e # l) l'" by blast
next
assume "∃l1 x l2. ?rhs_body l1 x l2 (e # l) l'"
then obtain l1 x l2 where body_ok: "?rhs_body l1 x l2 (e # l) l'" by blast
from body_ok ‹P e› have l1_eq[simp]: "l = l'"
by (cases l1) (simp_all)
with ‹P e› show "?lhs (e # l) l'" by simp
qed
next
case False
define rhs_pred where "rhs_pred ≡ λl1 x l2 l l'. ?rhs_body l1 x l2 l l'"
have rhs_fold: "⋀l1 x l2 l l'. ?rhs_body l1 x l2 l l' = rhs_pred l1 x l2 l l'"
unfolding rhs_pred_def by simp
have "(∃z l1 x l2. rhs_pred l1 x l2 l z ∧ e # z = l') = (∃l1 x l2. rhs_pred l1 x l2 (e # l) l')"
proof (intro iffI)
assume "∃z l1 x l2. rhs_pred l1 x l2 l z ∧ e # z = l'"
then obtain z l1 x l2 where "rhs_pred l1 x l2 l z" and l'_eq: "l' = e # z" by auto
with ‹¬(P e)› have "rhs_pred (e # l1) x l2 (e # l) l'"
unfolding rhs_pred_def by simp
thus "∃l1 x l2. rhs_pred l1 x l2 (e # l) l'" by blast
next
assume "∃l1 x l2. rhs_pred l1 x l2 (e # l) l'"
then obtain l1 x l2 where "rhs_pred l1 x l2 (e # l) l'" by blast
with ‹¬ (P e)› obtain l1' where l1_eq[simp]: "l1 = e # l1'"
unfolding rhs_pred_def by (cases l1) (auto)
with ‹rhs_pred l1 x l2 (e # l) l'›
have "rhs_pred l1' x l2 l (l1' @ l2) ∧ e # (l1' @ l2) = l'"
unfolding rhs_pred_def by (simp)
thus "∃z l1 x l2. rhs_pred l1 x l2 l z ∧ e # z = l'" by blast
qed
with ‹¬ P e› show ?thesis
unfolding rhs_fold
by (simp add: ind_hyp[unfolded rhs_fold])
qed
qed
lemma [code] :
"perm [] l ⟷ l = []" (is ?g1)
"perm (x # xs) l ⟷ (case delete_first (λe. e = x) l of
None => False
| Some l' => perm xs l')" (is ?g2)
proof -
show ?g1 by auto
next
show ?g2
proof (cases "delete_first (λe. e = x) l")
case None note del_eq = this
hence "x ∉ set l" by auto
with perm_set_eq [of "x # xs" l]
have "¬ perm (x # xs) l" by auto
thus ?thesis unfolding del_eq by simp
next
case (Some l') note del_eq = this
from del_eq[unfolded delete_first_eq_some]
obtain l1 l2 where l_eq: "l = l1 @ [x] @ l2" and l'_eq: "l' = l1 @ l2" by auto
have "(x # xs <~~> l1 @ x # l2) = (xs <~~> l1 @ l2)"
proof -
from perm_append_swap [of l1 "[x]"]
perm_append2 [of "l1 @ [x]" "x # l1" l2]
have "l1 @ x # l2 <~~> x # (l1 @ l2)" by simp
hence "x # xs <~~> l1 @ x # l2 ⟷ x # xs <~~> x # (l1 @ l2)"
by simp
thus ?thesis by simp
qed
with del_eq l_eq l'_eq show ?thesis by simp
qed
qed
:: "('a ⇒ 'a ⇒ bool)⇒ 'a list ⇒ bool " where
"sorted_by cmp [] = True"
| "sorted_by cmp [_] = True"
| "sorted_by cmp (x1 # x2 # xs) = ((cmp x1 x2) ∧ sorted_by cmp (x2 # xs))"
lemma [simp] :
"sorted_by ((≤) :: ('a::{linorder}) => 'a => bool) = sorted"
proof (rule ext)
fix l :: "'a list"
show "sorted_by (≤) l = sorted l"
proof (induct l)
case Nil thus ?case by simp
next
case (Cons x xs)
thus ?case
by (smt (verit, best) list.inject sorted1 sorted2 sorted_by.elims(1))
qed
qed
lemma :
"sorted_by cmp (x # xs) ⟹ sorted_by cmp xs"
by (cases xs) simp_all
lemma :
assumes trans_cmp: "transp cmp"
shows "sorted_by cmp (x # xs) = ((∀x' ∈ set xs . cmp x x') ∧ sorted_by cmp xs)"
proof (induct xs arbitrary: x)
case Nil thus ?case by simp
next
case (Cons x2 xs x1)
note ind_hyp = this
from trans_cmp
show ?case
by (auto simp add: ind_hyp transp_def)
qed
:: "('a ⇒ 'a ⇒ bool)⇒ 'a ⇒ 'a list ⇒ 'a list " where
"insert_sort_insert_by cmp e ([]) = ( [e])"
| "insert_sort_insert_by cmp e (x # xs) = ( if cmp e x then (e # (x # xs)) else x # (insert_sort_insert_by cmp e xs))"
lemma [simp] :
"length (insert_sort_insert_by cmp e l) = Suc (length l)"
by (induct l) auto
lemma [simp] :
"set (insert_sort_insert_by cmp e l) = insert e (set l)"
by (induct l) auto
lemma :
"(insert_sort_insert_by cmp e l) <~~> (e # l)"
by (induction l) simp_all
lemma :
assumes cmp_cases: "⋀y. y ∈ set l ⟹ ¬ (cmp e y) ⟹ cmp y e"
assumes cmp_trans: "transp cmp"
shows "sorted_by cmp l ⟹ sorted_by cmp (insert_sort_insert_by cmp e l)"
using cmp_cases
proof (induct l)
case Nil thus ?case by simp
next
case (Cons x1 l')
note ind_hyp = Cons(1)
note sorted_x1_l' = Cons(2)
note cmp_cases = Cons(3)
show ?case
proof (cases l')
case Nil with cmp_cases show ?thesis by simp
next
case (Cons x2 l'') note l'_eq = this
from l'_eq sorted_x1_l' have "cmp x1 x2" "sorted_by cmp l'" by simp_all
show ?thesis
proof (cases "cmp e x1")
case True
with ‹cmp x1 x2› ‹sorted_by cmp l'›
have "sorted_by cmp (x1 # l')"
unfolding l'_eq by (simp)
with ‹cmp e x1›
show ?thesis by simp
next
case False
with cmp_cases have "cmp x1 e" by simp
have "⋀x'. x' ∈ set l' ⟹ cmp x1 x'"
proof -
fix x'
assume "x' ∈ set l'"
hence "x' = x2 ∨ cmp x2 x'"
using ‹sorted_by cmp l'› l'_eq sorted_by_cons_trans [OF cmp_trans, of x2 l'']
by auto
with transpD[OF cmp_trans, of x1 x2 x'] ‹cmp x1 x2›
show "cmp x1 x'" by blast
qed
hence "sorted_by cmp (x1 # insert_sort_insert_by cmp e l')"
using ind_hyp [OF ‹sorted_by cmp l'›] ‹cmp x1 e› cmp_cases
unfolding sorted_by_cons_trans[OF cmp_trans]
by simp
with ‹¬(cmp e x1)›
show ?thesis by simp
qed
qed
qed
:: "('a ⇒ 'a ⇒ bool) ⇒ 'a list ⇒ 'a list " where
"insert_sort_by cmp [] = []"
| "insert_sort_by cmp (x # xs) = insert_sort_insert_by cmp x (insert_sort_by cmp xs)"
lemma :
"(insert_sort_by cmp l) <~~> l"
by (induction l) (simp_all add: insert_sort_insert_by_perm)
lemma [simp]:
"length (insert_sort_by cmp l) = length l"
by (induct l) auto
lemma [simp]:
"set (insert_sort_by cmp l) = set l"
by (induct l) auto
where
"sort_by = insert_sort_by"
lemma [simp]:
"length (sort_by cmp l) = length l"
"set (sort_by cmp l) = set l"
unfolding sort_by_def by simp_all
lemma :
"sort_by cmp l <~~> l"
unfolding sort_by_def
by (simp add: insert_sort_by_perm)
subsection ‹Maps›
:: "('v ⇒ 'w) ⇒ ('k, 'v) map ⇒ ('k, 'w) map" where
"map_image f m = (λk. map_option f (m k))"
definition map_domain_image :: "('k ⇒ 'v ⇒ 'w) ⇒ ('k, 'v) map ⇒ ('k, 'w) map" where
"map_domain_image f m = (λk. map_option (f k) (m k))"
lemma [simp]:
"(map_image f m) k = None ⟷ m k = None"
"(map_image f m) k = Some x ⟷ (∃x'. (m k = Some x') ∧ (x = f x'))"
"(map_image f Map.empty) = Map.empty"
"(map_image f (m (k ↦ v)) = (map_image f m) (k ↦ f v))"
unfolding map_image_def by auto
lemma [simp]:
"dom (map_image f m) = dom m"
"ran (map_image f m) = f ` (ran m)"
unfolding dom_def ran_def by auto
:: "('k, 'v) map ⇒ ('k * 'v) set" where
"map_to_set m = { (k, v) . m k = Some v }"
lemma [simp] :
"map_to_set Map.empty = {}" (is ?g1)
"map_to_set (m ((k::'k) ↦ (v::'v))) = (insert (k, v) (map_to_set (m |` (- {k}))))" (is ?g2)
proof -
show ?g1 unfolding map_to_set_def by simp
next
show ?g2
proof (rule set_eqI)
fix kv :: "('k * 'v)"
obtain k' v' where kv_eq[simp]: "kv = (k', v')" by (rule prod.exhaust)
show "(kv ∈ map_to_set (m(k ↦ v))) = (kv ∈ insert (k, v) (map_to_set (m |` (- {k}))))"
by (auto simp add: map_to_set_def)
qed
qed
subsection ‹Sets›
" s ≡ (SOME x. (x ∈ s))"
:: "('a × 'a) set ⇒ ('a × 'a) set" where
"without_trans_edges S ≡
let ts = trancl S in
{ (x, y) ∈ S. ∀z ∈ snd ` S. x ≠ z ∧ y ≠ z ⟶ ¬ ((x, z) ∈ ts ∧ (z, y) ∈ ts)}"
:: "'a set ⇒ ('a set ⇒ 'a set) ⇒ 'a set" where
"unbounded_lfp S f ≡
while (λx. x ⊂ S) f S"
:: "'a set ⇒ ('a set ⇒ 'a set) ⇒ 'a set" where
"unbounded_gfp S f ≡
while (λx. S ⊂ x) f S"
lemma [simp]:
"s ≠ {} ⟹ (set_choose s) ∈ s"
unfolding set_choose_def
by (rule someI_ex) auto
lemma [simp]:
"set_choose {x} = x"
unfolding set_choose_def
by auto
lemma [code]:
"set_choose (set [x]) = x"
by auto
lemma [intro] :
assumes "s ≠ {}"
shows "set_choose s ∈ s"
proof -
from ‹s ≠ {}›
obtain x where "x ∈ s" by auto
thus ?thesis
unfolding set_choose_def
by (rule someI)
qed
where
"set_case s c_empty c_sing c_else =
(if (s = {}) then c_empty else
(if (card s = 1) then c_sing (set_choose s) else
c_else))"
lemma [simp] :
"set_case {} c_empty c_sing c_else = c_empty"
"set_case {x} c_empty c_sing c_else = c_sing x"
"card s > 1 ⟹ set_case s c_empty c_sing c_else = c_else"
"¬(finite s) ⟹ set_case s c_empty c_sing c_else = c_else"
unfolding set_case_def by auto
lemma [simp] :
assumes x12_neq: "x1 ≠ x2"
shows "set_case (insert x1 (insert x2 xs)) c_empty c_sing c_else = c_else"
proof (cases "finite xs")
case False thus ?thesis by (simp)
next
case True note fin_xs = this
have "card {x1,x2} ≤ card (insert x1 (insert x2 xs))"
by (rule card_mono) (auto simp add: fin_xs)
with x12_neq have "1 < card (insert x1 (insert x2 xs))" by simp
thus ?thesis by auto
qed
lemma [code] :
"set_case (set []) c_empty c_sing c_else = c_empty"
"set_case (set [x]) c_empty c_sing c_else = c_sing x"
"set_case (set (x1 # x2 # xs)) c_empty c_sing c_else =
(if (x1 = x2) then
set_case (set (x2 # xs)) c_empty c_sing c_else
else
c_else)"
by auto
:: "'a set ⇒ ('a set ⇒ 'a set) ⇒ 'a set" where
"set_lfp s f = lfp (λs'. f s' ∪ s)"
lemma :
assumes mono_f: "mono f"
shows "set_lfp s f = (if (f s) ⊆ s then s else (set_lfp (s ∪ f s) f))" (is "?ls = ?rs")
proof (cases "f s ⊆ s")
case True note fs_sub_s = this
from fs_sub_s have "⋂{u. f u ∪ s ⊆ u} = s" by auto
hence "?ls = s" unfolding set_lfp_def lfp_def .
with fs_sub_s show "?ls = ?rs" by simp
next
case False note not_fs_sub_s = this
from mono_f have mono_f': "mono (λs'. f s' ∪ s)"
unfolding mono_def by auto
have "⋂{u. f u ∪ s ⊆ u} = ⋂{u. f u ∪ (s ∪ f s) ⊆ u}" (is "⋂?S1 = ⋂?S2")
proof
have "?S2 ⊆ ?S1" by auto
thus "⋂?S1 ⊆ ⋂?S2" by (rule Inf_superset_mono)
next
{ fix e
assume "e ∈ ⋂?S2"
hence S2_prop: "⋀s'. f s' ⊆ s' ⟹ s ⊆ s' ⟹ f s ⊆ s' ⟹ e ∈ s'" by simp
{ fix s'
assume "f s' ⊆ s'" "s ⊆ s'"
from mono_f ‹s ⊆ s'›
have "f s ⊆ f s'" unfolding mono_def by simp
with ‹f s' ⊆ s'› have "f s ⊆ s'" by simp
with ‹f s' ⊆ s'› ‹s ⊆ s'› S2_prop
have "e ∈ s'" by simp
}
hence "e ∈ ⋂?S1" by simp
}
thus "⋂?S2 ⊆ ⋂?S1" by auto
qed
hence "?ls = (set_lfp (s ∪ f s) f)"
unfolding set_lfp_def lfp_def .
with not_fs_sub_s show "?ls = ?rs" by simp
qed
lemma [simp] :
"mono f ⟹ f s ⊆ s ⟹ set_lfp s f = s"
"mono f ⟹ ¬(f s ⊆ s) ⟹ set_lfp s f = (set_lfp (s ∪ f s) f)"
by (metis set_lfp_tail_rec_def)+
where
"insert_in_list_at_arbitrary_pos x [] = {[x]}"
| "insert_in_list_at_arbitrary_pos x (y # ys) =
insert (x # y # ys) ((λl. y # l) ` (insert_in_list_at_arbitrary_pos x ys))"
lemma :
"xl ∈ insert_in_list_at_arbitrary_pos x l ⟷
(∃l1 l2. l = l1 @ l2 ∧ xl = l1 @ [x] @ l2)"
proof (induct l arbitrary: xl)
case Nil thus ?case by simp
next
case (Cons y l xyl)
note ind_hyp = this
show ?case
proof (rule iffI)
assume xyl_in: "xyl ∈ insert_in_list_at_arbitrary_pos x (y # l)"
show "∃l1 l2. y # l = l1 @ l2 ∧ xyl = l1 @ [x] @ l2"
proof (cases "xyl = x # y # l")
case True
hence "y # l = [] @ (y # l) ∧ xyl = [] @ [x] @ (y # l)" by simp
thus ?thesis by blast
next
case False
with xyl_in have "xyl ∈ (#) y ` insert_in_list_at_arbitrary_pos x l" by simp
with ind_hyp obtain l1 l2 where "l = l1 @ l2 ∧ xyl = y # l1 @ x # l2"
by (auto simp add: image_def Bex_def)
hence "y # l = (y # l1) @ l2 ∧ xyl = (y # l1) @ [x] @ l2" by simp
thus ?thesis by blast
qed
next
assume "∃l1 l2. y # l = l1 @ l2 ∧ xyl = l1 @ [x] @ l2"
then obtain l1 l2 where yl_eq: "y # l = l1 @ l2" and xyl_eq: "xyl = l1 @ [x] @ l2" by blast
show "xyl ∈ insert_in_list_at_arbitrary_pos x (y # l)"
proof (cases l1)
case Nil
with yl_eq xyl_eq
have "xyl = x # y # l" by simp
thus ?thesis by simp
next
case (Cons y' l1')
with yl_eq have l1_eq: "l1 = y # l1'" and l_eq: "l = l1' @ l2" by simp_all
have "∃l1'' l2''. l = l1'' @ l2'' ∧ l1' @ [x] @ l2 = l1'' @ [x] @ l2''"
apply (rule_tac exI[where x = l1'])
apply (rule_tac exI [where x = l2])
apply (simp add: l_eq)
done
hence "(l1' @ [x] @ l2) ∈ insert_in_list_at_arbitrary_pos x l"
unfolding ind_hyp by blast
hence "∃l'. l' ∈ insert_in_list_at_arbitrary_pos x l ∧ l1 @ x # l2 = y # l'"
by (rule_tac exI [where x = "l1' @ [x] @ l2"]) (simp add: l1_eq)
thus ?thesis
by (simp add: image_def Bex_def xyl_eq)
qed
qed
qed
:: "'a set ⇒ ('a list) set" where
"list_of_set_set s = { l . (set l = s) ∧ distinct l }"
lemma [simp]:
"list_of_set_set {} = {[]}"
unfolding list_of_set_set_def by auto
lemma [simp] :
"list_of_set_set (insert x s) =
⋃ ((insert_in_list_at_arbitrary_pos x) ` (list_of_set_set (s - {x})))"
(is "?lhs = ?rhs")
proof (intro set_eqI)
fix l
have "(set l = insert x s ∧ distinct l) ⟷ (∃l1 l2. set (l1 @ l2) = s - {x} ∧ distinct (l1 @ l2) ∧ l = l1 @ x # l2)"
proof (intro iffI)
assume "set l = insert x s ∧ distinct l"
hence set_l_eq: "set l = insert x s" and "distinct l" by simp_all
from ‹set l = insert x s›
have "x ∈ set l" by simp
then obtain l1 l2 where l_eq: "l = l1 @ x # l2"
unfolding in_set_conv_decomp by blast
from ‹distinct l› l_eq
have "distinct (l1 @ l2)" and x_nin: "x ∉ set (l1 @ l2)"
by auto
from x_nin set_l_eq[unfolded l_eq]
have set_l12_eq: "set (l1 @ l2) = s - {x}"
by auto
from ‹distinct (l1 @ l2)› l_eq set_l12_eq
show "∃l1 l2. set (l1 @ l2) = s - {x} ∧ distinct (l1 @ l2) ∧ l = l1 @ x # l2"
by blast
next
assume "∃l1 l2. set (l1 @ l2) = s - {x} ∧ distinct (l1 @ l2) ∧ l = l1 @ x # l2"
then obtain l1 l2 where "set (l1 @ l2) = s - {x}" "distinct (l1 @ l2)" "l = l1 @ x # l2"
by blast
thus "set l = insert x s ∧ distinct l"
by auto
qed
thus "l ∈ list_of_set_set (insert x s) ⟷ l ∈ (⋃ ((insert_in_list_at_arbitrary_pos x) ` (list_of_set_set (s - {x}))))"
unfolding list_of_set_set_def
by (simp add: insert_in_list_at_arbitrary_pos_thm ex_simps[symmetric] del: ex_simps)
qed
lemma [code]:
"list_of_set_set (set []) = {[]}"
"list_of_set_set (set (x # xs)) =
⋃ ((insert_in_list_at_arbitrary_pos x) ` (list_of_set_set ((set xs) - {x})))"
by simp_all
lemma :
"list_of_set_set s = {} ⟷ ¬ (finite s)"
proof -
have "finite s ⟷ (∃l. set l = s ∧ distinct l)"
proof (rule iffI)
assume "∃l. set l = s ∧ distinct l" then
obtain l where "s = set l" by blast
thus "finite s" by simp
next
assume "finite s"
thus "∃l. set l = s ∧ distinct l"
proof (induct s)
case empty
show ?case by auto
next
case (insert e s)
note e_nin_s = insert(2)
from insert(3) obtain l where set_l: "set l = s" and dist_l: "distinct l" by blast
from set_l have set_el: "set (e # l) = insert e s" by auto
from dist_l set_l e_nin_s have dist_el: "distinct (e # l)" by simp
from set_el dist_el show ?case by blast
qed
qed
thus ?thesis
unfolding list_of_set_set_def by simp
qed
:: "'a set ⇒ 'a list" where
"list_of_set s = set_choose (list_of_set_set s)"
lemma [simp] :
assumes fin_s: "finite s"
shows "set (list_of_set s) = s"
"distinct (list_of_set s)"
proof -
from fin_s list_of_set_set_is_empty[of s]
have "¬ (list_of_set_set s = {})" by simp
hence "list_of_set s ∈ list_of_set_set s"
unfolding list_of_set_def
by (rule set_choose_thm)
thus "set (list_of_set s) = s"
"distinct (list_of_set s)" unfolding list_of_set_set_def
by simp_all
qed
lemma :
"finite s ⟹ list_of_set s ∈ list_of_set_set s"
unfolding list_of_set_def
by (metis list_of_set_set_is_empty set_choose_thm)
where
"ordered_list_of_set cmp s = set_choose (sort_by cmp ` list_of_set_set s)"
subsection ‹sum›
find_consts "'a list => ('a list * _)"
:: "('a + 'b) list ⇒ 'a list * 'b list" where
"sum_partition [] = ([], [])"
| "sum_partition ((Inl l) # lrs) =
(let (ll, rl) = sum_partition lrs in
(l # ll, rl))"
| "sum_partition ((Inr r) # lrs) =
(let (ll, rl) = sum_partition lrs in
(ll, r # rl))"
lemma :
"List.length lrs = List.length (fst (sum_partition lrs)) + List.length (snd (sum_partition lrs))"
proof (induct lrs)
case Nil thus ?case by simp
next
case (Cons lr lrs) thus ?case
by (cases lr) (auto split: prod.split)
qed
subsection ‹sorting›
subsection ‹Strings›
declare String.literal.explode_inverse [simp]
subsection ‹num to string conversions›
:: "nat list ⇒ string" where
"nat_list_to_string nl = map char_of nl"
where
"is_digit (n::nat) = (n < 10)"
lemma [simp] :
"n < 10 ⟹ is_digit n"
"¬(n < 10) ⟹ ¬(is_digit n)"
unfolding is_digit_def by simp_all
lemma is_digit_expand :
"is_digit n ⟷
(n = 0) ∨ (n = 1) ∨ (n = 2) ∨ (n = 3) ∨ (n = 4) ∨
(n = 5) ∨ (n = 6) ∨ (n = 7) ∨ (n = 8) ∨ (n = 9)"
unfolding is_digit_def by auto
lemmas = is_digit_expand[THEN iffD1,elim_format]
lemmas = is_digit_expand[THEN iffD2,rule_format]
where
"is_digit_char c ⟷
(c = CHR ''0'') ∨ (c = CHR ''5'') ∨
(c = CHR ''1'') ∨ (c = CHR ''6'') ∨
(c = CHR ''2'') ∨ (c = CHR ''7'') ∨
(c = CHR ''3'') ∨ (c = CHR ''8'') ∨
(c = CHR ''4'') ∨ (c = CHR ''9'')"
lemma [simp] :
"is_digit_char (CHR ''0'')"
"is_digit_char (CHR ''1'')"
"is_digit_char (CHR ''2'')"
"is_digit_char (CHR ''3'')"
"is_digit_char (CHR ''4'')"
"is_digit_char (CHR ''5'')"
"is_digit_char (CHR ''6'')"
"is_digit_char (CHR ''7'')"
"is_digit_char (CHR ''8'')"
"is_digit_char (CHR ''9'')"
unfolding is_digit_char_def by simp_all
lemmas = is_digit_char_def[THEN iffD1,elim_format]
lemmas = is_digit_char_def[THEN iffD2,rule_format]
:: "nat ⇒ char" where
"digit_to_char n = (
if n = 0 then CHR ''0''
else if n = 1 then CHR ''1''
else if n = 2 then CHR ''2''
else if n = 3 then CHR ''3''
else if n = 4 then CHR ''4''
else if n = 5 then CHR ''5''
else if n = 6 then CHR ''6''
else if n = 7 then CHR ''7''
else if n = 8 then CHR ''8''
else if n = 9 then CHR ''9''
else CHR ''X'')"
lemma [simp]:
"digit_to_char 0 = CHR ''0''"
"digit_to_char (Suc 0) = CHR ''1''"
"digit_to_char 2 = CHR ''2''"
"digit_to_char 3 = CHR ''3''"
"digit_to_char 4 = CHR ''4''"
"digit_to_char 5 = CHR ''5''"
"digit_to_char 6 = CHR ''6''"
"digit_to_char 7 = CHR ''7''"
"digit_to_char 8 = CHR ''8''"
"digit_to_char 9 = CHR ''9''"
"n > 9 ⟹ digit_to_char n = CHR ''X''"
unfolding digit_to_char_def
by simp_all
:: "char ⇒ nat" where
"char_to_digit c = (
if c = CHR ''0'' then 0
else if c = CHR ''1'' then 1
else if c = CHR ''2'' then 2
else if c = CHR ''3'' then 3
else if c = CHR ''4'' then 4
else if c = CHR ''5'' then 5
else if c = CHR ''6'' then 6
else if c = CHR ''7'' then 7
else if c = CHR ''8'' then 8
else if c = CHR ''9'' then 9
else 10)"
lemma [simp]:
"char_to_digit (CHR ''0'') = 0"
"char_to_digit (CHR ''1'') = 1"
"char_to_digit (CHR ''2'') = 2"
"char_to_digit (CHR ''3'') = 3"
"char_to_digit (CHR ''4'') = 4"
"char_to_digit (CHR ''5'') = 5"
"char_to_digit (CHR ''6'') = 6"
"char_to_digit (CHR ''7'') = 7"
"char_to_digit (CHR ''8'') = 8"
"char_to_digit (CHR ''9'') = 9"
unfolding char_to_digit_def by simp_all
lemma [simp]:
assumes is_digit: "is_digit n"
shows "char_to_digit (digit_to_char n) = n"
using is_digit unfolding is_digit_expand by auto
lemma [simp]:
assumes is_digit: "is_digit_char c"
shows "digit_to_char (char_to_digit c) = c"
using is_digit
unfolding char_to_digit_def is_digit_char_def
by auto
lemma [simp]:
assumes is_digit: "is_digit_char c"
shows "char_to_digit c < 10"
using is_digit
unfolding char_to_digit_def is_digit_char_def
by auto
lemma [simp]:
"is_digit (char_to_digit c) = is_digit_char c"
unfolding char_to_digit_def is_digit_char_def is_digit_expand
by auto
lemma [simp]:
"is_digit_char (digit_to_char n) = is_digit n"
unfolding digit_to_char_def is_digit_char_def is_digit_expand
by auto
lemma :
"digit_to_char n1 = digit_to_char n2 ⟹
(is_digit n1 = is_digit n2) ∧ (is_digit n1 ⟶ (n1 = n2))"
by (metis diget_to_char_inv is_digit_intro)
lemma :
"char_to_digit c1 = char_to_digit c2 ⟹
(is_digit_char c1 = is_digit_char c2) ∧ (is_digit_char c1 ⟶ (c1 = c2))"
by (metis char_to_diget_inv is_digit_char_intro)
:: "nat ⇒ string" where
"nat_to_string n =
(if (is_digit n) then [digit_to_char n] else
nat_to_string (n div 10) @ [digit_to_char (n mod 10)])"
by auto
by (relation "measure id") (auto simp add: is_digit_def)
:: "int ⇒ string" where
"int_to_string i ≡
if i < 0 then
''-'' @ nat_to_string (nat (abs i))
else
nat_to_string (nat i)"
lemma [simp]:
"is_digit n ⟹ nat_to_string n = [digit_to_char n]"
"¬(is_digit n) ⟹ nat_to_string n = nat_to_string (n div 10) @ [digit_to_char (n mod 10)]"
by simp_all
declare nat_to_string.simps[simp del]
lemma [simp]:
"nat_to_string n ≠ []"
by (cases "is_digit n") simp_all
lemmas [simp] = nat_to_string_neq_nil[symmetric]
lemma [simp]:
"is_digit_char c ⟹ nat_to_string (char_to_digit c) = [c]"
by auto
lemma [simp] :
"(nat_to_string n1 = nat_to_string n2) ⟷ n1 = n2"
proof (rule iffI)
assume "n1 = n2"
thus "nat_to_string n1 = nat_to_string n2" by simp
next
assume "nat_to_string n1 = nat_to_string n2"
thus "n1 = n2"
proof (induct n2 arbitrary: n1 rule: less_induct)
case (less n2')
note ind_hyp = this(1)
note n2s_eq = less(2)
have is_dig_eq: "is_digit n2' = is_digit n1" using n2s_eq
apply (cases "is_digit n2'")
apply (case_tac [!] "is_digit n1")
apply (simp_all)
done
show ?case
proof (cases "is_digit n2'")
case True with n2s_eq is_dig_eq show ?thesis by simp (metis digit_to_char_11)
next
case False
with is_dig_eq have not_digs : "¬ (is_digit n1)" "¬ (is_digit n2')" by simp_all
from not_digs(2) have "n2' div 10 < n2'" unfolding is_digit_def by auto
note ind_hyp' = ind_hyp [OF this, of "n1 div 10"]
from not_digs n2s_eq ind_hyp' digit_to_char_11[of "n1 mod 10" "n2' mod 10"]
have "(n1 mod 10) = (n2' mod 10)" "n1 div 10 = n2' div 10" by simp_all
thus "n1 = n2'" by (metis div_mult_mod_eq)
qed
qed
qed
" s ≡ (∀c∈set s. is_digit_char c)"
" s ≡ is_nat_string s ∧ (s ≠ []) ∧ (hd s = CHR ''0'' ⟶ length s = 1)"
lemma [simp]:
"is_nat_string []"
"is_nat_string (c # s) ⟷ is_digit_char c ∧ is_nat_string s"
unfolding is_nat_string_def by simp_all
lemma [simp]:
"¬(is_strong_nat_string [])"
"is_strong_nat_string (c # s) ⟷ is_digit_char c ∧ is_nat_string s ∧
(c = CHR ''0'' ⟶ s = [])"
unfolding is_strong_nat_string_def by simp_all
:: "nat ⇒ string ⇒ nat" where
"string_to_nat_aux n [] = n"
| "string_to_nat_aux n (d#ds) =
string_to_nat_aux (n*10 + char_to_digit d) ds"
:: "string ⇒ nat option" where
"string_to_nat s ≡
(if is_nat_string s then Some (string_to_nat_aux 0 s) else None)"
:: "string ⇒ nat" where
"string_to_nat' s ≡ the (string_to_nat s)"
lemma :
assumes "is_nat_string s"
assumes "n > 0 ∨ is_strong_nat_string s"
shows "nat_to_string (string_to_nat_aux n s) =
(if n = 0 then '''' else nat_to_string n) @ s"
using assms
proof (induct s arbitrary: n)
case Nil
thus ?case
by (simp add: is_strong_nat_string_def)
next
case (Cons c s n)
from Cons(2) have "is_digit_char c" "is_nat_string s" by simp_all
note cs_ok = Cons(3)
let ?m = "n*10 + char_to_digit c"
note ind_hyp = Cons(1)[OF ‹is_nat_string s›, of ?m]
from ‹is_digit_char c› have m_div: "?m div 10 = n" and
m_mod: "?m mod 10 = char_to_digit c"
unfolding is_digit_char_def
by auto
show ?case
proof (cases "?m = 0")
case True
with ‹is_digit_char c›
have "n = 0" "c = CHR ''0''" unfolding is_digit_char_def by auto
moreover with cs_ok have "s = []" by simp
ultimately show ?thesis by simp
next
case False note m_neq_0 = this
with ind_hyp have ind_hyp':
"nat_to_string (string_to_nat_aux ?m s) = (nat_to_string ?m) @ s" by auto
hence "nat_to_string (string_to_nat_aux n (c # s)) = (nat_to_string ?m) @ s"
by simp
with ‹is_digit_char c› m_div show ?thesis by simp
qed
qed
lemma :
assumes strong_nat_s: "is_strong_nat_string s"
assumes s2n_s: "string_to_nat s = Some n"
shows "nat_to_string n = s"
proof -
from strong_nat_s have nat_s: "is_nat_string s" unfolding is_strong_nat_string_def by simp
with s2n_s have n_eq: "n = string_to_nat_aux 0 s" unfolding string_to_nat_def by simp
from string_to_nat_aux_inv[of s 0, folded n_eq] nat_s strong_nat_s
show ?thesis by simp
qed
lemma [case_names "digit" "non_digit"]:
assumes digit: "⋀d. is_digit d ⟹ P d"
assumes not_digit: "⋀n. ¬(is_digit n) ⟹ P (n div 10) ⟹ P (n mod 10) ⟹ P n"
shows "P n"
proof (induct n rule: less_induct)
case (less n)
note ind_hyp = this
show ?case
proof (cases "is_digit n")
case True with digit show ?thesis by simp
next
case False note not_dig = this
hence "n div 10 < n" "n mod 10 < n" unfolding is_digit_def by auto
with not_dig ind_hyp not_digit show ?thesis by simp
qed
qed
lemma [simp]:
"is_nat_string (nat_to_string n)"
unfolding is_nat_string_def
proof (induct n rule: nat_to_string_induct)
case (digit d)
thus ?case by simp
next
case (non_digit n)
thus ?case by simp
qed
lemma [simp]:
"(nat_to_string n = (CHR ''0'')#s) ⟷ (n = 0 ∧ s = [])"
unfolding is_nat_string_def
proof (induct n arbitrary: s rule: nat_to_string_induct)
case (digit d) thus ?case unfolding is_digit_expand by auto
next
case (non_digit n)
obtain c s' where ns_eq: "nat_to_string (n div 10) = c # s'"
by (cases "nat_to_string (n div 10)") auto
from non_digit(1) have "n div 10 ≠ 0" unfolding is_digit_def by auto
with non_digit(2) ns_eq have c_neq: "c ≠ CHR ''0''" by auto
from ‹¬ (is_digit n)› c_neq ns_eq
show ?case by auto
qed
lemma :
"is_strong_nat_string (nat_to_string n)"
proof (cases "is_digit n")
case True thus ?thesis by simp
next
case False note not_digit = this
obtain c s' where ns_eq: "nat_to_string n = c # s'"
by (cases "nat_to_string n") auto
from not_digit have "0 < n" unfolding is_digit_def by simp
with ns_eq have c_neq: "c ≠ CHR ''0''" by auto
hence "hd (nat_to_string n) ≠ CHR ''0''" unfolding ns_eq by simp
thus ?thesis unfolding is_strong_nat_string_def
by simp
qed
lemma :
"string_to_nat (nat_to_string n) = Some n"
by (metis nat_to_string_11
nat_to_string___is_nat_string
nat_to_string___is_strong_nat_string
string_to_nat_def
string_to_nat_inv)
where
"The_opt p = (if (∃!x. p x) then Some (The p) else None)"
lemma [simp] :
"((The_opt p) = (Some x)) ⟷ ((p x) ∧ ((∀ y. p y ⟶ (x = y))))"
(is "?lhs = ?rhs")
proof (cases "∃!x. p x")
case True
note exists_unique = this
then obtain x where p_x: "p x" by auto
from the1_equality[of p x] exists_unique p_x
have the_opt_eq: "The_opt p = Some x"
unfolding The_opt_def by simp
from exists_unique the_opt_eq p_x show ?thesis
by auto
next
case False
note not_unique = this
hence "The_opt p = None"
unfolding The_opt_def by simp
with not_unique show ?thesis by auto
qed
lemma [simp] :
"((The_opt p) = None) ⟷ ¬(∃!x. p x)"
unfolding The_opt_def by auto
end