
\subsubsection{Introduction}

The object of this recipe is to enumerate non-isomorphic graphs on $n$
vertices using P\'olya's theorem and GMP (the GNU multiple precision
arithmetic library). We will be concerned with the algorithmics rather
than the mathematics. You are encouraged to learn more about the
latter, e.g. from Frank Harary's books on the subject.

Fig. \ref{fig:all3} shows all possible graphs on three vertices. There
are eight of these; for a graph on $n$ vertices we have $2^{n (n-1)/
2}$ such graphs. We want a different statistic, namely one that takes
isomorphisms into account. Fig. \ref{fig:noniso3} shows that there are
really only four different graphs on three vertices. This is because
e.g. there exists a vertex permutation that maps the three graphs with
one edge to one another. We say that these three graphs constitute an
equivalence class.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{figure}
\begin{center}
\includegraphics{combinatorics/xgraphenum/all3.eps}
\caption{\label{fig:all3}
All eight graphs on three vertices.
}
\end{center}
\end{figure}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{figure}
\begin{center}
\includegraphics{combinatorics/xgraphenum/noniso3.eps}
\caption{\label{fig:noniso3}
All non-isomorphic graphs on three vertices.
}
\end{center}
\end{figure}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Let us now reformulate the problem so that P\'olya's theorem
applies. Given $n,$ we want to know how many non-isomorphic graphs,
i.e. equivalence classes there are with $k$ edges. We can think of the
edges as slots that are either filled (edge present) or empty (edge
absent). An empty slot has size zero and a filled one, size one. The
number of edges is the sum of the sizes of the slots. The slots
(edge locations) are being permuted by any of the $n!$ vertex
permutations. There is one edge permutation for each vertex
permutation. We will obtain the values for all $k$ at once, namely in
a generating function, i.e. in a function where the term $q z^k$
denotes the presence of $q$ non-isomorphic graphs with $k$ edges.

The generic definition of our problem is this: given a set of slots
that are being permuted by a permutation group (more on this later)
and a set of objects of different sizes that go into the slots (one
object per slot), count the number of equivalence classes of filled
slot configurations with respect to the permutation group whose total
size (i.e. sum of the sizes of the objects placed in the slots) is
$k.$ In our case the group is the pair group obtained from the
symmetric group acting on $n$ vertices and the objects that go into
the slots are present/absent edges.


{\em Example.} Recall Fig. \ref{fig:all3} and label the vertices 1, 2,
3. The table shows the vertex and the corresponding edge permutations
(the three edges are 12, 13 and 23; the permutations are in table
notation, e.g. $1 \rightarrow 2,$ $2 \rightarrow 3$ and $3 \rightarrow
1$ is written as $2 3 1$):

\begin{center}
\begin{tabular}{|c|c|} \hline
1 2 3 & 12 13 23 \\ \hline
1 3 2 & 13 12 23 \\ \hline
2 1 3 & 12 23 13 \\ \hline
2 3 1 & 23 12 13 \\ \hline
3 1 2 & 13 23 12 \\ \hline
3 2 1 & 23 13 12 \\ \hline
\end{tabular}
\end{center}

The eight graphs correspond to the three slots (edges) being filled or
empty.
\begin{center}
\begin{tabular}{|c|c|c|} \hline
12 & 13 & 23 \\ \hline \hline
empty & empty & empty \\ \hline
empty & empty & filled \\ \hline
empty & filled & empty \\ \hline
empty & filled & filled \\ \hline
filled & empty & empty \\ \hline
filled & empty & filled \\ \hline
filled & filled & empty \\ \hline
filled & filled & filled \\ \hline
\end{tabular}
\end{center}

The edge permutations permute the columns of the table, e.g. $12 \; 23
\; 13$ takes line two to line three, so these are in the same
equivalence class. Permuting edges does not change the total size of
the configuration (number of edges), so there is no permutation that
takes line two to line four.

Another common application of P\'olya's theorem is to count, say, the
number of different necklaces, where a necklace is made up of $n$
gemstones and there are $m$ different types of gemstones (colors)
available. We can choose these to have the same size or different
sizes. In terms of the above discussion, the slots are the positions on
the necklace, the objects that go into the slots are the gemstones and
the permutations rotate or flip the necklace or both.

\subsubsection{Permutations}

We will be using only a few basic facts about permutations and
permutation groups. The elements of the latter are permutations and
the multiplication operation is permutation composition. There must
not be any permutations whose product is not in the group. E.g. $\set{
123, 231}$ is not a group because $231 \circ 231 = 312,$ which is not
in the set. We are concerned with two groups: the symmetric group
$S_n$ on $n$ vertices, which includes all $n!$ permutations and the
corresponding pair group $S_n^{(2)}$ on $n (n-1)/2$ edges, whose
elements are obtained from the action of the vertex permutation on the
edges. E.g. consider the vertex permutation $23451$ and the edges $12
\; 13 \; 14 \; 15 \; 23 \; 24 \; 25 \; 34 \; 35 \; 45.$ The
corresponding edge permutation $\epsilon$ is $23 \; 24 \; 25 \; 12 \;
34 \; 35 \; 13 \; 45 \; 14 \; 15.$

We now switch to a more useful way of writing permutations, i.e. the
so-called disjoint cycle decomposition. This consists in writing the
permutation as a product of its cycles. E.g. the permutation $164325$
(table notation) would be written as $(1) \; (2 6 5) \; (3 4)$ since
e.g. it takes $2$ to $6$, $6$ to $5$ and $5$ back to $2$, and the edge
permutation $\epsilon$ as $(12 \; 23 \; 34 \; 45 \; 15) \; (13 \; 24
\; 35 \; 14 \; 25).$

The disjoint cycle decomposition tells us about the shape of the
permutation. This shape information is captured by a product notation,
where the variable $a_k$ stands for a cycle of length $k$ and $j_k$
for the number of cycles with this length, giving the product
$\prod_{k=1}^p a_k^{j_k}.$ E.g. the product for $(1) \; (2 6 5) \; (3
4)$ would be $a_1 a_2 a_3,$ whith $j_1 = j_2 = j_3 = 1$ and $j_4 = j_5
= j_6 = 0$ and for $\epsilon,$ $a_5^2$, with $j_1 = j_2 = j_3 = j_4 =
0,$ $j_5 = 2$ and $j_6 = j_7 = j_8 = j_9 = j_{10} = 0.$

\subsubsection{The Cycle Index}

The cycle index $Z(S)$ of a permutation group $S$ is the average of
$\prod_{k=1}^p a_k^{j_k}$ over all permutations in the group.
E.g. the cycle indices of the symmetric group $S_3$ and the pair group
$S_3^{(2)}$ are obtained from the following table.

