<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE Book SYSTEM "gapdoc.dtd">

<Book Name="nq">                                        <!-- REQUIRED -->

  <!--
                          The title page
                                                                      -->
  <TitlePage>                                           <!-- REQUIRED -->
    <Title>                                             <!-- REQUIRED -->
        <Package>NQ</Package>
    </Title>
    <Subtitle>                                          <!-- OPTIONAL -->
        A &GAP; 4 Package<Br></Br>
        computing nilpotent factor groups of finitely
        presented groups<Br></Br>
        &nbsp;<Br></Br>
        Based on the ANU Nilpotent Quotient Program
    </Subtitle>
    <Version>Version 2.2</Version>                      <!-- OPTIONAL -->
    <Author>
        Werner Nickel<Br></Br>                          <!-- REQUIRED -->
        &nbsp;
        <Address>
            Fachbereich Mathematik, AG 2<Br></Br>
            TU Darmstadt<Br></Br>
            Schlossgartenstr. 7<Br></Br>
            64289 Darmstadt<Br></Br>
            Germany
        </Address>
        <Email>
            nickel at mathematik.tu-darmstadt.de
        </Email>
        <Homepage>http://www.mathematik.tu-darmstadt.de/~nickel</Homepage>
    </Author>
    <Date>February 2007</Date>                          <!-- OPTIONAL -->
    <Copyright>                                         <!-- OPTIONAL -->
        &copyright; 1992-2007 Werner Nickel.
    </Copyright>
    <Acknowledgements> <!-- OPTIONAL --> 
    The development of this program was started while the
    author was supported by an Australian National University PhD
    scholarship and an Overseas Postgraduate Research Scholarship.

    <P/>Further development of this program was done with support from the
    DFG-Schwerpunkt-Projekt "`Algorithmische Zahlentheorie und
    Algebra"'.

    <P/>Over the years a number of people have made useful suggestions
    that found their way into the code:  Mike Newman, Michael
    Vaughan-Lee, Joachim Neubüser, Charles Sims.

    <P/>I thank Volkmar Felsch and Joachim Neubüser for their careful
    examination of the package prior to its release for GAP 4.

    <P/>This documentation was prepared with the <Package>GAPDoc</Package>
    package by Frank Lübeck and Max Neunhöffer.
    </Acknowledgements>
    </TitlePage>



  <TableOfContents/>                                    <!-- OPTIONAL -->



  <!--
                            The document
                                                                      -->
  <Body>                                                <!-- REQUIRED -->

  <Chapter>
  <Heading>Introduction</Heading>

  This package provides an interface between &GAP; 4 and the
  Australian National University Nilpotent Quotient Program (ANU NQ).
  The ANU NQ was implemented as part of the author's work towards his
  PhD at the Australian National University, hence the name of the
  program.  The program takes as input a finite presentation of a
  group and successively computes factor groups modulo the terms of
  the lower central series of the group.  These factor groups are
  computed in terms of polycyclic presentations.

  <P/> The ANU NQ is implemented  in  the programming language  C. The
  implementation has been developed in  a Unix environment and Unix is
  currently the only operating system  supported.  It runs on a number
  of different Unix versions, e.g.  Solaris and Linux.

  <P/> For integer matrix computations it relies on the GNU MP <Cite
  Key="GNUMP"/> package and requires this package to be installed on
  your system.
  
  <P/> This package relies  on the functionality for polycyclic groups
  provided  by the  &GAP; package  <Package>polycyclic</Package> <Cite
  Key="polycyclic"/>       and        requires       the       package
  <Package>polycyclic</Package> to be installed  as a &GAP; package on
  your computer system.

  <P/>
  Comments,  bug reports and  suggestions are  very welcome.

  <P/> This manual contains references to parts of the &GAP; Reference
  Manual which are typeset in a slightly idiosyncratic way.  The
  following example shows how such references are printed: 'For
  further information on creating a free group see <Ref BookName="ref"
  Func="FreeGroup"/>.'  The text in bold face refers to the &GAP;
  Reference Manual.

  <P/>Each item in the list of references at the end of this manual is
  followed by a list of numbers that specify the pages of the manual
  where the reference occurs.

  </Chapter>

  <Chapter><Heading>General remarks</Heading>

  In this chapter we define notation used throughout this manual and
  recollect basic facts about nilpotent groups.  We also provide some
  background information about the functionality implemented in this
  package. 


  <Section><Heading>Commutators and the Lower Central Series</Heading>

  <Index>commutator</Index> The <E>commutator</E> of two elements
  <M>h_1</M> and <M>h_2</M> of a group <M>G</M> is the element
  <M>h_1^{-1}h_2^{-1}h_1h_2</M> and is denoted by <M>[h_1,h_2]</M>.
  It satisfies the equation <M>h_1h_2 = h_2h_1[h_1,h_2]</M> and
  can be interpreted as the correction term that has to be introduced
  into a word if two elements of a group are interchanged.
  Iterated commutators are written in <E>left-normed fashion</E>:
  <Index>left-normed commutator</Index>
  <M>[h_1,h_2,\ldots,h_{n-1},h_n]=[[h_1,h_2,\ldots,h_{n-1}],h_n]</M>.

  <P/> 
  <Index>lower central series</Index>
  The <E>lower central series</E> of <M>G</M> is defined inductively
  as <M>\gamma_1(G) = G, \gamma_i(G) = [\gamma_{i-1}(G),G]</M> for
  <M>i \ge 2</M>.  Each term in the lower central series is a normal
  (even fully invariant) subgroup of <M>G</M>.  The factors of the
  lower central series are abelian groups.  On each factor the induced
  action of <M>G</M> via conjugation is the trivial action.

  <P/>The factor <M>\gamma_k(G)/\gamma_{k+1}(G)</M> is generated by
  the elements <M>[g,h]\gamma_{k+1}(G),</M> where <M>g</M> runs
  through a set of (representatives of) generators for
  <M>G/\gamma_2(G)</M> and <M>h</M> runs through a set of
  (representatives of) generators for
  <M>\gamma_{k-1}(G)/\gamma_k(G).</M> Therefore, each factor of the
  lower central series is finitely generated if <M>G</M> is finitely
  generated.

  <P/> If one factor of the lower central series is finite, then all
  subsequent factors are finite.  Then the exponent of the
  <M>k+1</M>-th factor is a divisor of the exponent of the <M>k</M>-th
  factor of the lower central series.  In particular, the exponents of
  all factors of the lower central series are bounded by the
  exponent of the first finite factor of the lower central series.
  </Section>

  <Section><Heading>Nilpotent groups</Heading>

  <Index>nilpotent</Index>
  A group <M>G</M> is called <E>nilpotent</E> if there is a positive
  integer <M>c</M> such that all <M>(c+1)</M>-fold commutators are
  trivial in <M>G.</M> The smallest integer with this property is
  called the 
  <Index>nilpotency class</Index><Index>class</Index>
  <E>nilpotency class</E> of <M>G</M>.  In terms of the lower
  central series a group <M>G \not= 1</M> has nilpotency class <M>c</M>
  if and only if
  <M>\gamma_{c}(G) \not= 1</M> and <M>\gamma_{c+1}(G) = 1</M>.

  <P/>Examples of nilpotent groups are finite <M>p</M>-groups, the
  group of unitriangular matrices over a ring with one and the factor
  groups of a free group modulo the terms of its lower central
  series.  

  <P/>Finiteness of a nilpotent group can be decided by the group's
  commutator factor group.  A nilpotent group is finite if and only if
  its commutator factor group is finite.  A group whose commutator
  factor group is finite can only have finite nilpotent quotient
  groups.

  <P/> By refining the lower central series of a finitely generated
  nilpotent group one can obtain a (sub)normal series
  <M>G_1&gt;G_2&gt;...&gt;G_{k+1}=1</M> with cyclic (central) factors.
  Therefore, every finitely generated nilpotent group is
  <Index>polycyclic</Index><E>polycyclic</E>.  Such a <E>polycyclic
  series</E> gives rise to a <Index>polycyclic generating
  sequence</Index> polycyclic generating sequence by choosing a
  generator <M>a_i</M> for each cyclic factor <M>G_i/G_{i+1}</M>.
  Let <M>I</M> be the
  set of indices such that <M>G_i/G_{i+1}</M> is finite.  A simple
  induction argument shows that every element of the group can be
  written uniquely as a <E>normal word</E> <M>a_1^{e_1}\ldots
  a_n^{e_n}</M> with integers <M>e_i</M> and <M>0\leq e_i&lt;m_i</M>
  for <M>i\in I</M>.

  </Section>
  
  <Section><Heading>Nilpotent presentations </Heading>

  <P/>From a polycyclic generating sequence one can obtain a
  <Index>polycyclic presentation</Index> <E>polycyclic
  presentation</E> for the group.  The following set of power and
  commutator relations is a defining set of relations.  The
  <Index>power relation</Index> <E>power relations</E> express
  <M>a_i^{m_i}</M> in terms of the generators
  <M>a_{i+1},\ldots,a_n</M> whenever <M>G_i/G_{i+1}</M> is finite with
  order <M>m_i</M>. The <Index>commutator relation</Index>
  <E>commutator relations</E> are obtained by expressing
  <M>[a_j,a_i]</M> for <M>j&gt;i</M> as a word in the generators
  <M>a_{i+1},\ldots,a_n</M>.  If the polycyclic series is obtained
  from refining the lower central series, then <M>[a_j,a_i]</M> is
  even a word in <M>a_{j+1},\ldots,a_n</M>.  In this case we obtain a
  nilpotent presentation.

  <P/>To be more precise, a <Index>nilpotent presentation</Index>
  <E>nilpotent presentation</E> is given on a finite number of
  generators <M>a_1,\ldots,a_n</M>.  Let <M>I</M> be the set of
  indices such that <M>G_i/G_{i+1}</M> is finite.  Let <M>m_i</M> be
  the order of <M>G_i/G_{i+1}</M> for <M>i\in I</M>.  Then a nilpotent
  presentation has the form
  <Display>
  \langle a,\ldots,a_n | 
      a_i^{m_i}   = w_{ii}(a_{i+1},\ldots,a_n) 
                 \mbox{ for } i\in I;\; 
      [a_j,a_i] = w_{ij}(a_{j+1},\ldots,a_n)
                 \mbox{ for } 1\leq i &lt; j\leq n\rangle
  </Display>
  Here, <M>w_{ij}(a_k,\ldots,a_n)</M> denotes a group word in the
  generators <M>a_k,\ldots,a_n</M>. 

  <P/>In a group given by a polycyclic presentation each element in
  the group can be written as a <E>normal word</E> <M>a_1^{e_1}\ldots
  a_n^{e_n}</M> with <M>e_i \in \Z</M> and <M>0 \leq e_i &lt; m_i</M>
  for <M>i \in I</M>.  A procedure called <E>collection</E> can be
  used to convert an arbitrary word in the generators into an
  equivalent normal word.  In general, the resulting normal word need
  not be unique.  The result of collecting a word may depend on the
  steps chosen during the collection procedure.  A polycyclic
  presentation with the property that two different normal words are
  never equivalent is called
  <E>consistent</E><Index>consistent</Index>.  A polycyclic
  presentation derived from a polycyclic series as above is
  consistent.  The following example shows an inconsistent polycyclic
  presentation

  <Display>\langle a,b\mid a^2, b^a = b^2 \rangle </Display> 

  as <M>b = baa = ab^2a = a^2b^4 = b^4</M> which implies <M>b^3=1</M>.
  Here we have the equivalent normal words <M>b^3</M> and the empty
  word.  It can be proved that consistency can be checked by
  collecting a finite number of words in the given generating set in
  two essentially different ways and checking if the resulting normal
  forms are the same in both cases.  See Chapter 9 of the book <Cite
  Key="Sims94"/> for an introduction to polycyclic groups and
  polycyclic presentations.

  <P/>For computations in a polycyclic group one chooses a consistent
  polycyclic presentation as it offers a simple solution to the word
  problem: Equality between two words is decided by collecting both
  words to their respective normal forms and comparing the normal
  forms.  Nilpotent groups and nilpotent presentations are special
  cases of polycyclic groups and polycyclic presentations.  Nilpotent
  presentations allow specially efficient collection methods.  The
  package <Package>Polycyclic</Package> provides algorithms to compute
  with polycyclic groups given by a polycyclic presentation.

  <P/>However, inconsistent nilpotent presentations arise naturally in
  the nilpotent quotient algorithm.  There is an algorithm based on
  the test words for consistency mentioned above to modify the arising
  inconsistent presentations suitably to obtain a consistent one for
  the same group.
  </Section>

  <Section><Heading>A sketch of the algorithm</Heading>

  The input for the ANU NQ in its simplest form is a finite
  presentation <M>\langle X|R\rangle</M> for a group <M>G</M>.  The
  first step of the algorithm determines a nilpotent presentation for
  the commutator quotient of <M>G</M>.  This is a presentation of the
  class-<M>1</M> quotient of <M>G</M>.  Call its generators
  <M>a_1,...,a_d</M>.  It also determines a homomorphism of <M>G</M>
  onto the commutator quotient and describes it by specifying the
  image of each generator in <M>X</M> as a word in the <M>a_i</M>.

  <P/>For the general step assume that the algorithm has computed a
  nilpotent presentation for the class-<M>c</M> quotient of <M>G</M>
  and that <M>a_1,...,a_d</M> are the generators introduced in the
  first step of the algorithm.  Furthermore, there is a map from X
  into the class-<M>c</M> quotient describing the epimorphism from
  <M>G</M> onto <M>G/\gamma_{c+1}(G)</M>.

  <P/>Let <M>b_1,...b_k</M> be the generators from the last step of the
  algorithm, the computation of <M>\gamma_c(G)/\gamma_{c+1}(G)</M>.
  This means that <M>b_1,...b_k</M> generate
  <M>\gamma_c(G)/\gamma_{c+1}(G)</M>.  Then the commutators
  <M>[b_j,a_i]</M> generate <M>\gamma_{c+1}(G)/\gamma_{c+2}(G)</M>. 
  The algorithm introduces new, central generators <M>c_{ij}</M> into
  the presentation, adds the relations <M>[b_j,a_i] = c_{ij}</M> and
  modifies the existing relations by appending suitable words in the
  <M>c_{ij}</M>, called <E>tails</E>, to the right hand sides of the
  power and commutator relations.  The resulting presentation is a
  nilpotent presentation for the <E>nilpotent cover</E> of
  <M>G/\gamma_{c+1}(G)</M>.  The nilpotent cover is the largest central
  extension of <M>G/\gamma_{c+1}(G)</M> generated by <M>d</M> elements.
  It is is uniquely determined up to isomorphism.
  
  <P/>The resulting presentation of the nilpotent cover is in general
  inconsistent.  Consistency is achieved by running the consistency
  test.  This results in relations among the generators
  <M>c_{ij}</M> which can be used to eliminate some of those
  generators or introduce power relations.  After this has been done
  we have a consistent nilpotent presentation for the nilpotent cover
  of <M>G/\gamma_{c+1}(G)</M>.
  
  <P/>Furthermore, the nilpotent cover need not satisfy the relations
  of <M>G</M>.  In other words, the epimorphism from <M>G</M> onto
  <M>G/\gamma_{c+1}(G)</M> cannot be lifted to an epimorphism onto the
  nilpotent cover.  Applying the epimorphism to each relator of
  <M>G</M> and collecting the resulting words of the nilpotent cover
  yields a set of words in the <M>c_{ij}</M>.  This gives further
  relations between the <M>c_{ij}</M> which leads to further
  eliminations or modifications of the power relations for the
  <M>c_{ij}</M>.

  <P/>After this, the inductive step of the ANU NQ is complete and a
  consistent nilpotent presentation for <M>G/\gamma_{c+2}(G)</M> is
  obtained together with an epimorphism from <M>G</M> onto the
  class-<M>(c+1)</M> quotient.

  <P/>Chapter 11 of the book <Cite Key="Sims94"/> discusses a
  nilpotent quotient algorithm.  A description of the implementation
  in the ANU NQ is contained in <Cite Key="Nickel96"/>
  </Section>

  <Section><Heading>Identical Relations</Heading><Label Name="IdRels"/>

  Let <M>w</M> be a word in free generators <M>x_1,\ldots,x_n</M>.  A
  group <M>G</M> satisfies the relation <M>w=1</M> <E>identically</E> if
  each map from <M>x_1,\ldots,x_n</M> into <M>G</M> maps <M>w</M> to
  the identity element of <M>G</M>.  We also say that <M>G</M> satisfies the
  <Index>identical relation</Index> <Index>law</Index> <E>identical
  relation</E> <M>w=1</M> or satisfies the <E>law</E> <M>w=1</M>.  In
  slight abuse of notation, we call the elements <M>x_1,\ldots,x_n</M>
  <Index>identical generator</Index> 
  <E>identical</E> generators.

  <P/> Common examples of identical relations are: A group of
  nilpotency class at most <M>c</M> satisfies the law
  <M>[x_1,\ldots,x_{c+1}]=1</M>.  A group that satisfies the law
  <M>[x,y,\ldots,y]=1</M> where <M>y</M> occurs <M>n</M>-times, is
  called an <M>n</M>-Engel group.  A group that satisfies the law
  <M>x^d=1</M> is a group of exponent <M>d</M>.

  <P/>
  To describe finitely presented groups that satisfy one or more laws,
  we extend a common notation for finitely presented groups 
  by specifying the identical generators as part of the generator
  list, separated from the group generators by a semicolon: For
  example
  <Display>
  \langle a,b,c; x,y | x^5, [x,y,y,y]\rangle
  </Display>
  is a group on 3 generators <M>a,b,c</M> of exponent <M>5</M>
  satisfying the 3rd Engel law.  The presentation above is equivalent
  to a presentation on 3 generators with an infinite set of relators,
  where the set of relators consists of all fifth powers of words in
  the generators and all commutators <M>[x,y,y,y]</M> where <M>x</M>
  and <M>y</M> run through all words in the generators <M>a,b,c</M>.
  The standalone programme accepts the notation introduced above as a
  description of
  its input.  In <Package>GAP 4</Package> finitely presented groups
  are specified in a different way, see 
  <Ref Func="NilpotentQuotient" Style="Text"/> for a description.

  <P/>
  This notation can also be used in words that mix group and identical
  generators as in the following example:
  <Display>
  \langle a,b,c; x | [x,c], [a,x,x,x] \rangle
  </Display>
  The first relator specifies a law which says that <M>c</M> commutes
  with all elements of   the group.  The second turns  <M>a</M> into a
  third right Engel element.   

  <P/>An element <M>a</M> is called <E>a right <M>n</M>-th 
  Engel element</E> or <E>a right <M>n</M>-Engel element</E> 
  <Index>right Engel element</Index> 
  if it satisfies the commutator law <M>[a,x,...,x]=1</M>
  where the identical generator <M>x</M> occurs <M>n</M>-times.
  Likewise, an element <M>b</M> is called an <E>left <M>n</M>-th Engel
  element</E> or <E>left <M>n</M>-Engel element</E> 
  <Index>left Engel element</Index>
  if it satisfies the commutator law <M>[x,b,b,...b]=1</M>.

  <P/>Let <M>G</M> be a nilpotent group.  Then <M>G</M> satisfies a
  given law if the law is satisfied by a certain finite set of
  instances given by Higman's Lemma, see <Cite Key="Higman59"/>.  The
  ANU NQ uses Higman's Lemma to obtain a finite presentation for
  groups that satisfy one or several identical relations.

  </Section>

  <Section Label="ExpTrees"><Heading>Expression Trees</Heading>
  Expressions involving commutators play an important role in the
  context of nilpotent groups.  Expanding an iterated commutator
  produces a complicated and long expression.  For example, 
  <Display>
            [x,y,z] = y^{-1}x^{-1}yxz^{-1}x^{-1}y^{-1}xyz.
  </Display>
  Evaluating a commutator <M>[a,b]</M> is done efficiently by
  computing the equation <M>(ba)^{-1}ab</M>.  Therefore, for each
  commutator we need to perform two multiplications and one inversion.
  Evaluating <M>[x,y,z]</M> needs four multiplications and two
  inversions.  Evaluation of an iterated commutator with <M>n</M>
  components takes <M>2n-1</M> multiplications and
  <M>n-1</M> inversions.  The expression on the right hand side above
  needs <M>9</M> multiplications and <M>5</M> inversions which is
  clearly much more expensive than evaluating the commutator directly.  

  <P/> Assuming that no cancellations occur, expanding an iterated
  commutator with n components produces a word with
  <M>2^{n+1}-2^{n-1}-2</M> factors half of which are inverses.  A
  similar effect occurs whenever a compact expression is expanded into
  a word in generators and inverses, for example <M>(ab)^{49}</M>.

  <P/> Therefore, it is important not to expand expressions into a
  word in generators and inverses.  For this purpose we provide a
  mechanism which we call here 
  <Index>expression trees</Index>
  <E>expression trees</E>.  An expression tree preserves the
  structure of a given expression.  It is a (binary) tree in which
  each node is assigned an operation and whose leaves are generators
  of a free group or integers.  For example, the expression
  <M>[(xy)^2, z]</M> is stored as a tree whose top node is a
  commutator node.  The right subtree is just a generator node
  (corresponding to <M>z</M>).  The
  left subtree is a power node whose subtrees are a
  product node on the left and an integer node on the right.  An
  expression tree can involve products, powers, conjugates and
  commutators.  However, the list of available operations can
  be extended.

  <P/>Evaluation of an expression tree is done recursively and
  requires as many operations as there are nodes in the tree.  An
  expression tree can be evaluated in a specific group by the function
  <Ref Func="EvaluateExpTree" Style="Text"/>.

  <P/>A presentation specified by expression trees is a record with
  the components <F>.generators</F> and <F>.relations</F>.  See 
  section <Ref Sect="FunctionsExpTrees"/> for a description of the functions
  that produce and manipulate expression trees.
  <Example>
