'For a transitive group, finds the block system generated by
``points``.
If a group ``G`` acts on a set ``S``, a nonempty subset ``B`` of ``S``
is called a block under the action of ``G`` if for all ``g`` in ``G``
we have ``gB = B`` (``g`` fixes ``B``) or ``gB`` and ``B`` have no
common points (``g`` moves ``B`` entirely). ([1], p.23; [6]).
The distinct translates ``gB`` of a block ``B`` for ``g`` in ``G``
partition the set ``S`` and this set of translates is known as a block
system. Moreover, we obviously have that all blocks in the partition
have the same size, hence the block size divides ``|S|`` ([1], p.23).
A ``G``-congruence is an equivalence relation ``~`` on the set ``S``
such that ``a ~ b`` implies ``g(a) ~ g(b)`` for all ``g`` in ``G``.
For a transitive group, the equivalence classes of a ``G``-congruence
and the blocks of a block system are the same thing ([1], p.23).
The algorithm below checks the group for transitivity, and then finds
the ``G``-congruence generated by the pairs ``(p_0, p_1), (p_0, p_2),
..., (p_0,p_{k-1})`` which is the same as finding the maximal block
system (i.e., the one with minimum block size) such that
``p_0, ..., p_{k-1}`` are in the same block ([1], p.83).
It is an implementation of Atkinson\'s algorithm, as suggested in [1],
and manipulates an equivalence relation on the set ``S`` using a
union-find data structure. The running time is just above
`O(|points||S|)`. ([1], pp. 83-87; [7]).
Examples
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> D = DihedralGroup(10)
>>> D.minimal_block([0, 5])
[0, 6, 2, 8, 4, 0, 6, 2, 8, 4]
>>> D.minimal_block([0, 1])
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
See Also
_union_find_rep, _union_find_merge, is_transitive, is_primitive'

def minimal_block(self, points):

    if (not self.is_transitive()):
        return False
    n = self.degree
    gens = self.generators
    parents = list(range(n))
    ranks = ([1] * n)
    not_rep = []
    k = len(points)
    if (k > self.max_div):
        return ([0] * n)
    for i in range((k - 1)):
        parents[points[(i + 1)]] = points[0]
        not_rep.append(points[(i + 1)])
    ranks[points[0]] = k
    i = 0
    len_not_rep = (k - 1)
    while (i < len_not_rep):
        gamma = not_rep[i]
        i += 1
        for gen in gens:
            delta = self._union_find_rep(gamma, parents)
            temp = self._union_find_merge(gen(gamma), gen(delta), ranks, parents, not_rep)
            if (temp == (-1)):
                return ([0] * n)
            len_not_rep += temp
    for i in range(n):
        self._union_find_rep(i, parents)
    return parents
