Exemplo n.º 1
0
    def test_pfcholesky(self):
        U = matrix(range(1,2*self.symb.n+1),(self.symb.n,2),tc='d')/self.symb.n
        alpha = matrix([1.2,-0.01])
        D = matrix(0.0,(2,2))
        D[::3] = alpha
        random.seed(1)
        V = matrix([random.random() for i in range(self.symb.n*3)],(self.symb.n,3))

        # PF Cholesky from spmatrix
        Lpf = cp.pfcholesky(self.A,U,alpha,p=amd.order)
        Vt = +V
        Lpf.trmm(Vt,trans='T')
        Lpf.trmm(Vt,trans='N')
        diff = list( (Vt - (cp.symmetrize(self.A) + U*D*U.T)*V)[:] )
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])

        Lpf.trsm(Vt,trans='N')
        Lpf.trsm(Vt,trans='T')
        diff = list( (Vt-V)[:] )
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])

        # PF Cholesky from cspmatrix factor
        L = cp.cspmatrix(self.symb) + self.A
        Lpf = cp.pfcholesky(L,U,alpha)
        Vt = +V
        Lpf.trmm(Vt,trans='T')
        Lpf.trmm(Vt,trans='N')
        diff = list( (Vt - (cp.symmetrize(self.A) + U*D*U.T)*V)[:] )
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])

        Lpf.trsm(Vt,trans='N')
        Lpf.trsm(Vt,trans='T')
        diff = list( (Vt-V)[:] )
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])
Exemplo n.º 2
0
    def spy(P,i=None,file=None,scale=None):
        """Generates sparsity plot using Pylab"""
        if type(P) is spmatrix:
            V = chompack.symmetrize(chompack.tril(P))
            n = V.size[0]
        else:
            if not P._A: raise AttributeError, "SDP data missing"
            n = +P.n; 
            if i == None: V = chompack.symmetrize(P.V)
            elif i>=0 and i<=P.m and P._A:
                r = P._A.CCS[1][P._A.CCS[0][i]:P._A.CCS[0][i+1]]
                if type(r) is int: I = [r%n]; J = [r/n]
                else: I,J = misc.ind2sub(n,r)
                V = chompack.symmetrize(spmatrix(0.,I,J,(n,n)))
            else: raise ValueError, "index out of range"

        from math import floor
        msize = max(1,int(floor(100./n)))

        if file==None: pylab.ion()
        else: pylab.ioff()
        f = pylab.figure(figsize=(6,6)); f.clf()
        if scale is None: scale = 1.0 
        I = V.I*scale+1; J = (n-V.J)*scale
        p = pylab.plot(I,J, 's', linewidth = 1, hold = 'False')
        pylab.setp(p, markersize = msize, markerfacecolor = 'k')
        g = pylab.gca()
        pylab.axis([0.5,n*scale+0.5,0.5,n*scale+0.5])
        g.set_aspect('equal')
        locs,labels = pylab.yticks()
        locs = locs[locs<=n*scale]; locs = locs[locs>=1]
        pylab.yticks(locs[::-1]-(locs[-1]-n*scale-1)-locs[0],
                     [str(int(loc)) for loc in locs])
        if file: pylab.savefig(file)
Exemplo n.º 3
0
    def test_cspmatrix(self):
        Ac = cp.cspmatrix(self.symb) + self.A
        self.assertTrue(Ac.is_factor is False)
        self.assertTrue(Ac.size[0] == Ac.size[1])
        self.assertTrue(Ac.size[0] == 17)

        diff = list((self.A - Ac.spmatrix(reordered=False,symmetric=False)).V)
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])

        diff = list(cp.symmetrize(self.A) - Ac.spmatrix(reordered=False,symmetric=True))
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])

        diff = list(cp.symmetrize(self.A)[self.symb.p,self.symb.p] - Ac.spmatrix(reordered=True,symmetric=True))
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])

        diff = list(cp.tril(cp.symmetrize(self.A)[self.symb.p,self.symb.p]) - Ac.spmatrix(reordered=True,symmetric=False))
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])
                
        diff = list((2*self.A -  (2*Ac).spmatrix(reordered=False,symmetric=False)).V)
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])

        diff = list((2*self.A -  (Ac+Ac).spmatrix(reordered=False,symmetric=False)).V)
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])

        Ac2 = Ac.copy()
        Ac2 += Ac
        diff = list((2*self.A -  Ac2.spmatrix(reordered=False,symmetric=False)).V)
        self.assertAlmostEqualLists(diff, len(diff)*[0.0])

        self.assertAlmostEqualLists(list(Ac.diag(reordered=False)), list(self.A[::18]))
        self.assertAlmostEqualLists(list(Ac.diag(reordered=True)), list(self.A[self.symb.p,self.symb.p][::18]))
