clutch.coneris.examples.random_counter3.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; *)
  incr_counter : val;
  read_counter : val;
  

Ghost state

The assumptions about Σ
  counterG : gFunctors Type;
  
name is used to associate locked with is_lock
  counter_name: Type;
  

Predicates

General properties of the predicates

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 Σ) :
    NE ->
    {{{ is_counter (L:=L) N c γ1
        |={EN,}=>
          ( ε (ε2 : fin 4%nat -> R),
               ε ( x, 0<=ε2 x)%R
              (SeriesC (λ n, 1 / 4 * ε2 n)%R <= ε)%R
              ( n, (ε2 n) ={, EN}=∗
          ( (z:nat), counter_content_auth (L:=L) γ1 z ={EN}=∗
                      counter_content_auth (L:=L) γ1 (z+n) Q ε ε2 z n)))
           
    }}}
      incr_counter c @ E
                                 {{{ (z n:nat), RET (#z, #n); ε ε2, Q ε ε2 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 ={EN}=∗
                    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.
      iApply fupd_mask_intro; first set_solver.
      iIntros "Hclose".
      iFrame.
      iExists (λ x, ε2 (fin_to_nat x)); repeat iSplit; try done.
      + rewrite SeriesC_finite_foldr/=. iPureIntro. lra.
      + iIntros (?) "?".
        iMod "Hclose". iModIntro.
        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.
  Qed.

End lemmas.