\begin{center}
\begin{tabular}{|c|c|c|c|} \hline
1 2 3 & $a_1^3   $& 12 13 23 & $a_1^3   $\\ \hline
1 3 2 & $a_1 a_2 $& 13 12 23 & $a_1 a_2 $\\ \hline
2 1 3 & $a_1 a_2 $& 12 23 13 & $a_1 a_2 $\\ \hline
2 3 1 & $a_3     $& 23 12 13 & $a_3     $\\ \hline
3 1 2 & $a_3     $& 13 23 12 & $a_3     $\\ \hline
3 2 1 & $a_1 a_2 $& 23 13 12 & $a_1 a_2 $\\ \hline
\end{tabular}
\end{center}

This special case yields
\[Z(S_3) = Z(S_3^{(2)}) =
\sxth a_1^3 + \half a_1 a_2  + \thrd a_3
.\]

\subsubsection{P\'olya's theorem}

This is what the theorem says: suppose you have some set of objects of
different sizes and distribute these objects into $n$ slots, where a
permutation group acts on the slots to create equivalence classes of
filled slot configurations. The generating function of these
equivalence classes is obtained by replacing $a_k$ by $f(z^k)$ in the
cycle index, where $f$ is the generating function of the objects.

The permutation group is $S_n^{(2)}$ (pair group acting on the
vertices) when we enumerate graphs and the generating function of the
objects is $1+z,$ indicating whether an edge is present (size one,
$z$) or not ($1$). Substitute $a_k = 1+z^k$ into $Z(S_3^{(2)})$ to
obtain
\[
\sxth (1+z)^3 + \half (1+z)(1+z^2) + \thrd (1+z^3) =
\sxth z^3 + \half z^2 + \half z + \sxth +
\half z^3 + \half z^2 + \half z + \half +
\thrd z^3 + \thrd =
z^3 + z^2 + z + 1,\]

which says that there is one graph with three edges, one with two, one
with one edge and one with no edges, as is also evident from
Fig.\ref{fig:noniso3}.

\subsubsection{Cycle index of the pair group}

We need the cyle index of $S_n^{(2)}$ in order to enumerate
graphs. There is one permutation for every permutation from $S_n$ in
$S_n^{(2)}.$ Fortunately we needn't iterate over all $n!$ permutations
in $S_n$, which would make the computation infeasible for all but
small $n$. Recall that the shape of the permutation determines the
product that it contributes to the cycle index. This means that
e.g. $(1 \; 2 \; 3) \; (4) \; (5 \; 6), \; (1) \; (2 \; 3) \; (4 \; 5
\; 6)$ and $(1 \; 2) \; (3 \; 4 \; 5) \; (6)$ all contribute the same
term to $S_6$, namely $a_1 a_2 a_3$ (three copies of it).

Hence we can enumerate the permutations in $S_n$ by iterating over all
possible shapes and computing how often each shape occurs. These
shapes are precisely the partitions of $n$ into some number of
summands. E.g. the cycle index for $S_3$ contains one product term for
each of the possible partitions $1+1+1,$ $1+2$ and $3.$ We need the
coefficient associated to each of these three partitions, i.e. the
number of times this shape occurs.

The disjoint cycle decomposition 
     $\prod_{k=1}^n a_k^{j_k}$
occurs
\[ \frac{n!}{\prod_{k=1}^n \PAR{k!}^{j_k}}
   \prod_{k=1}^n \PAR{\frac{k!}{k}}^{j_k}
   \prod_{k=1}^n \frac{1}{j_k!}
=
   \frac{n!}{\prod_{k=1}^n k^{j_k} j_k!}
\]
times. (Partition the $n$ elements into subsets, one for each cycle.
A subset of size $k$ generates $k!/k$ cycles. The same size $j_k$ set
of $k$-cycles may be chosen in $j_k!$ different ways.)

For $S_3$ this yields the following results:
\begin{itemize}
\item $1+1+1$: choose three subsets of size one in $3!/1!/1!/1! = 6$
  ways, every such subset generates $1!/1 = 1$ cycles but all $3!$
  choices for the three subsets are the same, giving $1.$
\item $1+2$: choose a subset of size two and one of size one in
  $3!/1!/2! = 3$ ways (there are three ways to choose the singleton):
  the size two subset generates $2!/2 = 1$ cycle and the size one
  subset, $1!/1 = 1$ cycle; there no duplicates in the choice of
  size $2$ or size $1$ subsets, giving $3.$
\item $3$: choose a subset of size three in $3!/3! = 1$ ways, this
  subset generates $3!/3 = 2$ cycles and again there are no duplicates
  in the choice of the size $3$ subset, giving $2.$
\end{itemize}
This computation confirms the value for $S_3$ that we computed
earlier.

How to obtain the possible partitions? This is simple, since there is
a folklore algorithm for the problem. Instead of computing the set of
partitions $P_n$ of $n$, we start with $P_{n, k},$ the set of
partitions of $n$ into $k$ summands. Now every partition in $P_{n, k}$
either contains one, and can be obtained by including one in a
partition from $P(n-1, k-1),$ or it does not contain one and $n-k >=
k,$ and it can be obtained from a partition from $P(n-k, k)$ by
incrementing its elements. We can compute $P_{n, k}$ recursively, the
base case being $P_{1, 1} = \set{[1]}.$ $P_n$ is the union of the
$P_{n, k}$ for $1\le k \le n.$

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{figure}
\begin{center}
\includegraphics[scale=0.9]{combinatorics/xgraphenum/vcycedges.eps}
\caption{\label{fig:vcycedges}
Vertex permutation with the shape $a_4^3 \; a_8$ and the three
possible types of edges.
}
\end{center}
\end{figure}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


At this point we have all possible shapes and we know how often they
occur. The last step is to compute the shape of the edge permutation
from the shape of the vertex permutation. An edge connects two
vertices. There are three possiblities: these vertices lie on the same
cycle of the vertex permutation, they lie on different cycles of the
same length or they lie on different cycles of different
lengths. These three possibilities are shown in
Fig. \ref{fig:vcycedges}. We must compute the length of the edge cycle
(i.e. how long it takes for the vertex pair to return to the start
edge when it moves in parallel along the vertex cycle) in each case
and how often it occurs.  There is an additional distinction to be
made when the vertices lie on the same cycle: a cycle of even length
contains vertex pairs that return to the start edge after having
covered exactly half, rather than the whole cycle. Furthermore, the
number of steps for the return to the start position for two vertices
on cycles of different lengths is given by the least common multiple
of those lengths. Note that we'll overcount cycles by a factor that is
equal to the length of the edge cycle. We illustrate with a sample
computation.

