Example #1
0
        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:])
Example #2
0
    def Fgp(x = None, z = None):

        if x is None: return mnl, matrix(0.0, (n,1))

        f = matrix(0.0, (mnl+1,1))
        Df = matrix(0.0, (mnl+1,n))

        # y = F*x+g
        blas.copy(g, y)
        base.gemv(F, x, y, beta=1.0)

        if z is not None: H = matrix(0.0, (n,n))

        for i, start, stop in ind:

            # yi := exp(yi) = exp(Fi*x+gi)
            ymax = max(y[start:stop])
            y[start:stop] = base.exp(y[start:stop] - ymax)

            # fi = log sum yi = log sum exp(Fi*x+gi)
            ysum = blas.asum(y, n=stop-start, offset=start)
            f[i] = ymax + math.log(ysum)

            # yi := yi / sum(yi) = exp(Fi*x+gi) / sum(exp(Fi*x+gi))
            blas.scal(1.0/ysum, y, n=stop-start, offset=start)

            # gradfi := Fi' * yi
            #        = Fi' * exp(Fi*x+gi) / sum(exp(Fi*x+gi))
            base.gemv(F, y, Df, trans='T', m=stop-start, incy=mnl+1,
                offsetA=start, offsetx=start, offsety=i)

            if z is not None:

                # Hi = Fi' * (diag(yi) - yi*yi') * Fi
                #    = Fisc' * Fisc
                # where
                # Fisc = diag(yi)^1/2 * (I - 1*yi') * Fi
                #      = diag(yi)^1/2 * (Fi - 1*gradfi')

                Fsc[:K[i], :] = F[start:stop, :]
                for k in range(start,stop):
                   blas.axpy(Df, Fsc, n=n, alpha=-1.0, incx=mnl+1,
                       incy=Fsc.size[0], offsetx=i, offsety=k-start)
                   blas.scal(math.sqrt(y[k]), Fsc, inc=Fsc.size[0],
                       offset=k-start)

                # H += z[i]*Hi = z[i] * Fisc' * Fisc
                blas.syrk(Fsc, H, trans='T', k=stop-start, alpha=z[i],
                    beta=1.0)

        if z is None:
            return f, Df
        return f, Df, H
Example #3
0
    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
Example #4
0
File: base.py Project: cvxopt/smcp
    def _gen_randsdp(self,V,m,d,seed):
        """
        Random data generator
        """
        setseed(seed)
        n = self._n
        V = chompack.tril(V)
        N = len(V)
        I = V.I; J = V.J
        Il = misc.sub2ind((n,n),I,J)
        Id = matrix([i for i in range(len(Il)) if I[i]==J[i]])

        # generate random y with norm 1
        y0 = normal(m,1)
        y0 /= blas.nrm2(y0)

        # generate random S0, X0
        S0 = mk_rand(V,cone='posdef',seed=seed)
        X0 = mk_rand(V,cone='completable',seed=seed)

        # generate random A1,...,Am
        if type(d) is float:
            nz = min(max(1, int(round(d*N))), N)
            A = sparse([[spmatrix(normal(N,1),Il,[0 for i in range(N)],(n**2,1))],
                        [spmatrix(normal(nz*m,1),
                                  [i for j in range(m) for i in random.sample(Il,nz)],
                                  [j for j in range(m) for i in range(nz)],(n**2,m))]])
        elif type(d) is list:
            if len(d) == m:
                nz = [min(max(1, int(round(v*N))), N) for v in d]
                nnz = sum(nz)
                A = sparse([[spmatrix(normal(N,1),Il,[0 for i in range(N)],(n**2,1))],
                            [spmatrix(normal(nnz,1),
                                      [i for j in range(m) for i in random.sample(Il,nz[j])],
                                      [j for j in range(m) for i in range(nz[j])],(n**2,m))]])
        else: raise TypeError

        # compute A0
        u = +S0.V
        for k in range(m):
            base.gemv(A[:,k+1][Il],matrix(y0[k]),u,beta=1.0,trans='N')
        A[Il,0] = u
        self._A = A

        # compute b
        X0[Il[Id]] *= 0.5
        self._b = matrix(0.,(m,1))
        u = matrix(0.)
        for k in range(m):
            base.gemv(A[:,k+1][Il],X0.V,u,trans='T',alpha=2.0)
            self._b[k] = u
Example #5
0
    def Gf(u, v, alpha=1.0, beta=0.0, trans='N'):

        if trans == 'N':

            # v[:m] := alpha * G * u[0] + beta * v[:m]
            base.gemv(G, u[0], v, alpha=alpha, beta=beta)

            # v[m:] := alpha * [-u[1],  -A(u[0])';  -A(u[0]), -u[2]]
            #          + beta * v[m:]
            blas.scal(beta, v, offset=m)
            v[m + I11] -= alpha * u[1][:]
            v[m + I21] -= alpha * A * u[0]
            v[m + I22] -= alpha * u[2][:]

        else:

            # v[0] := alpha * ( G.T * u[:m] - 2.0 * A.T * u[m + I21] )
            #         + beta v[1]
            base.gemv(G, u, v[0], trans='T', alpha=alpha, beta=beta)
            base.gemv(A,
                      u[m + I21],
                      v[0],
                      trans='T',
                      alpha=-2.0 * alpha,
                      beta=1.0)

            # v[1] := -alpha * u[m + I11] + beta * v[1]
            blas.scal(beta, v[1])
            blas.axpy(u[m + I11], v[1], alpha=-alpha)

            # v[2] := -alpha * u[m + I22] + beta * v[2]
            blas.scal(beta, v[2])
            blas.axpy(u[m + I22], v[2], alpha=-alpha)
Example #6
0
    def Gf(u, v, alpha = 1.0, beta = 0.0, trans = 'N'):

        if trans == 'N':
 
            # v[:m] := alpha * G * u[0] + beta * v[:m]
            base.gemv(G, u[0], v, alpha = alpha, beta = beta)

            # v[m:] := alpha * [-u[1],  -A(u[0])';  -A(u[0]), -u[2]]
            #          + beta * v[m:]
            blas.scal(beta, v, offset = m)
            v[m + I11] -= alpha * u[1][:]
            v[m + I21] -= alpha * A * u[0]
            v[m + I22] -= alpha * u[2][:]

        else:   
           
            # v[0] := alpha * ( G.T * u[:m] - 2.0 * A.T * u[m + I21] )
            #         + beta v[1]
            base.gemv(G, u, v[0], trans = 'T', alpha = alpha, beta = beta)  
            base.gemv(A, u[m + I21], v[0], trans = 'T', alpha = -2.0*alpha,
                beta = 1.0)

            # v[1] := -alpha * u[m + I11] + beta * v[1]
            blas.scal(beta, v[1])
            blas.axpy(u[m + I11], v[1], alpha = -alpha)

            # v[2] := -alpha * u[m + I22] + beta * v[2]
            blas.scal(beta, v[2])
            blas.axpy(u[m + I22], v[2], alpha = -alpha)
Example #7
0
    def G(x, y, alpha=1.0, beta=0.0, trans='N'):
        """
        Implements the linear operator

               [ -DX    E   -d   -I ]  
               [  0     0    0   -I ]  
               [  0   -e_1'  0    0 ]
          G =  [ -P_1'  0    0    0 ]     
               [  .     .    .    . ]    
               [  0   -e_k'  0    0 ]        
               [ -P_k'  0    0    0 ]       

        and its adjoint G'.

        """
        if trans == 'N':
            tmp = +y[:m]
            # y[:m] = alpha*(-DXw + Et - d*b - v) + beta*y[:m]
            base.gemv(E, x[n:n + k], tmp, alpha=alpha, beta=beta)
            blas.axpy(x[n + k + 1:], tmp, alpha=-alpha)
            blas.axpy(d, tmp, alpha=-alpha * x[n + k])
            y[:m] = tmp

            base.gemv(X, x[:n], tmp, alpha=alpha, beta=0.0)
            tmp = mul(d, tmp)
            y[:m] -= tmp

            # y[m:2*m] = -v
            y[m:2 * m] = -alpha * x[n + k + 1:] + beta * y[m:2 * m]

            # SOC 1,...,k
            for i in range(k):
                l = 2 * m + i * (n + 1)
                y[l] = -alpha * x[n + i] + beta * y[l]
                y[l + 1:l + 1 +
                  n] = -alpha * P[i] * x[:n] + beta * y[l + 1:l + 1 + n]

        else:
            tmp1 = mul(d, x[:m])
            tmp2 = y[:n]
            blas.gemv(X, tmp1, tmp2, trans='T', alpha=-alpha, beta=beta)
            for i in range(k):
                l = 2 * m + 1 + i * (n + 1)
                blas.gemv(P[i],
                          x[l:l + n],
                          tmp2,
                          trans='T',
                          alpha=-alpha,
                          beta=1.0)
            y[:n] = tmp2

            tmp2 = y[n:n + k]
            base.gemv(E, x[:m], tmp2, trans='T', alpha=alpha, beta=beta)
            blas.axpy(x[2 * m:2 * m + k * (1 + n):n + 1], tmp2, alpha=-alpha)
            y[n:n + k] = tmp2

            y[n + k] = -alpha * blas.dot(d, x[:m]) + beta * y[n + k]
            y[n + k +
              1:] = -alpha * (x[:m] + x[m:2 * m]) + beta * y[n + k + 1:]
