Ejemplo n.º 1
0
 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
Ejemplo n.º 2
0
    def test_get_det(self):

        try:
            import numpy as np
        except ImportError:
            self.skipTest("Numpy not available for determinant testing")

        from kvxopt.klu import numeric, symbolic, get_det
        from kvxopt import matrix, spmatrix

        V = [2, 3, 3, -1, 4, 4, -3, 1, 2, 2, 6, 1]
        Vc = list(map(lambda x: x + x * 1j, V))
        I = [0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4]
        J = [0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4, 4]
        B = matrix([1.0j] * 5)
        A = spmatrix(V, I, J)
        Ac = spmatrix(Vc, I, J)

        # Double matrix case
        Fs = symbolic(A)
        Fn = numeric(A, Fs)

        det1 = get_det(A, Fs, Fn)
        det2 = np.linalg.det(np.array(matrix(A)))

        self.assertAlmostEqual(det1, det2)

        # Complex matrix case
        Fs = symbolic(Ac)
        Fn = numeric(Ac, Fs)

        det1 = get_det(Ac, Fs, Fn)
        det2 = np.linalg.det(np.array(matrix(Ac)))

        self.assertAlmostEqual(det1, det2)
Ejemplo n.º 3
0
 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]])))
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
 def test_case2(self):
     x = variable(2)
     A = matrix([[2., 1., -1., 0.], [1., 2., 0., -1.]])
     b = matrix([3., 3., 0., 0.])
     c = matrix([-4., -5.])
     ineq = (A * x <= b)
     lp2 = op(dot(c, x), ineq)
     lp2.solve()
     self.assertAlmostEqual(lp2.objective.value()[0], -9.0, places=4)
Ejemplo n.º 6
0
 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
Ejemplo n.º 7
0
 def setUp(self):
     try:
         from kvxopt import glpk, matrix
         c = matrix([-4., -5.])
         G = matrix([[2., 1., -1., 0.], [1., 2., 0., -1.]])
         h = matrix([3., 3., 0., 0.])
         A = matrix([1.0,1.0],(1,2))
         b = matrix(1.0)
         self._prob_data = (c,G,h,A,b)
     except:
         self.skipTest("GLPK not available")
Ejemplo n.º 8
0
        def f(x, y, z):
            """
            Solve
                          -diag(z)                           = bx
                -diag(x) - inv(rti*rti') * z * inv(rti*rti') = bs

            On entry, x and z contain bx and bs.  
            On exit, they contain the solution, with z scaled
            (inv(rti)'*z*inv(rti) is returned instead of z).

            We first solve 

                ((rti*rti') .* (rti*rti')) * x = bx - diag(t*bs*t) 

            and take z  = -rti' * (diag(x) + bs) * rti.
            """

            # tbst := t * zs * t = t * bs * t
            tbst = matrix(z, (n, n))
            cngrnc(t, tbst)

            # x := x - diag(tbst) = bx - diag(rti*rti' * bs * rti*rti')
            x -= tbst[::n + 1]

            # x := (t.*t)^{-1} * x = (t.*t)^{-1} * (bx - diag(t*bs*t))
            lapack.potrs(tsq, x)

            # z := z + diag(x) = bs + diag(x)
            z[::n + 1] += x

            # z := -rti' * z * rti = -rti' * (diag(x) + bs) * rti
            cngrnc(rti, z, alpha=-1.0)
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
    def solve(self, A, b):
        """
        Solve linear system ``Ax = b`` using numeric factorization ``N`` and symbolic factorization ``F``.
        Store the solution in ``b``.

        This function caches the symbolic factorization in ``self.F`` and is faster in general.
        Will attempt ``Solver.linsolve`` if the cached symbolic factorization is invalid.

        Parameters
        ----------
        A
            Sparse matrix for the equation set coefficients.
        F
            The symbolic factorization of A or a matrix with the same non-zero shape as ``A``.
        N
            Numeric factorization of A.
        b
            RHS of the equation.

        Returns
        -------
        numpy.ndarray
            The solution in a 1-D ndarray
        """
        self.A = A
        self.b = b

        if self.factorize is True:
            self.F = self._symbolic(self.A)
            self.factorize = False

        try:
            self.N = self._numeric(self.A, self.F)
            self._solve(self.A, self.F, self.N, self.b)

            return np.ravel(self.b)
        except ValueError:
            logger.debug('Unexpected symbolic factorization.')
            self.F = self._symbolic(self.A)
            self.solve(self.A, self.b)

            return np.ravel(self.b)
        except ArithmeticError:
            logger.error('Jacobian matrix is singular.')
            # diag = self.A[0:self.A.size[0] ** 2:self.A.size[0]+1]
            # idx = (np.argwhere(np.array(matrix(diag)).ravel() == 0.0)).ravel()
            # logger.error('The xy indices of associated variables:')
            # logger.error(' '.join([str(item) for item in idx]))

            # works around a KVXOPT bug
            suspect_diag = []
            for i in range(self.A.size[0]):
                if self.A[i, i] == 0.0:
                    suspect_diag.append(i)

            logger.error('Suspect diagonal elements: {}'.format(suspect_diag))

            return np.ravel(matrix(np.nan, self.b.size, 'd'))
Ejemplo n.º 11
0
 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
Ejemplo n.º 12
0
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  
Ejemplo n.º 13
0
 def setUp(self):
     try:
         from kvxopt import dsdp, matrix
         c = matrix([1., -1., 1.])
         G = [
             matrix([[-7., -11., -11., 3.], [7., -18., -18., 8.],
                     [-2., -8., -8., 1.]])
         ]
         G += [
             matrix([[-21., -11., 0., -11., 10., 8., 0., 8., 5.],
                     [0., 10., 16., 10., -10., -10., 16., -10., 3.],
                     [-5., 2., -17., 2., -6., 8., -17., 8., 6.]])
         ]
         h = [matrix([[33., -9.], [-9., 26.]])]
         h += [matrix([[14., 9., 40.], [9., 91., 10.], [40., 10., 15.]])]
         self._prob_data = (c, G, h)
     except:
         self.skipTest("DSDP not available")
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
    def test_print(self):
        from kvxopt import printing, matrix, spmatrix
        printing.options['height'] = 2
        A = spmatrix(1.0, range(3), range(3), tc='d')
        print(printing.matrix_repr_default(matrix(A)))
        print(printing.matrix_str_default(matrix(A)))
        print(printing.spmatrix_repr_default(A))
        print(printing.spmatrix_str_default(A))
        print(printing.spmatrix_str_triplet(A))

        A = spmatrix(1.0, range(3), range(3), tc='z')
        print(printing.matrix_repr_default(matrix(A)))
        print(printing.matrix_str_default(matrix(A)))
        print(printing.spmatrix_repr_default(A))
        print(printing.spmatrix_str_default(A))
        print(printing.spmatrix_str_triplet(A))

        A = spmatrix([], [], [], (3, 3))
        print(printing.spmatrix_repr_default(A))
        print(printing.spmatrix_str_default(A))
        print(printing.spmatrix_str_triplet(A))