gap> RequirePackage( "nq" );
true
gap> gens := ExpressionTrees( 2 );
[ x1, x2 ]
gap> r1 := LeftNormedComm( [gens[1],gens[2],gens[2]] );
Comm( x1, x2, x2 )
gap> r2 := LeftNormedComm( [gens[1],gens[2],gens[2],gens[1]] );
Comm( x1, x2, x2, x1 )
gap> pres := rec( generators := gens, relations := [r1,r2] );
rec( generators := [ x1, x2 ], 
  relations := [ Comm( x1, x2, x2 ), Comm( x1, x2, x2, x1 ) ] )
  </Example>
  </Section>

  <Section><Heading>A word about the implementation</Heading>

  The ANU NQ is written in C, but not in ANSI C.  I hope to make one
  of the next versions ANSI compliable.  However, it uses a fairly
  restricted subset of the language so that it should be easy to
  compile it in new environments.  The code is 64-bit clean.  If you
  have difficulties with porting it to a new environment, let me know
  and I'll be happy to assist if time permits.

  <P/>The program has two collectors:  a simple collector from the left
  as described in <Cite Key="LS90"/> and a combinatorial from the left
  collector as described in <Cite Key="VL90a"/>.  The combinatorial
  collector is always faster than the simple collector, therefore, it
  is the collector used by this package by default.  This can be
  changed by modifying the global variable <Ref Var="NqDefaultOptions"
  Style="Text"/>.

  <P/>In a polycyclic group with generators that do not have power
  relations, exponents may become arbitrarily large.  Experience shows
  that this happens rarely in the computations done by the ANU NQ.
  Exponents are represented by 32-bit integers.  The collectors
  perform an overflow check and abort the computation if an overflow
  occurred.  In a GNU environment the program can be compiled using
  the `long long' 64-bit integer type.  For this uncomment the
  relevant line in src/Makefile and recompile the program.

  <P/>As part of the step that enforces consistency and the relations
  of the group, the ANU NQ performs computations with integer matrices
  and converts them to Hermite Normal Form.  The algorithm used here
  is a variation of the Kanan-Bachem algorithm based on the GNU
  multiple precision package GNU MP <Cite Key="GNUMP"/>.  Experience shows
  that the integer matrices are usually fairly sparse and Kanan-Bachem
  seems to be sufficient in this context.  However, the implementation
  might benefit from a more efficient strategy for computing Hermite
  Normal Forms.  This is a topic for further investigations.

  <P/>As the program does not compute the Smith Normal Form for each 
  factor of the lower central series but the Hermite Normal
  Form, it does not necessarily obtain a minimal generating set for
  each factor of the lower central series.  The following is a simple
  example of this behaviour.  We take the presentation
  <Display>
  \langle x, y | x^2 = y \rangle
  </Display>
  The group is clearly isomorphic to the additive group of the
  integers.  Applying the ANU NQ to this presentation gives the
  following nilpotent presentation:
  <Display>
    \langle A,B | A^2 = B, [B,A] \rangle
  </Display>
  A nilpotent presentation on a minimal generating set would be the
  presentation of the free group on one generator:
  <Display>
    \langle A | \; \rangle
  </Display>

  </Section>

  <Section><Heading>The input format of the standalone</Heading><Label Name="InputForm"/>

The input format for finite presentations resembles the way many
people write down a presentation on paper.  Here are some examples of
presentations that the ANU NQ accepts:

<Verb>
<![CDATA[
    < a, b | >                       # free group of rank 2

    < a, b, c; x, y | 
                [a,b,c],             # a left normed commutator
                [b,c,c,c]^6,         # another one raised to a power
                a^2 = c^-3*a^2*c^3,  # a relation
                a^(b*c) = a,         # a conjugate relation
                (a*[b,(a*c)])^6,     # something that looks complicated
                [x,y,y,y,y],         # an identical relation
                [c,x,x,x,x,x]        # c is a fifth right Engel element
    >
]]>
</Verb>

A presentation starts with '&tlt;' followed by a list of generators
separated by commas.  Generator names are strings that contain only
upper and lower case letters, digits, dots and underscores and that do
not start with a digit.  The list of generator names is separated from
the list of relators/relations by the symbol '<M>\mid</M>'.  The list of
generators can be followed by a list of identical generators separated
by a semicolon.  Relators and relations are separated by commas and
can be mixed arbitrarily.  Parentheses can be used in order to group
subexpressions together.  Square brackets can be used in order to form
left normed commutators.  The symbols '*' and '&circum;' can be
used to form products and powers, respectively. The presentation
finishes with the symbol '&tgt;'.  A comment starts with the symbol '&hash;'
and finishes at the end of the line.  The file src/presentation.c
contains a complete grammar for the presentations accepted by the ANU
NQ.


<P/>Typically, the input for the standalone is put into a file by
using a standard text editor.  The file can be passed as an argument
to the function <Ref Func="NilpotentQuotient" Style="Text"/>.  It is
also possible to put a presentation in the standalone's input format
into a string and use the string as argument for <Ref
Func="NilpotentQuotient" Style="Text"/>.

  </Section>
  </Chapter>  

  <Chapter>
  <Heading>The Functions of the Package</Heading>
  <Index>Nilpotent Quotient Package</Index>

     <Section><Heading>Nilpotent Quotients of Finitely Presented Groups</Heading>

        <ManSection>
        <Func Name="NilpotentQuotient" 
              Arg="[output-file,] fp-group [, id-gens] [, c]"/>   

        <Func Name="NilpotentQuotient"
              Arg="[output-file,] input-file [,c]"/> 

         <Description>
           The parameter <F>fp-group</F> is either a finitely
           presented group or a record specifying a presentation by
           expression trees (see section <Ref Sect="ExpTrees"/>).  The
           parameter <F>input-file</F> is a string specifying the name
           of a file containing a finite presentation in the input
           format (cf. section <Ref Label="InputForm"/>) of the ANU
           NQ.  Such a file can be prepared by a text editor or with
           the help of the function <Ref Func="NqStringFpGroup"
           Style="Text"/>. 

           <P/> Let <M>G</M> be the group defined by <F>fp-group</F>
           or the group defined in <F>input-file</F>.  The function
           computes a nilpotent presentation for
           <M>G/\gamma_{c+1}(G)</M> if the optional parameter <F>c</F>
           is specified.  If <F>c</F> is not given, then the function
           attempts to compute the largest nilpotent quotient of
           <M>G</M> and it will terminate only if <M>G</M> has a
           largest nilpotent quotient.  See section <Ref
           Sect="DiagnosticOutput"/> for a possibility to follow the
           progress of the computation.

           <P/>  The optional  argument  <F>id-gens</F> is  a list  of
           generators  of  the  free  group  underlying  the  finitely
           presented  group <F>fp-group</F>.   The generators  in this
           list  are treated  as identical  generators.  Consequently,
           all  relations  of   the  <F>fp-group</F>  involving  these
           generators  are treated  as identical  relations  for these
           generators.

           <P/> In addition to the arguments explained above, the
           function accepts the following options as shown in the
           first example below:

           <Index>options</Index>
           <List>
           <Item><Keyword>group</Keyword> 
           <Index Subkey="group">options</Index>
           This option can be used
           instead of the parameter <F>fp-group</F>.
           </Item>
           <Item><Keyword>input\_string</Keyword>
           <Index Subkey="input\_string">options</Index>
           This option can be
           used to specify a finitely presented group by a string in
           the input format of the standalone program.
           </Item>
           <Item><Keyword>input\_file</Keyword>
           <Index Subkey="input\_file">options</Index>
           This option specifies
           a file with input for the standalone program.
           </Item>
           <Item><Keyword>output\_file</Keyword> 
           <Index Subkey="ouput\_file">options</Index>
           This option specifies
           a file for the output of the standalone.
           </Item>

           <Item><Keyword>idgens</Keyword>
           <Index Subkey="idgens">options</Index>
           This options specifies a list of identical generators.
           </Item>
           <Item><Keyword>class</Keyword> 
           <Index Subkey="class">options</Index>
           This option specifies the nilpotency class up to which the
           nilpotent quotient will be computed.
           </Item>
           </List>

           <P/>The following example computes the class-5 quotient of
           the free group on two generators.
<Example>
<![CDATA[
gap> F := FreeGroup( 2 );
<free group on the generators [ f1, f2 ]>
gap> ## Equivalent to:  NilpotentQuotient( : group := F, class := 5 );
gap> ##                 NilpotentQuotient( F : class := 5 );          
gap> H := NilpotentQuotient( F, 5 );
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
gap> lcs := LowerCentralSeries( H );;
gap> for i in [1..5] do Print( lcs[i] / lcs[i+1], "\n" ); od;
Pcp-group with orders [ 0, 0 ]
Pcp-group with orders [ 0 ]
Pcp-group with orders [ 0, 0 ]
Pcp-group with orders [ 0, 0, 0 ]
Pcp-group with orders [ 0, 0, 0, 0, 0, 0 ]
]]>
</Example>

        Note that the lower central series in the example is part of
        the data returned by the standalone program.  Therefore, the
        execution of the function LowerCentralSeries takes no time.

        <P/>The next example computes the class-4 quotient of the
        infinite dihedral group.  The group is soluble but not
        nilpotent.  The first factor of its lower central series is a
        Klein four group and all the other factors are cyclic or order
        <M>2</M>. 
<Example>
<![CDATA[
gap> F := FreeGroup( 2 );
<free group on the generators [ f1, f2 ]>
gap> G := F / [F.1^2, F.2^2];
<fp group on the generators [ f1, f2 ]>
gap> H := NilpotentQuotient( G, 4 ); 
Pcp-group with orders [ 2, 2, 2, 2, 2 ]
gap> lcs := LowerCentralSeries( H );;
gap> for i in [1..Length(lcs)-1] do
>       Print( AbelianInvariants(lcs[i] / lcs[i+1]), "\n" );
> od;
[ 2, 2 ]
[ 2 ]
[ 2 ]
[ 2 ]
gap> 
]]>
</Example>
In the following example identical generators are used in order to
express the fact that the group is nilpotent of class <M>3</M>.  A
group is nilpotent of class <M>3</M> if it satisfies the identical
relation <M>[x_1,x_2,x_3,x_4]=1</M> (cf. Section <Ref
Sect="IdRels"/>). The result is the free nilpotent group of class
<M>3</M> on two generators.
<Example>
<![CDATA[
gap> F := FreeGroup( "a", "b", "w", "x", "y", "z" );
<free group on the generators [ a, b, w, x, y, z ]>
gap> G := F / [ LeftNormedComm( [F.3,F.4,F.5,F.6] ) ];
<fp group of size infinity on the generators [ a, b, w, x, y, z ]>
gap> ## The following is equivalent to: 
gap> ##   NilpotentQuotient( G : idgens := [F.3,F.4,F.5,F.6] );
gap> H := NilpotentQuotient( G, [F.3,F.4,F.5,F.6] );
Pcp-group with orders [ 0, 0, 0, 0, 0 ]
gap> NilpotencyClassOfGroup(H);
3
gap> LowerCentralSeries(H);
[ Pcp-group with orders [ 0, 0, 0, 0, 0 ], Pcp-group with orders [ 0, 0, 0 ], 
  Pcp-group with orders [ 0, 0 ], Pcp-group with orders [  ] ]
]]>
</Example>
The following example uses expression trees in order to specify the
third Engel law for the free group on <M>3</M> generators.
<Example>
<![CDATA[
gap> et := ExpressionTrees( 5 );                            
[ x1, x2, x3, x4, x5 ]
gap> comm := LeftNormedComm( [et[1], et[2], et[2], et[2]] );
Comm( x1, x2, x2, x2 )
gap> G := rec( generators := et, relations := [comm] );
rec( generators := [ x1, x2, x3, x4, x5 ], 
  relations := [ Comm( x1, x2, x2, x2 ) ] )
gap> H := NilpotentQuotient( G : idgens := [et[1],et[2]] );
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 2, 
  0, 6, 6, 0, 0, 2, 10, 10, 10 ]
gap> TorsionSubgroup( H );
Pcp-group with orders [ 2, 2, 2, 2, 2, 2, 2, 10, 10, 10 ]
gap> lcs := LowerCentralSeries( H );;
gap> NilpotencyClassOfGroup( H );
5
gap> for i in [1..5] do Print( lcs[i] / lcs[i+1], "\n" ); od;
Pcp-group with orders [ 0, 0, 0 ]
Pcp-group with orders [ 0, 0, 0 ]
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0 ]
Pcp-group with orders [ 2, 4, 2, 2, 0, 6, 6, 0, 0, 2 ]
Pcp-group with orders [ 10, 10, 10 ]
gap> for i in [1..5] do Print( AbelianInvariants(lcs[i]/lcs[i+1]), "\n" ); od;
[ 0, 0, 0 ]
[ 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 0 ]
[ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0 ]
[ 10, 10, 10 ]
]]>
</Example>
The example above also shows that the relative orders of an abelian
polycyclic  group need not be the abelian invariants (elementary
divisors) of the group.  Each zero corresponds to a generator of
infinite order.  The number of zeroes is always correct.
        </Description>
        </ManSection>

        <ManSection>
        <Func Name="NilpotentEngelQuotient" 
              Arg="[output-file,] fp-group, n, [, id-gens] [, c]"/>
        <Func Name="NilpotentEngelQuotient" 
              Arg="[output-file,] input-file, n, [, c]"/>
        <Description>
           This function is a special version of <Ref
           Func="NilpotentQuotient" Style="Text"/> which enforces the
           <M>n</M>-th Engel identity on the nilpotent quotients of the
           group specified by <F>fp-group</F> or by <F>input-file</F>.
           It accepts the same options as <F>NilpotentQuotient</F>.

           <P/>The Engel condition can also be enforced by using
           identical generators and the Engel law and <Ref
           Func="NilpotentQuotient" Style="Text"/>.  See the examples
           there. 

           <P/> The following example computes the relatively free
           fifth Engel group on two generators, determines its
           (normal) torsion subgroup and computes the corresponding
           quotient group.  The quotient modulo the torsion subgroup
           is torsion-free.  Therefore, there is a nilpotent
           presentation without power relations.  The example
           computes a nilpotent presentation for the torsion free
           factor group through the upper central series.  The factors
           of the upper central series in a torsion free group are
           torsion free.  In this way one obtains a set of generators
           of infinite order and the resulting nilpotent presentation
           has no power relations.
<Example>
gap> G := NilpotentEngelQuotient( FreeGroup(2), 5 );
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 10, 
  0, 0, 30, 0, 3, 3, 10, 2, 0, 6, 0, 0, 30, 2, 0, 9, 3, 5, 2, 6, 2, 10, 5, 5, 
  2, 0, 3, 3, 3, 3, 3, 5, 5, 3, 3 ]
gap> NilpotencyClassOfGroup(G);
9
gap> T := TorsionSubgroup( G );
Pcp-group with orders [ 3, 3, 2, 2, 3, 3, 2, 9, 3, 5, 2, 3, 2, 10, 5, 2, 3, 
  3, 3, 3, 3, 5, 5, 3, 3 ]
gap> IsAbelian( T );
true
gap> AbelianInvariants( T );
[ 3, 3, 3, 3, 3, 3, 3, 3, 30, 30, 30, 180, 180 ]
gap> H := G / T;
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 10, 
  0, 0, 30, 0, 5, 0, 2, 0, 0, 10, 0, 2, 5, 0 ]
gap> H := PcpGroupBySeries( UpperCentralSeries(H), "snf" );
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  0, 0, 0, 0, 0 ]
gap> ucs := UpperCentralSeries( H );;
gap> for i in [1..NilpotencyClassOfGroup(H)] do
> 	Print( ucs[i]/ucs[i+1], "\n" );
> od;
Pcp-group with orders [ 0, 0 ]
Pcp-group with orders [ 0 ]
Pcp-group with orders [ 0, 0 ]
Pcp-group with orders [ 0, 0, 0 ]
Pcp-group with orders [ 0, 0, 0, 0, 0, 0 ]
Pcp-group with orders [ 0, 0, 0, 0 ]
Pcp-group with orders [ 0, 0 ]
Pcp-group with orders [ 0, 0, 0 ]
</Example>

        </Description>
        </ManSection>

        <ManSection>
        
        <Func Name="NqEpimorphismNilpotentQuotient"
              Arg="[output-file,] fp-group [, id-gens] [, c]"/>
        <Description>
           This function computes an epimorphism from the group
           <M>G</M> given by the finite presentation <F>fp-group</F>
           onto <M>G/\gamma_{c+1}(G).</M> If <F>c</F> is not given,
           then the largest nilpotent quotient of <M>G</M> is computed
           and an epimorphism from <M>G</M> onto the largest nilpotent
           quotient of <M>G</M>.  If <M>G</M> does not have a largest
           nilpotent quotient, the function will not terminate if
           <M>c</M> is not given.
           
           <P/>  The optional  argument  <F>id-gens</F> is  a list  of
           generators  of  the  free  group  underlying  the  finitely
           presented  group <F>fp-group</F>.   The generators  in this
           list  are treated  as identical  generators.  Consequently,
           all  relations  of   the  <F>fp-group</F>  involving  these
           generators  are treated  as identical  relations  for these
           generators.

           <P/>If  identical   generators  are  specified,   then  the
           epimorphism  returned  maps  the  group  generated  by  the
           `non-identical' generators onto the nilpotent factor group.
           See the last example below.

           <P/>The function understands the same options as the
           function <Ref Func="NilpotentQuotient"/>.

