Require Export Program.Basics Program.
Require Import List Morphisms Lia.
Require Export LibUtils BasicUtils ProbSpace SigmaAlgebras.
Require Classical.
Require Import ClassicalDescription.
Import ListNotations.
Set Bullet Behavior "
Strict Subproofs".
Class RandomVariable {
Ts:
Type} {
Td:
Type}
      (
dom: 
SigmaAlgebra Ts)
      (
cod: 
SigmaAlgebra Td)
      (
rv_X: 
Ts -> 
Td)
  :=
    
rv_preimage_sa: 
forall (
B: 
event cod), 
sa_sigma (
event_preimage rv_X B).
Definition rv_preimage
           {
Ts:
Type}
           {
Td:
Type}
           {
dom: 
SigmaAlgebra Ts}
           {
cod: 
SigmaAlgebra Td}
           (
rv_X: 
Ts -> 
Td)
           {
rv:
RandomVariable dom cod rv_X} :
  
event cod -> 
event dom
  := 
fun b => 
exist _ _ (
rv_preimage_sa b).
Global Instance RandomVariable_proper {
Ts:
Type} {
Td:
Type}
  : 
Proper (
sa_equiv ==> 
sa_equiv ==> 
rv_eq ==> 
iff) (@
RandomVariable Ts Td).
Proof.
  unfold RandomVariable.
  
split; 
intros.
  - 
rewrite <- 
H1.
    
apply H.
    
destruct B.
    
destruct (
H0 x2) 
as [
_ HH].
    
apply (
H2 (
exist _ x2 (
HH s))).
  - 
rewrite H1.
    
apply H.
    
destruct B.
    
destruct (
H0 x2) 
as [
HH _].
    
apply (
H2 (
exist _ x2 (
HH s))).
Qed.
 
Instance RandomVariable_proper_le {
Ts Td : 
Type} :
  
Proper (
sa_sub ==> 
sa_sub --> 
rv_eq ==> 
impl) (@
RandomVariable Ts Td).
Proof.
  unfold RandomVariable.
  
intros ???????????.
  
rewrite <- 
H1.
  
apply H.
  
destruct B.
  
apply (
H2 (
exist _ x2 (
H0 _ s))).
Qed.
 
Global Instance rv_preimage_proper
       {
Ts:
Type}
       {
Td:
Type}
       {
dom: 
SigmaAlgebra Ts}
       {
cod: 
SigmaAlgebra Td}
       (
rv_X: 
Ts -> 
Td)
       {
rv:
RandomVariable dom cod rv_X} :
  
Proper (
event_equiv ==> 
event_equiv) (@
rv_preimage Ts Td dom cod rv_X rv).
Proof.
Class HasPreimageSingleton {
Td} (σ:
SigmaAlgebra Td)
  := 
sa_preimage_singleton :
       
forall {
Ts} {σ
s:
SigmaAlgebra Ts} (
rv_X:
Ts->
Td) {
rv : 
RandomVariable σ
s σ 
rv_X} 
c,
         
sa_sigma (
pre_event_preimage rv_X (
pre_event_singleton c)).
Definition preimage_singleton {
Ts Td} {σ
s:
SigmaAlgebra Ts} {σ
d:
SigmaAlgebra Td} {
has_pre:
HasPreimageSingleton σ
d}
           (
rv_X:
Ts->
Td) 
           {
rv : 
RandomVariable σ
s σ
d rv_X}
           (
c:
Td) : 
event σ
s
  := 
exist _ _ (
sa_preimage_singleton rv_X c).
Section Const.
  
Context {
Ts Td:
Type}.
  
Class ConstantRangeFunction
        (
rv_X:
Ts -> 
Td)
    := { 
    
frf_val : 
Td;
    
frf_val_complete : 
forall x, 
rv_X x = 
frf_val
      }.
  
  
Global Program Instance crvconst c : 
ConstantRangeFunction (
const c)
    := { 
frf_val := 
c }.
  
Global Instance discrete_sa_rv
         {
cod:
SigmaAlgebra Td} (
rv_X: 
Ts -> 
Td) 
    : 