Say the vertex permutation has the shape $a_3^2 \, a_6 \, a_7.$
\begin{itemize}
\item {\bf Same cycle.} 
\begin{itemize}
\item $a_3^2$: three vertex pairs, length three, twice: $a_3^2$
\item $a_6$: fifteen vertex pairs, three short cycles: $a_6^2 a_3$
\item $a_7$: twenty-one vertex pairs, length seven, $a_7^3$
\end{itemize}
\item {\bf Different cycles, same length.}
\begin{itemize}
\item $a_3^2$: nine vertex pairs, length three: $a_3^3$
\end{itemize}
\item {\bf Different cycles, different length.}
\begin{itemize}
\item $a_3^2 a_6$: eighteen vertex pairs, length six, twice, $a_6^6$
\item $a_3^2 a_7$: twenty-one vertex pairs, length twenty-one, twice,
  $a_{21}^2$
\item $a_6 a_7$: forty-two vertex pairs, length forty-two: $a_{42}.$
\end{itemize}
\end{itemize}
This shows that the corresponding edge permutation has the shape
$a_3^6 \, a_6^8 \, a_7^3 \, a_{21}^2 \, a_{42}$, and indeed
$18+48+21+42+42 = 171 = 1/2 \; 19 \; (19-1).$

We now have all the ingredients to implement the graph enumeration
algorithm. There will be four steps:

\begin{itemize}
\item Compute the partitions of $n.$
\item Compute the vertex permutation shapes from the partitions and
  the coefficient.
\item Compute the edge permutation shape, substitute $1+z$ and add the
  resulting polynomial to the current total.
\item Divide by $n!$ to obtain the generating function.
\end{itemize}

Note that we average the cycle index in the last step in order to be
able to work with integers during the whole computation. Speaking of
integers, our implementation will use the GMPInt wrapper class for GMP
integers.

\subsubsection{Concerning memory allocation}

The computation that we undertake produces many intermediate results.
These are: {\tt GMPInt} values to represent coefficients of the
products whose sum forms the cycle index; {\tt NSString} objects that
document the computation if the user activates debugging and {\tt
NSMutableArray} objects that hold partitions and product terms as well
as polynomials in one variable that result from the substitution of
$1+z$ into the cycle index. All of these can use up a lot of memory
very quickly, which is why we absolutely must implement garbage
collection. This is done in the loop that iterates over the partitions
and hence over the products that occur in the cycle index. We check
whether the number of allocated critical objects has doubled, and
empty the autorelease pool if it has.

\subsubsection{Implementation I: auxiliary functions}

There is a preliminary remark concerning our terminology. We use the
term multiset to refer to partitions and products. This is because a
partition like $[1, 1, 1, 2, 3]$ or $a_1^3 \; a_2 \; a_3$ is a
multiset containing three copies of the value ``1'' and one copy each
of the values ``2'' and ``3.''

Our list of auxiliary functions starts with the basic GCD
algorithm. The GCD $g$ of $p$ and $q$ divides $p = m q + r$ and $q$,
so it also divides $r < q.$ Hence replace $(p, q)$ by $(q, r)$ and
repeat until $r=0.$  We need the GCD to compute the LCM of the lengths
of two cycles of a vertex permutation. The LCM gives the length of the
edge cycle of those edges that have one vertex on each of the two
vertex cycles.

\begin{lstlisting}{}
int gcd(int p, int q)
{
    int r;

    if(p<q){
        int s;

        s = p;
        p = q;
        q = s;
    }

    while(r=p%q){
        p = q;
        q = r;
    }

    return q;
}
\end{lstlisting}

The function {\tt SumIt} sums a multiset, where each element
contributes according to its multiplicity and the first element has
value one. It iterates over the elements in a loop. This is very
useful for consistency checks. The cycle lengths of a vertex
permutation must sum to $n$, and the cycle lengths of the
corresponding edge permutation to $1/2 n (n-1).$

\begin{lstlisting}{}
int SumIt(NSArray *data)
{
    int sum, pos, max = [data count];

    for(sum=0, pos=0; pos<max; pos++){
        sum += (pos+1)*
            [[data objectAtIndex:pos] intValue];
    }

    return sum;
}
\end{lstlisting}

The next two functions are very important; they compute $P_{n, k}$ and
$P_n,$ respectively. Start with the former. The base case comes first:
the answer is $\set{[1]}$ when $n=1.$ The data structure that we use
is an array of arrays of integer {\tt NSNumber} objects. The number is
one summand from the partition, the inner array a single partition and
the outer array a collection of partitions.

\begin{lstlisting}{}
NSMutableArray *Partitionsk(int n, int k)
{
    NSMutableArray *part,
        *result = [NSMutableArray arrayWithCapacity:1];
    NSEnumerator *en;

    if(n==1){
        part = 
            [NSMutableArray
                arrayWithObject:
                    [NSNumber numberWithInt:1]];
        [result addObject:part];
        return result;
    }
\end{lstlisting}

The two recursions are next. Either the partition contains one or it
doesn't. There is a one-to-one correspondence with a permutation of
$P_{n-1, k-1}$ in the former case, so obtain those and collect them,
adding a summand with value one at the front of each summand array.

\begin{lstlisting}{}
    if(k>1){
        en = [Partitionsk(n-1, k-1) objectEnumerator];
        while((part = [en nextObject])!=nil){
            [part insertObject:[NSNumber numberWithInt:1]
                  atIndex:0];
            [result addObject:part];
        }
    }
\end{lstlisting}

If the partition does not contain one and $n-k$ is large enough for
$k$ summands, then we have a one-to-one correspondence with a
permutation from $P_{n-k, k}.$ We obtain these permutations and
increment each summand of each partition, collecting the new
partitions in the array {\tt result.} These are the only possible
cases and we are done.

\begin{lstlisting}{}
    if(n-k>=k){
        en = [Partitionsk(n-k, k) objectEnumerator];
        while((part = [en nextObject])!=nil){
            NSMutableArray *npart =
                [NSMutableArray arrayWithCapacity:k];
            int pos;
            for(pos=0; pos<k; pos++){
                int val = [[part objectAtIndex:pos] intValue];
                [npart 
                    addObject:
                        [NSNumber numberWithInt:val+1]];
            }
            [result addObject:npart];
        }
    }

    return result;
}
\end{lstlisting}

Obtaining all partitions of $n$ is now easy: compute the union of
$P_{n, k}$ for $ 1\le k \le n.$ This is done with a loop.

