ITree.Interp.Traces

ITrees as sets of traces



Inductive trace {E : Type Type} {R : Type} : Type :=
| TEnd : trace
| TRet : R trace
| TEventEnd : {X}, E X trace
| TEventResponse : {X}, E X X trace trace
.

(* Append two traces, ignoring the end of the first trace. *)
Fixpoint app_trace {E R S} (tr1 : @trace E R) (tr2 : @trace E S) : @trace E S :=
  match tr1 with
  | TEventResponse e x trTEventResponse e x (app_trace tr tr2)
  | _tr2
  end.

(* Get the value in the TRet at the end of the trace, if it exists. *)
Fixpoint trace_ret {E R} (tr : @trace E R) : option R :=
  match tr with
  | TRet r ⇒ (Some r)
  | TEventResponse _ _ trtrace_ret tr
  | _None
  end.

Inductive is_traceF {E : Type Type} {R : Type} :
  itreeF E R (itree E R) @trace E R Prop :=
| TraceEmpty : t, is_traceF t TEnd
| TraceRet : r, is_traceF (RetF r) (TRet r)
| TraceTau : t tr,
    is_traceF (observe t) tr
    is_traceF (TauF t) tr
| TraceVisEnd : X (e : E X) k,
    is_traceF (VisF e k) (TEventEnd e)
| TraceVisContinue : X (e : E X) (x : X) k tr,
    is_traceF (observe (k x)) tr
    is_traceF (VisF e k) (TEventResponse e x tr)
.

Definition is_trace {E : Type Type} {R : Type} (t : itree E R) :=
  is_traceF (observe t).

(* t1 ⊑ t2 *)
Definition trace_incl {E : Type Type} {R : Type} :
  itree E R itree E R Prop :=
  fun t1 t2
     tr, is_trace t1 tr is_trace t2 tr.

(* t1 ≡ t2 *)
Definition trace_eq {E : Type Type} {R : Type} :
  itree E R itree E R Prop :=
  fun t1 t2
    trace_incl t1 t2 trace_incl t2 t1.

Lemma is_traceF_tau : {E R} (t : itree E R) tr,
    is_traceF (observe t) tr
    is_traceF (TauF t) tr.
Proof.
  intros. split; intros.
  - constructor. remember (observe t).
    generalize dependent t.
    induction H; intros; subst; constructor; eapply IHis_traceF; auto.
  - inversion H; subst; try constructor; auto.
Qed.

Lemma sutt_trace_incl : {E R} (t1 t2 : itree E R),
    sutt eq t1 t2 trace_incl t1 t2.
Proof.
  red. intros. red in H0. remember (observe t1).
  generalize dependent t1. generalize dependent t2.
  induction H0; intros; try solve [constructor].
  - punfold H. rewrite <- Heqi in H.
    remember (RetF _). remember (observe t2).
    generalize dependent t2.
    induction H; intros; try inv Heqi0; red; rewrite <- Heqi1; constructor.
    eapply IHsuttF; eauto.
  - apply IHis_traceF with (t1:=t); auto.
    apply sutt_inv_tau_left. red. red in H. rewrite <- Heqi in H. auto.
  - punfold H. rewrite <- Heqi in H.
    remember (VisF _ _). remember (observe t2).
    generalize dependent t2.
    induction H; intros; try discriminate.
    + inv_Vis. subst. red. rewrite <- Heqi1. constructor.
    + red. rewrite <- Heqi1. constructor. eapply IHsuttF; eauto.
  - punfold H. rewrite <- Heqi in H.
    remember (VisF _ _). remember (observe t2).
    generalize dependent t2.
    induction H; intros; try discriminate.
    + inv_Vis. pclearbot. subst. red. rewrite <- Heqi1. constructor.
      eapply IHis_traceF; auto with itree.
    + red. rewrite <- Heqi1. constructor. apply IHsuttF; auto.
Qed.

Lemma eutt_trace_eq : {E R} (t1 t2 : itree E R),
    t1 t2 trace_eq t1 t2.
Proof.
  split.
  - apply sutt_trace_incl; apply eutt_sutt; auto.
  - symmetry in H. apply sutt_trace_incl; apply eutt_sutt; auto.
Qed.

Lemma eq_trace_inv {E R} (t1 t2 : @trace E R) (H : t1 = t2)
  : match t1, t2 with
    | TEnd, TEndTrue
    | TRet r1, TRet r2r1 = r2
    | TEventEnd e1, TEventEnd e2 p, eqeq E p e1 e2
    | TEventResponse e1 x1 t1, TEventResponse e2 x2 t2
       p, eqeq E p e1 e2 eqeq (fun XX) p x1 x2 t1 = t2
    | _, _False
    end.
Proof.
  destruct H, t1; auto.
  - eq_refl; cbn; auto.
  - eq_refl; cbn; auto.
Qed.

