def random_data_selection(Alist, C1ex, C2list, noo, nos): """Creates label data for the given solution C1ex Parameters ---------- Alist: list of xerus tensors Dictionary in CP format C1ex: xerus TTOperator Solution for which samples shall be constructed C2list: list of xerus tensors Selection operator in CP format noo: int number of dimensions nos: int number of samples Returns ------- Y: numpy array nos times noo matrix containing the labels for the given solution """ i1, i2, i3, i4, i5, i6, j1, j2, j3, j4, k1, k2, k3, k4 = xerus.indices(14) l = np.ones([nos, 1, noo]) r = np.ones([nos, 1, noo]) tmp1 = xerus.Tensor() for i in range(noo): t1 = C1ex.get_component(i) t2 = C2list[i] t3 = Alist[i] tmp1(i1, i2, i3, i4) << t3(k1, i2) * t1(i1, k1, k2, i4) * t2(k2, i3) tmp1np = tmp1.to_ndarray() l = np.einsum('mid,imdj->mjd', l, tmp1np) return np.einsum('mid,mid->dm', l, r)
def implicit_euler(A, x, stepSize, n): op = xe.TTOperator.identity(A.dimensions) - stepSize * A j, k = xe.indices(2) ourALS = xe.ALS_SPD ourALS.convergenceEpsilon = 1e-4 ourALS.numHalfSweeps = 100 results = [x] nextX = xe.TTTensor(x) for i in xrange(n): ourALS(op, nextX, x) # normalize norm = one_norm(nextX) nextX /= norm print("done itr", i, \ "residual:", xe.frob_norm(op(j/2,k/2)*nextX(k&0) - x(j&0)), \ "one-norm:", norm) x = xe.TTTensor(nextX) # ensure it is a copy results.append(x) return results
def implicit_euler(A, x, stepSize, n): op = xe.TTOperator.identity(A.dimensions) - stepSize*A j,k = xe.indices(2) ourALS = xe.ALS_SPD ourALS.convergenceEpsilon = 1e-4 ourALS.numHalfSweeps = 100 results = [x] nextX = xe.TTTensor(x) for i in xrange(n) : ourALS(op, nextX, x) # normalize norm = one_norm(nextX) nextX /= norm print("done itr", i, \ "residual:", xe.frob_norm(op(j/2,k/2)*nextX(k&0) - x(j&0)), \ "one-norm:", norm) x = xe.TTTensor(nextX) # ensure it is a copy results.append(x) return results
def eval_V(self, t, x): if type(t) == float or type(t) == np.float64: # print('t is float') V = self.V[self.t_to_ind(t)] add_fun_const = self.c_add_fun_list[self.t_to_ind(t)] else: # print('t is not float. t is', type(t)) V, add_fun_const = t if len(x.shape) == 1: ii, jj, kk = xe.indices(3) feat = self.P(x) temp = xe.Tensor([1]) comp = xe.Tensor() temp[0] = 1 for iter_1 in range(self.r): comp = V.get_component(iter_1) temp(kk) << temp(ii) * comp( ii, jj, kk) * xe.Tensor.from_buffer(feat[iter_1])(jj) return temp[0] + add_fun_const * self.add_fun(t, x) else: feat = self.P_batch(x) temp = np.ones(shape=(1, x.shape[1])) for iter_1 in range(x.shape[0]): comp = V.get_component(iter_1).to_ndarray() temp = np.einsum('il,ijk,jl->kl', temp, comp, feat[iter_1]) return temp[0] + add_fun_const * self.add_fun(0, x)
def adapt_ranks(self, U, S, Vt, smin): """ Add a new rank to S Parameters ---------- U: xe.Tensor left part of SVD S: xe.Tensor middle part of SVD, diagonal matrix Vt: xe.Tensor right part of SVD smin: float Threshold for smalles singluar values Returns ------- Unew: xe.Tensor left part of SVD with one rank increased Snew: xe.Tensor middle part of SVD, diagonal matrix with one rank increased Vtnew: xe.Tensor right part of SVD with one rank increased """ i1, i2, i3, i4, i5, i6, j1, j2, j3, j4, k1, k2, k3 = xe.indices(13) # print('adapt: U before', xe.frob_norm(U)) res = xe.Tensor() #S Snew = xe.Tensor([S.dimensions[0] + 1, S.dimensions[1] + 1]) Snew.offset_add(S, [0, 0]) Snew[S.dimensions[0], S.dimensions[1]] = 0.01 * smin #U onesU = xe.Tensor.ones([U.dimensions[0], U.dimensions[1]]) Unew = xe.Tensor( [U.dimensions[0], U.dimensions[1], U.dimensions[2] + 1]) Unew.offset_add(U, [0, 0, 0]) res(i1, i2) << U(i1, i2, k1) * U(j1, j2, k1) * onesU(j1, j2) onesU = onesU - res res(i1, i2) << U(i1, i2, k1) * U(j1, j2, k1) * onesU(j1, j2) onesU = onesU - res onesU.reinterpret_dimensions([U.dimensions[0], U.dimensions[1], 1]) if xe.frob_norm(onesU) != 0: onesU = onesU / xe.frob_norm(onesU) Unew.offset_add(onesU, [0, 0, U.dimensions[2]]) #Vt onesVt = xe.Tensor.ones([Vt.dimensions[1], Vt.dimensions[2]]) Vtnew = xe.Tensor( [Vt.dimensions[0] + 1, Vt.dimensions[1], Vt.dimensions[2]]) Vtnew.offset_add(Vt, [0, 0, 0]) res(i1, i2) << Vt(k1, i1, i2) * Vt(k1, j1, j2) * onesVt(j1, j2) onesVt = onesVt - res res(i1, i2) << Vt(k1, i1, i2) * Vt(k1, j1, j2) * onesVt(j1, j2) onesVt = onesVt - res onesVt.reinterpret_dimensions([1, Vt.dimensions[1], Vt.dimensions[2]]) if xe.frob_norm(onesVt) != 0: onesVt = onesVt / xe.frob_norm(onesVt) Vtnew.offset_add(onesVt, [Vt.dimensions[0], 0, 0]) return Unew, Snew, Vtnew
def contract_feat(self, T, feat_list): # y = proj @ x ii, jj, kk = xe.indices(3) # x_T = xe.Tensor.from_ndarray(y) comp = xe.Tensor() temp = xe.Tensor([1]) temp[0] = 1 r = T.order() for iter_1 in range(r): comp = T.get_component(iter_1) temp(kk) << temp(ii) * comp(ii, jj, kk) * xe.Tensor.from_ndarray( feat_list[iter_1])(jj) return temp[0]
def contract_feat_batch(self, T, feat_list): # y = proj @ x ii, jj, kk, ll = xe.indices(4) # x_T = xe.Tensor.from_ndarray(y) comp = xe.Tensor() temp = np.zeros([1, feat_list[0].shape[1]]) temp[0, :] = 1 r = T.order() for iter_1 in range(r): comp = T.get_component(iter_1).to_ndarray() # temp(kk, ll) << temp(ii, ll)*comp(ii, jj, kk)*xe.Tensor.from_ndarray(feat_list[iter_1])(jj,ll ) temp = np.einsum('il,ijk,jl->kl', temp, comp, feat_list[iter_1]) return temp[0, :]
def get_mean_concentration(x, i): k, l = xe.indices(2) result = xe.TensorNetwork(x) weights = xe.Tensor.from_function([MAX_NUM_PER_SITE], lambda idx: idx[0]) ones = xe.Tensor.ones([MAX_NUM_PER_SITE]) for j in xrange(x.degree()): if j == i: result(l & 0) << result(k, l & 1) * weights(k) else: result(l & 0) << result(k, l & 1) * ones(k) # at this point the degree of 'result' is 0, so there is only one entry return result[[]]
def push_right_stack(self, pos) : i1,i2,i3, j1,j2,j3, k1,k2 = xe.indices(8) Ai = self.A.get_component(pos) xi = self.x.get_component(pos) bi = self.b.get_component(pos) tmpA = xe.Tensor() tmpB = xe.Tensor() tmpA(j1, j2, j3) << xi(j1, k1, i1)*Ai(j2, k1, k2, i2)*xi(j3, k2, i3) \ * self.rightAStack[-1](i1, i2, i3) self.rightAStack.append(tmpA) tmpB(j1, j2) << xi(j1, k1, i1)*bi(j2, k1, i2) \ * self.rightBStack[-1](i1, i2) self.rightBStack.append(tmpB)
def get_mean_concentration(x, i): k,l = xe.indices(2) result = xe.TensorNetwork(x) weights = xe.Tensor.from_function([MAX_NUM_PER_SITE], lambda idx: idx[0]) ones = xe.Tensor.ones([MAX_NUM_PER_SITE]) for j in xrange(x.degree()) : if j == i : result(l&0) << result(k, l&1) * weights(k) else : result(l&0) << result(k, l&1) * ones(k) # at this point the degree of 'result' is 0, so there is only one entry return result[[]]
def solve(self) : # build right stack self.x.move_core(0, True) for pos in reversed(xrange(1, self.d)) : self.push_right_stack(pos) i1,i2,i3, j1,j2,j3, k1,k2 = xe.indices(8) residuals = [1000]*10 for itr in xrange(self.maxIterations) : residuals.append(self.calc_residual_norm()) if residuals[-1]/residuals[-10] > 0.99 : print("Done! Residual decreased from:", residuals[10], "to", residuals[-1], "in", len(residuals)-10, "sweeps") return print("Iteration:",itr, "Residual:", residuals[-1]) # sweep left -> right for pos in xrange(self.d): op = xe.Tensor() rhs = xe.Tensor() Ai = self.A.get_component(pos) bi = self.b.get_component(pos) op(i1, i2, i3, j1, j2, j3) << self.leftAStack[-1](i1, k1, j1)*Ai(k1, i2, j2, k2)*self.rightAStack[-1](i3, k2, j3) rhs(i1, i2, i3) << self.leftBStack[-1](i1, k1) * bi(k1, i2, k2) * self.rightBStack[-1](i3, k2) tmp = xe.Tensor() tmp(i1&0) << rhs(j1&0) / op(j1/2, i1/2) self.x.set_component(pos, tmp) if pos+1 < self.d : self.x.move_core(pos+1, True) self.push_left_stack(pos) self.rightAStack.pop() self.rightBStack.pop() # right -> left, only move core and update stack self.x.move_core(0, True) for pos in reversed(xrange(1,self.d)) : self.push_right_stack(pos) self.leftAStack.pop() self.leftBStack.pop()
def create_operator(degree): i, j, k, l = xe.indices(4) # create matrices M = create_M() S = create_S() L = create_L() Sstar = 0.7 * M + S I = xe.Tensor.identity([MAX_NUM_PER_SITE, MAX_NUM_PER_SITE]) # create empty TTOperator A = xe.TTOperator(2 * degree) # create first component comp = xe.Tensor() comp(i, j, k, l) << \ Sstar(j, k) * xe.Tensor.dirac([1, 3], 0)(i, l) \ + L(j, k) * xe.Tensor.dirac([1, 3], 1)(i, l) \ + I(j, k) * xe.Tensor.dirac([1, 3], 2)(i, l) A.set_component(0, comp) # create middle components comp(i, j, k, l) << \ I(j, k) * xe.Tensor.dirac([3, 3], [0, 0])(i, l) \ + M(j, k) * xe.Tensor.dirac([3, 3], [1, 0])(i, l) \ + S(j, k) * xe.Tensor.dirac([3, 3], [2, 0])(i, l) \ + L(j, k) * xe.Tensor.dirac([3, 3], [2, 1])(i, l) \ + I(j, k) * xe.Tensor.dirac([3, 3], [2, 2])(i, l) for c in xrange(1, degree - 1): A.set_component(c, comp) # create last component comp(i, j, k, l) << \ I(j, k) * xe.Tensor.dirac([3, 1], 0)(i, l) \ + M(j, k) * xe.Tensor.dirac([3, 1], 1)(i, l) \ + S(j, k) * xe.Tensor.dirac([3, 1], 2)(i, l) A.set_component(degree - 1, comp) return A
def create_operator(degree): i,j,k,l = xe.indices(4) # create matrices M = create_M() S = create_S() L = create_L() Sstar = 0.7*M + S; I = xe.Tensor.identity([MAX_NUM_PER_SITE, MAX_NUM_PER_SITE]) # create empty TTOperator A = xe.TTOperator(2*degree) # create first component comp = xe.Tensor() comp(i, j, k, l) << \ Sstar(j, k) * xe.Tensor.dirac([1, 3], 0)(i, l) \ + L(j, k) * xe.Tensor.dirac([1, 3], 1)(i, l) \ + I(j, k) * xe.Tensor.dirac([1, 3], 2)(i, l) A.set_component(0, comp) # create middle components comp(i, j, k, l) << \ I(j, k) * xe.Tensor.dirac([3, 3], [0, 0])(i, l) \ + M(j, k) * xe.Tensor.dirac([3, 3], [1, 0])(i, l) \ + S(j, k) * xe.Tensor.dirac([3, 3], [2, 0])(i, l) \ + L(j, k) * xe.Tensor.dirac([3, 3], [2, 1])(i, l) \ + I(j, k) * xe.Tensor.dirac([3, 3], [2, 2])(i, l) for c in xrange(1, degree-1) : A.set_component(c, comp) # create last component comp(i, j, k, l) << \ I(j, k) * xe.Tensor.dirac([3, 1], 0)(i, l) \ + M(j, k) * xe.Tensor.dirac([3, 1], 1)(i, l) \ + S(j, k) * xe.Tensor.dirac([3, 1], 2)(i, l) A.set_component(degree-1, comp) return A
def run_als(noo, nos, C1, C2list, Alist, C1ex, Y, max_iter, lam): """Perform the regularized ALS simulation Parameters ---------- noo: int number of dimension nos: int number of samples C1: xerus TTTensor iterate tensor C2list: list of xerus tensor selection tensor Alist: list of xerus tensor dictionary tensor C1ex: xerus TTTensor exact solution Y: xerus Tensor right hand side max_iter: int number of iterations lam: float regularization parameter Returns ------- errors: list of floats list of relative error after each sweep """ i1, i2, i3, i4, i5, i6, j1, j2, j3, j4, k1, k2, k3, k4 = xerus.indices(14) diff = C1ex - C1 tmp1 = xerus.Tensor() l = np.ones([noo, 1, 1, noo]) r = np.ones([noo, 1, 1, noo]) for i in range(noo): t1 = diff.get_component(i) t2 = C2list[i] tmp1(i1, i2, i3, j1, j2, j3) << t2(k1, i3) * t1(i1, k2, k1, j1) * t1( i2, k2, k3, j2) * t2(k3, j3) tmp1np = tmp1.to_ndarray() l = np.einsum('dije,ijdkle->dkle', l, tmp1np) lr = np.sqrt(np.einsum('ijkl,ijkl->', l, r)) / C1ex.frob_norm() errors = [lr] errors2 = [1] lams = [lam] # Initialize stacks rStack = [xerus.Tensor.ones([noo, 1, nos])] lStack = [xerus.Tensor.ones([noo, 1, nos])] for ind in range(noo - 1, 0, -1): C1_tmp = C1.get_component(ind) C2_tmp = C2list[ind] A_tmp = Alist[ind] C1_tmp(i1, i2, i3, i4) << C1_tmp(i1, k1, k2, i4) * A_tmp(k1, i2) * C2_tmp(k2, i3) rstacknp = rStack[-1].to_ndarray() C1_tmpnp = C1_tmp.to_ndarray() rstacknpres = np.einsum('imdj,djm->dim', C1_tmpnp, rstacknp) rStack.append(xerus.Tensor.from_ndarray(rstacknpres)) forward = True mem = -1 for it in range(0, max_iter): for pos in chain(range(0, noo), range(noo - 1, -1, -1)): if mem == pos: forward = not forward op = xerus.Tensor() rhs = xerus.Tensor() C2i = C2list[pos] Ai = Alist[pos] Ainp = Ai.to_ndarray() C2inp = C2i.to_ndarray() lStacknp = lStack[-1].to_ndarray() rStacknp = rStack[-1].to_ndarray() op_pre_np = np.einsum('dim,pm,sd,djm->ipsjmd', lStacknp, Ainp, C2inp, rStacknp) op_pre = xerus.Tensor.from_ndarray(op_pre_np) op(i1, i2, i3, i4, j1, j2, j3, j4) << op_pre( i1, i2, i3, i4, k1, k2) * op_pre(j1, j2, j3, j4, k1, k2) rhs(i1, i2, i3, i4) << op_pre(i1, i2, i3, i4, k1, k2) * Y(k2, k1) op += lam * xerus.Tensor.identity(op.dimensions) op_arr = op.to_ndarray() rhs_arr = rhs.to_ndarray() op_dim = op.dimensions op_arr_reshape = op_arr.reshape( (op_dim[0] * op_dim[1] * op_dim[2] * op_dim[3], op_dim[4] * op_dim[5] * op_dim[6] * op_dim[7])) rhs_dim = rhs.dimensions rhs_arr_reshape = rhs_arr.reshape( (rhs_dim[0] * rhs_dim[1] * rhs_dim[2] * rhs_dim[3])) sol_arr = np.linalg.solve(op_arr_reshape, rhs_arr_reshape) sol_arr_reshape = sol_arr.reshape( (op.dimensions[0], op.dimensions[1], op.dimensions[2], op.dimensions[3])) sol = xerus.Tensor.from_ndarray(sol_arr_reshape) C1.set_component(pos, sol) Ax = xerus.Tensor() Ax(i2, i1) << op_pre(j1, j2, j3, j4, i1, i2) * sol(j1, j2, j3, j4) error = (Ax - Y).frob_norm() / (Y.frob_norm()) error2 = C1.frob_norm() if forward and pos < noo - 1: C1.move_core(pos + 1, True) C1_tmp = C1.get_component(pos) rStack = rStack[:-1] C1_tmp( i1, i2, i3, i4) << C1_tmp(i1, k1, k2, i4) * Ai(k1, i2) * C2i(k2, i3) lstacknp = lStack[-1].to_ndarray() C1_tmpnp = C1_tmp.to_ndarray() lstacknpres = np.einsum('dim,imdj->djm', lstacknp, C1_tmpnp) lStack.append(xerus.Tensor.from_ndarray(lstacknpres)) if not forward and pos > 0: C1.move_core(pos - 1, True) C1_tmp = C1.get_component(pos) lStack = lStack[:-1] C1_tmp( i1, i2, i3, i4) << C1_tmp(i1, k1, k2, i4) * Ai(k1, i2) * C2i(k2, i3) rstacknp = rStack[-1].to_ndarray() C1_tmpnp = C1_tmp.to_ndarray() rstacknpres = np.einsum('imdj,djm->dim', C1_tmpnp, rstacknp) rStack.append(xerus.Tensor.from_ndarray(rstacknpres)) mem = pos #end of iteration #lam = lam/10 lam = np.max([np.min([0.1 * error / C1.frob_norm(), lam / 4]), 1e-14]) diff = C1ex - C1 tmp1 = xerus.Tensor() l = np.ones([noo, 1, 1, noo]) r = np.ones([noo, 1, 1, noo]) for i in range(noo): t1 = diff.get_component(i) t2 = C2list[i] tmp1(i1, i2, i3, j1, j2, j3) << t2(k1, i3) * t1( i1, k2, k1, j1) * t1(i2, k2, k3, j2) * t2(k3, j3) tmp1np = tmp1.to_ndarray() l = np.einsum('dije,ijdkle->dkle', l, tmp1np) lr = np.sqrt(np.einsum('ijkl,ijkl->', l, r)) / C1ex.frob_norm() print("Iteration " + str(it) + ' Error: ' + str(lr) + " Residual: " + str(error) + " Norm: " + str(C1.frob_norm()) + " Lambda: " + str(lam)) errors.append(lr) errors2.append(error) lams.append(lam) return errors
def update_components_np(self, G, w, mat_list, rew_MC, n_sweep, P_constraints_vec, smin, omega, kminor, adapt, maxranks, add_fun_list, current_fun_c): noo = G.order() Smu_left, Gamma, Smu_right, Theta, U_left, U_right, Vt_left, Vt_right = ( xe.Tensor() for i in range(8)) p = mat_list[0].shape[0] i1, i2, i3, i4, i5, i6, j1, j2, j3, j4, k1, k2, k3 = xe.indices(13) constraints_constant = 0 num_constraints = P_constraints_vec[0].shape[1] d = G.order() # building Stacks for operators lStack_x = [np.ones(shape=[1, rew_MC.size])] rStack_x = [np.ones(shape=[1, rew_MC.size])] G0_lStack = [np.ones(shape=(1, num_constraints))] G0_rStack = [np.ones(shape=(1, num_constraints))] if G.order() > 1: G.move_core(1) G.move_core(0) for i0 in range(d - 1, 0, -1): G_tmp = G.get_component(i0).to_ndarray() A_tmp_x = mat_list[i0] rStack_xnp = rStack_x[-1] G_tmp_np_x = np.tensordot(G_tmp, A_tmp_x, axes=((1), (0))) rStack_xnpres = np.einsum('jkm,km->jm', G_tmp_np_x, rStack_xnp) rStack_x.append(rStack_xnpres) rStack_G0_tmp = G0_rStack[-1] G0_tmp_np = np.tensordot(G_tmp, P_constraints_vec[i0], axes=((1), (0))) G0_tmp = np.einsum('jkm,km->jm', G0_tmp_np, rStack_G0_tmp) # G0_tmp = np.einsum('ijk,jl,kl->il',G_tmp, P_constraints_vec[i0], rStack_G0_tmp) G0_rStack.append(G0_tmp) #loop over each component from left to right for i0 in range(0, d): # get singular values and orthogonalize wrt the next core mu if i0 > 0: # get left and middle component Gmu_left = G.get_component(i0 - 1) Gmu_middle = G.get_component(i0) (U_left(i1, i2, k1), Smu_left(k1, k2), Vt_left( k2, i3)) << xe.SVD(Gmu_left(i1, i2, i3)) Gmu_middle(i1, i2, i3) << Vt_left(i1, k2) * Gmu_middle(k2, i2, i3) if G.ranks()[i0-1] < maxranks[i0-1] and adapt \ and Smu_left[int(np.max([Smu_left.dimensions[0] - kminor,0])),int(np.max([int(Smu_left.dimensions[1] - kminor),0]))] > smin: U_left, Smu_left, Gmu_middle = self.adapt_ranks( U_left, Smu_left, Gmu_middle, smin) sing = [Smu_left[i, i] for i in range(Smu_left.dimensions[0])] # print('left', 'smin', smin, 'sing', sing) Gmu_middle(i1, i2, i3) << Smu_left(i1, k1) * Gmu_middle(k1, i2, i3) G.set_component(i0 - 1, U_left) G.set_component(i0, Gmu_middle) Gamma = np.zeros(Smu_left.dimensions ) # build cut-off sing value matrix Gamma for j in range(Smu_left.dimensions[0]): Gamma[j, j] = 1 / np.max([smin, Smu_left[j, j]]) # print('Gamma', Gamma) if i0 < d - 1: # get middle and rightcomponent Gmu_middle = G.get_component(i0) Gmu_right = G.get_component(i0 + 1) (U_right(i1, i2, k1), Smu_right(k1, k2), Vt_right( k2, i3)) << xe.SVD(Gmu_middle(i1, i2, i3)) sing = [ Smu_right[i, i] for i in range(Smu_right.dimensions[0]) ] # print('right', 'smin', smin, 'sing', sing) Gmu_right(i1, i2, i3) << Vt_right(i1, k1) * Gmu_right(k1, i2, i3) #if mu == d-2 and G.ranks()[mu] < maxranks[mu] and adapt and Smu_right[Smu_right.dimensions[0] - kminor,Smu_right.dimensions[1] - kminor] > smin: # U_right, Smu_right, Gmu_right = adapt_ranks(U_right, Smu_right, Gmu_right,smin) Gmu_middle(i1, i2, i3) << U_right(i1, i2, k1) * Smu_right(k1, i3) # G.set_component(i0, Gmu_middle) # G.set_component(i0+1, Gmu_right) Theta = np.zeros([G.ranks()[i0], G.ranks()[i0] ]) # build cut-off sing value matrix Theta # Theta = np.zeros([Gmu_middle.dimensions[2],Gmu_middle.dimensions[2]]) # build cut-off sing value matrix Theta for j in range(Theta.shape[0]): if j >= Smu_right.dimensions[0]: sing_val = 0 else: singval = Smu_right[j, j] Theta[j, j] = 1 / np.max([smin, singval]) # update Stacks if i0 > 0: G_tmp = G.get_component(i0 - 1).to_ndarray() A_tmp_x = mat_list[i0 - 1] # G_tmp_np = np.einsum('ijk,jl->ikl', G_tmp, A_tmp_x) G_tmp_np_x = np.tensordot(G_tmp, A_tmp_x, axes=((1), (0))) lStack_xnp = lStack_x[-1] lStack_xnpres = np.einsum('jm,jkm->km', lStack_xnp, G_tmp_np_x) lStack_x.append(lStack_xnpres) del rStack_x[-1] G0_lStack_tmp = G0_lStack[-1] G0_tmp_np = np.tensordot(G_tmp, P_constraints_vec[i0 - 1], axes=((1), (0))) G0_tmp = np.einsum('jm,jkm->km', G0_lStack_tmp, G0_tmp_np) # G0_tmp = np.einsum('il,ijk,jl->kl',G0_lStack_tmp, G_tmp, P_constraints_vec[i0-1]) G0_lStack.append(G0_tmp) del G0_rStack[-1] Ai_x = mat_list[i0] lStack_xnp = lStack_x[-1] rStack_xnp = rStack_x[-1] op_pre = np.einsum('il,jl,kl->ijkl', lStack_xnp, Ai_x, rStack_xnp) # op = np.einsum('ijkl,mnol->ijkmno', op_pre, op_pre) op_G0 = np.einsum('il,jl,kl->ijkl', G0_lStack[-1], P_constraints_vec[i0], G0_rStack[-1]) op = np.zeros(op_pre.shape[:-1] + op_pre.shape[:-1]) op_dim = op.shape Gi = G.get_component(i0) id_reg_p = np.eye(p) if i0 > 0: id_reg_r = np.eye(Gi.dimensions[2]) # op_reg(i1,i2,i3,j1,j2,j3) << Gamma(i1,k1) * Gamma(k1,j1) * id_reg_r(i3,j3) * id_reg_p(i2,j2) op_reg = np.einsum('ij,jk,lm,no->inlkom', Gamma, Gamma, id_reg_r, id_reg_p) # print('op_reg', op_reg) op += w * w * op_reg # input() if i0 < d - 1: id_reg_l = np.eye(Gi.dimensions[0]) # op_reg(i1,i2,i3,j1,j2,j3) << Theta(i3,k1) * Theta(k1,j3) * id_reg_l(i1,j1) * id_reg_p(i2,j2) op_reg = np.einsum('ij,jk,lm,no->lnimok', Theta, Theta, id_reg_l, id_reg_p) op += w * w * op_reg op = op.reshape((op_dim[0] * op_dim[1] * op_dim[2], op_dim[3] * op_dim[4] * op_dim[5])) op = np.vstack([op, np.zeros(op.shape[0])[None, :]]) op = np.hstack([op, np.zeros(op.shape[0])[:, None]]) rhs_dim = op_pre.shape[:-1] op_pre = op_pre.reshape(op_dim[0] * op_dim[1] * op_dim[2], op_pre.shape[-1]) op_pre = np.concatenate([op_pre, add_fun_list[None, :]], axis=0) op += np.tensordot(op_pre, op_pre, axes=((1), (1))) # op += 2*rew_MC.size*constraints_constant*np.tensordot(op_G0, op_G0, axes=((3),(3))) # rhs = np.einsum('ijkl,l->ijk', op_pre, rew_MC) rhs = np.tensordot(op_pre, rew_MC, axes=((1), (0))) if (n_sweep == 1 and i0 == 0): comp = G.get_component(i0).to_ndarray() Ax = np.tensordot(op_pre[:-1, :].reshape(comp.shape + (rew_MC.size, )), comp, axes=([0, 1, 2], [0, 1, 2])) curr_const = np.einsum('il,jl,kl,ijk ->l', G0_lStack[-1], P_constraints_vec[i0], G0_rStack[-1], comp) w = min( np.linalg.norm(Ax + current_fun_c * add_fun_list - rew_MC) **2 / rew_MC.size + constraints_constant * np.linalg.norm(curr_const)**2, 10000) # print('first_res', w, np.linalg.norm(Ax - rew_MC)**2/rew_MC.size, constraints_constant*np.linalg.norm(curr_const)**2) op += 1e-4 * np.eye(op.shape[0]) rhs_reshape = rhs # rhs_reshape = rhs.reshape((rhs_dim[0] * rhs_dim[1] * rhs_dim[2])) sol_arr = np.linalg.solve(op, rhs_reshape) current_fun_c = sol_arr[-1] sol_arr = sol_arr[:-1] sol_arr_reshape = sol_arr.reshape( (rhs_dim[0], rhs_dim[1], rhs_dim[2])) sol = xe.Tensor.from_buffer(sol_arr_reshape) G.set_component(i0, sol) # calculate residuum # Ax = np.einsum('jkli,jkl->i', op_pre, sol_arr_reshape) # print(i0) comp = G.get_component(d - 1).to_ndarray() Ax = np.tensordot(op_pre[:-1, :].reshape(comp.shape + (rew_MC.size, )), comp, axes=([0, 1, 2], [0, 1, 2])) curr_const = np.einsum('il,jl,kl,ijk ->l', G0_lStack[-1], P_constraints_vec[d - 1], G0_rStack[-1], sol_arr_reshape) # print(curr_const) error1 = np.linalg.norm(Ax + current_fun_c * add_fun_list - rew_MC)**2 / rew_MC.size error2 = constraints_constant * np.linalg.norm(curr_const)**2 # print('after', error1, error2) return w, error1 + error2, current_fun_c
def calc_residual_norm(self) : i,j = xe.indices(2) return xe.frob_norm(self.A(i/2, j/2)*self.x(j&0) - self.b(i&0)) / self.solutionsNorm
def calc_grad(self, t, x): V = self.V[self.t_to_ind(t)] # print('t, self.t_to_ind(t)', t, self.t_to_ind(t),'frob_norm(v)', xe.frob_norm(V)) if len(x.shape) == 1: c1, c2, c3 = xe.indices(3) feat = self.P(x) dfeat = self.dP(x) dV = np.zeros(shape=self.r) temp = xe.Tensor([1]) comp = xe.Tensor() temp_right = xe.Tensor.ones([1]) temp_left = xe.Tensor.ones([1]) list_right = [None] * (self.r) list_right[self.r - 1] = xe.Tensor(temp_right) for iter_0 in range(self.r - 1, 0, -1): comp = V.get_component(iter_0) temp_right(c1) << temp_right(c3) * comp( c1, c2, c3) * xe.Tensor.from_buffer(feat[iter_0])(c2) # temp_right = xe.contract(comp, False, temp_right, False, 1) # temp_right = xe.contract(temp_right, False, xe.Tensor.from_buffer(feat[iter_0]), False, 1) list_right[iter_0 - 1] = xe.Tensor(temp_right) for iter_0 in range(self.r): comp = V.get_component(iter_0) temp() << temp_left(c1) * comp( c1, c2, c3) * xe.Tensor.from_buffer( dfeat[iter_0])(c2) * list_right[iter_0](c3) # temp = xe.contract(comp, False, list_right[iter_0], False, 1) # temp = xe.contract(temp, False, xe.Tensor.from_buffer(dfeat[iter_0]), False, 1) # temp = xe.contract(temp, False, temp_left, False, 1) temp_left(c3) << temp_left(c1) * comp( c1, c2, c3) * xe.Tensor.from_buffer(feat[iter_0])(c2) # temp_left = xe.contract(temp_left, False, comp, False, 1) # temp_left = xe.contract(xe.Tensor.from_buffer(feat[iter_0]), False, temp_left, False, 1) dV[iter_0] = temp[0] return dV + self.grad_add_fun(t, x) else: nos = x.shape[1] feat = self.P_batch(x) dfeat = self.dP_batch(x) dV_mat = np.zeros(shape=x.shape) temp = np.zeros(1) temp_right = np.ones(shape=(1, nos)) temp_left = np.ones(shape=(1, nos)) list_right = [None] * (self.r) list_right[self.r - 1] = temp_right for iter_0 in range(self.r - 1, 0, -1): comp = V.get_component(iter_0).to_ndarray() # temp_right(c1) << temp_right(c3) * comp(c1, c2, c3) * feat[iter_0](c2) list_right[iter_0 - 1] = np.einsum('kl,ijk,jl->il', list_right[iter_0], comp, feat[iter_0]) for iter_0 in range(self.r): comp = V.get_component(iter_0).to_ndarray() # temp() << temp_left(c1) * comp(c1, c2, c3) * dfeat[iter_0](c2) \ # * list_right[iter_0](c3) temp = np.einsum('il,ijk,jl,kl->l', temp_left, comp, dfeat[iter_0], list_right[iter_0]) # temp(c3) << temp_left(c1) * comp(c1, c2, c3) * feat[iter_0](c2) temp_left = np.einsum('il,ijk,jl->kl', temp_left, comp, feat[iter_0]) dV_mat[iter_0, :] = temp # _u = -gamma/lambd*np.dot(dV, B) - shift_TT return dV_mat + self.grad_add_fun(t, x)
def calc_laplace(self, t, x): if type(t) == float or type(t) == np.float64 or type(t) == int: # print('t is float') V = self.V[self.t_to_ind(t)] add_fun_const = self.c_add_fun_list[self.t_to_ind(t)] else: # print('t is not float. t is', type(t)) V, add_fun_const = t V = t # print('V in calc_grad', xe.Tensor(V)) # print('t, self.t_to_ind(t)', t, self.t_to_ind(t),'frob_norm(v)', xe.frob_norm(V)) if len(x.shape) == 1: c1, c2, c3 = xe.indices(3) feat = self.P(x) dfeat = self.ddP(x) dV = 0 temp = xe.Tensor([1]) comp = xe.Tensor() temp_right = xe.Tensor.ones([1]) temp_left = xe.Tensor.ones([1]) list_right = [None] * (self.r) list_right[self.r - 1] = xe.Tensor(temp_right) for iter_0 in range(self.r - 1, 0, -1): comp = V.get_component(iter_0) temp_right(c1) << temp_right(c3) * comp( c1, c2, c3) * xe.Tensor.from_buffer(feat[iter_0])(c2) # temp_right = xe.contract(comp, False, temp_right, False, 1) # temp_right = xe.contract(temp_right, False, xe.Tensor.from_buffer(feat[iter_0]), False, 1) list_right[iter_0 - 1] = xe.Tensor(temp_right) for iter_0 in range(self.r): comp = V.get_component(iter_0) temp() << temp_left(c1) * comp( c1, c2, c3) * xe.Tensor.from_buffer( dfeat[iter_0])(c2) * list_right[iter_0](c3) # temp = xe.contract(comp, False, list_right[iter_0], False, 1) # temp = xe.contract(temp, False, xe.Tensor.from_buffer(dfeat[iter_0]), False, 1) # temp = xe.contract(temp, False, temp_left, False, 1) temp_left(c3) << temp_left(c1) * comp( c1, c2, c3) * xe.Tensor.from_buffer(feat[iter_0])(c2) # temp_left = xe.contract(temp_left, False, comp, False, 1) # temp_left = xe.contract(xe.Tensor.from_buffer(feat[iter_0]), False, temp_left, False, 1) dV += temp[0] return dV + add_fun_const * self.laplacian_add_fun(t, x) else: nos = x.shape[1] feat = self.P_batch(x) dfeat = self.ddP_batch(x) dV_mat = np.zeros(shape=x.shape[-1]) temp = np.zeros(1) temp_right = np.ones(shape=(1, nos)) temp_left = np.ones(shape=(1, nos)) list_right = [None] * (self.r) list_right[self.r - 1] = temp_right for iter_0 in range(self.r - 1, 0, -1): comp = V.get_component(iter_0).to_ndarray() # temp_right(c1) << temp_right(c3) * comp(c1, c2, c3) * feat[iter_0](c2) list_right[iter_0 - 1] = np.einsum('kl,ijk,jl->il', list_right[iter_0], comp, feat[iter_0]) for iter_0 in range(self.r): comp = V.get_component(iter_0).to_ndarray() # temp() << temp_left(c1) * comp(c1, c2, c3) * dfeat[iter_0](c2) \ # * list_right[iter_0](c3) temp = np.einsum('il,ijk,jl,kl->l', temp_left, comp, dfeat[iter_0], list_right[iter_0]) # temp(c3) << temp_left(c1) * comp(c1, c2, c3) * feat[iter_0](c2) temp_left = np.einsum('il,ijk,jl->kl', temp_left, comp, feat[iter_0]) dV_mat += temp # _u = -gamma/lambd*np.dot(dV, B) - shift_TT return dV_mat + add_fun_const * self.laplacian_add_fun(t, x)
ttA = xe.TTOperator(A) # and verify its rank print("ttA ranks:", ttA.ranks()) # the right hand side of the equation both as Tensor and in (Q)TT format b = xe.Tensor.ones([2,]*9) ttb = xe.TTTensor.ones(b.dimensions) # construct a random initial guess of rank 3 for the ALS algorithm ttx = xe.TTTensor.random([2,]*9, [3,]*8) # and solve the system with the default ALS algorithm for symmetric positive operators xe.ALS_SPD(ttA, ttx, ttb) # to perform arithmetic operations we need to define some indices i,j,k = xe.indices(3) # calculate the residual of the just solved system to evaluate its accuracy # here i^9 denotes a multiindex named i of dimension 9 (ie. spanning 9 indices of the respective tensors) residual = xe.frob_norm( ttA(i^9,j^9)*ttx(j^9) - ttb(i^9) ) print("residual:", residual) # as an comparison solve the system exactly using the Tensor / operator x = xe.Tensor() x(j^9) << b(i^9) / A(i^9, j^9) # and calculate the Frobenius norm of the difference print("error:", xe.frob_norm(x - xe.Tensor(ttx)))
def update_components_salsa(G, noo, d, Alist, nos, Y, smin, w, kminor, adapt, mR, maxranks): """Perform one SALSA sweep Parameters ---------- G: xerus TTTensor iterate tensor noo: int number of dimension d: int number of dimension plus 1 Alist: list of xerus tensor dictionary tensor nos: int number of samples Y: xerus Tensor right hand side smin: float SALSA parameter smin w: float SALSA parameter omega kminor: int SALSA parameter number of additional ranks used in each simulation adapt: bool if adaption should be used if necessary mR: list of int list of maximal ranks overall maxranks: int maximal rank alowed Returns ------- error: float Residuum of iterate """ p = Alist[0].dimensions[0] Smu_left, Gamma, Smu_right, Theta, U_left, U_right, Vt_left, Vt_right = ( xerus.Tensor() for i in range(8)) i1, i2, i3, i4, i5, i6, j1, j2, j3, j4, k1, k2, k3 = xerus.indices(13) tmp = xerus.Tensor() # building Stacks for operators lStack = [xerus.Tensor.ones([1, nos])] rStack = [xerus.Tensor.ones([1, nos])] G_tmp = G.get_component(noo) tmp(i1, i2, i3) << G_tmp(i1, i3, k1) * rStack[-1](k1, i2) rStack.append(tmp) for ind in range(d - 2, 0, -1): G_tmp = G.get_component(ind) A_tmp = Alist[ind] G_tmp(i1, i2, i3) << G_tmp(i1, k1, i3) * A_tmp(k1, i2) rstacknp = rStack[-1].to_ndarray() G_tmpnp = G_tmp.to_ndarray() rstacknpres = np.einsum('jmk,kms->jms', G_tmpnp, rstacknp) rStack.append(xerus.Tensor.from_ndarray(rstacknpres)) #loop over each component from left to right for mu in range(0, d): # get singular values and orthogonalize wrt the next core mu if mu > 0: # get left and middle component Gmu_left = G.get_component(mu - 1) Gmu_middle = G.get_component(mu) (U_left(i1, i2, k1), Smu_left(k1, k2), Vt_left( k2, i3)) << xerus.SVD(Gmu_left(i1, i2, i3)) Gmu_middle(i1, i2, i3) << Vt_left(i1, k2) * Gmu_middle(k2, i2, i3) #for j in range(kmin): if G.ranks()[mu-1] < np.min([maxranks[mu-1],mR]) and adapt \ and Smu_left[int(np.max([Smu_left.dimensions[0] - kminor,0])),int(np.max([int(Smu_left.dimensions[1] - kminor),0]))] > smin: U_left, Smu_left, Gmu_middle = adapt_ranks( U_left, Smu_left, Gmu_middle, smin) sing = [Smu_left[i, i] for i in range(Smu_left.dimensions[0])] Gmu_middle(i1, i2, i3) << Smu_left(i1, k1) * Gmu_middle(k1, i2, i3) G.set_component(mu - 1, U_left) G.set_component(mu, Gmu_middle) Gamma = xerus.Tensor( Smu_left.dimensions) # build cut-off sing value matrix Gamma for j in range(Smu_left.dimensions[0]): Gamma[j, j] = 1 / np.max([smin, Smu_left[j, j]]) if mu < d - 1: # get middle and rightcomponent Gmu_middle = G.get_component(mu) Gmu_right = G.get_component(mu + 1) (U_right(i1, i2, k1), Smu_right(k1, k2), Vt_right( k2, i3)) << xerus.SVD(Gmu_middle(i1, i2, i3)) sing = [Smu_right[i, i] for i in range(Smu_right.dimensions[0])] Gmu_right(i1, i2, i3) << Vt_right(i1, k1) * Gmu_right(k1, i2, i3) #if mu == d-2 and G.ranks()[mu] < maxranks[mu] and adapt and Smu_right[Smu_right.dimensions[0] - kminor,Smu_right.dimensions[1] - kminor] > smin: # U_right, Smu_right, Gmu_right = adapt_ranks(U_right, Smu_right, Gmu_right,smin) Gmu_middle(i1, i2, i3) << U_right(i1, i2, k1) * Smu_right(k1, i3) G.set_component(mu, Gmu_middle) G.set_component(mu + 1, Gmu_right) Theta = xerus.Tensor([ Gmu_middle.dimensions[2], Gmu_middle.dimensions[2] ]) # build cut-off sing value matrix Theta for j in range(Theta.dimensions[0]): if j >= Smu_right.dimensions[0]: sing_val = 0 else: singval = Smu_right[j, j] Theta[j, j] = 1 / np.max([smin, singval]) #update Stacks if mu > 0: G_tmp = G.get_component(mu - 1) A_tmp = Alist[mu - 1] G_tmp(i1, i2, i3) << G_tmp(i1, k1, i3) * A_tmp(k1, i2) lstacknp = lStack[-1].to_ndarray() G_tmpnp = G_tmp.to_ndarray() lstacknpres = np.einsum('jm,jmk->km', lstacknp, G_tmpnp) lStack.append(xerus.Tensor.from_ndarray(lstacknpres)) rStack = rStack[:-1] op = xerus.Tensor() op_pre = xerus.Tensor() op_reg = xerus.Tensor() rhs = xerus.Tensor() Gi = G.get_component(mu) if mu != d - 1: Ai = Alist[mu] Ainp = Ai.to_ndarray() lStacknp = lStack[-1].to_ndarray() rStacknp = rStack[-1].to_ndarray() op_pre_np = np.einsum('im,jm,kms->ijkms', lStacknp, Ainp, rStacknp) op_pre = xerus.Tensor.from_ndarray(op_pre_np) op(i1, i2, i3, j1, j2, j3) << op_pre(i1, i2, i3, k1, k2) * op_pre(j1, j2, j3, k1, k2) rhs(i1, i2, i3) << op_pre(i1, i2, i3, k1, k2) * Y(k2, k1) else: tmp_id = xerus.Tensor.identity([noo, 1, noo, 1]) tmp_ones = xerus.Tensor.ones([1]) op(i1, i2, i3, j1, j2, j3) << lStack[-1](i1, k1) * lStack[-1]( j1, k1) * tmp_id(i2, i3, j2, j3) rhs(i1, i2, i3) << lStack[-1](i1, k1) * Y(i2, k1) * tmp_ones(i3) if mu < d - 1: id_reg_p = xerus.Tensor.identity([p, p]) else: id_reg_p = xerus.Tensor.identity([noo, noo]) if mu > 0: id_reg_r = xerus.Tensor.identity( [Gi.dimensions[2], Gi.dimensions[2]]) op_reg(i1, i2, i3, j1, j2, j3) << Gamma(i1, k1) * Gamma( k1, j1) * id_reg_r(i3, j3) * id_reg_p(i2, j2) op += w * w * op_reg if mu < d - 1: id_reg_l = xerus.Tensor.identity( [Gi.dimensions[0], Gi.dimensions[0]]) op_reg(i1, i2, i3, j1, j2, j3) << Theta(i3, k1) * Theta( k1, j3) * id_reg_l(i1, j1) * id_reg_p(i2, j2) op += w * w * op_reg #if mu > 0 and mu < d - 1: # op_reg(i1,i2,i3,j1,j2,j3) << Theta(i3,k1) * Theta(k1,j3) * Gamma(i1,k1) * Gamma(k1,j1) * id_reg_p(i2,j2) # op += w*w *w*w* op_reg op_arr = op.to_ndarray() rhs_arr = rhs.to_ndarray() gi_arr = Gi.to_ndarray() op_dim = op.dimensions op_arr_reshape = op_arr.reshape((op_dim[0] * op_dim[1] * op_dim[2], op_dim[3] * op_dim[4] * op_dim[5])) rhs_dim = rhs.dimensions rhs_arr_reshape = rhs_arr.reshape( (rhs_dim[0] * rhs_dim[1] * rhs_dim[2])) gi_dim = Gi.dimensions gi_arr_reshape = gi_arr.reshape((gi_dim[0] * gi_dim[1] * gi_dim[2])) sol_arr = np.linalg.solve(op_arr_reshape, rhs_arr_reshape) sol_arr_reshape = sol_arr.reshape((gi_dim[0], gi_dim[1], gi_dim[2])) sol = xerus.Tensor.from_ndarray(sol_arr_reshape) G.set_component(mu, sol) if mu != d - 1: Ax = xerus.Tensor() Ax(i2, i1) << op_pre(j1, j2, j3, i1, i2) * sol(j1, j2, j3) error = (Ax - Y).frob_norm() / Y.frob_norm() #print("mu=" + str(mu) +'\033[1m'+" e=" + str(error) +'\033[0m'+ ' nG=' + str(G.frob_norm()) + ' sing ' + str(sing[-kmin])) return error