Exemplo n.º 4
0
def embed_SDP(P,order="AMD",cholmod=False):
    if not isinstance(P,SDP): raise ValueError, "not an SDP object"
    if order=='AMD':
        from cvxopt.amd import order
    elif order=='METIS':
        from cvxopt.metis import order
    else: raise ValueError, "unknown ordering: %s " %(order)
    p = order(P.V)

    if cholmod:
        from cvxopt import cholmod
        V = +P.V + spmatrix([float(i+1) for i in xrange(P.n)],xrange(P.n),xrange(P.n))
        F = cholmod.symbolic(V,p=p)
        cholmod.numeric(V,F)
        f = cholmod.getfactor(F)
        fd = [(j,i) for i,j in enumerate(f[:P.n**2:P.n+1])]
        fd.sort()
        ip = matrix([j for _,j in fd])
        Ve = chompack.tril(chompack.perm(chompack.symmetrize(f),ip))
        Ie = misc.sub2ind((P.n,P.n),Ve.I,Ve.J)
    else:
        #Vc,n = chompack.embed(P.V,p)
        symb = chompack.symbolic(P.V,p)
        #Ve = chompack.sparse(Vc)
        Ve = symb.sparsity_pattern(reordered=False)
        Ie = misc.sub2ind((P.n,P.n),Ve.I,Ve.J)
    Pe = SDP()
    Pe._A = +P.A; Pe._b = +P.b
    Pe._A[:,0] += spmatrix(0.0,Ie,[0 for i in range(len(Ie))],(Pe._A.size[0],1))
    Pe._agg_sparsity()
    Pe._pname = P._pname + "_embed"
    Pe._ischordal = True; Pe._blockstruct = P._blockstruct
    return Pe      
Exemplo n.º 5
0
    def test_cspmatrix(self):
        Ac = cp.cspmatrix(self.symb) + self.A
        self.assertTrue(Ac.is_factor is False)
        self.assertTrue(Ac.size[0] == Ac.size[1])
        self.assertTrue(Ac.size[0] == 17)

        diff = list((self.A - Ac.spmatrix(reordered=False, symmetric=False)).V)
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        diff = list(
            cp.symmetrize(self.A) -
            Ac.spmatrix(reordered=False, symmetric=True))
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        diff = list(
            cp.symmetrize(self.A)[self.symb.p, self.symb.p] -
            Ac.spmatrix(reordered=True, symmetric=True))
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        diff = list(
            cp.tril(cp.symmetrize(self.A)[self.symb.p, self.symb.p]) -
            Ac.spmatrix(reordered=True, symmetric=False))
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        diff = list((2 * self.A -
                     (2 * Ac).spmatrix(reordered=False, symmetric=False)).V)
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        diff = list((2 * self.A -
                     (Ac + Ac).spmatrix(reordered=False, symmetric=False)).V)
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        Ac2 = Ac.copy()
        Ac2 += Ac
        diff = list(
            (2 * self.A - Ac2.spmatrix(reordered=False, symmetric=False)).V)
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        self.assertAlmostEqualLists(list(Ac.diag(reordered=False)),
                                    list(self.A[::18]))
        self.assertAlmostEqualLists(
            list(Ac.diag(reordered=True)),
            list(self.A[self.symb.p, self.symb.p][::18]))