Ejemplo n.º 16
0
 def test_ilp(self):
     from kvxopt import glpk, matrix
     c,G,h,A,b = self._prob_data
     sol1 = glpk.ilp(c, G, h, A, b, set([0]), set())
     self.assertTrue(sol1[0]=='optimal')
     sol2 = glpk.ilp(c, G, h, A, b, set([0]), set())
     self.assertTrue(sol2[0]=='optimal')
     sol3 = glpk.ilp(c, G, h, None, None, set([0, 1]), set())
     self.assertTrue(sol3[0]=='optimal')
     sol4 = glpk.ilp(c, G, h, None, None, set(), set([1]))
     self.assertTrue(sol4[0]=='optimal')
     sol5 = glpk.ilp(c, G, h, A, matrix(-1.0), set(), set([0,1]))
     self.assertTrue(sol5[0]=='LP relaxation is primal infeasible')
Ejemplo n.º 17
0
    def Fkkt(W):

        rti = W['rti'][0]

        # t = rti*rti' as a nonsymmetric matrix.
        t = matrix(0.0, (n, n))
        blas.gemm(rti, rti, t, transB='T')

        # Cholesky factorization of tsq = t.*t.
        tsq = t**2
        lapack.potrf(tsq)

        def f(x, y, z):
            """
            Solve
                          -diag(z)                           = bx
                -diag(x) - inv(rti*rti') * z * inv(rti*rti') = bs

            On entry, x and z contain bx and bs.  
            On exit, they contain the solution, with z scaled
            (inv(rti)'*z*inv(rti) is returned instead of z).

            We first solve 

                ((rti*rti') .* (rti*rti')) * x = bx - diag(t*bs*t) 

            and take z  = -rti' * (diag(x) + bs) * rti.
            """

            # tbst := t * zs * t = t * bs * t
            tbst = matrix(z, (n, n))
            cngrnc(t, tbst)

            # x := x - diag(tbst) = bx - diag(rti*rti' * bs * rti*rti')
            x -= tbst[::n + 1]

            # x := (t.*t)^{-1} * x = (t.*t)^{-1} * (bx - diag(t*bs*t))
            lapack.potrs(tsq, x)

            # z := z + diag(x) = bs + diag(x)
            z[::n + 1] += x

            # z := -rti' * z * rti = -rti' * (diag(x) + bs) * rti
            cngrnc(rti, z, alpha=-1.0)

        return f
Ejemplo n.º 18
0
    def cngrnc(r, x, alpha=1.0):
        """
        Congruence transformation

            x := alpha * r'*x*r.

        r and x are square matrices.  
        """

        # Scale diagonal of x by 1/2.
        x[::n + 1] *= 0.5

        # a := tril(x)*r
        a = +r
        tx = matrix(x, (n, n))
        blas.trmm(tx, a, side='L')

        # x := alpha*(a*r' + r*a')
        blas.syr2k(r, a, tx, trans='T', alpha=alpha)
        x[:] = tx[:]
Ejemplo n.º 19
0
    G[25, [16, 21]] = 1.0, -gamma

    # solve and return W, H, x, y, w, h
    sol = solvers.cpl(c, F, G, h)
    return  sol['x'][0], sol['x'][1], sol['x'][2:7], sol['x'][7:12], \
        sol['x'][12:17], sol['x'][17:]


try:
    import pylab
except ImportError:
    pass
else:
    pylab.figure(facecolor='w')
    pylab.subplot(221)
    Amin = matrix([100., 100., 100., 100., 100.])
    W, H, x, y, w, h = floorplan(Amin)
    for k in range(5):
        pylab.fill([x[k], x[k], x[k] + w[k], x[k] + w[k]],
                   [y[k], y[k] + h[k], y[k] + h[k], y[k]],
                   facecolor='#D0D0D0',
                   edgecolor='black')
        pylab.text(x[k] + .5 * w[k], y[k] + .5 * h[k], "%d" % (k + 1))
    pylab.axis([-1.0, 26, -1.0, 26])
    pylab.xticks([])
    pylab.yticks([])

    pylab.subplot(222)
    Amin = matrix([20., 50., 80., 150., 200.])
    W, H, x, y, w, h = floorplan(Amin)
    for k in range(5):
Ejemplo n.º 20
0
# The risk-return trade-off of section 8.4 (Quadratic programming).

from math import sqrt
from kvxopt import matrix
from kvxopt.blas import dot
from kvxopt.solvers import qp, options

n = 4
S = matrix([[4e-2, 6e-3, -4e-3, 0.0], [6e-3, 1e-2, 0.0, 0.0],
            [-4e-3, 0.0, 2.5e-3, 0.0], [0.0, 0.0, 0.0, 0.0]])
pbar = matrix([.12, .10, .07, .03])

G = matrix(0.0, (n, n))
G[::n + 1] = -1.0
h = matrix(0.0, (n, 1))
A = matrix(1.0, (1, n))
b = matrix(1.0)

N = 100
mus = [10**(5.0 * t / N - 1.0) for t in range(N)]
options['show_progress'] = False
xs = [qp(mu * S, -pbar, G, h, A, b)['x'] for mu in mus]
returns = [dot(pbar, x) for x in xs]
risks = [sqrt(dot(x, S * x)) for x in xs]

try:
    import pylab
except ImportError:
    pass
else:
    pylab.figure(1, facecolor='w')
