Example #1
0
    def lnprob(theta, Deltam, nsne, xi, redshiftterm):
        A, M, sigma, pv = theta
        if (A <= 0 or sigma < 0 or pv < 0):
            return -numpy.inf
        C = A * numpy.array(xi)
        numpy.fill_diagonal(
            C,
            C.diagonal() + sigma**2 / nsne + (pv * redshiftterm)**2)
        mterm = Deltam - M

        C = matrix(C)
        W = matrix(mterm)
        try:
            lapack.posv(C, W, uplo='U')
        except ArithmeticError:
            return -np.inf
        logdetC = 2 * numpy.log(numpy.array(C).diagonal()).sum()

        lp = -0.5 * (logdetC + blas.dot(matrix(mterm), W)) + cauchy.logpdf(
            sigma, loc=0.08, scale=0.5) + cauchy.logpdf(
                pv, loc=0, scale=600 / 3e5)

        if not numpy.isfinite(lp):
            return -np.inf
        return lp
Example #2
0
def lapack_posv(a, b):
    """
    Inverse using LaPaCK posv (definite positive) algorithm.

    :param a:
    :param b:
    :return:
    """
    b_posv = matrix(b)
    lapack.posv(matrix(a), b_posv)
    return b_posv
Example #3
0
def PLS2D_getBeta(theta, ZtX, ZtY, XtX, ZtZ, XtY, YtX, YtZ, XtZ, YtY, n, P,
                  tinds, rinds, cinds):

    # Obtain Lambda
    Lambda = mapping2D(theta, tinds, rinds, cinds)

    # Obtain Lambda'
    Lambdat = spmatrix.trans(Lambda)

    # Obtain Lambda'Z'Y and Lambda'Z'X
    LambdatZtY = Lambdat * ZtY
    LambdatZtX = Lambdat * ZtX

    # Set the factorisation to use LL' instead of LDL'
    cholmod.options['supernodal'] = 2

    # Obtain the cholesky decomposition
    LambdatZtZLambda = Lambdat * ZtZ * Lambda
    I = spmatrix(1.0, range(Lambda.size[0]), range(Lambda.size[0]))
    chol_dict = sparse_chol2D(LambdatZtZLambda + I,
                              perm=P,
                              retF=True,
                              retP=False,
                              retL=False)
    F = chol_dict['F']

    # Obtain C_u (annoyingly solve writes over the second argument,
    # whereas spsolve outputs)
    Cu = LambdatZtY[P, :]
    cholmod.solve(F, Cu, sys=4)

    # Obtain RZX
    RZX = LambdatZtX[P, :]
    cholmod.solve(F, RZX, sys=4)

    # Obtain RXtRX
    RXtRX = XtX - matrix.trans(RZX) * RZX

    # Obtain beta estimates (note: gesv also replaces the second
    # argument)
    betahat = XtY - matrix.trans(RZX) * Cu
    try:
        lapack.posv(RXtRX, betahat)
    except:
        lapack.gesv(RXtRX, betahat)

    return (betahat)
def barrier():

    # variables kept same from cvxopt example
    MAXITERS = 100
    ALPHA = 0.01
    BETA = 0.5

    x = matrix(0.0, (n, 1))
    H = matrix(0.0, (n, n))  # Symmetrix matrix

    for iter in range(MAXITERS):
        # get the gradient of the function
        d = (b - A * x)**-1
        g = A.T * d

        # print(d[:, n*[0]].size)
        # print(A.size)
        """bug here: won't multiply of two matrix of same dimension. code is looking into another dimension?"""
        # get Hessian
        # lower diaganol multiplied to constraint matrix, n*[0] is first center x^t(0)
        h = np.zeros(shape=(m, n))
        np.matmul(d[:, n * [0]], A, h)
        # use the BLAS solver to get the symmetric matrix and get roots
        blas.syrk(h, H, trans='T')

        # do Newton's step
        v = -g  # g is our gradient
        # LAPACK solves the matrix and gives us the tep value to transverse with
        lapack.posv(H, v)

        # Stop condition if exceeding tolerance
        lam = blas.dot(g, v)
        if sqrt(-lam) < mu:
            return x  # return the orignal value if we're above tolerance

        # Line search to go to optimal using ALPHA and BETA
        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

        # increment x by the step times the negative gradient otherwise
        x += step * v
