Theory Arrays_Ex
section ‹Arrays›
theory Arrays_Ex
imports "Auto2_HOL.Auto2_Main"
begin
text ‹Basic examples for arrays.›
subsection ‹List swap›
definition list_swap :: "'a list ⇒ nat ⇒ nat ⇒ 'a list" where [rewrite]:
"list_swap xs i j = xs[i := xs ! j, j := xs ! i]"
setup ‹register_wellform_data ("list_swap xs i j", ["i < length xs", "j < length xs"])›
setup ‹add_prfstep_check_req ("list_swap xs i j", "i < length xs ∧ j < length xs")›
lemma list_swap_eval:
"i < length xs ⟹ j < length xs ⟹
(list_swap xs i j) ! k = (if k = i then xs ! j else if k = j then xs ! i else xs ! k)" by auto2
setup ‹add_rewrite_rule_cond @{thm list_swap_eval} [with_cond "?k ≠ ?i", with_cond "?k ≠ ?j"]›
lemma list_swap_eval_triv [rewrite]:
"i < length xs ⟹ j < length xs ⟹ (list_swap xs i j) ! i = xs ! j"
"i < length xs ⟹ j < length xs ⟹ (list_swap xs i j) ! j = xs ! i" by auto2+
lemma length_list_swap [rewrite_arg]:
"length (list_swap xs i j) = length xs" by auto2
lemma mset_list_swap [rewrite]:
"i < length xs ⟹ j < length xs ⟹ mset (list_swap xs i j) = mset xs" by auto2
lemma set_list_swap [rewrite]:
"i < length xs ⟹ j < length xs ⟹ set (list_swap xs i j) = set xs" by auto2
setup ‹del_prfstep_thm @{thm list_swap_def}›
setup ‹add_rewrite_rule_back @{thm list_swap_def}›
subsection ‹Reverse›
lemma rev_nth [rewrite]:
"n < length xs ⟹ rev xs ! n = xs ! (length xs - 1 - n)"
@proof @induct xs @qed
fun rev_swap :: "'a list ⇒ nat ⇒ nat ⇒ 'a list" where
"rev_swap xs i j = (if i < j then rev_swap (list_swap xs i j) (i + 1) (j - 1) else xs)"
setup ‹register_wellform_data ("rev_swap xs i j", ["j < length xs"])›
setup ‹add_prfstep_check_req ("rev_swap xs i j", "j < length xs")›
lemma rev_swap_length [rewrite_arg]:
"j < length xs ⟹ length (rev_swap xs i j) = length xs"
@proof @fun_induct "rev_swap xs i j" @unfold "rev_swap xs i j" @qed
lemma rev_swap_eval [rewrite]:
"j < length xs ⟹ (rev_swap xs i j) ! k =
(if k < i then xs ! k else if k > j then xs ! k else xs ! (j - (k - i)))"
@proof @fun_induct "rev_swap xs i j" @unfold "rev_swap xs i j"
@case "i < j" @with
@case "k < i" @case "k > j" @have "j - (k - i) = j - k + i"
@end
@qed
lemma rev_swap_is_rev [rewrite]:
"length xs ≥ 1 ⟹ rev_swap xs 0 (length xs - 1) = rev xs" by auto2
subsection ‹Copy one array to the beginning of another›
fun array_copy :: "'a list ⇒ 'a list ⇒ nat ⇒ 'a list" where
"array_copy xs xs' 0 = xs'"
| "array_copy xs xs' (Suc n) = list_update (array_copy xs xs' n) n (xs ! n)"
setup ‹fold add_rewrite_rule @{thms array_copy.simps}›
setup ‹register_wellform_data ("array_copy xs xs' n", ["n ≤ length xs", "n ≤ length xs'"])›
setup ‹add_prfstep_check_req ("array_copy xs xs' n", "n ≤ length xs ∧ n ≤ length xs'")›
lemma array_copy_length [rewrite_arg]:
"n ≤ length xs ⟹ n ≤ length xs' ⟹ length (array_copy xs xs' n) = length xs'"
@proof @induct n @qed
lemma array_copy_ind [rewrite]:
"n ≤ length xs ⟹ n ≤ length xs' ⟹ k < n ⟹ (array_copy xs xs' n) ! k = xs ! k"
@proof @induct n @qed
lemma array_copy_correct [rewrite]:
"n ≤ length xs ⟹ n ≤ length xs' ⟹ take n (array_copy xs xs' n) = take n xs" by auto2
subsection ‹Sublist›
definition sublist :: "nat ⇒ nat ⇒ 'a list ⇒ 'a list" where [rewrite]:
"sublist l r xs = drop l (take r xs)"
setup ‹register_wellform_data ("sublist l r xs", ["l ≤ r", "r ≤ length xs"])›
setup ‹add_prfstep_check_req ("sublist l r xs", "l ≤ r ∧ r ≤ length xs")›
lemma length_sublist [rewrite_arg]:
"r ≤ length xs ⟹ length (sublist l r xs) = r - l" by auto2
lemma nth_sublist [rewrite]:
"r ≤ length xs ⟹ xs' = sublist l r xs ⟹ i < length xs' ⟹ xs' ! i = xs ! (i + l)" by auto2
lemma sublist_nil [rewrite]:
"r ≤ length xs ⟹ r ≤ l ⟹ sublist l r xs = []" by auto2
lemma sublist_0 [rewrite]:
"sublist 0 l xs = take l xs" by auto2
lemma sublist_drop [rewrite]:
"sublist l r (drop n xs) = sublist (l + n) (r + n) xs" by auto2
setup ‹del_prfstep_thm @{thm sublist_def}›
lemma sublist_single [rewrite]:
"l + 1 ≤ length xs ⟹ sublist l (l + 1) xs = [xs ! l]"
@proof @have "length [xs ! l] = 1" @qed
lemma sublist_append [rewrite]:
"l ≤ m ⟹ m ≤ r ⟹ r ≤ length xs ⟹ sublist l m xs @ sublist m r xs = sublist l r xs"
@proof
@let "xs1 = sublist l r xs" "xs2 = sublist l m xs" "xs3 = sublist m r xs"
@have "length (xs2 @ xs3) = (r - m) + (m - l)"
@have "∀i<length xs1. xs1 ! i = (xs2 @ xs3) ! i" @with
@case "i < length xs2"
@have "i - length xs2 < length xs3"
@end
@qed
lemma sublist_Cons [rewrite]:
"r ≤ length xs ⟹ l < r ⟹ xs ! l # sublist (l + 1) r xs = sublist l r xs"
@proof
@have "sublist l r xs = sublist l (l + 1) xs @ sublist (l + 1) r xs"
@qed
lemma sublist_equalityI:
"i ≤ j ⟹ j ≤ length xs ⟹ length xs = length ys ⟹
∀k. i ≤ k ⟶ k < j ⟶ xs ! k = ys ! k ⟹ sublist i j xs = sublist i j ys" by auto2
setup ‹add_backward2_prfstep_cond @{thm sublist_equalityI} [with_filt (order_filter "xs" "ys")]›
lemma set_sublist [resolve]:
"j ≤ length xs ⟹ x ∈ set (sublist i j xs) ⟹ ∃k. k ≥ i ∧ k < j ∧ x = xs ! k"
@proof
@let "xs' = sublist i j xs"
@obtain l where "l < length xs'" "xs' ! l = x"
@qed
lemma list_take_sublist_drop_eq [rewrite]:
"l ≤ r ⟹ r ≤ length xs ⟹ take l xs @ sublist l r xs @ drop r xs = xs"
@proof
@have "take l xs = sublist 0 l xs"
@have "drop r xs = sublist r (length xs) xs"
@qed
subsection ‹Updating a set of elements in an array›
definition list_update_set :: "(nat ⇒ bool) ⇒ (nat ⇒ 'a) ⇒ 'a list ⇒ 'a list" where [rewrite]:
"list_update_set S f xs = list (λi. if S i then f i else xs ! i) (length xs)"
lemma list_update_set_length [rewrite_arg]:
"length (list_update_set S f xs) = length xs" by auto2
lemma list_update_set_nth [rewrite]:
"xs' = list_update_set S f xs ⟹ i < length xs' ⟹ xs' ! i = (if S i then f i else xs ! i)" by auto2
setup ‹del_prfstep_thm @{thm list_update_set_def}›
fun list_update_set_impl :: "(nat ⇒ bool) ⇒ (nat ⇒ 'a) ⇒ 'a list ⇒ nat ⇒ 'a list" where
"list_update_set_impl S f xs 0 = xs"
| "list_update_set_impl S f xs (Suc k) =
(let xs' = list_update_set_impl S f xs k in
if S k then xs' [k := f k] else xs')"
setup ‹fold add_rewrite_rule @{thms list_update_set_impl.simps}›
setup ‹register_wellform_data ("list_update_set_impl S f xs n", ["n ≤ length xs"])›
lemma list_update_set_impl_ind [rewrite]:
"n ≤ length xs ⟹ list_update_set_impl S f xs n =
list (λi. if i < n then if S i then f i else xs ! i else xs ! i) (length xs)"
@proof @induct n arbitrary xs @qed
lemma list_update_set_impl_correct [rewrite]:
"list_update_set_impl S f xs (length xs) = list_update_set S f xs" by auto2
end