Set Implicit Arguments.
Require Export sampled_streams.
Require Arith.
Section SP_rec.
Hint Resolve sp_tl_nth_tl : 
sampled_str.
Hint Resolve sp_eq_sp_nth sp_nth_sp_eq : 
sampled_str.
Hint Resolve loc_nfstwf_S_n_n loc_nfstwf_S_n_n_tl loc_nfstwf_nth : 
sampled_str.
Hint Resolve undef_min : 
sampled_str.
Variable A: 
Set.
Section Rec1.
Variable B: 
Set.
Variable C: 
B -> 
clock. 
Variable F1: (
forall (
x: 
B), 
samplStr A (
C x)) -> 
forall (
x: 
B), 
samplStr A (
C x).
Variable P: 
B -> 
Prop.
Hypothesis F1_lfp :
  
forall (
s1 s2: 
forall (
x: 
B), 
samplStr A (
C x)) (
n: 
nat),
    (
forall (
x: 
B), 
P x -> 
sp_inf n (
s1 x) (
s2 x)) ->
    
forall (
x: 
B), 
P x -> 
sp_inf n (
F1 s1 x) (
F1 s2 x).
Hypothesis F1_nfstwf_inc :
  
forall (
n: 
nat) (
s: 
forall (
x: 
B), 
samplStr A (
C x)),
    (
forall (
x: 
B), 
P x -> 
loc_nfstwf n (
s x))
      -> 
forall (
x: 
B), 
P x -> 
loc_nfstwf (
S n) (
F1 s x).
Lemma powerF1_loc_nfstwf :
  
forall (
n: 
nat) (
x: 
B), 
P x ->
     
loc_nfstwf n (
funPower F1 n (
fun (
z: 
B) => 
undef A (
C z)) 
x).
Proof.
  intros n; 
elim n; 
auto with sampled_str.
  
intros; 
rewrite <- 
funPower_commut ; 
auto.
Qed.
 
Lemma powerF1_lfp :
  
forall (
n m: 
nat) (
s1 s2: 
forall (
x: 
B), 
samplStr A (
C x)),
    (
forall (
x: 
B), 
P x -> 
sp_inf m (
s1 x) (
s2 x)) ->
      
forall (
x: 
B), 
P x -> 
sp_inf m (
funPower F1 n s1 x) (
funPower F1 n s2 x).
Proof.
  intros n; elim n; simpl; auto.
Qed.
Lemma powerF1_increases :
  
forall (
n m: 
nat) (
x: 
B), 
P x ->
    
sp_inf m (
funPower F1 n (
fun (
z: 
B) => 
undef A (
C z)) 
x) (
funPower F1 (
S n) (
fun (
z: 
B) => 
undef A (
C z)) 
x).
Proof.
  intros; 
simpl; 
apply powerF1_lfp; 
auto with sampled_str.
Qed.
 
Hint Resolve powerF1_loc_nfstwf powerF1_increases : 
sampled_str.
Lemma powerF1_nth :
  
forall (
n m: 
nat) (
x: 
B), 
le n m -> 
P x ->
    
sp_nth n (
funPower F1 (
S m) (
fun (
z: 
B) => 
undef A (
C z)) 
x)
   = 
sp_nth n (
funPower F1 (
S (
S m)) (
fun (
z: 
B) => 
undef A (
C z)) 
x).
Proof.
Section Rec1_ext.
Variable r1: 
forall (
x: 
B), 
samplStr A (
C x).
Hypothesis r1_inv : 
forall (
x: 
B), 
P x -> 
sp_eq (
r1 x) (
F1 r1 x).
Lemma r1_prop :
  
forall (
n m: 
nat) (
x: 
B),
      
P x -> 
sp_inf m (
funPower F1 n (
fun (
z: 
B) => 
undef A (
C z)) 
x) (
r1 x).
Proof.
intros n; 
elim n.
  
simpl; 
auto with sampled_str.
  
intros n' 
HR m x H'; 
rewrite <- 
funPower_commut.
  
apply sp_inf_trans with (
s2 := 
F1 r1 x); 
auto with sampled_str.
Qed.
 
Theorem r1_ext :
  
forall (
n: 
nat) (
x: 
B), 
P x ->
      
sp_nth n (
r1 x) = 
sp_nth n (
funPower F1 (
S n) (
fun (
z: 
B) => 
undef A (
C z)) 
x).
Proof.
End Rec1_ext.
Let sp_app_powerF1_undef :
  
forall (
n: 
nat) (
s: 
forall (
x: 
B), 
samplStr A (
clock_nth_tl (
S n) (
C x))) (
x: 
B),
    
P x ->
     
sp_app_n (
funPower F1 n (
fun (
z: 
B) => 
undef A (
C z)) 
x) 
_
               (
sp_cons _ (
sp_nth n (
funPower F1 (
S n) (
fun (
z: 
B) => 
undef A (
C z)) 
x)) (
s x))
     = 
