(* Copyright 2012-2015 by Adam Petcher.				* * Use of this source code is governed by the license described	* * in the LICENSE file at the root of the source tree.		*)
(* A denotational semantics for computations that relates every computation to a denotation. *)
Set Implicit Arguments.
Require Export FCF.Comp.
Require Export FCF.Rat.
Local Open Scope list_scope.
Local Open Scope rat_scope.
Ltac simp_in_support :=
unfold setLet in *;
match goal with
| [H : In _ (getSupport (Bind _ _)) |- _ ] =>
apply getSupport_Bind_In in H; destruct_exists; intuition
| [H : In _ (getSupport (if ?t then _ else _)) |- _ ] => let x := fresh "x" in remember t as x; destruct x
| [H : In _ (getSupport (ret _)) |- _ ] => apply getSupport_In_Ret in H; try pairInv; subst
(*     | [H : false = inRange _ _ |- _] => symmetry in H *)
| [H : true = negb ?t |- _ ] => let x := fresh "x" in remember t as x; destruct x; simpl in H; try discriminate
end.
(* evalDist is a denotational semantics that produces a distribution instead of a value. *)
Definition Distribution(A : Set) := A -> Rat.
Definition indicator(A : Set)(P : A -> bool) :=
fun a => if (P a) then rat1 else rat0.
Fixpoint evalDist(A : Set)(c : Comp A) : Distribution A :=
match c with
| Ret eqd a => fun a' => if (eqd a a') then 1 else 0
| Bind c1 c2 => fun a =>
sumList (getSupport c1) (fun b => (evalDist c1 b) * (evalDist (c2 b) a))
| Rnd n => fun v => 1 / (expnat 2 n)
| Repeat c P => fun a => (indicator P a) * (ratInverse (sumList (filter P (getSupport c)) (evalDist c))) * (evalDist c a)
end.
Definition dist_sem_eq(A : Set)(c1 c2 : Comp A) :=
forall a, (evalDist c1 a) == (evalDist c2 a).
Definition Support(A : Set)(ls : list A)(d : Distribution A) :=
NoDup ls /\
(forall a, In a ls <-> ~((d a) == 0)).

Lemma getSupport_NoDup : forall (A : Set)(c : Comp A),
NoDup (getSupport c).