% generated by GAPDoc2LaTeX from XML source (Frank Luebeck)
\documentclass[a4paper,11pt]{report}
\usepackage{a4wide}
\sloppy
\pagestyle{myheadings}
\usepackage{amssymb}
\usepackage[latin1]{inputenc}
\usepackage{makeidx}
\makeindex
\usepackage{color}
\definecolor{DarkOlive}{rgb}{0.1047,0.2412,0.0064}
\definecolor{FireBrick}{rgb}{0.5812,0.0074,0.0083}
\definecolor{RoyalBlue}{rgb}{0.0236,0.0894,0.6179}
\definecolor{RoyalGreen}{rgb}{0.0236,0.6179,0.0894}
\definecolor{RoyalRed}{rgb}{0.6179,0.0236,0.0894}
\definecolor{LightBlue}{rgb}{0.8544,0.9511,1.0000}
\definecolor{Black}{rgb}{0.0,0.0,0.0}
\definecolor{FuncColor}{rgb}{1.0,0.0,0.0}
%% strange name because of pdflatex bug:
\definecolor{Chapter }{rgb}{0.0,0.0,1.0}

\usepackage{fancyvrb}

\usepackage{pslatex}

\usepackage{amsmath}\usepackage[pdftex=true,
        a4paper=true,bookmarks=false,pdftitle={Written with GAPDoc},
        pdfcreator={LaTeX with hyperref package / GAPDoc},
        colorlinks=true,backref=page,breaklinks=true,linkcolor=RoyalBlue,
        citecolor=RoyalGreen,filecolor=RoyalRed,
        urlcolor=RoyalRed,pagecolor=RoyalBlue]{hyperref}

% write page numbers to a .pnr log file for online help
\newwrite\pagenrlog
\immediate\openout\pagenrlog =\jobname.pnr
\immediate\write\pagenrlog{PAGENRS := [}
\newcommand{\logpage}[1]{\protect\write\pagenrlog{#1, \thepage,}}
%% were never documented, give conflicts with some additional packages


\newcommand{\GAP}{\textsf{GAP}}

\begin{document}

\logpage{[ 0, 0, 0 ]}
\begin{titlepage}
\begin{center}{\Huge \textbf{ \textsf{HAPprime} \mbox{}}}\\[1cm]
\hypersetup{pdftitle= \textsf{HAPprime} }
\markright{\scriptsize \mbox{}\hfill  \textsf{HAPprime}  \hfill\mbox{}}
{\Large \textbf{ Datatypes reference manual \mbox{}}}\\[1cm]
{Version 0.3\mbox{}}\\[1cm]
{10 December 2008\mbox{}}\\[1cm]
\mbox{}\\[2cm]
{\large \textbf{ Paul Smith\\
    \mbox{}}}\\
\hypersetup{pdfauthor= Paul Smith\\
    }
\end{center}\vfill

\mbox{}\\
{\mbox{}\\
\small \noindent \textbf{ Paul Smith\\
    } --- Email: \href{mailto://paul.smith@nuigalway.ie} {\texttt{paul.smith@nuigalway.ie}}\\
 --- Homepage: \href{http://www.maths.nuigalway.ie/~pas} {\texttt{http://www.maths.nuigalway.ie/\texttt{\symbol{126}}pas}}\\
 --- Address: \begin{minipage}[t]{8cm}\noindent
 Department of Mathematics,\\
 National University of Ireland, Galway\\
 Galway,\\
 Ireland. \end{minipage}
}\\
\end{titlepage}

\newpage\setcounter{page}{2}
{\small 
\section*{Copyright}
\logpage{[ 0, 0, 1 ]}
  {\copyright} 2006-2008 Paul Smith 

 \textsf{HAPprime} is released under the GNU General Public License (GPL). This file is part of \textsf{HAPprime}, though as documentation it is released under the GNU Free Documentation
License (see \href{http://www.gnu.org/licenses/licenses.html#FDL} {\texttt{http://www.gnu.org/licenses/licenses.html\#FDL}}). 

 \textsf{HAPprime} is free software; you can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version. 

 \textsf{HAPprime} is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details. 

 You should have received a copy of the GNU General Public License along with \textsf{HAPprime}; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
330, Boston, MA 02111-1307 USA 

 For more details, see \href{http://www.fsf.org/licenses/gpl.html} {\texttt{http://www.fsf.org/licenses/gpl.html}}. 

 \mbox{}}\\[1cm]
{\small 
\section*{Acknowledgements}
\logpage{[ 0, 0, 2 ]}
 \textsf{HAPprime} is supported by a Marie Curie Transfer of Knowledge grant based at the
Department of Mathematics, NUI Galway (MTKD-CT-2006-042685) \mbox{}}\\[1cm]
\newpage

\def\contentsname{Contents\logpage{[ 0, 0, 3 ]}}

\tableofcontents
\newpage

   
\chapter{\textcolor{Chapter }{Introduction}}\logpage{[ 1, 0, 0 ]}
\hyperdef{L}{X7DFB63A97E67C0A1}{}
{
  The \textsf{HAPprime} package is a \textsf{GAP} package which supplements the \textsf{HAP} package (\href{http://hamilton.nuigalway.ie/Hap/www/} {\texttt{http://hamilton.nuigalway.ie/Hap/www/}}), providing new and improved functions for doing homological algebra over
small prime-power groups. A detailed overview of the \textsf{HAPprime} package, with examples and documentation of the high-level functions, is
provided in the accompanying \textsf{HAPprime} user guide. 

 This document, the datatypes reference manual, supplements the \textsf{HAPprime} user guide. It describes the new \textsf{GAP} datatypes defined by the \textsf{HAPprime} package, and all of the associated functions for working with each of these
datatypes. The datatypes are 
\begin{description}
\item[{\texttt{FpGModuleGF}}]  (Chapter \ref{FpGModuleGF}) a free $\mathbb{F}G$-module compactly represented in terms of generating elements, with operations
that do as much manipulation as possible within this form, thus minimizing
memory use. 
\item[{\texttt{FpGModuleHomomorphismGF}}]  (Chapter \ref{FpGModuleGFHom}) a free linear homomorphism between two $\mathbb{F}G$-modules, each represented as a \texttt{FpGModuleGF}. this also uses the compact generator form to save memory in its operations. 
\item[{\texttt{HAPResolution}}]  (Chapter \ref{Resolution}) this datatype, defined in the \textsf{HAP} package, represents a free $\mathbb{F}G$-resolution of a $\mathbb{F}G$-module. \textsf{HAPprime} extends the definition of this datatype to save memory, and provides
additional functions to operate on resolutions. 
\item[{\texttt{HAPDerivation}}]  (Chapter \ref{Derivation}) a derivation over a polynomial ring $R$. In particular, \textsf{HAPprime} provides functions to calculate the kernel and homology of derivations for
polynomials over prime fields. 
\end{description}
 In addition, Chapter \ref{GeneralFunctions} provides documentation for some general functions defined in \textsf{HAPprime} which extend some of the basic \textsf{GAP} functionality in areas such as matrices and polynomials. 

 Each chapter of this reference manual begins with an overview of the datatype,
and then implementation details of any interesting functions. The function
reference of related functions then follows, subdivided into sections of
related functions. Examples demonstrating the use of each function are given
at the end of each section.   }

   
\chapter{\textcolor{Chapter }{Resolutions}}\label{Resolution}
\logpage{[ 2, 0, 0 ]}
\hyperdef{L}{X7C0B125E7D5415B4}{}
{
  A free $\mathbb{F}G$-resolution of an $\mathbb{F}G$-module $M$ is a sequence of module homomorphisms  
\[ \ldots \rightarrow M_{n+1} \rightarrow M_n \rightarrow M_{n-1} \rightarrow
\ldots \rightarrow M_1 \rightarrow M_0 \twoheadrightarrow M \]
   Where each $M_n$ is a free $\mathbb{F}G$-module and the image of $d_{n+1}: M_{n+1} \rightarrow M_{n}$ equals the kernel of $d_n: M_n \rightarrow M_{n-1}$ for all $n > 0$. 
\section{\textcolor{Chapter }{The \texttt{HAPResolution} datatype in \textsf{HAPprime}}}\logpage{[ 2, 1, 0 ]}
\hyperdef{L}{X86DA1C1B7EDE0DD8}{}
{
  Both \textsf{HAP} and \textsf{HAPprime} use the \texttt{HAPResolution} datatype to store resolutions, and you should refer to the \textsf{HAP} documentation for full details of this datatype. With resolutions computed by \textsf{HAP}, the boundary maps which define the module homomorphisms are stored as lists
of $\mathbb{Z}G$-module words, each of which is an integer pair \texttt{[i,g]}. By contrast, when \textsf{HAPprime} computes resolutions it stores the boundary maps as lists of $G$-generating vectors (as used in \texttt{FpGModuleHomomorphismGF}, see Chapter \ref{FpGModuleGFHom}). Over small finite fields (and in particular in GF(2)), these compressed
vectors take far less memory, saving at least a factor of two for long
resolutions. The different data storage method is entirely an internal change
- as far as the used is concerned, both versions behave exactly the same. }

 
\section{\textcolor{Chapter }{Implementation: Constructing resolutions}}\logpage{[ 2, 2, 0 ]}
\hyperdef{L}{X7D3C5D987DEB2360}{}
{
  Given the definition of a free $\mathbb{F}G$-resolution given above, a resolution of a module $M$ can be calculated by construction. If there are $k$ generators for $M$, we can set $M_0$ equal to the free $\mathbb{F}G$-module $(\mathbb{F}G)^k$, and the module homomorphism $d_0 : M_0 \rightarrow M$ to be the one that sends the $i$th standard generator of $(\mathbb{F}G)^k$ to the $i$th element of $M$. We can now recursively construct the other modules and module homomorphisms
in a similar manner. Given a boundary homomorphism $d_n = M_n \rightarrow M_{n-1}$, the kernel of this can be calculated. Then given a set of generators
(ideally a small set) for $ker(d_n)$, we can set $M_{n+1} = (\mathbb{F}G)^{|ker(d_n)|}$, and the new module homomorphism $d_{n+1}$ to be the one mapping the standard generators of $M_{n+1}$ onto the generators of $ker(d_n)$. 

 \textsf{HAPprime} implements the construction of resolutions using this method. The construction
is divided into two stages. The creation of the first homomorphism in the
resolution for $M$ is performed by the function \texttt{LengthZeroResolutionPrimePowerGroup} (\ref{LengthZeroResolutionPrimePowerGroup}), or for a resolution of the trivial $\mathbb{F}G$-module $\mathbb{F}$, the first two homomorphisms can be stated without calculation using \texttt{LengthOneResolutionPrimePowerGroup} (\ref{LengthOneResolutionPrimePowerGroup}). Once this initial sequence is created, a longer resolution can be created by
repeated application of one of \texttt{ExtendResolutionPrimePowerGroupGF} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupGF}), \texttt{ExtendResolutionPrimePowerGroupRadical} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupRadical}) or \texttt{ExtendResolutionPrimePowerGroupGF2} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupGF2}), each of which extends the resolution by one stage by constructing a new
module and homomorphism mapping onto the minimal generators of the kernel of
the last homomorphism of the input resolution. These extension functions
differ in speed and the amount of memory that they use. The lowest-memory
version, \texttt{ExtendResolutionPrimePowerGroupGF} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupGF}), uses the block structure of module generating vectors (see Section \ref{FpGModuleGFalgoblock}) and calculates kernels of the boundary homomorphisms using \texttt{KernelOfModuleHomomorphismSplit} (\ref{KernelOfModuleHomomorphismSplit}) and finds a minimal set of generators for this kernel using \texttt{MinimalGeneratorsModuleGF} (\ref{MinimalGeneratorsModuleGF}). The much faster but memory-hungry \texttt{ExtendResolutionPrimePowerGroupRadical} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupRadical}) uses \texttt{KernelOfModuleHomomorphism} (\ref{KernelOfModuleHomomorphism}) and \texttt{MinimalGeneratorsModuleRadical} (\ref{MinimalGeneratorsModuleRadical}) respectively. \texttt{ExtendResolutionPrimePowerGroupGF2} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupGF2}) uses \texttt{KernelOfModuleHomomorphismGF} (\ref{KernelOfModuleHomomorphismGF}) whic partitions the boundary homomorphism matrix using $\mathbb{F}G$-reduction. This gives a small memory saving over the \texttt{Radical} method, but can take as long as the \texttt{GF} scheme. 

 The construction of resolutions of length $n$ is wrapped up in the functions \texttt{ResolutionPrimePowerGroupGF}, \texttt{ResolutionPrimePowerGroupRadical} and \texttt{ResolutionPrimePowerGroupAutoMem}, which (as well as the extension functions) are fully documented in Section  (\textbf{HAPprime: ResolutionPrimePowerGroup}) of the \textsf{HAPprime} user manual. }

 
\section{\textcolor{Chapter }{Resolution construction functions}}\logpage{[ 2, 3, 0 ]}
\hyperdef{L}{X7D61ADD17A4CF194}{}
{
  

\subsection{\textcolor{Chapter }{LengthOneResolutionPrimePowerGroup}}
\logpage{[ 2, 3, 1 ]}\nobreak
\hyperdef{L}{X784BCF7C801B6E8E}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{LengthOneResolutionPrimePowerGroup({\slshape G})\index{LengthOneResolutionPrimePowerGroup@\texttt{LengthOneResolutionPrimePowerGroup}}
\label{LengthOneResolutionPrimePowerGroup}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPResolution} 



 Returns a free $\mathbb{F}G$-resolution of length 1 for group \mbox{\texttt{\slshape G}} (which must be of a prime power), i.e. the resolution  
\[ \mathbb{F}G^{k_1} \rightarrow \mathbb{F}G \twoheadrightarrow \mathbb{F} \]
   This function requires very little calculation: the first stage of the
resolution can simply be stated given a set of minimal generators for the
group. }

 

\subsection{\textcolor{Chapter }{LengthZeroResolutionPrimePowerGroup}}
\logpage{[ 2, 3, 2 ]}\nobreak
\hyperdef{L}{X8311B9697B5F7685}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{LengthZeroResolutionPrimePowerGroup({\slshape M})\index{LengthZeroResolutionPrimePowerGroup@\texttt{LengthZeroResolutionPrimePowerGroup}}
\label{LengthZeroResolutionPrimePowerGroup}
}\hfill{\scriptsize (function)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPResolution} 



 Returns a minimal free $\mathbb{F}G$-resolution of length 0 for the \texttt{FpGModuleGF} module \mbox{\texttt{\slshape M}}, i.e. the resolution  
\[ \mathbb{F}G^{k_0} \twoheadrightarrow M \]
   This function requires little calculation since the the first stage of the
resolution can simply be stated if the module has minimal generators: each
standard generator of the zeroth-degree module $M_0$ maps onto a generator of \mbox{\texttt{\slshape M}}. If \mbox{\texttt{\slshape M}} does not have minimal generators, they are calculated using \texttt{MinimalGeneratorsModuleRadical} (\ref{MinimalGeneratorsModuleRadical}). }

 }

 
\section{\textcolor{Chapter }{Resolution data access functions}}\logpage{[ 2, 4, 0 ]}
\hyperdef{L}{X84AD05E17FA85CB1}{}
{
  

\subsection{\textcolor{Chapter }{ResolutionLength}}
\logpage{[ 2, 4, 1 ]}\nobreak
\hyperdef{L}{X83F7747D8585608C}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ResolutionLength({\slshape R})\index{ResolutionLength@\texttt{ResolutionLength}}
\label{ResolutionLength}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the length (i.e. the maximum index $k$) in the resolution \mbox{\texttt{\slshape R}}. }

 

\subsection{\textcolor{Chapter }{ResolutionGroup}}
\logpage{[ 2, 4, 2 ]}\nobreak
\hyperdef{L}{X806048907CE5B7B6}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ResolutionGroup({\slshape R})\index{ResolutionGroup@\texttt{ResolutionGroup}}
\label{ResolutionGroup}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
 Group 



 Returns the group of the resolution \mbox{\texttt{\slshape R}}. }

 

\subsection{\textcolor{Chapter }{ResolutionFpGModuleGF}}
\logpage{[ 2, 4, 3 ]}\nobreak
\hyperdef{L}{X7FF354AC7EEE2197}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ResolutionFpGModuleGF({\slshape R, k})\index{ResolutionFpGModuleGF@\texttt{ResolutionFpGModuleGF}}
\label{ResolutionFpGModuleGF}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
 \texttt{FpGModuleGF} 



 Returns the module $M_k$ in the resolution \mbox{\texttt{\slshape R}}, as a \texttt{FpGModuleGF} (see Chapter \ref{FpGModuleGF}), assuming the canonical action. }

 

\subsection{\textcolor{Chapter }{ResolutionModuleRank}}
\logpage{[ 2, 4, 4 ]}\nobreak
\hyperdef{L}{X7AFBE74B85AC3D85}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ResolutionModuleRank({\slshape R, k})\index{ResolutionModuleRank@\texttt{ResolutionModuleRank}}
\label{ResolutionModuleRank}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the $\mathbb{F}G$ rank of the \mbox{\texttt{\slshape k}}th module $M_k$ in the resolution. }

 

\subsection{\textcolor{Chapter }{ResolutionModuleRanks}}
\logpage{[ 2, 4, 5 ]}\nobreak
\hyperdef{L}{X7EBA188478844D96}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ResolutionModuleRanks({\slshape R})\index{ResolutionModuleRanks@\texttt{ResolutionModuleRanks}}
\label{ResolutionModuleRanks}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
 List of integers 



 Returns a list containg the $\mathbb{F}G$ rank of the each of the modules $M_k$ in the resolution \mbox{\texttt{\slshape R}}. }

 

\subsection{\textcolor{Chapter }{BoundaryFpGModuleHomomorphismGF}}
\logpage{[ 2, 4, 6 ]}\nobreak
\hyperdef{L}{X803528CD872A1F4C}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BoundaryFpGModuleHomomorphismGF({\slshape R, k})\index{BoundaryFpGModuleHomomorphismGF@\texttt{BoundaryFpGModuleHomomorphismGF}}
\label{BoundaryFpGModuleHomomorphismGF}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
 \texttt{FpGModuleHomomorphismGF} 



 Returns the \mbox{\texttt{\slshape k}}th boundary map in the resolution \mbox{\texttt{\slshape R}}, as a \texttt{FpGModuleHomomorphismGF}. This represents the linear homomorphism $d_k: M_k \rightarrow M_{k-1}$. }

 

\subsection{\textcolor{Chapter }{ResolutionsAreEqual}}
\logpage{[ 2, 4, 7 ]}\nobreak
\hyperdef{L}{X7FB150F67DAF9059}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ResolutionsAreEqual({\slshape R, S})\index{ResolutionsAreEqual@\texttt{ResolutionsAreEqual}}
\label{ResolutionsAreEqual}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Boolean 



 Returns \texttt{true} if the resolutions appear to be equal, \texttt{false} otherwise. This compares the torsion coefficients of the homology from the two
resolutions. }

 }

 
\section{\textcolor{Chapter }{Example: Computing and working with resolutions}}\label{ResolutionExample}
\logpage{[ 2, 5, 0 ]}
\hyperdef{L}{X81D7C767813647B3}{}
{
  In this example we construct a minimal free $\mathbb{F}G$-resolution of length four for the group $G = D_8 \times Q_8$ of order 64, which will be the sequence  
\[ (\mathbb{F}G)^{22} \rightarrow (\mathbb{F}G)^{15} \rightarrow (\mathbb{F}G)^9
\rightarrow (\mathbb{F}G) \twoheadrightarrow \mathbb{F} \]
   We first build each stage explicitly, starting with \texttt{LengthOneResolutionPrimePowerGroup} (\ref{LengthOneResolutionPrimePowerGroup}) followed by repeated applications of \texttt{ExtendResolutionPrimePowerGroupRadical} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupRadical}). We extract various properties of this resolution. Finally, we construct
equivalent resolutions for $G$ using \texttt{ResolutionPrimePowerGroupGF} (\textbf{HAPprime: ResolutionPrimePowerGroupGF (for group)}) and \texttt{ResolutionPrimePowerGroupGF2} (\textbf{HAPprime: ResolutionPrimePowerGroupGF2 (for group)}) and check that the three are equivalent.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> G := DirectProduct(DihedralGroup(8), SmallGroup(8, 4));
  <pc group of size 64 with 6 generators>
  gap> R := LengthOneResolutionPrimePowerGroup(G);
  Resolution of length 1 in characteristic 2 for <pc group of size 64 with
  6 generators> .
  No contracting homotopy available.
  A partial contracting homotopy is available.
  
  gap> R := ExtendResolutionPrimePowerGroupRadical(R);;
  gap> R := ExtendResolutionPrimePowerGroupRadical(R);;
  gap> R := ExtendResolutionPrimePowerGroupRadical(R);
  Resolution of length 4 in characteristic 2 for <pc group of size 64 with
  6 generators> .
  No contracting homotopy available.
  A partial contracting homotopy is available.
  
  gap> #
  gap> ResolutionLength(R);
  4
  gap> ResolutionGroup(R);
  <pc group of size 64 with 6 generators>
  gap> ResolutionModuleRanks(R);
  [ 4, 9, 15, 22 ]
  gap> ResolutionModuleRank(R, 3);
  15
  gap> M2 := ResolutionFpGModuleGF(R, 2);
  Full canonical module FG^9 over the group ring of <pc group of size 64 with
  6 generators> in characteristic 2
  
  gap> d3 := BoundaryFpGModuleHomomorphismGF(R, 3);
  <Module homomorphism>
  
  gap> ImageOfModuleHomomorphism(d3);
  Module over the group ring of <pc group of size 64 with
  6 generators> in characteristic 2 with 15 generators in FG^9.
  
  gap> #
  gap> S := ResolutionPrimePowerGroupGF(G, 4);
  Resolution of length 4 in characteristic 2 for <pc group of size 64 with
  6 generators> .
  No contracting homotopy available.
  A partial contracting homotopy is available.
  
  gap> ResolutionsAreEqual(R, S);
  true
  gap> T := ResolutionPrimePowerGroupGF2(G, 4);
  Resolution of length 4 in characteristic 2 for <pc group of size 64 with
  6 generators> .
  No contracting homotopy available.
  A partial contracting homotopy is available.
  
  gap> ResolutionsAreEqual(R, T);
  true
\end{Verbatim}
 

 Further example of constructing resolutions and extracting data from them are
given in Sections \ref{FPGModuleExample1}, \ref{FPGModuleExample2}, \ref{FPGModuleExample3}, \ref{FPGModuleHomExample1} and \ref{FPGModuleHomExample2} in this reference manual, and also the chapter of  (\textbf{HAPprime: Examples}) in the \textsf{HAPprime} user guide. }

 
\section{\textcolor{Chapter }{Miscellaneous resolution functions}}\logpage{[ 2, 6, 0 ]}
\hyperdef{L}{X79487D6C80383A6A}{}
{
  

\subsection{\textcolor{Chapter }{BestCentralSubgroupForResolutionFiniteExtension}}
\logpage{[ 2, 6, 1 ]}\nobreak
\hyperdef{L}{X7AB2536286A7324D}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BestCentralSubgroupForResolutionFiniteExtension({\slshape G[, n]})\index{BestCentralSubgroupForResolutionFiniteExtension@\texttt{Best}\-\texttt{Central}\-\texttt{Subgroup}\-\texttt{For}\-\texttt{Resolution}\-\texttt{Finite}\-\texttt{Extension}}
\label{BestCentralSubgroupForResolutionFiniteExtension}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Group 



 Returns the central subgroup of \mbox{\texttt{\slshape G}} that is likely to give the smallest module ranks when using the \textsf{HAP} function \texttt{ResolutionFiniteExtension} (\textbf{HAP: ResolutionFiniteExtension}). That function computes a non-minimal resolution for \mbox{\texttt{\slshape G}} from the twisted tensor product of resolutions for a normal subgroup $N \vartriangleleft G$  and the quotient group $G/N$. The ranks of the modules in the resolution for $G$ are the products of the module ranks of the resolutions for these smaller
groups. This function tests \mbox{\texttt{\slshape n}} terms of the minimal resolutions for all the central subgroups of $G$ and the corresponding quotients to find the subgroup/quotient pair with the
smallest module ranks. If \mbox{\texttt{\slshape n}} is not provided, then $n=5$ is used. }

 }

 }

   
\chapter{\textcolor{Chapter }{Graded algebras}}\label{GradedAlgebra}
\logpage{[ 3, 0, 0 ]}
\hyperdef{L}{X8074AAF07A3E7D2C}{}
{
  A graded algebra $A$ is a ring that has a direct sum decomposition into Abelian additive groups
(called degrees)  
\[ A = \bigoplus_{n \in \mathbb{N}} A_n = A_0 \oplus A_1 \oplus A_2 \oplus \ldots \]
   and where multiplication of elements follows a grading such that  
\[ A_s \times A_r \longrightarrow A_{s+r} \]
   This means that for any elements $x \in A_s$ and $y \in A_r$, the product lies in degree $r+s$, i.e. $xy \in A_{s+r}$. 
\section{\textcolor{Chapter }{Graded algebras in \textsf{HAP} (and \textsf{HAPprime})}}\logpage{[ 3, 1, 0 ]}
\hyperdef{L}{X844F0654822DAFCC}{}
{
  Small finite algebras can be represented explicitly in \textsf{GAP} using a basis and a structure constant table  (\textbf{Tutorial: Algebras}), which specifies all products of basis elements. \textsf{HAP} extends this definition to provide a finite approximation to a graded algebra,
storing all basis elements and products up to a given degree, $n$. The graded algebras used by \textsf{HAP} add a new component to the algebra object \texttt{A}, the function \texttt{A!.degree(e)} which returns the degree of an algebra element \texttt{e}. 

 \textsf{HAPprime} uses this \textsf{HAP} algebra object and adds some attributes, providing information on the basis
and generators of the algebra. A ring presentation for this algebra can also
be computed and represented using the \texttt{GradedAlgebraPresentation} datatype (see Section \ref{GradedAlgebraPresentationDatatype}). }

 
\section{\textcolor{Chapter }{Data access functions}}\logpage{[ 3, 2, 0 ]}
\hyperdef{L}{X7DE3278D7E5DEE03}{}
{
  

\subsection{\textcolor{Chapter }{ModPRingGeneratorDegrees}}
\logpage{[ 3, 2, 1 ]}\nobreak
\hyperdef{L}{X78ED069183AD3EEA}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModPRingGeneratorDegrees({\slshape A})\index{ModPRingGeneratorDegrees@\texttt{ModPRingGeneratorDegrees}}
\label{ModPRingGeneratorDegrees}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns a list containing the degree of each generator in a minimal generating
set for the mod-$p$ cohomology ring \mbox{\texttt{\slshape A}}. The $i$th degree in the list corresponds to the $i$th generator returned by \texttt{ModPRingGenerators} (\textbf{HAP: ModPRingGenerators}) }

 

\subsection{\textcolor{Chapter }{ModPRingNiceBasis}}
\logpage{[ 3, 2, 2 ]}\nobreak
\hyperdef{L}{X780F21707FB7EFF4}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModPRingNiceBasis({\slshape A})\index{ModPRingNiceBasis@\texttt{ModPRingNiceBasis}}
\label{ModPRingNiceBasis}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns the information needed to convert the basis for \mbox{\texttt{\slshape A}} (see \texttt{Basis} (\textbf{Reference: Basis})) into a nicer basis consisting of only products of ring generators. The
function returns a pair of lists \texttt{[Coeff, Bas]}. The list \texttt{Coeff} is a change-of-basis matrix, where the $i$th row gives the standard basis element $i$ in terms of the nice basis. The list \texttt{Bas} can be used to form the new basis and is a list of integers where the $i$th 'nice basis' element is given by \texttt{Product(List(Bas[i], x-{\textgreater}Basis(A)[x]))}. 

 This attribute returns exactly the same list as is provided by component \texttt{A!.niceBasis} (see \texttt{ModPCohomologyRing} (\textbf{HAP: ModPCohomologyRing}), but automatically constructs this list if it is not available. }

 

\subsection{\textcolor{Chapter }{ModPRingNiceBasisAsPolynomials}}
\logpage{[ 3, 2, 3 ]}\nobreak
\hyperdef{L}{X7F40E8DA7AEC5CDC}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModPRingNiceBasisAsPolynomials({\slshape A})\index{ModPRingNiceBasisAsPolynomials@\texttt{ModPRingNiceBasisAsPolynomials}}
\label{ModPRingNiceBasisAsPolynomials}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 A list which gives the 'nice basis' of the algebra \mbox{\texttt{\slshape A}} (as returned by the second element of \texttt{ModPRingNiceBasis} (\ref{ModPRingNiceBasis})) in terms of products of the indeterminates in the ring presentation (as
given by \texttt{PresentationOfGradedStructureConstantAlgebra} (\ref{PresentationOfGradedStructureConstantAlgebra})). The $i$th entry in the list corresponds to the $i$th basis element returned by \texttt{ModPRingNiceBasis} (\ref{ModPRingNiceBasis}). }

 

