Theory LMS_List_Slice_Util
theory LMS_List_Slice_Util
imports List_Type
begin
section ‹Helpers›
lemma filter_abs_is_lms_upt_0:
"filter (abs_is_lms xs) [0..<n] = filter (abs_is_lms xs) [Suc 0..<n]"
by (metis filter.simps(2) abs_is_lms_0 tl_upt upt_0 upt_rec)
lemma filter_abs_is_lms_upt_hd:
"⟦abs_is_lms xs i; i < n⟧ ⟹
filter (abs_is_lms xs) [i..<n] = i # filter (abs_is_lms xs) [Suc i..<n]"
by (metis filter.simps(2) upt_rec)
section ‹LMS Slice›
subsection ‹Find the next LMS position›
fun
abs_find_index' :: "('a ⇒ bool) ⇒ 'a list ⇒ nat ⇒ nat"
where
"abs_find_index' P xs i =
(case xs of
[] ⇒ i
| x#xs' ⇒
(if P x
then i
else abs_find_index' P xs' (Suc i)))"
definition
abs_find_next_lms :: "('a :: {linorder, order_bot}) list ⇒ nat ⇒ nat"
where
"abs_find_next_lms T i =
(case find (λj. abs_is_lms T j) [Suc i..<length T] of
Some j ⇒ j
| _ ⇒ length T)"
lemma abs_find_next_lms_le_length:
"abs_find_next_lms T i ≤ length T"
unfolding abs_find_next_lms_def
apply (clarsimp split: option.split)
by (metis find_Some_iff abs_is_lms_gre_length not_less order.order_iff_strict)
lemma abs_find_next_lms_abs_is_lms:
"abs_is_lms T (Suc i) ⟹ abs_find_next_lms T i = Suc i"
unfolding abs_find_next_lms_def
apply (frule abs_is_lms_imp_less_length)
apply (clarsimp split: option.split simp: upt_rec)
done
lemma Suc_not_lms_imp_abs_find_next_eq_Suc:
"¬ abs_is_lms T (Suc i) ⟹ abs_find_next_lms T i = abs_find_next_lms T (Suc i)"
unfolding abs_find_next_lms_def
by (simp add: upt_rec)
lemma abs_find_next_lms_lower_bound_1:
"i < length T ⟹ i < abs_find_next_lms T i"
unfolding abs_find_next_lms_def
apply (clarsimp split: option.split)
using findSomeD by fastforce
lemma abs_find_next_lms_lower_bound_2:
"length T ≤ i ⟹ length T ≤ abs_find_next_lms T i"
unfolding abs_find_next_lms_def
by (clarsimp split: option.split)
lemma abs_find_next_lms_le_Suc:
"abs_find_next_lms T i ≤ abs_find_next_lms T (Suc i)"
apply (cases "Suc i < length T")
apply (metis find.simps(2) abs_find_next_lms_def abs_find_next_lms_abs_is_lms abs_find_next_lms_lower_bound_1
le_less upt_rec)
by (simp add: abs_find_next_lms_def)
lemma no_lms_between_i_and_next:
"⟦i < k; k < abs_find_next_lms T i⟧ ⟹ ¬abs_is_lms T k"
unfolding abs_find_next_lms_def
apply (clarsimp split: option.splits)
apply (drule findNoneD)
apply (erule ballE[of _ _ k])
apply blast
apply simp
apply (drule find_Some_iff[THEN iffD1])
apply clarsimp
apply (erule allE[of _ "k - Suc i"])
apply clarsimp
done
lemma abs_find_next_lms_less_length_abs_is_lms:
"abs_find_next_lms T i < length T ⟹
abs_is_lms T (abs_find_next_lms T i)"
unfolding abs_find_next_lms_def
apply (clarsimp split: option.splits)
apply (drule find_Some_iff[THEN iffD1])
apply clarsimp
done
lemma abs_find_next_lms_strict_upper_imp_lower_bound:
"abs_find_next_lms T i < length T ⟹
i < abs_find_next_lms T i"
unfolding abs_find_next_lms_def
apply (clarsimp split: option.splits)
using findSomeD by fastforce
lemma abs_find_next_lms_suffix:
assumes "i ≤ length T"
shows "abs_find_next_lms T i =
i + abs_find_next_lms (suffix T i) 0"
proof -
from abs_is_lms_i_gr_0[of _ i T] no_lms_between_i_and_next[of i _ T]
have P: "⋀k. ⟦0 < k; k < abs_find_next_lms T i - i⟧ ⟹ ¬abs_is_lms (suffix T i) k"
by (meson less_add_same_cancel2 less_diff_conv)
have "abs_find_next_lms T i = length T ∨ abs_find_next_lms T i < length T"
using abs_find_next_lms_le_length le_neq_implies_less by blast
moreover
have "abs_find_next_lms T i = length T ⟹ ?thesis"
proof -
assume "abs_find_next_lms T i = length T"
hence "⋀k. ⟦0 < k; k < length T - i⟧ ⟹ ¬abs_is_lms (suffix T i) k"
using P by presburger
hence "abs_find_next_lms (suffix T i) 0 = length T - i"
by (metis abs_find_next_lms_le_length abs_find_next_lms_less_length_abs_is_lms
abs_find_next_lms_strict_upper_imp_lower_bound le_neq_implies_less length_drop)
then show ?thesis
by (simp add: ‹abs_find_next_lms T i = length T› assms)
qed
moreover
have "abs_find_next_lms T i < length T ⟹ ?thesis"
proof -
assume "abs_find_next_lms T i < length T"
hence "abs_is_lms T (abs_find_next_lms T i)"
using abs_find_next_lms_less_length_abs_is_lms by blast
hence "abs_is_lms (suffix T i) (abs_find_next_lms T i - i)"
by (simp add: abs_is_lms_i_gr_0 ‹abs_find_next_lms T i < length T›
abs_find_next_lms_strict_upper_imp_lower_bound less_or_eq_imp_le)
with P
show ?thesis
by (metis add.commute abs_find_next_lms_le_length abs_find_next_lms_less_length_abs_is_lms
abs_find_next_lms_strict_upper_imp_lower_bound abs_is_lms_imp_less_length
le_neq_implies_less length_drop less_or_eq_imp_le nat_neq_iff
no_lms_between_i_and_next ordered_cancel_comm_monoid_diff_class.diff_add
zero_less_diff)
qed
ultimately show ?thesis
by blast
qed
lemma abs_find_next_lms_cons_Suc:
assumes "i ≤ length xs"
shows "abs_find_next_lms (x # xs) (Suc i) =
Suc (abs_find_next_lms xs i)"
proof -
have "abs_find_next_lms xs i = length xs ∨ abs_find_next_lms xs i < length xs"
using abs_find_next_lms_le_length le_neq_implies_less by blast
moreover
have "abs_find_next_lms xs i = length xs ⟹ ?thesis"
by (metis Suc_le_mono add.assoc assms drop_Suc_Cons
abs_find_next_lms_suffix length_Cons plus_1_eq_Suc)
moreover
have "abs_find_next_lms xs i < length xs ⟹ ?thesis"
by (metis (no_types, lifting) Suc_le_mono add.assoc length_Cons
assms drop_Suc_Cons abs_find_next_lms_suffix plus_1_eq_Suc)
ultimately show ?thesis
by blast
qed
lemma abs_find_next_lms_funpow_Suc:
"((abs_find_next_lms T)^^(Suc k)) i =
abs_find_next_lms T (((abs_find_next_lms T)^^k) i)"
by simp
lemma abs_find_next_lms_funpow_le:
"i < length T ⟹
((abs_find_next_lms T)^^k) i ≤
((abs_find_next_lms T)^^(Suc k)) i"
apply (induct k; clarsimp)
apply (simp add: abs_find_next_lms_lower_bound_1 less_or_eq_imp_le)
by (simp add: abs_find_next_lms_le_Suc lift_Suc_mono_le)
lemma no_lms_between_i_and_next_funpow:
"⟦((abs_find_next_lms T)^^k) i <
((abs_find_next_lms T)^^(Suc k)) i;
((abs_find_next_lms T)^^k) i < j;
j < ((abs_find_next_lms T)^^(Suc k)) i⟧ ⟹
¬ abs_is_lms T j"
by (simp add: no_lms_between_i_and_next)
lemma abs_find_next_lms_eq_Suc:
"xs ≠ [] ⟹ ∃k. abs_find_next_lms xs i = Suc k"
by (metis abs_find_next_lms_less_length_abs_is_lms
abs_is_lms_0 length_greater_0_conv not0_implies_Suc)
lemma filter_no_lms1:
"⟦abs_is_lms xs i; i < k; k ≤ abs_find_next_lms xs i⟧ ⟹
filter (abs_is_lms xs) [Suc i..<k] = []"
proof (induct k)
case 0
then show ?case
by simp
next
case (Suc k)
then show ?case
by (metis Suc_leD Suc_le_eq append_Nil filter.simps(1,2)
upt_Suc filter_append no_lms_between_i_and_next)
qed
lemma filter_no_lms2:
"⟦¬abs_is_lms xs i; i < k; k ≤ abs_find_next_lms xs i⟧ ⟹
filter (abs_is_lms xs) [i..<k] = []"
proof (induct k)
case 0
then show ?case
by simp
next
case (Suc k)
then show ?case
by (metis Suc_le_eq append_Nil filter.simps(1)
filter.simps(2) filter_append
not_less_eq_eq upt.simps(2) nle_le
no_lms_between_i_and_next upt_conv_Cons)
qed
subsection ‹LMS Prefix›
fun
closest_lms ::
"('a :: {linorder, order_bot}) list ⇒ nat ⇒ nat"
where
"closest_lms T i =
(if abs_is_lms T i
then i
else abs_find_next_lms T i)"
definition
lms_prefix ::
"('a :: {linorder, order_bot}) list ⇒ nat ⇒ 'a list"
where
"lms_prefix T i =
list_slice T i (Suc (closest_lms T i))"
lemma lms_lms_prefix:
"abs_is_lms T i ⟹ lms_prefix T i = [T ! i]"
unfolding lms_prefix_def
by (simp add: abs_is_lms_imp_less_length list_slice_Suc)
lemma suffix_to_lms_prefix:
"i < length T ⟹
suffix T i =
lms_prefix T i @
(list_slice T (Suc (closest_lms T i)) (length T))"
unfolding lms_prefix_def
apply clarsimp
apply (intro impI conjI)
apply (rule suffix_to_list_slice_app)
apply linarith
by (meson abs_find_next_lms_lower_bound_1 less_SucI
less_or_eq_imp_le suffix_to_list_slice_app)
lemma abs_find_next_lms_funpow_all_lms:
"⟦abs_is_lms xs ((abs_find_next_lms xs ^^ Suc k) x);
i ≤ k⟧ ⟹
abs_is_lms xs ((abs_find_next_lms xs ^^ Suc i) x)"
proof (induct k arbitrary: i)
case 0
then show ?case
by blast
next
case (Suc k)
note IH = this
hence "(abs_find_next_lms xs ^^ Suc (Suc k)) x < length xs"
using abs_is_lms_imp_less_length by blast
moreover
have "x < length xs"
by (metis calculation abs_find_next_lms_funpow_Suc
abs_find_next_lms_le_length abs_find_next_lms_lower_bound_2
abs_find_next_lms_strict_upper_imp_lower_bound funpow_swap1
linorder_not_less nat_neq_iff)
ultimately
have "(abs_find_next_lms xs ^^ Suc k) x < length xs"
using abs_find_next_lms_funpow_le order.strict_trans1 by blast
hence P: "abs_is_lms xs ((abs_find_next_lms xs ^^ Suc k) x)"
by (simp add: abs_find_next_lms_less_length_abs_is_lms)
from IH(3)
have "i ≤ k ∨ i = Suc k"
by (meson le_Suc_eq le_neq_implies_less)
moreover
from IH(1)[OF P, of i]
have "i ≤ k ⟹ ?case"
by blast
moreover
from IH(2)
have "i = Suc k ⟹ ?case"
by simp
ultimately show ?case
by blast
qed
subsection ‹LMS Slice›
definition
lms_slice :: "('a :: {linorder, order_bot}) list ⇒ nat ⇒ 'a list"
where
"lms_slice T i =
list_slice T i (Suc (abs_find_next_lms T i))"
lemma suffix_to_lms_slice:
"i < length T ⟹
suffix T i =
lms_slice T i @
(list_slice T (Suc (abs_find_next_lms T i)) (length T))"
unfolding lms_slice_def
apply (rule suffix_to_list_slice_app)
by (simp add: abs_find_next_lms_lower_bound_1
le_Suc_eq less_or_eq_imp_le)
lemma suffix_to_lms_slice_app_suffix:
"i < length T ⟹
suffix T i =
lms_slice T i @
(suffix T (Suc (abs_find_next_lms T i)))"
by (metis suffix_eq_list_slice suffix_to_lms_slice)
lemma lms_slice_cons:
"⟦i < length T; suffix_type T i = S_type⟧ ⟹
lms_slice T i =
T ! i # lms_slice T (Suc i)"
using abs_is_lms_def Suc_not_lms_imp_abs_find_next_eq_Suc
abs_find_next_lms_lower_bound_1 i_s_type_imp_Suc_i_not_lms
list_slice_Suc Suc_not_lms_imp_abs_find_next_eq_Suc
by (clarsimp simp: lms_slice_def) fastforce
lemma lms_slice_hd:
"i < length T ⟹
∃xs. lms_slice T i = T ! i # xs"
by (simp add: abs_find_next_lms_lower_bound_1 less_SucI list_slice_Suc lms_slice_def)
lemma lms_slice_suffix:
assumes "i ≤ length T"
shows "lms_slice (suffix T i) 0 =
lms_slice T i"
proof -
from list_slice_suffix[of T i "Suc (abs_find_next_lms T i)"]
lms_slice_def[of T i]
abs_find_next_lms_suffix[OF assms]
lms_slice_def[of "suffix T i" 0]
show ?thesis
by (metis add_Suc_right add_diff_cancel_left')
qed
lemma lms_slice_suffix_gen:
assumes "i ≤ length T"
and "j ≤ length T - i"
shows "lms_slice (suffix T i) j =
lms_slice T (i + j)"
proof -
have "lms_slice T (i + j) =
lms_slice (suffix T (i + j)) 0"
by (metis add.commute assms lms_slice_suffix le_diff_conv2)
hence "lms_slice T (i + j) =
lms_slice (suffix (suffix T i) j) 0"
by (simp add: add.commute)
moreover
have "lms_slice (suffix T i) j = lms_slice (suffix (suffix T i) j) 0"
by (metis assms(2) length_drop lms_slice_suffix)
ultimately show ?thesis
by simp
qed
lemma lms_slice_cons_Suc:
"i ≤ length xs ⟹ lms_slice (x # xs) (Suc i) = lms_slice xs i"
by (metis Suc_le_mono drop_Suc_Cons length_Cons lms_slice_suffix)
subsection ‹LMS Substring butlast›
definition lms_slice_butlast :: "('a :: {linorder, order_bot}) list ⇒ nat ⇒ 'a list"
where
"lms_slice_butlast T i = list_slice T i (abs_find_next_lms T i)"
lemma lms_slice_to_butlast_app:
"abs_find_next_lms T i < length T ⟹
lms_slice T i = lms_slice_butlast T i @ [T ! abs_find_next_lms T i]"
unfolding lms_slice_def lms_slice_butlast_def
apply (subst list_slice_append[of _ "abs_find_next_lms T i"])
apply (simp add: abs_find_next_lms_strict_upper_imp_lower_bound order.strict_implies_order)
apply simp
by (simp add: list_slice_Suc)
lemma lms_slice_eq_butlast:
"length T ≤ abs_find_next_lms T i ⟹
lms_slice T i = lms_slice_butlast T i"
by (metis le_SucI list_slice_end_gre_length lms_slice_butlast_def lms_slice_def)
lemma lms_slice_eq_suffix:
"length T ≤ abs_find_next_lms T i ⟹
lms_slice T i = suffix T i"
by (simp add: list_slice.simps lms_slice_butlast_def lms_slice_eq_butlast)
lemma suffix_abs_find_next_lms:
"abs_find_next_lms T i < length T ⟹
suffix T i = lms_slice_butlast T i @ suffix T (abs_find_next_lms T i)"
by (simp add: abs_find_next_lms_strict_upper_imp_lower_bound less_or_eq_imp_le list_slice_append
lms_slice_butlast_def suffix_eq_list_slice)
subsection ‹Suffix Types›
lemma suffix_type_lms_slice_l_s:
assumes "suffix_type T i = L_type"
and "suffix_type T (Suc i) = S_type"
shows "suffix_type (lms_slice T i) 0 = suffix_type T i"
proof -
have "Suc i < length T"
by (simp add: assms(2) suffix_type_s_bound)
have "abs_is_lms T (Suc i)"
by (simp add: assms abs_is_lms_def)
hence "abs_find_next_lms T i = Suc i"
by (simp add: abs_find_next_lms_abs_is_lms)
hence "lms_slice T i = [T ! i, T ! Suc i]"
by (metis Suc_n_not_le_n ‹Suc i < length T› le_Suc_eq not_le
list_slice_Suc list_slice_n_n lms_slice_def)
moreover
have "T ! i > T ! Suc i"
using ‹abs_is_lms T (Suc i)› abs_is_lms_neq by blast
ultimately show ?thesis
by (simp add: ‹suffix_type T i = L_type› suffix_type_cons_greater)
qed
lemma abs_find_next_lms_same_types:
assumes "∀k. i ≤ k ∧ k < length T ⟶ suffix_type T k = suffix_type T i"
and "i ≤ j"
shows "abs_find_next_lms T j = length T"
proof (cases "find (abs_is_lms T) [Suc j..<length T]")
assume "find (abs_is_lms T) [Suc j..<length T] = None"
then show "abs_find_next_lms T j = length T"
by (simp add: abs_find_next_lms_def)
next
fix x
assume "find (abs_is_lms T) [Suc j..<length T] = Some x"
hence "x < length T" "Suc j ≤ x" "abs_is_lms T x"
using ‹find (abs_is_lms T) [Suc j..<length T] = Some x› findSomeD by force+
hence "∃y. x = Suc y"
using abs_is_lms_def by blast
then obtain y where
"x = Suc y"
by blast
hence "suffix_type T y = L_type" "suffix_type T (Suc y) = S_type"
using ‹abs_is_lms T x› abs_is_lms_def by auto
have "i ≤ y"
using ‹Suc j ≤ x› ‹x = Suc y› assms(2) le_trans by blast
moreover
have "y < length T"
using Suc_lessD ‹x < length T› ‹x = Suc y› by blast
ultimately have "suffix_type T i = L_type"
by (metis ‹suffix_type T y = L_type› assms(1))
have "i ≤ Suc y"
by (simp add: ‹i ≤ y› le_SucI)
moreover
have "Suc y < length T"
using ‹x < length T› ‹x = Suc y› by blast
ultimately have "suffix_type T i = S_type"
by (metis ‹suffix_type T (Suc y) = S_type› assms(1))
with ‹suffix_type T i = L_type›
have "x = length T"
by simp
then show ?thesis
using ‹x < length T› by blast
qed
lemma lms_slice_same_types:
assumes "∀k. i ≤ k ∧ k < length T ⟶ suffix_type T k = suffix_type T i"
and "i ≤ j"
shows "lms_slice T j = suffix T j"
proof -
have "abs_find_next_lms T j = length T"
using assms abs_find_next_lms_same_types by blast
then show ?thesis
by (metis le0 le_add_same_cancel2 list_slice_end_gre_length lms_slice_def plus_1_eq_Suc
suffix_eq_list_slice)
qed
lemma all_l_types_up_to_next_lms:
"⟦i ≤ k; k < abs_find_next_lms T i; suffix_type T i = L_type⟧ ⟹ suffix_type T k = L_type"
proof(induct "k - i" arbitrary: k)
case 0
then show ?case by simp
next
case (Suc x)
have "∃k'. k = Suc k'"
using Suc.hyps(2) Suc_le_D diff_le_self by presburger
then obtain k' where
"k = Suc k'"
by blast
hence "x = k' - i"
using Suc.hyps(2) by linarith
moreover
have "i ≤ k'"
using Suc.hyps(2) ‹k = Suc k'› by linarith
moreover
have "k' < abs_find_next_lms T i"
using Suc.prems(2) Suc_lessD ‹k = Suc k'› by blast
ultimately have "suffix_type T k' = L_type"
using Suc.hyps(1) Suc.prems(3) by blast
have "i < k"
by (simp add: ‹i ≤ k'› ‹k = Suc k'› le_imp_less_Suc)
with Suc.prems(2) no_lms_between_i_and_next[of i k T]
have "¬ abs_is_lms T k"
by blast
with ‹suffix_type T k' = L_type› ‹k = Suc k'›
show ?case
using SL_types.exhaust abs_is_lms_def by blast
qed
lemma abs_find_next_lms_eq_length:
assumes "abs_find_next_lms T i = length T"
and "i < length T"
shows "suffix_type T i = S_type"
proof (rule ccontr)
assume "suffix_type T i ≠ S_type"
hence "suffix_type T i = L_type"
using SL_types.exhaust by blast
moreover
have "∃k. abs_find_next_lms T i = Suc k"
by (metis assms(1) assms(2) not_less0 old.nat.exhaust)
then obtain k where
"abs_find_next_lms T i = Suc k"
by blast
moreover
have "i ≤ k"
using assms(1,2) calculation by linarith
ultimately have "suffix_type T k = L_type"
by (metis all_l_types_up_to_next_lms lessI)
moreover
have "length T = Suc k"
using ‹abs_find_next_lms T i = Suc k› assms(1) by auto
ultimately show False
using suffix_type_last[of T k]
by simp
qed
lemma abs_find_next_lms_eq_length_all_s_types:
assumes "abs_find_next_lms T i = length T"
and "i ≤ j"
and "j < length T"
shows "suffix_type T j = S_type"
by (metis assms abs_find_next_lms_eq_length abs_find_next_lms_le_length abs_find_next_lms_less_length_abs_is_lms
abs_find_next_lms_lower_bound_1 le_neq_implies_less no_lms_between_i_and_next
order.strict_trans1)
lemma abs_find_next_lms_first_l_after_s_type:
assumes "abs_find_next_lms T i < length T"
and "suffix_type T i = S_type"
shows "∃j>i. j < abs_find_next_lms T i ∧ (∀k<j. i ≤ k ⟶ suffix_type T k = S_type) ∧
suffix_type T j = L_type"
proof -
have "∃j. abs_find_next_lms T i = Suc j"
by (metis assms(2) abs_find_next_lms_lower_bound_1 not_less0 old.nat.exhaust suffix_type_s_bound)
then obtain j where
"abs_find_next_lms T i = Suc j"
by blast
hence "abs_is_lms T (Suc j)"
using assms(1) abs_find_next_lms_less_length_abs_is_lms by fastforce
hence "suffix_type T j = L_type"
using SL_types.exhaust i_s_type_imp_Suc_i_not_lms by auto
moreover
have "j < length T"
using ‹abs_find_next_lms T i = Suc j› assms(1) by linarith
moreover
have "i ≤ j"
by (metis ‹abs_find_next_lms T i = Suc j› assms(1) abs_find_next_lms_strict_upper_imp_lower_bound
less_Suc_eq_le)
moreover
have "∀k>i. k ≤ j ⟶ ¬ abs_is_lms T k"
by (simp add: ‹abs_find_next_lms T i = Suc j› no_lms_between_i_and_next)
ultimately show ?thesis
using first_l_type_after_s_type[OF _ _ _ _assms(2), of j]
by (metis SL_types.simps(2) ‹abs_find_next_lms T i = Suc j› assms(2) dual_order.order_iff_strict
le_imp_less_Suc)
qed
lemma lms_slice_type:
assumes "i < length T"
shows "suffix_type (lms_slice T i) 0 = suffix_type T i"
proof -
have "∃k. abs_find_next_lms T i = Suc k"
by (meson Nat.lessE assms abs_find_next_lms_lower_bound_1)
then obtain k where
"abs_find_next_lms T i = Suc k"
by blast
have "suffix_type T i = L_type ∨ suffix_type T i = S_type"
using SL_types.exhaust by blast
moreover
have "suffix_type T i = L_type ⟹ ?thesis"
proof -
assume "suffix_type T i = L_type"
have "suffix_type T (Suc i) = L_type ∨ suffix_type T (Suc i) = S_type"
using SL_types.exhaust by blast
moreover
have "suffix_type T (Suc i) = S_type ⟹ ?thesis"
by (simp add: ‹suffix_type T i = L_type› suffix_type_lms_slice_l_s)
moreover
have "suffix_type T (Suc i) = L_type ⟹ ?thesis"
proof -
assume "suffix_type T (Suc i) = L_type"
from ‹abs_find_next_lms T i = Suc k›
have P: "∀k'≥i. k' < Suc k ⟶ suffix_type T k' = L_type"
by (simp add: ‹suffix_type T i = L_type› all_l_types_up_to_next_lms)
have "lms_slice T i = list_slice T i (Suc (Suc k))"
by (simp add: lms_slice_def ‹abs_find_next_lms T i = Suc k›)
moreover
{
have "i < k"
by (metis SL_types.simps(2) Suc_lessI ‹abs_find_next_lms T i = Suc k›
‹suffix_type T (Suc i) = L_type› ‹suffix_type T i = L_type› assms
abs_find_next_lms_less_length_abs_is_lms abs_find_next_lms_lower_bound_1 less_antisym
suffix_type_last suffix_type_same_imp_not_lms)
hence "list_slice T i (Suc (Suc k)) = list_slice T i k @ list_slice T k (Suc (Suc k))"
by (meson dual_order.order_iff_strict le_Suc_eq list_slice_append)
moreover
have "list_slice T k (Suc (Suc k)) = [T ! k, T ! (Suc k)]"
by (metis SL_types.simps(2) ‹abs_find_next_lms T i = Suc k› ‹suffix_type T i = L_type›
all_l_types_up_to_next_lms assms dual_order.order_iff_strict
abs_find_next_lms_le_length less_Suc_eq_le list_slice_Suc list_slice_n_n
not_less_eq suffix_type_last)
moreover
have "list_slice T i k = T ! i # list_slice T (Suc i) k"
using ‹i < k› assms list_slice_Suc by blast
ultimately have
"list_slice T i (Suc (Suc k)) = T ! i # (list_slice T (Suc i) k) @ [T ! k, T ! Suc k]"
by simp
}
ultimately have
"lms_slice T i = T ! i # (list_slice T (Suc i) k) @ [T ! k, T ! Suc k]"
by simp
let ?bs = "list_slice T (Suc i) k"
have "abs_is_lms T (Suc k)"
by (metis SL_types.simps(2) ‹abs_find_next_lms T i = Suc k› ‹suffix_type T i = L_type›
all_l_types_up_to_next_lms assms dual_order.order_iff_strict suffix_type_last
abs_find_next_lms_le_length abs_find_next_lms_less_length_abs_is_lms less_Suc_eq_le)
hence "T ! k > T ! Suc k"
using abs_is_lms_neq by blast
moreover
from sorted_letters_l_types[OF P[simplified ‹abs_find_next_lms T i = Suc k›]]
have "sorted (rev (list_slice T i (Suc k)))"
using ‹abs_is_lms T (Suc k)› abs_is_lms_gre_length linear by blast
moreover
have "list_slice T i (Suc k) = T ! i # (list_slice T (Suc i) k) @ [T ! k]"
by (metis SL_types.simps(2) ‹abs_find_next_lms T i = Suc k› ‹abs_is_lms T (Suc k)›
‹suffix_type T (Suc i) = L_type› assms dual_order.order_iff_strict not_less_eq
abs_find_next_lms_le_length abs_find_next_lms_lower_bound_1 abs_is_lms_def list_slice_Suc not_less
list_slice_append list_slice_n_n )
ultimately have
"list_less_ns (?bs @ [T ! k, T ! Suc k]) (T ! i # ?bs @ [T ! k, T ! Suc k])"
using rev_sorted_list_less_ns[of "T ! i" ?bs "T ! k" "T ! Suc k" "[]" "[]"]
by simp
moreover
have "suffix (lms_slice T i) 0 = T ! i # ?bs @ [T ! k, T ! Suc k]"
by (simp add: ‹lms_slice T i = T ! i # ?bs @ [T ! k, T ! Suc k]›)
moreover
have "suffix (lms_slice T i) (Suc 0) = ?bs @ [T ! k, T ! Suc k]"
by (simp add: ‹lms_slice T i = T ! i # list_slice T (Suc i) k @ [T ! k, T ! Suc k]›)
ultimately show ?thesis
by (metis ‹suffix_type T i = L_type› ordlistns.less_asym suffix_type_def)
qed
ultimately show ?thesis
by blast
qed
moreover
have "suffix_type T i = S_type ⟹ ?thesis"
proof -
assume "suffix_type T i = S_type"
hence "lms_slice T i = T ! i # lms_slice T (Suc i)"
using assms lms_slice_cons by blast
have "abs_find_next_lms T i < length T ∨ abs_find_next_lms T i = length T"
by (simp add: abs_find_next_lms_le_length nat_less_le)
moreover
have "abs_find_next_lms T i < length T ⟹ ?thesis"
proof -
assume "abs_find_next_lms T i < length T"
with abs_find_next_lms_first_l_after_s_type[OF _ ‹suffix_type T i = S_type›]
obtain j where
"i < j"
"j < abs_find_next_lms T i"
"∀k<j. i ≤ k ⟶ suffix_type T k = S_type"
"suffix_type T j = L_type"
by blast
hence "sorted (list_slice T i j)"
by (meson ‹abs_find_next_lms T i < length T› dual_order.order_iff_strict order.strict_trans
sorted_letters_s_types)
have "∃l. j = Suc l"
using ‹i < j› less_imp_Suc_add by blast
then obtain l where
"j = Suc l"
by blast
let ?xs = "list_slice T (Suc i) (Suc l)"
and ?ys = "list_slice T (Suc ((Suc l))) (Suc (Suc k))"
have "lms_slice T i = list_slice T i j @ list_slice T j (Suc (Suc k))"
by (metis ‹abs_find_next_lms T i = Suc k› ‹i < j› ‹j < abs_find_next_lms T i› less_SucI
less_imp_le_nat list_slice_append lms_slice_def)
moreover
have "list_slice T i j = T ! i # ?xs"
using ‹i < j› ‹j = Suc l› assms list_slice_Suc by blast
moreover
have "list_slice T j (Suc (Suc k)) = T ! Suc l # ?ys"
by (metis ‹abs_find_next_lms T i < length T› ‹abs_find_next_lms T i = Suc k› ‹j < abs_find_next_lms T i›
‹j = Suc l› less_SucI list_slice_Suc order.strict_trans)
ultimately have "lms_slice T i = T ! i # ?xs @ [T ! Suc l] @ ?ys"
by auto
have "i = l ∨ i < l"
using ‹i < j› less_antisym ‹j = Suc l› by blast
moreover
have "i = l ⟹ ?thesis"
proof -
assume "i = l"
hence "?xs = []"
using list_slice_n_n by blast
hence "lms_slice T i = T ! i # [T ! Suc l] @ ?ys"
using ‹lms_slice T i = T ! i # ?xs @ [T ! Suc l] @ ?ys›
by simp
moreover
have "T ! i < T ! Suc l"
by (metis SL_types.simps(2) ‹abs_find_next_lms T i < length T› ‹i = l› ‹j < abs_find_next_lms T i›
‹j = Suc l› ‹suffix_type T i = S_type› ‹suffix_type T j = L_type› suffix_type_neq
le_imp_less_or_eq order.strict_trans s_type_letter_le_Suc)
ultimately show ?thesis
by (simp add: ‹suffix_type T i = S_type› suffix_type_cons_less)
qed
moreover
have "i < l ⟹ ?thesis"
proof -
let ?zs = "list_slice T (Suc i) l"
assume "i < l"
hence "?xs = ?zs @ [T ! l]"
by (metis Suc_leI Suc_n_not_le_n ‹abs_find_next_lms T i < length T› ‹j < abs_find_next_lms T i›
‹j = Suc l› lessI less_le_trans linear list_slice_Suc list_slice_append
list_slice_n_n)
hence "lms_slice T i = T ! i # ?zs @ [T ! l, T ! Suc l] @ ?ys"
using ‹lms_slice T i = T ! i # ?xs @ [T ! Suc l] @ ?ys›
by simp
moreover
have "suffix_type T l = S_type"
by (simp add: ‹∀k<j. i ≤ k ⟶ suffix_type T k = S_type› ‹i < l› ‹j = Suc l› less_or_eq_imp_le)
hence "T ! l < T ! Suc l"
by (metis SL_types.simps(2) ‹abs_find_next_lms T i < length T› ‹j < abs_find_next_lms T i›
‹j = Suc l› ‹suffix_type T j = L_type› order.strict_iff_order order.strict_trans
s_type_letter_le_Suc suffix_type_neq)
ultimately show ?thesis
using ‹sorted (list_slice T i j)›
sorted_list_less_ns[of "T ! i" ?zs "T ! l" "T ! Suc l" ?ys ?ys]
by (metis ‹?xs = ?zs @ [T ! l]› ‹list_slice T i j = T ! i # ?xs› suffix_0 length_Cons
‹suffix_type T i = S_type› list.inject suffix_0 suffix_cons_Suc suffix_type_def
zero_less_Suc)
qed
ultimately show ?thesis
by blast
qed
moreover
have "abs_find_next_lms T i = length T ⟹ ?thesis"
proof -
assume "abs_find_next_lms T i = length T"
hence P: "∀k'≥i. k' < length T ⟶ suffix_type T k' = S_type"
using abs_find_next_lms_eq_length_all_s_types by blast
have "lms_slice T i = T ! i # list_slice T (Suc i) (length T)"
by (metis ‹abs_find_next_lms T i = length T› assms leI less_not_refl list_slice_Suc
lms_slice_butlast_def lms_slice_eq_butlast)
with sorted_letters_s_types[OF P]
sorted_cons_list_less_ns[of "T ! i" "list_slice T (Suc i) (length T)"]
show ?thesis
by (metis assms list_slice_Suc suffix_eq_list_slice suffix_type_suffix)
qed
ultimately show ?thesis
by blast
qed
ultimately show ?thesis
by blast
qed
lemma lms_slice_l_less_than_s_type_gen:
assumes "suffix_type (a # as) 0 = L_type"
and "suffix_type (a # bs) 0 = S_type"
shows "list_less_ns (lms_slice (a # as) 0) (lms_slice (a # bs) 0)"
proof -
from lms_slice_type[of 0 "a # as"] assms(1)
have "suffix_type (lms_slice (a # as) 0) 0 = L_type"
by simp
moreover
have "∃xs. lms_slice (a # as) 0 = a # xs"
by (simp add: list_slice_Suc lms_slice_def)
then obtain xs where
"lms_slice (a # as) 0 = a # xs"
by blast
moreover
from lms_slice_type[of 0 "a # bs"] assms(2)
have "suffix_type (lms_slice (a # bs) 0) 0 = S_type"
by simp
moreover
have "∃xs. lms_slice (a # bs) 0 = a # xs"
by (simp add: assms(2) lms_slice_cons)
then obtain ys where
"lms_slice (a # bs) 0 = a # ys"
by blast
ultimately show ?thesis
by (simp add: l_less_than_s_type_general)
qed
lemma lms_slice_l_less_than_s_type:
assumes "i < length T"
and "j < length T"
and "T ! i = T ! j"
and "suffix_type T i = L_type"
and "suffix_type T j = S_type"
shows "list_less_ns (lms_slice T i) (lms_slice T j)"
by (metis assms abs_find_next_lms_lower_bound_1 l_less_than_s_type_general less_SucI list_slice_Suc
lms_slice_def lms_slice_type)
lemma lms_prefix_type:
assumes "i < length T"
shows "suffix_type (lms_prefix T i) 0 = suffix_type T i"
proof -
have "abs_is_lms T i ∨ ¬abs_is_lms T i"
by blast
moreover
have "¬abs_is_lms T i ⟹ ?thesis"
by (metis assms closest_lms.simps lms_prefix_def lms_slice_def
lms_slice_type)
moreover
have "abs_is_lms T i ⟹ ?thesis"
by (simp add: abs_is_lms_def lms_lms_prefix suffix_type_last)
ultimately show ?thesis
by blast
qed
lemma lms_prefix_l_less_than_s_type_gen:
assumes "suffix_type (a # as) 0 = L_type"
and "suffix_type (a # bs) 0 = S_type"
shows "list_less_ns (lms_prefix (a # as) 0) (lms_prefix (a # bs) 0)"
by (metis assms closest_lms.simps lms_prefix_def abs_is_lms_def lessI lms_slice_def
lms_slice_l_less_than_s_type_gen not_gr_zero not_less_iff_gr_or_eq)
lemma lms_prefix_l_less_than_s_type:
assumes "i < length T"
and "j < length T"
and "T ! i = T ! j"
and "suffix_type T i = L_type"
and "suffix_type T j = S_type"
shows "list_less_ns (lms_prefix T i) (lms_prefix T j)"
proof -
let ?a = "T ! i"
have "∃as. lms_prefix T i = ?a # as"
by (simp add: assms(1) lms_prefix_def abs_find_next_lms_lower_bound_1 less_SucI
list_slice_Suc)
then obtain as where
"lms_prefix T i = ?a # as"
by blast
hence "suffix_type (?a # as) 0 = L_type"
using assms(1,4) lms_prefix_type by fastforce
have "∃bs. lms_prefix T j = ?a # bs"
by (simp add: assms(2,3) lms_prefix_def abs_find_next_lms_lower_bound_1 less_SucI
list_slice_Suc)
then obtain bs where
"lms_prefix T j = ?a # bs"
by blast
hence "suffix_type (?a # bs) 0 = S_type"
using assms(2) assms(5) lms_prefix_type by fastforce
with l_less_than_s_type_general[OF _ ‹suffix_type (?a # as) 0 = _›, of bs]
have "list_less_ns (?a # as) (?a # bs)" .
then show ?thesis
by (simp add: ‹lms_prefix T i = T ! i # as› ‹lms_prefix T j = T ! i # bs›)
qed
lemma l_type_lms_prefix_cons:
assumes "suffix_type T i = L_type"
and "i < length T"
shows "lms_prefix T i = T ! i # lms_prefix T (Suc i)"
proof -
have "suffix_type T (Suc i) = L_type ∨ suffix_type T (Suc i) = S_type"
using SL_types.exhaust by blast
moreover
have "suffix_type T (Suc i) = L_type ⟹ ?thesis"
proof -
assume "suffix_type T (Suc i) = L_type"
hence "¬abs_is_lms T (Suc i)"
by (simp add: ‹suffix_type T i = L_type› suffix_type_same_imp_not_lms)
with Suc_not_lms_imp_abs_find_next_eq_Suc
have "abs_find_next_lms T i = abs_find_next_lms T (Suc i)" .
hence "closest_lms T i = abs_find_next_lms T (Suc i)"
by (simp add: ‹suffix_type T i = L_type› abs_is_lms_def)
hence "lms_prefix T i = list_slice T i (Suc (abs_find_next_lms T (Suc i)))"
by (simp add: lms_prefix_def)
moreover
have "Suc i < Suc (abs_find_next_lms T (Suc i))"
using ‹abs_find_next_lms T i = abs_find_next_lms T (Suc i)› assms(2) abs_find_next_lms_lower_bound_1
by force
ultimately have
"lms_prefix T i = T ! i # list_slice T (Suc i) (Suc (abs_find_next_lms T (Suc i)))"
by (simp add: assms(2) list_slice_Suc)
then show ?thesis
by (simp add: ‹¬ abs_is_lms T (Suc i)› lms_prefix_def)
qed
moreover
have "suffix_type T (Suc i) = S_type ⟹ ?thesis"
proof -
assume "suffix_type T (Suc i) = S_type"
hence "abs_is_lms T (Suc i)"
by (simp add: assms(1) abs_is_lms_def)
hence "abs_find_next_lms T i = Suc i"
by (simp add: abs_find_next_lms_abs_is_lms)
hence "lms_prefix T i = [T ! i, T ! Suc i]"
by (metis Suc_lessD ‹abs_is_lms T (Suc i)› assms(2) closest_lms.simps lms_prefix_def
abs_is_lms_consec(1) lessI list_slice_Suc lms_lms_prefix)
moreover
have "lms_prefix T (Suc i) = [T ! Suc i]"
by (simp add: ‹abs_is_lms T (Suc i)› lms_lms_prefix)
ultimately show ?thesis
by simp
qed
ultimately show ?thesis
by blast
qed
section ‹Ordering LMS-substrings›
text ‹ This section contains theorems about how LMS-substrings and suffixes are ordered. ›
lemma lms_slice_eq_suffix_less:
assumes "lms_slice T i = lms_slice T j"
shows "list_less_ns (suffix T i) (suffix T j) ⟷
list_less_ns (suffix T (abs_find_next_lms T i)) (suffix T (abs_find_next_lms T j))"
proof -
have "⟦abs_find_next_lms T i < length T; abs_find_next_lms T j < length T⟧ ⟹ ?thesis"
proof -
assume A: "abs_find_next_lms T i < length T" "abs_find_next_lms T j < length T"
have "suffix T i = lms_slice_butlast T i @ suffix T (abs_find_next_lms T i)"
using A(1) suffix_abs_find_next_lms by blast
moreover
have "suffix T j = lms_slice_butlast T j @ suffix T (abs_find_next_lms T j)"
using A(2) suffix_abs_find_next_lms by blast
moreover
have "lms_slice_butlast T i = lms_slice_butlast T j"
by (metis A(1) A(2) assms butlast_snoc lms_slice_to_butlast_app)
ultimately show ?thesis
by (simp add: list_less_ns_app_same)
qed
moreover
have "⟦abs_find_next_lms T i = length T; abs_find_next_lms T j = length T⟧ ⟹ ?thesis"
by (metis assms dual_order.refl lms_slice_eq_suffix ordlistns.less_irrefl)
moreover
have "⟦abs_find_next_lms T i = length T; abs_find_next_lms T j < length T⟧ ⟹ ?thesis"
proof -
assume A: "abs_find_next_lms T i = length T" "abs_find_next_lms T j < length T"
have "suffix T i = lms_slice T i"
by (simp add: A(1) lms_slice_eq_suffix)
moreover
have "suffix T j = lms_slice T j @ suffix T (Suc (abs_find_next_lms T j))"
by (meson A(2) abs_find_next_lms_lower_bound_2 linorder_not_less
suffix_to_lms_slice_app_suffix)
ultimately show ?thesis
by (metis A(1) append.right_neutral assms cancel_comm_monoid_add_class.diff_cancel
length_0_conv length_drop list_less_ns_app ordlistns.not_less_iff_gr_or_eq
ordlistns.top.extremum_strict)
qed
moreover
have "⟦abs_find_next_lms T i < length T; abs_find_next_lms T j = length T⟧ ⟹ ?thesis"
proof -
assume A: "abs_find_next_lms T i < length T" "abs_find_next_lms T j = length T"
have "suffix T i = lms_slice T i @ suffix T (Suc (abs_find_next_lms T i))"
by (meson A(1) abs_find_next_lms_lower_bound_2 linorder_not_less
suffix_to_lms_slice_app_suffix)
moreover
have "suffix T j = lms_slice T j"
by (simp add: A(2) lms_slice_eq_suffix)
ultimately show ?thesis
by (metis A append_Nil2 assms drop_eq_Nil2 abs_find_next_lms_lower_bound_2 linorder_le_less_linear
list_less_ns_app nless_le ordlistns.top.not_eq_extremum suffix_neq_nil suffixes_neq)
qed
ultimately show ?thesis
by (meson abs_find_next_lms_le_length le_neq_implies_less)
qed
lemma lms_slice_eq_suffix_less_funpow':
assumes "∀k < n. lms_slice T (((abs_find_next_lms T)^^k) i) =
lms_slice T (((abs_find_next_lms T)^^k) j)"
and "k < n"
shows "list_less_ns (suffix T i) (suffix T j) ⟷
list_less_ns (suffix T (((abs_find_next_lms T)^^k) i)) (suffix T (((abs_find_next_lms T)^^k) j))"
using assms
proof (induct n arbitrary: k)
case 0
then show ?case
by blast
next
case (Suc n)
note IH = this
have "k < n ⟹ ?case"
by (simp add: Suc.hyps Suc.prems(1))
moreover
have "k = n ⟹ ?case"
proof -
assume "k = n"
have "k = 0 ⟹ ?thesis"
by auto
moreover
have "∃m. k = Suc m ⟹ ?thesis"
proof -
assume "∃m. k = Suc m"
then obtain m where "k = Suc m"
by blast
hence "m < n"
using ‹k = n› by blast
with IH(1)[of m]
have "list_less_ns (suffix T i) (suffix T j) =
list_less_ns (suffix T ((abs_find_next_lms T ^^ m) i))
(suffix T ((abs_find_next_lms T ^^ m) j))"
using Suc.prems(1) less_Suc_eq_le less_or_eq_imp_le by presburger
moreover
have "list_less_ns (suffix T ((abs_find_next_lms T ^^ m) i))
(suffix T ((abs_find_next_lms T ^^ m) j)) =
list_less_ns (suffix T (abs_find_next_lms T ((abs_find_next_lms T ^^ m) i)))
(suffix T (abs_find_next_lms T ((abs_find_next_lms T ^^ m) j)))"
using Suc.prems(1,2) Suc_lessD ‹k = Suc m› lms_slice_eq_suffix_less by blast
ultimately show ?thesis
by (simp add: ‹k = Suc m›)
qed
ultimately show ?thesis
using not0_implies_Suc by blast
qed
ultimately show ?case
using Suc.prems(2) less_Suc_eq by blast
qed
lemma lms_slice_eq_suffix_less_funpow:
assumes "∀k < n. lms_slice T (((abs_find_next_lms T)^^k) i) =
lms_slice T (((abs_find_next_lms T)^^k) j)"
shows "list_less_ns (suffix T i) (suffix T j) ⟷
list_less_ns (suffix T (((abs_find_next_lms T)^^n) i)) (suffix T (((abs_find_next_lms T)^^n) j))"
proof (cases n)
case 0
then show ?thesis
by auto
next
case (Suc m)
then show ?thesis
by (metis assms abs_find_next_lms_funpow_Suc lessI lms_slice_eq_suffix_less
lms_slice_eq_suffix_less_funpow')
qed
lemma list_slice_single:
"i < length xs ⟹ list_slice xs i (Suc i) = [xs ! i]"
by (simp add: list_slice_Suc)
lemma less_lms_slice_imp_suffix:
assumes "i < length T"
and "j < length T"
and "list_less_ns (lms_slice T i) (lms_slice T j)"
shows "list_less_ns (suffix T i) (suffix T j)"
proof -
let ?c1 = "∃b c as bs cs. lms_slice T i = as @ b # bs ∧
lms_slice T j = as @ c # cs ∧ b < c"
let ?c2 = "∃c cs. lms_slice T i = lms_slice T j @ c # cs"
from list_less_ns_exE[OF assms(3)[simplified list_less_ns_alt_def]]
have "?c1 ∨ ?c2" .
moreover
have "?c1 ⟹ ?thesis"
by (metis append.assoc append_Cons assms(1,2) list_less_ns_app_same list_less_ns_cons_diff
suffix_to_lms_slice_app_suffix)
moreover
have "?c2 ⟹ ?thesis"
proof -
assume "?c2"
then obtain c cs where
"lms_slice T i = lms_slice T j @ c # cs"
by blast
moreover
from lms_slice_hd[OF assms(2)]
obtain xs where
Sj: "lms_slice T j = T ! j # xs"
by blast
ultimately have Si: "lms_slice T i = T ! j # xs @ c # cs"
by simp
let ?i = "abs_find_next_lms T i"
let ?j = "abs_find_next_lms T j"
have "∃k. ?j = Suc k"
by (meson Nat.lessE assms(1) dual_order.strict_trans1
abs_find_next_lms_strict_upper_imp_lower_bound linorder_not_less)
then obtain k where
"?j = Suc k"
by blast
hence "j ≤ k"
using assms(2) abs_find_next_lms_lower_bound_1 by force
have "?j = length T ⟹ ?thesis"
by (metis append_Nil2 assms(1,3) abs_find_next_lms_le_length list_less_ns_app
lms_slice_eq_suffix ordlistns.dual_order.strict_trans
suffix_to_lms_slice_app_suffix)
moreover
have "?j < length T ⟹ ?thesis"
proof -
assume "?j < length T"
with lms_slice_to_butlast_app
have "lms_slice T j = lms_slice_butlast T j @ [T ! Suc k]"
using ‹?j = Suc k› by fastforce
moreover
have "∃ys. lms_slice_butlast T j = ys @ [T ! k]"
proof (cases "j = k")
case True
hence "lms_slice_butlast T j = list_slice T k (Suc k)"
by (metis ‹?j = Suc k› lms_slice_butlast_def)
moreover
have "list_slice T k (Suc k) = [T ! k]"
using True assms(2) list_slice_single by auto
ultimately show ?thesis
by simp
next
case False
hence "j < k"
by (simp add: ‹j ≤ k› le_neq_implies_less)
hence "list_slice T j (Suc k) = list_slice T j k @ [T ! k]"
by (metis ‹?j < length T› ‹?j = Suc k› ‹j ≤ k› le_SucI le_add2 list_slice_append
list_slice_single not_less plus_1_eq_Suc)
then show ?thesis
by (simp add: ‹?j = Suc k› lms_slice_butlast_def)
qed
then obtain ys where
"lms_slice_butlast T j = ys @ [T ! k]"
by blast
ultimately have Sj': "lms_slice T j = ys @ [T ! k, T ! Suc k]"
by simp
have Si': "lms_slice T i = ys @ T ! k # T ! Suc k # c # cs"
using Si Sj Sj' by auto
have "suffix_type T k = L_type"
by (metis ‹?j < length T› ‹?j = Suc k› abs_find_next_lms_less_length_abs_is_lms
abs_is_lms_neq nth_gr_imp_l_type)
have "abs_is_lms T (Suc k)"
by (metis ‹?j < length T› ‹?j = Suc k› abs_find_next_lms_less_length_abs_is_lms)
hence "T ! k > T ! Suc k"
using abs_is_lms_neq by blast
have Si: "suffix T i = ys @ T ! k # T ! Suc k # c # cs @ suffix T (Suc ?i)"
by (simp add: Si' assms(1) suffix_to_lms_slice_app_suffix)
moreover
have "suffix T j = ys @ T ! k # T ! Suc k # suffix T (Suc ?j)"
by (simp add: ‹lms_slice T j = ys @ [T ! k, T ! Suc k]› assms(2)
suffix_to_lms_slice_app_suffix)
ultimately have "list_less_ns (suffix T i) (suffix T j) ⟷
list_less_ns (T ! k # T ! Suc k # c # cs @ suffix T (Suc ?i))
(T ! k # T ! Suc k # suffix T (Suc ?j))"
by (simp add: list_less_ns_app_same)
moreover
have "suffix_type (T ! k # T ! Suc k # c # cs @ suffix T (Suc ?i)) (Suc 0) = L_type ⟹ ?thesis"
by (metis Cons_nth_drop_Suc ‹?j < length T› ‹?j = Suc k› ‹abs_is_lms T (Suc k)› calculation
abs_is_lms_def l_less_than_s_type_general list_less_ns_cons_same suffix_type_cons_suc
suffix_type_suffix)
moreover
have "suffix_type (T ! k # T ! Suc k # c # cs @ suffix T (Suc ?i)) (Suc 0) = S_type ⟹ ?thesis"
proof -
assume "suffix_type (T ! k # T ! Suc k # c # cs @ suffix T (Suc ?i)) (Suc 0) = S_type"
with Si
have "suffix_type T (Suc (i + length ys)) = S_type"
by (metis One_nat_def plus_1_eq_Suc suffix_cons_app suffix_type_suffix_gen)
moreover
have "suffix_type (T ! k # T ! Suc k # c # cs @ suffix T (Suc ?i)) 0 = L_type"
using ‹T ! Suc k < T ! k› suffix_type_cons_greater by blast
hence "suffix_type T (i + length ys) = L_type"
by (simp add: Si suffix_cons_app suffix_type_list_type_eq)
ultimately have "abs_is_lms T (Suc (i + length ys))"
using abs_is_lms_def by blast
moreover
{
have "i < ?i"
by (simp add: assms(1) abs_find_next_lms_lower_bound_1)
from ‹lms_slice T i = ys @ T ! k # T ! Suc k # c # cs›
have "Suc (Suc (length ys)) < length (lms_slice T i)"
by simp
have "?i = length T ⟹ Suc (i + length ys) < ?i"
by (simp add: ‹abs_is_lms T (Suc (i + length ys))› abs_is_lms_imp_less_length)
moreover
have "?i < length T ⟹ Suc (i + length ys) < ?i"
proof -
assume "?i < length T"
hence "length (lms_slice T i) = Suc ?i - i"
by (simp add: lms_slice_def Suc_leI)
hence "Suc (Suc (length ys)) < Suc ?i - i"
using ‹Suc (Suc (length ys)) < length (lms_slice T i)› by presburger
then show ?thesis
by linarith
qed
ultimately have "Suc (i + length ys) < ?i"
using abs_find_next_lms_le_length le_neq_implies_less by blast
}
ultimately show ?thesis
using no_lms_between_i_and_next[of i "Suc (i + length ys)"] less_add_Suc1 by blast
qed
ultimately show ?thesis
using SL_types.exhaust by blast
qed
ultimately show ?thesis
using abs_find_next_lms_le_length le_neq_implies_less by blast
qed
ultimately show ?thesis
by blast
qed
lemma lms_slice_list_less_ns_suffix:
assumes "abs_is_lms T i"
and "abs_is_lms T j"
and "list_less_ns (lms_slice T i) (lms_slice T j)"
shows "list_less_ns (suffix T i) (suffix T j)"
by (simp add: assms abs_is_lms_imp_less_length less_lms_slice_imp_suffix)
lemma less_suffix_imp_lms_slice:
assumes "i < length T"
and "j < length T"
and "lms_slice T i ≠ lms_slice T j"
and "list_less_ns (suffix T i) (suffix T j)"
shows "list_less_ns (lms_slice T i) (lms_slice T j)"
by (meson assms less_lms_slice_imp_suffix ordlistns.less_asym ordlistns.neqE)
lemma not_lms_imp_next_eq_lms_prefix:
"¬abs_is_lms T i ⟹ lms_slice T i = lms_prefix T i"
by (simp add: lms_prefix_def lms_slice_def)
lemma lms_slice_last:
assumes "valid_list T"
and "length T = Suc n"
shows "lms_slice T n = [bot]"
by (metis add_diff_cancel_left' assms butlast_snoc abs_find_next_lms_lower_bound_1 le_Suc_eq
length_butlast less_Suc_eq list_slice_Suc list_slice_start_gre_length lms_slice_def
nth_append_length plus_1_eq_Suc valid_list_ex_def)
lemma Min_valid_lms_slice:
assumes "valid_list T"
and "length T = Suc n"
shows "ordlistns.Min {lms_slice T i |i. i < length T} = lms_slice T n"
proof -
from lms_slice_last[OF assms]
have "lms_slice T n = [bot]"
by assumption
have "∀i < n. (lms_slice T i) ! 0 ≠ bot"
by (metis add_diff_cancel_left' assms abs_find_next_lms_lower_bound_1 less_SucI list_slice_Suc
lms_slice_def nth_Cons_0 plus_1_eq_Suc valid_list_def)
hence A: "∀i < n. bot < (lms_slice T i) ! 0"
using bot.not_eq_extremum by blast
have B: "∀i < length T. length (lms_slice T i) > 0"
by (simp add: abs_find_next_lms_lower_bound_1 less_SucI list_slice_Suc lms_slice_def)
show ?thesis
proof (intro ordlistns.Min_eqI conjI)
show "finite {lms_slice T i |i. i < length T}"
using finite_image_set by blast
next
fix ys
assume "ys ∈ {lms_slice T i |i. i < length T}"
hence "∃i < length T. ys = lms_slice T i"
by blast
then obtain i where
"i < length T"
"ys = lms_slice T i"
by blast
with ‹ys = lms_slice T i›
have R1: "i = n ⟹ list_less_eq_ns (lms_slice T n) ys"
by simp
from ‹i < length T› assms(2)
have R2_1: "i ≠ n ⟹ i < n"
by linarith
from A ‹lms_slice T n = [bot]› ‹i < length T› ‹ys = lms_slice T i›
have R2_2: "i < n ⟹ list_less_eq_ns (lms_slice T n) ys"
using list_less_eq_ns_def by fastforce
from R1 R2_2[OF R2_1]
show "list_less_eq_ns (lms_slice T n) ys"
by blast
next
show "lms_slice T n ∈ {lms_slice T i |i. i < length T}"
using assms(2) by auto
qed
qed
lemma unique_valid_lms_slice:
assumes "valid_list T"
and "length T = Suc n"
shows "∀i < n. lms_slice T i ≠ lms_slice T n"
proof (intro allI impI)
fix i
assume "i < n"
from lms_slice_last[OF assms]
have "lms_slice T n = [bot]"
by assumption
have "∀i < n. (lms_slice T i) ! 0 ≠ bot"
by (metis add_diff_cancel_left' assms abs_find_next_lms_lower_bound_1 less_SucI list_slice_Suc
lms_slice_def nth_Cons_0 plus_1_eq_Suc valid_list_def)
hence "∀i < n. bot < (lms_slice T i) ! 0"
using bot.not_eq_extremum by blast
with ‹lms_slice T n = [bot]› ‹i < n›
show "lms_slice T i ≠ lms_slice T n"
by auto
qed
lemma strict_Min_valid_lms_slice:
assumes "valid_list T"
and "length T = Suc n"
shows "∀i < n. list_less_ns (lms_slice T n) (lms_slice T i)"
by (metis add_diff_cancel_left' assms bot.not_eq_extremum abs_find_next_lms_lower_bound_1 less_Suc_eq
list_less_ns_cons_diff list_slice_Suc lms_slice_def lms_slice_last plus_1_eq_Suc
valid_list_def)
lemma ordlistns_lms_slice_imp_suffix_strict_sorted:
assumes "set xs ⊆ {i. abs_is_lms T i}" "ordlistns.strict_sorted (map (lms_slice T) xs)"
shows "ordlistns.strict_sorted (map (suffix T) xs)"
proof (intro sorted_wrt_mapI)
fix i j
assume "i < j" "j < length xs"
with sorted_wrt_mapD[OF assms(2), of i j]
have "list_less_ns (lms_slice T (xs ! i)) (lms_slice T (xs ! j))"
by blast
moreover
have "abs_is_lms T (xs ! i)"
using ‹i < j› ‹j < length xs› assms(1) subsetD by fastforce
hence "xs ! i < length T"
by (simp add: abs_is_lms_imp_less_length)
moreover
have "abs_is_lms T (xs ! j)"
using ‹j < length xs› assms(1) nth_mem by auto
hence "xs ! j < length T"
by (simp add: abs_is_lms_imp_less_length)
ultimately show "list_less_ns (suffix T (xs ! i)) (suffix T (xs ! j))"
using less_lms_slice_imp_suffix by blast
qed
section ‹Mapping from suffix to lists of LMS-Substrings›
text ‹ This section contains the mapping from LMS-type suffixes to suffixes of the reduced sequence.
The mapping is constructed in 3 major steps.
1) From suffix ID to a sequence of LMS-type suffix IDs
2) From a sequence of LMS-type suffix IDs to a sequence of LMS-substrings
3) From a LMS-type suffix to a reduced suffix
using the mappings 1, 2 and @{const ordlistns.elem_rank}
The mapping is also shown to be monotonic. ›
abbreviation "lms_substrs xs ≡ lms_slice xs ` {i. abs_is_lms xs i}"
abbreviation "lms_suffixes xs ≡ suffix xs ` {i. abs_is_lms xs i}"
abbreviation "nth_lms xs i ≡ (abs_find_next_lms xs ^^ Suc i) 0"
abbreviation "lms0 xs ≡ abs_find_next_lms xs 0"
abbreviation "lms0_suffix xs ≡ suffix xs (lms0 xs)"
abbreviation "lms0_substr xs ≡ lms_slice xs (lms0 xs)"
subsection ‹LMS Sequence›
definition lms_seq :: "'a :: {linorder,order_bot} list ⇒ nat ⇒ nat list"
where
"lms_seq xs i = filter (abs_is_lms xs) [i..<length xs]"
lemma lms_seq_distinct:
"distinct (lms_seq xs i)"
by (simp add: lms_seq_def)
lemma lms_seq_sorted:
"sorted (lms_seq xs i)"
by (simp add: filter_sorted lms_seq_def)
lemma lms_seq_strict_sorted:
"strict_sorted (lms_seq xs i)"
by (simp add: lms_seq_distinct lms_seq_sorted sorted_and_distinct_imp_strict_sorted)
lemma lms_seq_abs_is_lms_hd:
"abs_is_lms xs i ⟹ ∃ys. lms_seq xs i = i # ys"
by (simp add: filter_abs_is_lms_upt_hd abs_is_lms_imp_less_length lms_seq_def)
lemma length_lms_seq:
assumes "abs_is_lms xs i"
shows "length (lms_seq xs i) = card {j. abs_is_lms xs j ∧ i ≤ j}"
proof -
from distinct_length_filter[of "[i..<length xs]" "abs_is_lms xs"]
have "length (lms_seq xs i) = card ({x. abs_is_lms xs x} ∩ {i..<length xs})"
by (simp add: lms_seq_def)
moreover
have "{x. abs_is_lms xs x} ∩ {i..<length xs} = {x. abs_is_lms xs x ∧ i ≤ x}"
by (safe; clarsimp simp: abs_is_lms_imp_less_length)
ultimately show ?thesis
by simp
qed
lemma length_lms_seq_less:
assumes "abs_is_lms xs i"
and "abs_is_lms xs j"
and "i < j"
shows "length (lms_seq xs j) < length (lms_seq xs i)"
proof -
have "{k. abs_is_lms xs k ∧ j ≤ k} ⊆ {j. abs_is_lms xs j ∧ i ≤ j}"
using assms(3) by force
moreover
have "i ∈ {j. abs_is_lms xs j ∧ i ≤ j}"
using assms(1) less_or_eq_imp_le by blast
moreover
have "i ∉ {k. abs_is_lms xs k ∧ j ≤ k}"
using assms(3) linorder_not_less by blast
ultimately have "{k. abs_is_lms xs k ∧ j ≤ k} ⊂ {j. abs_is_lms xs j ∧ i ≤ j}"
by blast
hence "card {k. abs_is_lms xs k ∧ j ≤ k} < card {j. abs_is_lms xs j ∧ i ≤ j}"
by (simp add: lms_finite psubset_card_mono)
then show ?thesis
by (simp add: assms(1) assms(2) length_lms_seq)
qed
lemma lms_seq_nth_0:
"lms_seq xs (Suc k) ≠ [] ⟹ lms_seq xs (Suc k) ! 0 = abs_find_next_lms xs k"
unfolding lms_seq_def
apply (simp add: abs_find_next_lms_funpow_Suc abs_find_next_lms_def)
apply (drule filter_find)
by (clarsimp split: option.splits)
lemma lms_seq_eq_cons_lms:
assumes "abs_is_lms xs i" "i < k" "k ≤ abs_find_next_lms xs i"
shows "lms_seq xs i = i # lms_seq xs k"
proof -
have "filter (abs_is_lms xs) [Suc i..<k] = []"
using assms(1) assms(2) assms(3) filter_no_lms1 by blast
moreover
have "[i..<length xs] = i # [Suc i..<k] @ [k..<length xs]"
by (metis Suc_leI assms dual_order.trans abs_find_next_lms_le_length abs_is_lms_imp_less_length
le_add_diff_inverse upt_add_eq_append upt_conv_Cons)
hence "lms_seq xs i = i # (filter (abs_is_lms xs) [Suc i..<k]) @ (filter (abs_is_lms xs) [k..<length xs])"
by (simp add: assms(1) lms_seq_def)
ultimately show ?thesis
by (metis append_Nil lms_seq_def)
qed
lemma lms_seq_not_lms:
assumes "¬abs_is_lms xs i" "i < k" "k ≤ abs_find_next_lms xs i"
shows "lms_seq xs i = lms_seq xs k"
proof -
have "filter (abs_is_lms xs) [i..<k] = []"
using assms filter_no_lms2 by blast
moreover
have "[i..<length xs] = [i..<k] @ [k..<length xs]"
by (metis assms(2,3) dual_order.trans abs_find_next_lms_le_length le_add_diff_inverse
less_or_eq_imp_le upt_add_eq_append)
ultimately show ?thesis
by (simp add: lms_seq_def)
qed
lemma lms_seq_eq_cons:
assumes "lms_seq xs (Suc i) ≠ []"
shows "lms_seq xs (Suc i) = abs_find_next_lms xs i # lms_seq xs (Suc (abs_find_next_lms xs i))"
proof -
from lms_seq_nth_0[OF assms]
have "lms_seq xs (Suc i) ! 0 = abs_find_next_lms xs i" .
moreover
have "i < abs_find_next_lms xs i"
by (metis Suc_lessD assms filter.simps(1) abs_find_next_lms_lower_bound_1 lms_seq_def upt_rec)
hence "Suc i ≤ abs_find_next_lms xs i"
by simp
hence "lms_seq xs (Suc i) = lms_seq xs (abs_find_next_lms xs i)"
by (metis abs_find_next_lms_abs_is_lms abs_find_next_lms_le_Suc lms_seq_not_lms order_le_imp_less_or_eq)
ultimately show ?thesis
by (metis Suc_leI assms filter.simps(1) abs_find_next_lms_less_length_abs_is_lms
abs_find_next_lms_lower_bound_1 lessI lms_seq_def lms_seq_eq_cons_lms upt_rec)
qed
lemma lms_seq_nth_abs_is_lms:
"i < length (lms_seq xs k) ⟹ abs_is_lms xs ((lms_seq xs k) ! i)"
unfolding lms_seq_def
using nth_mem by fastforce
lemma lms_seq_0:
"lms_seq xs 0 = lms_seq xs (Suc 0)"
by (metis filter_abs_is_lms_upt_0 lms_seq_def)
lemma lms_seq_nth:
"i < length (lms_seq xs (Suc k)) ⟹ lms_seq xs (Suc k) ! i = ((abs_find_next_lms xs)^^(Suc i)) k"
proof (induct i arbitrary: k)
case 0
then show ?case
by (simp add: lms_seq_nth_0)
next
case (Suc i)
note IH = this
let ?j = "abs_find_next_lms xs k"
have "lms_seq xs (Suc k) = ?j # lms_seq xs (Suc ?j)"
using Suc.prems lms_seq_eq_cons by force
with IH(1)[of "?j"]
have "lms_seq xs (Suc ?j) ! i = (abs_find_next_lms xs ^^ Suc i) ?j"
using Suc.prems by fastforce
then show ?case
by (simp add: ‹lms_seq xs (Suc k) = ?j # lms_seq xs (Suc ?j)› funpow_swap1)
qed
lemma inj_on_lms_seq:
"inj_on (lms_seq xs) {i. abs_is_lms xs i}"
by (metis (mono_tags, lifting) inj_onI list.inject lms_seq_abs_is_lms_hd mem_Collect_eq)
lemma list_app_imp_suffix:
"xs = ys @ zs ⟹ suffix xs (length ys) = zs"
by auto
abbreviation "nth_lms_seq xs i ≡ lms_seq xs (nth_lms xs i)"
abbreviation "lms0_seq xs ≡ lms_seq xs (lms0 xs)"
lemma lms_seq_0_zeroth_lms:
"lms_seq xs 0 = lms0_seq xs"
by (metis gr_zeroI abs_is_lms_0 le_refl lms_seq_not_lms)
lemma lms_seq_set:
"set (lms_seq xs i) = {k. abs_is_lms xs k ∧ i ≤ k}"
by (intro equalityI subsetI; clarsimp simp add: abs_is_lms_def suffix_type_s_bound lms_seq_def)
lemma lms_seq_last_eq_length:
"length (lms_seq xs i) = Suc n ⟹
abs_find_next_lms xs ((lms_seq xs i) ! n) = length xs"
proof -
let ?k = "(lms_seq xs i) ! n"
assume "length (lms_seq xs i) = Suc n"
hence "i ≤ ?k"
by (metis (no_types, lifting) lessI lms_seq_set mem_Collect_eq nth_mem)
have "∀j < length xs. ?k < j ⟶ ¬abs_is_lms xs j"
proof safe
fix j
assume "j < length xs" "?k < j" "abs_is_lms xs j"
hence "j ∈ set (lms_seq xs i)"
using ‹i ≤ lms_seq xs i ! n› lms_seq_set by fastforce
hence "∃j'< length (lms_seq xs i). (lms_seq xs i) ! j' = j"
by (simp add: in_set_conv_nth)
then obtain j' where
"j' < length (lms_seq xs i)"
"(lms_seq xs i) ! j' = j"
by blast
with strict_sorted_nth_less_mono[OF lms_seq_strict_sorted[of xs i], of n j']
have "n < j'"
using ‹length (lms_seq xs i) = Suc n› ‹lms_seq xs i ! n < j› by fastforce
then show False
using ‹j' < length (lms_seq xs i)› ‹length (lms_seq xs i) = Suc n› by linarith
qed
then show ?thesis
by (meson abs_find_next_lms_le_length abs_find_next_lms_less_length_abs_is_lms
abs_find_next_lms_strict_upper_imp_lower_bound order.strict_iff_order)
qed
lemma lms0_seq_has_all_lms:
"set (lms0_seq xs) = {i. abs_is_lms xs i}"
by (metis (mono_tags, lifting) Collect_cong linorder_le_less_linear lms_seq_set mem_Collect_eq
no_lms_between_i_and_next set_lms_gr_0)
lemma lms0_seq_length:
"length (lms0_seq xs) = card {i. abs_is_lms xs i}"
by (metis distinct_card lms0_seq_has_all_lms lms_seq_distinct)
lemma lms0_seq_nth:
"i < card {i. abs_is_lms xs i} ⟹ lms0_seq xs ! i = nth_lms xs i"
by (metis lms0_seq_length lms_seq_0 lms_seq_0_zeroth_lms lms_seq_nth)
lemma lms_seq_Suc1:
assumes "abs_is_lms xs i"
shows "lms_seq xs i = i # lms_seq xs (Suc i)"
by (simp add: assms filter_abs_is_lms_upt_hd abs_is_lms_imp_less_length lms_seq_def)
lemma lms_seq_Suc2:
assumes "¬abs_is_lms xs i"
shows "lms_seq xs i = lms_seq xs (Suc i)"
by (metis (no_types, lifting) assms dual_order.strict_trans2 filter.simps(2) lessI
less_or_eq_imp_le lms_seq_def upt_rec)
lemma lms_seq_suf:
"i ≤ j ⟹ ∃ys. lms_seq xs i = ys @ lms_seq xs j"
proof (induct "j - i" arbitrary: i j)
case 0
then show ?case
by force
next
case (Suc x)
note IH = this
hence "∃j'. j = Suc j'"
by (metis Suc_le_D diff_le_self)
then obtain j' where
A: "j = Suc j'"
by blast
with IH(1)[of j' i] IH(2,3)
have B: "∃ys. lms_seq xs i = ys @ lms_seq xs j'"
by (metis Suc_diff_le Suc_eq_plus1 add.commute add_left_imp_eq antisym_conv2 le_Suc_eq
zero_less_Suc zero_less_diff)
show ?case
proof (cases "abs_is_lms xs j'")
assume "abs_is_lms xs j'"
with A B lms_seq_Suc1[of xs j']
show ?thesis
by auto
next
assume "¬abs_is_lms xs j'"
with A B lms_seq_Suc2[of xs j']
show ?thesis
by simp
qed
qed
lemma lms_lms_seq_is_suffix:
assumes "abs_is_lms xs i"
shows "∃k < length (lms0_seq xs).
suffix (lms0_seq xs) k = lms_seq xs i"
proof -
have "lms0 xs ≤ i"
by (metis assms bot_nat_0.not_eq_extremum abs_is_lms_0 linorder_not_less no_lms_between_i_and_next)
with lms_seq_suf[of "lms0 xs" i xs]
show ?thesis
by (metis assms length_Cons length_append length_greater_0_conv less_add_same_cancel1
less_numeral_extra(1) list.size(3) list_app_imp_suffix lms_seq_Suc1 plus_1_eq_Suc
zero_eq_add_iff_both_eq_0)
qed
lemma nth_lms:
"i < card {i. abs_is_lms xs i} ⟹
abs_is_lms xs (nth_lms xs i)"
proof -
assume "i < card {i. abs_is_lms xs i}"
hence "i < length (lms0_seq xs)"
by (metis distinct_card lms0_seq_has_all_lms lms_seq_distinct)
moreover
have "∃k. lms0 xs = Suc k"
by (metis calculation filter.simps(1) abs_find_next_lms_eq_Suc less_nat_zero_code list.size(3)
lms_seq_def upt.simps(1))
then obtain k where "lms0 xs = Suc k" by blast
ultimately show ?thesis
by (metis lms_seq_0 lms_seq_0_zeroth_lms lms_seq_nth lms_seq_nth_abs_is_lms)
qed
lemma card_abs_find_next_lms_funpow:
"i < card {k. abs_is_lms xs k} ⟹
card {k. abs_is_lms xs k ∧ k < nth_lms xs i} = i"
proof (induct i)
case 0
then show ?case
by (metis (mono_tags, lifting) Collect_empty_eq card_eq_0_iff comp_apply funpow.simps(2)
funpow_0 gr_zeroI abs_is_lms_0 no_lms_between_i_and_next)
next
case (Suc i)
note IH = this
let ?i = "nth_lms xs i"
let ?j = "nth_lms xs (Suc i)"
let ?A = "{k. abs_is_lms xs k ∧ k < ?i}"
let ?B = "{k. abs_is_lms xs k ∧ k < ?j}"
from IH
have A: "card ?A = i"
using Suc_lessD by blast
moreover
have P: "?i < ?j"
by (metis Suc.prems Suc_lessD abs_find_next_lms_funpow_Suc abs_find_next_lms_lower_bound_1
abs_is_lms_imp_less_length nth_lms)
with no_lms_between_i_and_next_funpow
have B: "∀j. ?i < j ∧ j < ?j ⟶ j ∉ ?B"
by blast
have C: "?i ∈ ?B"
using P Suc.prems Suc_lessD nth_lms by fastforce
have D: "?A ⊆ ?B"
using P by force
have "?B = insert ?i ?A"
using B nat_neq_iff C D
by (intro equalityI subsetI insert_iff[THEN iffD2]; auto)
moreover
have "?i ∉ ?A"
by blast
hence "card (insert ?i ?A) = Suc (card ?A)"
by simp
ultimately show ?case
by simp
qed
lemma lms_seq_nth_suffix:
"i < card {i. abs_is_lms xs i} ⟹
suffix (lms0_seq xs) i = nth_lms_seq xs i"
proof -
let ?i = "lms0 xs"
let ?j = "nth_lms xs i"
assume A: "i < card {i. abs_is_lms xs i}"
from nth_lms[OF A]
have "abs_is_lms xs ?j" .
moreover
have "?i ≤ ?j"
by (metis bot_nat_0.not_eq_extremum calculation abs_is_lms_0 linorder_not_less
no_lms_between_i_and_next)
hence "[?i..<length xs] = [?i..<?j] @ [?j..<length xs]"
by (metis abs_find_next_lms_funpow_Suc abs_find_next_lms_le_length le_add_diff_inverse
upt_add_eq_append)
moreover
have "length (filter (abs_is_lms xs) [?i..<?j]) = card {k. abs_is_lms xs k ∧ k < ?j}"
proof -
from filter_no_lms2[of xs 0 ?i]
have "filter (abs_is_lms xs) [0..<?i] = []"
using abs_is_lms_0 by fastforce
moreover
have "[0..<?j] = [0..<?i] @ [?i..<?j]"
by (metis ‹?i ≤ ?j› bot_nat_0.not_eq_extremum le_add_diff_inverse less_or_eq_imp_le
upt_add_eq_append)
ultimately have "filter (abs_is_lms xs) [0..<?j] = filter (abs_is_lms xs) [?i..<?j]"
by fastforce
moreover
have "length (filter (abs_is_lms xs) [0..<?j]) = card {k. abs_is_lms xs k ∧ k < ?j}"
proof -
from length_filter_conv_card[of "abs_is_lms xs" "[0..<?j]", simplified length_upt]
have "length (filter (abs_is_lms xs) [0..<?j]) = card {k. k < ?j ∧ abs_is_lms xs ([0..<?j] ! k)}"
by simp
moreover
have "{k. k < ?j ∧ abs_is_lms xs ([0..<?j] ! k)} = {k. abs_is_lms xs k ∧ k < ?j}"
by force
ultimately show ?thesis
by simp
qed
ultimately show ?thesis
by presburger
qed
ultimately show ?thesis
by (metis (no_types, lifting) A Collect_cong card_abs_find_next_lms_funpow filter_append
list_app_imp_suffix lms_seq_def)
qed
subsection ‹LMS-Substring Sequence›
definition lms_substr_seq :: "'a :: {linorder,order_bot} list ⇒ nat ⇒ 'a list list"
where
"lms_substr_seq xs i = map (lms_slice xs) (lms_seq xs i)"
lemma lms_substr_seq_length:
"length (lms_substr_seq xs i) = length (lms_seq xs i)"
by (simp add: lms_substr_seq_def)
lemma inj_on_map_lms_slice_lms_seq:
"inj_on (map (lms_slice xs)) (lms_seq xs ` {i. abs_is_lms xs i})"
proof (intro inj_onI)
fix x y
assume "x ∈ lms_seq xs ` {i. abs_is_lms xs i}"
"y ∈ lms_seq xs ` {i. abs_is_lms xs i}"
"map (lms_slice xs) x = map (lms_slice xs) y"
then obtain i j where
"x = lms_seq xs i" "y = lms_seq xs j"
"map (lms_slice xs) (lms_seq xs i) = map (lms_slice xs) (lms_seq xs j)"
"abs_is_lms xs i" "abs_is_lms xs j"
by clarsimp+
then have "lms_seq xs i = lms_seq xs j"
by (metis length_lms_seq_less length_map nat_neq_iff)
then show "x = y"
by (simp add: ‹x = lms_seq xs i› ‹y = lms_seq xs j›)
qed
lemma inj_on_lms_substr_seq:
"inj_on (lms_substr_seq xs) {i. abs_is_lms xs i}"
unfolding lms_substr_seq_def
using comp_inj_on[OF inj_on_lms_seq inj_on_map_lms_slice_lms_seq, simplified o_def]
by blast
lemma lms_substr_seq_nth:
"i < length (lms_substr_seq xs (Suc k)) ⟹
lms_substr_seq xs (Suc k) ! i = lms_slice xs ((abs_find_next_lms xs ^^ Suc i) k)"
by (simp add: lms_seq_nth lms_substr_seq_def)
lemma lms_substr_seq_nth_abs_is_lms:
"i < length (lms_substr_seq xs k) ⟹
(lms_substr_seq xs k) ! i ∈ lms_substrs xs"
by (simp add: lms_seq_nth_abs_is_lms lms_substr_seq_def)
definition suffix_to_id
where
"suffix_to_id xs ys = length xs - length ys"
lemma suffix_lengths_neq:
"⟦i < j; j < length xs⟧ ⟹ length (suffix xs i) > length (suffix xs j)"
by simp
lemma inj_on_suffix_to_id:
"inj_on (suffix_to_id xs) (suffix xs ` {i. abs_is_lms xs i})"
by (intro inj_onI; clarsimp simp: suffix_to_id_def abs_is_lms_imp_less_length less_or_eq_imp_le)
lemma suffix_id_suffix:
"i < length xs ⟹ suffix_to_id xs (suffix xs i) = i"
by (simp add: suffix_to_id_def)
lemma suffix_to_id_image:
"suffix_to_id xs ` suffix xs ` {i. abs_is_lms xs i} = {i. abs_is_lms xs i}"
proof safe
fix i
assume "abs_is_lms xs i"
then show "abs_is_lms xs (suffix_to_id xs (suffix xs i))"
by (simp add: abs_is_lms_imp_less_length suffix_id_suffix)
next
fix i
assume "abs_is_lms xs i"
then show "i ∈ suffix_to_id xs ` lms_suffixes xs"
by (simp add: image_iff abs_is_lms_imp_less_length suffix_id_suffix)
qed
abbreviation "lms_substr_seq_id xs ≡ (lms_substr_seq xs) ∘ (suffix_to_id xs)"
lemma lms_subtrs_seq_id_suffix:
"lms_substr_seq_id xs (suffix xs i) = lms_substr_seq xs i"
apply simp
apply (cases "i < length xs")
apply (simp add: suffix_id_suffix)
by (simp add: lms_seq_def lms_substr_seq_def suffix_to_id_def)
lemma lms_substr_seq_id_nth_abs_is_lms:
"i < length (lms_substr_seq_id xs (suffix xs k)) ⟹
(lms_substr_seq_id xs (suffix xs k)) ! i ∈ lms_substrs xs"
by (simp add: lms_seq_nth_abs_is_lms lms_substr_seq_def)
lemma inj_on_lms_substr_seq_o_suffix_to_id:
"inj_on (lms_substr_seq_id xs) (lms_suffixes xs)"
proof -
have "lms_substr_seq xs = map (lms_slice xs) ∘ lms_seq xs"
using lms_substr_seq_def by fastforce
with comp_inj_on[OF inj_on_lms_seq inj_on_map_lms_slice_lms_seq, of xs]
have "inj_on (lms_substr_seq xs) {i. abs_is_lms xs i}"
by simp
with comp_inj_on[OF inj_on_suffix_to_id[of xs], simplified suffix_to_id_image[of xs]]
show ?thesis
by blast
qed
lemma list_less_ns_lms_substr_seq_suffix:
assumes "abs_is_lms xs i"
and "abs_is_lms xs j"
and "nslexordp list_less_ns (lms_substr_seq xs i) (lms_substr_seq xs j)"
shows "list_less_ns (suffix xs i) (suffix xs j)"
proof -
have "∃i'. i = Suc i'"
using assms(1) abs_is_lms_def by blast
then obtain i' where
"i = Suc i'"
by blast
hence "abs_find_next_lms xs i' = i"
using assms(1) abs_find_next_lms_abs_is_lms by blast
have A: "⋀k. k < length (lms_substr_seq xs i) ⟹
lms_substr_seq xs i ! k = lms_slice xs ((abs_find_next_lms xs ^^ k) i)"
by (simp add: ‹abs_find_next_lms xs i' = i› ‹i = Suc i'› funpow_swap1 lms_substr_seq_nth)
have "∃j'. j = Suc j'"
using assms(2) abs_is_lms_def by blast
then obtain j' where
"j = Suc j'"
by blast
hence "abs_find_next_lms xs j' = j"
using assms(2) abs_find_next_lms_abs_is_lms by blast
have B: "⋀k. k < length (lms_substr_seq xs j) ⟹
lms_substr_seq xs j ! k = lms_slice xs ((abs_find_next_lms xs ^^ k) j)"
by (simp add: ‹abs_find_next_lms xs j' = j› ‹j = Suc j'› funpow_swap1 lms_substr_seq_nth)
let ?c1 = "∃b c as bs cs.
lms_substr_seq xs i = as @ b # bs ∧ lms_substr_seq xs j = as @ c # cs ∧
list_less_ns b c"
let ?c2 = "∃c cs. lms_substr_seq xs i = lms_substr_seq xs j @ c # cs"
from nslexordpE[OF assms(3)]
have "?c1 ∨ ?c2" .
moreover
have "?c1 ⟹ ?thesis"
proof -
assume ?c1
then obtain b c as bs cs where
"lms_substr_seq xs i = as @ b # bs"
"lms_substr_seq xs j = as @ c # cs"
"list_less_ns b c"
by blast
let ?b = "lms_slice xs ((abs_find_next_lms xs ^^ (length as)) i)"
from lms_substr_seq_nth[of "length as" xs i'] ‹i = Suc i'›
‹lms_substr_seq xs i = as @ b # bs›
have "b = lms_slice xs ((abs_find_next_lms xs ^^ Suc (length as)) i')"
by simp
with ‹abs_find_next_lms xs i' = i›
have "b = ?b"
by (simp add: funpow_swap1)
let ?c = "lms_slice xs ((abs_find_next_lms xs ^^ (length as)) j)"
from lms_substr_seq_nth[of "length as" xs j'] ‹j = Suc j'›
‹lms_substr_seq xs j = as @ c # cs›
have "c = lms_slice xs ((abs_find_next_lms xs ^^ Suc (length as)) j')"
by simp
with ‹abs_find_next_lms xs j' = j›
have "c = lms_slice xs ((abs_find_next_lms xs ^^ (length as)) j)"
by (simp add: funpow_swap1)
have P: "∀k<length as. lms_slice xs ((abs_find_next_lms xs ^^ k) i) =
lms_slice xs ((abs_find_next_lms xs ^^ k) j)"
proof (safe)
fix k
assume "k < length as"
with ‹lms_substr_seq xs i = as @ b # bs› A[of k]
have "as ! k = lms_slice xs ((abs_find_next_lms xs ^^ k) i)"
by (simp add: nth_append)
moreover
from ‹lms_substr_seq xs j = as @ c # cs› ‹k < length as› B[of k]
have "as ! k = lms_slice xs ((abs_find_next_lms xs ^^ k) j)"
by (simp add: nth_append)
ultimately show
"lms_slice xs ((abs_find_next_lms xs ^^ k) i) =
lms_slice xs ((abs_find_next_lms xs ^^ k) j)"
by simp
qed
have Q: "list_less_ns (suffix xs ((abs_find_next_lms xs ^^ (length as)) i))
(suffix xs ((abs_find_next_lms xs ^^ (length as)) j))"
by (metis ‹b = ?b› ‹c = ?c› ‹list_less_ns b c› drop_eq_Nil abs_find_next_lms_lower_bound_2
less_lms_slice_imp_suffix list_less_ns_nil lms_slice_eq_suffix
not_le_imp_less ordlistns.less_asym)
show ?thesis
proof (cases "length as")
case 0
then show ?thesis
using Q by force
next
case (Suc n)
assume "length as = Suc n"
moreover
from lms_slice_eq_suffix_less_funpow[OF P]
have "list_less_ns (suffix xs i) (suffix xs j) =
list_less_ns (suffix xs ((abs_find_next_lms xs ^^ (length as)) i))
(suffix xs ((abs_find_next_lms xs ^^ (length as)) j))"
using lessI by presburger
ultimately show ?thesis
using Q by blast
qed
qed
moreover
have "?c2 ⟹ ?thesis"
proof -
assume ?c2
then obtain c cs where
"lms_substr_seq xs i = lms_substr_seq xs j @ c # cs"
by blast
have "lms_substr_seq xs j ≠ []"
by (metis assms(2) list.distinct(1) list.map_disc_iff lms_seq_abs_is_lms_hd lms_substr_seq_def)
hence "∃n. length (lms_substr_seq xs j) = Suc n"
using not0_implies_Suc by auto
then obtain n where
"length (lms_substr_seq xs j) = Suc n"
by blast
have P: "∀k < Suc n. lms_slice xs ((abs_find_next_lms xs ^^ k) i) =
lms_slice xs ((abs_find_next_lms xs ^^ k) j)"
proof safe
fix k
assume "k < Suc n"
hence "lms_substr_seq xs j ! k = lms_slice xs ((abs_find_next_lms xs ^^ k) j)"
by (simp add: B ‹length (lms_substr_seq xs j) = Suc n›)
moreover
from ‹lms_substr_seq xs i = lms_substr_seq xs j @ c # cs› ‹k < Suc n›
have "lms_substr_seq xs i ! k = lms_slice xs ((abs_find_next_lms xs ^^ k) j)"
by (simp add: B ‹length (lms_substr_seq xs j) = Suc n› nth_append)
moreover
have "lms_substr_seq xs i ! k = lms_slice xs ((abs_find_next_lms xs ^^ k) i)"
using A ‹k < Suc n› ‹length (lms_substr_seq xs j) = Suc n›
‹lms_substr_seq xs i = lms_substr_seq xs j @ c # cs› by auto
ultimately show
"lms_slice xs ((abs_find_next_lms xs ^^ k) i) =
lms_slice xs ((abs_find_next_lms xs ^^ k) j)"
by simp
qed
have "list_less_ns (suffix xs i) (suffix xs j) =
list_less_ns (suffix xs ((abs_find_next_lms xs ^^ Suc n) i))
(suffix xs ((abs_find_next_lms xs ^^ Suc n) j))"
using lms_slice_eq_suffix_less_funpow[OF P]
by blast
moreover
from lms_seq_last_eq_length[of xs j n]
have "(abs_find_next_lms xs ^^ Suc n) j = length xs"
by (metis ‹abs_find_next_lms xs j' = j› ‹j = Suc j'› ‹length (lms_substr_seq xs j) = Suc n›
funpow_swap1 length_map lessI lms_seq_nth lms_substr_seq_def)
hence "suffix xs ((abs_find_next_lms xs ^^ Suc n) j) = []"
by force
ultimately show ?thesis
by (metis P ‹lms_substr_seq xs i = lms_substr_seq xs j @ c # cs› append_self_conv assms(1,2)
abs_is_lms_imp_less_length list.distinct(1) list_less_ns_nil suffix_id_suffix
lms_slice_eq_suffix_less_funpow ordlistns.not_less_iff_gr_or_eq)
qed
ultimately show ?thesis
by blast
qed
lemma monotone_on_lms_substr_seq_id:
"monotone_on (lms_suffixes xs) list_less_ns (nslexordp list_less_ns) (lms_substr_seq_id xs)"
(is "monotone_on ?A ?orda ?ordb ?f")
proof -
let ?B = "?f ` ?A"
from inj_on_imp_bij_betw[OF inj_on_lms_substr_seq_o_suffix_to_id]
have A: "bij_betw ?f ?A ?B" .
with bij_betw_inv_alt
have "∃g. bij_betw g ?B ?A ∧ inverses_on ?f g ?A ?B"
by blast
then obtain g where B:
"bij_betw g ?B ?A"
"inverses_on ?f g ?A ?B"
by blast
have C: "monotone_on ?B ?ordb ?orda g"
proof (intro monotone_onI)
fix x y
assume "x ∈ ?B" "y ∈ ?B" "nslexordp list_less_ns x y"
moreover
have "∃i. abs_is_lms xs i ∧ g x = suffix xs i"
using ‹x ∈ ?B› bij_betw_apply B(1) by fastforce
then obtain i where
"abs_is_lms xs i" "g x = suffix xs i"
by blast
moreover
have "∃j. abs_is_lms xs j ∧ g y = suffix xs j"
using ‹y ∈ ?B› bij_betw_apply B(1) by fastforce
then obtain j where
"abs_is_lms xs j" "g y = suffix xs j"
by blast
ultimately show "list_less_ns (g x) (g y)"
using list_less_ns_lms_substr_seq_suffix[of xs i j]
by (metis (mono_tags, lifting) B(2) comp_def inverses_onD2 abs_is_lms_imp_less_length
suffix_id_suffix)
qed
from nslexordp_asymp[of list_less_ns]
have "asymp_on ?B ?ordb"
using asympD by fastforce
from totalp_on_subset[OF nslexordp_totalp[of list_less_ns]]
have "totalp_on ?B ?ordb"
using ordlistns.totalp_on_less by blast
note D = ‹asymp_on ?B ?ordb› ‹totalp_on ?B ?ordb›
from monotone_on_bij_betw_inv[OF C D _ _ B(1) A inverses_on_sym[THEN iffD1, OF B(2)],
simplified]
show ?thesis .
qed
lemma list_less_ns_suffix_lms_substr_seq:
assumes "abs_is_lms xs i"
and "abs_is_lms xs j"
and "list_less_ns (suffix xs i) (suffix xs j)"
shows "nslexordp list_less_ns (lms_substr_seq xs i) (lms_substr_seq xs j)"
using monotone_onD[OF monotone_on_lms_substr_seq_id _ _ assms(3)]
assms(1,2) abs_is_lms_imp_less_length suffix_id_suffix by fastforce
lemma lms_substr_seq_suf:
"i ≤ j ⟹ ∃ys. lms_substr_seq xs i = ys @ lms_substr_seq xs j"
unfolding lms_substr_seq_def
by (frule lms_seq_suf[of _ _ xs]; clarsimp)
lemma lms_lms_substr_seq_is_suffix:
assumes "abs_is_lms xs i"
shows "∃k < length (lms_substr_seq xs (abs_find_next_lms xs 0)).
suffix (lms_substr_seq xs (abs_find_next_lms xs 0)) k = lms_substr_seq xs i"
unfolding lms_substr_seq_def
by (metis assms length_map lms_lms_seq_is_suffix[of xs i] suffix_map)
lemma lms_substr_seq_nth_suffix:
"i < card {i. abs_is_lms xs i} ⟹
suffix (lms_substr_seq xs (abs_find_next_lms xs 0)) i =
lms_substr_seq xs ((abs_find_next_lms xs ^^ Suc i) 0)"
by (simp add: lms_seq_nth_suffix lms_substr_seq_def suffix_map)
subsection ‹LMS Map›
lemma finite_lms_substrs:
"finite (lms_substrs xs)"
by (simp add: lms_finite)
definition lms_map :: "('a :: {linorder, order_bot}) list ⇒ 'a list ⇒ nat list"
where
"lms_map xs ≡ (map (ordlistns.elem_rank (lms_substrs xs))) ∘ (lms_substr_seq_id xs)"
lemma lms_substr_seq_o_suffix_to_id_range:
"(lms_substr_seq xs ∘ suffix_to_id xs) ` lms_suffixes xs ⊆ {ys. set ys ⊆ lms_substrs xs}"
unfolding lms_substr_seq_def suffix_to_id_def
by (safe; clarsimp simp: lms_seq_set)
lemma lms_map_o_def:
"lms_map xs ys = map (ordlistns.elem_rank (lms_substrs xs)) (lms_substr_seq_id xs ys)"
by (simp add: lms_map_def)
lemma inj_on_lms_map:
"inj_on (lms_map xs) (lms_suffixes xs)"
proof -
note A = comp_inj_on[OF inj_on_lms_substr_seq_o_suffix_to_id]
note B = inj_on_subset[OF bij_betw_imp_inj_on[OF bij_betw_map[OF ordlistns.bij_betw_elem_rank_upt]]]
from A[OF B, OF finite_lms_substrs lms_substr_seq_o_suffix_to_id_range, of xs]
show ?thesis
by (simp add: lms_map_def)
qed
lemma lms_map_length:
"length (lms_map xs ys) = length (lms_substr_seq xs (suffix_to_id xs ys))"
by (simp add: lms_map_def)
lemma lms_map_nth_suffix:
"i < card {i. abs_is_lms xs i} ⟹
suffix (lms_map xs (suffix xs (abs_find_next_lms xs 0))) i =
lms_map xs (suffix xs ((abs_find_next_lms xs ^^ Suc i) 0))"
by (simp add: abs_find_next_lms_le_length lms_map_def lms_seq_nth_suffix lms_substr_seq_def suffix_map
suffix_to_id_def)
lemma lms_lms_map_is_suffix:
assumes "abs_is_lms xs i"
shows "∃k < length (lms_map xs (suffix xs (abs_find_next_lms xs 0))).
suffix (lms_map xs (suffix xs (abs_find_next_lms xs 0))) k = lms_map xs (suffix xs i)"
proof -
have "suffix_to_id xs (suffix xs i) = i"
by (simp add: assms abs_is_lms_imp_less_length suffix_id_suffix)
moreover
have "suffix_to_id xs (suffix xs (abs_find_next_lms xs 0)) = abs_find_next_lms xs 0"
by (simp add: abs_find_next_lms_le_length suffix_to_id_def)
moreover
from lms_lms_substr_seq_is_suffix[OF assms]
obtain k where
"k < length (lms_substr_seq xs (abs_find_next_lms xs 0))"
"suffix (lms_substr_seq xs (abs_find_next_lms xs 0)) k = lms_substr_seq xs i"
by blast
moreover
have "k < length (lms_map xs (suffix xs (abs_find_next_lms xs 0)))"
by (simp add: calculation(2) calculation(3) lms_map_length)
moreover
have "suffix (lms_map xs (suffix xs (abs_find_next_lms xs 0))) k = lms_map xs (suffix xs i)"
by (simp add: lms_map_def calculation suffix_map)
ultimately show ?thesis
by blast
qed
lemma length_reduced_seq:
"length (lms_map xs (suffix xs (abs_find_next_lms xs 0))) = card (lms_suffixes xs)"
apply (simp add: lms_map_length lms_substr_seq_length)
apply (cases "abs_find_next_lms xs 0 < length xs")
apply (simp add: suffix_id_suffix)
apply (subst distinct_card[OF lms_seq_distinct[of xs "abs_find_next_lms xs 0"], symmetric])
apply (simp add: lms0_seq_has_all_lms)
apply (metis card_image inj_on_suffix_to_id suffix_to_id_image)
by (metis card_eq_0_iff diff_diff_cancel empty_set filter.simps(1) abs_find_next_lms_le_length
lms0_seq_has_all_lms image_is_empty length_drop linorder_le_less_linear list.size(3)
lms_seq_def suffix_to_id_def upt_eq_Nil_conv)
corollary lms_lms_map_in_suffixes:
"abs_is_lms xs i ⟹
lms_map xs (suffix xs i) ∈
suffix (lms_map xs (suffix xs (abs_find_next_lms xs 0))) ` {0..<card (lms_suffixes xs)}"
by (metis atLeastLessThan_iff imageI length_reduced_seq lms_lms_map_is_suffix zero_le)
lemma card_lms_suffixes:
"card (lms_suffixes xs) = card {i. abs_is_lms xs i}"
by (metis card_image inj_on_suffix_to_id suffix_to_id_image)
lemma lms_map_image:
"lms_map xs ` lms_suffixes xs =
suffix (lms_map xs (suffix xs (abs_find_next_lms xs 0))) ` {0..<card (lms_suffixes xs)}"
proof (safe)
fix i
assume "abs_is_lms xs i"
then show "lms_map xs (suffix xs i) ∈
suffix (lms_map xs (lms0_suffix xs)) ` {0..<card (lms_suffixes xs)}"
using lms_lms_map_in_suffixes by blast
next
fix i
assume "i ∈ {0..<card (lms_suffixes xs)}"
with card_lms_suffixes
have "i < card {i. abs_is_lms xs i}"
by (metis atLeastLessThan_iff)
with lms_map_nth_suffix[of i xs]
have "suffix (lms_map xs (lms0_suffix xs)) i = lms_map xs (suffix xs (nth_lms xs i))"
by blast
moreover
have "suffix xs (nth_lms xs i) ∈ lms_suffixes xs"
using ‹i < card {i. abs_is_lms xs i}› nth_lms by fastforce
ultimately show "suffix (lms_map xs (lms0_suffix xs)) i ∈ lms_map xs ` lms_suffixes xs"
by blast
qed
lemma monotone_on_lms_map:
"monotone_on (lms_suffixes xs) list_less_ns list_less_ns (lms_map xs)"
proof (intro monotone_onI)
fix x y
assume "x ∈ lms_suffixes xs" "y ∈ lms_suffixes xs" "list_less_ns x y"
with monotone_onD[OF monotone_on_lms_substr_seq_id, of x xs y]
have "nslexordp list_less_ns (lms_substr_seq_id xs x) (lms_substr_seq_id xs y)"
by blast
moreover
have "⋀x. lms_map xs x = map (ordlistns.elem_rank (lms_substrs xs)) (lms_substr_seq_id xs x)"
by (simp add: lms_map_def)
moreover
{
have "set (lms_substr_seq_id xs x) ⊆ lms_substrs xs"
by (simp add: Collect_mono_iff image_mono lms_seq_set lms_substr_seq_def)
moreover
have "set (lms_substr_seq_id xs y) ⊆ lms_substrs xs"
by (simp add: Collect_mono_iff image_mono lms_seq_set lms_substr_seq_def)
ultimately have
"nslexordp list_less_ns (lms_substr_seq_id xs x) (lms_substr_seq_id xs y) =
nslexordp (<) (map (ordlistns.elem_rank (lms_substrs xs)) (lms_substr_seq_id xs x))
(map (ordlistns.elem_rank (lms_substrs xs)) (lms_substr_seq_id xs y))"
using monotone_on_iff_nslexordp[OF ordlistns.strict_mono_on_elem_rank, simplified,
OF finite_lms_substrs[of xs] ordlistns.bij_betw_elem_rank_upt,
OF finite_lms_substrs[of xs]]
by blast
}
ultimately show "list_less_ns (lms_map xs x) (lms_map xs y)"
by (simp add: nslexordp_eq_list_less_ns)
qed
lemma list_less_ns_lms_map_suffix:
assumes "abs_is_lms xs i"
and "abs_is_lms xs j"
and "list_less_ns (lms_map xs (suffix xs i)) (lms_map xs (suffix xs j))"
shows "list_less_ns (suffix xs i) (suffix xs j)"
using monotone_on_iff[OF monotone_on_lms_map, simplified] assms by blast
abbreviation
"lms0_map xs ≡
lms_map xs (lms0_suffix xs)"
lemma sorted_reduced_seq_imp_lms:
assumes "ordlistns.strict_sorted (map (suffix (lms0_map xs)) ys)"
and "∀y ∈ set ys. y < card {i. abs_is_lms xs i}"
shows "ordlistns.strict_sorted (map (suffix xs) (map ((!) (lms0_seq xs)) ys))"
proof (intro sorted_wrt_mapI)
fix i j
assume "i < j" "j < length (map ((!) (lms0_seq xs)) ys)"
hence A: "i < j" "j < length ys"
by simp_all
with sorted_wrt_mapD[OF assms(1)]
have "list_less_ns (suffix (lms0_map xs) (ys ! i)) (suffix (lms0_map xs) (ys ! j))" .
moreover
from lms_map_nth_suffix[of "ys ! i" xs]
have "suffix (lms0_map xs) (ys ! i) = lms_map xs (suffix xs (nth_lms xs (ys ! i)))"
using A(1) A(2) assms(2) by fastforce
moreover
from lms_map_nth_suffix[of "ys ! j" xs]
have "suffix (lms0_map xs) (ys ! j) = lms_map xs (suffix xs (nth_lms xs (ys ! j)))"
using A(2) assms(2) by fastforce
moreover
have "abs_is_lms xs (nth_lms xs (ys ! i))"
by (meson A(1) A(2) assms(2) nth_lms nth_mem order.strict_trans)
hence "suffix xs (nth_lms xs (ys ! i)) ∈ lms_suffixes xs"
by blast
moreover
have "abs_is_lms xs (nth_lms xs (ys ! j))"
by (meson A(2) assms(2) nth_lms nth_mem order.strict_trans)
hence "suffix xs (nth_lms xs (ys ! j)) ∈ lms_suffixes xs"
by blast
ultimately have
"list_less_ns (suffix xs (nth_lms xs (ys ! i))) (suffix xs (nth_lms xs (ys ! j)))"
using monotone_on_iff[OF monotone_on_lms_map, simplified] by auto
moreover
from lms0_seq_nth[of "ys ! i" xs]
have "lms0_seq xs ! (ys ! i) = nth_lms xs (ys ! i)"
using A(1) A(2) assms(2) by force
moreover
from lms0_seq_nth[of "ys ! j" xs]
have "lms0_seq xs ! (ys ! j) = nth_lms xs (ys ! j)"
using A(2) assms(2) by force
ultimately have
"list_less_ns (suffix xs (lms0_seq xs ! (ys ! i))) (suffix xs (lms0_seq xs ! (ys ! j)))"
by presburger
then show "list_less_ns (suffix xs (map ((!) (lms0_seq xs)) ys ! i))
(suffix xs (map ((!) (lms0_seq xs)) ys ! j))"
using A(1) A(2) by fastforce
qed
lemma sorted_distinct_lms_substr:
assumes "ordlistns.sorted (map (lms_slice xs) ys)"
and "distinct (map (lms_slice xs) ys)"
and "∀y ∈ set ys. y < length xs"
shows "ordlistns.sorted (map (suffix xs) ys)"
proof (intro sorted_wrt_mapI)
fix i j
assume "i < j" "j < length ys"
with sorted_wrt_mapD[OF assms(1)]
have "list_less_eq_ns (lms_slice xs (ys ! i)) (lms_slice xs (ys ! j))" .
moreover
have "lms_slice xs (ys ! i) ≠ lms_slice xs (ys ! j)"
using ‹i < j› ‹j < length ys› assms(2) nth_eq_iff_index_eq by fastforce
ultimately have "list_less_ns (lms_slice xs (ys ! i)) (lms_slice xs (ys ! j))"
using ordlistns.nless_le by blast
then show "list_less_eq_ns (suffix xs (ys ! i)) (suffix xs (ys ! j))"
by (metis ‹i < j› ‹j < length ys› less_lms_slice_imp_suffix assms(3) dual_order.strict_trans
nth_mem ordlistns.dual_order.strict_implies_order)
qed
lemma distinct_lms0_map:
assumes "distinct (lms0_map xs)"
shows "distinct (map (lms_slice xs) (lms0_seq xs))"
proof (intro distinct_conv_nth[THEN iffD2] allI impI)
fix i j
assume "i < length (map (lms_slice xs) (lms0_seq xs))"
"j < length (map (lms_slice xs) (lms0_seq xs))"
"i ≠ j"
hence A: "i < length (lms0_seq xs)" "j < length (lms0_seq xs)" "i ≠ j"
by simp_all
with distinct_conv_nth[THEN iffD1, OF assms]
have B: "lms0_map xs ! i ≠ lms0_map xs ! j"
by (metis card_lms_suffixes length_reduced_seq lms0_seq_length)
moreover
have "lms_substr_seq_id xs (lms0_suffix xs) = map (lms_slice xs) (lms0_seq xs)"
by (metis lms_substr_seq_def lms_subtrs_seq_id_suffix)
hence "lms0_map xs = map (ordlistns.elem_rank (lms_substrs xs)) (map (lms_slice xs) (lms0_seq xs))"
by (simp add: lms_map_o_def)
with A
have "lms0_map xs ! i = ordlistns.elem_rank (lms_substrs xs) (lms_slice xs (lms0_seq xs ! i))"
"lms0_map xs ! j = ordlistns.elem_rank (lms_substrs xs) (lms_slice xs (lms0_seq xs ! j))"
by auto
ultimately have "lms_slice xs (lms0_seq xs ! i) ≠ lms_slice xs (lms0_seq xs ! j)"
by fastforce
then show "map (lms_slice xs) (lms0_seq xs) ! i ≠ map (lms_slice xs) (lms0_seq xs) ! j"
by (simp add: A(1) A(2))
qed
lemma sorted_distinct_lms_substr_perm:
assumes "ordlistns.sorted (map (lms_slice xs) ys)"
and "distinct (lms0_map xs)"
and "ys <~~> lms0_seq xs"
shows "ordlistns.sorted (map (suffix xs) ys)"
by (metis sorted_distinct_lms_substr[OF assms(1)] distinct_lms0_map[OF assms(2)] assms(3)
distinct_map abs_is_lms_imp_less_length lms0_seq_has_all_lms mem_Collect_eq
perm_distinct_iff perm_set_eq)
lemma list_less_ns_suffix_lms_map:
assumes "abs_is_lms xs i"
and "abs_is_lms xs j"
and "list_less_ns (suffix xs i) (suffix xs j)"
shows "list_less_ns (lms_map xs (suffix xs i)) (lms_map xs (suffix xs j))"
using monotone_on_iff[OF monotone_on_lms_map, simplified] assms by blast
lemma valid_list_lms_map:
assumes "valid_list (a # b # xs)"
and "abs_is_lms (a # b # xs) i"
shows "valid_list (lms_map (a # b # xs) (suffix (a # b # xs) i))"
proof -
let ?xs = "a # b # xs"
have "∃n. length ?xs = Suc n"
by simp
then obtain n where
"length ?xs = Suc n"
by blast
hence "abs_is_lms ?xs n"
using assms(1) abs_is_lms_last by fastforce
have "lms_slice ?xs n = [bot]"
using ‹length ?xs = Suc n› assms(1) lms_slice_last by blast
have "∃m. i = Suc m"
using assms(2) lms_type_list_less_ns by auto
then obtain m where
"i = Suc m"
by blast
have P: "∀x ∈ {k. abs_is_lms ?xs k}. x ≠ n ⟶
list_less_ns (lms_slice ?xs n) (lms_slice ?xs x)"
proof safe
fix x
assume "abs_is_lms ?xs x" "x ≠ n"
hence "∃ys. lms_slice ?xs x = ?xs ! x # ys"
using abs_is_lms_imp_less_length lms_slice_hd by blast
then obtain ys where
"lms_slice ?xs x = ?xs ! x # ys"
by blast
moreover
have "bot < ?xs ! x"
by (metis ‹abs_is_lms ?xs x› ‹length ?xs = Suc n› ‹x ≠ n› assms(1) bot.not_eq_extremum
diff_Suc_1 hd_drop_conv_nth abs_is_lms_imp_less_length last_suffix_index)
ultimately show "list_less_ns (lms_slice ?xs n) (lms_slice ?xs x)"
by (simp add: ‹lms_slice ?xs n = [bot]› list_less_ns_cons_diff)
qed
have Q: "ordlistns.elem_rank (lms_substrs ?xs) (lms_slice ?xs n) = 0"
unfolding ordlistns.elem_rank_def elm_rank_def
proof -
have "{y ∈ lms_substrs ?xs. list_less_ns y (lms_slice ?xs n)} = {}"
using P by auto
then show "card {y ∈ lms_substrs ?xs. list_less_ns y (lms_slice ?xs n)} = 0"
by (metis card.empty)
qed
have R: "∀x ∈ lms_substrs ?xs. list_less_ns (lms_slice ?xs n) x ⟶
ordlistns.elem_rank (lms_substrs ?xs) x > 0"
using ‹abs_is_lms ?xs n› finite_lms_substrs ordlistns.strict_mono_onD
ordlistns.strict_mono_on_elem_rank by fastforce
have "[i..<length ?xs] = [i..<n] @ [n..<Suc n]"
using ‹length ?xs = Suc n› assms(2) abs_is_lms_imp_less_length by fastforce
hence "last (lms_seq ?xs i) = n"
unfolding lms_seq_def
by (simp add: ‹abs_is_lms ?xs n›)
hence "last (lms_substr_seq ?xs i) = lms_slice ?xs n"
by (metis assms(2) last_map list.discI lms_seq_Suc1 lms_substr_seq_def)
hence "last (lms_substr_seq_id ?xs (suffix ?xs i)) = lms_slice ?xs n"
by (metis lms_subtrs_seq_id_suffix)
hence "last (lms_map ?xs (suffix ?xs i)) = 0"
unfolding lms_map_o_def
by (metis assms(2) Q last_map length_0_conv list.discI lms_seq_Suc1 lms_substr_seq_length
lms_subtrs_seq_id_suffix)
moreover
have "butlast (lms_seq ?xs i) = filter (abs_is_lms ?xs) [i..<n]"
unfolding lms_seq_def
using ‹[i..<length ?xs] = [i..<n] @ [n..<Suc n]› ‹abs_is_lms ?xs n› by auto
hence "∀x ∈ set (butlast (lms_seq ?xs i)). x ≠ n ∧ abs_is_lms ?xs x"
by clarsimp
hence "∀x ∈ set (butlast (lms_substr_seq ?xs i)).
list_less_ns (lms_slice ?xs n) x"
by (clarsimp simp: P map_butlast[symmetric] lms_substr_seq_def)
hence S: "∀x ∈ set (butlast (lms_substr_seq_id ?xs (suffix ?xs i))).
list_less_ns (lms_slice ?xs n) x"
by (metis lms_subtrs_seq_id_suffix)
have "∀x ∈ set (butlast (lms_map ?xs (suffix ?xs i))). x > 0"
proof safe
fix x
assume "x ∈ set (butlast (lms_map ?xs (suffix ?xs i)))"
moreover
have "butlast (lms_map ?xs (suffix ?xs i)) =
map (ordlistns.elem_rank (lms_substrs ?xs)) (butlast (lms_substr_seq_id ?xs (suffix ?xs i)))"
unfolding lms_map_o_def
by (simp add: map_butlast)
ultimately have
"∃y ∈ set (butlast (lms_substr_seq_id ?xs (suffix ?xs i))).
x = ordlistns.elem_rank (lms_substrs ?xs) y"
by (simp add: in_set_mapD)
then obtain y where A:
"y ∈ set (butlast (lms_substr_seq_id ?xs (suffix ?xs i)))"
"x = ordlistns.elem_rank (lms_substrs ?xs) y"
by blast
moreover
have "y ∈ lms_substrs (a # b # xs)"
by (metis calculation(1) in_set_butlastD in_set_conv_nth lms_substr_seq_id_nth_abs_is_lms)
ultimately show "0 < x"
using S R by blast
qed
moreover
have "lms_map ?xs (suffix ?xs i) ≠ []"
unfolding lms_map_o_def
by (metis assms(2) list.discI list.map_disc_iff lms_seq_Suc1 lms_substr_seq_def
lms_subtrs_seq_id_suffix)
ultimately show ?thesis
unfolding valid_list_iff_butlast_app_last
by (metis bot_nat_def less_numeral_extra(3))
qed
end