def factor(W, H = None, Df = None): blas.scal(0.0, K) if H is not None: K[:n, :n] = H K[n:n+p, :n] = A for k in range(n): if mnl: g[:mnl] = Df[:,k] g[mnl:] = G[:,k] scale(g, W, trans = 'T', inverse = 'I') pack(g, K, dims, mnl, offsety = k*ldK + n + p) K[(ldK+1)*(p+n) :: ldK+1] = -1.0 # Add positive regularization in 1x1 block and negative in 2x2 block. blas.copy(K, Ktilde) Ktilde[0 : (ldK+1)*n : ldK+1] += EPSILON Ktilde[(ldK+1)*n :: ldK+1] += -EPSILON lapack.sytrf(Ktilde, ipiv) 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. # # On entry, x, y, z contain bx, by, bz. On exit, they contain # the solution ux, uy, W*uz. blas.scal(0.0, sltn) blas.copy(x, u) blas.copy(y, u, offsety = n) scale(z, W, trans = 'T', inverse = 'I') pack(z, u, dims, mnl, offsety = n + p) blas.copy(u, r) # Iterative refinement algorithm: # Init: sltn = 0, r_0 = [bx; by; W^{-T}*bz] # 1. u_k = Ktilde^-1 * r_k # 2. sltn += u_k # 3. r_k+1 = r - K*sltn # Repeat until exceed MAX_ITER iterations or ||r|| <= ERROR_BOUND iteration = 0 resid_norm = 1 while iteration <= MAX_ITER and resid_norm > ERROR_BOUND: lapack.sytrs(Ktilde, ipiv, u) blas.axpy(u, sltn, alpha = 1.0) blas.copy(r, u) blas.symv(K, sltn, u, alpha = -1.0, beta = 1.0) resid_norm = math.sqrt(blas.dot(u, u)) iteration += 1 blas.copy(sltn, x, n = n) blas.copy(sltn, y, offsetx = n, n = p) unpack(sltn, z, dims, mnl, offsetx = n + p) return solve
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. # # On entry, x, y, z contain bx, by, bz. On exit, they contain # the solution ux, uy, W*uz. blas.copy(x, u) blas.copy(y, u, offsety=n) scale(z, W, trans='T', inverse='I') pack(z, u, dims, mnl, offsety=n + p) lapack.sytrs(K, ipiv, u) blas.copy(u, x, n=n) blas.copy(u, y, offsetx=n, n=p) unpack(u, z, dims, mnl, offsetx=n + p)
def factor(W, H=None, Df=None): blas.scal(0.0, K) if H is not None: K[:n, :n] = H K[n:n+p, :n] = A for k in range(n): if mnl: g[:mnl] = Df[:, k] g[mnl:] = G[:, k] scale(g, W, trans='T', inverse='I') pack(g, K, dims, mnl, offsety=k*ldK + n + p) K[(ldK+1)*(p+n):: ldK+1] = -1.0 # Add positive regularization in 1x1 block and negative in 2x2 block. K[0: (ldK+1)*n: ldK+1] += REG_EPS K[(ldK+1)*n:: ldK+1] += -REG_EPS lapack.sytrf(K, ipiv) 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. # # On entry, x, y, z contain bx, by, bz. On exit, they contain # the solution ux, uy, W*uz. blas.copy(x, u) blas.copy(y, u, offsety=n) scale(z, W, trans='T', inverse='I') pack(z, u, dims, mnl, offsety=n + p) lapack.sytrs(K, ipiv, u) blas.copy(u, x, n=n) blas.copy(u, y, offsetx=n, n=p) unpack(u, z, dims, mnl, offsetx=n + p) return solve
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. # # On entry, x, y, z contain bx, by, bz. On exit, they contain # the solution ux, uy, W*uz. blas.scal(0.0, sltn) blas.copy(x, u) blas.copy(y, u, offsety = n) scale(z, W, trans = 'T', inverse = 'I') pack(z, u, dims, mnl, offsety = n + p) blas.copy(u, r) # Iterative refinement algorithm: # Init: sltn = 0, r_0 = [bx; by; W^{-T}*bz] # 1. u_k = Ktilde^-1 * r_k # 2. sltn += u_k # 3. r_k+1 = r - K*sltn # Repeat until exceed MAX_ITER iterations or ||r|| <= ERROR_BOUND iteration = 0 resid_norm = 1 while iteration <= MAX_ITER and resid_norm > ERROR_BOUND: lapack.sytrs(Ktilde, ipiv, u) blas.axpy(u, sltn, alpha = 1.0) blas.copy(r, u) blas.symv(K, sltn, u, alpha = -1.0, beta = 1.0) resid_norm = math.sqrt(blas.dot(u, u)) iteration += 1 blas.copy(sltn, x, n = n) blas.copy(sltn, y, offsetx = n, n = p) unpack(sltn, z, dims, mnl, offsetx = n + p)
def solve(x, y, z): """ Returns solution of rho * ux + A'(uy) - r^-T * uz * r^-1 = bx A(ux) = by -ux - r * uz * r' = bz. On entry, x = bx, y = by, z = bz. On exit, x = ux, y = uy, z = uz. """ # bz is a copy of z in the format of x blas.copy(z, bz) blas.axpy(bz, x, alpha=rho) # x := Gamma .* (u' * x * u) # = Gamma .* (u' * (bx + rho * bz) * u) cngrnc(U, x, trans='T', offsetx=0) blas.tbmv(Gamma, x, n=ns2, k=0, ldA=1, offsetx=0) # y := y - As(x) # := by - As( Gamma .* u' * (bx + rho * bz) * u) #blas.copy(x,xp) #pack_ip(xp,n = ns,m=1,nl=nl) misc.pack(x, xp, {'l': 0, 'q': [], 's': [ns]}) blas.gemv(Aspkd, xp, y, trans = 'T',alpha = -1.0, beta = 1.0, \ m = ns*(ns+1)/2, n = ms,offsetx = 0) # y := -y - A(bz) # = -by - A(bz) + As(Gamma .* (u' * (bx + rho * bz) * u) Af(bz, y, alpha=-1.0, beta=-1.0) # y := H^-1 * y # = H^-1 ( -by - A(bz) + As(Gamma.* u'*(bx + rho*bz)*u) ) # = uy blas.trsv(H, y) blas.trsv(H, y, trans='T') # bz = Vt' * vz * Vt # = uz where # vz := Gamma .* ( As'(uy) - x ) # = Gamma .* ( As'(uy) - Gamma .* (u'*(bx + rho *bz)*u) ) # = Gamma.^2 .* ( u' * (A'(uy) - bx - rho * bz) * u ). #blas.copy(x,xp) #pack_ip(xp,n=ns,m=1,nl=nl) misc.pack(x, xp, {'l': 0, 'q': [], 's': [ns]}) blas.scal(-1.0, xp) blas.gemv(Aspkd, y, xp, alpha=1.0, beta=1.0, m=ns * (ns + 1) / 2, n=ms, offsety=0) # bz[j] is xp unpacked and multiplied with Gamma misc.unpack(xp, bz, {'l': 0, 'q': [], 's': [ns]}) blas.tbmv(Gamma, bz, n=ns2, k=0, ldA=1, offsetx=0) # bz = Vt' * bz * Vt # = uz cngrnc(Vt, bz, trans='T', offsetx=0) symmetrize(bz, ns, offset=0) # x = -bz - r * uz * r' # z contains r.h.s. bz; copy to x blas.copy(z, x) blas.copy(bz, z) cngrnc(W['r'][0], bz, offsetx=0) blas.axpy(bz, x) blas.scal(-1.0, x)
def F(W): # SVD R[j] = U[j] * diag(sig[j]) * Vt[j] lapack.gesvd(+W['r'][0], sv, jobu='A', jobvt='A', U=U, Vt=Vt) # Vt[j] := diag(sig[j])^-1 * Vt[j] for k in xrange(ns): blas.tbsv(sv, Vt, n=ns, k=0, ldA=1, offsetx=k * ns) # Gamma[j] is an ns[j] x ns[j] symmetric matrix # # (sig[j] * sig[j]') ./ sqrt(1 + rho * (sig[j] * sig[j]').^2) # S = sig[j] * sig[j]' S = matrix(0.0, (ns, ns)) blas.syrk(sv, S) Gamma = div(S, sqrt(1.0 + rho * S**2)) symmetrize(Gamma, ns) # As represents the scaled mapping # # As(x) = A(u * (Gamma .* x) * u') # As'(y) = Gamma .* (u' * A'(y) * u) # # stored in a similar format as A, except that we use packed # storage for the columns of As[i][j]. if type(A) is spmatrix: blas.scal(0.0, As) try: As[VecAIndex] = +A['s'][VecAIndex] except: As[VecAIndex] = +A[VecAIndex] else: blas.copy(A, As) # As[i][j][:,k] = diag( diag(Gamma[j]))*As[i][j][:,k] # As[i][j][l,:] = Gamma[j][l,l]*As[i][j][l,:] for k in xrange(ms): cngrnc(U, As, trans='T', offsetx=k * (ns2)) blas.tbmv(Gamma, As, n=ns2, k=0, ldA=1, offsetx=k * (ns2)) misc.pack(As, Aspkd, {'l': 0, 'q': [], 's': [ns] * ms}) # H is an m times m block matrix with i, k block # # Hik = sum_j As[i,j]' * As[k,j] # # of size ms[i] x ms[k]. Hik = 0 if As[i,j] or As[k,j] # are zero for all j H = matrix(0.0, (ms, ms)) blas.syrk(Aspkd, H, trans='T', beta=1.0, k=ns * (ns + 1) / 2) lapack.potrf(H) def solve(x, y, z): """ Returns solution of rho * ux + A'(uy) - r^-T * uz * r^-1 = bx A(ux) = by -ux - r * uz * r' = bz. On entry, x = bx, y = by, z = bz. On exit, x = ux, y = uy, z = uz. """ # bz is a copy of z in the format of x blas.copy(z, bz) blas.axpy(bz, x, alpha=rho) # x := Gamma .* (u' * x * u) # = Gamma .* (u' * (bx + rho * bz) * u) cngrnc(U, x, trans='T', offsetx=0) blas.tbmv(Gamma, x, n=ns2, k=0, ldA=1, offsetx=0) # y := y - As(x) # := by - As( Gamma .* u' * (bx + rho * bz) * u) #blas.copy(x,xp) #pack_ip(xp,n = ns,m=1,nl=nl) misc.pack(x, xp, {'l': 0, 'q': [], 's': [ns]}) blas.gemv(Aspkd, xp, y, trans = 'T',alpha = -1.0, beta = 1.0, \ m = ns*(ns+1)/2, n = ms,offsetx = 0) # y := -y - A(bz) # = -by - A(bz) + As(Gamma .* (u' * (bx + rho * bz) * u) Af(bz, y, alpha=-1.0, beta=-1.0) # y := H^-1 * y # = H^-1 ( -by - A(bz) + As(Gamma.* u'*(bx + rho*bz)*u) ) # = uy blas.trsv(H, y) blas.trsv(H, y, trans='T') # bz = Vt' * vz * Vt # = uz where # vz := Gamma .* ( As'(uy) - x ) # = Gamma .* ( As'(uy) - Gamma .* (u'*(bx + rho *bz)*u) ) # = Gamma.^2 .* ( u' * (A'(uy) - bx - rho * bz) * u ). #blas.copy(x,xp) #pack_ip(xp,n=ns,m=1,nl=nl) misc.pack(x, xp, {'l': 0, 'q': [], 's': [ns]}) blas.scal(-1.0, xp) blas.gemv(Aspkd, y, xp, alpha=1.0, beta=1.0, m=ns * (ns + 1) / 2, n=ms, offsety=0) # bz[j] is xp unpacked and multiplied with Gamma misc.unpack(xp, bz, {'l': 0, 'q': [], 's': [ns]}) blas.tbmv(Gamma, bz, n=ns2, k=0, ldA=1, offsetx=0) # bz = Vt' * bz * Vt # = uz cngrnc(Vt, bz, trans='T', offsetx=0) symmetrize(bz, ns, offset=0) # x = -bz - r * uz * r' # z contains r.h.s. bz; copy to x blas.copy(z, x) blas.copy(bz, z) cngrnc(W['r'][0], bz, offsetx=0) blas.axpy(bz, x) blas.scal(-1.0, x) return solve
def solve(x, y, z): """ Returns solution of rho * ux + A'(uy) - r^-T * uz * r^-1 = bx A(ux) = by -ux - r * uz * r' = bz. On entry, x = bx, y = by, z = bz. On exit, x = ux, y = uy, z = uz. """ # bz is a copy of z in the format of x blas.copy(z, bz) blas.axpy(bz, x, alpha=rho, offsetx=nl, offsety=nl) # x := Gamma .* (u' * x * u) # = Gamma .* (u' * (bx + rho * bz) * u) cngrnc(U, x, trans='T', offsetx=nl) blas.tbmv(Gamma, x, n=ns2, k=0, ldA=1, offsetx=nl) blas.tbmv(+W['d'], x, n=nl, k=0, ldA=1) # y := y - As(x) # := by - As( Gamma .* u' * (bx + rho * bz) * u) misc.pack(x, xp, dims) blas.gemv(Aspkd, xp, y, trans = 'T',alpha = -1.0, beta = 1.0, \ m = ns*(ns+1)/2, n = ms,offsetx = nl) #y = y - mul(+W['d'][:nl/2],xp[:nl/2])+ mul(+W['d'][nl/2:nl],xp[nl/2:nl]) blas.tbmv(+W['d'], xp, n=nl, k=0, ldA=1) blas.axpy(xp, y, alpha=-1, n=ms) blas.axpy(xp, y, alpha=1, n=ms, offsetx=nl / 2) # y := -y - A(bz) # = -by - A(bz) + As(Gamma .* (u' * (bx + rho * bz) * u) Af(bz, y, alpha=-1.0, beta=-1.0) # y := H^-1 * y # = H^-1 ( -by - A(bz) + As(Gamma.* u'*(bx + rho*bz)*u) ) # = uy blas.trsv(H, y) blas.trsv(H, y, trans='T') # bz = Vt' * vz * Vt # = uz where # vz := Gamma .* ( As'(uy) - x ) # = Gamma .* ( As'(uy) - Gamma .* (u'*(bx + rho *bz)*u) ) # = Gamma.^2 .* ( u' * (A'(uy) - bx - rho * bz) * u ). misc.pack(x, xp, dims) blas.scal(-1.0, xp) blas.gemv(Aspkd, y, xp, alpha=1.0, beta=1.0, m=ns * (ns + 1) / 2, n=ms, offsety=nl) #xp[:nl/2] = xp[:nl/2] + mul(+W['d'][:nl/2],y) #xp[nl/2:nl] = xp[nl/2:nl] - mul(+W['d'][nl/2:nl],y) blas.copy(y, tmp) blas.tbmv(+W['d'], tmp, n=nl / 2, k=0, ldA=1) blas.axpy(tmp, xp, n=nl / 2) blas.copy(y, tmp) blas.tbmv(+W['d'], tmp, n=nl / 2, k=0, ldA=1, offsetA=nl / 2) blas.axpy(tmp, xp, alpha=-1, n=nl / 2, offsety=nl / 2) # bz[j] is xp unpacked and multiplied with Gamma blas.copy(xp, bz) #,n = nl) misc.unpack(xp, bz, dims) blas.tbmv(Gamma, bz, n=ns2, k=0, ldA=1, offsetx=nl) # bz = Vt' * bz * Vt # = uz cngrnc(Vt, bz, trans='T', offsetx=nl) symmetrize(bz, ns, offset=nl) # x = -bz - r * uz * r' # z contains r.h.s. bz; copy to x #so far, z = bzc (untouched) blas.copy(z, x) blas.copy(bz, z) cngrnc(W['r'][0], bz, offsetx=nl) blas.tbmv(W['d'], bz, n=nl, k=0, ldA=1) blas.axpy(bz, x) blas.scal(-1.0, x)