RandomVariable (
discrete_sa Ts) 
cod rv_X.
  Proof.
  Context (
dom: 
SigmaAlgebra Ts)
          (
cod: 
SigmaAlgebra Td).
  
  
Global Instance rvconst c : 
RandomVariable dom cod (
const c).
    Proof.
End Const.
Instance id_rv {
Ts} {
dom:
SigmaAlgebra Ts} : 
RandomVariable dom dom (
fun x => 
x).
Proof.
Instance compose_rv {
Ts1 Ts2 Ts3} {
dom1 dom2 dom3}
         (
f : 
Ts1 -> 
Ts2)
         (
g : 
Ts2 -> 
Ts3)
         {
rvf : 
RandomVariable dom1 dom2 f}
         {
rvg : 
RandomVariable dom2 dom3 g} :
         
RandomVariable dom1 dom3 (
compose g f).
Proof.
  intros ?.
  
apply (
rvf (
exist _ _ (
rvg B))).
Qed.
 
Section Simple.
  
Context {
Ts:
Type} {
Td:
Type}.
  
Class FiniteRangeFunction
        (
rv_X:
Ts->
Td)
    := { 
    
frf_vals : 
list Td ;
    
frf_vals_complete : 
forall x, 
In (
rv_X x) 
frf_vals;
      }.
  
Lemma FiniteRangeFunction_ext (
x y:
Ts->
Td) :
    
rv_eq x y ->
    
FiniteRangeFunction x ->
    
FiniteRangeFunction y.
  Proof.
    repeat red; intros.
    invcs X.
    exists frf_vals0.
    intros.
    now rewrite <- H.
    Defined.
  Global Program Instance frf_crv (
rv_X:
Ts->
Td) {
crv:
ConstantRangeFunction rv_X} :
    
FiniteRangeFunction rv_X
    := {
    
frf_vals := [
frf_val]
      }.
  Next Obligation.
  Global Program Instance frf_fun (
rv_X : 
Ts -> 
Td) (
f : 
Td -> 
Td)
          (
frf:
FiniteRangeFunction rv_X) : 
    
FiniteRangeFunction (
fun v => 
f (
rv_X v)) :=
    {
frf_vals := 
map f frf_vals}.
  Next Obligation.
    destruct frf.
    
now apply in_map.
  Qed.
 
  Definition frfconst c : 
FiniteRangeFunction (
const c)
    := 
frf_crv (
const c).
  
Program Instance nodup_simple_random_variable (
dec:
forall (
x y:
Td), {
x = 
y} + {
x <> 
y})
          {
rv_X:
Ts->
Td}
          (
frf:
FiniteRangeFunction rv_X) : 
FiniteRangeFunction rv_X
    := { 
frf_vals := 
nodup dec frf_vals }.
  Next Obligation.
  Lemma nodup_simple_random_variable_NoDup
        (
dec:
forall (
x y:
Td), {
x = 
y} + {
x <> 
y})
        {
rv_X}
        (
frf:
FiniteRangeFunction rv_X) :
    
NoDup (
frf_vals (
FiniteRangeFunction:=
nodup_simple_random_variable dec frf)).
  Proof.
Lemma frf_singleton_rv (
rv_X : 
Ts -> 
Td)
        (
frf:
FiniteRangeFunction rv_X) 
        (
dom: 
SigmaAlgebra Ts)
        (
cod: 
SigmaAlgebra Td) :
    (
forall (
c : 
Td), 
In c frf_vals -> 
sa_sigma (
pre_event_preimage rv_X (
pre_event_singleton c))) ->
    
RandomVariable dom cod rv_X.
Proof.
  intros Fs.
  
intros x.
  
unfold event_preimage, 
pre_event_preimage in *.
  
unfold pre_event_singleton in *.
  
destruct frf.
  