<Example>
<![CDATA[
gap> F := FreeGroup(3);                              
<free group on the generators [ f1, f2, f3 ]>
gap> phi := NqEpimorphismNilpotentQuotient( F, 5 );
[ f1, f2, f3 ] -> [ g1, g2, g3 ]
gap> Image( phi, LeftNormedComm( [F.3, F.2, F.1] ) );
g12
gap> F := FreeGroup( "a", "b" ); 
<free group on the generators [ a, b ]>
gap> G := F / [ F.1^2, F.2^2 ];     
<fp group on the generators [ a, b ]>
gap> phi := NqEpimorphismNilpotentQuotient( G, 4 );   
[ a, b ] -> [ g1, g2 ]
gap> Image( phi, Comm(G.1,G.2) ); 
g3*g4
gap> F := FreeGroup( "a", "b", "u", "v", "x" );
<free group on the generators [ a, b, u, v, x ]>
gap> a := F.1;; b := F.2;; u := F.3;; v := F.4;; x := F.5;;
gap> G := F / [ x^5, LeftNormedComm( [u,v,v,v] ) ];
<fp group of size infinity on the generators [ a, b, u, v, x ]>
gap> phi := NqEpimorphismNilpotentQuotient( G : idgens:=[u,v,x], class:=5 );
[ a, b ] -> [ g1, g2 ]
gap> U := Source(phi);                            
Group([ a, b ])
gap> ImageElm( phi, LeftNormedComm( [U.1*U.2, U.2^-1,U.2^-1,U.2^-1,] ) );
id
]]>
</Example>
        Note that the last epimorphism is a map from the group
        generated by <M>a</M> and <M>b</M> onto the nilpotent
        quotient.  The identical generators are used only to formulate
        the identical relator.  They are not generators of the group
        <M>G</M>.  Also note that the left-normed commutator above is
        mapped to the identity as <M>G</M> satisfies the specified
        identical law.
        </Description>
        </ManSection>

        <ManSection>
        <Func Name="LowerCentralFactors" Arg="..."/>
        <Description> 
        This function accepts the same arguments and options as <Ref
        Func="NilpotentQuotient"/> and returns a list containing the
        abelian invariants of the central factors in the lower central
        series of the specified group.  