Ejemplo n.º 21
0
def conelp(c, G, h, dims=None, taskfile=None, **kwargs):
    """
    Solves a pair of primal and dual SOCPs

        minimize    c'*x
        subject to  G*x + s = h
                    s >= 0

        maximize    -h'*z
        subject to  G'*z + c = 0
                    z >= 0

    using MOSEK 8.

    The inequalities are with respect to a cone C defined as the Cartesian
    product of N + M + 1 cones:

        C = C_0 x C_1 x .... x C_N x C_{N+1} x ... x C_{N+M}.

    The first cone C_0 is the nonnegative orthant of dimension ml.
    The next N cones are second order cones of dimension mq[0], ...,
    mq[N-1].  The second order cone of dimension m is defined as

        { (u0, u1) in R x R^{m-1} | u0 >= ||u1||_2 }.

    The next M cones are positive semidefinite cones of order ms[0], ...,
    ms[M-1] >= 0.

    The formats of G and h are identical to that used in solvers.conelp().


    Input arguments.

        c is a dense 'd' matrix of size (n,1).

        dims is a dictionary with the dimensions of the components of C.
        It has three fields.
        - dims['l'] = ml, the dimension of the nonnegative orthant C_0.
          (ml >= 0.)
        - dims['q'] = mq = [ mq[0], mq[1], ..., mq[N-1] ], a list of N
          integers with the dimensions of the second order cones C_1, ...,
          C_N.  (N >= 0 and mq[k] >= 1.)
        - dims['s'] = ms = [ ms[0], ms[1], ..., ms[M-1] ], a list of M
          integers with the orders of the semidefinite cones C_{N+1}, ...,
          C_{N+M}.  (M >= 0 and ms[k] >= 0.)
        The default value of dims is {'l': G.size[0], 'q': [], 's': []}.

        G is a dense or sparse 'd' matrix of size (K,n), where

            K = ml + mq[0] + ... + mq[N-1] + ms[0]**2 + ... + ms[M-1]**2.

        Each column of G describes a vector

            v = ( v_0, v_1, ..., v_N, vec(v_{N+1}), ..., vec(v_{N+M}) )

        in V = R^ml x R^mq[0] x ... x R^mq[N-1] x S^ms[0] x ... x S^ms[M-1]
        stored as a column vector

            [ v_0; v_1; ...; v_N; vec(v_{N+1}); ...; vec(v_{N+M}) ].

        Here, if u is a symmetric matrix of order m, then vec(u) is the
        matrix u stored in column major order as a vector of length m**2.
        We use BLAS unpacked 'L' storage, i.e., the entries in vec(u)
        corresponding to the strictly upper triangular entries of u are
        not referenced.

        h is a dense 'd' matrix of size (K,1), representing a vector in V,
        in the same format as the columns of G.

        A is a dense or sparse 'd' matrix of size (p,n).  The default value
        is a sparse 'd' matrix of size (0,n).

        b is a dense 'd' matrix of size (p,1).   The default value is a
        dense 'd' matrix of size (0,1).

        Optionally, the interface can write a .task file, required for
        support questions on the MOSEK solver.

    Return values

        solsta is a MOSEK solution status key.

            If solsta is mosek.solsta.optimal,
                then (x, zl, zq, zs) contains the primal-dual solution.
            If solsta is moseksolsta.prim_infeas_cer,
                then (x, zl, zq, zs) is a certificate of dual infeasibility.
            If solsta is moseksolsta.dual_infeas_cer,
                then (x, zl, zq, zs) is a certificate of primal infeasibility.
            If solsta is mosek.solsta.unknown,
                then (x, zl, zq, zs) are all None

            Other return values for solsta include:
                mosek.solsta.dual_feas
                mosek.solsta.near_dual_feas
                mosek.solsta.near_optimal
                mosek.solsta.near_prim_and_dual_feas
                mosek.solsta.near_prim_feas
                mosek.solsta.prim_and_dual_feas
                mosek.solsta.prim_feas
            in which case the (x,y,z) value may not be well-defined.

        x, z the primal-dual solution.


    Options are passed to MOSEK solvers via the msk.options dictionary,
    e.g., the following turns off output from the MOSEK solvers

        >>> msk.options = {mosek.iparam.log:0}

    see the MOSEK Python API manual.
    """

    with mosek.Env() as env:

        if dims is None:
            (solsta, x, y, z) = lp(c, G, h)
            return (solsta, x, z, None)

        N, n = G.size

        ml, mq, ms = dims['l'], dims['q'], [k * k for k in dims['s']]
        cdim = ml + sum(mq) + sum(ms)
        if cdim == 0: raise ValueError("ml+mq+ms cannot be 0")

        # Data for kth 'q' constraint are found in rows indq[k]:indq[k+1] of G.
        indq = [dims['l']]
        for k in dims['q']:
            indq = indq + [indq[-1] + k]

        # Data for the kth 's' constraint are found in rows indq[-1] + (inds[k]:inds[k+1]) of G.
        inds = [0]
        for k in dims['s']:
            inds = inds + [inds[-1] + k * k]

        if type(h) is not matrix or h.typecode != 'd' or h.size[1] != 1:
            raise TypeError("'h' must be a 'd' matrix with 1 column")
        if type(G) is matrix or type(G) is spmatrix:
            if G.typecode != 'd' or G.size[0] != cdim:
                raise TypeError("'G' must be a 'd' matrix with %d rows " %
                                cdim)
            if h.size[0] != cdim:
                raise TypeError("'h' must have %d rows" % cdim)
        else:
            raise TypeError("'G' must be a matrix")

        if len(dims['q']) and min(dims['q']) < 1:
            raise TypeError("dimensions of quadratic cones must be positive")

        if len(dims['s']) and min(dims['s']) < 1:
            raise TypeError(
                "dimensions of semidefinite cones must be positive")

        bkc = n * [mosek.boundkey.fx]
        blc = list(-c)
        buc = list(-c)

        dimx = ml + sum(mq)
        bkx = ml * [mosek.boundkey.lo] + sum(mq) * [mosek.boundkey.fr]
        blx = ml * [0.0] + sum(mq) * [-inf]
        bux = dimx * [+inf]
        c = list(-h)

        cl, cs = c[:dimx], sparse(c[dimx:])
        Gl, Gs = sparse(G[:dimx, :]), sparse(G[dimx:, :])
        colptr, asub, acof = Gl.T.CCS
        aptrb, aptre = colptr[:-1], colptr[1:]

        with env.Task(0, 0) as task:
            task.set_Stream(mosek.streamtype.log, streamprinter)

            # set MOSEK options
            options = kwargs.get('options', globals()['options'])
            for (param, val) in options.items():
                if str(param)[:6] == "iparam":
                    task.putintparam(param, val)
                elif str(param)[:6] == "dparam":
                    task.putdouparam(param, val)
                elif str(param)[:6] == "sparam":
                    task.putstrparam(param, val)
                else:
                    raise ValueError("invalid MOSEK parameter: " + str(param))

            task.inputdata(
                n,  # number of constraints
                dimx,  # number of variables
                cl,  # linear objective coefficients
                0.0,  # objective fixed value
                list(aptrb),
                list(aptre),
                list(asub),
                list(acof),
                bkc,
                blc,
                buc,
                bkx,
                blx,
                bux)

            task.putobjsense(mosek.objsense.maximize)

            numbarvar = len(dims['s'])
            task.appendbarvars(dims['s'])

            barcsubj, barcsubk, barcsubl = (inds[-1]) * [0], (
                inds[-1]) * [0], (inds[-1]) * [0]
            barcval = [-h[indq[-1] + k] for k in range(inds[0], inds[-1])]
            for s in range(numbarvar):
                for (k, idx) in enumerate(range(inds[s], inds[s + 1])):
                    barcsubk[idx] = k // dims['s'][s]
                    barcsubl[idx] = k % dims['s'][s]
                    barcsubj[idx] = s

            # filter out upper triangular part
            trilidx = [
                idx for idx in range(len(barcsubk))
                if barcsubk[idx] >= barcsubl[idx]
            ]
            barcsubj = [barcsubj[k] for k in trilidx]
            barcsubk = [barcsubk[k] for k in trilidx]
            barcsubl = [barcsubl[k] for k in trilidx]
            barcval = [barcval[k] for k in trilidx]

            task.putbarcblocktriplet(len(trilidx), barcsubj, barcsubk,
                                     barcsubl, barcval)

            Gst = Gs.T
            barasubi = len(Gst) * [0]
            barasubj = len(Gst) * [0]
            barasubk = len(Gst) * [0]
            barasubl = len(Gst) * [0]
            baraval = len(Gst) * [0.0]
            colptr, row, val = Gst.CCS

            for s in range(numbarvar):
                for j in range(ms[s]):
                    for idx in range(colptr[inds[s] + j],
                                     colptr[inds[s] + j + 1]):
                        barasubi[idx] = row[idx]
                        barasubj[idx] = s
                        barasubk[idx] = j // dims['s'][s]
                        barasubl[idx] = j % dims['s'][s]
                        baraval[idx] = val[idx]

            # filter out upper triangular part
            trilidx = [
                idx for (idx, (k, l)) in enumerate(zip(barasubk, barasubl))
                if k >= l
            ]
            barasubi = [barasubi[k] for k in trilidx]
            barasubj = [barasubj[k] for k in trilidx]
            barasubk = [barasubk[k] for k in trilidx]
            barasubl = [barasubl[k] for k in trilidx]
            baraval = [baraval[k] for k in trilidx]

            task.putbarablocktriplet(len(trilidx), barasubi, barasubj,
                                     barasubk, barasubl, baraval)

            for k in range(len(mq)):
                task.appendcone(mosek.conetype.quad, 0.0,
                                range(ml + sum(mq[:k]), ml + sum(mq[:k + 1])))

            if taskfile:
                task.writetask(taskfile)

            task.optimize()

            task.solutionsummary(mosek.streamtype.msg)

            solsta = task.getsolsta(mosek.soltype.itr)

            xu, xl, zq = n * [0.0], n * [0.0], sum(mq) * [0.0]
            task.getsolutionslice(mosek.soltype.itr, mosek.solitem.slc, 0, n,
                                  xl)
            task.getsolutionslice(mosek.soltype.itr, mosek.solitem.suc, 0, n,
                                  xu)
            task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, ml,
                                  dimx, zq)
            x = matrix(xu) - matrix(xl)
            zq = matrix(zq)

            for s in range(numbarvar):
                xx = (dims['s'][s] * (dims['s'][s] + 1) >> 1) * [0.0]
                task.getbarxj(mosek.soltype.itr, s, xx)

                xs = matrix(0.0, (dims['s'][s], dims['s'][s]))
                idx = 0
                for j in range(dims['s'][s]):
                    for i in range(j, dims['s'][s]):
                        xs[i, j] = xx[idx]
                        if i != j:
                            xs[j, i] = xx[idx]
                        idx += 1

                zq = matrix([zq, xs[:]])

            if ml:
                zl = ml * [0.0]
                task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0,
                                      ml, zl)
                zl = matrix(zl)
            else:
                zl = matrix(0.0, (0, 1))

    if (solsta is mosek.solsta.unknown):
        return (solsta, None, None)
    else:
        return (solsta, x, matrix([zl, zq]))
