29 {<s,t> \<in> state*state. |
29 {<s,t> \<in> state*state. |
30 \<exists>nrel \<in> nat. nrel = length(s`rel) & |
30 \<exists>nrel \<in> nat. nrel = length(s`rel) & |
31 t = s(rel:=(s`rel)@[nth(nrel, s`giv)]) & |
31 t = s(rel:=(s`rel)@[nth(nrel, s`giv)]) & |
32 nrel < length(s`giv) & |
32 nrel < length(s`giv) & |
33 nth(nrel, s`ask) \<le> nth(nrel, s`giv)}" |
33 nth(nrel, s`ask) \<le> nth(nrel, s`giv)}" |
34 |
34 |
35 (** Choose a new token requirement **) |
35 (** Choose a new token requirement **) |
36 (** Including t=s suppresses fairness, allowing the non-trivial part |
36 (** Including t=s suppresses fairness, allowing the non-trivial part |
37 of the action to be ignored **) |
37 of the action to be ignored **) |
38 definition |
38 definition |
39 "client_tok_act == {<s,t> \<in> state*state. t=s | |
39 "client_tok_act == {<s,t> \<in> state*state. t=s | |
40 t = s(tok:=succ(s`tok mod NbT))}" |
40 t = s(tok:=succ(s`tok mod NbT))}" |
41 |
41 |
42 definition |
42 definition |
43 "client_ask_act == {<s,t> \<in> state*state. t=s | (t=s(ask:=s`ask@[s`tok]))}" |
43 "client_ask_act == {<s,t> \<in> state*state. t=s | (t=s(ask:=s`ask@[s`tok]))}" |
44 |
44 |
45 definition |
45 definition |
46 "client_prog == |
46 "client_prog == |
47 mk_program({s \<in> state. s`tok \<le> NbT & s`giv = Nil & |
47 mk_program({s \<in> state. s`tok \<le> NbT & s`giv = Nil & |
48 s`ask = Nil & s`rel = Nil}, |
48 s`ask = Nil & s`rel = Nil}, |
49 {client_rel_act, client_tok_act, client_ask_act}, |
49 {client_rel_act, client_tok_act, client_ask_act}, |
89 declare client_rel_act_def [THEN def_act_simp, simp] |
89 declare client_rel_act_def [THEN def_act_simp, simp] |
90 declare client_tok_act_def [THEN def_act_simp, simp] |
90 declare client_tok_act_def [THEN def_act_simp, simp] |
91 declare client_ask_act_def [THEN def_act_simp, simp] |
91 declare client_ask_act_def [THEN def_act_simp, simp] |
92 |
92 |
93 lemma client_prog_ok_iff: |
93 lemma client_prog_ok_iff: |
94 "\<forall>G \<in> program. (client_prog ok G) \<longleftrightarrow> |
94 "\<forall>G \<in> program. (client_prog ok G) \<longleftrightarrow> |
95 (G \<in> preserves(lift(rel)) & G \<in> preserves(lift(ask)) & |
95 (G \<in> preserves(lift(rel)) & G \<in> preserves(lift(ask)) & |
96 G \<in> preserves(lift(tok)) & client_prog \<in> Allowed(G))" |
96 G \<in> preserves(lift(tok)) & client_prog \<in> Allowed(G))" |
97 by (auto simp add: ok_iff_Allowed client_prog_def [THEN def_prg_Allowed]) |
97 by (auto simp add: ok_iff_Allowed client_prog_def [THEN def_prg_Allowed]) |
98 |
98 |
99 lemma client_prog_preserves: |
99 lemma client_prog_preserves: |
100 "client_prog:(\<Inter>x \<in> var-{ask, rel, tok}. preserves(lift(x)))" |
100 "client_prog:(\<Inter>x \<in> var-{ask, rel, tok}. preserves(lift(x)))" |
105 |
105 |
106 |
106 |
107 lemma preserves_lift_imp_stable: |
107 lemma preserves_lift_imp_stable: |
108 "G \<in> preserves(lift(ff)) ==> G \<in> stable({s \<in> state. P(s`ff)})"; |
108 "G \<in> preserves(lift(ff)) ==> G \<in> stable({s \<in> state. P(s`ff)})"; |
109 apply (drule preserves_imp_stable) |
109 apply (drule preserves_imp_stable) |
110 apply (simp add: lift_def) |
110 apply (simp add: lift_def) |
111 done |
111 done |
112 |
112 |
113 lemma preserves_imp_prefix: |
113 lemma preserves_imp_prefix: |
114 "G \<in> preserves(lift(ff)) |
114 "G \<in> preserves(lift(ff)) |
115 ==> G \<in> stable({s \<in> state. \<langle>k, s`ff\<rangle> \<in> prefix(nat)})"; |
115 ==> G \<in> stable({s \<in> state. \<langle>k, s`ff\<rangle> \<in> prefix(nat)})"; |
116 by (erule preserves_lift_imp_stable) |
116 by (erule preserves_lift_imp_stable) |
117 |
117 |
118 (*Safety property 1: ask, rel are increasing: (24) *) |
118 (*Safety property 1 \<in> ask, rel are increasing: (24) *) |
119 lemma client_prog_Increasing_ask_rel: |
119 lemma client_prog_Increasing_ask_rel: |
120 "client_prog: program guarantees Incr(lift(ask)) \<inter> Incr(lift(rel))" |
120 "client_prog: program guarantees Incr(lift(ask)) \<inter> Incr(lift(rel))" |
121 apply (unfold guar_def) |
121 apply (unfold guar_def) |
122 apply (auto intro!: increasing_imp_Increasing |
122 apply (auto intro!: increasing_imp_Increasing |
123 simp add: client_prog_ok_iff Increasing.increasing_def preserves_imp_prefix) |
123 simp add: client_prog_ok_iff Increasing.increasing_def preserves_imp_prefix) |
124 apply (safety, force, force)+ |
124 apply (safety, force, force)+ |
125 done |
125 done |
126 |
126 |
127 declare nth_append [simp] append_one_prefix [simp] |
127 declare nth_append [simp] append_one_prefix [simp] |
129 lemma NbT_pos2: "0<NbT" |
129 lemma NbT_pos2: "0<NbT" |
130 apply (cut_tac NbT_pos) |
130 apply (cut_tac NbT_pos) |
131 apply (rule Ord_0_lt, auto) |
131 apply (rule Ord_0_lt, auto) |
132 done |
132 done |
133 |
133 |
134 (*Safety property 2: the client never requests too many tokens. |
134 (*Safety property 2 \<in> the client never requests too many tokens. |
135 With no Substitution Axiom, we must prove the two invariants simultaneously. *) |
135 With no Substitution Axiom, we must prove the two invariants simultaneously. *) |
136 |
136 |
137 lemma ask_Bounded_lemma: |
137 lemma ask_Bounded_lemma: |
138 "[| client_prog ok G; G \<in> program |] |
138 "[| client_prog ok G; G \<in> program |] |
139 ==> client_prog \<squnion> G \<in> |
139 ==> client_prog \<squnion> G \<in> |
140 Always({s \<in> state. s`tok \<le> NbT} \<inter> |
140 Always({s \<in> state. s`tok \<le> NbT} \<inter> |
141 {s \<in> state. \<forall>elt \<in> set_of_list(s`ask). elt \<le> NbT})" |
141 {s \<in> state. \<forall>elt \<in> set_of_list(s`ask). elt \<le> NbT})" |
142 apply (rotate_tac -1) |
142 apply (rotate_tac -1) |
143 apply (auto simp add: client_prog_ok_iff) |
143 apply (auto simp add: client_prog_ok_iff) |
144 apply (rule invariantI [THEN stable_Join_Always2], force) |
144 apply (rule invariantI [THEN stable_Join_Always2], force) |
145 prefer 2 |
145 prefer 2 |
146 apply (fast intro: stable_Int preserves_lift_imp_stable, safety) |
146 apply (fast intro: stable_Int preserves_lift_imp_stable, safety) |
147 apply (auto dest: ActsD) |
147 apply (auto dest: ActsD) |
148 apply (cut_tac NbT_pos) |
148 apply (cut_tac NbT_pos) |
149 apply (rule NbT_pos2 [THEN mod_less_divisor]) |
149 apply (rule NbT_pos2 [THEN mod_less_divisor]) |
150 apply (auto dest: ActsD preserves_imp_eq simp add: set_of_list_append) |
150 apply (auto dest: ActsD preserves_imp_eq simp add: set_of_list_append) |
151 done |
151 done |
152 |
152 |
153 (* Export version, with no mention of tok in the postcondition, but |
153 (* Export version, with no mention of tok in the postcondition, but |
154 unfortunately tok must be declared local.*) |
154 unfortunately tok must be declared local.*) |
155 lemma client_prog_ask_Bounded: |
155 lemma client_prog_ask_Bounded: |
156 "client_prog \<in> program guarantees |
156 "client_prog \<in> program guarantees |
157 Always({s \<in> state. \<forall>elt \<in> set_of_list(s`ask). elt \<le> NbT})" |
157 Always({s \<in> state. \<forall>elt \<in> set_of_list(s`ask). elt \<le> NbT})" |
158 apply (rule guaranteesI) |
158 apply (rule guaranteesI) |
159 apply (erule ask_Bounded_lemma [THEN Always_weaken], auto) |
159 apply (erule ask_Bounded_lemma [THEN Always_weaken], auto) |
160 done |
160 done |
161 |
161 |
162 (*** Towards proving the liveness property ***) |
162 (*** Towards proving the liveness property ***) |
163 |
163 |
164 lemma client_prog_stable_rel_le_giv: |
164 lemma client_prog_stable_rel_le_giv: |
165 "client_prog \<in> stable({s \<in> state. <s`rel, s`giv> \<in> prefix(nat)})" |
165 "client_prog \<in> stable({s \<in> state. <s`rel, s`giv> \<in> prefix(nat)})" |
166 by (safety, auto) |
166 by (safety, auto) |
167 |
167 |
168 lemma client_prog_Join_Stable_rel_le_giv: |
168 lemma client_prog_Join_Stable_rel_le_giv: |
169 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); G \<in> preserves(lift(rel)) |] |
169 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); G \<in> preserves(lift(rel)) |] |
170 ==> client_prog \<squnion> G \<in> Stable({s \<in> state. <s`rel, s`giv> \<in> prefix(nat)})" |
170 ==> client_prog \<squnion> G \<in> Stable({s \<in> state. <s`rel, s`giv> \<in> prefix(nat)})" |
171 apply (rule client_prog_stable_rel_le_giv [THEN Increasing_preserves_Stable]) |
171 apply (rule client_prog_stable_rel_le_giv [THEN Increasing_preserves_Stable]) |
172 apply (auto simp add: lift_def) |
172 apply (auto simp add: lift_def) |
173 done |
173 done |
174 |
174 |
175 lemma client_prog_Join_Always_rel_le_giv: |
175 lemma client_prog_Join_Always_rel_le_giv: |
176 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); G \<in> preserves(lift(rel)) |] |
176 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); G \<in> preserves(lift(rel)) |] |
177 ==> client_prog \<squnion> G \<in> Always({s \<in> state. <s`rel, s`giv> \<in> prefix(nat)})" |
177 ==> client_prog \<squnion> G \<in> Always({s \<in> state. <s`rel, s`giv> \<in> prefix(nat)})" |
178 by (force intro!: AlwaysI client_prog_Join_Stable_rel_le_giv) |
178 by (force intro!: AlwaysI client_prog_Join_Stable_rel_le_giv) |
179 |
179 |
180 lemma def_act_eq: |
180 lemma def_act_eq: |
181 "A == {<s, t> \<in> state*state. P(s, t)} ==> A={<s, t> \<in> state*state. P(s, t)}" |
181 "A == {<s, t> \<in> state*state. P(s, t)} ==> A={<s, t> \<in> state*state. P(s, t)}" |
182 by auto |
182 by auto |
183 |
183 |
184 lemma act_subset: "A={<s,t> \<in> state*state. P(s, t)} ==> A<=state*state" |
184 lemma act_subset: "A={<s,t> \<in> state*state. P(s, t)} ==> A<=state*state" |
185 by auto |
185 by auto |
186 |
186 |
187 lemma transient_lemma: |
187 lemma transient_lemma: |
188 "client_prog \<in> |
188 "client_prog \<in> |
189 transient({s \<in> state. s`rel = k & <k, h> \<in> strict_prefix(nat) |
189 transient({s \<in> state. s`rel = k & <k, h> \<in> strict_prefix(nat) |
190 & <h, s`giv> \<in> prefix(nat) & h pfixGe s`ask})" |
190 & <h, s`giv> \<in> prefix(nat) & h pfixGe s`ask})" |
191 apply (rule_tac act = client_rel_act in transientI) |
191 apply (rule_tac act = client_rel_act in transientI) |
192 apply (simp (no_asm) add: client_prog_def [THEN def_prg_Acts]) |
192 apply (simp (no_asm) add: client_prog_def [THEN def_prg_Acts]) |
193 apply (simp (no_asm) add: client_rel_act_def [THEN def_act_eq, THEN act_subset]) |
193 apply (simp (no_asm) add: client_rel_act_def [THEN def_act_eq, THEN act_subset]) |
194 apply (auto simp add: client_prog_def [THEN def_prg_Acts] domain_def) |
194 apply (auto simp add: client_prog_def [THEN def_prg_Acts] domain_def) |
206 apply auto |
206 apply auto |
207 apply (simp (no_asm_use) add: gen_prefix_iff_nth) |
207 apply (simp (no_asm_use) add: gen_prefix_iff_nth) |
208 apply (auto simp add: id_def lam_def) |
208 apply (auto simp add: id_def lam_def) |
209 done |
209 done |
210 |
210 |
211 lemma strict_prefix_is_prefix: |
211 lemma strict_prefix_is_prefix: |
212 "<xs, ys> \<in> strict_prefix(A) \<longleftrightarrow> <xs, ys> \<in> prefix(A) & xs\<noteq>ys" |
212 "<xs, ys> \<in> strict_prefix(A) \<longleftrightarrow> <xs, ys> \<in> prefix(A) & xs\<noteq>ys" |
213 apply (unfold strict_prefix_def id_def lam_def) |
213 apply (unfold strict_prefix_def id_def lam_def) |
214 apply (auto dest: prefix_type [THEN subsetD]) |
214 apply (auto dest: prefix_type [THEN subsetD]) |
215 done |
215 done |
216 |
216 |
217 lemma induct_lemma: |
217 lemma induct_lemma: |
218 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); client_prog ok G; G \<in> program |] |
218 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); client_prog ok G; G \<in> program |] |
219 ==> client_prog \<squnion> G \<in> |
219 ==> client_prog \<squnion> G \<in> |
220 {s \<in> state. s`rel = k & <k,h> \<in> strict_prefix(nat) |
220 {s \<in> state. s`rel = k & <k,h> \<in> strict_prefix(nat) |
221 & <h, s`giv> \<in> prefix(nat) & h pfixGe s`ask} |
221 & <h, s`giv> \<in> prefix(nat) & h pfixGe s`ask} |
222 LeadsTo {s \<in> state. <k, s`rel> \<in> strict_prefix(nat) |
222 LeadsTo {s \<in> state. <k, s`rel> \<in> strict_prefix(nat) |
223 & <s`rel, s`giv> \<in> prefix(nat) & |
223 & <s`rel, s`giv> \<in> prefix(nat) & |
224 <h, s`giv> \<in> prefix(nat) & |
224 <h, s`giv> \<in> prefix(nat) & |
225 h pfixGe s`ask}" |
225 h pfixGe s`ask}" |
226 apply (rule single_LeadsTo_I) |
226 apply (rule single_LeadsTo_I) |
227 prefer 2 apply simp |
227 prefer 2 apply simp |
228 apply (frule client_prog_Increasing_ask_rel [THEN guaranteesD]) |
228 apply (frule client_prog_Increasing_ask_rel [THEN guaranteesD]) |
229 apply (rotate_tac [3] 2) |
229 apply (rotate_tac [3] 2) |
237 apply (erule_tac f = "lift (rel) " and a = "s`rel" in Increasing_imp_Stable) |
237 apply (erule_tac f = "lift (rel) " and a = "s`rel" in Increasing_imp_Stable) |
238 apply (simp (no_asm_simp)) |
238 apply (simp (no_asm_simp)) |
239 apply (erule client_prog_Join_Stable_rel_le_giv, blast, simp_all) |
239 apply (erule client_prog_Join_Stable_rel_le_giv, blast, simp_all) |
240 prefer 2 |
240 prefer 2 |
241 apply (blast intro: sym strict_prefix_is_prefix [THEN iffD2] prefix_trans prefix_imp_pfixGe pfixGe_trans) |
241 apply (blast intro: sym strict_prefix_is_prefix [THEN iffD2] prefix_trans prefix_imp_pfixGe pfixGe_trans) |
242 apply (auto intro: strict_prefix_is_prefix [THEN iffD1, THEN conjunct1] |
242 apply (auto intro: strict_prefix_is_prefix [THEN iffD1, THEN conjunct1] |
243 prefix_trans) |
243 prefix_trans) |
244 done |
244 done |
245 |
245 |
246 lemma rel_progress_lemma: |
246 lemma rel_progress_lemma: |
247 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); client_prog ok G; G \<in> program |] |
247 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); client_prog ok G; G \<in> program |] |
248 ==> client_prog \<squnion> G \<in> |
248 ==> client_prog \<squnion> G \<in> |
249 {s \<in> state. <s`rel, h> \<in> strict_prefix(nat) |
249 {s \<in> state. <s`rel, h> \<in> strict_prefix(nat) |
250 & <h, s`giv> \<in> prefix(nat) & h pfixGe s`ask} |
250 & <h, s`giv> \<in> prefix(nat) & h pfixGe s`ask} |
251 LeadsTo {s \<in> state. <h, s`rel> \<in> prefix(nat)}" |
251 LeadsTo {s \<in> state. <h, s`rel> \<in> prefix(nat)}" |
252 apply (rule_tac f = "\<lambda>x \<in> state. length(h) #- length(x`rel)" |
252 apply (rule_tac f = "\<lambda>x \<in> state. length(h) #- length(x`rel)" |
253 in LessThan_induct) |
253 in LessThan_induct) |
254 apply (auto simp add: vimage_def) |
254 apply (auto simp add: vimage_def) |
255 prefer 2 apply (force simp add: lam_def) |
255 prefer 2 apply (force simp add: lam_def) |
256 apply (rule single_LeadsTo_I) |
256 apply (rule single_LeadsTo_I) |
257 prefer 2 apply simp |
257 prefer 2 apply simp |
258 apply (subgoal_tac "h \<in> list(nat)") |
258 apply (subgoal_tac "h \<in> list(nat)") |
259 prefer 2 apply (blast dest: prefix_type [THEN subsetD]) |
259 prefer 2 apply (blast dest: prefix_type [THEN subsetD]) |
260 apply (rule induct_lemma [THEN LeadsTo_weaken]) |
260 apply (rule induct_lemma [THEN LeadsTo_weaken]) |
261 apply (simp add: length_type lam_def) |
261 apply (simp add: length_type lam_def) |
262 apply (auto intro: strict_prefix_is_prefix [THEN iffD2] |
262 apply (auto intro: strict_prefix_is_prefix [THEN iffD2] |
263 dest: common_prefix_linear prefix_type [THEN subsetD]) |
263 dest: common_prefix_linear prefix_type [THEN subsetD]) |
264 apply (erule swap) |
264 apply (erule swap) |
265 apply (rule imageI) |
265 apply (rule imageI) |
266 apply (force dest!: simp add: lam_def) |
266 apply (force dest!: simp add: lam_def) |
267 apply (simp add: length_type lam_def, clarify) |
267 apply (simp add: length_type lam_def, clarify) |
268 apply (drule strict_prefix_length_lt)+ |
268 apply (drule strict_prefix_length_lt)+ |
269 apply (drule less_imp_succ_add, simp)+ |
269 apply (drule less_imp_succ_add, simp)+ |
270 apply clarify |
270 apply clarify |
271 apply simp |
271 apply simp |
272 apply (erule diff_le_self [THEN ltD]) |
272 apply (erule diff_le_self [THEN ltD]) |
273 done |
273 done |
274 |
274 |
275 lemma progress_lemma: |
275 lemma progress_lemma: |
276 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); client_prog ok G; G \<in> program |] |
276 "[| client_prog \<squnion> G \<in> Incr(lift(giv)); client_prog ok G; G \<in> program |] |
277 ==> client_prog \<squnion> G |
277 ==> client_prog \<squnion> G |
278 \<in> {s \<in> state. <h, s`giv> \<in> prefix(nat) & h pfixGe s`ask} |
278 \<in> {s \<in> state. <h, s`giv> \<in> prefix(nat) & h pfixGe s`ask} |
279 LeadsTo {s \<in> state. <h, s`rel> \<in> prefix(nat)}" |
279 LeadsTo {s \<in> state. <h, s`rel> \<in> prefix(nat)}" |
280 apply (rule client_prog_Join_Always_rel_le_giv [THEN Always_LeadsToI], |
280 apply (rule client_prog_Join_Always_rel_le_giv [THEN Always_LeadsToI], |
281 assumption) |
281 assumption) |
282 apply (force simp add: client_prog_ok_iff) |
282 apply (force simp add: client_prog_ok_iff) |
283 apply (rule LeadsTo_weaken_L) |
283 apply (rule LeadsTo_weaken_L) |
284 apply (rule LeadsTo_Un [OF rel_progress_lemma |
284 apply (rule LeadsTo_Un [OF rel_progress_lemma |
285 subset_refl [THEN subset_imp_LeadsTo]]) |
285 subset_refl [THEN subset_imp_LeadsTo]]) |
286 apply (auto intro: strict_prefix_is_prefix [THEN iffD2] |
286 apply (auto intro: strict_prefix_is_prefix [THEN iffD2] |
287 dest: common_prefix_linear prefix_type [THEN subsetD]) |
287 dest: common_prefix_linear prefix_type [THEN subsetD]) |
288 done |
288 done |
289 |
289 |
290 (*Progress property: all tokens that are given will be released*) |
290 (*Progress property: all tokens that are given will be released*) |
291 lemma client_prog_progress: |
291 lemma client_prog_progress: |
292 "client_prog \<in> Incr(lift(giv)) guarantees |
292 "client_prog \<in> Incr(lift(giv)) guarantees |
293 (\<Inter>h \<in> list(nat). {s \<in> state. <h, s`giv> \<in> prefix(nat) & |
293 (\<Inter>h \<in> list(nat). {s \<in> state. <h, s`giv> \<in> prefix(nat) & |
294 h pfixGe s`ask} LeadsTo {s \<in> state. <h, s`rel> \<in> prefix(nat)})" |
294 h pfixGe s`ask} LeadsTo {s \<in> state. <h, s`rel> \<in> prefix(nat)})" |
295 apply (rule guaranteesI) |
295 apply (rule guaranteesI) |
296 apply (blast intro: progress_lemma, auto) |
296 apply (blast intro: progress_lemma, auto) |
297 done |
297 done |
298 |
298 |
299 lemma client_prog_Allowed: |
299 lemma client_prog_Allowed: |
300 "Allowed(client_prog) = |
300 "Allowed(client_prog) = |
301 preserves(lift(rel)) \<inter> preserves(lift(ask)) \<inter> preserves(lift(tok))" |
301 preserves(lift(rel)) \<inter> preserves(lift(ask)) \<inter> preserves(lift(tok))" |
302 apply (cut_tac v = "lift (ask)" in preserves_type) |
302 apply (cut_tac v = "lift (ask)" in preserves_type) |
303 apply (auto simp add: Allowed_def client_prog_def [THEN def_prg_Allowed] |
303 apply (auto simp add: Allowed_def client_prog_def [THEN def_prg_Allowed] |
304 cons_Int_distrib safety_prop_Acts_iff) |
304 cons_Int_distrib safety_prop_Acts_iff) |
305 done |
305 done |
306 |
306 |
307 end |
307 end |