Mefresa.Behaviour.MasterSlaveCoffee
In this module we show another example regarding the reasoning about
synchronized transition systems. In particular, we retake the example
from the Fiacre online tutorial 1 concerning the Master/Slave
coffee orders.
1 http://projects.laas.fr/fiacre/doc/fiacre-tutorial.html
Master and Slave Coffee example
Definition mem : state_mem := nil.
Definition slv0 : lts_state := LTS_State 0 mem.
Definition slv1 : lts_state := LTS_State 1 mem.
Definition receiveCoffeeOrder (n:nat) : action :=
Action (Message "order:MakeCoffee" Read (Val(n)::nil)) nil.
Function nCoffeeOrders n : actions :=
match n with
0 => receiveCoffeeOrder 0 :: nil
| S m => receiveCoffeeOrder n :: nCoffeeOrders m
end.
Definition receiveSandwichOrder : action :=
Action (Message "order:MakeSandwich" Read nil) nil.
Definition slave_order_acts n : actions := receiveSandwichOrder :: nCoffeeOrders n.
Definition slave_ready_act : action := Action (Message "ready" Read nil) nil.
Definition slave_acts n : actions := slave_ready_act :: (slave_order_acts n).
Definition slave_sts : lts_states := slv0 :: slv1 :: nil.
Function slave_transitions slave_order_acts : transitions :=
match slave_order_acts with
nil => (slv0, slave_ready_act, slv1) :: nil
| slave_act :: r => (slv1, slave_act, slv0) :: (slave_transitions r)
end.
Definition slavelts n : LTS := mk_LTS slave_sts slv0 (slave_acts n)
(slave_transitions (slave_order_acts n)).
The above mechanization should pose no doubt. Basically, it is a simple
LTS composed by two lts_states, slv0 and slv1, and the
actions specified by the slave_acts function. The transitions
are achieved through the slave_transitions function, and everything
is put together by slavelts definition.
The model of the masterlts follows the same rationale as discussed
for slavelts.
Master model
Definition mst0 : lts_state := LTS_State 0 mem.
Definition mst1 : lts_state := LTS_State 1 mem.
Definition makeCoffeeOrder (n:nat) : action :=
Action (Message "MakeCoffee" Emit (Val(n)::nil)) nil.
Function nMakeCoffeeOrders n : actions :=
match n with
0 => makeCoffeeOrder 0 :: nil
| S m => makeCoffeeOrder n :: nMakeCoffeeOrders m
end.
Definition makeSandwichOrder : action :=
Action (Message "MakeSandwich" Emit nil) nil.
Definition master_order_acts n : actions := makeSandwichOrder :: nMakeCoffeeOrders n.
Definition master_ready_act : action := Action (Message "ready" Emit nil) nil.
Definition master_acts n : actions := master_ready_act :: (master_order_acts n).
Definition master_sts : lts_states := mst0 :: mst1 :: nil.
Function master_transitions master_order_acts :=
match master_order_acts with
nil => (slv0, master_ready_act, slv1) :: nil
| master_act :: r => (slv1, master_act, slv0) :: (master_transitions r)
end.
Definition masterlts n : LTS := mk_LTS master_sts mst0 (master_acts n)
(master_transitions (master_order_acts n)).
Synchronization Vectors, and the overall Net
Definition synch_vectors :=
[ <<"ready" , "ready">> -> "ready" ;
<<"order:MakeSandwich", "MakeSandwich">> -> "order:Sandwich" ;
<<"order:MakeCoffee" , "MakeCoffee">> -> "order:Coffee" ].
Interleaving property
Inductive interleaving (X:Type) (Y:Type) (R:Y->X->Prop)
(a b : Y) : LList X -> Prop :=
InterleavingOne: forall l' l a' b',
l = LCons a' (LCons b' l') ->
R a a' ->
R b b' ->
interleaving R a b l
| InterleavingTwo: forall l' l a' b',
l = LCons b' (LCons a' l') ->
R a a' ->
R b b' ->
interleaving R a b l.
The above interleaving takes a relation R as parameter
since we may want a different relation then equality.
Further, we include two construtors in order to easily cope
with the order by which the interleaving starts.
Definition Rma (l:string) (act:action) : Prop :=
match l, act with
"ready", Action (Message l' _ct _lp) _asgns => "ready" = l'
| "order", Action (Message l' _ct _lp) _asgns =>
"order:Sandwich" = l' \/ "order:Coffee" = l'
| _, _ => False
end.
Above, the Rma definition is the interleaving relation that we shall
be using for the rest of this module.s Basically, we just
want to compare the labels of the involved actions.
For the sake of clarity, we demonstrate two examples illustrating
the interleaving predicate in action.
Example interelaving_test:
forall t a b,
a = Action (Message "ready" Read nil) nil ->
b = Action (Message "order:Sandwich" Read nil) nil ->
t = LCons a (LCons b LNil)->
t |= (Always (interleaving Rma "ready" "order")).
Proof.
intros. subst.
apply Always_LCons.
Case "1/2".
eapply InterleavingOne; [refl | ..]; compute; auto.
Case "2/2".
Abort.
Example interelaving_test':
forall t a b,
a = Action (Message "ready" Read nil) nil ->
b = Action (Message "order:Sandwich" Read nil) nil ->
t = LCons a (LCons b (LCons b (LCons a LNil)))->
t |= (Always (interleaving Rma "ready" "order")).
Proof.
intros. subst.
apply Always_LCons.
Case "1/2".
eapply InterleavingOne; [refl | ..]; compute; auto.
Case "2/2".
apply Always_LCons.
SCase "1/2".
eapply InterleavingTwo; [refl | ..]; compute; auto.
Abort.
A first Master/Coffee proof
Module InstantiatedExample.
Theorem Infinite_ready_interleaving:
forall t q,
Net_Trace (MasterSlaveCoffeeNet 2) q t ->
t |= (Always (interleaving Rma "ready" "order")).
Proof.
cofix;
intros t q Ht; inversion Ht; subst.
Case "1/3 : case of an LTS trace. reductio ad absurdum".
clear Ht.
discriminate H0.
Case "2/3 : case of a empty Net trace. reductio ad absurdum".
clear Ht.
inversion H; subst. clear H.
unfold synch_vectors in *.
inversion H1; [discriminate | subst].
inversion H0 ;subst. clear H0.
inversion H5; [discriminate | subst].
inversion H0; subst. clear H0.
inversion H7; [subst | discriminate].
clear H5 H7 H0 H1.
destruct H4 as [Hs0 | [Hs1 | Hf]]; subst; try inversion Hf;
destruct H6 as [Hm0 | [Hm1 | Hf']]; subst; try inversion Hf'.
SCase "1/4 : Current state is attainable, but no valid synch. vectors".
absurd (net_target_states (MasterSlaveCoffeeNet 2) (Net_State [slv0; mst0])
(<< "ready", "ready" >> -> "ready") = []).
SSCase "absurd: False case".
simpl; discriminate.
SSCase "absurd: True case".
apply H3. left; auto.
SCase "2/4: Current state is not attainable. Proof by contradiction". Focus.
clear -SCase SCase H2.
simpl in H2.
inversion H2; subst.
inversion H0; subst. clear H0.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse. clear H2 H.
destruct H4; [subst| fromfalse].
inversion H5; subst. clear H H5.
inversion H0; subst.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SCase SCase H.
assert (False).
apply H. compute. auto.
fromfalse.
destruct H3 as
[Hs1 | [Hs2 | [Hs3 | Hf] ]];
subst; try inversion Hf; simpl in *; inversion H4; subst;
(assert (False);
[ apply H; compute; auto | fromfalse]).
SCase "3/4: Current state is not attainable. Proof by contradiction".
clear -SCase SCase H2.
simpl in H2.
inversion H2; subst.
inversion H0; subst. clear H0.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse. clear H2 H.
destruct H4; [subst| fromfalse].
inversion H5; subst. clear H H5.
inversion H0; subst.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SCase SCase H.
assert (False).
apply H. compute. auto.
fromfalse.
destruct H3 as
[Hs1 | [Hs2 | [Hs3 | Hf] ]];
subst; try inversion Hf; simpl in *; inversion H4; subst;
(assert (False);
[ apply H; compute; auto | fromfalse]).
SCase "4/4: Current state is attainable, but no valid synch. vectors". Focus.
absurd (net_target_states (MasterSlaveCoffeeNet 2) (Net_State [slv1; mst1])
(<< "order:MakeSandwich", "MakeSandwich" >> -> "order:Sandwich") = []).
SSCase "absurd: False case".
simpl; discriminate.
SSCase "absurd: True case".
apply H3. right. left; auto.
Case "3/3 : case of lcons Net trace. Prove the interleaving!".
clear Ht.
inversion H; subst. clear H.
inversion H1; [discriminate | subst]. clear H1.
inversion H0; subst. clear H0.
inversion H7; [discriminate | subst].
inversion H0; subst.
inversion H8; [subst | discriminate].
clear H0 H9 H8 H7.
simpl in H4; simpl in H1.
simpl in H2.
destruct H1 as [Hs0 | [Hs1 | Hf]]; subst; try inversion Hf;
destruct H4 as [Hm0 | [Hm1 | Hf']]; subst; try inversion Hf'.
SCase "1/4 : Current state is attainable". Focus.
clear H2.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst;
try inversion Hf; compute in H5; inversion H5;
[ subst | fromfalse]. clear H5.
inversion H; subst. clear H.
apply Always_LCons.
SSCase "1/2 : interleaving". Focus.
inversion H6; subst.
SSSCase "1/3".
discriminate.
SSSCase "2/3".
inversion H; subst.
unfold synch_vectors in *.
absurd (net_target_states (MasterSlaveCoffeeNet 2)
(Net_State [LTS_State 1 []; LTS_State 1 []])
(<< "order:MakeSandwich", "MakeSandwich" >> -> "order:Sandwich") = []).
SSSSCase "absurd: False case".
simpl. discriminate.
SSSSCase "absurd: True case".
apply H3. right. left. auto.
SSSCase "3/3".
inversion H; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst; try inversion Hf;
simpl in H5; inversion H5; subst; try fromfalse;
inversion H3; subst.
SSSSCase "1/4 : Synch. Vector order sandwich".
clear H3 H5.
apply InterleavingOne with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Sandwich" Emit []) []));
auto.
refl. simpl. left; auto.
SSSSCase "2/4 : Synch. Vector order coffee".
clear H3 H5.
apply InterleavingOne with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Coffee" Emit [Val 2]) [])).
refl. refl. simpl. right. refl.
SSSSCase "3/4". Focus.
clear H3 H5.
inversion H4; subst.
apply InterleavingOne with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Coffee" Emit [Val 1]) [])).
refl. refl. simpl. right. refl.
SSSSCase "4/4".
clear H3 H5.
destruct H4 as [Ha | Hf];
try inversion Hf; inversion Ha; subst; clear Ha.
apply InterleavingOne with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Coffee" Emit [Val 0]) [])).
refl. refl. simpl. right. refl.
SSCase "2/2 : Recursion".
apply Infinite_ready_interleaving with
(q:=(Net_State [LTS_State 1 []; LTS_State 1 []])).
clear Infinite_ready_interleaving.
exact H6.
SCase "2/4 : Current state is not attainable. Proof by contradiction".
clear -Case SCase H2. Focus.
inversion H2; subst.
inversion H0; subst. clear H0.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse. clear H2 H.
destruct H4; [subst| fromfalse].
inversion H5; subst. clear H H5.
inversion H0; subst.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
destruct H3 as
[Ha | [Ha | [Ha | Hf]]];
try inversion Hf; inversion Ha; subst;
clear H H0; inversion H4; clear - SCase SCase Case H;
(assert (False);
[ apply H; compute; auto | fromfalse]).
SCase "3/4 : Current state is not attainable. Proof by contradiction".
clear -Case SCase H2.
inversion H2; subst.
inversion H0; subst. clear H0.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse. clear H2 H.
destruct H4; [subst| fromfalse].
inversion H5; subst. clear H H5.
inversion H0; subst.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
destruct H3 as
[Ha | [Ha | [Ha | Hf]]];
try inversion Hf; inversion Ha; subst;
clear H H0; inversion H4; clear - SCase SCase Case H;
(assert (False);
[ apply H; compute; auto | fromfalse]).
SSCase "4/4 : Current state is attainable".
clear H2.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst;
[ compute in H5; inversion H5 | idtac | idtac | try inversion Hf].
SSSCase "1/2". Focus.
compute in H5; inversion H5; [subst | fromfalse].
clear H5.
inversion H; subst. clear H.
apply Always_LCons.
SSSSCase "1/2 : interleaving". Focus.
inversion H6; [discriminate | ..]; subst.
SSSSSCase "1/2". Focus.
inversion H; subst.
unfold synch_vectors in *.
absurd (net_target_states (MasterSlaveCoffeeNet 2)
(Net_State [LTS_State 0 []; LTS_State 0 []])
(<< "ready", "ready" >> -> "ready") = []).
SSSSSSCase "absurd: False case".
simpl. discriminate.
SSSSSSCase "absurd: True case".
apply H3. left. auto.
SSSSSCase "2/2".
inversion H; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst; try inversion Hf;
simpl in H5; inversion H5; subst; try fromfalse;
inversion H3; subst.
clear H3 H5.
apply InterleavingTwo with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Sandwich" Emit []) []));
auto.
refl. simpl. left; auto.
SSSSCase "2/2 : Recursion".
apply Infinite_ready_interleaving with
(q:=(Net_State [LTS_State 0 []; LTS_State 0 []])).
clear Infinite_ready_interleaving.
exact H6.
SSSCase "2/2".
compute in H5.
destruct H5 as
[Ha | [Ha | [Ha | Hf]]];
try inversion Hf; inversion Ha; clear Ha; subst.
SSSSCase "1/9".
apply Always_LCons.
SSSSSCase "1/2 : interleaving". Focus.
inversion H6; [discriminate | ..]; subst.
SSSSSSCase "1/2". Focus.
inversion H; subst.
unfold synch_vectors in *.
absurd (net_target_states (MasterSlaveCoffeeNet 2)
(Net_State [LTS_State 0 []; LTS_State 0 []])
(<< "ready", "ready" >> -> "ready") = []).
SSSSSSSCase "absurd: False case".
simpl. discriminate.
SSSSSSSCase "absurd: True case".
apply H3. left. auto.
SSSSSSCase "2/2".
inversion H; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst; try inversion Hf;
simpl in H5; inversion H5; subst; try fromfalse;
inversion H3; subst.
clear H3 H5.
apply InterleavingTwo with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Coffee" Emit [Val 2]) []));
auto.
refl. simpl. right; auto.
SSSSSCase "2/2 : Recursion".
apply Infinite_ready_interleaving with
(q:=(Net_State [LTS_State 0 []; LTS_State 0 []])).
clear Infinite_ready_interleaving.
exact H6.
SSSSCase "2/9".
apply Always_LCons.
SSSSSCase "1/2 : interleaving". Focus.
inversion H6; [discriminate | ..]; subst.
SSSSSSCase "1/2". Focus.
inversion H; subst.
unfold synch_vectors in *.
absurd (net_target_states (MasterSlaveCoffeeNet 2)
(Net_State [LTS_State 0 []; LTS_State 0 []])
(<< "ready", "ready" >> -> "ready") = []).
SSSSSSSCase "absurd: False case".
simpl. discriminate.
SSSSSSSCase "absurd: True case".
apply H3. left. auto.
SSSSSSCase "2/2".
inversion H; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst; try inversion Hf;
simpl in H5; inversion H5; subst; try fromfalse;
inversion H3; subst.
clear H3 H5.
apply InterleavingTwo with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Coffee" Emit [Val 1]) []));
auto.
refl. simpl. right; auto.
SSSSSCase "2/2 : Recursion".
apply Infinite_ready_interleaving with
(q:=(Net_State [LTS_State 0 []; LTS_State 0 []])).
clear Infinite_ready_interleaving.
exact H6.
SSSSCase "3/9".
apply Always_LCons.
SSSSSCase "1/2 : interleaving". Focus.
inversion H6; [discriminate | ..]; subst.
SSSSSSCase "1/2". Focus.
inversion H; subst.
unfold synch_vectors in *.
absurd (net_target_states (MasterSlaveCoffeeNet 2)
(Net_State [LTS_State 0 []; LTS_State 0 []])
(<< "ready", "ready" >> -> "ready") = []).
SSSSSSSCase "absurd: False case".
simpl. discriminate.
SSSSSSSCase "absurd: True case".
apply H3. left. auto.
SSSSSSCase "2/2".
inversion H; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst; try inversion Hf;
simpl in H5; inversion H5; subst; try fromfalse;
inversion H3; subst.
clear H3 H5.
apply InterleavingTwo with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Coffee" Emit [Val 0]) []));
auto.
refl. simpl. right; auto.
SSSSSCase "2/2 : Recursion".
apply Infinite_ready_interleaving with
(q:=(Net_State [LTS_State 0 []; LTS_State 0 []])).
clear Infinite_ready_interleaving.
exact H6.
Qed.
End InstantiatedExample.
Reasoning on a parametrized MasterSlaveCoffeeNet
Lemma net_target_states_from_q0q0':
forall sv n,
In sv
[
<< "order:MakeSandwich", "MakeSandwich" >> -> "order:Sandwich";
<< "order:MakeCoffee", "MakeCoffee" >> -> "order:Coffee"] ->
(get_list_snd
(net_target_states (MasterSlaveCoffeeNet n) (Net_State [slv0; mst0]) sv)) =
[].
Proof.
induction n; intros.
Case "1/2: Base case". Focus.
destruct H as [Hs | [Hc | Hf]]; try inversion Hf; subst; refl.
Case "2/2: Induction step".
assert (get_list_snd
(net_target_states (MasterSlaveCoffeeNet n)
(Net_State [slv0; mst0]) sv) = []).
apply IHn; auto.
clear IHn.
rewrite <- H0.
apply f_equal.
apply f_equal. refl.
Qed.
Lemma net_target_states_from_q0q0:
forall n,
(get_list_snd
(net_target_states (MasterSlaveCoffeeNet n) (Net_State [slv0; mst0]) (<< "ready", "ready" >> -> "ready"))) =
[Net_State [slv1; mst1]].
Proof.
induction n; intros.
Case "1/2: Base case".
refl.
Case "2/2: Induction step".
rewrite <- IHn.
apply f_equal.
apply f_equal. refl.
Qed.
The above lemmas simply demonstrate that, from the initial state Net_State slv0; mst0,
we can either reach Net_State [slv1; mst1], if using
<< "ready", "ready" >> -> "ready" as synchronization vector (lemma [net_target_states_from_q0q0]),
or we do not reach any state if using other synchronization vectors
(lemma [net_target_states_from_q0q0']).
Lemma MasterSlaveCoffeeNet_allowed_actions_from_q1q1_n_ready_fact:
forall n,
(allowed_actions_from_sv_element [slavelts n; masterlts n]
[slv1; mst1] [sync_notation "ready"; sync_notation "ready"]) = [[]; []].
Proof.
induction n; [refl|..].
simpl in *.
rewrite IHn. refl.
Qed.
Lemma net_target_states_from_q1q1':
forall n,
(net_target_states (MasterSlaveCoffeeNet n) (Net_State [slv1; mst1])
(<< "ready", "ready" >> -> "ready")) = [].
Proof.
induction n; intros.
Case "1/2: Base case".
refl.
Case "2/2: Induction step".
unfold MasterSlaveCoffeeNet.
unfold net_target_states;
fold net_target_states.
replace ((allowed_actions_from_sv_element [slavelts (S n); masterlts (S n)]
[slv1; mst1] [sync_notation "ready"; sync_notation "ready"]))
with [[]; (nil:actions)].
SCase "Continue proof with replacement".
refl.
SCase "prove sound replacement".
symmetry.
apply MasterSlaveCoffeeNet_allowed_actions_from_q1q1_n_ready_fact.
Qed.
Lemma net_target_states_from_q1q1' states that, from Net_State slv1; mst1,
we do not reach any state if using the ("ready", "ready"
- > "ready") synchronization vector. It uses the previosuly defined lemma MasterSlaveCoffeeNet_allowed_actions_from_q1q1_n_ready_fact.
Lemma allowed_actions_from_q1q1_sandwich_fact:
forall n,
(allowed_actions_from_sv_element [slavelts n; masterlts n]
[slv1; mst1] [sync_notation "order:MakeSandwich"; sync_notation "MakeSandwich"]) =
[[Action (Message "order:MakeSandwich" Read []) []];
[Action (Message "MakeSandwich" Emit []) []]].
Proof.
induction n; [refl | ..].
simpl in *. rewrite IHn. refl.
Qed.
Lemma allowed_actions_from_q1q1_sandwich_fact follows the rationale
of the MasterSlaveCoffeeNet_allowed_actions_from_q1q1_n_ready_fact lemma
but w.r.t. the MakeSandwich action.
Set Implicit Arguments.
Inductive allowed_actions_from_q1q1_coffee :
nat -> list (list action) -> Prop :=
| Coffee0: allowed_actions_from_q1q1_coffee 0
[[Action (Message "order:MakeCoffee" Read [Val 0]) []];
[Action (Message "MakeCoffee" Emit [Val 0]) []]]
| CoffeeN: forall n (l:list (list action)) (lread lemit:list action),
l = lread :: lemit :: nil ->
forall lreadt lemitt,
lread = Action (Message "order:MakeCoffee" Read [Val n]) [] :: lreadt->
lemit = Action (Message "MakeCoffee" Emit [Val n]) [] :: lemitt ->
allowed_actions_from_q1q1_coffee (n-1) [lreadt; lemitt] ->
allowed_actions_from_q1q1_coffee n l.
Dealing with the action involving MakeCoffee requires a bit more care
as it includes a parameter. Above, we defined the predicate
allowed_actions_from_q1q1_coffee, defining the allowed MakeCoffee
actions w.r.t. to the parameter n used for MasterSlaveCoffeeNet.
Lemma allowed_actions_from_sv_elements_coffee_fact:
forall n,
allowed_actions_from_q1q1_coffee n
(allowed_actions_from_sv_element
[slavelts n; masterlts n] [slv1; mst1]
[sync_notation "order:MakeCoffee"; sync_notation "MakeCoffee"]).
Proof.
induction n.
Case "1/2".
simpl. apply Coffee0.
Case "2/2".
unfold slv1 in *; unfold mst1 in *.
simpl in *.
eapply CoffeeN with
(lread:=Action (Message "order:MakeCoffee" Read [Val (S n)]) []
:: lts_allowed_actions_with_label (LTS_State 1 mem) (slave_transitions (nCoffeeOrders n)) (SyncElement "order:MakeCoffee"))
(lemit:=Action (Message "MakeCoffee" Emit [Val (S n)]) []
:: lts_allowed_actions_with_label (LTS_State 1 mem)
(master_transitions (nMakeCoffeeOrders n)) (SyncElement "MakeCoffee")); auto.
simpl.
replace (n-0) with n.
exact IHn. clear IHn.
induction n; [refl | ..].
rewrite IHn. simpl. refl.
Qed.
Lemma allowed_actions_from_sv_elements_coffee_fact depicts the first proof
involving the allowed_actions_from_q1q1_coffee predicate.
Inductive valid_coffee_combination : nat -> list (list action) -> Prop :=
| VC0: valid_coffee_combination 0 [[Action (Message "order:MakeCoffee" Read [Val 0]) [];
Action (Message "MakeCoffee" Emit [Val 0]) []]]
| VCN: forall l h t n, l = h :: t ->
h = [Action (Message "order:MakeCoffee" Read [Val n]) [];
Action (Message "MakeCoffee" Emit [Val n]) [] ] ->
valid_coffee_combination (n-1) t ->
valid_coffee_combination n l.
The net_target_states function computes the combination of possible
actions that may occur at each LTS (slavelts and masterlts)
composing the Net object MasterSlaveCoffeeNet. The above predicate
valid_coffee_combination specifies the valid combinations w.r.t.
the MakeCoffee actions.
Lemma combineN_coffee_orders_fact:
forall n l,
allowed_actions_from_q1q1_coffee n l ->
valid_coffee_combination n (exclude_incompatible_parameter_messages
(treat_emissions (combineN l) [slv1; mst1])).
Proof.
Admitted.
As expected, we need to prove that, provided that we have allowed
MakeCoffee actions, we can show that valid_coffee_combination
for combination of compatible synchronized actions.
Proving this lemma is a bit tricky as it involves several definitions.
Still, the main problem is that when doing induction on l,
we dont quite get something useful w.r.t the
allowed_actions_from_q1q1_coffee predicate...
Inductive all_the_same (X:Type) (e:X) : list X -> Prop :=
| AllEmpty: all_the_same e nil
| AllStep : forall h t l, l = h::t -> e=h -> all_the_same e t -> all_the_same e l.
As the name indicates, the all_the_same predicate defines
lists whose elements are all equal to the parameter e.
Below, we show a rather trivial fact that shall be useful at a later stage.
Lemma all_the_same_fact:
forall (X:Type) (e:X) l,
all_the_same e l ->
forall x, In x l ->
x=e.
Proof.
induction l; intros.
Case "1/2".
fromfalse.
Case "2/2".
destruct H0; subst.
SCase "1/2".
inversion H; subst.
inversion H0; subst; refl.
SCase "2/2".
apply IHl; auto.
inversion H; subst.
inversion H1; subst; auto.
Qed.
Lemma net_target_states_from_q1q1:
forall sv n,
In sv
[
<< "order:MakeSandwich", "MakeSandwich" >> -> "order:Sandwich";
<< "order:MakeCoffee", "MakeCoffee" >> -> "order:Coffee"] ->
(all_the_same (Net_State [slv0; mst0]) (get_list_snd
(net_target_states (MasterSlaveCoffeeNet n) (Net_State [slv1; mst1]) sv))).
Proof.
induction n; intros.
Case "1/2: Base case".
destruct H as [Hs | [Hc | Hf]]; try inversion Hf; subst; simpl;
(eapply AllStep; eauto; apply AllEmpty).
Case "2/2: Induction step".
unfold MasterSlaveCoffeeNet in *.
unfold net_target_states in *;
fold net_target_states in *.
destruct H as [Hs | [Hc | Hf]]; subst; try inversion Hf.
SCase "Sandwich order".
admit.
SCase "Coffee order".
pose (allowed_actions_from_sv_elements_coffee_fact (S n)) as Hf.
pose (combineN_coffee_orders_fact Hf) as Hf2.
Admitted.
The above lemma net_target_states_from_q1q1 attempts to show that
forall n, activating one of the synchronization vectors regarding
the order of one kind of coffee or a sandwich, the
Net_States that can be attained are all equal to Net_State slv0; mst0.
Establishing the subgoal for Sandwich orders should pose no special
issue, as there is no parameter involved. For the Coffer order however,
we need to use Hf2. From valid_coffee_combination we ought
to be able to derive that we always attain Net_State slv0; mst0.
Lemma not_attainable_q0q0_q0q1:
forall n, ~ attainable (MasterSlaveCoffeeNet n) [] (Net_State [slv0; mst0])
(Net_State [slv0; mst1]).
Proof.
intro. intro. inversion H; subst. clear H0.
inversion H1; subst.
unfold synch_vectors in H2.
destruct H2 as [Hr | Hr]; subst.
Case "1/2 : Synch. vector ready". Focus.
rewrite net_target_states_from_q0q0 in H4; auto.
destruct H4 as [Hq1 | Hf]; [subst | fromfalse].
inversion H5; subst. clear H0.
inversion H2; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | Hr]; subst.
rewrite net_target_states_from_q1q1' in H6; auto.
assert (all_the_same (Net_State [slv0; mst0]) (get_list_snd
(net_target_states (MasterSlaveCoffeeNet n)
(Net_State [slv1; mst1]) sv))) as Hy.
apply net_target_states_from_q1q1 with (sv:=sv) (n:=n); auto.
assert (qn = Net_State [slv0; mst0]) as Hs.
induction ((get_list_snd
(net_target_states (MasterSlaveCoffeeNet n)
(Net_State [slv1; mst1]) sv))); [fromfalse|..].
destruct H6.
SCase "Head case". Focus.
subst.
clear -Hy Case SCase.
inversion Hy; subst. inversion H; subst; auto.
SCase "Tail case".
apply IHl; auto.
inversion Hy. inversion H3; subst; auto.
inversion H7; subst.
discriminate H8.
apply H0. compute. auto.
Case "2/2 : Synch. vectors orders".
rewrite net_target_states_from_q0q0' in H4; auto.
Qed.
Lemma not_attainable_q0q0_q1q0:
forall n, ~ attainable (MasterSlaveCoffeeNet n) [] (Net_State [slv0; mst0])
(Net_State [slv1; mst0]).
Proof.
intro. intro. inversion H; subst. clear H0.
inversion H1; subst.
unfold synch_vectors in H2.
destruct H2 as [Hr | Hr]; subst.
Case "1/2 : Synch. vector ready". Focus.
rewrite net_target_states_from_q0q0 in H4; auto.
destruct H4 as [Hq1 | Hf]; [subst | fromfalse].
inversion H5; subst. clear H0.
inversion H2; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | Hr]; subst.
rewrite net_target_states_from_q1q1' in H6; auto.
assert (qn = Net_State [slv0; mst0]) as Hs.
pose (net_target_states_from_q1q1 n Hr ).
eapply all_the_same_fact; eauto.
subst.
inversion H7; subst.
clear - Case H0.
apply H0. compute. auto.
Case "2/2 : Synch. vectors orders".
rewrite net_target_states_from_q0q0' in H4; auto.
Qed.
The two above lemmas, not_attainable_q0q0_q1q0 and
not_attainable_q0q0_q0q1 simply show that we cannot attain these
Net_States.
Lemma from_q1q1_target_states:
forall n,
net_target_states (MasterSlaveCoffeeNet n) (Net_State [slv1; mst1])
(<< "order:MakeCoffee", "MakeCoffee" >> -> "order:Coffee") <> [].
Proof.
induction n. discriminate.
Admitted.
Lemma from_q0q0_target_states:
forall n,
net_target_states (MasterSlaveCoffeeNet n) (Net_State [slv0; mst0])
(<< "ready", "ready" >> -> "ready") <> [].
Proof.
induction n; [discriminate | idtac].
assert (
(get_list_snd
(net_target_states (MasterSlaveCoffeeNet (S n)) (Net_State [slv0; mst0]) (<< "ready", "ready" >> -> "ready"))) =
[Net_State [slv1; mst1]]) as Ha.
apply net_target_states_from_q0q0.
intro.
rewrite H in Ha.
simpl in Ha. congruence.
Qed.
The above two lemmas from_q1q1_target_states and from_q0q0_target_states
regard the fact that we necessarily reach Net_States, departing the the
specified Net_State and activating the indicated SV.
Proving this kind of lemma involving the orders of Coffee is more
complicated since it involves the parameter n.
Lemma net_target_states_fromq0q0_output:
forall n,
(net_target_states (MasterSlaveCoffeeNet n) (Net_State [slv0; mst0])
(<< "ready", "ready" >> -> "ready")) = ((Action (Message "ready" Emit nil) nil), Net_State [slv1; mst1]) :: nil.
Proof.
induction n; intros.
Case "1/2: Base case".
refl.
Case "2/2: Induction step".
rewrite <- IHn.
apply f_equal.
apply f_equal. refl.
Qed.
The above lemma, net_target_states_fromq0q0_output acts a simple rewrite rule that
we shall use below.
Lemma from_q0q0_target_states_interleaving:
forall ga q' n l, In (ga, q')
(net_target_states (MasterSlaveCoffeeNet n)
(Net_State [slv0; mst0]) (<< "ready", "ready" >> -> "ready")) ->
Net_Trace (MasterSlaveCoffeeNet n) q' l ->
interleaving Rma "ready" "order" (LCons ga l).
Proof.
intros.
rewrite net_target_states_fromq0q0_output in H.
destruct H as [Ha | Hf]; [inversion Ha; subst | fromfalse].
clear Ha.
inversion H0; subst.
Case "1/3 : pLTS trace".
discriminate.
Case "2/3 : pNet empty trace". Focus.
clear H3 H0.
inversion H1; subst. clear H1.
inversion H; subst. clear H.
assert (net_target_states (MasterSlaveCoffeeNet n) (Net_State [slv1; mst1])
(<< "order:MakeCoffee", "MakeCoffee" >> -> "order:Coffee") <> []) as Ha.
apply from_q1q1_target_states.
assert (False) as Hf.
apply Ha. apply H4. right. right. left; auto.
inversion Hf.
Case "3/3 : pNet LCons trace".
clear H3 H0.
Admitted.
Lemma from_q0q0_target_states_interleaving' sv:
forall n,
(sv = (<<"order:MakeSandwich", "MakeSandwich">> -> "order:Sandwich") \/
sv = (<<"order:MakeCoffee" , "MakeCoffee">> -> "order:Coffee" )) ->
(net_target_states (MasterSlaveCoffeeNet n)
(Net_State [slv0; mst0]) sv) = [].
Proof.
Admitted.
Lemma from_q1q1_target_states_interleaving:
forall ga q' n l, In (ga, q')
(net_target_states (MasterSlaveCoffeeNet n)
(Net_State [slv1; mst1]) (<< "ready", "ready" >> -> "ready")) ->
interleaving Rma "ready" "order" (LCons ga l).
Proof.
Admitted.
Lemma from_q1q1_target_states_interleaving' sv:
forall n,
(sv = (<<"order:MakeSandwich", "MakeSandwich">> -> "order:Sandwich") \/
sv = (<<"order:MakeCoffee" , "MakeCoffee">> -> "order:Coffee" )) ->
(net_target_states (MasterSlaveCoffeeNet n)
(Net_State [slv1; mst1]) sv) = [].
Proof.
Admitted.
The above four lemmas, from_q0q0_target_states_interleaving,
from_q0q0_target_states_interleaving', from_q1q1_target_states_interleaving and
from_q1q1_target_states_interleaving' serve as helpers for our main goal,
depicted below by theorem Infinite_ready_interleaving.
The function net_target_states returns values of type list (action * net_state),
symbolizing the resulting global action, and the respective attained state. Since,
one synchronization vector may trigger several actions among the constituents LTSs,
we need to return a list.
This may not be the best solution for easing proofs. Perhaps using different
data structures would facilitate proofs..
Below, directly or indirectly, we use the above lemmas to establish our main theorem.
Theorem Infinite_ready_interleaving:
forall n t q,
Net_Trace (MasterSlaveCoffeeNet n) q t ->
t |= (Always (interleaving Rma "ready" "order")).
Proof.
induction n;
cofix;
intros t q Ht.
Case "Base case".
inversion Ht.
SCase "1/3".
clear Ht.
discriminate H0.
SCase "2/3". Focus.
clear Ht.
inversion H; subst. clear H.
unfold synch_vectors in *.
inversion H1; [discriminate | subst].
inversion H0 ;subst. clear H0.
inversion H5; [discriminate | subst].
inversion H0; subst. clear H0.
inversion H7; [subst | discriminate].
clear H5 H7 H0 H1.
destruct H4 as [Hs0 | [Hs1 | Hf]]; subst; try inversion Hf;
destruct H6 as [Hm0 | [Hm1 | Hf']]; subst; try inversion Hf'.
SSCase "1/4 : Current state is attainable, but no valid synch. vectors".
absurd (net_target_states (MasterSlaveCoffeeNet 0) (Net_State [slv0; mst0])
(<< "ready", "ready" >> -> "ready") = []).
SSSCase "absurd: False case".
simpl; discriminate.
SSSCase "absurd: True case".
apply H3. left; auto.
SSCase "2/4: Current state is not attainable. Proof by contradiction". Focus.
clear -SSCase SCase Case H2.
simpl in H2.
inversion H2; subst.
inversion H0; subst. clear H0.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse. clear H2 H.
destruct H4; [subst| fromfalse].
inversion H5; subst. clear H H5.
inversion H0; subst.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SSCase SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SSCase SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
SSCase "3/4: Current state is not attainable. Proof by contradiction". Focus.
clear -SSCase SCase Case H2.
simpl in H2.
inversion H2; subst.
inversion H0; subst. clear H0.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse. clear H2 H.
destruct H4; [subst| fromfalse].
inversion H5; subst. clear H H5.
inversion H0; subst.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SSCase SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SSCase SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
SSCase "4/4: Current state is attainable, but no valid synch. vectors". Focus.
absurd (net_target_states (MasterSlaveCoffeeNet 0) (Net_State [slv1; mst1])
(<< "order:MakeSandwich", "MakeSandwich" >> -> "order:Sandwich") = []).
SSSCase "absurd: False case".
simpl; discriminate.
SSSCase "absurd: True case".
apply H3. right. left; auto.
SCase "3/3". Focus.
clear Ht. subst.
inversion H; subst. clear H.
inversion H1; [discriminate | subst]. clear H1.
inversion H0; subst. clear H0.
inversion H7; [discriminate | subst].
inversion H0; subst.
inversion H8; [subst | discriminate].
clear H0 H9 H8 H7.
simpl in H4; simpl in H1.
simpl in H2.
destruct H1 as [Hs0 | [Hs1 | Hf]]; subst; try inversion Hf;
destruct H4 as [Hm0 | [Hm1 | Hf']]; subst; try inversion Hf'.
SSCase "1/4 : Current state is attainable". Focus.
clear H2.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst;
try inversion Hf; compute in H5; inversion H5;
[ subst | fromfalse]. clear H5.
inversion H; subst. clear H.
apply Always_LCons.
SSSCase "1/2 : interleaving". Focus.
inversion H6; subst.
SSSSCase "1/3".
discriminate.
SSSSCase "2/3".
inversion H; subst.
unfold synch_vectors in *.
absurd (net_target_states (MasterSlaveCoffeeNet 0)
(Net_State [LTS_State 1 []; LTS_State 1 []])
(<< "order:MakeSandwich", "MakeSandwich" >> -> "order:Sandwich") = []).
SSSSSCase "absurd: False case".
simpl. discriminate.
SSSSSCase "absurd: True case".
apply H3. right. left. auto.
SSSSCase "3/3".
inversion H; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst; try inversion Hf;
simpl in H5; inversion H5; subst; try fromfalse;
inversion H3; subst.
SSSSSCase "1/2 : Synch. Vector order sandwich".
clear H3 H5.
apply InterleavingOne with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Sandwich" Emit []) []));
auto.
refl. simpl. left; auto.
SSSSSCase "2/2 : Synch. Vector order coffee".
apply InterleavingOne with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Coffee" Emit [Val 0]) [])).
refl. refl. simpl. right. refl.
SSSCase "2/2 : Recursion".
apply Infinite_ready_interleaving with
(q:=(Net_State [LTS_State 1 []; LTS_State 1 []])).
clear Infinite_ready_interleaving.
exact H6.
SSCase "2/4 : Current state is not attainable. Proof by contradiction".
clear -Case SCase SSCase H2.
inversion H2; subst.
inversion H0; subst. clear H0.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse. clear H2 H.
destruct H4; [subst| fromfalse].
inversion H5; subst. clear H H5.
inversion H0; subst.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SSCase SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SSCase SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
SSCase "3/4 : Current state is not attainable. Proof by contradiction".
clear -Case SCase SSCase H2.
inversion H2; subst.
inversion H0; subst. clear H0.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse. clear H2 H.
destruct H4; [subst| fromfalse].
inversion H5; subst. clear H H5.
inversion H0; subst.
unfold synch_vectors in H1.
destruct H1 as [Hr | [Hs | [Hc| Hf]]]; try inversion Hf; subst;
simpl in *; try fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SSCase SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
destruct H3; [subst | fromfalse].
clear H0. inversion H4. clear - SSCase SCase Case H.
assert (False).
apply H. compute. auto.
fromfalse.
SSCase "4/4 : Current state is attainable".
clear H2.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst;
[ compute in H5; inversion H5 | idtac | idtac | try inversion Hf].
SSSCase "1/2". Focus.
compute in H5; inversion H5; [subst | fromfalse].
clear H5.
inversion H; subst. clear H.
apply Always_LCons.
SSSSCase "1/2 : interleaving". Focus.
inversion H6; [discriminate | ..]; subst.
SSSSSCase "1/2". Focus.
inversion H; subst.
unfold synch_vectors in *.
absurd (net_target_states (MasterSlaveCoffeeNet 0)
(Net_State [LTS_State 0 []; LTS_State 0 []])
(<< "ready", "ready" >> -> "ready") = []).
SSSSSSCase "absurd: False case".
simpl. discriminate.
SSSSSSCase "absurd: True case".
apply H3. left. auto.
SSSSSCase "2/2".
inversion H; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst; try inversion Hf;
simpl in H5; inversion H5; subst; try fromfalse;
inversion H3; subst.
clear H3 H5.
apply InterleavingTwo with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Sandwich" Emit []) []));
auto.
refl. simpl. left; auto.
SSSSCase "2/2 : Recursion".
apply Infinite_ready_interleaving with
(q:=(Net_State [LTS_State 0 []; LTS_State 0 []])).
clear Infinite_ready_interleaving.
exact H6.
SSSCase "2/2". Focus.
compute in H5; inversion H5; [subst | fromfalse].
clear H5.
inversion H; subst. clear H.
apply Always_LCons.
SSSSCase "1/2 : interleaving". Focus.
inversion H6; [discriminate | ..]; subst.
SSSSSCase "1/2". Focus.
inversion H; subst.
unfold synch_vectors in *.
absurd (net_target_states (MasterSlaveCoffeeNet 0)
(Net_State [LTS_State 0 []; LTS_State 0 []])
(<< "ready", "ready" >> -> "ready") = []).
SSSSSSCase "absurd: False case".
simpl. discriminate.
SSSSSSCase "absurd: True case".
apply H3. left. auto.
SSSSSCase "2/2".
inversion H; subst.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst; try inversion Hf;
simpl in H5; inversion H5; subst; try fromfalse;
inversion H3; subst.
clear H3 H5.
apply InterleavingTwo with (l':=l0)
(a':=(Action (Message "ready" Emit []) []))
(b':=(Action (Message "order:Coffee" Emit [Val 0]) []));
auto.
refl. simpl. right; auto.
SSSSCase "2/2 : Recursion".
apply Infinite_ready_interleaving with
(q:=(Net_State [LTS_State 0 []; LTS_State 0 []])).
clear Infinite_ready_interleaving.
exact H6.
Case "2/2 : Induction step".
inversion Ht; subst.
SCase "1/3 : pLTS trace => proof by contradiction".
discriminate H0.
SCase "2/3 : pNet Empty trace => proof by contradiction". Focus.
inversion H; subst. clear H.
unfold synch_vectors in *.
inversion H1; [discriminate | subst].
inversion H0 ;subst. clear H0.
inversion H5; [discriminate | subst].
inversion H0; subst. clear H0.
inversion H7; [subst | discriminate].
clear H5 H7 H0 H1.
destruct H4 as [Hs0 | [Hs1 | Hf]]; subst; try inversion Hf;
destruct H6 as [Hm0 | [Hm1 | Hf']]; subst; try inversion Hf'.
SSCase "1/4 : Current state is attainable, but no valid synch. vectors". Focus.
absurd (net_target_states (MasterSlaveCoffeeNet (S n)) (Net_State [slv0; mst0])
(<< "ready", "ready" >> -> "ready") = []).
SSSCase "absurd: False case".
apply from_q0q0_target_states.
SSSCase "absurd: True case".
apply H3. left; auto.
SSCase "2/4: Current state is not attainable. Reductio ad absurdum". Focus.
clear -SSCase SCase Case H2.
absurd (attainable (MasterSlaveCoffeeNet (S n)) []
(init_net_state (MasterSlaveCoffeeNet (S n)))
(Net_State [slv0; mst1])); auto.
apply not_attainable_q0q0_q0q1.
SSCase "3/4: Current state is not attainable. Reductio ad absurdum". Focus.
clear -SSCase SCase Case H2.
absurd (attainable (MasterSlaveCoffeeNet (S n)) []
(init_net_state (MasterSlaveCoffeeNet (S n)))
(Net_State [slv1; mst0])); auto.
apply not_attainable_q0q0_q1q0.
SSCase "4/4 : Current state is attainable, but no valid synch. vectors".
clear H2.
absurd (net_target_states (MasterSlaveCoffeeNet (S n))
(Net_State [slv1; mst1])
(<< "order:MakeCoffee", "MakeCoffee" >> -> "order:Coffee") = []);
[idtac | apply H3; intuition].
apply from_q1q1_target_states.
SCase "3/3 : pNet LCons trace". Focus.
clear Ht.
inversion H; subst. clear H.
inversion H1; [discriminate | subst]. clear H1.
inversion H0; subst. clear H0.
inversion H7; [discriminate | subst].
inversion H0; subst.
inversion H8; [subst | discriminate].
clear H0 H9 H8 H7.
simpl in H4; simpl in H1.
simpl in H2.
destruct H1 as [Hs0 | [Hs1 | Hf]]; subst; try inversion Hf;
destruct H4 as [Hm0 | [Hm1 | Hf']]; subst; try inversion Hf'.
SSCase "1/4 : Current state is attainable". Focus.
clear H2.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst;
try inversion Hf.
SSSCase "1/3 : Synch. vector: ready". Focus.
apply Always_LCons;
[ idtac
| apply Infinite_ready_interleaving with (q:=q'); exact H6 ].
clear Infinite_ready_interleaving.
apply from_q0q0_target_states_interleaving with
(n:=S n) (q':=q'); auto.
SSSCase "2/3 : Synch. vector: makesandwich".
rewrite from_q0q0_target_states_interleaving' with
(sv:=(<< "order:MakeSandwich", "MakeSandwich" >> -> "order:Sandwich")) in H5.
fromfalse.
left. refl.
SSSCase "3/3 : Synch. vector: makeCoffee".
rewrite from_q0q0_target_states_interleaving' with
(sv:=(<< "order:MakeCoffee", "MakeCoffee" >> -> "order:Coffee")) in H5.
fromfalse.
right. refl.
SSCase "2/4 : Current state is not attainable".
clear - Case SCase SSCase H2.
apply not_attainable_q0q0_q1q0 in H2.
fromfalse.
SSCase "3/4 : Current state is not attainable".
clear - Case SCase SSCase H2.
apply not_attainable_q0q0_q0q1 in H2.
fromfalse.
SSCase "4/4 : Current state is attainable".
clear H2.
unfold synch_vectors in H3.
destruct H3 as [Hr | [Hs | [Hc | Hf]]]; subst;
try inversion Hf.
SSSCase "1/3 : Synch. vector: ready". Focus.
apply Always_LCons;
[ idtac
| apply Infinite_ready_interleaving with (q:=q'); exact H6 ].
clear Infinite_ready_interleaving.
apply from_q1q1_target_states_interleaving with
(n:=S n) (q':=q'); auto.
SSSCase "2/3 : Synch. vector: makesandwich".
rewrite from_q1q1_target_states_interleaving' with
(sv:=(<< "order:MakeSandwich", "MakeSandwich" >> -> "order:Sandwich")) in H5.
fromfalse.
left. refl.
SSSCase "3/3 : Synch. vector: makeCoffee".
rewrite from_q1q1_target_states_interleaving' with
(sv:=(<< "order:MakeCoffee", "MakeCoffee" >> -> "order:Coffee")) in H5.
fromfalse.
right. refl.
Qed.