1#![allow(unused_imports)]
4use super::defs::*;
5use vstd::map_lib::*;
6use vstd::prelude::*;
7
8verus! {
10
11broadcast proof fn lemma_execution_sufix_0<T>(ex: Execution<T>)
12 ensures
13 #[trigger] ex.suffix(0) == ex,
14{
15}
16
17broadcast proof fn lemma_execution_sufix_sufix<T>(ex: Execution<T>, i: nat, j: nat)
18 ensures
19 #[trigger] ex.suffix(i).suffix(j) == ex.suffix(i + j),
20{
21}
22
23broadcast group group_execution_suffix_lemmas {
24 lemma_execution_sufix_0,
25 lemma_execution_sufix_sufix,
26}
27
28} verus! {
30
31broadcast proof fn implies_apply<T>(ex: Execution<T>, p: TempPred<T>, q: TempPred<T>)
32 requires
33 #[trigger] p.implies(q).satisfied_by(ex),
34 p.satisfied_by(ex),
35 ensures
36 q.satisfied_by(ex),
37{
38}
39
40proof fn implies_contraposition_apply<T>(ex: Execution<T>, p: TempPred<T>, q: TempPred<T>)
41 requires
42 p.implies(q).satisfied_by(ex),
43 not(q).satisfied_by(ex),
44 ensures
45 not(p).satisfied_by(ex),
46{
47}
48
49pub proof fn temp_pred_equality<T>(p: TempPred<T>, q: TempPred<T>)
50 requires
51 p.entails(q),
52 q.entails(p),
53 ensures
54 p == q,
55{
56 assert forall|ex: Execution<T>| #[trigger] (p.pred)(ex) == (q.pred)(ex) by {
57 if (p.pred)(ex) {
58 implies_apply::<T>(ex, p, q);
59 } else {
60 implies_contraposition_apply::<T>(ex, q, p);
61 }
62 };
63}
64
65proof fn later_unfold<T>(ex: Execution<T>, p: TempPred<T>)
66 requires
67 later(p).satisfied_by(ex),
68 ensures
69 p.satisfied_by(ex.suffix(1)),
70{
71}
72
73broadcast proof fn always_unfold<T>(ex: Execution<T>, p: TempPred<T>)
74 requires
75 #[trigger] always(p).satisfied_by(ex),
76 ensures
77 forall|i: nat| p.satisfied_by(#[trigger] ex.suffix(i)),
78{
79}
80
81proof fn eventually_unfold<T>(ex: Execution<T>, p: TempPred<T>)
82 requires
83 eventually(p).satisfied_by(ex),
84 ensures
85 exists|i: nat| p.satisfied_by(#[trigger] ex.suffix(i)),
86{
87}
88
89proof fn not_eventually_unfold<T>(ex: Execution<T>, p: TempPred<T>)
90 requires
91 not(eventually(p)).satisfied_by(ex),
92 ensures
93 forall|i| !p.satisfied_by(#[trigger] ex.suffix(i)),
94{
95}
96
97proof fn stable_unfold<T>(ex: Execution<T>, p: TempPred<T>)
98 requires
99 stable(p).satisfied_by(ex),
100 ensures
101 p.satisfied_by(ex) ==> forall|i| p.satisfied_by(#[trigger] ex.suffix(i)),
102{
103}
104
105proof fn leads_to_unfold<T>(ex: Execution<T>, p: TempPred<T>, q: TempPred<T>)
106 requires
107 p.leads_to(q).satisfied_by(ex),
108 ensures
109 forall|i: nat| p.implies(eventually(q)).satisfied_by(#[trigger] ex.suffix(i)),
110{
111}
112
113proof fn weak_fairness_unfold<T>(ex: Execution<T>, p: ActionPred<T>)
114 requires
115 weak_fairness(p).satisfied_by(ex),
116 ensures
117 forall|i|
118 always(lift_state(enabled(p))).implies(eventually(lift_action(p))).satisfied_by(
119 #[trigger] ex.suffix(i),
120 ),
121{
122}
123
124proof fn always_lift_state_unfold<T>(ex: Execution<T>, p: StatePred<T>)
125 requires
126 always(lift_state(p)).satisfied_by(ex),
127 ensures
128 forall|i| p.apply(#[trigger] ex.suffix(i).head()),
129{
130 broadcast use always_unfold;
131
132}
133
134proof fn always_lift_action_unfold<T>(ex: Execution<T>, p: ActionPred<T>)
135 requires
136 always(lift_action(p)).satisfied_by(ex),
137 ensures
138 forall|i| p.apply(#[trigger] ex.suffix(i).head(), ex.suffix(i).head_next()),
139{
140 broadcast use always_unfold;
141
142}
143
144broadcast proof fn tla_forall_unfold<T, A>(
145 ex: Execution<T>,
146 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
147)
148 requires
149 #[trigger] tla_forall(a_to_temp_pred).satisfied_by(ex),
150 ensures
151 forall|a| #[trigger] a_to_temp_pred(a).satisfied_by(ex),
152{
153}
154
155broadcast proof fn tla_exists_unfold<T, A>(
156 ex: Execution<T>,
157 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
158)
159 requires
160 #[trigger] tla_exists(a_to_temp_pred).satisfied_by(ex),
161 ensures
162 exists|a| #[trigger] a_to_temp_pred(a).satisfied_by(ex),
163{
164}
165
166proof fn tla_exists_proved_by_witness<T, A>(
167 ex: Execution<T>,
168 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
169 witness_a: A,
170)
171 requires
172 a_to_temp_pred(witness_a).satisfied_by(ex),
173 ensures
174 tla_exists(a_to_temp_pred).satisfied_by(ex),
175{
176}
177
178spec fn tla_exists_choose_witness<T, A>(
179 ex: Execution<T>,
180 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
181) -> A
182 recommends
183 exists|a| #[trigger] a_to_temp_pred(a).satisfied_by(ex),
184{
185 let witness = choose|a| #[trigger] a_to_temp_pred(a).satisfied_by(ex);
186 witness
187}
188
189proof fn implies_apply_with_always<T>(ex: Execution<T>, p: TempPred<T>, q: TempPred<T>)
190 requires
191 always(p.implies(q)).satisfied_by(ex),
192 always(p).satisfied_by(ex),
193 ensures
194 always(q).satisfied_by(ex),
195{
196 broadcast use always_unfold;
197
198}
199
200proof fn entails_apply<T>(ex: Execution<T>, p: TempPred<T>, q: TempPred<T>)
201 requires
202 p.entails(q),
203 p.satisfied_by(ex),
204 ensures
205 q.satisfied_by(ex),
206{
207 implies_apply::<T>(ex, p, q);
208}
209
210proof fn not_proved_by_contraposition<T>(ex: Execution<T>, p: TempPred<T>, q: TempPred<T>)
211 requires
212 p.implies(q).satisfied_by(ex),
213 not(q).satisfied_by(ex),
214 ensures
215 not(p).satisfied_by(ex),
216{
217}
218
219proof fn not_eventually_by_always_not<T>(ex: Execution<T>, p: TempPred<T>)
220 requires
221 always(not(p)).satisfied_by(ex),
222 ensures
223 not(eventually(p)).satisfied_by(ex),
224{
225 broadcast use always_unfold;
226
227}
228
229broadcast proof fn always_propagate_forwards<T>(ex: Execution<T>, p: TempPred<T>, i: nat)
230 requires
231 always(p).satisfied_by(ex),
232 ensures
233 #[trigger] always(p).satisfied_by(ex.suffix(i)),
234{
235 broadcast use {always_unfold, group_execution_suffix_lemmas};
236
237}
238
239proof fn always_double<T>(ex: Execution<T>, p: TempPred<T>)
240 requires
241 always(p).satisfied_by(ex),
242 ensures
243 always(always(p)).satisfied_by(ex),
244{
245 broadcast use {always_unfold, always_propagate_forwards};
246
247}
248
249proof fn always_to_current<T>(ex: Execution<T>, p: TempPred<T>)
250 requires
251 always(p).satisfied_by(ex),
252 ensures
253 p.satisfied_by(ex),
254{
255 assert(ex == ex.suffix(0));
256}
257
258proof fn always_to_future<T>(ex: Execution<T>, p: TempPred<T>, i: nat)
259 requires
260 always(p).satisfied_by(ex),
261 ensures
262 p.satisfied_by(ex.suffix(i)),
263{
264 broadcast use {always_unfold, always_propagate_forwards};
265
266}
267
268proof fn eventually_propagate_backwards<T>(ex: Execution<T>, p: TempPred<T>, i: nat)
269 requires
270 eventually(p).satisfied_by(ex.suffix(i)),
271 ensures
272 eventually(p).satisfied_by(ex),
273{
274 broadcast use group_execution_suffix_lemmas;
275
276}
277
278proof fn eventually_proved_by_witness<T>(ex: Execution<T>, p: TempPred<T>, witness_idx: nat)
279 requires
280 p.satisfied_by(ex.suffix(witness_idx)),
281 ensures
282 eventually(p).satisfied_by(ex),
283{
284}
285
286spec fn eventually_choose_witness<T>(ex: Execution<T>, p: TempPred<T>) -> nat
287 recommends
288 exists|i| p.satisfied_by(#[trigger] ex.suffix(i)),
289{
290 let witness = choose|i| p.satisfied_by(#[trigger] ex.suffix(i));
291 witness
292}
293
294proof fn valid_p_implies_always_p<T>(p: TempPred<T>)
295 requires
296 valid(p),
297 ensures
298 valid(always(p)),
299{
300}
301
302proof fn always_distributed_by_and<T>(p: TempPred<T>, q: TempPred<T>)
303 ensures
304 valid(always(p.and(q)).implies(always(p).and(always(q)))),
305{
306 broadcast use always_unfold;
307
308}
309
310proof fn p_and_always_p_equals_always_p<T>(p: TempPred<T>)
311 ensures
312 p.and(always(p)) == always(p),
313{
314 assert forall|ex| #[trigger] always(p).satisfied_by(ex) implies p.and(always(p)).satisfied_by(
315 ex,
316 ) by {
317 always_to_current::<T>(ex, p);
318 };
319 temp_pred_equality::<T>(p.and(always(p)), always(p));
320}
321
322proof fn a_to_temp_pred_equality<T, A>(p: spec_fn(A) -> TempPred<T>, q: spec_fn(A) -> TempPred<T>)
323 requires
324 forall|a: A| #[trigger] p(a).entails(q(a)) && q(a).entails(p(a)),
325 ensures
326 p == q,
327{
328 assert forall|a: A| #[trigger] p(a) == q(a) by {
329 temp_pred_equality::<T>(p(a), q(a));
330 };
331}
332
333proof fn tla_forall_or_equality<T, A>(a_to_temp_pred: spec_fn(A) -> TempPred<T>, q: TempPred<T>)
334 ensures
335 tla_forall(|a: A| a_to_temp_pred(a).or(q)) == tla_forall(a_to_temp_pred).or(q),
336{
337 broadcast use tla_forall_unfold;
338
339 let a_to_temp_pred_or_q = |a: A| a_to_temp_pred(a).or(q);
340 assert forall|ex| #[trigger] tla_forall(a_to_temp_pred_or_q).satisfied_by(ex) implies (
341 tla_forall(a_to_temp_pred).or(q)).satisfied_by(ex) by {
342 if !q.satisfied_by(ex) {
343 assert forall|a| #[trigger] a_to_temp_pred(a).satisfied_by(ex) by {
344 assert(a_to_temp_pred_or_q(a).satisfied_by(ex));
345 };
346 }
347 };
348 temp_pred_equality::<T>(
349 tla_forall(|a: A| a_to_temp_pred(a).or(q)),
350 tla_forall(a_to_temp_pred).or(q),
351 );
352}
353
354proof fn tla_exists_and_equality<T, A>(a_to_temp_pred: spec_fn(A) -> TempPred<T>, q: TempPred<T>)
355 ensures
356 tla_exists(|a: A| a_to_temp_pred(a).and(q)) == tla_exists(a_to_temp_pred).and(q),
357{
358 let a_to_temp_pred_and_q = |a: A| a_to_temp_pred(a).and(q);
359 assert forall|ex| #[trigger]
360 (tla_exists(a_to_temp_pred).and(q)).satisfied_by(ex) implies tla_exists(
361 a_to_temp_pred_and_q,
362 ).satisfied_by(ex) by {
363 let witness_a = tla_exists_choose_witness::<T, A>(ex, a_to_temp_pred);
364 tla_exists_proved_by_witness::<T, A>(ex, a_to_temp_pred_and_q, witness_a);
365 };
366 temp_pred_equality::<T>(
367 tla_exists(|a: A| a_to_temp_pred(a).and(q)),
368 tla_exists(a_to_temp_pred).and(q),
369 );
370}
371
372proof fn tla_exists_or_equality<T, A>(a_to_temp_pred: spec_fn(A) -> TempPred<T>, q: TempPred<T>)
373 ensures
374 tla_exists(|a: A| a_to_temp_pred(a).or(q)) == tla_exists(a_to_temp_pred).or(q),
375{
376 let a_to_temp_pred_or_q = |a: A| a_to_temp_pred(a).or(q);
377 assert forall|ex| #[trigger]
378 (tla_exists(a_to_temp_pred).or(q)).satisfied_by(ex) implies tla_exists(
379 a_to_temp_pred_or_q,
380 ).satisfied_by(ex) by {
381 if !q.satisfied_by(ex) {
382 let witness_a = tla_exists_choose_witness::<T, A>(ex, a_to_temp_pred);
383 tla_exists_proved_by_witness::<T, A>(ex, a_to_temp_pred_or_q, witness_a);
384 } else {
385 assert(a_to_temp_pred_or_q(arbitrary()).satisfied_by(ex));
386 }
387 };
388 temp_pred_equality::<T>(
389 tla_exists(|a: A| a_to_temp_pred(a).or(q)),
390 tla_exists(a_to_temp_pred).or(q),
391 );
392}
393
394proof fn tla_forall_implies_equality1<T, A>(
395 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
396 q: TempPred<T>,
397)
398 ensures
399 tla_forall(|a: A| a_to_temp_pred(a).implies(q)) == tla_exists(a_to_temp_pred).implies(q),
400{
401 let a_to_not_p = |a: A| not(a_to_temp_pred(a));
402 a_to_temp_pred_equality::<T, A>(
403 |a: A| a_to_temp_pred(a).implies(q),
404 |a: A| a_to_not_p(a).or(q),
405 );
406 temp_pred_equality::<T>(
407 tla_forall(|a: A| a_to_temp_pred(a).implies(q)),
408 tla_forall(|a: A| a_to_not_p(a).or(q)),
409 );
410 tla_forall_or_equality::<T, A>(a_to_not_p, q);
411 tla_forall_not_equality::<T, A>(a_to_temp_pred);
412 temp_pred_equality::<T>(
413 not(tla_exists(a_to_temp_pred)).or(q),
414 tla_exists(a_to_temp_pred).implies(q),
415 );
416}
417
418proof fn tla_forall_implies_equality2<T, A>(
419 p: TempPred<T>,
420 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
421)
422 ensures
423 tla_forall(|a: A| p.implies(a_to_temp_pred(a))) == p.implies(tla_forall(a_to_temp_pred)),
424{
425 a_to_temp_pred_equality::<T, A>(
426 |a: A| p.implies(a_to_temp_pred(a)),
427 |a: A| a_to_temp_pred(a).or(not(p)),
428 );
429 temp_pred_equality::<T>(
430 tla_forall(|a: A| p.implies(a_to_temp_pred(a))),
431 tla_forall(|a: A| a_to_temp_pred(a).or(not(p))),
432 );
433 tla_forall_or_equality::<T, A>(a_to_temp_pred, not(p));
434 temp_pred_equality::<T>(
435 tla_forall(a_to_temp_pred).or(not(p)),
436 p.implies(tla_forall(a_to_temp_pred)),
437 );
438}
439
440proof fn tla_exists_implies_equality1<T, A>(
441 p: TempPred<T>,
442 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
443)
444 ensures
445 tla_exists(|a: A| p.implies(a_to_temp_pred(a))) == p.implies(tla_exists(a_to_temp_pred)),
446{
447 a_to_temp_pred_equality::<T, A>(
448 |a: A| p.implies(a_to_temp_pred(a)),
449 |a: A| a_to_temp_pred(a).or(not(p)),
450 );
451 temp_pred_equality::<T>(
452 tla_exists(|a: A| p.implies(a_to_temp_pred(a))),
453 tla_exists(|a: A| a_to_temp_pred(a).or(not(p))),
454 );
455 tla_exists_or_equality::<T, A>(a_to_temp_pred, not(p));
456 temp_pred_equality::<T>(
457 tla_exists(a_to_temp_pred).or(not(p)),
458 p.implies(tla_exists(a_to_temp_pred)),
459 );
460}
461
462proof fn tla_forall_leads_to_equality1<T, A>(
463 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
464 q: TempPred<T>,
465)
466 ensures
467 tla_forall(|a: A| a_to_temp_pred(a).leads_to(q)) == tla_exists(a_to_temp_pred).leads_to(q),
468{
469 tla_forall_always_equality_variant::<T, A>(
470 |a: A| a_to_temp_pred(a).leads_to(q),
471 |a: A| a_to_temp_pred(a).implies(eventually(q)),
472 );
473 tla_forall_implies_equality1::<T, A>(a_to_temp_pred, eventually(q));
474}
475
476proof fn tla_forall_always_implies_equality2<T, A>(
477 p: TempPred<T>,
478 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
479)
480 ensures
481 tla_forall(|a: A| always(p.implies(a_to_temp_pred(a)))) == always(
482 p.implies(tla_forall(a_to_temp_pred)),
483 ),
484{
485 tla_forall_always_equality_variant::<T, A>(
486 |a: A| always(p.implies(a_to_temp_pred(a))),
487 |a: A| p.implies(a_to_temp_pred(a)),
488 );
489 tla_forall_implies_equality2::<T, A>(p, a_to_temp_pred);
490}
491
492proof fn tla_forall_not_equality<T, A>(a_to_temp_pred: spec_fn(A) -> TempPred<T>)
493 ensures
494 tla_forall(|a: A| not(a_to_temp_pred(a))) == not(tla_exists(a_to_temp_pred)),
495{
496 let a_to_not_p = |a: A| not(a_to_temp_pred(a));
497 assert forall|ex| #[trigger] tla_forall(a_to_not_p).satisfied_by(ex) implies not(
498 tla_exists(a_to_temp_pred),
499 ).satisfied_by(ex) by {
500 assert forall|a| !#[trigger] a_to_temp_pred(a).satisfied_by(ex) by {
501 assert(a_to_not_p(a).satisfied_by(ex));
502 };
503 };
504 temp_pred_equality::<T>(
505 tla_forall(|a: A| not(a_to_temp_pred(a))),
506 not(tla_exists(a_to_temp_pred)),
507 );
508}
509
510proof fn tla_forall_and_equality<T, A>(a_to_temp_pred: spec_fn(A) -> TempPred<T>, q: TempPred<T>)
511 ensures
512 tla_forall(|a: A| a_to_temp_pred(a).and(q)) == tla_forall(a_to_temp_pred).and(q),
513{
514 broadcast use tla_forall_unfold;
515
516 let a_to_temp_pred_and_q = |a: A| a_to_temp_pred(a).and(q);
517 assert forall|ex| #[trigger] tla_forall(a_to_temp_pred_and_q).satisfied_by(ex) implies (
518 tla_forall(a_to_temp_pred).and(q)).satisfied_by(ex) by {
519 assert forall|a| #[trigger] a_to_temp_pred(a).satisfied_by(ex) by {
520 assert(a_to_temp_pred_and_q(a).satisfied_by(ex));
521 };
522 assert(a_to_temp_pred_and_q(arbitrary()).satisfied_by(ex));
523 };
524 temp_pred_equality::<T>(
525 tla_forall(|a: A| a_to_temp_pred(a).and(q)),
526 tla_forall(a_to_temp_pred).and(q),
527 );
528}
529
530proof fn init_invariant_rec<T>(
531 ex: Execution<T>,
532 init: StatePred<T>,
533 next: ActionPred<T>,
534 inv: StatePred<T>,
535 i: nat,
536)
537 requires
538 lift_state(init).satisfied_by(ex),
539 always(lift_action(next)).satisfied_by(ex),
540 lift_state(init).implies(lift_state(inv)).satisfied_by(ex),
541 forall|idx: nat|
542 inv.apply(#[trigger] ex.suffix(idx).head()) && next.apply(
543 ex.suffix(idx).head(),
544 ex.suffix(idx).head_next(),
545 ) ==> inv.apply(ex.suffix(idx).head_next()),
546 ensures
547 inv.apply(ex.suffix(i).head()),
548 decreases i,
549{
550 broadcast use {always_unfold, group_execution_suffix_lemmas};
551
552 if i != 0 {
553 init_invariant_rec::<T>(ex, init, next, inv, (i - 1) as nat);
554 }
555}
556
557proof fn implies_new_invariant_rec<T>(
558 ex: Execution<T>,
559 init: StatePred<T>,
560 next: ActionPred<T>,
561 inv: StatePred<T>,
562 proved_inv: StatePred<T>,
563 i: nat,
564)
565 requires
566 lift_state(init).satisfied_by(ex),
567 always(lift_action(next)).satisfied_by(ex),
568 always(lift_state(proved_inv)).satisfied_by(ex),
569 lift_state(init).implies(lift_state(inv)).satisfied_by(ex),
570 forall|idx: nat|
571 inv.apply(#[trigger] ex.suffix(idx).head()) && proved_inv.apply(
572 #[trigger] ex.suffix(idx).head(),
573 ) && next.apply(ex.suffix(idx).head(), ex.suffix(idx).head_next()) ==> inv.apply(
574 ex.suffix(idx).head_next(),
575 ),
576 ensures
577 inv.apply(ex.suffix(i).head()),
578 decreases i,
579{
580 broadcast use {always_unfold, group_execution_suffix_lemmas};
581
582 if i != 0 {
583 implies_new_invariant_rec(ex, init, next, inv, proved_inv, (i - 1) as nat);
584 }
585}
586
587proof fn always_p_or_eventually_q_rec<T>(
588 ex: Execution<T>,
589 next: TempPred<T>,
590 p: TempPred<T>,
591 q: TempPred<T>,
592 i: nat,
593)
594 requires
595 always(p.and(next).implies(later(p).or(later(q)))).satisfied_by(ex),
596 always(next).satisfied_by(ex),
597 always(not(q)).satisfied_by(ex),
598 p.satisfied_by(ex),
599 ensures
600 p.satisfied_by(ex.suffix(i)),
601 decreases i,
602{
603 broadcast use {always_unfold, group_execution_suffix_lemmas};
604
605 if i != 0 {
606 always_p_or_eventually_q_rec::<T>(ex, next, p, q, (i - 1) as nat);
607 }
608}
609
610proof fn always_p_or_eventually_q<T>(
611 ex: Execution<T>,
612 next: TempPred<T>,
613 p: TempPred<T>,
614 q: TempPred<T>,
615)
616 requires
617 always(p.and(next).implies(later(p).or(later(q)))).satisfied_by(ex),
618 always(next).satisfied_by(ex),
619 ensures
620 always(p.implies(always(p).or(eventually(q)))).satisfied_by(ex),
621{
622 broadcast use {always_unfold, implies_apply, group_execution_suffix_lemmas};
623
624 assert forall|i| p.satisfied_by(#[trigger] ex.suffix(i)) implies always(p).satisfied_by(
625 ex.suffix(i),
626 ) || eventually(q).satisfied_by(ex.suffix(i)) by {
627 if !eventually(q).satisfied_by(ex.suffix(i)) {
628 assert forall|j| p.satisfied_by(#[trigger] ex.suffix(i).suffix(j)) by {
629 always_p_or_eventually_q_rec::<T>(ex.suffix(i), next, p, q, j);
630 };
631 }
632 };
633}
634
635proof fn next_preserves_inv_rec<T>(ex: Execution<T>, next: TempPred<T>, inv: TempPred<T>, i: nat)
636 requires
637 inv.satisfied_by(ex),
638 always(next).satisfied_by(ex),
639 always(inv.and(next).implies(later(inv))).satisfied_by(ex),
640 ensures
641 inv.satisfied_by(ex.suffix(i)),
642 decreases i,
643{
644 broadcast use {always_unfold, group_execution_suffix_lemmas};
645
646 if i != 0 {
647 next_preserves_inv_rec::<T>(ex, next, inv, (i - 1) as nat);
648 }
649}
650
651proof fn instantiate_entailed_always<T>(ex: Execution<T>, i: nat, spec: TempPred<T>, p: TempPred<T>)
652 requires
653 spec.satisfied_by(ex),
654 spec.implies(always(p)).satisfied_by(ex),
655 ensures
656 p.satisfied_by(ex.suffix(i)),
657{
658 broadcast use {always_unfold, implies_apply};
659
660}
661
662proof fn instantiate_entailed_leads_to<T>(
663 ex: Execution<T>,
664 i: nat,
665 spec: TempPred<T>,
666 p: TempPred<T>,
667 q: TempPred<T>,
668)
669 requires
670 spec.satisfied_by(ex),
671 spec.implies(p.leads_to(q)).satisfied_by(ex),
672 ensures
673 p.implies(eventually(q)).satisfied_by(ex.suffix(i)),
674{
675 broadcast use implies_apply;
676
677}
678
679} verus! {
682
683pub broadcast proof fn state_pred_and_apply_equality<T>(p: StatePred<T>, q: StatePred<T>, s: T)
686 ensures
687 #[trigger] p.and(q).apply(s) == (p.apply(s) && q.apply(s)),
688{
689}
690
691pub broadcast proof fn state_pred_or_apply_equality<T>(p: StatePred<T>, q: StatePred<T>, s: T)
693 ensures
694 #[trigger] p.or(q).apply(s) == (p.apply(s) || q.apply(s)),
695{
696}
697
698pub broadcast proof fn state_pred_not_apply_equality<T>(p: StatePred<T>, s: T)
700 ensures
701 #[trigger] p.not().apply(s) == !p.apply(s),
702{
703}
704
705pub broadcast proof fn state_pred_implies_apply_equality<T>(p: StatePred<T>, q: StatePred<T>, s: T)
707 ensures
708 #[trigger] p.implies(q).apply(s) == (p.apply(s) ==> q.apply(s)),
709{
710}
711
712pub broadcast proof fn lift_state_and_equality<T>(p: StatePred<T>, q: StatePred<T>)
717 ensures
718 #![trigger lift_state(p.and(q))]
719 #![trigger lift_state(p).and(lift_state(q))]
720 lift_state(p.and(q)) == lift_state(p).and(lift_state(q)),
721{
722}
723
724pub broadcast proof fn lift_state_or_equality<T>(p: StatePred<T>, q: StatePred<T>)
729 ensures
730 #![trigger lift_state(p.or(q))]
731 #![trigger lift_state(p).or(lift_state(q))]
732 lift_state(p.or(q)) == lift_state(p).or(lift_state(q)),
733{
734}
735
736pub broadcast proof fn lift_state_not_equality<T>(p: StatePred<T>)
741 ensures
742 #![trigger lift_state(p.not())]
743 #![trigger not(lift_state(p))]
744 lift_state(p.not()) == not(lift_state(p)),
745{
746}
747
748pub broadcast proof fn lift_state_implies_equality<T>(p: StatePred<T>, q: StatePred<T>)
753 ensures
754 #[trigger] lift_state(p.implies(q)) == lift_state(p).implies(lift_state(q)),
755{
756}
757
758pub broadcast proof fn always_and_equality<T>(p: TempPred<T>, q: TempPred<T>)
763 ensures
764 #[trigger] always(p.and(q)) == always(p).and(always(q)),
765{
766 broadcast use always_unfold;
767
768 temp_pred_equality::<T>(always(p.and(q)), always(p).and(always(q)));
769}
770
771pub broadcast proof fn entails_and_temp<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>)
781 requires
782 spec.entails(p),
783 spec.entails(q),
784 ensures
785 #[trigger] spec.entails(p.and(q)),
786{
787 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.and(q).satisfied_by(ex) by {
788 implies_apply::<T>(ex, spec, p);
789 implies_apply::<T>(ex, spec, q);
790 };
791}
792
793pub broadcast proof fn entails_and_temp_reverse<T>(
803 spec: TempPred<T>,
804 p: TempPred<T>,
805 q: TempPred<T>,
806)
807 requires
808 #[trigger] spec.entails(p.and(q)),
809 ensures
810 spec.entails(p),
811 spec.entails(q),
812{
813 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.satisfied_by(ex) by {
814 implies_apply::<T>(ex, spec, p.and(q));
815 };
816 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies q.satisfied_by(ex) by {
817 implies_apply::<T>(ex, spec, p.and(q));
818 };
819}
820
821pub broadcast proof fn entails_or_temp<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>)
832 requires
833 spec.entails(p) || spec.entails(q),
834 ensures
835 #[trigger] spec.entails(p.or(q)),
836{
837 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.or(q).satisfied_by(ex) by {
838 if spec.entails(p) {
839 implies_apply::<T>(ex, spec, p);
840 } else {
841 implies_apply::<T>(ex, spec, q);
842 }
843 };
844}
845
846pub broadcast proof fn entails_not_temp_reverse<T>(spec: TempPred<T>, p: TempPred<T>)
857 requires
858 #[trigger] spec.entails(not(p)),
859 spec != false_pred::<T>(),
860 ensures
861 !spec.entails(p),
862{
863 if forall|ex| !#[trigger] spec.satisfied_by(ex) {
864 temp_pred_equality::<T>(spec, false_pred::<T>());
865 }
866 let ex = choose|ex| spec.satisfied_by(ex);
867 assert(spec.implies(not(p)).satisfied_by(ex));
868 assert(!spec.implies(p).satisfied_by(ex));
869}
870
871pub broadcast proof fn entails_implies_temp_reverse<T>(
882 spec: TempPred<T>,
883 p: TempPred<T>,
884 q: TempPred<T>,
885)
886 requires
887 #[trigger] spec.entails(p.implies(q)),
888 ensures
889 spec.entails(p) ==> spec.entails(q),
890{
891 if spec.entails(p) {
892 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies q.satisfied_by(ex) by {
893 implies_apply::<T>(ex, spec, p.implies(q));
894 implies_apply::<T>(ex, spec, p);
895 };
896 }
897}
898
899broadcast group group_definition_basics {
900 state_pred_and_apply_equality,
901 state_pred_or_apply_equality,
902 state_pred_not_apply_equality,
903 state_pred_implies_apply_equality,
904 lift_state_and_equality,
905 lift_state_or_equality,
906 lift_state_not_equality,
907 lift_state_implies_equality,
908 always_and_equality,
909 entails_and_temp,
910 entails_and_temp_reverse,
911 entails_or_temp,
912 entails_not_temp_reverse,
913 entails_implies_temp_reverse,
914}
915
916pub broadcast proof fn always_double_equality<T>(p: TempPred<T>)
921 ensures
922 #[trigger] always(always(p)) == always(p),
923{
924 broadcast use {always_unfold, group_execution_suffix_lemmas};
925
926 assert forall|ex| #[trigger] always(always(p)).satisfied_by(ex) implies always(p).satisfied_by(
927 ex,
928 ) by {
929 assert(always(p).satisfied_by(ex.suffix(0)));
930 }
931 temp_pred_equality::<T>(always(always(p)), always(p));
932}
933
934pub broadcast proof fn always_lift_state_and_equality<T>(p: StatePred<T>, q: StatePred<T>)
939 ensures
940 #[trigger] always(lift_state(p.and(q))) == always(lift_state(p)).and(always(lift_state(q))),
941{
942 broadcast use group_definition_basics;
943
944}
945
946pub broadcast proof fn leads_to_self_temp<T>(p: TempPred<T>)
951 ensures
952 #[trigger] valid(p.leads_to(p)),
953{
954 broadcast use group_definition_basics;
955
956 assert forall|ex| #[trigger] always(p.implies(eventually(p))).satisfied_by(ex) by {
957 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(p).satisfied_by(
958 ex.suffix(i),
959 ) by {
960 assert(ex.suffix(i) == ex.suffix(i).suffix(0));
961 eventually_proved_by_witness::<T>(ex.suffix(i), p, 0);
962 };
963 };
964}
965
966pub proof fn entails_trans<T>(p: TempPred<T>, q: TempPred<T>, r: TempPred<T>)
974 requires
975 p.entails(q),
976 q.entails(r),
977 ensures
978 p.entails(r),
979{
980 assert forall|ex| p.satisfied_by(ex) implies r.satisfied_by(ex) by {
981 implies_apply::<T>(ex, p, q);
982 implies_apply::<T>(ex, q, r);
983 };
984}
985
986pub broadcast proof fn entails_preserved_by_always<T>(p: TempPred<T>, q: TempPred<T>)
993 requires
994 p.entails(q),
995 ensures
996 #[trigger] always(p).entails(always(q)),
997{
998 broadcast use always_unfold;
999
1000 assert forall|ex| always(p).satisfied_by(ex) implies always(q).satisfied_by(ex) by {
1001 assert forall|i: nat| q.satisfied_by(#[trigger] ex.suffix(i)) by {
1002 implies_apply::<T>(ex.suffix(i), p, q);
1003 };
1004 };
1005}
1006
1007pub proof fn eliminate_always<T>(spec: TempPred<T>, p: TempPred<T>)
1014 requires
1015 spec.entails(always(p)),
1016 ensures
1017 spec.entails(p),
1018{
1019 assert forall|ex| spec.satisfied_by(ex) implies #[trigger] p.satisfied_by(ex) by {
1020 implies_apply(ex, spec, always(p));
1021 assert(ex == ex.suffix(0));
1022 }
1023}
1024
1025pub broadcast proof fn always_implies_to_leads_to<T>(
1032 spec: TempPred<T>,
1033 p: TempPred<T>,
1034 q: TempPred<T>,
1035)
1036 requires
1037 #[trigger] spec.entails(always(p.implies(q))),
1038 ensures
1039 spec.entails(p.leads_to(q)),
1040{
1041 broadcast use {always_unfold, implies_apply, group_definition_basics};
1042
1043 assert forall|ex| spec.satisfied_by(ex) implies #[trigger] p.leads_to(q).satisfied_by(ex) by {
1044 implies_apply(ex, spec, always(p.implies(q)));
1045 assert forall|i: nat| p.satisfied_by(#[trigger] ex.suffix(i)) implies eventually(
1046 q,
1047 ).satisfied_by(ex.suffix(i)) by {
1048 assert(ex.suffix(i) == ex.suffix(i).suffix(0));
1049 };
1050 };
1051}
1052
1053pub broadcast proof fn always_to_always_later<T>(spec: TempPred<T>, p: TempPred<T>)
1060 requires
1061 spec.entails(always(p)),
1062 ensures
1063 #[trigger] spec.entails(always(later(p))),
1064{
1065 broadcast use {always_unfold, group_execution_suffix_lemmas};
1066
1067 entails_trans(spec, always(p), always(later(p)));
1068}
1069
1070pub broadcast proof fn entails_and_different_temp<T>(
1078 spec1: TempPred<T>,
1079 spec2: TempPred<T>,
1080 p: TempPred<T>,
1081 q: TempPred<T>,
1082)
1083 requires
1084 spec1.entails(p),
1085 spec2.entails(q),
1086 ensures
1087 #[trigger] spec1.and(spec2).entails(p.and(q)),
1088{
1089 assert forall|ex| #[trigger] spec1.and(spec2).satisfied_by(ex) implies p.and(q).satisfied_by(
1090 ex,
1091 ) by {
1092 implies_apply::<T>(ex, spec1, p);
1093 implies_apply::<T>(ex, spec2, q);
1094 };
1095}
1096
1097pub proof fn entails_implies_leads_to<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>)
1106 requires
1107 p.entails(q),
1108 ensures
1109 spec.entails(p.leads_to(q)),
1110{
1111 valid_p_implies_always_p(p.implies(q));
1112 always_implies_to_leads_to(spec, p, q);
1113}
1114
1115pub proof fn always_weaken<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>)
1123 requires
1124 valid(p.implies(q)),
1125 spec.entails(always(p)),
1126 ensures
1127 spec.entails(always(q)),
1128{
1129 entails_preserved_by_always::<T>(p, q);
1130 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies always(q).satisfied_by(ex) by {
1131 implies_apply::<T>(ex, spec, always(p));
1132 implies_apply::<T>(ex, always(p), always(q));
1133 };
1134}
1135
1136pub broadcast proof fn leads_to_apply<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>)
1144 requires
1145 spec.entails(p),
1146 #[trigger] spec.entails(p.leads_to(q)),
1147 ensures
1148 spec.entails(eventually(q)),
1149{
1150 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies eventually(q).satisfied_by(ex) by {
1151 implies_apply::<T>(ex, spec, p);
1152 implies_apply::<T>(ex, spec, p.leads_to(q));
1153 leads_to_unfold::<T>(ex, p, q);
1154 assert(ex == ex.suffix(0));
1155 implies_apply::<T>(ex, p, eventually(q));
1156 };
1157}
1158
1159pub proof fn leads_to_trans<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>, r: TempPred<T>)
1167 requires
1168 spec.entails(p.leads_to(q)),
1169 spec.entails(q.leads_to(r)),
1170 ensures
1171 spec.entails(p.leads_to(r)),
1172{
1173 broadcast use group_definition_basics;
1174
1175 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(r).satisfied_by(ex) by {
1176 assert forall|i: nat| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(
1177 r,
1178 ).satisfied_by(ex.suffix(i)) by {
1179 entails_apply(ex, spec, p.leads_to(q));
1180 always_unfold(ex, p.implies(eventually(q)));
1181 implies_apply(ex.suffix(i), p, eventually(q));
1182 eventually_unfold(ex.suffix(i), q);
1183 let q_witness_idx = eventually_choose_witness(ex.suffix(i), q);
1184
1185 assert(ex.suffix(i + q_witness_idx) == ex.suffix(i).suffix(q_witness_idx));
1186
1187 entails_apply(ex, spec, q.leads_to(r));
1188 always_unfold(ex, q.implies(eventually(r)));
1189 implies_apply(ex.suffix(i + q_witness_idx), q, eventually(r));
1190
1191 eventually_propagate_backwards(ex.suffix(i), r, q_witness_idx);
1192 }
1193 };
1194}
1195
1196pub proof fn always_lift_state_weaken<T>(spec: TempPred<T>, p: StatePred<T>, q: StatePred<T>)
1205 requires
1206 forall|s: T| #[trigger] p.apply(s) ==> q.apply(s),
1207 spec.entails(always(lift_state(p))),
1208 ensures
1209 spec.entails(always(lift_state(q))),
1210{
1211 always_weaken::<T>(spec, lift_state(p), lift_state(q));
1212}
1213
1214pub proof fn always_implies_preserved_by_always<T>(
1221 spec: TempPred<T>,
1222 p: TempPred<T>,
1223 q: TempPred<T>,
1224)
1225 requires
1226 spec.entails(always(p.implies(q))),
1227 ensures
1228 spec.entails(always(always(p).implies(always(q)))),
1229{
1230 broadcast use group_tla_rules;
1231
1232 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies always(
1233 always(p).implies(always(q)),
1234 ).satisfied_by(ex) by {
1235 assert forall|i| #[trigger] always(p).satisfied_by(ex.suffix(i)) implies always(
1236 q,
1237 ).satisfied_by(ex.suffix(i)) by {
1238 assert forall|j| #[trigger] q.satisfied_by(ex.suffix(i).suffix(j)) by {
1239 implies_apply::<T>(ex, spec, always(p.implies(q)));
1240 assert(ex.suffix(i + j) == ex.suffix(i).suffix(j));
1241 implies_apply::<T>(ex.suffix(i).suffix(j), p, q);
1242 };
1243 };
1244 };
1245}
1246
1247pub broadcast proof fn or_leads_to_combine<T>(
1255 spec: TempPred<T>,
1256 p: TempPred<T>,
1257 q: TempPred<T>,
1258 r: TempPred<T>,
1259)
1260 requires
1261 spec.entails(p.leads_to(r)),
1262 spec.entails(q.leads_to(r)),
1263 ensures
1264 #[trigger] spec.entails(p.or(q).leads_to(r)),
1265{
1266 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.or(q).leads_to(r).satisfied_by(
1267 ex,
1268 ) by {
1269 assert forall|i| #[trigger] p.or(q).satisfied_by(ex.suffix(i)) implies eventually(
1270 r,
1271 ).satisfied_by(ex.suffix(i)) by {
1272 implies_apply::<T>(ex, spec, p.leads_to(r));
1273 implies_apply::<T>(ex, spec, q.leads_to(r));
1274 leads_to_unfold::<T>(ex, p, r);
1275 leads_to_unfold::<T>(ex, q, r);
1276 };
1277 };
1278}
1279
1280pub proof fn or_leads_to_case_analysis<T>(
1288 spec: TempPred<T>,
1289 p: TempPred<T>,
1290 q: TempPred<T>,
1291 r: TempPred<T>,
1292)
1293 requires
1294 spec.entails(p.and(q).leads_to(r)),
1295 spec.entails(p.and(not(q)).leads_to(r)),
1296 ensures
1297 spec.entails(p.leads_to(r)),
1298{
1299 broadcast use group_definition_basics;
1300
1301 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(r).satisfied_by(ex) by {
1302 if spec.satisfied_by(ex) {
1303 assert(spec.implies(p.and(q).leads_to(r)).satisfied_by(ex));
1304 assert(spec.implies(p.and(not(q)).leads_to(r)).satisfied_by(ex));
1305
1306 leads_to_unfold(ex, p.and(q), r);
1307 leads_to_unfold(ex, p.and(not(q)), r);
1308
1309 assert forall|i| p.implies(eventually(r)).satisfied_by(#[trigger] ex.suffix(i)) by {}
1310 }
1311 }
1312}
1313
1314pub broadcast proof fn leads_to_always_combine<T>(
1322 spec: TempPred<T>,
1323 p: TempPred<T>,
1324 q: TempPred<T>,
1325 r: TempPred<T>,
1326)
1327 requires
1328 spec.entails(p.leads_to(always(q))),
1329 spec.entails(p.leads_to(always(r))),
1330 ensures
1331 #![trigger spec.entails(p.leads_to(always(q).and(always(r))))]
1332 #![trigger spec.entails(p.leads_to(always(q.and(r))))]
1333 spec.entails(p.leads_to(always(q.and(r)))),
1334 spec.entails(p.leads_to(always(q).and(always(r)))),
1335{
1336 broadcast use group_definition_basics;
1337
1338 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(
1339 always(q.and(r)),
1340 ).satisfied_by(ex) by {
1341 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(
1342 always(q.and(r)),
1343 ).satisfied_by(ex.suffix(i)) by {
1344 implies_apply::<T>(ex, spec, p.leads_to(always(q)));
1345 implies_apply::<T>(ex, spec, p.leads_to(always(r)));
1346
1347 implies_apply::<T>(ex.suffix(i), p, eventually(always(q)));
1348 implies_apply::<T>(ex.suffix(i), p, eventually(always(r)));
1349
1350 let witness_q_idx = eventually_choose_witness::<T>(ex.suffix(i), always(q));
1351 let witness_r_idx = eventually_choose_witness::<T>(ex.suffix(i), always(r));
1352
1353 if witness_q_idx < witness_r_idx {
1354 always_propagate_forwards::<T>(
1355 ex.suffix(i).suffix(witness_q_idx),
1356 q,
1357 (witness_r_idx - witness_q_idx) as nat,
1358 );
1359 assert(ex.suffix(i).suffix(witness_r_idx) == ex.suffix(i).suffix(
1360 witness_q_idx,
1361 ).suffix((witness_r_idx - witness_q_idx) as nat));
1362 eventually_proved_by_witness(ex.suffix(i), always(q.and(r)), witness_r_idx);
1363 } else {
1364 always_propagate_forwards::<T>(
1365 ex.suffix(i).suffix(witness_r_idx),
1366 r,
1367 (witness_q_idx - witness_r_idx) as nat,
1368 );
1369 assert(ex.suffix(i).suffix(witness_q_idx) == ex.suffix(i).suffix(
1370 witness_r_idx,
1371 ).suffix((witness_q_idx - witness_r_idx) as nat));
1372 eventually_proved_by_witness(ex.suffix(i), always(q.and(r)), witness_q_idx);
1373 }
1374 };
1375 };
1376 always_and_equality(q, r);
1377}
1378
1379pub proof fn leads_to_stable<T>(
1388 spec: TempPred<T>,
1389 next: TempPred<T>,
1390 p: TempPred<T>,
1391 q: TempPred<T>,
1392)
1393 requires
1394 spec.entails(always(q.and(next).implies(later(q)))),
1395 spec.entails(always(next)),
1396 spec.entails(p.leads_to(q)),
1397 ensures
1398 spec.entails(p.leads_to(always(q))),
1399{
1400 broadcast use {always_unfold, always_propagate_forwards, group_definition_basics};
1401
1402 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(always(q)).satisfied_by(
1403 ex,
1404 ) by {
1405 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(
1406 always(q),
1407 ).satisfied_by(ex.suffix(i)) by {
1408 implies_apply::<T>(ex, spec, p.leads_to(q));
1409 leads_to_unfold::<T>(ex, p, q);
1410 implies_apply::<T>(ex.suffix(i), p, eventually(q));
1411 let witness_idx = eventually_choose_witness::<T>(ex.suffix(i), q);
1412
1413 implies_apply::<T>(ex, spec, always(q.and(next).implies(later(q))));
1414 always_propagate_forwards::<T>(
1415 ex.suffix(i),
1416 q.and(next).implies(later(q)),
1417 witness_idx,
1418 );
1419
1420 implies_apply::<T>(ex, spec, always(next));
1421 always_propagate_forwards::<T>(ex.suffix(i), next, witness_idx);
1422
1423 assert forall|j| #[trigger]
1424 q.satisfied_by(ex.suffix(i).suffix(witness_idx).suffix(j)) by {
1425 assert forall|idx|
1426 q.satisfied_by(#[trigger] ex.suffix(i).suffix(witness_idx).suffix(idx))
1427 && next.satisfied_by(
1428 ex.suffix(i).suffix(witness_idx).suffix(idx),
1429 ) implies q.satisfied_by(ex.suffix(i).suffix(witness_idx).suffix(idx + 1)) by {
1430 implies_apply::<T>(
1431 ex.suffix(i).suffix(witness_idx).suffix(idx),
1432 q.and(next),
1433 later(q),
1434 );
1435 assert(ex.suffix(i).suffix(witness_idx).suffix(idx + 1) == ex.suffix(i).suffix(
1436 witness_idx,
1437 ).suffix(idx).suffix(1));
1438 };
1439 next_preserves_inv_rec::<T>(ex.suffix(i).suffix(witness_idx), next, q, j);
1440 };
1441
1442 eventually_proved_by_witness::<T>(ex.suffix(i), always(q), witness_idx);
1443 };
1444 };
1445}
1446
1447pub broadcast proof fn leads_to_framed_by_or<T>(
1454 spec: TempPred<T>,
1455 p: TempPred<T>,
1456 q: TempPred<T>,
1457 r: TempPred<T>,
1458)
1459 requires
1460 spec.entails(p.leads_to(q)),
1461 ensures
1462 #[trigger] spec.entails(p.or(r).leads_to(q.or(r))),
1463{
1464 broadcast use {implies_apply, group_execution_suffix_lemmas, group_definition_basics};
1465
1466 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.or(r).leads_to(
1467 q.or(r),
1468 ).satisfied_by(ex) by {
1469 assert forall|i| #[trigger] p.or(r).satisfied_by(ex.suffix(i)) implies eventually(
1470 q.or(r),
1471 ).satisfied_by(ex.suffix(i)) by {
1472 implies_apply(ex, spec, p.leads_to(q));
1473 leads_to_unfold(ex, p, q);
1474 if p.satisfied_by(ex.suffix(i)) {
1475 let witness_idx = eventually_choose_witness(ex.suffix(i), q);
1476 eventually_proved_by_witness(ex.suffix(i), q.or(r), witness_idx);
1477 } else {
1478 let witness_idx = 0;
1479 eventually_proved_by_witness(ex.suffix(i), q.or(r), witness_idx);
1480 }
1481 }
1482 }
1483}
1484
1485pub proof fn leads_to_shortcut_temp<T>(
1493 spec: TempPred<T>,
1494 p: TempPred<T>,
1495 q: TempPred<T>,
1496 r: TempPred<T>,
1497 s: TempPred<T>,
1498)
1499 requires
1500 spec.entails(p.leads_to(q.or(s))),
1501 spec.entails(q.leads_to(r.or(s))),
1502 ensures
1503 spec.entails(p.leads_to(r.or(s))),
1504{
1505 leads_to_framed_by_or(spec, q, r.or(s), s);
1506 temp_pred_equality(r.or(s).or(s), r.or(s));
1507 leads_to_trans(spec, p, q.or(s), r.or(s));
1508}
1509
1510pub broadcast proof fn entails_always_lift_state_and<T>(
1518 spec: TempPred<T>,
1519 p: StatePred<T>,
1520 q: StatePred<T>,
1521)
1522 requires
1523 spec.entails(always(lift_state(p))),
1524 spec.entails(always(lift_state(q))),
1525 ensures
1526 #[trigger] spec.entails(always(lift_state(p.and(q)))),
1527{
1528 broadcast use group_definition_basics;
1529
1530}
1531
1532pub broadcast proof fn entails_always_lift_state_and_elim<T>(
1540 spec: TempPred<T>,
1541 p: StatePred<T>,
1542 q: StatePred<T>,
1543)
1544 requires
1545 #[trigger] spec.entails(always(lift_state(p.and(q)))),
1546 ensures
1547 spec.entails(always(lift_state(p))),
1548 spec.entails(always(lift_state(q))),
1549{
1550 broadcast use group_definition_basics;
1551
1552}
1553
1554pub broadcast proof fn lift_state_exists_equality<T, A>(a_to_state_pred: spec_fn(A) -> StatePred<T>)
1560 ensures
1561 #[trigger] lift_state_exists(a_to_state_pred) == tla_exists(
1562 |a| lift_state(a_to_state_pred(a)),
1563 ),
1564{
1565 let p = lift_state_exists(a_to_state_pred);
1566 let q = tla_exists(|a| lift_state(a_to_state_pred(a)));
1567 let partial_p = |t| exists|a| #[trigger] a_to_state_pred(a).apply(t);
1568 let partial_q = |a| lift_state(a_to_state_pred(a));
1569 assert forall|ex| p.satisfied_by(ex) implies q.satisfied_by(ex) by {
1570 assert(exists|a| #[trigger] a_to_state_pred(a).apply(ex.head()));
1571 let witness_a = choose|a| #[trigger] a_to_state_pred(a).apply(ex.head());
1572 assert(partial_q(witness_a).satisfied_by(ex));
1573 };
1574
1575 temp_pred_equality::<T>(p, q);
1576}
1577
1578pub proof fn tla_forall_always_equality<T, A>(a_to_temp_pred: spec_fn(A) -> TempPred<T>)
1586 ensures
1587 tla_forall(|a: A| always(a_to_temp_pred(a))) == always(tla_forall(a_to_temp_pred)),
1588{
1589 broadcast use {always_unfold, tla_forall_unfold};
1590
1591 let a_to_always_p = |a: A| always(a_to_temp_pred(a));
1592
1593 assert forall|ex| #[trigger] tla_forall(a_to_always_p).satisfied_by(ex) implies always(
1594 tla_forall(a_to_temp_pred),
1595 ).satisfied_by(ex) by {
1596 assert forall|i| #[trigger] tla_forall(a_to_temp_pred).satisfied_by(ex.suffix(i)) by {
1597 assert forall|a| #[trigger] a_to_temp_pred(a).satisfied_by(ex.suffix(i)) by {
1598 assert(a_to_always_p(a).satisfied_by(ex));
1599 };
1600 };
1601 };
1602
1603 temp_pred_equality::<T>(
1604 tla_forall(|a: A| always(a_to_temp_pred(a))),
1605 always(tla_forall(a_to_temp_pred)),
1606 );
1607}
1608
1609pub proof fn tla_forall_always_equality_variant<T, A>(
1610 a_to_always: spec_fn(A) -> TempPred<T>,
1611 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
1612)
1613 requires
1614 forall|a: A|
1615 #![trigger a_to_always(a)]
1616 a_to_always(a).entails((|a: A| always(a_to_temp_pred(a)))(a)) && ((|a: A|
1617 always(a_to_temp_pred(a)))(a)).entails(a_to_always(a)),
1618 ensures
1619 tla_forall(a_to_always) == always(tla_forall(a_to_temp_pred)),
1620{
1621 a_to_temp_pred_equality::<T, A>(a_to_always, |a: A| always(a_to_temp_pred(a)));
1622 temp_pred_equality::<T>(tla_forall(a_to_always), tla_forall(|a: A| always(a_to_temp_pred(a))));
1623 tla_forall_always_equality::<T, A>(a_to_temp_pred);
1624}
1625
1626pub broadcast proof fn tla_forall_apply<T, A>(a_to_temp_pred: spec_fn(A) -> TempPred<T>, a: A)
1631 ensures
1632 #[trigger] tla_forall(a_to_temp_pred).entails(a_to_temp_pred(a)),
1633{
1634 broadcast use tla_forall_unfold;
1635
1636}
1637
1638pub proof fn use_always_tla_forall<T, A>(
1646 spec: TempPred<T>,
1647 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
1648 a: A,
1649)
1650 requires
1651 spec.entails(always(tla_forall(a_to_temp_pred))),
1652 ensures
1653 spec.entails(always(a_to_temp_pred(a))),
1654{
1655 entails_preserved_by_always(tla_forall(a_to_temp_pred), a_to_temp_pred(a));
1656 entails_trans(spec, always(tla_forall(a_to_temp_pred)), always(a_to_temp_pred(a)));
1657}
1658
1659pub broadcast proof fn spec_entails_tla_forall<T, A>(
1667 spec: TempPred<T>,
1668 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
1669)
1670 requires
1671 forall|a: A| spec.entails(#[trigger] a_to_temp_pred(a)),
1672 ensures
1673 #[trigger] spec.entails(tla_forall(a_to_temp_pred)),
1674{
1675 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies tla_forall(
1676 a_to_temp_pred,
1677 ).satisfied_by(ex) by {
1678 assert forall|a| #[trigger] a_to_temp_pred(a).satisfied_by(ex) by {
1679 implies_apply::<T>(ex, spec, a_to_temp_pred(a));
1680 };
1681 };
1682}
1683
1684pub proof fn spec_entails_always_tla_forall<T, A>(
1691 spec: TempPred<T>,
1692 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
1693)
1694 requires
1695 forall|a: A| spec.entails(always(#[trigger] a_to_temp_pred(a))),
1696 ensures
1697 spec.entails(always(tla_forall(a_to_temp_pred))),
1698{
1699 let a_to_always = |a: A| always(a_to_temp_pred(a));
1700 spec_entails_tla_forall(spec, a_to_always);
1701 tla_forall_always_equality_variant::<T, A>(a_to_always, a_to_temp_pred);
1702}
1703
1704pub broadcast proof fn always_implies_forall_intro<T, A>(
1711 spec: TempPred<T>,
1712 p: TempPred<T>,
1713 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
1714)
1715 requires
1716 forall|a: A| #[trigger] spec.entails(always(p.implies(a_to_temp_pred(a)))),
1717 ensures
1718 #[trigger] spec.entails(always(p.implies(tla_forall(a_to_temp_pred)))),
1719{
1720 let a_to_always_p_implies_q = |a: A| always(p.implies(a_to_temp_pred(a)));
1721 spec_entails_tla_forall::<T, A>(spec, a_to_always_p_implies_q);
1722 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies always(
1723 p.implies(tla_forall(a_to_temp_pred)),
1724 ).satisfied_by(ex) by {
1725 implies_apply::<T>(ex, spec, tla_forall(a_to_always_p_implies_q));
1726 tla_forall_always_implies_equality2::<T, A>(p, a_to_temp_pred)
1727 };
1728}
1729
1730pub broadcast proof fn tla_exists_leads_to_intro<T, A>(
1737 spec: TempPred<T>,
1738 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
1739 q: TempPred<T>,
1740)
1741 requires
1742 forall|a: A| #[trigger] spec.entails(a_to_temp_pred(a).leads_to(q)),
1743 ensures
1744 #[trigger] spec.entails(tla_exists(a_to_temp_pred).leads_to(q)),
1745{
1746 let a_to_temp_pred_leads_to_q = |a: A| a_to_temp_pred(a).leads_to(q);
1747 spec_entails_tla_forall::<T, A>(spec, a_to_temp_pred_leads_to_q);
1748 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies tla_exists(a_to_temp_pred).leads_to(
1749 q,
1750 ).satisfied_by(ex) by {
1751 implies_apply::<T>(ex, spec, tla_forall(a_to_temp_pred_leads_to_q));
1752 tla_forall_leads_to_equality1::<T, A>(a_to_temp_pred, q);
1753 };
1754}
1755
1756pub proof fn use_tla_forall<T, A>(
1763 spec: TempPred<T>,
1764 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
1765 a: A,
1766)
1767 requires
1768 spec.entails(tla_forall(a_to_temp_pred)),
1769 ensures
1770 spec.entails(a_to_temp_pred(a)),
1771{
1772 assert forall|ex: Execution<T>| #[trigger] spec.satisfied_by(ex) implies (a_to_temp_pred(
1773 a,
1774 )).satisfied_by(ex) by {
1775 entails_apply(ex, spec, tla_forall(a_to_temp_pred));
1776 assert(spec.implies(tla_forall(a_to_temp_pred)).satisfied_by(ex));
1777 };
1778}
1779
1780pub broadcast proof fn entails_tla_exists_by_witness<T, A>(
1781 spec: TempPred<T>,
1782 p: spec_fn(A) -> TempPred<T>,
1783 a: A,
1784)
1785 requires
1786 #[trigger] spec.entails(p(a)),
1787 ensures
1788 spec.entails(tla_exists(p)),
1789{
1790 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies tla_exists(p).satisfied_by(ex) by {
1791 implies_apply::<T>(ex, spec, p(a));
1792 tla_exists_unfold::<T, A>(ex, p);
1793 };
1794}
1795
1796pub proof fn implies_tla_exists_by_witness<T, A>(
1797 spec: TempPred<T>,
1798 p: TempPred<T>,
1799 q: spec_fn(A) -> TempPred<T>,
1800 a: A,
1801)
1802 requires
1803 spec.entails(p.implies(q(a))),
1804 ensures
1805 spec.entails(p.implies(tla_exists(q))),
1806{
1807 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.implies(
1808 tla_exists(q),
1809 ).satisfied_by(ex) by {
1810 implies_apply(ex, spec, p.implies(q(a)));
1811 };
1812}
1813
1814pub broadcast proof fn implies_tla_exists_intro<T, A>(
1815 spec: TempPred<T>,
1816 p: TempPred<T>,
1817 q: spec_fn(A) -> TempPred<T>,
1818)
1819 requires
1820 exists|a: A| #[trigger] spec.entails(p.implies(q(a))),
1821 ensures
1822 #[trigger] spec.entails(p.implies(tla_exists(q))),
1823{
1824 let witness = choose|a: A| #[trigger] spec.entails(p.implies(q(a)));
1825 implies_tla_exists_by_witness(spec, p, q, witness);
1826}
1827
1828pub proof fn leads_to_tla_exists_by_witness<T, A>(
1829 spec: TempPred<T>,
1830 p: TempPred<T>,
1831 q: spec_fn(A) -> TempPred<T>,
1832 a: A,
1833)
1834 requires
1835 spec.entails(p.leads_to(q(a))),
1836 ensures
1837 spec.entails(p.leads_to(tla_exists(q))),
1838{
1839 assert forall|ex| #[trigger] always(q(a).implies(tla_exists(q))).satisfied_by(ex) by {
1840 assert forall|i: nat| q(a).implies(tla_exists(q)).satisfied_by(ex.suffix(i)) by {
1841 if q(a).satisfied_by(ex.suffix(i)) {
1842 tla_exists_proved_by_witness(ex.suffix(i), q, a);
1843 }
1844 };
1845 };
1846 leads_to_weaken(spec, p, q(a), p, tla_exists(q));
1847}
1848
1849pub broadcast proof fn leads_to_tla_exists_intro<T, A>(
1850 spec: TempPred<T>,
1851 p: TempPred<T>,
1852 q: spec_fn(A) -> TempPred<T>,
1853)
1854 requires
1855 exists|a: A| #[trigger] spec.entails(p.leads_to(q(a))),
1856 ensures
1857 #[trigger] spec.entails(p.leads_to(tla_exists(q))),
1858{
1859 let witness = choose|a: A| #[trigger] spec.entails(p.leads_to(q(a)));
1860 leads_to_tla_exists_by_witness(spec, p, q, witness);
1861}
1862
1863pub broadcast proof fn lift_state_exists_leads_to_intro<T, A>(
1864 spec: TempPred<T>,
1865 a_to_temp_pred: spec_fn(A) -> StatePred<T>,
1866 q: TempPred<T>,
1867)
1868 requires
1869 forall|a: A| #[trigger] spec.entails(lift_state(a_to_temp_pred(a)).leads_to(q)),
1870 ensures
1871 #[trigger] spec.entails(lift_state_exists(a_to_temp_pred).leads_to(q)),
1872{
1873 lift_state_exists_equality(a_to_temp_pred);
1874 let lifted_a_to_temp_pred = |a: A| lift_state(a_to_temp_pred(a));
1875 tla_exists_leads_to_intro(spec, lifted_a_to_temp_pred, q);
1876}
1877
1878pub broadcast proof fn state_exists_intro<T, A>(a_to_temp_pred: spec_fn(A) -> StatePred<T>, s: T)
1879 requires
1880 exists|a: A| #[trigger] a_to_temp_pred(a).apply(s),
1881 ensures
1882 #[trigger] StatePred::state_exists(a_to_temp_pred).apply(s),
1883{
1884}
1885
1886pub broadcast proof fn lift_state_exists_absorb_equality<T, A>(
1887 a_to_state_pred: spec_fn(A) -> StatePred<T>,
1888 state_pred: StatePred<T>,
1889)
1890 ensures
1891 #[trigger] lift_state_exists(a_to_state_pred).and(lift_state(state_pred))
1892 == lift_state_exists(StatePred::absorb(a_to_state_pred, state_pred)),
1893{
1894 broadcast use group_definition_basics;
1895
1896 let lhs = lift_state_exists(a_to_state_pred).and(lift_state(state_pred));
1897 let rhs = lift_state_exists(StatePred::absorb(a_to_state_pred, state_pred));
1898
1899 assert forall|ex| lhs.satisfied_by(ex) == rhs.satisfied_by(ex) by {
1900 let s = ex.head();
1901
1902 if lhs.satisfied_by(ex) {
1903 let a = choose|a| #[trigger] a_to_state_pred(a).apply(s);
1904 assert(StatePred::absorb(a_to_state_pred, state_pred)(a).apply(s));
1905 }
1906 if rhs.satisfied_by(ex) {
1907 let a = choose|a| #[trigger] StatePred::absorb(a_to_state_pred, state_pred)(a).apply(s);
1908 }
1909 }
1910 temp_pred_equality(lhs, rhs);
1911}
1912
1913pub broadcast proof fn lift_state_forall_absorb_equality<T, A>(
1914 a_to_state_pred: spec_fn(A) -> StatePred<T>,
1915 state_pred: StatePred<T>,
1916)
1917 requires
1918 Set::<A>::full() != Set::<A>::empty(),
1919 ensures
1920 #[trigger] lift_state_forall(a_to_state_pred).and(lift_state(state_pred))
1921 == lift_state_forall(StatePred::absorb(a_to_state_pred, state_pred)),
1922{
1923 broadcast use group_definition_basics;
1924
1925 let lhs = lift_state_forall(a_to_state_pred).and(lift_state(state_pred));
1926 let rhs = lift_state_forall(StatePred::absorb(a_to_state_pred, state_pred));
1927
1928 assert forall|ex| lhs.satisfied_by(ex) == rhs.satisfied_by(ex) by {
1929 let s = ex.head();
1930
1931 if lhs.satisfied_by(ex) {
1932 assert forall|a| #[trigger]
1933 StatePred::absorb(a_to_state_pred, state_pred)(a).apply(s) by {}
1934 }
1935 if rhs.satisfied_by(ex) {
1936 let a = choose|a| Set::<A>::full().contains(a);
1937 assert(StatePred::absorb(a_to_state_pred, state_pred)(a).apply(s));
1938 assert forall|a| #[trigger] a_to_state_pred(a).apply(s) by {
1939 assert(StatePred::absorb(a_to_state_pred, state_pred)(a).apply(s));
1940 }
1941 }
1942 }
1943 temp_pred_equality(lhs, rhs);
1944}
1945
1946pub proof fn lift_state_exists_leads_to_case_analysis<T, A>(
1954 spec: TempPred<T>,
1955 a_to_temp_pred: spec_fn(A) -> StatePred<T>,
1956 p: StatePred<T>,
1957 q: TempPred<T>,
1958)
1959 requires
1960 spec.entails(lift_state_exists(StatePred::absorb(a_to_temp_pred, p)).leads_to(q)),
1961 spec.entails(lift_state_exists(StatePred::absorb(a_to_temp_pred, p.not())).leads_to(q)),
1962 ensures
1963 spec.entails(lift_state_exists(a_to_temp_pred).leads_to(q)),
1964{
1965 broadcast use {lift_state_exists_absorb_equality, group_definition_basics};
1966
1967 or_leads_to_case_analysis(spec, lift_state_exists(a_to_temp_pred), lift_state(p), q);
1968}
1969
1970pub proof fn leads_to_always_tla_forall<T, A>(
1985 spec: TempPred<T>,
1986 p: TempPred<T>,
1987 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
1988 domain: Set<A>,
1989)
1990 requires
1991 forall|a: A| spec.entails(p.leads_to(always(#[trigger] a_to_temp_pred(a)))),
1992 domain.finite(),
1993 domain.len() > 0,
1994 forall|a: A| #[trigger] domain.contains(a),
1995 ensures
1996 spec.entails(p.leads_to(always(tla_forall(a_to_temp_pred)))),
1997{
1998 broadcast use {always_unfold, always_propagate_forwards, group_definition_basics};
1999
2000 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(
2001 always(tla_forall(a_to_temp_pred)),
2002 ).satisfied_by(ex) by {
2003 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(
2004 always(tla_forall(a_to_temp_pred)),
2005 ).satisfied_by(ex.suffix(i)) by {
2006 assert forall|a: A|
2007 p.leads_to(always(#[trigger] a_to_temp_pred(a))).satisfied_by(ex) by {
2008 implies_apply::<T>(ex, spec, p.leads_to(always(a_to_temp_pred(a))));
2009 }
2010 assert forall|a: A|
2011 eventually(always(#[trigger] a_to_temp_pred(a))).satisfied_by(ex.suffix(i)) by {
2012 implies_apply::<T>(ex.suffix(i), p, eventually(always(a_to_temp_pred(a))));
2013 }
2014
2015 let a_to_witness = Map::new(
2016 |a: A| domain.contains(a),
2017 |a: A|
2018 {
2019 let wit = eventually_choose_witness::<T>(
2020 ex.suffix(i),
2021 always(a_to_temp_pred(a)),
2022 );
2023 wit
2024 },
2025 );
2026 assert(a_to_witness.dom() == domain);
2027 let r = |a1: nat, a2: nat| a1 <= a2;
2028 let values = a_to_witness.values();
2029 lemma_values_finite(a_to_witness);
2030 assert_by(
2031 values.len() > 0,
2032 {
2033 let x = a_to_witness.dom().choose();
2034 assert(values.contains(a_to_witness[x]));
2035 },
2036 );
2037 let max_witness = values.find_unique_maximal(r);
2038 values.find_unique_maximal_ensures(r);
2039 values.lemma_maximal_equivalent_greatest(r, max_witness);
2040
2041 assert forall|a: A|
2042 always(#[trigger] a_to_temp_pred(a)).satisfied_by(
2043 ex.suffix(i).suffix(max_witness),
2044 ) by {
2045 let witness = a_to_witness[a];
2046 assert(r(witness, max_witness));
2047 assert(ex.suffix(i).suffix(max_witness) == ex.suffix(i).suffix(witness).suffix(
2048 (max_witness - witness) as nat,
2049 ));
2050 }
2051 eventually_proved_by_witness(
2052 ex.suffix(i),
2053 always(tla_forall(a_to_temp_pred)),
2054 max_witness,
2055 );
2056 };
2057 };
2058}
2059
2060pub broadcast proof fn always_p_is_stable<T>(p: TempPred<T>)
2066 ensures
2067 #[trigger] valid(stable(always(p))),
2068{
2069 broadcast use {always_unfold, always_propagate_forwards};
2070
2071}
2072
2073pub proof fn p_leads_to_q_is_stable<T>(p: TempPred<T>, q: TempPred<T>)
2078 ensures
2079 valid(stable(p.leads_to(q))),
2080{
2081 always_p_is_stable(p.implies(eventually(q)));
2082}
2083
2084pub broadcast proof fn stable_and_temp<T>(p: TempPred<T>, q: TempPred<T>)
2092 requires
2093 valid(stable(p)),
2094 valid(stable(q)),
2095 ensures
2096 #[trigger] valid(stable(p.and(q))),
2097{
2098 assert forall|ex| #[trigger] p.and(q).satisfied_by(ex) implies always(p.and(q)).satisfied_by(
2099 ex,
2100 ) by {
2101 stable_unfold::<T>(ex, p);
2102 stable_unfold::<T>(ex, q);
2103 }
2104}
2105
2106pub proof fn tla_forall_a_p_leads_to_q_a_is_stable<T, A>(
2114 p: TempPred<T>,
2115 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
2116)
2117 requires
2118 forall|a: A| #[trigger] valid(stable(p.leads_to(a_to_temp_pred(a)))),
2119 ensures
2120 valid(stable(tla_forall(|a: A| p.leads_to(a_to_temp_pred(a))))),
2121{
2122 broadcast use group_definition_basics;
2123
2124 let target = tla_forall(|a: A| p.leads_to(a_to_temp_pred(a)));
2125 assert forall|ex|
2126 (forall|a: A| #[trigger]
2127 valid(stable(p.leads_to(a_to_temp_pred(a))))) implies #[trigger] stable(
2128 target,
2129 ).satisfied_by(ex) by {
2130 assert forall|i|
2131 (forall|a: A| #[trigger] valid(stable(p.leads_to(a_to_temp_pred(a)))))
2132 && target.satisfied_by(ex) implies #[trigger] target.satisfied_by(ex.suffix(i)) by {
2133 assert forall|a: A|
2134 p.leads_to(a_to_temp_pred(a)).satisfied_by(ex) implies #[trigger] p.leads_to(
2135 a_to_temp_pred(a),
2136 ).satisfied_by(ex.suffix(i)) by {
2137 assert(valid(stable(p.leads_to(a_to_temp_pred(a)))));
2138 assert(stable(p.leads_to(a_to_temp_pred(a))).satisfied_by(ex));
2139 if p.leads_to(a_to_temp_pred(a)).satisfied_by(ex) {
2140 }
2141 }
2142 }
2143 }
2144}
2145
2146pub proof fn unpack_conditions_from_spec<T>(
2154 spec: TempPred<T>,
2155 c: TempPred<T>,
2156 p: TempPred<T>,
2157 q: TempPred<T>,
2158)
2159 requires
2160 valid(stable(spec)),
2161 spec.and(c).entails(p.leads_to(q)),
2162 ensures
2163 spec.entails(p.and(c).leads_to(q)),
2164{
2165 broadcast use {always_unfold, implies_apply, group_definition_basics};
2166
2167 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.and(c).leads_to(q).satisfied_by(
2168 ex,
2169 ) by {
2170 assert forall|i| #[trigger] p.and(c).satisfied_by(ex.suffix(i)) implies eventually(
2171 q,
2172 ).satisfied_by(ex.suffix(i)) by {
2173 stable_unfold::<T>(ex, spec);
2174 implies_apply::<T>(ex.suffix(i), spec.and(c), p.leads_to(q));
2175 assert(ex.suffix(i) == ex.suffix(i).suffix(0));
2176 implies_apply::<T>(ex.suffix(i), p, eventually(q));
2177 };
2178 };
2179}
2180
2181pub proof fn pack_conditions_to_spec<T>(
2189 spec: TempPred<T>,
2190 c: TempPred<T>,
2191 p: TempPred<T>,
2192 q: TempPred<T>,
2193)
2194 requires
2195 spec.entails(p.and(c).leads_to(q)),
2196 ensures
2197 spec.and(always(c)).entails(p.leads_to(q)),
2198{
2199 broadcast use {always_unfold, always_propagate_forwards};
2200
2201 assert forall|ex| #[trigger] spec.and(always(c)).satisfied_by(ex) implies p.leads_to(
2202 q,
2203 ).satisfied_by(ex) by {
2204 implies_apply(ex, spec, p.and(c).leads_to(q));
2205 leads_to_unfold(ex, p.and(c), q);
2206
2207 }
2208}
2209
2210pub proof fn entails_and_equality<T>(p: TempPred<T>, q: TempPred<T>)
2221 requires
2222 p.entails(q),
2223 ensures
2224 p == p.and(q),
2225{
2226 assert forall|ex| #[trigger] p.satisfied_by(ex) implies p.and(q).satisfied_by(ex) by {
2227 entails_and_temp::<T>(p, p, q);
2228 entails_apply::<T>(ex, p, p.and(q));
2229 };
2230 temp_pred_equality::<T>(p, p.and(q));
2231}
2232
2233pub proof fn entails_trans_by_simplify<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>)
2241 requires
2242 spec.entails(p),
2243 spec.and(p).entails(q),
2244 ensures
2245 spec.entails(q),
2246{
2247 entails_and_equality(spec, p);
2248}
2249
2250pub proof fn leads_to_by_borrowing_inv<T>(
2259 spec: TempPred<T>,
2260 p: TempPred<T>,
2261 q: TempPred<T>,
2262 inv: TempPred<T>,
2263)
2264 requires
2265 spec.entails(p.and(inv).leads_to(q)),
2266 spec.entails(always(inv)),
2267 ensures
2268 spec.entails(p.leads_to(q)),
2269{
2270 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(q).satisfied_by(ex) by {
2271 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(q).satisfied_by(
2272 ex.suffix(i),
2273 ) by {
2274 instantiate_entailed_always(ex, i, spec, inv);
2275 instantiate_entailed_leads_to(ex, i, spec, p.and(inv), q);
2276 }
2277 }
2278}
2279
2280pub proof fn leads_to_always_enhance<T>(
2289 spec: TempPred<T>,
2290 inv: TempPred<T>,
2291 p: TempPred<T>,
2292 q1: TempPred<T>,
2293 q2: TempPred<T>,
2294)
2295 requires
2296 spec.entails(always(inv)),
2297 spec.entails(p.leads_to(always(q1))),
2298 q1.and(inv).entails(q2),
2299 ensures
2300 spec.entails(p.leads_to(always(q2))),
2301{
2302 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(always(q2)).satisfied_by(
2303 ex,
2304 ) by {
2305 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(
2306 always(q2),
2307 ).satisfied_by(ex.suffix(i)) by {
2308 implies_apply(ex, spec, always(inv));
2309 implies_apply(ex, spec, p.leads_to(always(q1)));
2310 leads_to_unfold(ex, p, always(q1));
2311 implies_apply(ex.suffix(i), p, eventually(always(q1)));
2312 let witness = eventually_choose_witness(ex.suffix(i), always(q1));
2313 assert forall|j| #[trigger] q2.satisfied_by(ex.suffix(i).suffix(witness).suffix(j)) by {
2314 assert(ex.suffix(i).suffix(witness).suffix(j) == ex.suffix(i + witness + j));
2315 implies_apply(ex.suffix(i).suffix(witness).suffix(j), q1.and(inv), q2);
2316 }
2317 eventually_proved_by_witness(ex.suffix(i), always(q2), witness);
2318 }
2319 }
2320}
2321
2322pub proof fn leads_to_weaken<T>(
2331 spec: TempPred<T>,
2332 p1: TempPred<T>,
2333 q1: TempPred<T>,
2334 p2: TempPred<T>,
2335 q2: TempPred<T>,
2336)
2337 requires
2338 spec.entails(always(p2.implies(p1))),
2339 spec.entails(always(q1.implies(q2))),
2340 spec.entails(p1.leads_to(q1)),
2341 ensures
2342 spec.entails(p2.leads_to(q2)),
2343{
2344 always_implies_to_leads_to::<T>(spec, p2, p1);
2345 always_implies_to_leads_to::<T>(spec, q1, q2);
2346 leads_to_trans::<T>(spec, p2, p1, q1);
2347 leads_to_trans::<T>(spec, p2, q1, q2);
2348}
2349
2350pub proof fn vacuous_leads_to<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>, r: TempPred<T>)
2358 requires
2359 spec.entails(always(r)),
2360 p.and(r) == false_pred::<T>(),
2361 ensures
2362 spec.entails(p.leads_to(q)),
2363{
2364 broadcast use {always_unfold, implies_apply, group_execution_suffix_lemmas};
2365
2366 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(q).satisfied_by(ex) by {
2367 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(q).satisfied_by(
2368 ex.suffix(i),
2369 ) by {
2370 assert_by(
2371 !p.satisfied_by(ex.suffix(i)),
2372 {
2373 implies_apply::<T>(ex, spec, always(r));
2374 if p.satisfied_by(ex.suffix(i)) {
2375 assert(p.and(r).satisfied_by(ex.suffix(i)));
2376 }
2377 },
2378 );
2379 }
2380 }
2381}
2382
2383pub proof fn strengthen_leads_to_with_until<T>(
2399 spec: TempPred<T>,
2400 next: TempPred<T>,
2401 p: TempPred<T>,
2402 q: TempPred<T>,
2403)
2404 requires
2405 spec.entails(always(p).leads_to(q)),
2406 spec.entails(always(p.and(next).implies(later(p).or(later(q))))),
2407 spec.entails(always(next)),
2408 ensures
2409 spec.entails(p.leads_to(q)),
2410{
2411 broadcast use {
2412 always_unfold,
2413 implies_apply,
2414 group_execution_suffix_lemmas,
2415 group_definition_basics,
2416 };
2417
2418 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(q).satisfied_by(ex) by {
2419 implies_apply(ex, spec, always(next));
2420 implies_apply(ex, spec, always(p.and(next).implies(later(p).or(later(q)))));
2421 always_p_or_eventually_q(ex, next, p, q);
2422 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(q).satisfied_by(
2423 ex.suffix(i),
2424 ) by {
2425 if always(p).satisfied_by(ex.suffix(i)) {
2426 implies_apply(ex, spec, always(p).leads_to(q));
2427 }
2428 }
2429 }
2430}
2431
2432pub proof fn transform_leads_to_with_until<T>(
2457 spec: TempPred<T>,
2458 next: TempPred<T>,
2459 p1: TempPred<T>,
2460 q1: TempPred<T>,
2461 p2: TempPred<T>,
2462 q2: TempPred<T>,
2463)
2464 requires
2465 spec.entails(p1.leads_to(q1)),
2466 spec.entails(always(p2.and(next).implies(later(p2).or(later(q2))))),
2467 spec.entails(always(next)),
2468 ensures
2469 spec.entails(p1.and(p2).leads_to((q1.and(p2)).or(q2))),
2470{
2471 broadcast use {
2472 always_unfold,
2473 implies_apply,
2474 group_execution_suffix_lemmas,
2475 group_definition_basics,
2476 };
2477
2478 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p1.and(p2).leads_to(
2479 (q1.and(p2)).or(q2),
2480 ).satisfied_by(ex) by {
2481 assert forall|i| #[trigger] p1.and(p2).satisfied_by(ex.suffix(i)) implies eventually(
2482 (q1.and(p2)).or(q2),
2483 ).satisfied_by(ex.suffix(i)) by {
2484 implies_apply::<T>(ex, spec, always(next));
2485 implies_apply::<T>(ex, spec, always(p2.and(next).implies(later(p2).or(later(q2)))));
2486
2487 always_p_or_eventually_q::<T>(ex, next, p2, q2);
2488
2489 implies_apply::<T>(ex, spec, p1.leads_to(q1));
2490
2491 if eventually(q2).satisfied_by(ex.suffix(i)) {
2492 let witness_idx = eventually_choose_witness::<T>(ex.suffix(i), q2);
2493 eventually_proved_by_witness::<T>(ex.suffix(i), (q1.and(p2)).or(q2), witness_idx);
2494 } else {
2495 let witness_idx = eventually_choose_witness::<T>(ex.suffix(i), q1);
2496 eventually_proved_by_witness::<T>(ex.suffix(i), (q1.and(p2)).or(q2), witness_idx);
2497 }
2498 }
2499 }
2500}
2501
2502pub proof fn leads_to_rank_step_one<T>(spec: TempPred<T>, p: spec_fn(nat) -> TempPred<T>)
2509 requires
2510 forall|n: nat| #![trigger p(n)] (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as nat)))),
2511 ensures
2512 forall|n: nat| #[trigger] spec.entails(p(n).leads_to(p(0))),
2513{
2514 let pre = {
2515 forall|n: nat| #![trigger p(n)] (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as nat))))
2516 };
2517 assert forall|n: nat| pre implies #[trigger] spec.entails(p(n).leads_to(p(0))) by {
2518 leads_to_rank_step_one_help(spec, p, n);
2519 }
2520}
2521
2522proof fn leads_to_rank_step_one_help<T>(spec: TempPred<T>, p: spec_fn(nat) -> TempPred<T>, n: nat)
2523 requires
2524 forall|n: nat| #![trigger p(n)] (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as nat)))),
2525 ensures
2526 spec.entails(p(n).leads_to(p(0))),
2527 decreases n,
2528{
2529 if n > 0 {
2530 leads_to_rank_step_one_help(spec, p, (n - 1) as nat);
2533 leads_to_trans_n!(spec, p(n), p((n - 1) as nat), p(0));
2534 } else {
2535 leads_to_self_temp(p(0));
2537 }
2538}
2539
2540pub proof fn leads_to_rank_step_one_usize<T>(spec: TempPred<T>, p: spec_fn(usize) -> TempPred<T>)
2542 requires
2543 forall|n: usize|
2544 #![trigger p(n)]
2545 (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as usize)))),
2546 ensures
2547 forall|n: usize| #[trigger] spec.entails(p(n).leads_to(p(0))),
2548{
2549 let pre = {
2550 forall|n: usize|
2551 #![trigger p(n)]
2552 (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as usize))))
2553 };
2554 assert forall|n: usize| pre implies #[trigger] spec.entails(p(n).leads_to(p(0))) by {
2555 leads_to_rank_step_one_usize_help(spec, p, n);
2556 }
2557}
2558
2559proof fn leads_to_rank_step_one_usize_help<T>(
2560 spec: TempPred<T>,
2561 p: spec_fn(usize) -> TempPred<T>,
2562 n: usize,
2563)
2564 requires
2565 forall|n: usize|
2566 #![trigger p(n)]
2567 (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as usize)))),
2568 ensures
2569 spec.entails(p(n).leads_to(p(0))),
2570 decreases n,
2571{
2572 if n > 0 {
2573 leads_to_rank_step_one_usize_help(spec, p, (n - 1) as usize);
2576 leads_to_trans_n!(spec, p(n), p((n - 1) as usize), p(0));
2577 } else {
2578 leads_to_self_temp(p(0));
2580 }
2581}
2582
2583pub proof fn init_invariant<T>(
2593 spec: TempPred<T>,
2594 init: StatePred<T>,
2595 next: ActionPred<T>,
2596 inv: StatePred<T>,
2597)
2598 requires
2599 forall|s: T| #[trigger] init.apply(s) ==> inv.apply(s),
2600 forall|s, s_prime: T|
2601 inv.apply(s) && #[trigger] next.apply(s, s_prime) ==> inv.apply(s_prime),
2602 spec.entails(lift_state(init)),
2603 spec.entails(always(lift_action(next))),
2604 ensures
2605 spec.entails(always(lift_state(inv))),
2606{
2607 broadcast use group_tla_rules;
2608
2609 assert forall|ex: Execution<T>| spec.satisfied_by(ex) implies #[trigger] always(
2610 lift_state(inv),
2611 ).satisfied_by(ex) by {
2612 implies_apply(ex, spec, lift_state(init));
2613 implies_apply(ex, spec, always(lift_action(next)));
2614 assert forall|i: nat| inv.apply(#[trigger] ex.suffix(i).head()) by {
2615 init_invariant_rec(ex, init, next, inv, i);
2616 };
2617 };
2618}
2619
2620pub proof fn implies_new_invariant<T>(
2629 spec: TempPred<T>,
2630 init: StatePred<T>,
2631 next: ActionPred<T>,
2632 inv: StatePred<T>,
2633 proved_inv: StatePred<T>,
2634)
2635 requires
2636 forall|s: T| #[trigger] init.apply(s) ==> inv.apply(s),
2637 forall|s, s_prime: T|
2638 inv.apply(s) && proved_inv.apply(s) && #[trigger] next.apply(s, s_prime) ==> inv.apply(
2639 s_prime,
2640 ),
2641 spec.entails(lift_state(init)),
2642 spec.entails(always(lift_action(next))),
2643 spec.entails(always(lift_state(proved_inv))),
2644 ensures
2645 spec.entails(always(lift_state(inv))),
2646{
2647 broadcast use group_tla_rules;
2648
2649 assert forall|ex: Execution<T>| spec.satisfied_by(ex) implies #[trigger] always(
2650 lift_state(inv),
2651 ).satisfied_by(ex) by {
2652 implies_apply(ex, spec, lift_state(init));
2653 implies_apply(ex, spec, always(lift_action(next)));
2654 implies_apply(ex, spec, always(lift_state(proved_inv)));
2655 assert forall|i: nat| inv.apply(#[trigger] ex.suffix(i).head()) by {
2656 implies_new_invariant_rec(ex, init, next, inv, proved_inv, i);
2657 };
2658 };
2659}
2660
2661pub proof fn wf1_variant_temp<T>(
2671 spec: TempPred<T>,
2672 next: TempPred<T>,
2673 forward: TempPred<T>,
2674 p: TempPred<T>,
2675 q: TempPred<T>,
2676)
2677 requires
2678 spec.entails(always(p.and(next).implies(later(p).or(later(q))))),
2679 spec.entails(always(p.and(next).and(forward).implies(later(q)))),
2680 spec.entails(always(next)),
2681 spec.entails(always(p).leads_to(forward)),
2682 ensures
2683 spec.entails(p.leads_to(q)),
2684{
2685 broadcast use group_tla_rules;
2686
2687 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(q).satisfied_by(ex) by {
2688 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(q).satisfied_by(
2689 ex.suffix(i),
2690 ) by {
2691 implies_apply::<T>(ex, spec, always(next));
2692 implies_apply::<T>(ex, spec, always(p.and(next).implies(later(p).or(later(q)))));
2693 implies_apply::<T>(ex, spec, always(p.and(next).and(forward).implies(later(q))));
2694
2695 always_p_or_eventually_q::<T>(ex, next, p, q);
2696 implies_apply::<T>(ex.suffix(i), p, always(p).or(eventually(q)));
2697 if always(p).satisfied_by(ex.suffix(i)) {
2698 implies_apply::<T>(ex, spec, always(p).leads_to(forward));
2699 leads_to_unfold::<T>(ex, always(p), forward);
2700 implies_apply::<T>(ex.suffix(i), always(p), eventually(forward));
2701 let witness_idx = eventually_choose_witness::<T>(ex.suffix(i), forward);
2702
2703 always_propagate_forwards::<T>(ex, next, i);
2704 always_propagate_forwards::<T>(ex, p.and(next).and(forward).implies(later(q)), i);
2705 implies_apply::<T>(
2706 ex.suffix(i).suffix(witness_idx),
2707 p.and(next).and(forward),
2708 later(q),
2709 );
2710 assert(ex.suffix(i).suffix(witness_idx).suffix(1) == ex.suffix(i).suffix(
2711 witness_idx + 1,
2712 ));
2713 eventually_proved_by_witness::<T>(ex.suffix(i), q, witness_idx + 1);
2714 }
2715 }
2716 }
2717}
2718
2719pub proof fn wf1<T>(
2730 spec: TempPred<T>,
2731 next: ActionPred<T>,
2732 forward: ActionPred<T>,
2733 p: StatePred<T>,
2734 q: StatePred<T>,
2735)
2736 requires
2737 forall|s, s_prime: T|
2738 p.apply(s) && #[trigger] next.apply(s, s_prime) ==> p.apply(s_prime) || q.apply(
2739 s_prime,
2740 ),
2741 forall|s, s_prime: T|
2742 p.apply(s) && #[trigger] next.apply(s, s_prime) && forward.apply(s, s_prime)
2743 ==> q.apply(s_prime),
2744 forall|s: T| #[trigger] p.apply(s) ==> enabled(forward).apply(s),
2745 spec.entails(always(lift_action(next))),
2746 spec.entails(weak_fairness(forward)),
2747 ensures
2748 spec.entails(lift_state(p).leads_to(lift_state(q))),
2749{
2750 broadcast use group_tla_rules;
2751
2752 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies always(lift_state(p)).leads_to(
2753 lift_action(forward),
2754 ).satisfied_by(ex) by {
2755 assert forall|i| #[trigger]
2756 always(lift_state(p)).satisfied_by(ex.suffix(i)) implies eventually(
2757 lift_action(forward),
2758 ).satisfied_by(ex.suffix(i)) by {
2759 implies_apply_with_always::<T>(
2760 ex.suffix(i),
2761 lift_state(p),
2762 lift_state(enabled(forward)),
2763 );
2764 assert(ex.suffix(i).suffix(0) == ex.suffix(i));
2765
2766 implies_apply::<T>(ex, spec, weak_fairness(forward));
2767 weak_fairness_unfold::<T>(ex, forward);
2768 implies_apply::<T>(
2769 ex.suffix(i),
2770 lift_state(enabled(forward)),
2771 eventually(lift_action(forward)),
2772 );
2773 };
2774 };
2775 wf1_variant_temp::<T>(
2776 spec,
2777 lift_action(next),
2778 lift_action(forward),
2779 lift_state(p),
2780 lift_state(q),
2781 );
2782}
2783
2784pub proof fn wf1_by_borrowing_inv<T>(
2796 spec: TempPred<T>,
2797 next: ActionPred<T>,
2798 forward: ActionPred<T>,
2799 p: StatePred<T>,
2800 q: StatePred<T>,
2801 inv: StatePred<T>,
2802)
2803 requires
2804 forall|s, s_prime: T|
2805 p.apply(s) && inv.apply(s) && #[trigger] next.apply(s, s_prime) ==> p.apply(s_prime)
2806 || q.apply(s_prime),
2807 forall|s, s_prime: T|
2808 p.apply(s) && inv.apply(s) && #[trigger] next.apply(s, s_prime) && forward.apply(
2809 s,
2810 s_prime,
2811 ) ==> q.apply(s_prime),
2812 forall|s: T| #[trigger] p.apply(s) && inv.apply(s) ==> enabled(forward).apply(s),
2813 spec.entails(always(lift_action(next))),
2814 spec.entails(always(lift_state(inv))),
2815 spec.entails(weak_fairness(forward)),
2816 ensures
2817 spec.entails(lift_state(p).leads_to(lift_state(q))),
2818{
2819 broadcast use group_tla_rules;
2820
2821 let next_and_inv = lift_action(next).and(lift_state(inv));
2822
2823 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies always(
2824 lift_state(p).and(lift_state(inv)),
2825 ).leads_to(lift_action(forward)).satisfied_by(ex) by {
2826 assert forall|i| #[trigger]
2827 always(lift_state(p).and(lift_state(inv))).satisfied_by(
2828 ex.suffix(i),
2829 ) implies eventually(lift_action(forward)).satisfied_by(ex.suffix(i)) by {
2830 implies_apply_with_always::<T>(
2831 ex.suffix(i),
2832 lift_state(p).and(lift_state(inv)),
2833 lift_state(enabled(forward)),
2834 );
2835 assert(ex.suffix(i).suffix(0) == ex.suffix(i));
2836 implies_apply::<T>(ex, spec, weak_fairness(forward));
2837 weak_fairness_unfold::<T>(ex, forward);
2838 implies_apply::<T>(
2839 ex.suffix(i),
2840 lift_state(enabled(forward)),
2841 eventually(lift_action(forward)),
2842 );
2843 };
2844 };
2845 entails_always_and_n!(spec, lift_action(next), lift_state(inv));
2846 always_and_equality(lift_state(p), lift_state(inv));
2847 always_double_equality(lift_state(inv));
2848 leads_to_by_borrowing_inv(
2849 spec,
2850 always(lift_state(p)),
2851 lift_action(forward),
2852 always(lift_state(inv)),
2853 );
2854 wf1_variant_temp::<T>(spec, next_and_inv, lift_action(forward), lift_state(p), lift_state(q));
2855}
2856
2857pub proof fn strengthen_next<T>(
2866 spec: TempPred<T>,
2867 next: ActionPred<T>,
2868 inv: StatePred<T>,
2869 next_and_inv: ActionPred<T>,
2870)
2871 requires
2872 spec.entails(always(lift_action(next))),
2873 spec.entails(always(lift_state(inv))),
2874 lift_action(next_and_inv).entails(lift_action(next).and(lift_state(inv))),
2875 lift_action(next).and(lift_state(inv)).entails(lift_action(next_and_inv)),
2876 ensures
2877 spec.entails(always(lift_action(next_and_inv))),
2878{
2879 entails_and_temp::<T>(spec, always(lift_action(next)), always(lift_state(inv)));
2880 always_and_equality::<T>(lift_action(next), lift_state(inv));
2881 temp_pred_equality::<T>(lift_action(next_and_inv), lift_action(next).and(lift_state(inv)));
2882}
2883
2884#[macro_export]
2886macro_rules! leads_to_trans_n {
2887 [$($tail:tt)*] => {
2888 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::leads_to_trans_n_internal!($($tail)*));
2889 };
2890}
2891
2892#[macro_export]
2893macro_rules! leads_to_trans_n_internal {
2894 ($spec:expr, $p1:expr, $p2:expr, $p3:expr $(,)?) => {
2895 leads_to_trans($spec, $p1, $p2, $p3);
2896 };
2897 ($spec:expr, $p1:expr, $p2:expr, $p3:expr, $($tail:tt)*) => {
2898 leads_to_trans($spec, $p1, $p2, $p3);
2899 leads_to_trans_n_internal!($spec, $p1, $p3, $($tail)*);
2900 };
2901}
2902
2903pub use leads_to_trans_n;
2904pub use leads_to_trans_n_internal;
2905
2906#[macro_export]
2911macro_rules! state_pred_and {
2912 ($p1:expr $(,)?) => {
2913 $p1
2914 };
2915 ($p1:expr, $p2:expr $(,)?) => {
2916 $p1.and($p2)
2917 };
2918 ($p1:expr, $p2:expr, $($tail:expr),+ $(,)?) => {
2919 {
2920 let tmp = $p1.and($p2);
2921 $( let tmp = tmp.and($tail); )*
2922 tmp
2923 }
2924 };
2925}
2926
2927pub use state_pred_and;
2928
2929#[macro_export]
2934macro_rules! temp_pred_and {
2935 [$($tail:tt)*] => {
2936 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::temp_pred_and_internal!($($tail)*))
2937 }
2938}
2939
2940#[macro_export]
2941macro_rules! temp_pred_and_internal {
2942 ($next:expr) => {
2943 $next
2944 };
2945 ($next:expr, $($expr:expr),* $(,)?) => {
2946 $next $(
2947 .and($expr)
2948 )*
2949 };
2950}
2951
2952pub use temp_pred_and;
2953pub use temp_pred_and_internal;
2954
2955#[macro_export]
2966macro_rules! entails_and_n {
2967 [$($tail:tt)*] => {
2968 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::entails_and_n_internal!($($tail)*));
2969 };
2970}
2971
2972#[macro_export]
2973macro_rules! entails_and_n_internal {
2974 ($spec:expr, $p1:expr, $p2:expr $(,)?) => {
2975 entails_and_temp($spec, $p1, $p2);
2976 };
2977 ($spec:expr, $p1:expr, $p2:expr, $($tail:tt)*) => {
2978 entails_and_temp($spec, $p1, $p2);
2979 entails_and_n_internal!($spec, $p1.and($p2), $($tail)*);
2980 };
2981}
2982
2983pub use entails_and_n;
2984pub use entails_and_n_internal;
2985
2986#[macro_export]
2997macro_rules! entails_always_and_n {
2998 [$($tail:tt)*] => {
2999 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::entails_always_and_n_internal!($($tail)*));
3000 };
3001}
3002
3003#[macro_export]
3004macro_rules! entails_always_and_n_internal {
3005 ($spec:expr, $p1:expr $(,)?) => {};
3006 ($spec:expr, $p1:expr, $p2:expr $(,)?) => {
3007 entails_and_temp($spec, always($p1), always($p2));
3008 always_and_equality($p1, $p2);
3009 };
3010 ($spec:expr, $p1:expr, $p2:expr, $($tail:tt)*) => {
3011 entails_and_temp($spec, always($p1), always($p2));
3012 always_and_equality($p1, $p2);
3013 entails_always_and_n_internal!($spec, $p1.and($p2), $($tail)*);
3014 };
3015}
3016
3017pub use entails_always_and_n;
3018pub use entails_always_and_n_internal;
3019
3020#[macro_export]
3021macro_rules! always_and_equality_n {
3022 [$($tail:tt)*] => {
3023 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::always_and_equality_n_internal!($($tail)*));
3024 };
3025}
3026
3027#[macro_export]
3028macro_rules! always_and_equality_n_internal {
3029 ($p1:expr, $p2:expr $(,)?) => {
3030 always_and_equality($p1, $p2);
3031 };
3032 ($p1:expr, $p2:expr, $($tail:tt)*) => {
3033 always_and_equality($p1, $p2);
3034 always_and_equality_n_internal!($p1.and($p2), $($tail)*);
3035 };
3036}
3037
3038pub use always_and_equality_n;
3039pub use always_and_equality_n_internal;
3040
3041#[macro_export]
3043macro_rules! always_lift_state_and_equality_n {
3044 [$($tail:tt)*] => {
3045 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::always_lift_state_and_equality_n_internal!($($tail)*));
3046 };
3047}
3048
3049#[macro_export]
3050macro_rules! always_lift_state_and_equality_n_internal {
3051 ($p1:expr, $p2:expr $(,)?) => {
3052 always_lift_state_and_equality($p1, $p2);
3053 };
3054 ($p1:expr, $p2:expr, $($tail:tt)*) => {
3055 always_lift_state_and_equality($p1, $p2);
3056 always_lift_state_and_equality_n_internal!(state_pred_and!($p1, $p2), $($tail)*);
3057 };
3058}
3059
3060pub use always_lift_state_and_equality_n;
3061pub use always_lift_state_and_equality_n_internal;
3062
3063#[macro_export]
3074macro_rules! or_leads_to_combine_n {
3075 [$($tail:tt)*] => {
3076 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::or_leads_to_combine_n_internal!($($tail)*));
3077 };
3078}
3079
3080#[macro_export]
3081macro_rules! or_leads_to_combine_n_internal {
3082 ($spec:expr, $p1:expr, $p2:expr; $q:expr) => {
3083 or_leads_to_combine($spec, $p1, $p2, $q);
3084 };
3085 ($spec:expr, $p1:expr, $p2:expr, $($rest:expr),+; $q:expr) => {
3086 or_leads_to_combine($spec, $p1, $p2, $q);
3087 or_leads_to_combine_n_internal!($spec, $p1.or($p2), $($rest),+; $q);
3088 };
3089}
3090
3091pub use or_leads_to_combine_n;
3092pub use or_leads_to_combine_n_internal;
3093
3094#[macro_export]
3097macro_rules! or_leads_to_combine_and_equality2 {
3098 ($spec:expr, $result:expr, $p1:expr, $($rest:expr),+; $q:expr) => {
3099 temp_pred_equality(
3100 $result,
3101 $p1$(.or($rest))+
3102 );
3103 or_leads_to_combine_n!($spec, $p1, $($rest),+; $q);
3104 }
3105}
3106
3107pub use or_leads_to_combine_and_equality2;
3108
3109#[macro_export]
3120macro_rules! leads_to_always_combine_n {
3121 [$($tail:tt)*] => {
3122 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::leads_to_always_combine_n_internal!($($tail)*));
3123 };
3124}
3125
3126#[macro_export]
3127macro_rules! leads_to_always_combine_n_internal {
3128 ($spec:expr, $p:expr, $q1:expr, $q2:expr $(,)?) => {
3129 leads_to_always_combine($spec, $p, $q1, $q2);
3130 };
3131 ($spec:expr, $p:expr, $q1:expr, $q2:expr, $($tail:tt)*) => {
3132 leads_to_always_combine($spec, $p, $q1, $q2);
3133 always_and_equality($q1, $q2);
3134 leads_to_always_combine_n_internal!($spec, $p, $q1.and($q2), $($tail)*);
3135 };
3136}
3137
3138pub use leads_to_always_combine_n;
3139pub use leads_to_always_combine_n_internal;
3140
3141#[macro_export]
3142macro_rules! leads_to_always_combine_n_with_equality {
3143 [$($tail:tt)*] => {
3144 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::leads_to_always_combine_n_with_equality_internal!($($tail)*));
3145 };
3146}
3147
3148#[macro_export]
3149macro_rules! leads_to_always_combine_n_with_equality_internal {
3150 ($spec:expr, $p:expr, $dst:expr, $($tail:tt)*) => {
3151 temp_pred_equality($dst, combine_with_next!($($tail)*));
3152 leads_to_always_combine_n!($spec, $p, $($tail)*);
3153 };
3154}
3155
3156pub use leads_to_always_combine_n_with_equality;
3157pub use leads_to_always_combine_n_with_equality_internal;
3158
3159#[macro_export]
3171macro_rules! combine_spec_entails_always_n {
3172 [$($tail:tt)*] => {
3173 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::combine_spec_entails_always_n_internal!($($tail)*))
3174 }
3175}
3176
3177#[macro_export]
3178macro_rules! combine_spec_entails_always_n_internal {
3179 ($spec:expr, $partial_spec:expr, $($tail:tt)*) => {
3180 assert_by(
3181 valid($spec.implies(always(temp_pred_and!($($tail)*)))),
3182 {
3183 entails_always_and_n!($spec, $($tail)*);
3184 }
3185 );
3186 entails_preserved_by_always(temp_pred_and!($($tail)*), $partial_spec);
3187 entails_trans($spec, always(temp_pred_and!($($tail)*)), always($partial_spec));
3188 };
3189}
3190
3191pub use combine_spec_entails_always_n;
3192pub use combine_spec_entails_always_n_internal;
3193
3194#[macro_export]
3205macro_rules! entails_always_lift_state_and_n {
3206 [$($tail:tt)*] => {
3207 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::entails_always_lift_state_and_n_internal!($($tail)*))
3208 };
3209}
3210
3211#[macro_export]
3212macro_rules! entails_always_lift_state_and_n_internal {
3213 ($spec:expr, $p1:expr) => {
3214 };
3216 ($spec:expr, $p1:expr, $p2:expr $(,)?) => {
3217 entails_always_lift_state_and($spec, $p1, $p2);
3219 };
3220 ($spec:expr, $p1:expr, $p2:expr, $p3:expr $(,)?) => {
3221 entails_always_lift_state_and($spec, $p1, $p2);
3223 let combined_p1_p2 = state_pred_and!($p1, $p2);
3224 entails_always_lift_state_and($spec, combined_p1_p2, $p3);
3225 };
3226 ($spec:expr, $p1:expr, $p2:expr, $($tail:expr),+ $(,)?) => {
3227 entails_always_lift_state_and($spec, $p1, $p2);
3229 let combined_p1_p2 = state_pred_and!($p1, $p2);
3230 entails_always_lift_state_and_n_internal!($spec, combined_p1_p2, $($tail),+);
3231 };
3232}
3233
3234pub use entails_always_lift_state_and_n;
3235pub use entails_always_lift_state_and_n_internal;
3236
3237#[macro_export]
3250macro_rules! invariant_n {
3251 [$($tail:tt)*] => {
3252 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::invariant_n_internal!($($tail)*))
3253 }
3254}
3255
3256#[macro_export]
3257macro_rules! invariant_n_internal {
3258 ($spec:expr, $partial_spec:expr, $inv:expr, $($tail:tt)*) => {
3259 assert_by(
3260 valid($spec.implies(always(temp_pred_and!($($tail)*)))),
3261 {
3262 entails_always_and_n!($spec, $($tail)*);
3263 }
3264 );
3265 entails_preserved_by_always(temp_pred_and!($($tail)*), $partial_spec);
3266 entails_trans($spec, always(temp_pred_and!($($tail)*)), always($partial_spec));
3267 entails_preserved_by_always($partial_spec, $inv);
3268 entails_trans($spec, always($partial_spec), always($inv));
3269 };
3270}
3271
3272pub use invariant_n;
3273pub use invariant_n_internal;
3274
3275#[macro_export]
3286macro_rules! stable_and_n {
3287 [$($tail:tt)*] => {
3288 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::stable_and_n_internal!($($tail)*));
3289 };
3290}
3291
3292#[macro_export]
3293macro_rules! stable_and_n_internal {
3294 ($p1:expr, $p2:expr $(,)?) => {
3295 stable_and_temp($p1, $p2);
3296 };
3297 ($p1:expr, $p2:expr, $($tail:tt)*) => {
3298 stable_and_temp($p1, $p2);
3299 stable_and_n_internal!($p1.and($p2), $($tail)*);
3300 };
3301}
3302
3303pub use stable_and_n;
3304pub use stable_and_n_internal;
3305
3306#[macro_export]
3312macro_rules! stable_and_always_n {
3313 [$($tail:tt)*] => {
3314 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::stable_and_always_n_internal!($($tail)*));
3315 };
3316}
3317
3318#[macro_export]
3319macro_rules! stable_and_always_n_internal {
3320 ($p1:expr, $($tail:expr),* $(,)?) => {
3321 always_p_is_stable($p1);
3322 $(always_p_is_stable($tail);)*
3323 stable_and_n!(always($p1), $(always($tail)),*);
3324 };
3325}
3326
3327pub use stable_and_always_n;
3328pub use stable_and_always_n_internal;
3329
3330#[macro_export]
3345macro_rules! implies_new_invariant_n {
3346 [$($tail:tt)*] => {
3347 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::implies_new_invariant_n_internal!($($tail)*))
3348 };
3349}
3350
3351#[macro_export]
3352macro_rules! implies_new_invariant_n_internal {
3353 ($spec:expr, $init:expr, $next:expr, $inv:expr, $p1:expr) => {
3354 implies_new_invariant($spec, $init, $next, $inv, $p1);
3355 };
3356 ($spec:expr, $init:expr, $next:expr, $inv:expr, $p1:expr,) => {
3357 implies_new_invariant_n_internal!($spec, $init, $next, $inv, $p1);
3358 };
3359 ($spec:expr, $init:expr, $next:expr, $inv:expr, $($preds:expr),+) => {
3360 {
3361 let combined_pred = state_pred_and!($($preds),+);
3362 entails_always_lift_state_and_n!($spec, $($preds),+);
3363 implies_new_invariant($spec, $init, $next, $inv, combined_pred);
3364 }
3365 };
3366 ($spec:expr, $init:expr, $next:expr, $inv:expr, $($preds:expr),+ ,) => {
3367 implies_new_invariant_n_internal!($spec, $init, $next, $inv, $($preds),+);
3368 };
3369}
3370
3371pub use implies_new_invariant_n;
3372pub use implies_new_invariant_n_internal;
3373
3374#[macro_export]
3389macro_rules! wf1_by_borrowing_inv_n {
3390 ($spec:expr, $next:expr, $forward:expr, $p:expr, $q:expr, $($inv:expr),+ $(,)?) => {{
3391 entails_always_lift_state_and_n!($spec, $($inv),+);
3392 let combined_inv = state_pred_and!($($inv),+);
3394 wf1_by_borrowing_inv($spec, $next, $forward, $p, $q, combined_inv)
3396 }};
3397}
3398
3399pub use wf1_by_borrowing_inv_n;
3400
3401#[macro_export]
3413macro_rules! always_lift_state_weaken_n {
3414 [$($tail:tt)*] => {
3415 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::always_lift_state_weaken_n_internal!($($tail)*))
3416 };
3417}
3418
3419#[macro_export]
3420macro_rules! always_lift_state_weaken_n_internal {
3421 ($spec:expr, $p1:expr, $h:expr) => {
3422 always_lift_state_weaken($spec, $p1, $h);
3423 };
3424 ($spec:expr, $p1:expr, $p2:expr, $h:expr) => {
3425 entails_always_lift_state_and_n!($spec, $p1, $p2);
3426 always_lift_state_weaken($spec, state_pred_and!($p1, $p2), $h);
3427 };
3428 ($spec:expr, $p1:expr, $p2:expr, $h:expr,) => {
3429 always_lift_state_weaken_n_internal!($spec, $p1, $p2, $h);
3430 };
3431 ($spec:expr, $p1:expr, $p2:expr, $($tail:expr),+ , $h:expr) => {
3432 entails_always_lift_state_and_n!($spec, $p1, $p2, $($tail),+);
3433 always_lift_state_weaken($spec, state_pred_and!($p1, $p2, $($tail),+), $h);
3434 };
3435 ($spec:expr, $p1:expr, $p2:expr, $($tail:expr),+ , $h:expr,) => {
3436 always_lift_state_weaken_n_internal!($spec, $p1, $p2, $($tail),+ , $h);
3437 };
3438}
3439
3440pub use always_lift_state_weaken_n;
3441pub use always_lift_state_weaken_n_internal;
3442
3443pub broadcast group group_tla_rules {
3444 state_pred_and_apply_equality,
3445 state_pred_or_apply_equality,
3446 state_pred_implies_apply_equality,
3447 state_pred_not_apply_equality,
3448 lift_state_and_equality,
3449 lift_state_or_equality,
3450 lift_state_not_equality,
3451 lift_state_implies_equality,
3452 entails_and_temp,
3453 entails_and_temp_reverse,
3454 entails_or_temp,
3455 entails_not_temp_reverse,
3456 entails_implies_temp_reverse,
3457 always_lift_state_and_equality,
3458 always_implies_to_leads_to,
3459 always_to_always_later,
3460 always_double_equality,
3461 always_and_equality,
3462 tla_forall_apply,
3463 spec_entails_tla_forall, always_implies_forall_intro, tla_exists_leads_to_intro, leads_to_self_temp,
3467 entails_and_different_temp,
3468 always_p_is_stable,
3469 stable_and_temp,
3470 entails_preserved_by_always,
3471 leads_to_apply, or_leads_to_combine,
3473 leads_to_always_combine,
3474 leads_to_framed_by_or,
3475 lift_state_exists_equality,
3476 implies_tla_exists_intro,
3477 leads_to_tla_exists_intro,
3478 state_exists_intro, entails_always_lift_state_and, entails_always_lift_state_and_elim,
3481 entails_tla_exists_by_witness, lift_state_exists_leads_to_intro,
3483 lift_state_exists_absorb_equality,
3484 lift_state_forall_absorb_equality,
3485 lift_state_not_equality,
3486}
3487
3488}