Exemplo n.º 6
0
    def test_pfcholesky(self):
        U = matrix(range(1, 2 * self.symb.n + 1),
                   (self.symb.n, 2), tc='d') / self.symb.n
        alpha = matrix([1.2, -0.01])
        D = matrix(0.0, (2, 2))
        D[::3] = alpha
        random.seed(1)
        V = matrix([random.random() for i in range(self.symb.n * 3)],
                   (self.symb.n, 3))

        # PF Cholesky from spmatrix
        Lpf = cp.pfcholesky(self.A, U, alpha, p=amd.order)
        Vt = +V
        Lpf.trmm(Vt, trans='T')
        Lpf.trmm(Vt, trans='N')
        diff = list((Vt - (cp.symmetrize(self.A) + U * D * U.T) * V)[:])
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        Lpf.trsm(Vt, trans='N')
        Lpf.trsm(Vt, trans='T')
        diff = list((Vt - V)[:])
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        # PF Cholesky from cspmatrix factor
        L = cp.cspmatrix(self.symb) + self.A
        Lpf = cp.pfcholesky(L, U, alpha)
        Vt = +V
        Lpf.trmm(Vt, trans='T')
        Lpf.trmm(Vt, trans='N')
        diff = list((Vt - (cp.symmetrize(self.A) + U * D * U.T) * V)[:])
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])

        Lpf.trsm(Vt, trans='N')
        Lpf.trsm(Vt, trans='T')
        diff = list((Vt - V)[:])
        self.assertAlmostEqualLists(diff, len(diff) * [0.0])