<Example>
gap> LowerCentralFactors( FreeGroup(2), 6 );
[ [ 0, 0 ], [ 0 ], [ 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], 
  [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ]
</Example>
        </Description>
        </ManSection>

     </Section>

     <Section Label="FunctionsExpTrees"><Heading>Expression Trees</Heading>

     <ManSection>
     <Func Name="ExpressionTrees" Arg="m[, prefix]" />
     <Func Name="ExpressionTrees" Arg="str1, str2, str3, ..." />
     <Description>

     The argument <F>m</F> must be a positive integer.  The function
     returns a list with <F>m</F> expression tree symbols named x1,
     x2,...  The optional parameter <F>prefix</F> must be a string and
     is used instead of <F>x</F> if present.

     <P/> Alternatively, the function can be executed with a list of
     strings <F>str1</F>, <F>str2</F>, ....  It returns a list of
     symbols with these strings as names.
 
     <P/> The following operations are defined for expression trees:
     multiplication, inversion, exponentiation, forming commutators,
     forming conjugates.

     <Example>
gap> t := ExpressionTrees( 3 );                      
[ x1, x2, x3 ]
gap> tree := Comm( t[1], t[2] )^3/LeftNormedComm( [t[1],t[2],t[3],t[1]] );
Comm( x1, x2 )^3/Comm( x1, x2, x3, x1 )
gap> t := ExpressionTrees( "a", "b", "x" );
[ a, b, x ]
gap> tree := Comm( t[1], t[2] )^3/LeftNormedComm( [t[1],t[2],t[3],t[1]] );
Comm( a, b )^3/Comm( a, b, x, a )
     </Example>
     </Description>
     </ManSection>
     <ManSection>
     <Func Name="EvaluateExpTree" Arg="tree, symbols, values" />
     <Description>
     The argument <F>tree</F> is an expression tree followed by the
     list of those symbols <F>symbols</F> from which the expression tree is
     built up.  The argument <F>values</F> is a list containing a
     constant for each symbol.  The function substitutes each value
     for the corresponding symbol and computes the resulting value for
     <F>tree</F>.
     <Example>
<![CDATA[
gap> F := FreeGroup( 3 );                               
<free group on the generators [ f1, f2, f3 ]>
gap> t := ExpressionTrees( "a", "b", "x" );
[ a, b, x ]
gap> tree := Comm( t[1], t[2] )^3/LeftNormedComm( [t[1],t[2],t[3],t[1]] );
Comm( a, b )^3/Comm( a, b, x, a )
gap> EvaluateExpTree( tree, t, GeneratorsOfGroup(F) );
f1^-1*f2^-1*f1*f2*f1^-1*f2^-1*f1*f2*f1^-1*f2^-1*f1*f2*f1^-1*f3^-1*f2^-1*f1^
-1*f2*f1*f3*f1^-1*f2^-1*f1*f2*f1*f2^-1*f1^-1*f2*f1*f3^-1*f1^-1*f2^-1*f1*f2*f3
]]>
     </Example>
     </Description>
     </ManSection>
  </Section>

  <Section><Heading>Auxiliary Functions</Heading>
     <ManSection>

     <Func Name="NqReadOutput" Arg="stream" />
     <Description>
     The only argument <F>stream</F> is an output stream of the ANU
     NQ.  The function reads the stream and returns a record that has a
     component for each global variable used in the output of the ANU
     NQ, see <Ref Var="NqGlobalVariables" Style="Text"/>.
     </Description>
     </ManSection>

     <ManSection>
     <Func Name="NqStringFpGroup" Arg="fp-group [,idgens]" />
     <Description>
     The function takes a finitely presented group <F>fp-group</F> and
     returns a string in the input format of the ANU NQ.  If the list
     <F>idgens</F> is present, then it must contain generators of the
     free group underlying the finitely presented group <Ref
     BookName="ref" Oper="FreeGroupOfFpGroup"/>.  The generators in
     <F>idgens</F> are treated as identical generators.
     <Example>
<![CDATA[
gap> F := FreeGroup(2);
<free group on the generators [ f1, f2 ]>
gap> G := F / [F.1^2, F.2^2, (F.1*F.2)^4];
<fp group on the generators [ f1, f2 ]>
gap> NqStringFpGroup( G );
"< x1, x2 |\n    x1^2,\n    x2^2,\n    x1*x2*x1*x2*x1*x2*x1*x2\n>\n"
gap> Print( last );
< x1, x2 |
    x1^2,
    x2^2,
    x1*x2*x1*x2*x1*x2*x1*x2
>
gap> PrintTo( "dihedral", last );
gap> ## The following is equivalent to: 
gap> ##     NilpotentQuotient( : input_file := "dihedral" );
gap> NilpotentQuotient( "dihedral" );
Pcp-group with orders [ 2, 2, 2 ]
gap> Exec( "rm dihedral" );
gap> F := FreeGroup(3);
<free group on the generators [ f1, f2, f3 ]>
gap> H := F / [ LeftNormedComm( [F.2,F.1,F.1] ),                               
>               LeftNormedComm( [F.2,F.1,F.2] ), F.3^7 ];
<fp group on the generators [ f1, f2, f3 ]>
gap> str := NqStringFpGroup( H, [F.3] );                                  
"< x1, x2; x3 |\n    x1^-1*x2^-1*x1*x2*x1^-1*x2^-1*x1^-1*x2*x1^2,\n    x1^-1*x\
2^-1*x1*x2^-1*x1^-1*x2*x1*x2,\n    x3^7\n>\n"
gap> NilpotentQuotient( : input_string := str );
Pcp-group with orders [ 7, 7, 7 ]
]]>
     </Example>
     </Description>
     </ManSection>
     <ManSection>
     <Func Name="NqStringExpTrees" Arg="fp-group [,idgens]" />
     <Description>
     The function takes a finitely presented group <F>fp-group</F>
     given in terms of expression trees and
     returns a string in the input format of the ANU NQ.  If the list
     <F>idgens</F> is present, then it must contain a sublist of the
     generators of the presentation. The generators in <F>idgens</F>
     are treated as identical generators. 
     <Example>
<![CDATA[
gap> x := ExpressionTrees( 2 );
[ x1, x2 ]
gap> rels := [x[1]^2, x[2]^2, (x[1]*x[2])^5]; 
[ x1^2, x2^2, (x1*x2)^5 ]
gap> NqStringExpTrees( rec( generators := x, relations := rels ) );
"< x1, x2 |\n    x1^2,\n    x2^2,\n    (x1*x2)^5\n>\n"
gap> Print( last );         
< x1, x2 |
    x1^2,
    x2^2,
    (x1*x2)^5
>
gap> x := ExpressionTrees( 3 );
[ x1, x2, x3 ]
gap> rels := [LeftNormedComm( [x[2],x[1],x[1]] ),                              
>             LeftNormedComm( [x[2],x[1],x[2]] ), x[3]^7 ];
[ Comm( x2, x1, x1 ), Comm( x2, x1, x2 ), x3^7 ]
gap> NqStringExpTrees( rec( generators := x, relations := rels ) );
"< x1, x2, x3 |\n    [ x2, x1, x1 ],\n    [ x2, x1, x2 ],\n    x3^7\n>\n"
gap> Print( last );
< x1, x2, x3 |
    [ x2, x1, x1 ],
    [ x2, x1, x2 ],
    x3^7
>
]]>
     </Example>
     </Description>
     </ManSection>

     <ManSection>
     <Func Name="NqElementaryDivisors" Arg="int-mat" />
     <Description>
     The function <Ref BookName="ref" Oper="ElementaryDivisorsMat"/>
     only returns the non-zero elementary divisors of an integer
     matrix.  This function computes the elementary divisors of
     <F>int-mat</F> and adds the appropriate number of zeroes in order
     to make it easier to recognize the isomorphism type of the
     abelian group presented by the integer matrix.  At the same time
     ones are stripped from the list of elementary divisors.
     </Description>
     </ManSection>
  </Section>

  <Section><Heading>Global Variables</Heading>
  <ManSection>
  <Var Name="NqRuntime"/>  
     <Description>
     This variable contains the number of milliseconds of runtime of
     the last call of ANU NQ.
     <Log>
gap> NilpotentEngelQuotient( FreeGroup(2), 5 );
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 10, 
  0, 0, 30, 0, 3, 3, 10, 2, 0, 6, 0, 0, 30, 2, 0, 9, 3, 5, 2, 6, 2, 10, 5, 5, 
  2, 0, 3, 3, 3, 3, 3, 5, 5, 3, 3 ]