\begin{lstlisting}{}
NSMutableArray *Partitions(int n)
{
    int k;
    NSMutableArray *result =
        [NSMutableArray arrayWithCapacity:1];

    for(k=1; k<=n; k++){
        NSMutableArray *partsk = Partitionsk(n, k);
        [result addObjectsFromArray:partsk];
    }
    
    return result;
}
\end{lstlisting}

We will need to turn partitions into multisets, i.e. vertex
permutation shapes that represent product terms of the form
$\prod_{k=1}^n a_k^{j_k}.$ This product correponds to a partition that
contains $j_k$ instances of the value $k.$ E.g. we want to turn $[1,
1, 1, 2, 2, 3]$ into $a_1^3 \; a_2^2 \; a_3$, which is represented as
the array $[3, 2, 1].$ First initialize the array with zero, i.e. in
our example we would have $[0, 0, 0]$  and the capacity of the array
would be three.

\begin{lstlisting}{}
NSMutableArray *PartitionToMSet(NSMutableArray *part)
{
    int pos, max = [[part lastObject] intValue];
    NSMutableArray *result =
        [NSMutableArray arrayWithCapacity:max];

    for(pos=0; pos<max; pos++){
        [result addObject:[NSNumber numberWithInt:0]];
    }
\end{lstlisting}

Then iterate over the partion and record a summand with value {\tt
value} (recall that these values are wrapped in {\tt NSNumber}
objects) at position {\tt value-1} of the multiset array. This is done
by reading the old value, incrementing it, and writing it back into
the array. This would yield the sequence $[1, 0, 0],$ $[2, 0, 0],$
$[3, 0, 0],$ $[3, 1, 0],$ $[3, 2, 0],$ and $[3, 2, 1]$ in the example.

\begin{lstlisting}{}
    NSEnumerator *en = [part objectEnumerator];
    NSNumber *val;
    while((val = [en nextObject])!=nil){
        int value = [val intValue],
            count = [[result objectAtIndex:value-1] intValue];
        [result replaceObjectAtIndex:value-1
                withObject:[NSNumber numberWithInt:count+1]];
    }

    return result;
}
\end{lstlisting}

Our program provides an extensive trace/debug facility that makes it
possible for the user to follow the computation very closely. Hence it
is imperative that we be able to convert from the internal
representation of a multiset into a string representation, i.e. we
must be able to turn $[3, 2, 1]$ into the string $a_1^3 \; a_2^2 \;
a_3.$ This is done by iterating over the multiset, reading the entry
at that position, and storing a string representation of the term in
the array {\tt factors.} (Empty fields are skipped.)

\begin{lstlisting}{}
NSString *MSetToProduct(NSMutableArray *mset)
{
    NSNumber *cval;
    NSMutableArray *factors = 
        [NSMutableArray arrayWithCapacity:1];
    int pos, max = [mset count];
    
    for(pos=0; pos<max; pos++){
        int count = [[mset objectAtIndex:pos] intValue];
\end{lstlisting}

The string representation of such a term has the form $a_k$ if
if $j_k$ is one, and the form $a_k^{j_k}$ otherwise.

\begin{lstlisting}{}
        if(count){
            NSString *item = 
                [NSString stringWithFormat:@"a_%d",
                          pos+1];
            if(count>1){
                item = [item stringByAppendingFormat:@"^%d",
                             count];
            }
            [factors addObject:item];
\end{lstlisting}

We join all terms that have been collected by concatenating
them. (They are separated by a single space in the result string.)

\begin{lstlisting}{}
        }
    }

    return [factors componentsJoinedByString:@" "];
}
\end{lstlisting}

Recall that the number of times a shape occurs in the symmetric group
is given by the formula
\[
   \frac{n!}{\prod_{k=1}^n k^{j_k} j_k!}.
\]
The next procedure computes the denominator of this fraction. Set up a
loop to iterate over the multiset and process nonzero entries only.

\begin{lstlisting}{}
GMPInt *MSetToCoeffDenom(NSMutableArray *mset)
{
    GMPInt *one = [GMPInt oneObj], 
        *res = one, *k = one;
    int pos, max = [mset count];
    
    for(pos=0; pos<max; pos++){
        int count = [[mset objectAtIndex:pos] intValue];
        if(count){
\end{lstlisting}

The actual computation is to multiply the current denominator by
$k^{j_k}$ and $j_k!$.

\begin{lstlisting}{}
            GMPInt
                *m1 = [k powUI:count], 
                *m2 = [GMPInt factorialUI:count];
                
            res = [res mul:m1];
            res = [res mul:m2];
        }
\end{lstlisting}

We increment $k$ at the end of the loop body and return the
denominator once the loop exits.

\begin{lstlisting}{}
        k = [k add:one];
    }

    return res;
}
\end{lstlisting}

The next function is really more of a macro that we'll use to turn
vertex permutation shapes into edge permutation shapes, which is why
it's marked {\tt inline}. It records an increase of a product term
$a_k$ by some amount.

\begin{lstlisting}{}
inline void AddToMSet(NSMutableArray *mset, int len, int count)
{
    int val = [[mset objectAtIndex:len-1] intValue];
    [mset replaceObjectAtIndex:len-1
          withObject:[NSNumber numberWithInt:val+count]];
}
\end{lstlisting}

The next function is of critical importance: it produces the terms of
the cycle index of the pair group. The maximum possible length of an
edge cycle obtained from a vertex permutation is $l (l-1)$, where $l$
is the length of the longest cycle of the vertex permutation. This
occurs if there are cycles of length $l-1$ and applies to edges with
one vertex on the $l-1$-cycle and the other on the $l$-cycle. The
maximum length is one for the identity permutation. The multiset of
edge cycles is initialized to be empty.

