Notation NoDup := (NoDupA E.eq).Notation InA := (InA E.eq).

(* Specifications: *)
Theorem fold_rec : forall (A:Type)(P : t -> A -> Type)(f : elt -> A -> A)(i:A)(s:t), (forall s', Empty s' -> P s' i) -> (forall x a s' s'', In x s -> ~In x s' -> Add x s' s'' -> P s' a -> P s'' (f x a)) -> P s (fold f s i).
Theorem fold_rec_bis : forall (A:Type)(P : t -> A -> Type)(f : elt -> A -> A)(i:A)(s:t), (forall s s' a, s[=]s' -> P s a -> P s' a) -> (P empty i) -> (forall x a s', In x s -> ~In x s' -> P s' a -> P (add x s') (f x a)) -> P s (fold f s i).
Lemma fold_rec_nodep : forall (A:Type)(P : A -> Type)(f : elt -> A -> A)(i:A)(s:t), P i -> (forall x a, In x s -> P a -> P (f x a)) -> P (fold f s i).
Lemma fold_rec_weak : forall (A:Type)(P : t -> A -> Type)(f : elt -> A -> A)(i:A), (forall s s' a, s[=]s' -> P s a -> P s' a) -> P empty i -> (forall x a s, ~In x s -> P s a -> P (add x s) (f x a)) -> forall s, P s (fold f s i).
Lemma fold_rel : forall (A B:Type)(R : A -> B -> Type) (f : elt -> A -> A)(g : elt -> B -> B)(i : A)(j : B)(s : t), R i j -> (forall x a b, In x s -> R a b -> R (f x a) (g x b)) -> R (fold f s i) (fold g s j).
Lemma set_induction : forall P : t -> Type, (forall s, Empty s -> P s) -> (forall s s', P s -> forall x, ~In x s -> Add x s s' -> P s') -> forall s, P s.
Lemma set_induction_bis : forall P : t -> Type, (forall s s', s [=] s' -> P s -> P s') -> P empty -> (forall x s, ~In x s -> P s -> P (add x s)) -> forall s, P s.
Lemma fold_identity : forall s, fold add s empty [=] s.
Lemma fold_0 : forall s (A : Type) (i : A) (f : elt -> A -> A), exists l : list elt, NoDup l /\ (forall x : elt, In x s <-> InA x l) /\ fold f s i = fold_right f i l.
Lemma fold_1 : forall s (A : Type) (eqA : A -> A -> Prop) (st : Equivalence eqA) (i : A) (f : elt -> A -> A), Empty s -> eqA (fold f s i) i.
Lemma fold_2 : forall s s' x (A : Type) (eqA : A -> A -> Prop) (st : Equivalence eqA) (i : A) (f : elt -> A -> A), compat_op E.eq eqA f -> transpose eqA f -> ~ In x s -> Add x s s' -> eqA (fold f s' i) (f x (fold f s i)).
Lemma fold_1b : forall s (A : Type)(i : A) (f : elt -> A -> A), Empty s -> (fold f s i) = i.
Lemma fold_commutes : forall i s x, eqA (fold f s (f x i)) (f x (fold f s i)).
Lemma fold_init : forall i i' s, eqA i i' -> eqA (fold f s i) (fold f s i').
Lemma fold_equal : forall i s s', s[=]s' -> eqA (fold f s i) (fold f s' i).
Lemma fold_empty : forall i, fold f empty i = i.
Lemma fold_add : forall i s x, ~In x s -> eqA (fold f (add x s) i) (f x (fold f s i)).
Lemma add_fold : forall i s x, In x s -> eqA (fold f (add x s) i) (fold f s i).
Lemma remove_fold_1: forall i s x, In x s -> eqA (f x (fold f (remove x s) i)) (fold f s i).
Lemma remove_fold_2: forall i s x, ~In x s -> eqA (fold f (remove x s) i) (fold f s i).
Lemma fold_union_inter : forall i s s', eqA (fold f (union s s') (fold f (inter s s') i)) (fold f s (fold f s' i)).
Lemma fold_diff_inter : forall i s s', eqA (fold f (diff s s') (fold f (inter s s') i)) (fold f s i).
Lemma fold_union: forall i s s', (forall x, ~(In x s/\In x s')) -> eqA (fold f (union s s') i) (fold f s (fold f s' i)).
Lemma fold_plus : forall s p, fold (fun _ => S) s p = fold (fun _ => S) s 0 + p.
Lemma cardinal_fold : forall s, cardinal s = fold (fun _ => S) s 0.
Lemma cardinal_0 : forall s, exists l : list elt, NoDupA E.eq l /\ (forall x : elt, In x s <-> InA E.eq x l) /\ cardinal s = length l.
Lemma cardinal_1 : forall s, Empty s -> cardinal s = 0.
Lemma cardinal_2 : forall s s' x, ~ In x s -> Add x s s' -> cardinal s' = S (cardinal s).
Lemma cardinal_Empty : forall s, Empty s <-> cardinal s = 0.
Lemma cardinal_inv_1 : forall s, cardinal s = 0 -> Empty s.
Lemma cardinal_inv_2 : forall s n, cardinal s = S n -> { x : elt | In x s }.
Lemma cardinal_inv_2b : forall s, cardinal s <> 0 -> { x : elt | In x s }.
Lemma Equal_cardinal : forall s s', s[=]s' -> cardinal s = cardinal s'.
Lemma fold_spec_right (s:t)(A:Type)(i:A)(f : elt -> A -> A) : fold f s i = List.fold_right f i (rev (elements s)).
Theorem fold_rec : forall (A:Type)(P : t -> A -> Type)(f : elt -> A -> A)(i:A)(s:t), (forall s', Empty s' -> P s' i) -> (forall x a s' s'', In x s -> ~In x s' -> Add x s' s'' -> P s' a -> P s'' (f x a)) -> P s (fold f s i).
Theorem fold_rec_bis : forall (A:Type)(P : t -> A -> Type)(f : elt -> A -> A)(i:A)(s:t), (forall s s' a, s[=]s' -> P s a -> P s' a) -> (P empty i) -> (forall x a s', In x s -> ~In x s' -> P s' a -> P (add x s') (f x a)) -> P s (fold f s i).
Lemma fold_rec_nodep : forall (A:Type)(P : A -> Type)(f : elt -> A -> A)(i:A)(s:t), P i -> (forall x a, In x s -> P a -> P (f x a)) -> P (fold f s i).
Lemma fold_rec_weak : forall (A:Type)(P : t -> A -> Type)(f : elt -> A -> A)(i:A), (forall s s' a, s[=]s' -> P s a -> P s' a) -> P empty i -> (forall x a s, ~In x s -> P s a -> P (add x s) (f x a)) -> forall s, P s (fold f s i).
Lemma fold_rel : forall (A B:Type)(R : A -> B -> Type) (f : elt -> A -> A)(g : elt -> B -> B)(i : A)(j : B)(s : t), R i j -> (forall x a b, In x s -> R a b -> R (f x a) (g x b)) -> R (fold f s i) (fold g s j).
Lemma set_induction : forall P : t -> Type, (forall s, Empty s -> P s) -> (forall s s', P s -> forall x, ~In x s -> Add x s s' -> P s') -> forall s, P s.
Lemma set_induction_bis : forall P : t -> Type, (forall s s', s [=] s' -> P s -> P s') -> P empty -> (forall x s, ~In x s -> P s -> P (add x s)) -> forall s, P s.
Lemma fold_identity : forall s, fold add s empty [=] s.
Lemma fold_0 : forall s (A : Type) (i : A) (f : elt -> A -> A), exists l : list elt, NoDup l /\ (forall x : elt, In x s <-> InA x l) /\ fold f s i = fold_right f i l.
Lemma fold_1 : forall s (A : Type) (eqA : A -> A -> Prop) (st : Equivalence eqA) (i : A) (f : elt -> A -> A), Empty s -> eqA (fold f s i) i.
Lemma fold_2 : forall s s' x (A : Type) (eqA : A -> A -> Prop) (st : Equivalence eqA) (i : A) (f : elt -> A -> A), Proper (E.eq==>eqA==>eqA) f -> transpose eqA f -> ~ In x s -> Add x s s' -> eqA (fold f s' i) (f x (fold f s i)).
Lemma fold_1b : forall s (A : Type)(i : A) (f : elt -> A -> A), Empty s -> (fold f s i) = i.
Lemma fold_commutes : forall i s x, eqA (fold f s (f x i)) (f x (fold f s i)).
Lemma fold_init : forall i i' s, eqA i i' -> eqA (fold f s i) (fold f s i').
Lemma fold_equal : forall i s s', s[=]s' -> eqA (fold f s i) (fold f s' i).
Lemma fold_empty : forall i, fold f empty i = i.
Lemma fold_add : forall i s x, ~In x s -> eqA (fold f (add x s) i) (f x (fold f s i)).
Lemma add_fold : forall i s x, In x s -> eqA (fold f (add x s) i) (fold f s i).
Lemma remove_fold_1: forall i s x, In x s -> eqA (f x (fold f (remove x s) i)) (fold f s i).
Lemma remove_fold_2: forall i s x, ~In x s -> eqA (fold f (remove x s) i) (fold f s i).
Lemma fold_union_inter : forall i s s', eqA (fold f (union s s') (fold f (inter s s') i)) (fold f s (fold f s' i)).
Lemma fold_diff_inter : forall i s s', eqA (fold f (diff s s') (fold f (inter s s') i)) (fold f s i).
Lemma fold_union: forall i s s', (forall x, ~(In x s/\In x s')) -> eqA (fold f (union s s') i) (fold f s (fold f s' i)).
Lemma fold_plus : forall s p, fold (fun _ => S) s p = fold (fun _ => S) s 0 + p.
Lemma cardinal_fold : forall s, cardinal s = fold (fun _ => S) s 0.
Lemma cardinal_0 : forall s, exists l : list elt, NoDupA E.eq l /\ (forall x : elt, In x s <-> InA E.eq x l) /\ cardinal s = length l.
Lemma cardinal_1 : forall s, Empty s -> cardinal s = 0.
Lemma cardinal_2 : forall s s' x, ~ In x s -> Add x s s' -> cardinal s' = S (cardinal s).
Lemma cardinal_Empty : forall s, Empty s <-> cardinal s = 0.
Lemma cardinal_inv_1 : forall s, cardinal s = 0 -> Empty s.
Lemma cardinal_inv_2 : forall s n, cardinal s = S n -> { x : elt | In x s }.
Lemma cardinal_inv_2b : forall s, cardinal s <> 0 -> { x : elt | In x s }.
Lemma Equal_cardinal : forall s s', s[=]s' -> cardinal s = cardinal s'.