def test_basic(self): import kvxopt a = kvxopt.matrix([1.0, 2.0, 3.0]) assert list(a) == [1.0, 2.0, 3.0] b = kvxopt.matrix([3.0, -2.0, -1.0]) c = kvxopt.spmatrix([1.0, -2.0, 3.0], [0, 2, 4], [1, 2, 4], (6, 5)) d = kvxopt.spmatrix([1.0, 2.0, 5.0], [0, 1, 2], [0, 0, 0], (3, 1)) e = kvxopt.mul(a, b) self.assertEqualLists(e, [3.0, -4.0, -3.0]) self.assertAlmostEqualLists(list(kvxopt.div(a, b)), [1.0 / 3.0, -1.0, -3.0]) self.assertAlmostEqual(kvxopt.div([1.0, 2.0, 0.25]), 2.0) self.assertEqualLists(list(kvxopt.min(a, b)), [1.0, -2.0, -1.0]) self.assertEqualLists(list(kvxopt.max(a, b)), [3.0, 2.0, 3.0]) self.assertEqual(kvxopt.max([1.0, 2.0]), 2.0) self.assertEqual(kvxopt.max(a), 3.0) self.assertEqual(kvxopt.max(c), 3.0) self.assertEqual(kvxopt.max(d), 5.0) self.assertEqual(kvxopt.min([1.0, 2.0]), 1.0) self.assertEqual(kvxopt.min(a), 1.0) self.assertEqual(kvxopt.min(c), -2.0) self.assertEqual(kvxopt.min(d), 1.0) self.assertEqual(len(c.imag()), 0) with self.assertRaises(OverflowError): kvxopt.matrix(1.0, (32780 * 4, 32780)) with self.assertRaises(OverflowError): kvxopt.spmatrix(1.0, (0, 32780 * 4), (0, 32780)) + 1
def g(x, y, z): x[:n] = 0.5 * (x[:n] - mul(d3, x[n:]) + mul( d1, z[:n] + mul(d3, z[:n])) - mul(d2, z[n:] - mul(d3, z[n:]))) x[:n] = div(x[:n], ds) # Solve # # S * v = 0.5 * A * D^-1 * ( bx[:n] - # (D2-D1)*(D1+D2)^-1 * bx[n:] + # D1 * ( I + (D2-D1)*(D1+D2)^-1 ) * bzl[:n] - # D2 * ( I - (D2-D1)*(D1+D2)^-1 ) * bzl[n:] ) blas.gemv(Asc, x, v) lapack.potrs(S, v) # x[:n] = D^-1 * ( rhs - A'*v ). blas.gemv(Asc, v, x, alpha=-1.0, beta=1.0, trans='T') x[:n] = div(x[:n], ds) # x[n:] = (D1+D2)^-1 * ( bx[n:] - D1*bzl[:n] - D2*bzl[n:] ) # - (D2-D1)*(D1+D2)^-1 * x[:n] x[n:] = div( x[n:] - mul(d1, z[:n]) - mul(d2, z[n:]), d1+d2 )\ - mul( d3, x[:n] ) # zl[:n] = D1^1/2 * ( x[:n] - x[n:] - bzl[:n] ) # zl[n:] = D2^1/2 * ( -x[:n] - x[n:] - bzl[n:] ). z[:n] = mul(W['di'][:n], x[:n] - x[n:] - z[:n]) z[n:] = mul(W['di'][n:], -x[:n] - x[n:] - z[n:])
def f(x, y, z): # z := - W**-T * z z[:n] = -div( z[:n], d1 ) z[n:2*n] = -div( z[n:2*n], d2 ) z[2*n:] -= 2.0*v*( v[0]*z[2*n] - blas.dot(v[1:], z[2*n+1:]) ) z[2*n+1:] *= -1.0 z[2*n:] /= beta # x := x - G' * W**-1 * z x[:n] -= div(z[:n], d1) - div(z[n:2*n], d2) + As.T * z[-(m+1):] x[n:] += div(z[:n], d1) + div(z[n:2*n], d2) # Solve for x[:n]: # # S*x[:n] = x[:n] - (W1**2 - W2**2)(W1**2 + W2**2)^-1 * x[n:] x[:n] -= mul( div(d1**2 - d2**2, d1**2 + d2**2), x[n:]) lapack.potrs(S, x) # Solve for x[n:]: # # (d1**-2 + d2**-2) * x[n:] = x[n:] + (d1**-2 - d2**-2)*x[:n] x[n:] += mul( d1**-2 - d2**-2, x[:n]) x[n:] = div( x[n:], d1**-2 + d2**-2) # z := z + W^-T * G*x z[:n] += div( x[:n] - x[n:2*n], d1) z[n:2*n] += div( -x[:n] - x[n:2*n], d2) z[2*n:] += As*x[:n]
def f(x, y, z): # Solve for x[:n]: # # A*x[:n] = bx[:n] + P' * ( ((D1-D2)*(D1+D2)^{-1})*bx[n:] # + (2*D1*D2*(D1+D2)^{-1}) * (bz[:m] - bz[m:]) ). blas.copy((mul(div(d1 - d2, d1 + d2), x[n:]) + mul(2 * D, z[:m] - z[m:])), u) blas.gemv(P, u, x, beta=1.0, trans='T') lapack.potrs(A, x) # x[n:] := (D1+D2)^{-1} * (bx[n:] - D1*bz[:m] - D2*bz[m:] # + (D1-D2)*P*x[:n]) base.gemv(P, x, u) x[n:] = div( x[n:] - mul(d1, z[:m]) - mul(d2, z[m:]) + mul(d1 - d2, u), d1 + d2) # z[:m] := d1[:m] .* ( P*x[:n] - x[n:] - bz[:m]) # z[m:] := d2[m:] .* (-P*x[:n] - x[n:] - bz[m:]) z[:m] = mul(di[:m], u - x[n:] - z[:m]) z[m:] = mul(di[m:], -u - x[n:] - z[m:])
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 F(x=None, z=None): if x is None: return 5, matrix(17 * [0.0] + 5 * [1.0]) if min(x[17:]) <= 0.0: return None f = -x[12:17] + div(Amin, x[17:]) Df = matrix(0.0, (5, 22)) Df[:, 12:17] = spmatrix(-1.0, range(5), range(5)) Df[:, 17:] = spmatrix(-div(Amin, x[17:]**2), range(5), range(5)) if z is None: return f, Df H = spmatrix(2.0 * mul(z, div(Amin, x[17::]**3)), range(17, 22), range(17, 22)) return f, Df, H
def Fkkt(W): # Factor # # S = A*D^-1*A' + I # # where D = 2*D1*D2*(D1+D2)^-1, D1 = d[:n]**-2, D2 = d[n:]**-2. d1, d2 = W['di'][:n]**2, W['di'][n:]**2 # ds is square root of diagonal of D ds = math.sqrt(2.0) * div(mul(W['di'][:n], W['di'][n:]), sqrt(d1 + d2)) d3 = div(d2 - d1, d1 + d2) # Asc = A*diag(d)^-1/2 Asc = A * spdiag(ds**-1) # S = I + A * D^-1 * A' blas.syrk(Asc, S) S[::m + 1] += 1.0 lapack.potrf(S) def g(x, y, z): x[:n] = 0.5 * (x[:n] - mul(d3, x[n:]) + mul( d1, z[:n] + mul(d3, z[:n])) - mul(d2, z[n:] - mul(d3, z[n:]))) x[:n] = div(x[:n], ds) # Solve # # S * v = 0.5 * A * D^-1 * ( bx[:n] - # (D2-D1)*(D1+D2)^-1 * bx[n:] + # D1 * ( I + (D2-D1)*(D1+D2)^-1 ) * bzl[:n] - # D2 * ( I - (D2-D1)*(D1+D2)^-1 ) * bzl[n:] ) blas.gemv(Asc, x, v) lapack.potrs(S, v) # x[:n] = D^-1 * ( rhs - A'*v ). blas.gemv(Asc, v, x, alpha=-1.0, beta=1.0, trans='T') x[:n] = div(x[:n], ds) # x[n:] = (D1+D2)^-1 * ( bx[n:] - D1*bzl[:n] - D2*bzl[n:] ) # - (D2-D1)*(D1+D2)^-1 * x[:n] x[n:] = div( x[n:] - mul(d1, z[:n]) - mul(d2, z[n:]), d1+d2 )\ - mul( d3, x[:n] ) # zl[:n] = D1^1/2 * ( x[:n] - x[n:] - bzl[:n] ) # zl[n:] = D2^1/2 * ( -x[:n] - x[n:] - bzl[n:] ). z[:n] = mul(W['di'][:n], x[:n] - x[n:] - z[:n]) z[n:] = mul(W['di'][n:], -x[:n] - x[n:] - z[n:]) return g
def test_basic_complex(self): import kvxopt a = kvxopt.matrix([1, -2, 3]) b = kvxopt.matrix([1.0, -2.0, 3.0]) c = kvxopt.matrix([1.0 + 2j, 1 - 2j, 0 + 1j]) d = kvxopt.spmatrix( [complex(1.0, 0.0), complex(0.0, 1.0), complex(2.0, -1.0)], [0, 1, 3], [0, 2, 3], (4, 4)) e = kvxopt.spmatrix( [complex(1.0, 0.0), complex(0.0, 1.0), complex(2.0, -1.0)], [2, 3, 3], [1, 2, 3], (4, 4)) self.assertAlmostEqualLists(list(kvxopt.div(b, c)), [0.2 - 0.4j, -0.4 - 0.8j, -3j]) self.assertAlmostEqualLists(list(kvxopt.div(b, 2.0j)), [-0.5j, 1j, -1.5j]) self.assertAlmostEqualLists(list(kvxopt.div(a, c)), [0.2 - 0.4j, -0.4 - 0.8j, -3j]) self.assertAlmostEqualLists(list(kvxopt.div(c, a)), [(1 + 2j), (-0.5 + 1j), 0.3333333333333333j]) self.assertAlmostEqualLists(list(kvxopt.div(c, c)), [1.0, 1.0, 1.0]) self.assertAlmostEqualLists(list(kvxopt.div(a, 2.0j)), [-0.5j, 1j, -1.5j]) self.assertAlmostEqualLists(list(kvxopt.div(c, 1.0j)), [2 - 1j, -2 - 1j, 1 + 0j]) self.assertAlmostEqualLists(list(kvxopt.div(1j, c)), [0.4 + 0.2j, -0.4 + 0.2j, 1 + 0j]) self.assertTrue(len(d) + len(e) == len(kvxopt.sparse([d, e]))) self.assertTrue(len(d) + len(e) == len(kvxopt.sparse([[d], [e]])))
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 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')
def F(x=None, z=None): if x is None: return 0, matrix(0.0, (n, 1)) y = A * x - b w = sqrt(rho + y**2) f = sum(w) Df = div(y, w).T * A if z is None: return f, Df H = A.T * spdiag(z[0] * rho * (w**-3)) * A return f, Df, H
def Fkkt(W): # Returns a function f(x, y, z) that solves # # [ 0 0 P' -P' ] [ x[:n] ] [ bx[:n] ] # [ 0 0 -I -I ] [ x[n:] ] [ bx[n:] ] # [ P -I -D1^{-1} 0 ] [ z[:m] ] = [ bz[:m] ] # [-P -I 0 -D2^{-1} ] [ z[m:] ] [ bz[m:] ] # # where D1 = diag(di[:m])^2, D2 = diag(di[m:])^2 and di = W['di']. # # On entry bx, bz are stored in x, z. # On exit x, z contain the solution, with z scaled (di .* z is # returned instead of z). # Factor A = 4*P'*D*P where D = d1.*d2 ./(d1+d2) and # d1 = d[:m].^2, d2 = d[m:].^2. di = W['di'] d1, d2 = di[:m]**2, di[m:]**2 D = div(mul(d1, d2), d1 + d2) Ds = spdiag(2 * sqrt(D)) base.gemm(Ds, P, Ps) blas.syrk(Ps, A, trans='T') lapack.potrf(A) def f(x, y, z): # Solve for x[:n]: # # A*x[:n] = bx[:n] + P' * ( ((D1-D2)*(D1+D2)^{-1})*bx[n:] # + (2*D1*D2*(D1+D2)^{-1}) * (bz[:m] - bz[m:]) ). blas.copy((mul(div(d1 - d2, d1 + d2), x[n:]) + mul(2 * D, z[:m] - z[m:])), u) blas.gemv(P, u, x, beta=1.0, trans='T') lapack.potrs(A, x) # x[n:] := (D1+D2)^{-1} * (bx[n:] - D1*bz[:m] - D2*bz[m:] # + (D1-D2)*P*x[:n]) base.gemv(P, x, u) x[n:] = div( x[n:] - mul(d1, z[:m]) - mul(d2, z[m:]) + mul(d1 - d2, u), d1 + d2) # z[:m] := d1[:m] .* ( P*x[:n] - x[n:] - bz[:m]) # z[m:] := d2[m:] .* (-P*x[:n] - x[n:] - bz[m:]) z[:m] = mul(di[:m], u - x[n:] - z[:m]) z[m:] = mul(di[m:], -u - x[n:] - z[m:]) return f
def Fkkt(x, z, W): ds = (2.0 * div(1 + x**2, (1 - x**2)**2))**-0.5 Asc = A * spdiag(ds) blas.syrk(Asc, S) S[::m + 1] += 1.0 lapack.potrf(S) a = z[0] def g(x, y, z): x[:] = mul(x, ds) / a blas.gemv(Asc, x, v) lapack.potrs(S, v) blas.gemv(Asc, v, x, alpha=-1.0, beta=1.0, trans='T') x[:] = mul(x, ds) return g
def f(x, y, z): x[:n] += P.T * (mul(div(d2**2 - d1**2, d1**2 + d2**2), x[n:]) + mul(.5 * D, z[:m] - z[m:])) lapack.potrs(A, x) u = P * x[:n] x[n:] = div( x[n:] - div(z[:m], d1**2) - div(z[m:], d2**2) + mul(d1**-2 - d2**-2, u), d1**-2 + d2**-2) z[:m] = div(u - x[n:] - z[:m], d1) z[m:] = div(-u - x[n:] - z[m:], d2)