Ejemplo n.º 22
0
def socp(c, Gl=None, hl=None, Gq=None, hq=None, taskfile=None, **kwargs):
    """
    Solves a pair of primal and dual SOCPs

        minimize    c'*x
        subject to  Gl*x + sl = hl
                    Gq[k]*x + sq[k] = hq[k],  k = 0, ..., N-1
                    sl >= 0,
                    sq[k] >= 0, k = 0, ..., N-1

        maximize    -hl'*zl - sum_k hq[k]'*zq[k]
        subject to  Gl'*zl + sum_k Gq[k]'*zq[k] + c = 0
                    zl >= 0,  zq[k] >= 0, k = 0, ..., N-1.

    using MOSEK 8.

    solsta, x, zl, zq = socp(c, Gl = None, hl = None, Gq = None, hq = None, taskfile=None)

    Return values

        solsta is a MOSEK solution status key.
            If solsta is mosek.solsta.optimal,
                then (x, zl, zq) contains the primal-dual solution.
            If solsta is mosek.solsta.prim_infeas_cer,
                then (x, zl, zq) is a certificate of dual infeasibility.
            If solsta is mosek.solsta.dual_infeas_cer,
                then (x, zl, zq) is a certificate of primal infeasibility.
            If solsta is mosek.solsta.unknown,
                then (x, zl, zq) are all None

            Other return values for solsta include:
                mosek.solsta.dual_feas
                mosek.solsta.near_dual_feas
                mosek.solsta.near_optimal
                mosek.solsta.near_prim_and_dual_feas
                mosek.solsta.near_prim_feas
                mosek.solsta.prim_and_dual_feas
                mosek.solsta.prim_feas
             in which case the (x,y,z) value may not be well-defined.

        x, zl, zq  the primal-dual solution.


    Options are passed to MOSEK solvers via the msk.options dictionary,
    e.g., the following turns off output from the MOSEK solvers

        >>> msk.options = {mosek.iparam.log: 0}

    see the MOSEK Python API manual.

    Optionally, the interface can write a .task file, required for
    support questions on the MOSEK solver.
    """

    with mosek.Env() as env:

        if type(c) is not matrix or c.typecode != 'd' or c.size[1] != 1:
            raise TypeError("'c' must be a dense column matrix")
        n = c.size[0]
        if n < 1: raise ValueError("number of variables must be at least 1")

        if Gl is None: Gl = spmatrix([], [], [], (0, n), tc='d')
        if (type(Gl) is not matrix and type(Gl) is not spmatrix) or \
            Gl.typecode != 'd' or Gl.size[1] != n:
            raise TypeError("'Gl' must be a dense or sparse 'd' matrix "\
                "with %d columns" %n)
        ml = Gl.size[0]
        if hl is None: hl = matrix(0.0, (0, 1))
        if type(hl) is not matrix or hl.typecode != 'd' or \
            hl.size != (ml,1):
            raise TypeError("'hl' must be a dense 'd' matrix of " \
                "size (%d,1)" %ml)

        if Gq is None: Gq = []
        if type(Gq) is not list or [
                G for G in Gq
                if (type(G) is not matrix and type(G) is not spmatrix)
                or G.typecode != 'd' or G.size[1] != n
        ]:
            raise TypeError("'Gq' must be a list of sparse or dense 'd' "\
                "matrices with %d columns" %n)
        mq = [G.size[0] for G in Gq]
        a = [k for k in range(len(mq)) if mq[k] == 0]
        if a: raise TypeError("the number of rows of Gq[%d] is zero" % a[0])
        if hq is None: hq = []
        if type(hq) is not list or len(hq) != len(mq) or [
                h for h in hq
                if (type(h) is not matrix and type(h) is not spmatrix)
                or h.typecode != 'd'
        ]:
            raise TypeError("'hq' must be a list of %d dense or sparse "\
                "'d' matrices" %len(mq))
        a = [k for k in range(len(mq)) if hq[k].size != (mq[k], 1)]
        if a:
            k = a[0]
            raise TypeError("'hq[%d]' has size (%d,%d).  Expected size "\
                "is (%d,1)." %(k, hq[k].size[0], hq[k].size[1], mq[k]))

        N = ml + sum(mq)
        h = matrix(0.0, (N, 1))
        if type(Gl) is matrix or [Gk for Gk in Gq if type(Gk) is matrix]:
            G = matrix(0.0, (N, n))
        else:
            G = spmatrix([], [], [], (N, n), 'd')
        h[:ml] = hl
        G[:ml, :] = Gl
        ind = ml
        for k in range(len(mq)):
            h[ind:ind + mq[k]] = hq[k]
            G[ind:ind + mq[k], :] = Gq[k]
            ind += mq[k]

        bkc = n * [mosek.boundkey.fx]
        blc = list(-c)
        buc = list(-c)

        bkx = ml * [mosek.boundkey.lo] + sum(mq) * [mosek.boundkey.fr]
        blx = ml * [0.0] + sum(mq) * [-inf]
        bux = N * [+inf]

        c = -h

        colptr, asub, acof = sparse([G.T]).CCS
        aptrb, aptre = colptr[:-1], colptr[1:]

        with env.Task(0, 0) as task:
            task.set_Stream(mosek.streamtype.log, streamprinter)

            # set MOSEK options
            options = kwargs.get('options', globals()['options'])
            for (param, val) in options.items():
                if str(param)[:6] == "iparam":
                    task.putintparam(param, val)
                elif str(param)[:6] == "dparam":
                    task.putdouparam(param, val)
                elif str(param)[:6] == "sparam":
                    task.putstrparam(param, val)
                else:
                    raise ValueError("invalid MOSEK parameter: " + str(param))

            task.inputdata(
                n,  # number of constraints
                N,  # number of variables
                list(c),  # linear objective coefficients
                0.0,  # objective fixed value
                list(aptrb),
                list(aptre),
                list(asub),
                list(acof),
                bkc,
                blc,
                buc,
                bkx,
                blx,
                bux)

            task.putobjsense(mosek.objsense.maximize)

            for k in range(len(mq)):
                task.appendcone(
                    mosek.conetype.quad, 0.0,
                    list(range(ml + sum(mq[:k]), ml + sum(mq[:k + 1]))))

            if taskfile:
                task.writetask(taskfile)

            task.optimize()

            task.solutionsummary(mosek.streamtype.msg)

            solsta = task.getsolsta(mosek.soltype.itr)

            xu, xl, zq = n * [0.0], n * [0.0], sum(mq) * [0.0]
            task.getsolutionslice(mosek.soltype.itr, mosek.solitem.slc, 0, n,
                                  xl)
            task.getsolutionslice(mosek.soltype.itr, mosek.solitem.suc, 0, n,
                                  xu)
            task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, ml, N,
                                  zq)
            x = matrix(xu) - matrix(xl)

            zq = [
                matrix(zq[sum(mq[:k]):sum(mq[:k + 1])]) for k in range(len(mq))
            ]

            if ml:
                zl = ml * [0.0]
                task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0,
                                      ml, zl)
                zl = matrix(zl)
            else:
                zl = matrix(0.0, (0, 1))

    if (solsta is mosek.solsta.unknown):
        return (solsta, None, None, None)
    else:
        return (solsta, x, zl, zq)
