def low_rank_matrix_approx(A, r, delta=1e-8, maxiter=50): m, n = A.shape r = min(m, n, r) J = np.sort(np.random.choice(n, r, replace=False)) approx_prev = MatrixLowRank((np.zeros((m, r)), np.zeros((r, n))), r) for i in range(maxiter): R = A[:, J] Q, T = np.linalg.qr(R) assert Q.shape == (m, r) I = np.sort(maxvol(Q)) C = A[I, :].T assert C.shape == (n, r) Q, T = np.linalg.qr(C) assert Q.shape == (n, r) J = np.sort(maxvol(Q)) QQ = Q[J, :] # We need to store the same as A matrix approx_next = MatrixLowRank((A[:, J], np.dot(Q, np.linalg.inv(QQ)).T), r=r) if (approx_next - approx_prev).norm < delta * approx_prev.norm: approx_next.round(delta) return approx_next.u, approx_next.norm * approx_next.v approx_prev = approx_next approx_prev.round(delta) return approx_prev.u, approx_prev.norm * approx_next.v
def cross(a, r=None, niters=10): m, n = a.shape if r is None: r = min(m, n) r = min([m, n, r]) indj = np.sort(np.random.choice(n, r, replace = False)) for i in range(niters): C = a[:,indj] indi = np.sort(maxvol(C)) R = a[indi, :] indj = np.sort(maxvol(R.T)) C = np.linalg.solve(C[indi, :].T, C.T).T return C, R
def cross(a, r=None, niters=10): m, n = a.shape if r is None: r = min(m, n) r = min([m, n, r]) indj = np.sort(np.random.choice(n, r, replace=False)) for i in range(niters): C = a[:, indj] indi = np.sort(maxvol(C)) R = a[indi, :] indj = np.sort(maxvol(R.T)) C = np.linalg.solve(C[indi, :].T, C.T).T return C, R
def low_rank_matrix_approx(A, r, delta=1e-8, maxiter=50): m, n = A.shape r = min(m, n, r) J = np.sort(np.random.choice(n, r, replace = False)) approx_prev = MatrixLowRank((np.zeros((m, r)), np.zeros((r, n))), r) for i in range(maxiter): R = A[:, J] Q, T = np.linalg.qr(R) assert Q.shape == (m, r) I = np.sort(maxvol(Q)) C = A[I, :].T assert C.shape == (n, r) Q, T = np.linalg.qr(C) assert Q.shape == (n, r) J = np.sort(maxvol(Q)) QQ = Q[J, :] # We need to store the same as A matrix approx_next = MatrixLowRank((A[:, J], np.dot(Q, np.linalg.inv(QQ)).T), r=r) if (approx_next - approx_prev).norm < delta * approx_prev.norm: approx_next.round(delta) return approx_next.u, approx_next.norm * approx_next.v approx_prev = approx_next approx_prev.round(delta) return approx_prev.u, approx_prev.norm * approx_next.v
def multifuncrs(X, funs, eps=1E-6, nswp=10, kickrank=5, y0=None, rmax=999999, # TODO:infinity \ kicktype='amr-two', \ pcatype='svd', \ trunctype='fro', \ d2=1, \ do_qr=False, \ verb=1): """Cross approximation of a (vector-)function of several TT-tensors. :param X: tuple of TT-tensors :param funs: multivariate function :param eps: accuracy """ dtype = np.float64 if len(filter(lambda x: x.is_complex, X)) > 0: dtype = np.complex128 y = y0 wasrand = False nx = len(X) d = X[0].d n = X[0].n rx = np.transpose(np.array([ttx.r for ttx in X])) #crx = [tt.tensor.to_list(ttx) for x in X] #crx = zip(*crx) crx = np.transpose(np.array([tt.tensor.to_list(ttx) for ttx in X], dtype=np.object)) crx = np.empty((nx, d), dtype=np.object) i = 0 for ttx in X: v = tt.tensor.to_list(ttx) j = 0 for w in v: crx[i, j] = w j = j + 1 i = i + 1 crx = crx.T if y is None: ry = d2 * np.ones((d + 1,), dtype=np.int32) ry[0] = 1 y = tt.rand(n, d, ry) wasrand = True ry = y.r cry = tt.tensor.to_list(y) Ry = np.zeros((d + 1, ), dtype=np.object) Ry[0] = np.array([[1.0]], dtype=dtype) Ry[d] = np.array([[1.0]], dtype=dtype) Rx = np.zeros((d + 1, nx), dtype=np.object) Rx[0, :] = np.ones(nx, dtype=dtype) Rx[d, :] = np.ones(nx, dtype=dtype) block_order = [+d, -d] # orth for i in range(0, d - 1): cr = cry[i] cr = reshape(cr, (ry[i] * n[i], ry[i + 1])) cr, rv = np.linalg.qr(cr) cr2 = cry[i + 1] cr2 = reshape(cr2, (ry[i + 1], n[i + 1] * ry[i + 2])) cr2 = np.dot(rv, cr2) # matrix multiplication ry[i + 1] = cr.shape[1] cr = reshape(cr, (ry[i], n[i], ry[i + 1])) cry[i + 1] = reshape(cr2, (ry[i + 1], n[i + 1], ry[i + 2])) cry[i] = cr Ry[i + 1] = np.dot(Ry[i], reshape(cr, (ry[i], n[i] * ry[i + 1]))) Ry[i + 1] = reshape(Ry[i + 1], (ry[i] * n[i], ry[i + 1])) curind = [] if wasrand: # EVERY DAY I'M SHUFFLIN' curind = np.random.permutation(n[i] * ry[i])[:ry[i + 1]] else: curind = maxvol(Ry[i + 1]) Ry[i + 1] = Ry[i + 1][curind, :] for j in range(0, nx): try: Rx[i + 1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) except: pass Rx[i + 1, j] = np.dot(Rx[i, j], Rx[i + 1, j]) Rx[i + 1, j] = reshape(Rx[i + 1, j], (ry[i] * n[i], rx[i + 1, j])) Rx[i + 1, j] = Rx[i + 1, j][curind, :] d2 = ry[d] ry[d] = 1 cry[d - 1] = np.transpose(cry[d - 1], [2, 0, 1]) # permute last_sweep = False swp = 1 dy = np.zeros((d, )) max_dy = 0 cur_order = copy.copy(block_order) order_index = 1 i = d - 1 # can't use 'dir' identifier in python dirn = int(math.copysign(1, cur_order[order_index])) # DMRG sweeps while swp <= nswp or dirn > 0: oldy = reshape(cry[i], (d2 * ry[i] * n[i] * ry[i + 1],)) if not last_sweep: # compute the X superblocks curbl = np.zeros((ry[i] * n[i] * ry[i + 1], nx), dtype=dtype) for j in range(0, nx): cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) cr = np.dot(Rx[i, j], cr) cr = reshape(cr, (ry[i] * n[i], rx[i + 1, j])) cr = np.dot(cr, Rx[i + 1, j]) curbl[:, j] = cr.flatten('F') # call the function newy = funs(curbl) # multiply with inverted Ry newy = reshape(newy, (ry[i], n[i] * ry[i + 1] * d2)) newy = np.linalg.solve(Ry[i], newy) # y = R \ y newy = reshape(newy, (ry[i] * n[i] * ry[i + 1], d2)) newy = reshape(np.transpose(newy), (d2 * ry[i] * n[i], ry[i + 1])) newy = np.transpose(np.linalg.solve( np.transpose(Ry[i + 1]), np.transpose(newy))) # y=y/R newy = reshape(newy, (d2 * ry[i] * n[i] * ry[i + 1],)) else: newy = oldy dy[i] = np.linalg.norm(newy - oldy) / np.linalg.norm(newy) max_dy = max(max_dy, dy[i]) # truncation if dirn > 0: # left-to-right newy = reshape(newy, (d2, ry[i] * n[i] * ry[i + 1])) newy = reshape(np.transpose(newy), (ry[i] * n[i], ry[i + 1] * d2)) else: newy = reshape(newy, (d2 * ry[i], n[i] * ry[i + 1])) r = 0 # defines a variable in global scope if kickrank >= 0: u, s, v = np.linalg.svd(newy, full_matrices=False) v = np.conj(np.transpose(v)) if trunctype == "fro" or last_sweep: r = my_chop2(s, eps / math.sqrt(d) * np.linalg.norm(s)) else: # truncate taking into account the (r+1) overhead in the cross # (T.S.: what?) cums = abs(s * np.arange(2, len(s) + 2)) ** 2 cums = np.cumsum(cums[::-1])[::-1] cums = cums / cums[0] ff = [i for i in range(len(cums)) if cums[i] < eps ** 2 / d] if len(ff) == 0: r = len(s) else: r = np.amin(ff) r = min(r, rmax, len(s)) else: if dirn > 0: u, v = np.linalg.qr(newy) v = np.conj(np.transpose(v)) r = u.shape[1] s = np.ones((r, )) else: v, u = np.linalg.qr(np.transpose(newy)) v = np.conj(v) u = np.transpose(u) r = u.shape[1] s = np.ones((r, )) if verb > 1: print '=multifuncrs= block %d{%d}, dy: %3.3e, r: %d' % (i, dirn, dy[i], r) # kicks and interfaces if dirn > 0 and i < d - 1: u = u[:, :r] v = np.dot(v[:, :r], np.diag(s[:r])) # kick radd = 0 rv = 1 if not last_sweep and kickrank > 0: uk = None if kicktype == 'amr-two': # AMR(two)-like kick. # compute the X superblocks ind2 = np.unique(np.random.randint( 0, ry[i + 2] * n[i + 1], ry[i + 1])) #ind2 = np.unique(np.floor(np.random.rand(ry[i + 1]) * (ry[i + 2] * n[i + 1]))) rkick = len(ind2) curbl = np.zeros((ry[i] * n[i] * rkick, nx), dtype=dtype) for j in range(nx): cr1 = reshape( crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) cr1 = np.dot(Rx[i, j], cr1) cr1 = reshape(cr1, (ry[i] * n[i], rx[i + 1, j])) cr2 = reshape( crx[i + 1, j], (rx[i + 1, j] * n[i + 1], rx[i + 2, j])) cr2 = np.dot(cr2, Rx[i + 2, j]) cr2 = reshape( cr2, (rx[i + 1, j], n[i + 1] * ry[i + 2])) cr2 = cr2[:, ind2] curbl[:, j] = reshape( np.dot(cr1, cr2), (ry[i] * n[i] * rkick,)) # call the function uk = funs(curbl) uk = reshape(uk, (ry[i], n[i] * rkick * d2)) uk = np.linalg.solve(Ry[i], uk) uk = reshape(uk, (ry[i] * n[i], rkick * d2)) if pcatype == 'svd': uk, sk, vk = np.linalg.svd(uk, full_matrices=False) vk = np.conj(np.transpose(vk)) uk = uk[:, :min(kickrank, uk.shape[1])] else: # uk = uchol(np.transpose(uk), kickrank + 1) # TODO uk = uk[:, :max(uk.shape[1] - kickrank + 1, 1):-1] else: uk = np.random.rand(ry[i] * n[i], kickrank) u, rv = np.linalg.qr(np.concatenate((u, uk), axis=1)) radd = uk.shape[1] v = np.concatenate( (v, np.zeros((ry[i + 1] * d2, radd), dtype=dtype)), axis=1) v = np.dot(rv, np.conj(np.transpose(v))) r = u.shape[1] cr2 = cry[i + 1] cr2 = reshape(cr2, (ry[i + 1], n[i + 1] * ry[i + 2])) v = reshape(v, (r * ry[i + 1], d2)) v = reshape(np.transpose(v), (d2 * r, ry[i + 1])) v = np.dot(v, cr2) ry[i + 1] = r u = reshape(u, (ry[i], n[i], r)) v = reshape(v, (d2, r, n[i + 1], ry[i + 2])) cry[i] = u cry[i + 1] = v Ry[i + 1] = np.dot(Ry[i], reshape(u, (ry[i], n[i] * ry[i + 1]))) Ry[i + 1] = reshape(Ry[i + 1], (ry[i] * n[i], ry[i + 1])) curind = maxvol(Ry[i + 1]) Ry[i + 1] = Ry[i + 1][curind, :] for j in range(nx): Rx[i + 1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) Rx[i + 1, j] = np.dot(Rx[i, j], Rx[i + 1, j]) Rx[i + 1, j] = reshape(Rx[i + 1, j], (ry[i] * n[i], rx[i + 1, j])) Rx[i + 1, j] = Rx[i + 1, j][curind, :] elif dirn < 0 and i > 0: u = np.dot(u[:, :r], np.diag(s[:r])) v = np.conj(v[:, :r]) radd = 0 rv = 1 if not last_sweep and kickrank > 0: if kicktype == 'amr-two': # compute the X superblocks ind2 = np.unique(np.random.randint( 0, ry[i - 1] * n[i - 1], ry[i])) rkick = len(ind2) curbl = np.zeros( (rkick * n[i] * ry[i + 1], nx), dtype=dtype) for j in range(nx): cr1 = reshape( crx[i, j], (rx[i, j] * n[i], rx[i + 1, j])) cr1 = np.dot(cr1, Rx[i + 1, j]) cr1 = reshape(cr1, (rx[i, j], n[i] * ry[i + 1])) cr2 = reshape( crx[i - 1, j], (rx[i - 1, j], n[i - 1] * rx[i, j])) cr2 = np.dot(Rx[i - 1, j], cr2) cr2 = reshape(cr2, (ry[i - 1] * n[i - 1], rx[i, j])) cr2 = cr2[ind2, :] curbl[:, j] = reshape( np.dot(cr2, cr1), (rkick * n[i] * ry[i + 1],)) # calling the function uk = funs(curbl) uk = reshape(uk, (rkick * n[i] * ry[i + 1], d2)) uk = reshape(np.transpose( uk), (d2 * rkick * n[i], ry[i + 1])) uk = np.transpose(np.linalg.solve( np.transpose(Ry[i + 1]), np.transpose(uk))) uk = reshape(uk, (d2 * rkick, n[i] * ry[i + 1])) if pcatype == 'svd': vk, sk, uk = np.linalg.svd(uk, full_matrices=False) uk = np.conj(np.transpose(uk)) # TODO: refactor uk = uk[:, :min(kickrank, uk.shape[1])] else: # uk = uchol(uk, kickrank + 1) # TODO uk = uk[:, :max(uk.shape[1] - kickrank + 1, 1):-1] else: uk = np.random.rand(n[i] * ry[i + 1], kickrank) v, rv = np.linalg.qr(np.concatenate((v, uk), axis=1)) radd = uk.shape[1] u = np.concatenate( (u, np.zeros((d2 * ry[i], radd), dtype=dtype)), axis=1) u = np.dot(u, np.transpose(rv)) r = v.shape[1] cr2 = cry[i - 1] cr2 = reshape(cr2, (ry[i - 1] * n[i - 1], ry[i])) u = reshape(u, (d2, ry[i] * r)) u = reshape(np.transpose(u), (ry[i], r * d2)) u = np.dot(cr2, u) u = reshape(u, (ry[i - 1] * n[i - 1] * r, d2)) u = reshape(np.transpose(u), (d2, ry[i - 1], n[i - 1], r)) v = reshape(np.transpose(v), (r, n[i], ry[i + 1])) ry[i] = r cry[i - 1] = u cry[i] = v Ry[i] = np.dot(reshape(v, (ry[i] * n[i], ry[i + 1])), Ry[i + 1]) Ry[i] = reshape(Ry[i], (ry[i], n[i] * ry[i + 1])) curind = maxvol(np.transpose(Ry[i])) Ry[i] = Ry[i][:, curind] for j in range(nx): Rx[i, j] = reshape(crx[i, j], (rx[i, j] * n[i], rx[i + 1, j])) Rx[i, j] = np.dot(Rx[i, j], Rx[i + 1, j]) Rx[i, j] = reshape(Rx[i, j], (rx[i, j], n[i] * ry[i + 1])) Rx[i, j] = Rx[i, j][:, curind] elif dirn > 0 and i == d - 1: newy = np.dot(np.dot(u[:, :r], np.diag(s[:r])), np.conj(np.transpose(v[:, :r]))) newy = reshape(newy, (ry[i] * n[i] * ry[i + 1], d2)) cry[i] = reshape(np.transpose(newy), (d2, ry[i], n[i], ry[i + 1])) elif dirn < 0 and i == 0: newy = np.dot(np.dot(u[:, :r], np.diag(s[:r])), np.conj(np.transpose(v[:, :r]))) newy = reshape(newy, (d2, ry[i], n[i], ry[i + 1])) cry[i] = newy i = i + dirn cur_order[order_index] = cur_order[order_index] - dirn if cur_order[order_index] == 0: order_index = order_index + 1 if verb > 0: print '=multifuncrs= sweep %d{%d}, max_dy: %3.3e, erank: %g' % (swp, order_index, max_dy, math.sqrt(np.dot(ry[:d], n * ry[1:]) / np.sum(n))) if last_sweep: break if max_dy < eps and dirn < 0: last_sweep = True kickrank = 0 if order_index >= len(cur_order): cur_order = copy.copy(block_order) order_index = 0 if last_sweep: cur_order = [d - 1] max_dy = 0 swp = swp + 1 dirn = int(math.copysign(1, cur_order[order_index])) i = i + dirn cry[d - 1] = np.transpose(cry[d - 1][:, :, :, 0], [1, 2, 0]) y = tt.tensor.from_list(cry) return y
def multifuncrs2(X, funs, eps = 1e-6, \ nswp = 10, \ rmax = 9999999, \ verb = 1, \ kickrank = 5, \ kickrank2 = 0, \ d2 = 1, \ eps_exit = None, \ y0 = None, \ do_qr = False, \ restart_it = 0): dtype = np.float64 if len(filter(lambda x: x.is_complex, X)) > 0: dtype = np.complex128 if eps_exit is None: eps_exit = eps y = y0 nx = len(X) d = X[0].d n = X[0].n rx = np.transpose(np.array([ttx.r for ttx in X])) crx = np.empty((nx, d), dtype=np.object) i = 0 for ttx in X: v = tt.tensor.to_list(ttx) j = 0 for w in v: crx[i, j] = w j = j + 1 i = i + 1 crx = crx.T wasrand = False if y is None: ry = d2 * np.ones((d + 1, ), dtype=np.int32) ry[0] = 1 y = tt.rand(n, d, ry) wasrand = True #Error vector z = tt.rand(n, d, kickrank) rz = z.r z = tt.tensor.to_list(z) ry = y.r cry = tt.tensor.to_list(y) #Interface matrices - for solution one_arr = np.ones((1, 1), dtype=dtype) Ry = np.zeros((d + 1, ), dtype=np.object) Ry[0] = one_arr Ry[d] = one_arr Rx = np.zeros((d + 1, nx), dtype=np.object) Rx[0, :] = np.ones(nx, dtype=dtype) Rx[d, :] = np.ones(nx, dtype=dtype) Ryz = np.zeros((d + 1, ), dtype=np.object) Ryz[0] = one_arr Ryz[d] = one_arr Rz = np.zeros((d + 1, ), dtype=np.object) Rz[0] = one_arr Rz[d] = one_arr Rxz = np.zeros((d + 1, nx), dtype=np.object) Rxz[0, :] = np.ones(nx, dtype=dtype) Rxz[d, :] = np.ones(nx, dtype=dtype) block_order = [+d, -d] # orth for i in range(0, d - 1): cr = cry[i] cr = reshape(cr, (ry[i] * n[i], ry[i + 1])) cr, rv = np.linalg.qr(cr) cr2 = cry[i + 1] cr2 = reshape(cr2, (ry[i + 1], n[i + 1] * ry[i + 2])) cr2 = np.dot(rv, cr2) # matrix multiplication ry[i + 1] = cr.shape[1] cr = reshape(cr, (ry[i], n[i], ry[i + 1])) cry[i + 1] = reshape(cr2, (ry[i + 1], n[i + 1], ry[i + 2])) cry[i] = cr Ry[i + 1] = np.dot(Ry[i], reshape(cr, (ry[i], n[i] * ry[i + 1]))) Ry[i + 1] = reshape(Ry[i + 1], (ry[i] * n[i], ry[i + 1])) curind = [] if wasrand: # EVERY DAY I'M SHUFFLIN' curind = np.random.permutation(n[i] * ry[i])[:ry[i + 1]] else: curind = maxvol(Ry[i + 1]) Ry[i + 1] = Ry[i + 1][curind, :] #Interface matrices for X for j in range(0, nx): Rx[i + 1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) Rx[i + 1, j] = np.dot(Rx[i, j], Rx[i + 1, j]) Rx[i + 1, j] = reshape(Rx[i + 1, j], (ry[i] * n[i], rx[i + 1, j])) Rx[i + 1, j] = Rx[i + 1, j][curind, :] #Error for kick crz = z[i] crz = reshape(crz, (rz[i] * n[i], rz[i + 1])) crz, rv = np.linalg.qr(crz) cr2 = z[i + 1] cr2 = reshape(cr2, (rz[i + 1], n[i + 1] * rz[i + 2])) cr2 = np.dot(rv, cr2) rz[i + 1] = crz.shape[1] crz = reshape(crz, (rz[i], n[i], rz[i + 1])) z[i + 1] = reshape(cr2, (rz[i + 1], n[i + 1], rz[i + 2])) z[i] = crz #Interfaces for error Rz[i + 1] = np.dot(Rz[i], reshape(crz, [rz[i], n[i] * rz[i + 1]])) Rz[i + 1] = reshape(Rz[i + 1], [rz[i] * n[i], rz[i + 1]]) Ryz[i + 1] = np.dot(Ryz[i], reshape(cr, [ry[i], n[i] * ry[i + 1]])) Ryz[i + 1] = reshape(Ryz[i + 1], [rz[i] * n[i], ry[i + 1]]) #Pick random initial indices curind = np.random.permutation(n[i] * rz[i])[:rz[i + 1]] Ryz[i + 1] = Ryz[i + 1][curind, :] Rz[i + 1] = Rz[i + 1][curind, :] #Interface matrices for X for j in range(0, nx): Rxz[i + 1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) Rxz[i + 1, j] = np.dot(Rxz[i, j], Rxz[i + 1, j]) Rxz[i + 1, j] = reshape(Rxz[i + 1, j], (rz[i] * n[i], rx[i + 1, j])) Rxz[i + 1, j] = Rxz[i + 1, j][curind, :] d2 = ry[d] ry[d] = 1 cry[d - 1] = np.transpose(cry[d - 1], [2, 0, 1]) # permute swp = 1 max_dy = 0.0 cur_order = copy.copy(block_order) order_index = 1 i = d - 1 dirn = int(math.copysign( 1, cur_order[order_index])) # can't use 'dir' identifier in python #DMRG sweeps while swp <= nswp or dirn > 0: oldy = reshape(cry[i], (d2 * ry[i] * n[i] * ry[i + 1], )) #Compute X superblocks curbl = np.zeros((ry[i] * n[i] * ry[i + 1], nx), dtype) for j in range(0, nx): cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) cr = np.dot(Rx[i, j], cr) cr = reshape(cr, (ry[i] * n[i], rx[i + 1, j])) cr = np.dot(cr, Rx[i + 1, j]) curbl[:, j] = cr.flatten('F') newy = funs(curbl) # multiply with inverted Ry newy = reshape(newy, (ry[i], n[i] * ry[i + 1] * d2)) newy = np.linalg.solve(Ry[i], newy) # y = R \ y newy = reshape(newy, (ry[i] * n[i] * ry[i + 1], d2)) newy = reshape(np.transpose(newy), (d2 * ry[i] * n[i], ry[i + 1])) newy = np.transpose( np.linalg.solve(np.transpose(Ry[i + 1]), np.transpose(newy))) # y=y/R newy = reshape(newy, (d2 * ry[i] * n[i] * ry[i + 1], )) try: dy = np.linalg.norm(newy - oldy) / np.linalg.norm(newy) except ZeroDivisionError: print 'Bad initial indices, the solution is exactly zero. Restarting' return max_dy = max(max_dy, dy) # truncation if dirn > 0: # left-to-right newy = reshape(newy, (d2, ry[i] * n[i] * ry[i + 1])) newy = reshape(np.transpose(newy), (ry[i] * n[i], ry[i + 1] * d2)) else: newy = reshape(newy, (d2 * ry[i], n[i] * ry[i + 1])) if kickrank >= 0: try: u, s, v = np.linalg.svd(newy, full_matrices=False) except: tmp = np.array(np.random.randn(newy.shape[1], newy.shape[1]), dtype=dtype) tmp, ru_tmp = np.linalg.qr(tmp) u, s, v = np.linalg.svd(np.dot(newy, tmp)) #u * s * v = A * tmp v = np.dot(v, np.conj(tmp).T) v = np.conj(np.transpose(v)) r = my_chop2(s, eps / math.sqrt(d) * np.linalg.norm(s)) else: if dirn > 0: u, v = np.linalg.qr(newy) v = np.conj(np.transpose(v)) r = u.shape[1] s = np.ones((r, )) else: v, u = np.linalg.qr(np.transpose(newy)) v = np.conj(v) u = np.transpose(u) r = u.shape[1] s = np.ones((r, )) if verb > 1: print '=multifuncrs= block %d{%d}, dy: %3.3e, r: %d' % (i, dirn, dy, r) #Kicks and interfaces if dirn > 0 and i < d - 1: u = u[:, :r] v = np.dot(v[:, :r], np.diag(s[:r])) # kick radd = 0 rv = 1 if kickrank > 0: #Compute the function at residual indices curbl_y = np.zeros((ry[i] * n[i] * rz[i + 1], nx), dtype=dtype) curbl_z = np.zeros((rz[i] * n[i] * rz[i + 1], nx), dtype=dtype) for j in xrange(nx): #For kick cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) cr = np.dot(Rx[i, j], cr) cr = reshape(cr, (ry[i] * n[i], rx[i + 1, j])) cr = np.dot(cr, Rxz[i + 1, j]) curbl_y[:, j] = cr.flatten('F') #For z update cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) cr = np.dot(Rxz[i, j], cr) cr = reshape(cr, (rz[i] * n[i], rx[i + 1, j])) cr = np.dot(cr, Rxz[i + 1, j]) curbl_z[:, j] = cr.flatten('F') #Call the function zy = reshape(funs(curbl_y), (-1, d2)) zz = reshape(funs(curbl_z), (-1, d2)) #Assemble y at z indices (sic!) and subtract dzy = reshape(np.dot(u, v.T), (ry[i] * n[i] * ry[i + 1], d2)) dzy = reshape(dzy.T, (d2 * ry[i] * n[i], ry[i + 1])) #Cast dzy from core items to samples at right indices dzy = np.dot(dzy, Ryz[i + 1]) dzy = reshape(dzy, (d2, ry[i] * n[i] * rz[i + 1])) dzy = dzy.T #zy still requires casting from samples to core entities zy = reshape(zy, (ry[i], n[i] * rz[i + 1] * d2)) zy = np.linalg.solve(Ry[i], zy) zy = reshape(zy, (ry[i] * n[i] * rz[i + 1], d2)) zy = zy - dzy dzy = reshape(dzy, (ry[i], n[i] * rz[i + 1] * d2)) dzy = np.dot(Ryz[i], dzy) dzy = reshape( dzy, (rz[i] * n[i] * rz[i + 1], d2)) #Sample from both sizes zz = zz - dzy #Interpolate all remaining samples into core elements zy = reshape(zy.T, (d2 * ry[i] * n[i], rz[i + 1])) zy = np.linalg.solve(Rz[i + 1].T, zy.T).T zy = reshape(zy, (d2, ry[i] * n[i] * rz[i + 1])) zy = reshape(zy.T, (ry[i] * n[i], rz[i + 1] * d2)) #SVD to eliminate d2 and possibly overestimated rz zy, sz, vz = np.linalg.svd(zy, full_matrices=False) zy = zy[:, :min(kickrank, zy.shape[1])] # For z update zz = reshape(zz, (rz[i], n[i] * rz[i + 1] * d2)) zz = np.linalg.solve(Rz[i], zz) zz = reshape(zz, (rz[i] * n[i] * rz[i + 1], d2)) zz = reshape(zz.T, (d2 * rz[i] * n[i], rz[i + 1])) zz = np.linalg.solve(Rz[i + 1].T, zz.T).T zz = reshape(zz, (d2, rz[i] * n[i] * rz[i + 1])) zz = reshape(zz.T, (rz[i] * n[i], rz[i + 1] * d2)) zz, sz, vz = np.linalg.svd(zz, full_matrices=False) zz = zz[:, :min(kickrank, zz.shape[1])] #Second random kick rank zz = np.hstack((zz, np.random.randn(rz[i] * n[i], kickrank2))) u, rv = np.linalg.qr(np.hstack((u, zy))) radd = zy.shape[1] v = np.hstack((v, np.zeros((ry[i + 1] * d2, radd), dtype=dtype))) v = np.dot(rv, v.T) r = u.shape[1] cr2 = cry[i + 1] cr2 = reshape(cr2, (ry[i + 1], n[i + 1] * ry[i + 2])) v = reshape(v, (r * ry[i + 1], d2)) v = reshape(v.T, (d2 * r, ry[i + 1])) v = np.dot(v, cr2) ry[i + 1] = r u = reshape(u, (ry[i], n[i], r)) v = reshape(v, (d2, r, n[i + 1], ry[i + 2])) #Stuff back cry[i] = u cry[i + 1] = v # Update kick zz, rv = np.linalg.qr(zz) rz[i + 1] = zz.shape[1] z[i] = reshape(zz, (rz[i], n[i], rz[i + 1])) #z[i + 1] is recomputed from scratch we do not need it now #Compute left interface matrices #Interface matrix for Y Ry[i + 1] = np.dot(Ry[i], reshape(u, (ry[i], n[i] * ry[i + 1]))) Ry[i + 1] = reshape(Ry[i + 1], (ry[i] * n[i], ry[i + 1])) curind = maxvol(Ry[i + 1]) Ry[i + 1] = Ry[i + 1][curind, :] #Interface matrices for X for j in xrange(nx): Rx[i + 1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) Rx[i + 1, j] = np.dot(Rx[i, j], Rx[i + 1, j]) Rx[i + 1, j] = reshape(Rx[i + 1, j], (ry[i] * n[i], rx[i + 1, j])) Rx[i + 1, j] = Rx[i + 1, j][curind, :] #for kick Ryz[i + 1] = np.dot(Ryz[i], reshape(u, (ry[i], n[i] * ry[i + 1]))) Ryz[i + 1] = reshape(Ryz[i + 1], (rz[i] * n[i], ry[i + 1])) Rz[i + 1] = np.dot(Rz[i], reshape(zz, (rz[i], n[i] * rz[i + 1]))) Rz[i + 1] = reshape(Rz[i + 1], (rz[i] * n[i], rz[i + 1])) curind = maxvol(Rz[i + 1]) Ryz[i + 1] = Ryz[i + 1][curind, :] Rz[i + 1] = Rz[i + 1][curind, :] #Interface matrices for X for j in xrange(nx): Rxz[i + 1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) Rxz[i + 1, j] = np.dot(Rxz[i, j], Rxz[i + 1, j]) Rxz[i + 1, j] = reshape(Rxz[i + 1, j], (rz[i] * n[i], rx[i + 1, j])) Rxz[i + 1, j] = Rxz[i + 1, j][curind, :] elif dirn < 0 and i > 0: # Right to left u = np.dot(u[:, :r], np.diag(s[:r])) v = np.conj(v[:, :r]) #kick radd = 0 rv = 0 if kickrank > 0: #AMEN kick #Compute the function at residual indices curbl_y = np.zeros((rz[i] * n[i] * ry[i + 1], nx), dtype=dtype) curbl_z = np.zeros((rz[i] * n[i] * rz[i + 1], nx), dtype=dtype) for j in xrange(nx): cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) cr = np.dot(Rxz[i, j], cr) cr = reshape(cr, (rz[i] * n[i], rx[i + 1, j])) cr = np.dot(cr, Rx[i + 1, j]) curbl_y[:, j] = cr.flatten('F') #for z update cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) cr = np.dot(Rxz[i, j], cr) cr = reshape(cr, (rz[i] * n[i], rx[i + 1, j])) cr = np.dot(cr, Rxz[i + 1, j]) curbl_z[:, j] = cr.flatten('F') #Call the function zy = reshape(funs(curbl_y), (-1, d2)) zz = reshape(funs(curbl_z), (-1, d2)) #Assemble y at z indices (sic!) and subtract dzy = reshape(np.dot(u, v.T), (ry[i], n[i] * ry[i + 1] * d2)) dzy = np.dot(Ryz[i], dzy) dzy = reshape(dzy, (rz[i] * n[i] * ry[i + 1], d2)) # zy still requires casting from samples to core entries zy = zy.T zy = reshape(zy, (d2 * rz[i] * n[i], ry[i + 1])) zy = np.linalg.solve(Ry[i + 1].T, zy.T).T zy = reshape(zy, (d2, rz[i] * n[i] * ry[i + 1])) zy = zy.T zy = zy - dzy dzy = reshape(dzy.T, (d2 * rz[i] * n[i], ry[i + 1])) dzy = np.dot(dzy, Ryz[i + 1]) dzy = reshape(dzy, (d2, rz[i] * n[i] * rz[i + 1])) zz = zz - dzy.T # Cast sample indices to core elements # ...for kick zy = reshape(zy, (rz[i], n[i] * ry[i + 1] * d2)) zy = np.linalg.solve(Rz[i], zy) zy = reshape(zy, (rz[i] * n[i] * ry[i + 1], d2)) zy = zy.T zy = reshape(zy, (d2 * rz[i], n[i] * ry[i + 1])) zu, zs, zy = np.linalg.svd(zy, full_matrices=False) zy = zy[:min(kickrank, zy.shape[0]), :] zy = zy.T # ...for z update zz = reshape(zz, (rz[i], n[i] * rz[i + 1] * d2)) zz = np.linalg.solve(Rz[i], zz) zz = reshape(zz, (rz[i] * n[i] * rz[i + 1], d2)) zz = reshape(zz.T, (d2 * rz[i] * n[i], rz[i + 1])) zz = np.linalg.solve(Rz[i + 1].T, zz.T).T zz = reshape(zz, (d2 * rz[i], n[i] * rz[i + 1])) zu, zs, zz = np.linalg.svd(zz, full_matrices=False) zz = zz[:min(kickrank, zz.shape[0]), :] zz = zz.T zz = np.hstack((zz, np.random.randn(n[i] * rz[i + 1], kickrank2))) v, rv = np.linalg.qr(np.hstack((v, zy))) radd = zy.shape[1] u = np.hstack((u, np.zeros((d2 * ry[i], radd), dtype=dtype))) u = np.dot(u, rv.T) r = v.shape[1] cr2 = cry[i - 1] cr2 = reshape(cr2, (ry[i - 1] * n[i - 1], ry[i])) u = reshape(u, (d2, ry[i] * r)) u = reshape(u.T, (ry[i], r * d2)) u = np.dot(cr2, u) u = reshape(u, (ry[i - 1] * n[i - 1] * r, d2)) u = reshape(u.T, (d2, ry[i - 1], n[i - 1], r)) v = reshape(v.T, (r, n[i], ry[i + 1])) # Stuff back ry[i] = r cry[i - 1] = u cry[i] = v #kick zz, rv = np.linalg.qr(zz) rz[i] = zz.shape[1] zz = reshape(zz.T, (rz[i], n[i], rz[i + 1])) z[i] = zz #z[i - 1] is recomputed from scratch we do not need it # Recompute left interface matrices # Interface matrix for Y Ry[i] = np.dot(reshape(v, (ry[i] * n[i], ry[i + 1])), Ry[i + 1]) Ry[i] = reshape(Ry[i], (ry[i], n[i] * ry[i + 1])) curind = maxvol(Ry[i].T) Ry[i] = Ry[i][:, curind] # Interface matrices for X for j in xrange(nx): Rx[i, j] = reshape(crx[i, j], (rx[i, j] * n[i], rx[i + 1, j])) Rx[i, j] = np.dot(Rx[i, j], Rx[i + 1, j]) Rx[i, j] = reshape(Rx[i, j], (rx[i, j], n[i] * ry[i + 1])) Rx[i, j] = Rx[i, j][:, curind] # for kick Rz[i] = np.dot(reshape(zz, (rz[i] * n[i], rz[i + 1])), Rz[i + 1]) Rz[i] = reshape(Rz[i], (rz[i], n[i] * rz[i + 1])) Ryz[i] = np.dot(reshape(v, (ry[i] * n[i], ry[i + 1])), Ryz[i + 1]) Ryz[i] = reshape(Ryz[i], (ry[i], n[i] * rz[i + 1])) curind = maxvol(Rz[i].T) Ryz[i] = Ryz[i][:, curind] Rz[i] = Rz[i][:, curind] # Interface matrices for X for j in xrange(nx): Rxz[i, j] = reshape(crx[i, j], (rx[i, j] * n[i], rx[i + 1, j])) Rxz[i, j] = np.dot(Rxz[i, j], Rxz[i + 1, j]) Rxz[i, j] = reshape(Rxz[i, j], (rx[i, j], n[i] * rz[i + 1])) Rxz[i, j] = Rxz[i, j][:, curind] elif dirn > 0 and i == d - 1: #Just stuff back the last core newy = np.dot(u[:, :r], np.dot(np.diag(s[:r]), np.conj(v[:, :r].T))) newy = reshape(newy, (ry[i] * n[i] * ry[i + 1], d2)) cry[i] = reshape(newy.T, (d2, ry[i], n[i], ry[i + 1])) elif dirn < 0 and i is 0: newy = np.dot(u[:, :r], np.dot(np.diag(s[:r]), np.conj(v[:, :r].T))) newy = reshape(newy, (d2, ry[i], n[i], ry[i + 1])) cry[i] = newy i += dirn # Reversing, residue check, etc cur_order[order_index] = cur_order[order_index] - dirn # New direction if cur_order[order_index] == 0: order_index = order_index + 1 if verb > 0: print '=multifuncrs= sweep %d{%d}, max_dy: %3.3e, erank: %g' % (swp, order_index, max_dy, \ math.sqrt(np.dot(ry[:d], n * ry[1:]) / np.sum(n))) if max_dy < eps_exit: break if order_index >= len(cur_order): #New global sweep cur_order = copy.copy(block_order) order_index = 0 max_dy = 0 swp = swp + 1 dirn = int(math.copysign(1, cur_order[order_index])) i = i + dirn cry[d - 1] = np.transpose(cry[d - 1][:, :, :, 0], [1, 2, 0]) y = tt.tensor.from_list(cry) return y
def multifuncrs2(X, funs, eps = 1e-6, \ nswp = 10, \ rmax = 9999999, \ verb = 1, \ kickrank = 5, \ kickrank2 = 0, \ d2 = 1, \ eps_exit = None, \ y0 = None, \ do_qr = False, \ restart_it = 0): dtype = np.float64 if len(filter(lambda x: x.is_complex, X)) > 0: dtype = np.complex128 if eps_exit is None: eps_exit = eps nx = len(X) d = X[0].d n = X[0].n rx = np.transpose(np.array([ttx.r for ttx in X])) crx = np.empty((nx, d), dtype = np.object) i = 0 for ttx in X: v = tt.tensor.to_list(ttx) j = 0 for w in v: crx[i, j] = w j = j + 1 i = i+1 crx = crx.T wasrand = False if y0 is None: ry = d2 * np.ones((d + 1,), dtype=np.int32) ry[0] = 1 y = tt.rand(n, d, ry) wasrand = True else: #Initial guess available y = y0.copy() ry = y.r.copy() #Error vector z = tt.rand(n, d, kickrank) rz = z.r z = tt.tensor.to_list(z) ry = y.r cry = tt.tensor.to_list(y) #Interface matrices - for solution one_arr = np.ones((1, 1), dtype=dtype) Ry = np.zeros((d + 1, ), dtype=np.object) Ry[0] = one_arr Ry[d] = one_arr Rx = np.zeros((d+1, nx), dtype=np.object) Rx[0, :] = np.ones(nx, dtype=dtype) Rx[d, :] = np.ones(nx, dtype=dtype) Ryz = np.zeros((d + 1, ), dtype = np.object) Ryz[0] = one_arr Ryz[d] = one_arr Rz = np.zeros((d + 1, ), dtype = np.object) Rz[0] = one_arr Rz[d] = one_arr Rxz = np.zeros((d + 1, nx), dtype = np.object) Rxz[0, :] = np.ones(nx, dtype=dtype) Rxz[d, :] = np.ones(nx, dtype=dtype) block_order = [+d, -d] # orth for i in range(0, d-1): cr = cry[i].copy() cr = reshape(cr, (ry[i] * n[i], ry[i+1])) cr, rv = np.linalg.qr(cr) cr2 = cry[i+1].copy() cr2 = reshape(cr2, (ry[i+1], n[i+1] * ry[i+2])) cr2 = np.dot(rv, cr2) # matrix multiplication ry[i+1] = cr.shape[1] cr = reshape(cr, (ry[i], n[i], ry[i+1])) cry[i+1] = reshape(cr2, (ry[i+1], n[i+1], ry[i+2])) cry[i] = cr Ry[i+1] = np.dot(Ry[i], reshape(cr, (ry[i], n[i] * ry[i+1]))) Ry[i+1] = reshape(Ry[i+1], (ry[i] * n[i], ry[i+1])) curind = [] if wasrand: # EVERY DAY I'M SHUFFLIN' curind = np.random.permutation(n[i] * ry[i])[:ry[i+1]] else: curind = maxvol(Ry[i+1]) Ry[i+1] = Ry[i+1][curind, :] #Interface matrices for X for j in range(0, nx): Rx[i+1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i+1, j])) Rx[i+1, j] = np.dot(Rx[i, j], Rx[i+1, j]) Rx[i+1, j] = reshape(Rx[i+1, j], (ry[i] * n[i], rx[i+1, j])) Rx[i+1, j] = Rx[i+1, j][curind, :] #Error for kick crz = z[i] crz = reshape(crz, (rz[i] * n[i], rz[i+1])) crz, rv = np.linalg.qr(crz) cr2 = z[i+1] cr2 = reshape(cr2, (rz[i+1], n[i+1] * rz[i+2])) cr2 = np.dot(rv, cr2) rz[i+1] = crz.shape[1] crz = reshape(crz, (rz[i], n[i], rz[i+1])) z[i+1] = reshape(cr2, (rz[i+1], n[i+1], rz[i+2])) z[i] = crz #Interfaces for error Rz[i+1] = np.dot(Rz[i], reshape(crz, [rz[i], n[i] * rz[i+1]])) Rz[i+1] = reshape(Rz[i+1], [rz[i] * n[i], rz[i+1]]) Ryz[i+1] = np.dot(Ryz[i], reshape(cr, [ry[i], n[i] * ry[i+1]])) Ryz[i+1] = reshape(Ryz[i+1], [rz[i] * n[i], ry[i+1]]) #Pick random initial indices curind = np.random.permutation(n[i] * rz[i])[:rz[i+1]] Ryz[i+1] = Ryz[i+1][curind, :] Rz[i+1] = Rz[i+1][curind, :] #Interface matrices for X for j in range(0, nx): Rxz[i+1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i+1, j])) Rxz[i+1, j] = np.dot(Rxz[i, j], Rxz[i+1, j]) Rxz[i+1, j] = reshape(Rxz[i+1, j], (rz[i] * n[i], rx[i+1, j])) Rxz[i+1, j] = Rxz[i+1, j][curind, :] d2 = ry[d] ry[d] = 1 cry[d-1] = np.transpose(cry[d-1], [2, 0, 1]) # permute swp = 1 max_dy = 0.0 cur_order = copy.copy(block_order) order_index = 1 i = d-1 dirn = int(math.copysign(1, cur_order[order_index])) # can't use 'dir' identifier in python #DMRG sweeps while swp <= nswp or dirn > 0: oldy = reshape(cry[i].copy(), (d2 * ry[i] * n[i] * ry[i+1], )) #Compute X superblocks curbl = np.zeros((ry[i] * n[i] * ry[i+1], nx), dtype) for j in range(0, nx): cr = reshape(crx[i, j].copy(), (rx[i, j], n[i] * rx[i+1, j])) cr = np.dot(Rx[i, j], cr) cr = reshape(cr, (ry[i] * n[i], rx[i+1, j])) cr = np.dot(cr, Rx[i+1, j]) curbl[:, j] = cr.flatten('F') newy = funs(curbl) #multiply with inverted Ry newy = reshape(newy, (ry[i], n[i] * ry[i+1] * d2)) newy = np.linalg.solve(Ry[i], newy) # y = R \ y newy = reshape(newy, (ry[i] * n[i] * ry[i+1], d2)) newy = reshape(np.transpose(newy), (d2 * ry[i] * n[i], ry[i+1])) newy = np.transpose(np.linalg.solve(np.transpose(Ry[i+1]), np.transpose(newy))) # y=y/R newy = reshape(newy, (d2 * ry[i] * n[i] * ry[i+1],)) try: dy = np.linalg.norm(newy - oldy) / np.linalg.norm(newy) except ZeroDivisionError: print 'Bad initial indices, the solution is exactly zero. Restarting' return max_dy = max(max_dy, dy) # truncation if dirn > 0: # left-to-right newy = reshape(newy, (d2, ry[i] * n[i] * ry[i+1])) newy = reshape(np.transpose(newy), (ry[i] * n[i], ry[i+1] * d2)) else: newy = reshape(newy, (d2 * ry[i], n[i] * ry[i+1])) if kickrank >= 0: try: u, s, v = np.linalg.svd(newy, full_matrices = False) except: tmp = np.array(np.random.randn(newy.shape[1], newy.shape[1]), dtype=dtype) tmp, ru_tmp = np.linalg.qr(tmp) u, s, v = np.linalg.svd(np.dot(newy, tmp)) #u * s * v = A * tmp v = np.dot(v, np.conj(tmp).T) v = np.conj(np.transpose(v)) r = my_chop2(s, eps / math.sqrt(d) * np.linalg.norm(s)) else: if dirn > 0: u, v = np.linalg.qr(newy) v = np.conj(np.transpose(v)) r = u.shape[1] s = np.ones((r, )) else: v, u = np.linalg.qr(np.transpose(newy)) v = np.conj(v) u = np.transpose(u) r = u.shape[1] s = np.ones((r, )) if verb > 1: print '=multifuncrs2= block %d{%d}, dy: %3.3e, r: %d' % (i, dirn, dy, r) #Kicks and interfaces if dirn > 0 and i < d-1: u = u[:, :r] v = np.dot(v[:, :r], np.diag(s[:r])) # kick radd = 0 rv = 1 if kickrank > 0: #Compute the function at residual indices curbl_y = np.zeros((ry[i] * n[i] * rz[i+1], nx), dtype=dtype) curbl_z = np.zeros((rz[i] * n[i] * rz[i+1], nx), dtype=dtype) for j in xrange(nx): #For kick cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i+1, j])) cr = np.dot(Rx[i, j], cr) cr = reshape(cr, (ry[i] * n[i], rx[i+1, j])) cr = np.dot(cr, Rxz[i+1, j]) curbl_y[:, j] = cr.flatten('F') #For z update cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i+1, j])) cr = np.dot(Rxz[i, j], cr) cr = reshape(cr, (rz[i] * n[i], rx[i+1, j])) cr = np.dot(cr, Rxz[i+1, j]) curbl_z[:, j] = cr.flatten('F') #Call the function zy = reshape(funs(curbl_y), (-1, d2)) zz = reshape(funs(curbl_z), (-1, d2)) #Assemble y at z indices (sic!) and subtract dzy = reshape(np.dot(u, v.T), (ry[i] * n[i] * ry[i+1], d2)) dzy = reshape(dzy.T, (d2 * ry[i] * n[i], ry[i+1])) #Cast dzy from core items to samples at right indices dzy = np.dot(dzy, Ryz[i+1]) dzy = reshape(dzy, (d2, ry[i] * n[i] * rz[i+1])) dzy = dzy.T #zy still requires casting from samples to core entities zy = reshape(zy, (ry[i], n[i] * rz[i+1] * d2)) zy = np.linalg.solve(Ry[i], zy) zy = reshape(zy, (ry[i] * n[i] * rz[i+1], d2)) zy = zy - dzy dzy = reshape(dzy, (ry[i], n[i] * rz[i+1] * d2)) dzy = np.dot(Ryz[i], dzy) dzy = reshape(dzy, (rz[i] * n[i] * rz[i+1], d2)) #Sample from both sizes zz = zz - dzy #Interpolate all remaining samples into core elements zy = reshape(zy.T, (d2 * ry[i] * n[i], rz[i+1])) zy = np.linalg.solve(Rz[i+1].T, zy.T).T zy = reshape(zy, (d2, ry[i] * n[i] * rz[i+1])) zy = reshape(zy.T, (ry[i] * n[i], rz[i+1] * d2)) #SVD to eliminate d2 and possibly overestimated rz zy, sz, vz = np.linalg.svd(zy, full_matrices = False) zy = zy[:, :min(kickrank, zy.shape[1])] # For z update zz = reshape(zz, (rz[i], n[i] * rz[i+1] * d2)) zz = np.linalg.solve(Rz[i], zz) zz = reshape(zz, (rz[i] * n[i] * rz[i+1], d2)) zz = reshape(zz.T, (d2 * rz[i] * n[i], rz[i+1])) zz = np.linalg.solve(Rz[i+1].T, zz.T).T zz = reshape(zz, (d2, rz[i] * n[i] * rz[i+1])) zz = reshape(zz.T, (rz[i] * n[i], rz[i+1] * d2)) zz, sz, vz = np.linalg.svd(zz, full_matrices = False) zz = zz[:, :min(kickrank, zz.shape[1])] #Second random kick rank zz = np.hstack((zz, np.random.randn(rz[i] * n[i], kickrank2))) u, rv = np.linalg.qr(np.hstack((u, zy))) radd = zy.shape[1] v = np.hstack((v, np.zeros((ry[i+1] * d2, radd), dtype=dtype))) v = np.dot(rv, v.T) r = u.shape[1] cr2 = cry[i+1].copy() cr2 = reshape(cr2, (ry[i+1], n[i+1] * ry[i+2])) v = reshape(v, (r * ry[i+1], d2)) v = reshape(v.T, (d2 * r, ry[i+1])) v = np.dot(v, cr2) ry[i+1] = r u = reshape(u, (ry[i], n[i], r)) v = reshape(v, (d2, r, n[i+1], ry[i+2])) #Stuff back cry[i] = u cry[i+1] = v # Update kick zz, rv = np.linalg.qr(zz) rz[i+1] = zz.shape[1] z[i] = reshape(zz, (rz[i], n[i], rz[i+1])) #z[i+1] is recomputed from scratch we do not need it now #Compute left interface matrices #Interface matrix for Y Ry[i+1] = np.dot(Ry[i], reshape(u, (ry[i], n[i] * ry[i+1]))) Ry[i+1] = reshape(Ry[i+1], (ry[i] * n[i], ry[i+1])) curind = maxvol(Ry[i+1]) Ry[i+1] = Ry[i+1][curind, :] #Interface matrices for X for j in xrange(nx): Rx[i+1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i+1, j])) Rx[i+1, j] = np.dot(Rx[i, j], Rx[i+1, j]) Rx[i+1, j] = reshape(Rx[i+1, j], (ry[i] * n[i], rx[i+1, j])) Rx[i+1, j] = Rx[i+1, j][curind, :] #for kick Ryz[i+1] = np.dot(Ryz[i], reshape(u, (ry[i], n[i] * ry[i+1]))) Ryz[i+1] = reshape(Ryz[i+1], (rz[i] * n[i], ry[i+1])) Rz[i+1] = np.dot(Rz[i], reshape(zz, (rz[i], n[i] * rz[i+1]))) Rz[i+1] = reshape(Rz[i+1], (rz[i] * n[i], rz[i+1])) curind = maxvol(Rz[i+1]) Ryz[i+1] = Ryz[i+1][curind, :] Rz[i+1] = Rz[i+1][curind, :] #Interface matrices for X for j in xrange(nx): Rxz[i+1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i+1, j])) Rxz[i+1, j] = np.dot(Rxz[i, j], Rxz[i+1, j]) Rxz[i+1, j] = reshape(Rxz[i+1, j], (rz[i] * n[i], rx[i+1, j])) Rxz[i+1, j] = Rxz[i+1, j][curind, :] elif dirn < 0 and i > 0: # Right to left u = np.dot(u[:, :r], np.diag(s[:r])) v = np.conj(v[:, :r]) #kick radd = 0 rv = 0 if kickrank > 0: #AMEN kick #Compute the function at residual indices curbl_y = np.zeros((rz[i] * n[i] * ry[i+1], nx), dtype=dtype) curbl_z = np.zeros((rz[i] * n[i] * rz[i+1], nx), dtype=dtype) for j in xrange(nx): cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i+1, j])) cr = np.dot(Rxz[i, j], cr) cr = reshape(cr, (rz[i] * n[i], rx[i+1, j])) cr = np.dot(cr, Rx[i+1, j]) curbl_y[:, j] = cr.flatten('F') #for z update cr = reshape(crx[i, j], (rx[i, j], n[i] * rx[i+1, j])) cr = np.dot(Rxz[i, j], cr) cr = reshape(cr, (rz[i] * n[i], rx[i+1, j])) cr = np.dot(cr, Rxz[i+1, j]) curbl_z[:, j] = cr.flatten('F') #Call the function zy = reshape(funs(curbl_y), (-1, d2)) zz = reshape(funs(curbl_z), (-1, d2)) #Assemble y at z indices (sic!) and subtract dzy = reshape(np.dot(u, v.T), (ry[i], n[i] * ry[i+1] * d2)) dzy = np.dot(Ryz[i], dzy) dzy = reshape(dzy, (rz[i] * n[i] * ry[i+1], d2)) # zy still requires casting from samples to core entries zy = zy.T zy = reshape(zy, (d2 * rz[i] * n[i], ry[i+1])) zy = np.linalg.solve(Ry[i+1].T, zy.T).T zy = reshape(zy, (d2, rz[i] * n[i] * ry[i+1])) zy = zy.T zy = zy - dzy dzy = reshape(dzy.T, (d2 * rz[i] * n[i], ry[i+1])) dzy = np.dot(dzy, Ryz[i+1]) dzy = reshape(dzy, (d2, rz[i] * n[i] * rz[i+1])) zz = zz - dzy.T # Cast sample indices to core elements # ...for kick zy = reshape(zy, (rz[i], n[i] * ry[i+1] * d2)) zy = np.linalg.solve(Rz[i], zy) zy = reshape(zy, (rz[i] * n[i] * ry[i+1], d2)) zy = zy.T zy = reshape(zy, (d2 * rz[i], n[i] * ry[i+1])) zu, zs, zy = np.linalg.svd(zy, full_matrices = False) zy = zy[:min(kickrank, zy.shape[0]), :] zy = zy.T # ...for z update zz = reshape(zz, (rz[i], n[i] * rz[i+1] * d2)) zz = np.linalg.solve(Rz[i], zz) zz = reshape(zz, (rz[i] * n[i] * rz[i+1], d2)) zz = reshape(zz.T, (d2 * rz[i] * n[i], rz[i+1])) zz = np.linalg.solve(Rz[i+1].T, zz.T).T zz = reshape(zz, (d2 * rz[i], n[i] * rz[i+1])) zu, zs, zz = np.linalg.svd(zz, full_matrices = False) zz = zz[:min(kickrank, zz.shape[0]), :] zz = zz.T zz = np.hstack((zz, np.random.randn(n[i] * rz[i+1], kickrank2))) v, rv = np.linalg.qr(np.hstack((v, zy))) radd = zy.shape[1] u = np.hstack((u, np.zeros((d2 * ry[i], radd), dtype=dtype))) u = np.dot(u, rv.T) r = v.shape[1] cr2 = cry[i-1].copy() cr2 = reshape(cr2, (ry[i-1] * n[i-1], ry[i])) u = reshape(u, (d2, ry[i] * r)) u = reshape(u.T, (ry[i], r * d2)) u = np.dot(cr2, u) u = reshape(u, (ry[i-1] * n[i-1] * r, d2)) u = reshape(u.T, (d2, ry[i-1], n[i-1], r)) v = reshape(v.T, (r, n[i], ry[i+1])) # Stuff back ry[i] = r cry[i-1] = u cry[i] = v #kick zz, rv = np.linalg.qr(zz) rz[i] = zz.shape[1] zz = reshape(zz.T, (rz[i], n[i], rz[i+1])) z[i] = zz #z[i-1] is recomputed from scratch we do not need it # Recompute left interface matrices # Interface matrix for Y Ry[i] = np.dot(reshape(v, (ry[i] * n[i], ry[i+1])), Ry[i+1]) Ry[i] = reshape(Ry[i], (ry[i], n[i] * ry[i+1])) curind = maxvol(Ry[i].T) Ry[i] = Ry[i][:, curind] # Interface matrices for X for j in xrange(nx): Rx[i, j] = reshape(crx[i, j], (rx[i, j] * n[i], rx[i+1, j])) Rx[i, j] = np.dot(Rx[i, j], Rx[i+1, j]) Rx[i, j] = reshape(Rx[i, j], (rx[i, j], n[i] * ry[i+1])) Rx[i, j] = Rx[i, j][:, curind] # for kick Rz[i] = np.dot(reshape(zz, (rz[i] * n[i], rz[i+1])), Rz[i+1]) Rz[i] = reshape(Rz[i], (rz[i], n[i] * rz[i+1])) Ryz[i] = np.dot(reshape(v, (ry[i] * n[i], ry[i+1])), Ryz[i+1]) Ryz[i] = reshape(Ryz[i], (ry[i], n[i] * rz[i+1])) curind = maxvol(Rz[i].T) Ryz[i] = Ryz[i][:, curind] Rz[i] = Rz[i][:, curind] # Interface matrices for X for j in xrange(nx): Rxz[i, j] = reshape(crx[i, j], (rx[i, j] * n[i], rx[i+1, j])) Rxz[i, j] = np.dot(Rxz[i, j], Rxz[i+1, j]) Rxz[i, j] = reshape(Rxz[i, j], (rx[i, j], n[i] * rz[i+1])) Rxz[i, j] = Rxz[i, j][:, curind] elif dirn > 0 and i == d-1: #Just stuff back the last core newy = np.dot(u[:, :r], np.dot(np.diag(s[:r]), np.conj(v[:, :r].T))) newy = reshape(newy, (ry[i] * n[i] * ry[i+1], d2)) cry[i] = reshape(newy.T, (d2, ry[i], n[i], ry[i+1])) elif dirn < 0 and i == 0: newy = np.dot(u[:, :r], np.dot(np.diag(s[:r]), np.conj(v[:, :r].T))) newy = reshape(newy, (d2, ry[i], n[i], ry[i+1])) cry[i] = newy i += dirn # Reversing, residue check, etc cur_order[order_index] = cur_order[order_index] - dirn # New direction if cur_order[order_index] == 0: order_index = order_index + 1 if verb > 0: print '=multifuncrs= sweep %d{%d}, max_dy: %3.3e, erank: %g' % (swp, order_index, max_dy, \ math.sqrt(np.dot(ry[:d], n * ry[1:]) / np.sum(n))) if max_dy < eps_exit and dirn > 0: break if order_index >= len(cur_order): #New global sweep cur_order = copy.copy(block_order) order_index = 0 max_dy = 0 swp = swp + 1 dirn = int(math.copysign(1, cur_order[order_index])) i = i + dirn cry[d-1] = np.transpose(cry[d-1][:, :, :, 0], [1, 2, 0]) y = tt.tensor.from_list(cry) return y
def multifuncrs(X, funs, eps=1E-6, \ nswp=10, \ kickrank=5, \ y0=None, \ rmax=999999,#TODO:infinity \ kicktype='amr-two', \ pcatype='svd', \ trunctype='fro', \ d2=1, \ do_qr=False, \ verb=1): """Cross approximation of a (vector-)function of several TT-tensors. :param X: tuple of TT-tensors :param funs: multivariate function :param eps: accuracy """ dtype = np.float64 if len(filter(lambda x: x.is_complex, X)) > 0: dtype = np.complex128 y = y0 wasrand = False nx = len(X) d = X[0].d n = X[0].n rx = np.transpose(np.array([ttx.r for ttx in X])) #crx = [tt.tensor.to_list(ttx) for x in X] #crx = zip(*crx) crx = np.transpose(np.array([tt.tensor.to_list(ttx) for ttx in X], dtype=np.object)) crx = np.empty((nx, d), dtype = np.object) i = 0 for ttx in X: v = tt.tensor.to_list(ttx) j = 0 for w in v: crx[i, j] = w j = j + 1 i = i + 1 crx = crx.T if y is None: ry = d2 * np.ones((d + 1,), dtype=np.int32) ry[0] = 1 y = tt.rand(n, d, ry) wasrand = True ry = y.r cry = tt.tensor.to_list(y) Ry = np.zeros((d + 1, ), dtype=np.object) Ry[0] = np.array([[1.0]], dtype=dtype) Ry[d] = np.array([[1.0]], dtype=dtype) Rx = np.zeros((d+1, nx), dtype=np.object) Rx[0, :] = np.ones(nx, dtype=dtype) Rx[d, :] = np.ones(nx, dtype=dtype) block_order = [+d, -d] # orth for i in range(0, d - 1): cr = cry[i] cr = reshape(cr, (ry[i] * n[i], ry[i + 1])) cr, rv = np.linalg.qr(cr) cr2 = cry[i + 1] cr2 = reshape(cr2, (ry[i + 1], n[i + 1] * ry[i + 2])) cr2 = np.dot(rv, cr2) # matrix multiplication ry[i + 1] = cr.shape[1] cr = reshape(cr, (ry[i], n[i], ry[i + 1])) cry[i + 1] = reshape(cr2, (ry[i + 1], n[i + 1], ry[i + 2])) cry[i] = cr Ry[i + 1] = np.dot(Ry[i], reshape(cr, (ry[i], n[i] * ry[i + 1]))) Ry[i + 1] = reshape(Ry[i + 1], (ry[i] * n[i], ry[i + 1])) curind = [] if wasrand: # EVERY DAY I'M SHUFFLIN' curind = np.random.permutation(n[i] * ry[i])[:ry[i + 1]] else: curind = maxvol(Ry[i + 1]) Ry[i + 1] = Ry[i + 1][curind, :] for j in range(0, nx): try: Rx[i + 1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) except: pass Rx[i + 1, j] = np.dot(Rx[i, j], Rx[i + 1, j]) Rx[i + 1, j] = reshape(Rx[i + 1, j], (ry[i] * n[i], rx[i + 1, j])) Rx[i + 1, j] = Rx[i + 1, j][curind, :] d2 = ry[d] ry[d] = 1 cry[d - 1] = np.transpose(cry[d - 1], [2, 0, 1]) # permute last_sweep = False swp = 1 dy = np.zeros((d, )) max_dy = 0 cur_order = copy.copy(block_order) order_index = 1 i = d - 1 dirn = int(math.copysign(1, cur_order[order_index])) # can't use 'dir' identifier in python # DMRG sweeps while swp <= nswp or dirn > 0: oldy = reshape(cry[i], (d2 * ry[i] * n[i] * ry[i + 1],)) if not last_sweep: # compute the X superblocks curbl = np.zeros((ry[i] * n[i] * ry[i + 1], nx), dtype=dtype) for j in range(0, nx): cr = reshape(crx[i,j], (rx[i, j], n[i] * rx[i + 1, j])) cr = np.dot(Rx[i, j], cr) cr = reshape(cr, (ry[i] * n[i], rx[i + 1, j])) cr = np.dot(cr, Rx[i + 1, j]) curbl[:, j] = cr.flatten('F'); # call the function newy = funs(curbl) # multiply with inverted Ry newy = reshape(newy, (ry[i], n[i] * ry[i + 1] * d2)) newy = np.linalg.solve(Ry[i], newy) # y = R \ y newy = reshape(newy, (ry[i] * n[i] * ry[i + 1], d2)) newy = reshape(np.transpose(newy), (d2 * ry[i] * n[i], ry[i + 1])) newy = np.transpose(np.linalg.solve(np.transpose(Ry[i + 1]), np.transpose(newy))) # y=y/R newy = reshape(newy, (d2 * ry[i] * n[i] * ry[i + 1],)) else: newy = oldy dy[i] = np.linalg.norm(newy - oldy) / np.linalg.norm(newy) max_dy = max(max_dy, dy[i]) # truncation if dirn > 0: # left-to-right newy = reshape(newy, (d2, ry[i] * n[i] * ry[i + 1])) newy = reshape(np.transpose(newy), (ry[i] * n[i], ry[i + 1] * d2)) else: newy = reshape(newy, (d2 * ry[i], n[i] * ry[i + 1])) r = 0 # defines a variable in global scope if kickrank >= 0: u, s, v = np.linalg.svd(newy, full_matrices=False) v = np.conj(np.transpose(v)) if trunctype == "fro" or last_sweep: r = my_chop2(s, eps / math.sqrt(d) * np.linalg.norm(s)) else: # truncate taking into account the (r+1) overhead in the cross (T.S.: what?) cums = abs(s * np.arange(2, len(s) + 2)) ** 2 cums = np.cumsum(cums[::-1])[::-1] cums = cums / cums[0] ff = [i for i in range(len(cums)) if cums[i] < eps ** 2 / d] if len(ff) == 0: r = len(s) else: r = np.amin(ff) r = min(r, rmax, len(s)) else: if dirn > 0: u, v = np.linalg.qr(newy) v = np.conj(np.transpose(v)) r = u.shape[1] s = np.ones((r, )) else: v, u = np.linalg.qr(np.transpose(newy)) v = np.conj(v) u = np.transpose(u) r = u.shape[1] s = np.ones((r, )) if verb > 1: print '=multifuncrs= block %d{%d}, dy: %3.3e, r: %d' % (i, dirn, dy[i], r) # kicks and interfaces if dirn > 0 and i < d - 1: u = u[:, :r] v = np.dot(v[:, :r], np.diag(s[:r])) # kick radd = 0 rv = 1 if not last_sweep and kickrank > 0: uk = None if kicktype == 'amr-two': # AMR(two)-like kick. # compute the X superblocks ind2 = np.unique(np.random.randint(0, ry[i + 2] * n[i + 1], ry[i + 1])) #ind2 = np.unique(np.floor(np.random.rand(ry[i + 1]) * (ry[i + 2] * n[i + 1]))) rkick = len(ind2) curbl = np.zeros((ry[i] * n[i] * rkick, nx), dtype=dtype) for j in range(nx): cr1 = reshape(crx[i,j], (rx[i, j], n[i] * rx[i + 1, j])) cr1 = np.dot(Rx[i, j], cr1) cr1 = reshape(cr1, (ry[i] * n[i], rx[i + 1, j])) cr2 = reshape(crx[i + 1,j], (rx[i + 1, j] * n[i + 1], rx[i + 2, j])) cr2 = np.dot(cr2, Rx[i + 2, j]) cr2 = reshape(cr2, (rx[i + 1, j], n[i + 1] * ry[i + 2])) cr2 = cr2[:, ind2] curbl[:, j] = reshape(np.dot(cr1, cr2), (ry[i] * n[i] * rkick,)) # call the function uk = funs(curbl) uk = reshape(uk, (ry[i], n[i] * rkick * d2)) uk = np.linalg.solve(Ry[i], uk) uk = reshape(uk, (ry[i] * n[i], rkick * d2)) if pcatype == 'svd': uk, sk, vk = np.linalg.svd(uk, full_matrices=False) vk = np.conj(np.transpose(vk)) uk = uk[:, :min(kickrank, uk.shape[1])] else: # uk = uchol(np.transpose(uk), kickrank + 1) # TODO uk = uk[:, :max(uk.shape[1] - kickrank + 1, 1):-1] else: uk = np.random.rand(ry[i] * n[i], kickrank) u, rv = np.linalg.qr(np.concatenate((u, uk), axis=1)) radd = uk.shape[1] v = np.concatenate((v, np.zeros((ry[i + 1] * d2, radd), dtype=dtype)), axis=1) v = np.dot(rv, np.conj(np.transpose(v))) r = u.shape[1] cr2 = cry[i + 1] cr2 = reshape(cr2, (ry[i + 1], n[i + 1] * ry[i + 2])) v = reshape(v, (r * ry[i + 1], d2)) v = reshape(np.transpose(v), (d2 * r, ry[i + 1])) v = np.dot(v, cr2) ry[i + 1] = r u = reshape(u, (ry[i], n[i], r)) v = reshape(v, (d2, r, n[i + 1], ry[i + 2])) cry[i] = u cry[i + 1] = v Ry[i + 1] = np.dot(Ry[i], reshape(u, (ry[i], n[i] * ry[i + 1]))) Ry[i + 1] = reshape(Ry[i + 1], (ry[i] * n[i], ry[i + 1])) curind = maxvol(Ry[i + 1]) Ry[i + 1] = Ry[i + 1][curind, :] for j in range(nx): Rx[i + 1, j] = reshape(crx[i, j], (rx[i, j], n[i] * rx[i + 1, j])) Rx[i + 1, j] = np.dot(Rx[i, j], Rx[i + 1, j]) Rx[i + 1, j] = reshape(Rx[i + 1, j], (ry[i] * n[i], rx[i + 1, j])) Rx[i + 1, j] = Rx[i + 1, j][curind, :] elif dirn < 0 and i > 0: u = np.dot(u[:, :r], np.diag(s[:r])) v = np.conj(v[:, :r]) radd = 0 rv = 1 if not last_sweep and kickrank > 0: if kicktype == 'amr-two': # compute the X superblocks ind2 = np.unique(np.random.randint(0, ry[i - 1] * n[i - 1], ry[i])) rkick = len(ind2) curbl = np.zeros((rkick * n[i] * ry[i + 1], nx), dtype=dtype) for j in range(nx): cr1 = reshape(crx[i, j], (rx[i, j] * n[i], rx[i + 1, j])) cr1 = np.dot(cr1, Rx[i + 1, j]) cr1 = reshape(cr1, (rx[i, j], n[i] * ry[i + 1])) cr2 = reshape(crx[i - 1, j], (rx[i - 1, j], n[i - 1] * rx[i, j])) cr2 = np.dot(Rx[i - 1, j], cr2) cr2 = reshape(cr2, (ry[i - 1] * n[i - 1], rx[i, j])) cr2 = cr2[ind2, :] curbl[:, j] = reshape(np.dot(cr2, cr1), (rkick * n[i] * ry[i + 1],)) # calling the function uk = funs(curbl) uk = reshape(uk, (rkick * n[i] * ry[i + 1], d2)) uk = reshape(np.transpose(uk), (d2 * rkick * n[i], ry[i + 1])) uk = np.transpose(np.linalg.solve(np.transpose(Ry[i + 1]), np.transpose(uk))) uk = reshape(uk, (d2 * rkick, n[i] * ry[i + 1])) if pcatype == 'svd': vk, sk, uk = np.linalg.svd(uk, full_matrices=False) uk = np.conj(np.transpose(uk)) uk = uk[:, :min(kickrank, uk.shape[1])] # TODO: refactor else: # uk = uchol(uk, kickrank + 1) # TODO uk = uk[:, :max(uk.shape[1] - kickrank + 1, 1):-1] else: uk = np.random.rand(n[i] * ry[i + 1], kickrank) v, rv = np.linalg.qr(np.concatenate((v, uk), axis=1)) radd = uk.shape[1] u = np.concatenate((u, np.zeros((d2 * ry[i], radd), dtype=dtype)), axis=1) u = np.dot(u, np.transpose(rv)) r = v.shape[1] cr2 = cry[i - 1] cr2 = reshape(cr2, (ry[i - 1] * n[i - 1], ry[i])) u = reshape(u, (d2, ry[i] * r)) u = reshape(np.transpose(u), (ry[i], r * d2)) u = np.dot(cr2, u) u = reshape(u, (ry[i - 1] * n[i - 1] * r, d2)) u = reshape(np.transpose(u), (d2, ry[i - 1], n[i - 1], r)) v = reshape(np.transpose(v), (r, n[i], ry[i + 1])) ry[i] = r cry[i - 1] = u cry[i] = v Ry[i] = np.dot(reshape(v, (ry[i] * n[i], ry[i + 1])), Ry[i + 1]) Ry[i] = reshape(Ry[i], (ry[i], n[i] * ry[i + 1])) curind = maxvol(np.transpose(Ry[i])) Ry[i] = Ry[i][:, curind] for j in range(nx): Rx[i, j] = reshape(crx[i, j], (rx[i, j] * n[i], rx[i + 1, j])) Rx[i, j] = np.dot(Rx[i, j], Rx[i + 1, j]) Rx[i, j] = reshape(Rx[i, j], (rx[i, j], n[i] * ry[i + 1])) Rx[i, j] = Rx[i, j][:, curind] elif dirn > 0 and i == d - 1: newy = np.dot(np.dot(u[:, :r], np.diag(s[:r])), np.conj(np.transpose(v[:, :r]))) newy = reshape(newy, (ry[i] * n[i] * ry[i + 1], d2)) cry[i] = reshape(np.transpose(newy), (d2, ry[i], n[i], ry[i + 1])) elif dirn < 0 and i == 0: newy = np.dot(np.dot(u[:, :r], np.diag(s[:r])), np.conj(np.transpose(v[:, :r]))) newy = reshape(newy, (d2, ry[i], n[i], ry[i + 1])) cry[i] = newy i = i + dirn cur_order[order_index] = cur_order[order_index] - dirn if cur_order[order_index] == 0: order_index = order_index + 1 if verb > 0: print '=multifuncrs= sweep %d{%d}, max_dy: %3.3e, erank: %g' % (swp, order_index, max_dy, \ math.sqrt(np.dot(ry[:d], n * ry[1:]) / np.sum(n))) if last_sweep: break if max_dy < eps and dirn < 0: last_sweep = True kickrank = 0 if order_index >= len(cur_order): cur_order = copy.copy(block_order) order_index = 0 if last_sweep: cur_order = [d - 1] max_dy = 0 swp = swp + 1 dirn = int(math.copysign(1, cur_order[order_index])) i = i + dirn cry[d - 1] = np.transpose(cry[d - 1][:, :, :, 0], [1, 2, 0]) y = tt.tensor.from_list(cry) return y