Example #8
0
def checksol(sol, A, B, C = None, d = None, G = None, h = None): 
    """
    Check optimality conditions

        C * x  + G' * z + A'(Z) + d = 0  
        G * x <= h 
        z >= 0,  || Z || < = 1
        z' * (h - G*x) = 0
        tr (Z' * (A(x) + B)) = || A(x) + B ||_*.

    """

    p, q = B.size
    n = A.size[1]
    if G is None: G = spmatrix([], [], [], (0, n))
    if h is None: h = matrix(0.0, (0, 1))
    m = h.size[0]
    if C is None: C = spmatrix(0.0, [], [], (n,n))
    if d is None: d = matrix(0.0, (n, 1))

    if sol['status'] is 'optimal':

        res = +d
        base.symv(C, sol['x'], res, beta = 1.0)
        base.gemv(G, sol['z'], res, beta = 1.0, trans = 'T')
        base.gemv(A, sol['Z'], res, beta = 1.0, trans = 'T')
        print "Dual residual: %e" %blas.nrm2(res)

        if m:
           print "Minimum primal slack (scalar inequalities): %e" \
               %min(h - G*sol['x'])
           print "Minimum dual slack (scalar inequalities): %e" \
               %min(sol['z'])

        if p:
            s = matrix(0.0, (p,1))
            X = matrix(A*sol['x'], (p, q)) + B
            lapack.gesvd(+X, s)
            nrmX = sum(s)
            lapack.gesvd(+sol['Z'], s)
            nrmZ = max(s)
            print "Norm of Z: %e" %nrmZ
            print "Nuclear norm of A(x) + B: %e" %nrmX
            print "Inner product of Z and A(x) + B: %e" \
                %blas.dot(sol['Z'], X)
        
    elif sol['status'] is 'primal infeasible':

        res = matrix(0.0, (n,1))
        base.gemv(G, sol['z'], res, beta = 1.0, trans = 'T')
        print "Dual residual: %e" %blas.nrm2(res)
        print "h' * z = %e" %blas.dot(h, sol['z'])
        print "Minimum dual slack (scalar inequalities): %e" \
            %min(sol['z'])


    else:
        pass
Example #9
0
def checksol(sol, A, B, C=None, d=None, G=None, h=None):
    """
    Check optimality conditions

        C * x  + G' * z + A'(Z) + d = 0  
        G * x <= h 
        z >= 0,  || Z || < = 1
        z' * (h - G*x) = 0
        tr (Z' * (A(x) + B)) = || A(x) + B ||_*.

    """

    p, q = B.size
    n = A.size[1]
    if G is None: G = spmatrix([], [], [], (0, n))
    if h is None: h = matrix(0.0, (0, 1))
    m = h.size[0]
    if C is None: C = spmatrix(0.0, [], [], (n, n))
    if d is None: d = matrix(0.0, (n, 1))

    if sol['status'] is 'optimal':

        res = +d
        base.symv(C, sol['x'], res, beta=1.0)
        base.gemv(G, sol['z'], res, beta=1.0, trans='T')
        base.gemv(A, sol['Z'], res, beta=1.0, trans='T')
        print "Dual residual: %e" % blas.nrm2(res)

        if m:
            print "Minimum primal slack (scalar inequalities): %e" \
                %min(h - G*sol['x'])
            print "Minimum dual slack (scalar inequalities): %e" \
                %min(sol['z'])

        if p:
            s = matrix(0.0, (p, 1))
            X = matrix(A * sol['x'], (p, q)) + B
            lapack.gesvd(+X, s)
            nrmX = sum(s)
            lapack.gesvd(+sol['Z'], s)
            nrmZ = max(s)
            print "Norm of Z: %e" % nrmZ
            print "Nuclear norm of A(x) + B: %e" % nrmX
            print "Inner product of Z and A(x) + B: %e" \
                %blas.dot(sol['Z'], X)

    elif sol['status'] is 'primal infeasible':

        res = matrix(0.0, (n, 1))
        base.gemv(G, sol['z'], res, beta=1.0, trans='T')
        print "Dual residual: %e" % blas.nrm2(res)
        print "h' * z = %e" % blas.dot(h, sol['z'])
        print "Minimum dual slack (scalar inequalities): %e" \
            %min(sol['z'])

    else:
        pass
Example #10
0
        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:])
Example #11
0
    def G(x, y, alpha = 1.0, beta = 0.0, trans = 'N'):
        """
        Implements the linear operator

               [ -DX    E   -d   -I ]  
               [  0     0    0   -I ]  
               [  0   -e_1'  0    0 ]
          G =  [ -P_1'  0    0    0 ]     
               [  .     .    .    . ]    
               [  0   -e_k'  0    0 ]        
               [ -P_k'  0    0    0 ]       

        and its adjoint G'.

        """
        if trans == 'N':
            tmp = +y[:m]
            # y[:m] = alpha*(-DXw + Et - d*b - v) + beta*y[:m]
            base.gemv(E, x[n:n+k], tmp, alpha = alpha, beta = beta)
            blas.axpy(x[n+k+1:], tmp, alpha = -alpha)
            blas.axpy(d, tmp, alpha = -alpha*x[n+k])
            y[:m] = tmp

            base.gemv(X, x[:n], tmp, alpha = alpha, beta = 0.0)
            tmp = mul(d,tmp)
            y[:m] -= tmp
            
            # y[m:2*m] = -v
            y[m:2*m] = -alpha * x[n+k+1:] + beta * y[m:2*m]

            # SOC 1,...,k
            for i in range(k):
                l = 2*m+i*(n+1)
                y[l] = -alpha * x[n+i] + beta * y[l]
                y[l+1:l+1+n] = -alpha * P[i] * x[:n] + beta * y[l+1:l+1+n];

        else:
            tmp1 = mul(d,x[:m])
            tmp2 = y[:n]
            blas.gemv(X, tmp1, tmp2, trans = 'T', alpha = -alpha, beta = beta)
            for i in range(k):
                l = 2*m+1+i*(n+1)
                blas.gemv(P[i], x[l:l+n], tmp2, trans = 'T', alpha = -alpha, beta = 1.0)
            y[:n] = tmp2

            tmp2 = y[n:n+k]
            base.gemv(E, x[:m], tmp2, trans = 'T', alpha = alpha, beta = beta)
            blas.axpy(x[2*m:2*m+k*(1+n):n+1], tmp2, alpha = -alpha)
            y[n:n+k] = tmp2

            y[n+k] = -alpha * blas.dot(d,x[:m]) + beta * y[n+k]
            y[n+k+1:] = -alpha * (x[:m] + x[m:2*m]) + beta * y[n+k+1:]
