Karim Belabas on Wed, 10 Apr 2019 12:07:44 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: Fast test for integer-rooted polynomial


Hello,

  here's my take on this:

1) about the characteristic polynomial: I don't see how to improve that step.
For such small matrices as the one presented, it doesn't help to compute it
modulo a prime (we use a multimodular algorithm which in practice stops after
a single prime...)

2) instead of factor(p) + couting irreducible factors, you could use
nfroots(,p) [ notice the comma "," ! ] then sum valuations. But since
your roots are heavily constrained, you can just directly sum valuations :

test2(a) = my(p = charpoly(a)); sum(i = 0, #a, valuation(p, x-i)) == #a;

On your given input I get

(11:52) gp > for(i=1,10^5,test(a))
time = 4680 ms.

(11:52) gp > for(i=1,10^5,test2(a))
time = 1604 ms.

So you can expect to test ~ 62k matrices per second. A direct C
implementation would probably optimize the valuations test to essentially 0
(i.e. a global speedup of about a factor 2, see below).

Another possibility would be to replace p = charpoly(a) by p /= gcd(p,p')
and test that if you expect many multiple roots. But it doesn't gain much
in your example, since timings decompose as follows:

(11:52) gp > for(i=1,10^5, ) \\ loop overhead
time = 4 ms.
(11:52) gp > for(i=1,10^5, p = charpoly(a))
time = 656 ms.
(12:53) gp > for(i=1,10^5, sum(i = 0, 9, valuation(p, x-i)))
time = 877 ms.

(12:53) gp > for(i=1,10^5, q = gcd(p,p'))
time = 373 ms.
(12:53) gp > for(i=1,10^5, sum(i = 0, 9, valuation(q, x-i)))
time = 464 ms.

Cheers,

    K.B.


* Denis Simon [2019-04-10 11:30]:
> Hi Gordon, 
> 
> writing your test as a function, this looks like 
> 
> test(a) = my(p,f); p=charpoly(a);f=factor(p);vecmax(apply(poldegree,f[,1]))==1 
> 
> If your matrices have a high probability to fail the test, then you could 
> do a first check modulo a prime : 
> 
> testp(a) = my(p,f); p=charpoly(a);f1=factormod(p,31,1);if(vecsum(f1[,2])<#a,0,f=factor(p);vecmax(apply(poldegree,f[,1]))==1) 
> 
> Denis SIMON. 
> 
> > De: "Watson Ladd" <watsonbladd@gmail.com>
> > À: "Gordon Royle" <gordon.royle@uwa.edu.au>
> > Cc: "pari-users" <pari-users@pari.math.u-bordeaux.fr>
> > Envoyé: Mercredi 10 Avril 2019 03:15:48
> > Objet: Re: Fast test for integer-rooted polynomial
> 
> > On Tue, Apr 9, 2019, 6:10 PM Gordon Royle < [ mailto:gordon.royle@uwa.edu.au |
> > gordon.royle@uwa.edu.au ] > wrote:
> 
> >> Dear Pari/GP users
> 
> >> This is a very simple task, but I want to do it billions of times, and so I want
> >> it to be as fast as possible.
> 
> >> I have written a suitable Pari/GP routine to do it, but just naively, and I
> >> wonder if there is a clever way to do it.
> 
> >> INPUT: Billions of symmetric matrices of smallish order (say at most 16 x 16)
> >> each of which has small integer entries.
> 
> >> OUTPUT: The input matrices that have only integer eigenvalues.
> 
> >> From the nature of the problem, I know that any integer eigenvalues lie in
> >> {0,1,2, …, n} where n is the order of the matrix.
> 
> >> What I do currently:
> 
> >> - get Pari to compute the characteristic polynomial (charpoly())
> >> - factor the characteristic polynomial
> >> - check that the factors are all linear
> 
> >> Here is an example:
> 
> >> a=
> >> [7,0,-1,-1,-1,-1,-1,-1,-1; 0,7,-1,-1,-1,-1,-1,-1,-1; -1,-1,7,0,-1,-1,-1,-1,-1;
> >> -1,-1,0,7,-1,-1,-1,-1,-1; -1,-1,-1,-1,7,0,-1,-1,-1; -1,-1,-1,-1,0,4,0,0,0;
> >> -1,-1,-1,-1,-1,0,7,-1,-1; -1,-1,-1,-1,-1,0,-1,7,-1; -1,-1,-1,-1,-1,0,-1,-1,7]
> >> p=charpoly(a)
> >> f=factor(p)
> >> print(f)
> 
> >> produces
> 
> >> [x - 9, 2; x - 8, 3; x - 7, 2; x - 4, 1; x, 1]
> 
> >> showing that the eigenvalues are just 9, 9, 8, 8, 8, 7, 7, 4, 0 which are
> >> integers as required.
> 
> >> This works fine, but of course, faster is better, which leads me to my
> >> questions:
> 
> >> Q1: Is there perhaps a better way to compute the char poly, such as the other
> >> methods supplied by Pari, perhaps using the flag=4 option to take advantage of
> >> the integer entries?
> 
> >> Q2: Is there perhaps a better way to check that the polynomial is a product of
> >> linear factors without actually factorising it? For example, for each i in
> >> {0,1,2, …, n}, check if p(i) = 0 and then divide by (x-i) if so. Repeat.
> 
> >> Q3: Or is there a way to check the eigenvalues without even computing the
> >> characteristic polynomial? (I looked at qfjacobi but it returns floating point
> >> numbers for the eigenvalues)
> 
> >> Thanks in advance for any suggestions
> 
> >> Gordon
> 
> > Why not compute the characteristic polynomial and then evaluate at 16 points and
> > compute multiplicaties via the derivative?

    K.B.
--
Karim Belabas, IMB (UMR 5251)  Tel: (+33) (0)5 40 00 26 17
Universite de Bordeaux         Fax: (+33) (0)5 40 00 21 23
351, cours de la Liberation    http://www.math.u-bordeaux.fr/~kbelabas/
F-33405 Talence (France)       http://pari.math.u-bordeaux.fr/  [PARI/GP]
`