Mefresa.Examples.GCMSpec
Require Import Mefresa.Operation.Compliance.
Proving the absence of Cross Bindings
Preliminary Definitions - Setting Up the Scene!
Definition cross_normal idC1 idI1 idC2 idI2 lc : Prop :=
(exists c, Some c = lc [idC1] /\
(exists i, Some i = (c ->interfaces)%comp [idI1, External] /\
(i ->role)%int = Client)%int) /\
(~ exists c, Some c = lc[idC2] /\
(exists i, Some i = (c ->interfaces)%comp [idI2, External])%int) /\
(forall c, In c lc ->
(exists c' c'', In c' (c->subComponents%comp) /\
Some c'' = (c'->subComponents%comp)[idC2] /\
(exists i, Some i = (c'' ->interfaces)%comp [idI2, External]%int /\
(i ->role)%int = Server))).
Definition cross_export idI1 idC2 idI2 lc li : Prop :=
(exists i, Some i = li [idI1, Internal]%int /\ (i ->role)%int = Client) /\
(~ exists c, Some c = lc[idC2] /\
(exists i, Some i = (c ->interfaces)%comp [idI2, External])%int) /\
(forall c, In c lc -> exists c', Some c' = (c->subComponents%comp)[idC2] /\
exists i, Some i = (c'->interfaces%comp)[idI2, External]%int /\
(i ->role)%int = Server).
Definition cross_import idI1 idC2 idI2 lc li : Prop :=
(exists i, Some i = li [idI1, Internal]%int /\ (i ->role)%int = Server) /\
(~ exists c, Some c = lc[idC2] /\
(exists i, Some i = (c ->interfaces)%comp [idI2, External])%int) /\
(forall c, In c lc -> exists c', Some c' = (c->subComponents%comp)[idC2] /\
exists i, Some i = (c'->interfaces%comp)[idI2, External]%int /\
(i ->role)%int = Client).
The 3 above definitions cross_normal, cross_export and cross_import define
what it means to be a cross binding of type Normal, Export and Import, respectively.
Essentially, they all state that the "second part" of the binding
(idC2 IdI2, for id of second component and id of second interface, resp.), is located
at a different level in the component hierarchy. Since we use idents to identify
components and interfaces, and since they need not to be unique among different
levels of the hierarchy, we need to explicitly state that there exists no component
and/or interface with such ident.
From this, we can proceed to the remaining few definitions that basically just place
the above ones in the context of our hierarchical component framework.
Definition valid_cross_binding b lc li : Prop :=
match b with
Normal p idC1 idI1 idC2 idI2 => cross_normal idC1 idI1 idC2 idI2 lc
| Export p idI1 idC2 idI2 => cross_export idI1 idC2 idI2 lc li
| Import _ idI1 idC2 idI2 => cross_import idI1 idC2 idI2 lc li
end.
Inductive cross_binding' b p lc : Prop :=
| CrossBinding_Base: p = (nil : path) ->
valid_cross_binding b lc nil ->
cross_binding' b p lc
| CrossBinding_Step: forall c,
Some c = get_component_with_path_aux p lc ->
valid_cross_binding b (c ->subComponents)%comp (c ->interfaces)%comp ->
cross_binding' b p lc.
Definition cross_binding b s : Prop :=
cross_binding' b (b->path%bind) (s->components%st).
Axiom binding_type_dec : forall b s,
{cross_binding b s} + {valid_component_binding b s}.
Cross Bindings Cannot Occur? Proof? Sure thing!
Lemma binding_cannot_be_crossing_if_valid:
forall b s,
valid_component_binding b s ->
cross_binding b s ->
False.
Proof.
intros.
destruct s.
destruct b.
Case "Normal Binding".
inversion H; simpl in *; subst.
SCase "Path is nil".
clear H.
inversion H0; simpl in *.
clear H H0.
unfold normal_binding in H2.
destruct H1 as (He, (Hf, Hg)).
clear Hg.
destruct He as (c', (He1,(i', (He3, He4)))).
rewrite <- He1 in H2.
destruct (l [i3]).
apply Hf.
exists c0; split; auto.
rewrite <- He3 in H2.
destruct (((c0 ->interfaces)%comp [i4, External])%int).
exists i5; auto.
inversion H2.
inversion H2.
inversion H.
SCase "Path is not Nil".
destruct H1 as (c1, (H01, H02)).
clear H.
inversion H0; simpl in *; subst.
simpl in H01.
congruence.
assert (c0 = c1).
rewrite <- H01 in H.
inversion H; auto.
subst.
unfold normal_binding in H02.
destruct H1 as (He, (Hf, Hg)).
clear Hg.
destruct He as (c', (He1,(i', (He3, He4)))).
rewrite <- He1 in H02.
destruct ((c1 ->subComponents)%comp [i3]).
apply Hf.
exists c0; split; auto.
rewrite <- He3 in H02.
destruct (((c0 ->interfaces)%comp [i4, External])%int).
exists i5; auto.
fromfalse.
fromfalse.
Case "Export Binding".
inversion H; simpl in *; subst.
SCase "Path is nil".
clear H.
inversion H0; simpl in *.
clear H H0.
unfold export_binding in H2.
destruct H1 as (He, (Hf, Hg)).
clear Hg.
destruct He as (i', (He1,He4)).
inversion He1.
inversion H.
SCase "Path is not Nil".
destruct H1 as (c1, (H01, H02)).
clear H.
inversion H0; simpl in *; subst.
simpl in H01.
inversion H01.
assert (c0 = c1).
rewrite <- H01 in H.
inversion H; auto.
subst.
unfold export_binding in H02.
destruct H1 as (He, (Hf, Hg)).
clear Hg.
destruct He as (i', (He1, He4)).
rewrite <- He1 in H02.
destruct ((c1 ->subComponents)%comp [i2]).
apply Hf.
exists c0; split; auto.
rewrite <- He4 in H02.
destruct (((c0 ->interfaces)%comp [i3, External])%int).
exists i4; auto.
fromfalse.
fromfalse.
Case "Import Binding".
inversion H; simpl in *; subst.
SCase "Path is nil".
clear H.
inversion H0; simpl in *.
clear H H0.
unfold export_binding in H2.
destruct H1 as (He, (Hf, Hg)).
clear Hg.
destruct He as (i', (He1,He4)).
inversion He1.
inversion H.
SCase "Path is not Nil".
destruct H1 as (c1, (H01, H02)).
clear H.
inversion H0; simpl in *; subst.
simpl in H01.
congruence.
assert (c0 = c1).
rewrite <- H01 in H.
inversion H; auto.
subst.
unfold import_binding in H02.
destruct H1 as (He, (Hf, Hg)).
clear Hg.
destruct He as (i', (He1, He4)).
rewrite <- He1 in H02.
destruct ((c1 ->subComponents)%comp [i2]).
apply Hf.
exists c0; split; auto.
rewrite <- He4 in H02.
destruct (((c0 ->interfaces)%comp [i3, External])%int).
exists i4; auto.
fromfalse.
fromfalse.
Qed.
The proof of binding_cannot_be_crossing_if_valid gives us
that a binding cannot be valid and crossing for the same
state. The argument of the proof is essentially a case
analysis on the binding type, where we show a contradiction
for all of the 3 constructors.
The proof above, although a little bit long, should pose no
trouble to the reader. Our definition of cross_bindings is
defined in a way that makes this proof easy, as it requires
to explicitly negate the presence of a component and/or
interface that would match the specified idents in the
"second part" of the cross_binding. This is a direct implication
of the data structure used to defined our hierarchical component
framework. As usual in Coq developments relying on inductive
definitions, choosing adequates data structures may considerably ease
the burden of theorem proving.
We shall now proceed to one last definition before moving to the main
proof. We define a predicate system_binding that states whether
a binding belongs to a state.
Definition system_binding (b:binding) (s:state) : Prop :=
match get_component_with_path (b->path%bind) s with
| None => False
| Some c => In b (c->bindings%comp)
end.
Theorem cross_binding_cannot_happen:
forall b system,
well_formed system ->
system_binding b system ->
cross_binding b system ->
False.
Proof.
intros.
apply binding_cannot_be_crossing_if_valid
with (b:=b) (s:=system); auto.
clear H1.
unfold system_binding in H0.
destruct get_component_with_path_dec
with (p:=b->path%bind)(s:=system); auto.
destruct system.
unfold well_formed in H.
destruct H as (Hi, (Hp, (Hic, (Hc, (Hl, Hw))))); subst; auto.
Case "It does exists!".
unfold valid_component_binding.
destruct (b->path%bind).
SCase "Path is nil".
destruct H1 as (c, (He, Hp)).
rewrite <- He in H0.
simpl in He.
inversion He.
SCase "Path is not nil".
destruct H1 as (c, (He, Hp)).
rewrite <- He in H0.
apply ValidComponentBinding_Step .
unfold get_component_with_path in He.
destruct system.
exists c.
split;auto.
assert (well_formed_bindings (c ->bindings)%comp (c ->subComponents)%comp (c ->interfaces)%comp).
destruct c; simpl in *; subst; auto.
inversion Hp; auto.
unfold well_formed_bindings in H1.
apply H1;auto.
Case "It does not exists!".
rewrite <- H1 in H0.
inversion H0.
Qed.
The key to the proof of our main theorem cross_binding_cannot_happen
lies in the argument of our previously proved lemma binding_cannot_be_crossing_if_valid.
The idea is to show that any binding present in the state must be a
valid_component_binding - this follows from the fact that the state is
well_formed. Then, since we know from binding_cannot_be_crossing_if_valid that
a binding cannot be a valid_component_binding and a valid_cross_binding at the same
time, we can conclude the proof.