MakeStabChain(const GeneratorSet& generatorSet, uint* base) { Group* group = new Group(0); for (generator in generatorSet) group->Extend(generator, base); return group; } // Extend the stabilizer chain rooted at this group with the given generator. void Group::Extend(const Permutation& generator, uint* base) { // This is the major optimization of Schreier-Sims. Weed out redundant Schreier generators. if (IsMember(generator)) return; // Our group just got bigger, but the stabilizer chain rooted at our subgroup is still the same. generatorSet.Add(generator); // Explore all new orbits we can reach with the addition of the new generator. // Note that if the tree was empty to begin with, the identity must be returned // in the set to satisfy a condition of Schreier's lemma. newTerritorySet = orbitTree.Grow(generator, base); // By the orbit-stabilizer theorem, the permutations in the returned set are // coset representatives of the cosets of our subgroup. for (permutation in newTerritorySet) transversalSet.Add(permutation); // We now apply Schreier's lemma to find new generators for our subgroup. // Some iterations of this loop are redundant, but we ignore that for simplicity. for (cosetRepresentative in transversalSet) { for (generator in generatorSet) { schreierGenerator = CalcSchreierGenerator(cosetRepresentative, generator); if (schreierGenerator.IsIdentity()) continue; if (!subGroup) subGroup = new Group(stabPoint + 1); subGroup->Extend(schreierGenerator, base); } } } Notable details left out here include the growing of the orbit tree and the calculation of each new Schreier generator. In place of the orbit tree, a Schreier vector can be used, but the idea is essentially the same. The tree is rooted at the identity element, which fixes the point stabilized by the subgroup. Each node of the tree can represent a permutation that, when combined with all permutations in the path from the root to it, takes that point to some new point not visited by any other node of the tree. By the orbit-stabilizer theorem, these form a transversal of the subgroup of our group that stabilizes the point whose entire orbit is maintained by the tree. Calculating a Schreier generator is a simple matter of applying Schreier's subgroup lemma. Another detail left out is the membership test. This test is based upon the sifting process. A permutation is sifted down the chain at each step by finding the containing coset, then using that coset's representative to find a permutation in the subgroup, and the process is repeated in the subgroup with that found permutation. If the end of the chain is reached