Example #12
0
        def f(x, y, z):
            """

            Solve 

                              C * ux + G' * uzl - 2*A'(uzs21) = bx
                                                       -uzs11 = bX1
                                                       -uzs22 = bX2
                                           G * ux - D^2 * uzl = bzl
                [ -uX1   -A(ux)' ]       [ uzs11 uzs21' ]     
                [                ] - T * [              ] * T = bzs.
                [ -A(ux) -uX2    ]       [ uzs21 uzs22  ]

            On entry, x = (bx, bX1, bX2) and z = [ bzl; bzs[:] ].
            On exit, x = (ux, uX1, uX2) and z = [ D*uzl; (r'*uzs*r)[:] ].

            Define X = uzs21, Z = T * uzs * T:   
 
                      C * ux + G' * uzl - 2*A'(X) = bx
                                [ 0  X' ]               [ bX1 0   ]
                            T * [       ] * T - Z = T * [         ] * T
                                [ X  0  ]               [ 0   bX2 ]
                               G * ux - D^2 * uzl = bzl
                [ -uX1   -A(ux)' ]   [ Z11 Z21' ]     
                [                ] - [          ] = bzs
                [ -A(ux) -uX2    ]   [ Z21 Z22  ]

            Return x = (ux, uX1, uX2), z = [ D*uzl; (rti'*Z*rti)[:] ].

            We use the congruence transformation 

                [ V1   0   ] [ T11  T21' ] [ V1'  0  ]   [ I  S' ]
                [          ] [           ] [         ] = [       ]
                [ 0    V2' ] [ T21  T22  ] [ 0    V2 ]   [ S  I  ]

            and the factorization 

                X + S * X' * S = L( L'(X) ) 

            to write this as

                                  C * ux + G' * uzl - 2*A'(X) = bx
                L'(V2^-1 * X * V1^-1) - L^-1(V2' * Z21 * V1') = bX
                                           G * ux - D^2 * uzl = bzl
                            [ -uX1   -A(ux)' ]   [ Z11 Z21' ]     
                            [                ] - [          ] = bzs,
                            [ -A(ux) -uX2    ]   [ Z21 Z22  ]

            or

                C * ux + Gs' * uuzl - 2*As'(XX) = bx
                                      XX - ZZ21 = bX
                                 Gs * ux - uuzl = D^-1 * bzl
                                 -As(ux) - ZZ21 = bbzs_21
                                     -uX1 - Z11 = bzs_11
                                     -uX2 - Z22 = bzs_22

            if we introduce scaled variables

                uuzl = D * uzl
                  XX = L'(V2^-1 * X * V1^-1) 
                     = L'(V2^-1 * uzs21 * V1^-1)
                ZZ21 = L^-1(V2' * Z21 * V1') 

            and define

                bbzs_21 = L^-1(V2' * bzs_21 * V1')
                                           [ bX1  0   ]
                     bX = L^-1( V2' * (T * [          ] * T)_21 * V1').
                                           [ 0    bX2 ]           
 
            Eliminating Z21 gives 

                C * ux + Gs' * uuzl - 2*As'(XX) = bx
                                 Gs * ux - uuzl = D^-1 * bzl
                                   -As(ux) - XX = bbzs_21 - bX
                                     -uX1 - Z11 = bzs_11
                                     -uX2 - Z22 = bzs_22 

            and eliminating uuzl and XX gives

                        H * ux = bx + Gs' * D^-1 * bzl + 2*As'(bX - bbzs_21)
                Gs * ux - uuzl = D^-1 * bzl
                  -As(ux) - XX = bbzs_21 - bX
                    -uX1 - Z11 = bzs_11
                    -uX2 - Z22 = bzs_22.


            In summary, we can use the following algorithm: 

            1. bXX := bX - bbzs21
                                        [ bX1 0   ]
                    = L^-1( V2' * ((T * [         ] * T)_21 - bzs_21) * V1')
                                        [ 0   bX2 ]

            2. Solve H * ux = bx + Gs' * D^-1 * bzl + 2*As'(bXX).

            3. From ux, compute 

                   uuzl = Gs*ux - D^-1 * bzl and 
                      X = V2 * L^-T(-As(ux) + bXX) * V1.

            4. Return ux, uuzl, 

                   rti' * Z * rti = r' * [ -bX1, X'; X, -bX2 ] * r
 
               and uX1 = -Z11 - bzs_11,  uX2 = -Z22 - bzs_22.

            """

            # Save bzs_11, bzs_22, bzs_21.
            lapack.lacpy(z, bz11, uplo = 'L', m = q, n = q, ldA = p+q,
                offsetA = m)
            lapack.lacpy(z, bz21, m = p, n = q, ldA = p+q, offsetA = m+q)
            lapack.lacpy(z, bz22, uplo = 'L', m = p, n = p, ldA = p+q,
                offsetA = m + (p+q+1)*q)


            # zl := D^-1 * zl
            #     = D^-1 * bzl
            blas.tbmv(W['di'], z, n = m, k = 0, ldA = 1)


            # zs := r' * [ bX1, 0; 0, bX2 ] * r.

            # zs := [ bX1, 0; 0, bX2 ]
            blas.scal(0.0, z, offset = m)
            lapack.lacpy(x[1], z, uplo = 'L', m = q, n = q, ldB = p+q,
                offsetB = m)
            lapack.lacpy(x[2], z, uplo = 'L', m = p, n = p, ldB = p+q,
                offsetB = m + (p+q+1)*q)

            # scale diagonal of zs by 1/2
            blas.scal(0.5, z, inc = p+q+1, offset = m)

            # a := tril(zs)*r  
            blas.copy(r, a)
            blas.trmm(z, a, side = 'L', m = p+q, n = p+q, ldA = p+q, ldB = 
                p+q, offsetA = m)

            # zs := a'*r + r'*a 
            blas.syr2k(r, a, z, trans = 'T', n = p+q, k = p+q, ldB = p+q,
                ldC = p+q, offsetC = m)



            # bz21 := L^-1( V2' * ((r * zs * r')_21 - bz21) * V1')
            #
            #                           [ bX1 0   ]
            #       = L^-1( V2' * ((T * [         ] * T)_21 - bz21) * V1').
            #                           [ 0   bX2 ]

            # a = [ r21 r22 ] * z
            #   = [ r21 r22 ] * r' * [ bX1, 0; 0, bX2 ] * r
            #   = [ T21  T22 ] * [ bX1, 0; 0, bX2 ] * r
            blas.symm(z, r, a, side = 'R', m = p, n = p+q, ldA = p+q, 
                ldC = p+q, offsetB = q)
    
            # bz21 := -bz21 + a * [ r11, r12 ]'
            #       = -bz21 + (T * [ bX1, 0; 0, bX2 ] * T)_21
            blas.gemm(a, r, bz21, transB = 'T', m = p, n = q, k = p+q, 
                beta = -1.0, ldA = p+q, ldC = p)

            # bz21 := V2' * bz21 * V1'
            #       = V2' * (-bz21 + (T*[bX1, 0; 0, bX2]*T)_21) * V1'
            blas.gemm(V2, bz21, tmp, transA = 'T', m = p, n = q, k = p, 
                ldB = p)
            blas.gemm(tmp, V1, bz21, transB = 'T', m = p, n = q, k = q, 
                ldC = p)

            # bz21[:] := D * (I-P) * bz21[:] 
            #       = L^-1 * bz21[:]
            #       = bXX[:]
            blas.copy(bz21, tmp)
            base.gemv(P, bz21, tmp, alpha = -1.0, beta = 1.0)
            base.gemv(D, tmp, bz21)


            # Solve H * ux = bx + Gs' * D^-1 * bzl + 2*As'(bXX).

            # x[0] := x[0] + Gs'*zl + 2*As'(bz21) 
            #       = bx + G' * D^-1 * bzl + 2 * As'(bXX)
            blas.gemv(Gs, z, x[0], trans = 'T', alpha = 1.0, beta = 1.0)
            blas.gemv(As, bz21, x[0], trans = 'T', alpha = 2.0, beta = 1.0) 

            # x[0] := H \ x[0] 
            #      = ux
            lapack.potrs(H, x[0])


            # uuzl = Gs*ux - D^-1 * bzl
            blas.gemv(Gs, x[0], z, alpha = 1.0, beta = -1.0)

            
            # bz21 := V2 * L^-T(-As(ux) + bz21) * V1
            #       = X
            blas.gemv(As, x[0], bz21, alpha = -1.0, beta = 1.0)
            blas.tbsv(DV, bz21, n = p*q, k = 0, ldA = 1)
            blas.copy(bz21, tmp)
            base.gemv(P, tmp, bz21, alpha = -1.0, beta = 1.0, trans = 'T')
            blas.gemm(V2, bz21, tmp)
            blas.gemm(tmp, V1, bz21)


            # zs := -zs + r' * [ 0, X'; X, 0 ] * r
            #     = r' * [ -bX1, X'; X, -bX2 ] * r.

            # a := bz21 * [ r11, r12 ]
            #   =  X * [ r11, r12 ]
            blas.gemm(bz21, r, a, m = p, n = p+q, k = q, ldA = p, ldC = p+q)
            
            # z := -z + [ r21, r22 ]' * a + a' * [ r21, r22 ]
            #    = rti' * uzs * rti
            blas.syr2k(r, a, z, trans = 'T', beta = -1.0, n = p+q, k = p,
                offsetA = q, offsetC = m, ldB = p+q, ldC = p+q)  



            # uX1 = -Z11 - bzs_11 
            #     = -(r*zs*r')_11 - bzs_11
            # uX2 = -Z22 - bzs_22 
            #     = -(r*zs*r')_22 - bzs_22


            blas.copy(bz11, x[1])
            blas.copy(bz22, x[2])

            # scale diagonal of zs by 1/2
            blas.scal(0.5, z, inc = p+q+1, offset = m)

            # a := r*tril(zs)  
            blas.copy(r, a)
            blas.trmm(z, a, side = 'R', m = p+q, n = p+q, ldA = p+q, ldB = 
                p+q, offsetA = m)

            # x[1] := -x[1] - a[:q,:] * r[:q, :]' - r[:q,:] * a[:q,:]'
            #       = -bzs_11 - (r*zs*r')_11
            blas.syr2k(a, r, x[1], n = q, alpha = -1.0, beta = -1.0) 

            # x[2] := -x[2] - a[q:,:] * r[q:, :]' - r[q:,:] * a[q:,:]'
            #       = -bzs_22 - (r*zs*r')_22
            blas.syr2k(a, r, x[2], n = p, alpha = -1.0, beta = -1.0, 
                offsetA = q, offsetB = q)

            # scale diagonal of zs by 1/2
            blas.scal(2.0, z, inc = p+q+1, offset = m)
Example #13
0
File: base.py Project: cvxopt/smcp
    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
