def kron_solve(B, A, Y): from scipy.linalg.lapack import dgetrf, dgetrs V = Y.space X = StencilVector(V) [s1, s2] = V.starts [e1, e2] = V.ends [p1, p2] = V.pads n1 = e1 - s1 + 1 n2 = e2 - s2 + 1 Vt = StencilVectorSpace([n2, n1], [p2, p1], [False, False]) Xt = StencilVector(Vt) # A is n1xn1 matrix # B is n2xn2 matrix A_arr = A.toarray() B_arr = B.toarray() A_lu, A_piv, A_finfo = dgetrf(A_arr) B_lu, B_piv, B_finfo = dgetrf(B_arr) for i2 in range(n2): Xt[i2, 0:n1], A_sinfo = dgetrs(A_lu, A_piv, Y[0:n1, i2]) for i1 in range(n1): X[i1, 0:n2], B_infos = dgetrs(B_lu, B_piv, Xt[0:n2, i1]) return X
def _solve_lu(fac, piv, b): ''' Solves the system of equations `Ax = b` given the LU factorization of `A`. Uses the `dgetrs` routine. Parameters ---------- fac : (n, n) float array piv : (n,) int array b : (n, *) float array Returns ------- (n, *) float array ''' # handle the case of an array with zero-length for an axis. if any(i == 0 for i in b.shape): return np.zeros(b.shape) x, info = dgetrs(fac, piv, b) if info != 0: raise ValueError('the %s-th argument had an illegal value' % -info) return x
def predict(self, Xstar): """Predicts the output for the supplied input data.""" assert len(Xstar.shape) == 1 or len(Xstar.shape) == 2 assert Xstar.shape[-1] == self.n if Xstar.ndim == 2: Phistar = self.mapping.evaluate(Xstar) # see Bishop, p. 174, 3.58 mean = numpy.dot(Phistar, self.W) # see Bishop, p. 174, 3.59 # see Rasmussen, p. 30, 2.11 sigma_n2 = self.sigma_n * self.sigma_n vT, info = dgetrs(self.L, numpy.arange(self.L.shape[0]), Phistar.T, trans=1, overwrite_b=1) assert info == 0, 'scipy.linalg.lapack.dgetrs(L, Phi*)' var = numpy.empty((Xstar.shape[0], self.W.shape[1])) var = sigma_n2 * (1. + inner1d(vT.T, vT.T))[:, numpy.newaxis] return mean, var else: mean, var = self.predict(Xstar[None, :]) return mean[0], var[0]
def solve(A, b): ''' Solves the system of equations *Ax = b* using the LU routines *dgetrf* and *dgetrs*. Parameters ---------- A : (N,N) float array b : (N,*) float array ''' if any(i == 0 for i in b.shape): return np.zeros(b.shape) lu, piv, info = dgetrf(A) # I am too lazy to look up the error codes if info != 0: raise np.linalg.LinAlgError( 'LAPACK routine *dgetrf* exited with error code %s' % info) x, info = dgetrs(lu, piv, b) if info != 0: raise np.linalg.LinAlgError( 'LAPACK routine *dgetrs* exited with error code %s' % info) return x
def _solve_lu(fac, piv, b): ''' Solves `Ax = b` given the LU factorization of `A` using `dgetrs` ''' if any(i == 0 for i in b.shape): return np.zeros(b.shape, dtype=float) x, info = dgetrs(fac, piv, b) if info < 0: raise ValueError('the %s-th argument had an illegal value' % -info) return x
def train(self, X, Y): """Trains the machine on the supplied set of inputs and outputs.""" assert X.shape[0] == Y.shape[0] assert len(X.shape) == len(Y.shape) == 2 assert X.shape[1] == self.n assert Y.shape[1] == self.p self.X = X self.Y = Y self.Phi = self.mapping.evaluate(self.X) m, n = self.Phi.shape sigma_n2 = self.sigma_n * self.sigma_n self.L = numpy.dot(self.Phi.T, self.Phi) idx = numpy.diag_indices(self.Phi.shape[1]) self.L[idx] += sigma_n2 self.up = 0 self.L, info = dpotrf(self.L, lower=self.up, clean=1, overwrite_a=1) self.B = numpy.dot(self.Phi.T, self.Y) self.LPhiY, info = dgetrs(self.L, numpy.arange(self.L.shape[0]), self.B, trans=1, overwrite_b=1) assert info == 0, 'scipy.linalg.lapack.dgetrs(L, B)' self.W, info = dgetrs(self.L, numpy.arange(self.L.shape[0]), self.LPhiY, trans=0, overwrite_b=0) assert info == 0, 'scipy.linalg.lapack.dgetrs(L, LPhiY)' self.lml = -0.5 * ((1. / (sigma_n2)) * (inner1d(self.Y.T, self.Y.T) - inner1d(self.LPhiY.T, self.LPhiY.T)) + (m - n) * numpy.log(sigma_n2) + m * numpy.log(2. * numpy.pi)) - \ numpy.log(self.L.diagonal()).sum()
def _lapack_solve(A, b): ''' Solves the system of equations Ax=b, using the lapack LU routines. This is faster than np.linalg.solve because it does fewer checks. A and b must be double precision numpy arrays ''' lu, piv, info = dgetrf(A, overwrite_a=True) if info != 0: raise np.linalg.LinAlgError( 'LAPACK routine dgetrf exited with error code %s' % info) x, info = dgetrs(lu, piv, b, overwrite_b=True) if info != 0: raise np.linalg.LinAlgError( 'LAPACK routine dgetrs exited with error code %s' % info) return x
def lmlgradient(self): """Computes the gradient of the log marginal likelihood given the trained state and the hyperpriors.""" LPhi, info = dgetrs(self.L, numpy.arange(self.L.shape[0]), self.Phi.T, trans=1, overwrite_b=0) assert info == 0, 'scipy.linalg.lapack.dgetrs(L, Phi.T)' A2 = (1. / self.sigma_n) * LPhi.T LPhiY = numpy.dot(LPhi, self.Y) sigma_n2 = self.sigma_n * self.sigma_n A1 = (1. / sigma_n2) * (self.Y - numpy.dot(LPhi.T, LPhiY)) mapgrad = self.mapping.gradient(self.Phi, self.X, A1, A2, self.sigma_n) grad = self.sigma_n * (inner1d(A1.T, A1.T) + inner1d(A2.T, A2.T).sum()) - \ self.Phi.shape[0] * (1. / self.sigma_n) grad = grad.sum() + self.sigma_n_prior.logpdfgrad( self.sigma_n) / self.sigma_n return numpy.concatenate(([grad], mapgrad.sum(axis=0)))
def calc_eq_g(l, B): L = B.shape[0] order = (np.arange(L) + l) % L Q, jpvt, tau, work, info = dgeqp3(B[order[0]] if L % 2 == 1 else np.dot(B[order[1]], B[order[0]])) d = Q.diagonal().copy() d[d == 0.0] = 1.0 T = ((np.triu(Q).T / d).T)[:, jpvt.argsort()] for m in range((1 if L % 2 == 1 else 2), L, 2): W, work, info = dormqr("R", "N", Q, tau, np.dot(B[order[m + 1]], B[order[m]]), work.shape[0]) W *= d jpvt = (W * W).sum(0).argsort()[::-1] Q, tau, work, info = dgeqrf(W[:, jpvt]) d[...] = Q.diagonal() d[d == 0.0] = 1.0 T = np.dot((np.triu(Q).T / d).T, T[jpvt, :]) N = B.shape[1] invDb = np.zeros((N, N)) for i in range(N): invDb[i, i] = 1.0 / d[i] if np.abs(d[i]) > 1.0 else 1.0 invDbQT, work, info = dormqr("R", "T", Q, tau, invDb, work.shape[0]) for i in range(N): if np.abs(d[i]) <= 1.0: T[i, :] *= d[i] T += invDbQT T_LU, piv, info = dgetrf(T) sign = 1 for i in range(N): if (T_LU[i, i] < 0) ^ (piv[i] != i) ^ (invDb[i, i] < 0) ^ (tau[i] > 0): sign *= -1 G, info = dgetrs(T_LU, piv, invDbQT) return G, sign
things. We are going to compare the low-level LAPACK functions degtrf and dgetrs to the built in scipy LU routines. """ from numpy import array from scipy.linalg import lu_solve, lu_factor from scipy.linalg.lapack import dgetrf, dgetrs from numpy.random import random import time # Make arrays NUM_ITER = 10 N = 1024 A = random((N,N)) b = random((N,1)) # Solve using scipy.linalg start = time.time() for it in range(NUM_ITER): (LU_and_piv) = lu_factor(A) (x) = lu_solve(LU_and_piv, b) stop = time.time() print "Time for scipy routine is", (stop - start)/NUM_ITER # Solve using scipy.linalg.lapack start = time.time() for it in range(NUM_ITER): (LU, piv, info) = dgetrf(A) (x) = dgetrs(LU, piv, b) stop = time.time() print "Time for LAPACK routine is", (stop - start)/NUM_ITER