\subsection{\textcolor{Chapter }{ModPRingBasisAsPolynomials}}
\logpage{[ 3, 2, 4 ]}\nobreak
\hyperdef{L}{X7E72445386B555DD}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModPRingBasisAsPolynomials({\slshape A})\index{ModPRingBasisAsPolynomials@\texttt{ModPRingBasisAsPolynomials}}
\label{ModPRingBasisAsPolynomials}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 A list which gives the basis of the algebra \mbox{\texttt{\slshape A}} (as returned by \texttt{Basis(A)}) in terms of sums of products of the indeterminates in the ring presentation
(as given by \texttt{PresentationOfGradedStructureConstantAlgebra} (\ref{PresentationOfGradedStructureConstantAlgebra})). The $i$th entry in the list corresponds to the $i$th basis element returned by \texttt{Basis} (\textbf{Reference: Basis}). }

 }

 
\section{\textcolor{Chapter }{Other functions}}\logpage{[ 3, 3, 0 ]}
\hyperdef{L}{X87C3D1B984960984}{}
{
  

\subsection{\textcolor{Chapter }{PresentationOfGradedStructureConstantAlgebra}}
\logpage{[ 3, 3, 1 ]}\nobreak
\hyperdef{L}{X79C71A2F878358BB}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PresentationOfGradedStructureConstantAlgebra({\slshape A})\index{PresentationOfGradedStructureConstantAlgebra@\texttt{Presentation}\-\texttt{Of}\-\texttt{Graded}\-\texttt{Structure}\-\texttt{Constant}\-\texttt{Algebra}}
\label{PresentationOfGradedStructureConstantAlgebra}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 \texttt{GradedAlgebraPresentation} 



 Returns a ring presentation for the graded algebra \mbox{\texttt{\slshape A}}. The ring \mbox{\texttt{\slshape A}} must be a structure constant algebra with embedded degrees, such as is
returned by \texttt{ModPCohomologyRing} (\textbf{HAP: ModPCohomologyRing}). The generators of the \texttt{GradedAlgebraPresentation} (as returned by \texttt{IndeterminatesOfGradedAlgebraPresentation} (\ref{IndeterminatesOfGradedAlgebraPresentation}) are in one-to-one correspondance with the generators of \mbox{\texttt{\slshape A}} as returned by \texttt{ModPRingGenerators} (\textbf{HAP: ModPRingGenerators}) (ignoring the first generator, which is in degree zero). }

 }

 
\section{\textcolor{Chapter }{Example: Graded algebras and mod-$p$ cohomology rings}}\label{RingsExample}
\logpage{[ 3, 4, 0 ]}
\hyperdef{L}{X790D62E37AA53C39}{}
{
  The mod-$p$ cohomology ring of a $p$-group is a graded algebra (see  (\textbf{HAPprime: Computing mod-p cohomology rings and their Poincar{\a'e} series})). As an example, we use the \textsf{HAP} function \texttt{ModPCohomologyRing} (\textbf{HAP: ModPCohomologyRing}) to compute this algebra for the quaternion group $Q_8$ up to and including degree five. We can display its generators and basis (and
degrees), and the information to construct a 'nice basis'  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> A := ModPCohomologyRing(SmallGroup(8, 4), 5);
  <algebra of dimension 9 over GF(2)>
  gap> Display(Basis(A));
  CanonicalBasis( Algebra( GF(2), [ v.1, v.2, v.3, v.4, v.5, v.6, v.7, v.8, v.9
   ] ) )
  gap> List(Basis(A), i->A!.degree(i));
  [ 0, 1, 1, 2, 2, 3, 4, 5, 5 ]
  gap> ModPRingGenerators(A);
  [ v.1, v.2, v.3, v.7 ]
  gap> ModPRingGeneratorDegrees(A);
  [ 0, 1, 1, 4 ]
  gap> ModPRingNiceBasis(A);
  [ [ [ 1, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0, 0, 0, 0 ],
        [ 0, 0, 1, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1, 0, 0, 0 ],
        [ 0, 0, 0, 0, 1, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 1 ],
        [ 0, 0, 0, 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0, 1, 0 ],
        [ 0, 0, 0, 0, 0, 0, 1, 1, 0 ] ],
    [ [ 1, 1, 1 ], [ 1, 1, 2 ], [ 1, 1, 3 ], [ 1, 1, 7 ], [ 1, 2, 2 ],
        [ 1, 2, 3 ], [ 1, 2, 7 ], [ 1, 3, 7 ], [ 2, 2, 3 ] ] ]
\end{Verbatim}
 A presentation for this algebra can be constructed using \texttt{PresentationOfGradedStructureConstantAlgebra} (\ref{PresentationOfGradedStructureConstantAlgebra}), which (see below) returns the presentation to be  
\[ H^*(G, \mathbb{F}) = \frac{\mathbb{F}[x_1,x_2,x_3]}{\langle x_1^2 + x_1x_2 +
x_2^2, x_2^3\rangle} \]
   where $x_1$ and $x_2$ have degree one and $x_3$ is degree four. The 'nice basis' referred to above is monomials of degree up
to five in this polynomial ring, and is not necessarily the same as the basis
of the algebra given by \texttt{Basis} (\textbf{Reference: Basis}), as demonstrated below.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> A := ModPCohomologyRing(SmallGroup(8, 4), 5);;
  gap> PresentationOfGradedStructureConstantAlgebra(A);
  Graded algebra GF(2)[ x_1, x_2, x_3 ] / [ x_1^2+x_1*x_2+x_2^2, x_2^3
   ] with indeterminate degrees [ 1, 1, 4 ]
  
  gap> ModPRingNiceBasisAsPolynomials(A);
  [ Z(2)^0, x_1, x_2, x_3, x_1^2, x_1*x_2, x_1*x_3, x_2*x_3, x_1^2*x_2 ]
  gap> ModPRingBasisAsPolynomials(A);
  [ Z(2)^0, x_1, x_2, x_1*x_2, x_1^2+x_1*x_2, x_1^2*x_2, x_3, x_2*x_3,
    x_1*x_3+x_2*x_3 ]
\end{Verbatim}
 }

 }

   
\chapter{\textcolor{Chapter }{Presentations of graded algebras}}\label{GradedAlgebraPresentationDatatype}
\logpage{[ 4, 0, 0 ]}
\hyperdef{L}{X7CF4153B7903F639}{}
{
  A graded algebra $A$ is a an algebra that has additional structure, called a grading (see Section \ref{GradedAlgebra}). Graded algebras of the type found in \textsf{HAPprime} have a presentation as a quotient of a polynomial ring  
\[ H^*(G, \mathbb{F}) = \frac{\mathbb{F}[x_1, x_2, \ldots, x_n]}{\langle I_1,
I_2, \ldots, I_m \rangle} \]
   where the polynomial ring indeterminates $x_i$ each have an associated degree $d_i$ and the $I_j$ are relations which together generate an ideal in the ring. 
\section{\textcolor{Chapter }{The \texttt{GradedAlgebraPresentation} datatype}}\logpage{[ 4, 1, 0 ]}
\hyperdef{L}{X7F7903AE8392D54A}{}
{
  For algebras that have a presentation as a quotient of a polynomial ring, the \texttt{GradedAlgebraPresentation} datatype stores a quotient $R/I$ where: 
\begin{itemize}
\item $R$ is a polynomial ring
\item $I$ is a set of relations in $R$ that generate an ideal
\end{itemize}
 and it also stores a grading in the form of 
\begin{itemize}
\item the degree of each indeterminate of $R$
\end{itemize}
 }

 
\section{\textcolor{Chapter }{Construction function}}\logpage{[ 4, 2, 0 ]}
\hyperdef{L}{X8589CD117D1ECD29}{}
{
  
\subsection{\textcolor{Chapter }{GradedAlgebraPresentation construction functions}}\label{GradedAlgebraPresentationConstructors}
\logpage{[ 4, 2, 1 ]}
\hyperdef{L}{X84A14CBF7C499665}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{GradedAlgebraPresentation({\slshape R, I, degs})\index{GradedAlgebraPresentation@\texttt{GradedAlgebraPresentation}}
\label{GradedAlgebraPresentation}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{GradedAlgebraPresentationNC({\slshape R, I, degs})\index{GradedAlgebraPresentationNC@\texttt{GradedAlgebraPresentationNC}}
\label{GradedAlgebraPresentationNC}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{GradedAlgebraPresentation} 



 Construct a \texttt{GradedAlgebraPresentation} object representing a presentation of a graded algebra as the quotient of a
polynomial ring \mbox{\texttt{\slshape R}} by the ideal \mbox{\texttt{\slshape I}} (as a list of relations in \mbox{\texttt{\slshape R}}) where the indeterminates of \mbox{\texttt{\slshape R}} (as returned by \texttt{IndeterminatesOfGradedAlgebraPresentation} (\ref{IndeterminatesOfGradedAlgebraPresentation}) have degrees \mbox{\texttt{\slshape degs}} respectively. 

 The function \texttt{GradedAlgebraPresentation} checks that the arguments are compatible, while the \texttt{NC} method performs no checks. }

 }

 
\section{\textcolor{Chapter }{Data access functions}}\logpage{[ 4, 3, 0 ]}
\hyperdef{L}{X7DE3278D7E5DEE03}{}
{
  

\subsection{\textcolor{Chapter }{BaseRing}}
\logpage{[ 4, 3, 1 ]}\nobreak
\hyperdef{L}{X877889A5792202F7}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{BaseRing({\slshape A})\index{BaseRing@\texttt{BaseRing}}
\label{BaseRing}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 Polynomial ring 



 Returns the base ring of the graded algebra presentation \mbox{\texttt{\slshape A}}. }

 

\subsection{\textcolor{Chapter }{CoefficientsRing}}
\logpage{[ 4, 3, 2 ]}\nobreak
\hyperdef{L}{X8235D10781BE8003}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{CoefficientsRing({\slshape A})\index{CoefficientsRing@\texttt{CoefficientsRing}}
\label{CoefficientsRing}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 Ring 



 Returns the ring of coefficients of the graded algebra presentation \mbox{\texttt{\slshape A}}. }

 

\subsection{\textcolor{Chapter }{IndeterminatesOfGradedAlgebraPresentation}}
\logpage{[ 4, 3, 3 ]}\nobreak
\hyperdef{L}{X844BB80282EA3EBA}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IndeterminatesOfGradedAlgebraPresentation({\slshape A})\index{IndeterminatesOfGradedAlgebraPresentation@\texttt{Indeterminates}\-\texttt{Of}\-\texttt{Graded}\-\texttt{Algebra}\-\texttt{Presentation}}
\label{IndeterminatesOfGradedAlgebraPresentation}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns the indeterminates used in the graded algebra presentation \mbox{\texttt{\slshape A}}. }

 

\subsection{\textcolor{Chapter }{GeneratorsOfPresentationIdeal}}
\logpage{[ 4, 3, 4 ]}\nobreak
\hyperdef{L}{X84299C5A7ACD6F71}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{GeneratorsOfPresentationIdeal({\slshape A})\index{GeneratorsOfPresentationIdeal@\texttt{GeneratorsOfPresentationIdeal}}
\label{GeneratorsOfPresentationIdeal}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns the relations in the ring presentation for the graded algebra \mbox{\texttt{\slshape A}}. The relations are returned sorted in order of increasing degree, and by
indeterminate within each degree. }

 

\subsection{\textcolor{Chapter }{PresentationIdeal}}
\logpage{[ 4, 3, 5 ]}\nobreak
\hyperdef{L}{X7DABCC1D85B33DAC}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PresentationIdeal({\slshape A})\index{PresentationIdeal@\texttt{PresentationIdeal}}
\label{PresentationIdeal}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 Ideal 



 Returns the ideal in the graded algebra presentation \mbox{\texttt{\slshape A}} as a \textsf{GAP} ideal  (\textbf{Reference: Ideal}). }

 

\subsection{\textcolor{Chapter }{IndeterminateDegrees}}
\logpage{[ 4, 3, 6 ]}\nobreak
\hyperdef{L}{X7BFB8AC97FE6BDD6}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IndeterminateDegrees({\slshape A})\index{IndeterminateDegrees@\texttt{IndeterminateDegrees}}
\label{IndeterminateDegrees}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns the degrees of the polynomial ring indeterminates in the graded
algebra presentation \mbox{\texttt{\slshape A}}. The ordering corresponds to the order of the ring indeterminates returned by \texttt{IndeterminatesOfGradedAlgebraPresentation} (\ref{IndeterminatesOfGradedAlgebraPresentation}). }

 
\subsection{\textcolor{Chapter }{Example: Constructing and accessing data of a \texttt{GradedAlgebraPresentation}}}\label{GradedAlgebraExample1}
\logpage{[ 4, 3, 7 ]}
\hyperdef{L}{X7DB98FC5869F4CBC}{}
{
  We demonstrate creating a \texttt{GradedAlgebraPresentation} object and reading back its data by creating the graded algebra $A$ with presentation $\mathbb{F}_2[x_1, x_2, x_3] / (x_1x_2, x_1^3+x_2^3)$ where $x_1$ and $x_2$ have degree 1 and $x_3$ has degree 4  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := PolynomialRing(GF(2), 3);;
  gap> A := GradedAlgebraPresentation(R, [R.1*R.2, R.1^3+R.2^3], [1,1,4]);
  Graded algebra GF(2)[ x_1, x_2, x_3 ] / [ x_1*x_2, x_1^3+x_2^3
   ] with indeterminate degrees [ 1, 1, 4 ]
  gap> BaseRing(A);
  GF(2)[x_1,x_2,x_3]
  gap> CoefficientsRing(A);
  GF(2)
  gap> IndeterminatesOfGradedAlgebraPresentation(A);
  [ x_1, x_2, x_3 ]
  gap> PresentationIdeal(A);
  <two-sided ideal in GF(2)[x_1,x_2,x_3], (2 generators)>
  gap> GeneratorsOfPresentationIdeal(A);
  [ x_1*x_2, x_1^3+x_2^3 ]
  gap> IndeterminateDegrees(A);
  [ 1, 1, 4 ]
\end{Verbatim}
 }

 }

 
\section{\textcolor{Chapter }{Other functions}}\logpage{[ 4, 4, 0 ]}
\hyperdef{L}{X87C3D1B984960984}{}
{
  
\subsection{\textcolor{Chapter }{TensorProduct}}\logpage{[ 4, 4, 1 ]}
\hyperdef{L}{X87EB0B4A852CF4C6}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{TensorProduct({\slshape A, B})\index{TensorProduct@\texttt{TensorProduct}!for two algebra presentations}
\label{TensorProduct:for two algebra presentations}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{TensorProduct({\slshape coll})\index{TensorProduct@\texttt{TensorProduct}!for collection of algebra presentations}
\label{TensorProduct:for collection of algebra presentations}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 GradedAlgebraPresentation 



 Returns a presentation for the graded algebra that is the tensor product of
two graded algebras presented by \mbox{\texttt{\slshape A}} and \mbox{\texttt{\slshape B}}, or of a list of graded algebras. }

 

\subsection{\textcolor{Chapter }{IsIsomorphicGradedAlgebra}}
\logpage{[ 4, 4, 2 ]}\nobreak
\hyperdef{L}{X8306E03281AF1CED}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IsIsomorphicGradedAlgebra({\slshape A, B})\index{IsIsomorphicGradedAlgebra@\texttt{IsIsomorphicGradedAlgebra}}
\label{IsIsomorphicGradedAlgebra}
}\hfill{\scriptsize (operation)}}\\


 Returns \texttt{true} if the graded algebras \mbox{\texttt{\slshape A}} and \mbox{\texttt{\slshape B}} are isomorphic, or \texttt{false} otherwise. This function tries all possible ring isomorphisms, so may take a
considerable length of time for graded algebras with a large number of
dimensions in each degree. }

 

\subsection{\textcolor{Chapter }{IsAssociatedGradedRing}}
\logpage{[ 4, 4, 3 ]}\nobreak
\hyperdef{L}{X87B04D4580DE8E10}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IsAssociatedGradedRing({\slshape A, B})\index{IsAssociatedGradedRing@\texttt{IsAssociatedGradedRing}}
\label{IsAssociatedGradedRing}
}\hfill{\scriptsize (operation)}}\\


 Returns \texttt{true} if the algebra \mbox{\texttt{\slshape A}} is an associated graded ring of the algebra \mbox{\texttt{\slshape B}}. This is the case if the additive structure is the same (i.e. the
Hilbert-Poincar{\a'e} series is the same), and the generators for \mbox{\texttt{\slshape A}} (and their degrees) are included in the generators for \mbox{\texttt{\slshape B}}. }

 

\subsection{\textcolor{Chapter }{DegreeOfRepresentative}}
\logpage{[ 4, 4, 4 ]}\nobreak
\hyperdef{L}{X85D95BF07C8E5DF7}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DegreeOfRepresentative({\slshape A, p})\index{DegreeOfRepresentative@\texttt{DegreeOfRepresentative}}
\label{DegreeOfRepresentative}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the degree of a polynomial representative \mbox{\texttt{\slshape p}} from the graded ring presentation \mbox{\texttt{\slshape A}}. }

 

\subsection{\textcolor{Chapter }{MaximumDegreeForPresentation}}
\logpage{[ 4, 4, 5 ]}\nobreak
\hyperdef{L}{X7CE381787AEC5CAC}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{MaximumDegreeForPresentation({\slshape A})\index{MaximumDegreeForPresentation@\texttt{MaximumDegreeForPresentation}}
\label{MaximumDegreeForPresentation}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the maximum degree in generators or relations that is needed to
generate the graded algebra presentation \mbox{\texttt{\slshape A}}. This is not necessarily the same as the largest degree in any of the
relations and generators - some relations may be redundant (for example due to
being a Groebner basis), so this routine checks for the largest degree of a
required generator, and returns the maximum of this and the generator degrees. }

 
\subsection{\textcolor{Chapter }{SubspaceDimensionDegree}}\logpage{[ 4, 4, 6 ]}
\hyperdef{L}{X7EF085B67B846215}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SubspaceDimensionDegree({\slshape A, d})\index{SubspaceDimensionDegree@\texttt{SubspaceDimensionDegree}!for one degree}
\label{SubspaceDimensionDegree:for one degree}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SubspaceDimensionDegree({\slshape A, degs})\index{SubspaceDimensionDegree@\texttt{SubspaceDimensionDegree}!for list of degrees}
\label{SubspaceDimensionDegree:for list of degrees}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Integer or list 



 Returns the dimension of degree \mbox{\texttt{\slshape d}} of the graded algebra \mbox{\texttt{\slshape A}}, or a list of dimensions corresponding to the list of degrees \mbox{\texttt{\slshape degs}}. }

 
\subsection{\textcolor{Chapter }{SubspaceBasisRepsByDegree}}\logpage{[ 4, 4, 7 ]}
\hyperdef{L}{X7834EE487CAA02D4}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SubspaceBasisRepsByDegree({\slshape A, d})\index{SubspaceBasisRepsByDegree@\texttt{SubspaceBasisRepsByDegree}!for one degree}
\label{SubspaceBasisRepsByDegree:for one degree}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SubspaceBasisRepsByDegree({\slshape A, degs})\index{SubspaceBasisRepsByDegree@\texttt{SubspaceBasisRepsByDegree}!for list of degrees}
\label{SubspaceBasisRepsByDegree:for list of degrees}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 List or list of lists 



 Returns a basis for degree \mbox{\texttt{\slshape d}} of the graded algebra \mbox{\texttt{\slshape A}}, or a list of bases for the list of degrees \mbox{\texttt{\slshape degs}}. Each basis is returned as a list of representatives. }

 