Example #5
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
Example #6
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
Example #7
0
# Nominal problem:  minimize || A*x - b ||_2
xnom = +b
lapack.gels(+A, xnom)
xnom = xnom[:n]

# Stochastic problem.
#
# minimize E || (A+u*B) * x - b ||_2^2
#          = || A*x - b||_2^2 + x'*P*x
#
# with P = E(u^2) * B'*B = (1/3) * B'*B

S = A.T * A + (1.0 / 3.0) * B.T * B
xstoch = A.T * b
lapack.posv(S, xstoch)

# Worst case approximation.
#
# minimize max_{-1 <= u <= 1} ||A*u - b||_2^2.

xwc = wcls(A, [B], b)

nopts = 500
us = -2.0 + (2.0 - (-2.0)) / (nopts - 1) * matrix(list(range(nopts)), tc='d')
rnom = [blas.nrm2((A + u * B) * xnom - b) for u in us]
rstoch = [blas.nrm2((A + u * B) * xstoch - b) for u in us]
rwc = [blas.nrm2((A + u * B) * xwc - b) for u in us]

if pylab_installed:
    pylab.figure(1, facecolor='w')
Example #8
0
def covsel(Y):
    """
    Returns the solution of

         minimize    -log det K + Tr(KY)
         subject to  K_{ij}=0,  (i,j) not in indices listed in I,J.

    Y is a symmetric sparse matrix with nonzero diagonal elements.
    I = Y.I,  J = Y.J.
    """

    I, J = Y.I, Y.J
    n, m = Y.size[0], len(I)
    N = I + J*n         # non-zero positions for one-argument indexing
    D = [k for k in range(m) if I[k]==J[k]]  # position of diagonal elements

    # 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: ", iters+1)
            break

        # line search
        dx = +v
        dx[D] *= 2      # scale the diagonal elems
        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
                s *= 0.5

        K.V = Kn.V

    return K
Example #9
0
    # Worst-case distribution from dual solution.
    X = [Z[2, :2].T / Z[2, 2] for Z in sol['zs'] if Z[2, 2] > 1e-5]

    return bound, P, q, r, X


# Compute bound for s0 with sigma = 1.0.
# Write ellipse {x | x'*P*x + 2*q'*x + r = 1} in the form
# {xc + L^{-T}*u | ||u||_2 = 1}

Sigma = matrix([1.0, 0.0, 0.0, 1.0], (2, 2))
bnd, P, q, r, X = cheb(A0, b0, Sigma)
xc = -q
L = +P
lapack.posv(L, xc)
L /= sqrt(1 - r - blas.dot(q, xc))

if pylab_installed:

    def makefig1():
        pylab.figure(1, facecolor='w', figsize=(6, 6))
        pylab.plot(V[0, :].T, V[1, :].T, 'b-')
        nopts = 1000
        angles = matrix([a * 2.0 * pi / nopts for a in range(nopts)],
                        (1, nopts))
        circle = matrix(0.0, (2, nopts))
        circle[0, :], circle[1, :] = cos(angles), sin(angles)
        for k in range(len(C)):
            c = C[k]
            pylab.plot([c[0]], [c[1]], 'ow')
Example #10
0
# Nominal problem:  minimize || A*x - b ||_2
xnom = +b
lapack.gels(+A, xnom)
xnom = xnom[:n]


# Stochastic problem.
#
# minimize E || (A+u*B) * x - b ||_2^2 
#          = || A*x - b||_2^2 + x'*P*x
#
# with P = E(u^2) * B'*B = (1/3) * B'*B

S = A.T * A + (1.0/3.0) * B.T * B
xstoch = A.T * b 
lapack.posv(S, xstoch)