Example #14
0
        def f(x, y, z):
            """

            Solve 

                              C * ux + G' * uzl - 2*A'(uzs21) = bx
                                                       -uzs11 = bX1
                                                       -uzs22 = bX2
                                           G * ux - D^2 * uzl = bzl
                [ -uX1   -A(ux)' ]       [ uzs11 uzs21' ]     
                [                ] - T * [              ] * T = bzs.
                [ -A(ux) -uX2    ]       [ uzs21 uzs22  ]

            On entry, x = (bx, bX1, bX2) and z = [ bzl; bzs[:] ].
            On exit, x = (ux, uX1, uX2) and z = [ D*uzl; (r'*uzs*r)[:] ].

            Define X = uzs21, Z = T * uzs * T:   
 
                      C * ux + G' * uzl - 2*A'(X) = bx
                                [ 0  X' ]               [ bX1 0   ]
                            T * [       ] * T - Z = T * [         ] * T
                                [ X  0  ]               [ 0   bX2 ]
                               G * ux - D^2 * uzl = bzl
                [ -uX1   -A(ux)' ]   [ Z11 Z21' ]     
                [                ] - [          ] = bzs
                [ -A(ux) -uX2    ]   [ Z21 Z22  ]

            Return x = (ux, uX1, uX2), z = [ D*uzl; (rti'*Z*rti)[:] ].

            We use the congruence transformation 

                [ V1   0   ] [ T11  T21' ] [ V1'  0  ]   [ I  S' ]
                [          ] [           ] [         ] = [       ]
                [ 0    V2' ] [ T21  T22  ] [ 0    V2 ]   [ S  I  ]

            and the factorization 

                X + S * X' * S = L( L'(X) ) 

            to write this as

                                  C * ux + G' * uzl - 2*A'(X) = bx
                L'(V2^-1 * X * V1^-1) - L^-1(V2' * Z21 * V1') = bX
                                           G * ux - D^2 * uzl = bzl
                            [ -uX1   -A(ux)' ]   [ Z11 Z21' ]     
                            [                ] - [          ] = bzs,
                            [ -A(ux) -uX2    ]   [ Z21 Z22  ]

            or

                C * ux + Gs' * uuzl - 2*As'(XX) = bx
                                      XX - ZZ21 = bX
                                 Gs * ux - uuzl = D^-1 * bzl
                                 -As(ux) - ZZ21 = bbzs_21
                                     -uX1 - Z11 = bzs_11
                                     -uX2 - Z22 = bzs_22

            if we introduce scaled variables

                uuzl = D * uzl
                  XX = L'(V2^-1 * X * V1^-1) 
                     = L'(V2^-1 * uzs21 * V1^-1)
                ZZ21 = L^-1(V2' * Z21 * V1') 

            and define

                bbzs_21 = L^-1(V2' * bzs_21 * V1')
                                           [ bX1  0   ]
                     bX = L^-1( V2' * (T * [          ] * T)_21 * V1').
                                           [ 0    bX2 ]           
 
            Eliminating Z21 gives 

                C * ux + Gs' * uuzl - 2*As'(XX) = bx
                                 Gs * ux - uuzl = D^-1 * bzl
                                   -As(ux) - XX = bbzs_21 - bX
                                     -uX1 - Z11 = bzs_11
                                     -uX2 - Z22 = bzs_22 

            and eliminating uuzl and XX gives

                        H * ux = bx + Gs' * D^-1 * bzl + 2*As'(bX - bbzs_21)
                Gs * ux - uuzl = D^-1 * bzl
                  -As(ux) - XX = bbzs_21 - bX
                    -uX1 - Z11 = bzs_11
                    -uX2 - Z22 = bzs_22.


            In summary, we can use the following algorithm: 

            1. bXX := bX - bbzs21
                                        [ bX1 0   ]
                    = L^-1( V2' * ((T * [         ] * T)_21 - bzs_21) * V1')
                                        [ 0   bX2 ]

            2. Solve H * ux = bx + Gs' * D^-1 * bzl + 2*As'(bXX).

            3. From ux, compute 

                   uuzl = Gs*ux - D^-1 * bzl and 
                      X = V2 * L^-T(-As(ux) + bXX) * V1.

            4. Return ux, uuzl, 

                   rti' * Z * rti = r' * [ -bX1, X'; X, -bX2 ] * r
 
               and uX1 = -Z11 - bzs_11,  uX2 = -Z22 - bzs_22.

            """

            # Save bzs_11, bzs_22, bzs_21.
            lapack.lacpy(z, bz11, uplo='L', m=q, n=q, ldA=p + q, offsetA=m)
            lapack.lacpy(z, bz21, m=p, n=q, ldA=p + q, offsetA=m + q)
            lapack.lacpy(z,
                         bz22,
                         uplo='L',
                         m=p,
                         n=p,
                         ldA=p + q,
                         offsetA=m + (p + q + 1) * q)

            # zl := D^-1 * zl
            #     = D^-1 * bzl
            blas.tbmv(W['di'], z, n=m, k=0, ldA=1)

            # zs := r' * [ bX1, 0; 0, bX2 ] * r.

            # zs := [ bX1, 0; 0, bX2 ]
            blas.scal(0.0, z, offset=m)
            lapack.lacpy(x[1], z, uplo='L', m=q, n=q, ldB=p + q, offsetB=m)
            lapack.lacpy(x[2],
                         z,
                         uplo='L',
                         m=p,
                         n=p,
                         ldB=p + q,
                         offsetB=m + (p + q + 1) * q)

            # scale diagonal of zs by 1/2
            blas.scal(0.5, z, inc=p + q + 1, offset=m)

            # a := tril(zs)*r
            blas.copy(r, a)
            blas.trmm(z,
                      a,
                      side='L',
                      m=p + q,
                      n=p + q,
                      ldA=p + q,
                      ldB=p + q,
                      offsetA=m)

            # zs := a'*r + r'*a
            blas.syr2k(r,
                       a,
                       z,
                       trans='T',
                       n=p + q,
                       k=p + q,
                       ldB=p + q,
                       ldC=p + q,
                       offsetC=m)

            # bz21 := L^-1( V2' * ((r * zs * r')_21 - bz21) * V1')
            #
            #                           [ bX1 0   ]
            #       = L^-1( V2' * ((T * [         ] * T)_21 - bz21) * V1').
            #                           [ 0   bX2 ]

            # a = [ r21 r22 ] * z
            #   = [ r21 r22 ] * r' * [ bX1, 0; 0, bX2 ] * r
            #   = [ T21  T22 ] * [ bX1, 0; 0, bX2 ] * r
            blas.symm(z,
                      r,
                      a,
                      side='R',
                      m=p,
                      n=p + q,
                      ldA=p + q,
                      ldC=p + q,
                      offsetB=q)

            # bz21 := -bz21 + a * [ r11, r12 ]'
            #       = -bz21 + (T * [ bX1, 0; 0, bX2 ] * T)_21
            blas.gemm(a,
                      r,
                      bz21,
                      transB='T',
                      m=p,
                      n=q,
                      k=p + q,
                      beta=-1.0,
                      ldA=p + q,
                      ldC=p)

            # bz21 := V2' * bz21 * V1'
            #       = V2' * (-bz21 + (T*[bX1, 0; 0, bX2]*T)_21) * V1'
            blas.gemm(V2, bz21, tmp, transA='T', m=p, n=q, k=p, ldB=p)
            blas.gemm(tmp, V1, bz21, transB='T', m=p, n=q, k=q, ldC=p)

            # bz21[:] := D * (I-P) * bz21[:]
            #       = L^-1 * bz21[:]
            #       = bXX[:]
            blas.copy(bz21, tmp)
            base.gemv(P, bz21, tmp, alpha=-1.0, beta=1.0)
            base.gemv(D, tmp, bz21)

            # Solve H * ux = bx + Gs' * D^-1 * bzl + 2*As'(bXX).

            # x[0] := x[0] + Gs'*zl + 2*As'(bz21)
            #       = bx + G' * D^-1 * bzl + 2 * As'(bXX)
            blas.gemv(Gs, z, x[0], trans='T', alpha=1.0, beta=1.0)
            blas.gemv(As, bz21, x[0], trans='T', alpha=2.0, beta=1.0)

            # x[0] := H \ x[0]
            #      = ux
            lapack.potrs(H, x[0])

            # uuzl = Gs*ux - D^-1 * bzl
            blas.gemv(Gs, x[0], z, alpha=1.0, beta=-1.0)

            # bz21 := V2 * L^-T(-As(ux) + bz21) * V1
            #       = X
            blas.gemv(As, x[0], bz21, alpha=-1.0, beta=1.0)
            blas.tbsv(DV, bz21, n=p * q, k=0, ldA=1)
            blas.copy(bz21, tmp)
            base.gemv(P, tmp, bz21, alpha=-1.0, beta=1.0, trans='T')
            blas.gemm(V2, bz21, tmp)
            blas.gemm(tmp, V1, bz21)

            # zs := -zs + r' * [ 0, X'; X, 0 ] * r
            #     = r' * [ -bX1, X'; X, -bX2 ] * r.

            # a := bz21 * [ r11, r12 ]
            #   =  X * [ r11, r12 ]
            blas.gemm(bz21, r, a, m=p, n=p + q, k=q, ldA=p, ldC=p + q)

            # z := -z + [ r21, r22 ]' * a + a' * [ r21, r22 ]
            #    = rti' * uzs * rti
            blas.syr2k(r,
                       a,
                       z,
                       trans='T',
                       beta=-1.0,
                       n=p + q,
                       k=p,
                       offsetA=q,
                       offsetC=m,
                       ldB=p + q,
                       ldC=p + q)

            # uX1 = -Z11 - bzs_11
            #     = -(r*zs*r')_11 - bzs_11
            # uX2 = -Z22 - bzs_22
            #     = -(r*zs*r')_22 - bzs_22

            blas.copy(bz11, x[1])
            blas.copy(bz22, x[2])

            # scale diagonal of zs by 1/2
            blas.scal(0.5, z, inc=p + q + 1, offset=m)

            # a := r*tril(zs)
            blas.copy(r, a)
            blas.trmm(z,
                      a,
                      side='R',
                      m=p + q,
                      n=p + q,
                      ldA=p + q,
                      ldB=p + q,
                      offsetA=m)

            # x[1] := -x[1] - a[:q,:] * r[:q, :]' - r[:q,:] * a[:q,:]'
            #       = -bzs_11 - (r*zs*r')_11
            blas.syr2k(a, r, x[1], n=q, alpha=-1.0, beta=-1.0)

            # x[2] := -x[2] - a[q:,:] * r[q:, :]' - r[q:,:] * a[q:,:]'
            #       = -bzs_22 - (r*zs*r')_22
            blas.syr2k(a,
                       r,
                       x[2],
                       n=p,
                       alpha=-1.0,
                       beta=-1.0,
                       offsetA=q,
                       offsetB=q)

            # scale diagonal of zs by 1/2
            blas.scal(2.0, z, inc=p + q + 1, offset=m)