gap> NqRuntime;
18200
     </Log>
     </Description>
  </ManSection>
  <ManSection>
  <Var Name="NqDefaultOptions"/>  
     <Description>
     This variable contains a list of strings which are the standard
     command line options passed to the ANU NQ in each call.
     Modifying this variable can be used to pass additional options to
     the ANU NQ.
     <Example>
gap> NqDefaultOptions;
[ "-g", "-p", "-C", "-s" ]
     </Example>
     The option <Arg>-g</Arg> causes the ANU NQ to produce output in
     &GAP;-format.  The option <Arg>-p</Arg> prevents the ANU NQ from
     listing the pc-presentation of the nilpotent quotient at the end
     of the calculation.  The option <Arg>-C</Arg> invokes the
     combinatorial collector.  The option <Arg>-s</Arg> is effective
     only in conjunction with options for computing with Engel
     identities and instructs the ANU NQ to use only semigroup words
     in the generators as instances of an Engel law.
     </Description>
  </ManSection>
  <ManSection>
  <Var Name="NqGlobalVariables"/>  
     <Description>
     This variable contains a list of strings with the names of the
     global variables that are used in the output stream of the ANU
     NQ.  While the output stream is read, these global variables are
     assigned new values.  To avoid overwriting these variables in
     case they contain values, their contents is saved before reading
     the output stream and restored afterwards.
     </Description>
  </ManSection>

  </Section>

  <Section Label="DiagnosticOutput"><Heading>Diagnostic Output</Heading>
  While the standalone program is running it can be asked to display
  progress information.  This is done by setting the info class
  <C>InfoNQ</C> to <M>1</M> via the function 
  <Ref BookName="ref" Oper="SetInfoLevel" />.
