Theory Simple_SACA_Verification
theory Simple_SACA_Verification
imports
"Simple_SACA"
"../spec/Suffix_Array"
begin
lemma suf_length_app:
"i < length xs ⟹ length (suffix (xs @ ys) i) = length (suffix xs i) + length ys"
apply (induct xs)
apply simp
apply simp
done
lemma distinct_natlist_add:
"distinct (xs :: nat list) ⟹ distinct (map ((+) n) xs)"
apply (induct xs arbitrary: n)
apply simp
apply clarsimp
done
lemma nat_minus_cancel_right:
"⟦(x::nat) ≤ n; y ≤ n; n - x = n - y⟧ ⟹ x = y"
apply (subst (asm) le_imp_diff_is_add, simp)
apply (subst (asm) add.commute)
apply (subst (asm) add_diff_assoc, simp)
apply (subst (asm) add.commute)
apply (drule sym)
apply (subst (asm) Nat.le_imp_diff_is_add, simp)
apply clarsimp
done
lemma distinct_natlist_sub:
"⟦distinct (xs :: nat list); ∀x ∈ set xs. x ≤ n⟧ ⟹ distinct (map ((-) n) xs)"
by (meson distinct_map inj_onI nat_minus_cancel_right)
lemma map_suf_app:
"n ≤ length xs ⟹
map (length ∘ suffix (xs @ ys)) [0..<n] = map ((+) (length ys)) (map (length ∘ (suffix xs)) [0..<n])"
apply (induct xs)
apply simp
apply clarsimp
apply (subst add.commute)
apply simp
done
lemma distinct_map_length_gen_suffixes:
"distinct (map length (gen_suffixes s))"
apply (induct s rule: rev_induct)
apply simp
apply (simp only: gen_suffixes.simps map_map length_append)
apply (subst upt_add_eq_append; simp only: map_append)
apply (subst map_suf_app; simp only: distinct_append)
apply (rule conjI)
apply (rule distinct_natlist_add; simp)
apply (rule conjI; clarsimp)
done
lemma different_length_different_list:
"length a ∉ length ` set xs ⟹ a ∉ set xs"
apply blast
done
lemma distinct_map_length_sort:
"distinct (map length xs) ⟹ distinct (map length (sort xs))"
apply (induct xs)
apply simp
apply clarsimp
apply (rule card_distinct)
apply simp
apply (drule distinct_card)
apply clarsimp
apply (frule different_length_different_list)
apply (subst insort_insert_insort[symmetric]; simp)
apply (subst set_insort_insert)
apply simp
done
lemma suffix_ids_def':
"suffix_ids s xs = map (((-) (length s)) ∘ length) xs"
apply simp
done
lemma distinct_simple_saca:
"distinct (simple_saca s)"
apply (subst simple_saca.simps)
apply (subst suffix_ids_def')
apply (subst map_map[symmetric])
apply (rule distinct_natlist_sub)
apply (rule distinct_map_length_sort[OF distinct_map_length_gen_suffixes])
apply clarsimp
done
lemma suf_suffix_id_suf:
"i < length s ⟹ suffix s (length s - length (suffix s i)) = suffix s i"
apply (induct s arbitrary: i)
apply simp
apply clarsimp
done
lemma in_set_ordlist_sort:
"(x ∈ set xs) = (x ∈ set (sort xs))"
by simp
lemma ordlist_sort_conv_nth:
"(∃i<length xs. xs ! i = x) = (∃i<length xs. (sort xs) ! i = x)"
by (metis in_set_conv_nth length_sort set_sort)
lemma ordlist_sort_nth_before:
"⟦i < length xs; (sort xs) ! i = x⟧ ⟹
∃j<length xs. xs ! j = x"
apply (subst ordlist_sort_conv_nth)
apply blast
done
lemma suf_sort_suf_nth:
"i < length s ⟹
suffix s (length s - length ((sort (gen_suffixes s)) ! i)) =
sort (gen_suffixes s) ! i"
proof -
assume "i < length s"
have "∃x. sort (gen_suffixes s) ! i = x"
by blast
then obtain x where
"sort (gen_suffixes s) ! i = x"
by blast
with ordlist_sort_nth_before[of i "gen_suffixes s" x]
have "∃j<length (gen_suffixes s). gen_suffixes s ! j = x"
by (simp add: ‹i < length s›)
then obtain j where
"j < length (gen_suffixes s)"
"gen_suffixes s ! j = x"
by blast
hence "sort (gen_suffixes s) ! i = gen_suffixes s ! j"
using ‹sort (gen_suffixes s) ! i = x› by blast
moreover
have "j < length s"
using ‹j < length (gen_suffixes s)› by auto
hence "gen_suffixes s ! j = suffix s j"
by simp
ultimately show ?thesis
by (metis ‹j < length s› suf_suffix_id_suf)
qed
lemma map_suf_simple_saca:
"map (suffix s) (simple_saca s) = sort (gen_suffixes s)"
apply (simp only: simple_saca.simps suffix_ids.simps)
apply (subst list_eq_iff_nth_eq)
apply (rule conjI)
apply simp
apply (clarsimp simp del: gen_suffixes.simps)
apply (rule suf_sort_suf_nth; simp)
done
interpretation simple_saca: Suffix_Array_General simple_saca
proof
fix s :: "('a :: {linorder, order_bot}) list"
show "simple_saca s <~~> [0..<length s]"
proof -
have "set (simple_saca s) = {0..<length s}"
by force
with perm_distinct_set_of_upt_iff[THEN iffD2, OF conjI, OF distinct_simple_saca]
show ?thesis
by blast
qed
show "strict_sorted (map (suffix s) (simple_saca s))"
proof -
from `simple_saca s <~~> [0..<length s]`
have "set (simple_saca s) = {0..<length s}"
using perm_distinct_set_of_upt_iff by blast
hence "∀x ∈ set (simple_saca s). x < length s"
using atLeastLessThan_iff by blast
with distinct_simple_saca distinct_suffixes
have "distinct (map (suffix s) (simple_saca s))"
by blast
have "sorted (map (suffix s) (simple_saca s))"
by (metis map_suf_simple_saca sorted_sort)
with `distinct (map (suffix s) (simple_saca s))` show ?thesis
using strict_sorted_iff by blast
qed
qed
end