# Worst case approximation.
#
# minimize max_{-1 <= u <= 1} ||A*u - b||_2^2.

xwc = wcls(A, [B], b)

nopts = 500
us = -2.0 + (2.0 - (-2.0))/(nopts-1) * matrix(list(range(nopts)),tc='d')
rnom = [ blas.nrm2( (A+u*B)*xnom - b) for u in us ]
rstoch = [ blas.nrm2( (A+u*B)*xstoch - b) for u in us ]
rwc = [ blas.nrm2( (A+u*B)*xwc - b) for u in us ]

if pylab_installed:
Example #11
0
    # Worst-case distribution from dual solution.
    X = [ Z[2,:2].T / Z[2,2] for Z in sol['zs'] if Z[2,2] > 1e-5 ]

    return bound, P, q, r, X


# Compute bound for s0 with sigma = 1.0.
# Write ellipse {x | x'*P*x + 2*q'*x + r = 1} in the form 
# {xc + L^{-T}*u | ||u||_2 = 1}

Sigma = matrix([1.0, 0.0, 0.0, 1.0], (2,2))
bnd, P, q, r, X = cheb(A0, b0, Sigma)
xc = -q
L = +P
lapack.posv(L, xc)
L /= sqrt(1 - r - blas.dot(q, xc))

if pylab_installed:
    def makefig1():
        pylab.figure(1, facecolor='w', figsize=(6,6))
        pylab.plot(V[0,:].T, V[1,:].T, 'b-')
        nopts = 1000
        angles = matrix( [a*2.0*pi/nopts for a in range(nopts) ], 
            (1,nopts) )
        circle = matrix(0.0, (2,nopts))
        circle[0,:], circle[1,:] = cos(angles), sin(angles)
        for k in range(len(C)):
            c = C[k]
            pylab.plot([c[0]], [c[1]], 'og')
            pylab.text(c[0], c[1], "s%d" %k)
Example #12
0
def PLS2D_getSigma2(theta, ZtX, ZtY, XtX, ZtZ, XtY, YtX, YtZ, XtZ, YtY, n, P,
                    I, tinds, rinds, cinds):

    # Obtain Lambda
    #t1 = time.time()
    Lambda = mapping2D(theta, tinds, rinds, cinds)
    #t2 = time.time()
    #print(t2-t1)#3.170967102050781e-05   9

    # Obtain Lambda'
    #t1 = time.time()
    Lambdat = spmatrix.trans(Lambda)
    #t2 = time.time()
    #print(t2-t1)# 3.5762786865234375e-06

    # Obtain Lambda'Z'Y and Lambda'Z'X
    #t1 = time.time()
    LambdatZtY = Lambdat * ZtY
    LambdatZtX = Lambdat * ZtX
    #t2 = time.time()
    #print(t2-t1)#1.049041748046875e-05   13

    # Obtain the cholesky decomposition
    #t1 = time.time()
    LambdatZtZLambda = Lambdat * (ZtZ * Lambda)
    #t2 = time.time()
    #print(t2-t1)#3.790855407714844e-05   2

    #t1 = time.time()
    chol_dict = sparse_chol2D(LambdatZtZLambda + I,
                              perm=P,
                              retF=True,
                              retP=False,
                              retL=False)
    F = chol_dict['F']
    #t2 = time.time()
    #print(t2-t1)#0.0001342296600341797   1

    # Obtain C_u (annoyingly solve writes over the second argument,
    # whereas spsolve outputs)
    #t1 = time.time()
    Cu = LambdatZtY[P, :]
    cholmod.solve(F, Cu, sys=4)
    #t2 = time.time()
    #print(t2-t1)#1.5974044799804688e-05   5

    # Obtain RZX
    #t1 = time.time()
    RZX = LambdatZtX[P, :]
    cholmod.solve(F, RZX, sys=4)
    #t2 = time.time()
    #print(t2-t1)#1.2159347534179688e-05   7

    # Obtain RXtRX
    #t1 = time.time()
    RXtRX = XtX - matrix.trans(RZX) * RZX
    #t2 = time.time()
    #print(t2-t1)#9.775161743164062e-06  11

    # Obtain beta estimates (note: gesv also replaces the second
    # argument)
    #t1 = time.time()
    betahat = XtY - matrix.trans(RZX) * Cu
    try:
        lapack.posv(RXtRX, betahat)
    except:
        lapack.gesv(RXtRX, betahat)
    #t2 = time.time()
    #print(t2-t1)#1.7404556274414062e-05   6

    # Obtain u estimates
    #t1 = time.time()
    uhat = Cu - RZX * betahat
    cholmod.solve(F, uhat, sys=5)
    cholmod.solve(F, uhat, sys=8)
    #t2 = time.time()
    #print(t2-t1)#1.2874603271484375e-05   8

    # Obtain b estimates
    #t1 = time.time()
    bhat = Lambda * uhat
    #t2 = time.time()
    #print(t2-t1)#2.86102294921875e-06  15

    # Obtain residuals sum of squares
    #t1 = time.time()
    resss = YtY - 2 * YtX * betahat - 2 * YtZ * bhat + 2 * matrix.trans(
        betahat) * XtZ * bhat + matrix.trans(
            betahat) * XtX * betahat + matrix.trans(bhat) * ZtZ * bhat
    #t2 = time.time()
    #print(t2-t1)#3.409385681152344e-05   4

    # Obtain penalised residual sum of squares
    #t1 = time.time()
    pss = resss + matrix.trans(uhat) * uhat

    return (pss / n)