\subsection{\textcolor{Chapter }{CoefficientsOfPoincareSeries}}
\logpage{[ 4, 4, 8 ]}\nobreak
\hyperdef{L}{X84D5111984AFDD31}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{CoefficientsOfPoincareSeries({\slshape A, n})\index{CoefficientsOfPoincareSeries@\texttt{CoefficientsOfPoincareSeries}}
\label{CoefficientsOfPoincareSeries}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns the first \mbox{\texttt{\slshape n}} coefficients of the Poincar{\a'e} series for the graded algebra with \mbox{\texttt{\slshape A}}. These are equal to the dimensions of degrees 0 to $n-1$ of the algebra (a fact that is used in the function \texttt{SubspaceDimensionDegree} (\ref{SubspaceDimensionDegree:for one degree})). 

 \emph{This function uses the \textsf{singular} package.} }

 

\subsection{\textcolor{Chapter }{HilbertPoincareSeries}}
\logpage{[ 4, 4, 9 ]}\nobreak
\hyperdef{L}{X7B93B7D082A50E61}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HilbertPoincareSeries({\slshape A})\index{HilbertPoincareSeries@\texttt{HilbertPoincareSeries}}
\label{HilbertPoincareSeries}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 Rational function 



 Returns the Poincar{\a'e} series for the graded algebra \mbox{\texttt{\slshape A}}. This is a rational function $P(t)/Q(t)$ which is a is a polynomial whose coefficients are the dimensions of each
degree of the algebra. 

 \emph{This function uses the \textsf{singular} package.} }

 

\subsection{\textcolor{Chapter }{LHSSpectralSequence}}
\logpage{[ 4, 4, 10 ]}\nobreak
\hyperdef{L}{X7F5D00C97A46D686}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{LHSSpectralSequence({\slshape G[, N], n})\index{LHSSpectralSequence@\texttt{LHSSpectralSequence}}
\label{LHSSpectralSequence}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{LHSSpectralSequenceLastSheet({\slshape G[, N]})\index{LHSSpectralSequenceLastSheet@\texttt{LHSSpectralSequenceLastSheet}}
\label{LHSSpectralSequenceLastSheet}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{GradedAlgebraPresentation} or list 



 Computes the Lyndon-Hoschild-Serre spectral sequence for the group extension $N \to G \to G/N$. If a normal suggroup \mbox{\texttt{\slshape N}} is not provided, then the largest central subgroup of $G$ is used, or (if the order of the centre is larger than $\sqrt{|G|}$) then the central subgroup that leads to the smallest initial sheet size is
chosen. 

 The function \texttt{LHSSpectralSequence} returns the first \mbox{\texttt{\slshape n}} sheets of the spectral sequence, or all of the sequence up to convergence, if
that occurs before the $(n+1)$th sheet. The Lyndon-Hoschild-Serre spectral sequence starts at the $E_2$ sheet, so the first element in returned list will always be empty. If \mbox{\texttt{\slshape n}} is set to \texttt{infinity} then the length of the returned list equals the number of sheets for
convergence, and the last sheet in the list is the limiting sheet. 

 The function \texttt{LHSSpectralSequenceLastSheet} returns only the limiting sheet of the spectral sequence. This ring is an
associated graded algebra of the mod-$p$ cohomology ring of $G$, with the same additive structure while not necessarily being isomorphic to
it. 

 There are four options  (\textbf{Reference: Options Stack}) which can be used to guide this algorithm: 
\begin{itemize}
\item \texttt{InitialLHSBicomplexSize} can be used to specify the initial size of the bicomplex (the default is 5).
If, in the process of computing the spectral sequence, this is found to be too
small then the algorithm restarts with a larger value. Specifying a larger
initial value in these cases can save time.
\item \texttt{LargerLHSBicomplexBreak} if set to \texttt{true} will force the calculation to enter a break loop before restarting with a
larger bicomplex, should the bicomplex be found to be too small. The user user
is prompted to type \texttt{return;} before continuing. The default behaviour is \texttt{false}, i.e. no prompt.
\item \texttt{LargerLHSBicomplexFail} if set to \texttt{true} will return \texttt{fail} should the bicomplex be found to be too small. The default behaviour is \texttt{false}, i.e. to either restart or prompt, depending on the setting of the previous
option.
\item \texttt{NoInductiveProof} if set to \texttt{true} will not check that the cohomology rings for $N$ and $G/N$ are correct. Instead, it will compute the cohomology rings only up to the
degree needed for the bicomplex size (5 by default, or specified by the \texttt{InitialLHSBicomplexSize} option).
\end{itemize}
 }

 }

 
\section{\textcolor{Chapter }{Example: Computing the Lyndon-Hoschild-Serre spectral sequence and mod-$p$ cohomology ring for a small $p$-group}}\label{GradedAlgebraExample2}
\logpage{[ 4, 5, 0 ]}
\hyperdef{L}{X87DD66E67D0D5485}{}
{
  The Lyndon-Hoschild-Serre spectral sequence is relates the cohomologies of a
normal subgroup $N$ and a quotient group $G/N$ to the cohomology of the total group $G$: the limiting sheet of the sequence is an associated graded ring of the
cohomology of $G$. 

 In this example we calculate the Lyndon-Hoschild-Serre spectral sequence for a
group of order 16 using the centre of $G$ as our normal subgroup. By asking for an infinite number of terms, this
function calculates enough terms to be sure that the sequence has converged.
We compare the dimensions in the first ($E_2$) and last ($E_\infty$) sheet, we demonstrate that the limiting sheet (the last in the list) is a
graded algebra by multiplying some elements, and we calculate the
Poincar{\a'e} series of the last sheet.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> G := SmallGroup(16, 4);;
  gap> SS := LHSSpectralSequence(G, Centre(G), infinity);
  [ , Graded algebra GF(2)[ x_1, x_2, x_3, x_4 ] /
      [  ] with indeterminate degrees [ 1, 1, 1, 1 ],
    Graded algebra GF(2)[ x_1, x_2, x_3, x_4 ] / [ x_2^2, x_1^2+x_1*x_2
       ] with indeterminate degrees [ 1, 1, 2, 2 ],
    Graded algebra GF(2)[ x_1, x_2, x_3, x_4 ] / [ x_2^2, x_1^2+x_1*x_2
       ] with indeterminate degrees [ 1, 1, 2, 2 ] ]
  gap> # i.e. we identify convergence after 3 terms
  gap> #
  gap> # Compare the dimensions of the first and last sheet
  gap> SubspaceDimensionDegree(SS[2], [1..10]);
  [ 4, 10, 20, 35, 56, 84, 120, 165, 220, 286 ]
  gap> SubspaceDimensionDegree(SS[3], [1..10]);
  [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
  gap> #
  gap> # Take the two basis elements from degree 1 and check that the
  gap> # product is in degree two
  gap> B := SubspaceBasisRepsByDegree(SS[3], 1);
  [ x_1, x_2 ]
  gap> DegreeOfRepresentative(SS[3], B[1]*B[2]);
  2
  gap> #
  gap> # And find the Poincare series
  gap> HilbertPoincareSeries(SS[3]);
  (1)/(x_1^2-2*x_1+1)
\end{Verbatim}
 The largest degree in the presentation for the limiting sheet in the
Lyndon-Hoschild-Serre spectral sequence for $G$ is the same as the largest degree in the presentation for the mod-$p$ cohomology ring of $G$. We continue this example by calculating this maximum degree, $n$, for our group $G$ and then computing the mod-$p$ cohomology ring. We confirm that the cohomology ring is an associated graded
ring of the limiting sheet of the spectral sequence, and check whether in this
case it is in fact also isomorphic.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> G := SmallGroup(16, 4);;
  gap> Einf := LHSSpectralSequenceLastSheet(G, Centre(G));
  Graded algebra GF(2)[ x_1, x_2, x_3, x_4 ] / [ x_2^2, x_1^2+x_1*x_2
   ] with indeterminate degrees [ 1, 1, 2, 2 ]
  gap> #
  gap> # Find the maximum degree
  gap> n := MaximumDegreeForPresentation(Einf);
  2
  gap> #
  gap> # And calculate the cohomology ring
  gap> H := Mod2CohomologyRingPresentation(G, n);
  Graded algebra GF(2)[ x_1, x_2, x_3, x_4 ] / [ x_1*x_2+x_2^2, x_1^2
   ] with indeterminate degrees [ 1, 1, 2, 2 ]
  gap> #
  gap> # Check for an associated graded ring, and isomorphism
  gap> IsAssociatedGradedRing(H, Einf);
  true
  gap> IsIsomorphicGradedAlgebra(H, Einf);
  true
\end{Verbatim}
 }

 }

   
\chapter{\textcolor{Chapter }{$\mathbb{F}G$-modules}}\label{FpGModuleGF}
\logpage{[ 5, 0, 0 ]}
\hyperdef{L}{X820435E87D83DF34}{}
{
  Let $\mathbb{F}G$ be the group ring of the group $G$ over the field $\mathbb{F}$. In this package we only consider the case where $G$ is a finite $p$-groups and $\mathbb{F} = \mathbb{F}_p$ is the field of $p$ elements. In addition, we only consider free $\mathbb{F}G$-modules. 
\section{\textcolor{Chapter }{The \texttt{FpGModuleGF} datatype}}\label{FpGModuleGFdatatype}
\logpage{[ 5, 1, 0 ]}
\hyperdef{L}{X85FA0B237AC4A19D}{}
{
  Modules and submodules of free $\mathbb{F}G$-modules are represented in \textsf{HAPprime} using the \texttt{FpGModuleGF} datatype, where the `\texttt{GF}' stands for `Generator Form'. This defines a module using a group $G$ and a set of $G$-generating vectors for the module's vector space, together with a group
action which operates on those vectors. A free $\mathbb{F}G$-module $\mathbb{F}G$ can be considered as a vector space $\mathbb{F}^{|G|}$ whose basis is the elements of $G$. An element of $(\mathbb{F}G)^n$ is the direct sum of $n$ copies of $\mathbb{F}G$ and, as an element of \texttt{FpGModuleGF}, is represented as a vector of length $n|G|$ with coefficients in $\mathbb{F}$. Representing our $\mathbb{F}G$-module elements as vectors is ideal for our purposes since \textsf{GAP}'s representation and manipulation of vectors and matrices over small prime
fields is very efficient in both memory and computation time. 

 The \textsf{HAP} package defines a \texttt{FpGModule} object, which is similar but stores a vector space basis rather than a $G$-generating set for the module's vector space. Storing a $G$-generating set saves memory, both in passive storage and in allowing more
efficient versions of some computation algorithms. 

 There are a number of construction functions for \texttt{FpGModuleGF}s: see \ref{FpGModuleConstructors} for details. A $\mathbb{F}G$-module is defined by the following: 
\begin{itemize}
\item  \texttt{gens}, a list of $G$-generating vectors for the underlying vector space. These do not need to be
minimal - they could even be a vector space basis. The \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModuleGF}) can be used to convert a module to one with a minimal set of generators. 
\item  \texttt{group}, the group $G$ for the module 
\item  \texttt{action}, a function \texttt{action(g, u)} that represents the module's group action on vectors. It takes a group element $g \in G$ and a vector \texttt{u} of length \texttt{actionBlockSize} and returns another vector \texttt{v} of the same length that is the product $v = gu$. If \texttt{action} is not provided, the canonical group permutation action is used. If the vector \texttt{u} is an integer multiple of \texttt{actionBlockSize} in length, the function \texttt{action} acts block-wise on the vector. 
\item  \texttt{actionBlockSize}, the length of vectors upon which \texttt{action} operates. This is usually the order of the group, $|G|$ (for example for the canonical action), but it is possible to specify this to
support other possible group actions that might act on larger vectors. \texttt{actionBlockSize} will always be equal to the ambient dimension of the module $\mathbb{F}G^1$. 
\end{itemize}
 The group, action and block size are internally wrapped up into a record \texttt{groupAndAction}, with entries \texttt{group}, \texttt{action} and \texttt{actionBlockSize}. This is used to simplify the passing of parameters to some functions. 

 Some additional information is sometimes needed to construct particular
classes of \texttt{FpGModuleGF}: 
\begin{itemize}
\item  \texttt{ambientDimension}, the length of vectors in the generating set: for a module $(\mathbb{F}G)^n$, this is equal to $n\times$\texttt{actionBlockSize}. This is needed in the case when the list of generating vectors is empty. 
\item  \texttt{form}, a string detailing whether the generators are known to be minimal or not,
and if so in which format. It can be one of \texttt{"unknown"}, \texttt{"fullcanonical"}, \texttt{"minimal"}, \texttt{"echelon"} or \texttt{"semiechelon"}. Some algorithms require a particular form, and algorithms such as \texttt{EchelonModuleGenerators} (\ref{EchelonModuleGenerators}) that manipulate a module's generators to create these forms set this entry. 
\end{itemize}
 }

  
\section{\textcolor{Chapter }{Implementation details: Block echelon form}}\label{FpGModuleGFalgo}
\logpage{[ 5, 2, 0 ]}
\hyperdef{L}{X79DF42E686679AFE}{}
{
  
\subsection{\textcolor{Chapter }{Generating vectors and their block structure}}\label{FpGModuleGFalgoblock}
\logpage{[ 5, 2, 1 ]}
\hyperdef{L}{X79DDD8C37A0B8425}{}
{
  Consider the vector representation of an element in the $\mathbb{F}G$-module $(\mathbb{F}G)^2$, where $G$ is a group of order four:  
\[ v \in (\mathbb{F}G)^2 = (g_1 + g_3, g_1 + g_2 + g_4) = [1 0 1 0 | 1 1 0 1] \]
   The first block of four entries in the vector correspond to the first $\mathbb{F}G$ summand and the second block to the second summand (and the group elements are
numbered in the order provided by the \textsf{GAP} function \texttt{Elements} (\textbf{Reference: Elements})). 

 Given a $G$-generating set for a $\mathbb{F}G$-module, the usual group action permutes the group elements, and thus the
effect on the vector is to permute the equivalent vector elements. Each
summand is independent, and so elements are permuted within the blocks
(normally of size $|G|$) seen in the example above. A consequence of this is that if any block (i.e.
summand) in a generator is entirely zero, then it remains zero under group (or $\mathbb{F}$) multiplication and so that generator contributes nothing to that part of the
vector space. This fact enables some of the structure of the module's vector
space to be inferred from the $G$-generators, without needing a full vector space basis . A desirable set of $G$-generators is one that has many zero blocks, and what we call the `block
echelon' form is one that has this property. }

 
\subsection{\textcolor{Chapter }{Matrix echelon reduction and head elements}}\logpage{[ 5, 2, 2 ]}
\hyperdef{L}{X82F0E0067C40FDD5}{}
{
  The block echelon form of a $\mathbb{F}G$-module generating set is analagous to the echelon form of matrices, used as a
first stage in many matrix algorithms, and we first briefly review matrix
echelon form. In a (row) echelon-form matrix, the head element in each row
(the first non-zero entry) is the identity, and is to the right of the head in
the previous row. A consequence of this is that the values below each head are
all zero. All zero rows are at the bottom of the matrix (or are removed). \textsf{GAP} also defines a semi-echelon form, in which it is guaranteed that all values
below each head is zero, but not that each head is to the right of those above
it. 

 Matrices can be converted into (semi-)echelon form by using Gaussian
elimination to perform row reduction (for example the \textsf{GAP} function \texttt{SemiEchelonMat} (\textbf{Reference: SemiEchelonMat})). A typical algorithm gradually builds up a list of matrix rows with unique
heads, which will eventually be an echelon-form set of basis elements for the
row space of the matrix. This set is initialised with the first row of the
matrix, and the algorithm is then applied to each subsequent row in turn. The
basis rows in the current set are used to reduce the next row of the matrix:
if, after reduction, it is non-zero then it will have a unique head and is
added to the list of basis rows; if it is zero then it may be removed. The
final set of vectors will be a semi-echelon basis for the row space of the
original matrix, which can then be permuted to give an echelon basis if
required. }

 
\subsection{\textcolor{Chapter }{Echelon block structure and minimal generators}}\logpage{[ 5, 2, 3 ]}
\hyperdef{L}{X814C05FC87ED4035}{}
{
  In the same way that the echelon form is useful for vector space generators,
we can convert a set of $\mathbb{F}G$-module generators into echelon form. However, unlike multiplication by a
field element, the group action on generating vectors also permutes the vector
elements, so a strict echelon form is less useful. Instead, we define a `block
echelon' form, treating the blocks in the vector (see example above) as the $\mathbb{F}G$-elements to be converted into echelon form. In block-echelon form, the first
non-zero block in each row is as far to the right as possible. Often, the
first non-zero block in a row will be to the right of the first non-zero block
in the row above, but when several generating vectors are needed in a block,
this may not be the case. The following example creates a random submodule of $(\mathbb{F}G)^n$ by picking five generating vectors at random. This module is first displayed
with the original generators, and then they are converted to block echelon
form using the the \textsf{HAPprime} function \texttt{EchelonModuleGenerators} (\ref{EchelonModuleGenerators}). The two generating sets both span the same vector space (i.e. the same $\mathbb{F}G$ module), but the latter representation is much more useful. 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> M := FpGModuleGF(RandomMat(5, 32, GF(2)), DihedralGroup(8));;
  gap> Display(M);
  Module over the group ring of Group( [ f1, f2, f3 ] )
   in characteristic 2 with 5 generators in FG^4.
  [.1..1.1.|.1....1.|1111.11.|11.1111.]
  [11.1..1.|1....11.|1...111.|1...11..]
  [11..1.1.|1.1.1...|11...1..|.11.11..]
  [11111111|111...1.|.11...1.|.1..1111]
  [.1111111|1.1.111.|..1..1..|1.111...]
  gap> echM := EchelonModuleGenerators(M);
  rec( module := Module over the group ring of <pc group of size 8 with
      3 generators> in characteristic 2 with 4 generators in FG^
      4. Generators are in minimal echelon form., headblocks := [ 1, 2, 3, 4 ] )
  gap> Display(echM.module);
  Module over the group ring of Group( [ f1, f2, f3 ] )
   in characteristic 2 with 4 generators in FG^4.
  [.1..1.1.|.1....1.|1111.11.|11.1111.]
  [........|.1111..1|111.1...|.11.11.1]
  [........|........|.1..1.1.|.1.1.111]
  [........|........|........|..1111.1]
  Generators are in minimal echelon form.gap>
  gap> M = echM.module;
  true
\end{Verbatim}
 

 The main algorithm for converting a set of generators into echelon form is \texttt{SemiEchelonModuleGeneratorsDestructive} (\ref{SemiEchelonModuleGeneratorsDestructive}). The generators for the $\mathbb{F}G$ module are represented as rows of a matrix, and (with the canonical action)
the first $|G|$ columns of this matrix correspond to the first block, the next $|G|$ columns to the second block, and so on. The first block of the matrix is taken
and the vector space $V_b$ spanned by the rows of that block is found (which will be a a subspace of $\mathbb{F}^{|G|}$). Taking the rows in the first block, find (by gradually leaving out rows) a
minimal subset that generates $V_b$. The rows of the full matrix that correspond to this minimal subset form the
first rows of the block-echelon form generators. Taking those rows, and all $G$-multiples of them, now calculate a semi-echelon basis for the vector space
that they generate (using \texttt{SemiEchelonMatDestructive} (\textbf{Reference: SemiEchelonMatDestructive})). This is used to reduce all of the other generators. Since the rows we have
chosen span the space of the first block, the first block in all the other
rows will be reduced to zero. We can now move on to the second block. 

 We now look at the rows of the matrix that start (have their first non-zero
entry) in the second block. In addition, some of the generators used for the
first block might additionally give rise to vector space basis vectors with
head elements in the second blocks. The rows need to be stored during the
first stage and reused here. We find a minimal set of the matrix rows with
second-block heads that, when taken with any second-block heads from the first
stage, generate the entire space spanned by the second block. The vector-space
basis from this new minimal set is then used to reduce the rest of the
generating rows as before, reducing all of the other rows' second blocks to
zero. The process is then repeated for each other block. Any generators that
are completely zero are then removed. The algorithm is summarised in the
following pseudocode: 
\begin{verbatim}  
  Let X be the list of generators still to convert (initially all the generators)
  Let Xe = [] be the list of generators already in block-echelon form
  Define X{b} to represent the $b$th block from generators X
  Define V(X) to represent the vector space generated by generators X
  -------------------------------------------------------------------------------
  for b in [1..blocks] 
    1. Find a minimal set of generators Xm from X such that 
       V(Xm{b} + Xe{b}) = V(X{b} + Xe{b})
    2. Remove Xm from X and add them to Xe
    3. Find a semi-echelon basis for V(Xe) and use this to reduce the elements 
       of block b in remaining vectors of X to zero
  end for
        
\end{verbatim}
 

 The result of this algorithm is a new generating set for the module that is
minimal in the sense that no vector can be removed from the set and leave it
still spanning the same vector space. In the case of a $\mathbb{F}G$-module with $\mathbb{F}$=GF(2), this is a globally minimal set: there is no possible alternative set
with fewer generators. }

 
\subsection{\textcolor{Chapter }{Intersection of two modules}}\label{FpGModuleGFalgoint}
\logpage{[ 5, 2, 4 ]}
\hyperdef{L}{X86F4852785A509BF}{}
{
  Knowing the block structure of the modules enables the intersection of two
modules to be calculated more efficiently. Consider two modules $U$ and $V$ with the block structure as given in this example: 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> DisplayBlocks(U);
  [*..]
  [**.]
  [.*.]
  gap> DisplayBlocks(V);
  [.**]
  [.**]
  [..*]
\end{Verbatim}
 To calculate the intersection of the two modules, it is normal to expand out
the two modules to find the vector space $U_\mathbb{F}$ and $V_\mathbb{F}$ of the two modules and calculate the intersection as a standard vector-space
intersection. However, in this case, since $U$ has no elements in the last block, and $V$ has no elements in the first block, the intersection must only have elements
in the middle block. This means that the first generator of $U$ and the last generator of $V$ can not be in the intersection and can be ignored for the purposes of the
intersection calculation. In general, rather than expanding the entirety of $U$ and $V$ into an $\mathbb{F}$-basis to calculate their intersection, one can expand $U$ and $V$ more intelligently into $\mathbb{F}$-bases $U'_\mathbb{F}$ and $V'_\mathbb{F}$ which are smaller than $U_\mathbb{F}$ and $V_\mathbb{F}$ but have the same intersection. 

 Having determined (by comparing the block structure of $U$ and $V$) that only the middle block in our example contributes to the intersection,
we only need to expand out the rows of $U$ and $V$ that have heads in that block. The first generator of $U$ generates no elements in the middle block, and trivially be ignored. The
second row of $U$ may or may not contribute to the intersection: this will need expanding out
and echelon reduced. The expanded rows that don't have heads in the central
block can then be discarded, with the other rows forming part of the basis of $U'_\mathbb{F}$. Likewise, the third generator of $U$ is expanded and echelon reduced to give the rest of the basis for $U'_\mathbb{F}$. To find $V'_\mathbb{F}$, the first two generators are expanded, semi-echelon reduced and the rows
with heads in the middle block kept. The third generator can be ignored.
Finally, the intersection of $U'_\mathbb{F}$ and $V'_\mathbb{F}$ can found using, for example, \texttt{SumIntersectionMatDestructive} (\textbf{HAPprime Datatypes: SumIntersectionMatDestructive}). 

 This algorithm, implemented in the function \texttt{IntersectionModulesGF} (\ref{IntersectionModulesGF}), will (for modules whose generators have zero columns) use less memory than a
full vector-space expansion, and in the case where $U$ and $V$ have no intersection, may need to perform no expansion at all. In the worst
case, both $U$ and $V$ will need a full expansion, using no more memory than the naive
implementation. Since any full expansion is done row-by-row, with echelon
reduction each time, it will in general still require less memory (but will be
slower). }

 }

  
\section{\textcolor{Chapter }{Construction functions}}\logpage{[ 5, 3, 0 ]}
\hyperdef{L}{X83D8009086035BCB}{}
{
  
\subsection{\textcolor{Chapter }{FpGModuleGF construction functions}}\label{FpGModuleConstructors}
\logpage{[ 5, 3, 1 ]}
\hyperdef{L}{X862AC894821415A4}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGF({\slshape gens, G[, action, actionBlockSize]})\index{FpGModuleGF@\texttt{FpGModuleGF}!construction from generators, group and action}
\label{FpGModuleGF:construction from generators, group and action}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGF({\slshape gens, groupAndAction})\index{FpGModuleGF@\texttt{FpGModuleGF}!construction from generators and groupAndAction}
\label{FpGModuleGF:construction from generators and groupAndAction}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGF({\slshape ambientDimension, G[, action, actionBlockSize]})\index{FpGModuleGF@\texttt{FpGModuleGF}!construction of empty module from group and action}
\label{FpGModuleGF:construction of empty module from group and action}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGF({\slshape ambientDimension, groupAndAction})\index{FpGModuleGF@\texttt{FpGModuleGF}!construction of empty module from groupAndAction}
\label{FpGModuleGF:construction of empty module from groupAndAction}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGF({\slshape G, n})\index{FpGModuleGF@\texttt{FpGModuleGF}!construction of full canonical module}
\label{FpGModuleGF:construction of full canonical module}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGF({\slshape groupAndAction, n})\index{FpGModuleGF@\texttt{FpGModuleGF}!construction of full canonical module from groupAndAction}
\label{FpGModuleGF:construction of full canonical module from groupAndAction}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGF({\slshape HAPmod})\index{FpGModuleGF@\texttt{FpGModuleGF}!construction from FpGModule}
\label{FpGModuleGF:construction from FpGModule}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGFNC({\slshape gens, G, form, action, actionBlockSize})\index{FpGModuleGFNC@\texttt{FpGModuleGFNC}!construction from generators, group and action}
\label{FpGModuleGFNC:construction from generators, group and action}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGFNC({\slshape ambientDimension, G, action, actionBlockSize})\index{FpGModuleGFNC@\texttt{FpGModuleGFNC}!construction for empty module with group and action}
\label{FpGModuleGFNC:construction for empty module with group and action}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleGFNC({\slshape gens, groupAndAction[, form]})\index{FpGModuleGFNC@\texttt{FpGModuleGFNC}!construction from generators and groupAndAction}
\label{FpGModuleGFNC:construction from generators and groupAndAction}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModuleGF 



 Creates and returns a \texttt{FpGModuleGF} module object. The most commonly-used constructor requires a list of
generators \mbox{\texttt{\slshape gens}} and a group \mbox{\texttt{\slshape G}}. The group action and block size can be specified using the \mbox{\texttt{\slshape action}} and \mbox{\texttt{\slshape actionBlockSize}} parameters, or if these are omitted then the canonical action is assumed.
These parameters can also be wrapped up in a \texttt{groupAndAction} record (see \ref{FpGModuleGFdatatype}). 

 An empty \texttt{FpGModuleGF} can be constructed by specifying a group and an \mbox{\texttt{\slshape ambientDimension}} instead of a set of generators. A module spanning $(\mathbb{F}G)^n$ with canonical generators and action can be constructed by giving a group \mbox{\texttt{\slshape G}} and a rank \mbox{\texttt{\slshape n}}. A \texttt{FpGModuleGF} can also be constructed from a \textsf{HAP} \texttt{FpGModule} \mbox{\texttt{\slshape HAPmod}}. 

 The generators in a \texttt{FpGModuleGF} do not need to be a minimal set. If you wish to create a module with minimal
generators, construct the module from a non-minimal set \mbox{\texttt{\slshape gens}} and then use one of the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}). When constructing a \texttt{FpGModuleGF} from a \texttt{FpGModule}, the \textsf{HAP} function \texttt{GeneratorsOfFpGModule} (\textbf{HAP: GeneratorsOfFpGModule}) is used to provide a set of generators, so in this case the generators will be
minimal. 

 Most of the forms of this function perform a few (cheap) tests to make sure
that the arguments are self-consistent. The \texttt{NC} versions of the constructors are provided for internal use, or when you know
what you are doing and wish to skip the tests. See Section \ref{FPGModuleExample0} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{FpGModuleFromFpGModuleGF}}
\logpage{[ 5, 3, 2 ]}\nobreak
\hyperdef{L}{X83232B1886BE75F0}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleFromFpGModuleGF({\slshape M})\index{FpGModuleFromFpGModuleGF@\texttt{FpGModuleFromFpGModuleGF}}
\label{FpGModuleFromFpGModuleGF}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModule 



 Returns a \textsf{HAP} \texttt{FpGModule} that represents the same module as the \texttt{FpGModuleGF} \mbox{\texttt{\slshape M}}. This uses \texttt{ModuleVectorSpaceBasis} (\ref{ModuleVectorSpaceBasis}) to find the vector space basis for \mbox{\texttt{\slshape M}} and constructs a \texttt{FpGModule} with this vector space and the same group and action as \mbox{\texttt{\slshape M}} See Section \ref{FPGModuleExample0} below for an example of usage. 

 \emph{TODO: This currently constructs an FpGModule object explicitly. It should use
a constructor once one is provided} }

 

\subsection{\textcolor{Chapter }{MutableCopyModule}}
\logpage{[ 5, 3, 3 ]}\nobreak
\hyperdef{L}{X832C55197A46CB77}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{MutableCopyModule({\slshape M})\index{MutableCopyModule@\texttt{MutableCopyModule}}
\label{MutableCopyModule}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModuleGF 



 Returns a copy of the module \mbox{\texttt{\slshape M}} where the generating vectors are fully mutable. The group and action in the
new module is identical to that in \mbox{\texttt{\slshape M}} - only the list of generators is copied and made mutable. (The assumption is
that this function used in situations where you just want a new generating
set.) }

 

\subsection{\textcolor{Chapter }{CanonicalAction}}
\logpage{[ 5, 3, 4 ]}\nobreak
\hyperdef{L}{X8315A82E7812289F}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{CanonicalAction({\slshape G})\index{CanonicalAction@\texttt{CanonicalAction}}
\label{CanonicalAction}
}\hfill{\scriptsize (attribute)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{CanonicalActionOnRight({\slshape G})\index{CanonicalActionOnRight@\texttt{CanonicalActionOnRight}}
\label{CanonicalActionOnRight}
}\hfill{\scriptsize (attribute)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{CanonicalGroupAndAction({\slshape G})\index{CanonicalGroupAndAction@\texttt{CanonicalGroupAndAction}}
\label{CanonicalGroupAndAction}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 Function \texttt{action(g,v)} or a record with elements \texttt{(group, action, actionOnRight, actionBlockSize)} 



 Returns a function of the form \texttt{action(g,v)} that performs the canonical group action of an element \texttt{g} of the group \mbox{\texttt{\slshape G}} on a vector \texttt{v} (acting on the left by default, or on the right with the \texttt{OnRight} version). The \texttt{GroupAndAction} version of this function returns the actions in a record together with the
group and the action block size. Under the canonical action, a free module $\mathbb{F}G$ is represented as a vector of length $|G|$ over the field $\mathbb{F}$, and the action is a permutation of the vector elements. 

 Note that these functions are attributes of a group, so that the canonical
action for a particular group object will always be an identical function
(which is desirable for comparing and combining modules and submodules). }

 
\subsection{\textcolor{Chapter }{Example: Constructing a \texttt{FpGModuleGF}}}\label{FPGModuleExample0}
\logpage{[ 5, 3, 5 ]}
\hyperdef{L}{X814553E382BC777E}{}
{
  The example below constructs four different $\mathbb{F}G$-modules, where $G$ is the quaternion group of order eight, and the action is the canonical action
in each case: 
\begin{enumerate}
\item \texttt{M} is the module $(\mathbb{F}G)^3$
\item \texttt{S} is the submodule of $(\mathbb{F}G)^3$ with elements only in the first summand
\item \texttt{T} is a random submodule \texttt{M} generated by five elements
\item \texttt{U} is the trivial (zero) submodule of $(\mathbb{F}G)^4$
\end{enumerate}
 We check whether \texttt{S}, \texttt{T} and \texttt{U} are submodules of \texttt{M}, examine a random element from \texttt{M}, and convert \texttt{S} into a \textsf{HAP} \texttt{FpGModule}. For the other functions used in this example, see Section \ref{FpGModuleGFmisc}.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> G := SmallGroup(8, 4);;
  gap> M := FpGModuleGF(G, 3);
  Full canonical module FG^3 over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2
  gap> gen := ListWithIdenticalEntries(24, Zero(GF(2)));;
  gap> gen[1] := One(GF(2));;
  gap> S := FpGModuleGF([gen], G);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 1 generator in FG^
  3. Generators are in minimal echelon form.
  gap> T := RandomSubmodule(M, 5);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 5 generators in FG^3.
  gap> U := FpGModuleGF(32, CanonicalGroupAndAction(G));
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 0 generators in FG^
  4. Generators are in minimal echelon form.
  gap>
  gap> IsSubModule(M, S);
  true
  gap> IsSubModule(M, T);
  true
  gap> IsSubModule(M, U);
  false
  gap>
  gap> e := RandomElement(M);
  <a GF2 vector of length 24>
  gap> Display([e]);
   . 1 1 . . 1 . . . . . 1 . . 1 1 . . 1 . 1 . . 1
  gap> IsModuleElement(S, e);
  false
  gap> IsModuleElement(T, e);
  true
  gap>
  gap> FpGModuleFromFpGModuleGF(S);
  Module of dimension 8 over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2
  
\end{Verbatim}
 }

 }

  
\section{\textcolor{Chapter }{Data access functions}}\logpage{[ 5, 4, 0 ]}
\hyperdef{L}{X7DE3278D7E5DEE03}{}
{
  

\subsection{\textcolor{Chapter }{ModuleGroup}}
\logpage{[ 5, 4, 1 ]}\nobreak
\hyperdef{L}{X85CF62207B6F6099}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleGroup({\slshape M})\index{ModuleGroup@\texttt{ModuleGroup}}
\label{ModuleGroup}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Group 



 Returns the group of the module \mbox{\texttt{\slshape M}}. See Section \ref{FPGModuleExample1} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleGroupOrder}}
\logpage{[ 5, 4, 2 ]}\nobreak
\hyperdef{L}{X81C2789D85109789}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleGroupOrder({\slshape M})\index{ModuleGroupOrder@\texttt{ModuleGroupOrder}}
\label{ModuleGroupOrder}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the order of the group of the module \mbox{\texttt{\slshape M}}. This function is identical to \texttt{Order(ModuleGroup(M))}, and is provided for convenience. See Section \ref{FPGModuleExample1} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleAction}}
\logpage{[ 5, 4, 3 ]}\nobreak
\hyperdef{L}{X7EE4E7ED86696752}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleAction({\slshape M})\index{ModuleAction@\texttt{ModuleAction}}
\label{ModuleAction}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Function 



 Returns the group action function of the module \mbox{\texttt{\slshape M}}. This is a function \texttt{action(g, v)} that takes a group element \texttt{g} and a vector \texttt{v} and returns a vector \texttt{w} that is the result of $w = gv$. See Section \ref{FPGModuleExample1} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleActionBlockSize}}