Example #15
0
    def F(W): 
        """
        Custom solver for the system

        [  It  0   0    Xt'     0     At1' ...  Atk' ][ dwt  ]   [ rwt ]
        [  0   0   0    -d'     0      0   ...   0   ][ db   ]   [ rb  ]
        [  0   0   0    -I     -I      0   ...   0   ][ dv   ]   [ rv  ]
        [  Xt -d  -I  -Wl1^-2                        ][ dzl1 ]   [ rl1 ]
        [  0   0  -I         -Wl2^-2                 ][ dzl2 ] = [ rl2 ]
        [ At1  0   0                -W1^-2           ][ dz1  ]   [ r1  ] 
        [  |   |   |                       .         ][  |   ]   [  |  ]
        [ Atk  0   0                          -Wk^-2 ][ dzk  ]   [ rk  ]

        where

        It = [ I 0 ]  Xt = [ -D*X E ]  Ati = [ 0   -e_i' ]  
             [ 0 0 ]                         [ -Pi   0   ] 

        dwt = [ dw ]  rwt = [ rw ]
              [ dt ]        [ rt ].

        """

        # scalings and 'intermediate' vectors
        # db = inv(Wl1)^2 + inv(Wl2)^2
        db = W['di'][:m]**2 + W['di'][m:2*m]**2
        dbi = div(1.0,db)
        
        # dt = I - inv(Wl1)*Dbi*inv(Wl1)
        dt = 1.0 - mul(W['di'][:m]**2,dbi)
        dtsqrt = sqrt(dt)

        # lam = Dt*inv(Wl1)*d
        lam = mul(dt,mul(W['di'][:m],d))

        # lt = E'*inv(Wl1)*lam
        lt = matrix(0.0,(k,1))
        base.gemv(E, mul(W['di'][:m],lam), lt, trans = 'T')

        # Xs = sqrt(Dt)*inv(Wl1)*X
        tmp = mul(dtsqrt,W['di'][:m])
        Xs = spmatrix(tmp,range(m),range(m))*X

        # Es = D*sqrt(Dt)*inv(Wl1)*E
        Es = spmatrix(mul(d,tmp),range(m),range(m))*E

        # form Ab = I + sum((1/bi)^2*(Pi'*Pi + 4*(v'*v + 1)*Pi'*y*y'*Pi)) + Xs'*Xs
        #  and Bb = -sum((1/bi)^2*(4*ui*v'*v*Pi'*y*ei')) - Xs'*Es
        #  and D2 = Es'*Es + sum((1/bi)^2*(1+4*ui^2*(v'*v - 1))
        Ab = matrix(0.0,(n,n))
        Ab[::n+1] = 1.0
        base.syrk(Xs,Ab,trans = 'T', beta = 1.0)
        Bb = matrix(0.0,(n,k))
        Bb = -Xs.T*Es # inefficient!?
        D2 = spmatrix(0.0,range(k),range(k))
        base.syrk(Es,D2,trans = 'T', partial = True)
        d2 = +D2.V
        del D2
        py = matrix(0.0,(n,1))
        for i in range(k):
            binvsq = (1.0/W['beta'][i])**2
            Ab += binvsq*Pt[i]
            dvv = blas.dot(W['v'][i],W['v'][i])
            blas.gemv(P[i], W['v'][i][1:], py, trans = 'T', alpha = 1.0, beta = 0.0)
            blas.syrk(py, Ab, alpha = 4*binvsq*(dvv+1), beta = 1.0)
            Bb[:,i] -= 4*binvsq*W['v'][i][0]*dvv*py
            d2[i] += binvsq*(1+4*(W['v'][i][0]**2)*(dvv-1))
        
        d2i = div(1.0,d2)
        d2isqrt = sqrt(d2i)

        # compute a = alpha - lam'*inv(Wl1)*E*inv(D2)*E'*inv(Wl1)*lam
        alpha = blas.dot(lam,mul(W['di'][:m],d))
        tmp = matrix(0.0,(k,1))
        base.gemv(E,mul(W['di'][:m],lam), tmp, trans = 'T')
        tmp = mul(tmp, d2isqrt) #tmp = inv(D2)^(1/2)*E'*inv(Wl1)*lam
        a = alpha - blas.dot(tmp,tmp)

        # compute M12 = X'*D*inv(Wl1)*lam + Bb*inv(D2)*E'*inv(Wl1)*lam
        tmp = mul(tmp, d2isqrt)
        M12 = matrix(0.0,(n,1))
        blas.gemv(Bb,tmp,M12, alpha = 1.0)
        tmp = mul(d,mul(W['di'][:m],lam))
        blas.gemv(X,tmp,M12, trans = 'T', alpha = 1.0, beta = 1.0)

        # form and factor M
        sBb = Bb * spmatrix(d2isqrt,range(k), range(k)) 
        base.syrk(sBb, Ab, alpha = -1.0, beta = 1.0)
        M = matrix([[Ab, M12.T],[M12, a]])
        lapack.potrf(M)
        
        def f(x,y,z):
            
            # residuals
            rwt = x[:n+k]
            rb = x[n+k]
            rv = x[n+k+1:n+k+1+m]
            iw_rl1 = mul(W['di'][:m],z[:m])
            iw_rl2 = mul(W['di'][m:2*m],z[m:2*m])
            ri = [z[2*m+i*(n+1):2*m+(i+1)*(n+1)] for i in range(k)]
            
            # compute 'derived' residuals 
            # rbwt = rwt + sum(Ai'*inv(Wi)^2*ri) + [-X'*D; E']*inv(Wl1)^2*rl1
            rbwt = +rwt
            for i in range(k):
                tmp = +ri[i]
                qscal(tmp,W['beta'][i],W['v'][i],inv=True)
                qscal(tmp,W['beta'][i],W['v'][i],inv=True)
                rbwt[n+i] -= tmp[0]
                blas.gemv(P[i], tmp[1:], rbwt, trans = 'T', alpha = -1.0, beta = 1.0)
            tmp = mul(W['di'][:m],iw_rl1)
            tmp2 = matrix(0.0,(k,1))
            base.gemv(E,tmp,tmp2,trans='T')
            rbwt[n:] += tmp2
            tmp = mul(d,tmp) # tmp = D*inv(Wl1)^2*rl1
            blas.gemv(X,tmp,rbwt,trans='T', alpha = -1.0, beta = 1.0)
            
            # rbb = rb - d'*inv(Wl1)^2*rl1
            rbb = rb - sum(tmp)

            # rbv = rv - inv(Wl2)*rl2 - inv(Wl1)^2*rl1
            rbv = rv - mul(W['di'][m:2*m],iw_rl2) - mul(W['di'][:m],iw_rl1) 
            
            # [rtw;rtt] = rbwt + [-X'*D; E']*inv(Wl1)^2*inv(Db)*rbv 
            tmp = mul(W['di'][:m]**2, mul(dbi,rbv))
            rtt = +rbwt[n:] 
            base.gemv(E, tmp, rtt, trans = 'T', alpha = 1.0, beta = 1.0)
            rtw = +rbwt[:n]
            tmp = mul(d,tmp)
            blas.gemv(X, tmp, rtw, trans = 'T', alpha = -1.0, beta = 1.0)

            # rtb = rbb - d'*inv(Wl1)^2*inv(Db)*rbv
            rtb = rbb - sum(tmp)
            
            # solve M*[dw;db] = [rtw - Bb*inv(D2)*rtt; rtb + lt'*inv(D2)*rtt]
            tmp = mul(d2i,rtt)
            tmp2 = matrix(0.0,(n,1))
            blas.gemv(Bb,tmp,tmp2)
            dwdb = matrix([rtw - tmp2,rtb + blas.dot(mul(d2i,lt),rtt)]) 
            lapack.potrs(M,dwdb)

            # compute dt = inv(D2)*(rtt - Bb'*dw + lt*db)
            tmp2 = matrix(0.0,(k,1))
            blas.gemv(Bb, dwdb[:n], tmp2, trans='T')
            dt = mul(d2i, rtt - tmp2 + lt*dwdb[-1])

            # compute dv = inv(Db)*(rbv + inv(Wl1)^2*(E*dt - D*X*dw - d*db))
            dv = matrix(0.0,(m,1))
            blas.gemv(X,dwdb[:n],dv,alpha = -1.0)
            dv = mul(d,dv) - d*dwdb[-1]
            base.gemv(E, dt, dv, beta = 1.0)
            tmp = +dv  # tmp = E*dt - D*X*dw - d*db
            dv = mul(dbi, rbv + mul(W['di'][:m]**2,dv))

            # compute wdz1 = inv(Wl1)*(E*dt - D*X*dw - d*db - dv - rl1)
            wdz1 = mul(W['di'][:m], tmp - dv) - iw_rl1

            # compute wdz2 = - inv(Wl2)*(dv + rl2)
            wdz2 = - mul(W['di'][m:2*m],dv) - iw_rl2

            # compute wdzi = inv(Wi)*([-ei'*dt; -Pi*dw] - ri)
            wdzi = []
            tmp = matrix(0.0,(n,1))
            for i in range(k):
                blas.gemv(P[i],dwdb[:n],tmp, alpha = -1.0, beta = 0.0) 
                tmp1 = matrix([-dt[i],tmp])
                blas.axpy(ri[i],tmp1,alpha = -1.0)
                qscal(tmp1,W['beta'][i],W['v'][i],inv=True)
                wdzi.append(tmp1)

            # solution
            x[:n] = dwdb[:n]
            x[n:n+k] = dt
            x[n+k] = dwdb[-1]
            x[n+k+1:] = dv
            z[:m] = wdz1 
            z[m:2*m] = wdz2
            for i in range(k):
                z[2*m+i*(n+1):2*m+(i+1)*(n+1)] = wdzi[i]

        return f
