(** ** The collection scheme **)

(** Let (X, A, a) be a pointed graph and R a binary relation over the
    class of pointed graph (that we suppose compatible) such that each
    element of the pointed graph (X, A, a) is related to at least one
    pointed graph via the relation R.

    Since the elements of (X, A, a) are (up to a bisimulation) the
    pointed graphs of the form (X, A, x) where x : X is a vertex
    such that (A x a), our assumption can be reformulated as

      for any x : X such that (A x a), there exists a pointed
      graph (Y, B, b) such that (R X A x Y B b).

    (Of course, the equivalence of both formulations relies on the
    compatibility of R with respect to its first argument).  Now, let
    us consider the family of small types

            (coll_fam X A a R)  :  X->Code->Typ1

    defined by using the choice operator "eps" as follows: *)

Definition coll_fam (X : Typ1) (A : Rel X) (a : X) 
  (R : REL) (x : X) : Code -> Typ1 :=
  eps (fun Y => ex (Rel Y) (fun B => ex Y (fun b => R X A x Y B b))).(** (Notice that the definition of (coll_fam X A a R) actually does not
    depend on the root a : X of the pointed graph (X, A, a).)

    By construction, the family of small types (coll_fam X A a R) is
    such that for any x : X, if there exists a pointed graph (Y, B, b)
    which is related to (X, A, x) via R, then there is a code c : Code
    such that (coll_fam X A a R x c) is the carrier of one of such
    pointed graphs, that is, such that

      (R X A x (coll_fam X A a R x c) B b)

    for some edge relation B and some root b on the carrier given by
    (coll_fam X A a R x c).

    It is now clear that if we take the super-powerset of the family
    (coll_fam X A a R) : X->Code->Typ1, we obtain a pointed graph that
    meets the specification of the collection scheme.

    Formally, the desired pointed graph

      ((coll X A a R), (COLL X A a R), (coll_rt X A a R))

    is defined as follows: *)

Definition coll (X : Typ1) (A : Rel X) (a : X) (R : REL) : Typ1 :=
  foo X Code (coll_fam X A a R).Definition COLL (X : Typ1) (A : Rel X) (a : X) (R : REL) :
  Rel (coll X A a R) := FOO X Code (coll_fam X A a R).Definition coll_rt (X : Typ1) (A : Rel X) (a : X) (R : REL) : 
  coll X A a R := foo_rt X Code (coll_fam X A a R).

(* Specifications: *)
Theorem collection : forall (X : Typ1) (A : Rel X) (a : X) (R : REL), LCOMPAT R -> RCOMPAT R -> (forall (X' : Typ1) (A' : Rel X') (a' : X'), ELT X' A' a' X A a -> exG (fun Y' B' b' => R X' A' a' Y' B' b')) -> forall (X' : Typ1) (A' : Rel X') (a' : X'), ELT X' A' a' X A a -> exG_rel (coll X A a R) (COLL X A a R) (coll_rt X A a R) (fun Y' B' b' => R X' A' a' Y' B' b').
Theorem collection2 : forall (X : Typ1) (A : Rel X) (a : X) (R : REL), LCOMPAT R -> RCOMPAT R -> forall (X' : Typ1) (A' : Rel X') (a' : X'), ELT X' A' a' X A a -> exG (fun Y' B' b' => R X' A' a' Y' B' b') -> exG_rel (coll X A a R) (COLL X A a R) (coll_rt X A a R) (fun Y' B' b' => R X' A' a' Y' B' b').