def sparse_chol(M, perm=None, retF=False, retP=True, retL=True): # Quick check that M is square if M.size[0] != M.size[1]: raise Exception('M must be square.') # Set the factorisation to use LL' instead of LDL' cholmod.options['supernodal'] = 2 if not perm is None: # Make an expression for the factorisation F = cholmod.symbolic(M, p=perm) else: # Make an expression for the factorisation F = cholmod.symbolic(M) # Calculate the factorisation cholmod.numeric(M, F) # Empty factorisation object factorisation = {} if retF: # Calculate the factorisation again (buggy if returning L for # some reason) F2 = cholmod.symbolic(M, p=perm) cholmod.numeric(M, F2) # If we want to return the F object, add it to the dictionary factorisation['F'] = F2 if retP: # Set p to [0,...,n-1] P = cvxopt.matrix(range(M.size[0]), (M.size[0], 1), tc='d') # Solve and replace p with the true permutation used cholmod.solve(F, P, sys=7) # Convert p into an integer array; more useful that way P = cvxopt.matrix(np.array(P).astype(np.int64), tc='i') # If we want to return the permutation, add it to the dictionary factorisation['P'] = P if retL: # Get the sparse cholesky factor L = cholmod.getfactor(F) # If we want to return the factor, add it to the dictionary factorisation['L'] = L # Return P and L return (factorisation)
def proj(y, ip=True): if not ip: y = +y tmp = matrix(0.0, size=(meq, 1)) ypre = +y base.gemv(L,y,tmp,trans='T',\ m = nssq, n = meq, beta = 1) cholmod.solve(LTLi, tmp) base.gemv(L,tmp,y,beta=1.0,alpha=-1.0,trans='N',\ m = nssq, n = meq) if not ip: return y
def eval(obj): try: s = cholmod.options['supernodal'] except KeyError: s = 2 # set to default. cholmod.options['supernodal'] = 0 A = cvxopt.base.sparse(obj) F = cholmod.symbolic(A) cholmod.numeric(A, F) Di = matrix(1.0, (4, 1)) cholmod.solve(F, Di, sys=6) # Reset state. cholmod.options['supernodal'] = s return -sum(cvxopt.base.log(Di))
def eval(obj): try: s = cholmod.options['supernodal'] except KeyError: s = 2 # set to default. cholmod.options['supernodal'] = 0 A = cvxopt.base.sparse(obj) F = cholmod.symbolic(A) cholmod.numeric(A, F) Di = matrix(1.0, (4,1)) cholmod.solve(F, Di, sys=6) # Reset state. cholmod.options['supernodal'] = s return -sum(cvxopt.base.log(Di))
def PLS2D_getBeta(theta, ZtX, ZtY, XtX, ZtZ, XtY, YtX, YtZ, XtZ, YtY, n, P, tinds, rinds, cinds): # Obtain Lambda Lambda = mapping2D(theta, tinds, rinds, cinds) # Obtain Lambda' Lambdat = spmatrix.trans(Lambda) # Obtain Lambda'Z'Y and Lambda'Z'X LambdatZtY = Lambdat * ZtY LambdatZtX = Lambdat * ZtX # Set the factorisation to use LL' instead of LDL' cholmod.options['supernodal'] = 2 # Obtain the cholesky decomposition LambdatZtZLambda = Lambdat * ZtZ * Lambda I = spmatrix(1.0, range(Lambda.size[0]), range(Lambda.size[0])) chol_dict = sparse_chol2D(LambdatZtZLambda + I, perm=P, retF=True, retP=False, retL=False) F = chol_dict['F'] # Obtain C_u (annoyingly solve writes over the second argument, # whereas spsolve outputs) Cu = LambdatZtY[P, :] cholmod.solve(F, Cu, sys=4) # Obtain RZX RZX = LambdatZtX[P, :] cholmod.solve(F, RZX, sys=4) # Obtain RXtRX RXtRX = XtX - matrix.trans(RZX) * RZX # Obtain beta estimates (note: gesv also replaces the second # argument) betahat = XtY - matrix.trans(RZX) * Cu try: lapack.posv(RXtRX, betahat) except: lapack.gesv(RXtRX, betahat) return (betahat)
(np.tile(theta[0:f1_n_lamcomps], f1_nl), np.tile(theta[f1_n_lamcomps:(f1_n_lamcomps + f2_n_lamcomps)], f2_nl))) lambda_theta = cvxopt.spmatrix( theta_repeated.tolist(), np.hstack((r_inds_f1, r_inds_f2)).astype(np.int64), np.hstack((c_inds_f1, c_inds_f2)).astype(np.int64)) theta_fromlambda = pd.unique(list(lambda_theta)) # Set the factorisation to use LL' instead of LDL' cholmod.options['supernodal'] = 2 # Make an expression for the factorisation F = cholmod.symbolic(ZtZ) # Calculate the factorisation cholmod.numeric(ZtZ, F) # Work out the permutation p = cvxopt.matrix(range(ZtZ.size[0]), (ZtZ.size[0], 1), tc='d') cholmod.solve(F, p, sys=7) # Get the sparse cholesky factorisation L = cholmod.getfactor(F) LLt2 = L * cvxopt.spmatrix.trans(L) p = cvxopt.matrix(np.array(p).astype(np.int64), tc='i') print(LLt2 - ZtZ[p, p]) #print(LLt-ZtZ[P,P])
def covsel(Y): """ Returns the solution of minimize -log det K + Tr(KY) subject to K_{ij}=0, (i,j) not in indices listed in I,J. Y is a symmetric sparse matrix with nonzero diagonal elements. I = Y.I, J = Y.J. """ I, J = Y.I, Y.J n, m = Y.size[0], len(I) N = I + J*n # non-zero positions for one-argument indexing D = [k for k in range(m) if I[k]==J[k]] # position of diagonal elements # starting point: symmetric identity with nonzero pattern I,J K = spmatrix(0.0, I, J) K[::n+1] = 1.0 # Kn is used in the line search Kn = spmatrix(0.0, I, J) # symbolic factorization of K F = cholmod.symbolic(K) # Kinv will be the inverse of K Kinv = matrix(0.0, (n,n)) for iters in range(100): # numeric factorization of K cholmod.numeric(K, F) d = cholmod.diag(F) # compute Kinv by solving K*X = I Kinv[:] = 0.0 Kinv[::n+1] = 1.0 cholmod.solve(F, Kinv) # solve Newton system grad = 2*(Y.V - Kinv[N]) hess = 2*(mul(Kinv[I,J],Kinv[J,I]) + mul(Kinv[I,I],Kinv[J,J])) v = -grad lapack.posv(hess,v) # stopping criterion sqntdecr = -blas.dot(grad,v) print("Newton decrement squared:%- 7.5e" %sqntdecr) if (sqntdecr < 1e-12): print("number of iterations: ", iters+1) break # line search dx = +v dx[D] *= 2 # scale the diagonal elems f = -2.0 * sum(log(d)) # f = -log det K s = 1 for lsiter in range(50): Kn.V = K.V + s*dx try: cholmod.numeric(Kn, F) except ArithmeticError: s *= 0.5 else: d = cholmod.diag(F) fn = -2.0 * sum(log(d)) + 2*s*blas.dot(v,Y.V) if (fn < f - 0.01*s*sqntdecr): break s *= 0.5 K.V = Kn.V return K
def factor(W, H=None, Df=None): if F['firstcall']: if type(G) is matrix: F['Gs'] = matrix(0.0, G.size) else: F['Gs'] = spmatrix(0.0, G.I, G.J, G.size) if mnl: if type(Df) is matrix: F['Dfs'] = matrix(0.0, Df.size) else: F['Dfs'] = spmatrix(0.0, Df.I, Df.J, Df.size) if (mnl and type(Df) is matrix) or type(G) is matrix or \ type(H) is matrix: F['S'] = matrix(0.0, (n, n)) F['K'] = matrix(0.0, (p, p)) else: F['S'] = spmatrix([], [], [], (n, n), 'd') F['Sf'] = None if type(A) is matrix: F['K'] = matrix(0.0, (p, p)) else: F['K'] = spmatrix([], [], [], (p, p), 'd') # Dfs = Wnl^{-1} * Df if mnl: base.gemm(spmatrix(W['dnli'], list(range(mnl)), list(range(mnl))), Df, F['Dfs'], partial=True) # Gs = Wl^{-1} * G. base.gemm(spmatrix(W['di'], list(range(ml)), list(range(ml))), G, F['Gs'], partial=True) if F['firstcall']: base.syrk(F['Gs'], F['S'], trans='T') if mnl: base.syrk(F['Dfs'], F['S'], trans='T', beta=1.0) if H is not None: F['S'] += H try: if type(F['S']) is matrix: lapack.potrf(F['S']) else: F['Sf'] = cholmod.symbolic(F['S']) cholmod.numeric(F['S'], F['Sf']) except ArithmeticError: F['singular'] = True if type(A) is matrix and type(F['S']) is spmatrix: F['S'] = matrix(0.0, (n, n)) base.syrk(F['Gs'], F['S'], trans='T') if mnl: base.syrk(F['Dfs'], F['S'], trans='T', beta=1.0) base.syrk(A, F['S'], trans='T', beta=1.0) if H is not None: F['S'] += H if type(F['S']) is matrix: lapack.potrf(F['S']) else: F['Sf'] = cholmod.symbolic(F['S']) cholmod.numeric(F['S'], F['Sf']) F['firstcall'] = False else: base.syrk(F['Gs'], F['S'], trans='T', partial=True) if mnl: base.syrk(F['Dfs'], F['S'], trans='T', beta=1.0, partial=True) if H is not None: F['S'] += H if F['singular']: base.syrk(A, F['S'], trans='T', beta=1.0, partial=True) if type(F['S']) is matrix: lapack.potrf(F['S']) else: cholmod.numeric(F['S'], F['Sf']) if type(F['S']) is matrix: # Asct := L^{-1}*A'. Factor K = Asct'*Asct. if type(A) is matrix: Asct = A.T else: Asct = matrix(A.T) blas.trsm(F['S'], Asct) blas.syrk(Asct, F['K'], trans='T') lapack.potrf(F['K']) else: # Asct := L^{-1}*P*A'. Factor K = Asct'*Asct. if type(A) is matrix: Asct = A.T cholmod.solve(F['Sf'], Asct, sys=7) cholmod.solve(F['Sf'], Asct, sys=4) blas.syrk(Asct, F['K'], trans='T') lapack.potrf(F['K']) else: Asct = cholmod.spsolve(F['Sf'], A.T, sys=7) Asct = cholmod.spsolve(F['Sf'], Asct, sys=4) base.syrk(Asct, F['K'], trans='T') Kf = cholmod.symbolic(F['K']) cholmod.numeric(F['K'], Kf) def solve(x, y, z): # Solve # # [ H A' GG'*W^{-1} ] [ ux ] [ bx ] # [ A 0 0 ] * [ uy ] = [ by ] # [ W^{-T}*GG 0 -I ] [ W*uz ] [ W^{-T}*bz ] # # and return ux, uy, W*uz. # # If not F['singular']: # # K*uy = A * S^{-1} * ( bx + GG'*W^{-1}*W^{-T}*bz ) - by # S*ux = bx + GG'*W^{-1}*W^{-T}*bz - A'*uy # W*uz = W^{-T} * ( GG*ux - bz ). # # If F['singular']: # # K*uy = A * S^{-1} * ( bx + GG'*W^{-1}*W^{-T}*bz + A'*by ) # - by # S*ux = bx + GG'*W^{-1}*W^{-T}*bz + A'*by - A'*y. # W*uz = W^{-T} * ( GG*ux - bz ). # z := W^{-1} * z = W^{-1} * bz scale(z, W, trans='T', inverse='I') # If not F['singular']: # x := L^{-1} * P * (x + GGs'*z) # = L^{-1} * P * (x + GG'*W^{-1}*W^{-T}*bz) # # If F['singular']: # x := L^{-1} * P * (x + GGs'*z + A'*y)) # = L^{-1} * P * (x + GG'*W^{-1}*W^{-T}*bz + A'*y) if mnl: base.gemv(F['Dfs'], z, x, trans='T', beta=1.0) base.gemv(F['Gs'], z, x, offsetx=mnl, trans='T', beta=1.0) if F['singular']: base.gemv(A, y, x, trans='T', beta=1.0) if type(F['S']) is matrix: blas.trsv(F['S'], x) else: cholmod.solve(F['Sf'], x, sys=7) cholmod.solve(F['Sf'], x, sys=4) # y := K^{-1} * (Asc*x - y) # = K^{-1} * (A * S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz) - by) # (if not F['singular']) # = K^{-1} * (A * S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz + # A'*by) - by) # (if F['singular']). base.gemv(Asct, x, y, trans='T', beta=-1.0) if type(F['K']) is matrix: lapack.potrs(F['K'], y) else: cholmod.solve(Kf, y) # x := P' * L^{-T} * (x - Asc'*y) # = S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz - A'*y) # (if not F['singular']) # = S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz + A'*by - A'*y) # (if F['singular']) base.gemv(Asct, y, x, alpha=-1.0, beta=1.0) if type(F['S']) is matrix: blas.trsv(F['S'], x, trans='T') else: cholmod.solve(F['Sf'], x, sys=5) cholmod.solve(F['Sf'], x, sys=8) # W*z := GGs*x - z = W^{-T} * (GG*x - bz) if mnl: base.gemv(F['Dfs'], x, z, beta=-1.0) base.gemv(F['Gs'], x, z, beta=-1.0, offsety=mnl) return solve
def solve_phase1(self, kktsolver='chol', MM=1e5): """ Solves primal Phase I problem using the feasible start solver. Returns primal feasible X. """ from cvxopt import cholmod, amd k = 1e-3 # compute Schur complement matrix Id = [i * (self.n + 1) for i in range(self.n)] As = self._A[:, 1:] As[Id, :] /= sqrt(2.0) M = spmatrix([], [], [], (self.m, self.m)) base.syrk(As, M, trans='T') u = +self.b # compute least-norm solution F = cholmod.symbolic(M) cholmod.numeric(M, F) cholmod.solve(F, u) x = 0.5 * self._A[:, 1:] * u X0 = spmatrix(x[self.V[:].I], self.V.I, self.V.J, (self.n, self.n)) # test feasibility p = amd.order(self.V) #Xc,Nf = chompack.embed(X0,p) #E = chompack.project(Xc,spmatrix(1.0,range(self.n),range(self.n))) symb = chompack.symbolic(self.V, p) Xc = chompack.cspmatrix(symb) + X0 try: # L = chompack.completion(Xc) L = Xc.copy() chompack.completion(L) # least-norm solution is feasible return X0 except: pass # create Phase I SDP object trA = matrix(0.0, (self.m + 1, 1)) e = matrix(1.0, (self.n, 1)) Aa = self._A[Id, 1:] base.gemv(Aa, e, trA, trans='T') trA[-1] = MM P1 = SDP() P1._A = misc.phase1_sdp(self._A, trA) P1._b = matrix([self.b - k * trA[:self.m], MM]) P1._agg_sparsity() # find feasible starting point for Phase I problem tMIN = 0.0 tMAX = 1.0 while True: t = (tMIN + tMAX) / 2.0 #Xt = chompack.copy(Xc) #chompack.axpy(E,Xt,t) Xt = Xc.copy() + spmatrix(t, range(self.n), range(self.n)) try: # L = chompack.completion(Xt) L = Xt.copy() chompack.completion(L) tMAX = t if tMAX - tMIN < 1e-1: break except: tMAX *= 2.0 tMIN = t tt = t + 1.0 U = X0 + spmatrix(tt, range(self.n, ), range(self.n)) trU = sum(U[:][Id]) Z0 = spdiag([U, spmatrix([tt + k, MM - trU], [0, 1], [0, 1], (2, 2))]) sol = P1.solve_feas(primalstart={'x': Z0}, kktsolver=kktsolver) s = sol['x'][-2, -2] - k if s > 0: return None, P1 else: sol.pop('y') sol.pop('s') X0 = sol.pop('x')[:self.n,:self.n]\ - spmatrix(s,range(self.n),range(self.n)) return X0, sol
def solve(x, y, z): """ Returns solution of rho * ux + A'(uy) - r^-T * uz * r^-1 = bx A(ux) = by -ux - r * uz * r' = bz. On entry, x = bx, y = by, z = bz. On exit, x = ux, y = uy, z = uz. """ # bz is a copy of z in the format of x blas.copy(z, bz) # x := x + rho * bz # = bx + rho * bz blas.axpy(bz, x, alpha=rho) # x := Gamma .* (u' * x * u) # = Gamma .* (u' * (bx + rho * bz) * u) offsetj = 0 for j in xrange(N): cngrnc(U[j], x, trans='T', offsetx=offsetj, n=ns[j]) blas.tbmv(Gamma[j], x, n=ns[j]**2, k=0, ldA=1, offsetx=offsetj) offsetj += ns[j]**2 # y := y - As(x) # := by - As( Gamma .* u' * (bx + rho * bz) * u) blas.copy(x, xp) offsetj = 0 for j in xrange(N): misc.pack2(xp, {'l': offsetj, 'q': [], 's': [ns[j]]}) offsetj += ns[j]**2 offseti = 0 for i in xrange(M): offsetj = 0 for j in xrange(N): if type(As[i][j]) is matrix: blas.gemv(As[i][j], xp, y, trans='T', alpha=-1.0, beta=1.0, m=ns[j] * (ns[j] + 1) / 2, n=ms[i], ldA=ns[j]**2, offsetx=offsetj, offsety=offseti) offsetj += ns[j]**2 offseti += ms[i] # y := -y - A(bz) # = -by - A(bz) + As(Gamma .* (u' * (bx + rho * bz) * u) Af(bz, y, alpha=-1.0, beta=-1.0) # y := H^-1 * y # = H^-1 ( -by - A(bz) + As(Gamma.* u'*(bx + rho*bz)*u) ) # = uy cholmod.solve(HF, y) # bz = Vt' * vz * Vt # = uz where # vz := Gamma .* ( As'(uy) - x ) # = Gamma .* ( As'(uy) - Gamma .* (u'*(bx + rho *bz)*u) ) # = Gamma.^2 .* ( u' * (A'(uy) - bx - rho * bz) * u ). blas.copy(x, xp) offsetj = 0 for j in xrange(N): # xp is -x[j] = -Gamma .* (u' * (bx + rho*bz) * u) # in packed storage misc.pack2(xp, {'l': offsetj, 'q': [], 's': [ns[j]]}) offsetj += ns[j]**2 blas.scal(-1.0, xp) offsetj = 0 for j in xrange(N): # xp += As'(uy) offseti = 0 for i in xrange(M): if type(As[i][j]) is matrix: blas.gemv(As[i][j], y, xp, alpha = 1.0, beta = 1.0, m = ns[j]*(ns[j]+1)/2, \ n = ms[i],ldA = ns[j]**2, \ offsetx = offseti, offsety = offsetj) offseti += ms[i] # bz[j] is xp unpacked and multiplied with Gamma #unpack(xp, bz[j], ns[j]) misc.unpack(xp, bz, { 'l': 0, 'q': [], 's': [ns[j]] }, offsetx=offsetj, offsety=offsetj) blas.tbmv(Gamma[j], bz, n=ns[j]**2, k=0, ldA=1, offsetx=offsetj) # bz = Vt' * bz * Vt # = uz cngrnc(Vt[j], bz, trans='T', offsetx=offsetj, n=ns[j]) symmetrize(bz, ns[j], offset=offsetj) offsetj += ns[j]**2 # x = -bz - r * uz * r' blas.copy(z, x) blas.copy(bz, z) offsetj = 0 for j in xrange(N): cngrnc(+W['r'][j], bz, offsetx=offsetj, n=ns[j]) offsetj += ns[j]**2 blas.axpy(bz, x) blas.scal(-1.0, x)
def solve(x, y, z): # Solve # # [ H A' GG'*W^{-1} ] [ ux ] [ bx ] # [ A 0 0 ] * [ uy ] = [ by ] # [ W^{-T}*GG 0 -I ] [ W*uz ] [ W^{-T}*bz ] # # and return ux, uy, W*uz. # # If not F['singular']: # # K*uy = A * S^{-1} * ( bx + GG'*W^{-1}*W^{-T}*bz ) - by # S*ux = bx + GG'*W^{-1}*W^{-T}*bz - A'*uy # W*uz = W^{-T} * ( GG*ux - bz ). # # If F['singular']: # # K*uy = A * S^{-1} * ( bx + GG'*W^{-1}*W^{-T}*bz + A'*by ) # - by # S*ux = bx + GG'*W^{-1}*W^{-T}*bz + A'*by - A'*y. # W*uz = W^{-T} * ( GG*ux - bz ). # z := W^{-1} * z = W^{-1} * bz scale(z, W, trans='T', inverse='I') # If not F['singular']: # x := L^{-1} * P * (x + GGs'*z) # = L^{-1} * P * (x + GG'*W^{-1}*W^{-T}*bz) # # If F['singular']: # x := L^{-1} * P * (x + GGs'*z + A'*y)) # = L^{-1} * P * (x + GG'*W^{-1}*W^{-T}*bz + A'*y) if mnl: base.gemv(F['Dfs'], z, x, trans='T', beta=1.0) base.gemv(F['Gs'], z, x, offsetx=mnl, trans='T', beta=1.0) if F['singular']: base.gemv(A, y, x, trans='T', beta=1.0) if type(F['S']) is matrix: blas.trsv(F['S'], x) else: cholmod.solve(F['Sf'], x, sys=7) cholmod.solve(F['Sf'], x, sys=4) # y := K^{-1} * (Asc*x - y) # = K^{-1} * (A * S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz) - by) # (if not F['singular']) # = K^{-1} * (A * S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz + # A'*by) - by) # (if F['singular']). base.gemv(Asct, x, y, trans='T', beta=-1.0) if type(F['K']) is matrix: lapack.potrs(F['K'], y) else: cholmod.solve(Kf, y) # x := P' * L^{-T} * (x - Asc'*y) # = S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz - A'*y) # (if not F['singular']) # = S^{-1} * (bx + GG'*W^{-1}*W^{-T}*bz + A'*by - A'*y) # (if F['singular']) base.gemv(Asct, y, x, alpha=-1.0, beta=1.0) if type(F['S']) is matrix: blas.trsv(F['S'], x, trans='T') else: cholmod.solve(F['Sf'], x, sys=5) cholmod.solve(F['Sf'], x, sys=8) # W*z := GGs*x - z = W^{-T} * (GG*x - bz) if mnl: base.gemv(F['Dfs'], x, z, beta=-1.0) base.gemv(F['Gs'], x, z, beta=-1.0, offsety=mnl)
def PLS2D_getSigma2(theta, ZtX, ZtY, XtX, ZtZ, XtY, YtX, YtZ, XtZ, YtY, n, P, I, tinds, rinds, cinds): # Obtain Lambda #t1 = time.time() Lambda = mapping2D(theta, tinds, rinds, cinds) #t2 = time.time() #print(t2-t1)#3.170967102050781e-05 9 # Obtain Lambda' #t1 = time.time() Lambdat = spmatrix.trans(Lambda) #t2 = time.time() #print(t2-t1)# 3.5762786865234375e-06 # Obtain Lambda'Z'Y and Lambda'Z'X #t1 = time.time() LambdatZtY = Lambdat * ZtY LambdatZtX = Lambdat * ZtX #t2 = time.time() #print(t2-t1)#1.049041748046875e-05 13 # Obtain the cholesky decomposition #t1 = time.time() LambdatZtZLambda = Lambdat * (ZtZ * Lambda) #t2 = time.time() #print(t2-t1)#3.790855407714844e-05 2 #t1 = time.time() chol_dict = sparse_chol2D(LambdatZtZLambda + I, perm=P, retF=True, retP=False, retL=False) F = chol_dict['F'] #t2 = time.time() #print(t2-t1)#0.0001342296600341797 1 # Obtain C_u (annoyingly solve writes over the second argument, # whereas spsolve outputs) #t1 = time.time() Cu = LambdatZtY[P, :] cholmod.solve(F, Cu, sys=4) #t2 = time.time() #print(t2-t1)#1.5974044799804688e-05 5 # Obtain RZX #t1 = time.time() RZX = LambdatZtX[P, :] cholmod.solve(F, RZX, sys=4) #t2 = time.time() #print(t2-t1)#1.2159347534179688e-05 7 # Obtain RXtRX #t1 = time.time() RXtRX = XtX - matrix.trans(RZX) * RZX #t2 = time.time() #print(t2-t1)#9.775161743164062e-06 11 # Obtain beta estimates (note: gesv also replaces the second # argument) #t1 = time.time() betahat = XtY - matrix.trans(RZX) * Cu try: lapack.posv(RXtRX, betahat) except: lapack.gesv(RXtRX, betahat) #t2 = time.time() #print(t2-t1)#1.7404556274414062e-05 6 # Obtain u estimates #t1 = time.time() uhat = Cu - RZX * betahat cholmod.solve(F, uhat, sys=5) cholmod.solve(F, uhat, sys=8) #t2 = time.time() #print(t2-t1)#1.2874603271484375e-05 8 # Obtain b estimates #t1 = time.time() bhat = Lambda * uhat #t2 = time.time() #print(t2-t1)#2.86102294921875e-06 15 # Obtain residuals sum of squares #t1 = time.time() resss = YtY - 2 * YtX * betahat - 2 * YtZ * bhat + 2 * matrix.trans( betahat) * XtZ * bhat + matrix.trans( betahat) * XtX * betahat + matrix.trans(bhat) * ZtZ * bhat #t2 = time.time() #print(t2-t1)#3.409385681152344e-05 4 # Obtain penalised residual sum of squares #t1 = time.time() pss = resss + matrix.trans(uhat) * uhat return (pss / n)
from cvxopt import matrix, spmatrix, cholmod A = spmatrix([10, 3, 5, -2, 5, 2], [0, 2, 1, 3, 2, 3], [0, 0, 1, 1, 2, 3]) X = matrix(range(8), (4,2), 'd') F = cholmod.symbolic(A) cholmod.numeric(A, F) cholmod.solve(F, X) print(X) P = cvxopt.matrix(P) print(cvxopt.matrix(list(map(lambda x: x != 1, abs(P))), P.size))
FA = umfpack.numeric(A, Fs) FB = umfpack.numeric(B, Fs) umfpack.solve(A, FA, x) umfpack.solve(B, FB, x) umfpack.solve(A, FA, x, trans='T') print(x) A = spmatrix([10, 3, 5, -2, 5, 2], [0, 2, 1, 3, 2, 3], [0, 0, 1, 1, 2, 3]) X = matrix(range(8), (4, 2), 'd') cholmod.linsolve(A, X) print(X) X = cholmod.splinsolve(A, spmatrix(1.0, range(4), range(4))) print(X) X = matrix(range(8), (4, 2), 'd') F = cholmod.symbolic(A) cholmod.numeric(A, F) cholmod.solve(F, X) print(X) F = cholmod.symbolic(A) cholmod.numeric(A, F) print(2.0 * sum(log(cholmod.diag(F)))) options['supernodal'] = 0 F = cholmod.symbolic(A) cholmod.numeric(A, F) Di = matrix(1.0, (4, 1)) cholmod.solve(F, Di, sys=6) print(-sum(log(Di)))
def covsel(Y): """ Returns the solution of minimize -log det K + tr(KY) subject to K_ij = 0 if (i,j) not in zip(I, J). Y is a symmetric sparse matrix with nonzero diagonal elements. I = Y.I, J = Y.J. """ cholmod.options['supernodal'] = 2 I, J = Y.I, Y.J n, m = Y.size[0], len(I) # non-zero positions for one-argument indexing N = I + J*n # position of diagonal elements D = [ k for k in range(m) if I[k]==J[k] ] # starting point: symmetric identity with nonzero pattern I,J K = spmatrix(0.0, I, J) K[::n+1] = 1.0 # Kn is used in the line search Kn = spmatrix(0.0, I, J) # symbolic factorization of K F = cholmod.symbolic(K) # Kinv will be the inverse of K Kinv = matrix(0.0, (n,n)) for iters in range(100): # numeric factorization of K cholmod.numeric(K, F) d = cholmod.diag(F) # compute Kinv by solving K*X = I Kinv[:] = 0.0 Kinv[::n+1] = 1.0 cholmod.solve(F, Kinv) # solve Newton system grad = 2 * (Y.V - Kinv[N]) hess = 2 * ( mul(Kinv[I,J], Kinv[J,I]) + mul(Kinv[I,I], Kinv[J,J]) ) v = -grad lapack.posv(hess,v) # stopping criterion sqntdecr = -blas.dot(grad,v) print("Newton decrement squared:%- 7.5e" %sqntdecr) if (sqntdecr < 1e-12): print("number of iterations: %d" %(iters+1)) break # line search dx = +v dx[D] *= 2 f = -2.0*sum(log(d)) # f = -log det K s = 1 for lsiter in range(50): Kn.V = K.V + s*dx try: cholmod.numeric(Kn, F) except ArithmeticError: s *= 0.5 else: d = cholmod.diag(F) fn = -2.0 * sum(log(d)) + 2*s*blas.dot(v,Y.V) if (fn < f - 0.01*s*sqntdecr): break else: s *= 0.5 K.V = Kn.V return K
def PLS(theta, ZtX, ZtY, XtX, ZtZ, XtY, YtX, YtZ, XtZ, YtY, P, tinds, rinds, cinds): #t1 = time.time() # Obtain Lambda from theta Lambda = mapping(theta, tinds, rinds, cinds) #t2 = time.time() #print(t2-t1) #t1 = time.time() # Obtain Lambda' Lambdat = spmatrix.trans(Lambda) #t2 = time.time() #print(t2-t1) #t1 = time.time() LambdatZtY = Lambdat * ZtY #t2 = time.time() #print(t2-t1) #t1 = time.time() LambdatZtX = Lambdat * ZtX #t2 = time.time() #print(t2-t1) #t1 = time.time() # Set the factorisation to use LL' instead of LDL' cholmod.options['supernodal'] = 2 #t2 = time.time() #print(t2-t1) # Obtain L #t1 = time.time() LambdatZtZLambda = Lambdat * ZtZ * Lambda #t2 = time.time() #print(t2-t1) #t1 = time.time() I = spmatrix(1.0, range(Lambda.size[0]), range(Lambda.size[0])) #t2 = time.time() #print(t2-t1) #t1 = time.time() chol_dict = sparse_chol(LambdatZtZLambda + I, perm=P, retF=True, retP=False, retL=False) #t2 = time.time() #print(t2-t1) #t1 = time.time() F = chol_dict['F'] #t2 = time.time() #print(t2-t1) # Obtain C_u (annoyingly solve writes over the second argument, # whereas spsolve outputs) #t1 = time.time() Cu = LambdatZtY[P, :] #t2 = time.time() #print(t2-t1) #t1 = time.time() cholmod.solve(F, Cu, sys=4) #t2 = time.time() #print(t2-t1) # Obtain RZX #t1 = time.time() RZX = LambdatZtX[P, :] #t2 = time.time() #print(t2-t1) #t1 = time.time() cholmod.solve(F, RZX, sys=4) #t2 = time.time() #print(t2-t1) # Obtain RXtRX #t1 = time.time() RXtRX = XtX - matrix.trans(RZX) * RZX #t2 = time.time() #print(t2-t1) #print(RXtRX.size) #print(X.size) #print(Y.size) #print(RZX.size) #print(Cu.size) # Obtain beta estimates (note: gesv also replaces the second # argument) #t1 = time.time() betahat = XtY - matrix.trans(RZX) * Cu #t2 = time.time() #print(t2-t1) #t1 = time.time() lapack.posv(RXtRX, betahat) #t2 = time.time() #print(t2-t1) # Obtain u estimates #t1 = time.time() uhat = Cu - RZX * betahat #t2 = time.time() #print(t2-t1) #t1 = time.time() cholmod.solve(F, uhat, sys=5) #t2 = time.time() #print(t2-t1) #t1 = time.time() cholmod.solve(F, uhat, sys=8) #t2 = time.time() #print(t2-t1) # Obtain b estimates #t1 = time.time() bhat = Lambda * uhat #t2 = time.time() #print(t2-t1) # Obtain residuals sum of squares #t1 = time.time() resss = YtY - 2 * YtX * betahat - 2 * YtZ * bhat + 2 * matrix.trans( betahat) * XtZ * bhat + matrix.trans( betahat) * XtX * betahat + matrix.trans(bhat) * ZtZ * bhat #t2 = time.time() #print(t2-t1) # Obtain penalised residual sum of squares #t1 = time.time() pss = resss + matrix.trans(uhat) * uhat #t2 = time.time() #print(t2-t1) # Obtain Log(|L|^2) #t1 = time.time() logdet = 2 * sum(cvxopt.log( cholmod.diag(F))) # this method only works for symm decomps # Need to do tr(R_X)^2 for rml #t2 = time.time() #print(t2-t1) # Obtain log likelihood logllh = -logdet / 2 - X.size[0] / 2 * (1 + np.log(2 * np.pi * pss) - np.log(X.size[0])) #print(L[::(L.size[0]+1)]) # gives diag #print(logllh[0,0]) #print(theta) return (-logllh[0, 0])
def PeLS2D(theta, ZtX, ZtY, XtX, ZtZ, XtY, YtX, YtZ, XtZ, YtY, n, P, I, tinds, rinds, cinds): # Obtain Lambda Lambda = mapping2D(theta, tinds, rinds, cinds) # Obtain Lambda' Lambdat = spmatrix.trans(Lambda) # Obtain Lambda'Z'Y and Lambda'Z'X LambdatZtY = Lambdat * ZtY LambdatZtX = Lambdat * ZtX # Obtain the cholesky decomposition LambdatZtZLambda = Lambdat * (ZtZ * Lambda) chol_dict = sparse_chol2D(LambdatZtZLambda + I, perm=P, retF=True, retP=False, retL=False) F = chol_dict['F'] # Obtain C_u (annoyingly solve writes over the second argument, # whereas spsolve outputs) Cu = LambdatZtY[P, :] cholmod.solve(F, Cu, sys=4) # Obtain RZX RZX = LambdatZtX[P, :] cholmod.solve(F, RZX, sys=4) # Obtain RXtRX RXtRX = XtX - matrix.trans(RZX) * RZX # Obtain beta estimates (note: gesv also replaces the second # argument) betahat = XtY - matrix.trans(RZX) * Cu try: lapack.posv(RXtRX, betahat) except: lapack.gesv(RXtRX, betahat) # Obtain u estimates uhat = Cu - RZX * betahat cholmod.solve(F, uhat, sys=5) cholmod.solve(F, uhat, sys=8) # Obtain b estimates bhat = Lambda * uhat # Obtain residuals sum of squares resss = YtY - 2 * YtX * betahat - 2 * YtZ * bhat + 2 * matrix.trans( betahat) * XtZ * bhat + matrix.trans( betahat) * XtX * betahat + matrix.trans(bhat) * ZtZ * bhat # Obtain penalised residual sum of squares pss = resss + matrix.trans(uhat) * uhat # Obtain Log(|L|^2) logdet = 2 * sum(cvxopt.log(cholmod.diag(F))) # Obtain log likelihood logllh = -logdet / 2 - n / 2 * (1 + np.log(2 * np.pi * pss[0, 0]) - np.log(n)) return (-logllh)
def solve_phase1(self,kktsolver='chol',MM = 1e5): """ Solves primal Phase I problem using the feasible start solver. Returns primal feasible X. """ from cvxopt import cholmod, amd k = 1e-3 # compute Schur complement matrix Id = [i*(self.n+1) for i in range(self.n)] As = self._A[:,1:] As[Id,:] /= sqrt(2.0) M = spmatrix([],[],[],(self.m,self.m)) base.syrk(As,M,trans='T') u = +self.b # compute least-norm solution F = cholmod.symbolic(M) cholmod.numeric(M,F) cholmod.solve(F,u) x = 0.5*self._A[:,1:]*u X0 = spmatrix(x[self.V[:].I],self.V.I,self.V.J,(self.n,self.n)) # test feasibility p = amd.order(self.V) #Xc,Nf = chompack.embed(X0,p) #E = chompack.project(Xc,spmatrix(1.0,range(self.n),range(self.n))) symb = chompack.symbolic(self.V,p) Xc = chompack.cspmatrix(symb) + X0 try: # L = chompack.completion(Xc) L = Xc.copy() chompack.completion(L) # least-norm solution is feasible return X0,None except: pass # create Phase I SDP object trA = matrix(0.0,(self.m+1,1)) e = matrix(1.0,(self.n,1)) Aa = self._A[Id,1:] base.gemv(Aa,e,trA,trans='T') trA[-1] = MM P1 = SDP() P1._A = misc.phase1_sdp(self._A,trA) P1._b = matrix([self.b-k*trA[:self.m],MM]) P1._agg_sparsity() # find feasible starting point for Phase I problem tMIN = 0.0 tMAX = 1.0 while True: t = (tMIN+tMAX)/2.0 #Xt = chompack.copy(Xc) #chompack.axpy(E,Xt,t) Xt = Xc.copy() + spmatrix(t,list(range(self.n)),list(range(self.n))) try: # L = chompack.completion(Xt) L = Xt.copy() chompack.completion(L) tMAX = t if tMAX - tMIN < 1e-1: break except: tMAX *= 2.0 tMIN = t tt = t + 1.0 U = X0 + spmatrix(tt,list(range(self.n,)),list(range(self.n))) trU = sum(U[:][Id]) Z0 = spdiag([U,spmatrix([tt+k,MM-trU],[0,1],[0,1],(2,2))]) sol = P1.solve_feas(primalstart = {'x':Z0}, kktsolver = kktsolver) s = sol['x'][-2,-2] - k if s > 0: return None,P1 else: sol.pop('y') sol.pop('s') X0 = sol.pop('x')[:self.n,:self.n]\ - spmatrix(s,list(range(self.n)),list(range(self.n))) return X0,sol