def classifier2(Y, soft=False): M = Y.size[0] # K = Y*X' / sigma K = matrix(0.0, (width, M)) blas.gemm(X, Y, K, transB='T', alpha=1.0 / sigma, m=width) # c[i] = ||Yi||^2 / sigma ones = matrix(1.0, (max(width, n, M), 1)) c = Y**2 * ones[:n] blas.scal(1.0 / sigma, c) # Kij := Kij - 0.5 * (ci + aj) # = || yi - xj ||^2 / (2*sigma) blas.ger(ones[:width], c, K, alpha=-0.5) blas.ger(a[:width], ones[:M], K, alpha=-0.5) # Kij = exp(Kij) K = exp(K) # complete K lapack.potrs(L11, K) K = matrix([K, matrix(0., (N - width, M))], (N, M)) chompack.trsm(Lc, K, trans='N') chompack.trsm(Lc, K, trans='T') x = matrix(b, (M, 1)) blas.gemv(K, z, x, trans='T', beta=1.0) if soft: return x else: return matrix([2 * (xk > 0.0) - 1 for xk in x])
def syr2(X, u, v, alpha=1.0, beta=1.0, reordered=False): r""" Computes the projected rank 2 update of a cspmatrix X .. math:: X := \alpha*P(u v^T + v u^T) + \beta X. """ assert X.is_factor is False, "cspmatrix factor object" symb = X.symb n = symb.n snptr = symb.snptr snode = symb.snode blkval = X.blkval blkptr = symb.blkptr relptr = symb.relptr snrowidx = symb.snrowidx sncolptr = symb.sncolptr if symb.p is not None and reordered is False: up = u[symb.p] vp = v[symb.p] else: up = u vp = v for k in range(symb.Nsn): nn = snptr[k + 1] - snptr[k] na = relptr[k + 1] - relptr[k] nj = na + nn for i in range(nn): blas.scal(beta, blkval, n=nj - i, offset=blkptr[k] + (nj + 1) * i) uk = up[snrowidx[sncolptr[k]:sncolptr[k + 1]]] vk = vp[snrowidx[sncolptr[k]:sncolptr[k + 1]]] blas.syr2(uk, vk, blkval, n=nn, offsetA=blkptr[k], ldA=nj, alpha=alpha) blas.ger(uk, vk, blkval, m=na, n=nn, offsetx=nn, offsetA=blkptr[k] + nn, ldA=nj, alpha=alpha) blas.ger(vk, uk, blkval, m=na, n=nn, offsetx=nn, offsetA=blkptr[k] + nn, ldA=nj, alpha=alpha) return
def A(x, y, alpha=1.0, beta=0.0, trans='N'): """ If trans is 'N', x is an N x m matrix and y an N-vector. y := alpha * x * 1_m + beta y. If trans is 'T', x is an N vector and y an N x m matrix. y := alpha * x * 1_m' + beta y. """ if trans == 'N': blas.gemv(x, ones, y, alpha=alpha, beta=beta) else: blas.scal(beta, y) blas.ger(x, ones, y, alpha=alpha)
def classifier(Y, soft=False): M = Y.size[0] # K = Y*X' / sigma K = matrix(0.0, (M, Nr)) blas.gemm(Y, Xr, K, transB='T', alpha=1.0 / sigma) # c[i] = ||Yi||^2 / sigma ones = matrix(1.0, (max([M, Nr, n]), 1)) c = Y**2 * ones[:n] blas.scal(1.0 / sigma, c) # Kij := Kij - 0.5 * (ci + aj) # = || yi - xj ||^2 / (2*sigma) blas.ger(c, ones, K, alpha=-0.5) blas.ger(ones, a[sv], K, alpha=-0.5) x = exp(K) * zr + b if soft: return x else: return matrix([2 * (xk > 0.0) - 1 for xk in x])
def syr2(X, u, v, alpha = 1.0, beta = 1.0, reordered=False): r""" Computes the projected rank 2 update of a cspmatrix X .. math:: X := \alpha*P(u v^T + v u^T) + \beta X. """ assert X.is_factor is False, "cspmatrix factor object" symb = X.symb n = symb.n snptr = symb.snptr snode = symb.snode blkval = X.blkval blkptr = symb.blkptr relptr = symb.relptr snrowidx = symb.snrowidx sncolptr = symb.sncolptr if symb.p is not None and reordered is False: up = u[symb.p] vp = v[symb.p] else: up = u vp = v for k in range(symb.Nsn): nn = snptr[k+1]-snptr[k] na = relptr[k+1]-relptr[k] nj = na + nn for i in range(nn): blas.scal(beta, blkval, n = nj-i, offset = blkptr[k]+(nj+1)*i) uk = up[snrowidx[sncolptr[k]:sncolptr[k+1]]] vk = vp[snrowidx[sncolptr[k]:sncolptr[k+1]]] blas.syr2(uk, vk, blkval, n = nn, offsetA = blkptr[k], ldA = nj, alpha = alpha) blas.ger(uk, vk, blkval, m = na, n = nn, offsetx = nn, offsetA = blkptr[k]+nn, ldA = nj, alpha = alpha) blas.ger(vk, uk, blkval, m = na, n = nn, offsetx = nn, offsetA = blkptr[k]+nn, ldA = nj, alpha = alpha) return
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 return solvers.cp(F, A=A, b=b)['x'] # Randomly generate a feasible problem m, n = 50, 500 y = normal(m, 1) # Random A with A'*y > 0. s = uniform(n, 1) A = normal(m, n) r = s - A.T * y # A = A - (1/y'*y) * y*r' blas.ger(y, r, A, alpha=1.0 / blas.dot(y, y)) # Random feasible x > 0. x = uniform(n, 1) b = A * x x = acent(A, b)
def scale(x, W, trans='N', inverse='N'): """ Applies Nesterov-Todd scaling or its inverse. Computes x := W*x (trans is 'N', inverse = 'N') x := W^T*x (trans is 'T', inverse = 'N') x := W^{-1}*x (trans is 'N', inverse = 'I') x := W^{-T}*x (trans is 'T', inverse = 'I'). x is a dense 'd' matrix. W is a dictionary with entries: - W['dnl']: positive vector - W['dnli']: componentwise inverse of W['dnl'] - W['d']: positive vector - W['di']: componentwise inverse of W['d'] - W['v']: lists of 2nd order cone vectors with unit hyperbolic norms - W['beta']: list of positive numbers - W['r']: list of square matrices - W['rti']: list of square matrices. rti[k] is the inverse transpose of r[k]. The 'dnl' and 'dnli' entries are optional, and only present when the function is called from the nonlinear solver. """ from cvxopt import blas ind = 0 # Scaling for nonlinear component xk is xk := dnl .* xk; inverse # scaling is xk ./ dnl = dnli .* xk, where dnl = W['dnl'], # dnli = W['dnli']. if 'dnl' in W: if inverse == 'N': w = W['dnl'] else: w = W['dnli'] for k in range(x.size[1]): blas.tbmv(w, x, n=w.size[0], k=0, ldA=1, offsetx=k * x.size[0]) ind += w.size[0] # Scaling for linear 'l' component xk is xk := d .* xk; inverse # scaling is xk ./ d = di .* xk, where d = W['d'], di = W['di']. if inverse == 'N': w = W['d'] else: w = W['di'] for k in range(x.size[1]): blas.tbmv(w, x, n=w.size[0], k=0, ldA=1, offsetx=k * x.size[0] + ind) ind += w.size[0] # Scaling for 'q' component is # # xk := beta * (2*v*v' - J) * xk # = beta * (2*v*(xk'*v)' - J*xk) # # where beta = W['beta'][k], v = W['v'][k], J = [1, 0; 0, -I]. # # Inverse scaling is # # xk := 1/beta * (2*J*v*v'*J - J) * xk # = 1/beta * (-J) * (2*v*((-J*xk)'*v)' + xk). w = matrix(0.0, (x.size[1], 1)) for k in range(len(W['v'])): v = W['v'][k] m = v.size[0] if inverse == 'I': blas.scal(-1.0, x, offset=ind, inc=x.size[0]) blas.gemv(x, v, w, trans='T', m=m, n=x.size[1], offsetA=ind, ldA=x.size[0]) blas.scal(-1.0, x, offset=ind, inc=x.size[0]) blas.ger(v, w, x, alpha=2.0, m=m, n=x.size[1], ldA=x.size[0], offsetA=ind) if inverse == 'I': blas.scal(-1.0, x, offset=ind, inc=x.size[0]) a = 1.0 / W['beta'][k] else: a = W['beta'][k] for i in range(x.size[1]): blas.scal(a, x, n=m, offset=ind + i * x.size[0]) ind += m # Scaling for 's' component xk is # # xk := vec( r' * mat(xk) * r ) if trans = 'N' # xk := vec( r * mat(xk) * r' ) if trans = 'T'. # # r is kth element of W['r']. # # Inverse scaling is # # xk := vec( rti * mat(xk) * rti' ) if trans = 'N' # xk := vec( rti' * mat(xk) * rti ) if trans = 'T'. # # rti is kth element of W['rti']. maxn = max([0] + [r.size[0] for r in W['r']]) a = matrix(0.0, (maxn, maxn)) for k in range(len(W['r'])): if inverse == 'N': r = W['r'][k] if trans == 'N': t = 'T' else: t = 'N' else: r = W['rti'][k] t = trans n = r.size[0] for i in range(x.size[1]): # scale diagonal of xk by 0.5 blas.scal(0.5, x, offset=ind + i * x.size[0], inc=n + 1, n=n) # a = r*tril(x) (t is 'N') or a = tril(x)*r (t is 'T') blas.copy(r, a) if t == 'N': blas.trmm(x, a, side='R', m=n, n=n, ldA=n, ldB=n, offsetA=ind + i * x.size[0]) else: blas.trmm(x, a, side='L', m=n, n=n, ldA=n, ldB=n, offsetA=ind + i * x.size[0]) # x := (r*a' + a*r') if t is 'N' # x := (r'*a + a'*r) if t is 'T' blas.syr2k(r, a, x, trans=t, n=n, k=n, ldB=n, ldC=n, offsetC=ind + i * x.size[0]) ind += n ** 2
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 return solvers.cp(F, A=A, b=b)["x"] # Randomly generate a feasible problem m, n = 50, 500 y = normal(m, 1) # Random A with A'*y > 0. s = uniform(n, 1) A = normal(m, n) r = s - A.T * y # A = A - (1/y'*y) * y*r' blas.ger(y, r, A, alpha=1.0 / blas.dot(y, y)) # Random feasible x > 0. x = uniform(n, 1) b = A * x x = acent(A, b)