assert (
exists ld, 
incl ld frf_vals0 /\
                (
forall d: 
Td, 
In d ld -> 
x d) /\
                (
forall d: 
Td, 
In d frf_vals0 -> 
x d -> 
In d ld)).
  {
    
clear frf_vals_complete0 Fs.
    
induction frf_vals0.
    - 
exists nil.
      
split.
      + 
intros ?; 
trivial.
      + 
split.
        * 
simpl; 
tauto.
        * 
intros ??.
          
auto.
    - 
destruct IHfrf_vals0 as [
ld [
ldincl [
In1 In2]]].
      
destruct (
Classical_Prop.classic (
x a)).
      + 
exists (
a::
ld).
        
split; [| 
split].
        * 
red; 
simpl; 
intros ? [?|?]; 
eauto.
        * 
simpl; 
intros ? [?|?].
          -- 
congruence.
          -- 
eauto.
        * 
intros ? [?|?]; 
simpl; 
eauto.
      + 
exists ld.
        
split; [| 
split].
        * 
red; 
simpl; 
eauto.
        * 
eauto.
        * 
simpl; 
intros ? [?|?] ?.
          -- 
congruence.
          -- 
eauto.
  } 
  
destruct H as [
ld [
ld_incl ld_iff]].
  
apply sa_proper with (
x0:=
pre_list_union (
map (
fun d omega => 
rv_X omega = 
d) 
ld)).
  - 
intros e.
    
split; 
intros HH.
    + 
destruct HH as [? [??]].
      
apply in_map_iff in H.
      
destruct H as [? [??]]; 
subst.
      
now apply ld_iff.
    + 
red; 
simpl.
      
apply ld_iff in HH.
      
eexists; 
split.
      * 
apply in_map_iff; 
simpl.
        
eexists; 
split; [
reflexivity |]; 
eauto.
      * 
reflexivity.
      * 
eauto.
  - 
apply sa_pre_list_union; 
intros.
    
apply in_map_iff in H.
    
destruct H as [? [??]]; 
subst.
    
apply Fs.
    
now apply ld_incl.
Qed.
 
Instance rv_fun_simple {
dom: 
SigmaAlgebra Ts}
         {
cod: 
SigmaAlgebra Td}
         (
x : 
Ts -> 
Td) (
f : 
Td -> 
Td)
         {
rvx : 
RandomVariable dom cod x}
         {
frfx : 
FiniteRangeFunction x} :
      (
forall (
c : 
Td), 
In c frf_vals -> 
sa_sigma (
pre_event_preimage x (
pre_event_singleton c))) ->
     
RandomVariable dom cod (
fun u => 
f (
x u)).    
Proof.
End Simple.
Require Import Finite ListAdd SigmaAlgebras EquivDec Eqdep_dec.
Section Finite.
  
Context {
Ts:
Type}{
Td:
Type}.
  
Program Instance Finite_FiniteRangeFunction {
fin:
Finite Ts}  (
rv_X:
Ts->
Td)
    : 
FiniteRangeFunction rv_X
    := {| 
    
frf_vals := 
map rv_X elms
      |}.
  Next Obligation.
  Lemma Finite_finitsubset1 {
A:
Type} {
decA:
EqDec A eq} (
x:
A) (
l:
list A) :
    { 
pfs : 
list (
In x l) | 
forall pf, 
In pf pfs} .
  Proof.
    induction l; 
simpl.
    - 
exists nil.
      
tauto.
    - 
destruct IHl as [
ll pfs].
      
      
destruct (
a == 
x).
      + 
exists ((
or_introl e) :: (
map (@
or_intror _ _) 
ll)).
        
intros [?|?].
        * 
left.
          
f_equal.
          
apply eq_proofs_unicity; 
intros.
          
destruct (
decA x0 y); 
tauto.
        * 
right.
          
apply in_map.
          
apply pfs.
      +  
exists (
map (@
or_intror _ _) 
ll).
         
intros [?|?].
         * 
congruence.
         * 
apply in_map.
           
apply pfs.
  Defined.
 
  Definition Finite_finitsubset2 {
A:
Type} {
decA:
EqDec A eq} (
x:
A) (
l:
list A) :
    