\begin{lstlisting}{}
NSMutableArray *VertexMSetToEdgeMSet(NSMutableArray *vmset)
{
    int vmxlen = [vmset count], vlen1, vlen2,
        upper = 0, 
        emxlen = (vmxlen==1 ? 1 : vmxlen*(vmxlen-1)), elen;
    int inst1, inst2, instcount;
    NSMutableArray *emset =
        [NSMutableArray arrayWithCapacity:emxlen];

    for(elen=1; elen<=emxlen; elen++){
        [emset addObject:[NSNumber numberWithInt:0]];
    }
\end{lstlisting}

The first case occurs when there are two vertices on the same
cycle. If the cycle length is odd, then the edge cycle has the same
length and the number of edges on such cycles is the number of
different vertex pairs on the cycle. We scale (divide) by the length
of the cycle because each cycle is counted once for each edge on
it. We must also scale the term by its multiplicity. (This corresponds
to choosing one of $j_k$ cycles.) We also record the new maximum edge
cycle length if it has changed. The latter two operations,
i.e. compensating for overcount and recording the new maximum edge
cycle length are common to all cases and will not be discussed
further.

\begin{lstlisting}{}
    // two vertices on the same cycle
    for(vlen1=2; vlen1<=vmxlen; vlen1++){
        inst1 = [[vmset objectAtIndex:vlen1-1] intValue];
        if(inst1){
            if(vlen1%2){
                elen = vlen1;
                instcount = vlen1*(vlen1-1)/2;
                instcount *= inst1;

                instcount /= elen;
                AddToMSet(emset, elen, instcount);
                if(elen>upper){
                    upper = elen;
                }
            }
\end{lstlisting}

The next case corresponds to two vertices being located on a cycle of
even length. Edges whose vertices are directly accross from one
another need only move through half the cycle to return to the start
position. This case is handled in the first half of the clause. The
second half corresponds to vertex pairs that are not directly accross
from one another and need to move through the entire cycle.

\begin{lstlisting}{}
            else{
                elen = vlen1/2;
                instcount = vlen1/2;
                instcount *= inst1;

                instcount /= elen;
                AddToMSet(emset, elen, instcount);
                if(elen>upper){
                    upper = elen;
                }

                elen = vlen1;
                instcount = vlen1*(vlen1-1)/2-vlen1/2;
                instcount *= inst1;

                instcount /= elen;
                AddToMSet(emset, elen, instcount);
                if(elen>upper){
                    upper = elen;
                }
                
            }
        }
    }
\end{lstlisting}

The second case occurs when two vertices lie on different cycles that
have the same length. We can choose these two cycles in $1/2 j_k
(j_k-1)$ ways. The two vertices move in parallel along the two
cycles and return to the start point only after having completed the
whole vertex cycle.

\begin{lstlisting}{}
    // two vertices on different cycles of the same length
    for(vlen1=1; vlen1<=vmxlen; vlen1++){
        inst1 = [[vmset objectAtIndex:vlen1-1] intValue];
        if(inst1>1){
            elen = vlen1;
            instcount = vlen1*vlen1;
            instcount *= inst1*(inst1-1)/2;

            instcount /= elen;
            AddToMSet(emset, elen, instcount);
            if(elen>upper){
                upper = elen;
            }
        }
    }
\end{lstlisting}

The last case occurs when the two vertices lie on different cycles of
different lengths. We check all possible combinations. We must process
all pairs $(j_{k_1}, j_{k_2})$ where $j_{k_1}$ and  $j_{k_2}$ are not
zero.

\begin{lstlisting}{}
    // two vertices on different cycles of different lengths
    for(vlen1=1; vlen1<=vmxlen; vlen1++){
        for(vlen2=vlen1+1; vlen2<=vmxlen; vlen2++){
            inst1 = [[vmset objectAtIndex:vlen1-1] intValue];
            inst2 = [[vmset objectAtIndex:vlen2-1] intValue];

            if(inst1 && inst2){
\end{lstlisting}

The number of steps is the LCM of the lengths of the two
cycles. E.g. for a cycle of length $2$ and one of length $3$, we visit
$11$, $22$, $13$, $21$, $12$, $23$ and $11$, a total of six
steps. There are $k_1 k_2$ possible edges for each of $j_{k_1}
j_{k_2}$ pairs of vertex cycles.

\begin{lstlisting}{}
                elen = vlen1*vlen2/gcd(vlen1, vlen2);
                instcount = vlen1*vlen2;
                instcount *= inst1*inst2;

                instcount /= elen;
                AddToMSet(emset, elen, instcount);
                if(elen>upper){
                    upper = elen;
                }
            }
        }
    }
\end{lstlisting}

The edge permutation shape is now ready. We remove any zeros that may
remain at the upper end.

\begin{lstlisting}{}
    if(upper<emxlen){
        [emset
            removeObjectsInRange:
                NSMakeRange(upper, emxlen-upper)];
    }

    return emset;
}
\end{lstlisting}

The remaining functions implement basic arithmetic for polynomials in
one variable. We use algorithms that suffice for our needs. E.g. we do
not implement polynomial multiplication by the FFT.

\subsubsection{Implementation II: Polynomials}

Polynomials are represented by arrays of {\tt GMPInt}
coefficients. Start with a very basic polynomial, namely the term
$f(z^k)$, i.e. $1+z^k.$ We set all coefficients except for the
constant term and $z^k$ to zero.

\begin{lstlisting}{}
NSMutableArray *PolyK(int k)
{
    NSMutableArray *p
        = [NSMutableArray arrayWithCapacity:k+1];
    int l;
    GMPInt *zero = [GMPInt zeroObj], *one = [GMPInt oneObj];

    [p addObject:one];
    for(l=1; l<k; l++){
        [p addObject:zero];
    }
    [p addObject:one];

    return p;
}
\end{lstlisting}

We add polynomials by iterating over their coefficients and computing
the sum of the coefficients of like powers.

\begin{lstlisting}{}
NSMutableArray *PolySum(NSMutableArray *p1, NSMutableArray *p2)
{
    int c1 = [p1 count], c2 = [p2 count];
    int mx = (c1>c2 ? c1 : c2), pos;
    GMPInt *zero = [GMPInt zeroObj];

    NSMutableArray *sum =
        [NSMutableArray arrayWithCapacity:mx];

    for(pos=0; pos<mx; pos++){
\end{lstlisting}

Polynomials of different degrees are handled by checking whether the
current power is present in the polynomial and using a zero value
otherwise.

\begin{lstlisting}{}
        GMPInt
            *n1 = (pos < c1 ? [p1 objectAtIndex:pos] : zero),
            *n2 = (pos < c2 ? [p2 objectAtIndex:pos] : zero),
            *res = [n1 add:n2];
        [sum addObject:res];
    }

    return sum;
}
\end{lstlisting}

The product of two polynomials is computed by iterating over all
possible pairs of terms. The terms $a z^n$ and $b z^m$ yield $ab
z^{m+n}.$ We start by computing the degree of the product. The
coefficient array must have one more slot than this value (for the
constant term). We initialize the product to be empty.