Example #16
0
        def f(x,y,z):
            
            # residuals
            rwt = x[:n+k]
            rb = x[n+k]
            rv = x[n+k+1:n+k+1+m]
            iw_rl1 = mul(W['di'][:m],z[:m])
            iw_rl2 = mul(W['di'][m:2*m],z[m:2*m])
            ri = [z[2*m+i*(n+1):2*m+(i+1)*(n+1)] for i in range(k)]
            
            # compute 'derived' residuals 
            # rbwt = rwt + sum(Ai'*inv(Wi)^2*ri) + [-X'*D; E']*inv(Wl1)^2*rl1
            rbwt = +rwt
            for i in range(k):
                tmp = +ri[i]
                qscal(tmp,W['beta'][i],W['v'][i],inv=True)
                qscal(tmp,W['beta'][i],W['v'][i],inv=True)
                rbwt[n+i] -= tmp[0]
                blas.gemv(P[i], tmp[1:], rbwt, trans = 'T', alpha = -1.0, beta = 1.0)
            tmp = mul(W['di'][:m],iw_rl1)
            tmp2 = matrix(0.0,(k,1))
            base.gemv(E,tmp,tmp2,trans='T')
            rbwt[n:] += tmp2
            tmp = mul(d,tmp) # tmp = D*inv(Wl1)^2*rl1
            blas.gemv(X,tmp,rbwt,trans='T', alpha = -1.0, beta = 1.0)
            
            # rbb = rb - d'*inv(Wl1)^2*rl1
            rbb = rb - sum(tmp)

            # rbv = rv - inv(Wl2)*rl2 - inv(Wl1)^2*rl1
            rbv = rv - mul(W['di'][m:2*m],iw_rl2) - mul(W['di'][:m],iw_rl1) 
            
            # [rtw;rtt] = rbwt + [-X'*D; E']*inv(Wl1)^2*inv(Db)*rbv 
            tmp = mul(W['di'][:m]**2, mul(dbi,rbv))
            rtt = +rbwt[n:] 
            base.gemv(E, tmp, rtt, trans = 'T', alpha = 1.0, beta = 1.0)
            rtw = +rbwt[:n]
            tmp = mul(d,tmp)
            blas.gemv(X, tmp, rtw, trans = 'T', alpha = -1.0, beta = 1.0)

            # rtb = rbb - d'*inv(Wl1)^2*inv(Db)*rbv
            rtb = rbb - sum(tmp)
            
            # solve M*[dw;db] = [rtw - Bb*inv(D2)*rtt; rtb + lt'*inv(D2)*rtt]
            tmp = mul(d2i,rtt)
            tmp2 = matrix(0.0,(n,1))
            blas.gemv(Bb,tmp,tmp2)
            dwdb = matrix([rtw - tmp2,rtb + blas.dot(mul(d2i,lt),rtt)]) 
            lapack.potrs(M,dwdb)

            # compute dt = inv(D2)*(rtt - Bb'*dw + lt*db)
            tmp2 = matrix(0.0,(k,1))
            blas.gemv(Bb, dwdb[:n], tmp2, trans='T')
            dt = mul(d2i, rtt - tmp2 + lt*dwdb[-1])

            # compute dv = inv(Db)*(rbv + inv(Wl1)^2*(E*dt - D*X*dw - d*db))
            dv = matrix(0.0,(m,1))
            blas.gemv(X,dwdb[:n],dv,alpha = -1.0)
            dv = mul(d,dv) - d*dwdb[-1]
            base.gemv(E, dt, dv, beta = 1.0)
            tmp = +dv  # tmp = E*dt - D*X*dw - d*db
            dv = mul(dbi, rbv + mul(W['di'][:m]**2,dv))

            # compute wdz1 = inv(Wl1)*(E*dt - D*X*dw - d*db - dv - rl1)
            wdz1 = mul(W['di'][:m], tmp - dv) - iw_rl1

            # compute wdz2 = - inv(Wl2)*(dv + rl2)
            wdz2 = - mul(W['di'][m:2*m],dv) - iw_rl2

            # compute wdzi = inv(Wi)*([-ei'*dt; -Pi*dw] - ri)
            wdzi = []
            tmp = matrix(0.0,(n,1))
            for i in range(k):
                blas.gemv(P[i],dwdb[:n],tmp, alpha = -1.0, beta = 0.0) 
                tmp1 = matrix([-dt[i],tmp])
                blas.axpy(ri[i],tmp1,alpha = -1.0)
                qscal(tmp1,W['beta'][i],W['v'][i],inv=True)
                wdzi.append(tmp1)

            # solution
            x[:n] = dwdb[:n]
            x[n:n+k] = dt
            x[n+k] = dwdb[-1]
            x[n+k+1:] = dv
            z[:m] = wdz1 
            z[m:2*m] = wdz2
            for i in range(k):
                z[2*m+i*(n+1):2*m+(i+1)*(n+1)] = wdzi[i]