Ejemplo n.º 23
0
def lp(c, G, h, A=None, b=None, taskfile=None, **kwargs):
    """
    Solves a pair of primal and dual LPs

        minimize    c'*x             maximize    -h'*z - b'*y
        subject to  G*x + s = h      subject to  G'*z + A'*y + c = 0
                    A*x = b                      z >= 0.
                    s >= 0

    using MOSEK 8.

    (solsta, x, z, y) = lp(c, G, h, A=None, b=None).

    Input arguments

        c is n x 1, G is m x n, h is m x 1, A is p x n, b is p x 1.  G and
        A must be dense or sparse 'd' matrices.  c, h and b are dense 'd'
        matrices with one column.  The default values for A and b are
        empty matrices with zero rows.

        Optionally, the interface can write a .task file, required for
        support questions on the MOSEK solver.

    Return values

        solsta is a MOSEK solution status key.

            If solsta is mosek.solsta.optimal, then (x, y, z) contains the
                primal-dual solution.
            If solsta is mosek.solsta.prim_infeas_cer, then (x, y, z) is a
                certificate of primal infeasibility.
            If solsta is mosek.solsta.dual_infeas_cer, then (x, y, z) is a
                certificate of dual infeasibility.
            If solsta is mosek.solsta.unknown, then (x, y, z) are all None.

            Other return values for solsta include:
                mosek.solsta.dual_feas
                mosek.solsta.near_dual_feas
                mosek.solsta.near_optimal
                mosek.solsta.near_prim_and_dual_feas
                mosek.solsta.near_prim_feas
                mosek.solsta.prim_and_dual_feas
                mosek.solsta.prim_feas
             in which case the (x,y,z) value may not be well-defined.

        x, y, z  the primal-dual solution.

    Options are passed to MOSEK solvers via the msk.options dictionary.
    For example, the following turns off output from the MOSEK solvers

        >>> msk.options = {mosek.iparam.log: 0}

    see the MOSEK Python API manual.
    """

    with mosek.Env() as env:

        if type(c) is not matrix or c.typecode != 'd' or c.size[1] != 1:
            raise TypeError("'c' must be a dense column matrix")
        n = c.size[0]
        if n < 1: raise ValueError("number of variables must be at least 1")

        if (type(G) is not matrix and type(G) is not spmatrix) or \
            G.typecode != 'd' or G.size[1] != n:
            raise TypeError("'G' must be a dense or sparse 'd' matrix "\
                "with %d columns" %n)
        m = G.size[0]
        if m == 0: raise ValueError("m cannot be 0")

        if type(h) is not matrix or h.typecode != 'd' or h.size != (m, 1):
            raise TypeError("'h' must be a 'd' matrix of size (%d,1)" % m)

        if A is None: A = spmatrix([], [], [], (0, n), 'd')
        if (type(A) is not matrix and type(A) is not spmatrix) or \
            A.typecode != 'd' or A.size[1] != n:
            raise TypeError("'A' must be a dense or sparse 'd' matrix "\
                "with %d columns" %n)
        p = A.size[0]
        if b is None: b = matrix(0.0, (0, 1))
        if type(b) is not matrix or b.typecode != 'd' or b.size != (p, 1):
            raise TypeError("'b' must be a dense matrix of size (%d,1)" % p)

        bkc = m * [mosek.boundkey.up] + p * [mosek.boundkey.fx]
        blc = m * [-inf] + [bi for bi in b]
        buc = list(h) + list(b)

        bkx = n * [mosek.boundkey.fr]
        blx = n * [-inf]
        bux = n * [+inf]

        colptr, asub, acof = sparse([G, A]).CCS
        aptrb, aptre = colptr[:-1], colptr[1:]

        with env.Task(0, 0) as task:
            task.set_Stream(mosek.streamtype.log, streamprinter)

            # set MOSEK options
            options = kwargs.get('options', globals()['options'])
            for (param, val) in options.items():
                if str(param)[:6] == "iparam":
                    task.putintparam(param, val)
                elif str(param)[:6] == "dparam":
                    task.putdouparam(param, val)
                elif str(param)[:6] == "sparam":
                    task.putstrparam(param, val)
                else:
                    raise ValueError("invalid MOSEK parameter: " + str(param))

            task.inputdata(
                m + p,  # number of constraints
                n,  # number of variables
                list(c),  # linear objective coefficients
                0.0,  # objective fixed value
                list(aptrb),
                list(aptre),
                list(asub),
                list(acof),
                bkc,
                blc,
                buc,
                bkx,
                blx,
                bux)

            task.putobjsense(mosek.objsense.minimize)

            if taskfile:
                task.writetask(taskfile)

            task.optimize()

            task.solutionsummary(mosek.streamtype.msg)

            solsta = task.getsolsta(mosek.soltype.bas)

            x, z = n * [0.0], m * [0.0]
            task.getsolutionslice(mosek.soltype.bas, mosek.solitem.xx, 0, n, x)
            task.getsolutionslice(mosek.soltype.bas, mosek.solitem.suc, 0, m,
                                  z)
            x, z = matrix(x), matrix(z)

            if p != 0:
                yu, yl = p * [0.0], p * [0.0]
                task.getsolutionslice(mosek.soltype.bas, mosek.solitem.suc, m,
                                      m + p, yu)
                task.getsolutionslice(mosek.soltype.bas, mosek.solitem.slc, m,
                                      m + p, yl)
                y = matrix(yu) - matrix(yl)
            else:
                y = matrix(0.0, (0, 1))

    if (solsta is mosek.solsta.unknown):
        return (solsta, None, None, None)
    else:
        return (solsta, x, z, y)