Exemplo n.º 7
0
def softmargin_completion(Q, d, gamma):
    """
    Solves the QP

        minimize    (1/2)*y'*Qc^{-1}*y + gamma*sum(v)
        subject to  diag(d)*(y + b*ones) + v >= 1
                    v >= 0

    (with variables y, b, v) and its dual, the 'soft-margin' SVM problem,

        maximize    -(1/2)*z'*Qc*z + d'*z
        subject to  0 <= diag(d)*z <= gamma*ones
                    sum(z) = 0

    (with variables z).

    Qc is the max determinant completion of Q.


    Input arguments.

        Q is a sparse N x N sparse matrix with chordal sparsity pattern
            and a positive definite completion

        d is an N-vector of labels -1 or 1.

        gamma is a positive parameter.

        F is the chompack pattern corresponding to Q.  If F is None, the
            pattern is computed.


    Output.

        z, y, b, v, optval, L, iters

    """

    if verbose: solvers.options['show_progress'] = True
    else: solvers.options['show_progress'] = False

    N = Q.size[0]
    p = chompack.maxcardsearch(Q)
    symb = chompack.symbolic(Q, p)
    Qc = chompack.cspmatrix(symb) + Q

    # Qinv is the inverse of the max. determinant p.d. completion of Q
    Lc = Qc.copy()
    chompack.completion(Lc)
    Qinv = Lc.copy()
    chompack.llt(Qinv)
    Qinv = Qinv.spmatrix(reordered=False)
    Qinv = chompack.symmetrize(Qinv)

    def P(u, v, alpha=1.0, beta=0.0):
        """
            v := alpha * [ Qc^-1, 0, 0;  0, 0, 0;  0, 0, 0 ] * u + beta * v
        """

        v *= beta
        base.symv(Qinv, u, v, alpha=alpha, beta=1.0)

    def G(u, v, alpha=1.0, beta=0.0, trans='N'):
        """
        If trans is 'N':

            v := alpha * [ -diag(d),  -d,  -I;  0,  0,  -I ] * u + beta * v.

        If trans is 'T':

            v := alpha * [ -diag(d), 0;  -d', 0;  -I, -I ] * u + beta * v.
        """

        v *= beta

        if trans is 'N':
            v[:N] -= alpha * (base.mul(d, u[:N] + u[N]) + u[-N:])
            v[-N:] -= alpha * u[-N:]

        else:
            v[:N] -= alpha * base.mul(d, u[:N])
            v[N] -= alpha * blas.dot(d, u, n=N)
            v[-N:] -= alpha * (u[:N] + u[N:])

    K = spmatrix(0.0, Qinv.I, Qinv.J)
    dy1, dy2 = matrix(0.0, (N, 1)), matrix(0.0, (N, 1))

    def Fkkt(W):
        """
        Custom KKT solver for

            [  Qinv  0   0  -D    0  ] [ ux_y ]   [ bx_y ]
            [  0     0   0  -d'   0  ] [ ux_b ]   [ bx_b ]
            [  0     0   0  -I   -I  ] [ ux_v ] = [ bx_v ]
            [ -D    -d  -I  -D1   0  ] [ uz_z ]   [ bz_z ]
            [  0     0  -I   0   -D2 ] [ uz_w ]   [ bz_w ]

        with D1 = diag(d1), D2 = diag(d2), d1 = W['d'][:N]**2,
        d2 = W['d'][N:])**2.
        """

        d1, d2 = W['d'][:N]**2, W['d'][N:]**2
        d3, d4 = (d1 + d2)**-1, (d1**-1 + d2**-1)**-1

        # Factor the chordal matrix K = Qinv + (D_1+D_2)^-1.
        K.V = Qinv.V
        K[::N + 1] = K[::N + 1] + d3
        L = chompack.cspmatrix(symb) + K
        chompack.cholesky(L)

        # Solve (Qinv + (D1+D2)^-1) * dy2 = (D1 + D2)^{-1} * 1
        blas.copy(d3, dy2)
        chompack.trsm(L, dy2, trans='N')
        chompack.trsm(L, dy2, trans='T')

        def g(x, y, z):

            # Solve
            #
            #     [ K    d3    ] [ ux_y ]
            #     [            ] [      ] =
            #     [ d3'  1'*d3 ] [ ux_b ]
            #
            #         [ bx_y ]   [ D  ]
            #         [      ] - [    ] * D3 * (D2 * bx_v + bx_z - bx_w).
            #         [ bx_b ]   [ d' ]

            x[:N] -= mul(d, mul(d3, mul(d2, x[-N:]) + z[:N] - z[-N:]))
            x[N] -= blas.dot(d, mul(d3, mul(d2, x[-N:]) + z[:N] - z[-N:]))

            # Solve dy1 := K^-1 * x[:N]
            blas.copy(x, dy1, n=N)
            chompack.trsm(L, dy1, trans='N')
            chompack.trsm(L, dy1, trans='T')

            # Find ux_y = dy1 - ux_b * dy2 s.t
            #
            #     d3' * ( dy1 - ux_b * dy2 + ux_b ) = x[N]
            #
            # i.e.  x[N] := ( x[N] - d3'* dy1 ) / ( d3'* ( 1 - dy2 ) ).

            x[N] = ( x[N] - blas.dot(d3, dy1) ) / \
                ( blas.asum(d3) - blas.dot(d3, dy2) )
            x[:N] = dy1 - x[N] * dy2

            # ux_v = D4 * ( bx_v -  D1^-1 (bz_z + D * (ux_y + ux_b))
            #     - D2^-1 * bz_w )

            x[-N:] = mul(
                d4, x[-N:] - div(z[:N] + mul(d, x[:N] + x[N]), d1) -
                div(z[N:], d2))

            # uz_z = - D1^-1 * ( bx_z - D * ( ux_y + ux_b ) - ux_v )
            # uz_w = - D2^-1 * ( bx_w - uz_w )
            z[:N] += base.mul(d, x[:N] + x[N]) + x[-N:]
            z[-N:] += x[-N:]
            blas.scal(-1.0, z)

            # Return W['di'] * uz
            blas.tbmv(W['di'], z, n=2 * N, k=0, ldA=1)

        return g

    q = matrix(0.0, (2 * N + 1, 1))

    if weights is 'proportional':
        dlist = list(d)
        C1 = 0.5 * N * gamma / dlist.count(1)
        C2 = 0.5 * N * gamma / dlist.count(-1)
        gvec = matrix([C1 if w == 1 else C2 for w in dlist], (N, 1))
        del dlist
        q[-N:] = gvec
    elif weights is 'equal':
        q[-N:] = gamma

    h = matrix(0.0, (2 * N, 1))
    h[:N] = -1.0
    sol = solvers.coneqp(P, q, G, h, kktsolver=Fkkt)
    u = matrix(0.0, (N, 1))
    y, b, v = sol['x'][:N], sol['x'][N], sol['x'][N + 1:]
    z = mul(d, sol['z'][:N])
    base.symv(Qinv, y, u)
    optval = 0.5 * blas.dot(y, u) + gamma * sum(v)
    return y, b, v, z, optval, Lc, sol['iterations']