Archived
5
0

Added symmetric poweriterations to sandbox

This commit is contained in:
2007-12-12 22:08:55 +00:00
parent 0956581c42
commit 1103245d85
10 changed files with 851 additions and 172 deletions

@ -30,7 +30,7 @@ class get_matvec:
if isinstance(obj, sb.ndarray):
self.callfunc = self.type1
return
meth = getattr(obj,self.methname,None)
meth = getattr(obj, self.methname, None)
if not callable(meth):
raise ValueError, "Object must be an array "\
"or have a callable %s attribute." % (self.methname,)
@ -48,12 +48,12 @@ class get_matvec:
return sb.dot(self.obj.A, x)
def type2(self, x):
return self.obj(x,*self.args)
return self.obj(x, *self.args)
def eigen(A,k=6,M=None,ncv=None,which='LM',
maxiter=None,tol=0, return_eigenvectors=True):
""" Return k eigenvalues and eigenvectors of the matrix A.
def eigen(A, k=6, M=None, ncv=None, which='LM',
maxiter=None, tol=0, return_eigenvectors=True, v0=None):
"""Return k eigenvalues and eigenvectors of the matrix A.
Solves A * x[i] = w[i] * x[i], the standard eigenvalue problem for
w[i] eigenvalues with corresponding eigenvectors x[i].
@ -69,6 +69,7 @@ def eigen(A,k=6,M=None,ncv=None,which='LM',
M -- (Not implemented)
A symmetric positive-definite matrix for the generalized
eigenvalue problem A * x = w * M * x
v0 -- Initial starting solution (n x 1)
Outputs:
@ -99,8 +100,8 @@ def eigen(A,k=6,M=None,ncv=None,which='LM',
"""
try:
n,ny=A.shape
n==ny
n, ny = A.shape
n == ny
except:
raise AttributeError("matrix is not square")
if M is not None:
@ -108,12 +109,12 @@ def eigen(A,k=6,M=None,ncv=None,which='LM',
# some defaults
if ncv is None:
ncv=2*k+1
ncv=min(ncv,n)
if maxiter==None:
maxiter=n*10
ncv = 2*k + 1
ncv = min(ncv, n)
if maxiter == None:
maxiter = n*10
# guess type
# guess type
resid = sb.zeros(n,'f')
try:
typ = A.dtype.char
@ -129,7 +130,7 @@ def eigen(A,k=6,M=None,ncv=None,which='LM',
raise ValueError("k must be less than rank(A), k=%d"%k)
if maxiter <= 0:
raise ValueError("maxiter must be positive, maxiter=%d"%maxiter)
whiches=['LM','SM','LR','SR','LI','SI']
whiches = ['LM','SM','LR','SR','LI','SI']
if which not in whiches:
raise ValueError("which must be one of %s"%' '.join(whiches))
if ncv > n or ncv < k:
@ -141,17 +142,26 @@ def eigen(A,k=6,M=None,ncv=None,which='LM',
eigextract = _arpack.__dict__[ltr+'neupd']
matvec = get_matvec(A)
v = sb.zeros((n,ncv),typ) # holds Ritz vectors
resid = sb.zeros(n,typ) # residual
workd = sb.zeros(3*n,typ) # workspace
workl = sb.zeros(3*ncv*ncv+6*ncv,typ) # workspace
iparam = sb.zeros(11,'int') # problem parameters
ipntr = sb.zeros(14,'int') # pointers into workspaces
info = 0
v = sb.zeros((n, ncv), typ) # holds Ritz vectors
if v0 == None:
resid = sb.zeros(n, typ) # residual
info = 0
else: # starting vector is given
nn, kk = v0.shape
if nn != n:
raise ValueError("starting vector must be: (%d, 1), got: (%d, %d)" %(n, nn, kk))
resid = v0[:,0].astype(typ)
info = 1
workd = sb.zeros(3*n, typ) # workspace
workl = sb.zeros(3*ncv*ncv+6*ncv, typ) # workspace
iparam = sb.zeros(11, 'int') # problem parameters
ipntr = sb.zeros(14, 'int') # pointers into workspaces
ido = 0
if typ in 'FD':
rwork = sb.zeros(ncv,typ.lower())
rwork = sb.zeros(ncv, typ.lower())
# only supported mode is 1: Ax=lx
ishfts = 1
@ -160,7 +170,7 @@ def eigen(A,k=6,M=None,ncv=None,which='LM',
iparam[0] = ishfts
iparam[2] = maxiter
iparam[6] = mode1
while True:
if typ in 'fd':
ido,resid,v,iparam,ipntr,info =\
@ -173,9 +183,9 @@ def eigen(A,k=6,M=None,ncv=None,which='LM',
if (ido == -1 or ido == 1):
# compute y = A * x
xslice = slice(ipntr[0]-1, ipntr[0]-1+n)
yslice = slice(ipntr[1]-1, ipntr[1]-1+n)
workd[yslice]=matvec(workd[xslice])
xslice = slice(ipntr[0] - 1, ipntr[0] - 1 + n)
yslice = slice(ipntr[1] - 1, ipntr[1] - 1 + n)
workd[yslice] = matvec(workd[xslice])
else: # done
break
@ -233,7 +243,7 @@ def eigen(A,k=6,M=None,ncv=None,which='LM',
def eigen_symmetric(A,k=6,M=None,ncv=None,which='LM',
maxiter=None,tol=0, return_eigenvectors=True):
maxiter=None,tol=0, return_eigenvectors=True, v0=None):
""" Return k eigenvalues and eigenvectors of the real symmetric matrix A.
Solves A * x[i] = w[i] * x[i], the standard eigenvalue problem for
@ -253,6 +263,8 @@ def eigen_symmetric(A,k=6,M=None,ncv=None,which='LM',
A symmetric positive-definite matrix for the generalized
eigenvalue problem A * x = w * M * x
v0 -- Starting vector (n, 1)
Outputs:
w -- An real array of k eigenvalues
@ -325,12 +337,22 @@ def eigen_symmetric(A,k=6,M=None,ncv=None,which='LM',
matvec = get_matvec(A)
v = sb.zeros((n,ncv),typ)
resid = sb.zeros(n,typ)
if v0 == None:
resid = sb.zeros(n, typ) # residual
info = 0
else: # starting solution is given
nn, kk = v0.shape
if nn != n:
raise ValueError("starting vectors must be: (%d, %d), got: (%d, %d)" %(n, k, nn, kk))
resid = v0[:,0].astype(typ)
info = 1
#resid = sb.zeros(n,typ)
workd = sb.zeros(3*n,typ)
workl = sb.zeros(ncv*(ncv+8),typ)
iparam = sb.zeros(11,'int')
ipntr = sb.zeros(11,'int')
info = 0
#info = 0
ido = 0
# only supported mode is 1: Ax=lx
@ -340,8 +362,7 @@ def eigen_symmetric(A,k=6,M=None,ncv=None,which='LM',
iparam[0] = ishfts
iparam[2] = maxiter
iparam[6] = mode1
while True:
ido,resid,v,iparam,ipntr,info =\
eigsolver(ido,bmat,which,k,tol,resid,v,iparam,ipntr,