Example #13
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
Example #14
0
def PLS(theta, ZtX, ZtY, XtX, ZtZ, XtY, YtX, YtZ, XtZ, YtY, P, tinds, rinds,
        cinds):

    #t1 = time.time()
    # Obtain Lambda from theta
    Lambda = mapping(theta, tinds, rinds, cinds)
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    # Obtain Lambda'
    Lambdat = spmatrix.trans(Lambda)
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    LambdatZtY = Lambdat * ZtY
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    LambdatZtX = Lambdat * ZtX
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    # Set the factorisation to use LL' instead of LDL'
    cholmod.options['supernodal'] = 2
    #t2 = time.time()
    #print(t2-t1)

    # Obtain L
    #t1 = time.time()
    LambdatZtZLambda = Lambdat * ZtZ * Lambda
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    I = spmatrix(1.0, range(Lambda.size[0]), range(Lambda.size[0]))
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    chol_dict = sparse_chol(LambdatZtZLambda + I,
                            perm=P,
                            retF=True,
                            retP=False,
                            retL=False)
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    F = chol_dict['F']
    #t2 = time.time()
    #print(t2-t1)

    # Obtain C_u (annoyingly solve writes over the second argument,
    # whereas spsolve outputs)
    #t1 = time.time()
    Cu = LambdatZtY[P, :]
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    cholmod.solve(F, Cu, sys=4)
    #t2 = time.time()
    #print(t2-t1)

    # Obtain RZX
    #t1 = time.time()
    RZX = LambdatZtX[P, :]
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    cholmod.solve(F, RZX, sys=4)
    #t2 = time.time()
    #print(t2-t1)

    # Obtain RXtRX
    #t1 = time.time()
    RXtRX = XtX - matrix.trans(RZX) * RZX
    #t2 = time.time()
    #print(t2-t1)

    #print(RXtRX.size)
    #print(X.size)
    #print(Y.size)
    #print(RZX.size)
    #print(Cu.size)

    # Obtain beta estimates (note: gesv also replaces the second
    # argument)
    #t1 = time.time()
    betahat = XtY - matrix.trans(RZX) * Cu
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    lapack.posv(RXtRX, betahat)
    #t2 = time.time()
    #print(t2-t1)

    # Obtain u estimates
    #t1 = time.time()
    uhat = Cu - RZX * betahat
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    cholmod.solve(F, uhat, sys=5)
    #t2 = time.time()
    #print(t2-t1)

    #t1 = time.time()
    cholmod.solve(F, uhat, sys=8)
    #t2 = time.time()
    #print(t2-t1)

    # Obtain b estimates
    #t1 = time.time()
    bhat = Lambda * uhat
    #t2 = time.time()
    #print(t2-t1)

    # Obtain residuals sum of squares
    #t1 = time.time()
    resss = YtY - 2 * YtX * betahat - 2 * YtZ * bhat + 2 * matrix.trans(
        betahat) * XtZ * bhat + matrix.trans(
            betahat) * XtX * betahat + matrix.trans(bhat) * ZtZ * bhat
    #t2 = time.time()
    #print(t2-t1)

    # Obtain penalised residual sum of squares
    #t1 = time.time()
    pss = resss + matrix.trans(uhat) * uhat
    #t2 = time.time()
    #print(t2-t1)

    # Obtain Log(|L|^2)
    #t1 = time.time()
    logdet = 2 * sum(cvxopt.log(
        cholmod.diag(F)))  # this method only works for symm decomps
    # Need to do tr(R_X)^2 for rml
    #t2 = time.time()
    #print(t2-t1)

    # Obtain log likelihood
    logllh = -logdet / 2 - X.size[0] / 2 * (1 + np.log(2 * np.pi * pss) -
                                            np.log(X.size[0]))

    #print(L[::(L.size[0]+1)]) # gives diag
    #print(logllh[0,0])
    #print(theta)

    return (-logllh[0, 0])
