Section LabeledStepExecution.
Variable A : Type.
Variable L : Type.
Variable trace : Type.
Definition lb_step_relation := A -> L -> A -> list trace -> Prop.
Definition lb_step_ex (step : lb_step_relation) (l : L) (a : A) : Prop :=
exists a' tr, step a l a' tr.
Record event := { evt_a : A ; evt_l : L ; evt_trace : list trace }.
Definition enabled (step : lb_step_relation) (l : L) (e : event) : Prop :=
lb_step_ex step l (evt_a e).
Definition occurred (l : L) (e : event) : Prop := l = evt_l e.
Definition inf_enabled (step : lb_step_relation) (l : L) (s : infseq event) : Prop :=
inf_often (now (enabled step l)) s.
Definition cont_enabled (step : lb_step_relation) (l : L) (s : infseq event) : Prop :=
continuously (now (enabled step l)) s.
Definition inf_occurred (l : L) (s : infseq event) : Prop :=
inf_often (now (occurred l)) s.
Definition strong_fairness (step : lb_step_relation) (silent : L) (s : infseq event) : Prop :=
forall l : L, l <> silent -> inf_enabled step l s -> inf_occurred l s.
Definition weak_fairness (step : lb_step_relation) (silent : L) (s : infseq event) : Prop :=
forall l : L, l <> silent -> cont_enabled step l s -> inf_occurred l s.
Proof using.
unfold strong_fairness. unfold inf_enabled, inf_occurred, inf_often.
intros step e silent s fair l neq alev.
assert (alevt_es: always (eventually (now (enabled step l))) (Cons e s)).
constructor.
constructor 2. destruct alev; assumption.
simpl. assumption.
clear alev. generalize (fair l neq alevt_es); clear fair alevt_es.
intro fair; case (always_Cons fair); trivial.
Qed.
Proof using.
move => step silent.
rewrite /extensional /strong_fairness /inf_enabled /inf_occurred /=.
move => s1 s2 H_eq H_s1 l' H_neq' H_en.
have H_s1l := H_s1 l'.
move: H_s1l.
set s1i := inf_often (now (occurred _)) s1.
move => H_s1l.
suff H_suff: s1i.
move: H_suff.
apply extensional_inf_often => //.
exact: extensional_now.
apply: H_s1l => {s1i}; first by [].
move: H_en.
apply: extensional_inf_often; last exact: exteq_sym.
exact: extensional_now.
Qed.
Proof using.
unfold weak_fairness. unfold cont_enabled, inf_occurred, continuously, inf_often.
intros step e silent s fair a neq eval.
assert (eval_es: eventually (always (now (enabled step a))) (Cons e s)).
apply E_next. assumption.
apply fair in eval_es.
apply always_invar in eval_es.
assumption.
assumption.
Qed.
Proof using.
move => step silent.
rewrite /extensional /weak_fairness /cont_enabled /inf_occurred /=.
move => s1 s2 H_eq H_s1 l' H_neq' H_en.
have H_s1l := H_s1 l'.
move: H_s1l.
set s1i := inf_often (now (occurred _)) s1.
move => H_s1l.
suff H_suff: s1i.
move: H_suff.
apply extensional_inf_often => //.
exact: extensional_now.
apply: H_s1l => {s1i}; first by [].
move: H_en.
apply: extensional_continuously; last exact: exteq_sym.
exact: extensional_now.
Qed.
Proof using.
move => step silent.
case => e s.
rewrite /strong_fairness /weak_fairness /inf_enabled /cont_enabled.
move => H_str l neq H_cont.
apply: H_str; first by [].
exact: continuously_inf_often.
Qed.
CoInductive lb_step_execution (step : lb_step_relation) : infseq event -> Prop :=
Cons_lb_step_exec : forall (e e' : event) (tr : list trace) (s : infseq event),
step (evt_a e) (evt_l e) (evt_a e') tr ->
evt_trace e' = evt_trace e ++ tr ->
lb_step_execution step (Cons e' s) ->
lb_step_execution step (Cons e (Cons e' s)).
Proof using.
intros step x s e. change (lb_step_execution step (tl (Cons x s))).
destruct e; simpl. assumption.
Qed.

Lemma lb_step_execution_extensional :
forall step, extensional (lb_step_execution step).