Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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, :]
Exemplo n.º 8
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[[]]
Exemplo n.º 9
0
Arquivo: als.py Projeto: lljbash/xerus
	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)
Exemplo n.º 10
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[[]]
Exemplo n.º 11
0
Arquivo: als.py Projeto: lljbash/xerus
	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()
Exemplo n.º 12
0
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
Exemplo n.º 13
0
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
Exemplo n.º 14
0
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
Exemplo n.º 16
0
Arquivo: als.py Projeto: lljbash/xerus
	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)
Exemplo n.º 19
0
Arquivo: qtt.py Projeto: lljbash/xerus
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)))

Exemplo n.º 20
0
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