Theory Filtermap
theory Filtermap
imports Trivia
begin
section ‹Preliminaries›
function filtermap ::
"('trans ⇒ bool) ⇒ ('trans ⇒ 'a) ⇒ 'trans list ⇒ 'a list"
where
"filtermap pred func [] = []"
|
"¬ pred trn ⟹ filtermap pred func (trn # tr) = filtermap pred func tr"
|
"pred trn ⟹ filtermap pred func (trn # tr) = func trn # filtermap pred func tr"
by auto (metis list.exhaust)
termination by lexicographic_order
lemma filtermap_map_filter: "filtermap pred func xs = map func (filter pred xs)"
by (induction xs) auto
lemma filtermap_append: "filtermap pred func (tr @ tr1) = filtermap pred func tr @ filtermap pred func tr1"
proof(induction tr arbitrary: tr1)
case (Cons trn tr)
thus ?case by (cases "pred trn") auto
qed auto
lemma filtermap_Nil_list_ex: "filtermap pred func tr = [] ⟷ ¬ list_ex pred tr"
proof(induction tr)
case (Cons trn tr)
thus ?case by (cases "pred trn") auto
qed auto
lemma filtermap_Nil_never: "filtermap pred func tr = [] ⟷ never pred tr"
proof(induction tr)
case (Cons trn tr)
thus ?case by (cases "pred trn") auto
qed auto
lemma length_filtermap: "length (filtermap pred func tr) ≤ length tr"
proof(induction tr)
case (Cons trn tr)
thus ?case by (cases "pred trn") auto
qed auto
lemma filtermap_list_all[simp]: "filtermap pred func tr = map func tr ⟷ list_all pred tr"
proof(induction tr)
case (Cons trn tr)
thus ?case apply (cases "pred trn")
by (simp_all) (metis impossible_Cons length_filtermap length_map)
qed auto
lemma filtermap_eq_Cons:
assumes "filtermap pred func tr = a # al1"
shows "∃ trn tr2 tr1.
tr = tr2 @ [trn] @ tr1 ∧ never pred tr2 ∧ pred trn ∧ func trn = a ∧ filtermap pred func tr1 = al1"
using assms proof(induction tr arbitrary: a al1)
case (Cons trn tr a al1)
show ?case
proof(cases "pred trn")
case False
hence "filtermap pred func tr = a # al1" using Cons by simp
from Cons(1)[OF this] obtain trnn tr2 tr1 where
1: "tr = tr2 @ [trnn] @ tr1 ∧ never pred tr2 ∧ pred trnn ∧ func trnn = a ∧
filtermap pred func tr1 = al1" by blast
show ?thesis apply(rule exI[of _ trnn], rule exI[of _ "trn # tr2"], rule exI[of _ tr1])
using Cons(2) 1 False by simp
next
case True
hence "filtermap pred func tr = al1" using Cons by simp
show ?thesis apply(rule exI[of _ trn], rule exI[of _ "[]"], rule exI[of _ tr])
using Cons(2) True by simp
qed
qed auto
lemma filtermap_eq_append:
assumes "filtermap pred func tr = al1 @ al2"
shows "∃ tr1 tr2. tr = tr1 @ tr2 ∧ filtermap pred func tr1 = al1 ∧ filtermap pred func tr2 = al2"
using assms proof(induction al1 arbitrary: tr)
case Nil show ?case
apply (rule exI[of _ "[]"], rule exI[of _ tr]) using Nil by auto
next
case (Cons a al1 tr)
hence "filtermap pred func tr = a # (al1 @ al2)" by simp
from filtermap_eq_Cons[OF this] obtain trn tr2 tr1
where tr: "tr = tr2 @ [trn] @ tr1" and n: "never pred tr2 ∧ pred trn ∧ func trn = a"
and f: "filtermap pred func tr1 = al1 @ al2" by blast
from Cons(1)[OF f] obtain tr11 tr22 where tr1: "tr1 = tr11 @ tr22"
and f1: "filtermap pred func tr11 = al1" and f2: "filtermap pred func tr22 = al2" by blast
show ?case apply (rule exI[of _ "tr2 @ [trn] @ tr11"], rule exI[of _ tr22])
using n filtermap_Nil_never f1 f2 unfolding tr tr1 filtermap_append by auto
qed
lemma holds_filtermap_RCons[simp]:
"pred trn ⟹ filtermap pred func (tr ## trn) = filtermap pred func tr ## func trn"
proof(induction tr)
case (Cons trn1 tr)
thus ?case by (cases "pred trn1") auto
qed auto
lemma not_holds_filtermap_RCons[simp]:
"¬ pred trn ⟹ filtermap pred func (tr ## trn) = filtermap pred func tr"
proof(induction tr)
case (Cons trn1 tr)
thus ?case by (cases "pred trn1") auto
qed auto
lemma filtermap_eq_RCons:
assumes "filtermap pred func tr = al1 ## a"
shows "∃ trn tr1 tr2.
tr = tr1 @ [trn] @ tr2 ∧ never pred tr2 ∧ pred trn ∧ func trn = a ∧ filtermap pred func tr1 = al1"
using assms proof(induction tr arbitrary: a al1 rule: rev_induct)
case (snoc trn tr a al1)
show ?case
proof(cases "pred trn")
case False
hence "filtermap pred func tr = al1 ## a" using snoc by simp
from snoc(1)[OF this] obtain trnn tr2 tr1 where
1: "tr = tr1 @ [trnn] @ tr2 ∧ never pred tr2 ∧ pred trnn ∧ func trnn = a ∧
filtermap pred func tr1 = al1" by blast
show ?thesis apply(rule exI[of _ trnn], rule exI[of _ tr1], rule exI[of _ "tr2 ## trn"])
using snoc(2) 1 False by simp
next
case True
hence "filtermap pred func tr = al1" using snoc by simp
show ?thesis apply(rule exI[of _ trn], rule exI[of _ tr], rule exI[of _ "[]"])
using snoc(2) True by simp
qed
qed auto
lemma filtermap_eq_Cons_RCons:
assumes "filtermap pred func tr = a # al1 ## b"
shows "∃ tra trna tr1 trnb trb.
tr = tra @ [trna] @ tr1 @ [trnb] @ trb ∧
never pred tra ∧
pred trna ∧ func trna = a ∧
filtermap pred func tr1 = al1 ∧
pred trnb ∧ func trnb = b ∧
never pred trb"
proof-
from filtermap_eq_Cons[OF assms] obtain trna tra tr2
where 0: "tr = tra @ [trna] @ tr2 ∧ never pred tra ∧ pred trna ∧ func trna = a"
and 1: "filtermap pred func tr2 = al1 ## b" by auto
from filtermap_eq_RCons[OF 1] obtain trnb tr1 trb where
2: "tr2 = tr1 @ [trnb] @ trb ∧ never pred trb ∧
pred trnb ∧ func trnb = b ∧ filtermap pred func tr1 = al1" by blast
show ?thesis apply(rule exI[of _ tra], rule exI[of _ trna], rule exI[of _ tr1],
rule exI[of _ trnb], rule exI[of _ trb])
using 2 0 by auto
qed
lemma filter_Nil_never: "[] = filter pred xs ⟹ never pred xs"
by (induction xs) (auto split: if_splits)
lemma never_Nil_filter: "never pred xs ⟷ [] = filter pred xs"
by (induction xs) (auto split: if_splits)
lemma snoc_eq_filterD:
assumes "xs ## x = filter Q ys"
obtains us vs where "ys = us @ x # vs" and "never Q vs" and "Q x" and "xs = filter Q us"
using assms proof (induction ys rule: rev_induct)
case Nil then show ?case by auto
next
case (snoc y ys)
show ?case
proof (cases)
assume "Q y"
moreover then have "x = y" using snoc.prems by auto
ultimately show thesis using snoc(3) snoc(2) by auto
next
assume "¬Q y"
show thesis
proof (rule snoc.IH)
show "xs ## x = filter Q ys" using ‹¬Q y› snoc(3) by auto
next
fix us vs
assume "ys = us @ x # vs" and "never Q vs" and "Q x" and "xs = filter Q us"
then show thesis using ‹¬Q y› snoc(2) by auto
qed
qed
qed
lemma filtermap_Cons2_eq:
"filtermap pred func [x, x'] = filtermap pred func [y, y']
⟹ filtermap pred func (x # x' # zs) = filtermap pred func (y # y' # zs)"
unfolding filtermap_append[of pred func "[x, x']" "zs", simplified]
filtermap_append[of pred func "[y, y']" "zs", simplified]
by simp
lemma filtermap_Cons_cong:
"filtermap pred func xs = filtermap pred func ys
⟹ filtermap pred func (x # xs) = filtermap pred func (x # ys)"
by (cases "pred x") auto
lemma set_filtermap:
"set (filtermap pred func xs) ⊆ {func x | x . x ∈∈ xs ∧ pred x}"
by (induct xs, simp) (case_tac "pred a", auto)
end