list {
x : 
A | 
In x l}.
  Proof.
  
  Program Instance Finite_finitesubset_dec {
A:
Type} {
decA:
EqDec A eq} (
l:
list A)
    : 
Finite {
x : 
A | 
In x l}.
  Next Obligation.
  Next Obligation.
  Definition finitesubset_sa {
A} (
l:
list A) : 
SigmaAlgebra {
x : 
A | 
In x l}
    := 
discrete_sa {
x : 
A | 
In x l}.
  
End Finite.
Section Event_restricted.
  
Context {
Ts:
Type} {
Td:
Type} {σ:
SigmaAlgebra Ts} {
cod : 
SigmaAlgebra Td}.
  
Global Program Instance Restricted_FiniteRangeFunction (
e:
event σ) (
f : 
Ts -> 
Td)
    (
frf: 
FiniteRangeFunction f) :
    
FiniteRangeFunction (
event_restricted_function e f) :=
    { 
frf_vals := 
frf_vals }.
  Next Obligation.
    destruct frf.
    apply frf_vals_complete0.
  Qed.
  Global Program Instance Restricted_RandomVariable (
e:
event σ) (
f : 
Ts -> 
Td)
          (
rv : 
RandomVariable σ 
cod f) :
    
RandomVariable (
event_restricted_sigma e) 
cod (
event_restricted_function e f).
  Next Obligation.
  Definition lift_event_restricted_domain_fun (
default:
Td) {
P:
event σ} (
f:
event_restricted_domain P -> 
Td) : 
Ts -> 
Td
    := 
fun x =>
         
match excluded_middle_informative (
P x) 
with
         | 
left pf => 
f (
exist _ _ pf)
         | 
right _ => 
default
         end.
  
Global Instance lift_event_restricted_domain_fun_rv (
default:
Td) {
P:
event σ} (
f:
event_restricted_domain P -> 
Td) :
    
RandomVariable (
event_restricted_sigma P) 
cod f ->
    
RandomVariable σ 
cod (
lift_event_restricted_domain_fun default f).
  Proof.
  Global Instance lift_event_restricted_domain_fun_frf (
default:
Td) {
P:
event σ} (
f:
event_restricted_domain P -> 
Td) :
    
FiniteRangeFunction f -> 
    
FiniteRangeFunction (
lift_event_restricted_domain_fun default f).
  Proof.
 End Event_restricted.
Section pullback.
  
Instance pullback_rv {
Ts:
Type} {
Td:
Type}
      (
cod: 
SigmaAlgebra Td)
      (
f: 
Ts -> 
Td) : 
RandomVariable (
pullback_sa cod f) 
cod f.
  Proof.
  Lemma pullback_rv_sub
        {
Ts:
Type} {
Td:
Type}
        (
dom : 
SigmaAlgebra Ts)
        (
cod: 
SigmaAlgebra Td)
        (
f: 
Ts -> 
Td) :
    
RandomVariable dom cod f ->
    
sa_sub (
pullback_sa cod f) 
dom.
  Proof.
    intros frv x [
y[
say yeqq]]; 
simpl in *.
    
apply (
sa_proper _ (
fun a => 
y (
f a))).
    - 
intros ?.
      
now rewrite yeqq.
    - 
specialize (
frv (
exist _ _ say)).
      
apply frv.
  Qed.
 
  Lemma pullback_sa_compose_sub
        {
Ts:
Type} {
Td:
Type}
        (
cod: 
SigmaAlgebra Td)
        (
f: 
Ts -> 
Td) (
g:
Td -> 
Td):
    
sa_sub (
pullback_sa cod g) 
cod ->
    
sa_sub (
pullback_sa cod (
compose g f)) (
pullback_sa cod f).
  Proof.
  Lemma pullback_sa_compose_sub_rv
        {
Ts:
Type} {
Td:
Type}
        (
cod: 
SigmaAlgebra Td)
        (
f: 
Ts -> 
Td) (
g:
Td -> 
Td)
        {
rvg : 
RandomVariable cod cod g} :
    