\begin{lstlisting}{}
NSMutableArray *PolyProd(NSMutableArray *f1, NSMutableArray *f2)
{
    int c1 = [f1 count], c2 = [f2 count];
    int cap = c1+c2-1, p, p1, p2;
    GMPInt *zero = [GMPInt zeroObj];

    NSMutableArray *prod =
        [NSMutableArray arrayWithCapacity:cap];

    for(p=0; p<cap; p++){
        [prod addObject:zero];
    }
\end{lstlisting}

We iterate over the terms of the two polynomials. We have a term for
the product when both terms have non-zero coefficients.

\begin{lstlisting}{}
    for(p1=0; p1<c1; p1++){
        for(p2=0; p2<c2; p2++){
            GMPInt
                *n1 = [f1 objectAtIndex:p1],
                *n2 = [f2 objectAtIndex:p2];
            if([n1 isZero]==NO && [n2 isZero]==NO){
\end{lstlisting}

If this is the case, then we compute the degree of the product and its
coefficient, read the old value for the degree, increment it, and
write it back into the coefficient array of the product. We return the
result when we are done.

\begin{lstlisting}{}
                int ex = p1+p2;
		GMPInt
                    *prev = [prod objectAtIndex:ex],
                    *p = [n1 mul:n2],
                    *cur = [prev add:p];
                [prod replaceObjectAtIndex:ex
                      withObject:cur];
            }
        }
    }

    return prod;
}
\end{lstlisting}

We need to be able to compute powers of polynomials $p$ because a term
like $a_k^m$ in the cycle index requires us to compute $(1+z^k)^m.$
This particular example can be computed with the binomial theorem, but
we use a generic routine that uses $\log m$ multiplications. The base
cases are first: one when the exponent is zero and $p$ when the
exponent is one.

\begin{lstlisting}{}
NSMutableArray *PolyPow(NSMutableArray *p, unsigned int ex)
{
    NSMutableArray *factor = p, 
        *res = 
        [NSMutableArray
            arrayWithObject:[GMPInt oneObj]];

    if(!ex){
        return res;
    }

    if(ex==1){
        return p;
    }
\end{lstlisting}

We now process the bits of the exponent in turn, starting with the
least significant bit. This is a folklore algorithm, too. If the bit
$b$ is set, then we include $p^{2^b}$ in the product. We obtain
$p^{2^b}$ by squaring $p^{2^{b-1}}.$

\begin{lstlisting}{}
    while(ex){
        if(ex%2){
            res = PolyProd(res, factor);
        }
        ex >>= 1;
        factor = PolyProd(factor, factor);
    }

    return res;
}
\end{lstlisting}

The next two routines in this section are very similar. We use them
either to multiply the coefficients of a polynomial by some integer
value, or to divide them by an integer value.

Multiplication is first. We iterate over the terms with a loop.

\begin{lstlisting}{}
NSMutableArray *PolyScaleMul(NSMutableArray *p, GMPInt *f)
{
    int pos, mx = [p count];
    NSMutableArray *res =
        [NSMutableArray arrayWithCapacity:mx];
    GMPInt *zero = [GMPInt zeroObj];

    for(pos=0; pos<mx; pos++){
\end{lstlisting}

If we find a non-zero coefficient, then we multiply it by the factor
$f$ and record the new value.

\begin{lstlisting}{}
        GMPInt
            *prev = [p objectAtIndex:pos], 
            *cur = zero;
        if([prev isZero]==NO){
            cur = [prev mul:f];
        }
        [res addObject:cur];
    }

    return res;
}
\end{lstlisting}

Division works the same way. We will use these two routines to scale
terms of the cycle index by their coefficients and average the
substituted cycle index at the very end.

\begin{lstlisting}{}
NSMutableArray *PolyScaleDiv(NSMutableArray *p, GMPInt *f)
{
    int pos, mx = [p count];
    NSMutableArray *res =
        [NSMutableArray arrayWithCapacity:mx];
    GMPInt *zero = [GMPInt zeroObj];

    for(pos=0; pos<mx; pos++){
	GMPInt
            *prev = [p objectAtIndex:pos], 
            *cur = zero;
        if([prev isZero]==NO){
            cur = [prev div:f];
        }
        [res addObject:cur];
    }

    return res;
}
\end{lstlisting}

At this point we have all the support that needs to be in place for us
to be able to actually substitute $1+z$ into a term from the cycle
index. We must replace $a_k$ by $(1+z^k)$ in the product
$\prod_{k=1}^p a_k^{j_k}.$ This is what the next routine does. It
iterates over the $j_k$ and looks for nonzero values.

\begin{lstlisting}{}
NSMutableArray *MSetToPoly(NSMutableArray *mset)
{
    NSMutableArray 
        *res = 
        [NSMutableArray
            arrayWithObject:[GMPInt oneObj]];
 
    int pos, mx = [mset count];

    for(pos=0; pos<mx; pos++){
        int e = [[mset objectAtIndex:pos] intValue];
        if(e){
\end{lstlisting}

If it finds such a value, then it includes the term $(1+z^k)^{j_k}$ in
the product. The last step is to return the result. E.g. this will
transform $a_1 \, a_2^3$ into $z^7+z^6+3z^5+3z^4+3z^3+3z^2+z+1.$

\begin{lstlisting}{}
            res = PolyProd(res, PolyPow(PolyK(pos+1), e));
        }
    }

    return res;
}
\end{lstlisting}

We promised extensive debug facilities and hence we need to be able to
convert polynomials into strings that we can output during
debugging. We do this in the next routine by computing the individual
terms and joining them by interpolating plus signs. We use the \LaTeX
\hspace{3pt} format, which is readable and ready for inclusion into
\LaTeX \hspace{3pt} documents.

We iterate over the terms and skip empty ones, processing the others
and storing the coefficient string in the variable {\tt cfStr}.

\begin{lstlisting}{}
NSString *PolyToString(NSMutableArray *p)
{
    int pos, mx = [p count];
    NSMutableArray *terms =
        [NSMutableArray arrayWithCapacity:mx];

    for(pos=0; pos<mx; pos++){
        GMPInt *coeff = [p objectAtIndex:pos];
        
        if([coeff isZero]==YES){
            continue;
        }

        NSString 
            *cfstr = [coeff stringValue], *term;
\end{lstlisting}

The constant term is identical to its coefficient.

\begin{lstlisting}{}
        if(!pos){
            term = cfstr;
        }
\end{lstlisting}

The term for $z$ is either $z$ when the coefficient $q$ is one, and
$qz$ otherwise.

\begin{lstlisting}{}
        else if(pos==1){
            if([coeff isOne]==YES){
                term = @"z";
            }
            else{
                term = 
                    [NSString stringWithFormat:
                                  @"%@ z", cfstr];
            }
        }
\end{lstlisting}

The term for $q z^k$ where $k>1$ is $z^k$ when $q$ is one and $q z^k$
otherwise.

\begin{lstlisting}{}
        else{
            if([coeff isOne]==YES){
                term =
                    [NSString stringWithFormat:
                                  @"z^{%d}", pos];
            }
            else{
                term =
                    [NSString stringWithFormat:
                                  @"%@ z^{%d}", cfstr, pos];
            }
        }

        [terms addObject:term];
    }
\end{lstlisting}

The routine returns the terms, joined by a plus sign.

\begin{lstlisting}{}
    return [terms componentsJoinedByString:@" + "];
}
\end{lstlisting}

