(** The general form of a backward simulation. *)
Record bsim_properties (L1 L2: semantics) (index: Type)
(order: index -> index -> Prop)
(match_states: index -> state L1 -> state L2 -> Prop) : Prop := {
bsim_order_wf: well_founded order;
bsim_start_stacks_exist:
forall s1 f arg m0, start_stack L1 m0 s1 f arg ->
exists s2, start_stack L2 m0 s2 f arg;
bsim_initial_states_exist:
forall s1, initial_state L1 s1 ->
exists s2, initial_state L2 s2;
bsim_match_start_stacks:
forall s1 s2 f arg m0, start_stack L1 m0 s1 f arg  ->
start_stack L2 m0 s2 f arg  ->
exists i, exists s1', start_stack L1 m0 s1' f arg /\ match_states i s1' s2;
bsim_match_initial_states:
forall s1 s2, initial_state L1 s1  ->
initial_state L2 s2  ->
exists i, exists s1', initial_state L1 s1' /\ match_states i s1' s2;
bsim_match_final_states:
forall i s1 s2 r,
match_states i s1 s2 -> safe L1 s1 -> final_state L2 s2 r ->
exists s1', Star L1 s1 E0 s1' /\ final_state L1 s1' r;
bsim_progress:
forall i s1 s2,
match_states i s1 s2 -> safe L1 s1 ->
(exists r, final_state L2 s2 r) \/
(exists t, exists s2', Step L2 s2 t s2');
bsim_simulation:
forall s2 t s2', Step L2 s2 t s2' ->
forall i s1, match_states i s1 s2 -> safe L1 s1 ->
exists i', exists s1',
(Plus L1 s1 t s1' \/ (Star L1 s1 t s1' /\ order i' i))
/\ match_states i' s1' s2';
bsim_public_preserved:
forall id, Senv.public_symbol (symbolenv L2) id = Senv.public_symbol (symbolenv L1) id
}.
Arguments bsim_properties: clear implicits.
Inductive backward_simulation (L1 L2: semantics) : Prop :=
Backward_simulation (index: Type)
(order: index -> index -> Prop)
(match_states: index -> state L1 -> state L2 -> Prop)
(props: bsim_properties L1 L2 index order match_states).
Arguments Backward_simulation {L1 L2 index} order match_states props.
(** An alternate form of the simulation diagram *)

Lemma bsim_simulation':
forall L1 L2 index order match_states, bsim_properties L1 L2 index order match_states ->
forall i s2 t s2', Step L2 s2 t s2' ->
forall s1, match_states i s1 s2 -> safe L1 s1 ->
(exists i', exists s1', Plus L1 s1 t s1' /\ match_states i' s1' s2')
\/ (exists i', order i' i /\ t = E0 /\ match_states i' s1 s2').