sa_sub (
pullback_sa cod (
compose g f)) (
pullback_sa cod f).
  Proof.
  Lemma pullback_sa_compose_isos
        {
Ts:
Type} {
Td:
Type}        
        (
rv1 : 
Ts -> 
Td) (
f g : 
Td -> 
Td)
        (
cod: 
SigmaAlgebra Td)
        (
rvf : 
RandomVariable cod cod f)
        (
rvg : 
RandomVariable cod cod g)
        (
inv:
forall (
rv : 
Ts -> 
Td) , 
rv_eq (
compose g (
compose f rv)) 
rv) :
    
sa_equiv (
pullback_sa cod rv1) (
pullback_sa cod (
compose f rv1)).
  Proof.
    
End pullback.
Section sa_sub.
  
Context {
Ts:
Type} 
          {
dom: 
SigmaAlgebra Ts}
          (
prts:
ProbSpace dom)
          {
dom2 : 
SigmaAlgebra Ts}
          (
sub : 
sa_sub dom2 dom).
  
Instance RandomVariable_sa_sub {
Td} {
cod : 
SigmaAlgebra Td}
           
x
           {
rv_x:
RandomVariable dom2 cod x}
  : 
RandomVariable dom cod x.
  Proof.
    intros e.
    
specialize (
rv_x e).
    
now apply sub.
  Qed.
 
End sa_sub.
Section filtration.
    
Context {
Ts:
Type}.
    
Global Instance filtrate_sa_rv {
Td} {
doms: 
nat -> 
SigmaAlgebra Ts} {
cod: 
SigmaAlgebra Td} (
rv:
Ts->
Td) 
n :
      
RandomVariable (
doms n) 
cod rv ->
      
RandomVariable (
filtrate_sa doms n) 
cod rv.
    Proof.
    
End filtration.
Section filtration_history.
  
Context {
Ts:
Type} {
Td:
Type} {
cod: 
SigmaAlgebra Td}.
  
Context (
X : 
nat -> 
Ts -> 
Td).
  
  
Definition filtration_history_sa : 
nat -> 
SigmaAlgebra Ts :=
    
filtrate_sa (
fun n => 
pullback_sa cod (
X n)).
  
Global Instance filtration_history_sa_is_filtration : 
IsFiltration (
filtration_history_sa).
  Proof.
    typeclasses eauto.
  Qed.
  
  Global Instance filtration_history_sa_rv n :
    
RandomVariable (
filtration_history_sa n) 
cod (
X n).
  Proof.
  Instance filtration_history_sa_le_rv
        (
n : 
nat) (
j:
nat) (
jlt: (
j <= 
n)%
nat) :
    
RandomVariable (
filtration_history_sa n) 
cod (
X j).
  Proof.
  Lemma filtration_history_sa_sub_le {
dom:
SigmaAlgebra Ts} 
n
        (
rv:
forall k, 
k <= 
n -> 
RandomVariable dom cod (
X k)) :
    
sa_sub (
filtration_history_sa n) 
dom.
  Proof.
  Lemma filtration_history_sa_sub {
dom:
SigmaAlgebra Ts}
    {
rv:
forall n, 
RandomVariable dom cod (
X n)} :
    
forall n, 
sa_sub (
filtration_history_sa n) 
dom.
  Proof.
  Definition filtration_history_limit_sa : 
SigmaAlgebra Ts
    := 
countable_union_sa (
fun k => 
pullback_sa _ (
X k)).
  
Lemma filtration_history_limit_sa_le_sub n : 
    
sa_sub (
filtration_history_sa n) 
filtration_history_limit_sa.
  Proof.
  Global Instance filtration_history_limit_sa_rv n :
    
RandomVariable (
filtration_history_limit_sa) 
cod (
X n).
  Proof.
  
  Lemma filtration_history_limit_sa_sub (
dom:
SigmaAlgebra Ts)
    {
rv:
forall n, 
RandomVariable dom cod (
X n)} :
    
sa_sub filtration_history_limit_sa dom.
  Proof.
  Global Instance filtration_history_is_sub_algebra
         (
dom:
SigmaAlgebra Ts)
         {
rv:
forall n, 
RandomVariable dom cod (
X n)} :
    
