src/HOL/BNF/Examples/Stream.thy
changeset 54027 e5853a648b59
parent 53808 b3e2022530e3
child 54469 0ccec59194af
equal deleted inserted replaced
54026:82d9b2701a03 54027:e5853a648b59
    99   by (induct w) auto
    99   by (induct w) auto
   100 
   100 
   101 lemma sset_streams:
   101 lemma sset_streams:
   102   assumes "sset s \<subseteq> A"
   102   assumes "sset s \<subseteq> A"
   103   shows "s \<in> streams A"
   103   shows "s \<in> streams A"
   104 proof (coinduct rule: streams.coinduct[of "\<lambda>s'. \<exists>a s. s' = a ## s \<and> a \<in> A \<and> sset s \<subseteq> A"])
   104 using assms proof (coinduction arbitrary: s)
   105   case streams from assms show ?case by (cases s) auto
   105   case streams then show ?case by (cases s) simp
   106 next
       
   107   fix s' assume "\<exists>a s. s' = a ## s \<and> a \<in> A \<and> sset s \<subseteq> A"
       
   108   then guess a s by (elim exE)
       
   109   with assms show "\<exists>a l. s' = a ## l \<and>
       
   110     a \<in> A \<and> ((\<exists>a s. l = a ## s \<and> a \<in> A \<and> sset s \<subseteq> A) \<or> l \<in> streams A)"
       
   111     by (cases s) auto
       
   112 qed
   106 qed
   113 
   107 
   114 
   108 
   115 subsection {* nth, take, drop for streams *}
   109 subsection {* nth, take, drop for streams *}
   116 
   110 
   173   by (subst stake_sdrop[symmetric, of _ i]) (metis sdrop_simps stream.collapse)
   167   by (subst stake_sdrop[symmetric, of _ i]) (metis sdrop_simps stream.collapse)
   174 
   168 
   175 lemma smap_alt: "smap f s = s' \<longleftrightarrow> (\<forall>n. f (s !! n) = s' !! n)" (is "?L = ?R")
   169 lemma smap_alt: "smap f s = s' \<longleftrightarrow> (\<forall>n. f (s !! n) = s' !! n)" (is "?L = ?R")
   176 proof
   170 proof
   177   assume ?R
   171   assume ?R
   178   thus ?L 
   172   then have "\<And>n. smap f (sdrop n s) = sdrop n s'"
   179     by (coinduct rule: stream.coinduct[of "\<lambda>s1 s2. \<exists>n. s1 = smap f (sdrop n s) \<and> s2 = sdrop n s'", consumes 0])
   173     by coinduction (auto intro: exI[of _ 0] simp del: sdrop.simps(2))
   180       (auto intro: exI[of _ 0] simp del: sdrop.simps(2))
   174   then show ?L using sdrop.simps(1) by metis
   181 qed auto
   175 qed auto
   182 
   176 
   183 lemma stake_invert_Nil[iff]: "stake n s = [] \<longleftrightarrow> n = 0"
   177 lemma stake_invert_Nil[iff]: "stake n s = [] \<longleftrightarrow> n = 0"
   184   by (induct n) auto
   178   by (induct n) auto
   185 
   179 
   216     moreover from Suc(3) have "\<not> (P (s !! 0))" by blast
   210     moreover from Suc(3) have "\<not> (P (s !! 0))" by blast
   217     ultimately show ?case by (subst sdrop_while.simps) simp
   211     ultimately show ?case by (subst sdrop_while.simps) simp
   218   qed (metis comp_apply sdrop.simps(1) sdrop_while.simps snth.simps(1))
   212   qed (metis comp_apply sdrop.simps(1) sdrop_while.simps snth.simps(1))
   219 qed
   213 qed
   220 
   214 
   221 definition "sfilter P = stream_unfold (shd o sdrop_while (Not o P)) (stl o sdrop_while (Not o P))"
   215 primcorec sfilter where
       
   216   "shd (sfilter P s) = shd (sdrop_while (Not o P) s)"
       
   217 | "stl (sfilter P s) = sfilter P (stl (sdrop_while (Not o P) s))"
   222 
   218 
   223 lemma sfilter_Stream: "sfilter P (x ## s) = (if P x then x ## sfilter P s else sfilter P s)"
   219 lemma sfilter_Stream: "sfilter P (x ## s) = (if P x then x ## sfilter P s else sfilter P s)"
   224 proof (cases "P x")
   220 proof (cases "P x")
   225   case True thus ?thesis unfolding sfilter_def
   221   case True thus ?thesis by (subst sfilter.ctr) (simp add: sdrop_while_Stream)
   226     by (subst stream.unfold) (simp add: sdrop_while_Stream)
       
   227 next
   222 next
   228   case False thus ?thesis unfolding sfilter_def
   223   case False thus ?thesis by (subst (1 2) sfilter.ctr) (simp add: sdrop_while_Stream)
   229     by (subst (1 2) stream.unfold) (simp add: sdrop_while_Stream)
       
   230 qed
   224 qed
   231 
   225 
   232 
   226 
   233 subsection {* unary predicates lifted to streams *}
   227 subsection {* unary predicates lifted to streams *}
   234 
   228 
   241   unfolding stream_all_iff list_all_iff by auto
   235   unfolding stream_all_iff list_all_iff by auto
   242 
   236 
   243 
   237 
   244 subsection {* recurring stream out of a list *}
   238 subsection {* recurring stream out of a list *}
   245 
   239 
   246 definition cycle :: "'a list \<Rightarrow> 'a stream" where
   240 primcorec cycle :: "'a list \<Rightarrow> 'a stream" where
   247   "cycle = stream_unfold hd (\<lambda>xs. tl xs @ [hd xs])"
   241   "shd (cycle xs) = hd xs"
   248 
   242 | "stl (cycle xs) = cycle (tl xs @ [hd xs])"
   249 lemma cycle_simps[simp]:
       
   250   "shd (cycle u) = hd u"
       
   251   "stl (cycle u) = cycle (tl u @ [hd u])"
       
   252   by (auto simp: cycle_def)
       
   253 
       
   254 lemma cycle_decomp: "u \<noteq> [] \<Longrightarrow> cycle u = u @- cycle u"
   243 lemma cycle_decomp: "u \<noteq> [] \<Longrightarrow> cycle u = u @- cycle u"
   255 proof (coinduct rule: stream.coinduct[of "\<lambda>s1 s2. \<exists>u. s1 = cycle u \<and> s2 = u @- cycle u \<and> u \<noteq> []", consumes 0, case_names _ Eq_stream])
   244 proof (coinduction arbitrary: u)
   256   case (Eq_stream s1 s2)
   245   case Eq_stream then show ?case using stream.collapse[of "cycle u"]
   257   then obtain u where "s1 = cycle u \<and> s2 = u @- cycle u \<and> u \<noteq> []" by blast
   246     by (auto intro!: exI[of _ "tl u @ [hd u]"])
   258   thus ?case using stream.unfold[of hd "\<lambda>xs. tl xs @ [hd xs]" u] by (auto simp: cycle_def)
   247 qed
   259 qed auto
       
   260 
   248 
   261 lemma cycle_Cons[code]: "cycle (x # xs) = x ## cycle (xs @ [x])"
   249 lemma cycle_Cons[code]: "cycle (x # xs) = x ## cycle (xs @ [x])"
   262 proof (coinduct rule: stream.coinduct[of "\<lambda>s1 s2. \<exists>x xs. s1 = cycle (x # xs) \<and> s2 = x ## cycle (xs @ [x])", consumes 0, case_names _ Eq_stream])
   250   by (subst cycle.ctr) simp
   263   case (Eq_stream s1 s2)
       
   264   then obtain x xs where "s1 = cycle (x # xs) \<and> s2 = x ## cycle (xs @ [x])" by blast
       
   265   thus ?case
       
   266     by (auto simp: cycle_def intro!: exI[of _ "hd (xs @ [x])"] exI[of _ "tl (xs @ [x])"] stream.unfold)
       
   267 qed auto
       
   268 
   251 
   269 lemma cycle_rotated: "\<lbrakk>v \<noteq> []; cycle u = v @- s\<rbrakk> \<Longrightarrow> cycle (tl u @ [hd u]) = tl v @- s"
   252 lemma cycle_rotated: "\<lbrakk>v \<noteq> []; cycle u = v @- s\<rbrakk> \<Longrightarrow> cycle (tl u @ [hd u]) = tl v @- s"
   270   by (auto dest: arg_cong[of _ _ stl])
   253   by (auto dest: arg_cong[of _ _ stl])
   271 
   254 
   272 lemma stake_append: "stake n (u @- s) = take (min (length u) n) u @ stake (n - length u) s"
   255 lemma stake_append: "stake n (u @- s) = take (min (length u) n) u @ stake (n - length u) s"
   302   by (induct n arbitrary: u) (auto simp: rotate1_rotate_swap rotate1_hd_tl rotate_conv_mod[symmetric])
   285   by (induct n arbitrary: u) (auto simp: rotate1_rotate_swap rotate1_hd_tl rotate_conv_mod[symmetric])
   303 
   286 
   304 
   287 
   305 subsection {* stream repeating a single element *}
   288 subsection {* stream repeating a single element *}
   306 
   289 
   307 definition "same x = stream_unfold (\<lambda>_. x) id ()"
   290 primcorec same where
   308 
   291   "shd (same x) = x"
   309 lemma same_simps[simp]: "shd (same x) = x" "stl (same x) = same x"
   292 | "stl (same x) = same x"
   310   unfolding same_def by auto
       
   311 
       
   312 lemma same_unfold[code]: "same x = x ## same x"
       
   313   by (metis same_simps stream.collapse)
       
   314 
   293 
   315 lemma snth_same[simp]: "same x !! n = x"
   294 lemma snth_same[simp]: "same x !! n = x"
   316   unfolding same_def by (induct n) auto
   295   unfolding same_def by (induct n) auto
   317 
   296 
   318 lemma stake_same[simp]: "stake n (same x) = replicate n x"
   297 lemma stake_same[simp]: "stake n (same x) = replicate n x"
   326 
   305 
   327 lemma stream_all_same[simp]: "stream_all P (same x) \<longleftrightarrow> P x"
   306 lemma stream_all_same[simp]: "stream_all P (same x) \<longleftrightarrow> P x"
   328   unfolding stream_all_def by auto
   307   unfolding stream_all_def by auto
   329 
   308 
   330 lemma same_cycle: "same x = cycle [x]"
   309 lemma same_cycle: "same x = cycle [x]"
   331   by (coinduct rule: stream.coinduct[of "\<lambda>s1 s2. s1 = same x \<and> s2 = cycle [x]"]) auto
   310   by coinduction auto
   332 
   311 
   333 
   312 
   334 subsection {* stream of natural numbers *}
   313 subsection {* stream of natural numbers *}
   335 
   314 
   336 definition "fromN n = stream_unfold id Suc n"
   315 primcorec fromN :: "nat \<Rightarrow> nat stream" where
   337 
   316   "fromN n = n ## fromN (n + 1)"
   338 lemma fromN_simps[simp]: "shd (fromN n) = n" "stl (fromN n) = fromN (Suc n)"
       
   339   unfolding fromN_def by auto
       
   340 
       
   341 lemma fromN_unfold[code]: "fromN n = n ## fromN (Suc n)"
       
   342   unfolding fromN_def by (metis id_def stream.unfold)
       
   343 
   317 
   344 lemma snth_fromN[simp]: "fromN n !! m = n + m"
   318 lemma snth_fromN[simp]: "fromN n !! m = n + m"
   345   unfolding fromN_def by (induct m arbitrary: n) auto
   319   unfolding fromN_def by (induct m arbitrary: n) auto
   346 
   320 
   347 lemma stake_fromN[simp]: "stake m (fromN n) = [n ..< m + n]"
   321 lemma stake_fromN[simp]: "stake m (fromN n) = [n ..< m + n]"
   350 lemma sdrop_fromN[simp]: "sdrop m (fromN n) = fromN (n + m)"
   324 lemma sdrop_fromN[simp]: "sdrop m (fromN n) = fromN (n + m)"
   351   unfolding fromN_def by (induct m arbitrary: n) auto
   325   unfolding fromN_def by (induct m arbitrary: n) auto
   352 
   326 
   353 lemma sset_fromN[simp]: "sset (fromN n) = {n ..}" (is "?L = ?R")
   327 lemma sset_fromN[simp]: "sset (fromN n) = {n ..}" (is "?L = ?R")
   354 proof safe
   328 proof safe
   355   fix m assume "m : ?L"
   329   fix m assume "m \<in> ?L"
   356   moreover
   330   moreover
   357   { fix s assume "m \<in> sset s" "\<exists>n'\<ge>n. s = fromN n'"
   331   { fix s assume "m \<in> sset s" "\<exists>n'\<ge>n. s = fromN n'"
   358     hence "n \<le> m" by (induct arbitrary: n rule: sset_induct1) fastforce+
   332     hence "n \<le> m"  by (induct arbitrary: n rule: sset_induct1) fastforce+
   359   }
   333   }
   360   ultimately show "n \<le> m" by blast
   334   ultimately show "n \<le> m" by auto
   361 next
   335 next
   362   fix m assume "n \<le> m" thus "m \<in> ?L" by (metis le_iff_add snth_fromN snth_sset)
   336   fix m assume "n \<le> m" thus "m \<in> ?L" by (metis le_iff_add snth_fromN snth_sset)
   363 qed
   337 qed
   364 
   338 
   365 abbreviation "nats \<equiv> fromN 0"
   339 abbreviation "nats \<equiv> fromN 0"
   366 
   340 
   367 
   341 
   368 subsection {* flatten a stream of lists *}
   342 subsection {* flatten a stream of lists *}
   369 
   343 
   370 definition flat where
   344 primcorec flat where
   371   "flat \<equiv> stream_unfold (hd o shd) (\<lambda>s. if tl (shd s) = [] then stl s else tl (shd s) ## stl s)"
       
   372 
       
   373 lemma flat_simps[simp]:
       
   374   "shd (flat ws) = hd (shd ws)"
   345   "shd (flat ws) = hd (shd ws)"
   375   "stl (flat ws) = flat (if tl (shd ws) = [] then stl ws else tl (shd ws) ## stl ws)"
   346 | "stl (flat ws) = flat (if tl (shd ws) = [] then stl ws else tl (shd ws) ## stl ws)"
   376   unfolding flat_def by auto
       
   377 
   347 
   378 lemma flat_Cons[simp, code]: "flat ((x # xs) ## ws) = x ## flat (if xs = [] then ws else xs ## ws)"
   348 lemma flat_Cons[simp, code]: "flat ((x # xs) ## ws) = x ## flat (if xs = [] then ws else xs ## ws)"
   379   unfolding flat_def using stream.unfold[of "hd o shd" _ "(x # xs) ## ws"] by auto
   349   by (subst flat.ctr) simp
   380 
   350 
   381 lemma flat_Stream[simp]: "xs \<noteq> [] \<Longrightarrow> flat (xs ## ws) = xs @- flat ws"
   351 lemma flat_Stream[simp]: "xs \<noteq> [] \<Longrightarrow> flat (xs ## ws) = xs @- flat ws"
   382   by (induct xs) auto
   352   by (induct xs) auto
   383 
   353 
   384 lemma flat_unfold: "shd ws \<noteq> [] \<Longrightarrow> flat ws = shd ws @- flat (stl ws)"
   354 lemma flat_unfold: "shd ws \<noteq> [] \<Longrightarrow> flat ws = shd ws @- flat (stl ws)"
   463   unfolding sproduct_def sset_smerge by (auto simp: stream.set_map)
   433   unfolding sproduct_def sset_smerge by (auto simp: stream.set_map)
   464 
   434 
   465 
   435 
   466 subsection {* interleave two streams *}
   436 subsection {* interleave two streams *}
   467 
   437 
   468 definition sinterleave :: "'a stream \<Rightarrow> 'a stream \<Rightarrow> 'a stream" where
   438 primcorec sinterleave where
   469   [code del]: "sinterleave s1 s2 =
   439   "shd (sinterleave s1 s2) = shd s1"
   470     stream_unfold (\<lambda>(s1, s2). shd s1) (\<lambda>(s1, s2). (s2, stl s1)) (s1, s2)"
   440 | "stl (sinterleave s1 s2) = sinterleave s2 (stl s1)"
   471 
       
   472 lemma sinterleave_simps[simp]:
       
   473   "shd (sinterleave s1 s2) = shd s1" "stl (sinterleave s1 s2) = sinterleave s2 (stl s1)"
       
   474   unfolding sinterleave_def by auto
       
   475 
   441 
   476 lemma sinterleave_code[code]:
   442 lemma sinterleave_code[code]:
   477   "sinterleave (x ## s1) s2 = x ## sinterleave s2 s1"
   443   "sinterleave (x ## s1) s2 = x ## sinterleave s2 s1"
   478   by (metis sinterleave_simps stream.exhaust stream.sel)
   444   by (subst sinterleave.ctr) simp
   479 
   445 
   480 lemma sinterleave_snth[simp]:
   446 lemma sinterleave_snth[simp]:
   481   "even n \<Longrightarrow> sinterleave s1 s2 !! n = s1 !! (n div 2)"
   447   "even n \<Longrightarrow> sinterleave s1 s2 !! n = s1 !! (n div 2)"
   482    "odd n \<Longrightarrow> sinterleave s1 s2 !! n = s2 !! (n div 2)"
   448    "odd n \<Longrightarrow> sinterleave s1 s2 !! n = s2 !! (n div 2)"
   483   by (induct n arbitrary: s1 s2)
   449   by (induct n arbitrary: s1 s2)
   505 qed
   471 qed
   506 
   472 
   507 
   473 
   508 subsection {* zip *}
   474 subsection {* zip *}
   509 
   475 
   510 definition "szip s1 s2 =
   476 primcorec szip where
   511   stream_unfold (map_pair shd shd) (map_pair stl stl) (s1, s2)"
   477   "shd (szip s1 s2) = (shd s1, shd s2)"
   512 
   478 | "stl (szip s1 s2) = szip (stl s1) (stl s2)"
   513 lemma szip_simps[simp]:
       
   514   "shd (szip s1 s2) = (shd s1, shd s2)" "stl (szip s1 s2) = szip (stl s1) (stl s2)"
       
   515   unfolding szip_def by auto
       
   516 
   479 
   517 lemma szip_unfold[code]: "szip (Stream a s1) (Stream b s2) = Stream (a, b) (szip s1 s2)"
   480 lemma szip_unfold[code]: "szip (Stream a s1) (Stream b s2) = Stream (a, b) (szip s1 s2)"
   518   unfolding szip_def by (subst stream.unfold) simp
   481   by (subst szip.ctr) simp
   519 
   482 
   520 lemma snth_szip[simp]: "szip s1 s2 !! n = (s1 !! n, s2 !! n)"
   483 lemma snth_szip[simp]: "szip s1 s2 !! n = (s1 !! n, s2 !! n)"
   521   by (induct n arbitrary: s1 s2) auto
   484   by (induct n arbitrary: s1 s2) auto
   522 
   485 
   523 
   486 
   524 subsection {* zip via function *}
   487 subsection {* zip via function *}
   525 
   488 
   526 definition "smap2 f s1 s2 =
   489 primcorec smap2 where
   527   stream_unfold (\<lambda>(s1,s2). f (shd s1) (shd s2)) (map_pair stl stl) (s1, s2)"
       
   528 
       
   529 lemma smap2_simps[simp]:
       
   530   "shd (smap2 f s1 s2) = f (shd s1) (shd s2)"
   490   "shd (smap2 f s1 s2) = f (shd s1) (shd s2)"
   531   "stl (smap2 f s1 s2) = smap2 f (stl s1) (stl s2)"
   491 | "stl (smap2 f s1 s2) = smap2 f (stl s1) (stl s2)"
   532   unfolding smap2_def by auto
       
   533 
   492 
   534 lemma smap2_unfold[code]:
   493 lemma smap2_unfold[code]:
   535   "smap2 f (Stream a s1) (Stream b s2) = Stream (f a b) (smap2 f s1 s2)"
   494   "smap2 f (Stream a s1) (Stream b s2) = Stream (f a b) (smap2 f s1 s2)"
   536   unfolding smap2_def by (subst stream.unfold) simp
   495   by (subst smap2.ctr) simp
   537 
   496 
   538 lemma smap2_szip:
   497 lemma smap2_szip:
   539   "smap2 f s1 s2 = smap (split f) (szip s1 s2)"
   498   "smap2 f s1 s2 = smap (split f) (szip s1 s2)"
   540   by (coinduct rule: stream.coinduct[of
   499   by (coinduction arbitrary: s1 s2) auto
   541     "\<lambda>s1 s2. \<exists>s1' s2'. s1 = smap2 f s1' s2' \<and> s2 = smap (split f) (szip s1' s2')"])
       
   542     fastforce+
       
   543 
   500 
   544 
   501 
   545 subsection {* iterated application of a function *}
   502 subsection {* iterated application of a function *}
   546 
   503 
   547 definition siterate :: "('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a stream" where
   504 primcorec siterate where
   548   "siterate f x = x ## stream_unfold f f x"
   505   "shd (siterate f x) = x"
   549 
   506 | "stl (siterate f x) = siterate f (f x)"
   550 lemma siterate_simps[simp]: "shd (siterate f x) = x" "stl (siterate f x) = siterate f (f x)"
       
   551   unfolding siterate_def by (auto intro: stream.unfold)
       
   552 
       
   553 lemma siterate_code[code]: "siterate f x = x ## siterate f (f x)"
       
   554   by (metis siterate_def stream.unfold)
       
   555 
   507 
   556 lemma stake_Suc: "stake (Suc n) s = stake n s @ [s !! n]"
   508 lemma stake_Suc: "stake (Suc n) s = stake n s @ [s !! n]"
   557   by (induct n arbitrary: s) auto
   509   by (induct n arbitrary: s) auto
   558 
   510 
   559 lemma snth_siterate[simp]: "siterate f x !! n = (f^^n) x"
   511 lemma snth_siterate[simp]: "siterate f x !! n = (f^^n) x"