Theory Lazy_List_Liminf
section ‹Supremum and Liminf of Lazy Lists›
theory Lazy_List_Liminf
imports Coinductive.Coinductive_List
begin
text ‹
Lazy lists, as defined in the \emph{Archive of Formal Proofs}, provide finite and infinite lists in
one type, defined coinductively. The present theory introduces the concept of the union of all
elements of a lazy list of sets and the limit of such a lazy list. The definitions are stated more
generally in terms of lattices. The basis for this theory is Section 4.1 (``Theorem Proving
Processes'') of Bachmair and Ganzinger's chapter.
›
subsection ‹Library›
lemma less_llength_ltake: "i < llength (ltake k Xs) ⟷ i < k ∧ i < llength Xs"
by simp
subsection ‹Supremum›
definition Sup_llist :: "'a set llist ⇒ 'a set" where
"Sup_llist Xs = (⋃i ∈ {i. enat i < llength Xs}. lnth Xs i)"
lemma lnth_subset_Sup_llist: "enat i < llength Xs ⟹ lnth Xs i ⊆ Sup_llist Xs"
unfolding Sup_llist_def by auto
lemma Sup_llist_imp_exists_index: "x ∈ Sup_llist Xs ⟹ ∃i. enat i < llength Xs ∧ x ∈ lnth Xs i"
unfolding Sup_llist_def by auto
lemma exists_index_imp_Sup_llist: "enat i < llength Xs ⟹ x ∈ lnth Xs i ⟹ x ∈ Sup_llist Xs"
unfolding Sup_llist_def by auto
lemma Sup_llist_LNil[simp]: "Sup_llist LNil = {}"
unfolding Sup_llist_def by auto
lemma Sup_llist_LCons[simp]: "Sup_llist (LCons X Xs) = X ∪ Sup_llist Xs"
unfolding Sup_llist_def
proof (intro subset_antisym subsetI)
fix x
assume "x ∈ (⋃i ∈ {i. enat i < llength (LCons X Xs)}. lnth (LCons X Xs) i)"
then obtain i where len: "enat i < llength (LCons X Xs)" and nth: "x ∈ lnth (LCons X Xs) i"
by blast
from nth have "x ∈ X ∨ i > 0 ∧ x ∈ lnth Xs (i - 1)"
by (metis lnth_LCons' neq0_conv)
then have "x ∈ X ∨ (∃i. enat i < llength Xs ∧ x ∈ lnth Xs i)"
by (metis len Suc_pred' eSuc_enat iless_Suc_eq less_irrefl llength_LCons not_less order_trans)
then show "x ∈ X ∪ (⋃i ∈ {i. enat i < llength Xs}. lnth Xs i)"
by blast
qed ((auto)[], metis i0_lb lnth_0 zero_enat_def, metis Suc_ile_eq lnth_Suc_LCons)
lemma lhd_subset_Sup_llist: "¬ lnull Xs ⟹ lhd Xs ⊆ Sup_llist Xs"
by (cases Xs) simp_all
subsection ‹Supremum up-to›
definition Sup_upto_llist :: "'a set llist ⇒ enat ⇒ 'a set" where
"Sup_upto_llist Xs j = (⋃i ∈ {i. enat i < llength Xs ∧ enat i ≤ j}. lnth Xs i)"
lemma Sup_upto_llist_eq_Sup_llist_ltake: "Sup_upto_llist Xs j = Sup_llist (ltake (eSuc j) Xs)"
unfolding Sup_upto_llist_def Sup_llist_def
by (smt (verit) Collect_cong Sup.SUP_cong iless_Suc_eq lnth_ltake less_llength_ltake mem_Collect_eq)
lemma Sup_upto_llist_enat_0[simp]:
"Sup_upto_llist Xs (enat 0) = (if lnull Xs then {} else lhd Xs)"
proof (cases "lnull Xs")
case True
then show ?thesis
unfolding Sup_upto_llist_def by auto
next
case False
show ?thesis
unfolding Sup_upto_llist_def image_def by (simp add: lhd_conv_lnth enat_0 enat_0_iff)
qed
lemma Sup_upto_llist_Suc[simp]:
"Sup_upto_llist Xs (enat (Suc j)) =
Sup_upto_llist Xs (enat j) ∪ (if enat (Suc j) < llength Xs then lnth Xs (Suc j) else {})"
unfolding Sup_upto_llist_def image_def by (auto intro: le_SucI elim: le_SucE)
lemma Sup_upto_llist_infinity[simp]: "Sup_upto_llist Xs ∞ = Sup_llist Xs"
unfolding Sup_upto_llist_def Sup_llist_def by simp
lemma Sup_upto_llist_0[simp]: "Sup_upto_llist Xs 0 = (if lnull Xs then {} else lhd Xs)"
unfolding zero_enat_def by (rule Sup_upto_llist_enat_0)
lemma Sup_upto_llist_eSuc[simp]:
"Sup_upto_llist Xs (eSuc j) =
(case j of
enat k ⇒ Sup_upto_llist Xs (enat (Suc k))
| ∞ ⇒ Sup_llist Xs)"
by (auto simp: eSuc_enat split: enat.split)
lemma Sup_upto_llist_mono[simp]: "j ≤ k ⟹ Sup_upto_llist Xs j ⊆ Sup_upto_llist Xs k"
unfolding Sup_upto_llist_def by auto
lemma Sup_upto_llist_subset_Sup_llist: "Sup_upto_llist Xs j ⊆ Sup_llist Xs"
unfolding Sup_llist_def Sup_upto_llist_def by auto
lemma elem_Sup_llist_imp_Sup_upto_llist:
"x ∈ Sup_llist Xs ⟹ ∃j < llength Xs. x ∈ Sup_upto_llist Xs (enat j)"
unfolding Sup_llist_def Sup_upto_llist_def by blast
lemma lnth_subset_Sup_upto_llist: "j < llength Xs ⟹ lnth Xs j ⊆ Sup_upto_llist Xs j"
unfolding Sup_upto_llist_def by auto
lemma finite_Sup_llist_imp_Sup_upto_llist:
assumes "finite X" and "X ⊆ Sup_llist Xs"
shows "∃k. X ⊆ Sup_upto_llist Xs (enat k)"
using assms
proof induct
case (insert x X)
then have x: "x ∈ Sup_llist Xs" and X: "X ⊆ Sup_llist Xs"
by simp+
from x obtain k where k: "x ∈ Sup_upto_llist Xs (enat k)"
using elem_Sup_llist_imp_Sup_upto_llist by fast
from X obtain k' where k': "X ⊆ Sup_upto_llist Xs (enat k')"
using insert.hyps(3) by fast
have "insert x X ⊆ Sup_upto_llist Xs (max k k')"
using k k' by (metis (mono_tags) Sup_upto_llist_mono enat_ord_simps(1) insert_subset
max.cobounded1 max.cobounded2 subset_iff)
then show ?case
by fast
qed simp
subsection ‹Liminf›
definition Liminf_llist :: "'a set llist ⇒ 'a set" where
"Liminf_llist Xs =
(⋃i ∈ {i. enat i < llength Xs}. ⋂j ∈ {j. i ≤ j ∧ enat j < llength Xs}. lnth Xs j)"
lemma Liminf_llist_LNil[simp]: "Liminf_llist LNil = {}"
unfolding Liminf_llist_def by simp
lemma Liminf_llist_LCons:
"Liminf_llist (LCons X Xs) = (if lnull Xs then X else Liminf_llist Xs)" (is "?lhs = ?rhs")
proof (cases "lnull Xs")
case nnull: False
show ?thesis
proof
{
fix x
assume "∃i. enat i ≤ llength Xs
∧ (∀j. i ≤ j ∧ enat j ≤ llength Xs ⟶ x ∈ lnth (LCons X Xs) j)"
then have "∃i. enat (Suc i) ≤ llength Xs
∧ (∀j. Suc i ≤ j ∧ enat j ≤ llength Xs ⟶ x ∈ lnth (LCons X Xs) j)"
by (cases "llength Xs",
metis not_lnull_conv[THEN iffD1, OF nnull] Suc_le_D eSuc_enat eSuc_ile_mono
llength_LCons not_less_eq_eq zero_enat_def zero_le,
metis Suc_leD enat_ord_code(3))
then have "∃i. enat i < llength Xs ∧ (∀j. i ≤ j ∧ enat j < llength Xs ⟶ x ∈ lnth Xs j)"
by (metis Suc_ile_eq Suc_n_not_le_n lift_Suc_mono_le lnth_Suc_LCons nat_le_linear)
}
then show "?lhs ⊆ ?rhs"
by (simp add: Liminf_llist_def nnull) (rule subsetI, simp)
{
fix x
assume "∃i. enat i < llength Xs ∧ (∀j. i ≤ j ∧ enat j < llength Xs ⟶ x ∈ lnth Xs j)"
then obtain i where
i: "enat i < llength Xs" and
j: "∀j. i ≤ j ∧ enat j < llength Xs ⟶ x ∈ lnth Xs j"
by blast
have "enat (Suc i) ≤ llength Xs"
using i by (simp add: Suc_ile_eq)
moreover have "∀j. Suc i ≤ j ∧ enat j ≤ llength Xs ⟶ x ∈ lnth (LCons X Xs) j"
using Suc_ile_eq Suc_le_D j by force
ultimately have "∃i. enat i ≤ llength Xs ∧ (∀j. i ≤ j ∧ enat j ≤ llength Xs ⟶
x ∈ lnth (LCons X Xs) j)"
by blast
}
then show "?rhs ⊆ ?lhs"
by (simp add: Liminf_llist_def nnull) (rule subsetI, simp)
qed
qed (simp add: Liminf_llist_def enat_0_iff(1))
lemma lfinite_Liminf_llist: "lfinite Xs ⟹ Liminf_llist Xs = (if lnull Xs then {} else llast Xs)"
proof (induction rule: lfinite_induct)
case (LCons xs)
then obtain y ys where
xs: "xs = LCons y ys"
by (meson not_lnull_conv)
show ?case
unfolding xs by (simp add: Liminf_llist_LCons LCons.IH[unfolded xs, simplified] llast_LCons)
qed (simp add: Liminf_llist_def)
lemma Liminf_llist_ltl: "¬ lnull (ltl Xs) ⟹ Liminf_llist Xs = Liminf_llist (ltl Xs)"
by (metis Liminf_llist_LCons lhd_LCons_ltl lnull_ltlI)
lemma Liminf_llist_subset_Sup_llist: "Liminf_llist Xs ⊆ Sup_llist Xs"
unfolding Liminf_llist_def Sup_llist_def by fast
lemma image_Liminf_llist_subset: "f ` Liminf_llist Ns ⊆ Liminf_llist (lmap ((`) f) Ns)"
unfolding Liminf_llist_def by auto
lemma Liminf_llist_imp_exists_index:
"x ∈ Liminf_llist Xs ⟹ ∃i. enat i < llength Xs ∧ x ∈ lnth Xs i"
unfolding Liminf_llist_def by auto
lemma not_Liminf_llist_imp_exists_index:
"¬ lnull Xs ⟹ x ∉ Liminf_llist Xs ⟹ enat i < llength Xs ⟹
(∃j. i ≤ j ∧ enat j < llength Xs ∧ x ∉ lnth Xs j)"
unfolding Liminf_llist_def by auto
lemma finite_subset_Liminf_llist_imp_exists_index:
assumes
nnil: "¬ lnull Xs" and
fin: "finite X" and
in_lim: "X ⊆ Liminf_llist Xs"
shows "∃i. enat i < llength Xs ∧ X ⊆ (⋂j ∈ {j. i ≤ j ∧ enat j < llength Xs}. lnth Xs j)"
proof -
show ?thesis
proof (cases "X = {}")
case True
then show ?thesis
using nnil by (auto intro: exI[of _ 0] simp: zero_enat_def[symmetric])
next
case nemp: False
have in_lim':
"∀x ∈ X. ∃i. enat i < llength Xs ∧ x ∈ (⋂j ∈ {j. i ≤ j ∧ enat j < llength Xs}. lnth Xs j)"
using in_lim[unfolded Liminf_llist_def] in_mono by fastforce
obtain i_of where
i_of_lt: "∀x ∈ X. enat (i_of x) < llength Xs" and
in_inter: "∀x ∈ X. x ∈ (⋂j ∈ {j. i_of x ≤ j ∧ enat j < llength Xs}. lnth Xs j)"
using bchoice[OF in_lim'] by blast
define i_max where
"i_max = Max (i_of ` X)"
have "i_max ∈ i_of ` X"
by (simp add: fin i_max_def nemp)
then obtain x_max where
x_max_in: "x_max ∈ X" and
i_max_is: "i_max = i_of x_max"
unfolding i_max_def by blast
have le_i_max: "∀x ∈ X. i_of x ≤ i_max"
unfolding i_max_def by (simp add: fin)
have "enat i_max < llength Xs"
using i_of_lt x_max_in i_max_is by auto
moreover have "X ⊆ (⋂j ∈ {j. i_max ≤ j ∧ enat j < llength Xs}. lnth Xs j)"
proof
fix x
assume x_in: "x ∈ X"
then have x_in_inter: "x ∈ (⋂j ∈ {j. i_of x ≤ j ∧ enat j < llength Xs}. lnth Xs j)"
using in_inter by auto
moreover have "{j. i_max ≤ j ∧ enat j < llength Xs}
⊆ {j. i_of x ≤ j ∧ enat j < llength Xs}"
using x_in le_i_max by auto
ultimately show "x ∈ (⋂j ∈ {j. i_max ≤ j ∧ enat j < llength Xs}. lnth Xs j)"
by auto
qed
ultimately show ?thesis
by auto
qed
qed
lemma Liminf_llist_lmap_image:
assumes f_inj: "inj_on f (Sup_llist (lmap g xs))"
shows "Liminf_llist (lmap (λx. f ` g x) xs) = f ` Liminf_llist (lmap g xs)" (is "?lhs = ?rhs")
proof
show "?lhs ⊆ ?rhs"
proof
fix x
assume "x ∈ Liminf_llist (lmap (λx. f ` g x) xs)"
then obtain i where
i_lt: "enat i < llength xs" and
x_in_fgj: "∀j. i ≤ j ⟶ enat j < llength xs ⟶ x ∈ f ` g (lnth xs j)"
unfolding Liminf_llist_def by auto
have ex_in_gi: "∃y. y ∈ g (lnth xs i) ∧ x = f y"
using f_inj i_lt x_in_fgj unfolding inj_on_def Sup_llist_def by auto
have "∃y. ∀j. i ≤ j ⟶ enat j < llength xs ⟶ y ∈ g (lnth xs j) ∧ x = f y"
apply (rule exI[of _ "SOME y. y ∈ g (lnth xs i) ∧ x = f y"])
using someI_ex[OF ex_in_gi] x_in_fgj f_inj i_lt x_in_fgj unfolding inj_on_def Sup_llist_def
by simp (metis (no_types, lifting) imageE)
then show "x ∈ f ` Liminf_llist (lmap g xs)"
using i_lt unfolding Liminf_llist_def by auto
qed
next
show "?rhs ⊆ ?lhs"
using image_Liminf_llist_subset[of f "lmap g xs", unfolded llist.map_comp] by auto
qed
lemma Liminf_llist_lmap_union:
assumes "∀x ∈ lset xs. ∀Y ∈ lset xs. g x ∩ h Y = {}"
shows "Liminf_llist (lmap (λx. g x ∪ h x) xs) =
Liminf_llist (lmap g xs) ∪ Liminf_llist (lmap h xs)" (is "?lhs = ?rhs")
proof (intro equalityI subsetI)
fix x
assume x_in: "x ∈ ?lhs"
then obtain i where
i_lt: "enat i < llength xs" and
j: "∀j. i ≤ j ∧ enat j < llength xs ⟶ x ∈ g (lnth xs j) ∨ x ∈ h (lnth xs j)"
using x_in[unfolded Liminf_llist_def, simplified] by blast
then have "(∃i'. enat i' < llength xs ∧ (∀j. i' ≤ j ∧ enat j < llength xs ⟶ x ∈ g (lnth xs j)))
∨ (∃i'. enat i' < llength xs ∧ (∀j. i' ≤ j ∧ enat j < llength xs ⟶ x ∈ h (lnth xs j)))"
using assms[unfolded disjoint_iff_not_equal] by (metis in_lset_conv_lnth)
then show "x ∈ ?rhs"
unfolding Liminf_llist_def by simp
next
fix x
show "x ∈ ?rhs ⟹ x ∈ ?lhs"
using assms unfolding Liminf_llist_def by auto
qed
lemma Liminf_set_filter_commute:
"Liminf_llist (lmap (λX. {x ∈ X. p x}) Xs) = {x ∈ Liminf_llist Xs. p x}"
unfolding Liminf_llist_def by force
subsection ‹Liminf up-to›
definition Liminf_upto_llist :: "'a set llist ⇒ enat ⇒ 'a set" where
"Liminf_upto_llist Xs k =
(⋃i ∈ {i. enat i < llength Xs ∧ enat i ≤ k}.
⋂j ∈ {j. i ≤ j ∧ enat j < llength Xs ∧ enat j ≤ k}. lnth Xs j)"
lemma Liminf_upto_llist_eq_Liminf_llist_ltake:
"Liminf_upto_llist Xs j = Liminf_llist (ltake (eSuc j) Xs)"
unfolding Liminf_upto_llist_def Liminf_llist_def
by (smt Collect_cong Sup.SUP_cong iless_Suc_eq lnth_ltake less_llength_ltake mem_Collect_eq)
lemma Liminf_upto_llist_enat[simp]:
"Liminf_upto_llist Xs (enat k) =
(if enat k < llength Xs then lnth Xs k else if lnull Xs then {} else llast Xs)"
proof (cases "enat k < llength Xs")
case True
then show ?thesis
unfolding Liminf_upto_llist_def by force
next
case k_ge: False
show ?thesis
proof (cases "lnull Xs")
case nil: True
then show ?thesis
unfolding Liminf_upto_llist_def by simp
next
case nnil: False
then obtain j where
j: "eSuc (enat j) = llength Xs"
using k_ge by (metis eSuc_enat_iff enat_ile le_less_linear lhd_LCons_ltl llength_LCons)
have fin: "lfinite Xs"
using k_ge not_lfinite_llength by fastforce
have le_k: "enat i < llength Xs ∧ i ≤ k ⟷ enat i < llength Xs" for i
using k_ge linear order_le_less_subst2 by fastforce
have "Liminf_upto_llist Xs (enat k) = llast Xs"
using j nnil lfinite_Liminf_llist[OF fin] nnil
unfolding Liminf_upto_llist_def Liminf_llist_def using llast_conv_lnth[OF j[symmetric]]
by (simp add: le_k)
then show ?thesis
using k_ge nnil by simp
qed
qed
lemma Liminf_upto_llist_infinity[simp]: "Liminf_upto_llist Xs ∞ = Liminf_llist Xs"
unfolding Liminf_upto_llist_def Liminf_llist_def by simp
lemma Liminf_upto_llist_0[simp]:
"Liminf_upto_llist Xs 0 = (if lnull Xs then {} else lhd Xs)"
unfolding Liminf_upto_llist_def image_def
by (simp add: enat_0[symmetric]) (simp add: enat_0 lnth_0_conv_lhd)
lemma Liminf_upto_llist_eSuc[simp]:
"Liminf_upto_llist Xs (eSuc j) =
(case j of
enat k ⇒ Liminf_upto_llist Xs (enat (Suc k))
| ∞ ⇒ Liminf_llist Xs)"
by (auto simp: eSuc_enat split: enat.split)
lemma elem_Liminf_llist_imp_Liminf_upto_llist:
"x ∈ Liminf_llist Xs ⟹
∃i < llength Xs. ∀j. i ≤ j ∧ j < llength Xs ⟶ x ∈ Liminf_upto_llist Xs (enat j)"
unfolding Liminf_llist_def Liminf_upto_llist_def using enat_ord_simps(1) by force
end