From Coq Require Import List.
Import List.ListNotations.
Open Scope list_scope.
From Coq Require Import Permutation.
From Coq Require Import Decidable.
From Coq Require Import Omega.
From Coq Require Import Setoid Morphisms.
From compcert Require Import common.Errors.
From Velus Require Import Common Clocks.
From Velus Require Import Operators Environment.
From Velus Require Import AcyGraph.
From Velus Require Import Lustre.LSyntax Lustre.LClocking Lustre.LCausality.
From Velus Require Import Lustre.Normalization.Fresh Lustre.Normalization.Normalization.
Conservation of causality through normalization
Module Type NCAUSALITY
(
Import Ids :
IDS)
(
Op :
OPERATORS)
(
OpAux :
OPERATORS_AUX Op)
(
Import Syn :
LSYNTAX Ids Op)
(
Import Cau :
LCAUSALITY Ids Op Syn)
(
Import Clo :
LCLOCKING Ids Op Syn)
(
Import Norm :
NORMALIZATION Ids Op OpAux Syn Cau).
Import Fresh Tactics.
Some auxiliary stuff
Fact in_vars_defined_concat :
forall x eqs eqs',
In eqs eqs' ->
In x (
vars_defined eqs) ->
In x (
vars_defined (
concat eqs')).
Proof.
Fact vars_defined_combine :
forall xs es,
length xs =
length es ->
vars_defined (
combine xs es) =
concat xs.
Proof.
If an expression is wc with regards to an environment, all it's
left-free vars appear in the environment
Fact wc_exp_Is_free_left :
forall G env e x k,
wc_exp G env e ->
Is_free_left x k e ->
InMembers x env.
Proof.
Local Hint Resolve In_InMembers.
Local Ltac solve_forall_exists H1 H2 H3 :=
try eapply Is_free_left_list_Exists in H3;
try destruct H3 as (?&
H3);
eapply Forall_Forall in H1; [|
eapply H2];
eapply Forall_Exists in H1; [|
eapply H3];
eapply Exists_exists in H1 as (?&?&(?&?)&?);
eauto.
induction e using exp_ind2;
intros *
Hwc Hfree;
inv Hwc;
inv Hfree;
eauto.
-
destruct H1;
eauto.
-
solve_forall_exists H H4 H3.
-
destruct H3 as [
Hex|
Hex].
solve_forall_exists H H4 Hex.
solve_forall_exists H0 H5 Hex.
-
destruct H2 as [[?
Hex]|
Hex];
subst;
eauto.
solve_forall_exists H H4 Hex.
-
destruct H3 as [[?
Hex]|[
Hex|
Hex]];
subst;
eauto.
solve_forall_exists H H5 Hex.
solve_forall_exists H0 H6 Hex.
-
destruct H3 as [[?
Hex]|[
Hex|
Hex]];
eauto.
solve_forall_exists H H6 Hex.
solve_forall_exists H0 H7 Hex.
-
solve_forall_exists H0 H5 H10.
-
destruct H13 as [
Hex|
Hex];
eauto.
solve_forall_exists H0 H5 Hex.
Qed.
Causality of the second phase of normalization
Recover info about the init equations in the state
Definition st_inits (
st :
fresh_st (
Op.type *
clock *
bool)) :=
idck (
idty (
filter (
fun '(
_, (
ty,
_,
b)) =>
b && (
ty ==
b Op.bool_type)) (
st_anns st))).
Fact st_follows_inits_incl :
forall st st',
st_follows st st' ->
incl (
st_inits st) (
st_inits st').
Proof.
Fact st_inits_find_Some :
forall st x (
ck :
nclock)
p,
find (
fun '(
_, (
ty,
ck',
isinit)) =>
isinit && (
ck' ==
b fst ck) && (
ty ==
b Op.bool_type)) (
st_anns st) =
Some (
x,
p) ->
In (
x, (
fst ck)) (
st_inits st).
Proof.
Fact st_inits_find_None :
forall st (
ck :
nclock),
find (
fun '(
_, (
ty,
ck',
isinit)) =>
isinit && (
ck' ==
b fst ck) && (
ty ==
b Op.bool_type)) (
st_anns st) =
None ->
~
In (
fst ck) (
map snd (
st_inits st)).
Proof.
intros *
Hfind.
intro contra.
unfold st_inits in contra.
repeat simpl_In.
apply filter_In in H0 as [
Hin Heq].
eapply find_none in Hfind;
eauto.
simpl in *.
apply Bool.andb_true_iff in Heq as [
Hb Hty];
subst;
simpl in Hfind.
rewrite Hty,
equiv_decb_refl in Hfind;
simpl in Hfind.
congruence.
Qed.
Fact fresh_ident_false_st_inits :
forall pref (
st st' :
fresh_st (
Op.type *
clock *
bool))
a id,
fresh_ident pref (
a,
false)
st = (
id,
st') ->
st_inits st' =
st_inits st.
Proof.
intros *
Hfresh.
unfold st_inits.
destruct a as [
ty ck].
apply fresh_ident_anns in Hfresh.
rewrite Hfresh.
simpl;
auto.
Qed.
Fact fresh_ident_true_st_inits :
forall pref st st'
ck id,
fresh_ident pref ((
Op.bool_type,
ck),
true)
st = (
id,
st') ->
st_inits st' = (
id,
ck)::
st_inits st.
Proof.
Fact init_var_for_clock_In_st_inits :
forall ck x eqs'
st st',
init_var_for_clock ck st = (
x,
eqs',
st') ->
In (
x,
ck) (
st_inits st').
Proof.
Hint Constructors Is_free_in_clock.
Fact add_whens_Is_free_left :
forall ck ty c,
forall x,
Is_free_left x 0 (
add_whens (
Econst c)
ty ck) ->
Is_free_in_clock x ck.
Proof.
induction ck;
intros *
Hfree;
inv Hfree;
simpl in *.
destruct H1 as [[
_ ?]|?];
subst;
auto.
-
inv H;
eauto.
rewrite add_whens_numstreams in H3;
auto.
inv H3.
Qed.
Definition st_clocks (
st :
fresh_st (
Op.type *
clock *
bool)) :=
idck (
idty (
st_anns st)).
Fact st_clocks_st_ids :
forall st,
map fst (
st_clocks st) =
st_ids st.
Proof.
Fact st_inits_incl_st_clocks :
forall st,
incl (
st_inits st) (
st_clocks st).
Proof.
Corollary st_inits_incl_st_ids :
forall st,
incl (
map fst (
st_inits st)) (
st_ids st).
Proof.
A variable is used to calculate a clock, either directly or indirectly
Definition used_in_clock {
a v} (
g:
AcyGraph v a)
x ck :=
Is_free_in_clock x ck \/ (
exists x',
is_trans_arc g x x' /\
Is_free_in_clock x'
ck).
Lemma used_in_clock_trans :
forall {
v a} (
g :
AcyGraph v a)
x y ck,
is_trans_arc g x y ->
used_in_clock g y ck ->
used_in_clock g x ck.
Proof.
intros * Ha [?|(?&?&?)].
- right. exists y; auto.
- right. exists x0; split; auto.
etransitivity; eauto.
Qed.
Lemma used_in_clock_add_arc' :
forall {
v a} (
g :
AcyGraph v a)
x'
y' (
g' :
AcyGraph v (
add_arc x'
y'
a))
x ck,
used_in_clock g x ck ->
used_in_clock g'
x ck.
Proof.
intros * [?|(?&?&?)].
-
left;
auto.
-
right.
exists x0.
split;
auto.
apply add_arc_spec2;
auto.
Qed.
Local Ltac destruct_conj_disj :=
match goal with
|
H :
_ /\
_ |-
_ =>
destruct H
|
H :
_ \/
_ |-
_ =>
destruct H
end;
subst.
Lemma used_in_clock_add_arc :
forall {
v a} (
g :
AcyGraph v a)
x'
y' (
g' :
AcyGraph v (
add_arc x'
y'
a))
x y ck,
y <>
y' ->
(
forall x,
is_trans_arc g x y ->
used_in_clock g x ck) ->
is_trans_arc g'
x y ->
used_in_clock g'
x ck.
Proof.
intros *
Hneq Hack Ha.
apply add_arc_spec2 in Ha.
repeat destruct_conj_disj.
-
apply Hack in H.
eapply used_in_clock_add_arc';
eauto.
-
congruence.
-
apply Hack in H0.
eapply used_in_clock_add_arc'
in H0;
eauto.
eapply used_in_clock_trans;
eauto.
apply add_arc_spec2;
auto.
-
congruence.
-
eapply Hack in H0.
eapply used_in_clock_add_arc'
in H0;
eauto.
eapply used_in_clock_trans;
eauto.
unfold is_arc.
apply add_arc_spec2;
auto 8.
Qed.
Lemma used_in_clock_add_after :
forall {
v a} (
g :
AcyGraph v a)
preds x' (
g' :
AcyGraph v (
add_after preds x'
a))
x ck,
used_in_clock g x ck ->
used_in_clock g'
x ck.
Proof.
intros * [?|(?&?&?)].
-
left;
auto.
-
right.
exists x0.
split;
auto.
apply add_after_spec2;
auto.
Qed.
Lemma used_in_clock_add_between' :
forall {
v a} (
g :
AcyGraph v a)
preds x'
y' (
g' :
AcyGraph v (
add_between preds x'
y'
a))
x ck,
~
PS.In y'
preds ->
~
PS.Exists (
fun p =>
has_trans_arc a y'
p)
preds ->
used_in_clock g x ck ->
used_in_clock g'
x ck.
Proof.
intros *
Hnin1 Hnin2 [?|(?&?&?)].
-
left;
auto.
-
right.
exists x0.
split;
auto.
eapply add_between_spec2;
eauto.
Qed.
Lemma used_in_clock_add_between :
forall {
v a} (
g :
AcyGraph v a)
preds x'
y' (
g' :
AcyGraph (
PS.add x'
v) (
add_between preds x'
y'
a))
x y ck,
~
PS.In y'
preds ->
~
PS.Exists (
fun p =>
has_trans_arc a y'
p)
preds ->
y <>
y' ->
y <>
x' ->
~
PS.In x'
v ->
(
forall x,
is_trans_arc g x y ->
used_in_clock g x ck) ->
is_trans_arc g'
x y ->
used_in_clock g'
x ck.
Proof.
Causality invariant
We add an invariant to our causality hypothesis:
Variables marked as init variables only depend on the variables of their clocks
This is necessary so that we can add arcs using them later on
Definition causal_inv vars eqs (
st :
fresh_st (
Op.type *
clock *
bool)) :=
NoDupMembers vars /\
st_valid_after st norm2 (
PSP.of_list (
map fst vars)) /\
exists v a (
g :
AcyGraph v a),
graph_of_eqs (
vars ++
st_clocks st)
eqs g /\
Forall (
fun '(
y,
ck) =>
forall x,
is_trans_arc g x y ->
used_in_clock g x ck) (
st_inits st).
Instance causal_inv_Proper:
Proper (@
Permutation (
ident *
clock) ==> @
Permutation equation ==> @
eq (
fresh_st (
Op.type *
clock *
bool)) ==> @
Basics.impl)
causal_inv.
Proof.
intros ? ?
Hp1 ? ?
Hp2 ?
st Heq (
Hnd&
Hvalid&
v&
a&
g&?&?);
subst.
repeat split.
-
rewrite <-
Hp1.
assumption.
-
rewrite <-
ps_from_list_ps_of_list in *.
rewrite <-
Hp1.
assumption.
-
exists v.
exists a.
exists g.
split;
auto.
rewrite <-
Hp1, <-
Hp2.
assumption.
Qed.
Fact graph_of_eqs_ck_causal_inv :
forall {
v a}
vars eqs (
g :
AcyGraph v a),
NoDupMembers vars ->
~
PS.In norm2 norm1_prefs ->
Forall (
AtomOrGensym norm1_prefs) (
map fst vars) ->
graph_of_eqs vars eqs g ->
causal_inv vars eqs init_st.
Proof.
Fact vars_defined_In :
forall x xs es eqs,
In (
xs,
es)
eqs ->
In x xs ->
In x (
vars_defined eqs).
Proof.
Fact causal_inv_add_init :
forall vars eqs x ck e st st',
causal_inv vars eqs st ->
wc_clock (
vars++
st_clocks st)
ck ->
(
forall x,
Is_free_left x 0
e ->
Is_free_in_clock x ck) ->
~
In ck (
map snd (
st_inits st)) ->
fresh_ident norm2 (
Op.bool_type,
ck,
true)
st = (
x,
st') ->
causal_inv vars (([
x], [
e])::
eqs)
st'.
Proof.
intros * (
Hnd&
Hvalid&
v&
a&
g&(
Hv&
Ha)&
Hinits)
Hwc Hfree Hnin Hfresh.
repeat constructor;
auto.
eapply fresh_ident_st_valid in Hfresh;
eauto.
assert (~
PS.In x v)
as Hnv.
{
intro contra.
rewrite Hv in contra.
eapply Facts.fresh_ident_nIn''
in Hfresh;
eauto.
rewrite ps_of_list_In,
map_app,
st_clocks_st_ids in contra;
auto. }
assert (
AcyGraph (
PS.add x v) (
add_after (
collect_free_clock ck)
x a))
as g'.
{
apply add_after_AcyGraph';
auto.
+
intro contra.
rewrite collect_free_clock_spec in contra.
eapply wc_clock_is_free_in,
fst_InMembers in Hwc;
eauto.
eapply Facts.fresh_ident_nIn''
in Hfresh;
eauto.
rewrite map_app,
st_clocks_st_ids in Hwc;
auto.
+
intros ?
Hin.
rewrite collect_free_clock_spec in Hin.
eapply wc_clock_is_free_in,
fst_InMembers in Hwc;
eauto.
rewrite Hv,
ps_of_list_In;
auto.
}
eexists.
eexists.
exists g'.
split; [
split|].
-
unfold vertices;
simpl.
rewrite Hv.
repeat rewrite <-
ps_from_list_ps_of_list.
rewrite add_ps_from_list_cons,
map_app,
map_app,
Permutation_middle.
apply fresh_ident_anns in Hfresh.
unfold st_clocks.
rewrite Hfresh.
reflexivity.
-
intros *
Hdep.
unfold is_arc.
rewrite add_after_spec.
destruct Hdep as [
Hdep|
Hdep];
eauto.
+
inversion_clear Hdep as [??
Hk|??
Hex]. 2:(
left;
eapply Ha;
left;
eauto).
destruct Hk as (?&
Hnth&
Hfree');
simpl in *.
rewrite nth_error_length_nth in Hnth.
specialize (
Hnth xH)
as (
Hl&
Hnth).
rewrite Nat.lt_1_r in Hl;
subst.
inv Hfree'; [|
inv H3].
right;
split;
auto.
rewrite collect_free_clock_spec.
auto.
+
destruct Hdep as (?&
Hin&
Hfree').
unfold st_clocks in Hin.
erewrite fresh_ident_anns in Hin;
eauto;
simpl in *.
rewrite <-
Permutation_middle in Hin.
inv Hin. 2:(
left;
apply Ha;
right;
eauto).
inv H.
right;
split;
auto.
rewrite collect_free_clock_spec.
auto.
-
erewrite fresh_ident_true_st_inits;
eauto.
constructor;
auto.
+
intros y Ha'.
eapply add_after_has_trans_arc3 in Ha'
as [
Hin|(?&
Hin&
Ha')];
eauto; [
left|
right].
1,2:
rewrite collect_free_clock_spec in Hin;
auto.
eexists;
split;
eauto.
apply add_after_spec2;
auto.
+
eapply Forall_impl_In; [|
eauto].
intros (?&?)
Hin Ha' ?
Ha''.
apply add_after_spec2 in Ha''
as [?|[(
_&?)|[(
_&
Ha'')|[(
_&?)|(
_&
Ha'')]]]];
subst.
2-5:
exfalso.
3,5:
eapply is_trans_arc_is_vertex with (
g0:=
g)
in Ha''
as (?&?);
eauto.
2,3:(
eapply Facts.fresh_ident_nIn;
eauto;
apply st_inits_incl_st_ids;
eapply in_map with (
f:=
fst)
in Hin;
eauto).
eapply Ha'
in H as [?|(?&?&?)]; [
left|
right];
auto.
eexists;
split;
eauto.
unfold is_arc.
apply add_after_spec2;
auto.
Qed.
Fact init_var_for_clock_causal_inv :
forall vars eqs ck x eqs'
st st',
wc_clock vars ck ->
causal_inv vars eqs st ->
init_var_for_clock ck st = (
x,
eqs',
st') ->
causal_inv vars (
eqs++
eqs')
st'.
Proof.
Lemma causal_inv_replace_eq :
forall vars st x xinit ck e e'
eqs,
In (
x,
ck) (
vars ++
st_clocks st) ->
~
InMembers x (
st_inits st) ->
In (
xinit,
ck) (
st_inits st) ->
numstreams e = 1 ->
causal_inv vars (([
x], [
e]) ::
eqs)
st ->
(
forall y,
Is_free_left y 0
e' -> (
Is_free_left y 0
e \/
y =
xinit)) ->
causal_inv vars (([
x], [
e']) ::
eqs)
st.
Proof.
Fact depends_on_vars_defined :
forall eqs x y,
depends_on eqs x y ->
In x (
vars_defined eqs).
Proof.
Lemma causal_inv_insert_eq :
forall G vars st st'
x x'
ty ck e e1 e2 eqs,
wl_exp G e2 ->
In (
x,
ck)
vars ->
~
InMembers x (
st_inits st) ->
numstreams e = 1 ->
fresh_ident norm2 (
ty,
ck,
false)
st = (
x',
st') ->
causal_inv vars (([
x], [
e]) ::
eqs)
st ->
(
forall y,
Is_free_left y 0
e1 -> (
y =
x' \/
Is_free_left y 0
e)) ->
(
forall y,
Is_free_left y 0
e2 ->
Is_free_left y 0
e) ->
causal_inv vars (([
x], [
e1]) :: ([
x'], [
e2]) ::
eqs)
st'.
Proof.
intros *
Hwl Hck Hnck Hnum Hfresh (?&?&
v&
a&
g&(
Hv&
Ha)&
Hinits)
Hf1 Hf2.
repeat split;
eauto.
assert (
forall y,
Is_free_left y 0
e2 \/
Is_free_in_clock y ck ->
is_arc g y x)
as Hax.
{
intros y [
Hfree|
Hfree].
-
eapply Hf2 in Hfree.
apply Ha.
left.
left.
exists 0.
repeat split;
auto.
left;
auto.
rewrite Hnum;
auto.
-
apply Ha.
right.
exists ck;
split;
auto.
apply in_or_app;
auto.
}
remember (
PS.union (
nth 0 (
collect_free_left e2)
PS.empty) (
collect_free_clock ck))
as preds.
assert (
AcyGraph (
PS.add x'
v) (
add_between preds x'
x a))
as g'.
{
eapply add_between_AcyGraph with (
g0:=
g);
subst;
eauto.
-
intros ?
Hin.
erewrite PS.union_spec,
collect_free_left_spec,
collect_free_clock_spec in Hin;
eauto.
apply Hax,
is_arc_is_vertex in Hin as (?&?);
auto.
-
unfold is_vertex.
rewrite Hv.
rewrite ps_of_list_In,
map_app.
apply in_or_app;
left.
rewrite in_map_iff.
exists (
x,
ck);
auto.
-
intros ?
Hin.
erewrite PS.union_spec,
collect_free_left_spec,
collect_free_clock_spec in Hin;
eauto.
-
intro contra.
apply Hv,
ps_of_list_In in contra.
eapply Facts.fresh_ident_nIn''
in Hfresh;
eauto.
apply Hfresh.
rewrite <-
st_clocks_st_ids, <-
map_app;
auto.
}
assert (~
PS.In x preds)
as Hnin1.
{
intro contra;
subst.
erewrite PS.union_spec,
collect_free_left_spec,
collect_free_clock_spec in contra;
eauto.
eapply Hax,
has_arc_irrefl in contra;
eauto.
}
assert (~
PS.Exists (
fun p :
PS.elt =>
has_trans_arc a x p)
preds)
as Hnin2.
{
intros (?&
Hin&
Ha'');
subst.
erewrite PS.union_spec,
collect_free_left_spec,
collect_free_clock_spec in Hin;
eauto.
eapply Hax in Hin.
eapply is_trans_arc_Asymmetric with (
g0:=
g)
in Ha'';
eauto.
eapply Ha''.
left;
eauto.
}
assert (~
PS.Exists (
fun p :
PS.elt =>
has_arc a x p)
preds)
as Hnin3.
{
intros (
x0&
Hin&
Ha'');
subst.
eapply Hnin2.
exists x0.
split;
auto.
}
eexists.
eexists.
exists g'.
split; [
split|];
auto.
-
unfold vertices;
simpl.
rewrite Hv.
repeat rewrite <-
ps_from_list_ps_of_list.
rewrite add_ps_from_list_cons,
map_app,
map_app,
Permutation_middle.
apply fresh_ident_anns in Hfresh.
unfold st_clocks.
rewrite Hfresh.
reflexivity.
-
intros *
Hdep.
unfold is_arc.
rewrite add_between_spec;
eauto.
destruct Hdep as [
Hdep|
Hdep]; [
inv Hdep;[|
inv H2]|].
+
destruct H2 as (?&
Hnth&?);
simpl in *.
rewrite nth_error_length_nth in Hnth.
specialize (
Hnth xH)
as (
Hlen&
Hnth).
apply Nat.lt_1_r in Hlen;
subst.
inv H1; [|
inv H6].
apply Hf1 in H6 as [?|?];
subst;
auto 10.
left.
apply Ha.
left.
left.
exists 0.
repeat split;
auto.
left;
auto.
rewrite Hnum;
auto.
+
destruct H3 as (?&
Hnth&?);
simpl in *.
rewrite nth_error_length_nth in Hnth.
specialize (
Hnth xH)
as (
Hlen&
Hnth).
apply Nat.lt_1_r in Hlen;
subst.
inv H1; [|
inv H6].
right;
left.
split;
auto.
rewrite PS.union_spec,
collect_free_left_spec;
eauto.
+
left.
apply Ha.
left.
right;
auto.
+
destruct Hdep as (
ck'&
Hin&
Hfree).
unfold st_clocks in Hin.
erewrite fresh_ident_anns in Hin;
eauto;
simpl in Hin.
rewrite <-
Permutation_middle in Hin.
inv Hin.
2:(
left;
apply Ha;
right;
eauto).
inv H1.
right.
left.
split;
auto.
rewrite PS.union_spec,
collect_free_clock_spec;
auto.
-
erewrite fresh_ident_false_st_inits;
eauto.
eapply Forall_impl_In; [|
eauto].
intros (?&?)
Hin Ha' ?
Ha''.
eapply used_in_clock_add_between;
eauto.
1-3:
intro contra;
subst.
+
eapply Hnck,
In_InMembers;
eauto.
+
eapply Facts.fresh_ident_nIn in Hfresh;
eauto.
apply Hfresh,
st_inits_incl_st_ids.
rewrite in_map_iff.
exists (
x',
c);
auto.
+
unfold is_vertex in contra.
rewrite Hv in contra.
eapply Facts.fresh_ident_nIn''
in Hfresh;
eauto.
rewrite ps_of_list_In,
map_app,
st_clocks_st_ids in contra;
auto.
Qed.
Lemma causal_inv_insert_eq_with_xinit :
forall G vars st st'
x x'
xinit ty ck e e1 e2 eqs,
wl_exp G e2 ->
In (
x,
ck)
vars ->
~
InMembers x (
st_inits st) ->
In (
xinit,
ck) (
st_inits st) ->
numstreams e = 1 ->
fresh_ident norm2 (
ty,
ck,
false)
st = (
x',
st') ->
causal_inv vars (([
x], [
e]) ::
eqs)
st ->
(
forall y,
Is_free_left y 0
e1 -> (
y =
x' \/
Is_free_left y 0
e \/
y =
xinit)) ->
(
forall y,
Is_free_left y 0
e2 ->
Is_free_in_clock y ck) ->
causal_inv vars (([
x], [
e1]) :: ([
x'], [
e2]) ::
eqs)
st'.
Proof.
intros *
Hwl Hck Hnck Hinit Hnum Hfresh (?&?&
v&
a&
g&(
Hv&
Ha)&
Hinits)
Hf1 Hf2.
repeat split;
eauto.
assert (
forall y,
Is_free_left y 0
e2 \/
Is_free_in_clock y ck ->
is_arc g y x)
as Hax.
{
intros y [
Hfree|
Hfree]; [
apply Hf2 in Hfree|].
1,2:
apply Ha;
right;
exists ck;
split; [
apply in_or_app|];
auto.
}
remember (
PS.union (
nth 0 (
collect_free_left e2)
PS.empty) (
collect_free_clock ck))
as preds.
assert (
AcyGraph (
PS.add x'
v) (
add_between preds x'
x a))
as g'.
{
eapply add_between_AcyGraph with (
g0:=
g);
subst;
eauto.
-
intros ?
Hin.
erewrite PS.union_spec,
collect_free_left_spec,
collect_free_clock_spec in Hin;
eauto.
apply Hax,
is_arc_is_vertex in Hin as (?&?);
auto.
-
unfold is_vertex.
rewrite Hv.
rewrite ps_of_list_In,
map_app.
apply in_or_app;
left.
rewrite in_map_iff.
exists (
x,
ck);
auto.
-
intros ?
Hin.
erewrite PS.union_spec,
collect_free_left_spec,
collect_free_clock_spec in Hin;
eauto.
-
intro contra.
apply Hv,
ps_of_list_In in contra.
eapply Facts.fresh_ident_nIn''
in Hfresh;
eauto.
apply Hfresh.
rewrite <-
st_clocks_st_ids, <-
map_app;
auto.
}
assert (~
PS.In x preds)
as Hnin1.
{
intro contra;
subst.
erewrite PS.union_spec,
collect_free_left_spec,
collect_free_clock_spec in contra;
eauto.
eapply Hax,
has_arc_irrefl in contra;
eauto.
}
assert (~
PS.Exists (
fun p :
PS.elt =>
has_trans_arc a x p)
preds)
as Hnin2.
{
intros (?&
Hin&
Ha'');
subst.
erewrite PS.union_spec,
collect_free_left_spec,
collect_free_clock_spec in Hin;
eauto.
eapply Hax in Hin.
eapply is_trans_arc_Asymmetric with (
g0:=
g)
in Ha'';
eauto.
eapply Ha''.
left;
eauto.
}
assert (~
PS.Exists (
fun p :
PS.elt =>
has_arc a x p)
preds)
as Hnin3.
{
intros (
x0&
Hin&
Ha'');
subst.
eapply Hnin2.
exists x0.
split;
auto.
}
assert (
AcyGraph (
PS.add x'
v) (
add_arc xinit x (
add_between preds x'
x a)))
as g''.
{
eapply AGadda;
eauto.
-
intro contra;
subst.
eapply Hnck,
In_InMembers;
eauto.
-
apply PSF.add_2.
rewrite Hv,
ps_of_list_In,
in_map_iff.
exists (
xinit,
ck);
split;
auto.
apply in_app_iff;
right.
apply st_inits_incl_st_clocks;
auto.
-
apply PSF.add_2.
rewrite Hv,
ps_of_list_In,
in_map_iff.
exists (
x,
ck);
split; [|
apply in_or_app];
auto.
-
intro contra.
assert (
has_trans_arc a x xinit)
as contra'.
{
rewrite add_between_spec2 in contra;
eauto.
repeat destruct_conj_disj;
auto.
1-8:
exfalso;
auto.
1,2:
apply In_InMembers in Hinit;
auto.
}
clear contra.
eapply Forall_forall in Hinits;
eauto.
eapply Hinits in contra'
as [?|(?&?&?)].
+
eapply has_arc_irrefl;
eauto.
eapply add_between_spec;
eauto.
left.
eapply Ha.
right.
exists ck.
split;
eauto.
apply in_or_app;
auto.
+
eapply is_trans_arc_Asymmetric;
eauto.
left.
eapply Ha.
right.
exists ck;
split;
eauto.
apply in_or_app;
auto.
}
eexists;
eexists.
exists g''.
split; [
split|];
auto.
-
unfold vertices;
simpl.
rewrite Hv.
repeat rewrite <-
ps_from_list_ps_of_list.
rewrite add_ps_from_list_cons,
map_app,
map_app,
Permutation_middle.
apply fresh_ident_anns in Hfresh.
unfold st_clocks.
rewrite Hfresh.
reflexivity.
-
intros *
Hdep.
unfold is_arc.
rewrite add_arc_spec.
repeat rewrite add_between_spec;
eauto.
destruct Hdep as [
Hdep|
Hdep]; [
inv Hdep;[|
inv H2]|].
+
destruct H2 as (?&
Hnth&?);
simpl in *.
rewrite nth_error_length_nth in Hnth.
specialize (
Hnth xH)
as (
Hlen&
Hnth).
apply Nat.lt_1_r in Hlen;
subst.
inv H1; [|
inv H6].
apply Hf1 in H6 as [?|[?|?]];
subst;
auto 10.
left.
left.
apply Ha.
left.
left.
exists 0.
repeat split;
auto.
left;
auto.
rewrite Hnum;
auto.
+
destruct H3 as (?&
Hnth&?);
simpl in *.
rewrite nth_error_length_nth in Hnth.
specialize (
Hnth xH)
as (
Hlen&
Hnth).
apply Nat.lt_1_r in Hlen;
subst.
inv H1; [|
inv H6].
left.
right;
left.
split;
auto.
rewrite PS.union_spec,
collect_free_left_spec;
eauto.
+
left.
left.
apply Ha.
left.
right;
auto.
+
destruct Hdep as (
ck'&
Hin&
Hfree).
unfold st_clocks in Hin.
erewrite fresh_ident_anns in Hin;
eauto;
simpl in Hin.
rewrite <-
Permutation_middle in Hin.
inv Hin.
2:(
left;
left;
apply Ha;
right;
eauto).
inv H1.
left.
right.
left.
split;
auto.
rewrite PS.union_spec,
collect_free_clock_spec;
auto.
-
erewrite fresh_ident_false_st_inits;
eauto.
eapply Forall_impl_In; [|
eauto].
intros (?&?)
Hin Ha' ?
Ha''.
eapply used_in_clock_add_arc with (
g0:=
g');
eauto.
1:
intros contra;
subst;
eapply Hnck,
In_InMembers;
eauto.
clear Ha''.
intros ?
Ha''.
eapply used_in_clock_add_between;
eauto.
1-3:
intro contra;
subst.
+
eapply Hnck,
In_InMembers;
eauto.
+
eapply Facts.fresh_ident_nIn in Hfresh;
eauto.
apply Hfresh,
st_inits_incl_st_ids.
rewrite in_map_iff.
exists (
x',
c);
auto.
+
unfold is_vertex in contra.
rewrite Hv in contra.
eapply Facts.fresh_ident_nIn''
in Hfresh;
eauto.
rewrite ps_of_list_In,
map_app,
st_clocks_st_ids in contra;
auto.
Qed.
Fact fby_equation_causal :
forall G vars to_cut eq eqs eqs'
st st',
Forall (
unnested_equation G) (
eq::
eqs) ->
wc_env vars ->
wc_equation G vars eq ->
causal_inv vars (
eq::
eqs)
st ->
fby_equation to_cut eq st = (
eqs',
st') ->
causal_inv vars (
eqs++
eqs')
st'.
Proof.
Fact fby_equations_causal' :
forall G vars to_cut eqs ceqs eqs'
st st',
wc_env vars ->
Forall (
unnested_equation G) (
ceqs++
eqs) ->
Forall (
wc_equation G vars)
eqs ->
causal_inv vars (
ceqs++
eqs)
st ->
fby_equations to_cut eqs st = (
eqs',
st') ->
causal_inv vars (
ceqs++
eqs')
st'.
Proof.
Corollary fby_equations_causal :
forall G vars to_cut eqs eqs'
st st',
wc_env vars ->
Forall (
unnested_equation G)
eqs ->
Forall (
wc_equation G vars)
eqs ->
causal_inv vars eqs st ->
fby_equations to_cut eqs st = (
eqs',
st') ->
causal_inv vars eqs'
st'.
Proof.
intros * Hwenv Hunt Hwl Hcaus Hfby.
eapply fby_equations_causal' with (ceqs:=[]) in Hfby; simpl; eauto.
Qed.
Fact Permutation_map_fst {
B} :
forall (
xs :
list (
ident *
B))
ys,
Permutation (
map fst xs)
ys ->
exists zs,
Permutation xs zs /\
ys =
map fst zs.
Proof.
induction xs;
intros *
Hperm.
-
apply Permutation_nil in Hperm;
subst.
exists [];
auto.
-
destruct a as [
id b].
specialize (
in_split id ys)
as (
ys1&
ys2&?);
subst.
{
rewrite <-
Hperm.
left;
auto. }
apply Permutation_cons_app_inv in Hperm.
apply IHxs in Hperm as (?&?&?).
symmetry in H0.
apply map_app'
in H0 as (
xs1&
xs2&?&?&?);
subst.
exists (
xs1 ++ (
id,
b) ::
xs2);
simpl;
split.
+
rewrite <-
Permutation_middle.
apply perm_skip;
auto.
+
rewrite map_app;
simpl.
reflexivity.
Qed.
Lemma normfby_node_causal :
forall G n to_cut Hunt Hpref,
wc_global G ->
wc_node G n ->
node_causal n ->
node_causal (
normfby_node G to_cut n Hunt Hpref).
Proof.
Lemma normfby_global_causal :
forall G Hunt Hprefs,
wc_global G ->
Forall node_causal G ->
Forall node_causal (
normfby_global G Hunt Hprefs).
Proof.
induction G;
intros *
Hwc Hcaus;
auto.
inv Hwc.
inv Hcaus.
constructor;
eauto.
eapply normfby_node_causal;
eauto.
Qed.
End NCAUSALITY.
Module NCausalityFun
(
Ids :
IDS)
(
Op :
OPERATORS)
(
OpAux :
OPERATORS_AUX Op)
(
Syn :
LSYNTAX Ids Op)
(
Cau :
LCAUSALITY Ids Op Syn)
(
Clo :
LCLOCKING Ids Op Syn)
(
Norm :
NORMALIZATION Ids Op OpAux Syn Cau)
<:
NCAUSALITY Ids Op OpAux Syn Cau Clo Norm.
Include NCAUSALITY Ids Op OpAux Syn Cau Clo Norm.
End NCausalityFun.