From Coq Require Import BinPos List.
Import List ListNotations.
From Velus Require Import CommonTactics Common.Common.
From Velus Require Import Lustre.Denot.Cpo.
Streams operations for the Lustre synchronous semantics
Inductive error :=
|
error_Ty
|
error_Cl
|
error_Op
.
Inductive sampl (
A :
Type) :
Type :=
|
abs
|
pres (
a:
A)
|
err (
e :
error).
Arguments abs {
A}.
Arguments pres {
A}
a.
Arguments err {
A}
e.
Local Hint Rewrite
ford_fcont_shift_simpl
curry_Curry
Curry_simpl
fcont_comp_simpl
fcont_comp2_simpl
fcont_comp3_simpl
fcont_comp4_simpl
SND_simpl Snd_simpl
FST_simpl Fst_simpl
DSCASE_simpl
DScase_cons
@
zip_cons
:
localdb.
Repeated absences
Section Abs.
Context {
A I :
Type}.
infinity of absences
Definition abss :
DS (
sampl A) :=
DS_const abs.
Definition abs_env :
DS_prod (
fun _ :
I =>
sampl A) :=
fun _ =>
abss.
Lemma abs_abs_abs :
abs_env ==
APP_env abs_env abs_env.
Proof.
Lemma all_cons_abs_env :
all_cons abs_env.
Proof.
Lemma abs_env_inf :
all_infinite abs_env.
Proof.
Lemma rem_abs_env :
REM_env (
abs_env) ==
abs_env.
Proof.
End Abs.
abstract_clock as defined in Vélus, considering errors as absences
Section Abstract_clock.
Context {
A I :
Type}.
Definition AC :
DS (
sampl A) -
C->
DS bool :=
MAP (
fun v =>
match v with pres _ =>
true | _ =>
false end).
Lemma AC_cons :
forall u U,
AC (
cons u U) ==
cons match u with
|
pres _ =>
true
| _ =>
false
end (
AC U).
Proof.
Lemma AC_is_cons :
forall U,
is_cons (
AC U) <->
is_cons U.
Proof.
Lemma first_AC :
forall s,
first (
AC s) ==
AC (
first s).
Proof.
Lemma rem_AC :
forall s,
rem (
AC s) ==
AC (
rem s).
Proof.
Lemma AC_app :
forall xs ys,
AC (
app xs ys) ==
app (
AC xs) (
AC ys).
Proof.
equivalent of clocks_of
Fixpoint bss (
ins :
list I) :
DS_prod (
fun _ =>
sampl A) -
C->
DS bool :=
match ins with
| [] =>
CTE _ _ (
DS_const false)
|
x ::
nil =>
AC @_
PROJ _
x
|
x ::
ins => (
ZIP orb @2_ (
AC @_
PROJ _
x)) (
bss ins)
end.
Lemma bss_cons :
forall x l env,
bss (
x ::
l)
env ==
ZIP orb (
AC (
env x)) (
bss l env).
Proof.
Lemma bss_cons2 :
forall x y l env,
bss (
x ::
y ::
l)
env =
ZIP orb (
AC (
env x)) (
bss (
y ::
l)
env).
Proof.
trivial.
Qed.
Lemma bss_inf :
forall l env,
all_infinite env ->
infinite (
bss l env).
Proof.
induction l as [|?[]];
simpl;
intros *
Hinf.
-
apply DS_const_inf.
-
autorewrite with cpodb.
apply map_inf,
Hinf.
-
autorewrite with cpodb.
apply zip_inf;
auto.
apply map_inf,
Hinf.
Qed.
Lemma bss_inf_dom :
forall l env,
infinite_dom env l ->
infinite (
bss l env).
Proof.
induction l as [|?[]];
simpl;
intros *
Hinf.
-
apply DS_const_inf.
-
autorewrite with cpodb.
apply map_inf,
Hinf;
now left.
-
autorewrite with cpodb.
unfold infinite_dom in *;
simpl in Hinf.
apply zip_inf;
auto.
apply map_inf,
Hinf;
now left.
Qed.
Lemma bss_switch_env :
forall l env env',
(
forall x,
In x l ->
env x ==
env' x) ->
bss l env ==
bss l env'.
Proof.
induction l as [|x []]; intros * Heq; auto.
- simpl; autorewrite with cpodb.
rewrite (Heq x); simpl; auto.
- simpl; autorewrite with cpodb.
rewrite (Heq x), IHl; simpl in *; eauto.
Qed.
Lemma rem_bss :
forall l env,
rem (
bss l env) ==
bss l (
REM_env env).
Proof.
End Abstract_clock.
unop and binop are in a separate section to ease their usage by other
primitives
Section Sunop_binop.
Context {
A B D :
Type}.
Definition sunop (
uop :
A ->
option B) :
DS (
sampl A) -
C->
DS (
sampl B) :=
MAP (
fun x =>
match x with
|
pres v =>
match uop v with
|
Some y =>
pres y
|
None =>
err error_Op
end
|
abs =>
abs
|
err e =>
err e
end).
Lemma sunop_eq :
forall uop u U,
sunop uop (
cons u U)
==
cons match u with
|
pres u =>
match uop u with
|
Some v =>
pres v
|
None =>
err error_Op
end
|
abs =>
abs
|
err e =>
err e
end (
sunop uop U).
Proof.
Definition sbinop (
bop :
A ->
B ->
option D) :
DS (
sampl A) -
C->
DS (
sampl B) -
C->
DS (
sampl D) :=
ZIP (
fun va vb =>
match va,
vb with
|
err e, _ =>
err e
| _,
err e =>
err e
|
abs,
abs =>
abs
|
pres a,
pres b =>
match bop a b with
|
Some v =>
pres v
|
None =>
err error_Op
end
| _, _ =>
err error_Cl
end).
Lemma sbinop_eq :
forall bop u U v V,
sbinop bop (
cons u U) (
cons v V)
==
cons match u,
v with
|
err e, _ =>
err e
| _,
err e =>
err e
|
abs,
abs =>
abs
|
pres a,
pres b =>
match bop a b with
|
Some v =>
pres v
|
None =>
err error_Op
end
| _, _ =>
err error_Cl
end (
sbinop bop U V).
Proof.
Lemma is_cons_sbinop :
forall bop U V,
is_cons U /\
is_cons V ->
is_cons (
sbinop bop U V).
Proof.
Lemma sbinop_is_cons :
forall bop U V,
is_cons (
sbinop bop U V) ->
is_cons U /\
is_cons V.
Proof.
End Sunop_binop.
Section SStream_functions.
Context {
A B :
Type}.
Rythm of constants if given by the base clock as an argument
Definition sconst (
v :
A) :
DS bool -
C->
DS (
sampl A) :=
MAP (
fun c :
bool =>
if c then pres v else abs).
Lemma sconst_cons :
forall c b bs,
sconst c (
cons b bs) ==
cons (
if b then pres c else abs) (
sconst c bs).
Proof.
Lemma AC_sconst :
forall c bs,
AC (
sconst c bs) ==
bs.
Proof.
fby1 is defined by means of two mutually recursive functions, see
fby1APf_eq and fby1f_eq above for explanation
That is why we keep an option in fby1, even if it is always called
with (Some _).
Definition fby1sf :
(
bool -
O->
option A -
O->
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A)) -
C->
(
bool -
O->
option A -
O->
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A)).
apply ford_fcont_shift.
intros [].
-
apply ford_fcont_shift.
intro ov.
apply curry,
curry.
eapply (
fcont_comp2 (
DSCASE _ _)).
2:
exact (
SND _ _).
apply ford_fcont_shift.
intro y.
apply curry.
match goal with
| |- _ (_ (
Dprod ?
pl ?
pr) _) =>
pose (
fby1 :=
fcont_ford_shift _ _ _ ((
FST _ _ @_
FST _ _ @_ (
FST pl pr)))
false);
pose (
xs := (
SND _ _ @_
FST _ _ @_
FST pl pr));
pose (
ys' :=
SND pl pr)
end.
refine match ov,
y with
|
Some v,
abs
|
None,
pres v => (
fcont_ford_shift _ _ _
fby1 (
Some v) @3_
ID _)
xs ys'
| _,
err _ => (
MAP (
fun _ =>
y) @_
xs)
| _, _ => (
MAP (
fun _ =>
err error_Cl) @_
xs)
end.
-
apply ford_fcont_shift.
intro ov.
apply curry,
curry.
eapply (
fcont_comp2 (
DSCASE _ _)).
2:
exact (
SND _ _ @_
FST _ _).
apply ford_fcont_shift.
intro x.
apply curry.
match goal with
| |- _ (_ (
Dprod ?
pl ?
pr) _) =>
pose (
fby1AP :=
fcont_ford_shift _ _ _ ((
FST _ _ @_
FST _ _ @_ (
FST pl pr)))
true);
pose (
ys := (
SND _ _ @_
FST pl pr));
pose (
xs' :=
SND pl pr)
end.
refine match ov,
x with
|
Some v,
pres _ =>
CONS (
pres v) @_ ((
fcont_ford_shift _ _ _
fby1AP None @3_
ID _)
xs' ys)
|
Some v,
abs =>
CONS abs @_ ((
fcont_ford_shift _ _ _
fby1AP (
Some v) @3_
ID _)
xs' ys)
| _,
err _ =>
CONS x @_
MAP (
fun _ =>
x) @_
xs'
| _, _ =>
CONS (
err error_Cl) @_
MAP (
fun _ =>
err error_Cl) @_
xs'
end.
Defined.
Lemma fby1APf_eq :
forall F ov xs y ys,
fby1sf F true ov xs (
cons y ys)
==
match ov,
y with
|
Some v,
abs
|
None,
pres v =>
F false (
Some v)
xs ys
| _,
err _ =>
map (
fun _ =>
y)
xs
| _, _ =>
map (
fun _ =>
err error_Cl)
xs
end.
Proof.
Lemma fby1f_eq :
forall F ov x xs ys,
fby1sf F false ov (
cons x xs)
ys
==
match ov,
x with
|
Some v,
pres _ =>
cons (
pres v) (
F true None xs ys)
|
Some v,
abs =>
cons abs (
F true (
Some v)
xs ys)
| _,
err _ =>
cons x (
map (
fun _ =>
x)
xs)
| _, _ =>
cons (
err error_Cl) (
map (
fun _ =>
err error_Cl)
xs)
end.
Proof.
Definition fby1s : (
bool -
O->
option A -
O->
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A)) :=
FIXP _
fby1sf.
Definition fby1AP :
option A -
O->
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A) :=
fby1s true.
Definition fby1 :
option A -
O->
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A) :=
fby1s false.
Lemma fby1AP_eq :
forall ov xs y ys,
fby1AP ov xs (
cons y ys)
==
match ov,
y with
|
Some v,
abs
|
None,
pres v =>
fby1 (
Some v)
xs ys
| _,
err _ =>
map (
fun _ =>
y)
xs
| _, _ =>
map (
fun _ =>
err error_Cl)
xs
end.
Proof.
Lemma fby1_eq :
forall ov x xs ys,
fby1 ov (
cons x xs)
ys
==
match ov,
x with
|
Some v,
abs =>
cons abs (
fby1AP (
Some v)
xs ys)
|
Some v,
pres _ =>
cons (
pres v) (
fby1AP None xs ys)
| _,
err _ =>
cons x (
map (
fun _ =>
x)
xs)
| _, _ =>
cons (
err error_Cl) (
map (
fun _ =>
err error_Cl)
xs)
end.
Proof.
Lemma fby1AP_cons :
forall ov xs ys,
is_cons (
fby1AP ov xs ys) ->
is_cons ys.
Proof.
Lemma fby1_cons :
forall ov xs ys,
is_cons (
fby1 ov xs ys) ->
is_cons xs.
Proof.
Lemma fby1_bot1 :
forall o ys,
fby1 o 0
ys == 0.
Proof.
Global Opaque fby1s.
Definition fbysf :
(
bool -
O->
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A)) -
C->
(
bool -
O->
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A)).
apply ford_fcont_shift.
intros [].
-
apply curry,
curry.
refine ((
DSCASE _ _ @2_ _) (
SND _ _)).
apply ford_fcont_shift.
intro y.
apply curry.
match goal with
| |- _ (_ (
Dprod ?
pl ?
pr) _) =>
pose (
fby :=
fcont_ford_shift _ _ _ ((
FST _ _ @_
FST _ _ @_ (
FST pl pr)))
false);
pose (
xs := (
SND _ _ @_
FST _ _ @_
FST pl pr));
pose (
ys' :=
SND pl pr)
end.
refine match y with
|
abs => (
fby @3_
ID _)
xs ys'
|
err _ => (
MAP (
fun _ =>
y) @_
xs)
|
pres _ => (
MAP (
fun _ =>
err error_Cl) @_
xs)
end.
-
apply curry,
curry.
eapply (
fcont_comp2 (
DSCASE _ _)).
2:
exact (
SND _ _ @_
FST _ _).
apply ford_fcont_shift.
intro x.
apply curry.
match goal with
| |- _ (_ (
Dprod ?
pl ?
pr) _) =>
pose (
fbyA :=
fcont_ford_shift _ _ _ ((
FST _ _ @_
FST _ _ @_ (
FST pl pr)))
true);
pose (
ys := (
SND _ _ @_
FST pl pr));
pose (
xs' :=
SND pl pr)
end.
refine match x with
|
abs =>
CONS abs @_ ((
fbyA @3_
ID _)
xs' ys)
|
pres v =>
CONS (
pres v) @_ ((
fby1AP None @2_
xs')
ys)
|
err _ =>
CONS x @_
MAP (
fun _ =>
x) @_
xs'
end.
Defined.
Lemma fbyAf_eq :
forall F xs y ys,
fbysf F true xs (
cons y ys)
==
match y with
|
abs =>
F false xs ys
|
err _ =>
map (
fun _ =>
y)
xs
|
pres _ =>
map (
fun _ =>
err error_Cl)
xs
end.
Proof.
Lemma fbyf_eq :
forall F x xs ys,
fbysf F false (
cons x xs)
ys
==
match x with
|
abs =>
cons abs (
F true xs ys)
|
pres v =>
cons x (
fby1AP None xs ys)
|
err _ =>
cons x (
map (
fun _ =>
x)
xs)
end.
Proof.
Definition fbys : (
bool -
O->
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A)) :=
FIXP _
fbysf.
Lemma fbysF_eq :
forall x xs ys,
fbys false (
cons x xs)
ys
==
match x with
|
abs =>
cons abs (
fbys true xs ys)
|
pres v =>
cons x (
fby1AP None xs ys)
|
err _ =>
cons x (
map (
fun _ =>
x)
xs)
end.
Proof.
Lemma fbysT_eq :
forall xs y ys,
fbys true xs (
cons y ys)
==
match y with
|
abs =>
fbys false xs ys
|
err _ =>
map (
fun _ =>
y)
xs
|
pres _ =>
map (
fun _ =>
err error_Cl)
xs
end.
Proof.
Definition fbyA :
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A) :=
fbys true.
Definition fby :
DS (
sampl A) -
C->
DS (
sampl A) -
C->
DS (
sampl A) :=
fbys false.
Lemma fbyA_eq :
forall xs y ys,
fbyA xs (
cons y ys)
==
match y with
|
abs =>
fby xs ys
|
err _ =>
map (
fun _ =>
y)
xs
|
pres _ =>
map (
fun _ =>
err error_Cl)
xs
end.
Proof.
Lemma fby_eq :
forall x xs ys,
fby (
cons x xs)
ys
==
match x with
|
abs =>
cons abs (
fbyA xs ys)
|
pres v =>
cons x (
fby1AP None xs ys)
|
err _ =>
cons x (
map (
fun _ =>
x)
xs)
end.
Proof.
Lemma fbyA_cons :
forall xs ys,
is_cons (
fbyA xs ys) ->
is_cons ys.
Proof.
Lemma fby_cons :
forall xs ys,
is_cons (
fby xs ys) ->
is_cons xs.
Proof.
Lemma is_cons_fby :
forall (
xs ys :
DS (
sampl A)),
is_cons xs ->
is_cons (
fby xs ys).
Proof.
Lemma fbyA_bot :
forall xs,
fbyA xs 0 == 0.
Proof.
Lemma fby_bot :
forall ys,
fby 0
ys == 0.
Proof.
Global Opaque fbys.
Section When_Case.
Variable enumtag :
Type.
Variable tag_of_val :
B ->
option enumtag.
Variable tag_eqb :
enumtag ->
enumtag ->
bool.
Hypothesis tag_eqb_eq :
forall t1 t2,
tag_eqb t1 t2 =
true <->
t1 =
t2.
Lemma tag_eqb_refl :
forall t,
tag_eqb t t =
true.
Proof.
Lemma tag_eqb_neq :
forall t1 t2,
tag_eqb t1 t2 =
false <->
t1 <>
t2.
Proof.
intros.
destruct (
tag_eqb _ _)
eqn:
HH.
-
firstorder;
congruence.
-
firstorder;
intros HHH%
tag_eqb_eq;
congruence.
Qed.
Definition swhen (
k :
enumtag) :
DS (
sampl A) -
C->
DS (
sampl B) -
C->
DS (
sampl A) :=
ZIP (
fun x c =>
match x,
c with
|
abs,
abs =>
abs
|
pres x,
pres c =>
match tag_of_val c with
|
None =>
err error_Ty
|
Some t =>
if tag_eqb k t
then pres x
else abs
end
|
err e, _ | _,
err e =>
err e
| _, _ =>
err error_Cl
end).
Lemma swhen_eq :
forall k c C x X,
swhen k (
cons x X) (
cons c C)
==
cons match x,
c with
|
abs,
abs =>
abs
|
pres x,
pres c =>
match tag_of_val c with
|
None =>
err error_Ty
|
Some t =>
if tag_eqb k t
then pres x
else abs
end
|
err e, _ | _,
err e =>
err e
| _, _ =>
err error_Cl
end (
swhen k X C).
Proof.
Lemma swhen_cons :
forall k xs cs,
is_cons (
swhen k xs cs) ->
is_cons xs /\
is_cons cs.
Proof.
Le cas du merge/case est plus délicat car il opère sur une liste
(nprod) de flots. On utilise pour ça nprod_Foldi, qui effectue
un fold_right sur la liste combinée des flots et des informations
de tag. (quel flot correspond à quel tag ?).
Definition is_tag (
i :
enumtag) (
x :
sampl B) :
sampl bool :=
match x with
|
pres v =>
or_default (
err error_Ty)
(
option_map (
fun j =>
pres (
tag_eqb i j)) (
tag_of_val v))
|
abs =>
abs
|
err e =>
err e
end.
Definition defcon (
c :
sampl B) :
sampl A :=
match c with
|
abs =>
abs
|
pres _ =>
err error_Ty
|
err e =>
err e
end.
Definition fmerge (
j :
enumtag) (
c :
sampl B) (
x a :
sampl A) :=
match is_tag j c,
a,
x with
|
abs,
abs,
abs =>
abs
|
pres true,
err error_Ty,
pres v =>
pres v
|
pres false,
a,
abs =>
a
| _,_,_ =>
err error_Cl
end.
Definition smerge (
l :
list enumtag) :
DS (
sampl B) -
C-> @
nprod (
DS (
sampl A)) (
length l) -
C->
DS (
sampl A).
eapply fcont_comp2.
apply nprod_Foldi.
2:
apply (
MAP defcon).
apply ford_fcont_shift;
intro j.
apply (
ZIP3 (
fmerge j)).
Defined.
Lemma smerge_eq :
forall l C np,
smerge l C np =
nprod_Foldi l (
fun j =>
ZIP3 (
fmerge j)
C) (
map defcon C)
np.
Proof.
trivial.
Qed.
Lemma smerge_is_cons :
forall l C np,
l <> [] ->
is_cons (
smerge l C np) ->
is_cons C /\
forall_nprod (@
is_cons _)
np.
Proof.
Lemma is_cons_smerge :
forall l cs xs,
is_cons cs ->
forall_nprod (@
is_cons _)
xs ->
is_cons (
smerge l cs xs).
Proof.
Lemma rem_smerge :
forall l C np,
rem (
smerge l C np)
==
smerge l (
rem C) (
lift (
REM _)
np).
Proof.
Lemma smerge_cons :
forall l c cs np,
forall (
Hc :
forall_nprod (@
is_cons _)
np),
smerge l (
cons c cs)
np
==
cons (
fold_right (
fun '(
j,
x) =>
fmerge j c x) (
defcon c)
(
combine l (
nprod_hds np Hc)))
(
smerge l cs (
lift (
REM _)
np)).
Proof.
intros.
apply first_rem_eq.
-
rewrite first_cons,
smerge_eq,
Foldi_fold_right.
generalize dependent np;
clear.
induction l;
intros.
+
simpl.
now rewrite first_map,
first_cons,
map_eq_cons,
map_bot.
+
simpl.
rewrite first_zip3,
first_cons, (
IHl _ (
forall_nprod_tl _ _
Hc)).
clear IHl.
destruct (@
is_cons_elim _ (
nprod_hd np))
as (
x &?&
Heq).
{
now apply forall_nprod_hd in Hc. }
remember (
projT1 _)
as y eqn:
Hy.
assert (
x =
y);
subst.
{
destruct (
uncons _)
as (?&?&
Hd);
simpl.
apply decomp_eqCon in Hd;
rewrite Hd in Heq.
now apply Con_eq_simpl in Heq. }
rewrite Heq,
first_cons,
zip3_cons,
zip3_bot1 at 1;
auto.
-
now rewrite rem_smerge, 2
rem_cons.
Qed.
Caractérisation de fmerge itéré sur la têtes des flots
Section fmerge_spec.
Lemma fmerge_abs :
forall (
l :
list (
enumtag *
sampl A))
c,
fold_right (
fun '(
j,
x) =>
fmerge j c x) (
defcon c)
l =
abs ->
c =
abs /\
Forall (
fun '(
j,
x) =>
x =
abs)
l.
Proof.
induction l as [|[]];
simpl;
intros c Hf.
{
destruct c;
simpl in Hf;
auto;
congruence. }
unfold fmerge at 1
in Hf.
destruct c as [|
k|];
simpl in Hf;
try congruence.
-
split;
auto.
destruct (
fold_right _ _ _)
eqn:
HH,
s;
try congruence.
apply IHl in HH as [];
auto.
-
unfold or_default,
option_map in Hf.
destruct (
tag_of_val _);
try congruence.
destruct (
tag_eqb _ _), (
fold_right _ _ _)
as [| |[]]
eqn:
HH,
s;
try congruence.
apply IHl in HH as [];
auto.
Qed.
Lemma fmerge_pres_abs :
forall (
l :
list (
enumtag *
sampl A))
i,
let c :=
pres i in
fold_right (
fun '(
j,
x) =>
fmerge j c x) (
defcon c)
l =
err error_Ty ->
Forall (
fun '(
j,
x) =>
x =
abs)
l.
Proof.
induction l as [|[]];
simpl;
intros i Hf;
auto.
unfold fmerge in Hf at 1.
destruct (
is_tag e _)
as [|[]|];
try congruence.
all:
destruct (
fold_right _ _ _)
as [| |[]]
eqn:
HH,
s;
try congruence.
all:
constructor;
eauto.
Qed.
Lemma fmerge_pres :
forall (
l :
list (
enumtag *
sampl A))
c v,
fold_right (
fun '(
j,
x) =>
fmerge j c x) (
defcon c)
l =
pres v ->
exists vc i,
c =
pres vc
/\
tag_of_val vc =
Some i
/\
Exists (
fun '(
j,
x) =>
j =
i /\
x =
pres v)
l
/\
Forall (
fun '(
j,
x) =>
j <>
i ->
x =
abs)
l.
Proof.
induction l as [|[
i s]];
simpl;
intros *
Hf.
{
destruct c;
simpl in Hf;
congruence. }
unfold fmerge at 1
in Hf.
destruct c as [|
k|];
simpl in Hf;
try congruence.
{
destruct (
fold_right _ _ _)
eqn:
HH,
s;
congruence. }
unfold or_default,
option_map in Hf.
destruct (
tag_of_val k)
as [
t|]
eqn:
Hk;
try congruence.
exists k,
t;
do 2
split;
auto.
destruct (
tag_eqb _ _)
eqn:
Ht.
-
apply tag_eqb_eq in Ht;
subst.
destruct (
fold_right _ _ _)
as [| |[]]
eqn:
HH,
s;
inversion Hf;
subst.
split;
constructor;
auto;
try congruence.
eapply fmerge_pres_abs,
Forall_impl in HH;
eauto.
intros [];
congruence.
-
destruct s;
try congruence.
apply IHl in Hf as (
vc &
k' &
Hk' &
Ht' &?&?).
inversion Hk';
subst.
rewrite Hk in *;
inversion Ht';
split;
auto.
Qed.
Lemma fmerge_abs_ok :
forall (
l :
list enumtag) (
ss :
list (
sampl A)),
let c :=
abs in
Forall (
eq abs)
ss ->
fold_right (
fun '(
j,
x) =>
fmerge j c x) (
defcon c) (
combine l ss) =
abs.
Proof.
induction l; intros * Heq; auto.
destruct ss; auto.
inversion_clear Heq; subst; simpl.
rewrite IHl; auto.
Qed.
Lemma fmerge_pres_ok :
forall (
l :
list enumtag) (
ss :
list (
sampl A))
vt i,
let c :=
pres vt in
tag_of_val vt =
Some i ->
NoDup l ->
Forall2 (
fun j x =>
match x with
|
pres _ =>
j =
i
|
abs =>
j <>
i
|
err _ =>
False
end)
l ss ->
In i l ->
exists v,
fold_right (
fun '(
j,
x) =>
fmerge j c x) (
defcon c) (
combine l ss) =
pres v.
Proof.
intros *
Hv Nd Hf.
enough ((
In i l ->
exists v,
fold_right (
fun '(
j,
x) =>
fmerge j c x)
(
defcon c) (
combine l ss) =
pres v)
/\ (~
In i l ->
fold_right (
fun '(
j,
x) =>
fmerge j c x)
(
defcon c) (
combine l ss) =
err error_Ty)); [
tauto|].
generalize dependent ss.
subst c;
simpl.
induction l;
simpl;
intros;
try tauto.
destruct ss as [|
s ss];
inversion_clear Hf.
inversion_clear Nd.
edestruct IHl as [
Hin Hnin];
eauto;
clear IHl.
simpl;
unfold fmerge at 1 3;
simpl.
unfold or_default,
option_map.
rewrite Hv.
split.
-
intros [|
Ini];
subst.
+
destruct s;
try tauto.
rewrite tag_eqb_refl.
setoid_rewrite Hnin;
eauto.
+
destruct s;
subst;
try tauto.
rewrite (
proj2 (
tag_eqb_neq a i));
eauto.
-
intro Nin.
rewrite (
proj2 (
tag_eqb_neq a i));
auto.
destruct s;
subst;
tauto.
Qed.
End fmerge_spec.
Global Opaque smerge.
Le scase ressemble au smerge mais vérifie que tous les flots sont
sur la même horloge que la condition cf. fcase.
On peut gérer le cas par défaut (lorsqu'une branche est volontairement
omise) en modifiant la valeur initiale de l'accumulateur du foldi :
sans branche par défaut, on initialise à abs/error_Ty comme dans smerge,
et sinon on part de la valeur par défaut, après l'avoir synchronisée
avec la condition cf. defcon2.
Definition fcase (
j :
enumtag) (
c :
sampl B) (
x a :
sampl A) :=
match is_tag j c,
a,
x with
|
abs,
abs,
abs =>
abs
| _,
abs, _ =>
err error_Cl
|
pres true,
err error_Ty,
pres v =>
pres v
|
pres true,
pres _,
pres v =>
pres v
|
pres false,
a,
pres _ =>
a
| _,_,_ =>
err error_Cl
end.
Definition scase (
l :
list enumtag) :
DS (
sampl B) -
C-> @
nprod (
DS (
sampl A)) (
length l) -
C->
DS (
sampl A).
eapply fcont_comp2.
apply nprod_Foldi.
2:
apply (
MAP defcon).
apply ford_fcont_shift;
intro j.
apply (
ZIP3 (
fcase j)).
Defined.
Lemma scase_eq :
forall l C np,
scase l C np =
nprod_Foldi l (
fun j =>
ZIP3 (
fcase j)
C) (
map defcon C)
np.
Proof.
trivial.
Qed.
Definition defcon2 (
c :
sampl B) (
v :
sampl A) :
sampl A :=
match c,
v with
|
abs,
abs =>
abs
|
pres _,
pres x =>
pres x
| _, _ =>
err error_Cl
end.
Definition scase_def_ (
l :
list enumtag) :
DS (
sampl B) -
C->
DS (
sampl A) -
C-> @
nprod (
DS (
sampl A)) (
length l) -
C->
DS (
sampl A).
apply curry.
eapply fcont_comp2.
eapply nprod_Foldi.
2:
apply (
uncurry (
ZIP defcon2)).
apply ford_fcont_shift;
intro j.
apply (
ZIP3 (
fcase j) @_
FST _ _).
Defined.
Lemma scase_def__eq :
forall l cs ds np,
scase_def_ l cs ds np =
nprod_Foldi l (
fun j =>
ZIP3 (
fcase j)
cs) (
ZIP defcon2 cs ds)
np.
Proof.
trivial.
Qed.
Definition scase_def (
l :
list enumtag) :
DS (
sampl B) -
C-> @
nprod (
DS (
sampl A)) (
S (
length l)) -
C->
DS (
sampl A).
apply curry.
refine ((
scase_def_ l @3_
FST _ _) _ _).
-
exact (
nprod_hd @_
SND _ _).
-
exact (
nprod_tl @_
SND _ _).
Defined.
Lemma scase_def_eq :
forall l cs ds np,
scase_def l cs (
nprod_cons ds np) =
scase_def_ l cs ds np.
Proof.
intros.
unfold scase_def.
autorewrite with localdb.
destruct l;
auto.
Qed.
Lemma scase_is_cons :
forall l C np,
l <> [] ->
is_cons (
scase l C np) ->
is_cons C /\
forall_nprod (@
is_cons _)
np.
Proof.
Lemma is_cons_scase :
forall l cs xs,
is_cons cs ->
forall_nprod (@
is_cons _)
xs ->
is_cons (
scase l cs xs).
Proof.
Lemma rem_scase :
forall l C np,
rem (
scase l C np)
==
scase l (
rem C) (
lift (
REM _)
np).
Proof.
Lemma scase_cons :
forall l c cs np,
forall (
Hc :
forall_nprod (@
is_cons _)
np),
scase l (
cons c cs)
np
==
cons (
fold_right (
fun '(
j,
x) =>
fcase j c x) (
defcon c)
(
combine l (
nprod_hds np Hc)))
(
scase l cs (
lift (
REM _)
np)).
Proof.
intros.
apply first_rem_eq.
-
rewrite first_cons,
scase_eq,
Foldi_fold_right.
generalize dependent np;
clear.
induction l;
intros.
+
simpl.
now rewrite first_map,
first_cons,
map_eq_cons,
map_bot.
+
simpl.
rewrite first_zip3,
first_cons, (
IHl _ (
forall_nprod_tl _ _
Hc)).
clear IHl.
destruct (@
is_cons_elim _ (
nprod_hd np))
as (
x &?&
Heq).
{
now apply forall_nprod_hd in Hc. }
remember (
projT1 _)
as y eqn:
Hy.
assert (
x =
y);
subst.
{
destruct (
uncons _)
as (?&?&
Hd);
simpl.
apply decomp_eqCon in Hd;
rewrite Hd in Heq.
now apply Con_eq_simpl in Heq. }
rewrite Heq,
first_cons,
zip3_cons,
zip3_bot1 at 1;
auto.
-
now rewrite rem_scase, 2
rem_cons.
Qed.
Lemma scase_def__is_cons :
forall l cs ds np,
l <> [] ->
is_cons (
scase_def_ l cs ds np) ->
is_cons cs /\
is_cons ds /\
forall_nprod (@
is_cons _)
np.
Proof.
Lemma scase_def_is_cons :
forall l cs dnp,
l <> [] ->
is_cons (
scase_def l cs dnp) ->
is_cons cs /\
forall_nprod (@
is_cons _)
dnp.
Proof.
Lemma is_cons_scase_def_ :
forall l cs ds xs,
is_cons cs ->
is_cons ds ->
forall_nprod (@
is_cons _)
xs ->
is_cons (
scase_def_ l cs ds xs).
Proof.
Lemma is_cons_scase_def :
forall l cs dxs,
is_cons cs ->
forall_nprod (@
is_cons _)
dxs ->
is_cons (
scase_def l cs dxs).
Proof.
Lemma rem_scase_def_ :
forall l cs ds np,
rem (
scase_def_ l cs ds np)
==
scase_def_ l (
rem cs) (
rem ds) (
lift (
REM _)
np).
Proof.
Lemma rem_scase_def :
forall l cs dnp,
rem (
scase_def l cs dnp)
==
scase_def l (
rem cs) (
lift (
REM _)
dnp).
Proof.
Lemma scase_def__cons :
forall l c cs d ds np,
forall (
Hc :
forall_nprod (@
is_cons _)
np),
scase_def_ l (
cons c cs) (
cons d ds)
np
==
cons (
fold_right (
fun '(
j,
x) =>
fcase j c x) (
defcon2 c d)
(
combine l (
nprod_hds np Hc)))
(
scase_def_ l cs ds (
lift (
REM _)
np)).
Proof.
intros.
apply first_rem_eq.
-
rewrite first_cons,
scase_def__eq,
Foldi_fold_right.
generalize dependent np;
clear.
induction l;
intros.
+
simpl.
now rewrite first_zip, 2
first_cons,
zip_cons,
zip_bot1.
+
simpl.
rewrite first_zip3,
first_cons, (
IHl _ (
forall_nprod_tl _ _
Hc)).
clear IHl.
destruct (@
is_cons_elim _ (
nprod_hd np))
as (
x &?&
Heq).
{
now apply forall_nprod_hd in Hc. }
remember (
projT1 _)
as y eqn:
Hy.
assert (
x =
y);
subst.
{
destruct (
uncons _)
as (?&?&
Hd);
simpl.
apply decomp_eqCon in Hd;
rewrite Hd in Heq.
now apply Con_eq_simpl in Heq. }
rewrite Heq,
first_cons,
zip3_cons,
zip3_bot1 at 1;
auto.
-
now rewrite rem_scase_def_, 3
rem_cons.
Qed.
Caractérisation de fcase itéré sur la têtes des flots
Section fcase_spec.
Lemma fcase_abs :
forall (
l :
list (
enumtag *
sampl A))
c a,
l <> [] ->
fold_right (
fun '(
j,
x) =>
fcase j c x)
a l =
abs ->
c =
abs /\
a =
abs /\
Forall (
fun '(
j,
x) =>
x =
abs)
l.
Proof.
Lemma fcase_pres_abs :
forall (
l :
list (
enumtag *
sampl A))
i,
let c :=
pres i in
fold_right (
fun '(
j,
x) =>
fcase j c x) (
defcon c)
l =
err error_Ty ->
Forall (
fun '(
j,
x) =>
is_tag j c =
pres false /\
exists v,
x =
pres v)
l.
Proof.
induction l as [|[]];
simpl;
intros i Hf;
auto.
unfold fcase in Hf at 1.
unfold is_tag,
or_default,
option_map in *.
cases_eqn HH;
subst.
take (
Some _ =
Some _)
and inv it.
take (
err _ =
err _)
and inv it.
constructor;
eauto.
eapply IHl,
Forall_impl in HH1;
eauto.
intros [];
cases;
congruence.
Qed.
Lemma fcase_pres :
forall (
l :
list (
enumtag *
sampl A))
c v,
fold_right (
fun '(
j,
x) =>
fcase j c x) (
defcon c)
l =
pres v ->
exists vc i,
c =
pres vc
/\
tag_of_val vc =
Some i
/\
List.Exists (
fun '(
j,
x) =>
j =
i /\
x =
pres v)
l
/\
List.Forall (
fun '(
j,
x) =>
exists v,
x =
pres v)
l.
Proof.
induction l as [|[
i s]];
simpl;
intros *
Hf.
{
destruct c;
simpl in Hf;
congruence. }
unfold fcase at 1
in Hf.
unfold is_tag,
or_default,
option_map in Hf.
cases_eqn HH;
subst.
all:
repeat take (
pres _ =
pres _)
and inv it.
all:
repeat take (
Some _ =
Some _)
and inv it.
all:
try take (
tag_eqb _ _ =
true)
and apply tag_eqb_eq in it;
subst.
-
eapply IHl in HH1 as (?&?&
Hinv &
Hv &?&?);
inv Hinv.
rewrite Hv in *;
take (
Some _ =
Some _)
and inv it.
do 2
esplit;
repeat split;
eauto.
-
apply fcase_pres_abs in HH1.
do 2
esplit;
repeat split;
eauto.
constructor;
eauto.
eapply Forall_impl;
eauto;
now intros [].
-
eapply IHl in HH1 as (?&?&
Hinv &?&?&?);
inv Hinv.
do 2
esplit;
repeat split;
eauto.
Qed.
Lemma fcase_pres2 :
forall (
l :
list (
enumtag *
sampl A))
c d v,
l <> [] ->
fold_right (
fun '(
j,
x) =>
fcase j c x) (
defcon2 c d)
l =
pres v ->
exists vc vd i,
c =
pres vc
/\
tag_of_val vc =
Some i
/\
d =
pres vd
/\
List.Forall (
fun '(
j,
x) =>
exists v,
x =
pres v)
l
/\
(
List.Exists (
fun '(
j,
x) =>
j =
i /\
x =
pres v)
l
\/
(
List.Forall (
fun '(
j,
x) =>
j <>
i)
l /\
vd =
v)).
Proof.
induction l as [|[
i s1][|[
j s2]]];
simpl;
intros *
Nnil Hf.
congruence.
-
clear IHl.
unfold fcase,
is_tag,
or_default,
option_map in Hf.
cases_eqn HH;
subst;
inv Hf;
simpl in *;
cases.
all:
repeat take (
Some _ =
Some _)
and inv it.
all:
repeat take (
pres _ =
pres _)
and inv it.
+
apply tag_eqb_eq in H0;
subst;
eauto 13.
+
apply tag_eqb_neq in H0;
subst;
eauto 13.
-
simpl in IHl.
unfold fcase at 1,
is_tag,
or_default,
option_map in Hf.
cases_eqn HH;
subst;
try congruence;
inv Hf.
all:
repeat take (
Some _ =
Some _)
and inv it.
+
apply tag_eqb_eq in H0;
subst.
eapply IHl in HH1 as (?&?&?&?&?&?&?&?);
subst;
try congruence;
eauto 13.
+
clear -
HH1;
exfalso.
unfold fcase at 1
in HH1.
cases_eqn HH;
subst;
inv HH1.
simpl in *;
cases;
clear HH.
all:
induction l;
simpl in *;
cases;
try congruence.
all:
unfold fcase at 1,
is_tag,
or_default,
option_map in HH2;
cases.
+
apply tag_eqb_neq in H0.
eapply IHl in HH1 as (?&?&?&?&?&?&?&
FE);
subst;
try congruence.
repeat take (
pres _ =
pres _)
and inv it.
destruct FE as [|[]];
subst;
eauto 12.
repeat esplit;
eauto;
right;
split;
auto.
constructor;
congruence.
Qed.
Lemma fcase_pres_ok :
forall (
l :
list enumtag) (
ss :
list (
sampl A))
vt i,
tag_of_val vt =
Some i ->
Forall (
fun x =>
match x with
|
pres _ =>
True
| _ =>
False
end)
ss ->
length l =
length ss ->
In i l ->
exists v,
fold_right (
fun '(
j,
x) =>
fcase j (
pres vt)
x) (
err error_Ty) (
combine l ss) =
pres v.
Proof.
Lemma fcase_def_pres_ok :
forall (
l :
list enumtag) (
ss :
list (
sampl A))
vt vd i,
tag_of_val vt =
Some i ->
Forall (
fun x =>
match x with
|
pres _ =>
True
| _ =>
False
end)
ss ->
exists v,
fold_right (
fun '(
j,
x) =>
fcase j (
pres vt)
x) (
pres vd) (
combine l ss) =
pres v.
Proof.
induction l;
simpl;
intros *
Ht Hf;
eauto.
destruct ss as [|[]
ss];
inv Hf;
try tauto;
simpl;
eauto.
unfold fcase at 1;
simpl.
rewrite Ht;
simpl.
edestruct IHl as (?& ->);
cases;
eauto.
Qed.
Lemma fcase_abs_ok :
forall (
l :
list enumtag) (
ss :
list (
sampl A)),
Forall (
eq abs)
ss ->
fold_right (
fun '(
j,
x) =>
fcase j abs x)
abs (
combine l ss) =
abs.
Proof.
induction l; intros * Heq; auto.
destruct ss; auto.
inversion_clear Heq; subst; simpl.
rewrite IHl; auto.
Qed.
End fcase_spec.
Global Opaque scase.
In this section we use the same function to denote the merge and
case operators. Notably, we do not try to detect all errors (wrong clocks,
error in sub-expressions, etc.).
It gives a nice definition with functional environments but is is very
unlikely to work well in proofs of SDtoRel.
question légitime : pourquoi on ne ferait pas comme ça ?
c'est pénible pour les raisonnements plus tard (pas d'inversion possible)
mais c'est plus simple à exprimer ici, et le résultat final devrait être
le même : si bien cadencé, alors on a la sémantique relationnelle.
Le fait que sbinop/swhen produise des erreurs parce qu'il n'y a pas le
choix justifie-t-il la production d'erreurs dans le merge/case ?
-> "pour faire pareil" n'est sans doute pas un bon argument
End When_Case.
End SStream_functions.
Section Sreset.
Context {
I A :
Type}.
Definition SI :=
fun _ :
I =>
sampl A.
Definition sresetf_aux :
((
DS_prod SI -
C->
DS_prod SI) -
C->
DS bool -
C->
DS_prod SI -
C->
DS_prod SI -
C->
DS_prod SI) -
C->
(
DS_prod SI -
C->
DS_prod SI) -
C->
DS bool -
C->
DS_prod SI -
C->
DS_prod SI -
C->
DS_prod SI.
do 4
apply curry.
match goal with
| |- _ (_ (
Dprod ?
pl ?
pr) _) =>
pose (
reset :=
FST _ _ @_ (
FST _ _ @_ (
FST _ _ @_ (
FST pl pr))));
pose (
f :=
SND _ _ @_ (
FST _ _ @_ (
FST _ _ @_ (
FST pl pr))));
pose (
R :=
SND _ _ @_ (
FST _ _ @_ (
FST pl pr)));
pose (
X :=
SND _ _ @_ (
FST pl pr));
pose (
Y :=
SND pl pr);
idtac
end.
apply Dprodi_DISTR;
intro x.
refine ((
DSCASE bool _ @2_ _)
R).
apply ford_fcont_shift;
intro r.
refine (
curry (_ @_
FST _ _)).
destruct r eqn:?.
exact (
PROJ _
x @_ ((
AP _ _ @5_
reset)
f
(
CONS false @_ (
REM _ @_
R))
X ((
AP _ _ @2_
f)
X))).
exact ((
APP _ @2_
PROJ _
x @_
Y)
(
PROJ _
x @_
((
AP _ _ @5_
reset)
f (
REM _ @_
R) (
REM_env @_
X) (
REM_env @_
Y)))).
Defined.
Lemma sresetf_aux_eq :
forall F f r R X Y,
sresetf_aux F f (
cons r R)
X Y ==
if r
then F f (
cons false R)
X (
f X)
else APP_env Y (
F f R (
REM_env X) (
REM_env Y)).
Proof.
Lemma is_cons_sresetf_aux :
forall F f R X Y x,
is_cons (
sresetf_aux F f R X Y x) ->
is_cons R.
Proof.
Definition sreset_aux :
(
DS_prod SI -
C->
DS_prod SI) -
C->
DS bool -
C->
DS_prod SI -
C->
DS_prod SI -
C->
DS_prod SI :=
FIXP _
sresetf_aux.
Lemma sreset_aux_eq :
forall f r R X Y,
sreset_aux f (
cons r R)
X Y ==
if r
then sreset_aux f (
cons false R)
X (
f X)
else APP_env Y (
sreset_aux f R (
REM_env X) (
REM_env Y)).
Proof.
Lemma sreset_aux_bot :
forall f X Y,
sreset_aux f 0
X Y == 0.
Proof.
Lemma is_cons_sreset_aux :
forall f R X Y x,
is_cons (
sreset_aux f R X Y x) ->
is_cons R.
Proof.
Lemma take_sreset_aux_false :
forall n f R (
X Y :
DS_prod SI),
take n R ==
take n (
DS_const false) ->
take_env n (
sreset_aux f R X Y) ==
take_env n Y.
Proof.
Definition sreset :
(
DS_prod SI -
C->
DS_prod SI) -
C->
DS bool -
C->
DS_prod SI -
C->
DS_prod SI.
apply curry,
curry.
match goal with
| |- _ (_ (
Dprod ?
pl ?
pr) _) =>
pose (
f :=
FST _ _ @_ (
FST pl pr));
pose (
R :=
SND _ _ @_ (
FST pl pr));
pose (
X :=
SND pl pr);
idtac
end.
exact ((
sreset_aux @4_
f)
R X ((
AP _ _ @2_
f)
X)).
Defined.
Lemma sreset_eq :
forall f R X,
sreset f R X ==
sreset_aux f R X (
f X).
Proof.
intros.
unfold sreset.
now autorewrite with localdb.
Qed.
End Sreset.
Global Opaque sresetf_aux sreset.