Ejemplo n.º 24
0
def ilp(c, G, h, A=None, b=None, I=None, taskfile=None, **kwargs):
    """
    Solves the mixed integer LP

        minimize    c'*x
        subject to  G*x + s = h
                    A*x = b
                    s >= 0
                    xi integer, forall i in I

    using MOSEK 8.

    solsta, x = ilp(c, G, h, A=None, b=None, I=None, taskfile=None).

    Input arguments

        G is m x n, h is m x 1, A is p x n, b is p x 1.  G and A must be
        dense or sparse 'd' matrices.   h and b are dense 'd' matrices
        with one column.  The default values for A and b are empty
        matrices with zero rows.

        I is a Python set with indices of integer elements of x.  By
        default all elements in x are constrained to be integer, i.e.,
        the default value of I is I = set(range(n))

        Dual variables are not returned for MOSEK.

        Optionally, the interface can write a .task file, required for
        support questions on the MOSEK solver.

    Return values

        solsta is a MOSEK solution status key.

            If solsta is mosek.solsta.integer_optimal, then x contains
                the solution.
            If solsta is mosek.solsta.unknown, then x is None.

            Other return values for solsta include:
                mosek.solsta.near_integer_optimal
            in which case the x value may not be well-defined,
            c.f., section 17.48 of the MOSEK Python API manual.

        x is the solution

    Options are passed to MOSEK solvers via the msk.options dictionary,
    e.g., the following turns off output from the MOSEK solvers

    >>> msk.options = {mosek.iparam.log: 0}

    see the MOSEK Python API manual.
    """

    with mosek.Env() as env:

        if type(c) is not matrix or c.typecode != 'd' or c.size[1] != 1:
            raise TypeError("'c' must be a dense column matrix")
        n = c.size[0]
        if n < 1: raise ValueError("number of variables must be at least 1")

        if (type(G) is not matrix and type(G) is not spmatrix) or \
            G.typecode != 'd' or G.size[1] != n:
            raise TypeError("'G' must be a dense or sparse 'd' matrix "\
                "with %d columns" %n)
        m = G.size[0]
        if m == 0: raise ValueError("m cannot be 0")

        if type(h) is not matrix or h.typecode != 'd' or h.size != (m, 1):
            raise TypeError("'h' must be a 'd' matrix of size (%d,1)" % m)

        if A is None: A = spmatrix([], [], [], (0, n), 'd')
        if (type(A) is not matrix and type(A) is not spmatrix) or \
            A.typecode != 'd' or A.size[1] != n:
            raise TypeError("'A' must be a dense or sparse 'd' matrix "\
                "with %d columns" %n)
        p = A.size[0]
        if b is None: b = matrix(0.0, (0, 1))
        if type(b) is not matrix or b.typecode != 'd' or b.size != (p, 1):
            raise TypeError("'b' must be a dense matrix of size (%d,1)" % p)

        if I is None: I = set(range(n))

        if type(I) is not set:
            raise TypeError("invalid argument for integer index set")

        for i in I:
            if type(i) is not int:
                raise TypeError("invalid integer index set I")

        if len(I) > 0 and min(I) < 0:
            raise IndexError("negative element in integer index set I")
        if len(I) > 0 and max(I) > n - 1:
            raise IndexError(
                "maximum element in in integer index set I is larger than n-1")

        bkc = m * [mosek.boundkey.up] + p * [mosek.boundkey.fx]
        blc = m * [-inf] + [bi for bi in b]
        buc = list(h) + list(b)

        bkx = n * [mosek.boundkey.fr]
        blx = n * [-inf]
        bux = n * [+inf]

        colptr, asub, acof = sparse([G, A]).CCS
        aptrb, aptre = colptr[:-1], colptr[1:]

        with env.Task(0, 0) as task:
            task.set_Stream(mosek.streamtype.log, streamprinter)

            # set MOSEK options
            options = kwargs.get('options', globals()['options'])
            for (param, val) in options.items():
                if str(param)[:6] == "iparam":
                    task.putintparam(param, val)
                elif str(param)[:6] == "dparam":
                    task.putdouparam(param, val)
                elif str(param)[:6] == "sparam":
                    task.putstrparam(param, val)
                else:
                    raise ValueError("invalid MOSEK parameter: " + str(param))

            task.inputdata(
                m + p,  # number of constraints
                n,  # number of variables
                list(c),  # linear objective coefficients
                0.0,  # objective fixed value
                list(aptrb),
                list(aptre),
                list(asub),
                list(acof),
                bkc,
                blc,
                buc,
                bkx,
                blx,
                bux)

            task.putobjsense(mosek.objsense.minimize)

            # Define integer variables
            if len(I) > 0:
                task.putvartypelist(list(I),
                                    len(I) * [mosek.variabletype.type_int])

            task.putintparam(mosek.iparam.mio_mode, mosek.miomode.satisfied)

            if taskfile:
                task.writetask(taskfile)

            task.optimize()

            task.solutionsummary(mosek.streamtype.msg)

            if len(I) > 0:
                solsta = task.getsolsta(mosek.soltype.itg)
            else:
                solsta = task.getsolsta(mosek.soltype.bas)

            x = n * [0.0]
            if len(I) > 0:
                task.getsolutionslice(mosek.soltype.itg, mosek.solitem.xx, 0,
                                      n, x)
            else:
                task.getsolutionslice(mosek.soltype.bas, mosek.solitem.xx, 0,
                                      n, x)
            x = matrix(x)

    if (solsta is mosek.solsta.unknown):
        return (solsta, None)
    else:
        return (solsta, x)
