4 Copyright 1998 University of Cambridge |
4 Copyright 1998 University of Cambridge |
5 |
5 |
6 The Lift-Control Example |
6 The Lift-Control Example |
7 *) |
7 *) |
8 |
8 |
9 theory Lift = UNITY_Main: |
9 theory Lift |
|
10 imports "../UNITY_Main" |
|
11 |
|
12 begin |
10 |
13 |
11 record state = |
14 record state = |
12 floor :: "int" (*current position of the lift*) |
15 floor :: "int" --{*current position of the lift*} |
13 "open" :: "bool" (*whether the door is opened at floor*) |
16 "open" :: "bool" --{*whether the door is opened at floor*} |
14 stop :: "bool" (*whether the lift is stopped at floor*) |
17 stop :: "bool" --{*whether the lift is stopped at floor*} |
15 req :: "int set" (*for each floor, whether the lift is requested*) |
18 req :: "int set" --{*for each floor, whether the lift is requested*} |
16 up :: "bool" (*current direction of movement*) |
19 up :: "bool" --{*current direction of movement*} |
17 move :: "bool" (*whether moving takes precedence over opening*) |
20 move :: "bool" --{*whether moving takes precedence over opening*} |
18 |
21 |
19 consts |
22 consts |
20 Min :: "int" (*least and greatest floors*) |
23 Min :: "int" --{*least and greatest floors*} |
21 Max :: "int" (*least and greatest floors*) |
24 Max :: "int" --{*least and greatest floors*} |
22 |
25 |
23 axioms |
26 axioms |
24 Min_le_Max [iff]: "Min \<le> Max" |
27 Min_le_Max [iff]: "Min \<le> Max" |
25 |
28 |
26 constdefs |
29 constdefs |
27 |
30 |
28 (** Abbreviations: the "always" part **) |
31 --{*Abbreviations: the "always" part*} |
29 |
32 |
30 above :: "state set" |
33 above :: "state set" |
31 "above == {s. \<exists>i. floor s < i & i \<le> Max & i \<in> req s}" |
34 "above == {s. \<exists>i. floor s < i & i \<le> Max & i \<in> req s}" |
32 |
35 |
33 below :: "state set" |
36 below :: "state set" |
43 "goingdown == below \<inter> ({s. ~ up s} \<union> -above)" |
46 "goingdown == below \<inter> ({s. ~ up s} \<union> -above)" |
44 |
47 |
45 ready :: "state set" |
48 ready :: "state set" |
46 "ready == {s. stop s & ~ open s & move s}" |
49 "ready == {s. stop s & ~ open s & move s}" |
47 |
50 |
48 (** Further abbreviations **) |
51 --{*Further abbreviations*} |
49 |
52 |
50 moving :: "state set" |
53 moving :: "state set" |
51 "moving == {s. ~ stop s & ~ open s}" |
54 "moving == {s. ~ stop s & ~ open s}" |
52 |
55 |
53 stopped :: "state set" |
56 stopped :: "state set" |
54 "stopped == {s. stop s & ~ open s & ~ move s}" |
57 "stopped == {s. stop s & ~ open s & ~ move s}" |
55 |
58 |
56 opened :: "state set" |
59 opened :: "state set" |
57 "opened == {s. stop s & open s & move s}" |
60 "opened == {s. stop s & open s & move s}" |
58 |
61 |
59 closed :: "state set" (*but this is the same as ready!!*) |
62 closed :: "state set" --{*but this is the same as ready!!*} |
60 "closed == {s. stop s & ~ open s & move s}" |
63 "closed == {s. stop s & ~ open s & move s}" |
61 |
64 |
62 atFloor :: "int => state set" |
65 atFloor :: "int => state set" |
63 "atFloor n == {s. floor s = n}" |
66 "atFloor n == {s. floor s = n}" |
64 |
67 |
65 Req :: "int => state set" |
68 Req :: "int => state set" |
66 "Req n == {s. n \<in> req s}" |
69 "Req n == {s. n \<in> req s}" |
67 |
70 |
68 |
71 |
69 |
72 |
70 (** The program **) |
73 --{*The program*} |
71 |
74 |
72 request_act :: "(state*state) set" |
75 request_act :: "(state*state) set" |
73 "request_act == {(s,s'). s' = s (|stop:=True, move:=False|) |
76 "request_act == {(s,s'). s' = s (|stop:=True, move:=False|) |
74 & ~ stop s & floor s \<in> req s}" |
77 & ~ stop s & floor s \<in> req s}" |
75 |
78 |
106 move_down :: "(state*state) set" |
109 move_down :: "(state*state) set" |
107 "move_down == |
110 "move_down == |
108 {(s,s'). s' = s (|floor := floor s - 1|) |
111 {(s,s'). s' = s (|floor := floor s - 1|) |
109 & ~ stop s & ~ up s & floor s \<notin> req s}" |
112 & ~ stop s & ~ up s & floor s \<notin> req s}" |
110 |
113 |
111 (*This action is omitted from prior treatments, which therefore are |
|
112 unrealistic: nobody asks the lift to do anything! But adding this |
|
113 action invalidates many of the existing progress arguments: various |
|
114 "ensures" properties fail.*) |
|
115 button_press :: "(state*state) set" |
114 button_press :: "(state*state) set" |
|
115 --{*This action is omitted from prior treatments, which therefore are |
|
116 unrealistic: nobody asks the lift to do anything! But adding this |
|
117 action invalidates many of the existing progress arguments: various |
|
118 "ensures" properties fail. Maybe it should be constrained to only |
|
119 allow button presses in the current direction of travel, like in a |
|
120 real lift.*} |
116 "button_press == |
121 "button_press == |
117 {(s,s'). \<exists>n. s' = s (|req := insert n (req s)|) |
122 {(s,s'). \<exists>n. s' = s (|req := insert n (req s)|) |
118 & Min \<le> n & n \<le> Max}" |
123 & Min \<le> n & n \<le> Max}" |
119 |
124 |
120 |
125 |
121 Lift :: "state program" |
126 Lift :: "state program" |
122 (*for the moment, we OMIT button_press*) |
127 --{*for the moment, we OMIT @{text button_press}*} |
123 "Lift == mk_total_program |
128 "Lift == mk_total_program |
124 ({s. floor s = Min & ~ up s & move s & stop s & |
129 ({s. floor s = Min & ~ up s & move s & stop s & |
125 ~ open s & req s = {}}, |
130 ~ open s & req s = {}}, |
126 {request_act, open_act, close_act, |
131 {request_act, open_act, close_act, |
127 req_up, req_down, move_up, move_down}, |
132 req_up, req_down, move_up, move_down}, |
128 UNIV)" |
133 UNIV)" |
129 |
134 |
130 |
135 |
131 (** Invariants **) |
136 --{*Invariants*} |
132 |
137 |
133 bounded :: "state set" |
138 bounded :: "state set" |
134 "bounded == {s. Min \<le> floor s & floor s \<le> Max}" |
139 "bounded == {s. Min \<le> floor s & floor s \<le> Max}" |
135 |
140 |
136 open_stop :: "state set" |
141 open_stop :: "state set" |
195 moving_up_def [simp] |
200 moving_up_def [simp] |
196 moving_down_def [simp] |
201 moving_down_def [simp] |
197 |
202 |
198 lemma open_stop: "Lift \<in> Always open_stop" |
203 lemma open_stop: "Lift \<in> Always open_stop" |
199 apply (rule AlwaysI, force) |
204 apply (rule AlwaysI, force) |
200 apply (unfold Lift_def, constrains) |
205 apply (unfold Lift_def, safety) |
201 done |
206 done |
202 |
207 |
203 lemma stop_floor: "Lift \<in> Always stop_floor" |
208 lemma stop_floor: "Lift \<in> Always stop_floor" |
204 apply (rule AlwaysI, force) |
209 apply (rule AlwaysI, force) |
205 apply (unfold Lift_def, constrains) |
210 apply (unfold Lift_def, safety) |
206 done |
211 done |
207 |
212 |
208 (*This one needs open_stop, which was proved above*) |
213 (*This one needs open_stop, which was proved above*) |
209 lemma open_move: "Lift \<in> Always open_move" |
214 lemma open_move: "Lift \<in> Always open_move" |
210 apply (cut_tac open_stop) |
215 apply (cut_tac open_stop) |
211 apply (rule AlwaysI, force) |
216 apply (rule AlwaysI, force) |
212 apply (unfold Lift_def, constrains) |
217 apply (unfold Lift_def, safety) |
213 done |
218 done |
214 |
219 |
215 lemma moving_up: "Lift \<in> Always moving_up" |
220 lemma moving_up: "Lift \<in> Always moving_up" |
216 apply (rule AlwaysI, force) |
221 apply (rule AlwaysI, force) |
217 apply (unfold Lift_def, constrains) |
222 apply (unfold Lift_def, safety) |
218 apply (auto dest: order_le_imp_less_or_eq simp add: add1_zle_eq) |
223 apply (auto dest: order_le_imp_less_or_eq simp add: add1_zle_eq) |
219 done |
224 done |
220 |
225 |
221 lemma moving_down: "Lift \<in> Always moving_down" |
226 lemma moving_down: "Lift \<in> Always moving_down" |
222 apply (rule AlwaysI, force) |
227 apply (rule AlwaysI, force) |
223 apply (unfold Lift_def, constrains) |
228 apply (unfold Lift_def, safety) |
224 apply (blast dest: order_le_imp_less_or_eq) |
229 apply (blast dest: order_le_imp_less_or_eq) |
225 done |
230 done |
226 |
231 |
227 lemma bounded: "Lift \<in> Always bounded" |
232 lemma bounded: "Lift \<in> Always bounded" |
228 apply (cut_tac moving_up moving_down) |
233 apply (cut_tac moving_up moving_down) |
229 apply (rule AlwaysI, force) |
234 apply (rule AlwaysI, force) |
230 apply (unfold Lift_def, constrains, auto) |
235 apply (unfold Lift_def, safety, auto) |
231 apply (drule not_mem_distinct, assumption, arith)+ |
236 apply (drule not_mem_distinct, assumption, arith)+ |
232 done |
237 done |
233 |
238 |
234 |
239 |
235 subsection{*Progress*} |
240 subsection{*Progress*} |
240 declare closed_def [THEN def_set_simp, simp] |
245 declare closed_def [THEN def_set_simp, simp] |
241 declare atFloor_def [THEN def_set_simp, simp] |
246 declare atFloor_def [THEN def_set_simp, simp] |
242 declare Req_def [THEN def_set_simp, simp] |
247 declare Req_def [THEN def_set_simp, simp] |
243 |
248 |
244 |
249 |
245 (** The HUG'93 paper mistakenly omits the Req n from these! **) |
250 text{*The HUG'93 paper mistakenly omits the Req n from these!*} |
246 |
251 |
247 (** Lift_1 **) |
252 (** Lift_1 **) |
248 lemma E_thm01: "Lift \<in> (stopped \<inter> atFloor n) LeadsTo (opened \<inter> atFloor n)" |
253 lemma E_thm01: "Lift \<in> (stopped \<inter> atFloor n) LeadsTo (opened \<inter> atFloor n)" |
249 apply (cut_tac stop_floor) |
254 apply (cut_tac stop_floor) |
250 apply (unfold Lift_def, ensures_tac "open_act") |
255 apply (unfold Lift_def, ensures_tac "open_act") |