# HG changeset patch # User traytel # Date 1360924319 -3600 # Node ID cc7423ce677414aee2043166012450013fb64917 # Parent 59e311235de4cbaf2845997da5db86f05ccbe279 extended stream library diff -r 59e311235de4 -r cc7423ce6774 src/HOL/BNF/Examples/Stream.thy --- a/src/HOL/BNF/Examples/Stream.thy Fri Feb 15 09:59:46 2013 +0100 +++ b/src/HOL/BNF/Examples/Stream.thy Fri Feb 15 11:31:59 2013 +0100 @@ -16,25 +16,33 @@ (* TODO: Provide by the package*) theorem stream_set_induct: - "\\s. P (shd s) s; \s y. \y \ stream_set (stl s); P y (stl s)\ \ P y s\ \ - \y \ stream_set s. P y s" -by (rule stream.dtor_set_induct) - (auto simp add: shd_def stl_def stream_case_def fsts_def snds_def split_beta) + "\\s. P (shd s) s; \s y. \y \ stream_set (stl s); P y (stl s)\ \ P y s\ \ + \y \ stream_set s. P y s" + by (rule stream.dtor_set_induct) + (auto simp add: shd_def stl_def stream_case_def fsts_def snds_def split_beta) + +lemma stream_map_simps[simp]: + "shd (stream_map f s) = f (shd s)" "stl (stream_map f s) = stream_map f (stl s)" + unfolding shd_def stl_def stream_case_def stream_map_def stream.dtor_unfold + by (case_tac [!] s) (auto simp: Stream_def stream.dtor_ctor) + +lemma stream_map_Stream[simp]: "stream_map f (x ## s) = f x ## stream_map f s" + by (metis stream.exhaust stream.sels stream_map_simps) theorem shd_stream_set: "shd s \ stream_set s" -by (auto simp add: shd_def stl_def stream_case_def fsts_def snds_def split_beta) - (metis UnCI fsts_def insertI1 stream.dtor_set) + by (auto simp add: shd_def stl_def stream_case_def fsts_def snds_def split_beta) + (metis UnCI fsts_def insertI1 stream.dtor_set) theorem stl_stream_set: "y \ stream_set (stl s) \ y \ stream_set s" -by (auto simp add: shd_def stl_def stream_case_def fsts_def snds_def split_beta) - (metis insertI1 set_mp snds_def stream.dtor_set_set_incl) + by (auto simp add: shd_def stl_def stream_case_def fsts_def snds_def split_beta) + (metis insertI1 set_mp snds_def stream.dtor_set_set_incl) (* only for the non-mutual case: *) theorem stream_set_induct1[consumes 1, case_names shd stl, induct set: "stream_set"]: assumes "y \ stream_set s" and "\s. P (shd s) s" and "\s y. \y \ stream_set (stl s); P y (stl s)\ \ P y s" shows "P y s" -using assms stream_set_induct by blast + using assms stream_set_induct by blast (* end TODO *) @@ -45,39 +53,18 @@ | "shift (x # xs) s = x ## shift xs s" lemma shift_append[simp]: "(xs @ ys) @- s = xs @- ys @- s" -by (induct xs) auto + by (induct xs) auto lemma shift_simps[simp]: "shd (xs @- s) = (if xs = [] then shd s else hd xs)" "stl (xs @- s) = (if xs = [] then stl s else tl xs @- s)" -by (induct xs) auto - - -subsection {* recurring stream out of a list *} + by (induct xs) auto -definition cycle :: "'a list \ 'a stream" where - "cycle = stream_unfold hd (\xs. tl xs @ [hd xs])" - -lemma cycle_simps[simp]: - "shd (cycle u) = hd u" - "stl (cycle u) = cycle (tl u @ [hd u])" -by (auto simp: cycle_def) +lemma stream_set_shift[simp]: "stream_set (xs @- s) = set xs \ stream_set s" + by (induct xs) auto -lemma cycle_decomp: "u \ [] \ cycle u = u @- cycle u" -proof (coinduct rule: stream.coinduct[of "\s1 s2. \u. s1 = cycle u \ s2 = u @- cycle u \ u \ []"]) - case (2 s1 s2) - then obtain u where "s1 = cycle u \ s2 = u @- cycle u \ u \ []" by blast - thus ?case using stream.unfold[of hd "\xs. tl xs @ [hd xs]" u] by (auto simp: cycle_def) -qed auto - -lemma cycle_Cons: "cycle (x # xs) = x ## cycle (xs @ [x])" -proof (coinduct rule: stream.coinduct[of "\s1 s2. \x xs. s1 = cycle (x # xs) \ s2 = x ## cycle (xs @ [x])"]) - case (2 s1 s2) - then obtain x xs where "s1 = cycle (x # xs) \ s2 = x ## cycle (xs @ [x])" by blast - thus ?case - by (auto simp: cycle_def intro!: exI[of _ "hd (xs @ [x])"] exI[of _ "tl (xs @ [x])"] stream.unfold) -qed auto +subsection {* set of streams with elements in some fixes set *} coinductive_set streams :: "'a set => 'a stream set" @@ -86,7 +73,7 @@ Stream[intro!, simp, no_atp]: "\a \ A; s \ streams A\ \ a ## s \ streams A" lemma shift_streams: "\w \ lists A; s \ streams A\ \ w @- s \ streams A" -by (induct w) auto + by (induct w) auto lemma stream_set_streams: assumes "stream_set s \ A" @@ -110,52 +97,137 @@ lemma flat_simps[simp]: "shd (flat ws) = hd (shd ws)" "stl (flat ws) = flat (if tl (shd ws) = [] then stl ws else tl (shd ws) ## stl ws)" -unfolding flat_def by auto + unfolding flat_def by auto lemma flat_Cons[simp]: "flat ((x # xs) ## ws) = x ## flat (if xs = [] then ws else xs ## ws)" -unfolding flat_def using stream.unfold[of "hd o shd" _ "(x # xs) ## ws"] by auto + unfolding flat_def using stream.unfold[of "hd o shd" _ "(x # xs) ## ws"] by auto lemma flat_Stream[simp]: "xs \ [] \ flat (xs ## ws) = xs @- flat ws" -by (induct xs) auto + by (induct xs) auto lemma flat_unfold: "shd ws \ [] \ flat ws = shd ws @- flat (stl ws)" -by (cases ws) auto + by (cases ws) auto -subsection {* take, drop, nth for streams *} +subsection {* nth, take, drop for streams *} + +primrec snth :: "'a stream \ nat \ 'a" (infixl "!!" 100) where + "s !! 0 = shd s" +| "s !! Suc n = stl s !! n" + +lemma snth_stream_map[simp]: "stream_map f s !! n = f (s !! n)" + by (induct n arbitrary: s) auto + +lemma shift_snth_less[simp]: "p < length xs \ (xs @- s) !! p = xs ! p" + by (induct p arbitrary: xs) (auto simp: hd_conv_nth nth_tl) + +lemma shift_snth_ge[simp]: "p \ length xs \ (xs @- s) !! p = s !! (p - length xs)" + by (induct p arbitrary: xs) (auto simp: Suc_diff_eq_diff_pred) + +lemma snth_stream_set[simp]: "s !! n \ stream_set s" + by (induct n arbitrary: s) (auto intro: shd_stream_set stl_stream_set) + +lemma stream_set_range: "stream_set s = range (snth s)" +proof (intro equalityI subsetI) + fix x assume "x \ stream_set s" + thus "x \ range (snth s)" + proof (induct s) + case (stl s x) + then obtain n where "x = stl s !! n" by auto + thus ?case by (auto intro: range_eqI[of _ _ "Suc n"]) + qed (auto intro: range_eqI[of _ _ 0]) +qed auto primrec stake :: "nat \ 'a stream \ 'a list" where "stake 0 s = []" | "stake (Suc n) s = shd s # stake n (stl s)" +lemma length_stake[simp]: "length (stake n s) = n" + by (induct n arbitrary: s) auto + +lemma stake_stream_map[simp]: "stake n (stream_map f s) = map f (stake n s)" + by (induct n arbitrary: s) auto + primrec sdrop :: "nat \ 'a stream \ 'a stream" where "sdrop 0 s = s" | "sdrop (Suc n) s = sdrop n (stl s)" -primrec snth :: "'a stream \ nat \ 'a" (infixl "!!" 100) where - "s !! 0 = shd s" -| "s !! Suc n = stl s !! n" +lemma sdrop_simps[simp]: + "shd (sdrop n s) = s !! n" "stl (sdrop n s) = sdrop (Suc n) s" + by (induct n arbitrary: s) auto + +lemma sdrop_stream_map[simp]: "sdrop n (stream_map f s) = stream_map f (sdrop n s)" + by (induct n arbitrary: s) auto lemma stake_sdrop: "stake n s @- sdrop n s = s" -by (induct n arbitrary: s) auto + by (induct n arbitrary: s) auto + +lemma id_stake_snth_sdrop: + "s = stake i s @- s !! i ## sdrop (Suc i) s" + by (subst stake_sdrop[symmetric, of _ i]) (metis sdrop_simps stream.collapse) -lemma stake_empty: "stake n s = [] \ n = 0" -by (cases n) auto +lemma stream_map_alt: "stream_map f s = s' \ (\n. f (s !! n) = s' !! n)" (is "?L = ?R") +proof + assume ?R + thus ?L + by (coinduct rule: stream.coinduct[of "\s1 s2. \n. s1 = stream_map f (sdrop n s) \ s2 = sdrop n s'"]) + (auto intro: exI[of _ 0] simp del: sdrop.simps(2)) +qed auto + +lemma stake_invert_Nil[iff]: "stake n s = [] \ n = 0" + by (induct n) auto lemma sdrop_shift: "\s = w @- s'; length w = n\ \ sdrop n s = s'" -by (induct n arbitrary: w s) auto + by (induct n arbitrary: w s) auto lemma stake_shift: "\s = w @- s'; length w = n\ \ stake n s = w" -by (induct n arbitrary: w s) auto + by (induct n arbitrary: w s) auto lemma stake_add[simp]: "stake m s @ stake n (sdrop m s) = stake (m + n) s" -by (induct m arbitrary: s) auto + by (induct m arbitrary: s) auto lemma sdrop_add[simp]: "sdrop n (sdrop m s) = sdrop (m + n) s" -by (induct m arbitrary: s) auto + by (induct m arbitrary: s) auto + + +subsection {* unary predicates lifted to streams *} + +definition "stream_all P s = (\p. P (s !! p))" + +lemma stream_all_iff[iff]: "stream_all P s \ Ball (stream_set s) P" + unfolding stream_all_def stream_set_range by auto + +lemma stream_all_shift[simp]: "stream_all P (xs @- s) = (list_all P xs \ stream_all P s)" + unfolding stream_all_iff list_all_iff by auto + + +subsection {* recurring stream out of a list *} + +definition cycle :: "'a list \ 'a stream" where + "cycle = stream_unfold hd (\xs. tl xs @ [hd xs])" + +lemma cycle_simps[simp]: + "shd (cycle u) = hd u" + "stl (cycle u) = cycle (tl u @ [hd u])" + by (auto simp: cycle_def) + +lemma cycle_decomp: "u \ [] \ cycle u = u @- cycle u" +proof (coinduct rule: stream.coinduct[of "\s1 s2. \u. s1 = cycle u \ s2 = u @- cycle u \ u \ []"]) + case (2 s1 s2) + then obtain u where "s1 = cycle u \ s2 = u @- cycle u \ u \ []" by blast + thus ?case using stream.unfold[of hd "\xs. tl xs @ [hd xs]" u] by (auto simp: cycle_def) +qed auto + +lemma cycle_Cons: "cycle (x # xs) = x ## cycle (xs @ [x])" +proof (coinduct rule: stream.coinduct[of "\s1 s2. \x xs. s1 = cycle (x # xs) \ s2 = x ## cycle (xs @ [x])"]) + case (2 s1 s2) + then obtain x xs where "s1 = cycle (x # xs) \ s2 = x ## cycle (xs @ [x])" by blast + thus ?case + by (auto simp: cycle_def intro!: exI[of _ "hd (xs @ [x])"] exI[of _ "tl (xs @ [x])"] stream.unfold) +qed auto lemma cycle_rotated: "\v \ []; cycle u = v @- s\ \ cycle (tl u @ [hd u]) = tl v @- s" -by (auto dest: arg_cong[of _ _ stl]) + by (auto dest: arg_cong[of _ _ stl]) lemma stake_append: "stake n (u @- s) = take (min (length u) n) u @ stake (n - length u) s" proof (induct n arbitrary: u) @@ -166,27 +238,105 @@ assumes "u \ []" "n < length u" shows "stake n (cycle u) = take n u" using min_absorb2[OF less_imp_le_nat[OF assms(2)]] -by (subst cycle_decomp[OF assms(1)], subst stake_append) auto + by (subst cycle_decomp[OF assms(1)], subst stake_append) auto lemma stake_cycle_eq[simp]: "u \ [] \ stake (length u) (cycle u) = u" -by (metis cycle_decomp stake_shift) + by (metis cycle_decomp stake_shift) lemma sdrop_cycle_eq[simp]: "u \ [] \ sdrop (length u) (cycle u) = cycle u" -by (metis cycle_decomp sdrop_shift) + by (metis cycle_decomp sdrop_shift) lemma stake_cycle_eq_mod_0[simp]: "\u \ []; n mod length u = 0\ \ stake n (cycle u) = concat (replicate (n div length u) u)" -by (induct "n div length u" arbitrary: n u) (auto simp: stake_add[symmetric]) + by (induct "n div length u" arbitrary: n u) (auto simp: stake_add[symmetric]) lemma sdrop_cycle_eq_mod_0[simp]: "\u \ []; n mod length u = 0\ \ sdrop n (cycle u) = cycle u" -by (induct "n div length u" arbitrary: n u) (auto simp: sdrop_add[symmetric]) + by (induct "n div length u" arbitrary: n u) (auto simp: sdrop_add[symmetric]) lemma stake_cycle: "u \ [] \ stake n (cycle u) = concat (replicate (n div length u) u) @ take (n mod length u) u" -by (subst mod_div_equality[of n "length u", symmetric], unfold stake_add[symmetric]) auto + by (subst mod_div_equality[of n "length u", symmetric], unfold stake_add[symmetric]) auto lemma sdrop_cycle: "u \ [] \ sdrop n (cycle u) = cycle (rotate (n mod length u) u)" -by (induct n arbitrary: u) (auto simp: rotate1_rotate_swap rotate1_hd_tl rotate_conv_mod[symmetric]) + by (induct n arbitrary: u) (auto simp: rotate1_rotate_swap rotate1_hd_tl rotate_conv_mod[symmetric]) + + +subsection {* stream repeating a single element *} + +definition "same x = stream_unfold (\_. x) id ()" + +lemma same_simps[simp]: "shd (same x) = x" "stl (same x) = same x" + unfolding same_def by auto + +lemma same_unfold: "same x = Stream x (same x)" + by (metis same_simps stream.collapse) + +lemma snth_same[simp]: "same x !! n = x" + unfolding same_def by (induct n) auto + +lemma stake_same[simp]: "stake n (same x) = replicate n x" + unfolding same_def by (induct n) (auto simp: upt_rec) + +lemma sdrop_same[simp]: "sdrop n (same x) = same x" + unfolding same_def by (induct n) auto + +lemma shift_replicate_same[simp]: "replicate n x @- same x = same x" + by (metis sdrop_same stake_same stake_sdrop) + +lemma stream_all_same[simp]: "stream_all P (same x) \ P x" + unfolding stream_all_def by auto + +lemma same_cycle: "same x = cycle [x]" + by (coinduct rule: stream.coinduct[of "\s1 s2. s1 = same x \ s2 = cycle [x]"]) auto + + +subsection {* stream of natural numbers *} + +definition "fromN n = stream_unfold id Suc n" + +lemma fromN_simps[simp]: "shd (fromN n) = n" "stl (fromN n) = fromN (Suc n)" + unfolding fromN_def by auto + +lemma snth_fromN[simp]: "fromN n !! m = n + m" + unfolding fromN_def by (induct m arbitrary: n) auto + +lemma stake_fromN[simp]: "stake m (fromN n) = [n ..< m + n]" + unfolding fromN_def by (induct m arbitrary: n) (auto simp: upt_rec) + +lemma sdrop_fromN[simp]: "sdrop m (fromN n) = fromN (n + m)" + unfolding fromN_def by (induct m arbitrary: n) auto + +abbreviation "nats \ fromN 0" + + +subsection {* zip *} + +definition "szip s1 s2 = + stream_unfold (map_pair shd shd) (map_pair stl stl) (s1, s2)" + +lemma szip_simps[simp]: + "shd (szip s1 s2) = (shd s1, shd s2)" "stl (szip s1 s2) = szip (stl s1) (stl s2)" + unfolding szip_def by auto + +lemma snth_szip[simp]: "szip s1 s2 !! n = (s1 !! n, s2 !! n)" + by (induct n arbitrary: s1 s2) auto + + +subsection {* zip via function *} + +definition "stream_map2 f s1 s2 = + stream_unfold (\(s1,s2). f (shd s1) (shd s2)) (map_pair stl stl) (s1, s2)" + +lemma stream_map2_simps[simp]: + "shd (stream_map2 f s1 s2) = f (shd s1) (shd s2)" + "stl (stream_map2 f s1 s2) = stream_map2 f (stl s1) (stl s2)" + unfolding stream_map2_def by auto + +lemma stream_map2_szip: + "stream_map2 f s1 s2 = stream_map (split f) (szip s1 s2)" + by (coinduct rule: stream.coinduct[of + "\s1 s2. \s1' s2'. s1 = stream_map2 f s1' s2' \ s2 = stream_map (split f) (szip s1' s2')"]) + fastforce+ end