Definition dummy {X Y} (P : X -> Prop) (Q : Y -> Prop) : X -> Y -> Prop :=
  fun x y => P x /\ Q y.

(* Specifications: *)
Lemma poram_lift2_strengthen_pre {X Y} (Pre Pre' Post : state -> state -> Prop) (P : X -> Y -> Prop) (m : Poram X) (m' : Poram Y) : (forall s s', Pre' s s' -> Pre s s') -> poram_lift2 Pre Post P m m' -> poram_lift2 Pre' Post P m m'.
Lemma plift2_conj {X X' Y Y'} (P : X -> Y -> Prop) (Q : X' -> Y' -> Prop) (dx : dist (X * X')) (dy : dist (Y * Y')) : plift2 (fun p p' => P (fst p) (fst p')) dx dy -> plift2 (fun p p' => Q (snd p) (snd p')) dx dy -> plift2 (prod_rel P Q) dx dy.
Lemma plift2_triv {X Y} (dx : dist X) (dy : dist Y) (P : X -> Y -> Prop) : (forall x y, P x y) -> plift2 P dx dy.
Lemma poram_split_dummy {X Y} (Pre Pre' Post Post' : state -> Prop) (m : Poram X) (m' : Poram Y) : poram_lift Pre Post triv m -> poram_lift Pre' Post' triv m' -> poram_lift2 (dummy Pre Pre') (dummy Post Post') triv2 m m'.
Lemma plift2_and {X Y} {P Q : X -> Y -> Prop} (m : dist X) (m' : dist Y) : plift2 P m m' -> plift2 Q m m' -> plift2 (fun x y => P x y /\ Q x y) m m'.
Lemma plift_to_plift2_l {X Y} (P : X -> Prop) (m : dist X) (m' : dist Y) : plift P m -> plift2 (fun x _ => P x) m m'.
Lemma plift_to_plift2_r {X Y} (Q : Y -> Prop) (m : dist X) (m' : dist Y) : plift Q m' -> plift2 (fun _ y => Q y) m m'.
Lemma plift2_split_eq {X Y Z} (f : X -> Z) (g : Y -> Z) (z : Z) (m : dist X) (m' : dist Y) : plift (fun x => f x = z) m -> plift (fun y => g y = z) m' -> plift2 (fun x y => f x = g y) m m'.
Lemma poram_lift2_kv_stable {X Y} (m : Poram X) (m' : Poram Y) : kv_stable m -> kv_stable m' -> poram_lift2 state_equiv state_equiv triv2 m m'.
Lemma get_state_val_Some_kv_rel k v s : well_formed s -> get_state_val k s = Some v -> kv_rel k v s.
Lemma get_state_val_None_kv_rel k s : well_formed s -> get_state_val k s = None -> kv_rel k 0 s.
Lemma poram_lift2_strengthen_pre {X Y} (Pre Pre' Post : state -> state -> Prop) (P : X -> Y -> Prop) (m : Poram X) (m' : Poram Y) : (forall s s', Pre' s s' -> Pre s s') -> poram_lift2 Pre Post P m m' -> poram_lift2 Pre' Post P m m'.
Lemma plift2_conj {X X' Y Y'} (P : X -> Y -> Prop) (Q : X' -> Y' -> Prop) (dx : dist (X * X')) (dy : dist (Y * Y')) : plift2 (fun p p' => P (fst p) (fst p')) dx dy -> plift2 (fun p p' => Q (snd p) (snd p')) dx dy -> plift2 (prod_rel P Q) dx dy.
Lemma plift2_triv {X Y} (dx : dist X) (dy : dist Y) (P : X -> Y -> Prop) : (forall x y, P x y) -> plift2 P dx dy.
Lemma poram_split_dummy {X Y} (Pre Pre' Post Post' : state -> Prop) (m : Poram X) (m' : Poram Y) : poram_lift Pre Post triv m -> poram_lift Pre' Post' triv m' -> poram_lift2 (dummy Pre Pre') (dummy Post Post') triv2 m m'.
Lemma plift2_and {X Y} {P Q : X -> Y -> Prop} (m : dist X) (m' : dist Y) : plift2 P m m' -> plift2 Q m m' -> plift2 (fun x y => P x y /\ Q x y) m m'.
Lemma plift_to_plift2_l {X Y} (P : X -> Prop) (m : dist X) (m' : dist Y) : plift P m -> plift2 (fun x _ => P x) m m'.
Lemma plift_to_plift2_r {X Y} (Q : Y -> Prop) (m : dist X) (m' : dist Y) : plift Q m' -> plift2 (fun _ y => Q y) m m'.
Lemma plift2_split_eq {X Y Z} (f : X -> Z) (g : Y -> Z) (z : Z) (m : dist X) (m' : dist Y) : plift (fun x => f x = z) m -> plift (fun y => g y = z) m' -> plift2 (fun x y => f x = g y) m m'.
Lemma poram_lift2_kv_stable {X Y} (m : Poram X) (m' : Poram Y) : kv_stable m -> kv_stable m' -> poram_lift2 state_equiv state_equiv triv2 m m'.
Lemma get_state_val_Some_kv_rel k v s : well_formed s -> get_state_val k s = Some v -> kv_rel k v s.
Lemma get_state_val_None_kv_rel k s : well_formed s -> get_state_val k s = None -> kv_rel k 0 s.