Example #15
0
def PeLS2D(theta, ZtX, ZtY, XtX, ZtZ, XtY, YtX, YtZ, XtZ, YtY, n, P, I, tinds,
           rinds, cinds):

    # Obtain Lambda
    Lambda = mapping2D(theta, tinds, rinds, cinds)

    # Obtain Lambda'
    Lambdat = spmatrix.trans(Lambda)

    # Obtain Lambda'Z'Y and Lambda'Z'X
    LambdatZtY = Lambdat * ZtY
    LambdatZtX = Lambdat * ZtX

    # Obtain the cholesky decomposition
    LambdatZtZLambda = Lambdat * (ZtZ * Lambda)
    chol_dict = sparse_chol2D(LambdatZtZLambda + I,
                              perm=P,
                              retF=True,
                              retP=False,
                              retL=False)
    F = chol_dict['F']

    # Obtain C_u (annoyingly solve writes over the second argument,
    # whereas spsolve outputs)
    Cu = LambdatZtY[P, :]
    cholmod.solve(F, Cu, sys=4)

    # Obtain RZX
    RZX = LambdatZtX[P, :]
    cholmod.solve(F, RZX, sys=4)

    # Obtain RXtRX
    RXtRX = XtX - matrix.trans(RZX) * RZX

    # Obtain beta estimates (note: gesv also replaces the second
    # argument)
    betahat = XtY - matrix.trans(RZX) * Cu
    try:
        lapack.posv(RXtRX, betahat)
    except:
        lapack.gesv(RXtRX, betahat)

    # Obtain u estimates
    uhat = Cu - RZX * betahat
    cholmod.solve(F, uhat, sys=5)
    cholmod.solve(F, uhat, sys=8)

    # Obtain b estimates
    bhat = Lambda * uhat

    # Obtain residuals sum of squares
    resss = YtY - 2 * YtX * betahat - 2 * YtZ * bhat + 2 * matrix.trans(
        betahat) * XtZ * bhat + matrix.trans(
            betahat) * XtX * betahat + matrix.trans(bhat) * ZtZ * bhat

    # Obtain penalised residual sum of squares
    pss = resss + matrix.trans(uhat) * uhat

    # Obtain Log(|L|^2)
    logdet = 2 * sum(cvxopt.log(cholmod.diag(F)))

    # Obtain log likelihood
    logllh = -logdet / 2 - n / 2 * (1 + np.log(2 * np.pi * pss[0, 0]) -
                                    np.log(n))

    return (-logllh)