Example #17
0
        def f(x, y, z):

            # residuals
            rwt = x[:n + k]
            rb = x[n + k]
            rv = x[n + k + 1:n + k + 1 + m]
            iw_rl1 = mul(W['di'][:m], z[:m])
            iw_rl2 = mul(W['di'][m:2 * m], z[m:2 * m])
            ri = [
                z[2 * m + i * (n + 1):2 * m + (i + 1) * (n + 1)]
                for i in range(k)
            ]

            # compute 'derived' residuals
            # rbwt = rwt + sum(Ai'*inv(Wi)^2*ri) + [-X'*D; E']*inv(Wl1)^2*rl1
            rbwt = +rwt
            for i in range(k):
                tmp = +ri[i]
                qscal(tmp, W['beta'][i], W['v'][i], inv=True)
                qscal(tmp, W['beta'][i], W['v'][i], inv=True)
                rbwt[n + i] -= tmp[0]
                blas.gemv(P[i], tmp[1:], rbwt, trans='T', alpha=-1.0, beta=1.0)
            tmp = mul(W['di'][:m], iw_rl1)
            tmp2 = matrix(0.0, (k, 1))
            base.gemv(E, tmp, tmp2, trans='T')
            rbwt[n:] += tmp2
            tmp = mul(d, tmp)  # tmp = D*inv(Wl1)^2*rl1
            blas.gemv(X, tmp, rbwt, trans='T', alpha=-1.0, beta=1.0)

            # rbb = rb - d'*inv(Wl1)^2*rl1
            rbb = rb - sum(tmp)

            # rbv = rv - inv(Wl2)*rl2 - inv(Wl1)^2*rl1
            rbv = rv - mul(W['di'][m:2 * m], iw_rl2) - mul(W['di'][:m], iw_rl1)

            # [rtw;rtt] = rbwt + [-X'*D; E']*inv(Wl1)^2*inv(Db)*rbv
            tmp = mul(W['di'][:m]**2, mul(dbi, rbv))
            rtt = +rbwt[n:]
            base.gemv(E, tmp, rtt, trans='T', alpha=1.0, beta=1.0)
            rtw = +rbwt[:n]
            tmp = mul(d, tmp)
            blas.gemv(X, tmp, rtw, trans='T', alpha=-1.0, beta=1.0)

            # rtb = rbb - d'*inv(Wl1)^2*inv(Db)*rbv
            rtb = rbb - sum(tmp)

            # solve M*[dw;db] = [rtw - Bb*inv(D2)*rtt; rtb + lt'*inv(D2)*rtt]
            tmp = mul(d2i, rtt)
            tmp2 = matrix(0.0, (n, 1))
            blas.gemv(Bb, tmp, tmp2)
            dwdb = matrix([rtw - tmp2, rtb + blas.dot(mul(d2i, lt), rtt)])
            lapack.potrs(M, dwdb)

            # compute dt = inv(D2)*(rtt - Bb'*dw + lt*db)
            tmp2 = matrix(0.0, (k, 1))
            blas.gemv(Bb, dwdb[:n], tmp2, trans='T')
            dt = mul(d2i, rtt - tmp2 + lt * dwdb[-1])

            # compute dv = inv(Db)*(rbv + inv(Wl1)^2*(E*dt - D*X*dw - d*db))
            dv = matrix(0.0, (m, 1))
            blas.gemv(X, dwdb[:n], dv, alpha=-1.0)
            dv = mul(d, dv) - d * dwdb[-1]
            base.gemv(E, dt, dv, beta=1.0)
            tmp = +dv  # tmp = E*dt - D*X*dw - d*db
            dv = mul(dbi, rbv + mul(W['di'][:m]**2, dv))

            # compute wdz1 = inv(Wl1)*(E*dt - D*X*dw - d*db - dv - rl1)
            wdz1 = mul(W['di'][:m], tmp - dv) - iw_rl1

            # compute wdz2 = - inv(Wl2)*(dv + rl2)
            wdz2 = -mul(W['di'][m:2 * m], dv) - iw_rl2

            # compute wdzi = inv(Wi)*([-ei'*dt; -Pi*dw] - ri)
            wdzi = []
            tmp = matrix(0.0, (n, 1))
            for i in range(k):
                blas.gemv(P[i], dwdb[:n], tmp, alpha=-1.0, beta=0.0)
                tmp1 = matrix([-dt[i], tmp])
                blas.axpy(ri[i], tmp1, alpha=-1.0)
                qscal(tmp1, W['beta'][i], W['v'][i], inv=True)
                wdzi.append(tmp1)

            # solution
            x[:n] = dwdb[:n]
            x[n:n + k] = dt
            x[n + k] = dwdb[-1]
            x[n + k + 1:] = dv
            z[:m] = wdz1
            z[m:2 * m] = wdz2
            for i in range(k):
                z[2 * m + i * (n + 1):2 * m + (i + 1) * (n + 1)] = wdzi[i]
Example #18
0
    def _gen_randsdp(self, V, m, d, seed):
        """
        Random data generator 
        """
        setseed(seed)
        n = self._n
        V = chompack.tril(V)
        N = len(V)
        I = V.I
        J = V.J
        Il = misc.sub2ind((n, n), I, J)
        Id = matrix([i for i in xrange(len(Il)) if I[i] == J[i]])

        # generate random y with norm 1
        y0 = normal(m, 1)
        y0 /= blas.nrm2(y0)

        # generate random S0, X0
        S0 = mk_rand(V, cone='posdef', seed=seed)
        X0 = mk_rand(V, cone='completable', seed=seed)

        # generate random A1,...,Am
        if type(d) is float:
            nz = min(max(1, int(round(d * N))), N)
            A = sparse(
                [[
                    spmatrix(normal(N, 1), Il, [0 for i in xrange(N)],
                             (n**2, 1))
                ],
                 [
                     spmatrix(
                         normal(nz * m, 1),
                         [i for j in xrange(m) for i in random.sample(Il, nz)],
                         [j for j in xrange(m) for i in xrange(nz)], (n**2, m))
                 ]])
        elif type(d) is list:
            if len(d) == m:
                nz = [min(max(1, int(round(v * N))), N) for v in d]
                nnz = sum(nz)
                A = sparse(
                    [[
                        spmatrix(normal(N, 1), Il, [0 for i in xrange(N)],
                                 (n**2, 1))
                    ],
                     [
                         spmatrix(normal(nnz, 1), [
                             i for j in xrange(m)
                             for i in random.sample(Il, nz[j])
                         ], [j for j in xrange(m) for i in xrange(nz[j])],
                                  (n**2, m))
                     ]])
        else:
            raise TypeError

        # compute A0
        u = +S0.V
        for k in xrange(m):
            base.gemv(A[:, k + 1][Il], matrix(y0[k]), u, beta=1.0, trans='N')
        A[Il, 0] = u
        self._A = A

        # compute b
        X0[Il[Id]] *= 0.5
        self._b = matrix(0., (m, 1))
        u = matrix(0.)
        for k in xrange(m):
            base.gemv(A[:, k + 1][Il], X0.V, u, trans='T', alpha=2.0)
            self._b[k] = u
Example #19
0
    def Fgp(x=None, z=None):

        if x is None: return mnl, matrix(0.0, (n, 1))

        f = matrix(0.0, (mnl + 1, 1))
        Df = matrix(0.0, (mnl + 1, n))

        # y = F*x+g
        blas.copy(g, y)
        base.gemv(F, x, y, beta=1.0)

        if z is not None: H = matrix(0.0, (n, n))

        for i, start, stop in ind:

            # yi := exp(yi) = exp(Fi*x+gi)
            ymax = max(y[start:stop])
            y[start:stop] = base.exp(y[start:stop] - ymax)

            # fi = log sum yi = log sum exp(Fi*x+gi)
            ysum = blas.asum(y, n=stop - start, offset=start)
            f[i] = ymax + math.log(ysum)

            # yi := yi / sum(yi) = exp(Fi*x+gi) / sum(exp(Fi*x+gi))
            blas.scal(1.0 / ysum, y, n=stop - start, offset=start)

            # gradfi := Fi' * yi
            #        = Fi' * exp(Fi*x+gi) / sum(exp(Fi*x+gi))
            base.gemv(F,
                      y,
                      Df,
                      trans='T',
                      m=stop - start,
                      incy=mnl + 1,
                      offsetA=start,
                      offsetx=start,
                      offsety=i)

            if z is not None:

                # Hi = Fi' * (diag(yi) - yi*yi') * Fi
                #    = Fisc' * Fisc
                # where
                # Fisc = diag(yi)^1/2 * (I - 1*yi') * Fi
                #      = diag(yi)^1/2 * (Fi - 1*gradfi')

                Fsc[:K[i], :] = F[start:stop, :]
                for k in range(start, stop):
                    blas.axpy(Df,
                              Fsc,
                              n=n,
                              alpha=-1.0,
                              incx=mnl + 1,
                              incy=Fsc.size[0],
                              offsetx=i,
                              offsety=k - start)
                    blas.scal(math.sqrt(y[k]),
                              Fsc,
                              inc=Fsc.size[0],
                              offset=k - start)

                # H += z[i]*Hi = z[i] * Fisc' * Fisc
                blas.syrk(Fsc,
                          H,
                          trans='T',
                          k=stop - start,
                          alpha=z[i],
                          beta=1.0)

        if z is None:
            return f, Df
        return f, Df, H
Example #20
0
 def fA(x, y, trans='N', alpha=1.0, beta=0.0):
     base.gemv(A, x, y, trans=trans, alpha=alpha, beta=beta)
Example #21
0
        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)
