(*>*) section‹ Example: data refinement (search)\label{sec:ex-data_refinement} ›
text‹
show a very simple example of data refinement: implementing sets with functional queues
breadth-first search (BFS). The objective here is to transfer a simple correctness property
on the abstract level to the concrete level.
:
▪ there is no concurrency in the BFS: this is just about data refinement
▪ however arbitrary interference is allowed
▪ the abstract level does not require the implementation of the pending set to make progress
▪ the concrete level does not require a representation invariant
▪ depth optimality is not shown
:
▪ queue ADT: 🍋‹$ISABELLE_HOME/src/Doc/Codegen/Introduction.thy›
▪ BFS verification:
▪ J. C. Filliâtre 🪙‹http://toccata.lri.fr/gallery/vstte12_bfs.en.html›
▪ 🍋‹$AFP/Refine_Monadic/examples/Breadth_First_Search.thy›
▪ our model is quite different
abbreviation absfn' :: "'a pending.concrete ==> 'a list"where ―‹ queue as a list › "absfn' s ≡ snd s @ rev (fst s)"
definition absfn :: "'a pending.concrete ==> 'a pending.abstract"where "absfn s = set (pending.absfn' s)"
setup‹Sign.mandatory_path "ag"›
lemma init: fixes Q :: "unit ==> 'a pending.abstract × 's ==> bool" fixes A :: "'s rel" assumes"stable (Id ×R A) (Q ())" shows"prog.p2s (pending.init pending.abstract) ≤{λs. Q () ({}, snd s)}, Id ×R A ⊨ UNIV ×R Id, {Q}" using assms by (auto intro: ag.prog.action simp: pending.abstract_def stable_def monotone_def)
lemma enq: fixes x :: 'a fixes Q :: "unit ==> 'a pending.abstract × 's ==> bool" fixes A :: "'s rel" assumes"stable (Id ×R A) (Q ())" shows"prog.p2s (pending.enq pending.abstract x) ≤{λs. Q () (insert x (fst s), snd s)}, Id ×R A ⊨ UNIV ×R Id, {Q}" using assms by (auto intro: ag.prog.action simp: pending.abstract_def stable_def monotone_def)
lemma deq: fixes Q :: "'a option ==> 'a pending.abstract × 's ==> bool" fixes A :: "'s rel" assumes"∧v. stable (Id ×R A) (Q v)" shows"prog.p2s (pending.deq pending.abstract) ≤{λs. if fst s = {} then Q None s else (∀x X. fst s = insert x X ⟶ Q (Some x) (X, snd s))}, Id ×R A ⊨ UNIV ×R Id, {Q}" unfolding pending.abstract_def pending.interface.simps by (rule ag.prog.action)
(use assms in‹auto simp: stable_def monotone_def le_bool_def split: if_split_asm›)
setup‹Sign.parent_path›
setup‹Sign.parent_path›
setup‹Sign.mandatory_path "set"›
record ('a, 's) interface =
init :: "('s, unit) prog"
ins :: "'a ==> ('s, unit) prog"
mem :: "'a ==> ('s, bool) prog"
type_synonym 'a abstract = "'a list" ―‹ model finite sets ›
definition abstract :: "('a, 's × 'a set.abstract × 't) set.interface"where "abstract = ( set.interface.init = prog.write (map_prod id (map_prod ⟨[]⟩ id)) , set.interface.ins = λx. prog.write (map_prod id (map_prod ((#) x) id)) , set.interface.mem = λx. prog.read (λs. x ∈ set (fst (snd s))) )"
setup‹Sign.mandatory_path "ag"›
lemma init: fixes Q :: "unit ==> 's × 'a set.abstract × 't ==> bool" fixes A :: "'s rel" assumes"stable (A ×R Id ×R B) (Q ())" shows"prog.p2s (set.init set.abstract) ≤{λs. Q () (fst s, [], snd (snd s))}, A ×R Id ×R B ⊨ Id ×R UNIV ×R Id, {Q}" using assms by (auto intro: ag.prog.action simp: set.abstract_def stable_def monotone_def)
lemma ins: fixes x :: 'a fixes Q :: "unit ==> 's × 'a set.abstract × 't ==> bool" fixes A :: "'s rel" assumes"stable (A ×R Id ×R B) (Q ())" shows"prog.p2s (set.ins set.abstract x) ≤{λs. Q () (fst s, x # fst (snd s), snd (snd s))}, A ×R Id ×R B ⊨ Id ×R UNIV ×R Id, {Q}" using assms by (auto intro: ag.prog.action simp: set.abstract_def stable_def monotone_def)
lemma mem: fixes Q :: "bool ==> 's × 'a set.abstract × 't ==> bool" assumes"∧v. stable (A ×R Id ×R B) (Q v)" shows"prog.p2s (set.mem set.abstract x) ≤{λs. Q (x ∈ set (fst (snd s))) s}, A ×R Id ×R B ⊨ Id ×R UNIV ×R Id, {Q}" using assms by (auto intro: ag.prog.action simp: set.abstract_def stable_def monotone_def)
setup‹Sign.parent_path›
setup‹Sign.parent_path›
context fixes pending :: "('a, 'p × 'a set.abstract × 's) pending.interface" fixes f :: "'a ==> 'a list" begin
definition loop :: "'a pred ==> ('p × 'a set.abstract × 's, 'a option) prog"where "loop p = prog.while (λ_. do { aopt ← pending.deq pending ; case aopt of None ==> prog.return (Inr None) | Some x ==> if p x then prog.return (Inr (Some x)) else do { prog.app (λy. do { b ← set.mem set.abstract y; prog.unlessM b (do { set.ins set.abstract y ; pending.enq pending y }) }) (f x) ; prog.return (Inl ()) } }) ()"
definition main :: "'a pred ==> 'a ==> ('p × 'a set.abstract × 's, 'a option) prog"where "main p x = do { set.init set.abstract ; pending.init pending ; set.ins set.abstract x ; pending.enq pending x ; loop p }"
definition search :: "'a pred ==> 'a ==> ('s, 'a option) prog"where "search p x = prog.local (prog.local (main p x))"
definition aloop_invP :: "'a pending.abstract ==> 'a set.abstract ==> bool"where "aloop_invP q v ⟷ q ⊆ set v ∧ set v ⊆ path `` {x0} ∧ set v ∩ Collect P ⊆ q ∧ x0∈ set v"
definition vclosureP :: "'a ==> 'a pending.abstract ==> 'a set.abstract ==> bool"where "vclosureP x q v ⟷ (x ∈ set v - q ⟶ step `` {x} ⊆ set v)"
definition search_postP :: "'a option ==> bool"where "search_postP rv = (case rv of None ==> finite (path `` {x0}) ∧ (path `` {x0} ∩ Collect P = {}) | Some y ==> (x0, y) ∈ path ∧ P y)"
abbreviation"aloop_inv s ≡ aloop_invP (fst s) (fst (snd s))" abbreviation"vclosure x s ≡ vclosureP x (fst s) (fst (snd s))" abbreviation"search_post rv ≡⟨search_postP rv⟩"
lemma vclosureP_closed: assumes"set v ⊆ path `` {x0}" assumes"∀y. vclosureP y {} v" assumes"x0∈ set v" shows"path `` {x0} = set v" proof - have"y ∈ set v"if"(x0, y) ∈ path"for y using that assms(2,3) by induct (auto simp: vclosureP_def) with assms(1) show ?thesis by fast qed
lemma vclosureP_app: assumes"∀y. x ≠ y ⟶ local.vclosureP y q v" assumes"set (f x) ⊆ set v" shows"vclosureP y q v" using assms by (fastforce simp: vclosureP_def)
lemma vclosureP_init: shows"vclosureP x {x0} [x0]" by (simp add: vclosureP_def)
lemma vclosureP_step: assumes"∀z. x ≠ z ⟶ vclosureP z q v" assumes"x ≠ z" shows"vclosureP z (insert y q) (y # v)" using assms by (fastforce simp: vclosureP_def)
lemma vclosureP_dequeue: assumes"∀z. vclosureP z (insert x q) v" assumes"x ≠ z" shows"vclosureP z q v" using assms by (fastforce simp: vclosureP_def)
lemma aloop_invPD: assumes"aloop_invP q v" assumes"x ∈ q" shows"(x0, x) ∈ path" using assms by (auto simp: aloop_invP_def)
lemma aloop_invP_init: shows"aloop_invP {x0} [x0]" by (simp add: aloop_invP_def)
lemma aloop_invP_step: assumes"aloop_invP q v" assumes"(x0, x) ∈ path" assumes"y ∈ set (f x) - set v" shows"aloop_invP (insert y q) (y # v)" using assms by (auto simp: aloop_invP_def elim: rtrancl_into_rtrancl)
lemma aloop_invP_dequeue: assumes"aloop_invP (insert x q) v" assumes"¬ P x" shows"aloop_invP q v" using assms by (auto simp: aloop_invP_def)
lemma search_postcond_None: assumes"aloop_invP {} v" assumes"∀y. vclosureP y {} v" shows"search_postP None" using assms by (auto simp: search_postP_def aloop_invP_def dest: vclosureP_closed)
lemma search_postcond_Some: assumes"aloop_invP q v" assumes"x ∈ q" assumes"P x" shows"search_postP (Some x)" using assms by (auto simp: search_postP_def aloop_invP_def)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.