[Matrix-SIG] Polynomial root finding and handy ndgrid construction.

Travis Oliphant Oliphant.Travis@mayo.edu
Wed, 14 Apr 1999 13:44:16 -0500 (CDT)


Here are some handy routines I've been using that others may have interest
in:

A polynomial root finder.

def roots(p):
        """r = roots(p) returns the roots of the polynomial defined in the
        sequence p: p[0] * x**n + p[1] * x**(n-1) + ... + p[n-1] * x + p[n]
        """
        p = asarray(p)
        N = len(p.shape)
        if (len(p.shape) > 1):
                raise ValueError, "Input must be 1-D."

        nz = nonzero(p)
        if len(nz) == 0 :
                return zeros(p.shape)

        # Strip leading zeros and trailing zeros
        # Save trailing zeros as roots
        N = p.shape[0]
        p = p[nz[0]:nz[-1]+1]
        r = zeros(N-nz[-1]-1)

        # Form companion matrix (eigenvalues are roots)
        n = p.shape[0]
        if (n > 1):
                a = diag(ones(p.shape[0]-2),-1)
                a[0,:] = -p[1:]/p[0]
                r = concatenate((r,eig(a)[0]))

        return r


Here's a class that makes constructing N-D grids very easy from an
interactive session.  It overloads the slice selection mechanism so that
the output is the equivalent of what MATLAB's ndgrid function produces.

class NDgrid:
    def __getitem__(self,key):
        try:
	    size = []
	    for k in range(len(key)):
	        step = key[k].step
                if step == None:
                    step = 1.0
                size.append((key[k].stop - key[k].start)/(step*1.0))
	    nn = indices(size,'d')
	    for k in range(len(size)):
                step = key[k].step
                if step == None:
                    step = 1.0
                nn[k] = (nn[k]+key[k].start/(1.0*step))*step
	    return nn
        except:
            return arange(key.start,key.stop,key.step)
	    
    def __getslice__(self,i,j):
        return arange(i,j)


Usage:

>>> nd = NDgrid()   # I put this in my .pythonrc file

>>> nd[0:4:0.5]
array([ 0. ,  0.5,  1. ,  1.5,  2. ,  2.5,  3. ,  3.5])

>>> nd[0:4:0.5,0:5]
array([[[ 0. ,  0. ,  0. ,  0. ,  0. ],
        [ 0.5,  0.5,  0.5,  0.5,  0.5],
        [ 1. ,  1. ,  1. ,  1. ,  1. ],
        [ 1.5,  1.5,  1.5,  1.5,  1.5],
        [ 2. ,  2. ,  2. ,  2. ,  2. ],
        [ 2.5,  2.5,  2.5,  2.5,  2.5],
        [ 3. ,  3. ,  3. ,  3. ,  3. ],
        [ 3.5,  3.5,  3.5,  3.5,  3.5]],
       [[ 0. ,  1. ,  2. ,  3. ,  4. ],
        [ 0. ,  1. ,  2. ,  3. ,  4. ],
        [ 0. ,  1. ,  2. ,  3. ,  4. ],
        [ 0. ,  1. ,  2. ,  3. ,  4. ],
        [ 0. ,  1. ,  2. ,  3. ,  4. ],
        [ 0. ,  1. ,  2. ,  3. ,  4. ],
        [ 0. ,  1. ,  2. ,  3. ,  4. ],
        [ 0. ,  1. ,  2. ,  3. ,  4. ]]])


Regards,

Travis