clutch.meas_lang.lang
(* From HB Require Import structures. *)
(* From Stdlib Require Import Logic.ClassicalEpsilon Psatz. *)
(* From stdpp Require Import base numbers binders strings gmap. *)
(* From mathcomp Require Import reals. *)
(* From mathcomp.analysis Require Import measure lebesgue_measure. *)
(* From mathcomp Require Import ssrbool all_algebra eqtype choice boolp fintype. *)
(* From iris.algebra Require Export ofe. *)
(* From clutch.prelude Require Export stdpp_ext. *)
(* From clutch.common Require Export locations. *)
(* From clutch.meas_lang Require Import ectxi_language ectx_language. *)
(* From Stdlib Require Export Reals. *)
(* From clutch.prob.monad Require Export laws. *)
(* From mathcomp.analysis Require Export Rstruct. *)
(* From mathcomp Require Import classical_sets. *)
(* Fix giryM to be the giry type with stdlib-valued real numbers *)
(* Notation giryM := (giryM (R := R)). *)
(* (* *)
(* From Stdlib Require Import Reals Psatz. *)
(* From stdpp Require Export binders strings. *)
(* From stdpp Require Import fin. *)
(* From stdpp Require Import gmap fin_maps countable fin. *)
(* From clutch.prob Require Export distribution. *)
(* From clutch.common Require Export language ectx_language ectxi_language locations. *)
(* From iris.prelude Require Import options. *)
(* From mathcomp Require Import ssrbool eqtype fintype choice all_algebra finmap. *)
(* From mathcomp Require Import mathcomp_extra boolp classical_sets functions. *)
(* From mathcomp Require Import cardinality fsbigop. *)
(* From mathcomp.analysis Require Import reals ereal signed normedtype sequences esum numfun measure lebesgue_measure lebesgue_integral. *)
(* *) *)
(* Delimit Scope expr_scope with E. *)
(* Delimit Scope val_scope with V. *)
(* Global Instance classical_eq_dec {T : Type} : EqDecision T. *)
(* Proof. intros ? ?; apply ClassicalEpsilon.excluded_middle_informative. Defined. *)
(* (* Instances for Z *) *)
(* HB.instance Definition _ := gen_eqMixin Z. *)
(* HB.instance Definition _ := gen_choiceMixin Z. *)
(* HB.instance Definition _ := isPointed.Build Z inhabitant. *)
(* (* Instances for loc *) *)
(* HB.instance Definition _ := gen_eqMixin loc. *)
(* HB.instance Definition _ := gen_choiceMixin loc. *)
(* HB.instance Definition _ := isPointed.Build loc inhabitant. *)
(* Module meas_lang. *)
(* (* Type of base_lit, parameterized by leaf types *) *)
(* Inductive base_lit_pre {TZ TB TL TR : Type} : Type := *)
(* | LitInt (n : TZ) *)
(* | LitBool (b : TB) *)
(* | LitUnit *)
(* | LitLoc (l : TL) *)
(* | LitLbl (l : TL) *)
(* | LitReal (r : TR). *)
(* Inductive un_op : Set := *)
(* | NegOp | MinusUnOp. *)
(* Inductive bin_op : Set := *)
(* | PlusOp | MinusOp | MultOp | QuotOp | RemOp (* Arithmetic *) *)
(* | AndOp | OrOp | XorOp (* Bitwise *) *)
(* | ShiftLOp | ShiftROp (* Shifts *) *)
(* | LeOp | LtOp | EqOp (* Relations *) *)
(* | OffsetOp. (* Pointer offset *) *)
(* Inductive expr_pre {TZ TB TL TR : Type} := *)
(* (* Values *) *)
(* | Val (v : val_pre) *)
(* (* Base lambda calculus *) *)
(* | Var (x : string) *)
(* | Rec (f x : binder) (e : expr_pre) *)
(* | App (e1 e2 : expr_pre) *)
(* (* Base types and their operations *) *)
(* | UnOp (op : un_op) (e : expr_pre) *)
(* | BinOp (op : bin_op) (e1 e2 : expr_pre) *)
(* | If (e0 e1 e2 : expr_pre) *)
(* (* Products *) *)
(* | Pair (e1 e2 : expr_pre) *)
(* | Fst (e : expr_pre) *)
(* | Snd (e : expr_pre) *)
(* (* Sums *) *)
(* | InjL (e : expr_pre) *)
(* | InjR (e : expr_pre) *)
(* | Case (e0 e1 e2 : expr_pre) *)
(* (* Heap *) *)
(* | AllocN (e1 e2 : expr_pre) (* Array length and initial value *) *)
(* | Load (e : expr_pre) *)
(* | Store (e1 e2 : expr_pre) *)
(* (* Finite probabilistic choice *) *)
(* | AllocTape (e : expr_pre) *)
(* | Rand (e1 e2 : expr_pre) *)
(* (* Real probabilistic choice *) *)
(* | AllocUTape *)
(* | URand (e : expr_pre) *)
(* (* No-op operator used for cost *) *)
(* | Tick (e : expr_pre ) *)
(* with val_pre {TZ TB TL TR : Type} := *)
(* | LitV (l : @base_lit_pre TZ TB TL TR) *)
(* | RecV (f x : binder) (e : expr_pre) *)
(* | PairV (v1 v2 : val_pre) *)
(* | InjLV (v : val_pre) *)
(* | InjRV (v : val_pre). *)
(* Section expr_algebra. *)
(* (** Defines the sigma algebra over expressions *) *)
(* Local Open Scope classical_set_scope. *)
(* (* FIXME: move *) *)
(* Definition image3 {TA TB TC rT} (A : set TA) (B : set TB) (C : set TC) (f : TA -> TB -> TC -> rT) := *)
(* set z | exists2 x, A x & exists2 y, B y & exists2 w, C w & f x y w = z. *)
(* Arguments image3 _ _ _ _ _ _ _ _ /. *)
(* Definition TZ : measurableType default_measure_display := <<discr Z>>. *)
(* Definition TB : measurableType default_measure_display := <<discr bool>>. *)
(* Definition TL : measurableType default_measure_display := <<discr loc>>. *)
(* Definition TR : measurableType default_measure_display := (R : realType). *)
(* Definition base_lit_S : Type := @base_lit_pre (set TZ) (set TB) (set TL) (set TR). *)
(* Definition val_S : Type := @val_pre (set TZ) (set TB) (set TL) (set TR). *)
(* Definition expr_S : Type := @expr_pre (set TZ) (set TB) (set TL) (set TR). *)
(* Definition base_lit_T : Type := @base_lit_pre TZ TB TL TR. *)
(* Definition val_T : Type := @val_pre TZ TB TL TR. *)
(* Definition expr_T : Type := @expr_pre TZ TB TL TR. *)
(* (* Cylinder constructions *) *)
(* (* Trees with sets on their leaves -> sets of trees with values on their leaves *) *)
(* Definition base_lit_ST (b : base_lit_S) : set base_lit_T := *)
(* match b with *)
(* | LitInt s => image s LitInt *)
(* | LitBool s => image s LitBool *)
(* | LitUnit => set LitUnit *)
(* | LitLoc s => image s LitLoc *)
(* | LitLbl s => image s LitLbl *)
(* | LitReal s => image s LitReal *)
(* end. *)
(* Fixpoint expr_ST (e : expr_S) : set expr_T := *)
(* match e with *)
(* | Val v => image (val_ST v) Val *)
(* | Var x => set (Var x) *)
(* | Rec f x e => image (expr_ST e) (Rec f x) *)
(* | App e1 e2 => image2 (expr_ST e1) (expr_ST e2) App *)
(* | UnOp op e => image (expr_ST e) (UnOp op) *)
(* | BinOp op e1 e2 => image2 (expr_ST e1) (expr_ST e2) (BinOp op) *)
(* | If e0 e1 e2 => image3 (expr_ST e0) (expr_ST e1) (expr_ST e2) If *)
(* | Pair e1 e2 => image2 (expr_ST e1) (expr_ST e2) Pair *)
(* | Fst e1 => image (expr_ST e1) Fst *)
(* | Snd e1 => image (expr_ST e1) Snd *)
(* | InjL e1 => image (expr_ST e1) InjL *)
(* | InjR e1 => image (expr_ST e1) InjR *)
(* | Case e0 e1 e2 => image3 (expr_ST e0) (expr_ST e1) (expr_ST e2) Case *)
(* | AllocN e1 e2 => image2 (expr_ST e1) (expr_ST e2) AllocN *)
(* | Load e => image (expr_ST e) Load *)
(* | Store e1 e2 => image2 (expr_ST e1) (expr_ST e2) Store *)
(* | AllocTape e => image (expr_ST e) AllocTape *)
(* | Rand e1 e2 => image2 (expr_ST e1) (expr_ST e2) Rand *)
(* | AllocUTape => set AllocUTape *)
(* | URand e => image (expr_ST e) URand *)
(* | Tick e => image (expr_ST e) Tick *)
(* end *)
(* with *)
(* val_ST (v : val_S) : set val_T := *)
(* match v with *)
(* | LitV b => image (base_lit_ST b) LitV *)
(* | RecV f x e => image (expr_ST e) (RecV f x) *)
(* | PairV v1 v2 => image2 (val_ST v1) (val_ST v2) PairV *)
(* | InjLV v => image (val_ST v) InjLV *)
(* | InjRV v => image (val_ST v) InjRV *)
(* end. *)
(* (* All trees with measurable sets on their leaves *) *)
(* Definition base_lit_ML : set base_lit_S := *)
(* fun b => *)
(* match b with *)
(* | LitInt s => measurable s *)
(* | LitBool s => measurable s *)
(* | LitUnit => True *)
(* | LitLoc s => measurable s *)
(* | LitLbl s => measurable s *)
(* | LitReal s => measurable s *)
(* end. *)
(* Fixpoint expr_ML (e : expr_S) : Prop := *)
(* match e with *)
(* | Val v => val_ML v *)
(* | Var x => True *)
(* | Rec f x e => expr_ML e *)
(* | App e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | UnOp op e => expr_ML e *)
(* | BinOp op e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | If e0 e1 e2 => expr_ML e0 /\ expr_ML e1 /\ expr_ML e2 *)
(* | Pair e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | Fst e1 => expr_ML e1 *)
(* | Snd e1 => expr_ML e1 *)
(* | InjL e1 => expr_ML e1 *)
(* | InjR e1 => expr_ML e1 *)
(* | Case e0 e1 e2 => expr_ML e0 /\ expr_ML e1 /\ expr_ML e2 *)
(* | AllocN e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | Load e => expr_ML e *)
(* | Store e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | AllocTape e => expr_ML e *)
(* | Rand e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | AllocUTape => True *)
(* | URand e => expr_ML e *)
(* | Tick e => expr_ML e *)
(* end *)
(* with *)
(* val_ML (v : val_S) : Prop := *)
(* match v with *)
(* | LitV b => base_lit_ML b *)
(* | RecV f x e => expr_ML e *)
(* | PairV v1 v2 => val_ML v1 /\ val_ML v2 *)
(* | InjLV v => val_ML v *)
(* | InjRV v => val_ML v *)
(* end. *)
(* (* Cylinders: Generators for the sigma algebra *) *)
(* Definition base_lit_cyl : set (set base_lit_T) := image base_lit_ML base_lit_ST. *)
(* Definition expr_cyl : set (set expr_T) := image expr_ML expr_ST. *)
(* Definition val_cyl : set (set val_T) := image val_ML val_ST. *)
(* (* Generate sigma algebras from the cylinders *) *)
(* HB.instance Definition _ := gen_eqMixin base_lit_T. *)
(* HB.instance Definition _ := gen_choiceMixin base_lit_T. *)
(* HB.instance Definition _ := isPointed.Build base_lit_T LitUnit. *)
(* HB.instance Definition _ := gen_eqMixin val_T. *)
(* HB.instance Definition _ := gen_choiceMixin val_T. *)
(* HB.instance Definition _ := isPointed.Build val_T (LitV LitUnit). *)
(* HB.instance Definition _ := gen_eqMixin expr_T. *)
(* HB.instance Definition _ := gen_choiceMixin expr_T. *)
(* HB.instance Definition _ := isPointed.Build expr_T (Val (LitV LitUnit)). *)
(* (* FIXME: Remove! *) *)
(* Local Lemma base_lit_meas_obligation : *)
(* ∀ A : set base_lit_T, <<s base_lit_cyl>> A → <<s base_lit_cyl >> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* Local Lemma val_meas_obligation : *)
(* ∀ A : set val_T, <<s val_cyl>> A → <<s val_cyl >> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* Local Lemma expr_meas_obligation : *)
(* ∀ A : set expr_T, <<s expr_cyl>> A → <<s expr_cyl >> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display base_lit_cyl) *)
(* base_lit_T *)
(* <<s base_lit_cyl>> *)
(* (@sigma_algebra0 _ setT base_lit_cyl) *)
(* base_lit_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT base_lit_cyl). *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display val_cyl) *)
(* val_T *)
(* <<s val_cyl>> *)
(* (@sigma_algebra0 _ setT val_cyl) *)
(* val_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT val_cyl). *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display expr_cyl) *)
(* expr_T *)
(* <<s expr_cyl>> *)
(* (@sigma_algebra0 _ setT expr_cyl) *)
(* expr_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT expr_cyl). *)
(* (* User-facing types *) *)
(* Definition base_lit : measurableType base_lit_cyl.-sigma := base_lit_T. *)
(* Definition expr : measurableType expr_cyl.-sigma := expr_T. *)
(* Definition val : measurableType val_cyl.-sigma := val_T. *)
(* End expr_algebra. *)
(* (** General lemmas about tapes *) *)
(* Definition tape_content_t (A : Type) : Type := nat -> option A. *)
(* Record tape (A : Type) : Type := { *)
(* tape_position : nat; *)
(* tape_contents : tape_content_t A *)
(* }. *)
(* Definition emptyTapeContents {A : Type} : tape_content_t A := fun _ => None. *)
(* Definition emptyTape {A : Type} : tape A := *)
(* {| tape_position := 0 ; *)
(* tape_contents := emptyTapeContents *)
(* |}. *)
(* (* History lookup: look through absolute history *) *)
(* Global Instance tape_content_lookup {A} : Lookup nat A (tape_content_t A) := fun i => fun h => h i. *)
(* (** Specialize tapes to btapes and utapes, construct siga algebra *) *)
(* Section tapes_algebra. *)
(* Local Open Scope classical_set_scope. *)
(* (* Tapes in the computable fragment *) *)
(* Record pre_btape : Type := { *)
(* btape_tape :> tape nat; *)
(* btape_bound : nat *)
(* }. *)
(* (* Tapes of real numbers *) *)
(* Definition pre_utape : Type := tape R. *)
(* (* FIXME: move *) *)
(* Definition image4 {TA TB TC TD rT} (A : set TA) (B : set TB) (C : set TC) (D : set TD) (f : TA -> TB -> TC -> TD -> rT) := *)
(* set z | exists2 x, A x & exists2 y, B y & exists2 w, C w & exists2 v, D v & f x y w v = z. *)
(* Arguments image4 _ _ _ _ _ _ _ _ _ /. *)
(* Definition btape_basis_emp : set (set pre_btape) := *)
(* let bound_set : set nat := setT in *)
(* let pos_set : set nat := setT in *)
(* (* The set of all btapes such that *)
(* - the bound is b *)
(* - the position is p *)
(* - the content is empty *) *)
(* let construct b p := *)
(* set {| btape_tape := {| tape_position := p; tape_contents := (fun _ => None) |} ; *)
(* btape_bound := b |}] in *)
(* image2 bound_set pos_set construct. *)
(* Program Definition btape_basis_full : set (set pre_btape) := *)
(* let bound_set : set nat := setT in *)
(* let pos_set : set nat := setT in *)
(* let index_set : set nat := setT in *)
(* let value_set : set nat := setT in *)
(* (* The set of all btapes such that *)
(* - the bound is b *)
(* - the position is p *)
(* - the content at index i is set to the value v *) *)
(* let construct b p i v := *)
(* (fun bt => *)
(* exists contents, *)
(* bt = {| btape_tape := {| tape_position := p; tape_contents := contents |}; btape_bound := b|} /\ *)
(* contents !! i = Some v) in *)
(* image4 bound_set pos_set index_set value_set construct. *)
(* Definition btape_basis := btape_basis_emp `|` btape_basis_full. *)
(* HB.instance Definition _ := gen_eqMixin pre_btape. *)
(* HB.instance Definition _ := gen_choiceMixin pre_btape. *)
(* HB.instance Definition _ := isPointed.Build pre_btape {| btape_tape := emptyTape ; btape_bound := 0 |}. *)
(* Local Lemma btape_meas_obligation : ∀ A : set pre_btape, <<s btape_basis>> A → <<s btape_basis>> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display btape_basis) *)
(* pre_btape *)
(* <<s btape_basis>> *)
(* (@sigma_algebra0 _ setT btape_basis) *)
(* btape_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT btape_basis). *)
(* Definition utape_basis_emp : set (set pre_utape) := *)
(* let pos_set : set nat := setT in *)
(* (* The set of all utapes such that *)
(* - the position is p *)
(* - the content is empty *) *)
(* let construct p := *)
(* set {| tape_position := p; tape_contents := (fun _ => None) |} in *)
(* image pos_set construct. *)
(* (* FIXME: This should not return a singleton! *) *)
(* Definition utape_basis_full : set (set pre_utape) := *)
(* let pos_set : set nat := setT in *)
(* let index_set : set nat := setT in *)
(* let value_set : set (set (R : realType)) := 'measurable in *)
(* (* The set of all utapes such that *)
(* - the position is p *)
(* - the content at position i is set to some value in set_of_v *) *)
(* let construct p i set_of_v := *)
(* (fun ut => *)
(* exists contents r, *)
(* ut = {| tape_position := p; tape_contents := contents |} /\ *)
(* contents !! i = Some r /\ *)
(* set_of_v r) in *)
(* image3 pos_set index_set value_set construct. *)
(* Definition utape_basis : set (set pre_utape) := utape_basis_emp `|` utape_basis_full. *)
(* HB.instance Definition _ := gen_eqMixin pre_utape. *)
(* HB.instance Definition _ := gen_choiceMixin pre_utape. *)
(* HB.instance Definition _ := isPointed.Build pre_utape emptyTape. *)
(* Local Lemma utape_meas_obligation : ∀ A : set pre_utape, <<s utape_basis>> A → <<s utape_basis>> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display utape_basis) *)
(* pre_utape *)
(* <<s utape_basis>> *)
(* (@sigma_algebra0 _ setT utape_basis) *)
(* utape_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT utape_basis). *)
(* (* User-facing types *) *)
(* Definition btape : measurableType btape_basis.-sigma := pre_btape. *)
(* Definition utape : measurableType utape_basis.-sigma := pre_utape. *)
(* End tapes_algebra. *)
(* (* btape and utape definitions *) *)
(* (* All values of the tape are within the tape bound *) *)
(* Definition btape_inbounds (t : btape): Prop := *)
(* forall n : nat, *)
(* tape_contents _ t n = None \/ *)
(* exists v : nat, tape_contents _ t n = Some v /\ v < btape_bound t. *)
(* (* All tape values prior to state have been determined *) *)
(* Definition tape_history_deterministic {A} (t : tape A) : Prop := *)
(* forall i : nat, i < tape_position _ t -> exists v : A, tape_contents _ t i = Some v. *)
(* (* Tape lookup: look relative to current index. t !! 0 will be the next sample. *) *)
(* Global Instance tape_rel_lookup {A} : Lookup nat A (tape A) := fun i => fun t => (tape_contents _ t (i + tape_position _ t)). *)
(* Definition tape_content_update_unsafe {A} (i : nat) (v : option A) (h : tape_content_t A) : tape_content_t A *)
(* := fun i' => if i' =? i then v else h i'. *)
(* Global Instance tape_content_insert {A} : Insert nat (option A) (tape_content_t A) := tape_content_update_unsafe. *)
(* Definition tapeUpdateUnsafe {A} (i : nat) (v : option A) (t : tape A) : tape A := *)
(* {| tape_position := tape_position _ t; *)
(* tape_contents := < (i + tape_position _ t) := v > (tape_contents _ t) *)
(* |}. *)
(* Global Instance tape_insert {A} : Insert nat (option A) (tape A) := tapeUpdateUnsafe. *)
(* Program Definition tapeAdvance {A} (t : tape A) : tape A *)
(* := {| tape_position := 1 + tape_position _ t; tape_contents := tape_contents _ t |}. *)
(* (* Advance the tape by 1, returning an updated tape and the first sample on the tape. *) *)
(* Program Definition tapeNext {A} (t : tape A) (H : isSome (t !! 0)) : A * (tape A) *)
(* := match (t !! 0) with *)
(* | None => _ *)
(* | Some v => *)
(* (v, *)
(* {| tape_position := 1 + tape_position _ t; *)
(* tape_contents := tape_contents _ t |}) *)
(* end. *)
(* Next Obligation. by move=>/= ? ? H1 H2; symmetry in H2; rewrite H2//= in H1. Defined. *)
(* (* Representation predicates for common tape structures *) *)
(* Definition tapeHasPrefix {A} (t : tape A) (l : list A) : Prop *)
(* := forall i : nat, i < length l -> t !! i = l !! i. *)
(* Definition tapeEmptyAfter {A} (t : tape A) (b : nat) : Prop *)
(* := forall i : nat, i >= b -> t !! i = None. *)
(* (* Tapes a la base clutch *) *)
(* Definition isFiniteTape (t : btape) (l : list nat) : Prop *)
(* := tapeHasPrefix t l *)
(* /\ tapeEmptyAfter t (length l) *)
(* /\ btape_inbounds t *)
(* /\ tape_history_deterministic t. *)
(* (* TODO: realIsBinarySequence (cannonical form w/ 0-termination on dyadic numbers) *) *)
(* Definition tapeHasInfinitePrefix {A} (t : tape A) (f : nat -> A) : Prop *)
(* := forall i : nat, t !! i = Some (f i). *)
(* (* TODO: tapeIsRealInRange (l : R) ... := bound = 1, tapeHasInfinitePrefic *) *)
(* (* tapeOfReal ... ?*) *)
(* (* Tape with "Junk" prefix *) *)
(* Definition tapeHasEventually {A} (t : tape A) (l : list A) : Prop *)
(* := exists offset: nat, forall i : nat, i < length l -> t !! (i + offset) = l !! i. *)
(* Global Instance tape_inhabited {A} : Inhabited (tape A) := populate emptyTape. *)
(* Global Instance tapes_lookup_total {A} : LookupTotal loc (tape A) (gmap loc (tape A)). *)
(* Proof. apply map_lookup_total. Defined. *)
(* Global Instance tapes_insert {A} : Insert loc (tape A) (gmap loc (tape A)). *)
(* Proof. apply map_insert. Defined. *)
(* Bind Scope expr_scope with expr. *)
(* Bind Scope val_scope with val. *)
(* Notation of_val := Val (only parsing). *)
(* Definition to_val (e : expr) : option val := *)
(* match e with *)
(* | Val v => Some v *)
(* | _ => None *)
(* end. *)
(* Section state_algebra. *)
(* Local Open Scope classical_set_scope. *)
(* (** The state: a loc-indexed heap of vals, and loc-indexed tapes, and loc-indexed utapes *) *)
(* Record state_pre : Type := { *)
(* heap : gmap loc val; *)
(* tapes : gmap loc btape; *)
(* utapes : gmap loc utape *)
(* }. *)
(* Definition gmap_loc_cyl_emp d (T : measurableType d) : set (set (gmap loc T)) := *)
(* set (fun g => forall l, g !! l = None). *)
(* Definition gmap_loc_cyl_full d (T : measurableType d) : set (set (gmap loc T)) := *)
(* let loc_set : set loc := setT in *)
(* let T_set : set (set T) := d.-measurable in *)
(* (* The set of all gmaps such that *)
(* - the value at position l is set to an element in the set ts *) *)
(* let construct (l : loc) (ts : set T) : set (gmap loc T) := *)
(* fun g => exists v : T, g !! l = Some v /\ ts v in *)
(* image2 loc_set T_set construct. *)
(* Definition gmap_loc_cyl d (T : measurableType d) : set (set (gmap loc T)) := *)
(* gmap_loc_cyl_emp d T `|` gmap_loc_cyl_full d T. *)
(* (* The set of all states such that *)
(* each field is a gmap cylinder *)
(* *) *)
(* Program Definition state_cyl : set (set state_pre) := *)
(* let hs_set := gmap_loc_cyl _ val in *)
(* let ts_set := gmap_loc_cyl _ btape in *)
(* let us_set := gmap_loc_cyl _ utape in *)
(* let construct (hs : set (gmap loc val)) (ht : set (gmap loc btape)) (hu : set (gmap loc utape)) : set state_pre := *)
(* fun σ => *)
(* exists g1 : gmap loc val, *)
(* exists g2 : gmap loc btape, *)
(* exists g3 : gmap loc utape, *)
(* σ = {| heap := g1; tapes := g2; utapes := g3|} /\ *)
(* hs g1 /\ *)
(* ht g2 /\ *)
(* hu g3 *)
(* in *)
(* image3 hs_set ts_set us_set construct. *)
(* HB.instance Definition _ := gen_eqMixin state_pre. *)
(* HB.instance Definition _ := gen_choiceMixin state_pre. *)
(* HB.instance Definition _ := isPointed.Build state_pre {| heap := gmap_empty; tapes := gmap_empty; utapes := gmap_empty |}. *)
(* Local Lemma state_pre_meas_obligation : ∀ A : set state_pre, <<s state_cyl>> A → <<s state_cyl>> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* (* There's got to be a way to delete this *) *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display state_cyl) *)
(* state_pre *)
(* <<s state_cyl>> *)
(* (@sigma_algebra0 _ setT state_cyl) *)
(* state_pre_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT state_cyl). *)
(* Definition state : measurableType state_cyl.-sigma := state_pre. *)
(* End state_algebra. *)
(* (** Equality and other typeclass stuff *) *)
(* Lemma to_of_val v : to_val (of_val v) = Some v. *)
(* Proof. by destruct v. Qed. *)
(* Lemma of_to_val e v : to_val e = Some v → of_val v = e. *)
(* Proof. destruct e=>//=. by intros = <-. Qed. *)
(* (* FIXME *)
(* Global Instance of_val_inj : Inj (=) (=) of_val. *)
(* Proof. intros ??. congruence. Qed. *)
(* *) *)
(* (* *)
(* Global Instance state_inhabited : Inhabited state := populate {| heap := gmap_empty; tapes := gmap_empty; utapes := gmap_empty |}. *)
(* Global Instance val_inhabited : Inhabited val := populate (LitV LitUnit). *)
(* Global Instance expr_inhabited : Inhabited expr := populate (Val inhabitant). *)
(* *) *)
(* Canonical Structure stateO := leibnizO state. *)
(* Canonical Structure locO := leibnizO loc. *)
(* Canonical Structure valO := leibnizO val. *)
(* Canonical Structure exprO := leibnizO expr. *)
(* (** Evaluation contexts *) *)
(* Inductive ectx_item := *)
(* | AppLCtx (v2 : val) *)
(* | AppRCtx (e1 : expr) *)
(* | UnOpCtx (op : un_op) *)
(* | BinOpLCtx (op : bin_op) (v2 : val) *)
(* | BinOpRCtx (op : bin_op) (e1 : expr) *)
(* | IfCtx (e1 e2 : expr) *)
(* | PairLCtx (v2 : val) *)
(* | PairRCtx (e1 : expr) *)
(* | FstCtx *)
(* | SndCtx *)
(* | InjLCtx *)
(* | InjRCtx *)
(* | CaseCtx (e1 : expr) (e2 : expr) *)
(* | AllocNLCtx (v2 : val) *)
(* | AllocNRCtx (e1 : expr) *)
(* | LoadCtx *)
(* | StoreLCtx (v2 : val) *)
(* | StoreRCtx (e1 : expr) *)
(* | AllocTapeCtx *)
(* | RandLCtx (v2 : val) *)
(* | RandRCtx (e1 : expr) *)
(* | URandCtx *)
(* | TickCtx. *)
(* (* FIXME: Hide cosntructors, so that we don't need to mention base_lit *) *)
(* (* *)
(* Definition fill_item (Ki : ectx_item) (e : expr) : expr := *)
(* match Ki with *)
(* | AppLCtx v2 => App e (of_val v2) *)
(* | AppRCtx e1 => App e1 e *)
(* | UnOpCtx op => UnOp op e *)
(* | BinOpLCtx op v2 => BinOp op e (Val v2) *)
(* | BinOpRCtx op e1 => BinOp op e1 e *)
(* | IfCtx e1 e2 => If e e1 e2 *)
(* | PairLCtx v2 => Pair e (Val v2) *)
(* | PairRCtx e1 => Pair e1 e *)
(* | FstCtx => Fst e *)
(* | SndCtx => Snd e *)
(* | InjLCtx => InjL e *)
(* | InjRCtx => InjR e *)
(* | CaseCtx e1 e2 => Case e e1 e2 *)
(* | AllocNLCtx v2 => AllocN e (Val v2) *)
(* | AllocNRCtx e1 => AllocN e1 e *)
(* | LoadCtx => Load e *)
(* | StoreLCtx v2 => Store e (Val v2) *)
(* | StoreRCtx e1 => Store e1 e *)
(* | AllocTapeCtx => AllocTape e *)
(* | RandLCtx v2 => Rand e (Val v2) *)
(* | RandRCtx e1 => Rand e1 e *)
(* | URandCtx => URand e *)
(* | TickCtx => Tick e *)
(* end. *)
(* Definition decomp_item (e : expr) : option (ectx_item * expr) := *)
(* let noval (e : expr) (ei : ectx_item) := *)
(* match e with Val _ => None | _ => Some (ei, e) end in *)
(* match e with *)
(* | App e1 e2 => *)
(* match e2 with *)
(* | (Val v) => noval e1 (AppLCtx v) *)
(* | _ => Some (AppRCtx e1, e2) *)
(* end *)
(* | UnOp op e => noval e (UnOpCtx op) *)
(* | BinOp op e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (BinOpLCtx op v) *)
(* | _ => Some (BinOpRCtx op e1, e2) *)
(* end *)
(* | If e0 e1 e2 => noval e0 (IfCtx e1 e2) *)
(* | Pair e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (PairLCtx v) *)
(* | _ => Some (PairRCtx e1, e2) *)
(* end *)
(* | Fst e => noval e FstCtx *)
(* | Snd e => noval e SndCtx *)
(* | InjL e => noval e InjLCtx *)
(* | InjR e => noval e InjRCtx *)
(* | Case e0 e1 e2 => noval e0 (CaseCtx e1 e2) *)
(* | AllocN e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (AllocNLCtx v) *)
(* | _ => Some (AllocNRCtx e1, e2) *)
(* end *)
(* | Load e => noval e LoadCtx *)
(* | Store e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (StoreLCtx v) *)
(* | _ => Some (StoreRCtx e1, e2) *)
(* end *)
(* | AllocTape e => noval e AllocTapeCtx *)
(* | Rand e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (RandLCtx v) *)
(* | _ => Some (RandRCtx e1, e2) *)
(* end *)
(* | URand e => noval e URandCtx *)
(* | Tick e => noval e TickCtx *)
(* | _ => None *)
(* end. *)
(* (** Substitution *) *)
(* Fixpoint subst (x : string) (v : val) (e : expr) : expr := *)
(* match e with *)
(* | Val _ => e *)
(* | Var y => if decide (x = y) then Val v else Var y *)
(* | Rec f y e => *)
(* Rec f y *)
(* | App e1 e2 => App (subst x v e1) (subst x v e2) *)
(* | UnOp op e => UnOp op (subst x v e) *)
(* | BinOp op e1 e2 => BinOp op (subst x v e1) (subst x v e2) *)
(* | If e0 e1 e2 => If (subst x v e0) (subst x v e1) (subst x v e2) *)
(* | Pair e1 e2 => Pair (subst x v e1) (subst x v e2) *)
(* | Fst e => Fst (subst x v e) *)
(* | Snd e => Snd (subst x v e) *)
(* | InjL e => InjL (subst x v e) *)
(* | InjR e => InjR (subst x v e) *)
(* | Case e0 e1 e2 => Case (subst x v e0) (subst x v e1) (subst x v e2) *)
(* | AllocN e1 e2 => AllocN (subst x v e1) (subst x v e2) *)
(* | Load e => Load (subst x v e) *)
(* | Store e1 e2 => Store (subst x v e1) (subst x v e2) *)
(* | AllocTape e => AllocTape (subst x v e) *)
(* | AllocUTape => AllocUTape *)
(* | Rand e1 e2 => Rand (subst x v e1) (subst x v e2) *)
(* | URand e => URand (subst x v e) *)
(* | Tick e => Tick (subst x v e) *)
(* end. *)
(* Definition subst' (mx : binder) (v : val) : expr → expr := *)
(* match mx with BNamed x => subst x v | BAnon => λ x, x end. *)
(* (** The stepping relation *) *)
(* Definition un_op_eval (op : un_op) (v : val) : option val := *)
(* match op, v with *)
(* | NegOp, LitV (LitBool b) => Some LitBool (negb b) *)
(* | NegOp, LitV (LitInt z) => Some LitInt (Z.lnot z) *)
(* | MinusUnOp, LitV (LitInt z) => Some LitInt (- z) *)
(* | MinusUnOp, LitV (LitReal r) => Some LitReal (- r)*)
(* | _, _ => None *)
(* end. *)
(* Definition bin_op_eval_int (op : bin_op) (n1 n2 : Z) : base_lit := *)
(* match op with *)
(* | PlusOp => LitInt (n1 + n2) *)
(* | MinusOp => LitInt (n1 - n2) *)
(* | MultOp => LitInt (n1 * n2) *)
(* | QuotOp => LitInt (n1 `quot` n2) *)
(* | RemOp => LitInt (n1 `rem` n2) *)
(* | AndOp => LitInt (Z.land n1 n2) *)
(* | OrOp => LitInt (Z.lor n1 n2) *)
(* | XorOp => LitInt (Z.lxor n1 n2) *)
(* | ShiftLOp => LitInt (n1 ≪ n2) *)
(* | ShiftROp => LitInt (n1 ≫ n2) *)
(* | LeOp => LitBool (bool_decide (n1 ≤ n2)) *)
(* | LtOp => LitBool (bool_decide (n1 < n2)) *)
(* | EqOp => LitBool (bool_decide (n1 = n2)) *)
(* | OffsetOp => LitInt (n1 + n2) (* Treat offsets as ints *) *)
(* end*)
(* Definition bin_op_eval_bool (op : bin_op) (b1 b2 : bool) : option base_lit := *)
(* match op with *)
(* | PlusOp | MinusOp | MultOp | QuotOp | RemOp => None (* Arithmetic *) *)
(* | AndOp => Some (LitBool (b1 && b2)) *)
(* | OrOp => Some (LitBool (b1 || b2)) *)
(* | XorOp => Some (LitBool (xorb b1 b2)) *)
(* | ShiftLOp | ShiftROp => None (* Shifts *) *)
(* | LeOp | LtOp => None (* InEquality *) *)
(* | EqOp => Some (LitBool (bool_decide (b1 = b2))) *)
(* | OffsetOp => None *)
(* end. *)
(* Definition bin_op_eval_loc (op : bin_op) (l1 : loc) (v2 : base_lit) : option base_lit := *)
(* match op, v2 with *)
(* | OffsetOp, LitInt off => Some *)
(* | LeOp, LitLoc l2 => Some *)
(* | LtOp, LitLoc l2 => Some *)
(* | _, _ => None *)
(* end. *)
(* Definition bin_op_eval_real (op : bin_op) (r1 r2 : R) : option base_lit := *)
(* match op with *)
(* | PlusOp => Some *)
(* | MinusOp => Some *)
(* | MultOp => Some *)
(* | LeOp => Some bool_decide *)
(* | LtOp => Some bool_decide *)
(* | EqOp => Some bool_decide *)
(* | _ => None *)
(* end*)
(* Definition bin_op_eval (op : bin_op) (v1 v2 : val) : option val := *)
(* if decide (op = EqOp) then *)
(* if decide (v1 = v2) then *)
(* Some LitBool *)
(* else *)
(* None *)
(* else *)
(* match v1 , v2 with *)
(* | LitV (LitInt n1), LitV (LitInt n2) => Some bin_op_eval_int op n1 n2 *)
(* | LitV (LitReal r1), LitV (LitReal r2) => LitV <*)
(* | LitV (LitBool b1), LitV (LitBool b2) => LitV <*)
(* | LitV (LitLoc l1), LitV v2 => LitV <*)
(* | _, _ => None *)
(* end. *)
(* Definition state_upd_heap (f : gmap loc val → gmap loc val) (σ : state) : state := *)
(* {| heap := f σ.(heap); tapes := σ.(tapes); utapes := σ.(utapes) |}. *)
(* Global Arguments state_upd_heap _ !_ /. *)
(* Definition state_upd_tapes (f : gmap loc btape → gmap loc btape) (σ : state) : state := *)
(* {| heap := σ.(heap); tapes := f σ.(tapes); utapes := σ.(utapes) |}. *)
(* Global Arguments state_upd_tapes _ !_ /. *)
(* Definition state_upd_utapes (f : gmap loc utape → gmap loc utape) (σ : state) : state := *)
(* {| heap := σ.(heap); tapes := σ.(tapes); utapes := f σ.(utapes) |}. *)
(* Global Arguments state_upd_utapes _ !_ /. *)
(* Lemma state_upd_tapes_twice σ l xs ys : *)
(* state_upd_tapes < l := ys > (state_upd_tapes < l := xs > σ) = state_upd_tapes < l:= ys > σ. *)
(* Proof. rewrite /state_upd_tapes /=. f_equal. apply insert_insert_eq. Qed. *)
(* Lemma state_upd_tapes_same σ σ' l xs ys : *)
(* state_upd_tapes <l:=ys> σ = state_upd_tapes <l:=xs> σ' -> xs = ys. *)
(* Proof. rewrite /state_upd_tapes /=. intros K. simplify_eq. *)
(* rewrite map_eq_iff in H. *)
(* specialize (H l). *)
(* rewrite !lookup_insert_eq in H. *)
(* by simplify_eq. *)
(* Qed. *)
(* Lemma state_upd_tapes_no_change σ l ys : *)
(* tapes σ !! l = Some ys -> *)
(* state_upd_tapes <l := ys> σ = σ . *)
(* Proof. *)
(* destruct σ as ? t. simpl. *)
(* intros Ht. *)
(* f_equal. *)
(* apply insert_id. done. *)
(* Qed. *)
(* (* *)
(* Lemma state_upd_tapes_same' σ σ' l n xs (x y : stdpp.fin.fin (S n)) : *)
(* state_upd_tapes <l:=(fin (n; xs++[x]))> σ = state_upd_tapes <l:=(fin(n; xs++[y]))> σ' -> x = y. *)
(* Proof. intros H. apply state_upd_tapes_same in H. by simplify_eq. Qed. *)
(* Lemma state_upd_tapes_neq' σ σ' l n xs (x y : stdpp.fin.fin (S n)) : *)
(* x≠y -> state_upd_tapes <l:=(fin(n; xs++[x]))> σ ≠ state_upd_tapes <l:=(fin(n; xs++[y]))> σ'. *)
(* Proof. move => H /state_upd_tapes_same ?. simplify_eq. Qed. *)
(* *) *)
(* Fixpoint heap_array (l : loc) (vs : list val) : gmap loc val := *)
(* match vs with *)
(* | => ∅ *)
(* | v :: vs' => {l := v} ∪ heap_array (l +ₗ 1) vs' *)
(* end. *)
(* Lemma heap_array_singleton l v : heap_array l v = {l := v}. *)
(* Proof. by rewrite /heap_array right_id. Qed. *)
(* Lemma heap_array_app l vs1 vs2 : heap_array l (vs1 ++ vs2) = (heap_array l vs1) ∪ (heap_array (l +ₗ (length vs1)) vs2) . *)
(* Proof. *)
(* revert l. *)
(* induction vs1; intro l. *)
(* - simpl. *)
(* rewrite map_empty_union loc_add_0 //. *)
(* - rewrite -app_comm_cons /= IHvs1. *)
(* rewrite map_union_assoc. *)
(* do 2 f_equiv. *)
(* rewrite Nat2Z.inj_succ /=. *)
(* rewrite /Z.succ *)
(* Z.add_comm *)
(* loc_add_assoc //. *)
(* Qed. *)
(* Lemma heap_array_lookup l vs v k : *)
(* heap_array l vs !! k = Some v ↔ *)
(* ∃ j, (0 ≤ j)*)
(* Proof. *)
(* revert k l; induction vs as |v' vs IH => l' l /=. *)
(* { rewrite lookup_empty. naive_solver lia. } *)
(* rewrite -insert_union_singleton_l lookup_insert_Some IH. split. *)
(* - intros [-> ?] | (Hl & j & ? & -> & ?). *)
(* { eexists 0. rewrite loc_add_0. naive_solver lia. } *)
(* eexists (1 + j)*)
(* - intros (j & ? & -> & Hil). destruct (decide (j = 0)); simplify_eq/=. *)
(* { rewrite loc_add_0; eauto. } *)
(* right. split. *)
(* { rewrite -{1}(loc_add_0 l). intros ?*)
(* assert (Z.to_nat j = S (Z.to_nat (j - 1))) as Hj. *)
(* { rewrite -Z2Nat.inj_succ; last lia. f_equal; lia. } *)
(* rewrite Hj /= in Hil. *)
(* eexists (j - 1)*)
(* auto with lia. *)
(* Qed. *)
(* Lemma heap_array_map_disjoint (h : gmap loc val) (l : loc) (vs : list val) : *)
(* (∀ i, (0 ≤ i)Z → h !! (l +ₗ i) = None) → *)
(* (heap_array l vs) #ₘ h. *)
(* Proof. *)
(* intros Hdisj. apply map_disjoint_spec=> l' v1 v2. *)
(* intros (j&?&->&Hjinj_lt)*)
(* move: Hj. rewrite Z2Nat.id // => ?. by rewrite Hdisj. *)
(* Qed. *)
(* Definition state_upd_heap_N (l : loc) (n : nat) (v : val) (σ : state) : state := *)
(* state_upd_heap (λ h, heap_array l (replicate n v) ∪ h) σ. *)
(* Lemma state_upd_heap_singleton l v σ : *)
(* state_upd_heap_N l 1 v σ = state_upd_heap <l:= v> σ. *)
(* Proof. *)
(* destruct σ as h p. rewrite /state_upd_heap_N /=. f_equiv. *)
(* rewrite right_id insert_union_singleton_l. done. *)
(* Qed. *)
(* Lemma state_upd_tapes_heap σ l1 l2 xs m v : *)
(* state_upd_tapes <l2:=xs> (state_upd_heap_N l1 m v σ) = *)
(* state_upd_heap_N l1 m v (state_upd_tapes <l2:=xs> σ). *)
(* Proof. *)
(* by rewrite /state_upd_tapes /state_upd_heap_N /=. *)
(* Qed. *)
(* Lemma heap_array_replicate_S_end l v n : *)
(* heap_array l (replicate (S n) v) = heap_array l (replicate n v) ∪ {l +ₗ n:= v}. *)
(* Proof. *)
(* induction n. *)
(* - simpl. *)
(* rewrite map_union_empty. *)
(* rewrite map_empty_union. *)
(* by rewrite loc_add_0. *)
(* - rewrite replicate_S_end *)
(* heap_array_app *)
(* IHn /=. *)
(* rewrite map_union_empty length_replicate //. *)
(* Qed. *)
(* (* [local] Open Scope R. *) *)
(* Section pointed_instances. *)
(* Local Open Scope classical_set_scope. *)
(* (* Fail Check (<<discr state>> : measurableType _). *) *)
(* HB.instance Definition _ := gen_eqMixin state. *)
(* HB.instance Definition _ := gen_choiceMixin state. *)
(* HB.instance Definition _ := isPointed.Build state inhabitant. *)
(* (* Check (<<discr state>> : measurableType _). *) *)
(* (** cfg is pointed (automatic) *) *)
(* (* Check (<<discr cfg>> : measurableType _). *) *)
(* (** state * loc is pointed (automatic) *) *)
(* (* Check (<<discr (state * loc)>> : measurableType _). *) *)
(* (** R is pointed *) *)
(* Check (<<discr R>> : measurableType _). *)
(* End pointed_instances. *)
(* Section meas_semantics. *)
(* Local Open Scope classical_set_scope. *)
(* Local Open Scope expr_scope. *)
(* Definition discr_cfg : measurableType _ := (<<discr expr>> * <<discr state>>)*)
(* Definition head_stepM_def (c : discr_cfg) : giryM discr_cfg := *)
(* let (e1, σ1) := c in *)
(* match e1 with *)
(* | Rec f x e => *)
(* giryM_ret R ((Val *)
(* | Pair (Val v1) (Val v2) => *)
(* giryM_ret R ((Val *)
(* | InjL (Val v) => *)
(* giryM_ret R ((Val *)
(* | InjR (Val v) => *)
(* giryM_ret R ((Val *)
(* | App (Val (RecV f x e1)) (Val v2) => *)
(* giryM_ret R ((subst' x v2 (subst' f (RecV f x e1) e1) , σ1) : discr_cfg) *)
(* | UnOp op (Val v) => *)
(* match un_op_eval op v with *)
(* | Some w => giryM_ret R ((Val w, σ1) : discr_cfg) *)
(* | _ => giryM_zero *)
(* end *)
(* | BinOp op (Val v1) (Val v2) => *)
(* match bin_op_eval op v1 v2 with *)
(* | Some w => giryM_ret R ((Val w, σ1) : discr_cfg) *)
(* | _ => giryM_zero *)
(* end *)
(* | If (Val (LitV (LitBool true))) e1 e2 => *)
(* giryM_ret R ((e1 , σ1) : discr_cfg) *)
(* | If (Val (LitV (LitBool false))) e1 e2 => *)
(* giryM_ret R ((e2 , σ1) : discr_cfg) *)
(* | Fst (Val (PairV v1 v2)) => *)
(* giryM_ret R ((Val v1 , σ1) : discr_cfg) (* Syntax error when I remove the space between v1 and , *) *)
(* | Snd (Val (PairV v1 v2)) => *)
(* giryM_ret R ((Val v2, σ1) : discr_cfg) *)
(* | Case (Val (InjLV v)) e1 e2 => *)
(* giryM_ret R ((App e1 (Val v), σ1) : discr_cfg) *)
(* | Case (Val (InjRV v)) e1 e2 => *)
(* giryM_ret R ((App e2 (Val v), σ1) : discr_cfg) *)
(* | AllocN (Val (LitV (LitInt N))) (Val v) => *)
(* let ℓ := fresh_loc σ1.(heap) in *)
(* if bool_decide (0 < Z.to_nat N)*)
(* then giryM_ret R ((Val LitLoc ℓ, state_upd_heap_N ℓ (Z.to_nat N) v σ1) : discr_cfg) *)
(* else giryM_zero *)
(* | Load (Val (LitV (LitLoc l))) => *)
(* match σ1.(heap) !! l with *)
(* | Some v => giryM_ret R ((Val v, σ1) : discr_cfg) *)
(* | None => giryM_zero *)
(* end *)
(* | Store (Val (LitV (LitLoc l))) (Val w) => *)
(* match σ1.(heap) !! l with *)
(* | Some v => giryM_ret R ((Val *)
(* | None => giryM_zero *)
(* end *)
(* (* Uniform sampling from 0, 1 , ..., N *) *)
(* | Rand (Val (LitV (LitInt N))) (Val (LitV LitUnit)) => *)
(* giryM_map *)
(* (m_discr (fun (n : 'I_(S (Z.to_nat N))) => ((Val LitInt n, σ1) : discr_cfg))) *)
(* (giryM_unif (Z.to_nat N)) *)
(* | AllocTape (Val (LitV (LitInt z))) => *)
(* let ι := fresh_loc σ1.(tapes) in *)
(* giryM_ret R ((Val LitLbl ι, state_upd_tapes <ι := {| btape_tape := emptyTape ; btape_bound := (Z.to_nat z) |} > σ1) : discr_cfg) *)
(* (* Rand with a tape *) *)
(* | Rand (Val (LitV (LitInt N))) (Val (LitV (LitLbl l))) => *)
(* match σ1.(tapes) !! l with *)
(* | Some btape => *)
(* (* There exists a tape with label l *) *)
(* let τ := btape.(btape_tape) in *)
(* let M := btape.(btape_bound) in *)
(* if (bool_decide (M = Z.to_nat N)) then *)
(* (* Tape bounds match *) *)
(* match (τ !! 0) with *)
(* | Some v => *)
(* (* There is a next value on the tape *) *)
(* let σ' := state_upd_tapes < l := {| btape_tape := (tapeAdvance τ); btape_bound := M |} > σ1 in *)
(* (giryM_ret R ((Val LitInt *)
(* | None => *)
(* (* Next slot on tape is empty *) *)
(* giryM_map *)
(* (m_discr (fun (v : 'I_(S (Z.to_nat N))) => *)
(* (* Fill the tape head with new sample *) *)
(* let τ' := < (0 : nat) := Some (v : nat) > τ in *)
(* (* Advance the tape *) *)
(* let σ' := state_upd_tapes < l := {| btape_tape := (tapeAdvance τ'); btape_bound := M |} > σ1 in *)
(* (* Return the new sample and state *) *)
(* ((Val LitInt *)
(* (giryM_unif (Z.to_nat N)) *)
(* end *)
(* else *)
(* (* Tape bounds do not match *) *)
(* (* Do not advance the tape, but still generate a new sample *) *)
(* giryM_map *)
(* (m_discr (fun (n : 'I_(S (Z.to_nat N))) => ((Val LitInt n, σ1) : discr_cfg))) *)
(* (giryM_unif (Z.to_nat N)) *)
(* | None => giryM_zero *)
(* end *)
(* | AllocUTape => *)
(* let ι := fresh_loc σ1.(utapes) in *)
(* giryM_ret R ((Val LitLbl ι, state_upd_utapes < ι := emptyTape > σ1) : discr_cfg) *)
(* (* Urand with no tape *) *)
(* | URand (Val (LitV LitUnit)) => *)
(* giryM_map *)
(* (m_discr (fun u => ((Val LitReal u, σ1) : discr_cfg))) *)
(* giryM_zero *)
(* (* Urand with a tape *) *)
(* | URand (Val (LitV (LitLbl l))) => *)
(* match σ1.(utapes) !! l with *)
(* | Some τ => *)
(* (* tape l is allocated *) *)
(* match (τ !! 0) with *)
(* | Some u => *)
(* (* Head has a sample *) *)
(* let σ' := state_upd_utapes < l := (tapeAdvance τ) > σ1 in *)
(* (giryM_ret R ((Val LitReal u, σ') : discr_cfg)) *)
(* | None => *)
(* (* Head has no sample *) *)
(* giryM_map *)
(* (m_discr (fun (u : R) => *)
(* (* Fill tape head with new sample *) *)
(* let τ' := < (0 : nat) := Some u > τ in *)
(* (* Advance tape *) *)
(* let σ' := state_upd_utapes < l := (tapeAdvance τ') > σ1 in *)
(* (* Return the update value an state *) *)
(* ((Val LitReal u, σ') : discr_cfg))) *)
(* giryM_zero *)
(* end *)
(* | None => giryM_zero *)
(* end *)
(* | Tick (Val (LitV (LitInt n))) => giryM_ret R ((Val LitUnit, σ1) : discr_cfg) *)
(* | _ => giryM_zero *)
(* end. *)
(* (* I don't care if this this true; we will delete it soon and replace it with a proof for the real SA. *) *)
(* Local Lemma head_stepM_def_measurable : *)
(* @measurable_fun _ _ discr_cfg (giryM discr_cfg) setT head_stepM_def. *)
(* Proof. Admitted. *)
(* HB.instance Definition _ := *)
(* isMeasurableMap.Build _ _ _ _ _ head_stepM_def_measurable. *)
(* Definition head_stepM : measurable_map (<<discr expr>> * <<discr state>>)type) := *)
(* head_stepM_def. *)
(* End meas_semantics. *)
(* (* *)
(* Lemma state_step_unfold σ α N ns: *)
(* tapes σ !! α = Some (N; ns) -> *)
(* state_step σ α = dmap (λ n, state_upd_tapes (<α := (N; ns ++ [n])>) σ) (dunifP N). *)
(* Proof. *)
(* intros H. *)
(* rewrite /state_step. *)
(* rewrite bool_decide_eq_true_2; last first. *)
(* { by apply elem_of_dom. } *)
(* by rewrite (lookup_total_correct (tapes σ) α (N; ns)); last done. *)
(* Qed. *)
(* *) *)
(* (** Basic properties about the language *) *)
(* Global Instance fill_item_inj Ki : Inj (=) (=) (fill_item Ki). *)
(* Proof. induction Ki; intros ???; simplify_eq/=; auto with f_equal. Qed. *)
(* Lemma fill_item_val Ki e : *)
(* is_Some (to_val (fill_item Ki e)) → is_Some (to_val e). *)
(* Proof. intros v ?. induction Ki; simplify_option_eq; eauto. Qed. *)
(* (* ??? *) *)
(* (* *)
(* Lemma val_head_stuck e σ ρ : *)
(* head_step e σ ρ > 0 → to_val e = None. *)
(* Proof. destruct ρ, e; |done... rewrite /pmf /=. lra. Qed. *)
(* Lemma head_ctx_step_val Ki e σ ρ : *)
(* head_step (fill_item Ki e) σ ρ > 0 → is_Some (to_val e). *)
(* Proof. *)
(* destruct ρ, Ki ; *)
(* rewrite /pmf/= ; *)
(* repeat case_match; clear -H ; inversion H; intros ; (lra || done). *)
(* Qed. *)
(* *) *)
(* Local Open Scope classical_set_scope. *)
(* (** A relational characterization of the support of head_step to make it easier to *)
(* do inversion and prove reducibility easier c.f. lemma below *) *)
(* Inductive head_step_rel : expr -> state -> expr -> state → Prop := *)
(* (* Values *) *)
(* | RecS f x e σ : *)
(* head_step_rel (Rec f x e) σ (Val *)
(* | PairS v1 v2 σ : *)
(* head_step_rel (Pair (Val v1) (Val v2)) σ (Val *)
(* | InjLS v σ : *)
(* head_step_rel (InjL InjLV v) σ *)
(* | InjRS v σ : *)
(* head_step_rel (InjR InjRV v) σ *)
(* (* Pure reductions *) *)
(* | BetaS f x e1 v2 e' σ : *)
(* e' = subst' x v2 (subst' f (RecV f x e1) e1) → *)
(* head_step_rel (App (Val *)
(* | UnOpS op v v' σ : *)
(* un_op_eval op v = Some v' → *)
(* head_step_rel (UnOp op (Val v)) σ (Val v') σ *)
(* | BinOpS op v1 v2 v' σ : *)
(* bin_op_eval op v1 v2 = Some v' → *)
(* head_step_rel (BinOp op (Val v1) (Val v2)) σ (Val v') σ *)
(* | IfTrueS e1 e2 σ : *)
(* head_step_rel (If (Val LitBool true) e1 e2) σ e1 σ *)
(* | IfFalseS e1 e2 σ : *)
(* head_step_rel (If (Val LitBool false) e1 e2) σ e2 σ *)
(* | FstS v1 v2 σ : *)
(* head_step_rel (Fst (Val *)
(* | SndS v1 v2 σ : *)
(* head_step_rel (Snd (Val *)
(* | CaseLS v e1 e2 σ : *)
(* head_step_rel (Case (Val *)
(* | CaseRS v e1 e2 σ : *)
(* head_step_rel (Case (Val *)
(* (* Heap *) *)
(* | AllocNS z N v σ l : *)
(* l = fresh_loc σ.(heap) → *)
(* N = Z.to_nat z → *)
(* (0 < N)*)
(* head_step_rel *)
(* (AllocN (Val (LitV (LitInt z))) (Val v)) σ *)
(* (Val LitLoc l) (state_upd_heap_N l N v σ) *)
(* | LoadS l v σ : *)
(* σ.(heap) !! l = Some v → *)
(* head_step_rel (Load (Val LitLoc l)) σ (of_val v) σ *)
(* | StoreS l v w σ : *)
(* σ.(heap) !! l = Some v → *)
(* head_step_rel (Store (Val LitLoc l) (Val w)) σ *)
(* (Val *)
(* (* Rand *) *)
(* | RandNoTapeS z N (n_int : Z) (n_nat : nat) σ: *)
(* N = Z.to_nat z → *)
(* n_nat < N -> *)
(* Z.of_nat n_nat = n_int -> *)
(* head_step_rel (Rand (Val LitInt z) (Val LitV *)
(* | AllocTapeS z N σ l : *)
(* l = fresh_loc σ.(tapes) → *)
(* N = Z.to_nat z → *)
(* head_step_rel (AllocTape (Val (LitV (LitInt z)))) σ *)
(* (Val LitLbl l) (state_upd_tapes <l := {| btape_tape := emptyTape ; btape_bound := N |}> σ) *)
(* | RandTapeS l z N n b b' σ : *)
(* N = Z.to_nat z → *)
(* σ.(tapes) !! l = Some {| btape_tape := b ; btape_bound := N |} -> *)
(* b !! 0 = Some (Z.to_nat n) -> *)
(* b' = tapeAdvance b -> *)
(* head_step_rel (Rand (Val (LitV (LitInt z))) (Val (LitV (LitLbl l)))) σ *)
(* (Val LitInt *)
(* | RandTapeEmptyS l z N (n_nat : nat) (n_int : Z) σ : *)
(* N = Z.to_nat z → *)
(* Z.of_nat n_nat = n_int -> *)
(* n_nat < N -> *)
(* σ.(tapes) !! l = Some {| btape_tape := emptyTape; btape_bound := N |} → *)
(* head_step_rel (Rand (Val (LitV (LitInt z))) (Val LitLbl l)) σ (Val LitInt n_nat) σ *)
(* | RandTapeOtherS l z M N b (n_nat : nat) (n_int : Z) σ : *)
(* N = Z.to_nat z → *)
(* Z.of_nat n_nat = n_int -> *)
(* n_nat < N -> *)
(* σ.(tapes) !! l = Some {| btape_tape := b ; btape_bound := M |} → *)
(* N ≠ M → *)
(* head_step_rel (Rand (Val (LitV (LitInt z))) (Val LitLbl l)) σ (Val LitInt n_int) σ *)
(* (* Urand *) *)
(* | URandNoTapeS (r : R) σ : *)
(* (0 <= r)*)
(* (r <= 1)*)
(* head_step_rel (URand (Val LitV *)
(* | AllocUTapeS σ l : *)
(* l = fresh_loc σ.(tapes) → *)
(* head_step_rel AllocUTape σ *)
(* (Val LitLbl l) (state_upd_utapes <l := emptyTape> σ) *)
(* | URandTapeS l b b' r σ : *)
(* σ.(utapes) !! l = Some b -> *)
(* b !! 0 = Some r -> *)
(* b' = tapeAdvance b -> *)
(* head_step_rel (URand (Val (LitV (LitLbl l)))) σ *)
(* (Val LitReal *)
(* | URandTapeEmptyS l (r : R) b σ : *)
(* (0 <= r)*)
(* (r <= 1)*)
(* σ.(utapes) !! l = Some b → *)
(* head_step_rel (URand (Val LitLbl l)) σ (Val LitReal r) σ *)
(* (* Tick *) *)
(* | TickS σ z : *)
(* head_step_rel (Tick LitV LitV *)
(* Create HintDb head_step. *)
(* Global Hint Constructors head_step_rel : head_step. *)
(* (* 0*)
(* unconstrained. *) *)
(* Global Hint Extern 1 *)
(* (head_step_rel (Rand (Val (LitV _)) (Val (LitV LitUnit))) _ _ _) => *)
(* eapply (RandNoTapeS _ _ 0*)
(* Global Hint Extern 1 *)
(* (head_step_rel (Rand (Val (LitV _)) (Val (LitV (LitLbl _)))) _ _ _) => *)
(* eapply (RandTapeEmptyS _ _ _ 0*)
(* Global Hint Extern 1 *)
(* (head_step_rel (Rand (Val (LitV _)) (Val (LitV (LitLbl _)))) _ _ _) => *)
(* eapply (RandTapeOtherS _ _ _ _ _ 0*)
(* (* *)
(* Ltac inv_head_step := *)
(* repeat *)
(* match goal with *)
(* | H : context @bool_decide ?P ?dec |- _ => *)
(* try (rewrite bool_decide_eq_true_2 in H; |done); *)
(* try (rewrite bool_decide_eq_false_2 in H; |done); *)
(* destruct_decide (@bool_decide_reflect P dec); simplify_eq *)
(* | _ => progress simplify_map_eq; simpl in *; inv_distr; repeat case_match; inv_distr *)
(* | H : to_val _ = Some _ |- _ => apply of_to_val in H *)
(* | H : is_Some (_ !! _) |- _ => destruct H *)
(* end. *)
(* Lemma head_step_support_equiv_rel e1 e2 σ1 σ2 : *)
(* head_step e1 σ1 (e2, σ2) > 0 ↔ head_step_rel e1 σ1 e2 σ2. *)
(* Proof. *)
(* split. *)
(* - intros ?. destruct e1; inv_head_step; eauto with head_step. *)
(* - inversion 1; simplify_map_eq/=; try case_bool_decide; simplify_eq; solve_distr; done. *)
(* Qed. *)
(* Lemma state_step_support_equiv_rel σ1 α σ2 : *)
(* state_step σ1 α σ2 > 0 ↔ state_step_rel σ1 α σ2. *)
(* Proof. *)
(* rewrite /state_step. split. *)
(* - case_bool_decide; |intros; inv_distr. *)
(* case_match. intros ?. inv_distr. *)
(* econstructor; eauto with lia. *)
(* - inversion_clear 1. *)
(* rewrite bool_decide_eq_true_2 // H1. solve_distr. *)
(* Qed. *)
(* Lemma state_step_head_step_not_stuck e σ σ' α : *)
(* state_step σ α σ' > 0 → (∃ ρ, head_step e σ ρ > 0) ↔ (∃ ρ', head_step e σ' ρ' > 0). *)
(* Proof. *)
(* rewrite state_step_support_equiv_rel. *)
(* inversion_clear 1. *)
(* split; intros [e2 σ2] Hs. *)
(* (* TODO: the sub goals used to be solved by simplify_map_eq *) *)
(* - destruct e; inv_head_step; try by (unshelve (eexists; solve_distr)). *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq in H11. done. *)
(* * rewrite lookup_insert_ne // in H11. rewrite H11 in H7. done. *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq in H11. done. *)
(* * rewrite lookup_insert_ne // in H11. rewrite H11 in H7. done. *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq in H10. done. *)
(* * rewrite lookup_insert_ne // in H10. rewrite H10 in H7. done. *)
(* - destruct e; inv_head_step; try by (unshelve (eexists; solve_distr)). *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * apply not_elem_of_dom_2 in H11. done. *)
(* * rewrite lookup_insert_ne // in H7. rewrite H11 in H7. done. *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq // in H7. *)
(* apply not_elem_of_dom_2 in H11. done. *)
(* * rewrite lookup_insert_ne // in H7. rewrite H11 in H7. done. *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq // in H7. *)
(* apply not_elem_of_dom_2 in H10. done. *)
(* * rewrite lookup_insert_ne // in H7. rewrite H10 in H7. done. *)
(* Qed. *)
(* *) *)
(* (* *)
(* Lemma head_step_mass e σ : *)
(* (∃ ρ, head_step e σ ρ > 0) → SeriesC (head_step e σ) = 1. *)
(* Proof. *)
(* intros [] Hs%head_step_support_equiv_rel. *)
(* inversion Hs; *)
(* repeat (simplify_map_eq/=; solve_distr_mass || case_match; try (case_bool_decide; done)). *)
(* Qed. *)
(* *) *)
(* Lemma fill_item_no_val_inj Ki1 Ki2 e1 e2 : *)
(* to_val e1 = None → to_val e2 = None → *)
(* fill_item Ki1 e1 = fill_item Ki2 e2 → Ki1 = Ki2. *)
(* Proof. destruct Ki2, Ki1; naive_solver eauto with f_equal. Qed. *)
(* Fixpoint height (e : expr) : nat := *)
(* match e with *)
(* | Val _ => 1 *)
(* | Var _ => 1 *)
(* | Rec _ _ e => 1 + height e *)
(* | App e1 e2 => 1 + height e1 + height e2 *)
(* | UnOp _ e => 1 + height e *)
(* | BinOp _ e1 e2 => 1 + height e1 + height e2 *)
(* | If e0 e1 e2 => 1 + height e0 + height e1 + height e2 *)
(* | Pair e1 e2 => 1 + height e1 + height e2 *)
(* | Fst e => 1 + height e *)
(* | Snd e => 1 + height e *)
(* | InjL e => 1 + height e *)
(* | InjR e => 1 + height e *)
(* | Case e0 e1 e2 => 1 + height e0 + height e1 + height e2 *)
(* | AllocN e1 e2 => 1 + height e1 + height e2 *)
(* | Load e => 1 + height e *)
(* | Store e1 e2 => 1 + height e1 + height e2 *)
(* | AllocTape e => 1 + height e *)
(* | AllocUTape => 1 *)
(* | Rand e1 e2 => 1 + height e1 + height e2 *)
(* | URand e => 1 + height e *)
(* | Tick e => 1 + height e *)
(* end. *)
(* Definition expr_ord (e1 e2 : expr) : Prop := (height e1 < height e2)*)
(* Lemma expr_ord_wf' h e : (height e ≤ h)*)
(* Proof. *)
(* rewrite /expr_ord. revert e; induction h. *)
(* { destruct e; simpl; lia. } *)
(* intros ; simpl; *)
(* constructor; simpl; intros ; eauto with lia. *)
(* Defined. *)
(* Lemma expr_ord_wf : well_founded expr_ord. *)
(* Proof. red; intro; eapply expr_ord_wf'; eauto. Defined. *)
(* (* TODO: this proof is slow, but I do not see how to make it faster... *) *)
(* Lemma decomp_expr_ord Ki e e' : decomp_item e = Some (Ki, e') → expr_ord e' e. *)
(* Proof. *)
(* rewrite /expr_ord /decomp_item. *)
(* destruct Ki ; repeat destruct_match ; intros = ; subst ; cbn ; lia. *)
(* Qed. *)
(* Lemma decomp_fill_item Ki e : *)
(* to_val e = None → decomp_item (fill_item Ki e) = Some (Ki, e). *)
(* Proof. destruct Ki ; simpl ; by repeat destruct_match. Qed. *)
(* (* TODO: this proof is slow, but I do not see how to make it faster... *) *)
(* Lemma decomp_fill_item_2 e e' Ki : *)
(* decomp_item e = Some (Ki, e') → fill_item Ki e' = e ∧ to_val e' = None. *)
(* Proof. *)
(* rewrite /decomp_item ; *)
(* destruct e ; try done ; *)
(* destruct Ki ; cbn ; repeat destruct_match ; intros = ; subst ; auto. *)
(* Qed. *)
(* Local Open Scope classical_set_scope. *)
(* Definition fill_item_mf K := m_discr (fill_item K : <<discr expr>> -> <<discr expr>>). *)
(* Definition meas_lang_mixin : *)
(* @MeasEctxiLanguageMixin _ _ _ <<discr expr>> <<discr val>> <<discr state>> ectx_item *)
(* of_val to_val fill_item_mf decomp_item expr_ord head_stepM_def. *)
(* Proof. *)
(* split. *)
(* Admitted. *)
(* ***) *)
(* End meas_lang. *)
(* (* *)
(* (** Language *) *)
(* Canonical Structure meas_ectxi_lang := MeasEctxiLanguage meas_lang.head_stepM meas_lang.meas_lang_mixin. *)
(* Canonical Structure meas_ectx_lang := MeasEctxLanguageOfEctxi meas_ectxi_lang. *)
(* Canonical Structure meas_lang := MeasLanguageOfEctx meas_ectx_lang. *)
(* (* Prefer meas_lang names over ectx_language names. *) *)
(* Export meas_lang. *)
(* *) *)
(* From Stdlib Require Import Logic.ClassicalEpsilon Psatz. *)
(* From stdpp Require Import base numbers binders strings gmap. *)
(* From mathcomp Require Import reals. *)
(* From mathcomp.analysis Require Import measure lebesgue_measure. *)
(* From mathcomp Require Import ssrbool all_algebra eqtype choice boolp fintype. *)
(* From iris.algebra Require Export ofe. *)
(* From clutch.prelude Require Export stdpp_ext. *)
(* From clutch.common Require Export locations. *)
(* From clutch.meas_lang Require Import ectxi_language ectx_language. *)
(* From Stdlib Require Export Reals. *)
(* From clutch.prob.monad Require Export laws. *)
(* From mathcomp.analysis Require Export Rstruct. *)
(* From mathcomp Require Import classical_sets. *)
(* Fix giryM to be the giry type with stdlib-valued real numbers *)
(* Notation giryM := (giryM (R := R)). *)
(* (* *)
(* From Stdlib Require Import Reals Psatz. *)
(* From stdpp Require Export binders strings. *)
(* From stdpp Require Import fin. *)
(* From stdpp Require Import gmap fin_maps countable fin. *)
(* From clutch.prob Require Export distribution. *)
(* From clutch.common Require Export language ectx_language ectxi_language locations. *)
(* From iris.prelude Require Import options. *)
(* From mathcomp Require Import ssrbool eqtype fintype choice all_algebra finmap. *)
(* From mathcomp Require Import mathcomp_extra boolp classical_sets functions. *)
(* From mathcomp Require Import cardinality fsbigop. *)
(* From mathcomp.analysis Require Import reals ereal signed normedtype sequences esum numfun measure lebesgue_measure lebesgue_integral. *)
(* *) *)
(* Delimit Scope expr_scope with E. *)
(* Delimit Scope val_scope with V. *)
(* Global Instance classical_eq_dec {T : Type} : EqDecision T. *)
(* Proof. intros ? ?; apply ClassicalEpsilon.excluded_middle_informative. Defined. *)
(* (* Instances for Z *) *)
(* HB.instance Definition _ := gen_eqMixin Z. *)
(* HB.instance Definition _ := gen_choiceMixin Z. *)
(* HB.instance Definition _ := isPointed.Build Z inhabitant. *)
(* (* Instances for loc *) *)
(* HB.instance Definition _ := gen_eqMixin loc. *)
(* HB.instance Definition _ := gen_choiceMixin loc. *)
(* HB.instance Definition _ := isPointed.Build loc inhabitant. *)
(* Module meas_lang. *)
(* (* Type of base_lit, parameterized by leaf types *) *)
(* Inductive base_lit_pre {TZ TB TL TR : Type} : Type := *)
(* | LitInt (n : TZ) *)
(* | LitBool (b : TB) *)
(* | LitUnit *)
(* | LitLoc (l : TL) *)
(* | LitLbl (l : TL) *)
(* | LitReal (r : TR). *)
(* Inductive un_op : Set := *)
(* | NegOp | MinusUnOp. *)
(* Inductive bin_op : Set := *)
(* | PlusOp | MinusOp | MultOp | QuotOp | RemOp (* Arithmetic *) *)
(* | AndOp | OrOp | XorOp (* Bitwise *) *)
(* | ShiftLOp | ShiftROp (* Shifts *) *)
(* | LeOp | LtOp | EqOp (* Relations *) *)
(* | OffsetOp. (* Pointer offset *) *)
(* Inductive expr_pre {TZ TB TL TR : Type} := *)
(* (* Values *) *)
(* | Val (v : val_pre) *)
(* (* Base lambda calculus *) *)
(* | Var (x : string) *)
(* | Rec (f x : binder) (e : expr_pre) *)
(* | App (e1 e2 : expr_pre) *)
(* (* Base types and their operations *) *)
(* | UnOp (op : un_op) (e : expr_pre) *)
(* | BinOp (op : bin_op) (e1 e2 : expr_pre) *)
(* | If (e0 e1 e2 : expr_pre) *)
(* (* Products *) *)
(* | Pair (e1 e2 : expr_pre) *)
(* | Fst (e : expr_pre) *)
(* | Snd (e : expr_pre) *)
(* (* Sums *) *)
(* | InjL (e : expr_pre) *)
(* | InjR (e : expr_pre) *)
(* | Case (e0 e1 e2 : expr_pre) *)
(* (* Heap *) *)
(* | AllocN (e1 e2 : expr_pre) (* Array length and initial value *) *)
(* | Load (e : expr_pre) *)
(* | Store (e1 e2 : expr_pre) *)
(* (* Finite probabilistic choice *) *)
(* | AllocTape (e : expr_pre) *)
(* | Rand (e1 e2 : expr_pre) *)
(* (* Real probabilistic choice *) *)
(* | AllocUTape *)
(* | URand (e : expr_pre) *)
(* (* No-op operator used for cost *) *)
(* | Tick (e : expr_pre ) *)
(* with val_pre {TZ TB TL TR : Type} := *)
(* | LitV (l : @base_lit_pre TZ TB TL TR) *)
(* | RecV (f x : binder) (e : expr_pre) *)
(* | PairV (v1 v2 : val_pre) *)
(* | InjLV (v : val_pre) *)
(* | InjRV (v : val_pre). *)
(* Section expr_algebra. *)
(* (** Defines the sigma algebra over expressions *) *)
(* Local Open Scope classical_set_scope. *)
(* (* FIXME: move *) *)
(* Definition image3 {TA TB TC rT} (A : set TA) (B : set TB) (C : set TC) (f : TA -> TB -> TC -> rT) := *)
(* set z | exists2 x, A x & exists2 y, B y & exists2 w, C w & f x y w = z. *)
(* Arguments image3 _ _ _ _ _ _ _ _ /. *)
(* Definition TZ : measurableType default_measure_display := <<discr Z>>. *)
(* Definition TB : measurableType default_measure_display := <<discr bool>>. *)
(* Definition TL : measurableType default_measure_display := <<discr loc>>. *)
(* Definition TR : measurableType default_measure_display := (R : realType). *)
(* Definition base_lit_S : Type := @base_lit_pre (set TZ) (set TB) (set TL) (set TR). *)
(* Definition val_S : Type := @val_pre (set TZ) (set TB) (set TL) (set TR). *)
(* Definition expr_S : Type := @expr_pre (set TZ) (set TB) (set TL) (set TR). *)
(* Definition base_lit_T : Type := @base_lit_pre TZ TB TL TR. *)
(* Definition val_T : Type := @val_pre TZ TB TL TR. *)
(* Definition expr_T : Type := @expr_pre TZ TB TL TR. *)
(* (* Cylinder constructions *) *)
(* (* Trees with sets on their leaves -> sets of trees with values on their leaves *) *)
(* Definition base_lit_ST (b : base_lit_S) : set base_lit_T := *)
(* match b with *)
(* | LitInt s => image s LitInt *)
(* | LitBool s => image s LitBool *)
(* | LitUnit => set LitUnit *)
(* | LitLoc s => image s LitLoc *)
(* | LitLbl s => image s LitLbl *)
(* | LitReal s => image s LitReal *)
(* end. *)
(* Fixpoint expr_ST (e : expr_S) : set expr_T := *)
(* match e with *)
(* | Val v => image (val_ST v) Val *)
(* | Var x => set (Var x) *)
(* | Rec f x e => image (expr_ST e) (Rec f x) *)
(* | App e1 e2 => image2 (expr_ST e1) (expr_ST e2) App *)
(* | UnOp op e => image (expr_ST e) (UnOp op) *)
(* | BinOp op e1 e2 => image2 (expr_ST e1) (expr_ST e2) (BinOp op) *)
(* | If e0 e1 e2 => image3 (expr_ST e0) (expr_ST e1) (expr_ST e2) If *)
(* | Pair e1 e2 => image2 (expr_ST e1) (expr_ST e2) Pair *)
(* | Fst e1 => image (expr_ST e1) Fst *)
(* | Snd e1 => image (expr_ST e1) Snd *)
(* | InjL e1 => image (expr_ST e1) InjL *)
(* | InjR e1 => image (expr_ST e1) InjR *)
(* | Case e0 e1 e2 => image3 (expr_ST e0) (expr_ST e1) (expr_ST e2) Case *)
(* | AllocN e1 e2 => image2 (expr_ST e1) (expr_ST e2) AllocN *)
(* | Load e => image (expr_ST e) Load *)
(* | Store e1 e2 => image2 (expr_ST e1) (expr_ST e2) Store *)
(* | AllocTape e => image (expr_ST e) AllocTape *)
(* | Rand e1 e2 => image2 (expr_ST e1) (expr_ST e2) Rand *)
(* | AllocUTape => set AllocUTape *)
(* | URand e => image (expr_ST e) URand *)
(* | Tick e => image (expr_ST e) Tick *)
(* end *)
(* with *)
(* val_ST (v : val_S) : set val_T := *)
(* match v with *)
(* | LitV b => image (base_lit_ST b) LitV *)
(* | RecV f x e => image (expr_ST e) (RecV f x) *)
(* | PairV v1 v2 => image2 (val_ST v1) (val_ST v2) PairV *)
(* | InjLV v => image (val_ST v) InjLV *)
(* | InjRV v => image (val_ST v) InjRV *)
(* end. *)
(* (* All trees with measurable sets on their leaves *) *)
(* Definition base_lit_ML : set base_lit_S := *)
(* fun b => *)
(* match b with *)
(* | LitInt s => measurable s *)
(* | LitBool s => measurable s *)
(* | LitUnit => True *)
(* | LitLoc s => measurable s *)
(* | LitLbl s => measurable s *)
(* | LitReal s => measurable s *)
(* end. *)
(* Fixpoint expr_ML (e : expr_S) : Prop := *)
(* match e with *)
(* | Val v => val_ML v *)
(* | Var x => True *)
(* | Rec f x e => expr_ML e *)
(* | App e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | UnOp op e => expr_ML e *)
(* | BinOp op e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | If e0 e1 e2 => expr_ML e0 /\ expr_ML e1 /\ expr_ML e2 *)
(* | Pair e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | Fst e1 => expr_ML e1 *)
(* | Snd e1 => expr_ML e1 *)
(* | InjL e1 => expr_ML e1 *)
(* | InjR e1 => expr_ML e1 *)
(* | Case e0 e1 e2 => expr_ML e0 /\ expr_ML e1 /\ expr_ML e2 *)
(* | AllocN e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | Load e => expr_ML e *)
(* | Store e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | AllocTape e => expr_ML e *)
(* | Rand e1 e2 => expr_ML e1 /\ expr_ML e2 *)
(* | AllocUTape => True *)
(* | URand e => expr_ML e *)
(* | Tick e => expr_ML e *)
(* end *)
(* with *)
(* val_ML (v : val_S) : Prop := *)
(* match v with *)
(* | LitV b => base_lit_ML b *)
(* | RecV f x e => expr_ML e *)
(* | PairV v1 v2 => val_ML v1 /\ val_ML v2 *)
(* | InjLV v => val_ML v *)
(* | InjRV v => val_ML v *)
(* end. *)
(* (* Cylinders: Generators for the sigma algebra *) *)
(* Definition base_lit_cyl : set (set base_lit_T) := image base_lit_ML base_lit_ST. *)
(* Definition expr_cyl : set (set expr_T) := image expr_ML expr_ST. *)
(* Definition val_cyl : set (set val_T) := image val_ML val_ST. *)
(* (* Generate sigma algebras from the cylinders *) *)
(* HB.instance Definition _ := gen_eqMixin base_lit_T. *)
(* HB.instance Definition _ := gen_choiceMixin base_lit_T. *)
(* HB.instance Definition _ := isPointed.Build base_lit_T LitUnit. *)
(* HB.instance Definition _ := gen_eqMixin val_T. *)
(* HB.instance Definition _ := gen_choiceMixin val_T. *)
(* HB.instance Definition _ := isPointed.Build val_T (LitV LitUnit). *)
(* HB.instance Definition _ := gen_eqMixin expr_T. *)
(* HB.instance Definition _ := gen_choiceMixin expr_T. *)
(* HB.instance Definition _ := isPointed.Build expr_T (Val (LitV LitUnit)). *)
(* (* FIXME: Remove! *) *)
(* Local Lemma base_lit_meas_obligation : *)
(* ∀ A : set base_lit_T, <<s base_lit_cyl>> A → <<s base_lit_cyl >> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* Local Lemma val_meas_obligation : *)
(* ∀ A : set val_T, <<s val_cyl>> A → <<s val_cyl >> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* Local Lemma expr_meas_obligation : *)
(* ∀ A : set expr_T, <<s expr_cyl>> A → <<s expr_cyl >> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display base_lit_cyl) *)
(* base_lit_T *)
(* <<s base_lit_cyl>> *)
(* (@sigma_algebra0 _ setT base_lit_cyl) *)
(* base_lit_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT base_lit_cyl). *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display val_cyl) *)
(* val_T *)
(* <<s val_cyl>> *)
(* (@sigma_algebra0 _ setT val_cyl) *)
(* val_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT val_cyl). *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display expr_cyl) *)
(* expr_T *)
(* <<s expr_cyl>> *)
(* (@sigma_algebra0 _ setT expr_cyl) *)
(* expr_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT expr_cyl). *)
(* (* User-facing types *) *)
(* Definition base_lit : measurableType base_lit_cyl.-sigma := base_lit_T. *)
(* Definition expr : measurableType expr_cyl.-sigma := expr_T. *)
(* Definition val : measurableType val_cyl.-sigma := val_T. *)
(* End expr_algebra. *)
(* (** General lemmas about tapes *) *)
(* Definition tape_content_t (A : Type) : Type := nat -> option A. *)
(* Record tape (A : Type) : Type := { *)
(* tape_position : nat; *)
(* tape_contents : tape_content_t A *)
(* }. *)
(* Definition emptyTapeContents {A : Type} : tape_content_t A := fun _ => None. *)
(* Definition emptyTape {A : Type} : tape A := *)
(* {| tape_position := 0 ; *)
(* tape_contents := emptyTapeContents *)
(* |}. *)
(* (* History lookup: look through absolute history *) *)
(* Global Instance tape_content_lookup {A} : Lookup nat A (tape_content_t A) := fun i => fun h => h i. *)
(* (** Specialize tapes to btapes and utapes, construct siga algebra *) *)
(* Section tapes_algebra. *)
(* Local Open Scope classical_set_scope. *)
(* (* Tapes in the computable fragment *) *)
(* Record pre_btape : Type := { *)
(* btape_tape :> tape nat; *)
(* btape_bound : nat *)
(* }. *)
(* (* Tapes of real numbers *) *)
(* Definition pre_utape : Type := tape R. *)
(* (* FIXME: move *) *)
(* Definition image4 {TA TB TC TD rT} (A : set TA) (B : set TB) (C : set TC) (D : set TD) (f : TA -> TB -> TC -> TD -> rT) := *)
(* set z | exists2 x, A x & exists2 y, B y & exists2 w, C w & exists2 v, D v & f x y w v = z. *)
(* Arguments image4 _ _ _ _ _ _ _ _ _ /. *)
(* Definition btape_basis_emp : set (set pre_btape) := *)
(* let bound_set : set nat := setT in *)
(* let pos_set : set nat := setT in *)
(* (* The set of all btapes such that *)
(* - the bound is b *)
(* - the position is p *)
(* - the content is empty *) *)
(* let construct b p := *)
(* set {| btape_tape := {| tape_position := p; tape_contents := (fun _ => None) |} ; *)
(* btape_bound := b |}] in *)
(* image2 bound_set pos_set construct. *)
(* Program Definition btape_basis_full : set (set pre_btape) := *)
(* let bound_set : set nat := setT in *)
(* let pos_set : set nat := setT in *)
(* let index_set : set nat := setT in *)
(* let value_set : set nat := setT in *)
(* (* The set of all btapes such that *)
(* - the bound is b *)
(* - the position is p *)
(* - the content at index i is set to the value v *) *)
(* let construct b p i v := *)
(* (fun bt => *)
(* exists contents, *)
(* bt = {| btape_tape := {| tape_position := p; tape_contents := contents |}; btape_bound := b|} /\ *)
(* contents !! i = Some v) in *)
(* image4 bound_set pos_set index_set value_set construct. *)
(* Definition btape_basis := btape_basis_emp `|` btape_basis_full. *)
(* HB.instance Definition _ := gen_eqMixin pre_btape. *)
(* HB.instance Definition _ := gen_choiceMixin pre_btape. *)
(* HB.instance Definition _ := isPointed.Build pre_btape {| btape_tape := emptyTape ; btape_bound := 0 |}. *)
(* Local Lemma btape_meas_obligation : ∀ A : set pre_btape, <<s btape_basis>> A → <<s btape_basis>> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display btape_basis) *)
(* pre_btape *)
(* <<s btape_basis>> *)
(* (@sigma_algebra0 _ setT btape_basis) *)
(* btape_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT btape_basis). *)
(* Definition utape_basis_emp : set (set pre_utape) := *)
(* let pos_set : set nat := setT in *)
(* (* The set of all utapes such that *)
(* - the position is p *)
(* - the content is empty *) *)
(* let construct p := *)
(* set {| tape_position := p; tape_contents := (fun _ => None) |} in *)
(* image pos_set construct. *)
(* (* FIXME: This should not return a singleton! *) *)
(* Definition utape_basis_full : set (set pre_utape) := *)
(* let pos_set : set nat := setT in *)
(* let index_set : set nat := setT in *)
(* let value_set : set (set (R : realType)) := 'measurable in *)
(* (* The set of all utapes such that *)
(* - the position is p *)
(* - the content at position i is set to some value in set_of_v *) *)
(* let construct p i set_of_v := *)
(* (fun ut => *)
(* exists contents r, *)
(* ut = {| tape_position := p; tape_contents := contents |} /\ *)
(* contents !! i = Some r /\ *)
(* set_of_v r) in *)
(* image3 pos_set index_set value_set construct. *)
(* Definition utape_basis : set (set pre_utape) := utape_basis_emp `|` utape_basis_full. *)
(* HB.instance Definition _ := gen_eqMixin pre_utape. *)
(* HB.instance Definition _ := gen_choiceMixin pre_utape. *)
(* HB.instance Definition _ := isPointed.Build pre_utape emptyTape. *)
(* Local Lemma utape_meas_obligation : ∀ A : set pre_utape, <<s utape_basis>> A → <<s utape_basis>> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display utape_basis) *)
(* pre_utape *)
(* <<s utape_basis>> *)
(* (@sigma_algebra0 _ setT utape_basis) *)
(* utape_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT utape_basis). *)
(* (* User-facing types *) *)
(* Definition btape : measurableType btape_basis.-sigma := pre_btape. *)
(* Definition utape : measurableType utape_basis.-sigma := pre_utape. *)
(* End tapes_algebra. *)
(* (* btape and utape definitions *) *)
(* (* All values of the tape are within the tape bound *) *)
(* Definition btape_inbounds (t : btape): Prop := *)
(* forall n : nat, *)
(* tape_contents _ t n = None \/ *)
(* exists v : nat, tape_contents _ t n = Some v /\ v < btape_bound t. *)
(* (* All tape values prior to state have been determined *) *)
(* Definition tape_history_deterministic {A} (t : tape A) : Prop := *)
(* forall i : nat, i < tape_position _ t -> exists v : A, tape_contents _ t i = Some v. *)
(* (* Tape lookup: look relative to current index. t !! 0 will be the next sample. *) *)
(* Global Instance tape_rel_lookup {A} : Lookup nat A (tape A) := fun i => fun t => (tape_contents _ t (i + tape_position _ t)). *)
(* Definition tape_content_update_unsafe {A} (i : nat) (v : option A) (h : tape_content_t A) : tape_content_t A *)
(* := fun i' => if i' =? i then v else h i'. *)
(* Global Instance tape_content_insert {A} : Insert nat (option A) (tape_content_t A) := tape_content_update_unsafe. *)
(* Definition tapeUpdateUnsafe {A} (i : nat) (v : option A) (t : tape A) : tape A := *)
(* {| tape_position := tape_position _ t; *)
(* tape_contents := < (i + tape_position _ t) := v > (tape_contents _ t) *)
(* |}. *)
(* Global Instance tape_insert {A} : Insert nat (option A) (tape A) := tapeUpdateUnsafe. *)
(* Program Definition tapeAdvance {A} (t : tape A) : tape A *)
(* := {| tape_position := 1 + tape_position _ t; tape_contents := tape_contents _ t |}. *)
(* (* Advance the tape by 1, returning an updated tape and the first sample on the tape. *) *)
(* Program Definition tapeNext {A} (t : tape A) (H : isSome (t !! 0)) : A * (tape A) *)
(* := match (t !! 0) with *)
(* | None => _ *)
(* | Some v => *)
(* (v, *)
(* {| tape_position := 1 + tape_position _ t; *)
(* tape_contents := tape_contents _ t |}) *)
(* end. *)
(* Next Obligation. by move=>/= ? ? H1 H2; symmetry in H2; rewrite H2//= in H1. Defined. *)
(* (* Representation predicates for common tape structures *) *)
(* Definition tapeHasPrefix {A} (t : tape A) (l : list A) : Prop *)
(* := forall i : nat, i < length l -> t !! i = l !! i. *)
(* Definition tapeEmptyAfter {A} (t : tape A) (b : nat) : Prop *)
(* := forall i : nat, i >= b -> t !! i = None. *)
(* (* Tapes a la base clutch *) *)
(* Definition isFiniteTape (t : btape) (l : list nat) : Prop *)
(* := tapeHasPrefix t l *)
(* /\ tapeEmptyAfter t (length l) *)
(* /\ btape_inbounds t *)
(* /\ tape_history_deterministic t. *)
(* (* TODO: realIsBinarySequence (cannonical form w/ 0-termination on dyadic numbers) *) *)
(* Definition tapeHasInfinitePrefix {A} (t : tape A) (f : nat -> A) : Prop *)
(* := forall i : nat, t !! i = Some (f i). *)
(* (* TODO: tapeIsRealInRange (l : R) ... := bound = 1, tapeHasInfinitePrefic *) *)
(* (* tapeOfReal ... ?*) *)
(* (* Tape with "Junk" prefix *) *)
(* Definition tapeHasEventually {A} (t : tape A) (l : list A) : Prop *)
(* := exists offset: nat, forall i : nat, i < length l -> t !! (i + offset) = l !! i. *)
(* Global Instance tape_inhabited {A} : Inhabited (tape A) := populate emptyTape. *)
(* Global Instance tapes_lookup_total {A} : LookupTotal loc (tape A) (gmap loc (tape A)). *)
(* Proof. apply map_lookup_total. Defined. *)
(* Global Instance tapes_insert {A} : Insert loc (tape A) (gmap loc (tape A)). *)
(* Proof. apply map_insert. Defined. *)
(* Bind Scope expr_scope with expr. *)
(* Bind Scope val_scope with val. *)
(* Notation of_val := Val (only parsing). *)
(* Definition to_val (e : expr) : option val := *)
(* match e with *)
(* | Val v => Some v *)
(* | _ => None *)
(* end. *)
(* Section state_algebra. *)
(* Local Open Scope classical_set_scope. *)
(* (** The state: a loc-indexed heap of vals, and loc-indexed tapes, and loc-indexed utapes *) *)
(* Record state_pre : Type := { *)
(* heap : gmap loc val; *)
(* tapes : gmap loc btape; *)
(* utapes : gmap loc utape *)
(* }. *)
(* Definition gmap_loc_cyl_emp d (T : measurableType d) : set (set (gmap loc T)) := *)
(* set (fun g => forall l, g !! l = None). *)
(* Definition gmap_loc_cyl_full d (T : measurableType d) : set (set (gmap loc T)) := *)
(* let loc_set : set loc := setT in *)
(* let T_set : set (set T) := d.-measurable in *)
(* (* The set of all gmaps such that *)
(* - the value at position l is set to an element in the set ts *) *)
(* let construct (l : loc) (ts : set T) : set (gmap loc T) := *)
(* fun g => exists v : T, g !! l = Some v /\ ts v in *)
(* image2 loc_set T_set construct. *)
(* Definition gmap_loc_cyl d (T : measurableType d) : set (set (gmap loc T)) := *)
(* gmap_loc_cyl_emp d T `|` gmap_loc_cyl_full d T. *)
(* (* The set of all states such that *)
(* each field is a gmap cylinder *)
(* *) *)
(* Program Definition state_cyl : set (set state_pre) := *)
(* let hs_set := gmap_loc_cyl _ val in *)
(* let ts_set := gmap_loc_cyl _ btape in *)
(* let us_set := gmap_loc_cyl _ utape in *)
(* let construct (hs : set (gmap loc val)) (ht : set (gmap loc btape)) (hu : set (gmap loc utape)) : set state_pre := *)
(* fun σ => *)
(* exists g1 : gmap loc val, *)
(* exists g2 : gmap loc btape, *)
(* exists g3 : gmap loc utape, *)
(* σ = {| heap := g1; tapes := g2; utapes := g3|} /\ *)
(* hs g1 /\ *)
(* ht g2 /\ *)
(* hu g3 *)
(* in *)
(* image3 hs_set ts_set us_set construct. *)
(* HB.instance Definition _ := gen_eqMixin state_pre. *)
(* HB.instance Definition _ := gen_choiceMixin state_pre. *)
(* HB.instance Definition _ := isPointed.Build state_pre {| heap := gmap_empty; tapes := gmap_empty; utapes := gmap_empty |}. *)
(* Local Lemma state_pre_meas_obligation : ∀ A : set state_pre, <<s state_cyl>> A → <<s state_cyl>> (~` A). *)
(* Proof. eapply sigma_algebraC. Qed. *)
(* (* There's got to be a way to delete this *) *)
(* HB.instance Definition _ := @isMeasurable.Build *)
(* (sigma_display state_cyl) *)
(* state_pre *)
(* <<s state_cyl>> *)
(* (@sigma_algebra0 _ setT state_cyl) *)
(* state_pre_meas_obligation *)
(* (@sigma_algebra_bigcup _ setT state_cyl). *)
(* Definition state : measurableType state_cyl.-sigma := state_pre. *)
(* End state_algebra. *)
(* (** Equality and other typeclass stuff *) *)
(* Lemma to_of_val v : to_val (of_val v) = Some v. *)
(* Proof. by destruct v. Qed. *)
(* Lemma of_to_val e v : to_val e = Some v → of_val v = e. *)
(* Proof. destruct e=>//=. by intros = <-. Qed. *)
(* (* FIXME *)
(* Global Instance of_val_inj : Inj (=) (=) of_val. *)
(* Proof. intros ??. congruence. Qed. *)
(* *) *)
(* (* *)
(* Global Instance state_inhabited : Inhabited state := populate {| heap := gmap_empty; tapes := gmap_empty; utapes := gmap_empty |}. *)
(* Global Instance val_inhabited : Inhabited val := populate (LitV LitUnit). *)
(* Global Instance expr_inhabited : Inhabited expr := populate (Val inhabitant). *)
(* *) *)
(* Canonical Structure stateO := leibnizO state. *)
(* Canonical Structure locO := leibnizO loc. *)
(* Canonical Structure valO := leibnizO val. *)
(* Canonical Structure exprO := leibnizO expr. *)
(* (** Evaluation contexts *) *)
(* Inductive ectx_item := *)
(* | AppLCtx (v2 : val) *)
(* | AppRCtx (e1 : expr) *)
(* | UnOpCtx (op : un_op) *)
(* | BinOpLCtx (op : bin_op) (v2 : val) *)
(* | BinOpRCtx (op : bin_op) (e1 : expr) *)
(* | IfCtx (e1 e2 : expr) *)
(* | PairLCtx (v2 : val) *)
(* | PairRCtx (e1 : expr) *)
(* | FstCtx *)
(* | SndCtx *)
(* | InjLCtx *)
(* | InjRCtx *)
(* | CaseCtx (e1 : expr) (e2 : expr) *)
(* | AllocNLCtx (v2 : val) *)
(* | AllocNRCtx (e1 : expr) *)
(* | LoadCtx *)
(* | StoreLCtx (v2 : val) *)
(* | StoreRCtx (e1 : expr) *)
(* | AllocTapeCtx *)
(* | RandLCtx (v2 : val) *)
(* | RandRCtx (e1 : expr) *)
(* | URandCtx *)
(* | TickCtx. *)
(* (* FIXME: Hide cosntructors, so that we don't need to mention base_lit *) *)
(* (* *)
(* Definition fill_item (Ki : ectx_item) (e : expr) : expr := *)
(* match Ki with *)
(* | AppLCtx v2 => App e (of_val v2) *)
(* | AppRCtx e1 => App e1 e *)
(* | UnOpCtx op => UnOp op e *)
(* | BinOpLCtx op v2 => BinOp op e (Val v2) *)
(* | BinOpRCtx op e1 => BinOp op e1 e *)
(* | IfCtx e1 e2 => If e e1 e2 *)
(* | PairLCtx v2 => Pair e (Val v2) *)
(* | PairRCtx e1 => Pair e1 e *)
(* | FstCtx => Fst e *)
(* | SndCtx => Snd e *)
(* | InjLCtx => InjL e *)
(* | InjRCtx => InjR e *)
(* | CaseCtx e1 e2 => Case e e1 e2 *)
(* | AllocNLCtx v2 => AllocN e (Val v2) *)
(* | AllocNRCtx e1 => AllocN e1 e *)
(* | LoadCtx => Load e *)
(* | StoreLCtx v2 => Store e (Val v2) *)
(* | StoreRCtx e1 => Store e1 e *)
(* | AllocTapeCtx => AllocTape e *)
(* | RandLCtx v2 => Rand e (Val v2) *)
(* | RandRCtx e1 => Rand e1 e *)
(* | URandCtx => URand e *)
(* | TickCtx => Tick e *)
(* end. *)
(* Definition decomp_item (e : expr) : option (ectx_item * expr) := *)
(* let noval (e : expr) (ei : ectx_item) := *)
(* match e with Val _ => None | _ => Some (ei, e) end in *)
(* match e with *)
(* | App e1 e2 => *)
(* match e2 with *)
(* | (Val v) => noval e1 (AppLCtx v) *)
(* | _ => Some (AppRCtx e1, e2) *)
(* end *)
(* | UnOp op e => noval e (UnOpCtx op) *)
(* | BinOp op e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (BinOpLCtx op v) *)
(* | _ => Some (BinOpRCtx op e1, e2) *)
(* end *)
(* | If e0 e1 e2 => noval e0 (IfCtx e1 e2) *)
(* | Pair e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (PairLCtx v) *)
(* | _ => Some (PairRCtx e1, e2) *)
(* end *)
(* | Fst e => noval e FstCtx *)
(* | Snd e => noval e SndCtx *)
(* | InjL e => noval e InjLCtx *)
(* | InjR e => noval e InjRCtx *)
(* | Case e0 e1 e2 => noval e0 (CaseCtx e1 e2) *)
(* | AllocN e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (AllocNLCtx v) *)
(* | _ => Some (AllocNRCtx e1, e2) *)
(* end *)
(* | Load e => noval e LoadCtx *)
(* | Store e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (StoreLCtx v) *)
(* | _ => Some (StoreRCtx e1, e2) *)
(* end *)
(* | AllocTape e => noval e AllocTapeCtx *)
(* | Rand e1 e2 => *)
(* match e2 with *)
(* | Val v => noval e1 (RandLCtx v) *)
(* | _ => Some (RandRCtx e1, e2) *)
(* end *)
(* | URand e => noval e URandCtx *)
(* | Tick e => noval e TickCtx *)
(* | _ => None *)
(* end. *)
(* (** Substitution *) *)
(* Fixpoint subst (x : string) (v : val) (e : expr) : expr := *)
(* match e with *)
(* | Val _ => e *)
(* | Var y => if decide (x = y) then Val v else Var y *)
(* | Rec f y e => *)
(* Rec f y *)
(* | App e1 e2 => App (subst x v e1) (subst x v e2) *)
(* | UnOp op e => UnOp op (subst x v e) *)
(* | BinOp op e1 e2 => BinOp op (subst x v e1) (subst x v e2) *)
(* | If e0 e1 e2 => If (subst x v e0) (subst x v e1) (subst x v e2) *)
(* | Pair e1 e2 => Pair (subst x v e1) (subst x v e2) *)
(* | Fst e => Fst (subst x v e) *)
(* | Snd e => Snd (subst x v e) *)
(* | InjL e => InjL (subst x v e) *)
(* | InjR e => InjR (subst x v e) *)
(* | Case e0 e1 e2 => Case (subst x v e0) (subst x v e1) (subst x v e2) *)
(* | AllocN e1 e2 => AllocN (subst x v e1) (subst x v e2) *)
(* | Load e => Load (subst x v e) *)
(* | Store e1 e2 => Store (subst x v e1) (subst x v e2) *)
(* | AllocTape e => AllocTape (subst x v e) *)
(* | AllocUTape => AllocUTape *)
(* | Rand e1 e2 => Rand (subst x v e1) (subst x v e2) *)
(* | URand e => URand (subst x v e) *)
(* | Tick e => Tick (subst x v e) *)
(* end. *)
(* Definition subst' (mx : binder) (v : val) : expr → expr := *)
(* match mx with BNamed x => subst x v | BAnon => λ x, x end. *)
(* (** The stepping relation *) *)
(* Definition un_op_eval (op : un_op) (v : val) : option val := *)
(* match op, v with *)
(* | NegOp, LitV (LitBool b) => Some LitBool (negb b) *)
(* | NegOp, LitV (LitInt z) => Some LitInt (Z.lnot z) *)
(* | MinusUnOp, LitV (LitInt z) => Some LitInt (- z) *)
(* | MinusUnOp, LitV (LitReal r) => Some LitReal (- r)*)
(* | _, _ => None *)
(* end. *)
(* Definition bin_op_eval_int (op : bin_op) (n1 n2 : Z) : base_lit := *)
(* match op with *)
(* | PlusOp => LitInt (n1 + n2) *)
(* | MinusOp => LitInt (n1 - n2) *)
(* | MultOp => LitInt (n1 * n2) *)
(* | QuotOp => LitInt (n1 `quot` n2) *)
(* | RemOp => LitInt (n1 `rem` n2) *)
(* | AndOp => LitInt (Z.land n1 n2) *)
(* | OrOp => LitInt (Z.lor n1 n2) *)
(* | XorOp => LitInt (Z.lxor n1 n2) *)
(* | ShiftLOp => LitInt (n1 ≪ n2) *)
(* | ShiftROp => LitInt (n1 ≫ n2) *)
(* | LeOp => LitBool (bool_decide (n1 ≤ n2)) *)
(* | LtOp => LitBool (bool_decide (n1 < n2)) *)
(* | EqOp => LitBool (bool_decide (n1 = n2)) *)
(* | OffsetOp => LitInt (n1 + n2) (* Treat offsets as ints *) *)
(* end*)
(* Definition bin_op_eval_bool (op : bin_op) (b1 b2 : bool) : option base_lit := *)
(* match op with *)
(* | PlusOp | MinusOp | MultOp | QuotOp | RemOp => None (* Arithmetic *) *)
(* | AndOp => Some (LitBool (b1 && b2)) *)
(* | OrOp => Some (LitBool (b1 || b2)) *)
(* | XorOp => Some (LitBool (xorb b1 b2)) *)
(* | ShiftLOp | ShiftROp => None (* Shifts *) *)
(* | LeOp | LtOp => None (* InEquality *) *)
(* | EqOp => Some (LitBool (bool_decide (b1 = b2))) *)
(* | OffsetOp => None *)
(* end. *)
(* Definition bin_op_eval_loc (op : bin_op) (l1 : loc) (v2 : base_lit) : option base_lit := *)
(* match op, v2 with *)
(* | OffsetOp, LitInt off => Some *)
(* | LeOp, LitLoc l2 => Some *)
(* | LtOp, LitLoc l2 => Some *)
(* | _, _ => None *)
(* end. *)
(* Definition bin_op_eval_real (op : bin_op) (r1 r2 : R) : option base_lit := *)
(* match op with *)
(* | PlusOp => Some *)
(* | MinusOp => Some *)
(* | MultOp => Some *)
(* | LeOp => Some bool_decide *)
(* | LtOp => Some bool_decide *)
(* | EqOp => Some bool_decide *)
(* | _ => None *)
(* end*)
(* Definition bin_op_eval (op : bin_op) (v1 v2 : val) : option val := *)
(* if decide (op = EqOp) then *)
(* if decide (v1 = v2) then *)
(* Some LitBool *)
(* else *)
(* None *)
(* else *)
(* match v1 , v2 with *)
(* | LitV (LitInt n1), LitV (LitInt n2) => Some bin_op_eval_int op n1 n2 *)
(* | LitV (LitReal r1), LitV (LitReal r2) => LitV <*)
(* | LitV (LitBool b1), LitV (LitBool b2) => LitV <*)
(* | LitV (LitLoc l1), LitV v2 => LitV <*)
(* | _, _ => None *)
(* end. *)
(* Definition state_upd_heap (f : gmap loc val → gmap loc val) (σ : state) : state := *)
(* {| heap := f σ.(heap); tapes := σ.(tapes); utapes := σ.(utapes) |}. *)
(* Global Arguments state_upd_heap _ !_ /. *)
(* Definition state_upd_tapes (f : gmap loc btape → gmap loc btape) (σ : state) : state := *)
(* {| heap := σ.(heap); tapes := f σ.(tapes); utapes := σ.(utapes) |}. *)
(* Global Arguments state_upd_tapes _ !_ /. *)
(* Definition state_upd_utapes (f : gmap loc utape → gmap loc utape) (σ : state) : state := *)
(* {| heap := σ.(heap); tapes := σ.(tapes); utapes := f σ.(utapes) |}. *)
(* Global Arguments state_upd_utapes _ !_ /. *)
(* Lemma state_upd_tapes_twice σ l xs ys : *)
(* state_upd_tapes < l := ys > (state_upd_tapes < l := xs > σ) = state_upd_tapes < l:= ys > σ. *)
(* Proof. rewrite /state_upd_tapes /=. f_equal. apply insert_insert_eq. Qed. *)
(* Lemma state_upd_tapes_same σ σ' l xs ys : *)
(* state_upd_tapes <l:=ys> σ = state_upd_tapes <l:=xs> σ' -> xs = ys. *)
(* Proof. rewrite /state_upd_tapes /=. intros K. simplify_eq. *)
(* rewrite map_eq_iff in H. *)
(* specialize (H l). *)
(* rewrite !lookup_insert_eq in H. *)
(* by simplify_eq. *)
(* Qed. *)
(* Lemma state_upd_tapes_no_change σ l ys : *)
(* tapes σ !! l = Some ys -> *)
(* state_upd_tapes <l := ys> σ = σ . *)
(* Proof. *)
(* destruct σ as ? t. simpl. *)
(* intros Ht. *)
(* f_equal. *)
(* apply insert_id. done. *)
(* Qed. *)
(* (* *)
(* Lemma state_upd_tapes_same' σ σ' l n xs (x y : stdpp.fin.fin (S n)) : *)
(* state_upd_tapes <l:=(fin (n; xs++[x]))> σ = state_upd_tapes <l:=(fin(n; xs++[y]))> σ' -> x = y. *)
(* Proof. intros H. apply state_upd_tapes_same in H. by simplify_eq. Qed. *)
(* Lemma state_upd_tapes_neq' σ σ' l n xs (x y : stdpp.fin.fin (S n)) : *)
(* x≠y -> state_upd_tapes <l:=(fin(n; xs++[x]))> σ ≠ state_upd_tapes <l:=(fin(n; xs++[y]))> σ'. *)
(* Proof. move => H /state_upd_tapes_same ?. simplify_eq. Qed. *)
(* *) *)
(* Fixpoint heap_array (l : loc) (vs : list val) : gmap loc val := *)
(* match vs with *)
(* | => ∅ *)
(* | v :: vs' => {l := v} ∪ heap_array (l +ₗ 1) vs' *)
(* end. *)
(* Lemma heap_array_singleton l v : heap_array l v = {l := v}. *)
(* Proof. by rewrite /heap_array right_id. Qed. *)
(* Lemma heap_array_app l vs1 vs2 : heap_array l (vs1 ++ vs2) = (heap_array l vs1) ∪ (heap_array (l +ₗ (length vs1)) vs2) . *)
(* Proof. *)
(* revert l. *)
(* induction vs1; intro l. *)
(* - simpl. *)
(* rewrite map_empty_union loc_add_0 //. *)
(* - rewrite -app_comm_cons /= IHvs1. *)
(* rewrite map_union_assoc. *)
(* do 2 f_equiv. *)
(* rewrite Nat2Z.inj_succ /=. *)
(* rewrite /Z.succ *)
(* Z.add_comm *)
(* loc_add_assoc //. *)
(* Qed. *)
(* Lemma heap_array_lookup l vs v k : *)
(* heap_array l vs !! k = Some v ↔ *)
(* ∃ j, (0 ≤ j)*)
(* Proof. *)
(* revert k l; induction vs as |v' vs IH => l' l /=. *)
(* { rewrite lookup_empty. naive_solver lia. } *)
(* rewrite -insert_union_singleton_l lookup_insert_Some IH. split. *)
(* - intros [-> ?] | (Hl & j & ? & -> & ?). *)
(* { eexists 0. rewrite loc_add_0. naive_solver lia. } *)
(* eexists (1 + j)*)
(* - intros (j & ? & -> & Hil). destruct (decide (j = 0)); simplify_eq/=. *)
(* { rewrite loc_add_0; eauto. } *)
(* right. split. *)
(* { rewrite -{1}(loc_add_0 l). intros ?*)
(* assert (Z.to_nat j = S (Z.to_nat (j - 1))) as Hj. *)
(* { rewrite -Z2Nat.inj_succ; last lia. f_equal; lia. } *)
(* rewrite Hj /= in Hil. *)
(* eexists (j - 1)*)
(* auto with lia. *)
(* Qed. *)
(* Lemma heap_array_map_disjoint (h : gmap loc val) (l : loc) (vs : list val) : *)
(* (∀ i, (0 ≤ i)Z → h !! (l +ₗ i) = None) → *)
(* (heap_array l vs) #ₘ h. *)
(* Proof. *)
(* intros Hdisj. apply map_disjoint_spec=> l' v1 v2. *)
(* intros (j&?&->&Hjinj_lt)*)
(* move: Hj. rewrite Z2Nat.id // => ?. by rewrite Hdisj. *)
(* Qed. *)
(* Definition state_upd_heap_N (l : loc) (n : nat) (v : val) (σ : state) : state := *)
(* state_upd_heap (λ h, heap_array l (replicate n v) ∪ h) σ. *)
(* Lemma state_upd_heap_singleton l v σ : *)
(* state_upd_heap_N l 1 v σ = state_upd_heap <l:= v> σ. *)
(* Proof. *)
(* destruct σ as h p. rewrite /state_upd_heap_N /=. f_equiv. *)
(* rewrite right_id insert_union_singleton_l. done. *)
(* Qed. *)
(* Lemma state_upd_tapes_heap σ l1 l2 xs m v : *)
(* state_upd_tapes <l2:=xs> (state_upd_heap_N l1 m v σ) = *)
(* state_upd_heap_N l1 m v (state_upd_tapes <l2:=xs> σ). *)
(* Proof. *)
(* by rewrite /state_upd_tapes /state_upd_heap_N /=. *)
(* Qed. *)
(* Lemma heap_array_replicate_S_end l v n : *)
(* heap_array l (replicate (S n) v) = heap_array l (replicate n v) ∪ {l +ₗ n:= v}. *)
(* Proof. *)
(* induction n. *)
(* - simpl. *)
(* rewrite map_union_empty. *)
(* rewrite map_empty_union. *)
(* by rewrite loc_add_0. *)
(* - rewrite replicate_S_end *)
(* heap_array_app *)
(* IHn /=. *)
(* rewrite map_union_empty length_replicate //. *)
(* Qed. *)
(* (* [local] Open Scope R. *) *)
(* Section pointed_instances. *)
(* Local Open Scope classical_set_scope. *)
(* (* Fail Check (<<discr state>> : measurableType _). *) *)
(* HB.instance Definition _ := gen_eqMixin state. *)
(* HB.instance Definition _ := gen_choiceMixin state. *)
(* HB.instance Definition _ := isPointed.Build state inhabitant. *)
(* (* Check (<<discr state>> : measurableType _). *) *)
(* (** cfg is pointed (automatic) *) *)
(* (* Check (<<discr cfg>> : measurableType _). *) *)
(* (** state * loc is pointed (automatic) *) *)
(* (* Check (<<discr (state * loc)>> : measurableType _). *) *)
(* (** R is pointed *) *)
(* Check (<<discr R>> : measurableType _). *)
(* End pointed_instances. *)
(* Section meas_semantics. *)
(* Local Open Scope classical_set_scope. *)
(* Local Open Scope expr_scope. *)
(* Definition discr_cfg : measurableType _ := (<<discr expr>> * <<discr state>>)*)
(* Definition head_stepM_def (c : discr_cfg) : giryM discr_cfg := *)
(* let (e1, σ1) := c in *)
(* match e1 with *)
(* | Rec f x e => *)
(* giryM_ret R ((Val *)
(* | Pair (Val v1) (Val v2) => *)
(* giryM_ret R ((Val *)
(* | InjL (Val v) => *)
(* giryM_ret R ((Val *)
(* | InjR (Val v) => *)
(* giryM_ret R ((Val *)
(* | App (Val (RecV f x e1)) (Val v2) => *)
(* giryM_ret R ((subst' x v2 (subst' f (RecV f x e1) e1) , σ1) : discr_cfg) *)
(* | UnOp op (Val v) => *)
(* match un_op_eval op v with *)
(* | Some w => giryM_ret R ((Val w, σ1) : discr_cfg) *)
(* | _ => giryM_zero *)
(* end *)
(* | BinOp op (Val v1) (Val v2) => *)
(* match bin_op_eval op v1 v2 with *)
(* | Some w => giryM_ret R ((Val w, σ1) : discr_cfg) *)
(* | _ => giryM_zero *)
(* end *)
(* | If (Val (LitV (LitBool true))) e1 e2 => *)
(* giryM_ret R ((e1 , σ1) : discr_cfg) *)
(* | If (Val (LitV (LitBool false))) e1 e2 => *)
(* giryM_ret R ((e2 , σ1) : discr_cfg) *)
(* | Fst (Val (PairV v1 v2)) => *)
(* giryM_ret R ((Val v1 , σ1) : discr_cfg) (* Syntax error when I remove the space between v1 and , *) *)
(* | Snd (Val (PairV v1 v2)) => *)
(* giryM_ret R ((Val v2, σ1) : discr_cfg) *)
(* | Case (Val (InjLV v)) e1 e2 => *)
(* giryM_ret R ((App e1 (Val v), σ1) : discr_cfg) *)
(* | Case (Val (InjRV v)) e1 e2 => *)
(* giryM_ret R ((App e2 (Val v), σ1) : discr_cfg) *)
(* | AllocN (Val (LitV (LitInt N))) (Val v) => *)
(* let ℓ := fresh_loc σ1.(heap) in *)
(* if bool_decide (0 < Z.to_nat N)*)
(* then giryM_ret R ((Val LitLoc ℓ, state_upd_heap_N ℓ (Z.to_nat N) v σ1) : discr_cfg) *)
(* else giryM_zero *)
(* | Load (Val (LitV (LitLoc l))) => *)
(* match σ1.(heap) !! l with *)
(* | Some v => giryM_ret R ((Val v, σ1) : discr_cfg) *)
(* | None => giryM_zero *)
(* end *)
(* | Store (Val (LitV (LitLoc l))) (Val w) => *)
(* match σ1.(heap) !! l with *)
(* | Some v => giryM_ret R ((Val *)
(* | None => giryM_zero *)
(* end *)
(* (* Uniform sampling from 0, 1 , ..., N *) *)
(* | Rand (Val (LitV (LitInt N))) (Val (LitV LitUnit)) => *)
(* giryM_map *)
(* (m_discr (fun (n : 'I_(S (Z.to_nat N))) => ((Val LitInt n, σ1) : discr_cfg))) *)
(* (giryM_unif (Z.to_nat N)) *)
(* | AllocTape (Val (LitV (LitInt z))) => *)
(* let ι := fresh_loc σ1.(tapes) in *)
(* giryM_ret R ((Val LitLbl ι, state_upd_tapes <ι := {| btape_tape := emptyTape ; btape_bound := (Z.to_nat z) |} > σ1) : discr_cfg) *)
(* (* Rand with a tape *) *)
(* | Rand (Val (LitV (LitInt N))) (Val (LitV (LitLbl l))) => *)
(* match σ1.(tapes) !! l with *)
(* | Some btape => *)
(* (* There exists a tape with label l *) *)
(* let τ := btape.(btape_tape) in *)
(* let M := btape.(btape_bound) in *)
(* if (bool_decide (M = Z.to_nat N)) then *)
(* (* Tape bounds match *) *)
(* match (τ !! 0) with *)
(* | Some v => *)
(* (* There is a next value on the tape *) *)
(* let σ' := state_upd_tapes < l := {| btape_tape := (tapeAdvance τ); btape_bound := M |} > σ1 in *)
(* (giryM_ret R ((Val LitInt *)
(* | None => *)
(* (* Next slot on tape is empty *) *)
(* giryM_map *)
(* (m_discr (fun (v : 'I_(S (Z.to_nat N))) => *)
(* (* Fill the tape head with new sample *) *)
(* let τ' := < (0 : nat) := Some (v : nat) > τ in *)
(* (* Advance the tape *) *)
(* let σ' := state_upd_tapes < l := {| btape_tape := (tapeAdvance τ'); btape_bound := M |} > σ1 in *)
(* (* Return the new sample and state *) *)
(* ((Val LitInt *)
(* (giryM_unif (Z.to_nat N)) *)
(* end *)
(* else *)
(* (* Tape bounds do not match *) *)
(* (* Do not advance the tape, but still generate a new sample *) *)
(* giryM_map *)
(* (m_discr (fun (n : 'I_(S (Z.to_nat N))) => ((Val LitInt n, σ1) : discr_cfg))) *)
(* (giryM_unif (Z.to_nat N)) *)
(* | None => giryM_zero *)
(* end *)
(* | AllocUTape => *)
(* let ι := fresh_loc σ1.(utapes) in *)
(* giryM_ret R ((Val LitLbl ι, state_upd_utapes < ι := emptyTape > σ1) : discr_cfg) *)
(* (* Urand with no tape *) *)
(* | URand (Val (LitV LitUnit)) => *)
(* giryM_map *)
(* (m_discr (fun u => ((Val LitReal u, σ1) : discr_cfg))) *)
(* giryM_zero *)
(* (* Urand with a tape *) *)
(* | URand (Val (LitV (LitLbl l))) => *)
(* match σ1.(utapes) !! l with *)
(* | Some τ => *)
(* (* tape l is allocated *) *)
(* match (τ !! 0) with *)
(* | Some u => *)
(* (* Head has a sample *) *)
(* let σ' := state_upd_utapes < l := (tapeAdvance τ) > σ1 in *)
(* (giryM_ret R ((Val LitReal u, σ') : discr_cfg)) *)
(* | None => *)
(* (* Head has no sample *) *)
(* giryM_map *)
(* (m_discr (fun (u : R) => *)
(* (* Fill tape head with new sample *) *)
(* let τ' := < (0 : nat) := Some u > τ in *)
(* (* Advance tape *) *)
(* let σ' := state_upd_utapes < l := (tapeAdvance τ') > σ1 in *)
(* (* Return the update value an state *) *)
(* ((Val LitReal u, σ') : discr_cfg))) *)
(* giryM_zero *)
(* end *)
(* | None => giryM_zero *)
(* end *)
(* | Tick (Val (LitV (LitInt n))) => giryM_ret R ((Val LitUnit, σ1) : discr_cfg) *)
(* | _ => giryM_zero *)
(* end. *)
(* (* I don't care if this this true; we will delete it soon and replace it with a proof for the real SA. *) *)
(* Local Lemma head_stepM_def_measurable : *)
(* @measurable_fun _ _ discr_cfg (giryM discr_cfg) setT head_stepM_def. *)
(* Proof. Admitted. *)
(* HB.instance Definition _ := *)
(* isMeasurableMap.Build _ _ _ _ _ head_stepM_def_measurable. *)
(* Definition head_stepM : measurable_map (<<discr expr>> * <<discr state>>)type) := *)
(* head_stepM_def. *)
(* End meas_semantics. *)
(* (* *)
(* Lemma state_step_unfold σ α N ns: *)
(* tapes σ !! α = Some (N; ns) -> *)
(* state_step σ α = dmap (λ n, state_upd_tapes (<α := (N; ns ++ [n])>) σ) (dunifP N). *)
(* Proof. *)
(* intros H. *)
(* rewrite /state_step. *)
(* rewrite bool_decide_eq_true_2; last first. *)
(* { by apply elem_of_dom. } *)
(* by rewrite (lookup_total_correct (tapes σ) α (N; ns)); last done. *)
(* Qed. *)
(* *) *)
(* (** Basic properties about the language *) *)
(* Global Instance fill_item_inj Ki : Inj (=) (=) (fill_item Ki). *)
(* Proof. induction Ki; intros ???; simplify_eq/=; auto with f_equal. Qed. *)
(* Lemma fill_item_val Ki e : *)
(* is_Some (to_val (fill_item Ki e)) → is_Some (to_val e). *)
(* Proof. intros v ?. induction Ki; simplify_option_eq; eauto. Qed. *)
(* (* ??? *) *)
(* (* *)
(* Lemma val_head_stuck e σ ρ : *)
(* head_step e σ ρ > 0 → to_val e = None. *)
(* Proof. destruct ρ, e; |done... rewrite /pmf /=. lra. Qed. *)
(* Lemma head_ctx_step_val Ki e σ ρ : *)
(* head_step (fill_item Ki e) σ ρ > 0 → is_Some (to_val e). *)
(* Proof. *)
(* destruct ρ, Ki ; *)
(* rewrite /pmf/= ; *)
(* repeat case_match; clear -H ; inversion H; intros ; (lra || done). *)
(* Qed. *)
(* *) *)
(* Local Open Scope classical_set_scope. *)
(* (** A relational characterization of the support of head_step to make it easier to *)
(* do inversion and prove reducibility easier c.f. lemma below *) *)
(* Inductive head_step_rel : expr -> state -> expr -> state → Prop := *)
(* (* Values *) *)
(* | RecS f x e σ : *)
(* head_step_rel (Rec f x e) σ (Val *)
(* | PairS v1 v2 σ : *)
(* head_step_rel (Pair (Val v1) (Val v2)) σ (Val *)
(* | InjLS v σ : *)
(* head_step_rel (InjL InjLV v) σ *)
(* | InjRS v σ : *)
(* head_step_rel (InjR InjRV v) σ *)
(* (* Pure reductions *) *)
(* | BetaS f x e1 v2 e' σ : *)
(* e' = subst' x v2 (subst' f (RecV f x e1) e1) → *)
(* head_step_rel (App (Val *)
(* | UnOpS op v v' σ : *)
(* un_op_eval op v = Some v' → *)
(* head_step_rel (UnOp op (Val v)) σ (Val v') σ *)
(* | BinOpS op v1 v2 v' σ : *)
(* bin_op_eval op v1 v2 = Some v' → *)
(* head_step_rel (BinOp op (Val v1) (Val v2)) σ (Val v') σ *)
(* | IfTrueS e1 e2 σ : *)
(* head_step_rel (If (Val LitBool true) e1 e2) σ e1 σ *)
(* | IfFalseS e1 e2 σ : *)
(* head_step_rel (If (Val LitBool false) e1 e2) σ e2 σ *)
(* | FstS v1 v2 σ : *)
(* head_step_rel (Fst (Val *)
(* | SndS v1 v2 σ : *)
(* head_step_rel (Snd (Val *)
(* | CaseLS v e1 e2 σ : *)
(* head_step_rel (Case (Val *)
(* | CaseRS v e1 e2 σ : *)
(* head_step_rel (Case (Val *)
(* (* Heap *) *)
(* | AllocNS z N v σ l : *)
(* l = fresh_loc σ.(heap) → *)
(* N = Z.to_nat z → *)
(* (0 < N)*)
(* head_step_rel *)
(* (AllocN (Val (LitV (LitInt z))) (Val v)) σ *)
(* (Val LitLoc l) (state_upd_heap_N l N v σ) *)
(* | LoadS l v σ : *)
(* σ.(heap) !! l = Some v → *)
(* head_step_rel (Load (Val LitLoc l)) σ (of_val v) σ *)
(* | StoreS l v w σ : *)
(* σ.(heap) !! l = Some v → *)
(* head_step_rel (Store (Val LitLoc l) (Val w)) σ *)
(* (Val *)
(* (* Rand *) *)
(* | RandNoTapeS z N (n_int : Z) (n_nat : nat) σ: *)
(* N = Z.to_nat z → *)
(* n_nat < N -> *)
(* Z.of_nat n_nat = n_int -> *)
(* head_step_rel (Rand (Val LitInt z) (Val LitV *)
(* | AllocTapeS z N σ l : *)
(* l = fresh_loc σ.(tapes) → *)
(* N = Z.to_nat z → *)
(* head_step_rel (AllocTape (Val (LitV (LitInt z)))) σ *)
(* (Val LitLbl l) (state_upd_tapes <l := {| btape_tape := emptyTape ; btape_bound := N |}> σ) *)
(* | RandTapeS l z N n b b' σ : *)
(* N = Z.to_nat z → *)
(* σ.(tapes) !! l = Some {| btape_tape := b ; btape_bound := N |} -> *)
(* b !! 0 = Some (Z.to_nat n) -> *)
(* b' = tapeAdvance b -> *)
(* head_step_rel (Rand (Val (LitV (LitInt z))) (Val (LitV (LitLbl l)))) σ *)
(* (Val LitInt *)
(* | RandTapeEmptyS l z N (n_nat : nat) (n_int : Z) σ : *)
(* N = Z.to_nat z → *)
(* Z.of_nat n_nat = n_int -> *)
(* n_nat < N -> *)
(* σ.(tapes) !! l = Some {| btape_tape := emptyTape; btape_bound := N |} → *)
(* head_step_rel (Rand (Val (LitV (LitInt z))) (Val LitLbl l)) σ (Val LitInt n_nat) σ *)
(* | RandTapeOtherS l z M N b (n_nat : nat) (n_int : Z) σ : *)
(* N = Z.to_nat z → *)
(* Z.of_nat n_nat = n_int -> *)
(* n_nat < N -> *)
(* σ.(tapes) !! l = Some {| btape_tape := b ; btape_bound := M |} → *)
(* N ≠ M → *)
(* head_step_rel (Rand (Val (LitV (LitInt z))) (Val LitLbl l)) σ (Val LitInt n_int) σ *)
(* (* Urand *) *)
(* | URandNoTapeS (r : R) σ : *)
(* (0 <= r)*)
(* (r <= 1)*)
(* head_step_rel (URand (Val LitV *)
(* | AllocUTapeS σ l : *)
(* l = fresh_loc σ.(tapes) → *)
(* head_step_rel AllocUTape σ *)
(* (Val LitLbl l) (state_upd_utapes <l := emptyTape> σ) *)
(* | URandTapeS l b b' r σ : *)
(* σ.(utapes) !! l = Some b -> *)
(* b !! 0 = Some r -> *)
(* b' = tapeAdvance b -> *)
(* head_step_rel (URand (Val (LitV (LitLbl l)))) σ *)
(* (Val LitReal *)
(* | URandTapeEmptyS l (r : R) b σ : *)
(* (0 <= r)*)
(* (r <= 1)*)
(* σ.(utapes) !! l = Some b → *)
(* head_step_rel (URand (Val LitLbl l)) σ (Val LitReal r) σ *)
(* (* Tick *) *)
(* | TickS σ z : *)
(* head_step_rel (Tick LitV LitV *)
(* Create HintDb head_step. *)
(* Global Hint Constructors head_step_rel : head_step. *)
(* (* 0*)
(* unconstrained. *) *)
(* Global Hint Extern 1 *)
(* (head_step_rel (Rand (Val (LitV _)) (Val (LitV LitUnit))) _ _ _) => *)
(* eapply (RandNoTapeS _ _ 0*)
(* Global Hint Extern 1 *)
(* (head_step_rel (Rand (Val (LitV _)) (Val (LitV (LitLbl _)))) _ _ _) => *)
(* eapply (RandTapeEmptyS _ _ _ 0*)
(* Global Hint Extern 1 *)
(* (head_step_rel (Rand (Val (LitV _)) (Val (LitV (LitLbl _)))) _ _ _) => *)
(* eapply (RandTapeOtherS _ _ _ _ _ 0*)
(* (* *)
(* Ltac inv_head_step := *)
(* repeat *)
(* match goal with *)
(* | H : context @bool_decide ?P ?dec |- _ => *)
(* try (rewrite bool_decide_eq_true_2 in H; |done); *)
(* try (rewrite bool_decide_eq_false_2 in H; |done); *)
(* destruct_decide (@bool_decide_reflect P dec); simplify_eq *)
(* | _ => progress simplify_map_eq; simpl in *; inv_distr; repeat case_match; inv_distr *)
(* | H : to_val _ = Some _ |- _ => apply of_to_val in H *)
(* | H : is_Some (_ !! _) |- _ => destruct H *)
(* end. *)
(* Lemma head_step_support_equiv_rel e1 e2 σ1 σ2 : *)
(* head_step e1 σ1 (e2, σ2) > 0 ↔ head_step_rel e1 σ1 e2 σ2. *)
(* Proof. *)
(* split. *)
(* - intros ?. destruct e1; inv_head_step; eauto with head_step. *)
(* - inversion 1; simplify_map_eq/=; try case_bool_decide; simplify_eq; solve_distr; done. *)
(* Qed. *)
(* Lemma state_step_support_equiv_rel σ1 α σ2 : *)
(* state_step σ1 α σ2 > 0 ↔ state_step_rel σ1 α σ2. *)
(* Proof. *)
(* rewrite /state_step. split. *)
(* - case_bool_decide; |intros; inv_distr. *)
(* case_match. intros ?. inv_distr. *)
(* econstructor; eauto with lia. *)
(* - inversion_clear 1. *)
(* rewrite bool_decide_eq_true_2 // H1. solve_distr. *)
(* Qed. *)
(* Lemma state_step_head_step_not_stuck e σ σ' α : *)
(* state_step σ α σ' > 0 → (∃ ρ, head_step e σ ρ > 0) ↔ (∃ ρ', head_step e σ' ρ' > 0). *)
(* Proof. *)
(* rewrite state_step_support_equiv_rel. *)
(* inversion_clear 1. *)
(* split; intros [e2 σ2] Hs. *)
(* (* TODO: the sub goals used to be solved by simplify_map_eq *) *)
(* - destruct e; inv_head_step; try by (unshelve (eexists; solve_distr)). *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq in H11. done. *)
(* * rewrite lookup_insert_ne // in H11. rewrite H11 in H7. done. *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq in H11. done. *)
(* * rewrite lookup_insert_ne // in H11. rewrite H11 in H7. done. *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq in H10. done. *)
(* * rewrite lookup_insert_ne // in H10. rewrite H10 in H7. done. *)
(* - destruct e; inv_head_step; try by (unshelve (eexists; solve_distr)). *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * apply not_elem_of_dom_2 in H11. done. *)
(* * rewrite lookup_insert_ne // in H7. rewrite H11 in H7. done. *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq // in H7. *)
(* apply not_elem_of_dom_2 in H11. done. *)
(* * rewrite lookup_insert_ne // in H7. rewrite H11 in H7. done. *)
(* + destruct (decide (α = l1)); simplify_eq. *)
(* * rewrite lookup_insert_eq // in H7. *)
(* apply not_elem_of_dom_2 in H10. done. *)
(* * rewrite lookup_insert_ne // in H7. rewrite H10 in H7. done. *)
(* Qed. *)
(* *) *)
(* (* *)
(* Lemma head_step_mass e σ : *)
(* (∃ ρ, head_step e σ ρ > 0) → SeriesC (head_step e σ) = 1. *)
(* Proof. *)
(* intros [] Hs%head_step_support_equiv_rel. *)
(* inversion Hs; *)
(* repeat (simplify_map_eq/=; solve_distr_mass || case_match; try (case_bool_decide; done)). *)
(* Qed. *)
(* *) *)
(* Lemma fill_item_no_val_inj Ki1 Ki2 e1 e2 : *)
(* to_val e1 = None → to_val e2 = None → *)
(* fill_item Ki1 e1 = fill_item Ki2 e2 → Ki1 = Ki2. *)
(* Proof. destruct Ki2, Ki1; naive_solver eauto with f_equal. Qed. *)
(* Fixpoint height (e : expr) : nat := *)
(* match e with *)
(* | Val _ => 1 *)
(* | Var _ => 1 *)
(* | Rec _ _ e => 1 + height e *)
(* | App e1 e2 => 1 + height e1 + height e2 *)
(* | UnOp _ e => 1 + height e *)
(* | BinOp _ e1 e2 => 1 + height e1 + height e2 *)
(* | If e0 e1 e2 => 1 + height e0 + height e1 + height e2 *)
(* | Pair e1 e2 => 1 + height e1 + height e2 *)
(* | Fst e => 1 + height e *)
(* | Snd e => 1 + height e *)
(* | InjL e => 1 + height e *)
(* | InjR e => 1 + height e *)
(* | Case e0 e1 e2 => 1 + height e0 + height e1 + height e2 *)
(* | AllocN e1 e2 => 1 + height e1 + height e2 *)
(* | Load e => 1 + height e *)
(* | Store e1 e2 => 1 + height e1 + height e2 *)
(* | AllocTape e => 1 + height e *)
(* | AllocUTape => 1 *)
(* | Rand e1 e2 => 1 + height e1 + height e2 *)
(* | URand e => 1 + height e *)
(* | Tick e => 1 + height e *)
(* end. *)
(* Definition expr_ord (e1 e2 : expr) : Prop := (height e1 < height e2)*)
(* Lemma expr_ord_wf' h e : (height e ≤ h)*)
(* Proof. *)
(* rewrite /expr_ord. revert e; induction h. *)
(* { destruct e; simpl; lia. } *)
(* intros ; simpl; *)
(* constructor; simpl; intros ; eauto with lia. *)
(* Defined. *)
(* Lemma expr_ord_wf : well_founded expr_ord. *)
(* Proof. red; intro; eapply expr_ord_wf'; eauto. Defined. *)
(* (* TODO: this proof is slow, but I do not see how to make it faster... *) *)
(* Lemma decomp_expr_ord Ki e e' : decomp_item e = Some (Ki, e') → expr_ord e' e. *)
(* Proof. *)
(* rewrite /expr_ord /decomp_item. *)
(* destruct Ki ; repeat destruct_match ; intros = ; subst ; cbn ; lia. *)
(* Qed. *)
(* Lemma decomp_fill_item Ki e : *)
(* to_val e = None → decomp_item (fill_item Ki e) = Some (Ki, e). *)
(* Proof. destruct Ki ; simpl ; by repeat destruct_match. Qed. *)
(* (* TODO: this proof is slow, but I do not see how to make it faster... *) *)
(* Lemma decomp_fill_item_2 e e' Ki : *)
(* decomp_item e = Some (Ki, e') → fill_item Ki e' = e ∧ to_val e' = None. *)
(* Proof. *)
(* rewrite /decomp_item ; *)
(* destruct e ; try done ; *)
(* destruct Ki ; cbn ; repeat destruct_match ; intros = ; subst ; auto. *)
(* Qed. *)
(* Local Open Scope classical_set_scope. *)
(* Definition fill_item_mf K := m_discr (fill_item K : <<discr expr>> -> <<discr expr>>). *)
(* Definition meas_lang_mixin : *)
(* @MeasEctxiLanguageMixin _ _ _ <<discr expr>> <<discr val>> <<discr state>> ectx_item *)
(* of_val to_val fill_item_mf decomp_item expr_ord head_stepM_def. *)
(* Proof. *)
(* split. *)
(* Admitted. *)
(* ***) *)
(* End meas_lang. *)
(* (* *)
(* (** Language *) *)
(* Canonical Structure meas_ectxi_lang := MeasEctxiLanguage meas_lang.head_stepM meas_lang.meas_lang_mixin. *)
(* Canonical Structure meas_ectx_lang := MeasEctxLanguageOfEctxi meas_ectxi_lang. *)
(* Canonical Structure meas_lang := MeasLanguageOfEctx meas_ectx_lang. *)
(* (* Prefer meas_lang names over ectx_language names. *) *)
(* Export meas_lang. *)
(* *) *)