Lemma trace_incl_sutt : {E R} (t1 t2 : itree E R),
    trace_incl t1 t2 sutt eq t1 t2.
Proof.
  intros E R. pcofix CIH. pstep. intros t1 t2 Hincl.
  unfold trace_incl in ×. unfold is_trace in ×.
  destruct (observe t1).
  - assert (H : is_traceF (RetF r0 : itreeF E R (itree E R)) (TRet r0)) by constructor.
    apply Hincl in H. clear Hincl. destruct (observe t2); inv H.
    + constructor. auto.
    + constructor.
      remember (observe t). remember (TRet _).
      generalize dependent t.
      induction H1; intros; try inv Heqt0; auto with itree.
      constructor. eapply IHis_traceF; eauto.
  - constructor. right. apply CIH. intros. apply Hincl. constructor. auto.
  - assert (H: is_traceF (VisF e k) (TEventEnd e)) by constructor.
    apply Hincl in H. destruct (observe t2); inv H.
    + constructor.
      assert ( tr, is_traceF (VisF e k) tr is_traceF (observe t) tr).
      {
        intros. rewrite is_traceF_tau. apply Hincl; auto.
      }
      clear Hincl. rename H into Hincl.
      remember (observe t). remember (TEventEnd _).
      generalize dependent t.
      induction H1; intros; try discriminate.
      × constructor. eapply IHis_traceF; eauto.
        intros. rewrite is_traceF_tau. apply Hincl; auto.
      × apply eq_trace_inv in Heqt0; destruct Heqt0 as [<- <-].
        subst. constructor. intro. right. apply CIH. intros.
        assert (is_traceF (VisF e k) (TEventResponse e x tr)) by (constructor; auto).
        apply Hincl in H1. inv H1. ddestruction. auto.
    + ddestruction. constructor. intro. right. apply CIH. intros.
      assert (is_traceF (VisF e0 k) (TEventResponse e0 x tr)) by (constructor; auto).
      apply Hincl in H0. inv H0. ddestruction; auto.
Qed.

Theorem trace_incl_iff_sutt : {E R} (t1 t2 : itree E R),
    sutt eq t1 t2 trace_incl t1 t2.
Proof.
  split.
  - apply sutt_trace_incl.
  - apply trace_incl_sutt.
Qed.

Lemma trace_eq_eutt : {E R} (t1 t2 : itree E R),
    trace_eq t1 t2 t1 t2.
Proof.
  intros E R t1 t2 [? ?]. apply sutt_eutt.
  - apply trace_incl_sutt; auto.
  - apply trace_incl_sutt in H0. clear H.
    generalize dependent t1. generalize dependent t2. pcofix CIH; pstep; intros.
    punfold H0. induction H0; constructor; try red; pclearbot; eauto with paco itree.
    right. rewrite itree_eta'. eauto with paco itree.
Qed.

Theorem trace_eq_iff_eutt : {E R} (t1 t2 : itree E R),
    t1 t2 trace_eq t1 t2.
Proof.
  split.
  - apply eutt_trace_eq.
  - apply trace_eq_eutt.
Qed.

Inductive event (E : Type Type) : Type :=
| Event : {X}, E X X event E
.

(* step_ ev t' t if t steps to t' (read right to left!)
   with visible event ev. *)

Inductive step_ {E : Type Type} {R : Type}
          (ev : event E) (t' : itree E R) :
  itree E R Prop :=
| StepTau : t, step_ ev t' t step_ ev t' (Tau t)
| StepVis : X (e : E X) (x : X) k,
    ev = Event _ e x
    t' = k x
    step_ ev t' (Vis e k)
.

Definition step {E : Type Type} {R : Type}
           (ev : event E) (t t' : itree E R) : Prop :=
  step_ ev t' t.

CoInductive simulates {E : Type Type} {R : Type} :
  itree E R itree E R Prop :=
| SimStep : t1 t2,
    ( ev t1',
        step ev t1 t1'
         t2', step ev t2 t2' simulates t1' t2')
    simulates t1 t2.

Theorem simulates_trace_incl {E : Type Type} {R : Type} :
   t1 t2 : itree E R,
    simulates t1 t2 trace_incl t1 t2.
Proof.
Abort.

(* Set-of-traces monad *)
Definition traces (E : Type Type) (R : Type) : Type :=
  @trace E R Prop.

Definition bind_traces {E : Type Type} {R S : Type}
           (ts : traces E R) (kts : R traces E S) : traces E S :=
  fun tr
    (tr = TEnd ts TEnd)
    ( X (e : E X), tr = TEventEnd e ts (TEventEnd e))
    ( r tr1 tr2,
        tr = app_trace tr1 tr2
        trace_ret tr1 = Some r
        ts tr1
        kts r tr).

Definition ret_traces {E : Type Type} {R : Type} :
  R traces E R :=
  fun r tr
    tr = TEnd tr = TRet r.