Theory Sequence
section ‹ Infinite Sequences ›
theory Sequence
imports
HOL.Real
List_Extra
"HOL-Library.Sublist"
"HOL-Library.Nat_Bijection"
begin
typedef 'a seq = "UNIV :: (nat ⇒ 'a) set"
by (auto)
setup_lifting type_definition_seq
definition ssubstr :: "nat ⇒ nat ⇒ 'a seq ⇒ 'a list" where
"ssubstr i j xs = map (Rep_seq xs) [i ..< j]"
lift_definition nth_seq :: "'a seq ⇒ nat ⇒ 'a" (infixl ‹!⇩s› 100)
is "λ f i. f i" .
abbreviation sinit :: "nat ⇒ 'a seq ⇒ 'a list" where
"sinit i xs ≡ ssubstr 0 i xs"
lemma sinit_len [simp]:
"length (sinit i xs) = i"
by (simp add: ssubstr_def)
lemma sinit_0 [simp]: "sinit 0 xs = []"
by (simp add: ssubstr_def)
lemma prefix_upt_0 [intro]:
"i ≤ j ⟹ prefix [0..<i] [0..<j]"
by (induct i, auto, metis append_prefixD le0 prefix_order.lift_Suc_mono_le prefix_order.order_refl upt_Suc)
lemma sinit_prefix:
"i ≤ j ⟹ prefix (sinit i xs) (sinit j xs)"
by (simp add: map_mono_prefix prefix_upt_0 ssubstr_def)
lemma sinit_strict_prefix:
"i < j ⟹ strict_prefix (sinit i xs) (sinit j xs)"
by (metis sinit_len sinit_prefix le_less nat_neq_iff prefix_order.dual_order.strict_iff_order)
lemma nth_sinit:
"i < n ⟹ sinit n xs ! i = xs !⇩s i"
apply (auto simp add: ssubstr_def)
apply (transfer, auto)
done
lemma sinit_append_split:
assumes "i < j"
shows "sinit j xs = sinit i xs @ ssubstr i j xs"
proof -
have "[0..<i] @ [i..<j] = [0..<j]"
by (metis assms le0 le_add_diff_inverse le_less upt_add_eq_append)
thus ?thesis
by (auto simp add: ssubstr_def, transfer, simp add: map_append[THEN sym])
qed
lemma sinit_linear_asym_lemma1:
assumes "asym R" "i < j" "(sinit i xs, sinit i ys) ∈ lexord R" "(sinit j ys, sinit j xs) ∈ lexord R"
shows False
proof -
have sinit_xs: "sinit j xs = sinit i xs @ ssubstr i j xs"
by (metis assms(2) sinit_append_split)
have sinit_ys: "sinit j ys = sinit i ys @ ssubstr i j ys"
by (metis assms(2) sinit_append_split)
from sinit_xs sinit_ys assms(4)
have "(sinit i ys, sinit i xs) ∈ lexord R ∨ (sinit i ys = sinit i xs ∧ (ssubstr i j ys, ssubstr i j xs) ∈ lexord R)"
by (auto dest: lexord_append)
with assms lexord_asymmetric show False
by (force)
qed
lemma sinit_linear_asym_lemma2:
assumes "asym R" "(sinit i xs, sinit i ys) ∈ lexord R" "(sinit j ys, sinit j xs) ∈ lexord R"
shows False
proof (cases i j rule: linorder_cases)
case less with assms show ?thesis
by (auto dest: sinit_linear_asym_lemma1)
next
case equal with assms show ?thesis
by (simp add: lexord_asymmetric)
next
case greater with assms show ?thesis
by (auto dest: sinit_linear_asym_lemma1)
qed
lemma range_ext:
assumes "∀i :: nat. ∀x∈{0..<i}. f(x) = g(x)"
shows "f = g"
proof (rule ext)
fix x :: nat
obtain i :: nat where "i > x"
by (metis lessI)
with assms show "f(x) = g(x)"
by (auto)
qed
lemma sinit_ext:
"(∀ i. sinit i xs = sinit i ys) ⟹ xs = ys"
by (simp add: ssubstr_def, transfer, auto intro: range_ext)
definition seq_lexord :: "'a rel ⇒ ('a seq) rel" where
"seq_lexord R = {(xs, ys). (∃ i. (sinit i xs, sinit i ys) ∈ lexord R)}"
lemma seq_lexord_irreflexive:
"∀x. (x, x) ∉ R ⟹ (xs, xs) ∉ seq_lexord R"
by (auto dest: lexord_irreflexive simp add: irrefl_def seq_lexord_def)
lemma seq_lexord_irrefl:
"irrefl R ⟹ irrefl (seq_lexord R)"
by (simp add: irrefl_def seq_lexord_irreflexive)
lemma seq_lexord_transitive:
assumes "trans R"
shows "trans (seq_lexord R)"
unfolding seq_lexord_def
proof (rule transI, clarify)
fix xs ys zs :: "'a seq" and m n :: nat
assume las: "(sinit m xs, sinit m ys) ∈ lexord R" "(sinit n ys, sinit n zs) ∈ lexord R"
hence inz: "m > 0"
using gr0I by force
from las(1) obtain i where sinitm: "(sinit m xs!i, sinit m ys!i) ∈ R" "i < m" "∀ j<i. sinit m xs!j = sinit m ys!j"
using lexord_eq_length by force
from las(2) obtain j where sinitn: "(sinit n ys!j, sinit n zs!j) ∈ R" "j < n" "∀ k<j. sinit n ys!k = sinit n zs!k"
using lexord_eq_length by force
show "∃i. (sinit i xs, sinit i zs) ∈ lexord R"
proof (cases "i ≤ j")
case True note lt = this
with sinitm sinitn have "(sinit n xs!i, sinit n zs!i) ∈ R"
by (metis assms le_eq_less_or_eq le_less_trans nth_sinit transD)
moreover from lt sinitm sinitn have "∀ j<i. sinit m xs!j = sinit m zs!j"
by (metis less_le_trans less_trans nth_sinit)
ultimately have "(sinit n xs, sinit n zs) ∈ lexord R" using sinitm(2) sinitn(2) lt
apply (rule_tac lexord_intro_elems)
apply (auto)
apply (metis less_le_trans less_trans nth_sinit)
done
thus ?thesis by auto
next
case False
then have ge: "i > j" by auto
with assms sinitm sinitn have "(sinit n xs!j, sinit n zs!j) ∈ R"
by (metis less_trans nth_sinit)
moreover from ge sinitm sinitn have "∀ k<j. sinit m xs!k = sinit m zs!k"
by (metis dual_order.strict_trans nth_sinit)
ultimately have "(sinit n xs, sinit n zs) ∈ lexord R" using sinitm(2) sinitn(2) ge
apply (rule_tac lexord_intro_elems)
apply (auto)
apply (metis less_trans nth_sinit)
done
thus ?thesis by auto
qed
qed
lemma seq_lexord_trans:
"⟦ (xs, ys) ∈ seq_lexord R; (ys, zs) ∈ seq_lexord R; trans R ⟧ ⟹ (xs, zs) ∈ seq_lexord R"
by (meson seq_lexord_transitive transE)
lemma seq_lexord_antisym:
"⟦ asym R; (a, b) ∈ seq_lexord R ⟧ ⟹ (b, a) ∉ seq_lexord R"
by (auto dest: sinit_linear_asym_lemma2 simp add: seq_lexord_def)
lemma seq_lexord_asym:
assumes "asym R"
shows "asym (seq_lexord R)"
by (meson assms asymD asymI seq_lexord_antisym seq_lexord_irrefl)
lemma seq_lexord_total:
assumes "total R"
shows "total (seq_lexord R)"
using assms by (auto simp add: total_on_def seq_lexord_def, meson lexord_linear sinit_ext)
lemma seq_lexord_linear:
assumes "(∀ a b. (a,b)∈ R ∨ a = b ∨ (b,a) ∈ R)"
shows "(x,y) ∈ seq_lexord R ∨ x = y ∨ (y,x) ∈ seq_lexord R"
proof -
have "total R"
using assms total_on_def by blast
hence "total (seq_lexord R)"
using seq_lexord_total by blast
thus ?thesis
by (auto simp add: total_on_def)
qed
instantiation seq :: (ord) ord
begin
definition less_seq :: "'a seq ⇒ 'a seq ⇒ bool" where
"less_seq xs ys ⟷ (xs, ys) ∈ seq_lexord {(xs, ys). xs < ys}"
definition less_eq_seq :: "'a seq ⇒ 'a seq ⇒ bool" where
"less_eq_seq xs ys = (xs = ys ∨ xs < ys)"
instance ..
end
instance seq :: (order) order
proof
fix xs :: "'a seq"
show "xs ≤ xs" by (simp add: less_eq_seq_def)
next
fix xs ys zs :: "'a seq"
assume "xs ≤ ys" and "ys ≤ zs"
then show "xs ≤ zs"
by (force dest: seq_lexord_trans simp add: less_eq_seq_def less_seq_def trans_def)
next
fix xs ys :: "'a seq"
assume "xs ≤ ys" and "ys ≤ xs"
then show "xs = ys"
apply (auto simp add: less_eq_seq_def less_seq_def)
apply (rule seq_lexord_irreflexive [THEN notE])
defer
apply (rule seq_lexord_trans)
apply (auto intro: transI)
done
next
fix xs ys :: "'a seq"
show "xs < ys ⟷ xs ≤ ys ∧ ¬ ys ≤ xs"
apply (auto simp add: less_seq_def less_eq_seq_def)
defer
apply (rule seq_lexord_irreflexive [THEN notE])
apply auto
apply (rule seq_lexord_irreflexive [THEN notE])
defer
apply (rule seq_lexord_trans)
apply (auto intro: transI)
apply (simp add: seq_lexord_irreflexive)
done
qed
instance seq :: (linorder) linorder
proof
fix xs ys :: "'a seq"
have "(xs, ys) ∈ seq_lexord {(u, v). u < v} ∨ xs = ys ∨ (ys, xs) ∈ seq_lexord {(u, v). u < v}"
by (rule seq_lexord_linear) auto
then show "xs ≤ ys ∨ ys ≤ xs"
by (auto simp add: less_eq_seq_def less_seq_def)
qed
lemma seq_lexord_mono [mono]:
"(⋀ x y. f x y ⟶ g x y) ⟹ (xs, ys) ∈ seq_lexord {(x, y). f x y} ⟶ (xs, ys) ∈ seq_lexord {(x, y). g x y}"
apply (auto simp add: seq_lexord_def)
apply (metis case_prodD case_prodI lexord_take_index_conv mem_Collect_eq)
done
fun insort_rel :: "'a rel ⇒ 'a ⇒ 'a list ⇒ 'a list" where
"insort_rel R x [] = [x]" |
"insort_rel R x (y # ys) = (if (x = y ∨ (x,y) ∈ R) then x # y # ys else y # insort_rel R x ys)"
inductive sorted_rel :: "'a rel ⇒ 'a list ⇒ bool" where
Nil_rel [iff]: "sorted_rel R []" |
Cons_rel: "∀ y ∈ set xs. (x = y ∨ (x, y) ∈ R) ⟹ sorted_rel R xs ⟹ sorted_rel R (x # xs)"
definition list_of_set :: "'a rel ⇒ 'a set ⇒ 'a list" where
"list_of_set R = folding_on.F (insort_rel R) []"
lift_definition seq_inj :: "'a seq seq ⇒ 'a seq" is
"λ f i. f (fst (prod_decode i)) (snd (prod_decode i))" .
lift_definition seq_proj :: "'a seq ⇒ 'a seq seq" is
"λ f i j. f (prod_encode (i, j))" .
lemma seq_inj_inverse: "seq_proj (seq_inj x) = x"
by (transfer, simp)
lemma seq_proj_inverse: "seq_inj (seq_proj x) = x"
by (transfer, simp)
lemma seq_inj: "inj seq_inj"
by (metis injI seq_inj_inverse)
lemma seq_inj_surj: "bij seq_inj"
apply (rule bijI)
apply (auto simp add: seq_inj)
apply (metis rangeI seq_proj_inverse)
done
end