src/HOL/Imperative_HOL/ex/Linked_Lists.thy
changeset 63167 0909deb8059b
parent 63092 a949b2a5f51d
child 66453 cc19f7ca2ed6
equal deleted inserted replaced
63166:143f58bb34f9 63167:0909deb8059b
     1 (*  Title:      HOL/Imperative_HOL/ex/Linked_Lists.thy
     1 (*  Title:      HOL/Imperative_HOL/ex/Linked_Lists.thy
     2     Author:     Lukas Bulwahn, TU Muenchen
     2     Author:     Lukas Bulwahn, TU Muenchen
     3 *)
     3 *)
     4 
     4 
     5 section {* Linked Lists by ML references *}
     5 section \<open>Linked Lists by ML references\<close>
     6 
     6 
     7 theory Linked_Lists
     7 theory Linked_Lists
     8 imports "../Imperative_HOL" "~~/src/HOL/Library/Code_Target_Int"
     8 imports "../Imperative_HOL" "~~/src/HOL/Library/Code_Target_Int"
     9 begin
     9 begin
    10 
    10 
    11 section {* Definition of Linked Lists *}
    11 section \<open>Definition of Linked Lists\<close>
    12 
    12 
    13 setup {* Sign.add_const_constraint (@{const_name Ref}, SOME @{typ "nat \<Rightarrow> 'a::type ref"}) *}
    13 setup \<open>Sign.add_const_constraint (@{const_name Ref}, SOME @{typ "nat \<Rightarrow> 'a::type ref"})\<close>
    14 datatype 'a node = Empty | Node 'a "'a node ref"
    14 datatype 'a node = Empty | Node 'a "'a node ref"
    15 
    15 
    16 primrec
    16 primrec
    17   node_encode :: "'a::countable node \<Rightarrow> nat"
    17   node_encode :: "'a::countable node \<Rightarrow> nat"
    18 where
    18 where
    53                               return (x#xs)
    53                               return (x#xs)
    54                          }"
    54                          }"
    55 by (simp_all add: traverse.simps[of "Empty"] traverse.simps[of "Node x r"])
    55 by (simp_all add: traverse.simps[of "Empty"] traverse.simps[of "Node x r"])
    56 
    56 
    57 
    57 
    58 section {* Proving correctness with relational abstraction *}
    58 section \<open>Proving correctness with relational abstraction\<close>
    59 
    59 
    60 subsection {* Definition of list_of, list_of', refs_of and refs_of' *}
    60 subsection \<open>Definition of list_of, list_of', refs_of and refs_of'\<close>
    61 
    61 
    62 primrec list_of :: "heap \<Rightarrow> ('a::heap) node \<Rightarrow> 'a list \<Rightarrow> bool"
    62 primrec list_of :: "heap \<Rightarrow> ('a::heap) node \<Rightarrow> 'a list \<Rightarrow> bool"
    63 where
    63 where
    64   "list_of h r [] = (r = Empty)"
    64   "list_of h r [] = (r = Empty)"
    65 | "list_of h r (a#as) = (case r of Empty \<Rightarrow> False | Node b bs \<Rightarrow> (a = b \<and> list_of h (Ref.get h bs) as))"
    65 | "list_of h r (a#as) = (case r of Empty \<Rightarrow> False | Node b bs \<Rightarrow> (a = b \<and> list_of h (Ref.get h bs) as))"
    77 where
    77 where
    78   "refs_of' h r [] = False"
    78   "refs_of' h r [] = False"
    79 | "refs_of' h r (x#xs) = ((x = r) \<and> refs_of h (Ref.get h x) xs)"
    79 | "refs_of' h r (x#xs) = ((x = r) \<and> refs_of h (Ref.get h x) xs)"
    80 
    80 
    81 
    81 
    82 subsection {* Properties of these definitions *}
    82 subsection \<open>Properties of these definitions\<close>
    83 
    83 
    84 lemma list_of_Empty[simp]: "list_of h Empty xs = (xs = [])"
    84 lemma list_of_Empty[simp]: "list_of h Empty xs = (xs = [])"
    85 by (cases xs, auto)
    85 by (cases xs, auto)
    86 
    86 
    87 lemma list_of_Node[simp]: "list_of h (Node x ps) xs = (\<exists>xs'. (xs = x # xs') \<and> list_of h (Ref.get h ps) xs')"
    87 lemma list_of_Node[simp]: "list_of h (Node x ps) xs = (\<exists>xs'. (xs = x # xs') \<and> list_of h (Ref.get h ps) xs')"
   214 proof -
   214 proof -
   215   from assms obtain rs where "refs_of' h r rs" by (rule list_of'_refs_of')
   215   from assms obtain rs where "refs_of' h r rs" by (rule list_of'_refs_of')
   216   thus ?thesis by (auto simp add: refs_of'_def')
   216   thus ?thesis by (auto simp add: refs_of'_def')
   217 qed
   217 qed
   218 
   218 
   219 subsection {* More complicated properties of these predicates *}
   219 subsection \<open>More complicated properties of these predicates\<close>
   220 
   220 
   221 lemma list_of_append:
   221 lemma list_of_append:
   222   "list_of h n (as @ bs) \<Longrightarrow> \<exists>m. list_of h m bs"
   222   "list_of h n (as @ bs) \<Longrightarrow> \<exists>m. list_of h m bs"
   223 apply (induct as arbitrary: n)
   223 apply (induct as arbitrary: n)
   224 apply auto
   224 apply auto
   256 lemma refs_of'_distinct: "refs_of' h p rs \<Longrightarrow> distinct rs"
   256 lemma refs_of'_distinct: "refs_of' h p rs \<Longrightarrow> distinct rs"
   257   unfolding refs_of'_def'
   257   unfolding refs_of'_def'
   258   by (fastforce simp add: refs_of_distinct refs_of_next)
   258   by (fastforce simp add: refs_of_distinct refs_of_next)
   259 
   259 
   260 
   260 
   261 subsection {* Interaction of these predicates with our heap transitions *}
   261 subsection \<open>Interaction of these predicates with our heap transitions\<close>
   262 
   262 
   263 lemma list_of_set_ref: "refs_of h q rs \<Longrightarrow> p \<notin> set rs \<Longrightarrow> list_of (Ref.set p v h) q as = list_of h q as"
   263 lemma list_of_set_ref: "refs_of h q rs \<Longrightarrow> p \<notin> set rs \<Longrightarrow> list_of (Ref.set p v h) q as = list_of h q as"
   264 proof (induct as arbitrary: q rs)
   264 proof (induct as arbitrary: q rs)
   265   case Nil thus ?case by simp
   265   case Nil thus ?case by simp
   266 next
   266 next
   376     unfolding refs_of'_def'[of _ p]
   376     unfolding refs_of'_def'[of _ p]
   377     apply (auto, frule refs_of_set_ref2) by (auto dest: Ref.noteq_sym)
   377     apply (auto, frule refs_of_set_ref2) by (auto dest: Ref.noteq_sym)
   378   with assms that show thesis by auto
   378   with assms that show thesis by auto
   379 qed
   379 qed
   380 
   380 
   381 section {* Proving make_llist and traverse correct *}
   381 section \<open>Proving make_llist and traverse correct\<close>
   382 
   382 
   383 lemma refs_of_invariant:
   383 lemma refs_of_invariant:
   384   assumes "refs_of h (r::('a::heap) node) xs"
   384   assumes "refs_of h (r::('a::heap) node) xs"
   385   assumes "\<forall>refs. refs_of h r refs \<longrightarrow> (\<forall>ref \<in> set refs. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref)"
   385   assumes "\<forall>refs. refs_of h r refs \<longrightarrow> (\<forall>ref \<in> set refs. Ref.present h ref \<and> Ref.present h' ref \<and> Ref.get h ref = Ref.get h' ref)"
   386   shows "refs_of h' r xs"
   386   shows "refs_of h' r xs"
   516   from make_llist[OF makell] have "list_of h1 r1 xs" ..
   516   from make_llist[OF makell] have "list_of h1 r1 xs" ..
   517   from traverse [OF this] trav show ?thesis
   517   from traverse [OF this] trav show ?thesis
   518     using effect_deterministic by fastforce
   518     using effect_deterministic by fastforce
   519 qed
   519 qed
   520 
   520 
   521 section {* Proving correctness of in-place reversal *}
   521 section \<open>Proving correctness of in-place reversal\<close>
   522 
   522 
   523 subsection {* Definition of in-place reversal *}
   523 subsection \<open>Definition of in-place reversal\<close>
   524 
   524 
   525 partial_function (heap) rev' :: "('a::heap) node ref \<Rightarrow> 'a node ref \<Rightarrow> 'a node ref Heap"
   525 partial_function (heap) rev' :: "('a::heap) node ref \<Rightarrow> 'a node ref \<Rightarrow> 'a node ref Heap"
   526 where
   526 where
   527   [code]: "rev' q p =
   527   [code]: "rev' q p =
   528    do {
   528    do {
   539 primrec rev :: "('a:: heap) node \<Rightarrow> 'a node Heap" 
   539 primrec rev :: "('a:: heap) node \<Rightarrow> 'a node Heap" 
   540 where
   540 where
   541   "rev Empty = return Empty"
   541   "rev Empty = return Empty"
   542 | "rev (Node x n) = do { q \<leftarrow> ref Empty; p \<leftarrow> ref (Node x n); v \<leftarrow> rev' q p; !v }"
   542 | "rev (Node x n) = do { q \<leftarrow> ref Empty; p \<leftarrow> ref (Node x n); v \<leftarrow> rev' q p; !v }"
   543 
   543 
   544 subsection {* Correctness Proof *}
   544 subsection \<open>Correctness Proof\<close>
   545 
   545 
   546 lemma rev'_invariant:
   546 lemma rev'_invariant:
   547   assumes "effect (rev' q p) h h' v"
   547   assumes "effect (rev' q p) h h' v"
   548   assumes "list_of' h q qs"
   548   assumes "list_of' h q qs"
   549   assumes "list_of' h p ps"
   549   assumes "list_of' h p ps"
   647   with lookup show ?thesis
   647   with lookup show ?thesis
   648     by (auto elim: effect_lookupE)
   648     by (auto elim: effect_lookupE)
   649 qed
   649 qed
   650 
   650 
   651 
   651 
   652 section {* The merge function on Linked Lists *}
   652 section \<open>The merge function on Linked Lists\<close>
   653 text {* We also prove merge correct *}
   653 text \<open>We also prove merge correct\<close>
   654 
   654 
   655 text{* First, we define merge on lists in a natural way. *}
   655 text\<open>First, we define merge on lists in a natural way.\<close>
   656 
   656 
   657 fun Lmerge :: "('a::ord) list \<Rightarrow> 'a list \<Rightarrow> 'a list"
   657 fun Lmerge :: "('a::ord) list \<Rightarrow> 'a list \<Rightarrow> 'a list"
   658 where
   658 where
   659   "Lmerge (x#xs) (y#ys) =
   659   "Lmerge (x#xs) (y#ys) =
   660      (if x \<le> y then x # Lmerge xs (y#ys) else y # Lmerge (x#xs) ys)"
   660      (if x \<le> y then x # Lmerge xs (y#ys) else y # Lmerge (x#xs) ys)"
   661 | "Lmerge [] ys = ys"
   661 | "Lmerge [] ys = ys"
   662 | "Lmerge xs [] = xs"
   662 | "Lmerge xs [] = xs"
   663 
   663 
   664 subsection {* Definition of merge function *}
   664 subsection \<open>Definition of merge function\<close>
   665 
   665 
   666 partial_function (heap) merge :: "('a::{heap, ord}) node ref \<Rightarrow> 'a node ref \<Rightarrow> 'a node ref Heap"
   666 partial_function (heap) merge :: "('a::{heap, ord}) node ref \<Rightarrow> 'a node ref \<Rightarrow> 'a node ref Heap"
   667 where
   667 where
   668 [code]: "merge p q = (do { v \<leftarrow> !p; w \<leftarrow> !q;
   668 [code]: "merge p q = (do { v \<leftarrow> !p; w \<leftarrow> !q;
   669   (case v of Empty \<Rightarrow> return q
   669   (case v of Empty \<Rightarrow> return q
   692 
   692 
   693 
   693 
   694 lemma sum_distrib: "case_sum fl fr (case x of Empty \<Rightarrow> y | Node v n \<Rightarrow> (z v n)) = (case x of Empty \<Rightarrow> case_sum fl fr y | Node v n \<Rightarrow> case_sum fl fr (z v n))"
   694 lemma sum_distrib: "case_sum fl fr (case x of Empty \<Rightarrow> y | Node v n \<Rightarrow> (z v n)) = (case x of Empty \<Rightarrow> case_sum fl fr y | Node v n \<Rightarrow> case_sum fl fr (z v n))"
   695 by (cases x) auto
   695 by (cases x) auto
   696 
   696 
   697 subsection {* Induction refinement by applying the abstraction function to our induct rule *}
   697 subsection \<open>Induction refinement by applying the abstraction function to our induct rule\<close>
   698 
   698 
   699 text {* From our original induction rule Lmerge.induct, we derive a new rule with our list_of' predicate *}
   699 text \<open>From our original induction rule Lmerge.induct, we derive a new rule with our list_of' predicate\<close>
   700 
   700 
   701 lemma merge_induct2:
   701 lemma merge_induct2:
   702   assumes "list_of' h (p::'a::{heap, ord} node ref) xs"
   702   assumes "list_of' h (p::'a::{heap, ord} node ref) xs"
   703   assumes "list_of' h q ys"
   703   assumes "list_of' h q ys"
   704   assumes "\<And> ys p q. \<lbrakk> list_of' h p []; list_of' h q ys; Ref.get h p = Empty \<rbrakk> \<Longrightarrow> P p q [] ys"
   704   assumes "\<And> ys p q. \<lbrakk> list_of' h p []; list_of' h q ys; Ref.get h p = Empty \<rbrakk> \<Longrightarrow> P p q [] ys"
   739     show ?thesis by blast
   739     show ?thesis by blast
   740   qed
   740   qed
   741 qed
   741 qed
   742 
   742 
   743 
   743 
   744 text {* secondly, we add the effect statement in the premise, and derive the effect statements for the single cases which we then eliminate with our effect elim rules. *}
   744 text \<open>secondly, we add the effect statement in the premise, and derive the effect statements for the single cases which we then eliminate with our effect elim rules.\<close>
   745   
   745   
   746 lemma merge_induct3: 
   746 lemma merge_induct3: 
   747 assumes  "list_of' h p xs"
   747 assumes  "list_of' h p xs"
   748 assumes  "list_of' h q ys"
   748 assumes  "list_of' h q ys"
   749 assumes  "effect (merge p q) h h' r"
   749 assumes  "effect (merge p q) h h' r"
   788     by (auto elim!: effect_lookupE effect_bindE effect_returnE effect_ifE effect_updateE)
   788     by (auto elim!: effect_lookupE effect_bindE effect_returnE effect_ifE effect_updateE)
   789   from 4(6)[OF 1] assms(7) [OF 4(1-5)] 1 2 show ?case by simp
   789   from 4(6)[OF 1] assms(7) [OF 4(1-5)] 1 2 show ?case by simp
   790 qed
   790 qed
   791 
   791 
   792 
   792 
   793 subsection {* Proving merge correct *}
   793 subsection \<open>Proving merge correct\<close>
   794 
   794 
   795 text {* As many parts of the following three proofs are identical, we could actually move the
   795 text \<open>As many parts of the following three proofs are identical, we could actually move the
   796 same reasoning into an extended induction rule *}
   796 same reasoning into an extended induction rule\<close>
   797  
   797  
   798 lemma merge_unchanged:
   798 lemma merge_unchanged:
   799   assumes "refs_of' h p xs"
   799   assumes "refs_of' h p xs"
   800   assumes "refs_of' h q ys"  
   800   assumes "refs_of' h q ys"  
   801   assumes "effect (merge p q) h h' r'"
   801   assumes "effect (merge p q) h h' r'"
   820     from pnrs_def 3(12) have "r \<noteq> p" by auto
   820     from pnrs_def 3(12) have "r \<noteq> p" by auto
   821     with 3(11) 3(12) pnrs_def refs_of'_distinct[OF 3(9)] have p_in: "p \<notin> set pnrs \<union> set ys" by auto
   821     with 3(11) 3(12) pnrs_def refs_of'_distinct[OF 3(9)] have p_in: "p \<notin> set pnrs \<union> set ys" by auto
   822     from 3(11) pnrs_def have no_inter: "set pnrs \<inter> set ys = {}" by auto
   822     from 3(11) pnrs_def have no_inter: "set pnrs \<inter> set ys = {}" by auto
   823     from 3(7)[OF refs_of'_pn 3(10) this p_in] 3(3) have p_is_Node: "Ref.get h1 p = Node x pn"
   823     from 3(7)[OF refs_of'_pn 3(10) this p_in] 3(3) have p_is_Node: "Ref.get h1 p = Node x pn"
   824       by simp
   824       by simp
   825     from 3(7)[OF refs_of'_pn 3(10) no_inter r_in] 3(8) `r \<noteq> p` show ?case
   825     from 3(7)[OF refs_of'_pn 3(10) no_inter r_in] 3(8) \<open>r \<noteq> p\<close> show ?case
   826       by simp
   826       by simp
   827   next
   827   next
   828     case (4 x xs' y ys' p q pn qn h1 r1 h' xs ys r)
   828     case (4 x xs' y ys' p q pn qn h1 r1 h' xs ys r)
   829     from 4(10) 4(4) obtain qnrs
   829     from 4(10) 4(4) obtain qnrs
   830       where qnrs_def: "ys = q#qnrs"
   830       where qnrs_def: "ys = q#qnrs"
   833     with 4(12) have r_in: "r \<notin> set xs \<union> set qnrs" by auto
   833     with 4(12) have r_in: "r \<notin> set xs \<union> set qnrs" by auto
   834     from qnrs_def 4(12) have "r \<noteq> q" by auto
   834     from qnrs_def 4(12) have "r \<noteq> q" by auto
   835     with 4(11) 4(12) qnrs_def refs_of'_distinct[OF 4(10)] have q_in: "q \<notin> set xs \<union> set qnrs" by auto
   835     with 4(11) 4(12) qnrs_def refs_of'_distinct[OF 4(10)] have q_in: "q \<notin> set xs \<union> set qnrs" by auto
   836     from 4(11) qnrs_def have no_inter: "set xs \<inter> set qnrs = {}" by auto
   836     from 4(11) qnrs_def have no_inter: "set xs \<inter> set qnrs = {}" by auto
   837     from 4(7)[OF 4(9) refs_of'_qn this q_in] 4(4) have q_is_Node: "Ref.get h1 q = Node y qn" by simp
   837     from 4(7)[OF 4(9) refs_of'_qn this q_in] 4(4) have q_is_Node: "Ref.get h1 q = Node y qn" by simp
   838     from 4(7)[OF 4(9) refs_of'_qn no_inter r_in] 4(8) `r \<noteq> q` show ?case
   838     from 4(7)[OF 4(9) refs_of'_qn no_inter r_in] 4(8) \<open>r \<noteq> q\<close> show ?case
   839       by simp
   839       by simp
   840   qed
   840   qed
   841 qed
   841 qed
   842 
   842 
   843 lemma refs_of'_merge:
   843 lemma refs_of'_merge:
   935   from refs_of'_merge[OF prs_def refs_of'_qn 4(6) no_inter this] q_in have q_rs: "q \<notin> set rs" by auto
   935   from refs_of'_merge[OF prs_def refs_of'_qn 4(6) no_inter this] q_in have q_rs: "q \<notin> set rs" by auto
   936   with 4(7)[OF no_inter2] 4(1-5) 4(8) q_rs rs_def q_stays
   936   with 4(7)[OF no_inter2] 4(1-5) 4(8) q_rs rs_def q_stays
   937   show ?case by (auto simp: list_of'_set_ref)
   937   show ?case by (auto simp: list_of'_set_ref)
   938 qed
   938 qed
   939 
   939 
   940 section {* Code generation *}
   940 section \<open>Code generation\<close>
   941 
   941 
   942 text {* A simple example program *}
   942 text \<open>A simple example program\<close>
   943 
   943 
   944 definition test_1 where "test_1 = (do { ll_xs \<leftarrow> make_llist [1..(15::int)]; xs \<leftarrow> traverse ll_xs; return xs })" 
   944 definition test_1 where "test_1 = (do { ll_xs \<leftarrow> make_llist [1..(15::int)]; xs \<leftarrow> traverse ll_xs; return xs })" 
   945 definition test_2 where "test_2 = (do { ll_xs \<leftarrow> make_llist [1..(15::int)]; ll_ys \<leftarrow> rev ll_xs; ys \<leftarrow> traverse ll_ys; return ys })"
   945 definition test_2 where "test_2 = (do { ll_xs \<leftarrow> make_llist [1..(15::int)]; ll_ys \<leftarrow> rev ll_xs; ys \<leftarrow> traverse ll_ys; return ys })"
   946 
   946 
   947 definition test_3 where "test_3 =
   947 definition test_3 where "test_3 =
   956     return zs
   956     return zs
   957   })"
   957   })"
   958 
   958 
   959 code_reserved SML upto
   959 code_reserved SML upto
   960 
   960 
   961 ML_val {* @{code test_1} () *}
   961 ML_val \<open>@{code test_1} ()\<close>
   962 ML_val {* @{code test_2} () *}
   962 ML_val \<open>@{code test_2} ()\<close>
   963 ML_val {* @{code test_3} () *}
   963 ML_val \<open>@{code test_3} ()\<close>
   964 
   964 
   965 export_code test_1 test_2 test_3 checking SML SML_imp OCaml? OCaml_imp? Haskell? Scala Scala_imp
   965 export_code test_1 test_2 test_3 checking SML SML_imp OCaml? OCaml_imp? Haskell? Scala Scala_imp
   966 
   966 
   967 end
   967 end