1#![allow(unused_imports)]
4use super::defs::*;
5use vstd::map_lib::*;
6use vstd::prelude::*;
7
8verus! {
10
11broadcast proof fn lemma_execution_suffix_0<T>(ex: Execution<T>)
12 ensures
13 #[trigger] ex.suffix(0) == ex,
14{
15}
16
17broadcast proof fn lemma_execution_suffix_suffix<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_suffix_0,
25 lemma_execution_suffix_suffix,
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 ISet::<A>::full() != ISet::<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| ISet::<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.len() > 0,
1993 forall|a: A| #[trigger] domain.contains(a),
1994 ensures
1995 spec.entails(p.leads_to(always(tla_forall(a_to_temp_pred)))),
1996{
1997 broadcast use {always_unfold, always_propagate_forwards, group_definition_basics};
1998
1999 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(
2000 always(tla_forall(a_to_temp_pred)),
2001 ).satisfied_by(ex) by {
2002 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(
2003 always(tla_forall(a_to_temp_pred)),
2004 ).satisfied_by(ex.suffix(i)) by {
2005 assert forall|a: A|
2006 p.leads_to(always(#[trigger] a_to_temp_pred(a))).satisfied_by(ex) by {
2007 implies_apply::<T>(ex, spec, p.leads_to(always(a_to_temp_pred(a))));
2008 }
2009 assert forall|a: A|
2010 eventually(always(#[trigger] a_to_temp_pred(a))).satisfied_by(ex.suffix(i)) by {
2011 implies_apply::<T>(ex.suffix(i), p, eventually(always(a_to_temp_pred(a))));
2012 }
2013
2014 let a_to_witness = Map::new(
2015 domain,
2016 |a: A|
2017 {
2018 let wit = eventually_choose_witness::<T>(
2019 ex.suffix(i),
2020 always(a_to_temp_pred(a)),
2021 );
2022 wit
2023 },
2024 );
2025 assert(a_to_witness.dom() == domain);
2026 let r = |a1: nat, a2: nat| a1 <= a2;
2027 let values = a_to_witness.values();
2028 assert_by(
2029 values.len() > 0,
2030 {
2031 let x = a_to_witness.dom().choose();
2032 assert(values.contains(a_to_witness[x]));
2033 },
2034 );
2035 let max_witness = values.find_unique_maximal(r);
2036 values.find_unique_maximal_ensures(r);
2037 values.lemma_maximal_equivalent_greatest(r, max_witness);
2038
2039 assert forall|a: A|
2040 always(#[trigger] a_to_temp_pred(a)).satisfied_by(
2041 ex.suffix(i).suffix(max_witness),
2042 ) by {
2043 let witness = a_to_witness[a];
2044 assert(values.contains(witness));
2045 assert(r(witness, max_witness));
2046 assert(ex.suffix(i).suffix(max_witness) == ex.suffix(i).suffix(witness).suffix(
2047 (max_witness - witness) as nat,
2048 ));
2049 }
2050 eventually_proved_by_witness(
2051 ex.suffix(i),
2052 always(tla_forall(a_to_temp_pred)),
2053 max_witness,
2054 );
2055 };
2056 };
2057}
2058
2059pub broadcast proof fn always_p_is_stable<T>(p: TempPred<T>)
2065 ensures
2066 #[trigger] valid(stable(always(p))),
2067{
2068 broadcast use {always_unfold, always_propagate_forwards};
2069
2070}
2071
2072pub proof fn p_leads_to_q_is_stable<T>(p: TempPred<T>, q: TempPred<T>)
2077 ensures
2078 valid(stable(p.leads_to(q))),
2079{
2080 always_p_is_stable(p.implies(eventually(q)));
2081}
2082
2083pub broadcast proof fn stable_and_temp<T>(p: TempPred<T>, q: TempPred<T>)
2091 requires
2092 valid(stable(p)),
2093 valid(stable(q)),
2094 ensures
2095 #[trigger] valid(stable(p.and(q))),
2096{
2097 assert forall|ex| #[trigger] p.and(q).satisfied_by(ex) implies always(p.and(q)).satisfied_by(
2098 ex,
2099 ) by {
2100 stable_unfold::<T>(ex, p);
2101 stable_unfold::<T>(ex, q);
2102 }
2103}
2104
2105pub proof fn tla_forall_a_p_leads_to_q_a_is_stable<T, A>(
2113 p: TempPred<T>,
2114 a_to_temp_pred: spec_fn(A) -> TempPred<T>,
2115)
2116 requires
2117 forall|a: A| #[trigger] valid(stable(p.leads_to(a_to_temp_pred(a)))),
2118 ensures
2119 valid(stable(tla_forall(|a: A| p.leads_to(a_to_temp_pred(a))))),
2120{
2121 broadcast use group_definition_basics;
2122
2123 let target = tla_forall(|a: A| p.leads_to(a_to_temp_pred(a)));
2124 assert forall|ex|
2125 (forall|a: A| #[trigger]
2126 valid(stable(p.leads_to(a_to_temp_pred(a))))) implies #[trigger] stable(
2127 target,
2128 ).satisfied_by(ex) by {
2129 assert forall|i|
2130 (forall|a: A| #[trigger] valid(stable(p.leads_to(a_to_temp_pred(a)))))
2131 && target.satisfied_by(ex) implies #[trigger] target.satisfied_by(ex.suffix(i)) by {
2132 assert forall|a: A|
2133 p.leads_to(a_to_temp_pred(a)).satisfied_by(ex) implies #[trigger] p.leads_to(
2134 a_to_temp_pred(a),
2135 ).satisfied_by(ex.suffix(i)) by {
2136 assert(valid(stable(p.leads_to(a_to_temp_pred(a)))));
2137 assert(stable(p.leads_to(a_to_temp_pred(a))).satisfied_by(ex));
2138 if p.leads_to(a_to_temp_pred(a)).satisfied_by(ex) {
2139 }
2140 }
2141 }
2142 }
2143}
2144
2145pub proof fn unpack_conditions_from_spec<T>(
2153 spec: TempPred<T>,
2154 c: TempPred<T>,
2155 p: TempPred<T>,
2156 q: TempPred<T>,
2157)
2158 requires
2159 valid(stable(spec)),
2160 spec.and(c).entails(p.leads_to(q)),
2161 ensures
2162 spec.entails(p.and(c).leads_to(q)),
2163{
2164 broadcast use {always_unfold, implies_apply, group_definition_basics};
2165
2166 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.and(c).leads_to(q).satisfied_by(
2167 ex,
2168 ) by {
2169 assert forall|i| #[trigger] p.and(c).satisfied_by(ex.suffix(i)) implies eventually(
2170 q,
2171 ).satisfied_by(ex.suffix(i)) by {
2172 stable_unfold::<T>(ex, spec);
2173 implies_apply::<T>(ex.suffix(i), spec.and(c), p.leads_to(q));
2174 assert(ex.suffix(i) == ex.suffix(i).suffix(0));
2175 implies_apply::<T>(ex.suffix(i), p, eventually(q));
2176 };
2177 };
2178}
2179
2180pub proof fn pack_conditions_to_spec<T>(
2188 spec: TempPred<T>,
2189 c: TempPred<T>,
2190 p: TempPred<T>,
2191 q: TempPred<T>,
2192)
2193 requires
2194 spec.entails(p.and(c).leads_to(q)),
2195 ensures
2196 spec.and(always(c)).entails(p.leads_to(q)),
2197{
2198 broadcast use {always_unfold, always_propagate_forwards};
2199
2200 assert forall|ex| #[trigger] spec.and(always(c)).satisfied_by(ex) implies p.leads_to(
2201 q,
2202 ).satisfied_by(ex) by {
2203 implies_apply(ex, spec, p.and(c).leads_to(q));
2204 leads_to_unfold(ex, p.and(c), q);
2205
2206 }
2207}
2208
2209pub proof fn entails_and_equality<T>(p: TempPred<T>, q: TempPred<T>)
2220 requires
2221 p.entails(q),
2222 ensures
2223 p == p.and(q),
2224{
2225 assert forall|ex| #[trigger] p.satisfied_by(ex) implies p.and(q).satisfied_by(ex) by {
2226 entails_and_temp::<T>(p, p, q);
2227 entails_apply::<T>(ex, p, p.and(q));
2228 };
2229 temp_pred_equality::<T>(p, p.and(q));
2230}
2231
2232pub proof fn entails_trans_by_simplify<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>)
2240 requires
2241 spec.entails(p),
2242 spec.and(p).entails(q),
2243 ensures
2244 spec.entails(q),
2245{
2246 entails_and_equality(spec, p);
2247}
2248
2249pub proof fn leads_to_by_borrowing_inv<T>(
2258 spec: TempPred<T>,
2259 p: TempPred<T>,
2260 q: TempPred<T>,
2261 inv: TempPred<T>,
2262)
2263 requires
2264 spec.entails(p.and(inv).leads_to(q)),
2265 spec.entails(always(inv)),
2266 ensures
2267 spec.entails(p.leads_to(q)),
2268{
2269 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(q).satisfied_by(ex) by {
2270 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(q).satisfied_by(
2271 ex.suffix(i),
2272 ) by {
2273 instantiate_entailed_always(ex, i, spec, inv);
2274 instantiate_entailed_leads_to(ex, i, spec, p.and(inv), q);
2275 }
2276 }
2277}
2278
2279pub proof fn leads_to_always_enhance<T>(
2288 spec: TempPred<T>,
2289 inv: TempPred<T>,
2290 p: TempPred<T>,
2291 q1: TempPred<T>,
2292 q2: TempPred<T>,
2293)
2294 requires
2295 spec.entails(always(inv)),
2296 spec.entails(p.leads_to(always(q1))),
2297 q1.and(inv).entails(q2),
2298 ensures
2299 spec.entails(p.leads_to(always(q2))),
2300{
2301 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(always(q2)).satisfied_by(
2302 ex,
2303 ) by {
2304 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(
2305 always(q2),
2306 ).satisfied_by(ex.suffix(i)) by {
2307 implies_apply(ex, spec, always(inv));
2308 implies_apply(ex, spec, p.leads_to(always(q1)));
2309 leads_to_unfold(ex, p, always(q1));
2310 implies_apply(ex.suffix(i), p, eventually(always(q1)));
2311 let witness = eventually_choose_witness(ex.suffix(i), always(q1));
2312 assert forall|j| #[trigger] q2.satisfied_by(ex.suffix(i).suffix(witness).suffix(j)) by {
2313 assert(ex.suffix(i).suffix(witness).suffix(j) == ex.suffix(i + witness + j));
2314 implies_apply(ex.suffix(i).suffix(witness).suffix(j), q1.and(inv), q2);
2315 }
2316 eventually_proved_by_witness(ex.suffix(i), always(q2), witness);
2317 }
2318 }
2319}
2320
2321pub proof fn leads_to_weaken<T>(
2330 spec: TempPred<T>,
2331 p1: TempPred<T>,
2332 q1: TempPred<T>,
2333 p2: TempPred<T>,
2334 q2: TempPred<T>,
2335)
2336 requires
2337 spec.entails(always(p2.implies(p1))),
2338 spec.entails(always(q1.implies(q2))),
2339 spec.entails(p1.leads_to(q1)),
2340 ensures
2341 spec.entails(p2.leads_to(q2)),
2342{
2343 always_implies_to_leads_to::<T>(spec, p2, p1);
2344 always_implies_to_leads_to::<T>(spec, q1, q2);
2345 leads_to_trans::<T>(spec, p2, p1, q1);
2346 leads_to_trans::<T>(spec, p2, q1, q2);
2347}
2348
2349pub proof fn vacuous_leads_to<T>(spec: TempPred<T>, p: TempPred<T>, q: TempPred<T>, r: TempPred<T>)
2357 requires
2358 spec.entails(always(r)),
2359 p.and(r) == false_pred::<T>(),
2360 ensures
2361 spec.entails(p.leads_to(q)),
2362{
2363 broadcast use {always_unfold, implies_apply, group_execution_suffix_lemmas};
2364
2365 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(q).satisfied_by(ex) by {
2366 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(q).satisfied_by(
2367 ex.suffix(i),
2368 ) by {
2369 assert_by(
2370 !p.satisfied_by(ex.suffix(i)),
2371 {
2372 implies_apply::<T>(ex, spec, always(r));
2373 if p.satisfied_by(ex.suffix(i)) {
2374 assert(p.and(r).satisfied_by(ex.suffix(i)));
2375 }
2376 },
2377 );
2378 }
2379 }
2380}
2381
2382pub proof fn strengthen_leads_to_with_until<T>(
2398 spec: TempPred<T>,
2399 next: TempPred<T>,
2400 p: TempPred<T>,
2401 q: TempPred<T>,
2402)
2403 requires
2404 spec.entails(always(p).leads_to(q)),
2405 spec.entails(always(p.and(next).implies(later(p).or(later(q))))),
2406 spec.entails(always(next)),
2407 ensures
2408 spec.entails(p.leads_to(q)),
2409{
2410 broadcast use {
2411 always_unfold,
2412 implies_apply,
2413 group_execution_suffix_lemmas,
2414 group_definition_basics,
2415 };
2416
2417 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(q).satisfied_by(ex) by {
2418 implies_apply(ex, spec, always(next));
2419 implies_apply(ex, spec, always(p.and(next).implies(later(p).or(later(q)))));
2420 always_p_or_eventually_q(ex, next, p, q);
2421 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(q).satisfied_by(
2422 ex.suffix(i),
2423 ) by {
2424 if always(p).satisfied_by(ex.suffix(i)) {
2425 implies_apply(ex, spec, always(p).leads_to(q));
2426 }
2427 }
2428 }
2429}
2430
2431pub proof fn transform_leads_to_with_until<T>(
2456 spec: TempPred<T>,
2457 next: TempPred<T>,
2458 p1: TempPred<T>,
2459 q1: TempPred<T>,
2460 p2: TempPred<T>,
2461 q2: TempPred<T>,
2462)
2463 requires
2464 spec.entails(p1.leads_to(q1)),
2465 spec.entails(always(p2.and(next).implies(later(p2).or(later(q2))))),
2466 spec.entails(always(next)),
2467 ensures
2468 spec.entails(p1.and(p2).leads_to((q1.and(p2)).or(q2))),
2469{
2470 broadcast use {
2471 always_unfold,
2472 implies_apply,
2473 group_execution_suffix_lemmas,
2474 group_definition_basics,
2475 };
2476
2477 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p1.and(p2).leads_to(
2478 (q1.and(p2)).or(q2),
2479 ).satisfied_by(ex) by {
2480 assert forall|i| #[trigger] p1.and(p2).satisfied_by(ex.suffix(i)) implies eventually(
2481 (q1.and(p2)).or(q2),
2482 ).satisfied_by(ex.suffix(i)) by {
2483 implies_apply::<T>(ex, spec, always(next));
2484 implies_apply::<T>(ex, spec, always(p2.and(next).implies(later(p2).or(later(q2)))));
2485
2486 always_p_or_eventually_q::<T>(ex, next, p2, q2);
2487
2488 implies_apply::<T>(ex, spec, p1.leads_to(q1));
2489
2490 if eventually(q2).satisfied_by(ex.suffix(i)) {
2491 let witness_idx = eventually_choose_witness::<T>(ex.suffix(i), q2);
2492 eventually_proved_by_witness::<T>(ex.suffix(i), (q1.and(p2)).or(q2), witness_idx);
2493 } else {
2494 let witness_idx = eventually_choose_witness::<T>(ex.suffix(i), q1);
2495 eventually_proved_by_witness::<T>(ex.suffix(i), (q1.and(p2)).or(q2), witness_idx);
2496 }
2497 }
2498 }
2499}
2500
2501pub proof fn leads_to_rank_step_one<T>(spec: TempPred<T>, p: spec_fn(nat) -> TempPred<T>)
2508 requires
2509 forall|n: nat| #![trigger p(n)] (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as nat)))),
2510 ensures
2511 forall|n: nat| #[trigger] spec.entails(p(n).leads_to(p(0))),
2512{
2513 let pre = {
2514 forall|n: nat| #![trigger p(n)] (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as nat))))
2515 };
2516 assert forall|n: nat| pre implies #[trigger] spec.entails(p(n).leads_to(p(0))) by {
2517 leads_to_rank_step_one_help(spec, p, n);
2518 }
2519}
2520
2521proof fn leads_to_rank_step_one_help<T>(spec: TempPred<T>, p: spec_fn(nat) -> TempPred<T>, n: nat)
2522 requires
2523 forall|n: nat| #![trigger p(n)] (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as nat)))),
2524 ensures
2525 spec.entails(p(n).leads_to(p(0))),
2526 decreases n,
2527{
2528 if n > 0 {
2529 leads_to_rank_step_one_help(spec, p, (n - 1) as nat);
2532 leads_to_trans_n!(spec, p(n), p((n - 1) as nat), p(0));
2533 } else {
2534 leads_to_self_temp(p(0));
2536 }
2537}
2538
2539pub proof fn leads_to_rank_step_one_usize<T>(spec: TempPred<T>, p: spec_fn(usize) -> TempPred<T>)
2541 requires
2542 forall|n: usize|
2543 #![trigger p(n)]
2544 (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as usize)))),
2545 ensures
2546 forall|n: usize| #[trigger] spec.entails(p(n).leads_to(p(0))),
2547{
2548 let pre = {
2549 forall|n: usize|
2550 #![trigger p(n)]
2551 (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as usize))))
2552 };
2553 assert forall|n: usize| pre implies #[trigger] spec.entails(p(n).leads_to(p(0))) by {
2554 leads_to_rank_step_one_usize_help(spec, p, n);
2555 }
2556}
2557
2558proof fn leads_to_rank_step_one_usize_help<T>(
2559 spec: TempPred<T>,
2560 p: spec_fn(usize) -> TempPred<T>,
2561 n: usize,
2562)
2563 requires
2564 forall|n: usize|
2565 #![trigger p(n)]
2566 (n > 0 ==> spec.entails(p(n).leads_to(p((n - 1) as usize)))),
2567 ensures
2568 spec.entails(p(n).leads_to(p(0))),
2569 decreases n,
2570{
2571 if n > 0 {
2572 leads_to_rank_step_one_usize_help(spec, p, (n - 1) as usize);
2575 leads_to_trans_n!(spec, p(n), p((n - 1) as usize), p(0));
2576 } else {
2577 leads_to_self_temp(p(0));
2579 }
2580}
2581
2582pub proof fn init_invariant<T>(
2592 spec: TempPred<T>,
2593 init: StatePred<T>,
2594 next: ActionPred<T>,
2595 inv: StatePred<T>,
2596)
2597 requires
2598 forall|s: T| #[trigger] init.apply(s) ==> inv.apply(s),
2599 forall|s, s_prime: T|
2600 inv.apply(s) && #[trigger] next.apply(s, s_prime) ==> inv.apply(s_prime),
2601 spec.entails(lift_state(init)),
2602 spec.entails(always(lift_action(next))),
2603 ensures
2604 spec.entails(always(lift_state(inv))),
2605{
2606 broadcast use group_tla_rules;
2607
2608 assert forall|ex: Execution<T>| spec.satisfied_by(ex) implies #[trigger] always(
2609 lift_state(inv),
2610 ).satisfied_by(ex) by {
2611 implies_apply(ex, spec, lift_state(init));
2612 implies_apply(ex, spec, always(lift_action(next)));
2613 assert forall|i: nat| inv.apply(#[trigger] ex.suffix(i).head()) by {
2614 init_invariant_rec(ex, init, next, inv, i);
2615 };
2616 };
2617}
2618
2619pub proof fn implies_new_invariant<T>(
2628 spec: TempPred<T>,
2629 init: StatePred<T>,
2630 next: ActionPred<T>,
2631 inv: StatePred<T>,
2632 proved_inv: StatePred<T>,
2633)
2634 requires
2635 forall|s: T| #[trigger] init.apply(s) ==> inv.apply(s),
2636 forall|s, s_prime: T|
2637 inv.apply(s) && proved_inv.apply(s) && #[trigger] next.apply(s, s_prime) ==> inv.apply(
2638 s_prime,
2639 ),
2640 spec.entails(lift_state(init)),
2641 spec.entails(always(lift_action(next))),
2642 spec.entails(always(lift_state(proved_inv))),
2643 ensures
2644 spec.entails(always(lift_state(inv))),
2645{
2646 broadcast use group_tla_rules;
2647
2648 assert forall|ex: Execution<T>| spec.satisfied_by(ex) implies #[trigger] always(
2649 lift_state(inv),
2650 ).satisfied_by(ex) by {
2651 implies_apply(ex, spec, lift_state(init));
2652 implies_apply(ex, spec, always(lift_action(next)));
2653 implies_apply(ex, spec, always(lift_state(proved_inv)));
2654 assert forall|i: nat| inv.apply(#[trigger] ex.suffix(i).head()) by {
2655 implies_new_invariant_rec(ex, init, next, inv, proved_inv, i);
2656 };
2657 };
2658}
2659
2660pub proof fn wf1_variant_temp<T>(
2670 spec: TempPred<T>,
2671 next: TempPred<T>,
2672 forward: TempPred<T>,
2673 p: TempPred<T>,
2674 q: TempPred<T>,
2675)
2676 requires
2677 spec.entails(always(p.and(next).implies(later(p).or(later(q))))),
2678 spec.entails(always(p.and(next).and(forward).implies(later(q)))),
2679 spec.entails(always(next)),
2680 spec.entails(always(p).leads_to(forward)),
2681 ensures
2682 spec.entails(p.leads_to(q)),
2683{
2684 broadcast use group_tla_rules;
2685
2686 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies p.leads_to(q).satisfied_by(ex) by {
2687 assert forall|i| #[trigger] p.satisfied_by(ex.suffix(i)) implies eventually(q).satisfied_by(
2688 ex.suffix(i),
2689 ) by {
2690 implies_apply::<T>(ex, spec, always(next));
2691 implies_apply::<T>(ex, spec, always(p.and(next).implies(later(p).or(later(q)))));
2692 implies_apply::<T>(ex, spec, always(p.and(next).and(forward).implies(later(q))));
2693
2694 always_p_or_eventually_q::<T>(ex, next, p, q);
2695 implies_apply::<T>(ex.suffix(i), p, always(p).or(eventually(q)));
2696 if always(p).satisfied_by(ex.suffix(i)) {
2697 implies_apply::<T>(ex, spec, always(p).leads_to(forward));
2698 leads_to_unfold::<T>(ex, always(p), forward);
2699 implies_apply::<T>(ex.suffix(i), always(p), eventually(forward));
2700 let witness_idx = eventually_choose_witness::<T>(ex.suffix(i), forward);
2701
2702 always_propagate_forwards::<T>(ex, next, i);
2703 always_propagate_forwards::<T>(ex, p.and(next).and(forward).implies(later(q)), i);
2704 implies_apply::<T>(
2705 ex.suffix(i).suffix(witness_idx),
2706 p.and(next).and(forward),
2707 later(q),
2708 );
2709 assert(ex.suffix(i).suffix(witness_idx).suffix(1) == ex.suffix(i).suffix(
2710 witness_idx + 1,
2711 ));
2712 eventually_proved_by_witness::<T>(ex.suffix(i), q, witness_idx + 1);
2713 }
2714 }
2715 }
2716}
2717
2718pub proof fn wf1<T>(
2729 spec: TempPred<T>,
2730 next: ActionPred<T>,
2731 forward: ActionPred<T>,
2732 p: StatePred<T>,
2733 q: StatePred<T>,
2734)
2735 requires
2736 forall|s, s_prime: T|
2737 p.apply(s) && #[trigger] next.apply(s, s_prime) ==> p.apply(s_prime) || q.apply(
2738 s_prime,
2739 ),
2740 forall|s, s_prime: T|
2741 p.apply(s) && #[trigger] next.apply(s, s_prime) && forward.apply(s, s_prime)
2742 ==> q.apply(s_prime),
2743 forall|s: T| #[trigger] p.apply(s) ==> enabled(forward).apply(s),
2744 spec.entails(always(lift_action(next))),
2745 spec.entails(weak_fairness(forward)),
2746 ensures
2747 spec.entails(lift_state(p).leads_to(lift_state(q))),
2748{
2749 broadcast use group_tla_rules;
2750
2751 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies always(lift_state(p)).leads_to(
2752 lift_action(forward),
2753 ).satisfied_by(ex) by {
2754 assert forall|i| #[trigger]
2755 always(lift_state(p)).satisfied_by(ex.suffix(i)) implies eventually(
2756 lift_action(forward),
2757 ).satisfied_by(ex.suffix(i)) by {
2758 implies_apply_with_always::<T>(
2759 ex.suffix(i),
2760 lift_state(p),
2761 lift_state(enabled(forward)),
2762 );
2763 assert(ex.suffix(i).suffix(0) == ex.suffix(i));
2764
2765 implies_apply::<T>(ex, spec, weak_fairness(forward));
2766 weak_fairness_unfold::<T>(ex, forward);
2767 implies_apply::<T>(
2768 ex.suffix(i),
2769 lift_state(enabled(forward)),
2770 eventually(lift_action(forward)),
2771 );
2772 };
2773 };
2774 wf1_variant_temp::<T>(
2775 spec,
2776 lift_action(next),
2777 lift_action(forward),
2778 lift_state(p),
2779 lift_state(q),
2780 );
2781}
2782
2783pub proof fn wf1_by_borrowing_inv<T>(
2795 spec: TempPred<T>,
2796 next: ActionPred<T>,
2797 forward: ActionPred<T>,
2798 p: StatePred<T>,
2799 q: StatePred<T>,
2800 inv: StatePred<T>,
2801)
2802 requires
2803 forall|s, s_prime: T|
2804 p.apply(s) && inv.apply(s) && #[trigger] next.apply(s, s_prime) ==> p.apply(s_prime)
2805 || q.apply(s_prime),
2806 forall|s, s_prime: T|
2807 p.apply(s) && inv.apply(s) && #[trigger] next.apply(s, s_prime) && forward.apply(
2808 s,
2809 s_prime,
2810 ) ==> q.apply(s_prime),
2811 forall|s: T| #[trigger] p.apply(s) && inv.apply(s) ==> enabled(forward).apply(s),
2812 spec.entails(always(lift_action(next))),
2813 spec.entails(always(lift_state(inv))),
2814 spec.entails(weak_fairness(forward)),
2815 ensures
2816 spec.entails(lift_state(p).leads_to(lift_state(q))),
2817{
2818 broadcast use group_tla_rules;
2819
2820 let next_and_inv = lift_action(next).and(lift_state(inv));
2821
2822 assert forall|ex| #[trigger] spec.satisfied_by(ex) implies always(
2823 lift_state(p).and(lift_state(inv)),
2824 ).leads_to(lift_action(forward)).satisfied_by(ex) by {
2825 assert forall|i| #[trigger]
2826 always(lift_state(p).and(lift_state(inv))).satisfied_by(
2827 ex.suffix(i),
2828 ) implies eventually(lift_action(forward)).satisfied_by(ex.suffix(i)) by {
2829 implies_apply_with_always::<T>(
2830 ex.suffix(i),
2831 lift_state(p).and(lift_state(inv)),
2832 lift_state(enabled(forward)),
2833 );
2834 assert(ex.suffix(i).suffix(0) == ex.suffix(i));
2835 implies_apply::<T>(ex, spec, weak_fairness(forward));
2836 weak_fairness_unfold::<T>(ex, forward);
2837 implies_apply::<T>(
2838 ex.suffix(i),
2839 lift_state(enabled(forward)),
2840 eventually(lift_action(forward)),
2841 );
2842 };
2843 };
2844 entails_always_and_n!(spec, lift_action(next), lift_state(inv));
2845 always_and_equality(lift_state(p), lift_state(inv));
2846 always_double_equality(lift_state(inv));
2847 leads_to_by_borrowing_inv(
2848 spec,
2849 always(lift_state(p)),
2850 lift_action(forward),
2851 always(lift_state(inv)),
2852 );
2853 wf1_variant_temp::<T>(spec, next_and_inv, lift_action(forward), lift_state(p), lift_state(q));
2854}
2855
2856pub proof fn strengthen_next<T>(
2865 spec: TempPred<T>,
2866 next: ActionPred<T>,
2867 inv: StatePred<T>,
2868 next_and_inv: ActionPred<T>,
2869)
2870 requires
2871 spec.entails(always(lift_action(next))),
2872 spec.entails(always(lift_state(inv))),
2873 lift_action(next_and_inv).entails(lift_action(next).and(lift_state(inv))),
2874 lift_action(next).and(lift_state(inv)).entails(lift_action(next_and_inv)),
2875 ensures
2876 spec.entails(always(lift_action(next_and_inv))),
2877{
2878 entails_and_temp::<T>(spec, always(lift_action(next)), always(lift_state(inv)));
2879 always_and_equality::<T>(lift_action(next), lift_state(inv));
2880 temp_pred_equality::<T>(lift_action(next_and_inv), lift_action(next).and(lift_state(inv)));
2881}
2882
2883#[macro_export]
2885macro_rules! leads_to_trans_n {
2886 [$($tail:tt)*] => {
2887 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::leads_to_trans_n_internal!($($tail)*));
2888 };
2889}
2890
2891#[macro_export]
2892macro_rules! leads_to_trans_n_internal {
2893 ($spec:expr, $p1:expr, $p2:expr, $p3:expr $(,)?) => {
2894 leads_to_trans($spec, $p1, $p2, $p3);
2895 };
2896 ($spec:expr, $p1:expr, $p2:expr, $p3:expr, $($tail:tt)*) => {
2897 leads_to_trans($spec, $p1, $p2, $p3);
2898 leads_to_trans_n_internal!($spec, $p1, $p3, $($tail)*);
2899 };
2900}
2901
2902pub use leads_to_trans_n;
2903pub use leads_to_trans_n_internal;
2904
2905#[macro_export]
2910macro_rules! state_pred_and {
2911 ($p1:expr $(,)?) => {
2912 $p1
2913 };
2914 ($p1:expr, $p2:expr $(,)?) => {
2915 $p1.and($p2)
2916 };
2917 ($p1:expr, $p2:expr, $($tail:expr),+ $(,)?) => {
2918 {
2919 let tmp = $p1.and($p2);
2920 $( let tmp = tmp.and($tail); )*
2921 tmp
2922 }
2923 };
2924}
2925
2926pub use state_pred_and;
2927
2928#[macro_export]
2933macro_rules! temp_pred_and {
2934 [$($tail:tt)*] => {
2935 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::temp_pred_and_internal!($($tail)*))
2936 }
2937}
2938
2939#[macro_export]
2940macro_rules! temp_pred_and_internal {
2941 ($next:expr) => {
2942 $next
2943 };
2944 ($next:expr, $($expr:expr),* $(,)?) => {
2945 $next $(
2946 .and($expr)
2947 )*
2948 };
2949}
2950
2951pub use temp_pred_and;
2952pub use temp_pred_and_internal;
2953
2954#[macro_export]
2965macro_rules! entails_and_n {
2966 [$($tail:tt)*] => {
2967 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::entails_and_n_internal!($($tail)*));
2968 };
2969}
2970
2971#[macro_export]
2972macro_rules! entails_and_n_internal {
2973 ($spec:expr, $p1:expr, $p2:expr $(,)?) => {
2974 entails_and_temp($spec, $p1, $p2);
2975 };
2976 ($spec:expr, $p1:expr, $p2:expr, $($tail:tt)*) => {
2977 entails_and_temp($spec, $p1, $p2);
2978 entails_and_n_internal!($spec, $p1.and($p2), $($tail)*);
2979 };
2980}
2981
2982pub use entails_and_n;
2983pub use entails_and_n_internal;
2984
2985#[macro_export]
2996macro_rules! entails_always_and_n {
2997 [$($tail:tt)*] => {
2998 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::entails_always_and_n_internal!($($tail)*));
2999 };
3000}
3001
3002#[macro_export]
3003macro_rules! entails_always_and_n_internal {
3004 ($spec:expr, $p1:expr $(,)?) => {};
3005 ($spec:expr, $p1:expr, $p2:expr $(,)?) => {
3006 entails_and_temp($spec, always($p1), always($p2));
3007 always_and_equality($p1, $p2);
3008 };
3009 ($spec:expr, $p1:expr, $p2:expr, $($tail:tt)*) => {
3010 entails_and_temp($spec, always($p1), always($p2));
3011 always_and_equality($p1, $p2);
3012 entails_always_and_n_internal!($spec, $p1.and($p2), $($tail)*);
3013 };
3014}
3015
3016pub use entails_always_and_n;
3017pub use entails_always_and_n_internal;
3018
3019#[macro_export]
3020macro_rules! always_and_equality_n {
3021 [$($tail:tt)*] => {
3022 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::always_and_equality_n_internal!($($tail)*));
3023 };
3024}
3025
3026#[macro_export]
3027macro_rules! always_and_equality_n_internal {
3028 ($p1:expr, $p2:expr $(,)?) => {
3029 always_and_equality($p1, $p2);
3030 };
3031 ($p1:expr, $p2:expr, $($tail:tt)*) => {
3032 always_and_equality($p1, $p2);
3033 always_and_equality_n_internal!($p1.and($p2), $($tail)*);
3034 };
3035}
3036
3037pub use always_and_equality_n;
3038pub use always_and_equality_n_internal;
3039
3040#[macro_export]
3042macro_rules! always_lift_state_and_equality_n {
3043 [$($tail:tt)*] => {
3044 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::always_lift_state_and_equality_n_internal!($($tail)*));
3045 };
3046}
3047
3048#[macro_export]
3049macro_rules! always_lift_state_and_equality_n_internal {
3050 ($p1:expr, $p2:expr $(,)?) => {
3051 always_lift_state_and_equality($p1, $p2);
3052 };
3053 ($p1:expr, $p2:expr, $($tail:tt)*) => {
3054 always_lift_state_and_equality($p1, $p2);
3055 always_lift_state_and_equality_n_internal!(state_pred_and!($p1, $p2), $($tail)*);
3056 };
3057}
3058
3059pub use always_lift_state_and_equality_n;
3060pub use always_lift_state_and_equality_n_internal;
3061
3062#[macro_export]
3073macro_rules! or_leads_to_combine_n {
3074 [$($tail:tt)*] => {
3075 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::or_leads_to_combine_n_internal!($($tail)*));
3076 };
3077}
3078
3079#[macro_export]
3080macro_rules! or_leads_to_combine_n_internal {
3081 ($spec:expr, $p1:expr, $p2:expr; $q:expr) => {
3082 or_leads_to_combine($spec, $p1, $p2, $q);
3083 };
3084 ($spec:expr, $p1:expr, $p2:expr, $($rest:expr),+; $q:expr) => {
3085 or_leads_to_combine($spec, $p1, $p2, $q);
3086 or_leads_to_combine_n_internal!($spec, $p1.or($p2), $($rest),+; $q);
3087 };
3088}
3089
3090pub use or_leads_to_combine_n;
3091pub use or_leads_to_combine_n_internal;
3092
3093#[macro_export]
3096macro_rules! or_leads_to_combine_and_equality2 {
3097 ($spec:expr, $result:expr, $p1:expr, $($rest:expr),+; $q:expr) => {
3098 temp_pred_equality(
3099 $result,
3100 $p1$(.or($rest))+
3101 );
3102 or_leads_to_combine_n!($spec, $p1, $($rest),+; $q);
3103 }
3104}
3105
3106pub use or_leads_to_combine_and_equality2;
3107
3108#[macro_export]
3119macro_rules! leads_to_always_combine_n {
3120 [$($tail:tt)*] => {
3121 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::leads_to_always_combine_n_internal!($($tail)*));
3122 };
3123}
3124
3125#[macro_export]
3126macro_rules! leads_to_always_combine_n_internal {
3127 ($spec:expr, $p:expr, $q1:expr, $q2:expr $(,)?) => {
3128 leads_to_always_combine($spec, $p, $q1, $q2);
3129 };
3130 ($spec:expr, $p:expr, $q1:expr, $q2:expr, $($tail:tt)*) => {
3131 leads_to_always_combine($spec, $p, $q1, $q2);
3132 always_and_equality($q1, $q2);
3133 leads_to_always_combine_n_internal!($spec, $p, $q1.and($q2), $($tail)*);
3134 };
3135}
3136
3137pub use leads_to_always_combine_n;
3138pub use leads_to_always_combine_n_internal;
3139
3140#[macro_export]
3141macro_rules! leads_to_always_combine_n_with_equality {
3142 [$($tail:tt)*] => {
3143 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::leads_to_always_combine_n_with_equality_internal!($($tail)*));
3144 };
3145}
3146
3147#[macro_export]
3148macro_rules! leads_to_always_combine_n_with_equality_internal {
3149 ($spec:expr, $p:expr, $dst:expr, $($tail:tt)*) => {
3150 temp_pred_equality($dst, combine_with_next!($($tail)*));
3151 leads_to_always_combine_n!($spec, $p, $($tail)*);
3152 };
3153}
3154
3155pub use leads_to_always_combine_n_with_equality;
3156pub use leads_to_always_combine_n_with_equality_internal;
3157
3158#[macro_export]
3170macro_rules! combine_spec_entails_always_n {
3171 [$($tail:tt)*] => {
3172 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::combine_spec_entails_always_n_internal!($($tail)*))
3173 }
3174}
3175
3176#[macro_export]
3177macro_rules! combine_spec_entails_always_n_internal {
3178 ($spec:expr, $partial_spec:expr, $($tail:tt)*) => {
3179 assert_by(
3180 valid($spec.implies(always(temp_pred_and!($($tail)*)))),
3181 {
3182 entails_always_and_n!($spec, $($tail)*);
3183 }
3184 );
3185 entails_preserved_by_always(temp_pred_and!($($tail)*), $partial_spec);
3186 entails_trans($spec, always(temp_pred_and!($($tail)*)), always($partial_spec));
3187 };
3188}
3189
3190pub use combine_spec_entails_always_n;
3191pub use combine_spec_entails_always_n_internal;
3192
3193#[macro_export]
3204macro_rules! entails_always_lift_state_and_n {
3205 [$($tail:tt)*] => {
3206 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::entails_always_lift_state_and_n_internal!($($tail)*))
3207 };
3208}
3209
3210#[macro_export]
3211macro_rules! entails_always_lift_state_and_n_internal {
3212 ($spec:expr, $p1:expr) => {
3213 };
3215 ($spec:expr, $p1:expr, $p2:expr $(,)?) => {
3216 entails_always_lift_state_and($spec, $p1, $p2);
3218 };
3219 ($spec:expr, $p1:expr, $p2:expr, $p3:expr $(,)?) => {
3220 entails_always_lift_state_and($spec, $p1, $p2);
3222 let combined_p1_p2 = state_pred_and!($p1, $p2);
3223 entails_always_lift_state_and($spec, combined_p1_p2, $p3);
3224 };
3225 ($spec:expr, $p1:expr, $p2:expr, $($tail:expr),+ $(,)?) => {
3226 entails_always_lift_state_and($spec, $p1, $p2);
3228 let combined_p1_p2 = state_pred_and!($p1, $p2);
3229 entails_always_lift_state_and_n_internal!($spec, combined_p1_p2, $($tail),+);
3230 };
3231}
3232
3233pub use entails_always_lift_state_and_n;
3234pub use entails_always_lift_state_and_n_internal;
3235
3236#[macro_export]
3249macro_rules! invariant_n {
3250 [$($tail:tt)*] => {
3251 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::invariant_n_internal!($($tail)*))
3252 }
3253}
3254
3255#[macro_export]
3256macro_rules! invariant_n_internal {
3257 ($spec:expr, $partial_spec:expr, $inv:expr, $($tail:tt)*) => {
3258 assert_by(
3259 valid($spec.implies(always(temp_pred_and!($($tail)*)))),
3260 {
3261 entails_always_and_n!($spec, $($tail)*);
3262 }
3263 );
3264 entails_preserved_by_always(temp_pred_and!($($tail)*), $partial_spec);
3265 entails_trans($spec, always(temp_pred_and!($($tail)*)), always($partial_spec));
3266 entails_preserved_by_always($partial_spec, $inv);
3267 entails_trans($spec, always($partial_spec), always($inv));
3268 };
3269}
3270
3271pub use invariant_n;
3272pub use invariant_n_internal;
3273
3274#[macro_export]
3285macro_rules! stable_and_n {
3286 [$($tail:tt)*] => {
3287 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::stable_and_n_internal!($($tail)*));
3288 };
3289}
3290
3291#[macro_export]
3292macro_rules! stable_and_n_internal {
3293 ($p1:expr, $p2:expr $(,)?) => {
3294 stable_and_temp($p1, $p2);
3295 };
3296 ($p1:expr, $p2:expr, $($tail:tt)*) => {
3297 stable_and_temp($p1, $p2);
3298 stable_and_n_internal!($p1.and($p2), $($tail)*);
3299 };
3300}
3301
3302pub use stable_and_n;
3303pub use stable_and_n_internal;
3304
3305#[macro_export]
3311macro_rules! stable_and_always_n {
3312 [$($tail:tt)*] => {
3313 ::verus_builtin_macros::verus_proof_macro_exprs!($crate::temporal_logic::rules::stable_and_always_n_internal!($($tail)*));
3314 };
3315}
3316
3317#[macro_export]
3318macro_rules! stable_and_always_n_internal {
3319 ($p1:expr, $($tail:expr),* $(,)?) => {
3320 always_p_is_stable($p1);
3321 $(always_p_is_stable($tail);)*
3322 stable_and_n!(always($p1), $(always($tail)),*);
3323 };
3324}
3325
3326pub use stable_and_always_n;
3327pub use stable_and_always_n_internal;
3328
3329#[macro_export]
3344macro_rules! implies_new_invariant_n {
3345 [$($tail:tt)*] => {
3346 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::implies_new_invariant_n_internal!($($tail)*))
3347 };
3348}
3349
3350#[macro_export]
3351macro_rules! implies_new_invariant_n_internal {
3352 ($spec:expr, $init:expr, $next:expr, $inv:expr, $p1:expr) => {
3353 implies_new_invariant($spec, $init, $next, $inv, $p1);
3354 };
3355 ($spec:expr, $init:expr, $next:expr, $inv:expr, $p1:expr,) => {
3356 implies_new_invariant_n_internal!($spec, $init, $next, $inv, $p1);
3357 };
3358 ($spec:expr, $init:expr, $next:expr, $inv:expr, $($preds:expr),+) => {
3359 {
3360 let combined_pred = state_pred_and!($($preds),+);
3361 entails_always_lift_state_and_n!($spec, $($preds),+);
3362 implies_new_invariant($spec, $init, $next, $inv, combined_pred);
3363 }
3364 };
3365 ($spec:expr, $init:expr, $next:expr, $inv:expr, $($preds:expr),+ ,) => {
3366 implies_new_invariant_n_internal!($spec, $init, $next, $inv, $($preds),+);
3367 };
3368}
3369
3370pub use implies_new_invariant_n;
3371pub use implies_new_invariant_n_internal;
3372
3373#[macro_export]
3388macro_rules! wf1_by_borrowing_inv_n {
3389 ($spec:expr, $next:expr, $forward:expr, $p:expr, $q:expr, $($inv:expr),+ $(,)?) => {{
3390 entails_always_lift_state_and_n!($spec, $($inv),+);
3391 let combined_inv = state_pred_and!($($inv),+);
3393 wf1_by_borrowing_inv($spec, $next, $forward, $p, $q, combined_inv)
3395 }};
3396}
3397
3398pub use wf1_by_borrowing_inv_n;
3399
3400#[macro_export]
3412macro_rules! always_lift_state_weaken_n {
3413 [$($tail:tt)*] => {
3414 ::vstd::prelude::verus_proof_macro_exprs!($crate::temporal_logic::rules::always_lift_state_weaken_n_internal!($($tail)*))
3415 };
3416}
3417
3418#[macro_export]
3419macro_rules! always_lift_state_weaken_n_internal {
3420 ($spec:expr, $p1:expr, $h:expr) => {
3421 always_lift_state_weaken($spec, $p1, $h);
3422 };
3423 ($spec:expr, $p1:expr, $p2:expr, $h:expr) => {
3424 entails_always_lift_state_and_n!($spec, $p1, $p2);
3425 always_lift_state_weaken($spec, state_pred_and!($p1, $p2), $h);
3426 };
3427 ($spec:expr, $p1:expr, $p2:expr, $h:expr,) => {
3428 always_lift_state_weaken_n_internal!($spec, $p1, $p2, $h);
3429 };
3430 ($spec:expr, $p1:expr, $p2:expr, $($tail:expr),+ , $h:expr) => {
3431 entails_always_lift_state_and_n!($spec, $p1, $p2, $($tail),+);
3432 always_lift_state_weaken($spec, state_pred_and!($p1, $p2, $($tail),+), $h);
3433 };
3434 ($spec:expr, $p1:expr, $p2:expr, $($tail:expr),+ , $h:expr,) => {
3435 always_lift_state_weaken_n_internal!($spec, $p1, $p2, $($tail),+ , $h);
3436 };
3437}
3438
3439pub use always_lift_state_weaken_n;
3440pub use always_lift_state_weaken_n_internal;
3441
3442pub broadcast group group_tla_rules {
3443 state_pred_and_apply_equality,
3444 state_pred_or_apply_equality,
3445 state_pred_implies_apply_equality,
3446 state_pred_not_apply_equality,
3447 lift_state_and_equality,
3448 lift_state_or_equality,
3449 lift_state_not_equality,
3450 lift_state_implies_equality,
3451 entails_and_temp,
3452 entails_and_temp_reverse,
3453 entails_or_temp,
3454 entails_not_temp_reverse,
3455 entails_implies_temp_reverse,
3456 always_lift_state_and_equality,
3457 always_implies_to_leads_to,
3458 always_to_always_later,
3459 always_double_equality,
3460 always_and_equality,
3461 tla_forall_apply,
3462 spec_entails_tla_forall, always_implies_forall_intro, tla_exists_leads_to_intro, leads_to_self_temp,
3466 entails_and_different_temp,
3467 always_p_is_stable,
3468 stable_and_temp,
3469 entails_preserved_by_always,
3470 leads_to_apply, or_leads_to_combine,
3472 leads_to_always_combine,
3473 leads_to_framed_by_or,
3474 lift_state_exists_equality,
3475 implies_tla_exists_intro,
3476 leads_to_tla_exists_intro,
3477 state_exists_intro, entails_always_lift_state_and, entails_always_lift_state_and_elim,
3480 entails_tla_exists_by_witness, lift_state_exists_leads_to_intro,
3482 lift_state_exists_absorb_equality,
3483 lift_state_forall_absorb_equality,
3484 lift_state_not_equality,
3485}
3486
3487}