\logpage{[ 5, 4, 4 ]}\nobreak
\hyperdef{L}{X7CFEF3B887425980}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleActionBlockSize({\slshape M})\index{ModuleActionBlockSize@\texttt{ModuleActionBlockSize}}
\label{ModuleActionBlockSize}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the block size of the group action of the module \mbox{\texttt{\slshape M}}. This is the length of vectors (or the factor of the length) upon which the
group action function acts. See Section \ref{FPGModuleExample1} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleGroupAndAction}}
\logpage{[ 5, 4, 5 ]}\nobreak
\hyperdef{L}{X81F860F380EB55FC}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleGroupAndAction({\slshape M})\index{ModuleGroupAndAction@\texttt{ModuleGroupAndAction}}
\label{ModuleGroupAndAction}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Record with elements \texttt{(group, action, actionOnRight, actionBlockSize)} 



 Returns details of the module's group and action in a record with the
following elements: 
\begin{itemize}
\item \texttt{group} The module's group
\item \texttt{action} The module's group action, as a function of the form \texttt{action(g, v)} that takes a vector \texttt{v} and returns the vector $w = gv$
\item \texttt{actionOnRight} The module's group action when acting on the right, as a function of the form \texttt{action(g, v)} that takes a vector \texttt{v} and returns the vector $w = vg$
\item \texttt{actionBlockSize} The module's group action block size. This is the ambient dimension of vectors
in the module $\mathbb{F}G$
\end{itemize}
 This function is provided for convenience, and is used by a number of internal
functions. The canonical groups and action can be constructed using the
function \texttt{CanonicalGroupAndAction} (\ref{CanonicalGroupAndAction}). See Section \ref{FPGModuleExample1} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleCharacteristic}}
\logpage{[ 5, 4, 6 ]}\nobreak
\hyperdef{L}{X78BDED977DA309FD}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleCharacteristic({\slshape M})\index{ModuleCharacteristic@\texttt{ModuleCharacteristic}}
\label{ModuleCharacteristic}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the characteristic of the field $\mathbb{F}$ of the $\mathbb{F}G$-module \mbox{\texttt{\slshape M}}. See Section \ref{FPGModuleExample1} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleField}}
\logpage{[ 5, 4, 7 ]}\nobreak
\hyperdef{L}{X86AC3239861EAB8A}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleField({\slshape M})\index{ModuleField@\texttt{ModuleField}}
\label{ModuleField}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Field 



 Returns the field $\mathbb{F}$ of the $\mathbb{F}G$-module \mbox{\texttt{\slshape M}}. See Section \ref{FPGModuleExample1} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleAmbientDimension}}
\logpage{[ 5, 4, 8 ]}\nobreak
\hyperdef{L}{X7A020F6F7EFDFFC7}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleAmbientDimension({\slshape M})\index{ModuleAmbientDimension@\texttt{ModuleAmbientDimension}}
\label{ModuleAmbientDimension}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the ambient dimension of the module \mbox{\texttt{\slshape M}}. The module \mbox{\texttt{\slshape M}} is represented as a submodule of $\mathbb{F}G^n$ using generating vectors for a vector space. This function returns the
dimension of this underlying vector space. This is equal to the length of each
generating vector, and also $n\times$\texttt{actionBlockSize}. See Section \ref{FPGModuleExample1} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{AmbientModuleDimension}}
\logpage{[ 5, 4, 9 ]}\nobreak
\hyperdef{L}{X86B97B587B7C12E7}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{AmbientModuleDimension({\slshape M})\index{AmbientModuleDimension@\texttt{AmbientModuleDimension}}
\label{AmbientModuleDimension}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Integer 



 The module \mbox{\texttt{\slshape M}} is represented a submodule embedded within the free module $\mathbb{F}G^n$. This function returns $n$, the dimension of the ambient module. This is the same as the number of
blocks. See Section \ref{FPGModuleExample1} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{DisplayBlocks (for FpGModuleGF)}}
\logpage{[ 5, 4, 10 ]}\nobreak
\hyperdef{L}{X7DF15EFA78F1DDF6}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DisplayBlocks({\slshape M})\index{DisplayBlocks@\texttt{DisplayBlocks}!for FpGModuleGF}
\label{DisplayBlocks:for FpGModuleGF}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 nothing 



 Displays the structure of the module generators \mbox{\texttt{\slshape gens}} in a compact human-readable form. Since the group action permutes generating
vectors in blocks of length \texttt{actionBlockSize}, any block that contains non-zero elements will still contain non-zero
elements after the group action, but a block that is all zero will remain all
zero. This operation displays the module generators in a per-block form, with
a \texttt{*} where the block is non-zero and \texttt{.} where the block is all zero. 

 The standard \textsf{GAP} methods \texttt{View} (\textbf{Reference: View}), \texttt{Print} (\textbf{Reference: Print}) and \texttt{Display} (\textbf{Reference: Display}) are also available.) See Section \ref{FPGModuleExample3} below for an example of usage. }

 
\subsection{\textcolor{Chapter }{Example: Accessing data about a \texttt{FpGModuleGF}}}\label{FPGModuleExample1}
\logpage{[ 5, 4, 11 ]}
\hyperdef{L}{X7E4C3C5C7CC7B559}{}
{
  In the following example, we construct three terms of a (minimal) resolution
of the dihedral group of order eight, which is a chain complex of $\mathbb{F}G$-modules.  
\[ (\mathbb{F}G)^3 \to (\mathbb{F}G)^3 \to \mathbb{F}G \to \mathbb{F} \to 0 \]
   We obtain the last homomorphism in this chain complex and calculate its
kernel, returning this as a \texttt{FpGModuleGF}. We can use the data access functions described above to extract information
about this module. 

 See Chapters \ref{FpGModuleGFHom} and \ref{Resolution} respectively for more information about $\mathbb{F}G$-module homomorphisms and resolutions in \textsf{HAPprime} 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := ResolutionPrimePowerGroupRadical(DihedralGroup(8), 2);
  Resolution of length 2 in characteristic 2 for <pc group of size 8 with
  3 generators> .
  No contracting homotopy available.
  A partial contracting homotopy is available.
  
  gap> phi := BoundaryFpGModuleHomomorphismGF(R, 2);
  <Module homomorphism>
  
  gap> M := KernelOfModuleHomomorphism(phi);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 15 generators in FG^3.
  
  gap> # Now find out things about this module M
  gap> ModuleGroup(M);
  <pc group of size 8 with 3 generators>
  gap> ModuleGroupOrder(M);
  8
  gap> ModuleAction(M);
  function( g, v ) ... end
  gap> ModuleActionBlockSize(M);
  8
  gap> ModuleGroupAndAction(M);
  rec( group := <pc group of size 8 with 3 generators>,
    action := function( g, v ) ... end,
    actionOnRight := function( g, v ) ... end, actionBlockSize := 8 )
  gap> ModuleCharacteristic(M);
  2
  gap> ModuleField(M);
  GF(2)
  gap> ModuleAmbientDimension(M);
  24
  gap> AmbientModuleDimension(M);
  3
\end{Verbatim}
 }

 }

  
\section{\textcolor{Chapter }{Generator and vector space functions}}\logpage{[ 5, 5, 0 ]}
\hyperdef{L}{X85D634767E456A9D}{}
{
  

\subsection{\textcolor{Chapter }{ModuleGenerators}}
\logpage{[ 5, 5, 1 ]}\nobreak
\hyperdef{L}{X7D6B0216838295A2}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleGenerators({\slshape M})\index{ModuleGenerators@\texttt{ModuleGenerators}}
\label{ModuleGenerators}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 List of vectors 



 Returns, as the rows of a matrix, a list of the set of currently-stored
generating vectors for the vector space of the module \mbox{\texttt{\slshape M}}. Note that this set is not necessarily minimal. The function \texttt{ModuleGeneratorsAreMinimal} (\ref{ModuleGeneratorsAreMinimal}) will return \texttt{true} if the set is known to be minimal, and the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}) can be used to ensure a minimal set, if necessary. See Section \ref{FPGModuleExample2} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleGeneratorsAreMinimal}}
\logpage{[ 5, 5, 2 ]}\nobreak
\hyperdef{L}{X7F643D50826E15E2}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleGeneratorsAreMinimal({\slshape M})\index{ModuleGeneratorsAreMinimal@\texttt{ModuleGeneratorsAreMinimal}}
\label{ModuleGeneratorsAreMinimal}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Boolean 



 Returns \texttt{true} if the module generators are known to be minimal, or \texttt{false} otherwise. Generators are known to be minimal if the one of the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}) have been previously used on this module, or if the module was created from
a \textsf{HAP} \texttt{FpGModule}. See Section \ref{FPGModuleExample2} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleGeneratorsAreEchelonForm}}
\logpage{[ 5, 5, 3 ]}\nobreak
\hyperdef{L}{X7978F2DD787C2BB6}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleGeneratorsAreEchelonForm({\slshape M})\index{ModuleGeneratorsAreEchelonForm@\texttt{ModuleGeneratorsAreEchelonForm}}
\label{ModuleGeneratorsAreEchelonForm}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Boolean 



 Return \texttt{true} if the module generators are known to be in echelon form, or (i.e. \texttt{EchelonModuleGenerators} (\ref{EchelonModuleGenerators}) has been called for this module), or \texttt{false} otherwise. Some algorithms work more efficiently if (or require that) the
generators of the module are in block-echelon form, i.e. each generator in the
module's list of generators has its first non-zero block in the same location
or later than the generator before it in the list. See Section \ref{FPGModuleExample2} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleIsFullCanonical}}
\logpage{[ 5, 5, 4 ]}\nobreak
\hyperdef{L}{X85178CA8858B8616}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleIsFullCanonical({\slshape M})\index{ModuleIsFullCanonical@\texttt{ModuleIsFullCanonical}}
\label{ModuleIsFullCanonical}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Boolean 



 Returns \texttt{true} if the module is known to represent the full module $\mathbb{F}G^n$, with canonical generators and group action, or \texttt{false} otherwise. A module is only known to be canonical if it was constructed using
the canonical module \texttt{FpGModuleGF} constructor (\texttt{FpGModuleGF} (\ref{FpGModuleGF:construction of full canonical module})). If this is true, the module is displayed in a concise form, and some
functions have a trivial implementation. See Section \ref{FPGModuleExample2} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleGeneratorsForm}}
\logpage{[ 5, 5, 5 ]}\nobreak
\hyperdef{L}{X87572B78824FB28E}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleGeneratorsForm({\slshape M})\index{ModuleGeneratorsForm@\texttt{ModuleGeneratorsForm}}
\label{ModuleGeneratorsForm}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 String 



 Returns a string giving the form of the module generators. This may be one of
the following: 
\begin{itemize}
\item \texttt{"unknown"} The form is not known 
\item \texttt{"minimal"} The generators are known to be minimal, but not in any particular form 
\item \texttt{"fullcanonical"} The generators are the canonical (and minimal) generators for $\mathbb{F}G^n$ 
\item \texttt{"semiechelon"} The generators are minimal and in semi-echelon form. 
\item \texttt{"echelon"} The generators are minimal and in echelon form 
\end{itemize}
 See Section \ref{FPGModuleExample2} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleRank}}
\logpage{[ 5, 5, 6 ]}\nobreak
\hyperdef{L}{X7DFFBBD6809A2B41}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleRank({\slshape M})\index{ModuleRank@\texttt{ModuleRank}}
\label{ModuleRank}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleRankDestructive({\slshape M})\index{ModuleRankDestructive@\texttt{ModuleRankDestructive}}
\label{ModuleRankDestructive}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the rank of the module \mbox{\texttt{\slshape M}}, i.e. the number of minimal generators. If the module is already in minimal
form (according to \texttt{ModuleGeneratorsAreMinimal} (\ref{ModuleGeneratorsAreMinimal})) then the number of generators is returned with no calculation. Otherwise, \texttt{MinimalGeneratorsModuleGF} (\ref{MinimalGeneratorsModuleGF}) or \texttt{MinimalGeneratorsModuleGFDestructive} (\ref{MinimalGeneratorsModuleGFDestructive}) respectively are used to find a set of minimal generators. See Section \ref{FPGModuleExample2} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ModuleVectorSpaceBasis}}
\logpage{[ 5, 5, 7 ]}\nobreak
\hyperdef{L}{X7DFAF92283C6FFDC}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleVectorSpaceBasis({\slshape M})\index{ModuleVectorSpaceBasis@\texttt{ModuleVectorSpaceBasis}}
\label{ModuleVectorSpaceBasis}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 List of vectors 



 Returns a matrix whose rows are a basis for the vector space of the \texttt{FpGModuleGF} module \mbox{\texttt{\slshape M}}. Since \texttt{FpGModuleGF} stores modules as a minimal $G$-generating set, this function has to calculate all $G$-multiples of this generating set and row-reduce this to find a basis. See
Section \ref{FPGModuleExample2} below for an example of usage. 

 \emph{TODO: A GF version of this one } }

 

\subsection{\textcolor{Chapter }{ModuleVectorSpaceDimension}}
\logpage{[ 5, 5, 8 ]}\nobreak
\hyperdef{L}{X8377A6E986D36D12}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleVectorSpaceDimension({\slshape M})\index{ModuleVectorSpaceDimension@\texttt{ModuleVectorSpaceDimension}}
\label{ModuleVectorSpaceDimension}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the dimension of the vector space of the module \mbox{\texttt{\slshape M}}. Since \texttt{FpGModuleGF} stores modules as a minimal $G$-generating set, this function has to calculate all $G$-multiples of this generating set and row-reduce this to find the size of the
basis. See Section \ref{FPGModuleExample2} below for an example of usage. 

 \emph{TODO: A GF version of this function } }

 
\subsection{\textcolor{Chapter }{MinimalGeneratorsModule}}\label{MinimalGeneratorsModule}
\logpage{[ 5, 5, 9 ]}
\hyperdef{L}{X81C340AD7EE8FA63}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{MinimalGeneratorsModuleGF({\slshape M})\index{MinimalGeneratorsModuleGF@\texttt{MinimalGeneratorsModuleGF}}
\label{MinimalGeneratorsModuleGF}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{MinimalGeneratorsModuleGFDestructive({\slshape M})\index{MinimalGeneratorsModuleGFDestructive@\texttt{MinimalGeneratorsModuleGFDestructive}}
\label{MinimalGeneratorsModuleGFDestructive}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{MinimalGeneratorsModuleRadical({\slshape M})\index{MinimalGeneratorsModuleRadical@\texttt{MinimalGeneratorsModuleRadical}}
\label{MinimalGeneratorsModuleRadical}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModuleGF 



 Returns a module equal to the \texttt{FpGModuleGF} \mbox{\texttt{\slshape M}}, but which has a minimal set of generators. Two algorithms are provided: 
\begin{itemize}
\item The two \texttt{GF} versions use \texttt{EchelonModuleGenerators} (\ref{EchelonModuleGenerators}) and \texttt{EchelonModuleGeneratorsDestructive} (\ref{EchelonModuleGeneratorsDestructive}) respectively. In characteristic two, these return a set of minimal generators,
and use less memory than the \texttt{Radical} version, but take longer. If the characteristic is not two, these functions
revert to \texttt{MinimalGeneratorsModuleRadical}. 
\item The \texttt{Radical} version uses the radical of the module in a manner similar to the function  \textbf{HAP: GeneratorsOfFpGModule}. This is much faster, but requires a considerable amount of temporary storage
space. 
\end{itemize}
 See Section \ref{FPGModuleExample2} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{RadicalOfModule}}
\logpage{[ 5, 5, 10 ]}\nobreak
\hyperdef{L}{X7E44920683157DE2}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{RadicalOfModule({\slshape M})\index{RadicalOfModule@\texttt{RadicalOfModule}}
\label{RadicalOfModule}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModuleGF 



 Returns radical of the \texttt{FpGModuleGF} module \mbox{\texttt{\slshape M}} as another \texttt{FpGModuleGF}. The radical is the module generated by the vectors $v-gv$ for all $v$ in the set of generating vectors for \mbox{\texttt{\slshape M}} and all $g$ in a set of generators for the module's group. 

 The generators for the returned module will not be in minimal form: the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}) can be used to convert the module to a minimal form if necessary. See
Section \ref{FPGModuleExample2} below for an example of usage. }

 
\subsection{\textcolor{Chapter }{Example: Generators and basis vectors of a \texttt{FpGModuleGF}}}\label{FPGModuleExample2}
\logpage{[ 5, 5, 11 ]}
\hyperdef{L}{X7F9E3DF87FE60C1A}{}
{
  Starting with the same module as in the earlier example (Section \ref{FPGModuleExample1}), we now investigate the generators of the module \texttt{M}. The generating vectors (of which there are 15) returned by the function \texttt{KernelOfModuleHomomorphism} (\ref{KernelOfModuleHomomorphism}) are not a minimal set, but the function \texttt{MinimalGeneratorsModuleGF} (\ref{MinimalGeneratorsModuleGF}) creates a new object \texttt{N} representing the same module, but now with only four generators. The vector
space spanned by these generators has 15 basis vectors, so representing the
module by a $G$-generating set instead is much more efficient. (The original generating set
in \texttt{M} was in fact an $\mathbb{F}$-basis, so the dimension of the vector space should come as no surprise.) 

 We can also find the radical of the module, and this is used internally for
the faster, but more memory-hungry, \texttt{MinimalGeneratorsModuleRadical} (\ref{MinimalGeneratorsModuleRadical}). 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := ResolutionPrimePowerGroupRadical(DihedralGroup(8), 2);;
  gap> phi := BoundaryFpGModuleHomomorphismGF(R, 2);;
  gap> M := KernelOfModuleHomomorphism(phi);;
  gap> #
  gap> ModuleGenerators(M);
  [ <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24> ]
  gap> ModuleGeneratorsAreMinimal(M);
  false
  gap> ModuleGeneratorsForm(M);
  "unknown"
  gap> #
  gap> N := MinimalGeneratorsModuleGF(M);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 4 generators in FG^
  3. Generators are in minimal echelon form.
  
  gap> M = N;    # Check that the new module spans the same space
  true
  gap> ModuleGeneratorsAreEchelonForm(N);
  true
  gap> ModuleIsFullCanonical(N);
  false
  gap> M = N;
  true
  gap> ModuleVectorSpaceBasis(N);
  [ <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24>, <a GF2 vector of length 24>,
    <a GF2 vector of length 24> ]
  gap> ModuleVectorSpaceDimension(N);
  15
  gap> #
  gap> N2 := MinimalGeneratorsModuleRadical(M);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 4 generators in FG^
  3. Generators are minimal.
  
  gap> #
  gap> R := RadicalOfModule(M);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 120 generators in FG^3.
  
  gap> N2 = N;
  true
\end{Verbatim}
 }

 }

  
\section{\textcolor{Chapter }{Block echelon functions}}\logpage{[ 5, 6, 0 ]}
\hyperdef{L}{X7B989D1181EBBBB5}{}
{
  

\subsection{\textcolor{Chapter }{EchelonModuleGenerators}}
\logpage{[ 5, 6, 1 ]}\nobreak
\hyperdef{L}{X84E3AA228784BF01}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{EchelonModuleGenerators({\slshape M})\index{EchelonModuleGenerators@\texttt{EchelonModuleGenerators}}
\label{EchelonModuleGenerators}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{EchelonModuleGeneratorsDestructive({\slshape M})\index{EchelonModuleGeneratorsDestructive@\texttt{EchelonModuleGeneratorsDestructive}}
\label{EchelonModuleGeneratorsDestructive}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SemiEchelonModuleGenerators({\slshape M})\index{SemiEchelonModuleGenerators@\texttt{SemiEchelonModuleGenerators}}
\label{SemiEchelonModuleGenerators}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SemiEchelonModuleGeneratorsDestructive({\slshape M})\index{SemiEchelonModuleGeneratorsDestructive@\texttt{SemiEchelonModuleGeneratorsDestructive}}
\label{SemiEchelonModuleGeneratorsDestructive}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{EchelonModuleGeneratorsMinMem({\slshape M})\index{EchelonModuleGeneratorsMinMem@\texttt{EchelonModuleGeneratorsMinMem}}
\label{EchelonModuleGeneratorsMinMem}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{EchelonModuleGeneratorsMinMemDestructive({\slshape M})\index{EchelonModuleGeneratorsMinMemDestructive@\texttt{EchelonModuleGeneratorsMinMemDestructive}}
\label{EchelonModuleGeneratorsMinMemDestructive}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SemiEchelonModuleGeneratorsMinMem({\slshape M})\index{SemiEchelonModuleGeneratorsMinMem@\texttt{SemiEchelonModuleGeneratorsMinMem}}
\label{SemiEchelonModuleGeneratorsMinMem}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SemiEchelonModuleGeneratorsMinMemDestructive({\slshape M})\index{SemiEchelonModuleGeneratorsMinMemDestructive@\texttt{Semi}\-\texttt{Echelon}\-\texttt{Module}\-\texttt{Generators}\-\texttt{Min}\-\texttt{Mem}\-\texttt{Destructive}}
\label{SemiEchelonModuleGeneratorsMinMemDestructive}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Record \texttt{(module, headblocks)} 



 Returns a record with two components: 
\begin{itemize}
\item \texttt{module} A module whose generators span the same vector space as that of the input
module \mbox{\texttt{\slshape M}}, but whose generators are in a block echelon (or semi-echelon) form
\item \texttt{headblocks} A list giving, for each generating vector in \mbox{\texttt{\slshape M}}, the block in which the head for that generating row lies
\end{itemize}
 In block-echelon form. each generator is row-reduced using $G$g-multiples of the other other generators to produce a new, equivalent
generating set where the first non-zero block in each generator is as far to
the right as possible. The resulting form, with many zero blocks, can allow
more memory-efficient operations on the module. See Section \ref{FpGModuleGFalgo} for details. In addition, the standard (non-\texttt{MinMem}) form guarantees that the set of generators are minimal in the sense that no
generator can be removed from the set while leaving the spanned vector space
the same. In the GF(2) case, this is the global minimum. 

 Several versions of this algorithm are provided. The \texttt{SemiEchelon} versions of these functions do not guarantee a particular generator ordering,
while the \texttt{Echelon} versions sort the generators into order of increasing initial zero blocks. The
non-\texttt{Destructive} versions of this function return a new module and do not modify the input
module; the \texttt{Destructive} versions change the generators of the input module in-place, and return this
module. All versions are memory-efficient, and do not need a full vector-space
basis. The \texttt{MinMem} versions are guaranteed to expand at most two generators at any one time,
while the standard version may, in the (unlikely) worst-case, need to expand
half of the generating set. As a result of this difference in the algorithm,
the \texttt{MinMem} version is likely to return a greater number of generators (which will not be
minimal), but those generators typically have a greater number of zero blocks
after the first non-zero block in the generator. The \texttt{MinMem} operations are currently only implemented for GF(2) modules. See Section \ref{FPGModuleExample3} below for an example of usage. }

 

\subsection{\textcolor{Chapter }{ReverseEchelonModuleGenerators}}
\logpage{[ 5, 6, 2 ]}\nobreak
\hyperdef{L}{X856E45CC84B53128}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ReverseEchelonModuleGenerators({\slshape M})\index{ReverseEchelonModuleGenerators@\texttt{ReverseEchelonModuleGenerators}}
\label{ReverseEchelonModuleGenerators}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ReverseEchelonModuleGeneratorsDestructive({\slshape M})\index{ReverseEchelonModuleGeneratorsDestructive@\texttt{Reverse}\-\texttt{Echelon}\-\texttt{Module}\-\texttt{Generators}\-\texttt{Destructive}}
\label{ReverseEchelonModuleGeneratorsDestructive}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModuleGF 



 Returns an \texttt{FpGModuleGF} module whose vector space spans the same space as the input module \mbox{\texttt{\slshape M}}, but whose generating vectors are modified to try to get as many zero blocks
as possible at the end of each vector. This function performs echelon
reduction of generating rows in a manner similar to \texttt{EchelonModuleGenerators} (\ref{EchelonModuleGenerators}), but working from the bottom upwards. It is guaranteed that this function
will not change the head block (the location of the first non-zero block) in
each generating row, and hence if the generators are already in an
upper-triangular form (e.g. following a call to \texttt{EchelonModuleGenerators} (\ref{EchelonModuleGenerators})) then it will not disturb that form and the resulting generators will be
closer to a diagonal form. 

 The \texttt{Destructive} version of this function modifies the input module's generators in-place and
then returns that module; the non-\texttt{Destructive} version works on a copy of the input module and so will not modify the
original module. 

 This operation is currently only implemented for GF(2) modules. See Section \ref{FPGModuleExample2} below for an example of usage. }

 
\subsection{\textcolor{Chapter }{Example: Converting a \texttt{FpGModuleGF} to block echelon form}}\label{FPGModuleExample3}
\logpage{[ 5, 6, 3 ]}
\hyperdef{L}{X83306CFA857F177C}{}
{
  We can construct a larger module than in the earlier examples (Sections \ref{FPGModuleExample1} and \ref{FPGModuleExample2}) by taking the kernel of the third boundary homomorphism of a minimal
resolution of a group of order 32, which as returned by the function \texttt{KernelOfModuleHomomorphism} (\ref{KernelOfModuleHomomorphism}) has a generating set with many redundant generators. We display the block
structure of the generators of this module after applying various block
echelon reduction functions.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := ResolutionPrimePowerGroupRadical(SmallGroup(32, 10), 3);;
  gap> phi := BoundaryFpGModuleHomomorphismGF(R, 3);;
  gap> #
  gap> M := KernelOfModuleHomomorphism(phi);
  Module over the group ring of <pc group of size 32 with
  5 generators> in characteristic 2 with 65 generators in FG^4.
  
  gap> #
  gap> N := SemiEchelonModuleGenerators(M);
  rec( module := Module over the group ring of <pc group of size 32 with
      5 generators> in characteristic 2 with 5 generators in FG^
      4. Generators are in minimal semi-echelon form.
      , headblocks := [ 2, 3, 1, 1, 3 ] )
  gap> DisplayBlocks(N.module);
  Module over the group ring of Group( [ f1, f2, f3, f4, f5 ] )
   in characteristic 2 with 5 generators in FG^4.
  [.*.*]
  [..**]
  [***.]
  [****]
  [..**]
  Generators are in minimal semi-echelon form.
  gap> N2 := SemiEchelonModuleGeneratorsMinMem(M);
  rec( module := Module over the group ring of <pc group of size 32 with
      5 generators> in characteristic 2 with 9 generators in FG^4. 
      , headblocks := [ 2, 1, 3, 1, 1, 4, 1, 3, 4 ] )
  gap> DisplayBlocks(N2.module);
  Module over the group ring of Group( [ f1, f2, f3, f4, f5 ] )
   in characteristic 2 with 9 generators in FG^4.
  [.*..]
  [**..]
  [..**]
  [****]
  [****]
  [...*]
  [****]
  [..**]
  [...*]
  
  gap> #
  gap> EchelonModuleGeneratorsDestructive(M);;
  gap> DisplayBlocks(M);
  Module over the group ring of Group( [ f1, f2, f3, f4, f5 ] )
   in characteristic 2 with 5 generators in FG^4.
  [***.]
  [****]
  [.*.*]
  [..**]
  [..**]
  Generators are in minimal echelon form.
  gap> ReverseEchelonModuleGeneratorsDestructive(M);
  Module over the group ring of <pc group of size 32 with
  5 generators> in characteristic 2 with 5 generators in FG^
  4. Generators are in minimal echelon form.
  
  gap> DisplayBlocks(M);
  Module over the group ring of Group( [ f1, f2, f3, f4, f5 ] )
   in characteristic 2 with 5 generators in FG^4.
  [***.]
  [****]
  [.*..]
  [..*.]
  [..**]
  Generators are in minimal echelon form.
\end{Verbatim}
 }

 }

  
\section{\textcolor{Chapter }{Sum and intersection functions}}\logpage{[ 5, 7, 0 ]}
\hyperdef{L}{X7B22D74482E6EF40}{}
{
  
\subsection{\textcolor{Chapter }{DirectSumOfModules}}\logpage{[ 5, 7, 1 ]}
\hyperdef{L}{X879541298181840D}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DirectSumOfModules({\slshape M, N})\index{DirectSumOfModules@\texttt{DirectSumOfModules}!for two modules}
\label{DirectSumOfModules:for two modules}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DirectSumOfModules({\slshape coll})\index{DirectSumOfModules@\texttt{DirectSumOfModules}!for collection of modules}
\label{DirectSumOfModules:for collection of modules}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DirectSumOfModules({\slshape M, n})\index{DirectSumOfModules@\texttt{DirectSumOfModules}!for n copies of the same module}
\label{DirectSumOfModules:for n copies of the same module}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModule 



 Returns the \texttt{FpGModuleGF} module that is the direct sum of the specified modules (which must have a
common group and action). The input can be either two modules \mbox{\texttt{\slshape M}} and \mbox{\texttt{\slshape N}}, a list of modules \mbox{\texttt{\slshape coll}}, or one module \mbox{\texttt{\slshape M}} and an exponent \mbox{\texttt{\slshape n}} specifying the number of copies of \mbox{\texttt{\slshape M}} to sum. See Section \ref{FPGModuleExample4} below for an example of usage. 

 If the input modules all have minimal generators and/or echelon form, the
construction of the direct sum guarantees that the output module will share
the same form. }

 

\subsection{\textcolor{Chapter }{DirectDecompositionOfModule}}
\logpage{[ 5, 7, 2 ]}\nobreak
\hyperdef{L}{X82A18B41872A8149}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DirectDecompositionOfModule({\slshape M})\index{DirectDecompositionOfModule@\texttt{DirectDecompositionOfModule}}
\label{DirectDecompositionOfModule}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DirectDecompositionOfModuleDestructive({\slshape M})\index{DirectDecompositionOfModuleDestructive@\texttt{DirectDecompositionOfModuleDestructive}}
\label{DirectDecompositionOfModuleDestructive}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 List of FpGModuleGFs 



 Returns a list of \texttt{FpGModuleGF}s whose direct sum is equal to the input \texttt{FpGModuleGF} module \mbox{\texttt{\slshape M}}. The list may consist of one element: the original module. 

 This function relies on the block structure of a set of generators that have
been converted to both echelon and reverse-echelon form (see \texttt{EchelonModuleGenerators} (\ref{EchelonModuleGenerators}) and \texttt{ReverseEchelonModuleGenerators} (\ref{ReverseEchelonModuleGenerators})), and calls these functions if the module is not already in echelon form. In
this form, it can be possible to trivially identify direct summands. There is
no guarantee either that this function will return a decomposition if one is
available, or that the modules returned in a decomposition are themselves
indecomposable. See Section \ref{FPGModuleExample4} below for an example of usage. 

 The \texttt{Destructive} version of this function uses the \texttt{Destructive} versions of the echelon functions, and so modifies the input module and
returns modules who share generating rows with the modified \mbox{\texttt{\slshape M}}. The non-\texttt{Destructive} version operates on a copy of \mbox{\texttt{\slshape M}}, and returns modules with unique rows. }

 

\subsection{\textcolor{Chapter }{IntersectionModules}}
\logpage{[ 5, 7, 3 ]}\nobreak
\hyperdef{L}{X83D609B679B53F5C}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IntersectionModules({\slshape M, N})\index{IntersectionModules@\texttt{IntersectionModules}}
\label{IntersectionModules}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IntersectionModulesGF({\slshape M, N})\index{IntersectionModulesGF@\texttt{IntersectionModulesGF}}
\label{IntersectionModulesGF}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IntersectionModulesGFDestructive({\slshape M, N})\index{IntersectionModulesGFDestructive@\texttt{IntersectionModulesGFDestructive}}
\label{IntersectionModulesGFDestructive}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IntersectionModulesGF2({\slshape M, N})\index{IntersectionModulesGF2@\texttt{IntersectionModulesGF2}}
\label{IntersectionModulesGF2}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModuleGF 



 Returns the \texttt{FpGModuleGF} module that is the intersection of the modules \mbox{\texttt{\slshape M}} and \mbox{\texttt{\slshape N}}. This function calculates the intersection using vector space methods (i.e. \texttt{SumIntersectionMatDestructive} (\textbf{HAPprime Datatypes: SumIntersectionMatDestructive})). The standard version works on the complete vector space bases of the input
modules. The \texttt{GF} version considers the block structure of the generators of \mbox{\texttt{\slshape M}} and \mbox{\texttt{\slshape N}} and only expands the necessary rows and blocks. This can lead to a large
saving and memory if \mbox{\texttt{\slshape M}} and \mbox{\texttt{\slshape N}} are in echelon form and have a small intersection. See Section \ref{FpGModuleGFalgoint} for details. See Section \ref{FPGModuleExample4} below for an example of usage. The \texttt{GF2} version computes the intersection by a $G$-version of the standard vector space algorithm, using \texttt{EchelonModuleGenerators} (\ref{EchelonModuleGenerators}) to perform echelon reduction on an augmented set of generators. This is much
slower than the \texttt{GF} version, but may use less memory. 

 The vector spaces in \texttt{FpGModuleGF}s are assumed to all be with respect to the same canonical basis, so it is
assumed that modules are compatible if they have the same group and the same
ambient dimension. 

 The \texttt{Destructive} version of the \texttt{GF} function corrupts or permutes the generating vectors of \mbox{\texttt{\slshape M}} and \mbox{\texttt{\slshape N}}, leaving it invalid; the non-destructive version operates on copies of them,
leaving the original modules unmodified. The generating vectors in the module
returned by this function are in fact also a \emph{vector space} basis for the module, so will not be minimal. The returned module can be
converted to a set of minimal generators using one of the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}). 

 This operation is currently only defined for GF(2). }

 

