src/HOL/Imperative_HOL/ex/Linked_Lists.thy
changeset 37792 ba0bc31b90d7
parent 37771 1bec64044b5e
child 37826 4c0a5e35931a
equal deleted inserted replaced
37791:0d6b64060543 37792:ba0bc31b90d7
    29 instance node :: (heap) heap ..
    29 instance node :: (heap) heap ..
    30 
    30 
    31 primrec make_llist :: "'a\<Colon>heap list \<Rightarrow> 'a node Heap"
    31 primrec make_llist :: "'a\<Colon>heap list \<Rightarrow> 'a node Heap"
    32 where 
    32 where 
    33   [simp del]: "make_llist []     = return Empty"
    33   [simp del]: "make_llist []     = return Empty"
    34             | "make_llist (x#xs) = do tl   \<leftarrow> make_llist xs;
    34             | "make_llist (x#xs) = do { tl \<leftarrow> make_llist xs;
    35                                       next \<leftarrow> ref tl;
    35                                         next \<leftarrow> ref tl;
    36                                       return (Node x next)
    36                                         return (Node x next)
    37                                    done"
    37                                    }"
    38 
    38 
    39 
    39 
    40 text {* define traverse using the MREC combinator *}
    40 text {* define traverse using the MREC combinator *}
    41 
    41 
    42 definition
    42 definition
    43   traverse :: "'a\<Colon>heap node \<Rightarrow> 'a list Heap"
    43   traverse :: "'a\<Colon>heap node \<Rightarrow> 'a list Heap"
    44 where
    44 where
    45 [code del]: "traverse = MREC (\<lambda>n. case n of Empty \<Rightarrow> return (Inl [])
    45 [code del]: "traverse = MREC (\<lambda>n. case n of Empty \<Rightarrow> return (Inl [])
    46                                 | Node x r \<Rightarrow> (do tl \<leftarrow> Ref.lookup r;
    46                                 | Node x r \<Rightarrow> do { tl \<leftarrow> Ref.lookup r;
    47                                                   return (Inr tl) done))
    47                                                   return (Inr tl) })
    48                    (\<lambda>n tl xs. case n of Empty \<Rightarrow> undefined
    48                    (\<lambda>n tl xs. case n of Empty \<Rightarrow> undefined
    49                                       | Node x r \<Rightarrow> return (x # xs))"
    49                                       | Node x r \<Rightarrow> return (x # xs))"
    50 
    50 
    51 
    51 
    52 lemma traverse_simps[code, simp]:
    52 lemma traverse_simps[code, simp]:
    53   "traverse Empty      = return []"
    53   "traverse Empty      = return []"
    54   "traverse (Node x r) = do tl \<leftarrow> Ref.lookup r;
    54   "traverse (Node x r) = do { tl \<leftarrow> Ref.lookup r;
    55                             xs \<leftarrow> traverse tl;
    55                               xs \<leftarrow> traverse tl;
    56                             return (x#xs)
    56                               return (x#xs)
    57                          done"
    57                          }"
    58 unfolding traverse_def
    58 unfolding traverse_def
    59 by (auto simp: traverse_def MREC_rule)
    59 by (auto simp: traverse_def MREC_rule)
    60 
    60 
    61 
    61 
    62 section {* Proving correctness with relational abstraction *}
    62 section {* Proving correctness with relational abstraction *}
   527 section {* Proving correctness of in-place reversal *}
   527 section {* Proving correctness of in-place reversal *}
   528 
   528 
   529 subsection {* Definition of in-place reversal *}
   529 subsection {* Definition of in-place reversal *}
   530 
   530 
   531 definition rev' :: "(('a::heap) node ref \<times> 'a node ref) \<Rightarrow> 'a node ref Heap"
   531 definition rev' :: "(('a::heap) node ref \<times> 'a node ref) \<Rightarrow> 'a node ref Heap"
   532 where "rev' = MREC (\<lambda>(q, p). do v \<leftarrow> !p; (case v of Empty \<Rightarrow> (return (Inl q))
   532 where "rev' = MREC (\<lambda>(q, p). do { v \<leftarrow> !p; (case v of Empty \<Rightarrow> (return (Inl q))
   533                             | Node x next \<Rightarrow> do
   533                             | Node x next \<Rightarrow> do {
   534                                     p := Node x q;
   534                                     p := Node x q;
   535                                     return (Inr (p, next))
   535                                     return (Inr (p, next))
   536                                   done) done)
   536                                   })})
   537              (\<lambda>x s z. return z)"
   537              (\<lambda>x s z. return z)"
   538 
   538 
   539 lemma rev'_simps [code]:
   539 lemma rev'_simps [code]:
   540   "rev' (q, p) =
   540   "rev' (q, p) =
   541    do
   541    do {
   542      v \<leftarrow> !p;
   542      v \<leftarrow> !p;
   543      (case v of
   543      (case v of
   544         Empty \<Rightarrow> return q
   544         Empty \<Rightarrow> return q
   545       | Node x next \<Rightarrow>
   545       | Node x next \<Rightarrow>
   546         do
   546         do {
   547           p := Node x q;
   547           p := Node x q;
   548           rev' (p, next)
   548           rev' (p, next)
   549         done)
   549         })
   550   done"
   550   }"
   551   unfolding rev'_def MREC_rule[of _ _ "(q, p)"] unfolding rev'_def[symmetric]
   551   unfolding rev'_def MREC_rule[of _ _ "(q, p)"] unfolding rev'_def[symmetric]
   552 thm arg_cong2
   552 thm arg_cong2
   553   by (auto simp add: expand_fun_eq intro: arg_cong2[where f = "op \<guillemotright>="] split: node.split)
   553   by (auto simp add: expand_fun_eq intro: arg_cong2[where f = "op \<guillemotright>="] split: node.split)
   554 
   554 
   555 primrec rev :: "('a:: heap) node \<Rightarrow> 'a node Heap" 
   555 primrec rev :: "('a:: heap) node \<Rightarrow> 'a node Heap" 
   556 where
   556 where
   557   "rev Empty = return Empty"
   557   "rev Empty = return Empty"
   558 | "rev (Node x n) = (do q \<leftarrow> ref Empty; p \<leftarrow> ref (Node x n); v \<leftarrow> rev' (q, p); !v done)"
   558 | "rev (Node x n) = do { q \<leftarrow> ref Empty; p \<leftarrow> ref (Node x n); v \<leftarrow> rev' (q, p); !v }"
   559 
   559 
   560 subsection {* Correctness Proof *}
   560 subsection {* Correctness Proof *}
   561 
   561 
   562 lemma rev'_invariant:
   562 lemma rev'_invariant:
   563   assumes "crel (rev' (q, p)) h h' v"
   563   assumes "crel (rev' (q, p)) h h' v"
   678 
   678 
   679 subsection {* Definition of merge function *}
   679 subsection {* Definition of merge function *}
   680 
   680 
   681 definition merge' :: "(('a::{heap, ord}) node ref * ('a::{heap, ord})) * ('a::{heap, ord}) node ref * ('a::{heap, ord}) node ref \<Rightarrow> ('a::{heap, ord}) node ref Heap"
   681 definition merge' :: "(('a::{heap, ord}) node ref * ('a::{heap, ord})) * ('a::{heap, ord}) node ref * ('a::{heap, ord}) node ref \<Rightarrow> ('a::{heap, ord}) node ref Heap"
   682 where
   682 where
   683 "merge' = MREC (\<lambda>(_, p, q). (do v \<leftarrow> !p; w \<leftarrow> !q;
   683 "merge' = MREC (\<lambda>(_, p, q). do { v \<leftarrow> !p; w \<leftarrow> !q;
   684   (case v of Empty \<Rightarrow> return (Inl q)
   684   (case v of Empty \<Rightarrow> return (Inl q)
   685           | Node valp np \<Rightarrow>
   685           | Node valp np \<Rightarrow>
   686             (case w of Empty \<Rightarrow> return (Inl p)
   686             (case w of Empty \<Rightarrow> return (Inl p)
   687                      | Node valq nq \<Rightarrow>
   687                      | Node valq nq \<Rightarrow>
   688                        if (valp \<le> valq) then
   688                        if (valp \<le> valq) then
   689                          return (Inr ((p, valp), np, q))
   689                          return (Inr ((p, valp), np, q))
   690                        else
   690                        else
   691                          return (Inr ((q, valq), p, nq)))) done))
   691                          return (Inr ((q, valq), p, nq)))) })
   692  (\<lambda> _ ((n, v), _, _) r. do n := Node v r; return n done)"
   692  (\<lambda> _ ((n, v), _, _) r. do { n := Node v r; return n })"
   693 
   693 
   694 definition merge where "merge p q = merge' (undefined, p, q)"
   694 definition merge where "merge p q = merge' (undefined, p, q)"
   695 
   695 
   696 lemma if_return: "(if P then return x else return y) = return (if P then x else y)"
   696 lemma if_return: "(if P then return x else return y) = return (if P then x else y)"
   697 by auto
   697 by auto
   711 unfolding merge'_def merge_def
   711 unfolding merge'_def merge_def
   712 apply (simp add: MREC_rule) done
   712 apply (simp add: MREC_rule) done
   713 term "Ref.change"
   713 term "Ref.change"
   714 lemma merge_simps [code]:
   714 lemma merge_simps [code]:
   715 shows "merge p q =
   715 shows "merge p q =
   716 do v \<leftarrow> !p;
   716 do { v \<leftarrow> !p;
   717    w \<leftarrow> !q;
   717    w \<leftarrow> !q;
   718    (case v of node.Empty \<Rightarrow> return q
   718    (case v of node.Empty \<Rightarrow> return q
   719     | Node valp np \<Rightarrow>
   719     | Node valp np \<Rightarrow>
   720         case w of node.Empty \<Rightarrow> return p
   720         case w of node.Empty \<Rightarrow> return p
   721         | Node valq nq \<Rightarrow>
   721         | Node valq nq \<Rightarrow>
   722             if valp \<le> valq then do r \<leftarrow> merge np q;
   722             if valp \<le> valq then do { r \<leftarrow> merge np q;
   723                                    p := (Node valp r);
   723                                    p := (Node valp r);
   724                                    return p
   724                                    return p
   725                                 done
   725                                 }
   726             else do r \<leftarrow> merge p nq;
   726             else do { r \<leftarrow> merge p nq;
   727                     q := (Node valq r);
   727                     q := (Node valq r);
   728                     return q
   728                     return q
   729                  done)
   729                  })
   730 done"
   730 }"
   731 proof -
   731 proof -
   732   {fix v x y
   732   {fix v x y
   733     have case_return: "(case v of Empty \<Rightarrow> return x | Node v n \<Rightarrow> return (y v n)) = return (case v of Empty \<Rightarrow> x | Node v n \<Rightarrow> y v n)" by (cases v) auto
   733     have case_return: "(case v of Empty \<Rightarrow> return x | Node v n \<Rightarrow> return (y v n)) = return (case v of Empty \<Rightarrow> x | Node v n \<Rightarrow> y v n)" by (cases v) auto
   734     } note case_return = this
   734     } note case_return = this
   735 show ?thesis
   735 show ?thesis
   995 
   995 
   996 export_code rev in SML file -
   996 export_code rev in SML file -
   997 
   997 
   998 text {* A simple example program *}
   998 text {* A simple example program *}
   999 
   999 
  1000 definition test_1 where "test_1 = (do ll_xs <- make_llist [1..(15::int)]; xs <- traverse ll_xs; return xs done)" 
  1000 definition test_1 where "test_1 = (do { ll_xs <- make_llist [1..(15::int)]; xs <- traverse ll_xs; return xs })" 
  1001 definition test_2 where "test_2 = (do ll_xs <- make_llist [1..(15::int)]; ll_ys <- rev ll_xs; ys <- traverse ll_ys; return ys done)"
  1001 definition test_2 where "test_2 = (do { ll_xs <- make_llist [1..(15::int)]; ll_ys <- rev ll_xs; ys <- traverse ll_ys; return ys })"
  1002 
  1002 
  1003 definition test_3 where "test_3 =
  1003 definition test_3 where "test_3 =
  1004   (do
  1004   (do {
  1005     ll_xs \<leftarrow> make_llist (filter (%n. n mod 2 = 0) [2..8]);
  1005     ll_xs \<leftarrow> make_llist (filter (%n. n mod 2 = 0) [2..8]);
  1006     ll_ys \<leftarrow> make_llist (filter (%n. n mod 2 = 1) [5..11]);
  1006     ll_ys \<leftarrow> make_llist (filter (%n. n mod 2 = 1) [5..11]);
  1007     r \<leftarrow> ref ll_xs;
  1007     r \<leftarrow> ref ll_xs;
  1008     q \<leftarrow> ref ll_ys;
  1008     q \<leftarrow> ref ll_ys;
  1009     p \<leftarrow> merge r q;
  1009     p \<leftarrow> merge r q;
  1010     ll_zs \<leftarrow> !p;
  1010     ll_zs \<leftarrow> !p;
  1011     zs \<leftarrow> traverse ll_zs;
  1011     zs \<leftarrow> traverse ll_zs;
  1012     return zs
  1012     return zs
  1013   done)"
  1013   })"
  1014 
  1014 
  1015 code_reserved SML upto
  1015 code_reserved SML upto
  1016 
  1016 
  1017 ML {* @{code test_1} () *}
  1017 ML {* @{code test_1} () *}
  1018 ML {* @{code test_2} () *}
  1018 ML {* @{code test_2} () *}