clutch.coneris.examples.random_counter2.random_counter

From clutch.coneris Require Import coneris.

Set Default Proof Using "Type*".

Class random_counter `{!conerisGS Σ} := RandCounter
{
  

Operations

  new_counter : val;
  incr_counter : val;
  read_counter : val;
  

Ghost state

The assumptions about Σ
  counterG : gFunctors → Type;
  
name is used to associate locked with is_lock
  (* tape_name: Type; *)
  counter_name: Type;
  

Predicates

General properties of the predicates

  #[global] is_counter_persistent {L : counterG Σ} N c γ1 ::
    Persistent (is_counter (L:=L) N c γ1);
  #[global] counter_tapes_timeless {L : counterG Σ} α ns ::
    Timeless (counter_tapes (L:=L) α ns);
  #[global] counter_content_auth_timeless {L : counterG Σ} γ z ::
    Timeless (counter_content_auth (L:=L) γ z);
  #[global] counter_content_frag_timeless {L : counterG Σ} γ f z ::
    Timeless (counter_content_frag (L:=L) γ f z);
  
                                
  counter_tapes_presample {L:counterG Σ} N E γ c α ε (ε2 : fin 4%nat -> R):
  ↑N ⊆ E ->
  (∀ x, 0<=ε2 x)%R ->
  (SeriesC (λ n, 1 / 4 * ε2 n)%R <= ε)%R ->
  is_counter(L:=L) N c γ -∗
  counter_tapes (L:=L) α None -∗
  ↯ ε -∗
  state_update E E (∃ n, ↯ (ε2 n) ∗ counter_tapes (L:=L) α (Some (fin_to_nat n)));

  counter_content_auth_exclusive {L : counterG Σ} γ z1 z2:
    counter_content_auth (L:=L) γ z1 -∗ counter_content_auth (L:=L) γ z2 -∗ False;
  counter_content_less_than {L : counterG Σ} γ z z' f:
  counter_content_auth (L:=L) γ z -∗ counter_content_frag (L:=L) γ f z' -∗ ⌜(z'<=z)%nat ⌝;
  counter_content_frag_combine {L:counterG Σ} γ f f' z z':
    (counter_content_frag (L:=L) γ f z ∗ counter_content_frag (L:=L) γ f' z')%I ≡
    counter_content_frag (L:=L) γ (f+f')%Qp (z+z')%nat;
  counter_content_agree {L : counterG Σ} γ z z':
    counter_content_auth (L:=L) γ z -∗ counter_content_frag (L:=L) γ 1%Qp z' -∗ ⌜(z'=z)%nat ⌝;
  counter_content_update {L : counterG Σ} γ f z1 z2 z3:
    counter_content_auth (L:=L) γ z1 -∗ counter_content_frag (L:=L) γ f z2 ==∗
    counter_content_auth (L:=L) γ (z1+z3)%nat ∗ counter_content_frag (L:=L) γ f (z2+z3)%nat;
  
  

Program specs

  new_counter_spec {L : counterG Σ} E N:
  {{{ True }}} new_counter #() @E
    {{{ c, RET c; ∃ γ1, is_counter (L:=L) N c γ1 ∗
                           counter_content_frag (L:=L) γ1 1%Qp 0%nat
    }}};
  incr_counter_spec {L: counterG Σ} N E c γ1 (Q:nat->nat->iProp Σ) :
    ↑N⊆E ->
    {{{ is_counter (L:=L) N c γ1 ∗
        (∀ α, counter_tapes (L:=L) α None -∗
         state_update (E) (E)
           (∃ n, counter_tapes (L:=L) α (Some n) ∗
            (∀ (z:nat), counter_content_auth (L:=L) γ1 z ={E∖↑N}=∗
                      counter_content_auth (L:=L) γ1 (z+n) ∗ Q z n)))
           
    }}}
      incr_counter c @ E
                                 {{{ (z n:nat), RET (#z, #n); Q z n }}};
  read_counter_spec {L: counterG Σ} N E c γ1 Q:
    ↑N ⊆ E ->
    {{{ is_counter (L:=L) N c γ1 ∗
         (∀ (z:nat), counter_content_auth (L:=L) γ1 z ={E∖↑N}=∗
                    counter_content_auth (L:=L) γ1 z∗ Q z)
        
    }}}
      read_counter c @ E
      {{{ (n':nat), RET #n'; Q n'
      }}}
}.

Section lemmas.
  Context `{rc:random_counter} {L: counterG Σ}.
  Lemma incr_counter_spec_seq N E c γ1 ε (ε2:nat -> R) (q:Qp) (z:nat):
    ↑N ⊆ E->
    (∀ n, 0<= ε2 n)%R->
    (((ε2 0%nat) + (ε2 1%nat)+ (ε2 2%nat)+ (ε2 3%nat))/4 <= ε)%R →
    {{{ is_counter (L:=L) N c γ1 ∗
        ↯ ε ∗
        counter_content_frag (L:=L) γ1 q z
    }}}
      incr_counter c @ E
                                 {{{ (z':nat) (n:nat),
                                       RET (#z', #n); ⌜(0<=n<4)%nat⌝ ∗
                                                      ⌜(z<=z')%nat⌝ ∗
                                                      ↯(ε2 n) ∗
                                                     counter_content_frag (L:=L) γ1 q (z+n)%nat }}}.
  Proof.
    iIntros (Hsubset Hpos Hineq Φ) "(#Hinv & Herr & Hcontent) HΦ".
    pose (ε2' := (λ x, if (x<=?3)%nat then ε2 x else 1%R)).
    wp_apply (incr_counter_spec _ _ _ _
                (λ z' n , ⌜0<=n<4⌝ ∗ ⌜z<=z'⌝ ∗
                          ↯ (ε2 n) ∗
                                 counter_content_frag (L:=L) γ1 q (z+n)%nat
                )%I
               with "[-HΦ]").
    - done.
    - iSplit; first done.
      iIntros (α) "Htape".
      iMod (counter_tapes_presample _ _ _ _ _ _ (λ x, ε2 (fin_to_nat x)) with "[//][$][$]") as "(%n & Herr & Htape)"; [try done..|].
      + rewrite SeriesC_finite_foldr/=. lra.
      + iModIntro. iFrame.
        iIntros (?) "?".
        iDestruct (counter_content_less_than with "[$][$]") as "%".
        iMod (counter_content_update with "[$][$]") as "[??]".
        iFrame.
        iModIntro.
        iPureIntro; repeat split; try done; try lia.
        apply fin_to_nat_lt.
    - iIntros (z' n) "(% & % & Herr & Hfrag' )".
      iApply "HΦ".
      iFrame.
      by iSplit.
  Qed.

End lemmas.