\subsection{\textcolor{Chapter }{SumModules}}
\logpage{[ 5, 7, 4 ]}\nobreak
\hyperdef{L}{X84A6FBC37BD8EEAB}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SumModules({\slshape M, N})\index{SumModules@\texttt{SumModules}}
\label{SumModules}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModuleGF 



 Returns the \texttt{FpGModuleGF} module that is the sum of the input modules \mbox{\texttt{\slshape M}} and \mbox{\texttt{\slshape N}}. This function simply concatenates the generating vectors of the two modules
and returns the result. If a set of minimal generators are needed then use one
of the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}) on the result. See Section \ref{FPGModuleExample4} below for an example of usage. 

 The vector spaces in \texttt{FpGModuleGF} are assumed to all be with respect to the same canonical basis, so it is
assumed that modules are compatible if they have the same group and the same
ambient dimension. }

 
\subsection{\textcolor{Chapter }{Example: Sum and intersection of \texttt{FpGModuleGF}s}}\label{FPGModuleExample4}
\logpage{[ 5, 7, 5 ]}
\hyperdef{L}{X8198B7C986776BA8}{}
{
  We can construct the direct sum of $\mathbb{F}G$-modules, and (attempt to) calculate a direct decomposition of a module. For
example, we can show that  
\[ (\mathbb{F}G)^2 \oplus \mathbb{F}G = \mathbb{F}G \oplus \mathbb{F}G \oplus
\mathbb{F}G \]
    
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> G := CyclicGroup(64);;
  gap> FG := FpGModuleGF(G, 1);
  Full canonical module FG^1 over the group ring of <pc group of size 64 with
  6 generators> in characteristic 2
  
  gap> FG2 := FpGModuleGF(G, 2);
  Full canonical module FG^2 over the group ring of <pc group of size 64 with
  6 generators> in characteristic 2
  
  gap> M := DirectSumOfModules(FG2, FG);
  Full canonical module FG^3 over the group ring of <pc group of size 64 with
  6 generators> in characteristic 2
  
  gap> DirectDecompositionOfModule(M);
  [ Module over the group ring of <pc group of size 64 with
      6 generators> in characteristic 2 with 1 generator in FG^
      1. Generators are in minimal echelon form.
      , Module over the group ring of <pc group of size 64 with
      6 generators> in characteristic 2 with 1 generator in FG^
      1. Generators are in minimal echelon form.
      , Module over the group ring of <pc group of size 64 with
      6 generators> in characteristic 2 with 1 generator in FG^
      1. Generators are in minimal echelon form.
       ]
\end{Verbatim}
 

 We can also compute the sum and intersection of $\mathbb{F}G$-modules. In the example below we construct two submodules of $\mathbb{F}G$, where $G$ is the dihedral group of order four: \texttt{M} is the submodule generated by $g_1 + g_2$, and \texttt{N} is the submodule generated by $g_1 + g_2 + g_3 + g_4$. We calculate their sum and intersection. Since \texttt{N} is in this case a submodule of \texttt{M} it is easy to check that the correct results are obtained.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> G := DihedralGroup(4);;
  gap> M := FpGModuleGF([[1,1,0,0]]*One(GF(2)), G);
  Module over the group ring of <pc group of size 4 with
  2 generators> in characteristic 2 with 1 generator in FG^
  1. Generators are in minimal echelon form.
  
  gap> N := FpGModuleGF([[1,1,1,1]]*One(GF(2)), G);
  Module over the group ring of <pc group of size 4 with
  2 generators> in characteristic 2 with 1 generator in FG^
  1. Generators are in minimal echelon form.
  
  gap> #
  gap> S := SumModules(M,N);
  Module over the group ring of <pc group of size 4 with
  2 generators> in characteristic 2 with 2 generators in FG^1.
  
  gap> I := IntersectionModules(M,N);
  Module over the group ring of <pc group of size 4 with
  2 generators> in characteristic 2 with 1 generator in FG^1.
  
  gap> #
  gap> S = M and I = N;
  true
\end{Verbatim}
 }

 }

  
\section{\textcolor{Chapter }{Miscellaneous functions}}\label{FpGModuleGFmisc}
\logpage{[ 5, 8, 0 ]}
\hyperdef{L}{X8308D685809A4E2F}{}
{
  

\subsection{\textcolor{Chapter }{= (for FpGModuleGF)}}
\logpage{[ 5, 8, 1 ]}\nobreak
\hyperdef{L}{X81A073C47FB50620}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{=({\slshape M, N})\index{=@\texttt{=}!for FpGModuleGF}
\label{=:for FpGModuleGF}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Boolean 



 Returns \texttt{true} if the modules are equal, \texttt{false} otherwise. This checks that the groups and actions in each module are equal
(i.e. identical), and that the vector space spanned by the two modules are the
same. (All vector spaces in \texttt{FpGModuleGF}s of the same ambient dimension are assumed to be embedded in the same
canonical basis.) See Section \ref{FPGModuleExample2} above for an example of usage. }

 
\subsection{\textcolor{Chapter }{IsModuleElement}}\logpage{[ 5, 8, 2 ]}
\hyperdef{L}{X78EB919D85362902}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IsModuleElement({\slshape M, elm})\index{IsModuleElement@\texttt{IsModuleElement}!for element}
\label{IsModuleElement:for element}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IsModuleElement({\slshape M, coll})\index{IsModuleElement@\texttt{IsModuleElement}!for collection of elements}
\label{IsModuleElement:for collection of elements}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Boolean 



 Returns \texttt{true} if the vector \mbox{\texttt{\slshape elm}} can be interpreted as an element of the module \mbox{\texttt{\slshape M}}, or \texttt{false} otherwise. If a collection of elements is given as the second argument then a
list of responses is returned, one for each element in the collection. See
Section \ref{FPGModuleExample0} above for an example of usage. }

 

\subsection{\textcolor{Chapter }{IsSubModule}}
\logpage{[ 5, 8, 3 ]}\nobreak
\hyperdef{L}{X8071ECEB7A92965A}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IsSubModule({\slshape M, N})\index{IsSubModule@\texttt{IsSubModule}}
\label{IsSubModule}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Boolean 



 Returns \texttt{true} if the module \mbox{\texttt{\slshape N}} is a submodule of \mbox{\texttt{\slshape M}}. This checks that the modules have the same group and action, and that the
generators for module \mbox{\texttt{\slshape N}} are elements of the module \mbox{\texttt{\slshape M}}. (All vector spaces in \texttt{FpGModuleGF}s of the same ambient dimension are assumed to be embedded in the same
canonical basis.) See Section \ref{FPGModuleExample0} above for an example of usage. }

 

\subsection{\textcolor{Chapter }{RandomElement}}
\logpage{[ 5, 8, 4 ]}\nobreak
\hyperdef{L}{X82FB0B387E53B073}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{RandomElement({\slshape M[, n]})\index{RandomElement@\texttt{RandomElement}}
\label{RandomElement}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Vector 



 Returns a vector which is a random element from the module \mbox{\texttt{\slshape M}}. If a second argument, \mbox{\texttt{\slshape n}} is give, then a list of \mbox{\texttt{\slshape n}} random elements is returned. See Section \ref{FPGModuleExample0} above for an example of usage. }

 
\subsection{\textcolor{Chapter }{Random Submodule}}\logpage{[ 5, 8, 5 ]}
\hyperdef{L}{X84EB237885A48F03}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{RandomSubmodule({\slshape M, ngens})\index{RandomSubmodule@\texttt{RandomSubmodule}}
\label{RandomSubmodule}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{FpGModuleGF} 



 Returns a \texttt{FpGModuleGF} module that is a submodule of \mbox{\texttt{\slshape M}}, with \mbox{\texttt{\slshape ngens}} generators selected at random from elements of \mbox{\texttt{\slshape M}}. These generators are not guaranteed to be minimal, so the rank of the
submodule will not necessarily be equal to \mbox{\texttt{\slshape ngens}}. If a module with minimal generators is required, the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}) can be used to convert the module to a minimal form See Section \ref{FPGModuleExample0} above for an example of usage. }

 }

 }

   