Ejemplo n.º 25
0
def qp(P, q, G=None, h=None, A=None, b=None, taskfile=None, **kwargs):
    """
    Solves a quadratic program

        minimize    (1/2)*x'*P*x + q'*x
        subject to  G*x <= h
                    A*x = b.

    using MOSEK 8.

    solsta, x, z, y = qp(P, q, G=None, h=None, A=None, b=None, taskfile=None)

    Return values

        solsta is a MOSEK solution status key.

            If solsta is mosek.solsta.optimal,
                then (x, y, z) contains the primal-dual solution.
            If solsta is mosek.solsta.prim_infeas_cer,
                then (x, y, z) is a certificate of primal infeasibility.
            If solsta is mosek.solsta.dual_infeas_cer,
                then (x, y, z) is a certificate of dual infeasibility.
            If solsta is mosek.solsta.unknown, then (x, y, z) are all None.

            Other return values for solsta include:
                mosek.solsta.dual_feas
                mosek.solsta.near_dual_feas
                mosek.solsta.near_optimal
                mosek.solsta.near_prim_and_dual_feas
                mosek.solsta.near_prim_feas
                mosek.solsta.prim_and_dual_feas
                mosek.solsta.prim_feas
            in which case the (x,y,z) value may not be well-defined.

        x, z, y  the primal-dual solution.

    Options are passed to MOSEK solvers via the msk.options dictionary,
    e.g., the following turns off output from the MOSEK solvers

        >>> msk.options = {mosek.iparam.log: 0}

    see the MOSEK Python API manual.

    Optionally, the interface can write a .task file, required for
    support questions on the MOSEK solver.
    """

    with mosek.Env() as env:

        if (type(P) is not matrix and type(P) is not spmatrix) or \
            P.typecode != 'd' or P.size[0] != P.size[1]:
            raise TypeError("'P' must be a square dense or sparse 'd' matrix ")
        n = P.size[0]

        if n < 1: raise ValueError("number of variables must be at least 1")

        if type(q) is not matrix or q.typecode != 'd' or q.size != (n, 1):
            raise TypeError("'q' must be a 'd' matrix of size (%d,1)" % n)

        if G is None: G = spmatrix([], [], [], (0, n), 'd')
        if (type(G) is not matrix and type(G) is not spmatrix) or \
            G.typecode != 'd' or G.size[1] != n:
            raise TypeError("'G' must be a dense or sparse 'd' matrix "\
                "with %d columns" %n)

        m = G.size[0]
        if h is None: h = matrix(0.0, (0, 1))
        if type(h) is not matrix or h.typecode != 'd' or h.size != (m, 1):
            raise TypeError("'h' must be a 'd' matrix of size (%d,1)" % m)

        if A is None: A = spmatrix([], [], [], (0, n), 'd')
        if (type(A) is not matrix and type(A) is not spmatrix) or \
            A.typecode != 'd' or A.size[1] != n:
            raise TypeError("'A' must be a dense or sparse 'd' matrix "\
                "with %d columns" %n)
        p = A.size[0]
        if b is None: b = matrix(0.0, (0, 1))
        if type(b) is not matrix or b.typecode != 'd' or b.size != (p, 1):
            raise TypeError("'b' must be a dense matrix of size (%d,1)" % p)

        if m + p == 0: raise ValueError("m + p must be greater than 0")

        c = list(q)

        bkc = m * [mosek.boundkey.up] + p * [mosek.boundkey.fx]
        blc = m * [-inf] + [bi for bi in b]
        buc = list(h) + list(b)

        bkx = n * [mosek.boundkey.fr]
        blx = n * [-inf]
        bux = n * [+inf]

        colptr, asub, acof = sparse([G, A]).CCS
        aptrb, aptre = colptr[:-1], colptr[1:]

        with env.Task(0, 0) as task:
            task.set_Stream(mosek.streamtype.log, streamprinter)

            # set MOSEK options
            options = kwargs.get('options', globals()['options'])
            for (param, val) in options.items():
                if str(param)[:6] == "iparam":
                    task.putintparam(param, val)
                elif str(param)[:6] == "dparam":
                    task.putdouparam(param, val)
                elif str(param)[:6] == "sparam":
                    task.putstrparam(param, val)
                else:
                    raise ValueError("invalid MOSEK parameter: " + str(param))

            task.inputdata(
                m + p,  # number of constraints
                n,  # number of variables
                c,  # linear objective coefficients
                0.0,  # objective fixed value
                list(aptrb),
                list(aptre),
                list(asub),
                list(acof),
                bkc,
                blc,
                buc,
                bkx,
                blx,
                bux)

            Ps = sparse(P)
            I, J = Ps.I, Ps.J
            tril = [k for k in range(len(I)) if I[k] >= J[k]]
            task.putqobj(list(I[tril]), list(J[tril]), list(Ps.V[tril]))

            task.putobjsense(mosek.objsense.minimize)

            if taskfile:
                task.writetask(taskfile)

            task.optimize()

            task.solutionsummary(mosek.streamtype.msg)

            solsta = task.getsolsta(mosek.soltype.itr)

            x = n * [0.0]
            task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0, n, x)
            x = matrix(x)

            if m != 0:
                z = m * [0.0]
                task.getsolutionslice(mosek.soltype.itr, mosek.solitem.suc, 0,
                                      m, z)
                z = matrix(z)
            else:
                z = matrix(0.0, (0, 1))

            if p != 0:
                yu, yl = p * [0.0], p * [0.0]
                task.getsolutionslice(mosek.soltype.itr, mosek.solitem.suc, m,
                                      m + p, yu)
                task.getsolutionslice(mosek.soltype.itr, mosek.solitem.slc, m,
                                      m + p, yl)
                y = matrix(yu) - matrix(yl)
            else:
                y = matrix(0.0, (0, 1))

    if (solsta is mosek.solsta.unknown):
        return (solsta, None, None, None)
    else:
        return (solsta, x, z, y)
Ejemplo n.º 26
0
# The quadratic cone program of section 8.2 (Quadratic cone programs).

# minimize   (1/2)*x'*A'*A*x - b'*A*x
# subject to x >= 0
#            ||x||_2 <= 1

from kvxopt import matrix, solvers
A = matrix([[.3, -.4, -.2, -.4, 1.3], [.6, 1.2, -1.7, .3, -.3],
            [-.3, .0, .6, -1.2, -2.0]])
b = matrix([1.5, .0, -1.2, -.7, .0])
m, n = A.size

