<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="mathml.xsl"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"
       "http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd" [
       <!ENTITY mathml "http://www.w3.org/1998/Math/MathML">
       ] >

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<link rel="stylesheet" type="text/css" href="mathml.css" />
<title>GAP (edim) - Chapter 1: The EDIM-Package</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<meta name="generator" content="GAPDoc2HTML" />
<link rel="stylesheet" type="text/css" href="manual.css" />
</head>
<body>


<div class="pcenter"><table class="chlink"><tr><td class="chlink1">Goto Chapter: </td><td><a href="chap0_mml.xml">Top</a></td><td><a href="chap1_mml.xml">1</a></td><td><a href="chapBib_mml.xml">Bib</a></td><td><a href="chapInd_mml.xml">Ind</a></td></tr></table><br /></div>
<p><a id="s0ss0" name="s0ss0"></a></p>

<h3>1. The <strong class="pkg">EDIM</strong>-Package</h3>

<p><em>(Elementary Divisors and Integer Matrices, by Frank Lübeck)</em></p>

<p>This chapter describes the functions defined in the <strong class="pkg">GAP</strong>4 package <strong class="pkg">EDIM</strong>. The main functions implement variants of an algorithm for computing for a given prime <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math> the <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math>-parts of the elementary divisors of an integer matrix. These algorithms use a <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math>-adic method and are described by the author in <a href="chapBib_mml.xml#biBL98">[L02]</a> (see <code class="func">ElementaryDivisorsPPartRk</code> (<a href="chap1_mml.xml#s2ss1"><b>1.2-1</b></a>)).</p>

<p>These functions were already applied to integer matrices of dimension greater than <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mn>11000</mn></mrow></math> (which had many non-trivial elementary divisors which were products of small primes).</p>

<p>Furthermore there are functions for finding the biggest elementary divisor of an invertible integer matrix and the inverse of a rational invertible matrix (see <code class="func">ExponentSquareIntMatFullRank</code> (<a href="chap1_mml.xml#s3ss3"><b>1.3-3</b></a>) and <code class="func">InverseRatMat</code> (<a href="chap1_mml.xml#s3ss1"><b>1.3-1</b></a>)). These algorithms use <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math>-adic approximations, explained in <a href="chap1_mml.xml#s7ss0"><b>1.7</b></a>.</p>

<p>Finally we distribute implementations of some other algorithms for finding elementary divisors or normal forms of integer matrices: A <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math>-modular algorithm by Havas and Sterling from <a href="chapBib_mml.xml#biBHS79">[HS79]</a> (see <code class="func">ElementaryDivisorsPPartHavasSterling</code> (<a href="chap1_mml.xml#s2ss2"><b>1.2-2</b></a>)) and LLL-based algorithms for extended greatest common divisors of integers (see <code class="func">GcdexIntLLL</code> (<a href="chap1_mml.xml#s5ss1"><b>1.5-1</b></a>)) and for Hermite normal forms of integer matrices with (very nice) transforming matrices (see <code class="func">HermiteIntMatLLL</code> (<a href="chap1_mml.xml#s5ss2"><b>1.5-2</b></a>)).</p>

<p>By default the <strong class="pkg">EDIM</strong> is automatically loaded by <strong class="pkg">GAP</strong> when it is installed. If the automatic loading is disabled in your installation you must load the package with <code class="code">RequirePackage("edim");</code> before its functions become available.</p>

<p>Please, send me an e-mail (<a href="mailto:Frank.Luebeck@Math.RWTH-Aachen.De">Frank.Luebeck@Math.RWTH-Aachen.De</a>) if you have any questions, remarks, suggestions, etc. concerning this mini-package. Also, I would like to hear about applications of this package.</p>

<p>Frank Lübeck</p>

<p><a id="s1ss0" name="s1ss0"></a></p>

<h4>1.1 Installation of the <strong class="pkg">EDIM</strong>-package</h4>

<p>To install this package (after extracting the packages archive file to the GAP home directory) go to the directory <code class="file">pkg/edim</code> (the directory containing this README file) and call</p>

<p><code class="code">/bin/sh ./configure [path]</code></p>

<p>where <code class="code">path</code> is a path to the main <strong class="pkg">GAP</strong> root directory (if not given, the default <code class="file">../..</code> is assumed).</p>

<p>Afterwards call <code class="code">make</code> to compile a binary file.</p>

<p>If you installed GAP on several architectures, you must execute this <code class="code">configure/make</code> step on each of the architectures immediately after configuring GAP itself on this architecture. The package will also work without this step but then the kernel function <code class="func">ElementaryDivisorsPPartRkExpSmall</code> (<a href="chap1_mml.xml#s2ss1"><b>1.2-1</b></a>) (see <code class="func">ElementaryDivisorsPPartRkExpSmall</code> (<a href="chap1_mml.xml#s2ss1"><b>1.2-1</b></a>)) will not be available.</p>

<p>The <code class="file">INSTALL</code> in the main package directory also explains how to compile the kernel function into a static module. You can also run a test of the installation by typing <code class="code">make test</code>.</p>

<p><a id="s1ss1" name="s1ss1"></a></p>

<h5>1.1-1 InfoEDIM</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; InfoEDIM</code></td><td class="tdright">( info class )</td></tr></table></div>
<p>This is an <code class="keyw">Info</code> class for the <strong class="pkg">EDIM</strong>-package. By <code class="code">SetInfoLevel(InfoEDIM, 1);</code> you can switch on the printing of some information during the computations of certain <strong class="pkg">EDIM</strong>-functions.</p>

<p><a id="s2ss0" name="s2ss0"></a></p>

<h4>1.2 
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow><mi>p</mi></mrow></math>-Parts of Elementary Divisors</h4>

