International Journal of Algebra, Vol. 7, 2013, no. 8, 369 - 390

HIKARI Ltd, www.m-hikari.com

Applications of Strong Gr¨obner Bases

over Euclidean Domains

Daniel Lichtblau

Wolfram Research

100 Trade Centre Dr

Champaign, IL 61820, USA

danl@wolfram.com

Copyright c

!2013 Daniel Lichtblau. This is an open access article distributed under the

Creative Commons Attribution License, which permits unrestricted use, distribution, and repro-

duction in any medium, provided the original work is properly cited.

Abstract

Strong Gr¨obner bases over Euclidean domains and even more general rings

were ﬁrst deﬁned in the 1980s. Since that time, eﬃcient ways to compute

them, and a variety of applications, have appeared. In this note we show, via

simple examples, applications to solving equations in quotient rings, Hensel

lifting, Hermite normal form computations, reduction of univariate polynomial

lattices, and ﬁnding small generators in quadratic number rings.

Mathematics Subject Classiﬁcation: 11C08, 11C20, 11D04, 11R11, 13B25,

13F07, 13P05, 13P10, 14Q99, 15A23, 15B36

Keywords: Gr¨obner basis, Euclidean domain, Hensel lifting, Hermite normal

form, linear diophantine systems, lattice reduction, Popov form

1 Introduction

The theory and application of Gr¨obner bases of polynomials over ﬁelds has been

developed extensively, and proven indispensible in many areas of computational

mathematics. When going from a ﬁeld as base ring to a more general ring, there

are options for which properties of Gr¨obner bases one might hope to preserve. For

370 D. Lichtblau

Euclidean domains as base rings there are both “weak” and “strong” Gr¨obner bases.

The former have the beneﬁt that they are easier to compute,. The cost is that

reduction of polynomials modulo such a basis is now more expensive as compared

to the working with strong bases. These bases are discussed in [8], [5] section 8,

[9], [23], [3], [2]. These references also present various algorithms for computing

either weak or strong bases. While all are based to some extent on the Buchberger

algorithm over ﬁelds, there are qualiﬁcations that create substantial ineﬃciency as

compared to the ﬁeld case. An exception is [19], which in various respects is similar

to the Buchberger algorithm over ﬁelds. That said, it is more specialized to the

case of weak bases and also does not fully develop the redundancy criteria of the

Buchberger algorithm.

In [16] we develop an eﬃcient computation of Gr¨obner bases over base rings

that are eﬀectively computable Euclidean domains. After providing the relevant

deﬁnitions and theory, an algorithm is presented that is very much in the spirit of the

Buchberger algorithm for working over ﬁelds. In particular it uses S-polynomials,

generalized division for reduction, and has criteria for eliminating pairs that are

analogous to those for the ﬁeld case. Our goal in this companion work is to provide

a number of examples of both general and special cases. We will show how several

important, and seemingly disparate, computations may be viewed as Gr¨obner bases

over rings, and to point to practial applications along the way.

We will begin with basic examples similar to those in [16]. These recall to the

reader some uses of extra variables for purposes of computing ideal intersections or

working in extension rings that are not themselves Euclidean. We next show how

such bases may be used to perform Hensel lifting of univariate polynomials factored

over a prime modulus. We then cover computation of matrix Hermite normal forms,

as well as Popov forms for matrices of univariate polynomials over a ﬁeld (the

polynomials themselves are now the base ring, with new variables corresponding

to matrix rows). The next application we show is to bivariate modular polynomial

factorization. We ﬁnish our examples with computation of small generators of ideals

in quadratic number rings.

For purposes of brevity and simplicity of exposition we will omit most formal

statements and proofs of correctness for the methods we present. Such proofs would

use arguments based on term ordering and integer sizes, and are generally straight-

forward. Instead we will indicate why they work by reminding the reader of how

Gr¨obner bases correspond to objects under study in the various applications.

All examples are run using Mathematica 9 [29] using a 3.1 GHz processor run-

ning on the Linux operating system. One indicates that computationa are to be per-

formed over speciﬁc Euclidean domains (integers and univariate polynomial rings)

via settings of the Coef f icientDomain option. We intersperse snippets of code

throughout, and place larger code blocks in an appendix. That latter, in total, stills

comes to fewer than 100 lines. This may give an indication of the ease of adapting

such Gr¨obner bases to a wide variety of applications.

Strong Gr¨obner bases 371

2 Basic Examples

We begin with an example adapted from [2]. We wish to compute a Gr¨obner basis

for an ideal in the polynomial ring Z[√−11][x, y]. Our base ring is not a unique fac-

torization domain, hence not a Euclidean domain. We ﬁnesse this issue by adding

a new variable and a corresponding deﬁning polynomial to handle the quadratic

extension. In this way we can work directly over the integers. So our ring will be

Z[x, y, α]/{α2+ 11}. We want to treat the extension variable as though it were a

coeﬃcient. A well known way to achieve this end is to have the the new variable or-

dered lexicographically lower than all others. When ﬁnished we remove the deﬁning

polynomial for the extension.

Rest[GroebnerBasis[{2xy −αy, (1 + α)x2−xy, α2+ 11},

Rest[GroebnerBasis[{2xy −αy, (1 + α)x2−xy, α2+ 11},

Rest[GroebnerBasis[{2xy −αy, (1 + α)x2−xy, α2+ 11},

{x, y, α},CoeﬃcientDomain →Integers]]

{x, y, α},CoeﬃcientDomain →Integers]]

{x, y, α},CoeﬃcientDomain →Integers]]

{25y+ 10y2−5yα,15y+5y2+y2α,−25y+xy +5y3+ 12yα,

6x2+ 10y+5y2−3yα, x2−25y+5y3+x2α+ 12yα}

As a second example, we will ﬁnd a basis for the ideal intersection {3x2−2y−

4,y

2+5y−3xy +2}∩{16xy −6}in Z[x, y]. This may be done as below. Note that

we again use and subsequently eliminate an auxiliary variable, this time ordered

lexicographically greater than the others (specifying it as the third argument tells

GroebnerBasis it is to be eliminated).

GroebnerBasis[Flatten[

GroebnerBasis[Flatten[

GroebnerBasis[Flatten[

{w{3x2−2y−4,y

2+5y−3xy +2},(1 −w){16xy −6}}],{x, y},w,

{w{3x2−2y−4,y

2+5y−3xy +2},(1 −w){16xy −6}}],{x, y},w,

{w{3x2−2y−4,y

2+5y−3xy +2},(1 −w){16xy −6}}],{x, y},w,

CoeﬃcientDomain →Integers,MonomialOrder →EliminationOrder]

CoeﬃcientDomain →Integers,MonomialOrder →EliminationOrder]

CoeﬃcientDomain →Integers,MonomialOrder →EliminationOrder]

{12 + 30y−50xy +6y2−80xy2+ 48x2y2−16xy3,

24 −18x2+ 12y−64xy + 48x3y−32xy2,

−60 −36x−90y+ 160xy + 96x2y−24y2+ 240xy2−6y3+ 64xy3+ 16xy4,

−24 −12x−36y+ 70xy + 32x2y+ 90xy2−16x2y2+ 16x2y3}

Another application is to do computations involving ideals deﬁned over quotient

rings that may contain zero divisors. As an example we will show a key step, the

basis computation, for ﬁnding all solutions in the ring Z5072012170009 to the system

below.

gb = GroebnerBasis[{5072012170009,−4984359602099 + x2−3y2−9xz,

gb = GroebnerBasis[{5072012170009,−4984359602099 + x2−3y2−9xz,

gb = GroebnerBasis[{5072012170009,−4984359602099 + x2−3y2−9xz,

−1780431462965 + 7xy +5y3+z2,−4585397367278 + x3−3y2+z−12z3},

−1780431462965 + 7xy +5y3+z2,−4585397367278 + x3−3y2+z−12z3},

−1780431462965 + 7xy +5y3+z2,−4585397367278 + x3−3y2+z−12z3},

{x, y, z},CoeﬃcientDomain →Integers]

{x, y, z},CoeﬃcientDomain →Integers]

{x, y, z},CoeﬃcientDomain →Integers]

{5072012170009,1174872829454 + 12173501962z−1363165624472z2+...

−1977589465047z16 −2210999439349z17}

A related area of application for Gr¨obner bases over the integers is in computa-

tions with ﬁnitely presented groups, as discussed in chapter 10 of [24].

372 D. Lichtblau

3 Hensel Lifting of Univariate Polynomials

We now show an application that uses the special case of polynomials in one variable

over the integers modulo a power nof a prime p. We begin with a simple example

rigged so that the correct result is obvious.

poly = Expand[(x5+ 18x4+ 34x3+5x2+ 21x+ 30)

poly = Expand[(x5+ 18x4+ 34x3+5x2+ 21x+ 30)

poly = Expand[(x5+ 18x4+ 34x3+5x2+ 21x+ 30)

(x4+ 24x3+ 22x2+ 17x+ 15)];

(x4+ 24x3+ 22x2+ 17x+ 15)];

(x4+ 24x3+ 22x2+ 17x+ 15)];

We will ﬁrst factor the polynomial modulo a small prime, removing the (possibly

trivial) constant factor.

mod = 11;

mod = 11;

mod = 11;

fax = FactorList[poly,Modulus →mod];

fax = FactorList[poly,Modulus →mod];

fax = FactorList[poly,Modulus →mod];

fax = First/@Rest[fax]

fax = First/@Rest[fax]

fax = First/@Rest[fax]

{4+6x+2x3+x4,8 + 10x+5x2+x3+7x4+x5}

Next we wish to make the factors correct modulo a power of the prime. This

correction step is referred to as Hensel lifting [27] chapter 15 and is used in most

algorithms for factoring polynomials over the rationals. It is typically done by

iterations of Newton’s method in a p-adic setting, but Gr¨obner bases may instead

be used to advantage. In eﬀect we take p-adic GCDs of our polynomial along with

each factor raised to the indicated power, and these GCDs are the lifted factors.

For this particular example we will take the factors, square them, compute Gr¨obner