\subsubsection{Implementation III: P\'olya's theorem}

Counting graphs is easy with the set of routines that we have
presented and we can concentrate on the high-level aspects of the
algorithm. Our program needs a bit of an interface; it will process
the command line and accept two arguments, the first of which is an
optional switch {\tt -d}, which turns on debugging, and the second or
third gives $n$, the number of vertices of the graphs.

We need an autorelease pool as explained earlier. We also need the
command line arguments if we want to process them. 

\begin{lstlisting}{}
int main(int argc, char** argv, char **env)
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    NSProcessInfo *procInfo = [NSProcessInfo processInfo];
    NSArray *args = [procInfo arguments];
    int ac = [args count];

    NSString *nstr;
\end{lstlisting}

The first thing we do before any other processing is to clear the
debug flag and declare an array of classes whose memory allocation we
wish to debug. In the case of mutable arrays and strings we obtain the
class from an instance rather than the class itself. This is because
these two classes produce instances whose class is not the same as the
class that was asked to instantiate itself. We also initialize an
array of allocation counters that allow  us to test when allocation
has doubled and empty the autorelease pool if this is the case. The
variable {\tt cl} is used to iterate over the array of classes.

\begin{lstlisting}{}
    BOOL debug = NO;

    Class todebug[] = { 
        [GMPInt class],
        [[NSMutableArray array] class],
        [[NSString stringWithFormat:@"instance %d", 0] class],
        nil
        }, *current;
    int allocs[] = {
        0, 0, 0
    };
    GSDebugAllocationActive(YES);
    BOOL gc; id cl; int cind;
\end{lstlisting}

We still have some basic command line processing to do. We require two
or three arguments; everything else is an error. (The arguments
include the program name.)

\begin{lstlisting}{}
    if(ac!=2 && ac!=3){
        [NSException raise:NSInvalidArgumentException
                     format:@"usage: %@ [-d] <n>",
                     [procInfo processName]];
    }
\end{lstlisting}

If we have three arguments, then the second one must be the debug
flag. We raise an exception if it isn't.

\begin{lstlisting}{}
    if(ac==3 && 
       [[args objectAtIndex:1] isEqualToString:@"-d"]==NO){
        [NSException raise:NSInvalidArgumentException
                     format:@"'-d' expected, got %@",
                     [args objectAtIndex:1]];
    }
\end{lstlisting}

We turn debugging on if we did get a debug flag and extract the string
for $n$ from the third position.

\begin{lstlisting}{}
    else if(ac==3){
        nstr = [args objectAtIndex:2];
        debug = YES;
    }
\end{lstlisting}

The string for $n$ is in the second position if there was no debug
flag.

\begin{lstlisting}{}
    else{
        nstr = [args objectAtIndex:1];
    }
\end{lstlisting}

We instantiate a scanner so that we can extract the value from the
argument string for $n.$ We raise an exception if the scanner could
not read an integer or if it wasn't positive. Otherwise we initialize
{\tt t}, which is the number of edges.

\begin{lstlisting}{}
    NSScanner *scn = [NSScanner scannerWithString:nstr];
    int n = -1;
    if([scn scanInt:&n]==NO || n<1){
        [NSException raise:NSInvalidArgumentException
                     format:@"positive vertex count, please; "
                     @"got %d", n];
    }
    int t = n*(n-1)/2, s;
\end{lstlisting}

We can now prepare for the computation. We compute $n!$ and store the
value in $f$, retaining $f$. We need $f$ as the numerator of the
coefficient of a product term in the cycle index and to check that the
coefficients of those terms really do add up to $n!$ This is the
purpose of the checksum.

\begin{lstlisting}{}
    GMPInt *f = [GMPInt factorialUI:n],
        *vertexCheckSum = [GMPInt zeroObj];
    [f retain]; [vertexCheckSum retain];
\end{lstlisting}

We will be iterating over partitions, turning them into vertex
permutations first and then edge permutations, finally substituting
them with $1+z.$ The variable {\tt psum} holds the sum of the terms
that we have processed so far. It is a polynomial and starts out being
zero.

\begin{lstlisting}{}
    NSMutableArray *psum =
        [NSMutableArray 
            arrayWithObject:
                [GMPInt zeroObj]];
    [psum retain];
\end{lstlisting}

We are ready for the first step, i.e. computing the partitions. We
store and retain the result so that it will not be released. We must
also retain the enumerator that we use to iterate over the
partitions. We may now start the iteration itself.

\begin{lstlisting}{}
    NSMutableArray *part, *parts = Partitions(n);
    [parts retain];

    NSEnumerator *en = [parts objectEnumerator];
    [en retain];

    while((part = [en nextObject])!=nil){
\end{lstlisting}

First we convert the partition to a vertex permutation shape, then we
convert that shape in turn into an edge permutation shape. We compute
the denominator of the coefficient. The numerator is $n!$. This yields
the coefficient.

\begin{lstlisting}{}
        NSMutableArray 
            *vmset = PartitionToMSet(part),
            *emset = VertexMSetToEdgeMSet(vmset);

        GMPInt *denom = MSetToCoeffDenom(vmset),
            *coeff = [f div:denom];
\end{lstlisting}

We add the coefficient to the checksum and do the substitution of
$1+z^k$ for $a_k$ in the edge permutation multiset.

\begin{lstlisting}{}
        [vertexCheckSum autorelease];
        vertexCheckSum = [vertexCheckSum add:coeff];
        [vertexCheckSum retain];

        NSMutableArray *poly = MSetToPoly(emset);
\end{lstlisting}

We temporarily leave the computation in order to output debugging
information if the user did activate the debug feature. We convert the
current cycle multisets for the vertex and the edge permutation to
strings and output them together with the coefficient and the
polynomial we obtained.

\begin{lstlisting}{}
        if(debug==YES){
            NSString 
                *vprod = MSetToProduct(vmset),
                *eprod = MSetToProduct(emset);

            fprintf(stderr, "%s [ %s ] [ %s ] %s\n", 
                    [[coeff description] cString],
                    [vprod cString],
                    [eprod cString],
                    [PolyToString(poly) cString]);
        }
\end{lstlisting}

Now return to the computation. We release the old sum of the
substituted cycle index terms, compute the new sum, and retain it.

\begin{lstlisting}{}
        [psum autorelease];
        psum = PolySum(psum, PolyScaleMul(poly, coeff));
        [psum retain];
\end{lstlisting}

Two important consistency checks are next. The cycle lengths for the
vertex permutation must add up to $n,$ anything else is an error.

\begin{lstlisting}{}
        if((s=SumIt(vmset))!=n){
            [NSException
                raise:NSInternalInconsistencyException
                format:@"vertices don't add up: %d, %d",
                n, s];
        }
\end{lstlisting}

Similarly, the cycle lengths for the edge permutation must add up to
$t = 1/2 n (n-1).$

\begin{lstlisting}{}
        if((s=SumIt(emset))!=t){
            [NSException
                raise:NSInternalInconsistencyException
                format: @"edges don't add up: %d, %d", 
                t, s];
        }
\end{lstlisting}

We leave the computation for the second time, this time in order to
release objects that are no longer used. We start by setting the
release flag to off and compare the number of allocated objects of the
three classes that we track to the number of allocations that we have
recorded for them. If this value has more than doubled, then it is
time to release the pool.

\begin{lstlisting}{}
        gc = NO; 
        current=todebug;
        while(*current!=nil){
            cind = current-todebug;
            id cl=*current++;
            
            if(2*allocs[cind]<GSDebugAllocationCount(cl)){
                gc = YES;
                break;
            }
        }
\end{lstlisting}

We release the pool if necessary and record the new values for the
number of allocated objects from each class. This ends the body of the
loop and hence the actual computation.

\begin{lstlisting}{}
        if(gc==YES){
            if(debug==YES){
                fputs("GC ...\n", stderr);
            }
            [pool release];
            pool = [NSAutoreleasePool new];

	    current=todebug;
            while(*current!=nil){
                cind = current-todebug;
                id cl=*current++;
                
                allocs[cind] = GSDebugAllocationCount(cl);
            }
        }
    }
