theory Sequence
imports Main "HOL-Library.Sublist"
begin
lemma last_concat:
"last xss ≠ [] ⟹ concat xss ≠ [] ⟹ last (concat xss) = last (last xss)"
by (metis append_Nil2 append_butlast_last_id concat.simps concat_append last_appendR)
inductive_set sequence for I P where
base [simp, intro!]: "x ∈ I ⟹ [x] ∈ sequence I P"
| trans_step [intro]: "x ∈ I ⟹ y # ys ∈ sequence I P ⟹ P x y ⟹ x # y # ys ∈ sequence I P"
lemma sequence_hd_to_I:
"x # xs ∈ sequence I P ⟹ x ∈ I"
using sequence.cases by auto
abbreviation "seq_to_rel f xs ≡ (fst (f (hd xs)), snd (f (last xs)))"
lemma sequence_mono1:
"I ⊆ U ⟹ sequence I P ⊆ sequence U P"
proof -
assume sub: "I ⊆ U"
{fix xs assume "xs ∈ sequence I P" then have "xs ∈ sequence U P"
using sub by (induct) auto}
then show ?thesis by blast
qed
lemma sequence_mono2:
"P ≤ Q ⟹ sequence I P ⊆ sequence I Q"
proof -
assume p: "P ≤ Q"
{fix xs assume "xs ∈ sequence I P" then have "xs ∈ sequence I Q"
using p by (induct) auto}
then show ?thesis by blast
qed
lemma no_empty_seq [simp]:
"[] ∉ sequence I P ⟷ True"
"[] ∈ sequence I P ⟷ False"
using sequence.cases by auto
lemma seq_not_NilD:
"xs ∈ sequence I P ⟹ xs ≠ []"
using sequence.cases by auto
lemma seq_singeltonD [dest]:
"[x] ∈ sequence I P ⟹ x ∈ I"
using sequence.cases by auto
lemma seq_in_I:
"xs ∈ sequence I P ⟹ x ∈ set xs ⟹ x ∈ I"
by (induct rule: sequence.induct) auto
lemma sequence_members [simp]:
"⋃ (set ` sequence I P) = I"
by (auto dest: seq_in_I)
lemma sequence_ConsI [intro]:
assumes "x ∈ I" and "xs ≠ [] ⟹ P x (hd xs) ∧ xs ∈ sequence I P"
shows "x # xs ∈ sequence I P"
proof (cases xs)
case Nil then show ?thesis using assms(1) by auto
next
case (Cons y ys)
show ?thesis using assms unfolding Cons
by (intro trans_step) auto
qed
lemma sequence_propI:
assumes "⋀ x. x ∈ set xs ⟹ x ∈ I" "xs ≠ []"
and "⋀ i. Suc i < length xs ⟹ P (xs ! i) (xs ! Suc i)"
shows "xs ∈ sequence I P" using assms
by (induct xs) (force simp: nth_Cons' hd_conv_nth)+
lemma seq_property_head:
assumes "(x # y # xs) ∈ sequence I P"
shows "P x y" using assms
using sequence.cases by auto
lemma seq_property_head':
assumes "(x # ys) ∈ sequence I P" "ys ≠ []"
shows "P x (hd ys)" using assms
using seq_property_head
by (cases ys) (auto simp add: seq_property_head)
lemma suffix_seq_in_seq:
assumes "xs ∈ sequence I P" "suffix ys xs" "ys ≠ []"
shows "ys ∈ sequence I P" using assms
proof (induct xs arbitrary: ys)
case (base x) then show ?case
by (simp add: suffix_Cons)
qed (auto simp: suffix_Cons)
lemma prefix_seq_in_seq:
assumes "ys ∈ sequence I P" "prefix xs ys" "xs ≠ []"
shows "xs ∈ sequence I P" using assms
proof (induct ys arbitrary: xs rule: list.induct)
case (Cons x ys)
obtain xs' where [simp]: "xs = x # xs'" using Cons(3, 4)
by (force simp: prefix_Cons)
have pr: "prefix xs' ys" using Cons(3) by auto
show ?case
proof (cases "xs' = []")
case True
then show ?thesis using Cons by (auto dest: sequence_hd_to_I)
next
case False
have "x ∈ I" using Cons(2) by (auto dest: sequence_hd_to_I)
then show ?thesis using False Cons(1)[of xs'] Cons(2-)
apply (cases ys) apply auto
by (metis list.sel(1) list.sel(3) list.simps(3) prefix_Cons seq_property_head sequence_ConsI suffix_seq_in_seq suffix_tl)
qed
qed auto
lemma sublist_seq_in_seq:
assumes "xs ∈ sequence I P" and "sublist ys xs" and "ys ≠ []"
shows "ys ∈ sequence I P"
proof -
from assms(2) obtain us ss where xs: "xs = us @ ys @ ss"
unfolding sublist_def by blast
from suffix_seq_in_seq[OF assms(1), of "ys @ ss"]
have "ys @ ss ∈ sequence I P" using assms(3) unfolding xs
using suffixI by blast
from prefix_seq_in_seq[OF this _ assms(3)] show ?thesis
using prefixI by blast
qed
lemma seq_append_seq:
assumes "xs @ ys ∈ sequence I P"
shows "xs ≠ [] ⟹ xs ∈ sequence I P" "ys ≠ [] ⟹ ys ∈ sequence I P"
proof -
show "xs ≠ [] ⟹ xs ∈ sequence I P"
using prefix_seq_in_seq[OF assms, of xs] by force
next
show "ys ≠ [] ⟹ ys ∈ sequence I P"
using suffix_seq_in_seq[OF assms, of ys]
using suffixI by blast
qed
lemma tail_seq_in_seq:
assumes "xs ∈ sequence I P" "tl xs ≠ []"
shows "tl xs ∈ sequence I P"
using suffix_seq_in_seq[OF assms(1)] assms(2-)
by auto
lemma seq_property:
assumes "xs ∈ sequence I P" "Suc i < length xs"
shows "P (xs ! i) (xs ! Suc i)"
proof -
let ?ys = "drop i xs"
show ?thesis using assms(2-)
using seq_property_head[of "hd ?ys" "hd (tl ?ys)" "tl (tl ?ys)"]
using suffix_seq_in_seq[OF assms(1), of "drop i xs"]
by (metis Cons_nth_drop_Suc Suc_lessD list.distinct(1) seq_property_head suffix_drop)
qed
lemma seq_last_append_prop:
"xs @ [x] ∈ sequence I P ⟹ xs ≠ [] ⟹ P (last xs) x"
using seq_property[of "xs @ [x]" I P "length xs - 1"]
by (auto simp: nth_append last_conv_nth)
lemma sequence_converse_induct [consumes 1, case_names base step]:
assumes "xs ∈ sequence I P"
and "⋀x. x ∈ I ⟹ R [x]"
and IH: "⋀x ys. x ∈ I ⟹ ys ∈ sequence I P ⟹ ys ≠ [] ⟹ R ys ⟹ P (last ys) x ⟹ R (ys @ [x])"
shows "R xs" using assms(1)
proof (induct xs rule: rev_induct)
case (snoc x xs) show ?case
proof (cases xs)
case [simp]: Nil show ?thesis using seq_in_I[OF snoc(2)]
by (auto intro!: assms(2)[of x])
next
case [simp]: (Cons y ys)
from prefix_seq_in_seq[OF snoc(2)] have "y # ys ∈ sequence I P" by auto
then show ?thesis using snoc IH[where ?ys = "y # ys" and ?x = x]
using seq_last_append_prop[OF snoc(2)]
using seq_in_I[OF snoc(2), of x]
by auto
qed
qed auto
lemma sequence_concat_onP [intro]:
assumes "xs ∈ sequence I P" "ys ∈ sequence I P"
and "P (last xs) (hd ys)"
shows "xs @ ys ∈ sequence I P" using assms
proof (induct xs rule: list.induct)
case (Cons x xs) note IH = this
have "xs ≠ [] ⟹ xs @ ys ∈ sequence I P" using tail_seq_in_seq[OF IH(2)] IH by auto
moreover have "xs ≠ [] ⟹ P x (hd xs)" using IH(2) seq_property_head[of x "hd xs" "tl xs"]
by (cases xs) auto
ultimately show ?case using IH(2-) seq_in_I[OF IH(2), of x]
by (auto split!: if_splits intro: sequence_ConsI)
qed auto
lemma sequence_member_min:
"xs ∈ sequence I P ⟹ xs ∈ sequence (set xs) P"
proof (induct rule: sequence.induct)
case (trans_step x y ys)
then show ?case using sequence_mono1[of _ "insert x (insert y (set ys))"]
by (intro sequence_ConsI[where ?xs = "y # ys"]) auto
qed auto
lemma sequence_concat_cl [intro!]:
assumes "⋀ xs. xs ∈ set xss ⟹ xs ∈ sequence I P" "xss ≠ []"
and "⋀ i. Suc i < length xss ⟹ P (last (xss ! i)) (hd (xss ! Suc i))"
shows "concat xss ∈ sequence I P" using assms
proof (induct xss rule: rev_induct)
case (snoc a xss) show ?case
proof (cases "xss = []")
case True
then show ?thesis using snoc(2) by auto
next
case False
then have *: "last xss ≠ []" "concat xss ≠ []" using snoc(2) last_in_set[OF False]
by simp_all (metis ‹last xss ∈ set xss› no_empty_seq)+
have fh: "xs ∈ set xss ⟹ xs ∈ sequence I P" for xs using snoc(2)[of xs]
by (auto simp: nth_append split!: if_splits)
have sh: "Suc i < length xss ⟹ P (last (xss ! i)) (hd (xss ! Suc i))" for i
using snoc(4)[of i] by (auto simp: nth_append split!: if_splits)
from snoc(1)[OF fh _ sh] snoc(3) False have "concat xss ∈ sequence I P"
by auto
moreover have "a ∈ sequence I P" using snoc(2) by auto
ultimately show ?thesis using snoc(4)[of "length xss - 1"] False
by (auto simp: last_concat[OF *] last_conv_nth[OF False] nth_append)
qed
qed auto
definition seq_rel_spec where
"seq_rel_spec f S R ⟷ [] ∉ S ∧ (∀ xs ∈ S. seq_to_rel f xs ∈ R)"
definition rel_seq_spec where
"rel_seq_spec f R S ⟷ [] ∉ S ∧ (∀ s t. (s, t) ∈ R ⟶ (∃ xs ∈ S. (s, t) = seq_to_rel f xs))"
definition rel_seq_strict_spec where
"rel_seq_strict_spec f R S ⟷ rel_seq_spec f R S ∧ (∀ xs ∈ S. set (map f xs) ⊆ R)"
lemma rel_seq_spec_nempty [simp]:
"rel_seq_spec f R S ⟹ [] ∉ S"
by (simp add: rel_seq_spec_def)
lemma rel_seq_strict_spec [simp]:
"rel_seq_strict_spec f R S ⟹ rel_seq_spec f R S"
"rel_seq_strict_spec f R S ⟹ [] ∉ S"
by (auto simp add: rel_seq_strict_spec_def)
lemma rel_seq_specE [elim]:
assumes "rel_seq_spec f R S" "(s, t) ∈ R"
obtains xs where "xs ∈ S" "xs ≠ []" "s = fst (f (hd xs))" "t = snd (f (last xs))"
using assms unfolding rel_seq_spec_def
by auto
lemma rel_seq_strict_specE [elim]:
assumes "rel_seq_strict_spec f R S" "(s, t) ∈ R"
obtains xs where "xs ∈ S" "xs ≠ []" "s = fst (f (hd xs))" "t = snd (f (last xs))" "∀ i < length xs. f (xs ! i) ∈ R"
using assms unfolding rel_seq_strict_spec_def
by (auto simp: image_subset_iff)
lemma rel_seq_specI [intro!]:
"[] ∉ S ⟹ (⋀ s t. (s, t) ∈ R ⟹ ∃ xs ∈ S. s = fst (f (hd xs)) ∧ t = snd (f (last xs))) ⟹ rel_seq_spec f R S"
unfolding rel_seq_spec_def by auto
lemma seq_rel_specD [dest]:
"seq_rel_spec f S R ⟹ xs ≠ [] ⟹ xs ∈ S ⟹ (fst (f (hd xs)), snd (f (last xs))) ∈ R"
unfolding seq_rel_spec_def by auto
definition pred_impl_eq_on where
"pred_impl_eq_on f I U P ⟷ (∀ x y. x ∈ I ⟶ y ∈ U ⟶ P x y ⟶ snd (f x) = fst (f y))"
definition eq_impl_pred_on where
"eq_impl_pred_on f I U P ⟷ (∀ x y. x ∈ I ⟶ y ∈ U ⟶ snd (f x) = fst (f y) ⟶ P x y)"
definition seq_impl_in_rel_on where
"seq_impl_in_rel_on f r I P ⟷ f ` I ⊆ r ∧ pred_impl_eq_on f I I P"
definition rel_impl_in_seq_on where
"rel_impl_in_seq_on f r I P ⟷ r ⊆ f ` I ∧ eq_impl_pred_on f I I P"
lemma sequence_hd_last_to_trancl:
assumes "f ` I ⊆ r"
and "⋀ x y. x ∈ I ⟹ y ∈ I ⟹ P x y ⟹ snd (f x) = fst (f y)"
and "xs ∈ sequence I P"
shows "(fst (f (hd xs)), snd (f (last xs))) ∈ r⇧+" using assms(3)
proof (induct xs)
case (base x)
then show ?case using assms(1)
by (simp add: image_subset_iff r_into_trancl')
next
case (trans_step x y ys)
from trans_step(2) have "y ∈ I" using seq_in_I by force
from assms(2)[OF _ this, of x] assms(1) trans_step(1, 4)
have "snd (f x) = fst (f y)" "f x ∈ r⇧+"
by (simp_all add: image_subset_iff r_into_trancl')
then show ?case using trans_step(3)
by auto (metis prod.collapse trancl_trans)+
qed
lemma trancl_to_sequence:
assumes "r ⊆ f ` I"
and "⋀ x y. x ∈ I ⟹ y ∈ I ⟹ f x ∈ r ⟹ f y ∈ r ⟹ snd (f x) = fst (f y) ⟹ P x y"
and "(s, t) ∈ r⇧+"
shows "∃ xs. fst (f (hd xs)) = s ∧ snd (f (last xs)) = t ∧ xs ∈ sequence I P ∧
(∀ i < length xs. f (xs ! i) ∈ r)" using assms(3)
proof (induct rule: converse_trancl_induct)
case (base s)
then obtain x where "x ∈ I" "f x = (s, t)" using assms(1) by auto
then show ?case using base
by (intro exI[of _ "[x]"]) auto
next
case (step s u)
from step(1, 3) assms(1) obtain x xs where elem: "x ∈ I" "f x = (s, u)"
and list: "fst (f (hd xs)) = u" "snd (f (last xs)) = t"
"xs ∈ sequence I P" "∀ i < length xs. f (xs ! i) ∈ r"
by auto
from assms(2)[OF elem(1), of "hd xs"] list(3, 4) step(1)
have "P x (hd xs)" using seq_in_I
by (cases xs) (fastforce simp: elem(2) hd_conv_nth simp flip: list(1))+
then show ?case using list elem step(1)
by (intro exI[of _ "x # xs"]) (auto simp: nth_Cons')
qed
definition seq_comp where
"seq_comp P R S = {xs| xs ys zs. xs = ys @ zs ∧ ys ∈ R ∧ zs ∈ S ∧ ys ≠ [] ∧ zs ≠ [] ∧ P (last ys) (hd zs)}"
lemma seq_comp_nempty[simp]: "[] ∉ seq_comp P R S"
by (auto simp: seq_comp_def)
lemma seq_compE [elim]:
assumes "xs ∈ seq_comp P R S"
obtains ys zs where "ys ≠ []" "zs ≠ []" " xs = ys @ zs" "ys ∈ R" "zs ∈ S" "P (last ys) (hd zs)"
using assms unfolding seq_comp_def
by auto
lemma seq_comp_appendI [intro]:
"xs ≠ [] ⟹ ys ≠ [] ⟹ xs ∈ R ⟹ ys ∈ S ⟹ P (last xs) (hd ys) ⟹ xs @ ys ∈ seq_comp P R S"
by (auto simp: seq_comp_def)
lemma seq_comp_rel_conf:
assumes "seq_rel_spec f S R" "seq_rel_spec f S' R'"
and "pred_impl_eq_on f (⋃ (set ` S)) (⋃ (set ` S')) P"
shows "seq_rel_spec f (seq_comp P S S') (R O R')"
using seq_rel_specD[OF assms(1)] seq_rel_specD[OF assms(2)]
using assms(3) unfolding pred_impl_eq_on_def
by (auto simp: seq_rel_spec_def relcomp_unfold elim!: seq_compE)
(metis last_in_set list.set_sel(1))
lemma relcomp_seq_conf:
assumes "rel_seq_spec f R S" "rel_seq_spec f R' S'"
and "eq_impl_pred_on f (⋃ (set ` S)) (⋃ (set ` S')) P"
shows "rel_seq_spec f (R O R') (seq_comp P S S')"
proof -
{fix s t assume "(s, t) ∈ R O R'"
then obtain u where comp: "(s, u) ∈ R" "(u, t) ∈ R'" by auto
from rel_seq_specE[OF assms(1) this(1)] rel_seq_specE[OF assms(2) this(2)]
obtain xs ys where
rep: "xs ∈ S" "xs ≠ []" "s = fst (f (hd xs))" "u = snd (f (last xs))"
"ys ∈ S'" "ys ≠ []" "u = fst (f (hd ys))" "t = snd (f (last ys))"
by metis
from assms(3) rep have "P (last xs) (hd ys)" by (force simp: eq_impl_pred_on_def)
then have mem: "xs @ ys ∈ seq_comp P S S'" using rep by auto
have "∃ xs ∈ seq_comp P S S'. s = fst (f (hd xs)) ∧ t = snd (f (last xs))"
using rep(2, 3, 6, 8) by (intro bexI[OF _ mem]) auto}
then show ?thesis by auto
qed
end