<Log>
gap> NilpotentQuotient(FreeGroup(2),5);
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
gap> SetInfoLevel( InfoNQ, 1 );
gap> NilpotentQuotient(FreeGroup(2),5);
#I  Class 1: 2 generators with relative orders  0 0
#I  Class 2: 1 generators with relative orders: 0
#I  Class 3: 2 generators with relative orders: 0 0
#I  Class 4: 3 generators with relative orders: 0 0 0
#I  Class 5: 6 generators with relative orders: 0 0 0 0 0 0
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
gap> SetInfoLevel( InfoNQ, 0 );
</Log>
  </Section>
  </Chapter>

  <Chapter><Heading>Examples</Heading>
  <Section><Heading>Right Engel elements</Heading>
  An old problem in the context of Engel elements is the question:  Is
  a right <M>n</M>-Engel element left <M>n</M>-Engel?  It is known
  that the answer is no.  For details about the history of the
  problem, see <Cite Key="NewmanNickel94"/>.  In this paper the
  authors show that for <M>n>4</M> there are nilpotent groups with
  right <M>n</M>-Engel elements no power of which is a left
  <M>n</M>-Engel element.  The insight was based on computations with
  the ANU NQ which we reproduce here.  We also show the cases
  <M>5>n</M>.
  <Example>
