Inductive res_join' : resource -> resource -> resource -> Type :=
    res_join'_NO1 : forall (sh1 sh2 sh3 : Share.t) nsh1 nsh2 nsh3,
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (NO sh2 nsh2) (NO sh3 nsh3)
  | res_join'_NO2 : forall (sh1 sh2 sh3 : Share.t) rsh1 nsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (NO sh2 nsh2) (YES sh3 rsh3 k p)
  | res_join'_NO3 : forall (sh1 sh2 sh3 : Share.t) nsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_YES : forall (sh1 sh2 sh3 : Share.t) rsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_PURE : forall (k : AV.kind) (p : preds),
                    res_join' (PURE k p) (PURE k p) (PURE k p).Inductive res_join' : resource -> resource -> resource -> Type :=
    res_join'_NO1 : forall (sh1 sh2 sh3 : Share.t) nsh1 nsh2 nsh3,
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (NO sh2 nsh2) (NO sh3 nsh3)
  | res_join'_NO2 : forall (sh1 sh2 sh3 : Share.t) rsh1 nsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (NO sh2 nsh2) (YES sh3 rsh3 k p)
  | res_join'_NO3 : forall (sh1 sh2 sh3 : Share.t) nsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_YES : forall (sh1 sh2 sh3 : Share.t) rsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_PURE : forall (k : AV.kind) (p : preds),
                    res_join' (PURE k p) (PURE k p) (PURE k p).Inductive res_join' : resource -> resource -> resource -> Type :=
    res_join'_NO1 : forall (sh1 sh2 sh3 : Share.t) nsh1 nsh2 nsh3,
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (NO sh2 nsh2) (NO sh3 nsh3)
  | res_join'_NO2 : forall (sh1 sh2 sh3 : Share.t) rsh1 nsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (NO sh2 nsh2) (YES sh3 rsh3 k p)
  | res_join'_NO3 : forall (sh1 sh2 sh3 : Share.t) nsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_YES : forall (sh1 sh2 sh3 : Share.t) rsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_PURE : forall (k : AV.kind) (p : preds),
                    res_join' (PURE k p) (PURE k p) (PURE k p).Inductive res_join' : resource -> resource -> resource -> Type :=
    res_join'_NO1 : forall (sh1 sh2 sh3 : Share.t) nsh1 nsh2 nsh3,
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (NO sh2 nsh2) (NO sh3 nsh3)
  | res_join'_NO2 : forall (sh1 sh2 sh3 : Share.t) rsh1 nsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (NO sh2 nsh2) (YES sh3 rsh3 k p)
  | res_join'_NO3 : forall (sh1 sh2 sh3 : Share.t) nsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_YES : forall (sh1 sh2 sh3 : Share.t) rsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_PURE : forall (k : AV.kind) (p : preds),
                    res_join' (PURE k p) (PURE k p) (PURE k p).Inductive res_join' : resource -> resource -> resource -> Type :=
    res_join'_NO1 : forall (sh1 sh2 sh3 : Share.t) nsh1 nsh2 nsh3,
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (NO sh2 nsh2) (NO sh3 nsh3)
  | res_join'_NO2 : forall (sh1 sh2 sh3 : Share.t) rsh1 nsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (NO sh2 nsh2) (YES sh3 rsh3 k p)
  | res_join'_NO3 : forall (sh1 sh2 sh3 : Share.t) nsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_YES : forall (sh1 sh2 sh3 : Share.t) rsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_PURE : forall (k : AV.kind) (p : preds),
                    res_join' (PURE k p) (PURE k p) (PURE k p).Inductive res_join' : resource -> resource -> resource -> Type :=
    res_join'_NO1 : forall (sh1 sh2 sh3 : Share.t) nsh1 nsh2 nsh3,
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (NO sh2 nsh2) (NO sh3 nsh3)
  | res_join'_NO2 : forall (sh1 sh2 sh3 : Share.t) rsh1 nsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (NO sh2 nsh2) (YES sh3 rsh3 k p)
  | res_join'_NO3 : forall (sh1 sh2 sh3 : Share.t) nsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (NO sh1 nsh1) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_YES : forall (sh1 sh2 sh3 : Share.t) rsh1 rsh2 rsh3
                     (k : AV.kind) (p : preds),
                   sepalg.join sh1 sh2 sh3 ->
                   res_join' (YES sh1 rsh1 k p) (YES sh2 rsh2 k p) (YES sh3 rsh3 k p)
  | res_join'_PURE : forall (k : AV.kind) (p : preds),
                    res_join' (PURE k p) (PURE k p) (PURE k p).

(* Specifications: *)
Lemma res_join'_spec r1 r2 r3 : res_join r1 r2 r3 -> res_join' r1 r2 r3.
Lemma res_join'_spec_inv r1 r2 r3 : res_join' r1 r2 r3 -> res_join r1 r2 r3.
Lemma resource_decay_at_LK {nextb n r1 r2 b sh n' i} : resource_decay_at nextb n r1 r2 b -> res_option r1 = Some (sh, LK n' i) <-> res_option r2 = Some (sh, LK n' i).
Lemma resource_decay_join b phi1 phi1' phi2 phi3 : rmap_bound b phi2 -> resource_decay b phi1 phi1' -> ghost_of phi1' = own.ghost_approx phi1' (ghost_of phi1) -> sepalg.join phi1 phi2 phi3 -> exists phi3', sepalg.join phi1' (age_to (level phi1') phi2) phi3' /\ resource_decay b phi3 phi3' /\ ghost_of phi3' = own.ghost_approx phi3' (ghost_of phi3).