\end{lstlisting}

We subtract the actual total for the coefficients from $n!$ and record
all three values (n!, checksum, difference) in a string.

\begin{lstlisting}{}
    GMPInt *delta = [f sub:vertexCheckSum];
    NSString *csinfo =
        [NSString stringWithFormat:@"expected %@, "
                  @"got %@, difference %@",
                  [f stringValue],
                  vertexCheckSum, delta];
\end{lstlisting}

We raise an exception if the checksum and $n!$ do not match.

\begin{lstlisting}{}
    if([delta isZero]==NO){
            [NSException
                raise:NSInternalInconsistencyException
                format: @"checksum: %@", csinfo];
    }
\end{lstlisting}

We print some statistics if the user requested them, namely the
checksum summary and the allocation counts of all classes that we are
tracking.

\begin{lstlisting}{}
    if(debug==YES){
        fprintf(stderr, "\nchecksum: %s\n\n", [csinfo cString]);

        current=todebug;
        while(*current!=nil){
            cl=*current++;
            fprintf(stderr, "%s count %u total %u peak %u\n",
                    [NSStringFromClass(cl) cString],
                    GSDebugAllocationCount(cl),
                    GSDebugAllocationTotal(cl),
                    GSDebugAllocationPeak(cl));
        }
    }
\end{lstlisting}

We are done. It remains to average the cycle index by dividing the sum
of the polynomial terms by $n!$ and print the result. This is the
generating function that we are looking for. The term $q z^k$ where $1
\le k \le \half n (n-1)$ tells us that there are $q$ nonisomorphic
graphs with $k$ edges on $n$ vertices.

\begin{lstlisting}{}
    printf("%s\n",
           [PolyToString(PolyScaleDiv(psum, f)) cString]);

    [pool release];
    exit(0);
}
\end{lstlisting}

\subsubsection{Results}

These are the first few generating functions $g_n$ for small $n.$

\begin{eqnarray*}
g_2 & = & 1 + z \\
g_3 & = & 1 + z + z^{2} + z^{3} \\
g_4 & = & 1 + z + 2 z^{2} + 3 z^{3} + 2 z^{4} + z^{5} + z^{6} \\
g_5 & = & 1 + z + 2 z^{2} + 4 z^{3} + 6 z^{4} + 6 z^{5} + 6 z^{6} \\
& + & 4 z^{7} + 2 z^{8} + z^{9} + z^{10}\\
g_6 & = & 1 + z + 2 z^{2} + 5 z^{3} + 9 z^{4} + 15 z^{5} + 21 z^{6} \\
& + & 24 z^{7} + 24 z^{8} + 21 z^{9} + 15 z^{10} + 9 z^{11} \\
& + & 5 z^{12} + 2 z^{13} + z^{14} + z^{15}\\
g_7 & = & 1 + z + 2 z^{2} + 5 z^{3} + 10 z^{4} + 21 z^{5} \\
& + & 41 z^{6} + 65 z^{7} + 97 z^{8} + 131 z^{9} + 148 z^{10} \\
& + & 148 z^{11} + 131 z^{12} + 97 z^{13} + 65 z^{14} + 41 z^{15} \\
& + & 21 z^{16} + 10 z^{17} + 5 z^{18} + 2 z^{19} + z^{20} + z^{21} \\
g_8 & = & 1 + z + 2 z^{2} + 5 z^{3} + 11 z^{4} + 24 z^{5} \\
& + & 56 z^{6} + 115 z^{7} + 221 z^{8} + 402 z^{9} + 663 z^{10} \\
& + & 980 z^{11} + 1312 z^{12} + 1557 z^{13} + 1646 z^{14} \\
& + & 1557 z^{15} + 1312 z^{16} + 980 z^{17} + 663 z^{18} \\
& + & 402 z^{19} + 221 z^{20} + 115 z^{21} + 56 z^{22} \\
& + & 24 z^{23} + 11 z^{24} + 5 z^{25} + 2 z^{26} + z^{27} + z^{28} \\
\end{eqnarray*}

And here is an excerpt from the result for $n=32.$

\begin{eqnarray*}
& \ldots & \\
& + &
34761657216148743448344973243138057890667300337466944 
z^{72} \\
& + &
200461626459336565845980681588043820267288760177587840 
z^{73} \\
& + & 
1138648479398347554889254519273951546678680253899786257 
z^{74} \\
& + &
6371020632922419133637914798015058708350896416489205295 
z^{75} \\
& + &
35117687386619298252758128999284099659276881466816638923 
z^{76} \\
& + & 
190712745660577653411399573067088056308497057681671998323 
z^{77} \\
& + &
1020497580980184635651931255165238794997244766608114575302 
z^{78} \\
& + & 
5381036625283742958677377853029609055260579018816386455844 
z^{79} \\
& + &
27963157472855646088638121146117229104449204522412651394430 
z^{80} \\
& \ldots & \\
\end{eqnarray*}