Example #22
0
    def F(W):
        """
        Custom solver for the system

        [  It  0   0    Xt'     0     At1' ...  Atk' ][ dwt  ]   [ rwt ]
        [  0   0   0    -d'     0      0   ...   0   ][ db   ]   [ rb  ]
        [  0   0   0    -I     -I      0   ...   0   ][ dv   ]   [ rv  ]
        [  Xt -d  -I  -Wl1^-2                        ][ dzl1 ]   [ rl1 ]
        [  0   0  -I         -Wl2^-2                 ][ dzl2 ] = [ rl2 ]
        [ At1  0   0                -W1^-2           ][ dz1  ]   [ r1  ] 
        [  |   |   |                       .         ][  |   ]   [  |  ]
        [ Atk  0   0                          -Wk^-2 ][ dzk  ]   [ rk  ]

        where

        It = [ I 0 ]  Xt = [ -D*X E ]  Ati = [ 0   -e_i' ]  
             [ 0 0 ]                         [ -Pi   0   ] 

        dwt = [ dw ]  rwt = [ rw ]
              [ dt ]        [ rt ].

        """

        # scalings and 'intermediate' vectors
        # db = inv(Wl1)^2 + inv(Wl2)^2
        db = W['di'][:m]**2 + W['di'][m:2 * m]**2
        dbi = div(1.0, db)

        # dt = I - inv(Wl1)*Dbi*inv(Wl1)
        dt = 1.0 - mul(W['di'][:m]**2, dbi)
        dtsqrt = sqrt(dt)

        # lam = Dt*inv(Wl1)*d
        lam = mul(dt, mul(W['di'][:m], d))

        # lt = E'*inv(Wl1)*lam
        lt = matrix(0.0, (k, 1))
        base.gemv(E, mul(W['di'][:m], lam), lt, trans='T')

        # Xs = sqrt(Dt)*inv(Wl1)*X
        tmp = mul(dtsqrt, W['di'][:m])
        Xs = spmatrix(tmp, range(m), range(m)) * X

        # Es = D*sqrt(Dt)*inv(Wl1)*E
        Es = spmatrix(mul(d, tmp), range(m), range(m)) * E

        # form Ab = I + sum((1/bi)^2*(Pi'*Pi + 4*(v'*v + 1)*Pi'*y*y'*Pi)) + Xs'*Xs
        #  and Bb = -sum((1/bi)^2*(4*ui*v'*v*Pi'*y*ei')) - Xs'*Es
        #  and D2 = Es'*Es + sum((1/bi)^2*(1+4*ui^2*(v'*v - 1))
        Ab = matrix(0.0, (n, n))
        Ab[::n + 1] = 1.0
        base.syrk(Xs, Ab, trans='T', beta=1.0)
        Bb = matrix(0.0, (n, k))
        Bb = -Xs.T * Es  # inefficient!?
        D2 = spmatrix(0.0, range(k), range(k))
        base.syrk(Es, D2, trans='T', partial=True)
        d2 = +D2.V
        del D2
        py = matrix(0.0, (n, 1))
        for i in range(k):
            binvsq = (1.0 / W['beta'][i])**2
            Ab += binvsq * Pt[i]
            dvv = blas.dot(W['v'][i], W['v'][i])
            blas.gemv(P[i], W['v'][i][1:], py, trans='T', alpha=1.0, beta=0.0)
            blas.syrk(py, Ab, alpha=4 * binvsq * (dvv + 1), beta=1.0)
            Bb[:, i] -= 4 * binvsq * W['v'][i][0] * dvv * py
            d2[i] += binvsq * (1 + 4 * (W['v'][i][0]**2) * (dvv - 1))

        d2i = div(1.0, d2)
        d2isqrt = sqrt(d2i)

        # compute a = alpha - lam'*inv(Wl1)*E*inv(D2)*E'*inv(Wl1)*lam
        alpha = blas.dot(lam, mul(W['di'][:m], d))
        tmp = matrix(0.0, (k, 1))
        base.gemv(E, mul(W['di'][:m], lam), tmp, trans='T')
        tmp = mul(tmp, d2isqrt)  #tmp = inv(D2)^(1/2)*E'*inv(Wl1)*lam
        a = alpha - blas.dot(tmp, tmp)

        # compute M12 = X'*D*inv(Wl1)*lam + Bb*inv(D2)*E'*inv(Wl1)*lam
        tmp = mul(tmp, d2isqrt)
        M12 = matrix(0.0, (n, 1))
        blas.gemv(Bb, tmp, M12, alpha=1.0)
        tmp = mul(d, mul(W['di'][:m], lam))
        blas.gemv(X, tmp, M12, trans='T', alpha=1.0, beta=1.0)

        # form and factor M
        sBb = Bb * spmatrix(d2isqrt, range(k), range(k))
        base.syrk(sBb, Ab, alpha=-1.0, beta=1.0)
        M = matrix([[Ab, M12.T], [M12, a]])
        lapack.potrf(M)

        def f(x, y, z):

            # residuals
            rwt = x[:n + k]
            rb = x[n + k]
            rv = x[n + k + 1:n + k + 1 + m]
            iw_rl1 = mul(W['di'][:m], z[:m])
            iw_rl2 = mul(W['di'][m:2 * m], z[m:2 * m])
            ri = [
                z[2 * m + i * (n + 1):2 * m + (i + 1) * (n + 1)]
                for i in range(k)
            ]

            # compute 'derived' residuals
            # rbwt = rwt + sum(Ai'*inv(Wi)^2*ri) + [-X'*D; E']*inv(Wl1)^2*rl1
            rbwt = +rwt
            for i in range(k):
                tmp = +ri[i]
                qscal(tmp, W['beta'][i], W['v'][i], inv=True)
                qscal(tmp, W['beta'][i], W['v'][i], inv=True)
                rbwt[n + i] -= tmp[0]
                blas.gemv(P[i], tmp[1:], rbwt, trans='T', alpha=-1.0, beta=1.0)
            tmp = mul(W['di'][:m], iw_rl1)
            tmp2 = matrix(0.0, (k, 1))
            base.gemv(E, tmp, tmp2, trans='T')
            rbwt[n:] += tmp2
            tmp = mul(d, tmp)  # tmp = D*inv(Wl1)^2*rl1
            blas.gemv(X, tmp, rbwt, trans='T', alpha=-1.0, beta=1.0)

            # rbb = rb - d'*inv(Wl1)^2*rl1
            rbb = rb - sum(tmp)

            # rbv = rv - inv(Wl2)*rl2 - inv(Wl1)^2*rl1
            rbv = rv - mul(W['di'][m:2 * m], iw_rl2) - mul(W['di'][:m], iw_rl1)

            # [rtw;rtt] = rbwt + [-X'*D; E']*inv(Wl1)^2*inv(Db)*rbv
            tmp = mul(W['di'][:m]**2, mul(dbi, rbv))
            rtt = +rbwt[n:]
            base.gemv(E, tmp, rtt, trans='T', alpha=1.0, beta=1.0)
            rtw = +rbwt[:n]
            tmp = mul(d, tmp)
            blas.gemv(X, tmp, rtw, trans='T', alpha=-1.0, beta=1.0)

            # rtb = rbb - d'*inv(Wl1)^2*inv(Db)*rbv
            rtb = rbb - sum(tmp)

            # solve M*[dw;db] = [rtw - Bb*inv(D2)*rtt; rtb + lt'*inv(D2)*rtt]
            tmp = mul(d2i, rtt)
            tmp2 = matrix(0.0, (n, 1))
            blas.gemv(Bb, tmp, tmp2)
            dwdb = matrix([rtw - tmp2, rtb + blas.dot(mul(d2i, lt), rtt)])
            lapack.potrs(M, dwdb)

            # compute dt = inv(D2)*(rtt - Bb'*dw + lt*db)
            tmp2 = matrix(0.0, (k, 1))
            blas.gemv(Bb, dwdb[:n], tmp2, trans='T')
            dt = mul(d2i, rtt - tmp2 + lt * dwdb[-1])

            # compute dv = inv(Db)*(rbv + inv(Wl1)^2*(E*dt - D*X*dw - d*db))
            dv = matrix(0.0, (m, 1))
            blas.gemv(X, dwdb[:n], dv, alpha=-1.0)
            dv = mul(d, dv) - d * dwdb[-1]
            base.gemv(E, dt, dv, beta=1.0)
            tmp = +dv  # tmp = E*dt - D*X*dw - d*db
            dv = mul(dbi, rbv + mul(W['di'][:m]**2, dv))

            # compute wdz1 = inv(Wl1)*(E*dt - D*X*dw - d*db - dv - rl1)
            wdz1 = mul(W['di'][:m], tmp - dv) - iw_rl1

            # compute wdz2 = - inv(Wl2)*(dv + rl2)
            wdz2 = -mul(W['di'][m:2 * m], dv) - iw_rl2

            # compute wdzi = inv(Wi)*([-ei'*dt; -Pi*dw] - ri)
            wdzi = []
            tmp = matrix(0.0, (n, 1))
            for i in range(k):
                blas.gemv(P[i], dwdb[:n], tmp, alpha=-1.0, beta=0.0)
                tmp1 = matrix([-dt[i], tmp])
                blas.axpy(ri[i], tmp1, alpha=-1.0)
                qscal(tmp1, W['beta'][i], W['v'][i], inv=True)
                wdzi.append(tmp1)

            # solution
            x[:n] = dwdb[:n]
            x[n:n + k] = dt
            x[n + k] = dwdb[-1]
            x[n + k + 1:] = dv
            z[:m] = wdz1
            z[m:2 * m] = wdz2
            for i in range(k):
                z[2 * m + i * (n + 1):2 * m + (i + 1) * (n + 1)] = wdzi[i]

        return f
Example #23
0
    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