-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathprimitive_laws.v
More file actions
742 lines (689 loc) · 23.7 KB
/
Copy pathprimitive_laws.v
File metadata and controls
742 lines (689 loc) · 23.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
(** This file proves the basic laws of the ProbLang weakest precondition by
applying the lifting lemmas. *)
From iris.proofmode Require Import proofmode.
From iris.base_logic.lib Require Export ghost_map.
From clutch.base_logic Require Export error_credits_mult error_credits.
From clutch.diffpriv Require Export weakestpre ectx_lifting.
From clutch.prob_lang Require Export class_instances.
From clutch.prob_lang Require Import tactics lang notation metatheory.
From clutch.prob_lang.spec Require Export spec_ra spec_rules spec_tactics.
From iris.prelude Require Import options.
Class diffprivGS Σ := HeapG {
diffprivGS_invG : invGS_gen HasNoLc Σ;
(* CMRA for the state *)
diffprivGS_heap :: ghost_mapG Σ loc val;
diffprivGS_tapes :: ghost_mapG Σ loc tape;
diffprivGS_tapes_laplace :: ghost_mapG Σ loc tape_laplace;
(* ghost names for the state *)
diffprivGS_heap_name : gname;
diffprivGS_tapes_name : gname;
diffprivGS_tapes_laplace_name : gname;
(* CMRA and ghost name for the spec *)
diffprivGS_spec :: specG_prob_lang Σ;
(* CMRA and ghost names for the error *)
diffprivGS_error_eps :: ecmGS Σ;
diffprivGS_error_del :: ecGS Σ;
}.
Class diffprivGpreS Σ := DiffprivGpreS {
diffprivGpreS_iris :: invGpreS Σ;
diffprivGpreS_heap :: ghost_mapG Σ loc val;
diffprivGpreS_tapes :: ghost_mapG Σ loc tape;
diffprivGpreS_tapes_laplace :: ghost_mapG Σ loc tape_laplace;
diffprivGpreS_spcec :: specGpreS Σ;
diffprivGpreS_err_eps :: ecmGpreS Σ;
diffprivGpreS_err_del :: ecGpreS Σ;
}.
Definition diffprivΣ : gFunctors :=
#[invΣ;
ghost_mapΣ loc val;
ghost_mapΣ loc tape;
ghost_mapΣ loc tape_laplace;
specΣ;
ecmΣ;
ecΣ].
Global Instance subG_diffprivGPreS {Σ} : subG diffprivΣ Σ → diffprivGpreS Σ.
Proof. solve_inG. Qed.
Definition heap_auth `{diffprivGS Σ} :=
@ghost_map_auth _ _ _ _ _ diffprivGS_heap diffprivGS_heap_name.
Definition tapes_auth `{diffprivGS Σ} :=
@ghost_map_auth _ _ _ _ _ diffprivGS_tapes diffprivGS_tapes_name.
Definition tapes_laplace_auth `{diffprivGS Σ} :=
@ghost_map_auth _ _ _ _ _ diffprivGS_tapes_laplace diffprivGS_tapes_laplace_name.
Definition mult_ec_supply `{diffprivGS Σ} :=
@ecm_supply _ diffprivGS_error_eps.
Definition add_ec_supply `{diffprivGS Σ} :=
@ec_supply _ diffprivGS_error_del.
Global Instance diffprivGS_irisGS `{!diffprivGS Σ} : diffprivWpGS prob_lang Σ := {
diffprivWpGS_invGS := diffprivGS_invG;
state_interp σ := (heap_auth (DfracOwn 1) σ.(heap) ∗ tapes_auth (DfracOwn 1) σ.(tapes) ∗ tapes_laplace_auth (DfracOwn 1) σ.(tapes_laplace))%I;
err_interp ε δ := ((mult_ec_supply ε) ∗ (add_ec_supply δ))%I;
}.
(** Heap *)
Notation "l ↦{ dq } v" := (@ghost_map_elem _ _ _ _ _ diffprivGS_heap diffprivGS_heap_name l dq v)
(at level 20, format "l ↦{ dq } v") : bi_scope.
Notation "l ↦□ v" := (l ↦{ DfracDiscarded } v)%I
(at level 20, format "l ↦□ v") : bi_scope.
Notation "l ↦{# q } v" := (l ↦{ DfracOwn q } v)%I
(at level 20, format "l ↦{# q } v") : bi_scope.
Notation "l ↦ v" := (l ↦{ DfracOwn 1 } v)%I
(at level 20, format "l ↦ v") : bi_scope.
(** Tapes *)
Notation "l ↪{ dq } v" := (@ghost_map_elem _ _ tape _ _ diffprivGS_tapes diffprivGS_tapes_name l dq v)
(at level 20, format "l ↪{ dq } v") : bi_scope.
Notation "l ↪□ v" := (l ↪{ DfracDiscarded } v)%I
(at level 20, format "l ↪□ v") : bi_scope.
Notation "l ↪{# q } v" := (l ↪{ DfracOwn q } v)%I
(at level 20, format "l ↪{# q } v") : bi_scope.
Notation "l ↪ v" := (l ↪{ DfracOwn 1 } v)%I
(at level 20, format "l ↪ v") : bi_scope.
(** User-level tapes *)
Definition nat_tape `{diffprivGS Σ} l (N : nat) (ns : list nat) : iProp Σ :=
∃ (fs : list (fin (S N))), ⌜fin_to_nat <$> fs = ns⌝ ∗ l ↪ (N; fs).
Notation "l ↪N ( M ; ns )" := (nat_tape l M ns)%I
(at level 20, format "l ↪N ( M ; ns )") : bi_scope.
Notation "l ↪L ( num , den , mean ; xs )" := (@ghost_map_elem _ _ tape_laplace _ _ diffprivGS_tapes_laplace diffprivGS_tapes_laplace_name
l (DfracOwn 1) (Tape_Laplace num den mean xs))%I
(at level 20, format "l ↪L ( num , den , mean ; xs )") : bi_scope.
(*
Definition nat_spec_tape `{diffprivGS Σ} l (N : nat) (ns : list nat) : iProp Σ :=
∃ (fs : list (fin (S N))), ⌜fin_to_nat <$> fs = ns⌝ ∗ l ↪ₛ (N; fs).
Notation "l ↪ₛN ( M ; ns )" := (nat_spec_tape l M ns)%I
(at level 20, format "l ↪ₛN ( M ; ns )") : bi_scope.
*)
Section tape_interface.
Context `{!diffprivGS Σ}.
(** Helper lemmas to go back and forth between the user-level representation
of tapes (using nat) and the backend (using fin) *)
Lemma tapeN_to_empty l M :
(l ↪N ( M ; [] ) -∗ l ↪ ( M ; [] )).
Proof.
iIntros "Hl".
iDestruct "Hl" as (?) "(%Hmap & Hl')".
by destruct (fmap_nil_inv _ _ Hmap).
Qed.
Lemma empty_to_tapeN l M :
(l ↪ ( M ; [] ) -∗ l ↪N ( M ; [] )).
Proof.
iIntros "Hl".
iExists []. auto.
Qed.
Lemma read_tape_head l M n ns :
(l ↪N ( M ; n :: ns ) -∗
∃ x xs, l ↪ ( M ; x :: xs ) ∗ ⌜ fin_to_nat x = n ⌝ ∗
( l ↪ ( M ; xs ) -∗l ↪N ( M ; ns ) )).
Proof.
iIntros "Hl".
iDestruct "Hl" as (xss) "(%Hmap & Hl')".
destruct (fmap_cons_inv _ _ _ _ Hmap) as (x&xs&->&Hxs&->).
iExists x, xs.
iFrame.
iSplit; auto.
iIntros.
iExists xs; auto.
Qed.
(*
Lemma spec_tapeN_to_empty l M :
(l ↪ₛN ( M ; [] ) -∗ l ↪ₛ ( M ; [] )).
Proof.
iIntros "Hl".
iDestruct "Hl" as (?) "(%Hmap & Hl')".
by destruct (fmap_nil_inv _ _ Hmap).
Qed.
Lemma empty_to_spec_tapeN l M :
(l ↪ₛ ( M ; [] ) -∗ l ↪ₛN ( M ; [] )).
Proof.
iIntros "Hl".
iExists []. auto.
Qed.
Lemma read_spec_tape_head l M n ns :
(l ↪ₛN ( M ; n :: ns ) -∗
∃ x xs, l ↪ₛ ( M ; x :: xs ) ∗ ⌜ fin_to_nat x = n ⌝ ∗
( l ↪ₛ ( M ; xs ) -∗l ↪ₛN ( M ; ns ) )).
Proof.
iIntros "Hl".
iDestruct "Hl" as (xss) "(%Hmap & Hl')".
destruct (fmap_cons_inv _ _ _ _ Hmap) as (x&xs&->&Hxs&->).
iExists x, xs.
iFrame.
iSplit; auto.
iIntros.
iExists xs; auto.
Qed.
*)
End tape_interface.
Section lifting.
Context `{!diffprivGS Σ}.
Implicit Types P Q : iProp Σ.
Implicit Types Φ Ψ : val → iProp Σ.
Implicit Types σ : state.
Implicit Types v : val.
Implicit Types l : loc.
(** Recursive functions: we do not use this lemma as it is easier to use Löb
induction directly, but this demonstrates that we can state the expected
reasoning principle for recursive functions, without any visible ▷. *)
Lemma wp_rec_löb E f x e Φ Ψ :
□ ( □ (∀ v, Ψ v -∗ WP (rec: f x := e)%V v @ E {{ Φ }}) -∗
∀ v, Ψ v -∗ WP (subst' x v (subst' f (rec: f x := e) e)) @ E {{ Φ }}) -∗
∀ v, Ψ v -∗ WP (rec: f x := e)%V v @ E {{ Φ }}.
Proof.
iIntros "#Hrec". iLöb as "IH". iIntros (v) "HΨ".
iApply lifting.wp_pure_step_later; first done.
iNext. iApply ("Hrec" with "[] HΨ"). iIntros "!>" (w) "HΨ".
iApply ("IH" with "HΨ").
Qed.
(** Heap *)
Lemma wp_alloc E v s :
{{{ True }}} Alloc (Val v) @ s; E {{{ l, RET LitV (LitLoc l); l ↦ v }}}.
Proof.
iIntros (Φ) "_ HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "[Hh Ht] !#".
solve_red.
iIntros "!> /=" (e2 σ2 Hs); inv_head_step.
iMod ((ghost_map_insert (fresh_loc σ1.(heap)) v) with "Hh") as "[? Hl]".
{ apply not_elem_of_dom, fresh_loc_is_fresh. }
iFrame.
rewrite map_union_empty -insert_union_singleton_l.
iFrame.
iIntros "!>". by iApply "HΦ".
Qed.
Lemma wp_allocN_seq (N : nat) (z : Z) E v s :
TCEq N (Z.to_nat z) →
(0 < N)%Z →
{{{ True }}}
AllocN (Val $ LitV $ LitInt $ z) (Val v) @ s; E
{{{ l, RET LitV (LitLoc l); [∗ list] i ∈ seq 0 N, (l +ₗ (i : nat)) ↦ v }}}.
Proof.
iIntros (-> Hn Φ) "_ HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "[Hh Ht] !#".
iSplit.
{ iPureIntro.
rewrite /head_reducible.
eexists.
apply head_step_support_equiv_rel.
econstructor; eauto.
lia.
}
iIntros "!> /=" (e2 σ2 Hs); inv_head_step.
iMod ((ghost_map_insert_big _ _ with "Hh")) as "[$ Hl]".
iIntros "!>". iFrame.
iApply "HΦ".
iInduction (H) as [ | ?] "IH" forall (σ1).
- simpl.
iSplit; auto.
rewrite map_union_empty.
rewrite loc_add_0.
by rewrite big_sepM_singleton.
- rewrite seq_S.
rewrite heap_array_replicate_S_end.
iPoseProof (big_sepM_union _ _ _ _ with "Hl") as "[H1 H2]".
iApply big_sepL_app.
iSplitL "H1".
+ iApply "IH".
{ iPureIntro. lia. }
iApply "H1".
+ simpl. iSplit; auto.
by rewrite big_sepM_singleton.
Unshelve.
{
apply heap_array_map_disjoint.
intros.
apply not_elem_of_dom_1.
by apply fresh_loc_offset_is_fresh.
}
apply heap_array_map_disjoint.
intros.
apply not_elem_of_dom_1.
rewrite dom_singleton.
apply not_elem_of_singleton_2.
intros H2.
apply loc_add_inj in H2.
rewrite length_replicate in H1.
lia.
Qed.
Lemma wp_load E l dq v s :
{{{ ▷ l ↦{dq} v }}} Load (Val $ LitV $ LitLoc l) @ s; E {{{ RET v; l ↦{dq} v }}}.
Proof.
iIntros (Φ) ">Hl HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "[Hh Ht] !#".
iDestruct (ghost_map_lookup with "Hh Hl") as %?.
solve_red.
iIntros "!> /=" (e2 σ2 Hs); inv_head_step.
iFrame. iModIntro. by iApply "HΦ".
Qed.
Lemma wp_store E l v' v s :
{{{ ▷ l ↦ v' }}} Store (Val $ LitV (LitLoc l)) (Val v) @ s; E
{{{ RET LitV LitUnit; l ↦ v }}}.
Proof.
iIntros (Φ) ">Hl HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "[Hh Ht] !#".
iDestruct (ghost_map_lookup with "Hh Hl") as %?.
solve_red.
iIntros "!> /=" (e2 σ2 Hs); inv_head_step.
iMod (ghost_map_update with "Hh Hl") as "[$ Hl]".
iFrame. iModIntro. by iApply "HΦ".
Qed.
Lemma wp_rand (N : nat) (z : Z) E s :
TCEq N (Z.to_nat z) →
{{{ True }}} rand #z @ s; E {{{ (n : nat), RET #n; ⌜n <= N⌝ }}}.
Proof.
iIntros (-> Φ) "_ HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "Hσ !#".
solve_red.
iIntros "!>" (e2 σ2 Hs).
inv_head_step.
iFrame.
iApply ("HΦ" $! x).
iPureIntro.
pose proof (fin_to_nat_lt x); lia.
Qed.
(** Tapes *)
Lemma wp_alloc_tape N z E s :
TCEq N (Z.to_nat z) →
{{{ True }}} alloc #z @ s; E {{{ α, RET #lbl:α; α ↪N (N; []) }}}.
Proof.
iIntros (-> Φ) "_ HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "(Hh & Ht & ?) !# /=".
solve_red.
iIntros "!>" (e2 σ2 Hs); inv_head_step.
iMod (ghost_map_insert (fresh_loc σ1.(tapes)) with "Ht") as "[$ Hl]".
{ apply not_elem_of_dom, fresh_loc_is_fresh. }
iFrame. iModIntro.
iApply "HΦ".
iExists []; auto.
Qed.
Lemma wp_rand_tape N α n ns z E s :
TCEq N (Z.to_nat z) →
{{{ ▷ α ↪N (N; n :: ns) }}}
rand(#lbl:α) #z @ s; E
{{{ RET #(LitInt n); α ↪N (N; ns) ∗ ⌜n <= N⌝ }}}.
Proof.
iIntros (-> Φ) ">Hl HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "(Hh & Ht & ?) !#".
iDestruct (read_tape_head with "Hl") as (x xs) "(Hl&<-&Hret)".
iDestruct (ghost_map_lookup with "Ht Hl") as %?.
solve_red.
iIntros "!>" (e2 σ2 Hs).
inv_head_step.
iMod (ghost_map_update with "Ht Hl") as "[$ Hl]".
iFrame. iModIntro.
iApply "HΦ".
iSplit; first by iApply "Hret".
iPureIntro.
pose proof (fin_to_nat_lt x); lia.
Qed.
Lemma wp_rand_tape_empty N z α E s :
TCEq N (Z.to_nat z) →
{{{ ▷ α ↪N (N; []) }}}
rand(#lbl:α) #z @ s; E
{{{ (n : nat), RET #(LitInt n); α ↪N (N; []) ∗ ⌜n <= N⌝ }}}.
Proof.
iIntros (-> Φ) ">Hl HΦ".
iPoseProof (tapeN_to_empty with "Hl") as "Hl".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "(Hh & Ht & ?) !#".
iDestruct (ghost_map_lookup with "Ht Hl") as %?.
solve_red.
iIntros "!>" (e2 σ2 Hs).
inv_head_step.
iFrame.
iModIntro. iApply ("HΦ" with "[$Hl]").
iSplit; auto.
iPureIntro.
pose proof (fin_to_nat_lt x); lia.
Qed.
Lemma wp_rand_tape_wrong_bound N M z α E ns s :
TCEq N (Z.to_nat z) →
N ≠ M →
{{{ ▷ α ↪N (M; ns) }}}
rand(#lbl:α) #z @ s; E
{{{ (n : nat), RET #(LitInt n); α ↪N (M; ns) ∗ ⌜n <= N⌝ }}}.
Proof.
iIntros (-> ? Φ) ">Hl HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "(Hh & Ht & ?) !#".
iDestruct "Hl" as (?) "(?&Hl)".
iDestruct (ghost_map_lookup with "Ht Hl") as %?.
solve_red.
iIntros "!>" (e2 σ2 Hs).
inv_head_step.
iFrame.
iModIntro.
iApply ("HΦ").
iFrame.
iPureIntro.
pose proof (fin_to_nat_lt x); lia.
Qed.
(** Laplace Tapes *)
Lemma wp_alloc_tape_laplace num den mean E s :
{{{ True }}} AllocTapeLaplace #num #den #mean @ s; E {{{ α, RET #lbl:α; α ↪L (num,den,mean; []) }}}.
Proof.
iIntros (Φ) "_ HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "(Hh & ? & Ht) !# /=".
solve_red.
iIntros "!>" (e2 σ2 Hs); inv_head_step.
iMod (ghost_map_insert (fresh_loc σ1.(tapes_laplace)) with "Ht") as "[$ Hl]".
{ apply not_elem_of_dom, fresh_loc_is_fresh. }
iFrame. iModIntro.
iApply "HΦ".
auto.
Qed.
Lemma wp_laplace_tape num den mean num' den' mean' α n ns E s :
TCEq num num' →
TCEq den den' →
TCEq mean mean' →
{{{ ▷ α ↪L (num, den, mean; n :: ns) }}}
Laplace #num #den #mean (#lbl:α) @ s; E
{{{ RET #(LitInt n); α ↪L (num, den, mean; ns) }}}.
Proof.
iIntros (-> -> -> Φ) ">Hl HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "(Hh & ? & Ht) !#".
(* iDestruct (read_tape_head with "Hl") as (x xs) "(Hl&<-&Hret)". *)
iDestruct (ghost_map_lookup with "Ht Hl") as %?.
solve_red.
iIntros "!>" (e2 σ2 Hs).
inv_head_step.
- iMod (ghost_map_update with "Ht Hl") as "[$ Hl]".
iFrame. iModIntro.
iApply "HΦ". done.
- iMod (ghost_map_update with "Ht Hl") as "[$ Hl]".
iFrame. iModIntro.
iApply "HΦ". done.
Qed.
Lemma wp_laplace_tape_empty num den mean num' den' mean' α E s :
TCEq num num' →
TCEq den den' →
TCEq mean mean' →
{{{ ▷ α ↪L (num, den, mean; []) }}}
Laplace #num #den #mean (#lbl:α) @ s; E
{{{ (z : Z), RET #(LitInt z); α ↪L (num, den, mean; []) }}}.
Proof.
iIntros (-> -> -> Φ) ">Hl HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "(Hh & ? & Ht) !#".
iDestruct (ghost_map_lookup with "Ht Hl") as %?.
solve_red.
iIntros "!>" (e2 σ2 Hs).
inv_head_step.
- iFrame.
iModIntro. iApply ("HΦ" with "[$Hl]").
- iFrame.
iModIntro. iApply ("HΦ" with "[$Hl]").
- iFrame.
iModIntro. iApply ("HΦ" with "[$Hl]").
- iFrame.
iModIntro. iApply ("HΦ" with "[$Hl]").
Qed.
Lemma wp_laplace_tape_wrong_bound num den mean num' den' mean' α E ns s :
not (num = num' ∧ den = den' ∧ mean = mean') →
{{{ ▷ α ↪L (num', den', mean'; ns) }}}
Laplace #num #den #mean (#lbl:α) @ s; E
{{{ (z : Z), RET #(LitInt z); α ↪L (num', den', mean'; ns) }}}.
Proof.
iIntros (? Φ) ">Hl HΦ".
iApply wp_lift_atomic_head_step; [done|].
iIntros (σ1) "(Hh & ? & Ht) !#".
iDestruct (ghost_map_lookup with "Ht Hl") as %?.
iSplit.
{
iPureIntro.
eauto with head_step.
}
iIntros "!>" (e2 σ2 Hs).
inv_head_step.
- iFrame.
iModIntro.
iApply ("HΦ").
intuition simplify_eq.
- iFrame.
iModIntro.
iApply ("HΦ").
iFrame.
- iFrame.
iModIntro.
iApply ("HΦ").
iFrame.
- iFrame.
iModIntro.
iApply ("HΦ").
iFrame.
Qed.
(** spec [rand] *)
Lemma wp_rand_r N z E e K Φ :
TCEq N (Z.to_nat z) →
⤇ fill K (rand #z) ∗
(∀ n : nat, ⤇ fill K #n -∗ ⌜ n <= N ⌝ -∗ WP e @ E {{ Φ }})
⊢ WP e @ E {{ Φ }}.
Proof.
iIntros (->) "(Hj & Hwp)".
iApply wp_lift_step_spec_couple.
iIntros (σ1 e1' σ1' ε1 δ1) "(Hσ & Hs & Hε)".
iDestruct (spec_auth_prog_agree with "Hs Hj") as %->.
iApply fupd_mask_intro; [set_solver|]; iIntros "Hclose".
iApply spec_coupl_step; [solve_red|].
rewrite fill_dmap //=.
iIntros (e2' σ2' ([? ? ]&?&Hs)%dmap_pos).
simplify_eq/=.
rewrite head_prim_step_eq // in Hs.
inv_head_step.
iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "Hj").
iPureIntro.
pose proof (fin_to_nat_lt x); lia.
Qed.
(** This is just a wrapper for tp_alloctape that works with nats
TODO : Make into tactic *)
Lemma wp_alloc_tape_r N z E e K Φ :
TCEq N (Z.to_nat z) →
⤇ fill K (alloc #z) ∗
(∀ α, ⤇ fill K #lbl:α -∗ α ↪ₛN (N; []) -∗ WP e @ E {{ Φ }})
⊢ WP e @ E {{ Φ }}.
Proof.
iIntros (->) "(Hj & Hwp)".
tp_alloctape as α "Hα".
iApply ("Hwp" with "Hj").
iFrame.
iPureIntro.
auto.
Qed.
(** spec [rand(α)] with empty tape *)
Lemma wp_rand_empty_r N z E e K α Φ :
TCEq N (Z.to_nat z) →
⤇ fill K (rand(#lbl:α) #z) ∗ α ↪ₛN (N; []) ∗
(∀ n : nat, (α ↪ₛN (N; []) ∗ ⤇ fill K #n) -∗ ⌜ n <= N ⌝ -∗ WP e @ E {{ Φ }})
⊢ WP e @ E {{ Φ }}.
Proof.
iIntros (->) "(Hj & Hα & Hwp)".
iApply wp_lift_step_spec_couple.
iIntros (σ1 e1' σ1' ε1 δ1) "(Hσ & Hs & Hε)".
iPoseProof (spec_tapeN_to_empty with "Hα") as "Hα".
iDestruct (spec_auth_prog_agree with "Hs Hj") as %->.
iDestruct (spec_auth_lookup_tape with "Hs Hα") as %?.
iApply fupd_mask_intro; [set_solver|]; iIntros "Hclose".
iApply spec_coupl_step; [solve_red|].
rewrite fill_dmap //=.
iIntros (e2' σ2' ([? ? ]&?&Hs)%dmap_pos).
simplify_eq/=.
rewrite head_prim_step_eq // in Hs.
inv_head_step.
iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[Hα Hj]");
first by iFrame; auto.
iPureIntro.
pose proof (fin_to_nat_lt x); lia.
Qed.
(** This is just a wrapper for tp_rand that works with nats
TODO: Make into tactic *)
Lemma wp_rand_tape_r N z E e K α Φ n ns :
TCEq N (Z.to_nat z) →
⤇ fill K (rand(#lbl:α) #z) ∗ α ↪ₛN (N; n::ns) ∗
((α ↪ₛN (N; ns) ∗ ⤇ fill K #n) -∗ ⌜ n <= N ⌝ -∗ WP e @ E {{ Φ }})
⊢ WP e @ E {{ Φ }}.
Proof.
iIntros (Heq) "(Hj & Hα & Hwp)".
iDestruct (read_spec_tape_head with "Hα") as (x xs) "(Hl&<-&Hret)".
tp_rand.
iDestruct ("Hret" with "Hl") as "Hret".
iApply ("Hwp" with "[$]").
iPureIntro.
pose proof (fin_to_nat_lt x); lia.
Qed.
(** spec [rand(α)] with wrong tape *)
Lemma wp_rand_wrong_tape_r N M z E e K α Φ ns :
TCEq N (Z.to_nat z) →
N ≠ M →
⤇ fill K (rand(#lbl:α) #z) ∗ α ↪ₛN (M; ns) ∗
(∀ (n : nat), (α ↪ₛN (M; ns) ∗ ⤇ fill K #n) -∗ ⌜ n <= N ⌝ -∗ WP e @ E {{ Φ }})
⊢ WP e @ E {{ Φ }}.
Proof.
iIntros (-> ?) "(Hj & Hα & Hwp)".
iApply wp_lift_step_spec_couple.
iIntros (σ1 e1' σ1' ε1 δ1) "(Hσ & Hs & Hε)".
iDestruct "Hα" as (?) "(%&Hα)".
iDestruct (spec_auth_prog_agree with "Hs Hj") as %->.
iDestruct (spec_auth_lookup_tape with "Hs Hα") as %?.
iApply fupd_mask_intro; [set_solver|]; iIntros "Hclose".
iApply spec_coupl_step; [solve_red|].
rewrite fill_dmap //=.
iIntros (e2' σ2' ([? ? ]&?&Hs)%dmap_pos).
simplify_eq/=.
rewrite head_prim_step_eq // in Hs.
inv_head_step.
iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[-]"); first by iFrame.
iPureIntro.
pose proof (fin_to_nat_lt x); lia.
Qed.
(** spec [Laplace] *)
Lemma wp_laplace_r (num den mean : Z) E e K Φ :
⤇ fill K (Laplace #num #den #mean #()) ∗
(∀ z : Z, ⤇ fill K #z -∗ WP e @ E {{ Φ }})
⊢ WP e @ E {{ Φ }}.
Proof.
iIntros "(Hj & Hwp)".
iApply wp_lift_step_spec_couple.
iIntros (σ1 e1' σ1' ε1 δ1) "(Hσ & Hs & Hε)".
iDestruct (spec_auth_prog_agree with "Hs Hj") as %->.
iApply fupd_mask_intro; [set_solver|]; iIntros "Hclose".
iApply spec_coupl_step ; [solve_red|].
rewrite fill_dmap //=.
iIntros (e2' σ2' ([? ? ]&?&Hs)%dmap_pos).
simplify_eq/=.
rewrite head_prim_step_eq // in Hs.
inv_head_step.
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "Hj").
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "Hj").
Qed.
(** spec [Laplace(α)] with empty tape *)
Lemma wp_laplace_empty_r (num den mean num' den' mean' : Z) E e K α Φ :
TCEq num num' →
TCEq den den' →
TCEq mean mean' →
⤇ fill K (Laplace #num #den #mean (#lbl:α)) ∗ α ↪Lₛ (num,den,mean; []) ∗
(∀ z : Z, (α ↪Lₛ (num,den,mean; []) ∗ ⤇ fill K #z) -∗ WP e @ E {{ Φ }})
⊢ WP e @ E {{ Φ }}.
Proof.
iIntros (->->->) "(Hj & Hα & Hwp)".
iApply wp_lift_step_spec_couple.
iIntros (σ1 e1' σ1' ε1 δ1) "(Hσ & Hs & Hε)".
iDestruct (spec_auth_prog_agree with "Hs Hj") as %->.
iDestruct (spec_auth_lookup_tape_laplace with "Hs Hα") as %?.
iApply fupd_mask_intro; [set_solver|]; iIntros "Hclose".
iApply spec_coupl_step; [solve_red|].
rewrite fill_dmap //=.
iIntros (e2' σ2' ([? ? ]&?&Hs)%dmap_pos).
simplify_eq/=.
rewrite head_prim_step_eq // in Hs.
inv_head_step.
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[Hα Hj]");
first by iFrame; auto.
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[Hα Hj]");
first by iFrame; auto.
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[Hα Hj]");
first by iFrame; auto.
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[Hα Hj]");
first by iFrame; auto.
Qed.
(** spec [Laplace(α)] with wrong tape *)
Lemma wp_laplace_wrong_tape_r (num den mean num' den' mean' : Z) E e K α Φ zs :
not (num = num' ∧ den = den' ∧ mean = mean') →
⤇ fill K (Laplace #num #den #mean (#lbl:α)) ∗ α ↪Lₛ (num', den', mean'; zs) ∗
(∀ (z : Z), (α ↪Lₛ (num', den', mean'; zs) ∗ ⤇ fill K #z) -∗ WP e @ E {{ Φ }})
⊢ WP e @ E {{ Φ }}.
Proof.
iIntros (?) "(Hj & Hα & Hwp)".
iApply wp_lift_step_spec_couple.
iIntros (σ1 e1' σ1' ε1 δ1) "(Hσ & Hs & Hε)".
iDestruct (spec_auth_prog_agree with "Hs Hj") as %->.
iDestruct (spec_auth_lookup_tape_laplace with "Hs Hα") as %?.
iApply fupd_mask_intro; [set_solver|]; iIntros "Hclose".
iApply spec_coupl_step; [solve_red|].
rewrite fill_dmap //=.
iIntros (e2' σ2' ([? ? ]&?&Hs)%dmap_pos).
simplify_eq/=.
rewrite head_prim_step_eq // in Hs.
inv_head_step.
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[-]"); first by iFrame.
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[-]"); first by iFrame.
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[-]"); first by iFrame.
- iApply spec_coupl_ret.
iMod (spec_update_prog (fill K #_) with "Hs Hj") as "[$ Hj]".
iFrame. iModIntro.
iMod "Hclose" as "_"; iModIntro.
iApply ("Hwp" with "[-]"); first by iFrame.
Qed.
End lifting.
Global Hint Extern 0 (TCEq _ (Z.to_nat _ )) => rewrite Nat2Z.id : typeclass_instances.