gap> RequirePackage( "nq" );
true
gap> ##  SetInfoLevel( InfoNQ, 1 );
gap> ##
gap> ##  setup calculation
gap> ##
gap> et := ExpressionTrees( "a", "b", "x" );
[ a, b, x ]
gap> a := et[1];; b := et[2];; x := et[3];;
gap> 
gap> ##
gap> ##  define the group for n = 2,3,4,5
gap> ##
gap> 
gap> rengel := LeftNormedComm( [a,x,x] );
Comm( a, x, x )
gap> G := rec( generators := et, relations := [rengel] );
rec( generators := [ a, b, x ], relations := [ Comm( a, x, x ) ] )
gap> ## The following is equivalent to:
gap> ##   NilpotentQuotient( : input_string := NqStringExpTrees( G, [x] ) )
gap> H := NilpotentQuotient( G, [x] );
Pcp-group with orders [ 0, 0, 0 ]
gap> LeftNormedComm( [ H.2,H.1,H.1 ] );
id
gap> LeftNormedComm( [ H.1,H.2,H.2 ] );
id
</Example>
This shows that each right 2-Engel element in a finitely generated
nilpotent group is a left 2-Engel element.  Note that the group above
is the largest nilpotent group generated by two elements, one of which
is right 2-Engel.  Every nilpotent group generated by an arbitrary
element and a right 2-Engel element is a homomorphic image of the
group <M>H</M>.
<Example>
gap> rengel := LeftNormedComm( [a,x,x,x] );
Comm( a, x, x, x )
gap> G := rec( generators := et, relations := [rengel] );
rec( generators := [ a, b, x ], relations := [ Comm( a, x, x, x ) ] )
gap> H := NilpotentQuotient( G, [x] );
Pcp-group with orders [ 0, 0, 0, 0, 0, 4, 2, 2 ]
gap> LeftNormedComm( [ H.1,H.2,H.2,H.2 ] );
id
gap> h := LeftNormedComm( [ H.2,H.1,H.1,H.1 ] );
g6^2*g7*g8
gap> Order( h );
4
</Example>
The element <M>h</M> has order <M>4</M>.  In a nilpotent group without
<M>2</M>-torsion a right 3-Engel element is left 3-Engel.
<Example>
gap> rengel := LeftNormedComm( [a,x,x,x,x] );
Comm( a, x, x, x, x )
gap> G := rec( generators := et, relations := [rengel] );
rec( generators := [ a, b, x ], relations := [ Comm( a, x, x, x, x ) ] )
gap> H := NilpotentQuotient( G, [x] );
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 12, 0, 5, 10, 2, 0, 30, 
  5, 2, 5, 5, 5, 5 ]
