(** * Definition and properties of deterministic semantics *)

Record sem_deterministic (L: semantics) := mk_deterministic {
  det_step: forall s0 t1 s1 t2 s2,
    Step L s0 t1 s1 -> Step L s0 t2 s2 -> s1 = s2 /\ t1 = t2;
  det_initial_state: forall s1 s2,
    initial_state L s1 -> initial_state L s2 -> s1 = s2;
  det_final_state: forall s r1 r2,
    final_state L s r1 -> final_state L s r2 -> r1 = r2;
  det_final_nostep: forall s r,
    final_state L s r -> Nostep L s
}.(** * Definition and properties of deterministic semantics *)

Record sem_deterministic (L: semantics) := mk_deterministic {
  det_step: forall s0 t1 s1 t2 s2,
    Step L s0 t1 s1 -> Step L s0 t2 s2 -> s1 = s2 /\ t1 = t2;
  det_initial_state: forall s1 s2,
    initial_state L s1 -> initial_state L s2 -> s1 = s2;
  det_final_state: forall s r1 r2,
    final_state L s r1 -> final_state L s r2 -> r1 = r2;
  det_final_nostep: forall s r,
    final_state L s r -> Nostep L s
}.(** * Definition and properties of deterministic semantics *)

Record sem_deterministic (L: semantics) := mk_deterministic {
  det_step: forall s0 t1 s1 t2 s2,
    Step L s0 t1 s1 -> Step L s0 t2 s2 -> s1 = s2 /\ t1 = t2;
  det_initial_state: forall s1 s2,
    initial_state L s1 -> initial_state L s2 -> s1 = s2;
  det_final_state: forall s r1 r2,
    final_state L s r1 -> final_state L s r2 -> r1 = r2;
  det_final_nostep: forall s r,
    final_state L s r -> Nostep L s
}.(** * Definition and properties of deterministic semantics *)

Record sem_deterministic (L: semantics) := mk_deterministic {
  det_step: forall s0 t1 s1 t2 s2,
    Step L s0 t1 s1 -> Step L s0 t2 s2 -> s1 = s2 /\ t1 = t2;
  det_initial_state: forall s1 s2,
    initial_state L s1 -> initial_state L s2 -> s1 = s2;
  det_final_state: forall s r1 r2,
    final_state L s r1 -> final_state L s r2 -> r1 = r2;
  det_final_nostep: forall s r,
    final_state L s r -> Nostep L s
}.(** * Definition and properties of deterministic semantics *)

Record sem_deterministic (L: semantics) := mk_deterministic {
  det_step: forall s0 t1 s1 t2 s2,
    Step L s0 t1 s1 -> Step L s0 t2 s2 -> s1 = s2 /\ t1 = t2;
  det_initial_state: forall s1 s2,
    initial_state L s1 -> initial_state L s2 -> s1 = s2;
  det_final_state: forall s r1 r2,
    final_state L s r1 -> final_state L s r2 -> r1 = r2;
  det_final_nostep: forall s r,
    final_state L s r -> Nostep L s
}.(** * Definition and properties of deterministic semantics *)

Record sem_deterministic (L: semantics) := mk_deterministic {
  det_step: forall s0 t1 s1 t2 s2,
    Step L s0 t1 s1 -> Step L s0 t2 s2 -> s1 = s2 /\ t1 = t2;
  det_initial_state: forall s1 s2,
    initial_state L s1 -> initial_state L s2 -> s1 = s2;
  det_final_state: forall s r1 r2,
    final_state L s r1 -> final_state L s r2 -> r1 = r2;
  det_final_nostep: forall s r,
    final_state L s r -> Nostep L s
}.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.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.

(* Specifications: *)
Lemma steps_deterministic: forall s0 t1 s1 t2 s2, Star L s0 t1 s1 -> Star L s0 t2 s2 -> Nostep L s1 -> Nostep L s2 -> t1 = t2 /\ s1 = s2.
Lemma terminates_not_goes_wrong: forall s t1 s1 r t2 s2, Star L s t1 s1 -> final_state L s1 r -> Star L s t2 s2 -> Nostep L s2 -> (forall r, ~final_state L s2 r) -> False.
Lemma star_final_not_forever_silent: forall s t s', Star L s t s' -> Nostep L s' -> Forever_silent L s -> False.
Lemma star2_final_not_forever_silent: forall s t1 s1 t2 s2, Star L s t1 s1 -> Nostep L s1 -> Star L s t2 s2 -> Forever_silent L s2 -> False.
Lemma star_final_not_forever_reactive: forall s t s', Star L s t s' -> forall T, Nostep L s' -> Forever_reactive L s T -> False.
Lemma star_forever_silent_inv: forall s t s', Star L s t s' -> Forever_silent L s -> t = E0 /\ Forever_silent L s'.
Lemma forever_silent_reactive_exclusive: forall s T, Forever_silent L s -> Forever_reactive L s T -> False.
Lemma forever_reactive_determ': forall s T1 T2, Forever_reactive L s T1 -> Forever_reactive L s T2 -> traceinf_sim' T1 T2.
Lemma forever_reactive_determ: forall s T1 T2, Forever_reactive L s T1 -> Forever_reactive L s T2 -> traceinf_sim T1 T2.
Lemma forever_silent_reactive_exclusive2: forall s t s' T, Star L s t s' -> Forever_silent L s' -> Forever_reactive L s T -> False.