bases over the integers of the set {poly,squaredfactor,squaredmodulus}, and extract

the last elements of these bases. This will correspond to quadratic Hensel lifting,

insofar as a factor that is correct modulo some value pbecomes correct modulo p2.

We will in so doing recover the original factors up to sign.

(Last [GroebnerBasis [{mod2,poly,#1},CoeﬃcientDomain →Integers]] &) /@fax2

(Last [GroebnerBasis [{mod2,poly,#1},CoeﬃcientDomain →Integers]] &) /@fax2

(Last [GroebnerBasis [{mod2,poly,#1},CoeﬃcientDomain →Integers]] &) /@fax2

{−15 −17x−22x2−24x3−x4,30 + 21x+5x2+ 34x3+ 18x4+x5}

This recovered the actual factors because we arranged an example for which the

modular factors each corresponded to an actual factor, and moreover the factors

were monic, had coeﬃcients of the same sign, and these were all less than half the

prime squared. Hence they are recovered exactly from one quadratic Hensel lift.

The real question to be answered is why these Gr¨obner basis computations gave the

quadratic Hensel lifts of the modular factors. We address this next.

Theorem 1. Given a square free univariate polynomial fover the rationals, and

an integer psuch that the leading coeﬃcient of fis not divisible by p,fis square

free modulo p, and f≡pg0h0. Assume s=GCD [g02,f]exists modulo p2. Then s

is the Hensel lift of g0modulo p2.

Note that this p-adic GCD may be computed, as above, by a Gr¨obner basis over

the integers. Indeed it is simply a convenient shorthand for running the Euclidean

algorithm under the assumption that no zero divisors are encountered along the way.

Strong Gr¨obner bases 373

Proof. We are given f≡pg0h0. Suppose the quadratically lifted equation is f≡p2

g1h1where g1≡pg0and h1≡ph0. The assumptions imply that the degrees of g0

and g1are equal (and likewise with the cofactors). We may write g1=g0+pt0.

Then a simple computation shows that g1(g0−pt0)≡p2g02. We see that g1|fand

g1|g02modulo p2. Now let s= GCD [g02,f]. Then we have g1|s. In order to show

these are equal up to unit multiples (which proves the theorem), it suﬃces to show

that degree [g1]≥degree[s].

Suppose degree[s]>degree [g1]. Then degree[s]>degree [g0]. Since s|fmodulo

p2we have s|fmodulo p. But also s|g02so the strict degree inequality implies that

sis not square free modulo p. Hence fis not square free modulo p, contradicting

our assumption.

One may realize that a polynomial factorization code based on this result will

have a probabilistic aspect. We might inadvertently use an “unlucky” prime wherein

at some step of the lifting process a GCD does not exist. This can happen if a leading

coeﬃcient in the process becomes noninvertible because it is a product of p. It is

not hard to see that for a given polynomial there can only be ﬁnitely many such

unlucky primes. Moreover provided one uses a random prime that is large compared

to the degree of factors and degree of lifting required, the probability will be low

that the prime is unlucky.

To give some indication of eﬃciency we now demonstrate on a more challenging

example. It comes from a factorization example presented in [26]. The polynomial

in question is of degree 190 and has, as its roots, all the sums of pairs of roots of a

simpler polynomial, of degree 20. Code to create it is provided in the appendix.

The end goal is to factor this over the integers. While it would take us too far

aﬁeld to discuss the steps that use lattice reduction, we will show the Hensel lifting

phase below. To this end we ﬁrst factor modulo a prime of modest size.

mod = Prime[4000];

mod = Prime[4000];

mod = Prime[4000];

fax = FactorList[newpoly,Modulus →mod];

fax = FactorList[newpoly,Modulus →mod];

fax = FactorList[newpoly,Modulus →mod];

fax = First/@Rest[fax];

fax = First/@Rest[fax];

fax = First/@Rest[fax];

Next we wish to make the factors correct modulo a power of the prime. The spe-

ciﬁc power is dictated by size considerations that arise in the factorization algorithm;

for our example it will be 36. This lift can actually be done in one step (this can be

shown similar to the proof of theorem 1 above; see also multivariate factorization

in [15]). For reasons of eﬃciency it is better to iterate squarings rather than try to

lift to the full power in one step, as the squaring method keeps the degree relatively

small during the lifting process. We must then do more basis computations, but the

improved speed per computation more than compensates for this. Hence we are, as

above, doing quadratic Hensel lifting. The code for this is in the appendix.

Timing[liftedfax = liftfactors[fax,newpoly,mod,36]; ]

Timing[liftedfax = liftfactors[fax,newpoly,mod,36]; ]

Timing[liftedfax = liftfactors[fax,newpoly,mod,36]; ]

{1.790000,Null}

374 D. Lichtblau

We have attained a speed comparable to what was presented in [26] for this

step of the algorithm using but a few lines of code to implement the Hensel lift.

The rest of the factorization involves constructing and reducing a particular lattice.

We remark that prior to the advent of the van Hoeij algorithm this example was

essentially intractable.

Some further remarks about this method of p-adic lifting are in order. First,

it is clear that dedicated code will be faster than a general purpose Gr¨obner basis

program. We have such code in Mathematica, and for the example above it is

about ﬁve times faster. Tests on more strenuous problems indicate that it is quite

competitive with what seems to be the best Hensel lifting method in the literature

to date, Shoup’s “tree-lift” (which is a form of divide-and-conquer algorithm) [27],

chapter 15, section 5. Speciﬁcally, while it is clear that the behavior of Shoup’s

method is asymptotically better than that of the method presented above (it relies

on computation of quotients and remainders rather than GCDs), our experience

was that for practical purposes the method in this section was actually faster for the

knapsack factorization examples we tried at [30]. As these typically required lifting

to many digits, this is evidence of the practicality of the method above.

4 Computation and Use of Matrix Hermite Nor-

mal Forms

Another nice application of Gr¨obner bases over a Euclidean domain is in computing

the Hermite normal form of a matrix with elements in that domain. We illustrate

for the case of matrices of univariate polynomials.

Before we show an example we need code to generate a “random” polynomial

matrix. For this example we will use a 3x5 matrix of polynomials in xof degree at

most 2. The code to create a random matrix of such polynomials is in the appendix.

SeedRandom[1111];

SeedRandom[1111];

SeedRandom[1111];

mat = randomMatrix[2,3,5,x]

mat = randomMatrix[2,3,5,x]

mat = randomMatrix[2,3,5,x]

{{−1,−1+4x, 2+7x+9x2,4−6x−2x2,8−9x−3x2},

{7−9x, −9−9x, −9+5x, −7+8x+9x2,−2},

{−3+x+3x2,4,−4−9x, −7,−3}}

To set this up we need to extend Mathematica’s GroebnerBasis to handle

modules, using a “position over term” (POT) ordering [2]. We represent elements

as vectors with respect to module basis variables. The input consists of polynomials

that are linear with respect to the module variables. We then augment with relations

that force all products of the module variables to be zero and ﬁnd the Gr¨obner basis.

The code, adapted from [12], may be found in the appendix.

As the Hermite form is obtained by row operations over the base ring (that is,

division is forbidden), it is equivalent to a module Gr¨obner basis in the case where

our polynomial ring is just the base ring (that is, there are no other polynomial

Strong Gr¨obner bases 375

variables). We convert each row of the matrix to a polynomial vector representation

by making each column into a new “variable”. Now we use the module Gr¨obner

basis routine described above. Since we use a POT term order, the reduction works

to ﬁrst ﬁnd a minimal element (according to the Euclidean valuation) in the ﬁrst

column, then in the second, and so forth. When ﬁnished we convert the result back

to matrix form. We summarize this discussion as a simple theorem.

Theorem 2. One can represent a diophantine system over a Euclidean domain

(e.g. integers or univariate polynomials over a ﬁeld) as a module over the domain,

and via a module Gr¨obner basis computation one can then obtain the Hermite form

of the matrix.

We mention a minor departure from the standard version of the Hermite normal

form. There is an issue of normalization of nonzero entries that lie above piv-

ots (when we regard the lattice as being generated by rows, that is, compute the

row-based Hermite form). The Gr¨obner basis method just described will do this

diﬀerently in many cases from the forms described in the literature. This is both

easily remedied after the fact if so desired, and also is of no consequence in terms of

practical usage. We ignore the distinction and work with the result proved by the

Gr¨obner basis.

As an example now we obtain our module basis over Z8933[x] for the matrix

above. We work over a prime ﬁeld in order to restrict the size of the coeﬃcients.

hnf = groebnerHNF[mat,Polynomials[x],8933]

hnf = groebnerHNF[mat,Polynomials[x],8933]

hnf = groebnerHNF[mat,Polynomials[x],8933]

{{1,0,1917 + 1070x+ 3059x2+ 8245x3+ 8000x4,3765 + 4710x+ 4646

x2+ 7963x3+ 5748x4,324 + 2015x+ 8444x2+ 6027x3+ 311x4},

{0,1,1679 + 4306x+ 7219x2+ 1156x3+ 2499x4,4895 + 745x+ 2205x2+

4054x3+ 3533x4,4867 + 1191x+ 1666x2+ 3704x3+ 8100x4},

{0,0,6543 + 7867x+ 6763x2+ 1615x3+ 4524x4+x5,1286 + 7316x+ 1030x2+

955x3+ 2536x4+ 4963x5,3970 + 1175x+ 3348x2+ 7720x3+ 7939x4+ 5955x5}}

What we do above is by no means the only way to obtain the Hermite form of a

matrix of polynomials. Several tactics for obtaining good computational eﬃciency

are discussed in [25]. At the expense of more code one could adapt some of them

to work within this Gr¨obner basis method. We also point out that method shown

above for computing a matrix Hermite decomposition can readily be extended to

compute a Smith decomposition, and in practice it seems to be fairly eﬃcient.

We now adapt the technology in the previous example to solve linear polynomial

diophantine systems. To solve such a system we transpose the matrix, prepend the

right hand side vector, augment on the right with an identity matrix, and take the

Hermite normal form. We ﬁnd the row corresponding to the right hand side, check

that it was multiplied, if at all, by a unit. When this is the case the solution vector

can be taken from the rest of that row (which corresponds to multiples of columns of

the original matrix that were needed to zero the right hand side) multiplied by the

376 D. Lichtblau

negative reciprocal of that unit. Null vectors come from later rows in the Hermite

normal form and we return those as well. This method of diophantine solving may

be found e.g. in [4]. A more eﬃcient variant is presented in [20]. Note that this is

readily adapted to handle a system of modular congruences. We simply treat the

modulus in each congruence as something to be multiplied by a new variable, hence

each gets a new row.

The tactic of augmenting with an identity matrix, well known e.g. for matrix

inversion, is a form of “tag variable” manipulation in Gr¨obner basis technology. It

can be used, for example, to record syzygies or conversion matrices using nothing

beyond a standard GroebnerBasis function. The method appears in [6] and was

also discussed in [13] (the relevant conferences were indeed but days apart).

For this example we use a 4 ×6 matrix of polynomials in xof degree at most 3.

Again we will work modulo 8933. We ﬁrst set up a random polynomial system.

SeedRandom[11111];

SeedRandom[11111];

SeedRandom[11111];

mod = 8933;

mod = 8933;

mod = 8933;

{mat,rhs}= randomSystem[3,4,6,x]

{mat,rhs}= randomSystem[3,4,6,x]

{mat,rhs}= randomSystem[3,4,6,x]

{{−9−2x, −1+3x, 8+8x+2x2−2x3,−4+4x+x2−6x3,−8 + 10x−7x2−x3,10},

{−4−5x−9x2,2,5−3x, 6+6x, −10,−9x2},

{9−7x+4x2,10 −8x, 9,−2−9x−6x2,−3−9x, −5+6x},

{−1,−10 −x, 9+9x+6x2,4,−9−9x, −1}}

{−1−6x−2x2−2x3,−5+9x−10x2+6x3,−5+2x+ 10x2−6x3,4+4x−3x3}

We compute a particular solution as well as a basis for the null vectors (solutions

to the homogeneous system).

{sol,nulls}= systemSolve[mat,rhs,Polynomials[x],mod]

{sol,nulls}= systemSolve[mat,rhs,Polynomials[x],mod]

{sol,nulls}= systemSolve[mat,rhs,Polynomials[x],mod]

{0,−6911 −8325x−1007x2−3258x3−5553x4−461x5−2962x6−2697x7−5078x8,

−1595 −5252x−6226x2−4661x3−4977x4−8450x5−6487x6−3824x7,

−2138 −3927x−285x2−3502x3−2954x4−7104x5−4269x6−5140x7,

−3462 −306x−1529x2−8826x3−4560x4−3639x5−8726x6−6177x7,

−3040 −6860x−7638x2−7785x3−1317x4−3941x5−4273x6},

{{1,1278+8648x+1881x2+7702x3+5712x4+4601x5+855x6+3166x7+7530x8,5957+

5383x+ 7939x2+ 2088x3+ 1863x4+ 6071x5+ 1016x6+ 1255x7,2282 + 4590x+

3441x2+ 5607x3+ 6567x4+ 7241x5+ 5280x6+ 7826x7,1923 + 7650x+ 8533x2+

179x3+6723x4+ 3135x5+6022x6+ 4132x7,5854 + 103x+5232x2+ 5526x3+387x4+

8186x5+517x6},{0,116+4911x+8497x2+4984x3+158x4+7000x5+3210x6+3726x7+

4x8+x9,4999 + 1437x+ 2565x2+ 3994x3+ 3624x4+ 8754x5+ 2977x6+ 758x7+

1489x8,2529 + 6147x+ 8417x2+ 6672x3+ 2816x4+ 6216x5+ 5228x6+ 7431x7+

5954x8,6720 + 3620x+ 5556x2+ 1650x3+ 1274x4+ 342x5+ 2973x6+ 1489x7+

5963x8,2400 + 2757x+ 7612x2+ 6882x3+ 8738x4+ 4064x5+ 7836x6+ 8436x7}}

Strong Gr¨obner bases 377

It is straightforward to check the result. The matrix times the solution vector

must give the right hand side, and the matrix times the null vectors must give zeroes.

zeroTensor[t ]:=Max[Abs[t]] == 0

zeroTensor[t ]:=Max[Abs[t]] == 0

zeroTensor[t ]:=Max[Abs[t]] == 0

{zeroTensor[Expand[mat.sol −rhs,Modulus →mod]],

{zeroTensor[Expand[mat.sol −rhs,Modulus →mod]],

{zeroTensor[Expand[mat.sol −rhs,Modulus →mod]],

zeroTensor[Expand[mat.Transpose[nulls],Modulus →mod]]}

zeroTensor[Expand[mat.Transpose[nulls],Modulus →mod]]}

zeroTensor[Expand[mat.Transpose[nulls],Modulus →mod]]}

{True,True}

We now show an example from [7] for the analogous case of an integer system.

We have six modular congruences in six variables that we wish to satisfy, with

coeﬃcient matrix, right hand side, and moduli as below. In this case our Euclidean

domain is of course the integers. The code in the appendix is suﬃciently generic as

to handle this base ring as well.

mat = {{70,0,6,89,0,7},{87,93,78,73,0,0{,}0,87,0,0,41,0},

mat = {{70,0,6,89,0,7},{87,93,78,73,0,0{,}0,87,0,0,41,0},

mat = {{70,0,6,89,0,7},{87,93,78,73,0,0{,}0,87,0,0,41,0},

{0,12,37,69,0,15},{75,0,90,65,14,0},{0,0,0,0,91,96}};

{0,12,37,69,0,15},{75,0,90,65,14,0},{0,0,0,0,91,96}};

{0,12,37,69,0,15},{75,0,90,65,14,0},{0,0,0,0,91,96}};

rhs = {−30,−53,−3,−53,−41,−55};

rhs = {−30,−53,−3,−53,−41,−55};

rhs = {−30,−53,−3,−53,−41,−55};

moduli = {280,5665,110,1545,3125,1925};

moduli = {280,5665,110,1545,3125,1925};

moduli = {280,5665,110,1545,3125,1925};

{soln,nulls}= systemSolve[mat,rhs,Integers,0,moduli]

{soln,nulls}= systemSolve[mat,rhs,Integers,0,moduli]

{soln,nulls}= systemSolve[mat,rhs,Integers,0,moduli]

{0,−2,4,12802,−29779,−34696},

{{5,0,0,−18165,4400,333025},{0,−5,0,−16135,26475,445025},

{0,0,15,17755,−26950,540925},{0,0,0,−39655,−4950,594825},

{0,0,0,0,−68750,0},{0,0,0,0,0,1586200}}

We check that the solution indeed satisﬁes the congruences, and that matrix

times null vectors gives zero vectors modulo the congruence moduli.

{zeroTensor[Mod[mat.soln −rhs,moduli]],

{zeroTensor[Mod[mat.soln −rhs,moduli]],

{zeroTensor[Mod[mat.soln −rhs,moduli]],

zeroTensor[Mod[mat.Transpose[nulls],moduli]]}

zeroTensor[Mod[mat.Transpose[nulls],moduli]]}

zeroTensor[Mod[mat.Transpose[nulls],moduli]]}

{True,True}

In addition to being faster (though slow in comparison to what one can do

with specialized Hermite normal form algorithm over the integers as in [25]), the

Hermite form method we use has the advantage that it gives a smaller solution,

with components of 5 digits as compared to 12 in [7]. Moreover it provides the

null vectors, and we can proceed to add multiples of them to the solution in order

to obtain a solution that is smaller still. To this end, we will digress brieﬂy from

the topic of Gr¨obner bases over Euclidean rings, in order to describe how to ﬁnd

small integer solutions to a linear diophantine system. While this is an important

computation in its own right (e.g. for integer linear programming, see [1], [14]),

we also show later how the corresponding polynomial case might be handled using

Gr¨obner bases.

To ﬁnd a small solution to an integer linear equation we form a matrix comprised

of the solution and null vectors. We augment by prepending one column containing

zeroes in the null vector rows and a suitably chosen integer to act as an “anchor” in

378 D. Lichtblau

the row containing the original solution vector. We then apply lattice reduction [10].

The purpose of the anchor is to prevent the solution vector from being multiplied by

anything other than a unit, and we check after reduction whether this succeeded. If

so, the new solution is obtained from the remaining entries in the row containing the

anchor (there may be more than one such, in which case the ﬁrst will be smallest).

Code in the appendix does this, returning the original solution if it fails in the

attempt to ﬁnd something smaller.

Using this we now obtain our new solution for the above example.

newsol = smallSolution[soln,nulls]

newsol = smallSolution[soln,nulls]

newsol = smallSolution[soln,nulls]

{565,358,−326,227,21,−221}

This method, when used with more powerful technology for computing the Her-

mite form, will readily handle much larger problems, and moreover works well

over the Gaussian integers. In the example below we use a minor modiﬁcation of

systemSolve. It uses the Mathematica built in function HermiteDecomposition,

instead of groebnerH NF , as the former is specialized for working over (rational or

Gaussian) integers.

SeedRandom[1111];

SeedRandom[1111];

SeedRandom[1111];

mat = RandomInteger[{−100,100},{30,35}]+iRandomInteger[{−100,100},{30,35}];

mat = RandomInteger[{−100,100},{30,35}]+iRandomInteger[{−100,100},{30,35}];

mat = RandomInteger[{−100,100},{30,35}]+iRandomInteger[{−100,100},{30,35}];

rhs = RandomInteger[{−100,100},30] + iRandomInteger[{−100,100},30];

rhs = RandomInteger[{−100,100},30] + iRandomInteger[{−100,100},30];

rhs = RandomInteger[{−100,100},30] + iRandomInteger[{−100,100},30];

Timing[{soln,nulls}= systemSolve2[mat,rhs]; ]

Timing[{soln,nulls}= systemSolve2[mat,rhs]; ]

Timing[{soln,nulls}= systemSolve2[mat,rhs]; ]

{0.710000,Null}

Timing[smallsoln = smallSolution[soln,nulls]; ]

Timing[smallsoln = smallSolution[soln,nulls]; ]

Timing[smallsoln = smallSolution[soln,nulls]; ]

zeroTensor[mat.smallsoln −rhs]

zeroTensor[mat.smallsoln −rhs]

zeroTensor[mat.smallsoln −rhs]

{0.190000,Null}

True

We check that the new solution is indeed much smaller than the original.

{Max[Abs[N[soln]]],Max[Abs[N[smallsoln]]]}

{Max[Abs[N[soln]]],Max[Abs[N[smallsoln]]]}

{Max[Abs[N[soln]]],Max[Abs[N[smallsoln]]]}

{3.31318 ×1073,6.08455 ×1014 }

So the initial solution had elements with up to 74 digits whereas those in the

small solution do not exceed 15 digits.

A related method for ﬁnding a small solution is presented in [17]. It also uses

Hermite normal form computation to obtain a solution vector as part of the trans-

formation matrix, but attempts to enforce small size in that matrix via an imple-

mentation based on lattice reduction. A simpler form of what we showed above

(with anchor set to 1) has been referred to as the “embedding” technique in [22].

It is not clear where it originated (the code in the appendix dates to 1995) and it

seems to have been independently discovered a few times. We also remark that the

method used above can be strengthened in some cases to obtain still smaller solu-

tions. Speciﬁcally, one can iterate, reducing the size of the weight as the solution

vectors get progressively smaller, and this sometimes gives further size reductions.

Strong Gr¨obner bases 379

5 Reduction of Polynomial Lattices

We now provide a univariate polynomial analog to the lattice reduction method

for obtaining “small” generators. Reduction here is in the sense of [11], wherein

one minimizes the largest degree of polynomials appearing in the matrix. This

gives what is also called the weak Popov form of the matrix [21]. The idea is to

compute a degree-based basis for the module, now using a “term over position”

(TOP) order for the module Gr¨obner basis computation. This enforces that highest

degree polynomials, regardless of column, will be higher in the term order than ones

of lower degree, and hence will force degrees to be minimal. We again summarize

this informal discussion as a theorem.

Theorem 3. One can represent a diophantine system by a matrix of univariate

polynomials over a ﬁeld as a module over this domain, and via a module Gr¨obner

basis computation one can then obtain the Popov form of the matrix.

As one might expect from the description of this method, the actual implemen-

tation (see appendix) is virtually identical to that for computing the Hermite form,

diﬀering primarily in the module term ordering. There is also a slight diﬀerence in

that we actually compute our Gr¨obner basis over the base ﬁeld of the polynomial

ring, now treating the polynomial variable as a bona ﬁde variable rather than a

coeﬃcient. This is necessitated by our requirement of a TOP term order, wherein

we must rank the module variables lower than the ring variable.

As an example we will again generate a random matrix, this time with all entries

of ﬁxed degree.

SeedRandom[1111]

SeedRandom[1111]

SeedRandom[1111]

mat = randomMatrix[4,3,5,x]

mat = randomMatrix[4,3,5,x]

mat = randomMatrix[4,3,5,x]

{{−8+5x−3x2−8x3−4x4,2+4x+2x2−2x3+7x4,−1−10x+9x2−6x3−

3x4,−2+5x−2x2+4x3+6x4,4+5x2−8x3−5x4},{4+5x−3x2−6x3−6x4,−7−

9x+8x2+9x3+2x4,10 + x+5x2+8x3−8x4,4+5x−2x2+x3−9x4,−10 −4x−

3x2+3x3+ 10x4},{−2x2+4x3+x4,7 + 10x−5x2−3x3−10x4,−6−8x−6x2+

7x3−3x4,−9−4x−5x2−6x3−8x4,−6 + 10x+4x2+7x3−9x4}}

We begin by computing the Hermite form, as this is in some sense as “far” as

possible from “reduced” (as measured by orthogonality defect from [11]).

hnf = groebnerHNF[mat,Polynomials[x]]

hnf = groebnerHNF[mat,Polynomials[x]]

hnf = groebnerHNF[mat,Polynomials[x]]

{{−3463744008314029656300,0,1419109784191676132539−5451418815988215855358x+

6840308700051010164924x2+7151499989765769609279x3−3466256061833707815106x4+

...},{...},{0,0,244 −299x−614x2+ 2838x3−217x4−2050x5+ 2192x6+ 669x7−

598x8−2215x9+ 10x10 + 37x11 −12x12,−264 + 159x+ 856x2−476x3−914x4+

292x5+651x6−2849x7−1789x8+ 132x9+1876x10 + 1131x11 +373x12 ,−736 +40x+

1464x2−1948x3−1790x4−889x5+ 2722x6+ 2172x7+ 621x8+ 1078x9−644x10 −

1092x11 −926x12}}

380 D. Lichtblau

redlat = polynomialLatticeReduce[hnf]

redlat = polynomialLatticeReduce[hnf]

redlat = polynomialLatticeReduce[hnf]

{{596−125x+143x2+130x3,−585−869x+318x2+515x3,592+885x−153x2+374x3+

12x4,554 + 11x+220x2+5x3−373x4,−358 −472x−525x2+325x3+ 926x4},{268 −

55x+61x2+62x3,−255−379x+138x2+229x3−12x4,260+387x−75x2+178x3,238+

x+92x2−5x3−179x4,−170−200x−231x2+155x3+406x4},{−892+175x−205x2−

182x3+ 12x4,879 + 1303x−486x2−781x3,−896 −1311x+ 219x2−574x3,−826 −

25x−320x2−7x3+ 575x4,554 + 704x+ 783x2−491x3−1390x4}}

It should be noted that, as was shown with the integer case above, this lattice

reduction might be put to use to ﬁnd “small” (that is, low degree) solutions to

diophantine polynomial systems with nontrivial null spaces. We will not pursue

that here.

6 Bivariate Modular Polynomial Factorization

We now put together techniques from the preceding sections for the purpose of fac-

toring a bivariate polynomial modulo a prime. For an example we will generate a

pair of random polynomials such that there are terms of highest total degree in each

variable separately; this brings no actual loss of generality, as one can always attain

this for one variable by a linear change of coordinates. We make a few other useful

choices so as not to run afoul of necessary conditions e.g. degree changing on sub-

stitution of a value for one variable. Again, these are all conveniences insofar as one

can work in an extension ﬁeld in one variable, in essence performing a substitution

of an algebraic element outside the base ﬁeld. The purpose of this section is not

to derive a bulletproof algorithm but rather to illustrate the method on a relatively

simple, yet nontrivial, example.

We ﬁrst generate a pair of pseudorandom bivariate polynomials and take their

product.

mod = 19;

mod = 19;

mod = 19;

totdeg = 6;

totdeg = 6;

totdeg = 6;

SeedRandom[11112222];

SeedRandom[11112222];

SeedRandom[11112222];

poly1 = randomBivariatePoly !totdeg

2,mod, x, y";

poly1 = randomBivariatePoly !totdeg

2,mod, x, y";

poly1 = randomBivariatePoly !totdeg

2,mod, x, y";

poly2 = randomBivariatePoly !totdeg

2,mod, x, y";

poly2 = randomBivariatePoly !totdeg

2,mod, x, y";

poly2 = randomBivariatePoly !totdeg

2,mod, x, y";

poly = Expand[poly1poly2,Modulus →mod]

poly = Expand[poly1poly2,Modulus →mod]

poly = Expand[poly1poly2,Modulus →mod]

8+7x+9x2+15x3+2x4+2x5+12x6+18y+5xy+6x2y+11x3y+2x4y+13y2+5xy2+

15x2y2+ 15x4y2+ 10y3+9xy3+8x2y3+ 12x3y3+3y4+9xy4+5x2y4+ 13xy5+7y6

We will evaluate at x= 11 and factor, removing the constant term. This pro-

duces all univariate factors of the evaluated polynomial.

val = 11;

val = 11;

val = 11;

fax = Map[First,Drop[FactorList[poly/.x→val,Modulus →mod],1]]

fax = Map[First,Drop[FactorList[poly/.x→val,Modulus →mod],1]]

fax = Map[First,Drop[FactorList[poly/.x→val,Modulus →mod],1]]

{7+y, 8+y, 13 + y, 15 + y, 7 + 10y+y2}

Strong Gr¨obner bases 381

As in the Hensel lifting section we will use a simple Gr¨obner basis computation

to lift a factor modulo a power of the ideal (x−11) that is suﬃcient to reclaim

factors of degree 3 in x. A proof that this method gives the correct Hensel lifting

could be constructed along the lines of that for the case when the base ﬁeld is the

complex numbers; see [15].

subst = (x−val);

subst = (x−val);

subst = (x−val);

pow = 24;

pow = 24;

pow = 24;

substpower = substpow;

substpower = substpow;

substpower = substpow;

liftedfactor = Last[GroebnerBasis[{poly,substpower,fax[[1]]pow},y,

liftedfactor = Last[GroebnerBasis[{poly,substpower,fax[[1]]pow},y,

liftedfactor = Last[GroebnerBasis[{poly,substpower,fax[[1]]pow},y,

Modulus →mod,CoeﬃcientDomain →Polynomials[x]]]

Modulus →mod,CoeﬃcientDomain →Polynomials[x]]]

Modulus →mod,CoeﬃcientDomain →Polynomials[x]]]

11 + 8x+6x2+9x3+6x4+ 12x5+2x6+ 10x7+ 17x8+9x9+ 13x10 + 16x11 +4x12 +

15x13 + 17x14 +5x15 + 17x16 + 16x17 +7x18 + 17x19 +9x20 +8x21 +5x22 + 15x23 +y

See [11] for bounds on how high one must lift in order to be guaranteed of ﬁnding

a correct factor. We used degree of 24 which is suﬃcient for the example at hand.

As in that reference we now set up a lattice of univariate polynomials in x, using

shifts of both the lifted polynomial and the power of the prime ideal over which we

initially factored.

deg = Exponent[liftedfactor,y];

deg = Exponent[liftedfactor,y];

deg = Exponent[liftedfactor,y];

lattice1 = Table[If[i== j, substpower,0],{i, deg},{j, totdeg}];

lattice1 = Table[If[i== j, substpower,0],{i, deg},{j, totdeg}];

lattice1 = Table[If[i== j, substpower,0],{i, deg},{j, totdeg}];

coeﬀs = PadRight[CoeﬃcientList[liftedfactor,y],totdeg];

coeﬀs = PadRight[CoeﬃcientList[liftedfactor,y],totdeg];

coeﬀs = PadRight[CoeﬃcientList[liftedfactor,y],totdeg];

lattice2 = Table[RotateRight[coeﬀs,j],{j, 0,totdeg −1−deg}];

lattice2 = Table[RotateRight[coeﬀs,j],{j, 0,totdeg −1−deg}];

lattice2 = Table[RotateRight[coeﬀs,j],{j, 0,totdeg −1−deg}];

lattice = Join[lattice1,lattice2];

lattice = Join[lattice1,lattice2];

lattice = Join[lattice1,lattice2];

The minimal lattice row will provide a factor [11]. It might be a nontrivial

multiple of the correct factor so we use a GCD extraction to get that factor.

candidate = First[redlat = polynomialLatticeReduce[lattice,mod]].

candidate = First[redlat = polynomialLatticeReduce[lattice,mod]].

candidate = First[redlat = polynomialLatticeReduce[lattice,mod]].

yRange[0,Length[lattice[[1]]]−1]

yRange[0,Length[lattice[[1]]]−1]

yRange[0,Length[lattice[[1]]]−1]

(8 + 9x+ 14x2+x3)y2+ (16 + x+2x2)y3+ (4 + 14x)y4+4y5

fac = PolynomialGCD[candidate,poly,Modulus →mod]

fac = PolynomialGCD[candidate,poly,Modulus →mod]

fac = PolynomialGCD[candidate,poly,Modulus →mod]

8+9x+ 14x2+x3+ 16y+xy +2x2y+4y2+ 14xy2+4y3

We check that we have indeed recovered one of the true modular factors of our

original polynomial.

PolynomialMod[5 ∗poly2,mod]==fac

PolynomialMod[5 ∗poly2,mod]==fac

PolynomialMod[5 ∗poly2,mod]==fac

True

We remark that one can do the lifting step using a diﬀerent term order and in

so doing recover the factor without resorting to a lattice reduction step. We show

this below.

liftedfactor2 = First[GroebnerBasis[{poly,(x−val)10,fax[[1]]10},{x, y},

liftedfactor2 = First[GroebnerBasis[{poly,(x−val)10,fax[[1]]10},{x, y},

liftedfactor2 = First[GroebnerBasis[{poly,(x−val)10,fax[[1]]10},{x, y},

Modulus →mod,MonomialOrder →DegreeReverseLexicographic]]

Modulus →mod,MonomialOrder →DegreeReverseLexicographic]]

Modulus →mod,MonomialOrder →DegreeReverseLexicographic]]

8+9x+ 14x2+x3+ 16y+xy +2x2y+4y2+ 14xy2+4y3

382 D. Lichtblau

The theoretical underpinnings to this approach are given, along with eﬃciency

improvements, in [15]. One advantage, as might be noted above, is that often the

lifting degree requirement is smaller.

7 Computing Small Generators of Ideals in Quadratic

Number Rings

A ring of integers extended by a square root is an important object in number

theory. Say dsatisﬁes d2=D, where Dis a squarefree integer. Two elements of the

quadratic integer ring Z[d], say x=r+sd and y=u+vd, comprise the basis of

an ideal. We will compute small generators for that ideal. We can moreover recover

Bezout relations. That is, we ﬁnd a pair of multipliers {m, n}∈Z[d] such that

mx +ny =gfor each such generator g.

Here we use code from previous sections to provide multipliers for the Bezout

relations. We compute a module basis with ﬁrst column comprised of our given xand

y, and a 2×2 identity matrix to the right of that column. We furthermore have a 3×3

matrix beneath this, comprised of the reducing quadratic on the diagonal and zero

elsewhere. The Hermite form of this matrix, computed via g roebnerH NF , will have

as ﬁrst row the greatest common divisor and the Bezout relation multipliers. For full

generality, we handle the case where d2≡41 by instead using the deﬁning polynomial

((2d−1)2−D)/ 4; this allows us the full range of elements in the corresponding

quadratic ring. The division by 4, which would be superﬂuous were our coeﬃcient

domain a ﬁeld, is necessary for attaining a monic deﬁning polynomial.

There is an added wrinkle. The Bezout relation multipliers computed as above

can be quite large. But we can ﬁnd a smaller set, exactly as we found small integer

solutions to diophantine systems. We simply treat the quadratic integers as integer

pairs, ﬂatten our vectors of these, and invoke smallSolution. Then we translate

consecutive pairs of the resulting integer vector back to quadratic integers. Code

for all this may be found in the appendix.

We show a quick example. We’ll work over Z!√−19"(so d=#1+√−19$% 2,

with inputs 51 + 43dand 26 −55d.

bezrels = bezout[d, 51 + 43d, 26 −55d, −19]

bezrels = bezout[d, 51 + 43d, 26 −55d, −19]

bezrels = bezout[d, 51 + 43d, 26 −55d, −19]

{{1,{115 −2#1+i√19$,101 −17 #1+i√19$}}}

We now check that result by expanding to see we recover the claimed GCD.

Expand !bezrels[[1,2]].{51 + 43 #1+√−19$% 2,26 −55 #1+√−19$% 2}−bezrels[[1,1]]"

Expand !bezrels[[1,2]].{51 + 43 #1+√−19$% 2,26 −55 #1+√−19$% 2}−bezrels[[1,1]]"

Expand !bezrels[[1,2]].{51 + 43 #1+√−19$% 2,26 −55 #1+√−19$% 2}−bezrels[[1,1]]"

0

We now generate and work with a signiﬁcantly larger example.

n= 50;

n= 50;

n= 50;

randsqrt = &RandomInteger [10n]/.a Integer√b→√b

randsqrt = &RandomInteger [10n]/.a Integer√b→√b

randsqrt = &RandomInteger [10n]/.a Integer√b→√b

randqints = {RandomInteger [10n,2] .{1,d},RandomInteger [10n,2] .{1,d}}

randqints = {RandomInteger [10n,2] .{1,d},RandomInteger [10n,2] .{1,d}}

randqints = {RandomInteger [10n,2] .{1,d},RandomInteger [10n,2] .{1,d}}

Strong Gr¨obner bases 383

√76645210216068275341252449427250942042565641503899

{41230119139644742056691832704420484800325317097349+

66637694434836005939093652315806699696521110837633d,

29376606053454810686236077314995219308578051470644+

68102540162537581922579541354979200541266074057948d}

Timing[bezrels = bezout[d, Sequence@@randqints,randsqrt2]; ]

Timing[bezrels = bezout[d, Sequence@@randqints,randsqrt2]; ]

Timing[bezrels = bezout[d, Sequence@@randqints,randsqrt2]; ]

{0.013998, Null}

In the special case where the ideal is {1}, (e.g. {x, y }generates the entire ring),

then we actually have obtained an extended GCD. More generally it is easy to show

that when there is a GCD and it is a rational integer, or else there is no rational

integer in the ideal, then the above code ﬁnds that GCD and the corresponding

Bezout relation. In other cases one would need to do further work to either recover

a GCD or else (in the case where the class number of the quadratic ring is not 1)

show that no GCD exists. See [28], [18] for further details. We show below a simple

approach that works in many situations. We work with d=√53719.

sqrt = Sqrt[53719];

sqrt = Sqrt[53719];

sqrt = Sqrt[53719];

qints = {73609 + 15577d, 2991 + 6417d};

qints = {73609 + 15577d, 2991 + 6417d};

qints = {73609 + 15577d, 2991 + 6417d};

bezrels = bezout[d, Sequence@@qints,sqrt2]

bezrels = bezout[d, Sequence@@qints,sqrt2]

bezrels = bezout[d, Sequence@@qints,sqrt2]

{{1+√53719,{14462895 −3265382√53719,−1344274 + 7923502√53719}},

{6,{1128711 −254907√53719,−104180 + 618536√53719}}}

We have reduced the ideal sum to one generated by #1+√53719,6$. There is

in fact a GCD, though, because the ring Z!√53719"is a principal ideal domain

(this follows from the fact that √53719 has class number of 1). Checking norms

shows that any common factor of 6 and 1 + √53719 will have a norm of 6 or -

6. Thus we have a Pell type of equation to solve: ﬁnd integers {a, b}such that

(6a+b)2−53719b2=±6. Well known facts about such equations tell us that any

solution will have (6a+b)/b as a convergent to the continued fraction expansion of

√53719. We remark that for this method to work, we require that the right hand

side, ±6 in this case, have absolute value less than √53719.

cf = ContinuedFraction !√53719";

cf = ContinuedFraction !√53719";

cf = ContinuedFraction !√53719";

frax = Convergents[cf];

frax = Convergents[cf];

frax = Convergents[cf];

solns1 = Table[Solve[

solns1 = Table[Solve[

solns1 = Table[Solve[

{(6 ∗a+b)2−53719 ∗b2== 6,(6 ∗a+b)/b == frax[[j]]},{a, b}],{j, Length[frax]}];

{(6 ∗a+b)2−53719 ∗b2== 6,(6 ∗a+b)/b == frax[[j]]},{a, b}],{j, Length[frax]}];

{(6 ∗a+b)2−53719 ∗b2== 6,(6 ∗a+b)/b == frax[[j]]},{a, b}],{j, Length[frax]}];

solns2 = Table[Solve[

solns2 = Table[Solve[

solns2 = Table[Solve[

{(6 ∗a+b)2−53719 ∗b2== −6,(6 ∗a+b)/b == frax[[j]]},{a, b}],{j, Length[frax]}];

{(6 ∗a+b)2−53719 ∗b2== −6,(6 ∗a+b)/b == frax[[j]]},{a, b}],{j, Length[frax]}];

{(6 ∗a+b)2−53719 ∗b2== −6,(6 ∗a+b)/b == frax[[j]]},{a, b}],{j, Length[frax]}];

Cases[Flatten[{a, b}/.solns1,1],{xInteger,y Integer}]

Cases[Flatten[{a, b}/.solns1,1],{xInteger,y Integer}]

Cases[Flatten[{a, b}/.solns1,1],{xInteger,y Integer}]

{}

Cases[Flatten[{a, b}/.solns2,1],{xInteger,y Integer}]

Cases[Flatten[{a, b}/.solns2,1],{xInteger,y Integer}]

Cases[Flatten[{a, b}/.solns2,1],{xInteger,y Integer}]

384 D. Lichtblau

{{−3428948410941086922003618340136587439827999302403486

984497710688926584615684288776613161602832,

−891509721403085091303569452219823749022330292638348842

55241520937582267870954684338850528243},

{342894841094108692200361834013658743982799930240348698

4497710688926584615684288776613161602832,

8915097214030850913035694522198237490223302926383488425

5241520937582267870954684338850528243}}

We have found a GCD.

gcd = Expand[

gcd = Expand[

gcd = Expand[

{342894841094108692200361834013658743982799930240348

{342894841094108692200361834013658743982799930240348

{342894841094108692200361834013658743982799930240348

6984497710688926584615684288776613161602832,

6984497710688926584615684288776613161602832,

6984497710688926584615684288776613161602832,

8915097214030850913035694522198237490223302926383488

8915097214030850913035694522198237490223302926383488

8915097214030850913035694522198237490223302926383488

4255241520937582267870954684338850528243}.

4255241520937582267870954684338850528243}.

4255241520937582267870954684338850528243}.

{6,1+√53719}]

{6,1+√53719}]

{6,1+√53719}]

2066284143778683004115206698604150701387022884368475679

1241505654497089961976687344017820145235+

8915097214030850913035694522198237490223302926383488425

5241520937582267870954684338850528243√53719

We conﬁrm that the norm is indeed -6.

Expand !gcd ∗#gcd /.√53719->−√53719$"

Expand !gcd ∗#gcd /.√53719->−√53719$"

Expand !gcd ∗#gcd /.√53719->−√53719$"

−6

8 Summary

We have presented several applications of Gr¨obner bases over Euclidean domains.

The ﬁrst ones showed how to work over quotient rings of Euclidean rings. Next

we provided an algorithm, using Gr¨obner bases over Euclidean domains, to perform

Hensel lifting of polynomial factors modulo powers of a prime ideal. We proceeded to

compute matrix Hermite and weak Popov normal forms, and showed an application

of these to multivariate modular factorization. We ﬁnished with an example showing

nontrivial computations in quadratic number rings.

While many of these applications are specialized, in the sense that good methods

are available that do not require Gr¨obner bases, it is all the same nice to have the

methods given herein. One reason is that the code is simple and also ﬂexible should

modiﬁcations be desired. Another is that the methods presented here perform rea-

sonably well on many problems that are of nontrivial size. Perhaps most interesting

is that several fundamental computations in computer algebra, such as Hensel lift-

ing, matrix canonical forms, and polynomial lattice reduction, as well as interplay

Strong Gr¨obner bases 385

between these, may be cast as either Gr¨obner bases computations over Euclidean

domains or close relatives thereof.

ACKNOWLEDGEMENTS.

I thank Michael Trott for drawing my attention to the article by Dolzmann and

Sturm, as well as referees for beneﬁcial comments on prior drafts of this work.

9 Code Appendix

Here we create the polynomial of degree 190 that we use in section 3.

poly1 = x20 −5x18 + 864x15 −375x14 −2160x13 + 1875x12 + 10800x11 + 186624x10−

poly1 = x20 −5x18 + 864x15 −375x14 −2160x13 + 1875x12 + 10800x11 + 186624x10−

poly1 = x20 −5x18 + 864x15 −375x14 −2160x13 + 1875x12 + 10800x11 + 186624x10−

54000x9+ 46875x8+ 270000x7−234375x6−2700000x5−1953125x2+ 9765625;

54000x9+ 46875x8+ 270000x7−234375x6−2700000x5−1953125x2+ 9765625;

54000x9+ 46875x8+ 270000x7−234375x6−2700000x5−1953125x2+ 9765625;

rts = x/.Solve[poly1==0,x];

rts = x/.Solve[poly1==0,x];

rts = x/.Solve[poly1==0,x];

sums = Flatten[Table[rts[[i]] + rts[[j]],{i, 19},{j, i +1,20}]];

sums = Flatten[Table[rts[[i]] + rts[[j]],{i, 19},{j, i +1,20}]];

sums = Flatten[Table[rts[[i]] + rts[[j]],{i, 19},{j, i +1,20}]];

newpoly = Expand[Times@@(x−N[sums,200])];

newpoly = Expand[Times@@(x−N[sums,200])];

newpoly = Expand[Times@@(x−N[sums,200])];

newpoly = Chop[newpoly]/.a Real →Round[a];

newpoly = Chop[newpoly]/.a Real →Round[a];

newpoly = Chop[newpoly]/.a Real →Round[a];

Here is the code for quadratic Hensel lifting of polynomial factors from Zp[x]. It

is an important step in ﬁnding factors in Z[x].

liftfactors[fax ,poly ,mod ,pow ]:=Module[

liftfactors[fax ,poly ,mod ,pow ]:=Module[

liftfactors[fax ,poly ,mod ,pow ]:=Module[

{modpow = mod,top = Ceiling[Log[2,pow]],liftedfax = fax},

{modpow = mod,top = Ceiling[Log[2,pow]],liftedfax = fax},

{modpow = mod,top = Ceiling[Log[2,pow]],liftedfax = fax},

Do[modpow = If[j== top,modpow,modpow2];

Do[modpow = If[j== top,modpow,modpow2];

Do[modpow = If[j== top,modpow,modpow2];

liftedfax = Expand[liftedfax2,Modulus →modpow];

liftedfax = Expand[liftedfax2,Modulus →modpow];

liftedfax = Expand[liftedfax2,Modulus →modpow];

liftedfax = Map[Last[GroebnerBasis[{modpow,poly,#},

liftedfax = Map[Last[GroebnerBasis[{modpow,poly,#},

liftedfax = Map[Last[GroebnerBasis[{modpow,poly,#},

CoeﬃcientDomain →Integers]]&,liftedfax],{j, top}];

CoeﬃcientDomain →Integers]]&,liftedfax],{j, top}];

CoeﬃcientDomain →Integers]]&,liftedfax],{j, top}];

liftedfax]

liftedfax]

liftedfax]

Here is code to create a random matrix of univariate polynomials over the inte-

gers.

randomPolynomial[deg Integer,var ]:=Table [varj,{j, 0,deg}].

randomPolynomial[deg Integer,var ]:=Table [varj,{j, 0,deg}].

randomPolynomial[deg Integer,var ]:=Table [varj,{j, 0,deg}].

RandomInteger[{−10,10},deg +1]

RandomInteger[{−10,10},deg +1]

RandomInteger[{−10,10},deg +1]

randomMatrix[degmax ,rows ,cols ,var ]:=Module[{deg},

randomMatrix[degmax ,rows ,cols ,var ]:=Module[{deg},

randomMatrix[degmax ,rows ,cols ,var ]:=Module[{deg},

Table[deg = RandomInteger[{0,degmax}];

Table[deg = RandomInteger[{0,degmax}];

Table[deg = RandomInteger[{0,degmax}];

randomPolynomial[deg,var],{rows},{cols}]]

randomPolynomial[deg,var],{rows},{cols}]]

randomPolynomial[deg,var],{rows},{cols}]]

randomSystem[degmax ,rows ,cols ,var ]:=

randomSystem[degmax ,rows ,cols ,var ]:=

randomSystem[degmax ,rows ,cols ,var ]:=

{randomMatrix[degmax,rows,cols,var],

{randomMatrix[degmax,rows,cols,var],

{randomMatrix[degmax,rows,cols,var],

Table[randomPolynomial[degmax,var],{rows}]}

Table[randomPolynomial[degmax,var],{rows}]}

Table[randomPolynomial[degmax,var],{rows}]}

Next is our workhorse for computing Gr¨obner bases over modules.

moduleGroebnerBasis[polys ,vars ,cvars ,opts ]:=Module[

moduleGroebnerBasis[polys ,vars ,cvars ,opts ]:=Module[

moduleGroebnerBasis[polys ,vars ,cvars ,opts ]:=Module[

{newpols,rels,len = Length[cvars],gb, j, k, ruls},

{newpols,rels,len = Length[cvars],gb, j, k, ruls},

{newpols,rels,len = Length[cvars],gb, j, k, ruls},

386 D. Lichtblau

rels = Flatten[Table[cvars[[j]] ∗cvars[[k]],{j, len},{k, j, len}]];

rels = Flatten[Table[cvars[[j]] ∗cvars[[k]],{j, len},{k, j, len}]];

rels = Flatten[Table[cvars[[j]] ∗cvars[[k]],{j, len},{k, j, len}]];

newpols = Join[polys,rels];

newpols = Join[polys,rels];

newpols = Join[polys,rels];

gb = GroebnerBasis[newpols,Join[cvars,vars],opts];

gb = GroebnerBasis[newpols,Join[cvars,vars],opts];

gb = GroebnerBasis[newpols,Join[cvars,vars],opts];

rul = Map[(# →{})&,rels];

rul = Map[(# →{})&,rels];

rul = Map[(# →{})&,rels];

gb = Flatten[gb/.rul];

gb = Flatten[gb/.rul];

gb = Flatten[gb/.rul];

Collect[gb,cvars]]

Collect[gb,cvars]]

Collect[gb,cvars]]

We use a module Gr¨obner basis to compute the Hermite normal form of a matrix

over a Euclidean domain.

groebnerHNF[mat ?MatrixQ,domain ,mod :0]:=Module[

groebnerHNF[mat ?MatrixQ,domain ,mod :0]:=Module[

groebnerHNF[mat ?MatrixQ,domain ,mod :0]:=Module[

{len = Length[First[mat]],newvars,generators,mgb},

{len = Length[First[mat]],newvars,generators,mgb},

{len = Length[First[mat]],newvars,generators,mgb},

newvars = Array[v, len];

newvars = Array[v, len];

newvars = Array[v, len];

generators = mat.newvars;

generators = mat.newvars;

generators = mat.newvars;

mgb = moduleGroebnerBasis[generators,{},newvars,

mgb = moduleGroebnerBasis[generators,{},newvars,

mgb = moduleGroebnerBasis[generators,{},newvars,

CoeﬃcientDomain →domain,Modulus →mod];

CoeﬃcientDomain →domain,Modulus →mod];

CoeﬃcientDomain →domain,Modulus →mod];

Outer[D, Reverse[mgb],newvars]]

Outer[D, Reverse[mgb],newvars]]

Outer[D, Reverse[mgb],newvars]]

Given a linear system of equations with univariate polynomials for coeﬃcients,

the code below will return a univariate polynomial solution vector if one exists. It

also computes a basis of univariate polynomial null vectors for the system.

systemSolve[mat ?MatrixQ,rhs ?VectorQ,dom ,mod :0,moduli :{}]/;

systemSolve[mat ?MatrixQ,rhs ?VectorQ,dom ,mod :0,moduli :{}]/;

systemSolve[mat ?MatrixQ,rhs ?VectorQ,dom ,mod :0,moduli :{}]/;

Length[rhs] == Length[mat]:=Module[

Length[rhs] == Length[mat]:=Module[

Length[rhs] == Length[mat]:=Module[

{newmat,modrows,hnf,j =1,len = Length[mat],zeros,solvec,nullvecs},

{newmat,modrows,hnf,j =1,len = Length[mat],zeros,solvec,nullvecs},

{newmat,modrows,hnf,j =1,len = Length[mat],zeros,solvec,nullvecs},

newmat = Prepend[Transpose[mat],rhs];

newmat = Prepend[Transpose[mat],rhs];

newmat = Prepend[Transpose[mat],rhs];

newmat = Transpose[Join[Transpose[newmat],IdentityMatrix[Length[newmat]]]];

newmat = Transpose[Join[Transpose[newmat],IdentityMatrix[Length[newmat]]]];

newmat = Transpose[Join[Transpose[newmat],IdentityMatrix[Length[newmat]]]];

If[moduli +={},modrows =

If[moduli +={},modrows =

If[moduli +={},modrows =

Table[If[j== k, moduli[[j]],0],{j, Length[moduli]},{k, Length[newmat[[1]]]}];

Table[If[j== k, moduli[[j]],0],{j, Length[moduli]},{k, Length[newmat[[1]]]}];

Table[If[j== k, moduli[[j]],0],{j, Length[moduli]},{k, Length[newmat[[1]]]}];

newmat = Join[newmat,modrows]];

newmat = Join[newmat,modrows]];

newmat = Join[newmat,modrows]];

hnf = groebnerHNF[newmat,dom,mod];

hnf = groebnerHNF[newmat,dom,mod];

hnf = groebnerHNF[newmat,dom,mod];

zeros = Table[0,{len}];

zeros = Table[0,{len}];

zeros = Table[0,{len}];

While[j≤Length[hnf]&&Take[hnf[[j]],len]=!=zeros,j++];

While[j≤Length[hnf]&&Take[hnf[[j]],len]=!=zeros,j++];

While[j≤Length[hnf]&&Take[hnf[[j]],len]=!=zeros,j++];

solvec = Drop[hnf[[j]],len + 1]/−hnf[[j, len + 1]];

solvec = Drop[hnf[[j]],len + 1]/−hnf[[j, len + 1]];

solvec = Drop[hnf[[j]],len + 1]/−hnf[[j, len + 1]];

nullvecs = Map[Drop[#,len + 1]&,Drop[hnf,j]];

nullvecs = Map[Drop[#,len + 1]&,Drop[hnf,j]];

nullvecs = Map[Drop[#,len + 1]&,Drop[hnf,j]];

{solvec,nullvecs}]

{solvec,nullvecs}]

{solvec,nullvecs}]

This next code ﬁnds small solutions to integer linear equations, given a particular

solution and a basis for the integer null space.

smallSolution[sol ?VectorQ,nulls ?MatrixQ]:=Module[

smallSolution[sol ?VectorQ,nulls ?MatrixQ]:=Module[

smallSolution[sol ?VectorQ,nulls ?MatrixQ]:=Module[

{max,dim = Length[nulls] + 1,weight,auglat,lat,k,soln},

{max,dim = Length[nulls] + 1,weight,auglat,lat,k,soln},

{max,dim = Length[nulls] + 1,weight,auglat,lat,k,soln},

lat = Prepend[LatticeReduce[nulls],sol];

lat = Prepend[LatticeReduce[nulls],sol];

lat = Prepend[LatticeReduce[nulls],sol];

max = Max[Flatten[Abs[lat]]];

max = Max[Flatten[Abs[lat]]];

max = Max[Flatten[Abs[lat]]];

weight = dim max2;

weight = dim max2;

weight = dim max2;

Strong Gr¨obner bases 387

auglat = Map[Prepend[#,0]&,lat];

auglat = Map[Prepend[#,0]&,lat];

auglat = Map[Prepend[#,0]&,lat];

auglat[[1,1]] = weight;

auglat[[1,1]] = weight;

auglat[[1,1]] = weight;

lat = LatticeReduce[auglat];

lat = LatticeReduce[auglat];

lat = LatticeReduce[auglat];

For[k=1,lat[[k, 1]]==0,k++];

For[k=1,lat[[k, 1]]==0,k++];

For[k=1,lat[[k, 1]]==0,k++];

soln = lat[[k]];

soln = lat[[k]];

soln = lat[[k]];

Which[

Which[

Which[

soln[[1]]==weight,Drop[soln,1],

soln[[1]]==weight,Drop[soln,1],

soln[[1]]==weight,Drop[soln,1],

soln[[1]]== −weight,−Drop[soln,1],

soln[[1]]== −weight,−Drop[soln,1],

soln[[1]]== −weight,−Drop[soln,1],

True,sol]]

True,sol]]

True,sol]]

The following computes a matrix weak Popov normal form. This is also referred

to as a lattice reduction for the case of matrices comprised of univariate polynomials

over a ﬁeld.

polynomialLatticeReduce[mat ?MatrixQ,mod :0]:=Module[

polynomialLatticeReduce[mat ?MatrixQ,mod :0]:=Module[

polynomialLatticeReduce[mat ?MatrixQ,mod :0]:=Module[

{len = Length[First[mat]],newvars,generators,mgb,v},

{len = Length[First[mat]],newvars,generators,mgb,v},

{len = Length[First[mat]],newvars,generators,mgb,v},

newvars = Array[v, len];

newvars = Array[v, len];

newvars = Array[v, len];

generators = mat.newvars;

generators = mat.newvars;

generators = mat.newvars;

mgb = moduleGroebnerBasis[generators,Variables[mat],newvars,

mgb = moduleGroebnerBasis[generators,Variables[mat],newvars,

mgb = moduleGroebnerBasis[generators,Variables[mat],newvars,

CoeﬃcientDomain →Rationals,Modulus →mod,

CoeﬃcientDomain →Rationals,Modulus →mod,

CoeﬃcientDomain →Rationals,Modulus →mod,

MonomialOrder →DegreeReverseLexicographic];

MonomialOrder →DegreeReverseLexicographic];

MonomialOrder →DegreeReverseLexicographic];

Outer[D, mgb,newvars]]

Outer[D, mgb,newvars]]

Outer[D, mgb,newvars]]

Here is code for generating a pseudorandom bivariate polynomial of a given total

degree with coeﬃcients in a given prime ﬁeld.

randomBivariatePoly[deg ,mod ,x,y ]:=

randomBivariatePoly[deg ,mod ,x,y ]:=

randomBivariatePoly[deg ,mod ,x,y ]:=

'deg

i=0 'deg −i

j=0 RandomInteger[{If[i+j== deg &&ij == 0,1,0],mod −1}]xiyj

'deg

i=0 'deg −i

j=0 RandomInteger[{If[i+j== deg &&ij == 0,1,0],mod −1}]xiyj

'deg

i=0 'deg −i

j=0 RandomInteger[{If[i+j== deg &&ij == 0,1,0],mod −1}]xiyj

With modest preprocessing we can use smallSolution to obtain “small” elements

in quadratic rings.

quadraticIntegerToIntegerVector[n1 Integer,alg ]:={n1,0}

quadraticIntegerToIntegerVector[n1 Integer,alg ]:={n1,0}

quadraticIntegerToIntegerVector[n1 Integer,alg ]:={n1,0}

quadraticIntegerToIntegerVector[n1 . + n2 . ∗alg ,alg ]:={n1,n2}

quadraticIntegerToIntegerVector[n1 . + n2 . ∗alg ,alg ]:={n1,n2}

quadraticIntegerToIntegerVector[n1 . + n2 . ∗alg ,alg ]:={n1,n2}

smallSolutionQuadratic[vec ,nulls ,alg ]:=Module[

smallSolutionQuadratic[vec ,nulls ,alg ]:=Module[

smallSolutionQuadratic[vec ,nulls ,alg ]:=Module[

{soln,nulls2},

{soln,nulls2},

{soln,nulls2},

soln = quadraticVectorToIntegerVector[vec,alg];

soln = quadraticVectorToIntegerVector[vec,alg];

soln = quadraticVectorToIntegerVector[vec,alg];

nulls2 = Map[quadraticVectorToIntegerVector[#,alg]&,nulls];

nulls2 = Map[quadraticVectorToIntegerVector[#,alg]&,nulls];

nulls2 = Map[quadraticVectorToIntegerVector[#,alg]&,nulls];

soln = smallSolution[soln,nulls2];

soln = smallSolution[soln,nulls2];

soln = smallSolution[soln,nulls2];

Partition[soln,2]/.{aInteger,b Integer}:>a + alg ∗b]

Partition[soln,2]/.{aInteger,b Integer}:>a + alg ∗b]

Partition[soln,2]/.{aInteger,b Integer}:>a + alg ∗b]

Here is the Bezout relation code.

bezout[d ,m1 Integer,m2 . + n2 . ∗d,tsqr ]:=Module[

bezout[d ,m1 Integer,m2 . + n2 . ∗d,tsqr ]:=Module[

bezout[d ,m1 Integer,m2 . + n2 . ∗d,tsqr ]:=Module[

{theta,polys},

{theta,polys},

{theta,polys},

polys = {m1,m2 + n2 ∗theta};

polys = {m1,m2 + n2 ∗theta};

polys = {m1,m2 + n2 ∗theta};

388 D. Lichtblau

polyBezout[polys,theta, d, tsqr]]

polyBezout[polys,theta, d, tsqr]]

polyBezout[polys,theta, d, tsqr]]

bezout[d ,m2 . + n2 . ∗d,m1 Integer,tsqr ]:=Module[

bezout[d ,m2 . + n2 . ∗d,m1 Integer,tsqr ]:=Module[

bezout[d ,m2 . + n2 . ∗d,m1 Integer,tsqr ]:=Module[

{theta,polys},

{theta,polys},

{theta,polys},

polys = {m2 + n2theta,m1};

polys = {m2 + n2theta,m1};

polys = {m2 + n2theta,m1};

polyBezout[polys,theta, d, tsqr]]

polyBezout[polys,theta, d, tsqr]]

polyBezout[polys,theta, d, tsqr]]

polyBezout[polys ,theta ,d,tsqr ]:=Module[

polyBezout[polys ,theta ,d,tsqr ]:=Module[

polyBezout[polys ,theta ,d,tsqr ]:=Module[

{defpoly,mat,gb,gcd,solns,soln,nulls,relations,subs},

{defpoly,mat,gb,gcd,solns,soln,nulls,relations,subs},

{defpoly,mat,gb,gcd,solns,soln,nulls,relations,subs},

defpoly = If[Mod[tsqr,4] == 1,subs = theta →(1 + Sqrt[tsqr])/2;

defpoly = If[Mod[tsqr,4] == 1,subs = theta →(1 + Sqrt[tsqr])/2;

defpoly = If[Mod[tsqr,4] == 1,subs = theta →(1 + Sqrt[tsqr])/2;

Expand[((2theta −1)2−tsqr)/4],

Expand[((2theta −1)2−tsqr)/4],

Expand[((2theta −1)2−tsqr)/4],

subs = theta →Sqrt[tsqr]; theta2−tsqr];

subs = theta →Sqrt[tsqr]; theta2−tsqr];

subs = theta →Sqrt[tsqr]; theta2−tsqr];

mat = Join[Transpose[Join[{polys},IdentityMatrix[2]]],defpolyIdentityMatrix[3]];

mat = Join[Transpose[Join[{polys},IdentityMatrix[2]]],defpolyIdentityMatrix[3]];

mat = Join[Transpose[Join[{polys},IdentityMatrix[2]]],defpolyIdentityMatrix[3]];

gb = groebnerHNF[mat,Integers];

gb = groebnerHNF[mat,Integers];

gb = groebnerHNF[mat,Integers];

relations = Select[gb,#[[1]]=!=0&&FreeQ[#[[1]],theta ]&];

relations = Select[gb,#[[1]]=!=0&&FreeQ[#[[1]],theta ]&];

relations = Select[gb,#[[1]]=!=0&&FreeQ[#[[1]],theta ]&];

solns = Map[Rest,relations];

solns = Map[Rest,relations];

solns = Map[Rest,relations];

nulls = Map[Rest,Cases[gb,{0,}]];

nulls = Map[Rest,Cases[gb,{0,}]];

nulls = Map[Rest,Cases[gb,{0,}]];

nulls = DeleteCases[nulls,vec /;!FreeQ[vec,theta ]];

nulls = DeleteCases[nulls,vec /;!FreeQ[vec,theta ]];

nulls = DeleteCases[nulls,vec /;!FreeQ[vec,theta ]];

solns = Map[smallSolutionQuadratic[#,nulls,theta]&,solns];

solns = Map[smallSolutionQuadratic[#,nulls,theta]&,solns];

solns = Map[smallSolutionQuadratic[#,nulls,theta]&,solns];

Partition[Riﬄe[Map[First,relations],solns]/.subs,2]]

Partition[Riﬄe[Map[First,relations],solns]/.subs,2]]

Partition[Riﬄe[Map[First,relations],solns]/.subs,2]]

References

[1] K. Aardal, C. A. J. Hurkens, and A. K. Lenstra. Solving a system of linear dio-

phantine equations with lower and upper bounds on the variables. Mathematics

of Operations Research, 25(3):427–442, 2000.

[2] W. Adams and P. Loustaunau. An Introduction to Gr¨obner Bases. American

Mathematical Society, Providence, RI, USA, 1994.

[3] T. Becker, H. Kredel, and V. Weispfenning. Gr¨obner Bases: a Computational

Approach to Commutative Algebra. Springer-Verlag, London, UK, 1993.

[4] W. Blankenship. Algorithm 288: Solution of simultaneous linear diophantine

equations. Communications of the ACM, 9(7):514, 1966.

[5] B. Buchberger. Gr¨obner-Bases: An Algorithmic Method in Polynomial Ideal

Theory., chapter 6, pages 184–232. Reidel Publishing Company, Dodrecht -

Boston - Lancaster, 1985.

[6] M. Caboara and C. Traverso. Eﬃcient algorithms for ideal operations (ex-

tended abstract). In In International Symposium on Symbolic and Algebraic

Computation (ISSAC 99, pages 147–152, 1998.

Strong Gr¨obner bases 389

[7] A. Dolzmann and T. Sturm. Parametric systems of linear congruences. In Com-

puter Algebra in Scientiﬁc Computing. Proceedings of the CASC 2000, pages

149–166. Springer, 2001.

[8] A. Kandri-Rody and D. Kapur. Algorithms for computing Groebner bases of

polynomial ideals over various euclidean rings. In EUROSAM, pages 195–206,

1984.

[9] A. Kandri-Rody and D. Kapur. Computing a Gr¨obner basis of a polynomial

ideal over a euclidean domain. Journal of Symbolic Computation, 6(1):37–57,

1988.

[10] A. Lenstra, H. L. Jr., and L. Lovasz. Factoring polynomials with rational

coeﬃcients. Mathematische Annalen, 261(4):515–534, 1982.

[11] A. K. Lenstra. Factoring multivariate polynomials over ﬁnite ﬁelds. Journal of

Computer and System Sciences, 30(2):235–248, 1985.

[12] D. Lichtblau. Gr¨obner bases in Mathematica 3.0. The Mathematica Journal,

6(4):81–88, 1996. http://library.wolfram.com/infocenter/Articles/2179/.

[13] D. Lichtblau. Practical computations with Gr¨obner bases.

http://www.math.unm.edu/ACA/1998/sessions.html, 1998.

[14] D. Lichtblau. Making change and ﬁnding repﬁgits: balancing a knapsack. In

ICMS, pages 182–193, 2006.

[15] D. Lichtblau. Polynomial GCD and factorization via approximate Gr¨obner

bases. In Proceedings of the 2010 12th International Symposium on Symbolic

and Numeric Algorithms for Scientiﬁc Computing, SYNASC ’10, pages 29–36,

Washington, DC, USA, 2010. IEEE Computer Society.

[16] D. Lichtblau. Eﬀective computation of strong Gr¨obner bases over euclidean

domains. to appear, Illinois Journal of Mathematics, 2013.

[17] K. Matthews. Short solutions of A X=B using a LLL-based Hermite normal

form algorithm. Manuscript, 2001.

[18] A. Miled and A. Ouertani. Extended gcd of quadratic integers.

http://arxiv.org/abs/1002.4487, 2010.

[19] H. M. M¨oller. On the construction of Gr¨obner bases using syzygies. J. Symb.

Comput., 6(2-3):345–359, 1988.

[20] T. Mulders and A. Storjohann. Diophantine linear system solving. In In Inter-

national Symposium on Symbolic and Algebraic Computation (ISSAC 99, pages

181–188. ACM Press, 1999.

390 D. Lichtblau

[21] T. Mulders and A. Storjohann. On lattice reduction for polynomial matrices.

Journal of Symbolic Computation, 35(4):377–401, 2003.

[22] P. Nguyen. Cryptanalysis of the Goldreich-Goldwasser-Halevi cryptosystem

from Crypto ’97. In Proceedings of Advances in Cryptology - CRYPTO ’99,

volume 1666 of Lecture Notes in Computer Science, pages 288–304. Springer-

Verlag, 1999.

[23] L. Pan. On the D-bases of polynomial ideals over principal ideal domains. J.

Symb. Comput., 7(1):55–69, 1989.

[24] C. Sims. Computation with Finitely Presented Groups. Cambridge University

Press, 1994.

[25] A. Storjohann. Computation of Hermite and Smith Normal Forms of Matri-

ces. University of Waterloo, 1994. Master’s Thesis, University of Waterloo

Deptartment of Computer Science.

[26] M. van Hoeij. Factoring polynomials and the knapsack problem. Journal of

Number Theory, 95(2):167–189, 2002.

[27] J. von zur Gathen and J. Gerhard. Modern Computer Algebra. Cambridge

University Press, New York, NY, USA, 2003.

[28] A. Weilert. Two eﬃcient algorithms for the computation of ideal sums in

quadratic orders. Mathematics of Computation, 75(254):941–981, 2006.

[29] I. Wolfram Research. Mathematica 9, 2012.

[30] P. Zimmermann. Polynomial factorization challenges: a collection of polyno-

mials diﬃcult to factor, 2003. http://www.loria.fr/ zimmerma/mupad/.

Received: March 9, 2013