gap> LeftNormedComm( [ H.1,H.2,H.2,H.2,H.2 ] );
id
gap> h := LeftNormedComm( [ H.2,H.1,H.1,H.1,H.1 ] );
g9*g10^2*g11^10*g12^5*g13^2*g14^8*g15*g16^6*g17^10*g18*g20^4*g21^4*g22^2*g23^2
gap> Order( h );
60
</Example>
The previous calculation shows that in a nilpotent group without
<M>2,3,5</M>-torsion a right 4-Engel element is left 4-Engel. 
<Example>
gap> rengel := LeftNormedComm( [a,x,x,x,x,x] );
Comm( a, x, x, x, x, x )
gap> G := rec( generators := et, relations := [rengel] );
rec( generators := [ a, b, x ], relations := [ Comm( a, x, x, x, x, x ) ] )
gap> H := NilpotentQuotient( G, [x], 9 );
Pcp-group with orders [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 30, 
  0, 0, 30, 0, 3, 6, 0, 0, 10, 30, 0, 0, 0, 0, 30, 30, 0, 0, 3, 6, 5, 2, 0, 
  2, 408, 2, 0, 0, 0, 10, 10, 30, 10, 0, 0, 0, 3, 3, 3, 2, 204, 6, 6, 0, 10, 
  10, 10, 2, 2, 2, 0, 300, 0, 0, 18 ]
gap> LeftNormedComm( [ H.1,H.2,H.2,H.2,H.2,H.2 ] );
id
gap> h := LeftNormedComm( [ H.2,H.1,H.1,H.1,H.1,H.1 ] );;
gap> Order( h );
infinity
</Example>
Finally, we see that in a torsion-free group a right 5-Engel element
need not be a left 5-Engel element.
  </Section>
  </Chapter>

  <Chapter>
  <Heading>Installation of the Package</Heading> 

  Installation of the package requires the GNU multiple precision
  library (GNU MP <Cite Key="GNUMP"/>).  If this library is not
  available on your system, it has to be installed first.  A copy of
  GNU MP can be obtained via anonymous ftp from many file servers
  around the world, for example: <URL>www.swox.com/gmp/</URL>.

  Installation of the ANU NQ is done in two steps.  First the
  configure script is run:
  <Listing Type="Installation"> ./configure  </Listing>
  Among other things it will check whether it succeeds in locating
  the GNU MP library and the corresponding include files.  If
  configure reports no problems, the next step is to start the
  compilation:
  <Listing Type="Installation"> make </Listing>
  If the configure script told you that it could not find the GNU MP
  include files or the GNU MP libraries, you have to run make with
  additional parameters.  For example, if you have installed GNU MP
  yourself in your home directory, you would type something like the
  following
  <Listing Type="Installation"> 
  make GNU_MP_INC=/home/me/gmp-4.1.1 GNU_MP_LIB=/home/me/gmp-4.1.1/.libs
  </Listing>

  <P/> A compiled version of the program named `nq' is then placed
  into the directory `bin/&tlt;complicated name&tgt;'.  The
  &tlt;complicated name&tgt; component encodes the operating system
  and the compiler used.  This allows you to compile NQ on several
  architectures sharing the same files system.

  <P/>
  If there are any warnings or even fatal error messages during the
  compilation process, please send a copy to the address at the end of
  this document together with information about your operating system,
  the compiler you used and any changes you might have made to the
  source code.  I will have a look at your problems and try to fix
  them.
 
  <P/> After the compilation is finished you can check if the ANU NQ
  is running properly on your system.  Simply type

  <Listing Type="Installation"> make test </Listing>
  
  The file runs some computations and compares their output with the
  output files in the directory `examples'.  If testNq reports any
  errors, please follow the instruction that testNq prints out.

  <P/>The installation is completed by compiling the manual of the
  package.  This is done from within <Package>GAP</Package>.

  <Listing Type="Installation">
gap> NqBuildManual();
Composing XML document . . .
Parsing XML document . . .
Checking XML structure . . .
LaTeX version and calling latex and pdflatex:
    writing LaTeX file, 3 x latex, bibtex and makeindex, 2 x pdflatex, dvips
Text version . . .
#I  first run, collecting cross references, index, toc, bib and so on . . .
#I  table of contents complete.
#I  producing the index . . .
#I  reading bibliography data files . . . 
#I  writing bibliography . . .
#I  second run through document . . .
Writing manual.six file . . .
And finally the HTML version . . .
#I  first run, collecting cross references, index, toc, bib and so on . . .
#I  table of contents complete.
#I  producing the index . . .
#I  reading bibliography data files . . . 
#I  writing bibliography . . .
#I  second run through document . . .
gap> ?NilpotentQuotient
Help: several entries match this topic - type ?2 to get match [2]

[1] ANU NQ: NilpotentQuotient
[2] ANU NQ: NilpotentQuotient
[3] Reference: NilpotentQuotientOfFpLieAlgebra
gap>
  </Listing>
  </Chapter>

  </Body>

  <Bibliography Databases="nq" />
  <TheIndex/>                                               
</Book>
