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} () *} |