<p>Here we explain the main functions of the package.</p>

<p><a id="s2ss1" name="s2ss1"></a></p>

<h5>1.2-1 ElementaryDivisorsPPartRk</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; ElementaryDivisorsPPartRk</code>( <var>A, p[, rk]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; ElementaryDivisorsPPartRkI</code>( <var>A, p, rk</var> )</td><td class="tdright">( function )</td></tr></table></div>
<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; ElementaryDivisorsPPartRkII</code>( <var>A, p, rk</var> )</td><td class="tdright">( function )</td></tr></table></div>
<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; ElementaryDivisorsPPartRkExp</code>( <var>A, p, rk, exp</var> )</td><td class="tdright">( function )</td></tr></table></div>
<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; ElementaryDivisorsPPartRkExpSmall</code>( <var>A, p, rk, exp, il</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>These functions return a list <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo stretchy="false">[</mo> <msub><mi>m</mi><mrow><mn>1</mn></mrow> </msub> <mo>,</mo> <msub><mi>m</mi><mrow><mn>2</mn></mrow> </msub> <mo>,</mo><mo>&mldr;</mo><mo>,</mo> <msub><mi>m</mi><mrow><mi>r</mi></mrow> </msub> <mo stretchy="false">]</mo></mrow></math> where <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>m</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> is the number of nonzero elementary divisors of <var>A</var> divisible by <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>p</mi></var><msup><mi></mi><mrow><mi>i</mi></mrow></msup> </mrow></math> (see <code class="func">ElementaryDivisorsMat</code> (<a href="../../../doc/htm/ref/CHAP023.htm#SECT008"><b>Reference: ElementaryDivisorsMat</b></a>) for a definition of the elementary divisors).</p>

<p>The algorithms for these functions are described in <a href="chapBib_mml.xml#biBL98">[L02]</a>.</p>

<p><var>A</var> must be a matrix with integer entries, <var>p</var> a prime, and <var>rk</var> the rank of <var>A</var> (as rational matrix). In the first version of the command <var>rk</var> is computed, if it is not given.</p>

<p>The first version of the command delegates its job to the fourth version by trying growing values for <var>exp</var>, see below.</p>

<p>The second and third versions implement the main algorithm described in <a href="chapBib_mml.xml#biBL98">[L02]</a> and a variation. Here <code class="func">ElementaryDivisorsPPartRkII</code> has a bit more overhead, but can be advantageous because the intermediate entries during the computation can be much smaller.</p>

<p>In the fourth form <var>exp</var> must be an upper bound for the highest power of <var>p</var> appearing in an elementary divisor of <var>A</var>. This information allows reduction of matrix entries modulo <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>p</mi></var><msup><mi></mi><mrow><var><mi>exp</mi></var></mrow></msup> </mrow></math> during the computation.</p>

<p>If <var>exp</var> is too small or the given <var>rk</var> is not correct the function returns `fail'.</p>

<p>As long as <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>p</mi></var><msup><mi></mi><mrow><var><mi>exp</mi></var></mrow></msup> </mrow></math> is smaller than <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msup><mn>2</mn><mrow><mn>28</mn></mrow> </msup> </mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>p</mi></var><msup><mi></mi><mrow><var><mi>exp</mi></var><mo>+</mo><mn>2</mn></mrow></msup> </mrow></math> is smaller than <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msup><mn>2</mn><mrow><mn>31</mn></mrow> </msup> </mrow></math> we use internally a kernel function which can also be used directly in the fifth form of the command. There <var>il</var> can be <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mn>0</mn></mrow></math> or <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mn>1</mn></mrow></math> where in the second case some information is printed during the computation.</p>

<p>This last form of the function was already succesfully applied to dense matrices of rank up to <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mn>11000</mn></mrow></math>.</p>

<p>Note that you have to compile a file (see <a href="chap1_mml.xml#s1ss0"><b>1.1</b></a>) while installing this package, if you want to have this kernel function available.</p>


<table class="example">
<tr><td><pre>

gap&gt; ReadPkg("edim",  "tst/mat");
Reading 242x242 integer matrix 'mat' and its elementary divisors 'eldiv'.
gap&gt; ElementaryDivisorsPPartRkI(mat, 2, 242); time; # mat has full rank
[ 94, 78, 69, 57, 23, 23, 9, 2, 2, 0 ]
9170
gap&gt; ElementaryDivisorsPPartRkExpSmall(mat, 2, 242, 10, 0); time;
[ 94, 78, 69, 57, 23, 23, 9, 2, 2, 0 ]
560

</pre></td></tr></table>

<p><a id="s2ss2" name="s2ss2"></a></p>

<h5>1.2-2 ElementaryDivisorsPPartHavasSterling</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; ElementaryDivisorsPPartHavasSterling</code>( <var>A, p, d</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>For an integer matrix <var>A</var> and a prime <var>p</var> this function returns a list <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo stretchy="false">[</mo> <msub><mi>m</mi><mrow><mn>1</mn></mrow> </msub> <mo>,</mo> <msub><mi>m</mi><mrow><mn>2</mn></mrow> </msub> <mo>,</mo><mo>&mldr;</mo><mo>,</mo> <msub><mi>m</mi><mrow><mi>r</mi></mrow> </msub> <mo stretchy="false">]</mo></mrow></math> where <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>m</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> is the number of nonzero elementary divisors of <var>A</var> divisible by <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>p</mi></var><msup><mi></mi><mrow><mi>i</mi></mrow></msup> </mrow></math>.</p>

<p>An upper bound <var>d</var> for the highest power of <var>p</var> appearing in an elementary divisor of <var>A</var> must be given. Smaller <var>d</var> improve the performance of the algorithm considerably.</p>

<p>This is an implementation of the modular algorithm described in <a href="chapBib_mml.xml#biBHS79">[HS79]</a>.</p>

<p>We added a slight improvement: we divide the considered submatrices by the <var>p</var>-part of the greatest common divisor of all entries (and lower the <var>d</var> appropriately). This reduces the size of the entries and often shortens the pivot search.</p>


<table class="example">
<tr><td><pre>

gap&gt; ReadPkg("edim",  "tst/mat");
Reading 242x242 integer matrix 'mat' and its elementary divisors 'eldiv'.
gap&gt; ElementaryDivisorsPPartHavasSterling(mat, 2, 10); time;
[ 94, 78, 69, 57, 23, 23, 9, 2, 2 ]
25390

</pre></td></tr></table>

<p><a id="s3ss0" name="s3ss0"></a></p>

<h4>1.3 Inverse of Rational Matrices</h4>

<p><a id="s3ss1" name="s3ss1"></a></p>

<h5>1.3-1 InverseRatMat</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; InverseRatMat</code>( <var>A[, p]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns the inverse of an invertible matrix over the rational numbers.</p>

<p>It first computes the inverse modulo some prime <var>p</var>, computes from this a <var>p</var>-adic approximation to the inverse and finally constructs the rational entries from their <var>p</var>-adic approximations. See section <a href="chap1_mml.xml#s7ss0"><b>1.7</b></a> for more details.</p>

<p>This seems to be better than <strong class="pkg">GAP</strong>'s standard Gauß algorithm (<code class="code">A\^{}-1</code>) already for small matrices. (Try, e.g., <code class="code">RandomMat(20,20,[-10000..10000])</code> or <code class="code">RandomMat(100,100)</code>.)</p>

<p>The optional argument <var>p</var> should be a prime such that <var>A</var> modulo <var>p</var> is invertible (default is <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>p</mi></var><mo>=</mo><mn>251</mn></mrow></math>). If <var>A</var> is not invertible modulo <var>p</var> then <var>p</var> is automatically replaced by the next prime.</p>

<p><a id="s3ss2" name="s3ss2"></a></p>

<h5>1.3-2 RationalSolutionIntMat</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; RationalSolutionIntMat</code>( <var>A, v[, p[, invA]]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns the solution <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>x</mi></mrow></math> of the system of linear equations <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>x</mi><var><mi>A</mi></var><mo>=</mo><var><mi>v</mi></var></mrow></math>.</p>

<p>Here, <var>A</var> must be a matrix with integer entries which is invertible over the rationals and <var>v</var> must be a vector with integer entries of the appropriate length.</p>

<p>The optional arguments are a prime <var>p</var> such that <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>A</mi></var><mo>mod</mo><mi>p</mi></mrow></math> is invertible (if not given, <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi><mo>=</mo><mn>251</mn></mrow></math> is assumed) and the inverse <var>invA</var> of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>A</mi></var><mo>mod</mo><mi>p</mi></mrow></math>.</p>

<p>The solution is computed via <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math>-adic approximation as explained in <a href="chap1_mml.xml#s7ss0"><b>1.7</b></a>.</p>

<p><a id="s3ss3" name="s3ss3"></a></p>

<h5>1.3-3 ExponentSquareIntMatFullRank</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; ExponentSquareIntMatFullRank</code>( <var>A[, p[, nr]]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns the biggest elementary divisor of a square integer matrix <var>A</var> of full rank.</p>

<p>For such a matrix <var>A</var> the least common multiple of the denominators of all entries of the inverse matrix <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>A</mi></var><msup><mi></mi><mrow><mo>-</mo><mn>1</mn></mrow></msup> </mrow></math> is exactly the biggest elementary divisor of <var>A</var>.</p>

<p>This function is implemented by a slight modification of <code class="func">InverseRatMat</code> (<a href="chap1_mml.xml#s3ss1"><b>1.3-1</b></a>). The third argument <var>nr</var> tells the function to return the least common multiple of the first <var>nr</var> rows of the rational inverse matrix only. Very often the function will already return the biggest elementary divisor with <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>nr</mi></var><mo>=</mo><mn>2</mn></mrow></math> or <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mn>3</mn></mrow></math> (and the command without this argument would spend most time in checking, that this is correct).</p>

<p>The optional argument <var>p</var> should be a prime such that <var>A</var> modulo <var>p</var> is invertible (default is <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>p</mi></var><mo>=</mo><mn>251</mn></mrow></math>). If <var>A</var> is not invertible modulo <var>p</var> then <var>p</var> is automatically replaced by the next prime.</p>


<table class="example">
<tr><td><pre>

gap&gt; ReadPkg("edim",  "tst/mat");
Reading 242x242 integer matrix 'mat' and its elementary divisors 'eldiv'.
gap&gt; inv := InverseRatMat(mat);; time;                      
14960
gap&gt; ExponentSquareIntMatFullRank(mat, 101, 3); # same as without the `3'
115200

</pre></td></tr></table>

<p><a id="s4ss0" name="s4ss0"></a></p>

<h4>1.4 All Elementary Divisors Using p-adic Method</h4>

<p>In the following two functions we put things together. In particular we handle the prime parts of the elementary divisors efficiently for primes appearing with low powers in the highest elementary divisor respectively determinant divisor.</p>

<p><a id="s4ss1" name="s4ss1"></a></p>

<h5>1.4-1 ElementaryDivisorsSquareIntMatFullRank</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; ElementaryDivisorsSquareIntMatFullRank</code>( <var>A</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns a list of nonzero elementary divisors of an integer matrix <var>A</var>.</p>

<p>Here we start with computing the biggest elementary divisor via <code class="func">ExponentSquareIntMatFullRank</code> (<a href="chap1_mml.xml#s3ss3"><b>1.3-3</b></a>). If it runs into a problem because <var>A</var> is singular modulo a choosen prime (it starts by default with 251) then the prime is automatically replaced by the next one.</p>

<p>The rest is done using <code class="func">ElementaryDivisorsPPartRkExp</code> (<a href="chap1_mml.xml#s2ss1"><b>1.2-1</b></a>) and <code class="func">RankMod</code> (<a href="chap1_mml.xml#s6ss5"><b>1.6-5</b></a>).</p>

<p>The function fails if the biggest elementary divisor cannot be completely factored and the non-factored part is not a divisor of the biggest elementary divisor only.</p>

<p>Note that this function may for many matrices not be the best choice for computing all elementary divisors. You may first try the standard <strong class="pkg">GAP</strong> library routines for Smith normal form instead of this function. Nevertheless remember <code class="func">ElementaryDivisorsSquareIntMatFullRank</code> for hard and big examples. It is particularly good when the largest elementary divisor is a very small factor of the determinant.</p>


<table class="example">
<tr><td><pre>

gap&gt; Collected(ElementaryDivisorsSquareIntMatFullRank(mat));      
[ [ 1, 49 ], [ 3, 99 ], [ 6, 7 ], [ 30, 9 ], [ 60, 9 ], [ 120, 2 ], 
  [ 360, 10 ], [ 720, 22 ], [ 3600, 12 ], [ 14400, 14 ], [ 28800, 7 ], 
  [ 115200, 2 ] ]
gap&gt; time;
10180
gap&gt; last2 = Collected(DiagonalOfMat(NormalFormIntMat(mat, 1).normal));
true
gap&gt; time;
188490

</pre></td></tr></table>

<p><a id="s4ss2" name="s4ss2"></a></p>

<h5>1.4-2 ElementaryDivisorsIntMatDeterminant</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; ElementaryDivisorsIntMatDeterminant</code>( <var>A, det[, rk]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns a list of nonzero elementary divisors of an integer matrix <var>A</var>.</p>

<p>Here <var>det</var> must be an integer which is a multiple of the biggest determinant divisor of <var>A</var>. If the matrix does not have full rank then its rank <var>rk</var> must be given, too.</p>

<p>The argument <var>det</var> can be given in the form of <code class="code">Collected(FactorsInt(<var>det</var>))</code>.</p>

<p>This function handles prime divisors of <var>det</var> with multiplicity smaller than 4 specially, for the other prime divisors <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math> it delegates to <code class="func">ElementaryDivisorsPPartRkExp</code> (<a href="chap1_mml.xml#s2ss1"><b>1.2-1</b></a>) where the <var>exp</var> argument is the multiplicity of the <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math> in <var>det</var>. (Note that this is not very good when <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math> has actually a much smaller multiplicity in the largest elementary divisor.)</p>


<table class="example">
<tr><td><pre>

gap&gt; ReadPkg("edim",  "tst/mat");
Reading 242x242 integer matrix 'mat' and its elementary divisors 'eldiv'.
gap&gt; # not so good:
gap&gt; ElementaryDivisorsIntMatDeterminant(mat,Product(eldiv)) = 
Concatenation([1..49]*0+1, eldiv); time;
true
185770

</pre></td></tr></table>

<p><a id="s5ss0" name="s5ss0"></a></p>

<h4>1.5 Gcd and Normal Forms Using LLL</h4>

<p>The <strong class="pkg">EDIM</strong>-mini package also contains implementations of an extended Gcd-algorithm for integers and a Hermite and Smith normal form algorithm for integer matrices using LLL-techiques. They are well described in the paper <a href="chapBib_mml.xml#biBHMM98">[HMM98]</a> by Havas, Majewski and Matthews.</p>

<p>They are particularly useful if one wants to have the normal forms together with transforming matrices. These transforming matrices have spectacularly nice (i.e., "small") entries in cases of input matrices which are non-square or not of full rank (otherwise the transformation to the Hermite normal form is unique).</p>

<p>In detail:</p>

<p><a id="s5ss1" name="s5ss1"></a></p>

<h5>1.5-1 GcdexIntLLL</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; GcdexIntLLL</code>( <var>n1, n2, ...</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns for integers <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>n</mi><mn>1</mn></var><mo>,</mo><var><mi>n</mi><mn>2</mn></var><mo>,</mo><mo>&mldr;</mo></mrow></math> a list <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo stretchy="false">[</mo><mi>g</mi><mo>,</mo><mo stretchy="false">[</mo> <msub><mi>c</mi><mrow><mn>1</mn></mrow> </msub> <mo>,</mo> <msub><mi>c</mi><mrow><mn>2</mn></mrow> </msub> <mo>,</mo><mo>&mldr;</mo><mo stretchy="false">]</mo><mo stretchy="false">]</mo></mrow></math>, where <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>g</mi><mo>=</mo> <msub><mi>c</mi><mrow><mn>1</mn></mrow> </msub> <var><mi>n</mi><mn>1</mn></var><mo>+</mo> <msub><mi>c</mi><mrow><mn>2</mn></mrow> </msub> <var><mi>n</mi><mn>2</mn></var><mo>+</mo><mo>&mldr;</mo></mrow></math> is the greatest common divisor of the <var>ni</var>. Here all the <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>c</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> are usually very small.</p>


<table class="example">
<tr><td><pre>

gap&gt; GcdexIntLLL( 517, 244, -304, -872, -286, 854, 866, 224, -765, -38);
[ 1, [ 0, 0, 0, 0, 1, 0, 1, 1, 1, 1 ] ]

</pre></td></tr></table>

<p><a id="s5ss2" name="s5ss2"></a></p>

<h5>1.5-2 HermiteIntMatLLL</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; HermiteIntMatLLL</code>( <var>A</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This returns the Hermite normal form of an integer matrix <var>A</var> and uses the LLL-algorithm to avoid entry explosion.</p>

<p><a id="s5ss3" name="s5ss3"></a></p>

<h5>1.5-3 HermiteIntMatLLLTrans</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; HermiteIntMatLLLTrans</code>( <var>A</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns a pair of matrices <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo stretchy="false">[</mo><mi>H</mi><mo>,</mo><mi>L</mi><mo stretchy="false">]</mo></mrow></math> where <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>H</mi><mo>=</mo><mi>L</mi><var><mi>A</mi></var></mrow></math> is the Hermite normal form of an integer matrix <var>A</var>. The transforming matrix <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>L</mi></mrow></math> can have surprisingly small entries.</p>


<table class="example">
<tr><td><pre>

gap&gt; ReadPkg("edim",  "tst/mat2");
Reading 34x34 integer matrix 'mat2' and its elementary divisors 'eldiv2'.
gap&gt; tr := HermiteIntMatLLLTrans(mat2);; Maximum(List(Flat(tr[2]), AbsInt));
606
gap&gt; tr[2]*mat2 = tr[1];                                                
true

</pre></td></tr></table>

<p><a id="s5ss4" name="s5ss4"></a></p>

<h5>1.5-4 SmithIntMatLLL</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; SmithIntMatLLL</code>( <var>A</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns the Smith normal form of an integer matrix <var>A</var> using the LLL-algorithm to avoid entry explosion.</p>

<p><a id="s5ss5" name="s5ss5"></a></p>

<h5>1.5-5 SmithIntMatLLLTrans</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; SmithIntMatLLLTrans</code>( <var>A</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo stretchy="false">[</mo><mi>S</mi><mo>,</mo><mi>L</mi><mo>,</mo><mi>R</mi><mo stretchy="false">]</mo></mrow></math> where <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>S</mi><mo>=</mo><mi>L</mi><var><mi>A</mi></var><mi>R</mi></mrow></math> is the Smith normal form of an integer matrix <var>A</var>.</p>

<p>We apply the algorithm for Hermite normal form several times to get the Smith normal form, that is not in the paper <a href="chapBib_mml.xml#biBHMM98">[HMM98]</a>. The transforming matrices need not be as nice as for the Hermite normal form.</p>


<table class="example">
<tr><td><pre>

gap&gt; ReadPkg("edim",  "tst/mat2");
Reading 34x34 integer matrix 'mat2' and its elementary divisors 'eldiv2'.
gap&gt; tr := SmithIntMatLLLTrans(mat2);;
gap&gt; tr[2] * mat2 * tr[3] = tr[1];    
true

</pre></td></tr></table>

<p><a id="s6ss0" name="s6ss0"></a></p>

<h4>1.6 Utility Functions from the <strong class="pkg">EDIM</strong>-package</h4>

<p><a id="s6ss1" name="s6ss1"></a></p>

<h5>1.6-1 RatNumberFromModular</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; RatNumberFromModular</code>( <var>n, k, l, x</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>r</mi><mo>/</mo><mi>s</mi><mo>=</mo><var><mi>x</mi></var><mo>mod</mo><var><mi>n</mi></var></mrow></math>, if it exists. More precisely:</p>

<p><var>n</var>, <var>k</var>, <var>l</var> must be positive integers with <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mn>2</mn><var><mi>k</mi></var><var><mi>l</mi></var><mo>&le;</mo><var><mi>n</mi></var></mrow></math> and <var>x</var> an integer with <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo>-</mo><var><mi>n</mi></var><mo>/</mo><mn>2</mn><mo>&lt;</mo><var><mi>x</mi></var><mo>&le;</mo><var><mi>n</mi></var><mo>/</mo><mn>2</mn></mrow></math>. If it exists this function returns a rational number <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>r</mi><mo>/</mo><mi>s</mi></mrow></math> with <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mn>0</mn><mo>&lt;</mo><mi>s</mi><mo>&lt;</mo><var><mi>l</mi></var></mrow></math>, <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mrow></mrow><mo>gcd</mo><mo stretchy="false">(</mo><mi>s</mi><mo>,</mo><var><mi>n</mi></var><mo stretchy="false">)</mo><mo>=</mo><mn>1</mn></mrow></math>, <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo>-</mo><var><mi>k</mi></var><mo>&lt;</mo><mi>r</mi><mo>&lt;</mo><var><mi>k</mi></var></mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>r</mi><mo>/</mo><mi>s</mi></mrow></math> congruent to <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>x</mi></var><mo>mod</mo><var><mi>n</mi></var></mrow></math> (i.e., <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><var><mi>n</mi></var>\mid<mi>r</mi><mo>-</mo><mi>s</mi><var><mi>x</mi></var></mrow></math>). Such an <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>r</mi><mo>/</mo><mi>s</mi></mrow></math> is unique. The function returns <code class="keyw">fail</code> if such a number does not exist.</p>

<p><a id="s6ss2" name="s6ss2"></a></p>

<h5>1.6-2 InverseIntMatMod</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; InverseIntMatMod</code>( <var>A, p</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns an inverse matrix modulo a prime <var>p</var> or <code class="keyw">fail</code>. More precisely:</p>

<p><var>A</var> must be an integer matrix and <var>p</var> a prime such that <var>A</var> is invertible modulo <var>p</var>. This function returns an integer matrix <var>inv</var> with entries in the range <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo stretchy="false">]</mo><mo>-</mo><var><mi>p</mi></var><mo>/</mo><mn>2</mn><mo>&mldr;</mo><var><mi>p</mi></var><mo>/</mo><mn>2</mn><mo stretchy="false">]</mo></mrow></math> such that <var>inv</var><var>A</var> reduced modulo p is the identity matrix.</p>

<p>It returns <code class="keyw">fail</code> if the inverse modulo <var>p</var> does not exist. This function is particularly fast for primes smaller 256.</p>

<p><a id="s6ss3" name="s6ss3"></a></p>

<h5>1.6-3 HadamardBoundIntMat</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; HadamardBoundIntMat</code>( <var>A</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>The Hadamard bound for a square integer matrix <var>A</var> is the product of Euclidean norms of the nonzero rows (or columns) of <var>A</var>. It is an upper bound for the absolute value of the determinant of <var>A</var>.</p>

<p><a id="s6ss4" name="s6ss4"></a></p>

<h5>1.6-4 CheapFactorsInt</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; CheapFactorsInt</code>( <var>n[, nr]</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns a list of factors of an integer <var>n</var>, including "small" prime factors - here the optional argument <var>nr</var> is the number of iterations for `FactorsRho' (default is 2000).</p>

<p>This is only a slight modification of the library function <code class="func">FactorsInt</code> (<a href="../../../doc/htm/ref/CHAP014.htm#SECT003"><b>Reference: FactorsInt</b></a>) which avoids an error message when the number is not completely factored.</p>

<p><a id="s6ss5" name="s6ss5"></a></p>

<h5>1.6-5 RankMod</h5>

<div class="func"><table class="func" width="100%"><tr><td class="tdleft"><code class="func">&gt; RankMod</code>( <var>A, p</var> )</td><td class="tdright">( function )</td></tr></table></div>
<p>This function returns the rank of an integer matrix <var>A</var> modulo <var>p</var>. Here <var>p</var> must not necessarily be a prime. If it is not and this function returns an integer, then this is the rank of <var>A</var> for all prime divisors of <var>p</var>.</p>

<p>If during the computation a factorisation of <var>p</var> is found (because some pivot entry has nontrivial greatest common divisor with <var>p</var>) then the function is recursively applied to the found factors <code class="code">f\_i</code> of <var>p</var>. The result is then given in the form <code class="code">[[f\_1, rk\_1], [f\_2, rk\_2], ...]</code>.</p>

<p>The idea to make this function useful for non primes was to use it with large factors of the biggest elementary divisor of <var>A</var> whose prime factorization cannot be found easily.</p>


<table class="example">
<tr><td><pre>

gap&gt; ReadPkg("edim",  "tst/mat");
Reading 242x242 integer matrix 'mat' and its elementary divisors 'eldiv'.
gap&gt; RankMod(mat, 5);
155
gap&gt; RankMod(mat, (2*79*4001));
[ [ 2, 148 ], [ 79, 242 ], [ 4001, 242 ] ]

</pre></td></tr></table>

<p><a id="s7ss0" name="s7ss0"></a></p>

<h4>1.7 InverseRatMat - the Algorithm</h4>

<p>The idea is to recover a rational matrix from an <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math>-adic approximation for some prime <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math>. This description came out of discussions with Jürgen Müller. I thank John Cannon for pointing out that the basic idea already appeared in the paper <a href="chapBib_mml.xml#biBD82">[D82]</a> of Dixon.</p>

<p>Let <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>A</mi></mrow></math> be an invertible matrix over the rational numbers. By multiplying with a constant we may assume that its entries are in fact integers.</p>

<p>(1) We first describe how to find an <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math>-adic approximation of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msup><mi>A</mi><mrow><mo>-</mo><mn>1</mn></mrow> </msup> </mrow></math>. Find a prime <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math> such that <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>A</mi></mrow></math> is invertible modulo <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math> and let <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>B</mi></mrow></math> be the integer matrix with entries in the range <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mrow><mo>]</mo><mo>-</mo><mi>l</mi><mo>/</mo><mn>2</mn><mo>,</mo><mi>l</mi><mo>/</mo><mn>2</mn><mo>]</mo></mrow></mrow></math> such that <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>BA</mi></mrow></math> is congruent to the identity matrix modulo <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math>. (This can be computed fast by usual Gauß elimination.)</p>

<p>Now let <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>v</mi><mo>&isin;</mo>\Z<msup><mi></mi><mrow><mi>r</mi></mrow></msup> </mrow></math> be a row vector. Define two sequences <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>v</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>x</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> of row vectors in <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow>\Z<msup><mi></mi><mrow><mi>r</mi></mrow></msup> </mrow></math> by: <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>x</mi><mrow><mn>0</mn></mrow> </msub> <mo>:</mo><mo>=</mo><mn>0</mn><mo>&isin;</mo>\Z<msup><mi></mi><mrow><mi>r</mi></mrow></msup> </mrow></math>, <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>v</mi><mrow><mn>0</mn></mrow> </msub> <mo>:</mo><mo>=</mo><mo>-</mo><mi>v</mi></mrow></math> and for <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>i</mi><mo>&gt;</mo><mn>0</mn></mrow></math> set <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>x</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> to the vector congruent to <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo>-</mo> <msub><mi>v</mi><mrow><mi>i</mi><mo>-</mo><mn>1</mn></mrow> </msub> <mi>B</mi></mrow></math> modulo <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math> having entries in the range <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mrow><mo>]</mo><mo>-</mo><mi>l</mi><mo>/</mo><mn>2</mn><mo>,</mo><mi>l</mi><mo>/</mo><mn>2</mn><mo>]</mo></mrow></mrow></math>. Then all entries of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>x</mi><mrow><mi>i</mi></mrow> </msub> <mi>A</mi><mo>+</mo> <msub><mi>v</mi><mrow><mi>i</mi><mo>-</mo><mn>1</mn></mrow> </msub> </mrow></math> are divisible by <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math> and we set <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>v</mi><mrow><mi>i</mi></mrow> </msub> <mo>:</mo><mo>=</mo><mo stretchy="false">(</mo><mn>1</mn><mo>/</mo><mi>l</mi><mo stretchy="false">)</mo><mo>&middot;</mo><mo stretchy="false">(</mo> <msub><mi>x</mi><mrow><mi>i</mi></mrow> </msub> <mi>A</mi><mo>+</mo> <msub><mi>v</mi><mrow><mi>i</mi><mo>-</mo><mn>1</mn></mrow> </msub> <mo stretchy="false">)</mo></mrow></math>.</p>

<p>Induction shows that for <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>y</mi><mrow><mi>i</mi></mrow> </msub> <mo>:</mo><mo>=</mo> <munderover><mrow></mrow><mo>&sum;</mo><mrow><mi>k</mi><mo>=</mo><mn>1</mn> </mrow> <mrow><mi>i</mi></mrow></munderover> <msup><mi>l</mi><mrow><mi>k</mi><mo>-</mo><mn>1</mn></mrow> </msup> <msub><mi>x</mi><mrow><mi>k</mi></mrow> </msub> </mrow></math> we have <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>y</mi><mrow><mi>i</mi></mrow> </msub> <mi>A</mi><mo>=</mo><mi>v</mi><mo>+</mo> <msup><mi>l</mi><mrow><mi>i</mi></mrow> </msup> <msub><mi>v</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> for all <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>i</mi><mo>&ge;</mo><mn>0</mn></mrow></math>. Hence the sequence <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>y</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math>, <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>i</mi><mo>&ge;</mo><mn>0</mn></mrow></math>, gives an <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math>-adic approximation to the vector <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>y</mi><mo>&isin;</mo>\Q<msup><mi></mi><mrow><mi>r</mi></mrow></msup> </mrow></math> with <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>y</mi><mi>A</mi><mo>=</mo><mi>v</mi></mrow></math>.</p>

<p>(2) The second point is to show how we can get the vector <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>y</mi></mrow></math> from a sufficiently good approximation <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>y</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math>. Note that the sequence of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>y</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> becomes constant for <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>i</mi><mo>&ge;</mo> <msub><mi>i</mi><mrow><mn>0</mn></mrow> </msub> </mrow></math> if all entries of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>y</mi></mrow></math> are integers of absolute value smaller than <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msup><mi>l</mi><mrow> <msub><mi>i</mi><mrow><mn>0</mn></mrow> </msub> </mrow> </msup> <mo>/</mo><mn>2</mn></mrow></math> because of our choice of representatives of residue classes modulo <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>l</mi></mrow></math> in the interval <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mrow><mo>]</mo><mo>-</mo><mi>l</mi><mo>/</mo><mn>2</mn><mo>,</mo><mi>l</mi><mo>/</mo><mn>2</mn><mo>]</mo></mrow></mrow></math>.</p>

<p>More generally consider <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>a</mi><mo>/</mo><mi>b</mi><mo>&isin;</mo>\Q</mrow></math> with <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>b</mi><mo>&gt;</mo><mn>0</mn></mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>a</mi><mo>,</mo><mi>b</mi></mrow></math> coprime. Then there is for each <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>n</mi><mo>&isin;</mo>\N</mrow></math> which is coprime to <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>b</mi></mrow></math> a unique <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>c</mi><mo>&isin;</mo>\Z</mrow></math> with <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo>-</mo><mi>n</mi><mo>/</mo><mn>2</mn><mo>&lt;</mo><mi>c</mi><mo>&le;</mo><mi>n</mi><mo>/</mo><mn>2</mn></mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>a</mi><mo>&equiv;</mo><mi>c</mi><mi>b</mi><mo>mod</mo><mi>n</mi></mrow></math>. This <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>c</mi></mrow></math> can be computed via the extended Euclidean algorithm applied to <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>b</mi></mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>n</mi></mrow></math>.</p>

<p>Now let <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>n</mi><mo>,</mo><mi>&alpha;</mi><mo>,</mo><mi>&beta;</mi><mo>&isin;</mo>\N</mrow></math> with <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mn>2</mn><mi>&alpha;</mi><mi>&beta;</mi><mo>&le;</mo><mi>n</mi></mrow></math>. Then the map <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow>{<mi>a</mi><mo>/</mo><mi>b</mi><mo>&isin;</mo>\Q\mid<mo>-</mo><mi>&alpha;</mi><mo>&le;</mo><mi>a</mi><mo>&le;</mo><mi>&alpha;</mi><mo>,</mo><mn>1</mn><mo>&le;</mo><mi>b</mi><mo>&lt;</mo><mi>&beta;</mi>}<mo>&rarr;</mo><mrow><mo>]</mo><mo>-</mo><mi>n</mi><mo>/</mo><mn>2</mn><mo>,</mo><mi>n</mi><mo>/</mo><mn>2</mn><mo>]</mo></mrow></mrow></math>, <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>a</mi><mo>/</mo><mi>b</mi><mo>&rarr;</mo><mi>c</mi></mrow></math> (defined as above) is injective (since for <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>a</mi><mo>/</mo><mi>b</mi></mrow></math>, <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>a</mi><mo>'</mo><mo>/</mo><mi>b</mi><mo>'</mo></mrow></math> in the above set we have <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>a</mi><mi>b</mi><mo>'</mo><mo>-</mo><mi>a</mi><mo>'</mo><mi>b</mi><mo>&equiv;</mo><mn>0</mn><mo>mod</mo><mi>n</mi></mrow></math> if and only if <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>a</mi><mi>b</mi><mo>'</mo><mo>-</mo><mi>a</mi><mo>'</mo><mi>b</mi><mo>=</mo><mn>0</mn></mrow></math>).</p>

<p>In practice we can use for any <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>c</mi><mo>&isin;</mo><mrow><mo>]</mo><mo>-</mo><mi>n</mi><mo>/</mo><mn>2</mn><mo>,</mo><mi>n</mi><mo>/</mo><mn>2</mn><mo>]</mo></mrow></mrow></math> a certain extended Euclidean algorithm applied to <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>n</mi></mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>c</mi></mrow></math> to decide if <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>c</mi></mrow></math> is in the image of the above map and to find the corresponding <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>a</mi><mo>/</mo><mi>b</mi></mrow></math> if it exists.</p>

<p>(3) To put things together we apply (2) to the entries of the vectors <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>y</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> constructed in (1), choosing <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>n</mi><mo>=</mo> <msup><mi>l</mi><mrow><mi>i</mi></mrow> </msup> </mrow></math>, <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>&alpha;</mi><mo>=</mo><msqrt><mrow><mi>n</mi></mrow></msqrt><mo>/</mo><mn>2</mn></mrow></math> and <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>&beta;</mi><mo>=</mo><msqrt><mrow><mi>n</mi></mrow></msqrt></mrow></math>. If we have found this way a candidate for <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>y</mi></mrow></math> we can easily check if it is correct by computing <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>y</mi><mi>A</mi></mrow></math>. If <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>&mu;</mi></mrow></math> is the maximal absolute value of all numerators and denominators of the entries of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>y</mi></mrow></math> it is clear from (2) that we will find <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>y</mi></mrow></math> from <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>y</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> if <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msup><mi>l</mi><mrow><mi>i</mi></mrow> </msup> <mo>&gt;</mo><mn>2</mn> <msup><mi>&mu;</mi><mrow><mn>2</mn></mrow> </msup> </mrow></math>.</p>

<p>(4) If we take as <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>v</mi></mrow></math> in (1) to(3) all standard unit vectors we clearly get the rows of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msup><mi>A</mi><mrow><mo>-</mo><mn>1</mn></mrow> </msup> </mrow></math>. But we can do it better. Namely we can take as <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>v</mi></mrow></math> the standard unit vectors multiplied by the least common multiple <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>&epsi;</mi></mrow></math> of the denominators of the already computed entries of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msup><mi>A</mi><mrow><mo>-</mo><mn>1</mn></mrow> </msup> </mrow></math>. In many examples this <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>&epsi;</mi></mrow></math> actually equals <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>&epsi;</mi><mrow><mi>r</mi></mrow> </msub> </mrow></math> after the computation of the first or first few rows. Therefore we will often find quickly the next row of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msup><mi>A</mi><mrow><mo>-</mo><mn>1</mn></mrow> </msup> </mrow></math> already in (1), because we find a <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>v</mi><mrow><mi>i</mi></mrow> </msub> <mo>=</mo><mn>0</mn></mrow></math> such that the sequence of <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <msub><mi>y</mi><mrow><mi>i</mi></mrow> </msub> </mrow></math> becomes constant ( <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mo>=</mo><mi>y</mi></mrow></math>).</p>

<p><a id="s7ss1" name="s7ss1"></a></p>

<h5>1.7-1 Rank of Integer Matrix</h5>

<p>The following strategy has shown to be useful in proving that some very big integer matrix is not invertible.</p>


<ul>
<li><p>Check the rank modulo some small primes, say with <code class="func">RankMod</code> (<a href="chap1_mml.xml#s6ss5"><b>1.6-5</b></a>).</p>

</li>
<li><p>If the rank seems less than the number of rows choose a prime <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math>, a collection of lines which is linearly independent modulo <math xmlns="http://www.w3.org/1998/Math/MathML"> <mrow><mi>p</mi></mrow></math>, and another line linearly dependend on these. Guess that this last line is also linearly dependend on the chosen collection over the rational numbers (maybe check modulo several small primes).</p>

</li>
<li><p>Find columns of the collection of lines which give an invertible matrix modulo some prime.</p>

</li>
<li><p>Then use <code class="func">RationalSolutionIntMat</code> (<a href="chap1_mml.xml#s3ss2"><b>1.3-2</b></a>) with the invertible submatrix and corresponding entries of the linearly dependend row to prove this.</p>

</li>
</ul>
<p>Guessing the rank of a matrix from the rank modulo several primes, chosing a maximal set of lines which are linearly independent modulo some primes, and using <code class="func">RationalSolutionIntMat</code> (<a href="chap1_mml.xml#s3ss2"><b>1.3-2</b></a>) with the remaining lines, one may also find the exact rank of a huge integer matrix.</p>


<div class="pcenter">
<table class="chlink"><tr><td><a href="chap0_mml.xml">Top of Book</a></td><td><a href="chap0_mml.xml">Previous Chapter</a></td><td><a href="chapBib_mml.xml">Next Chapter</a></td></tr></table>
<br />


<div class="pcenter"><table class="chlink"><tr><td class="chlink1">Goto Chapter: </td><td><a href="chap0_mml.xml">Top</a></td><td><a href="chap1_mml.xml">1</a></td><td><a href="chapBib_mml.xml">Bib</a></td><td><a href="chapInd_mml.xml">Ind</a></td></tr></table><br /></div>

</div>

<hr />
<p class="foot">generated by <a href="http://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc">GAPDoc2HTML</a></p>
</body>
</html>
