Axiom jointo_swapped :
  forall {A} {m1 m2 : A -> map} (Adec:forall x y:A,{x=y}+{x<>y})
    i j Phi e a b a' b',
    swapped m1 m2 i j a b a' b' ->
    join a b e ->
    join a' b' e ->
    jointo m1 Phi ->
    jointo m2 Phi.(*+ Definition of safety *)

(* We define safety based on specification of externals (acquire and
release) *)

(* no need for an oracle, so it is unit *)
Definition Z := unit.Record ext : Type := mkext {
    ext_type : Type;
    Pre : ext_type -> Z -> map -> Prop;
    Post : ext_type -> Z -> map -> Prop
  }.Record ext : Type := mkext {
    ext_type : Type;
    Pre : ext_type -> Z -> map -> Prop;
    Post : ext_type -> Z -> map -> Prop
  }.Record ext : Type := mkext {
    ext_type : Type;
    Pre : ext_type -> Z -> map -> Prop;
    Post : ext_type -> Z -> map -> Prop
  }.Record ext : Type := mkext {
    ext_type : Type;
    Pre : ext_type -> Z -> map -> Prop;
    Post : ext_type -> Z -> map -> Prop
  }.Record ext : Type := mkext {
    ext_type : Type;
    Pre : ext_type -> Z -> map -> Prop;
    Post : ext_type -> Z -> map -> Prop
  }.Definition after_external : C -> option C :=
  fun c =>
    match c with
    | acquire _ k => Some k
    | release _ k => Some k
    | _ => None
    end.Axiom join_Hrel1 : forall m1 m2 m3 n, join m1 m2 m3 -> Hrel n m3 m1.Axiom join_Hrel2 : forall m1 m2 m3 n, join m1 m2 m3 -> Hrel n m1 m3.Inductive safeN_ (at_ext : C -> option ext) : nat -> Z -> C -> map -> Prop :=
    safeN_0 : forall (z : Z) (c : C) (m : map), safeN_ at_ext 0 z c m
  | safeN_step : forall (n : nat) (z : Z) (c c' : C') (m m' : map),
      corestep c m c' m' ->
      safeN_ at_ext n z (normal c') m' ->
      safeN_ at_ext (S n) z (normal c) m
  | safeN_external : forall (n : nat) (z : Z) (c : C) (m : map) (e : ext) (x : ext_type e),
      at_ext c = Some e ->
      Pre e x z m ->
      (forall (m' : map) (z' : Z) (n' : nat),
          n' <= n ->
          Hrel n' m m' ->
          Post e x z' m' ->
          exists c' : C,
            after_external c = Some c' /\
            safeN_ at_ext n' z' c' m') ->
      safeN_ at_ext (S n) z c m.Inductive safeN_ (at_ext : C -> option ext) : nat -> Z -> C -> map -> Prop :=
    safeN_0 : forall (z : Z) (c : C) (m : map), safeN_ at_ext 0 z c m
  | safeN_step : forall (n : nat) (z : Z) (c c' : C') (m m' : map),
      corestep c m c' m' ->
      safeN_ at_ext n z (normal c') m' ->
      safeN_ at_ext (S n) z (normal c) m
  | safeN_external : forall (n : nat) (z : Z) (c : C) (m : map) (e : ext) (x : ext_type e),
      at_ext c = Some e ->
      Pre e x z m ->
      (forall (m' : map) (z' : Z) (n' : nat),
          n' <= n ->
          Hrel n' m m' ->
          Post e x z' m' ->
          exists c' : C,
            after_external c = Some c' /\
            safeN_ at_ext n' z' c' m') ->
      safeN_ at_ext (S n) z c m.Inductive safeN_ (at_ext : C -> option ext) : nat -> Z -> C -> map -> Prop :=
    safeN_0 : forall (z : Z) (c : C) (m : map), safeN_ at_ext 0 z c m
  | safeN_step : forall (n : nat) (z : Z) (c c' : C') (m m' : map),
      corestep c m c' m' ->
      safeN_ at_ext n z (normal c') m' ->
      safeN_ at_ext (S n) z (normal c) m
  | safeN_external : forall (n : nat) (z : Z) (c : C) (m : map) (e : ext) (x : ext_type e),
      at_ext c = Some e ->
      Pre e x z m ->
      (forall (m' : map) (z' : Z) (n' : nat),
          n' <= n ->
          Hrel n' m m' ->
          Post e x z' m' ->
          exists c' : C,
            after_external c = Some c' /\
            safeN_ at_ext n' z' c' m') ->
      safeN_ at_ext (S n) z c m.Inductive safeN_ (at_ext : C -> option ext) : nat -> Z -> C -> map -> Prop :=
    safeN_0 : forall (z : Z) (c : C) (m : map), safeN_ at_ext 0 z c m
  | safeN_step : forall (n : nat) (z : Z) (c c' : C') (m m' : map),
      corestep c m c' m' ->
      safeN_ at_ext n z (normal c') m' ->
      safeN_ at_ext (S n) z (normal c) m
  | safeN_external : forall (n : nat) (z : Z) (c : C) (m : map) (e : ext) (x : ext_type e),
      at_ext c = Some e ->
      Pre e x z m ->
      (forall (m' : map) (z' : Z) (n' : nat),
          n' <= n ->
          Hrel n' m m' ->
          Post e x z' m' ->
          exists c' : C,
            after_external c = Some c' /\
            safeN_ at_ext n' z' c' m') ->
      safeN_ at_ext (S n) z c m.

Lemma strong_nat_ind (P : nat -> Prop) (IH : forall n, (forall i, i < n -> P i) -> P n) n : P n.