sp_app_n (
funPower F1 (
S n) (
fun (
z: 
B) => 
undef A (
C z)) 
x) 
_ (
s x).
Proof.
CoFixpoint rec1_tmp (
n: 
nat) (
s: 
forall (
x: 
B), 
samplStr A (
C x)) :
     
forall (
x: 
B), 
samplStr A (
clock_nth_tl n (
C x)) :=
  
let s' := 
F1 s in fun x => 
sp_cons _ (
sp_nth n (
s' 
x)) (
rec1_tmp (
S n) 
s' 
x).
Let rec1_tmp_power :
  
forall (
n: 
nat) (
x: 
B), 
rec1_tmp n (
funPower F1 n (
fun (
z: 
B) => 
undef A (
C z))) 
x
      = 
sp_cons _ (
sp_nth n (
funPower F1 (
S n) (
fun (
z: 
B) => 
undef A (
C z)) 
x))
                (
rec1_tmp (
S n) (
funPower F1 (
S n) (
fun (
z: 
B) => 
undef A (
C z))) 
x).
Proof.
Lemma rec1_tmp_S_n_m :
  
forall (
n m: 
nat) (
x: 
B),
    
sp_nth (
S n) (
rec1_tmp m (
funPower F1 m (
fun (
z: 
B) => 
undef A (
C z))) 
x)
    ==<< 
samplElt A >> 
sp_nth n (
rec1_tmp (
S m) (
funPower F1 (
S m) (
fun (
z: 
B) => 
undef A (
C z))) 
x).
Proof.
Lemma rec1_tmp_wf :
  
forall (
n: 
nat) (
x: 
B), 
P x ->
     
sp_wf (
rec1_tmp n (
funPower F1 n (
fun (
z: 
B) => 
undef A (
C z))) 
x).
Proof.
Let rec1_tmp_lemma_aux :
  
forall (
n: 
nat) (
x: 
B), 
P x ->
    
flat_ord (
sp_nth n (
F1 (
funPower F1 n (
fun (
z: 
B) => 
undef A (
C z))) 
x))
       (
sp_nth n (
F1 (
fun (
y: 
B) => 
sp_app_n (
funPower F1 n (
fun (
z: 
B) => 
undef A (
C z)) 
y)
                                
_ (
rec1_tmp n (
funPower F1 n (
fun (
z: 
B) => 
undef A (
C z))) 
y)) 
x)).
Proof.
Let rec1_tmp_lemma :
  
forall (
n m: 
nat) (
x: 
B), 
P x ->
     
sp_inf n (
rec1_tmp m (
funPower F1 m (
fun (
z: 
B) => 
undef A (
C z))) 
x)
                           (
sp_nth_tl m (
F1 (
fun (
y: 
B) => 
sp_app_n (
funPower F1 m (
fun (
z: 
B) => 
undef A (
C z)) 
y)
                                                           
_ (
rec1_tmp m (
funPower F1 m (
fun (
z: 
B) => 
undef A (
C z))) 
y))
                                         
x)).
Proof.
fixpoint operator *
Definition rec1 (
y: 
B) : 
samplStr A (
C y) :=
  
rec1_tmp O (
fun (
x: 
B) => 
undef A (
C x)) 
y.
Lemma rec1_wf :
  
forall (
x: 
B), 
P x -> 
sp_wf (
rec1 x).
Proof.
Theorem rec1_inv :
  
forall (
x: 
B), 
P x -> 
sp_eq (
rec1 x) (
F1 rec1 x).
Proof.
Theorem rec1_uniq :
  
forall (
r1: 
forall (
x: 
B), 
samplStr A (
C x)),
    (
forall (
x: 
B), 
P x -> 
sp_eq (
r1 x) (
F1 r1 x))
     -> 
forall (
x: 
B), 
P x -> 
sp_eq (
rec1 x) (
r1 x).
Proof.
End Rec1.
Section Rec1_lfp.
Variable B: 
Set.
Variable C: 
B -> 
clock.
Variable F1 F2: (
forall (
x: 
B), 
samplStr A (
C x))  -> 
forall (
x: 
B), 
samplStr A (
C x).
Variable n: 
nat.
Hypothesis F1_inf_F2 :
  
forall (
s1 s2: 
forall (
x: 
B), 
samplStr A (
C x)),
    (
forall (
x: 
B), 
sp_inf n (
s1 x) (
s2 x))
    -> 
forall (
x: 
B), 
sp_inf n (
F1 s1 x) (
F2 s2 x).
Lemma power_F1_F2_inf :
  
forall (
m: 
nat) (
s1 s2: 
forall (
x: 
B), 
samplStr A (
C x)),
    (
forall (
x: 
B), 
sp_inf n (
s1 x) (
s2 x))
    -> 
