Equivalence classes on the Transitive Closure of a Reflexive Relation The goal of this challenge is to compute the set of equivalence classes over the transitive closure of a symmetric, reflexive relation. For those who don't know what that means, here is a brief introduction into the relevant terms:

A relation &loz; is symmetric if a &loz; b &harr; b &loz; a. It is reflexive if each object is related to itself, i.e. a &loz; a  always holds. It is transitive  if a &loz; b &and; b &loz; c &rarr; a &loz; c, i.e. if a is related to b and b is related to c, then a is related to c. An equivalence relation is a relation that is symmetric, reflexive and transitive.

The transitive closure &loz;* of &loz; is a transitive relation such that a &loz;* b holds if and only if there is a (possibly empty) series of objects c1, c2, ..., cn such that a &loz; c1 &loz; c2 &loz; &middot;&middot;&middot; &loz; cn &loz; b. The transitive closure of a symmetric, reflexive relation is an equivalence relation.

Let &equiv; be an equivalence relation over the set S. An equivalence class a&equiv; of an object a over the relation &equiv; is the largest subset of S such that a &equiv; x for all x &in; S or formally: a&equiv; = { x | x &in; S, a &equiv; x }. All elements of a&equiv; are equivalent to one another.

The set of equivalence classes S/&equiv; of &equiv; over S is the set of equivalence classes of all members of S.

Constraints

In this task, your objective is to write a function that takes a binary relation &cong; and a finite non-empty set S. You may take input in a suitable way and choose a suitable data-structure for S (e.g. an array or a linked list). Assume that &cong; is a symmetric, reflexive relation over S. Your function should return or print out the set of equivalence classes over S of the transitiveclosure of &cong;. You may choose a suitable output format or data structure for the result. As the result is a set, each object in S may appear only once.

You may not use library routines or other builtin functionality to find the components of a graph or related things.

Winning condition

The shortest answer in octets wins. The most elegant answer is chosen in case of a tie.

Sample input

The reflexive and symmetric members of &cong; have been omitted for brevity.

S1 = {A, B, C, D, E, F, G, H}
&cong;1 = {(A, B), (B, C), (B, E), (D, G) (E, H)}
S1/&cong;1* = {{A, B, C, E, H}, {D, G}, {F}}.

S2 = {&alpha;, &beta;, &gamma;, &delta;, &epsilon;, &zeta;, &eta;, &theta;, &iota;, &kappa;}
&cong;2 = {(&alpha;, &zeta;), (&alpha;, &iota;), (&beta;, &gamma;), (&beta;, &epsilon;), (&gamma;, &delta;), (&gamma;, &epsilon;), (&zeta;, &theta;), (&eta;, &kappa;), (&theta;, &iota;)}
S2/&cong;2* = {{&alpha;, &zeta;, &theta;, &iota;}, {&beta;, &gamma;, &delta;, &epsilon;}, {&eta;, &kappa;}}

S3 = {&spades;, &clubs;, &hearts;, &diams;}
&cong;3 = {}
S3/&cong;3* = {{&spades;}, {&clubs;}, {&hearts;}, {&diams;}}

S4 = {&Alpha;, &Beta;, &Gamma;, &Delta;, &Epsilon;, &Zeta;, &Eta;, &Theta;, &Iota;, &Kappa;, &Lambda;}
&cong;4 = {(&Alpha;, &Epsilon;), (&Beta;, &Zeta;), (&Gamma;, &Eta;), (&Delta;, &Theta;), (&Epsilon;, &Iota;), (&Zeta;, &Kappa;), (&Eta;, &Lambda;), (&Theta;, &Alpha;), (&Iota;, &Beta;), (&Kappa;, &Gamma;), (&Lambda;, &Delta;)}
S4/&cong;4* = {{&Alpha;, &Beta;, &Gamma;, &Delta;, &Epsilon;, &Zeta;, &Eta;, &Theta;, &Iota;, &Kappa;, &Lambda;}}
Pyth, 50 29 bytes

JchQ1FNeQAmf/@JTd0N XGJ.(JH;J


Input is expected to be a list of two elements where the first element is a list of all the objects in S, and the second element is a list of all the members in ≅, represented as lists. So for the first example, the input is

[["A", "B", "C", "D", "E", "F", "G", "H"], [["A", "B"], ["B", "C"], ["B", "E"], ["D", "G"], ["E", "H"]]]


Explanation:

                               Implicit assignment of Q to input, so head(Q) is S and end(Q) is ≅
JchQ1                          Assign J to chop(head(Q),1) e.g. [1,2,3] =&gt; [[1],[2],[3]]
     FNeQ                      For N in end(Q)
         A                       Assign [H,G] to following list
          m       N                Map following function over N
           f     0                   Return first T where following function of T starting at 0,1,2... is truthy         
            /@JTd                      lambda d: true if d is J[T]
                    XGJ.(JH;     Append J[H] to J[G] and pop J[H]
                            J  Print J


Note that if transitive or reflexive members (i.e. redundant) members of ≅ are included, my code should output junk.

You can try it out here.