From Velus Require Import Common.
From Coq Require Import List.
From Coq Require Import Morphisms.
From Coq Require Import Permutation.
From Velus Require Export ClockDefs.
Clocks
Inductive Is_free_in_clock :
ident ->
clock ->
Prop :=
|
FreeCon1:
forall x ck'
xc,
Is_free_in_clock x (
Con ck'
x xc)
|
FreeCon2:
forall x y ck'
xc,
Is_free_in_clock x ck'
->
Is_free_in_clock x (
Con ck'
y xc).
From Coq Require Import Classes.EquivDec.
Open Scope bool.
Fixpoint clock_eq (
ck1 ck2:
clock) :
bool :=
match ck1,
ck2 with
|
Cbase,
Cbase =>
true
|
Con ck1'
x1 b1,
Con ck2'
x2 b2 =>
(
Pos.eqb x1 x2 && (
b1 ==
b b2)) &&
clock_eq ck1'
ck2'
|
_,
_ =>
false
end.
Lemma clock_eq_spec:
forall ck1 ck2,
clock_eq ck1 ck2 =
true <->
ck1 =
ck2.
Proof.
Instance clock_EqDec :
EqDec clock eq.
Proof.
intros ck1 ck2.
compute.
pose proof (
clock_eq_spec ck1 ck2)
as Heq.
destruct (
clock_eq ck1 ck2); [
left|
right].
now apply Heq.
intro HH.
apply Heq in HH.
discriminate.
Qed.
Lemma clock_eqb_eq :
forall (
x y:
clock),
x ==
b y =
true <->
x =
y.
Proof.
Lemma clock_eqb_neq :
forall (
x y:
clock),
x ==
b y =
false <->
x <>
y.
Proof.
intros *;
split;
intro H.
-
intro contra.
rewrite <-
clock_eqb_eq in contra.
congruence.
-
destruct (
x ==
b y)
eqn:
Hec;
auto.
rewrite clock_eqb_eq in Hec.
congruence.
Qed.
Instance nclock_EqDec :
EqDec nclock eq.
Proof.
eapply prod_eqdec.
-
eapply clock_EqDec.
-
unfold EqDec.
intros x y;
destruct x;
destruct y;
try (
right;
congruence).
+
specialize (
EqDec_instance_0 i i0)
as [?|?].
*
left.
rewrite e.
reflexivity.
*
right.
intro contra.
inv contra.
congruence.
+
left.
reflexivity.
Qed.
Lemma nclock_eqb_eq :
forall (
x y:
nclock),
x ==
b y =
true <->
x =
y.
Proof.
Lemma clock_not_in_clock:
forall ck x b,
~(
ck =
Con ck x b).
Proof.
intros * Hck.
induction ck; try discriminate.
injection Hck; intros.
apply IHck. now subst b x.
Qed.
Well-clocking
Inductive wc_clock (
vars:
list (
ident *
clock)) :
clock ->
Prop :=
|
CCbase:
wc_clock vars Cbase
|
CCon:
forall ck x b,
wc_clock vars ck ->
In (
x,
ck)
vars ->
wc_clock vars (
Con ck x b).
Hint Constructors wc_clock :
lclocking.
Definition wc_env vars :
Prop :=
Forall (
fun xck =>
wc_clock vars (
snd xck))
vars.
Lemma wc_env_var:
forall vars x ck,
wc_env vars
->
In (
x,
ck)
vars
->
wc_clock vars ck.
Proof.
intros vars x ck Hwc Hcv.
now apply Forall_forall with (2:=
Hcv)
in Hwc.
Qed.
Lemma wc_clock_add:
forall x v env ck,
~
InMembers x env ->
wc_clock env ck ->
wc_clock ((
x,
v) ::
env)
ck.
Proof.
induction ck;
auto using wc_clock.
inversion 2.
auto using wc_clock with datatypes.
Qed.
Lemma wc_env_add:
forall x env ck,
~
InMembers x env ->
wc_clock env ck ->
wc_env env ->
wc_env ((
x,
ck) ::
env).
Proof.
Lemma wc_clock_sub:
forall vars ck x b,
wc_env vars
->
wc_clock vars (
Con ck x b)
->
In (
x,
ck)
vars.
Proof.
intros vars ck x b Hwc Hclock.
inversion_clear Hclock as [|? ? ? Hclock' Hcv'].
assumption.
Qed.
Instance wc_clock_Proper:
Proper (@
Permutation (
ident *
clock) ==> @
eq clock ==>
iff)
wc_clock.
Proof.
intros env'
env Henv ck'
ck Hck.
rewrite Hck;
clear Hck ck'.
induction ck.
-
split;
auto using wc_clock.
-
destruct IHck.
split;
inversion_clear 1;
constructor;
try rewrite Henv in *;
auto using wc_clock.
Qed.
Instance wc_env_Proper:
Proper (@
Permutation (
ident *
clock) ==>
iff)
wc_env.
Proof.
intros env'
env Henv.
unfold wc_env.
split;
intro HH.
-
apply Forall_forall.
intros x Hin.
rewrite <-
Henv in Hin.
apply Forall_forall with (1:=
HH)
in Hin.
now rewrite Henv in Hin.
-
apply Forall_forall.
intros x Hin.
rewrite Henv in Hin.
apply Forall_forall with (1:=
HH)
in Hin.
now rewrite <-
Henv in Hin.
Qed.
Parent relation
Inductive clock_parent ck :
clock ->
Prop :=
|
CP0:
forall x b,
clock_parent ck (
Con ck x b)
|
CP1:
forall ck'
x b,
clock_parent ck ck'
->
clock_parent ck (
Con ck'
x b).
Lemma clock_parent_parent':
forall ck'
ck i b,
clock_parent (
Con ck i b)
ck'
->
clock_parent ck ck'.
Proof.
Hint Constructors clock_parent.
induction ck'
as [|?
IH]; [
now inversion 1|].
intros ck i'
b'
Hcp.
inversion Hcp as [|? ? ?
Hcp']; [
now auto|].
apply IH in Hcp';
auto.
Qed.
Lemma clock_parent_parent:
forall ck'
ck i b,
clock_parent (
Con ck i b)
ck'
->
clock_parent ck (
Con ck'
i b).
Proof.
Hint Constructors clock_parent.
destruct ck'; [
now inversion 1|].
intros ck i'
b'
Hcp.
inversion Hcp as [|? ? ?
Hcp']; [
now auto|].
apply clock_parent_parent'
in Hcp';
auto.
Qed.
Lemma clock_parent_trans:
forall ck1 ck2 ck3,
clock_parent ck1 ck2 ->
clock_parent ck2 ck3 ->
clock_parent ck1 ck3.
Proof.
induction ck2. now inversion 1.
intros ck3 H12 H23.
apply clock_parent_parent' in H23.
inversion_clear H12; auto.
Qed.
Instance clock_parent_Transitive:
Transitive clock_parent.
Proof clock_parent_trans.
Lemma clock_parent_Cbase:
forall ck i b,
clock_parent Cbase (
Con ck i b).
Proof.
induction ck as [|? IH]; [now constructor|].
intros; constructor; apply IH.
Qed.
Lemma clock_parent_not_refl:
forall ck,
~
clock_parent ck ck.
Proof.
induction ck as [|? IH]; [now inversion 1|].
intro Hp; inversion Hp as [? ? HR|? ? ? Hp'].
- rewrite HR in Hp; contradiction.
- apply clock_parent_parent' in Hp'; contradiction.
Qed.
Lemma clock_parent_no_loops:
forall ck ck',
clock_parent ck ck'
->
ck <>
ck'.
Proof.
Lemma clock_no_loops:
forall ck x b,
Con ck x b <>
ck.
Proof.
induction ck as [|? IH]; [discriminate 1|].
injection 1; intros ? Heq.
apply IH.
Qed.
Lemma clock_parent_Con:
forall ck ck'
i b j c,
clock_parent (
Con ck i b) (
Con ck'
j c)
->
clock_parent ck ck'.
Proof.
destruct ck;
induction ck'
as [|?
IH].
-
inversion 1
as [|? ? ?
Hp].
apply clock_parent_parent'
in Hp;
inversion Hp.
-
intros;
now apply clock_parent_Cbase.
-
inversion 1
as [|? ? ?
Hp];
inversion Hp.
-
intros i'
b'
j c.
inversion 1
as [? ?
Hck'|? ? ?
Hp];
[
rewrite Hck'
in IH;
now constructor|].
apply IH in Hp;
auto.
Qed.
Lemma clock_parent_strict':
forall ck'
ck,
~(
clock_parent ck ck' /\
clock_parent ck'
ck).
Proof.
induction ck'
as [|?
IH];
destruct ck;
destruct 1
as [
Hp Hp'];
try now (
inversion Hp ||
inversion Hp').
apply clock_parent_Con in Hp.
apply clock_parent_Con in Hp'.
eapply IH;
split;
eassumption.
Qed.
Lemma clock_parent_strict:
forall ck'
ck,
(
clock_parent ck ck' -> ~
clock_parent ck'
ck).
Proof.
destruct ck'; [now inversion 1|].
intros ck Hp Hp'.
eapply clock_parent_strict'; split; eassumption.
Qed.
Lemma Con_not_clock_parent:
forall ck x b,
~
clock_parent (
Con ck x b)
ck.
Proof.
Lemma Is_free_in_clock_self_or_parent:
forall x ck,
Is_free_in_clock x ck
->
exists ck'
b,
ck =
Con ck'
x b \/
clock_parent (
Con ck'
x b)
ck.
Proof.
Hint Constructors clock_parent.
induction ck as [|?
IH]; [
now inversion 1|].
intro Hfree.
inversion Hfree as [|? ? ? ?
Hfree'];
clear Hfree;
subst.
-
exists ck,
b;
now auto.
-
specialize (
IH Hfree');
clear Hfree'.
destruct IH as [
ck' [
b'
Hcp]].
exists ck',
b';
right.
destruct Hcp as [
Hcp|
Hcp]; [
rewrite Hcp|
inversion Hcp];
now auto.
Qed.
Lemma Is_free_in_clock_parent:
forall vars x ck ck',
NoDupMembers vars ->
In (
x,
ck')
vars ->
wc_clock vars ck ->
Is_free_in_clock x ck ->
clock_parent ck'
ck.
Proof.
induction ck as [|?
IH];
intros ck'
Hndup Hin Hwc Hfree;
inv Hfree;
inv Hwc.
-
clear IH.
eapply NoDupMembers_det with (
t:=
ck) (
t':=
ck')
in Hndup;
eauto;
subst.
constructor.
-
constructor;
auto.
Qed.
Lemma wc_clock_parent:
forall C ck'
ck,
wc_env C
->
clock_parent ck ck'
->
wc_clock C ck'
->
wc_clock C ck.
Proof.
Hint Constructors wc_clock.
induction ck'
as [|
ck'
IH];
destruct ck as [|
ck i'
ty'];
try now (
inversion 3 ||
auto).
intros Hwc Hp Hck.
inversion Hp as [
j c [
HR1 HR2 HR3]|
ck''
j c Hp' [
HR1 HR2 HR3]].
-
rewrite <-
HR1 in *;
clear HR1 HR2 HR3.
now inversion_clear Hck.
-
subst.
apply IH with (1:=
Hwc) (2:=
Hp').
now inversion Hck.
Qed.
Lemma instck_parent:
forall bk sub ck ck',
instck bk sub ck =
Some ck' ->
ck' =
bk \/
clock_parent bk ck'.
Proof.
induction ck.
now inversion_clear 1;
auto.
simpl.
intros ck'
Hi.
right.
destruct (
instck bk sub ck). 2:
discriminate.
destruct (
sub i). 2:
discriminate.
specialize (
IHck c eq_refl).
inversion_clear Hi.
destruct IHck;
subst;
auto.
Qed.
Lemma instck_subclock_not_clock_eq:
forall ck isub xck c x b,
instck ck isub xck =
Some c ->
clock_eq ck (
Con c x b) =
false.
Proof.
Lemma clock_parent_dec :
forall ck ck',
clock_parent ck ck' \/ ~
clock_parent ck ck'.
Proof.
intros ck;
induction ck'.
-
right.
intro contra;
inv contra.
-
destruct IHck'.
+
left.
constructor;
auto.
+
destruct (
clock_EqDec ck ck')
as [
Heq|
Hneq].
*
rewrite Heq.
left.
constructor.
*
right.
intro contra.
inv contra;
try congruence.
Qed.
Lemma exists_child_clock :
forall (
vars :
list (
ident *
clock)),
vars =
nil \/
exists id,
exists ck,
In (
id,
ck)
vars /\
Forall (
fun '(
_,
ck') => ~
clock_parent ck ck')
vars.
Proof.
induction vars;
auto.
right.
destruct a as [
id ck].
destruct IHvars as [?|[
id' [
ck' [
HIn cl]]]];
subst.
-
exists id.
exists ck.
split;
constructor;
auto.
intro contra.
apply clock_parent_no_loops in contra;
auto.
-
destruct (
clock_parent_dec ck'
ck).
+
exists id.
exists ck.
split.
*
left;
auto.
*
constructor;
auto.
intro contra.
eapply clock_parent_strict;
eauto.
eapply Forall_impl;
eauto.
intros [
id''
ck'']
Hpar;
simpl in Hpar.
intro contra.
apply Hpar.
etransitivity;
eauto.
+
exists id'.
exists ck'.
split.
*
right;
auto.
*
constructor;
auto.
Qed.
Corollary exists_child_clock' :
forall (
vars :
list (
ident *
clock)),
NoDupMembers vars ->
wc_env vars ->
vars =
nil \/
exists id,
exists ck,
In (
id,
ck)
vars /\
Forall (
fun '(
_,
ck') => ~
Is_free_in_clock id ck')
vars.
Proof.
Lemma wc_clock_nparent_remove :
forall vars id ck ck',
~
clock_parent ck'
ck ->
wc_clock ((
id,
ck')::
vars)
ck ->
wc_clock vars ck.
Proof.
induction ck; intros ck' Hnpar Hwc; constructor; inv Hwc.
- eapply IHck; eauto.
- destruct H3; eauto.
inv H.
exfalso. apply Hnpar. constructor.
Qed.
Corollary wc_clock_no_loops_remove :
forall vars id ck,
wc_clock ((
id,
ck)::
vars)
ck ->
wc_clock vars ck.
Proof.
Lemma instck_inv :
forall bck sub ck ck'
x,
instck bck sub ck =
Some ck' ->
Is_free_in_clock x ck' ->
Is_free_in_clock x bck \/
(
exists x',
sub x' =
Some x /\
Is_free_in_clock x'
ck).
Proof.
induction ck; intros * Hinst Hfree.
- inv Hinst. auto.
- inversion Hinst as [Hins]. cases_eqn Hins. inv Hins.
inversion_clear Hfree as [| ???? Hfr].
right. exists i. split. auto. constructor.
apply IHck in Hfr as [|[y []]] ; auto. right.
exists y. split; auto. now constructor.
Qed.
Lemma instck_free_bck :
forall bck sub ck ck'
x,
instck bck sub ck =
Some ck' ->
Is_free_in_clock x bck ->
Is_free_in_clock x ck'.
Proof.
induction ck;
intros *
Hinst Hfree.
-
inv Hinst.
auto.
-
inversion Hinst as [
Hins].
cases_eqn Hins.
inv Hins.
specialize (
IHck c x eq_refl Hfree).
now constructor.
Qed.
Lemma instck_free_sub :
forall bck sub ck ck'
x x',
instck bck sub ck =
Some ck' ->
Is_free_in_clock x ck ->
sub x =
Some x' ->
Is_free_in_clock x'
ck'.
Proof.
induction ck;
intros *
Hinst Hfree Hsub.
-
inv Hfree.
-
inv Hfree.
+
inversion Hinst as [
Hins].
cases_eqn Hins.
inv Hsub.
inv Hins.
constructor.
+
inversion Hinst as [
Hins].
cases_eqn Hins.
inv Hins.
specialize (
IHck c x x'
eq_refl H1 Hsub).
now constructor.
Qed.