I = matrix(0.0, (n, n))
I[::n + 1] = 1.0
G = matrix([-I, matrix(0.0, (1, n)), I])
h = matrix(n * [0.0] + [1.0] + n * [0.0])
dims = {'l': n, 'q': [n + 1], 's': []}
x = solvers.coneqp(A.T * A, -A.T * b, G, h, dims)['x']
print("\nx = \n")
print(x)
Ejemplo n.º 27
0
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
Ejemplo n.º 28
0
def l1regls(A, y):
    """
    
    Returns the solution of l1-norm regularized least-squares problem
  
        minimize || A*x - y ||_2^2  + || x ||_1.

    """

    m, n = A.size
    q = matrix(1.0, (2 * n, 1))
    q[:n] = -2.0 * A.T * y

    def P(u, v, alpha=1.0, beta=0.0):
        """
            v := alpha * 2.0 * [ A'*A, 0; 0, 0 ] * u + beta * v 
        """
        v *= beta
        v[:n] += alpha * 2.0 * A.T * (A * u[:n])

    def G(u, v, alpha=1.0, beta=0.0, trans='N'):
        """
            v := alpha*[I, -I; -I, -I] * u + beta * v  (trans = 'N' or 'T')
        """

        v *= beta
        v[:n] += alpha * (u[:n] - u[n:])
        v[n:] += alpha * (-u[:n] - u[n:])

    h = matrix(0.0, (2 * n, 1))

    # Customized solver for the KKT system
    #
    #     [  2.0*A'*A  0    I      -I     ] [x[:n] ]     [bx[:n] ]
    #     [  0         0   -I      -I     ] [x[n:] ]  =  [bx[n:] ].
    #     [  I        -I   -D1^-1   0     ] [zl[:n]]     [bzl[:n]]
    #     [ -I        -I    0      -D2^-1 ] [zl[n:]]     [bzl[n:]]
    #
    # where D1 = W['di'][:n]**2, D2 = W['di'][n:]**2.
    #
    # We first eliminate zl and x[n:]:
    #
    #     ( 2*A'*A + 4*D1*D2*(D1+D2)^-1 ) * x[:n] =
    #         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:]
    #
    #     x[n:] = (D1+D2)^-1 * ( bx[n:] - D1*bzl[:n]  - D2*bzl[n:] )
    #         - (D2-D1)*(D1+D2)^-1 * x[:n]
    #
    #     zl[:n] = D1 * ( x[:n] - x[n:] - bzl[:n] )
    #     zl[n:] = D2 * (-x[:n] - x[n:] - bzl[n:] ).
    #
    # The first equation has the form
    #
    #     (A'*A + D)*x[:n]  =  rhs
    #
    # and is equivalent to
    #
    #     [ D    A' ] [ x:n] ]  = [ rhs ]
    #     [ A   -I  ] [ v    ]    [ 0   ].
    #
    # It can be solved as
    #
    #     ( A*D^-1*A' + I ) * v = A * D^-1 * rhs
    #     x[:n] = D^-1 * ( rhs - A'*v ).

    S = matrix(0.0, (m, m))
    Asc = matrix(0.0, (m, n))
    v = matrix(0.0, (m, 1))

    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

    return solvers.coneqp(P, q, G, h, kktsolver=Fkkt)['x'][:n]
Ejemplo n.º 29
0
def floorplan(Amin):

    #     minimize    W+H
    #     subject to  Amink / hk <= wk, k = 1,..., 5
    #                 x1 >= 0,  x2 >= 0, x4 >= 0
    #                 x1 + w1 + rho <= x3
    #                 x2 + w2 + rho <= x3
    #                 x3 + w3 + rho <= x5
    #                 x4 + w4 + rho <= x5
    #                 x5 + w5 <= W
    #                 y2 >= 0,  y3 >= 0,  y5 >= 0
    #                 y2 + h2 + rho <= y1
    #                 y1 + h1 + rho <= y4
    #                 y3 + h3 + rho <= y4
    #                 y4 + h4 <= H
    #                 y5 + h5 <= H
    #                 hk/gamma <= wk <= gamma*hk,  k = 1, ..., 5
    #
    # 22 Variables W, H, x (5), y (5), w (5), h (5).
    #
    # W, H:  scalars; bounding box width and height
    # x, y:  5-vectors; coordinates of bottom left corners of blocks
    # w, h:  5-vectors; widths and heigths of the 5 blocks

    rho, gamma = 1.0, 5.0  # min spacing, min aspect ratio

    # The objective is to minimize W + H.  There are five nonlinear
    # constraints
    #
    #     -wk + Amink / hk <= 0,  k = 1, ..., 5

    c = matrix(2 * [1.0] + 20 * [0.0])

    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

    G = matrix(0.0, (26, 22))
    h = matrix(0.0, (26, 1))

    # -x1 <= 0
    G[0, 2] = -1.0

    # -x2 <= 0
    G[1, 3] = -1.0

    # -x4 <= 0
    G[2, 5] = -1.0

    # x1 - x3 + w1 <= -rho
    G[3, [2, 4, 12]], h[3] = [1.0, -1.0, 1.0], -rho

    # x2 - x3 + w2 <= -rho
    G[4, [3, 4, 13]], h[4] = [1.0, -1.0, 1.0], -rho

    # x3 - x5 + w3 <= -rho
    G[5, [4, 6, 14]], h[5] = [1.0, -1.0, 1.0], -rho

    # x4 - x5 + w4 <= -rho
    G[6, [5, 6, 15]], h[6] = [1.0, -1.0, 1.0], -rho

    # -W + x5 + w5 <= 0
    G[7, [0, 6, 16]] = -1.0, 1.0, 1.0

    # -y2 <= 0
    G[8, 8] = -1.0

    # -y3 <= 0
    G[9, 9] = -1.0

    # -y5 <= 0
    G[10, 11] = -1.0

    # -y1 + y2 + h2 <= -rho
    G[11, [7, 8, 18]], h[11] = [-1.0, 1.0, 1.0], -rho

    # y1 - y4 + h1 <= -rho
    G[12, [7, 10, 17]], h[12] = [1.0, -1.0, 1.0], -rho

    # y3 - y4 + h3 <= -rho
    G[13, [9, 10, 19]], h[13] = [1.0, -1.0, 1.0], -rho

    # -H + y4 + h4 <= 0
    G[14, [1, 10, 20]] = -1.0, 1.0, 1.0

    # -H + y5 + h5 <= 0
    G[15, [1, 11, 21]] = -1.0, 1.0, 1.0

    # -w1 + h1/gamma <= 0
    G[16, [12, 17]] = -1.0, 1.0 / gamma

    # w1 - gamma * h1 <= 0
    G[17, [12, 17]] = 1.0, -gamma

    # -w2 + h2/gamma <= 0
    G[18, [13, 18]] = -1.0, 1.0 / gamma

    #  w2 - gamma * h2 <= 0
    G[19, [13, 18]] = 1.0, -gamma

    # -w3 + h3/gamma <= 0
    G[20, [14, 18]] = -1.0, 1.0 / gamma

    #  w3 - gamma * h3 <= 0
    G[21, [14, 19]] = 1.0, -gamma

    # -w4  + h4/gamma <= 0
    G[22, [15, 19]] = -1.0, 1.0 / gamma

    #  w4 - gamma * h4 <= 0
    G[23, [15, 20]] = 1.0, -gamma

    # -w5 + h5/gamma <= 0
    G[24, [16, 21]] = -1.0, 1.0 / gamma

    #  w5 - gamma * h5 <= 0.0
    G[25, [16, 21]] = 1.0, -gamma

    # solve and return W, H, x, y, w, h
    sol = solvers.cpl(c, F, G, h)
    return  sol['x'][0], sol['x'][1], sol['x'][2:7], sol['x'][7:12], \
        sol['x'][12:17], sol['x'][17:]
Ejemplo n.º 30
0
        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


# Generate an analytic centering problem  
#
#    -b1 <=  Ar*x <= b2 
#
# with random mxn Ar and random b1, b2.

m, n  = 500, 500
Ar = normal(m,n);
A = matrix([Ar, -Ar])
b = uniform(2*m,1)

x, ntdecrs = acent(A, b)  
try: 
    import pylab
except ImportError: 
    pass
else:
    pylab.semilogy(range(len(ntdecrs)), ntdecrs, 'o', 
             range(len(ntdecrs)), ntdecrs, '-')
    pylab.xlabel('Iteration number')
    pylab.ylabel('Newton decrement')
    pylab.show()