def F(x=None, z=None): if x is None: return 0, matrix(0.0, (n, 1)) if max(abs(x)) >= 1.0: return None r = -b blas.gemv(A, x, r, beta=-1.0) w = x**2 f = 0.5 * blas.nrm2(r)**2 - sum(log(1 - w)) gradf = div(x, 1.0 - w) blas.gemv(A, r, gradf, trans='T', beta=2.0) if z is None: return f, gradf.T else: def Hf(u, v, alpha=1.0, beta=0.0): """ v := alpha * (A'*A*u + 2*((1+w)./(1-w)).*u + beta *v """ v *= beta v += 2.0 * alpha * mul(div(1.0 + w, (1.0 - w)**2), u) blas.gemv(A, u, r) blas.gemv(A, r, v, alpha=alpha, beta=1.0, trans='T') return f, gradf.T, Hf
def F(x=None, z=None): if x is None: return 0, matrix(1.0, (n, 1)) if min(x) <= 0.0: return None f = -sum(log(x)) Df = -(x**-1).T if z is None: return matrix(f), Df H = spdiag(z[0] * x**-2) return f, Df, H
def F(x = None, z = None): if x is None: return 0, matrix(0.0, (3,1)) if max(abs(x)) >= 1.0: return None u = 1 - x**2 val = -sum(log(u)) Df = div(2*x, u).T if z is None: return val, Df H = spdiag(2 * z[0] * div(1 + u**2, u**2)) return val, Df, H
def acent(A,b): """ Computes analytic center of A*x <= b with A m by n of rank n. We assume that b > 0 and the feasible set is bounded. """ MAXITERS = 100 ALPHA = 0.01 BETA = 0.5 TOL = 1e-8 ntdecrs = [] m, n = A.size x = matrix(0.0, (n,1)) H = matrix(0.0, (n,n)) for iter in range(MAXITERS): # Gradient is g = A^T * (1./(b-A*x)). d = (b-A*x)**-1 g = A.T * d # Hessian is H = A^T * diag(1./(b-A*x))^2 * A. Asc = mul( d[:,n*[0]], A) blas.syrk(Asc, H, trans='T') # Newton step is v = H^-1 * g. v = -g lapack.posv(H, v) # Directional derivative and Newton decrement. lam = blas.dot(g, v) ntdecrs += [ sqrt(-lam) ] print("%2d. Newton decr. = %3.3e" %(iter,ntdecrs[-1])) if ntdecrs[-1] < TOL: return x, ntdecrs # Backtracking line search. y = mul(A*v, d) step = 1.0 while 1-step*max(y) < 0: step *= BETA while True: if -sum(log(1-step*y)) < ALPHA*step*lam: break step *= BETA x += step*v
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
# The small GP of section 9.3 (Geometric programming). from kvxopt import matrix, log, exp, solvers Aflr = 1000.0 Awall = 100.0 alpha = 0.5 beta = 2.0 gamma = 0.5 delta = 2.0 F = matrix([[-1., 1., 1., 0., -1., 1., 0., 0.], [-1., 1., 0., 1., 1., -1., 1., -1.], [-1., 0., 1., 1., 0., 0., -1., 1.]]) g = log( matrix([ 1.0, 2 / Awall, 2 / Awall, 1 / Aflr, alpha, 1 / beta, gamma, 1 / delta ])) K = [1, 2, 1, 1, 1, 1, 1] h, w, d = exp(solvers.gp(K, F, g)['x']) print("\n h = %f, w = %f, d = %f.\n" % (h, w, d))