forall (
x: 
B), 
sp_inf n (
funPower F1 m s1 x) (
funPower F2 m s2 x).
Proof.
  intros m; elim m; simpl; auto with sampled_str.
Qed.
Hint Resolve rec1_tmp_S_n_m : 
sampled_str.
Lemma rec1_tmp_lfp :
  
forall (
m: 
nat) (
x: 
B), 
le m n ->
      
sp_inf (
minus n m)
                 (
rec1_tmp _ F1 m (
funPower F1 m (
fun (
z: 
B) => 
undef A _)) 
x)
                 (
rec1_tmp _ F2 m (
funPower F2 m (
fun (
z: 
B) => 
undef A _)) 
x).
Proof.
Theorem rec1_lfp :
  
forall (
x: 
B), 
sp_inf n (
rec1 _ F1 x) (
rec1 _ F2 x).
Proof.
End Rec1_lfp.
Section Rec1_loc_nfstwf.
Variable B: 
Set.
Variable C: 
B -> 
clock.
Variable F1: (
forall (
x: 
B), 
samplStr A (
C x)) -> 
forall (
x: 
B), 
samplStr A (
C x).
Variable P: 
B -> 
Prop.
Variable n: 
nat.
Hypothesis F1_nfstwf_inc_limited :
  
forall (
m: 
nat) (
s: 
forall (
x: 
B), 
samplStr A (
C x)),
    
lt m n ->
    (
forall (
x: 
B), 
P x -> 
loc_nfstwf m (
s x))
      ->
forall (
x: 
B), 
P x -> 
loc_nfstwf (
S m) (
F1 s x).
Lemma powerF1_loc_nfstwf_limited :
  
forall (
m: 
nat) (
x: 
B), 
P x -> 
le m n ->
  
loc_nfstwf m (
funPower F1 m (
fun (
z: 
B) => 
undef A _) 
x).
Proof.
  intros m; 
elim m.
  
simpl; 
auto with sampled_str.
  
intros; 
rewrite <- 
funPower_commut; 
auto with arith sampled_str.
Qed.
 
Hypothesis F1_lfp :
  
forall (
s1 s2: 
forall (
x: 
B), 
samplStr A (
C x)) (
n: 
nat),
    (
forall (
x: 
B), 
P x -> 
sp_inf n (
s1 x) (
s2 x)) ->
    
forall (
x: 
B), 
P x -> 
sp_inf n (
F1 s1 x) (
F1 s2 x).
Lemma powerF1_increases_le :
  
forall (
k1 k2: 
nat), 
le k1 k2 -> 
forall (
m: 
nat) (
x: 
B), 
P x ->
    
sp_inf m (
funPower F1 k1 (
fun (
z: 
B) => 
undef A (
C z)) 
x) (
funPower F1 k2 (
fun (
z: 
B) => 
undef A (
C z)) 
x).
Proof.
Lemma powerF1_loc_nfstwf_lim :
  
forall (
m: 
nat) (
x: 
B), 
P x -> 
le (
glob2loc m (
C x)) 
n ->
  
loc_nfstwf (
glob2loc m (
C x)) (
funPower F1 m (
fun (
z: 
B) => 
undef A _) 
x).
Proof.
Require Import Lia.
Lemma rec1_tmp_loc_nfstwf :
  
forall (
m k: 
nat) (
x: 
B), 
P x -> 
le (
plus m (
glob2loc k (
C x))) 
n ->
   
forall (
s: 
forall (
z: 
B), 
samplStr A (
C z)),
   
s = 
funPower F1 k (
fun (
z: 
B) => 
undef A _)
    -> 
loc_nfstwf m (
rec1_tmp _ F1 k s x).
Proof.
Theorem rec1_loc_nfstwf :
  
forall (
x: 
B), 
P x -> 
loc_nfstwf n (
rec1 _ F1 x).
Proof.
End Rec1_loc_nfstwf.
Section Rec0.
Variable c: 
clock.
Variable F0: 
samplStr A c -> 
samplStr A c.
Hypothesis F0_lfp :
  
forall (
s1 s2: 
samplStr A c) (
n: 
nat),
    
sp_inf n s1 s2 -> 
sp_inf n (
F0 s1) (
F0 s2).
Hypothesis F0_nfstwf_inc :
  
forall (
n: 
nat) (
s: 
samplStr A c),
    
glob_nfstwf n s -> 
glob_nfstwf (
S n) (
F0 s).
Lemma F0_loc_nfstwf_inc :
  
forall (
n: 
nat) (
s: 
samplStr A c),
    
loc_nfstwf n s -> 
loc_nfstwf (
S n) (
F0 s).
Proof.
Hint Resolve F0_loc_nfstwf_inc : 
sampled_str.
Definition rec0 :=
  