IsSubAlgebras dom (
filtration_history_sa).
  Proof.
End filtration_history.
Section filtration_history_props.
  
Context {
Ts:
Type} {
Td:
Type} {
cod: 
SigmaAlgebra Td}.
  
Lemma filtration_history_sa_iso_l_sub
        (
rv1 : 
nat -> 
Ts -> 
Td) (
f g : 
nat -> 
Td -> 
Td)
        (
inv:
forall n x, 
g n (
f n x) = 
x)
        (
g_sigma:
forall k s, 
sa_sigma s -> 
sa_sigma (
fun x => 
s (
g k x))) :
    
forall n, 
sa_sub (
filtration_history_sa rv1 n) ((
filtration_history_sa (
fun n x => 
f n (
rv1 n x)) 
n)).
  Proof.
  Lemma filtration_history_sa_f_sub
        (
rv1 : 
nat -> 
Ts -> 
Td) (
f : 
nat -> 
Td -> 
Td)
        (
f_sigma:
forall k s, 
sa_sigma s -> 
sa_sigma (
fun x => 
s (
f k x))) :
    
forall n, 
sa_sub ((
filtration_history_sa (
fun n x => 
f n (
rv1 n x)) 
n)) (
filtration_history_sa rv1 n).
  Proof.
  Lemma filtration_history_sa_isos
        (
rv1 : 
nat -> 
Ts -> 
Td) (
f g : 
nat -> 
Td -> 
Td)
        (
inv:
forall n x, 
g n (
f n x) = 
x)
        (
f_sigma:
forall k s, 
sa_sigma s -> 
sa_sigma (
fun x => 
s (
f k x)))
        (
g_sigma:
forall k s, 
sa_sigma s -> 
sa_sigma (
fun x => 
s (
g k x))) :
    
forall n, 
sa_equiv (
filtration_history_sa rv1 n) ((
filtration_history_sa (
fun n x => 
f n (
rv1 n x)) 
n)).
  Proof.
  
End filtration_history_props.
Section adapted.
  
Context {
Ts:
Type} {
Td:
Type} (
cod: 
SigmaAlgebra Td).
  
Class IsAdapted (
X : 
nat -> 
Ts -> 
Td) (
sas : 
nat -> 
SigmaAlgebra Ts)
    := 
is_adapted : 
forall (
n:
nat), 
RandomVariable (
sas n) 
cod (
X n).
  
Global Instance filtration_history_sa_is_adapted (
X : 
nat -> 
Ts -> 
Td) :
    
IsAdapted X (
filtration_history_sa X).
  Proof.
  Global Instance is_adapted_proper : 
Proper (
pointwise_relation _ rv_eq ==> 
pointwise_relation _ sa_sub ==> 
impl) 
IsAdapted.
  Proof.
  Global Instance is_adapted_eq_proper : 
Proper (
pointwise_relation _ rv_eq ==> 
pointwise_relation _ sa_equiv ==> 
iff) 
IsAdapted.
  Proof.
  Lemma filtration_history_sa_is_least
        (
X : 
nat -> 
Ts -> 
Td) 
sas
        {
filt:
IsFiltration sas}
        {
adapt:
IsAdapted X sas}:
    
forall n, 
sa_sub (
filtration_history_sa X n) (
sas n).
  Proof.
End adapted.
Section prod_space.
  
Context {
Ts Td1 Td2}
          {
dom:
SigmaAlgebra Ts} {
cod1:
SigmaAlgebra Td1}
          {
cod2:
SigmaAlgebra Td2}.
  
Global Instance product_sa_rv
         (
X1:
Ts->
Td1) (
X2:
Ts->
Td2) 
         {
rv1:
RandomVariable dom cod1 X1}
         {
rv2:
RandomVariable dom cod2 X2} :
    
RandomVariable dom (
product_sa cod1 cod2) (
fun a => (
X1 a, 
X2 a)).
  Proof.
End prod_space.