Section DETERM_SEM.
Variable L: semantics.
Hypothesis DET: sem_deterministic L.
Ltac use_step_deterministic :=
match goal with
| [ S1: Step ?L _ ?t1 _, S2: Step ?L _ ?t2 _ |- _ ] =>
destruct (det_step _ DET _ _ _ _ _ S1 S2) as [EQ1 EQ2]; subst
end.
(** Determinism for finite transition sequences. *)
Ltac use_star_step_diamond :=
match goal with
| [ S1: Star ?L _ ?t1 _, S2: Star ?L _ ?t2 _ |- _ ] =>
let t := fresh "t" in let P := fresh "P" in let EQ := fresh "EQ" in
destruct (star_step_diamond _ _ _ S1 _ _ S2)
as [t [ [P EQ] | [P EQ] ]]; subst
end.
Ltac use_nostep :=
match goal with
| [ S: Step ?L ?s _ _, NO: Nostep ?L ?s |- _ ] => elim (NO _ _ S)
end.
Ltac use_star_step_triangle :=
match goal with
| [ S1: Star ?L _ ?t1 _, S2: Star ?L _ ?t2 ?s2, NO: Nostep ?L ?s2 |- _ ] =>
let t := fresh "t" in let P := fresh "P" in let EQ := fresh "EQ" in
destruct (star_step_triangle _ _ _ _ _ S1 S2 NO)
as [t [P EQ]]; subst
end.
(** Determinism for infinite transition sequences. *)
(** Determinism for program executions *)
Definition same_behaviors (beh1 beh2: program_behavior) : Prop :=
match beh1, beh2 with
| Terminates t1 r1, Terminates t2 r2 => t1 = t2 /\ r1 = r2
| Diverges t1, Diverges t2 => t1 = t2
| Reacts t1, Reacts t2 => traceinf_sim t1 t2
| Goes_wrong t1, Goes_wrong t2 => t1 = t2
| _, _ => False
end.

Theorem program_behaves_deterministic:
forall beh1 beh2,
program_behaves L beh1 -> program_behaves L beh2 ->
same_behaviors beh1 beh2.