\chapter{\textcolor{Chapter }{$\mathbb{F}G$-module homomorphisms}}\label{FpGModuleGFHom}
\logpage{[ 6, 0, 0 ]}
\hyperdef{L}{X82F28552819A6542}{}
{
  
\section{\textcolor{Chapter }{The \texttt{FpGModuleHomomorphismGF} datatype}}\label{FpGModuleHomGFdatatype}
\logpage{[ 6, 1, 0 ]}
\hyperdef{L}{X85481E577D3BAB8E}{}
{
  Linear homomorphisms between free $\mathbb{F}G$-modules (as \texttt{FpGModuleGF} objects - see Chapter \ref{FpGModuleGF}) are represented in \textsf{HAPprime} using the \texttt{FpGModuleHomomorphismGF} datatype. This represents module homomorphisms in a similar manner to $\mathbb{F}G$-modules, using a set of generating vectors, in this case vectors that
generate the images in the target module of the generators of the source
module. 

 Three items need to be passed to the constructor function \texttt{FpGModuleHomomorphismGF} (\ref{FpGModuleHomomorphismGF}): 
\begin{itemize}
\item \texttt{source} the source \texttt{FpGModuleGF} module for the homomorphism 
\item \texttt{target} the target \texttt{FpGModuleGF} module for the homomorphism 
\item \texttt{gens} a list of vectors that are the images (in \texttt{target}) under the homomorphisms of each of the generators stored in \texttt{source} 
\end{itemize}
 }

 
\section{\textcolor{Chapter }{Calculating the kernel of a $\mathbb{F}G$-module homorphism by splitting into two homomorphisms}}\label{FpGModuleHomGFkernel}
\logpage{[ 6, 2, 0 ]}
\hyperdef{L}{X83FF0EBD81A405A9}{}
{
  \textsf{HAPprime} represents a homomorphism between two $\mathbb{F}G$-modules as a list of generators for the image of the homomorphism. Each
generator is given as an element in the target module, represented as a vector
in the same manner as used in the \texttt{FpGModuleGF} datatype (see Chapter \ref{FpGModuleGF}). Given a set of such generating vectors, an $\mathbb{F}$-generating set for the image of the homomorphism (as elements of the target
module's vector space) is given by taking all $G$-multiples of the generators. Writing the vectors in this expanded set as a
matrix, the kernel of the boundary homomorphism is the (left) null-space of
this matrix. As with \texttt{FpGModuleGF}s, the block structure of the generating vectors (see Section \ref{FpGModuleGFalgoblock}) allows this null-space to be calculated without necessarily expanding the
whole matrix. 

 This basic algorithm is implemented in the \textsf{HAPprime} function \texttt{KernelOfModuleHomomorphismSplit} (\ref{KernelOfModuleHomomorphismSplit}). The generating vectors for a module homomorphism $H$ are divided in half, with the homomorphism generated by the first half of the
generating vectors being called $U$ and that by the second half being called $V$. Given this partition the kernel of $H$ can be defined as  
\[ ker(H) = preim_U(I) \cap [-preim_V(I)] \]
   where 
\begin{itemize}
\item  $I = im(U) \cap im(V)$ is the intersection of the images of the two homomorphisms $U$ and $V$
\item  $preim_U(I)$ the set of all preimages of $I$ under $U$
\item  $preim_V(I)$ the set of all preimages of $I$ under $V$
\end{itemize}
 Rather than computing the complete set of preimages, instead the
implementation takes a preimage representative of each generator for $I$ and adds the kernel of the homomorphisms $U$ and $V$. The means that instead of calculating the null-space of the full expanded
matrix, we can compute the answer by calculating the kernels of two
homomorphisms with fewer generators, as well as the intersection of two
modules, and some preimage representatives. Each of these operations takes
less memory than the naive null-space calculation. The intersection of two $\mathbb{F}G$-modules can be compactly calculated using the generators' block structure
(see Section \ref{FpGModuleGFalgoint}), while the kernels of $U$ and $V$ can be computed recursively using these same algorithm. The block structure
can also help in calculating the preimage, but at a considerable cost in time,
so this is not done. However, since $U$ and $V$ have fewer generators than the original homomorphism $H$, a space saving is still made. 

 In the case where the problem is seperable, i.e. a $U$ and $V$ can be found for which there is no intersection, this approach can give a
large saving. The separable components of the homomorphism can be readily
identified from the block structure of the generators (they are the rows which
share no blocks or heads with other rows), and the kernels of these can be
calculated independently, with no intersection to worry about. This is
implemented in the alternative algorithm \texttt{KernelOfModuleHomomorphismIndependentSplit} (\ref{KernelOfModuleHomomorphismIndependentSplit}). }

 
\section{\textcolor{Chapter }{Calculating the kernel of a $\mathbb{F}G$-module homorphism by column reduction and partitioning}}\label{FpGModuleHomGFkernel2}
\logpage{[ 6, 3, 0 ]}
\hyperdef{L}{X8356C3B680B7110E}{}
{
  The list of generators of the image of a $\mathbb{F}G$-module homomorphism can be interpreted as the rows of a matrix $A$ with elements in $\mathbb{F}G$, and it is the kernel of this matrix which must be found (i.e. the solutions
to $xA=0$. If column reduction is performed on this matrix (by adding $\mathbb{F}G$-multiples of other columns to a column), the kernel is left unchanged, and
this process can be performed to enable the kernel to be found by a recursive
algorithm similar to standard back substitution methods. 

 Given the matrix $A = (a_{ij})$, take the $\mathbb{F}G$-module generated by the first row $(a_{1j})$ and find a minimal (or small) subset of elements $\{a_{1j}\}_{j \in J}$ that generate this module. Without altering the kernel, we can permute the
columns of $A$ such that $J = \{1 \ldots t\}$. Taking $\mathbb{F}$ and $G$-multiples of these columns from the remaining columns, the first row of these
columns can be reduced to zero, giving a new matrix $A'$. This matrix can be partitioned as follows:  
\[ \begin{pmatrix} B & 0 \\ C & D \end{pmatrix} \]
   where $B$ is $1\times t$, $C$ is $(m-1)\times t$ and $D$ is $(m-1)\times (n-t)$. It is assumed that $B$ and $C$ are `small' and operations on these can can be easily handled in memory using
standard linear algebra, while $D$ may still be large. 

 Taking the $\mathbb{F}G$-module generated by the $t$ columns which form the $BC$ partition of the matrix, we compute $E$, a set of minimal generators for the submodule of this which is zero in the
first row. These are added as columns at the end of $A'$, giving a matrix  
\[ \begin{pmatrix} B & 0 & 0\\ C & D & E\end{pmatrix} \]
   

 The kernel of this matrix can be shown to be  
\[ \begin{pmatrix} \ker B & 0\\ L & \ker (DE)\end{pmatrix} \]
   where 
\[ L = preim_B((\ker (DE)) C) \]
 The augmentation of $D$ with $E$ guarantees that this preimage always exists. Since $B$ and $C$ are small, both $\ker B$ and $L$ are easy to compute using linear algebra, while $\ker (DE)$ can be computed by recursion. 

 Unfortunately, $E$ can be large, and the accumulated increase of size of the matrix over many
recursions negates the time and memory saving that this algorithm might be
expected to give. Testing indicates that it is currently no faster than the \texttt{KernelOfModuleHomomorphismSplit} (\ref{KernelOfModuleHomomorphismSplit}) method, and does not save much memory over the full expansion using linear
algebra. An improved version of this algorithm would reduce $E$ by $D$ before augmentation, thus adding a smaller set of generators and restricting
the explosion in size. If $D$ were already in echelon form, this would also be time-efficient. }

 
\section{\textcolor{Chapter }{Construction functions}}\logpage{[ 6, 4, 0 ]}
\hyperdef{L}{X83D8009086035BCB}{}
{
  
\subsection{\textcolor{Chapter }{FpGModuleHomomorphismGF construction functions}}\logpage{[ 6, 4, 1 ]}
\hyperdef{L}{X8640D133855BB892}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleHomomorphismGF({\slshape S, T, gens})\index{FpGModuleHomomorphismGF@\texttt{FpGModuleHomomorphismGF}}
\label{FpGModuleHomomorphismGF}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{FpGModuleHomomorphismGFNC({\slshape S, T, gens})\index{FpGModuleHomomorphismGFNC@\texttt{FpGModuleHomomorphismGFNC}}
\label{FpGModuleHomomorphismGFNC}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{FpGModuleHomomorphismGF} 



 Creates and returns an \texttt{FpGModuleHomomorphismGF} module homomorphism object. This represents the homomorphism from the module \mbox{\texttt{\slshape S}} to the module \mbox{\texttt{\slshape T}} with a list of vectors \mbox{\texttt{\slshape gens}} whose rows are the images in \mbox{\texttt{\slshape T}} of the generators of \mbox{\texttt{\slshape S}}. The modules must (currently) be over the same group. 

 The standard constructor checks that the homomorphism is compatible with the
modules, i.e. that the vectors in \mbox{\texttt{\slshape gens}} have the correct dimension and that they lie within the target module \mbox{\texttt{\slshape T}}. It also checks whether the generators of \mbox{\texttt{\slshape S}} are minimal. If they are not, then the homomorphism is created with a copy of \mbox{\texttt{\slshape S}} that has minimal generators (using \texttt{MinimalGeneratorsModuleRadical} (\ref{MinimalGeneratorsModuleRadical})), and \mbox{\texttt{\slshape gens}} is also copied and converted to agree with the new form of \mbox{\texttt{\slshape S}}. If you wish to skip these checks then use the \texttt{NC} version of this function. 

 IMPORTANT: The generators of the module \mbox{\texttt{\slshape S}} and the generator matrix \mbox{\texttt{\slshape gens}} must be remain consistent for the lifetime of this homomorphism. If the
homomorphism is constructed with a mutable source module or generator matrix,
then you must be careful not to modify them while the homomorphism is needed. }

 
\subsection{\textcolor{Chapter }{Example: Constructing a \texttt{FpGModuleHomomorphismGF}}}\label{FPGModuleHomExample0}
\logpage{[ 6, 4, 2 ]}
\hyperdef{L}{X7EA7C568836E9730}{}
{
  In this example we construct the module homomorphism $\phi: (\mathbb{F}G)^2 \to \mathbb{F}G$ which maps both generators of $(\mathbb{F}G)^2$ to the generator of $\mathbb{F}G$  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> G := SmallGroup(8, 4);;
  gap> im := [1,0,0,0,0,0,0,0]*One(GF(2));
  [ Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2) ]
  gap> phi := FpGModuleHomomorphismGF(
  >              FpGModuleGF(G, 2),
  >              FpGModuleGF(G, 1),
  >              [im, im]);
  <Module homomorphism>
\end{Verbatim}
 }

 }

 
\section{\textcolor{Chapter }{Data access functions}}\logpage{[ 6, 5, 0 ]}
\hyperdef{L}{X7DE3278D7E5DEE03}{}
{
  

\subsection{\textcolor{Chapter }{SourceModule}}
\logpage{[ 6, 5, 1 ]}\nobreak
\hyperdef{L}{X835A27F3877D7B04}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SourceModule({\slshape phi})\index{SourceModule@\texttt{SourceModule}}
\label{SourceModule}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{FpGModuleGF} 



 Returns the source module for the homomorphism \mbox{\texttt{\slshape phi}}, as an \texttt{FpGModuleGF}. }

 

\subsection{\textcolor{Chapter }{TargetModule}}
\logpage{[ 6, 5, 2 ]}\nobreak
\hyperdef{L}{X810013F0852729DD}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{TargetModule({\slshape phi})\index{TargetModule@\texttt{TargetModule}}
\label{TargetModule}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 FpGModuleGF 



 Returns the targetmodule for the homomorphism \mbox{\texttt{\slshape phi}}, as an \texttt{FpGModuleGF}. }

 

\subsection{\textcolor{Chapter }{ModuleHomomorphismGeneratorMatrix}}
\logpage{[ 6, 5, 3 ]}\nobreak
\hyperdef{L}{X81173EB682B5C903}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ModuleHomomorphismGeneratorMatrix({\slshape phi})\index{ModuleHomomorphismGeneratorMatrix@\texttt{ModuleHomomorphismGeneratorMatrix}}
\label{ModuleHomomorphismGeneratorMatrix}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 List of vectors 



 Returns the generating vectors \texttt{gens} of the representation of the homomorphism \mbox{\texttt{\slshape phi}}. These vectors are the images in the target module of the generators of the
source module. }

 

\subsection{\textcolor{Chapter }{DisplayBlocks (for FpGModuleHomomorphismGF)}}
\logpage{[ 6, 5, 4 ]}\nobreak
\hyperdef{L}{X7EF5C42A79568EAE}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DisplayBlocks({\slshape phi})\index{DisplayBlocks@\texttt{DisplayBlocks}!for FpGModuleHomomorphismGF}
\label{DisplayBlocks:for FpGModuleHomomorphismGF}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
 nothing 



 Prints a detailed description of the module in human-readable form, with the
module generators and generator matrix shown in block form. The standard \textsf{GAP} methods \texttt{View} (\textbf{Reference: View}), \texttt{Print} (\textbf{Reference: Print}) and \texttt{Display} (\textbf{Reference: Display}) are also available.) }

 

\subsection{\textcolor{Chapter }{DisplayModuleHomomorphismGeneratorMatrix}}
\logpage{[ 6, 5, 5 ]}\nobreak
\hyperdef{L}{X7D200588818203D6}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DisplayModuleHomomorphismGeneratorMatrix({\slshape phi})\index{DisplayModuleHomomorphismGeneratorMatrix@\texttt{DisplayModuleHomomorphismGeneratorMatrix}}
\label{DisplayModuleHomomorphismGeneratorMatrix}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
 nothing 



 Prints a detailed description of the module homomorphism generating vectors \texttt{gens} in human-readable form. This is the display method used in the \texttt{Display} (\textbf{Reference: Display}) method for this datatype. }

 

\subsection{\textcolor{Chapter }{DisplayModuleHomomorphismGeneratorMatrixBlocks}}
\logpage{[ 6, 5, 6 ]}\nobreak
\hyperdef{L}{X831A8A6485A484D7}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DisplayModuleHomomorphismGeneratorMatrixBlocks({\slshape phi})\index{DisplayModuleHomomorphismGeneratorMatrixBlocks@\texttt{Display}\-\texttt{Module}\-\texttt{Homomorphism}\-\texttt{Generator}\-\texttt{Matrix}\-\texttt{Blocks}}
\label{DisplayModuleHomomorphismGeneratorMatrixBlocks}
}\hfill{\scriptsize (method)}}\\
\textbf{\indent Returns:\ }
 nothing 



 Prints a detailed description of the module homomorphism generating vectors \texttt{gens} in human-readable form. This is the function used in the \texttt{DisplayBlocks} (\ref{DisplayBlocks:for FpGModuleHomomorphismGF}) method. }

 
\subsection{\textcolor{Chapter }{Example: Accessing data about a \texttt{FpGModuleHomomorphismGF}}}\label{FPGModuleHomExample1}
\logpage{[ 6, 5, 7 ]}
\hyperdef{L}{X7C5F52FE80BB871A}{}
{
  A free $\mathbb{F}G$ resolution is a chain complex of $\mathbb{F}G$-modules and homomorphisms, and the homomorphisms in a \texttt{HAPResolution} (see Chapter \ref{Resolution}) can be extracted as a \texttt{FpGModuleHomomorphismGF} using the function \texttt{BoundaryFpGModuleHomomorphismGF} (\ref{BoundaryFpGModuleHomomorphismGF}). We construct a resolution \texttt{R} and then examine the third resolution in the chain complex, which is a $\mathbb{F}G$-module homomorphism $d_3 : (\mathbb{F}G)^7 \to (\mathbb{F}G)^5$.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := ResolutionPrimePowerGroupRadical(SmallGroup(64, 141), 3);;
  #I  Dimension 2: rank 5
  #I  Dimension 3: rank 7
  gap> d3 := BoundaryFpGModuleHomomorphismGF(R, 3);;
  gap> SourceModule(d3);
  Full canonical module FG^7 over the group ring of <pc group of size 64 with
  6 generators> in characteristic 2
  
  gap> TargetModule(d3);
  Full canonical module FG^5 over the group ring of <pc group of size 64 with
  6 generators> in characteristic 2
  
  gap> ModuleHomomorphismGeneratorMatrix(d3);
  <an immutable 7x320 matrix over GF2>
  gap> DisplayBlocks(d3);
  Module homomorphism with source:
  Full canonical module FG^7 over the group ring of Group(
  [ f1, f2, f3, f4, f5, f6 ] )
   in characteristic 2
  
  and target:
  Full canonical module FG^5 over the group ring of Group(
  [ f1, f2, f3, f4, f5, f6 ] )
   in characteristic 2
  
  and generator matrix:
  [*.*.*]
  [*****]
  [.**..]
  [.**..]
  [..**.]
  [...**]
  [...*.]
  
\end{Verbatim}
 

 Note that the module homomorphism generating vectors in a resolution
calculated using \textsf{HAPprime} are in block-echelon form (see Section \ref{FpGModuleGFalgo}). This makes it efficient to compute the kernel of this homomorphism using \texttt{KernelOfModuleHomomorphismSplit} (\ref{KernelOfModuleHomomorphismSplit}), as described in Section \ref{FpGModuleHomGFkernel}, since there is only a small intersection between the images generated by the
top and bottom halves of the generating vectors. }

 }

 
\section{\textcolor{Chapter }{Image and kernel functions}}\logpage{[ 6, 6, 0 ]}
\hyperdef{L}{X79444C767921055C}{}
{
  
\subsection{\textcolor{Chapter }{ImageOfModuleHomomorphism}}\logpage{[ 6, 6, 1 ]}
\hyperdef{L}{X8038F50582425ECA}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageOfModuleHomomorphism({\slshape phi})\index{ImageOfModuleHomomorphism@\texttt{ImageOfModuleHomomorphism}!image of homomorphism}
\label{ImageOfModuleHomomorphism:image of homomorphism}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageOfModuleHomomorphism({\slshape phi, M})\index{ImageOfModuleHomomorphism@\texttt{ImageOfModuleHomomorphism}!of module}
\label{ImageOfModuleHomomorphism:of module}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageOfModuleHomomorphism({\slshape phi, elm})\index{ImageOfModuleHomomorphism@\texttt{ImageOfModuleHomomorphism}!of element}
\label{ImageOfModuleHomomorphism:of element}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageOfModuleHomomorphism({\slshape phi, coll})\index{ImageOfModuleHomomorphism@\texttt{ImageOfModuleHomomorphism}!of collections of elements}
\label{ImageOfModuleHomomorphism:of collections of elements}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageOfModuleHomomorphismDestructive({\slshape phi, elm})\index{ImageOfModuleHomomorphismDestructive@\texttt{ImageOfModuleHomomorphismDestructive}!of element}
\label{ImageOfModuleHomomorphismDestructive:of element}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageOfModuleHomomorphismDestructive({\slshape phi, coll})\index{ImageOfModuleHomomorphismDestructive@\texttt{ImageOfModuleHomomorphismDestructive}!of collection of elements}
\label{ImageOfModuleHomomorphismDestructive:of collection of elements}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{FpGModuleGF}, vector or list of vectors depending on argument 



 For a module homomorphism \mbox{\texttt{\slshape phi}}, the one-argument function returns the module that is the image of the
homomorphism, while the two-argument versions return the result of mapping of
an \texttt{FpGModuleGF} \mbox{\texttt{\slshape M}}, a module element \mbox{\texttt{\slshape elm}} (given as a vector), or a collection of module elements \mbox{\texttt{\slshape coll}} through the homomorphism. This uses standard linear algebra to find the image
of elements from the source module. 

 The \texttt{Destructive} versions of the function will corrupt the second parameter, which must be
mutable as a result. The version of this operation that returns a module does
not guarantee that the module will be in minimal form, and one of the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}) should be used on the result if a minimal set of generators is needed. }

 
\subsection{\textcolor{Chapter }{PreImageRepresentativeOfModuleHomomorphism}}\logpage{[ 6, 6, 2 ]}
\hyperdef{L}{X850FD5AE80BF6F11}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PreImageRepresentativeOfModuleHomomorphism({\slshape phi, elm})\index{PreImageRepresentativeOfModuleHomomorphism@\texttt{Pre}\-\texttt{Image}\-\texttt{Representative}\-\texttt{Of}\-\texttt{Module}\-\texttt{Homomorphism}!for element}
\label{PreImageRepresentativeOfModuleHomomorphism:for element}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PreImageRepresentativeOfModuleHomomorphism({\slshape phi, coll})\index{PreImageRepresentativeOfModuleHomomorphism@\texttt{Pre}\-\texttt{Image}\-\texttt{Representative}\-\texttt{Of}\-\texttt{Module}\-\texttt{Homomorphism}!for collection of elements}
\label{PreImageRepresentativeOfModuleHomomorphism:for collection of elements}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PreImageRepresentativeOfModuleHomomorphism({\slshape phi, M})\index{PreImageRepresentativeOfModuleHomomorphism@\texttt{Pre}\-\texttt{Image}\-\texttt{Representative}\-\texttt{Of}\-\texttt{Module}\-\texttt{Homomorphism}!for module}
\label{PreImageRepresentativeOfModuleHomomorphism:for module}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PreImageRepresentativeOfModuleHomomorphismGF({\slshape phi, elm})\index{PreImageRepresentativeOfModuleHomomorphismGF@\texttt{Pre}\-\texttt{Image}\-\texttt{Representative}\-\texttt{Of}\-\texttt{Module}\-\texttt{HomomorphismGF}!for element}
\label{PreImageRepresentativeOfModuleHomomorphismGF:for element}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PreImageRepresentativeOfModuleHomomorphismGF({\slshape phi, coll})\index{PreImageRepresentativeOfModuleHomomorphismGF@\texttt{Pre}\-\texttt{Image}\-\texttt{Representative}\-\texttt{Of}\-\texttt{Module}\-\texttt{HomomorphismGF}!for collection of elements}
\label{PreImageRepresentativeOfModuleHomomorphismGF:for collection of elements}
}\hfill{\scriptsize (operation)}}\\


 For an element \mbox{\texttt{\slshape elm}} in the image of \mbox{\texttt{\slshape phi}}, this returns a representative of the set of preimages of \mbox{\texttt{\slshape elm}} under \mbox{\texttt{\slshape phi}}, otherwise it returns \texttt{fail}. If a list of vectors \mbox{\texttt{\slshape coll}} is provided then the function returns a list of preimage representatives, one
for each element in the list (the returned list can contain \texttt{fail} entries if there are vectors with no solution). For an \texttt{FpGModuleGF} module \mbox{\texttt{\slshape M}}, this returns a module whose image under \mbox{\texttt{\slshape phi}} is \mbox{\texttt{\slshape M}} (or \texttt{fail}). The module returned will not necessarily have minimal generators, and one
of the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}) should be used on the result if a minimal set of generators is needed. 

 The standard functions use linear algebra, expanding the generator matrix into
a full matrix and using \texttt{SolutionMat} (\textbf{Reference: SolutionMat}) to calculate a preimage of \mbox{\texttt{\slshape elm}}. In the case where a list of vectors is provided, the matrix decomposition is
only performed once, which can save significant time. 

 The \texttt{GF} versions of the functions can give a large memory saving when the generators
of the homomorphism \mbox{\texttt{\slshape phi}} are in echelon form, and operate by doing back-substitution using the
generator form of the matrices. }

 

\subsection{\textcolor{Chapter }{KernelOfModuleHomomorphism}}
\logpage{[ 6, 6, 3 ]}\nobreak
\hyperdef{L}{X86C7D57A825235EE}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{KernelOfModuleHomomorphism({\slshape phi})\index{KernelOfModuleHomomorphism@\texttt{KernelOfModuleHomomorphism}}
\label{KernelOfModuleHomomorphism}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{KernelOfModuleHomomorphismSplit({\slshape phi})\index{KernelOfModuleHomomorphismSplit@\texttt{KernelOfModuleHomomorphismSplit}}
\label{KernelOfModuleHomomorphismSplit}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{KernelOfModuleHomomorphismIndependentSplit({\slshape phi})\index{KernelOfModuleHomomorphismIndependentSplit@\texttt{Kernel}\-\texttt{Of}\-\texttt{Module}\-\texttt{Homomorphism}\-\texttt{Independent}\-\texttt{Split}}
\label{KernelOfModuleHomomorphismIndependentSplit}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{KernelOfModuleHomomorphismGF({\slshape phi})\index{KernelOfModuleHomomorphismGF@\texttt{KernelOfModuleHomomorphismGF}}
\label{KernelOfModuleHomomorphismGF}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{FpGModuleGF} 



 Returns the kernel of the module homomorphism \mbox{\texttt{\slshape phi}}, as an \texttt{FpGModuleGF} module. There are three independent algorithms for calculating the kernel,
represented by different versions of this function: 
\begin{itemize}
\item  The standard version calculates the kernel by the obvious vector-space method.
The homomorphism's generators are expanded into a full vector-space basis and
the kernel of that vector space homomorphism is found. The generators of the
returned module are in fact a vector space basis for the kernel module. 
\item  The \texttt{Split} version divides the homomorphism into two (using the first half and the second
half of the generating vectors), and uses the preimage of the intersection of
the images of the two halves to calculate the kernel (see Section \ref{FpGModuleHomGFkernel}). If the generating vectors for \mbox{\texttt{\slshape phi}} are in block echelon form (see Section \ref{FpGModuleGFalgo}), then this approach provides a considerable memory saving over the standard
approach. 
\item  The \texttt{IndependentSplit} version splits the generating vectors into sets that generate vector spaces
which have no intersection, and calculates the kernel as the sum of the
kernels of those independent rows. If the generating vectors can be decomposed
in this manner (i.e. the the generator matrix is in a diagonal form), this
will provide a very large memory saving over the standard approach. 
\item  The \texttt{GF} version performs column reduction and partitioning of the generator matrix to
enable a recursive approach to computing the kernel (see Section \ref{FpGModuleHomGFkernel2}). The level of partitioning is governed by the option \texttt{MaxFGExpansionSize}, which defaults to $10^9$, allowing about 128Mb of memory to be used for standard linear algebra before
partitioning starts. See  (\textbf{Reference: Options Stack}) for details of using options in \textsf{GAP} 
\end{itemize}
 None of these basis versions of the functions guarantee to return a minimal
set of generators, and one of the \texttt{MinimalGeneratorsModule} functions (\ref{MinimalGeneratorsModule}) should be used on the result if a minimal set of generators is needed. All
of the functions leave the input homomorphism \mbox{\texttt{\slshape phi}} unchanged. }

 
\subsection{\textcolor{Chapter }{Example: Kernel and Image of a \texttt{FpGModuleHomomorphismGF}}}\label{FPGModuleHomExample2}
\logpage{[ 6, 6, 4 ]}
\hyperdef{L}{X795D4069832F15F8}{}
{
  A free $\mathbb{F}G$-resolution of a module is an exact sequence of module homomorphisms. In this
example we use the functions \texttt{ImageOfModuleHomomorphism} (\ref{ImageOfModuleHomomorphism:image of homomorphism}) and \texttt{KernelOfModuleHomomorphism} (\ref{KernelOfModuleHomomorphism}) to check that one of the sequences in a resolution is exact, i.e. that in the
sequence  
\[ M_3 \to M_2 \to M_1 \]
   the image of the first homomorphism $d_3: M_3 \to M_2$ is the kernel of the second homomorphism $d_2: M_2 \to M_1$ 

 We also demonstrate that we can find the image and preimage of module elements
under our module homomorphisms. We take an element \texttt{e} of $M_2$, in this case by taking the first generating element of the kernel of $d_2$, and map it up to $M_3$ and back. 

 Finally, we compute the kernel using the other available methods, and check
that the results are the same.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := ResolutionPrimePowerGroupRadical(SmallGroup(8, 3), 3);;
  gap> d2 := BoundaryFpGModuleHomomorphismGF(R, 2);;
  gap> d3 := BoundaryFpGModuleHomomorphismGF(R, 3);;
  gap> #
  gap> I := ImageOfModuleHomomorphism(d3);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 4 generators in FG^3.
  
  gap> K := KernelOfModuleHomomorphism(d2);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 15 generators in FG^3.
  
  gap> I = K;
  true
  gap> #
  gap> e := ModuleGenerators(K)[1];;
  gap> PreImageRepresentativeOfModuleHomomorphism(d3, e);
  <a GF2 vector of length 32>
  gap> f := PreImageRepresentativeOfModuleHomomorphism(d3, e);
  <a GF2 vector of length 32>
  gap> ImageOfModuleHomomorphism(d3, f);
  <a GF2 vector of length 24>
  gap> last = e;
  true
  gap> #
  gap> L := KernelOfModuleHomomorphismSplit(d2);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 5 generators in FG^3.
  
  gap> K = L;
  true
  gap> M := KernelOfModuleHomomorphismGF(d2);
  Module over the group ring of <pc group of size 8 with
  3 generators> in characteristic 2 with 4 generators in FG^
  3. Generators are minimal.
  
  gap> K = M;
  true
\end{Verbatim}
 }

 }

 }

   
\chapter{\textcolor{Chapter }{Ring homomorphisms}}\label{RingHomomorphism}
\logpage{[ 7, 0, 0 ]}
\hyperdef{L}{X7E88C32A82E942DA}{}
{
  A ring homomorphism is a linear function $f: R \to S$ that maps between two rings $R$ and $S$ and which preserves the operations of multiplication and addition:  
\[ \begin{align*} f(a + b) &= f(a) + f(b) \\ f(ab) &= f(a)f(b) \\ f(1) &= 1
\end{align*} \]
   
\section{\textcolor{Chapter }{The \texttt{HAPRingHomomorphism} datatype}}\logpage{[ 7, 1, 0 ]}
\hyperdef{L}{X7A0B792785E2AA8A}{}
{
  The \texttt{HAPRingHomomorphism} datatype represents a particular class of ring homomorphisms (in fact usually
ring isomorphisms), namely those between rings presented as quotient rings of
polynomial rings, where the source and target rings have the same coefficient
ring. They represent the mapping  
\[ \frac{R}{I} \to \frac{S}{J} \]
   where $R = k[x_1, \ldots, x_n]$ and $S = k[y_1, \ldots, x_m]$ and $I$ and $J$ are ideals in $R$ and $S$ respectively. 

 Such a ring homomorphism may be specified by the following information 
\begin{itemize}
\item a polynomial ring $R$
\item a list of polynomials in $R$ that generate the ideal $I$
\item a list $Q = [q_1, ..., q_n]$ where each $q_i \in S/J$ is the image of the indeterminate $x_i$ in $R$ under the homomorphism.
\end{itemize}
 The target ideal $J$ is assumed to be the image of $I$ under the homomorphism. 
\subsection{\textcolor{Chapter }{Implementation details}}\logpage{[ 7, 1, 1 ]}
\hyperdef{L}{X7AB84A0B83B2C1F1}{}
{
  Various different internal representations are used for ring homomorphisms in \textsf{HAPprime}, depending on the source and target ring. The user need not be concerned with
the different representations, which correspond to the five constructors \texttt{HAPRingToSubringHomomorphism} (\ref{HAPRingToSubringHomomorphism}), \texttt{HAPSubringToRingHomomorphism} (\ref{HAPSubringToRingHomomorphism:for relations defined at source}), \texttt{HAPRingHomomorphismByIndeterminateMap} (\ref{HAPRingHomomorphismByIndeterminateMap}), \texttt{HAPRingReductionHomomorphism} (\ref{HAPRingReductionHomomorphism:for ring presentation}) and \texttt{HAPZeroRingHomomorphism} (\ref{HAPZeroRingHomomorphism}), and which are hopefully largely self-explanatory. 

 Most of the provided representations of ring homomorphisms use Gr{\"o}bner
bases and polynomial reduction to perform the mapping. This uses the \textsf{singular} package  (\textbf{singular: singular: the GAP interface to Singular}) which gives good speed and access to improved monomial orderings. This
datatype cannot be used without the \textsf{singular} package. }

 
\subsection{\textcolor{Chapter }{Elimination orderings}}\label{RingHomEliminationOrdering}
\logpage{[ 7, 1, 2 ]}
\hyperdef{L}{X7AB0F3977DC63F54}{}
{
  Using Gr{\"o}bner bases to map from one polynomial ring $R$ to another polynomial ring $S$ relies on applying a global ordering to the joint ring $R \cup S$. For all polynomials $p \in R$ and $q \in S$, this ordering must give $p > q$, so that terms involving elements of $R$ will be replaced by those in $S$. A straightforward solution is to use a lexicographic term ordering which
orders the indeterminates of $R$ before those of $S$. However, computing Gr{\"o}bner bases using a lexicographic ordering can be
much more expensive that with other orderings, or sometimes even a change of
the order of indeterminates is enough change the order of the computation. A
range of different ordering can be requested by using the \textsf{GAP} options stack  (\textbf{Reference: Options Stack}), and setting the options \texttt{EliminationIndexOrder} and \texttt{EliminationBlockOrdering} as described below. 

 The option \texttt{EliminationIndexOrder} determines the indeterminate ordering to use. Possible values are the
following strings: 
\begin{itemize}
\item \texttt{"Forward"} (default) Indeterminates are ordered as in the definition of $R$ and $S$: $p_1 > p_2 > \ldots > p_n > q_1 > q_2 > \ldots > q_m$.
\item \texttt{"Reverse"} Lexicographic ordering in reverse order to that in the definition of $R$ and $S$: $p_n > p_{n-1} > \ldots > p_1 > q_m > q_{m-1} > \ldots > q_1$.
\item \texttt{"Shuffle"} Lexicographic ordering using a random shuffle of the indeterminates in $R$ and $S$.
\item \texttt{"ShuffleNN"} where \texttt{NN} is some non-negative integer. This is the same as \texttt{Shuffle}, but using the value of \texttt{NN} as the random seed (and hence is deterministic).
\end{itemize}
 

 When comparing two monomials, the elimination ordering ensures that the parts
of the two monomials involving the indeterminates from $R$ are compared first, and then in the event of a tie, the part involving those
from $S$ are compared. The option \texttt{EliminationBlockOrdering} determines the monomial ordering to use for each of these two comparisons.
This is given as a string which is the concatenation of the two required
orderings. For example, the default ordering is \texttt{"LexGrlex"} which means lexicographic ordering over the indeterminates of $R$, and graded lexicographic over the indeterminates of $S$. 
\begin{itemize}
\item \texttt{"Lex"} Lexicographic ordering, the equivalent of the \textsf{GAP} ordering \texttt{MonomialLexOrdering} (\textbf{Reference: MonomialLexOrdering})).
\item \texttt{"Grlex"} Graded lexicographic ordering, the equivalent of \texttt{MonomialGrlexOrdering} (\textbf{Reference: MonomialGrlexOrdering}).
\item \texttt{"Grevlex"} Graded reverse lexicographic ordering, the equivalent of \texttt{MonomialGrevlexOrdering} (\textbf{Reference: MonomialGrevlexOrdering}).
\end{itemize}
 }

 }

 
\section{\textcolor{Chapter }{Construction functions}}\logpage{[ 7, 2, 0 ]}
\hyperdef{L}{X83D8009086035BCB}{}
{
  

\subsection{\textcolor{Chapter }{HAPRingToSubringHomomorphism}}
\logpage{[ 7, 2, 1 ]}\nobreak
\hyperdef{L}{X7A500F53808DDDA9}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HAPRingToSubringHomomorphism({\slshape Rring, Rrels, Simages})\index{HAPRingToSubringHomomorphism@\texttt{HAPRingToSubringHomomorphism}}
\label{HAPRingToSubringHomomorphism}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPRingHomomorphism} 



 Creates a \texttt{HAPRingHomomorphism} which represents the mapping $R/I \to S/J$. In this form, \mbox{\texttt{\slshape Rring}} a polynomial ring $R$ and \mbox{\texttt{\slshape Rrels}} an ideal $I$ in that ring. The image of the indeterminates of \mbox{\texttt{\slshape R}} under this mapping are given in \mbox{\texttt{\slshape Simages}} and generate the ring $S$, while the relations \mbox{\texttt{\slshape Rrels}} are mapped to generate $J$. The ring $S$ may be a subring of the full polynomial ring in its indeterminates. }

 
\subsection{\textcolor{Chapter }{HAPSubringToRingHomomorphism}}\logpage{[ 7, 2, 2 ]}
\hyperdef{L}{X7A7E46337D6F47B6}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HAPSubringToRingHomomorphism({\slshape Rgens, Rrels, Sring})\index{HAPSubringToRingHomomorphism@\texttt{HAPSubringToRingHomomorphism}!for relations defined at source}
\label{HAPSubringToRingHomomorphism:for relations defined at source}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HAPSubringToRingHomomorphism({\slshape Rgens, Sring, Srels})\index{HAPSubringToRingHomomorphism@\texttt{HAPSubringToRingHomomorphism}!for relations defined at image}
\label{HAPSubringToRingHomomorphism:for relations defined at image}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPRingHomomorphism} 



 Creates a \texttt{HAPRingHomomorphism} which represents the mapping $R/I \to S/J$. The ring $R$ is generated by a set of polynomials \mbox{\texttt{\slshape Rgens}} (so $R$ may be a subring of the full polynomial ring in its indeterminates). The
images of \mbox{\texttt{\slshape Rgens}} under the mapping are the indeterminates of the polynomial ring given in \mbox{\texttt{\slshape Sring}}. The ideals can be specified either as a set of relations \mbox{\texttt{\slshape Srels}} in the target ring $S$, or as a set of relations \mbox{\texttt{\slshape Rrels}} in the source ring. In this second case, \mbox{\texttt{\slshape Rrels}} can be polynomials in the full polynomial ring, in which case the ideal $I$ is the intersection of the ideal they generate in the full ring with the
subring generated by \mbox{\texttt{\slshape Rgens}}. In both cases, the specified ideal is mapped with the homomorphism (or its
inverse) to find the corresponding ideal in the other ring. 

 This ring homomorphism uses Gr{\"o}bner bases to perform the mapping, and the
time taken to calculate the basis in this function can be influenced by the
choice of monomial ordering. See \ref{RingHomEliminationOrdering} for more details. }

 

\subsection{\textcolor{Chapter }{HAPRingHomomorphismByIndeterminateMap}}
\logpage{[ 7, 2, 3 ]}\nobreak
\hyperdef{L}{X7A77983F7D6E0AC7}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HAPRingHomomorphismByIndeterminateMap({\slshape R, Rrels, S})\index{HAPRingHomomorphismByIndeterminateMap@\texttt{HAPRingHomomorphismByIndeterminateMap}}
\label{HAPRingHomomorphismByIndeterminateMap}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPRingHomomorphism} 



 Creates a \texttt{HAPRingHomomorphism} which represents the map $R/I \to S/J $ which is a simple relabelling of indeterminates: the image of the $i$th indeterminate of \mbox{\texttt{\slshape R}} under the mapping is taken to be the $i$th indeterminate of \mbox{\texttt{\slshape S}}. The ideal $I$ is generated by \mbox{\texttt{\slshape Rrels}} and are mapped using the homomorphism to generate $J$. }

 

\subsection{\textcolor{Chapter }{HAPRingReductionHomomorphism (for ring presentation)}}
\logpage{[ 7, 2, 4 ]}\nobreak
\hyperdef{L}{X7E011BEB868B14B4}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HAPRingReductionHomomorphism({\slshape R, Rrels[, avoid]})\index{HAPRingReductionHomomorphism@\texttt{HAPRingReductionHomomorphism}!for ring presentation}
\label{HAPRingReductionHomomorphism:for ring presentation}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HAPRingReductionHomomorphism({\slshape phi[, avoid]})\index{HAPRingReductionHomomorphism@\texttt{HAPRingReductionHomomorphism}!for image of ring homomorphism}
\label{HAPRingReductionHomomorphism:for image of ring homomorphism}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPRingHomomorphism} 



 For a polynomial ring \mbox{\texttt{\slshape R}} and ideal $I$ generated by \mbox{\texttt{\slshape Rrels}}, this function finds an isomorphic ring in fewer indeterminates (or the same
number, if this is not possible). This new ring will avoid the indeterminates
of \mbox{\texttt{\slshape R}} and any further indeterminates listed in \mbox{\texttt{\slshape avoid}}. The function returns the map between $R/I$ and the new ring. 

 In the second form, this function reduces the target ring of the ring
homomorphism \mbox{\texttt{\slshape phi}} and returns the map between this and the reduced ring. This map will also
avoid the indeterminates in the source ring of \mbox{\texttt{\slshape phi}}. }

 

\subsection{\textcolor{Chapter }{HAPZeroRingHomomorphism}}
\logpage{[ 7, 2, 5 ]}\nobreak
\hyperdef{L}{X8288925E86054FE9}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HAPZeroRingHomomorphism({\slshape R, Rrels})\index{HAPZeroRingHomomorphism@\texttt{HAPZeroRingHomomorphism}}
\label{HAPZeroRingHomomorphism}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPRingHomomorphism} 



 Creates a \texttt{HAPRingHomomorphism} which maps from the ring $R$, with an ideal generated by \mbox{\texttt{\slshape Rrels}}, into the trival ring generated by zero. }

 

\subsection{\textcolor{Chapter }{InverseRingHomomorphism}}
\logpage{[ 7, 2, 6 ]}\nobreak
\hyperdef{L}{X78106D04821D02EC}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{InverseRingHomomorphism({\slshape phi})\index{InverseRingHomomorphism@\texttt{InverseRingHomomorphism}}
\label{InverseRingHomomorphism}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPRingHomomorphism} 



 Returns (as a ring homomorphism) the inverse of the ring homomorphism \mbox{\texttt{\slshape phi}}. 

 If the inverse homomorphism requires an elimination Gr{\"o}bner basis to
perform the mapping (for example when computing the inverse of a \texttt{HAPRingHomomorphism} constructed with \texttt{HAPRingToSubringHomomorphism} (\ref{HAPRingToSubringHomomorphism})) then the ordering can be specified using the options stack. See \ref{RingHomEliminationOrdering} for more details. }

 

\subsection{\textcolor{Chapter }{CompositionRingHomomorphism}}
\logpage{[ 7, 2, 7 ]}\nobreak
\hyperdef{L}{X7ABEFEFC8285FD48}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{CompositionRingHomomorphism({\slshape phiA, phiB})\index{CompositionRingHomomorphism@\texttt{CompositionRingHomomorphism}}
\label{CompositionRingHomomorphism}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPRingHomomorphism} 



 Returns the ring homomorphism that is the composition of the ring
homomorphisms \mbox{\texttt{\slshape phiA}} and \mbox{\texttt{\slshape phiB}}. The source ring of \mbox{\texttt{\slshape phiB}} must be in the image ring of \mbox{\texttt{\slshape phiA}}. }

 }

 
\section{\textcolor{Chapter }{Data access functions}}\logpage{[ 7, 3, 0 ]}
\hyperdef{L}{X7DE3278D7E5DEE03}{}
{
  

\subsection{\textcolor{Chapter }{SourceGenerators}}
\logpage{[ 7, 3, 1 ]}\nobreak
\hyperdef{L}{X7E44FAD67C045016}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SourceGenerators({\slshape phi})\index{SourceGenerators@\texttt{SourceGenerators}}
\label{SourceGenerators}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 A list of generators for the source ring $R/I$ of the ring homomorphism. \mbox{\texttt{\slshape phi}}. }

 

\subsection{\textcolor{Chapter }{SourceRelations}}
\logpage{[ 7, 3, 2 ]}\nobreak
\hyperdef{L}{X79FA0ADF7EA5B043}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SourceRelations({\slshape phi})\index{SourceRelations@\texttt{SourceRelations}}
\label{SourceRelations}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 A list of the relations that generate the ideal $I$ of in the source ring of the ring homomorphism \mbox{\texttt{\slshape phi}}. }

 

\subsection{\textcolor{Chapter }{SourcePolynomialRing}}
\logpage{[ 7, 3, 3 ]}\nobreak
\hyperdef{L}{X7DDE043C789AEC3A}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SourcePolynomialRing({\slshape phi})\index{SourcePolynomialRing@\texttt{SourcePolynomialRing}}
\label{SourcePolynomialRing}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 \texttt{PolynomialRing} 



 Returns the polynomial ring which contains the source ring of the ring
homomorphism \mbox{\texttt{\slshape phi}}. Polynomials to be mapped by \mbox{\texttt{\slshape phi}} must be in this ring. }

 

\subsection{\textcolor{Chapter }{ImageGenerators}}
\logpage{[ 7, 3, 4 ]}\nobreak
\hyperdef{L}{X838F30B3805177C1}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageGenerators({\slshape phi})\index{ImageGenerators@\texttt{ImageGenerators}}
\label{ImageGenerators}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 A list of generators for the image ring $S/J$ of the ring homomorphism \mbox{\texttt{\slshape phi}}. }

 

\subsection{\textcolor{Chapter }{ImageRelations}}
\logpage{[ 7, 3, 5 ]}\nobreak
\hyperdef{L}{X7F50B38D87439BEE}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageRelations({\slshape phi})\index{ImageRelations@\texttt{ImageRelations}}
\label{ImageRelations}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 A list of the relations that generate the ideal $J$ of in the image ring of the ring homomorphism \mbox{\texttt{\slshape phi}}. }

 

\subsection{\textcolor{Chapter }{ImagePolynomialRing}}
\logpage{[ 7, 3, 6 ]}\nobreak
\hyperdef{L}{X863B0F2978792F7F}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImagePolynomialRing({\slshape phi})\index{ImagePolynomialRing@\texttt{ImagePolynomialRing}}
\label{ImagePolynomialRing}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 \texttt{PolynomialRing} 



 Returns the polynomial ring which contains the image of the ring homomorphism \mbox{\texttt{\slshape phi{\textgreater}}}. All polynomials mapped by \mbox{\texttt{\slshape phi}} will be in this ring. }

 }

 
\section{\textcolor{Chapter }{General functions}}\logpage{[ 7, 4, 0 ]}
\hyperdef{L}{X7B65E0C37AAB6066}{}
{
  
\subsection{\textcolor{Chapter }{ImageOfRingHomomorphism}}\logpage{[ 7, 4, 1 ]}
\hyperdef{L}{X8680F51E82EA1939}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageOfRingHomomorphism({\slshape phi, poly})\index{ImageOfRingHomomorphism@\texttt{ImageOfRingHomomorphism}!for one polynomial}
\label{ImageOfRingHomomorphism:for one polynomial}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageOfRingHomomorphism({\slshape phi, coll})\index{ImageOfRingHomomorphism@\texttt{ImageOfRingHomomorphism}!for collection of polynomials}
\label{ImageOfRingHomomorphism:for collection of polynomials}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Polynomial or list 



 Returns the image of the polynomial \mbox{\texttt{\slshape poly}} under the ring homomorphism \mbox{\texttt{\slshape phi}}. The input must be an element(s) of the source ring of \mbox{\texttt{\slshape phi}} (see \texttt{SourcePolynomialRing} (\ref{SourcePolynomialRing})). }

 
\subsection{\textcolor{Chapter }{PreimageOfRingHomomorphism}}\logpage{[ 7, 4, 2 ]}
\hyperdef{L}{X7B1B2C0980375531}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PreimageOfRingHomomorphism({\slshape phi, poly})\index{PreimageOfRingHomomorphism@\texttt{PreimageOfRingHomomorphism}!for one polynomial}
\label{PreimageOfRingHomomorphism:for one polynomial}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PreimageOfRingHomomorphism({\slshape phi, coll})\index{PreimageOfRingHomomorphism@\texttt{PreimageOfRingHomomorphism}!for collection of polynomials}
\label{PreimageOfRingHomomorphism:for collection of polynomials}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Polynomial or list 



 Returns the preimage of the polynomial \mbox{\texttt{\slshape poly}} under the ring homomorphism \mbox{\texttt{\slshape phi}}. The input must be an element(s) of the image ring of \mbox{\texttt{\slshape phi}} (see \texttt{ImagePolynomialRing} (\ref{ImagePolynomialRing})). This function is a synonym for \texttt{ImageOfRingHomomorphism(InverseRingHomomorphism(phi), poly)}. }

 }

 
\section{\textcolor{Chapter }{Example: Constructing and using a \texttt{HAPRingHomomorphism}}}\label{RingHomomorphismExample}
\logpage{[ 7, 5, 0 ]}
\hyperdef{L}{X7A00ADEE8679D3AD}{}
{
  As an initial example, we shall construct a ring homomorphism $\phi: k[x_1, x_2] \to k[x_3, x_4]$ (i.e. ideal) with the mapping $x_1 \mapsto x_3$ and $x_2 \mapsto x_3 + x_4$. In all these examples, we shall take $k$ to be the field of two elements, GF(2). We demonstrate that this is an
isomorphism by mapping a polynomial from the source ring to the target and
back again.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := PolynomialRing(GF(2), 2);;
  gap> S := PolynomialRing(GF(2), 2, IndeterminatesOfPolynomialRing(R));;
  gap> phi := HAPRingToSubringHomomorphism(R, [], [S.1, S.1+S.2]);
  <Ring homomorphism>
  gap> p := ImageOfRingHomomorphism(phi, R.1^3+R.1*R.2+R.2);
  x_3^3+x_3^2+x_3*x_4+x_3+x_4
  gap> PreimageOfRingHomomorphism(phi, p);
  x_1^3+x_1*x_2+x_2
\end{Verbatim}
 

 Some ring presentations are not in minimal form: there is an isomorphic ring
in fewer indeterminates. The \texttt{HAPRingReductionHomomorphism} (\ref{HAPRingReductionHomomorphism:for ring presentation}) function can find and return an isomorphism that maps to this reduced ring.
For example, the ring $k[x_1, x_2, x_3]/(x_1^2 + x_2^3, x_2^2 + x_3)$ has an isomorphic presentation in only two indeterminates, as this computation
shows:  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := PolynomialRing(GF(2), 3);;
  gap> I := [R.1^2+R.2^3, R.2^2+R.3];
  [ x_2^3+x_1^2, x_2^2+x_3 ]
  gap> phi := HAPRingReductionHomomorphism(R, I);
  <Ring homomorphism>
  gap> ImagePolynomialRing(phi);
  GF(2)[x_4,x_5]
  gap> ImageRelations(phi);
  [ x_5^3+x_4^2 ]
\end{Verbatim}
 

 The source and target of \texttt{HAPRingHomomorphism}s can be quotient rings, and any relations can be specified at the source of
target. When mapping from a subring to a full ring, the source relations do
not necessarily need to be specified in the source ring, but could instead be
given in its containing ring. For example, consider the ring $R/I$ where $R = k[x_1, x_2, x_3]$ and $I = x_1^3+x_3$ and the subring generated by $(x_1, x_2, x_3^2)$. If we wish to specify the homomorphism $\phi: R/I \to S/J$ where $S = k[x_4, x_5, x_6]$ with the natural map from the generators of $R$ to those of $S$ then we only need specify the original ideal $I$, even though it is not in the subring. The intersection between $I$ and the subring is found to be $x_1^4+x_3^2$, and it is this ideal that is used in the homomorphism, as this example
shows:  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := PolynomialRing(GF(2), 3);;
  gap> I := [R.1^2+R.3];
  [ x_1^2+x_3 ]
  gap> S := PolynomialRing(GF(2), 3, IndeterminatesOfPolynomialRing(R));;
  gap> phi := HAPSubringToRingHomomorphism([R.1, R.2, R.3^2], I, S);
  <Ring homomorphism>
  gap> Display(phi);
  Ring homomorphism
    x_1 -> x_4
    x_2 -> x_5
    x_3^2 -> x_6
  with relations
    [ x_1^2+x_3 ]
  and
    [ x_4^4+x_6 ]
  gap> Display(InverseRingHomomorphism(phi));
  Ring homomorphism
    x_4 -> x_1
    x_5 -> x_2
    x_6 -> x_3^2
  with relations
    [ x_4^4+x_6 ]
  and
    [ x_1^4+x_3^2 ]
\end{Verbatim}
 

 Ring homomorphisms can also be composed with each other. For example, we can
take the \texttt{HAPSubringToRingHomomorphism} (\ref{HAPSubringToRingHomomorphism:for relations defined at image}) above and change the target indeterminates by composing this with a \texttt{HAPRingHomomorphismByIndeterminateMap} (\ref{HAPRingHomomorphismByIndeterminateMap}):  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := PolynomialRing(GF(2), 3);;
  gap> I := [R.1^2+R.3];
  [ x_1^2+x_3 ]
  gap> S := PolynomialRing(GF(2), 3, IndeterminatesOfPolynomialRing(R));;
  gap> phi := HAPSubringToRingHomomorphism([R.1, R.2, R.3^2], I, S);
  <Ring homomorphism>
  gap> #
  gap> T := PolynomialRing(GF(2), 3, [R.1, R.2, R.3, S.1, S.2, S.3]);;
  gap> phi2 := HAPRingHomomorphismByIndeterminateMap(
  >   ImagePolynomialRing(phi), ImageRelations(phi), T);
  <Ring homomorphism>
  gap> Display(CompositionRingHomomorphism(phi, phi2));
  Ring homomorphism
    x_1 -> x_7
    x_2 -> x_8
    x_3^2 -> x_9
  with relations
    [ x_1^2+x_3 ]
  and
    [ x_7^4+x_9 ]
\end{Verbatim}
 }

 }

   
\chapter{\textcolor{Chapter }{Derivations}}\label{Derivation}
\logpage{[ 8, 0, 0 ]}
\hyperdef{L}{X80C0FB5A7B72B145}{}
{
  A derivation $d$ of a ring $R$ is a map $R \to R$ that obeys the product rule 
\[ d(rs) = d(r)s + rd(s) \]
 for elements $r$, $s$ in the field, and which is also distributive over addition in the ring 
\[ d(r+s) = d(r) + d(s) \]
 
\section{\textcolor{Chapter }{The \texttt{HAPDerivation} datatype}}\logpage{[ 8, 1, 0 ]}
\hyperdef{L}{X86F29D447B67B28F}{}
{
  The \texttt{HAPDerivation} datatype represents a derivation of a polynomial ring $R$. Given the product and addition rules above, a derivation can be completely
specified in terms of the images of the ring indeterminates. Consequently, a \texttt{HAPDerivation} is specified by providing: 
\begin{itemize}
\item a polynomial ring $R$
\item a list of images, under the derivation, of each of the ring's indeterminates.
\end{itemize}
 Optionally, you can also provide 
\begin{itemize}
\item a set of relations $I$ (which is assumed to be empty if none is provided).
\end{itemize}
 The support for derivations over quotient rings using \texttt{HAPDerivation} is limited. The ring is always assumed to simply be the polynomial ring $R$, but when calculating the kernel and homology (see \texttt{KernelOfDerivation} (\ref{KernelOfDerivation}) and \texttt{HomologyOfDerivation} (\ref{HomologyOfDerivation})), any relations in $I$ are also included in the result's relations, which is the equivalent of
calculating the kernel of homology of the derivation $R/I \to R/I$. }

 
\section{\textcolor{Chapter }{Computing the kernel and homology of a derivation}}\logpage{[ 8, 2, 0 ]}
\hyperdef{L}{X85F99EEF86DD595D}{}
{
  Computing the kernel of a derivation is difficult in the general case, but for
polynomial rings over $\mathbb{F}_p$ we have a novel solution which allows derivations to be considered as module
homomorphisms. 

 Consider a ring $R$ over $GF(2)$. For any $r \in R$, 
\[ d(r^2) = d(rr) = d(r)r + rd(r) = 2d(r) = 0 \]
 In general, for a ring $R = \mathbb{F}_p[x_1, \ldots, x_n]$, the subring $S = \mathbb{F}_p[x_1^p, \ldots, x_n^p]$ is in the kernel of $d$. For this choice of $S$, $R$ can always be written as a free $S$-module with $2^n$ generators. 

 Consider now taking the derivation of $sr$ where $s \in S$ and $r \in R$, 
\[ d(sr) = sd(r) + d(s)r = sd(r) \]
 since $s$ is in the kernel of $d$. In other words, when $R$ is written as an $S$-module, the derivation $d$ behaves exactly as as an $S$-module homomorphism. 

 The \textsf{Singular} computer algebra system can compute the kernels of module homomorphisms over
polynomial rings, and the \textsf{singular} package provides an interface between \textsf{Singular} and \textsf{GAP}. The function \texttt{KernelOfDerivation} (\ref{KernelOfDerivation}) constructs $S$, expresses $d$ as an $S$-module homomorphism (as well as converting any ideal), and asks \textsf{Singular} for the kernel. \textsf{Singular} returns the result as a set of module generators, which are then reduced to a
set of ring generators and a presentation found. This makes further use of \textsf{Singular}, and the \texttt{HAPRingHomomorphism} datatype (see Chapter \ref{RingHomomorphism}). 

 The homology of a derivation is defined to be 
\[ Hom(d) = \ker (d) / im (d) \]
 Given the kernel of a derivation and the image (expressed as the images of the
module generators), the homology can be readily computed, as is done by \texttt{HomologyOfDerivation} (\ref{HomologyOfDerivation}). The natural presentation obtained by concatenating the kernel relations and
the image typically contains redundancies and the \texttt{HAPRingReductionHomomorphism} (\ref{HAPRingReductionHomomorphism:for image of ring homomorphism}) is used to generate a nicer presentation involving fewer indeterminates and
relations. }

 
\section{\textcolor{Chapter }{Construction function}}\logpage{[ 8, 3, 0 ]}
\hyperdef{L}{X8589CD117D1ECD29}{}
{
  
\subsection{\textcolor{Chapter }{HAPDerivation construction functions}}\label{HAPDerivationConstructors}
\logpage{[ 8, 3, 1 ]}
\hyperdef{L}{X7B8058948424E639}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HAPDerivation({\slshape R[, I], images})\index{HAPDerivation@\texttt{HAPDerivation}}
\label{HAPDerivation}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HAPDerivationNC({\slshape R, I, images})\index{HAPDerivationNC@\texttt{HAPDerivationNC}}
\label{HAPDerivationNC}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 \texttt{HAPDerivation} 



 Construct a \texttt{HAPDerivation} object representing the derivation $d$ where \mbox{\texttt{\slshape R}} is a polynomial ring and \mbox{\texttt{\slshape images}} is the list of the images of the ring indeterminates under the derivation, $\{d(x_1), d(x_2), \ldots, d(x_n)\}$. An optional set of relations \mbox{\texttt{\slshape I}} can also be provided, which are passed to \texttt{KernelOfDerivation} (\ref{KernelOfDerivation}) when calculating the kernel or homology of this derivation. The function \texttt{HAPDerivation} checks that the arguments are compatible, while the \texttt{NC} method performs no checks. }

 }

 
\section{\textcolor{Chapter }{Data access function}}\logpage{[ 8, 4, 0 ]}
\hyperdef{L}{X789E616983759E10}{}
{
  

\subsection{\textcolor{Chapter }{DerivationRing}}
\logpage{[ 8, 4, 1 ]}\nobreak
\hyperdef{L}{X803EA43A7F21FB99}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DerivationRing({\slshape d})\index{DerivationRing@\texttt{DerivationRing}}
\label{DerivationRing}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 Polynomial ring 



 Returns the ring over which the derivation \mbox{\texttt{\slshape d}} is defined. }

 

\subsection{\textcolor{Chapter }{DerivationImages}}
\logpage{[ 8, 4, 2 ]}\nobreak
\hyperdef{L}{X7AE49BC082B7219D}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DerivationImages({\slshape d})\index{DerivationImages@\texttt{DerivationImages}}
\label{DerivationImages}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List of polynomials 



 A derivation \mbox{\texttt{\slshape d}} over a (quotient) polynomial ring is defined by a set of images. This function
returns this list of images. The $i$th element of the list is the image of indeterminate number $i$ in that ring family. (Note that indeterminate number $i$ is not necessarily the $i$th indeterminate in that particular ring. See  (\textbf{Reference: Indeterminates}) for more details.) }

 

\subsection{\textcolor{Chapter }{DerivationRelations}}
\logpage{[ 8, 4, 3 ]}\nobreak
\hyperdef{L}{X811828517C62421B}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{DerivationRelations({\slshape d})\index{DerivationRelations@\texttt{DerivationRelations}}
\label{DerivationRelations}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List of polynomials 



 Returns the relations of the quotient ring over which the derivation \mbox{\texttt{\slshape d}} is defined. }

 
\subsection{\textcolor{Chapter }{Example: Constructing and accessing data of a \texttt{HAPDerivation}}}\label{DerivationExample1}
\logpage{[ 8, 4, 4 ]}
\hyperdef{L}{X84A549558235F536}{}
{
  We demonstrate creating a \texttt{HAPDerivation} object and reading back its data by creating a derivation $d$ of the polynomial ring over the integers with two indeterminates, $\mathbb{Z}[x_1, x_2, x_3]$, which has the mapping $d(x_1) = d(x_2) = 1$, $d(x_3) = 0$.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> ring := PolynomialRing(Integers, 3);;
  gap> d := HAPDerivation(ring, [One(ring), One(ring), Zero(ring)]);
  <Derivation>
  gap> 
  gap> DerivationRing(d);
  Integers[x_1,x_2,x_3]
  gap> DerivationImages(d);
  [ 1, 1, 0 ]
  gap> DerivationRelations(d);
  [  ]
\end{Verbatim}
 }

 }

 
\section{\textcolor{Chapter }{Image, kernel and homology functions}}\logpage{[ 8, 5, 0 ]}
\hyperdef{L}{X7956001A816B2507}{}
{
  

\subsection{\textcolor{Chapter }{ImageOfDerivation}}
\logpage{[ 8, 5, 1 ]}\nobreak
\hyperdef{L}{X7B523CEF85223194}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ImageOfDerivation({\slshape d, poly})\index{ImageOfDerivation@\texttt{ImageOfDerivation}}
\label{ImageOfDerivation}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Polynomial 



 Returns the image of the polynomial \mbox{\texttt{\slshape poly}} under the derivation \mbox{\texttt{\slshape d}}. (\mbox{\texttt{\slshape poly}} must be a polynomial in the derivation's ring.) }

 

\subsection{\textcolor{Chapter }{KernelOfDerivation}}
\logpage{[ 8, 5, 2 ]}\nobreak
\hyperdef{L}{X842250387FC8302C}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{KernelOfDerivation({\slshape d[, avoid]})\index{KernelOfDerivation@\texttt{KernelOfDerivation}}
\label{KernelOfDerivation}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns a ring presentation $S/J$ for the kernel of the derivation \mbox{\texttt{\slshape d}}, where $S$ is a polynomial ring and $J$ are a set of relations. This operation returns a list with the following
elements: 
\begin{enumerate}
\item the new polynomial ring $S$
\item a basis for the ideal, as a set of relations $J$
\item the ring isomorphism between the kernel (i.e. a subring of the derivation's
ring) and the new ring. This is given using the \texttt{HAPRingHomomorphism} type, for details of which see \ref{RingHomomorphism}
\end{enumerate}
 An optional parameter, \mbox{\texttt{\slshape avoid}}, can be provided which lists indeterminates to avoid when creating the the
new polynomial ring. 

 \emph{This function is only available if the package \textsf{singular} is available}. }

 

\subsection{\textcolor{Chapter }{HomologyOfDerivation}}
\logpage{[ 8, 5, 3 ]}\nobreak
\hyperdef{L}{X803D9B5E7A26F749}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HomologyOfDerivation({\slshape d[, avoid]})\index{HomologyOfDerivation@\texttt{HomologyOfDerivation}}
\label{HomologyOfDerivation}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns a ring presentation $S/J$ for the homology of the derivation \mbox{\texttt{\slshape d}}, where $S$ is a polynomial ring and $J$ are a set of relations. Returns a polynomial ring presentation for the
homology $ker(d)/im(d)$ of the derivation \mbox{\texttt{\slshape d}}. This operation returns a list with the following elements: 
\begin{enumerate}
\item the new polynomial ring $S$
\item a basis for the ideal, as a set of relations $J$
\item the ring isomorphism between the kernel (i.e. a subring of the derivation's
ring) and the new ring. This is given using the \texttt{HAPRingHomomorphism} type, for details of which see \ref{RingHomomorphism}
\end{enumerate}
 

 An optional parameter, \mbox{\texttt{\slshape avoid}}, can be provided which lists indeterminates to avoid when creating the the
new polynomial ring. }

 
\subsection{\textcolor{Chapter }{Example: Homology of a \texttt{HAPDerivation}}}\label{DerivationExample3}
\logpage{[ 8, 5, 4 ]}
\hyperdef{L}{X78B45E8C86F90981}{}
{
  In this example, we wish to calculate the homology of a derivation $d$ on the ring $\mathbb{F}_2[x,y,z]/(yx^2 + xy^2)$ where $d(x) = d(y) = 0$ and $d(z) = yx^2 + xy^2$. To demonstrate some of the other functions, we also calculate the kernel of
this derivation and the image of the element $xz$.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> ring := PolynomialRing(GF(2), 3);;
  gap> x := ring.1;; y := ring.2;; z := ring.3;;
  gap> d := HAPDerivation(ring, [x^2 + x*y + y^2],
  >                [Zero(ring), Zero(ring), x^2*y + x*y^2]);
  <Derivation>
  gap> #
  gap> ImageOfDerivation(d, x*z);
  x_1^3*x_2+x_1^2*x_2^2
  gap> KernelOfDerivation(d);
  [ GF(2)[x_7,x_8,x_9], [ x_7^2+x_7*x_8+x_8^2 ], <Ring homomorphism> ]
  gap> HomologyOfDerivation(d);
  [ GF(2)[x_4,x_5,x_6], [ x_4^2+x_4*x_5+x_5^2, x_5^3 ], <Ring homomorphism> ]
\end{Verbatim}
 }

 

 The result we were after, the homology of $d$, can be read from the final result as follows. The first two entries in the
list give the homology group as a quotient ring: the quotient of the
polynomial ring $\mathbb{F}_2[x_6,x_7,x_8]$ with the two relations $(x_7^2+x_7x_8+x_8^2, x_8^3)$. The last entry in the list gives the new indeterminates in terms of the
original indeterminates, and from this we know that it would be friendlier to
write the result as  
\[ \frac{\mathbb{F}_2[x,y,e^2]}{(x^2+xy+y^2, y^3)} \]
   The kernel of the derivation can read from the result in a similar manner. }

 }

   
\chapter{\textcolor{Chapter }{Poincar{\a'e} series}}\label{Poincare}
\logpage{[ 9, 0, 0 ]}
\hyperdef{L}{X7FF2605B79D7B5F8}{}
{
  The Poincar{\a'e} series for the mod-$p$ cohomology ring $H^*(G, \mathbb{F})$ is the infinite series 
\[ a_0 + a_1x + a_2x^2 + a_3x^3 + ... \]
 where $a_k$ is the dimension of the vector space $H^k(G, \mathbb{F})$. The Poincar{\a'e} function is a rational function $P(x)/Q(x)$ which is equal to the Poincar{\a'e} series. 
\section{\textcolor{Chapter }{Computing the Poincar{\a'e} series using spectral sequences}}\logpage{[ 9, 1, 0 ]}
\hyperdef{L}{X872F597F7AACA402}{}
{
  \textsf{HAPprime} can calculate a provably-correct Poincar{\a'e} series for the mod-$p$ cohomology ring of a small $p$-group using spectral sequences, without having to compute the actual
cohomology ring. The limiting sheet of a Lyndon-Hochschild-Serre spectral
sequence for a group $G$ will be a ring with the same additive structure as the cohomology ring for $G$, and thus the same Poincar{\a'e} series. This is implemented in the \textsf{HAPprime} function \texttt{PoincareSeriesLHS} (\textbf{HAPprime: PoincareSeriesLHS}). See the documentation for that function in the user guide for more details. }

 
\section{\textcolor{Chapter }{Computing the Poincar{\a'e} series using a minimal resolution}}\logpage{[ 9, 2, 0 ]}
\hyperdef{L}{X7978D58181D2725F}{}
{
  Given a resolution $R$ of length $n$ for a group $G$, the \textsf{HAP} function \texttt{PoincareSeries} (\textbf{HAP: PoincareSeries}) calculates a quotient of polynomials such that the coefficient of $x^k$ equals the dimension of $H^k(G, \mathbb{F})$ for $k = 1$ to $k = n$. Given a sufficiently long resolution $R$, this quotient should equal the true Poincar{\a'e} series. The function can
also automatically find a suitable value for $n$ by trying resolutions of increasing length until a consistent estimate is
found for the Poincar{\a'e} series. This is likely to be correct, but we have
no proof that this will always be the case. 

 The function \texttt{ExtendResolutionPrimePowerGroupAutoMem} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupAutoMem}) allows \textsf{HAPprime} to provide a simplified implementation for calculating Poincar{\a'e} series in
the case where $n$ is not specified (since extending existing resolutions is difficult in \textsf{HAP}). The \textsf{HAPprime} function \texttt{PoincareSeriesAutoMem} (\textbf{HAPprime Datatypes: PoincareSeriesAutoMem}) is a replacement for \textsf{HAP}'s \texttt{PoincareSeries} (\textbf{HAP: PoincareSeries}) in the case where $G$ is a $p$-group and the optimal $n$ is not known. 

 By using the \textsf{HAPprime} resolution-calculation functions, \texttt{PoincareSeriesAutoMem} (\textbf{HAPprime Datatypes: PoincareSeriesAutoMem}) saves memory when storing resolution, and switches to the \texttt{GF} algorithm when memory is low. As a result, it can calculate the Poincar{\a'e}
series for groups that would be impossible using \textsf{HAP} without having about five times the memory available to the machine.  

\subsection{\textcolor{Chapter }{PoincareSeriesAutoMem}}
\logpage{[ 9, 2, 1 ]}\nobreak
\hyperdef{L}{X7F0911257D80691E}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PoincareSeriesAutoMem({\slshape G[, n]})\index{PoincareSeriesAutoMem@\texttt{PoincareSeriesAutoMem}}
\label{PoincareSeriesAutoMem}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Rational function 



 For a finite p-group \mbox{\texttt{\slshape G}}, this function calculates and returns a quotient of polynomials $f(x) = P(x)/Q(x)$ (i.e. the Poincar{\a'e} series) whose coefficient of $x^k$ equals the rank of the vector space $H_k(G, \mathbb{F}_p)$ for all $k$ in the range $k=1$ to $k=n$. If no value is given for \mbox{\texttt{\slshape n}} then increasing values of $n$ are tried to find the minimum value which gives a consistent Poincar{\a'e}
series, defined as a the minimum value $n > 10$ such that \texttt{PoincareSeries(G, n) = PoincareSeries(G, n-1) = PoincareSeries(G, n-2)}. 

 This function uses the \textsf{HAP} function \texttt{PoincareSeries} (\textbf{HAP: PoincareSeries}) to calculate the Poincar{\a'e} series, but the \textsf{HAPprime} function \texttt{ExtendResolutionPrimePowerGroupAutoMem} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupAutoMem}) to calculate and gradually extend the resolution, so should be both faster and
more memory-efficient than using \texttt{PoincareSeries} by itself. See Section \ref{PoincareExample} for an example. 

 The Poincar{\a'e} series calculated using this function is likely to be
correct, but we have no proof that this will be the case. If a correct
Poincar{\a'e} series is required, use \texttt{PoincareSeriesLHS} (\textbf{HAPprime: PoincareSeriesLHS}) }

 }

 
\section{\textcolor{Chapter }{Example Poincar{\a'e} series computations}}\label{PoincareExample}
\logpage{[ 9, 3, 0 ]}
\hyperdef{L}{X82A90FCC80BAC1F9}{}
{
  This example compares the time taken by \texttt{PoincareSeries} (\textbf{HAP: PoincareSeries}) and \texttt{PoincareSeriesAutoMem} (\textbf{HAPprime Datatypes: PoincareSeriesAutoMem}), and shows that the times are roughly comparable:  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> G := SmallGroup(64, 210);;
  gap> # Compute the Poincare series using HAP
  gap> P1 := PoincareSeries(G);time;
  (x_1^4+x_1^2+x_1+1)/(-x_1^7+3*x_1^6-5*x_1^5+7*x_1^4-7*x_1^3+5*x_1^2-3*x_1+1)
  51355
  gap> # Compute the Poincare series using HAPprime
  gap> P2 := PoincareSeriesAutoMem(G);time;
  (x_1^4+x_1^2+x_1+1)/(-x_1^7+3*x_1^6-5*x_1^5+7*x_1^4-7*x_1^3+5*x_1^2-3*x_1+1)
  39774
  gap> P1 = P2;
  true
\end{Verbatim}
 The \textsf{HAPprime} function \texttt{PoincareSeriesLHS} (\textbf{HAPprime: PoincareSeriesLHS}) uses an alternative approach to compute Poincar{\a'e} series which are
guaranteed to be correct. In many cases it is also faster, as we see if we
compute the Poincar{\a'e} series for the same group using this function:  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> G := SmallGroup(64, 210);;
  gap> P3 := PoincareSeriesLHS(G);time;
  (x_1^4+x_1^2+x_1+1)/(-x_1^7+3*x_1^6-5*x_1^5+7*x_1^4-7*x_1^3+5*x_1^2-3*x_1+1)
  3564
\end{Verbatim}
 }

 
\section{\textcolor{Chapter }{The Poincar{\a'e} series of groups of order 64 and 128}}\logpage{[ 9, 4, 0 ]}
\hyperdef{L}{X84E1A5148674E7E0}{}
{
  Using \textsf{HAPprime}, on a dual-processor AMD Opteron 250 machine, we have calculated the
Poincar{\a'e} series for all of the groups of order 64 using the
resolution-based technique. Most computed within a few seconds using only a
few Mb of memory. With a maximum of 1Gb of memory available to \textsf{GAP}, four groups (numbers 4, 60, 242 and 266 from the \textsf{GAP} \texttt{SmallGroup} library) needed to switch to using \texttt{ExtendResolutionPrimePowerGroupGF} (\textbf{HAPprime: ExtendResolutionPrimePowerGroupGF}). Calculating the Poincar{\a'e} series of the most difficult group, \texttt{SmallGroup(64, 60)}, took 24 days, computing a resolution whose last term was $M_{16} = (\mathbb{F}G)^{2445}$. The complete list of the Poincar{\a'e} series for all groups of order 64 is
available on the \textsf{HAPprime} website \href{http://www.maths.nuigalway.ie/~pas/CHA/HAPprime/HAPprimeindex.html} {\texttt{http://www.maths.nuigalway.ie/\texttt{\symbol{126}}pas/CHA/HAPprime/HAPprimeindex.html}} 

 There is an on-going programme of calculating the Poincar{\a'e} series for the
groups of order 128. To date, using the same constraints as for the groups of
order 64 above, we have computed the Poincar{\a'e} series for about half of
them. For latest details, again please see the \textsf{HAPprime} website. }

 }

   
\chapter{\textcolor{Chapter }{General Functions}}\label{GeneralFunctions}
\logpage{[ 10, 0, 0 ]}
\hyperdef{L}{X7B65E0C37AAB6066}{}
{
  Some of the functions provided by \textsf{HAPprime} are not specifically aimed at homological algebra or extending the \textsf{HAP} package. The functions in this chapter, which are used internally by \textsf{HAPprime} extend some of the standard \textsf{GAP} functions and datatypes. 
\section{\textcolor{Chapter }{Matrices}}\logpage{[ 10, 1, 0 ]}
\hyperdef{L}{X812CCAB278643A59}{}
{
  For details of the standard \textsf{GAP} vector and matrix functions, see  (\textbf{Tutorial: matrices}) and  (\textbf{Reference: Matrices}) in the \textsf{GAP} tutorial and reference manuals. \textsf{HAPprime} provides improved versions of a couple of standard matrix operations, and two
small helper functions. 

\subsection{\textcolor{Chapter }{SumIntersectionMatDestructive}}
\logpage{[ 10, 1, 1 ]}\nobreak
\hyperdef{L}{X845EA1B28618D9A7}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SumIntersectionMatDestructive({\slshape U, V})\index{SumIntersectionMatDestructive@\texttt{SumIntersectionMatDestructive}}
\label{SumIntersectionMatDestructive}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SumIntersectionMatDestructiveSE({\slshape Ubasis, Uheads, Vbasis, Vheads})\index{SumIntersectionMatDestructiveSE@\texttt{SumIntersectionMatDestructiveSE}}
\label{SumIntersectionMatDestructiveSE}
}\hfill{\scriptsize (operation)}}\\


 Returns a list of length 2 with, at the first position, the sum of the vector
spaces generated by the rows of \mbox{\texttt{\slshape U}} and \mbox{\texttt{\slshape V}}, and, at the second position, the intersection of the spaces. 

 Like the \textsf{GAP} core function \texttt{SumIntersectionMat} (\textbf{Reference: SumIntersectionMat}), this performs Zassenhaus' algorithm to compute bases for the sum and the
intersection. However, this version operates directly on the input matrices
(thus corrupting them), and is rewritten to require only approximately 1.5
times the space of the original input matrices. By contrast, the original \textsf{GAP} version uses three times the memory of the original matrices to perform the
calculation, and since it doesn't modify the input matrices will require a
total of four times the space of the original matrices. 

 The function \texttt{SumIntersectionMatDestructiveSE} takes as arguments not a pair of generating matrices, but a pair of
semi-echelon basis matrices and the corresponding head locations, such as is
returned by a call to \texttt{SemiEchelonMatDestructive} (\textbf{Reference: SemiEchelonMatDestructive}) (these arguments must all be mutable, so \texttt{SemiEchelonMat} (\textbf{Reference: SemiEchelonMat}) cannot be used). This function is used internally by \texttt{SumIntersectionMatDestructive}, and is provided for the occasions when the user might already have the
semi-echelon versions available, in which case a small amount of time will be
saved. }

 

\subsection{\textcolor{Chapter }{SolutionMat (for multiple vectors)}}
\logpage{[ 10, 1, 2 ]}\nobreak
\hyperdef{L}{X8359E68C7F38BA5F}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SolutionMat({\slshape M, V})\index{SolutionMat@\texttt{SolutionMat}!for multiple vectors}
\label{SolutionMat:for multiple vectors}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SolutionMatDestructive({\slshape M, V})\index{SolutionMatDestructive@\texttt{SolutionMatDestructive}!for multiple vectors}
\label{SolutionMatDestructive:for multiple vectors}
}\hfill{\scriptsize (operation)}}\\


 Calculates, for each row vector $v_i$ in the matrix \mbox{\texttt{\slshape V}}, a solution to $x_i \times M = v_i$, and returns these solutions in a matrix $X$, whose rows are the vectors $x_i$. If there is not a solution for a $v_i$, then \texttt{fail} is returned for that row. 

 These functions are identical to the kernel functions \texttt{SolutionMat} (\textbf{Reference: SolutionMat}) and \texttt{SolutionMatDestructive} (\textbf{Reference: SolutionMatDestructive}), but are provided for cases where multiple solutions using the same matrix \mbox{\texttt{\slshape M}} are required. In these cases, using this function is far faster, since the
matrix is only decomposed once. 

 The \texttt{Destructive} version corrupts both the input matrices, while the non-\texttt{Destructive} version operates on copies of these. }

 

\subsection{\textcolor{Chapter }{IsSameSubspace}}
\logpage{[ 10, 1, 3 ]}\nobreak
\hyperdef{L}{X872D9F5D7ED6F4AA}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IsSameSubspace({\slshape U, V})\index{IsSameSubspace@\texttt{IsSameSubspace}}
\label{IsSameSubspace}
}\hfill{\scriptsize (operation)}}\\


 Returns \texttt{true} if the subspaces spanned by the rows of \mbox{\texttt{\slshape U}} and \mbox{\texttt{\slshape V}} are the same, \texttt{false} otherwise. 

 This function treats the rows of the two matrices as vectors from the same
vector space (with the same basis), and tests whether the subspace spanned by
the two sets of vectors is the same. }

 

\subsection{\textcolor{Chapter }{PrintDimensionsMat}}
\logpage{[ 10, 1, 4 ]}\nobreak
\hyperdef{L}{X789478557955E1C3}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{PrintDimensionsMat({\slshape M})\index{PrintDimensionsMat@\texttt{PrintDimensionsMat}}
\label{PrintDimensionsMat}
}\hfill{\scriptsize (operation)}}\\


 Returns a string containing the dimensions of the matrix \mbox{\texttt{\slshape M}} in the form \texttt{"mxn"}, where \texttt{m} is the number of rows and \texttt{n} the number of columns. If the matrix is empty, the returned string is \texttt{"empty"}. }

 
\subsection{\textcolor{Chapter }{Example: matrices and vector spaces}}\logpage{[ 10, 1, 5 ]}
\hyperdef{L}{X8080767383F9EF31}{}
{
  \textsf{GAP} uses rows of a matrix to represent basis vectors for a vector space. In this
example we have two matrics $U$ and $V$ that we suspect represent the same subspace. Using \texttt{SolutionMat} (\ref{SolutionMat:for multiple vectors}) we can see that $V$ lies in $U$, but \texttt{IsSameSubspace} (\ref{IsSameSubspace}) shows that they are the same subspace, as is confirmed by having identical
sums and intersections.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> U := [[1,2,3],[4,5,6]];;
  gap> V := [[3,3,3],[5,7,9]];;
  gap> SolutionMat(U, V);
  [ [ -1, 1 ], [ 1, 1 ] ]
  gap> IsSameSubspace(U, V);
  true
  gap> SumIntersectionMatDestructive(U, V);
  [ [ [ 1, 2, 3 ], [ 0, 1, 2 ] ], [ [ 0, 1, 2 ], [ 1, 0, -1 ] ] ]
  gap> IsSameSubspace(last[1], last[2]);
  true
  gap> PrintDimensionsMat(V);
  "2x3"
\end{Verbatim}
 }

 }

 
\section{\textcolor{Chapter }{Polynomials}}\logpage{[ 10, 2, 0 ]}
\hyperdef{L}{X826D8334845549EC}{}
{
  \textsf{GAP} provides some functions for manipulating polynomials and polynomial ideals -
see  (\textbf{Reference: Polynomials and Rational Functions}). The \textsf{HAPprime} packages adds further functions to decompose polynomials into terms and
monomials, and some functions for tidying up polynomial ideals. 

\subsection{\textcolor{Chapter }{TermsOfPolynomial}}
\logpage{[ 10, 2, 1 ]}\nobreak
\hyperdef{L}{X7E8B84388516792D}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{TermsOfPolynomial({\slshape poly})\index{TermsOfPolynomial@\texttt{TermsOfPolynomial}}
\label{TermsOfPolynomial}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List of pairs 



 Returns a list of the terms in the polynomial. This list is a list of pairs of
the form \texttt{[mon, coeff]} where \texttt{mon} is a monomial and \texttt{coeff} is the coefficient of that monomial in the polynomial. The monomials are
sorted according to the total degree/lexicographic order (the same as the in \texttt{MonomialGrLexOrdering} (\textbf{Reference: MonomialGrlexOrdering})). }

 

\subsection{\textcolor{Chapter }{IsMonomial (for polynomial)}}
\logpage{[ 10, 2, 2 ]}\nobreak
\hyperdef{L}{X82862FA1817C7767}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IsMonomial({\slshape poly})\index{IsMonomial@\texttt{IsMonomial}!for polynomial}
\label{IsMonomial:for polynomial}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 Boolean 



 Returns \texttt{true} if \mbox{\texttt{\slshape poly}} is a monomial, i.e. the polynomial contains only one term. }

 

\subsection{\textcolor{Chapter }{UnivariateMonomialsOfMonomial}}
\logpage{[ 10, 2, 3 ]}\nobreak
\hyperdef{L}{X7A603BCA83895309}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{UnivariateMonomialsOfMonomial({\slshape mon})\index{UnivariateMonomialsOfMonomial@\texttt{UnivariateMonomialsOfMonomial}}
\label{UnivariateMonomialsOfMonomial}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns a list of the univariate monomials of the largest order whose product
equals \mbox{\texttt{\slshape mon}}. The univariate monomials are sorted according to their indeterminate number. }

 

\subsection{\textcolor{Chapter }{IndeterminateAndExponentOfUnivariateMonomial}}
\logpage{[ 10, 2, 4 ]}\nobreak
\hyperdef{L}{X7DE6473B7AE6EC7F}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IndeterminateAndExponentOfUnivariateMonomial({\slshape mon})\index{IndeterminateAndExponentOfUnivariateMonomial@\texttt{Indeterminate}\-\texttt{And}\-\texttt{Exponent}\-\texttt{Of}\-\texttt{Univariate}\-\texttt{Monomial}}
\label{IndeterminateAndExponentOfUnivariateMonomial}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns a list \texttt{[indet, exp]} where \texttt{indet} is the indeterminate of the univariate monomial \mbox{\texttt{\slshape mon}} and \texttt{exp} is the exponent of that indeterminate in the monomial. If \mbox{\texttt{\slshape mon}} is an element in the coefficient ring (i.e. the monomial contains no
indeterminates) then the first element will be \mbox{\texttt{\slshape mon}} with an exponent of zero. If \mbox{\texttt{\slshape mon}} is not a univariate monomial, then \texttt{fail} is returned. }

 

\subsection{\textcolor{Chapter }{IndeterminatesOfPolynomial}}
\logpage{[ 10, 2, 5 ]}\nobreak
\hyperdef{L}{X86FFC6697CAF53B8}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{IndeterminatesOfPolynomial({\slshape poly})\index{IndeterminatesOfPolynomial@\texttt{IndeterminatesOfPolynomial}}
\label{IndeterminatesOfPolynomial}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns a list of the indeterminates used in the polynomial \mbox{\texttt{\slshape poly}}. }

 
\subsection{\textcolor{Chapter }{ReduceIdeal}}\logpage{[ 10, 2, 6 ]}
\hyperdef{L}{X87DE84AC7B62DC5C}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ReduceIdeal({\slshape I, O})\index{ReduceIdeal@\texttt{ReduceIdeal}!for Ideal}
\label{ReduceIdeal:for Ideal}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ReduceIdeal({\slshape rels, O})\index{ReduceIdeal@\texttt{ReduceIdeal}!for list of relations}
\label{ReduceIdeal:for list of relations}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Ideal or list 



 For an ideal \mbox{\texttt{\slshape I}} returns an ideal containing a reduced generating set for the ideal, i.e. one
in which no monomial in a relation in \mbox{\texttt{\slshape I}} is divisible by the leading term of another polynomial in \mbox{\texttt{\slshape I}}. The monomial ordering to be used is specified by \mbox{\texttt{\slshape O}} (see  (\textbf{Reference: Monomial Orderings})). The ideal can instead be specified by a list of relations \mbox{\texttt{\slshape rels}}, in which case a reduced list of relations is returned. }

 

\subsection{\textcolor{Chapter }{ReducedPolynomialRingPresentation}}
\logpage{[ 10, 2, 7 ]}\nobreak
\hyperdef{L}{X84E9467E84243B77}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ReducedPolynomialRingPresentation({\slshape R, I[, avoid]})\index{ReducedPolynomialRingPresentation@\texttt{ReducedPolynomialRingPresentation}}
\label{ReducedPolynomialRingPresentation}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{ReducedPolynomialRingPresentationMap({\slshape R, I[, avoid]})\index{ReducedPolynomialRingPresentationMap@\texttt{ReducedPolynomialRingPresentationMap}}
\label{ReducedPolynomialRingPresentationMap}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 List 



 For a polynomial ring \mbox{\texttt{\slshape R}} and a list of relations \mbox{\texttt{\slshape I}} in that ring, returns a list \texttt{[S, J]} representing a polynomial quotient ring $S/J$ which is isomorphic to the ring $R/I$, but which involves the minimal number of ring indeterminates. The
indeterminates in \texttt{S} will be distinct from thise in \mbox{\texttt{\slshape R}}, and an optional argument \mbox{\texttt{\slshape avoid}} can be used to give a list of further indeterminates to avoid when creating
the ring \texttt{S}. 

 The extended version of this function, \texttt{ReducedPolynomialRingPresentationMap}, returns an additional third element to the list, which contains two lists
giving the mapping between the new ring indeterminates and the old ring
indeterminates. The first list is of polynomials in the original
indeterminates, the second the equivalent polynomials in the new ring
indeterminates. }

 
\subsection{\textcolor{Chapter }{Example: monomials, polynomials and ring presentations}}\logpage{[ 10, 2, 8 ]}
\hyperdef{L}{X7F8D0B27815DDA6B}{}
{
  A monomial is some product of ring indeterminates. A polynomial is a sum of
monomials, where each monomial may also be multiplied by an element from the
field of the polynomial. It can be useful to decompose polynomials as follows: 
\begin{itemize}
\item decompose a polynomial into its individual terms (where a term is a product of
a monomial and a field element). The function \texttt{TermsOfPolynomial} (\ref{TermsOfPolynomial}) does this.
\item decompose a monomial into its component univariate monomials, each of which is
some (power of) a single indeterminates. This operation is performed by \texttt{UnivariateMonomialsOfMonomial} (\ref{UnivariateMonomialsOfMonomial}).
\item decompose a univariate monomial into it the indeterminates and exponent (\texttt{IndeterminateAndExponentOfUnivariateMonomial} (\ref{IndeterminateAndExponentOfUnivariateMonomial})).
\end{itemize}
 In the example below, we decompose $x + xy^2 + 3y^3$ into its three terms, and then further decompose the $xy^2$ term.  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := PolynomialRing(Integers, 2);;
  gap> x := R.1;; y := R.2;;
  gap> poly := x + x*y^2 + 3*y^3;
  x_1*x_2^2+3*x_2^3+x_1
  gap> terms := TermsOfPolynomial(poly);
  [ [ x_1, 1 ], [ x_2^3, 3 ], [ x_1*x_2^2, 1 ] ]
  gap> UnivariateMonomialsOfMonomial(terms[3][1]);
  [ x_1, x_2^2 ]
  gap> IndeterminateAndExponentOfUnivariateMonomial(last[2]);
  [ x_2, 2 ]
\end{Verbatim}
 

 \textsf{HAPprime} also provides some functions to help the generation of ring presentations. In
the following example we consider the polynomial ring $\mathbb{Z}[w,x,y,z]$ an an ideal $I = \langle w^2 + x, w^3 + x^3 \rangle$. We first convert this ideal into reduced form (where no monomial in a
polynomial is divisible by the leading term of any other polynomial). Then we
calculate a reduced ring presentation for the quotient ring $R/I$, where we find that the indeterminate $x$ is can be removed and a new ring $S/J = \mathbb{Z}[w,y,z]/\langle w^6-w^3 \rangle$ is isomorphic to $R/I$  
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> R := PolynomialRing(Integers, 4);;
  gap> w := R.1;; x := R.2;;
  gap> I := [w^2 + x, w^3 + x^3];
  [ x_1^2+x_2, x_1^3+x_2^3 ]
  gap> ReduceIdeal(I, MonomialLexOrdering());
  [ x_1^2+x_2, -x_2^3+x_1*x_2 ]
  gap> 
  gap> ReducedPolynomialRingPresentation(R, I);
  [ Integers[x_5,x_6,x_7], [ x_5^6-x_5^3 ] ]
\end{Verbatim}
 }

 }

 
\section{\textcolor{Chapter }{Singular}}\logpage{[ 10, 3, 0 ]}
\hyperdef{L}{X840A7A5D7AE407F2}{}
{
  

\subsection{\textcolor{Chapter }{SingularSetNormalFormIdeal}}
\logpage{[ 10, 3, 1 ]}\nobreak
\hyperdef{L}{X783EE9057FE65731}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SingularSetNormalFormIdeal({\slshape I})\index{SingularSetNormalFormIdeal@\texttt{SingularSetNormalFormIdeal}}
\label{SingularSetNormalFormIdeal}
}\hfill{\scriptsize (operation)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SingularSetNormalFormIdealNC({\slshape I})\index{SingularSetNormalFormIdealNC@\texttt{SingularSetNormalFormIdealNC}}
\label{SingularSetNormalFormIdealNC}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 nothing 



 Sets the ideal to be used by singular for any subsequent calls to \texttt{SingularPolynomialNormalForm} (\ref{SingularPolynomialNormalForm}) to be \mbox{\texttt{\slshape I}}. After calling this function, the singular base ring and term ordering (see \texttt{SingularBaseRing} (\textbf{singular: SingularBaseRing}) and \texttt{TermOrdering} (\textbf{singular: TermOrdering})) will be set to be that of the ring containing \mbox{\texttt{\slshape I}}, so an additional call to \texttt{SingularSetBaseRing} (\textbf{singular: SingularSetBaseRing}) is not necessary. 

 The standard form of this function ensures that \mbox{\texttt{\slshape I}} is a reduced Gr{\"o}bner basis with respect to the value of \texttt{TermOrdering} (\textbf{singular: TermOrdering}) for the ring containing the ideal, while the \texttt{NC} assumes that \mbox{\texttt{\slshape I}} is already such a Gr{\"o}bner basis. }

 

\subsection{\textcolor{Chapter }{SingularPolynomialNormalForm}}
\logpage{[ 10, 3, 2 ]}\nobreak
\hyperdef{L}{X7E6A0D647D39110B}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SingularPolynomialNormalForm({\slshape poly[, I]})\index{SingularPolynomialNormalForm@\texttt{SingularPolynomialNormalForm}}
\label{SingularPolynomialNormalForm}
}\hfill{\scriptsize (operation)}}\\
\textbf{\indent Returns:\ }
 Polynomial 



 Returns the normal form of the polynomial \mbox{\texttt{\slshape poly}} after reduction by the ideal \mbox{\texttt{\slshape I}}. The ideal can either be passed to this function, in which case it is
converted to a Gr{\"o}bner basis (with respect to the term ordering of the
ideal's ring - see \texttt{TermOrdering} (\textbf{singular: TermOrdering})), or the ideal to use can be set first be calling \texttt{SingularSetNormalFormIdeal} (\ref{SingularSetNormalFormIdeal}), which is more efficient for repeated use of this function (the latter
function also sets the base ring and term ordering). }

 

\subsection{\textcolor{Chapter }{SingularGroebnerBasis}}
\logpage{[ 10, 3, 3 ]}\nobreak
\hyperdef{L}{X804568497F686594}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SingularGroebnerBasis({\slshape I})\index{SingularGroebnerBasis@\texttt{SingularGroebnerBasis}}
\label{SingularGroebnerBasis}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns a list of relations which form a Gr{\"o}bner basis for the ideal \mbox{\texttt{\slshape I}} given the \texttt{TermOrdering} (\textbf{singular: TermOrdering}) associated with the ring containing \mbox{\texttt{\slshape I}}. This function is the same as the \textsf{singular} function \texttt{GroebnerBasis} (\textbf{singular: GroebnerBasis}), but fixes a bug in that package when using unusual term ordering. }

 

\subsection{\textcolor{Chapter }{SingularReducedGroebnerBasis}}
\logpage{[ 10, 3, 4 ]}\nobreak
\hyperdef{L}{X7FB57C4F7D3164E6}{}
{\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{SingularReducedGroebnerBasis({\slshape I})\index{SingularReducedGroebnerBasis@\texttt{SingularReducedGroebnerBasis}}
\label{SingularReducedGroebnerBasis}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 List 



 Returns a list of relations which form a reduced Gr{\"o}bner basis for the
ideal \mbox{\texttt{\slshape I}} given the \texttt{TermOrdering} (\textbf{singular: TermOrdering}) associated with the ring containing \mbox{\texttt{\slshape I}}. This function is the equivalent of the \textsf{singular} function \texttt{GroebnerBasis} (\textbf{singular: GroebnerBasis}) (and uses that function), but ensures that a reduced basis is returned. }

 }

 
\section{\textcolor{Chapter }{Groups}}\logpage{[ 10, 4, 0 ]}
\hyperdef{L}{X8716635F7951801B}{}
{
  Small groups in \textsf{GAP} can be indexed by their small groups library number  (\textbf{Reference: Small Groups}). An alternative indexing scheme, the Hall-Senior number, is used by Jon
Carlson to publish his cohomology ring calculations at \href{http://www.math.uga.edu/~lvalero/cohointro.html} {\texttt{http://www.math.uga.edu/\texttt{\symbol{126}}lvalero/cohointro.html}}. To allow comparison with these results, we provide a function that converts
from the \textsf{GAP} small groups library numbers to Hall-Senior number for the groups of order 8,
16, 32 and 64. 
\subsection{\textcolor{Chapter }{HallSeniorNumber}}\logpage{[ 10, 4, 1 ]}
\hyperdef{L}{X7FD16926859DD49B}{}
{
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HallSeniorNumber({\slshape order, i})\index{HallSeniorNumber@\texttt{HallSeniorNumber}!for SmallGroup library ref}
\label{HallSeniorNumber:for SmallGroup library ref}
}\hfill{\scriptsize (attribute)}}\\
\noindent\textcolor{FuncColor}{$\Diamond$\ \texttt{HallSeniorNumber({\slshape G})\index{HallSeniorNumber@\texttt{HallSeniorNumber}!for group}
\label{HallSeniorNumber:for group}
}\hfill{\scriptsize (attribute)}}\\
\textbf{\indent Returns:\ }
 Integer 



 Returns the Hall-Senior number for a small group (of order 8, 16, 32 or 64).
The group can be specified an \mbox{\texttt{\slshape order}}, \mbox{\texttt{\slshape i}} pair from the \textsf{GAP}  (\textbf{Reference: Small Groups}) library, or as a group \mbox{\texttt{\slshape G}}, in which case \texttt{IdSmallGroup} (\textbf{Reference: IdSmallGroup}) is used to identify the group. }

 
\begin{Verbatim}[fontsize=\small,frame=single,label=Example]
  gap> HallSeniorNumber(32, 5);
  20
  gap> HallSeniorNumber(SmallGroup(64, 1));
  11
\end{Verbatim}
 }

 }

   \def\indexname{Index\logpage{[ "Ind", 0, 0 ]}
\hyperdef{L}{X83A0356F839C696F}{}
}


\printindex

\newpage
\immediate\write\pagenrlog{["End"], \arabic{page}];}
\immediate\closeout\pagenrlog
\end{document}
