Instructions for using schreier.c - May 12, 2010. ------------------------------------------------- Declarations: #include "schreier.h" schreier *gp; /* This will point to the Schreier structure */ permnode *gens; /* This will point to the stored generators */ Initialising group: newgroup(&gp, &gens, n); - This creates the two structures needed for a trivial group of degree n. In the case that &gens == NULL, it creates the scheier structure only. This enables a previous set of generators to be used to initialise a new group; Adding a generator p[0..n-1] : There are three options: addpermutation(&gens, p, n); - This just adds p to the stored generators without updating the Schreier structure. addgenerator(&gp, &gens, p, n); - This filters p through the Schreier structure once, adding either p or an equivalent generator if it is not found to be in the group already. It is possible that the generator can be added even though it is not needed, even if it is identical to a previous generator. It returns a boolean value which is FALSE if p was found to be in the group and useless, otherwise it returns TRUE. condaddgenerator(&gp, &gens, p, n); - This is the same as addgenerator() except that it guarantees to never add a generator which is identical to a previous generator. However, it still might not notice if it is in the group generated by the previous generators. Updating the Schreier structure: At any moment, a partial base is known (initially empty) and some partial Schreier vectors and orbits relative to that partial base. To make the Schreier vectors and orbits more likely to be complete, you can filter random group elements through it: expandschreier(gp, &gens, n); - Filter random elements until schreierfails consecutive failures occur. Uses the existing partial base and does not attempt to extend it. schreier_fails(fails); - Change the value of schreierfails (default 10). The previous is returned as the function value. Orbits of stabiliser of partial base fix[0..nfix-1]: getorbits(fix, nfix, gp, &gens, n); - If fix[0..nfix-1] is a prefix of the partial base held internally, the existing orbits are returned immediately without changing the Schreier structure. (Call expandschreier() first if this is not good enough.) - Otherwise, the Schreier structure is modified to use the partial base fix[0..nfix-1], keeping as much information as possible. Then expandschreier() is called and the orbits are returned. The function value points to an int array containing the orbits. The orbits are in nauty format (orbits[i] is the least vertex in the same orbit as vertex i). Since a randomised algorithm is used, correctness is not guaranteed. However, the partition returned is guaranteed to be finer than the true orbits partition. getorbitsmin(fix, nfix, gp, &gens, &orbits, cell, ncell, n); - If the basis elements fix[0..nfix-1] are minimal in their orbits, as far as we know, return value nfix and set *orbits to point to orbits fixing fix[0..nfix-1]. If fix[i] is seen to be not minimal for some i <= nfix-1, return i and set *orbits to point to orbits fixing fix[0..i-1]. If the partial base is already known, or fix[0..nfix-1] can already be seen to be non-minimal, do this work without more filtering. - Otherwise, filter until schreierfails failures, or until cell[0..ncell-1] is a subset of an orbit. This last test is omitted if cell=NULL. The pointer &orbits remains valid until getorbits() or getorbitsmin() is called with an incompatible base (neither a prefix nor an extension). For both getorbits() and getorbitsmin(), the orbits vector whose address is returned MUST NOT BE MODIFIED by the calling program. The pointer will remain valid until getorbits(), getorbitsmin(), pruneset() or grouporder() is called for a base that is neither a prefix nor an extension of this base. During that time it will contain the orbits of some group (not necessarily the full group) fixing this base. Finishing: deleteunmarked(&gens); - Delete some redundant generators. Those left are guaranteed to generate the group. This invalidates the Schreier structure, so call freeschreier(&gp, NULL) afterwards. freeschreier(&gp, &gens); - Free these two structures. Do this before using (gp,gens) for another group. schreier_freedyn(); - Frees all the dynamic memory allocated by the Schreier code. This is optional since the same dynamic memory will be reused if you have a new group. Getting information: schreier_gens(gens) - Return the number of stored generators. grouporder(fix, nfix, gp, &gens, &grpsize1, &grpsize2, n); - Make an estimate of the group size using the base or base-less-one fix[0..nfix-1]. grpsize1 is double and grpsize2 is int, as in nauty.h. The value returned is the product of the orbit sizes at each level times the largest orbit size at the end. Correct with some probability. dumpschreier(FILE* f, gp, gens, n); - Write to file f a complete description of the structures. permnode *findpermutation(permnode *gens, int *p, int n) - return a pointer to the permnode in the circular list which is identical to p, if it exists. Otherwise return NULL.