(* Specifications: *)
Lemma strong_induction {P: nat -> Prop}:
(forall n, (forall m, m < n -> P m) -> P n) ->
(forall n, P n).
Lemma prop_ext: prop_extensionality.
Lemma fin_subset_match {A B: Type} {P: A -> B -> Prop}: forall (X: Ensemble A) (Y: Ensemble B),
(forall x, X x -> exists y, P x y /\ Y y) ->
forall xs, Forall (fun x => X x) xs -> exists ys, Forall2 P xs ys /\ Forall (fun y => Y y) ys.
Lemma Forall2_lr_rev {A B: Type} {P: A -> B -> Prop}: forall xs ys,
Forall2 (fun y x => P x y) ys xs ->
Forall2 P xs ys.
(* This one copy from RamifyCoq *)
Lemma Forall_app_iff: forall {A : Type} (P : A -> Prop) (l1 l2 : list A), Forall P (l1 ++ l2) <-> Forall P l1 /\ Forall P l2.
Inductive remove_rel {A: Type}: A -> list A -> list A -> Prop :=
| remove_rel_nil: forall a, remove_rel a nil nil
| remove_rel_cons_eq: forall a xs ys, remove_rel a xs ys -> remove_rel a (a :: xs) ys
| remove_rel_cons_neq: forall a b xs ys, a <> b -> remove_rel a xs ys -> remove_rel a (b :: xs) (b :: ys).
Lemma remove_rel_In: forall (A : Type) (l1 l2 : list A) (x : A), remove_rel x l1 l2 -> ~ In x l2.
Lemma remove_rel_exist: forall (A : Type) (l1 : list A) (x : A) (DEC: forall y, x = y \/ x <> y), exists l2, remove_rel x l1 l2.
Lemma remove_rel_result_belong: forall (A : Type) (l1 l2 : list A) (x : A), remove_rel x l1 l2 -> Forall (fun y => In y l1) l2.
Definition isSome {A} (o: option A) := match o with Some _ => True | None => False end.
(* These three lemmas are copied from veric/assert_lemmas.v and veric/initial_world.v *)
Lemma nth_error_in_bounds: forall {A} (l: list A) i, (O <= i < length l)%nat
-> exists x, nth_error l i = value x.
Lemma nth_error_app: forall {T} (al bl : list T) (j: nat),
nth_error (al++bl) (length al + j) = nth_error bl j.
Lemma nth_error_app1: forall {T} (al bl : list T) (j: nat),
(j < length al)%nat ->
nth_error (al++bl) j = nth_error al j.
Lemma nth_error_None_iff: forall {A} (l: list A) n, nth_error l n = None <-> n >= length l.
Lemma Forall_rev: forall {A} (P: A -> Prop) (l: list A), Forall P (rev l) <-> Forall P l.
Lemma cut2_exists {A: Type}: forall (h: stream A) (P: A -> Prop),
(exists h1 h2,
is_fin_stream h1 /\
h = stream_app h1 h2 /\
(forall n a, h1 n = Some a -> ~ P a) /\
(exists a, h2 0 = Some a /\ P a)) \/
(forall n a, h n = Some a -> ~ P a).
Lemma cut_omega_exists {A: Type}: forall (h: stream A) (P: A -> Prop),
(exists a, h 0 = Some a /\ P a) ->
(exists hs,
(forall n, is_fin_stream (hs n)) /\
h = stream_capp hs /\
(forall m n a, hs m (S n) = Some a -> ~ P a) /\
(forall n, exists a, hs n 0 = Some a /\ P a)) \/
(exists hs: list (stream A),
(Forall is_fin_stream hs) /\
h = fold_right stream_app empty_stream hs /\
(Forall (fun h0: stream A => forall n a, h0 (S n) = Some a -> ~ P a) hs) /\
(Forall (fun h0: stream A => exists a, h0 0 = Some a /\ P a) hs)).