rec1 (
fun (
x: 
unit) => 
c) (
fun (
f: 
unit-> 
samplStr A c) (
x: 
unit) => 
F0 (
f x)) 
tt.
Lemma rec0_wf : 
sp_wf rec0.
Proof.
  unfold rec0; 
apply rec1_wf with
     (
C := 
fun (
x: 
unit) => 
c)
     (
F1 := 
fun (
f: 
unit-> 
samplStr A c) (
x: 
unit) => 
F0 (
f x))
     (
x := 
tt)
     (
P := 
fun (
_: 
unit) => 
True);
   
auto with sampled_str.
Qed.
 
Theorem rec0_inv : 
sp_eq rec0 (
F0 rec0).
Proof.
  unfold rec0; 
apply rec1_inv with
     (
C := 
fun (
x: 
unit) => 
c)
     (
F1 := 
fun (
f: 
unit-> 
samplStr A c) (
x: 
unit) => 
F0 (
f x))
     (
x := 
tt)
     (
P := 
fun (
_: 
unit) => 
True);
   
auto with sampled_str.
Qed.
 
Theorem rec0_uniq :
  
forall (
r0: 
samplStr A c), 
sp_eq r0 (
F0 r0) -> 
sp_eq rec0 r0.
Proof.
  unfold rec0; 
intros r0 H; 
apply rec1_uniq with
     (
C:= 
fun (
x: 
unit) => 
c)
     (
F1:= 
fun (
f: 
unit-> 
samplStr A c) (
x: 
unit) => 
F0 (
f x))
     (
x := 
tt)
     (
r1 := 
fun (
_: 
unit) => 
r0)
     (
P := 
fun (
_: 
unit) => 
True);
   
auto with sampled_str.
Qed.
 
End Rec0.
Section Rec0_props.
Variable c: 
clock.
Theorem rec0_lfp :
  
forall (
F1 F2: 
samplStr A c -> 
samplStr A c) (
n: 
nat),
    (
forall (
s1 s2: 
samplStr A c),
       
sp_inf n s1 s2 -> 
sp_inf n (
F1 s1) (
F2 s2))
     -> 
sp_inf n (
rec0 F1) (
rec0 F2).
Proof.
  intros F1 F2 H n.
  
unfold rec0; 
apply rec1_lfp with
     (
C := 
fun (
x: 
unit) => 
c)
     (
F1 := 
fun (
f: 
unit-> 
samplStr A c) (
x: 
unit) => 
F1 (
f x))
     (
F2 := 
fun (
f: 
unit -> 
samplStr A c) (
x: 
unit) => 
F2 (
f x))
     (
x := 
tt);
   
auto.
Qed.
 
Theorem rec0_loc_nfstwf :
  
forall (
F0: 
samplStr A c -> 
samplStr A c) (
n: 
nat),
    (
forall (
m: 
nat) (
s: 
samplStr A c),
      
lt m n -> 
loc_nfstwf m s -> 
loc_nfstwf (
S m) (
F0 s))
    -> (
forall (
s1 s2: 
samplStr A c) (
m: 
nat),
          
sp_inf m s1 s2 -> 
sp_inf m (
F0 s1) (
F0 s2))
    -> 
loc_nfstwf n (
rec0 F0).
Proof.
  intros F0 n H1 H2.
  
unfold rec0; 
apply rec1_loc_nfstwf with
     (
C := 
fun (
x: 
unit) => 
c)
     (
F1 := 
fun (
f: 
unit-> 
samplStr A c) (
x: 
unit) => 
F0 (
f x))
     (
x := 
tt)
     (
n := 
n)
     (
P:= 
fun (
_: 
unit) => 
True);
   
auto.
Qed.
 
Require Peano_dec.
Theorem rec0_glob_nfstwf :
  
forall (
F0: 
samplStr A c -> 
samplStr A c) (
n: 
nat),
    (
forall (
m: 
nat) (
s: 
samplStr A c),
      
lt m n -> 
glob_nfstwf m s -> 
glob_nfstwf (
S m) (
F0 s))
    -> (
forall (
s1 s2: 
samplStr A c) (
m: 
nat),
         
sp_inf m s1 s2 -> 
sp_inf m (
F0 s1) (
F0 s2))
    -> 
glob_nfstwf n (
rec0 F0).
Proof.
  intros F0 n H1 H2; apply loc_nfstwf_glob_nfstwf;
  apply rec0_loc_nfstwf; auto.
  intros; apply nfstwf_function_convert_S_recip with (f := F0) (n := n); auto.
Qed.
End Rec0_props.
End SP_rec.
Notation "'<' 
c '>
rec0' " := (
rec0 (
c := 
c)) (
at level 100).
Unset Implicit Arguments.