jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def dnormalize(cls, Rots):
        U, _, V = torch.svd(Rots)
        S = cls.dId.clone().repeat(Rots.shape[0], 1, 1)
        S[:, 2, 2] = torch.det(U) * torch.det(V)
        return U.bmm(S).bmm(V.transpose(1, 2))
//  [python]
def dnormalize(cls, Rots):
        U, S, V = torch.linalg.svd(Rots)
        S = cls.dId.clone().repeat(Rots.shape[0], 1, 1)
        S[:, 2, 2] = torch.det(U) * torch.det(V)
        return U.bmm(S).bmm(V.transpose(1, 2))
//  [python]
def match_colors_for_image_set(self, image_set, train_save_dir):  # code from ARF
        """
        image_set: [N, H, W, 3]
        style_img: [H, W, 3]
        """
        imageio.imwrite(
            os.path.join(train_save_dir, "style_image.png"),
            np.clip(self.np_style_img * 255.0, 0.0, 255.0).astype(np.uint8),
        )
        sh = image_set.shape
        image_set = image_set.reshape(-1, 3)
        image_set = torch.tensor(image_set).to(self.device)
        style_img = self.style_img.reshape(-1, 3).to(image_set.device)

        mu_c = image_set.mean(0, keepdim=True)
        mu_s = style_img.mean(0, keepdim=True)

        cov_c = torch.matmul((image_set - mu_c).transpose(1, 0), image_set - mu_c) / float(image_set.size(0))
        cov_s = torch.matmul((style_img - mu_s).transpose(1, 0), style_img - mu_s) / float(style_img.size(0))

        u_c, sig_c, _ = torch.svd(cov_c)
        u_s, sig_s, _ = torch.svd(cov_s)

        u_c_i = u_c.transpose(1, 0)
        u_s_i = u_s.transpose(1, 0)

        scl_c = torch.diag(1.0 / torch.sqrt(torch.clamp(sig_c, 1e-8, 1e8)))
        scl_s = torch.diag(torch.sqrt(torch.clamp(sig_s, 1e-8, 1e8)))

        tmp_mat = u_s @ scl_s @ u_s_i @ u_c @ scl_c @ u_c_i
        tmp_vec = mu_s.view(1, 3) - mu_c.view(1, 3) @ tmp_mat.T

        image_set = image_set @ tmp_mat.T + tmp_vec.view(1, 3)
        image_set = image_set.contiguous().clamp_(0.0, 1.0).view(sh)

        color_tf = torch.eye(4).float().to(tmp_mat.device)
        color_tf[:3, :3] = tmp_mat
        color_tf[:3, 3:4] = tmp_vec.T
        return image_set, color_tf
//  [python]
def match_colors_for_image_set(self, image_set, train_save_dir):  # code from ARF
        """
        image_set: [N, H, W, 3]
        style_img: [H, W, 3]
        """
        imageio.imwrite(
            os.path.join(train_save_dir, "style_image.png"),
            np.clip(self.np_style_img * 255.0, 0.0, 255.0).astype(np.uint8),
        )
        sh = image_set.shape
        image_set = image_set.reshape(-1, 3)
        image_set = torch.tensor(image_set).to(self.device)
        style_img = self.style_img.reshape(-1, 3).to(image_set.device)

        mu_c = image_set.mean(0, keepdim=True)
        mu_s = style_img.mean(0, keepdim=True)

        cov_c = torch.matmul((image_set - mu_c).transpose(1, 0), image_set - mu_c) / float(image_set.size(0))
        cov_s = torch.matmul((style_img - mu_s).transpose(1, 0), style_img - mu_s) / float(style_img.size(0))

        u_c, sig_c, v_c = torch.linalg.svd(cov_c)
        u_s, sig_s, v_s = torch.linalg.svd(cov_s)

        u_c_i = u_c.transpose(1, 0)
        u_s_i = u_s.transpose(1, 0)

        scl_c = torch.diag(1.0 / torch.sqrt(torch.clamp(sig_c, 1e-8, 1e8)))
        scl_s = torch.diag(torch.sqrt(torch.clamp(sig_s, 1e-8, 1e8)))

        tmp_mat = u_s @ scl_s @ u_s_i @ u_c @ scl_c @ u_c_i
        tmp_vec = mu_s.view(1, 3) - mu_c.view(1, 3) @ tmp_mat.T

        image_set = image_set @ tmp_mat.T + tmp_vec.view(1, 3)
        image_set = image_set.contiguous().clamp_(0.0, 1.0).view(sh)

        color_tf = torch.eye(4).float().to(tmp_mat.device)
        color_tf[:3, :3] = tmp_mat
        color_tf[:3, 3:4] = tmp_vec.T
        return image_set, color_tf
//  [python]
def init_low_rank(self, weight):
        u, s, v = torch.svd(weight.t())
        self.low_rank1.data = u[:, :self.rank] @ torch.diag(s[:self.rank])
        self.low_rank2.data = v[:, :self.rank].t()
        assert torch.norm(weight.t() - u @ torch.diag(s) @ v.t()) < 0.01
//  [python]
def init_low_rank(self, weight):
        u, s, v = torch.linalg.svd(weight.t())
        self.low_rank1.data = u[:, :self.rank] @ torch.diag(s[:self.rank])
        self.low_rank2.data = v[:, :self.rank].t()
        assert torch.norm(weight.t() - u @ torch.diag(s) @ v.t()) < 0.01
//  [python]
def decompose_model_paras2(para_list1, para_list2, gradient_list1, gradient_list2):
    
    print("here")
    
    for i in range(len(para_list1)):
        
        para1 = para_list1[i]
        
        para2 = para_list2[i]
        
        grad1 = gradient_list1[i]
        
        grad2 = gradient_list2[i]
        
        
        if len(para1.shape) <= 1:
            continue
        
        u1,s1,v1 = torch.svd(para1)
         
        u2,s2,v2 = torch.svd(para2)
         
        u3,s3,v3 = torch.svd(grad1)
         
        u4,s4,v4 = torch.svd(grad2) 
        
        
        uu1, ss1, vv1 = torch.svd(para1 - para2)
        
        uu2, ss2, vv2 = torch.svd(grad1 - grad2)
        
        print("layer::", i)
        print("para_diff::")
        print(torch.norm(para1 - para2))
        
        print(torch.norm(para1 - para2, p=float("inf")))
        
        print(torch.norm(para1, p=float("inf")))
        
        
        print("grad_diff::")
        
        print(torch.norm(grad1 - grad2))
        
        
        print("difference::")
        
#         print(torch.norm(torch.mm(uu1, torch.t(uu2)) - torch.eye(uu1.shape[0], dtype = torch.double)))
#         
#         print(torch.norm(torch.mm(torch.t(vv2), vv1) - torch.eye(vv1.shape[1], dtype = torch.double)))
        
        print(torch.norm(torch.mm(u1, torch.t(u4)) - torch.eye(u1.shape[0], dtype = torch.double)))
         
        print(torch.norm(torch.mm(u2, torch.t(u4)) - torch.eye(u1.shape[0], dtype = torch.double)))
         
         
        print(torch.norm(torch.mm(v1, torch.t(v2)) - torch.eye(v1.shape[0], dtype = torch.double)))
         
        print(torch.norm(torch.mm(v1, torch.t(v3)) - torch.eye(v1.shape[0], dtype = torch.double)))
         
        print(torch.norm(torch.mm(v1, torch.t(v4)) - torch.eye(v1.shape[0], dtype = torch.double)))
         
        print(torch.norm(torch.mm(v2, torch.t(v4)) - torch.eye(v1.shape[0], dtype = torch.double)))
//  [python]
def decompose_model_paras2(para_list1, para_list2, gradient_list1, gradient_list2):
    
    print("here")
    
    for i in range(len(para_list1)):
        
        para1 = para_list1[i]
        
        para2 = para_list2[i]
        
        grad1 = gradient_list1[i]
        
        grad2 = gradient_list2[i]
        
        
        if len(para1.shape) <= 1:
            continue
        
        u1,s1,v1 = torch.linalg.svd(para1)
         
        u2,s2,v2 = torch.linalg.svd(para2)
         
        u3,s3,v3 = torch.linalg.svd(grad1)
         
        u4,s4,v4 = torch.linalg.svd(grad2) 
        
        
        uu1, ss1, vv1 = torch.linalg.svd(para1 - para2)
        
        uu2, ss2, vv2 = torch.linalg.svd(grad1 - grad2)
        
        print("layer::", i)
        print("para_diff::")
        print(torch.norm(para1 - para2))
        
        print(torch.norm(para1 - para2, p=float("inf")))
        
        print(torch.norm(para1, p=float("inf")))
        
        
        print("grad_diff::")
        
        print(torch.norm(grad1 - grad2))
        
        
        print("difference::")
        
#         print(torch.norm(torch.mm(uu1, torch.t(uu2)) - torch.eye(uu1.shape[0], dtype = torch.double)))
#         
#         print(torch.norm(torch.mm(torch.t(vv2), vv1) - torch.eye(vv1.shape[1], dtype = torch.double)))
        
        print(torch.norm(torch.mm(u1, torch.t(u4)) - torch.eye(u1.shape[0], dtype = torch.double)))
         
        print(torch.norm(torch.mm(u2, torch.t(u4)) - torch.eye(u1.shape[0], dtype = torch.double)))
         
         
        print(torch.norm(torch.mm(v1, torch.t(v2)) - torch.eye(v1.shape[0], dtype = torch.double)))
         
        print(torch.norm(torch.mm(v1, torch.t(v3)) - torch.eye(v1.shape[0], dtype = torch.double)))
         
        print(torch.norm(torch.mm(v1, torch.t(v4)) - torch.eye(v1.shape[0], dtype = torch.double)))
         
        print(torch.norm(torch.mm(v2, torch.t(v4)) - torch.eye(v1.shape[0], dtype = torch.double)))
//  [python]
def forward(self, f_s, f_t):
        U_s, _, _ = torch.svd(f_s.t())
        U_t, _, _ = torch.svd(f_t.t())
        P_s, cosine, P_t = torch.svd(torch.mm(U_s.t(), U_t))
        sine = torch.sqrt(1 - torch.pow(cosine, 2))
        rsd = torch.norm(sine, 1)  # Representation Subspace Distance
        bmp = torch.norm(torch.abs(P_s) - torch.abs(P_t), 2)  # Base Mismatch Penalization
        return rsd + self.trade_off * bmp
//  [python]
def forward(self, f_s, f_t):
        U_s, _, _ = torch.linalg.svd(f_s.t())
        U_t, _, _ = torch.linalg.svd(f_t.t())
        P_s, cosine, P_t = torch.linalg.svd(torch.mm(U_s.t(), U_t))
        sine = torch.sqrt(1 - torch.pow(cosine, 2))
        rsd = torch.norm(sine, 1)  # Representation Subspace Distance
        bmp = torch.norm(torch.abs(P_s) - torch.abs(P_t), 2)  # Base Mismatch Penalization
        return rsd + self.trade_off * bmp
//  [python]
def normal(tensor, type):
    r"""renormalize a random tensor to be (semi-) unitary
    """
    dims = tensor.size()
    bond_in, _ = type
    dim1 = np.prod(dims[:bond_in])
    dim2 = np.prod(dims[bond_in:])

    tensor = tensor.view(dim1, dim2)
    tensor, _, _ = torch.svd(tensor)
    return tensor.view(dims)
//  [python]
def normal(tensor, type):
    r"""renormalize a random tensor to be (semi-) unitary
    """
    dims = tensor.size()
    bond_in, _ = type
    dim1 = np.prod(dims[:bond_in])
    dim2 = np.prod(dims[bond_in:])

    tensor = tensor.view(dim1, dim2)
    tensor, _, _ = torch.linalg.svd(tensor)
    return tensor.view(dims)
//  [python]
def forward(ctx, M):
        # s, u = th.symeig(M, eigenvectors=True, upper=True)  # s in a ascending sequence.
        ut, s, u = th.svd(M)  # s in a descending sequence.
        # print('0-eigenvalue # {}'.format((s <= 1e-5).sum()))
        s = th.clamp(s, min=1e-10)  # 1e-5
        ctx.save_for_backward(M, u, s)
        return u, s
//  [python]
def forward(ctx, M):
        ut, s, u = th.linalg.svd(M)  # s in a descending sequence.
        # print('0-eigenvalue # {}'.format((s <= 1e-5).sum()))
        s = th.clamp(s, min=1e-10)  # 1e-5
        ctx.save_for_backward(M, u, s)
        return u, s
//  [python]
def measure_I_W(W):
    assert(len(W.shape) == 2)
    ## W: embedding matrix, shape=[n_data, dim]
    u, s, v = torch.svd(W) ## v.shape=[dim, n_data]
    z = torch.exp(torch.matmul(W, v)).sum(0) ## (W*v).shape=[n_data, n_data]
    i_w = z.min() / z.max()
    return float(i_w)
//  [python]
def measure_I_W(W):
    assert(len(W.shape) == 2)
    ## W: embedding matrix, shape=[n_data, dim]
    u, s, v = torch.linalg.svd(W) ## v.shape=[dim, n_data]
    z = torch.exp(torch.matmul(W, v)).sum(0) ## (W*v).shape=[n_data, n_data]
    i_w = z.min() / z.max()
    return float(i_w)
//  [python]
def spectral_init(weight, rank):

    U, S, V = torch.svd(weight)
    sqrtS = torch.diag(torch.sqrt(S[:rank]))
    return torch.matmul(U[:,:rank], sqrtS), torch.matmul(V[:,:rank], sqrtS).T
//  [python]
def spectral_init(weight, rank):

    U, S, V = torch.linalg.svd(weight)
    sqrtS = torch.diag(torch.sqrt(S[:rank]))
    return torch.matmul(U[:,:rank], sqrtS), torch.matmul(V[:,:rank], sqrtS).T
//  [python]
def clip_singular_values(M, min=1e-6):
    U, s, V = torch.svd(M)
    s = torch.clamp(s, min=min)
    return torch.mm(torch.mm(U, torch.diag(s)), V.t())
//  [python]
def clip_singular_values(M, min=1e-6):
    U, s, V = torch.linalg.svd(M)
    s = torch.clamp(s, min=min)
    return torch.mm(torch.mm(U, torch.diag(s)), V.t())
//  [python]
def avg_rot(rot):
    # input [B,...,3,3] --> output [...,3,3]
    rot = rot.mean(dim=0)
    U, _, V = torch.svd(rot)
    rot = U @ V.transpose(-1, -2)
    return rot
//  [python]
def avg_rot(rot):
    # input [B,...,3,3] --> output [...,3,3]
    rot = rot.mean(dim=0)
    U, _, V = torch.linalg.svd(rot)
    rot = U @ V.transpose(-1, -2)
    return rot
//  [python]
def init_bimap_parameter(W):
    """ initializes a (ho,hi,ni,no) 4D-StiefelParameter"""
    # C* = C +λI , where I is the identity matrix, λ could be set to \alpha× trace(C ), and \alpha is a very small value like 10^(-6).
    ho, hi, ni, no = W.shape
    for i in range(ho):  # can vectorize
        for j in range(hi):  # can vectorize
            v = torch.empty(ni, ni, dtype=W.dtype,
                            device=W.device).uniform_(0., 1.)
            inp_svd = v.matmul(v.t())
            alpha = 1e-5
            inp_svd = add_id_matrix(inp_svd, alpha)
            # vv = torch.svd(inp_svd)[0][:, :no]
            vv = torch.svd(inp_svd.cpu())[0][:, :no]
            W.data[i, j] = vv.cuda()
//  [python]
def init_bimap_parameter(W):
    """ initializes a (ho,hi,ni,no) 4D-StiefelParameter"""
    # C* = C +λI , where I is the identity matrix, λ could be set to \alpha× trace(C ), and \alpha is a very small value like 10^(-6).
    ho, hi, ni, no = W.shape
    for i in range(ho):  # can vectorize
        for j in range(hi):  # can vectorize
            v = torch.empty(ni, ni, dtype=W.dtype,
                            device=W.device).uniform_(0., 1.)
            inp_svd = v.matmul(v.t())
            alpha = 1e-5
            inp_svd = add_id_matrix(inp_svd, alpha)
            # vv = torch.svd(inp_svd)[0][:, :no]
            vv = torch.linalg.svd(inp_svd.cpu())[0][:, :no]
            W.data[i, j] = vv.cuda()
//  [python]
def test_svd_no_singularvectors(self):
        A = torch.randn(2, 2, dtype=torch.float32, requires_grad=True)
        u, s, v = torch.svd(A, compute_uv=False)
        with self.assertRaisesRegex(RuntimeError, 'cannot compute backward'):
            torch.autograd.backward([u, s, v], [torch.ones_like(u), torch.ones_like(s), torch.ones_like(v)])
//  [python]
def test_svd_no_singularvectors(self):
        A = torch.randn(2, 2, dtype=torch.float32, requires_grad=True)
        u, s, v = torch.linalg.svd(A, compute_uv=False)
        with self.assertRaisesRegex(RuntimeError, 'cannot compute backward'):
            torch.autograd.backward([u, s, v], [torch.ones_like(u), torch.ones_like(s), torch.ones_like(v)])
//  [python]
def compute_eigendecomposition(self, impl="svd"):
        data_mat = self.data.view(-1, self.data.size(2))
        if impl == "svd":
            _, sqrt_evals, self.evecs = torch.svd(data_mat, some=True)
            self.evals = sqrt_evals**2
        else:
            raise NotImplementedError
//  [python]
def compute_eigendecomposition(self, impl="svd"):
        data_mat = self.data.view(-1, self.data.size(2))
        if impl == "svd":
            _, self.evecs, self.evals = torch.linalg.svd(data_mat, full_matrices=False)
            self.evals = self.evals**2
        else:
            raise NotImplementedError
//  [python]
def cca(self, zs):
        r"""CCA loss calculation.
        Adapted from: https://github.com/jameschapman19/cca_zoo/blob/main/cca_zoo/deep/_discriminative/_dmcca.py

        Args:
            z (list): list of latent dimensions for each view of type torch.Tensor.

        Returns:
            cca_loss (torch.Tensor): CCA loss.
        """

        zs = [
            z - z.mean(dim=0)
            for z in zs
        ]
        all_views = torch.cat(zs, dim=1)

        #Calculate cross-covariance matrix
        C = torch.cov(all_views.T)
        C = C - torch.block_diag(
            *[torch.cov(z.T) for z in zs]
        )
        C =  C / len(zs)

        #Calculate block covariance matrix
        D = torch.block_diag(
            *[
                (1 - EPS) * torch.cov(z.T)
                + EPS
                * torch.eye(z.shape[1], device=z.device)
                for z in zs
            ]
        )
        D = D / len(zs)

        C += D

        U, S, V = torch.svd(D)
        # Enforce positive definite by taking a torch max() with EPS
        S = torch.clamp(S, min=EPS)
        # Calculate inverse square-root
        inv_sqrt_S = torch.diag_embed(torch.pow(S, -0.5))
        # Calculate inverse square-root matrix
        R = torch.matmul(torch.matmul(U, inv_sqrt_S), V.transpose(-1, -2))

        C_whitened = R @ C @ R.T
        eigvals = torch.linalg.eigvalsh(C_whitened)
        idx = torch.argsort(eigvals, descending=True)
        eigvals = eigvals[idx[:self.z_dim]]
        eigvals = torch.nn.LeakyReLU()(eigvals[torch.gt(eigvals, 0)])
        corr = eigvals.sum()

        return -corr
//  [python]
def cca(self, zs):
        r"""CCA loss calculation.
        Adapted from: https://github.com/jameschapman19/cca_zoo/blob/main/cca_zoo/deep/_discriminative/_dmcca.py

        Args:
            z (list): list of latent dimensions for each view of type torch.Tensor.

        Returns:
            cca_loss (torch.Tensor): CCA loss.
        """

        zs = [
            z - z.mean(dim=0)
            for z in zs
        ]
        all_views = torch.cat(zs, dim=1)

        #Calculate cross-covariance matrix
        C = torch.cov(all_views.T)
        C = C - torch.block_diag(
            *[torch.cov(z.T) for z in zs]
        )
        C =  C / len(zs)

        #Calculate block covariance matrix
        D = torch.block_diag(
            *[
                (1 - EPS) * torch.cov(z.T)
                + EPS
                * torch.eye(z.shape[1], device=z.device)
                for z in zs
            ]
        )
        D = D / len(zs)

        C += D

        U, S, V = torch.linalg.svd(D)
        # Enforce positive definite by taking a torch max() with EPS
        S = torch.clamp(S, min=EPS)
        # Calculate inverse square-root
        inv_sqrt_S = torch.diag_embed(torch.pow(S, -0.5))
        # Calculate inverse square-root matrix
        R = torch.matmul(torch.matmul(U, inv_sqrt_S), V.transpose(-1, -2))

        C_whitened = R @ C @ R.T
        eigvals = torch.linalg.eigvalsh(C_whitened)
        idx = torch.argsort(eigvals, descending=True)
        eigvals = eigvals[idx[:self.z_dim]]
        eigvals = torch.nn.LeakyReLU()(eigvals[torch.gt(eigvals, 0)])
        corr = eigvals.sum()

        return -corr
//  [python]
def wct(cont_feat, styl_feat):
    cFSize = cont_feat.size()
    c_mean = torch.mean(cont_feat, 1)  # c x (h x w)
    c_mean = c_mean.unsqueeze(1).expand_as(cont_feat)
    cont_feat = cont_feat - c_mean

    iden = torch.eye(cFSize[0])  # .double()
    iden = iden.cuda()
    contentConv = torch.mm(cont_feat, cont_feat.t()).div(cFSize[1] - 1)# + iden
    # del iden
    c_u, c_e, c_v = torch.svd(contentConv, some=False)
    # c_e2, c_v = torch.eig(contentConv, True)
    # c_e = c_e2[:,0]

    k_c = cFSize[0]
    for i in range(cFSize[0] - 1, -1, -1):
        if c_e[i] >= 0.00001:
            k_c = i + 1
            break

    sFSize = styl_feat.size()
    s_mean = torch.mean(styl_feat, 1)
    styl_feat = styl_feat - s_mean.unsqueeze(1).expand_as(styl_feat)
    styleConv = torch.mm(styl_feat, styl_feat.t()).div(sFSize[1] - 1)
    s_u, s_e, s_v = torch.svd(styleConv, some=False)

    k_s = sFSize[0]
    for i in range(sFSize[0] - 1, -1, -1):
        if s_e[i] >= 0.00001:
            k_s = i + 1
            break

    c_d = (c_e[0:k_c]).pow(-0.5)
    step1 = torch.mm(c_v[:, 0:k_c], torch.diag(c_d))
    step2 = torch.mm(step1, (c_v[:, 0:k_c].t()))
    whiten_cF = torch.mm(step2, cont_feat)

    s_d = (s_e[0:k_s]).pow(0.5)
    targetFeature = torch.mm(torch.mm(torch.mm(s_v[:, 0:k_s], torch.diag(s_d)), (s_v[:, 0:k_s].t())), whiten_cF)
    targetFeature = targetFeature + s_mean.unsqueeze(1).expand_as(targetFeature)
    return targetFeature
//  [python]
def wct(cont_feat, styl_feat):
    cFSize = cont_feat.size()
    c_mean = torch.mean(cont_feat, 1)  # c x (h x w)
    c_mean = c_mean.unsqueeze(1).expand_as(cont_feat)
    cont_feat = cont_feat - c_mean

    iden = torch.eye(cFSize[0])  # .double()
    iden = iden.cuda()
    contentConv = torch.mm(cont_feat, cont_feat.t()).div(cFSize[1] - 1)# + iden
    # del iden
    c_u, c_s, c_v = torch.linalg.svd(contentConv)
    # c_e2, c_v = torch.eig(contentConv, True)
    # c_e = c_e2[:,0]

    k_c = cFSize[0]
    for i in range(cFSize[0] - 1, -1, -1):
        if c_s[i] >= 0.00001:
            k_c = i + 1
            break

    sFSize = styl_feat.size()
    s_mean = torch.mean(styl_feat, 1)
    styl_feat = styl_feat - s_mean.unsqueeze(1).expand_as(styl_feat)
    styleConv = torch.mm(styl_feat, styl_feat.t()).div(sFSize[1] - 1)
    s_u, s_s, s_v = torch.linalg.svd(styleConv)

    k_s = sFSize[0]
    for i in range(sFSize[0] - 1, -1, -1):
        if s_s[i] >= 0.00001:
            k_s = i + 1
            break

    c_d = (c_s[0:k_c]).pow(-0.5)
    step1 = torch.mm(c_v[:, 0:k_c], torch.diag(c_d))
    step2 = torch.mm(step1, (c_v[:, 0:k_c].t()))
    whiten_cF = torch.mm(step2, cont_feat)

    s_d = (s_s[0:k_s]).pow(0.5)
    targetFeature = torch.mm(torch.mm(torch.mm(s_v[:, 0:k_s], torch.diag(s_d)), (s_v[:, 0:k_s].t())), whiten_cF)
    targetFeature = targetFeature + s_mean.unsqueeze(1).expand_as(targetFeature)
    return targetFeature
//  [python]
def symmetric_orthogonalization(x: torch.Tensor) -> torch.Tensor:
    """Maps 9D input vectors onto SO(3) via symmetric orthogonalization.
    x: should have size [batch_size, 9]
    Output has size [batch_size, 3, 3], where each inner 3x3 matrix is in SO(3).

    for rotation matrix R in SO(3), SVD (R) == R.

    get code from `An Analysis of {SVD} for Deep Rotation Estimation, NIPS 2020`
    """
    init_shape = x.shape
    m = x.view(-1, 3, 3)
    u, s, v = torch.svd(m)
    vt = torch.transpose(v, 1, 2)
    det = torch.det(torch.matmul(u, vt))
    det = det.view(-1, 1, 1)
    vt = torch.cat((vt[:, :2, :], vt[:, -1:, :] * det), 1)
    r = torch.matmul(u, vt)
    return r.view(init_shape)
//  [python]
def symmetric_orthogonalization(x: torch.Tensor) -> torch.Tensor:
    """Maps 9D input vectors onto SO(3) via symmetric orthogonalization.
    x: should have size [batch_size, 9]
    Output has size [batch_size, 3, 3], where each inner 3x3 matrix is in SO(3).

    for rotation matrix R in SO(3), SVD (R) == R.

    get code from `An Analysis of {SVD} for Deep Rotation Estimation, NIPS 2020`
    """
    init_shape = x.shape
    m = x.view(-1, 3, 3)
    u, s, v = torch.linalg.svd(m)
    vt = torch.transpose(v, 1, 2)
    det = torch.det(torch.matmul(u, vt))
    det = det.view(-1, 1, 1)
    vt = torch.cat((vt[:, :2, :], vt[:, -1:, :] * det), 1)
    r = torch.matmul(u, vt)
    return r.view(init_shape)
//  [python]
def svd(
        self,
    ) -> Tuple[
        Float[torch.Tensor, "*leading_dims ldim mdim"],
        Float[torch.Tensor, "*leading_dims mdim"],
        Float[torch.Tensor, "*leading_dims rdim mdim"],
    ]:
        """
        Efficient algorithm for finding Singular Value Decomposition, a tuple (U, S, Vh) for matrix M st S is a vector and U, Vh are orthogonal matrices, and U @ S.diag() @ Vh.T == M

        (Note that Vh is given as the transpose of the obvious thing)
        """
        Ua, Sa, Vha = torch.svd(self.A)
        Ub, Sb, Vhb = torch.svd(self.B)
        middle = Sa[..., :, None] * utils.transpose(Vha) @ Ub * Sb[..., None, :]
        Um, Sm, Vhm = torch.svd(middle)
        U = Ua @ Um
        Vh = Vhb @ Vhm
        S = Sm
        return U, S, Vh
//  [python]
def svd(
        self,
    ) -> Tuple[
        Float[torch.Tensor, "*leading_dims ldim mdim"],
        Float[torch.Tensor, "*leading_dims mdim"],
        Float[torch.Tensor, "*leading_dims rdim mdim"],
    ]:
        """
        Efficient algorithm for finding Singular Value Decomposition, a tuple (U, S, Vh) for matrix M st S is a vector and U, Vh are orthogonal matrices, and U @ S.diag() @ Vh.T == M

        (Note that Vh is given as the transpose of the obvious thing)
        """
        Ua, Sa, Vha = torch.linalg.svd(self.A)
        Ub, Sb, Vhb = torch.linalg.svd(self.B)
        middle = Sa[..., :, None] * utils.transpose(Vha) @ Ub * Sb[..., None, :]
        Um, Sm, Vhm = torch.linalg.svd(middle)
        U = Ua @ Um
        Vh = Vhb @ Vhm
        S = Sm
        return U, S, Vh
//  [python]
def __wct_core(self, cont_feat, styl_feat):
        cFSize = cont_feat.size()
        c_mean = torch.mean(cont_feat, 1)  # c x (h x w)
        c_mean = c_mean.unsqueeze(1).expand_as(cont_feat)
        cont_feat = cont_feat - c_mean
        
        iden = torch.eye(cFSize[0])  # .double()
        if self.is_cuda:
            iden = iden.cuda()
        
        contentConv = torch.mm(cont_feat, cont_feat.t()).div(cFSize[1] - 1) + iden
        # del iden
        c_u, c_e, c_v = torch.svd(contentConv, some=False)
        # c_e2, c_v = torch.eig(contentConv, True)
        # c_e = c_e2[:,0]
        
        k_c = cFSize[0]
        for i in range(cFSize[0] - 1, -1, -1):
            if c_e[i] >= 0.00001:
                k_c = i + 1
                break
        
        sFSize = styl_feat.size()
        s_mean = torch.mean(styl_feat, 1)
        styl_feat = styl_feat - s_mean.unsqueeze(1).expand_as(styl_feat)
        styleConv = torch.mm(styl_feat, styl_feat.t()).div(sFSize[1] - 1)
        s_u, s_e, s_v = torch.svd(styleConv, some=False)
        
        k_s = sFSize[0]
        for i in range(sFSize[0] - 1, -1, -1):
            if s_e[i] >= 0.00001:
                k_s = i + 1
                break
        
        c_d = (c_e[0:k_c]).pow(-0.5)
        step1 = torch.mm(c_v[:, 0:k_c], torch.diag(c_d))
        step2 = torch.mm(step1, (c_v[:, 0:k_c].t()))
        whiten_cF = torch.mm(step2, cont_feat)

        s_d = (s_e[0:k_s]).pow(0.5)
        targetFeature = torch.mm(torch.mm(torch.mm(s_v[:, 0:k_s], torch.diag(s_d)), (s_v[:, 0:k_s].t())), whiten_cF)
        targetFeature = targetFeature + s_mean.unsqueeze(1).expand_as(targetFeature)
        return targetFeature
//  [python]
def __wct_core(self, cont_feat, styl_feat):
        cFSize = cont_feat.size()
        c_mean = torch.mean(cont_feat, 1)  # c x (h x w)
        c_mean = c_mean.unsqueeze(1).expand_as(cont_feat)
        cont_feat = cont_feat - c_mean
        
        iden = torch.eye(cFSize[0])  # .double()
        if self.is_cuda:
            iden = iden.cuda()
        
        contentConv = torch.mm(cont_feat, cont_feat.t()).div(cFSize[1] - 1) + iden
        # del iden
        c_u, c_s, c_v = torch.linalg.svd(contentConv)
        # c_e2, c_v = torch.eig(contentConv, True)
        # c_e = c_e2[:,0]
        
        k_c = cFSize[0]
        for i in range(cFSize[0] - 1, -1, -1):
            if c_s[i] >= 0.00001:
                k_c = i + 1
                break
        
        sFSize = styl_feat.size()
        s_mean = torch.mean(styl_feat, 1)
        styl_feat = styl_feat - s_mean.unsqueeze(1).expand_as(styl_feat)
        styleConv = torch.mm(styl_feat, styl_feat.t()).div(sFSize[1] - 1)
        s_u, s_s, s_v = torch.linalg.svd(styleConv)
        
        k_s = sFSize[0]
        for i in range(sFSize[0] - 1, -1, -1):
            if s_s[i] >= 0.00001:
                k_s = i + 1
                break
        
        c_d = (c_s[0:k_c]).pow(-0.5)
        step1 = torch.mm(c_v[:, 0:k_c], torch.diag(c_d))
        step2 = torch.mm(step1, (c_v[:, 0:k_c].t()))
        whiten_cF = torch.mm(step2, cont_feat)

        s_d = (s_s[0:k_s]).pow(0.5)
        targetFeature = torch.mm(torch.mm(torch.mm(s_v[:, 0:k_s], torch.diag(s_d)), (s_v[:, 0:k_s].t())), whiten_cF)
        targetFeature = targetFeature + s_mean.unsqueeze(1).expand_as(targetFeature)
        return targetFeature
//  [python]
def best_fit_transform_torch(self, A, B):
        '''
        Calculates the least-squares best-fit transform that maps corresponding points A to B in m spatial dimensions
        Input:
            A: Nxm numpy array of corresponding points, usually points on mdl
            B: Nxm numpy array of corresponding points, usually points on camera axis
        Returns:
        T: (m+1)x(m+1) homogeneous transformation matrix that maps A on to B
        R: mxm rotation matrix
        t: mx1 translation vector
        '''
        assert A.size() == B.size()
        # get number of dimensions
        m = A.size()[1]
        # translate points to their centroids
        centroid_A = torch.mean(A, dim=0)
        centroid_B = torch.mean(B, dim=0)
        AA = A - centroid_A
        BB = B - centroid_B
        # rotation matirx
        H = torch.mm(AA.transpose(1, 0), BB)
        U, S, Vt = torch.svd(H)
        R = torch.mm(Vt.transpose(1, 0), U.transpose(1, 0))
        # special reflection case
        if torch.det(R) < 0:
            Vt[m-1, :] *= -1
            R = torch.mm(Vt.transpose(1, 0), U.transpose(1, 0))
        # translation
        t = centroid_B - torch.mm(R, centroid_A.view(3, 1))[:, 0]
        T = torch.zeros(3, 4).cuda()
        T[:, :3] = R
        T[:, 3] = t
        return  T
//  [python]
def best_fit_transform_torch(self, A, B):
        '''
        Calculates the least-squares best-fit transform that maps corresponding points A to B in m spatial dimensions
        Input:
            A: Nxm numpy array of corresponding points, usually points on mdl
            B: Nxm numpy array of corresponding points, usually points on camera axis
        Returns:
        T: (m+1)x(m+1) homogeneous transformation matrix that maps A on to B
        R: mxm rotation matrix
        t: mx1 translation vector
        '''
        assert A.size() == B.size()
        # get number of dimensions
        m = A.size()[1]
        # translate points to their centroids
        centroid_A = torch.mean(A, dim=0)
        centroid_B = torch.mean(B, dim=0)
        AA = A - centroid_A
        BB = B - centroid_B
        # rotation matirx
        H = torch.mm(AA.transpose(1, 0), BB)
        U, S, Vt = torch.linalg.svd(H)
        R = torch.mm(Vt.transpose(1, 0), U.transpose(1, 0))
        # special reflection case
        if torch.det(R) < 0:
            Vt[m-1, :] *= -1
            R = torch.mm(Vt.transpose(1, 0), U.transpose(1, 0))
        # translation
        t = centroid_B - torch.mm(R, centroid_A.view(3, 1))[:, 0]
        T = torch.zeros(3, 4).cuda()
        T[:, :3] = R
        T[:, 3] = t
        return  T
//  [python]
def kabsch(A, B):
    a_mean = A.mean(dim=1, keepdims=True)
    b_mean = B.mean(dim=1, keepdims=True)
    A_c = A - a_mean
    B_c = B - b_mean
    # Covariance matrix
    H = torch.bmm(A_c.transpose(1,2), B_c)  # [B, 3, 3]
    U, S, V = torch.svd(H)
    # Rotation matrix
    R = torch.bmm(V, U.transpose(1,2))  # [B, 3, 3]
    # Translation vector
    t = b_mean - torch.bmm(R, a_mean.transpose(1,2)).transpose(1,2)
    A_aligned = torch.bmm(R, A.transpose(1,2)).transpose(1,2) + t
    return A_aligned, R, t
//  [python]
def kabsch(A, B):
    a_mean = A.mean(dim=1, keepdims=True)
    b_mean = B.mean(dim=1, keepdims=True)
    A_c = A - a_mean
    B_c = B - b_mean
    # Covariance matrix
    H = torch.bmm(A_c.transpose(1,2), B_c)  # [B, 3, 3]
    U, S, V = torch.linalg.svd(H)
    # Rotation matrix
    R = torch.bmm(V, U.transpose(1,2))  # [B, 3, 3]
    # Translation vector
    t = b_mean - torch.bmm(R, a_mean.transpose(1,2)).transpose(1,2)
    A_aligned = torch.bmm(R, A.transpose(1,2)).transpose(1,2) + t
    return A_aligned, R, t
//  [python]
def nullspace(A, tol=1e-12):
    U, S, V = torch.svd(A, some=False)
    if S.min() >= tol:
        null_start = len(S)
    else:
        null_start = int(len(S) - torch.sum(S<tol))

    V_null = V[:, null_start:]
    return V_null
//  [python]
def nullspace(A, tol=1e-12):
    U, S, V = torch.linalg.svd(A)
    if S.min() >= tol:
        null_start = len(S)
    else:
        null_start = int(len(S) - torch.sum(S<tol))

    V_null = V[:, null_start:]
    return V_null
//  [python]
print(torch.cross(v2, v1)) # z축 단위 벡터의 음수값 (v1 x v2 == -v2 x v1)
print(m1)
m3 = torch.matmul(m1, m2)
print(m3)                  # m1 행렬을 3번 곱한 결과
print(torch.svd(m3))
//  [python]
print(torch.linalg.svd(m3))
//  [python]
def interpolate_cut(cut1, cut2, theta):
    """ interpolate two isometries
     theta = pi/2: mix = cut1
     theta = 0   : mix = cut2
    """
    mix = np.sin(theta) * cut1 + np.cos(theta) * cut2
    U, _, V = torch.svd(mix)
    return U@V.t()
//  [python]
def interpolate_cut(cut1, cut2, theta):
    """ interpolate two isometries
     theta = pi/2: mix = cut1
     theta = 0   : mix = cut2
    """
    mix = np.sin(theta) * cut1 + np.cos(theta) * cut2
    U, _, V = torch.linalg.svd(mix)
    return U@V.t()
//  [python]
print(torch.asin(r))

# 행렬식 및 특이값 분해와 같은 선형 대수 연산을 사용할 수 있습니다.
print('\nr의 행렬식:')
print(torch.det(r))
print('\nr의 특이값 분해:')
print(torch.svd(r))
//  [python]
print(torch.asin(r))

# 행렬식 및 특이값 분해와 같은 선형 대수 연산을 사용할 수 있습니다.
print('\nr의 행렬식:')
print(torch.det(r))
print('\nr의 특이값 분해:')
print(torch.linalg.svd(r))
//  [python]
def kabsch(
    mobile,
    stationary,
    return_translation_rotation=False,
):
    X = rearrange(
        mobile,
        "... l d -> ... d l",
    )
    Y = rearrange(
        stationary,
        "... l d -> ... d l",
    )

    #  center X and Y to the origin
    XT, YT = X.mean(dim=-1, keepdim=True), Y.mean(dim=-1, keepdim=True)
    X_ = X - XT
    Y_ = Y - YT

    # calculate convariance matrix
    C = torch.einsum("... x l, ... y l -> ... x y", X_, Y_)

    # Optimal rotation matrix via SVD
    if int(torch.__version__.split(".")[1]) < 8:
        # warning! int torch 1.<8 : W must be transposed
        V, S, W = torch.svd(C)
        W = rearrange(W, "... a b -> ... b a")
    else:
        V, S, W = torch.linalg.svd(C)

    # determinant sign for direction correction
    v_det = torch.det(V.to("cpu")).to(X.device)
    w_det = torch.det(W.to("cpu")).to(X.device)
    d = (v_det * w_det) < 0.0
    if d.any():
        S[d] = S[d] * (-1)
        V[d, :] = V[d, :] * (-1)

    # Create Rotation matrix U
    U = torch.matmul(V, W)  # .to(device)

    U = rearrange(
        U,
        "... d x -> ... x d",
    )
    XT = rearrange(
        XT,
        "... d x -> ... x d",
    )
    YT = rearrange(
        YT,
        "... d x -> ... x d",
    )

    if return_translation_rotation:
        return XT, U, YT

    transform = (
        lambda coords: torch.einsum(
            "... l d, ... x d -> ... l x",
            coords - XT,
            U,
        )
        + YT
    )
    mobile = transform(mobile)

    return mobile, transform
//  [python]
def kabsch(
    mobile,
    stationary,
    return_translation_rotation=False,
):
    X = rearrange(
        mobile,
        "... l d -> ... d l",
    )
    Y = rearrange(
        stationary,
        "... l d -> ... d l",
    )

    #  center X and Y to the origin
    XT, YT = X.mean(dim=-1, keepdim=True), Y.mean(dim=-1, keepdim=True)
    X_ = X - XT
    Y_ = Y - YT

    # calculate convariance matrix
    C = torch.einsum("... x l, ... y l -> ... x y", X_, Y_)

    # Optimal rotation matrix via SVD
    V, S, W = torch.linalg.svd(C)

    # determinant sign for direction correction
    v_det = torch.det(V.to("cpu")).to(X.device)
    w_det = torch.det(W.to("cpu")).to(X.device)
    d = (v_det * w_det) < 0.0
    if d.any():
        S[d] = S[d] * (-1)
        V[d, :] = V[d, :] * (-1)

    # Create Rotation matrix U
    U = torch.matmul(V, W)  # .to(device)

    U = rearrange(
        U,
        "... d x -> ... x d",
    )
    XT = rearrange(
        XT,
        "... d x -> ... x d",
    )
    YT = rearrange(
        YT,
        "... d x -> ... x d",
    )

    if return_translation_rotation:
        return XT, U, YT

    transform = (
        lambda coords: torch.einsum(
            "... l d, ... x d -> ... l x",
            coords - XT,
            U,
        )
        + YT
    )
    mobile = transform(mobile)

    return mobile, transform
//  [python]
def cpu_op_exec(self, input1, some, compute_uv=False):
        output_u, output_s, output_v = torch.svd(input1, some, compute_uv)
        return output_u, output_s, output_v
//  [python]
def cpu_op_exec(self, input1, some, compute_uv=False):
        output_u, output_s, output_v = torch.linalg.svd(input1, some, compute_uv)
        return output_u, output_s, output_v
//  [python]
def R_from_2poses(joints0, joints1, is_torch=False):
    '''
    input: joints0 & joints1
    output: rotation matrix R, CS0->CS1
    '''
    if is_torch:
        joints0, joints1 = torch.stack(joints0), torch.stack(joints1)
        Cov = joints0.T @ joints1
        U, S, V = torch.svd(Cov)
        return U @ V.T
    else:
        joints0, joints1 = np.array(joints0), np.array(joints1)
        Cov = joints0.T @ joints1
        U, S, Vt = np.linalg.svd(Cov)
        return U @ Vt
//  [python]
def R_from_2poses(joints0, joints1, is_torch=False):
    '''
    input: joints0 & joints1
    output: rotation matrix R, CS0->CS1
    '''
    if is_torch:
        joints0, joints1 = torch.stack(joints0), torch.stack(joints1)
        Cov = joints0.T @ joints1
        U, S, V = torch.linalg.svd(Cov)
        return U @ V.T
    else:
        joints0, joints1 = np.array(joints0), np.array(joints1)
        Cov = joints0.T @ joints1
        U, S, Vt = np.linalg.svd(Cov)
        return U @ Vt
//  [python]
def reset_parameters(self, mode: Optional[str] = None) -> None:
        mode = mode or self.mode
        W = init.kaiming_normal_(
            torch.empty(
                self.grid_dim_y,
                self.grid_dim_x,
                self.miniblock,
                self.miniblock,
                dtype=torch.cfloat,
                device=self.device,
            )
        )
        _, S, _ = torch.svd(W, compute_uv=False)
        self.S.data.copy_(S)

        if mode == "zero_bias":
            self.T.reset_parameters(alg="zero")
            self.Tr.reset_parameters(alg="zero")
            self.T.phases.requires_grad_(False)
            self.Tr.phases.requires_grad_(False)
        elif mode == "hadamard":
            self.T.reset_parameters(alg="hadamard")
            self.Tr.reset_parameters(alg="hadamard")
            self.T.phases.requires_grad_(False)
            self.Tr.phases.requires_grad_(False)
        elif mode == "fft":
            self.T.reset_parameters(alg="fft")
            self.Tr.reset_parameters(alg="fft")
            self.T.phases.requires_grad_(False)
            self.Tr.phases.requires_grad_(False)
        elif mode == "trainable":
            self.T.reset_parameters(alg="uniform")
            self.Tr.reset_parameters(alg="uniform")
            self.T.phases.requires_grad_(True)
            self.Tr.phases.requires_grad_(True)
        else:
            raise NotImplementedError

        if self.bias is not None:
            init.uniform_(self.bias, 0, 0)
//  [python]
def reset_parameters(self, mode: Optional[str] = None) -> None:
        mode = mode or self.mode
        W = init.kaiming_normal_(
            torch.empty(
                self.grid_dim_y,
                self.grid_dim_x,
                self.miniblock,
                self.miniblock,
                dtype=torch.cfloat,
                device=self.device,
            )
        )
        _, S, _ = torch.linalg.svd(W, compute_uv=False)
        self.S.data.copy_(S)

        if mode == "zero_bias":
            self.T.reset_parameters(alg="zero")
            self.Tr.reset_parameters(alg="zero")
            self.T.phases.requires_grad_(False)
            self.Tr.phases.requires_grad_(False)
        elif mode == "hadamard":
            self.T.reset_parameters(alg="hadamard")
            self.Tr.reset_parameters(alg="hadamard")
            self.T.phases.requires_grad_(False)
            self.Tr.phases.requires_grad_(False)
        elif mode == "fft":
            self.T.reset_parameters(alg="fft")
            self.Tr.reset_parameters(alg="fft")
            self.T.phases.requires_grad_(False)
            self.Tr.phases.requires_grad_(False)
        elif mode == "trainable":
            self.T.reset_parameters(alg="uniform")
            self.Tr.reset_parameters(alg="uniform")
            self.T.phases.requires_grad_(True)
            self.Tr.phases.requires_grad_(True)
        else:
            raise NotImplementedError

        if self.bias is not None:
            init.uniform_(self.bias, 0, 0)
//  [python]
def compute_similarity_transform(S1: torch.Tensor, S2: torch.Tensor) -> torch.Tensor:
    """
    Computes a similarity transform (sR, t) in a batched way that takes
    a set of 3D points S1 (B, N, 3) closest to a set of 3D points S2 (B, N, 3),
    where R is a 3x3 rotation matrix, t 3x1 translation, s scale.
    i.e. solves the orthogonal Procrutes problem.
    Args:
        S1 (torch.Tensor): First set of points of shape (B, N, 3).
        S2 (torch.Tensor): Second set of points of shape (B, N, 3).
    Returns:
        (torch.Tensor): The first set of points after applying the similarity transformation.
    """

    batch_size = S1.shape[0]
    S1 = S1.permute(0, 2, 1)
    S2 = S2.permute(0, 2, 1)
    # 1. Remove mean.
    mu1 = S1.mean(dim=2, keepdim=True)
    mu2 = S2.mean(dim=2, keepdim=True)
    X1 = S1 - mu1
    X2 = S2 - mu2

    # 2. Compute variance of X1 used for scale.
    var1 = (X1**2).sum(dim=(1, 2))

    # 3. The outer product of X1 and X2.
    K = torch.matmul(X1, X2.permute(0, 2, 1))

    # 4. Solution that Maximizes trace(R'K) is R=U*V', where U, V are singular vectors of K.
    U, s, V = torch.svd(K)
    Vh = V.permute(0, 2, 1)

    # Construct Z that fixes the orientation of R to get det(R)=1.
    Z = torch.eye(U.shape[1]).unsqueeze(0).repeat(batch_size, 1, 1)
    Z[:, -1, -1] *= torch.sign(torch.linalg.det(torch.matmul(U, Vh)))

    # Construct R.
    R = torch.matmul(torch.matmul(V, Z), U.permute(0, 2, 1))

    # 5. Recover scale.
    trace = torch.matmul(R, K).diagonal(offset=0, dim1=-1, dim2=-2).sum(dim=-1)
    scale = (trace / var1).unsqueeze(dim=-1).unsqueeze(dim=-1)

    # 6. Recover translation.
    t = mu2 - scale * torch.matmul(R, mu1)

    # 7. Error:
    S1_hat = scale * torch.matmul(R, S1) + t

    return S1_hat.permute(0, 2, 1)
//  [python]
def compute_similarity_transform(S1: torch.Tensor, S2: torch.Tensor) -> torch.Tensor:
    """
    Computes a similarity transform (sR, t) in a batched way that takes
    a set of 3D points S1 (B, N, 3) closest to a set of 3D points S2 (B, N, 3),
    where R is a 3x3 rotation matrix, t 3x1 translation, s scale.
    i.e. solves the orthogonal Procrutes problem.
    Args:
        S1 (torch.Tensor): First set of points of shape (B, N, 3).
        S2 (torch.Tensor): Second set of points of shape (B, N, 3).
    Returns:
        (torch.Tensor): The first set of points after applying the similarity transformation.
    """

    batch_size = S1.shape[0]
    S1 = S1.permute(0, 2, 1)
    S2 = S2.permute(0, 2, 1)
    # 1. Remove mean.
    mu1 = S1.mean(dim=2, keepdim=True)
    mu2 = S2.mean(dim=2, keepdim=True)
    X1 = S1 - mu1
    X2 = S2 - mu2

    # 2. Compute variance of X1 used for scale.
    var1 = (X1**2).sum(dim=(1, 2))

    # 3. The outer product of X1 and X2.
    K = torch.matmul(X1, X2.permute(0, 2, 1))

    # 4. Solution that Maximizes trace(R'K) is R=U*V', where U, V are singular vectors of K.
    U, S, V = torch.linalg.svd(K)
    Vh = V.permute(0, 2, 1)

    # Construct Z that fixes the orientation of R to get det(R)=1.
    Z = torch.eye(U.shape[1]).unsqueeze(0).repeat(batch_size, 1, 1)
    Z[:, -1, -1] *= torch.sign(torch.linalg.det(torch.matmul(U, Vh)))

    # Construct R.
    R = torch.matmul(torch.matmul(V, Z), U.permute(0, 2, 1))

    # 5. Recover scale.
    trace = torch.matmul(R, K).diagonal(offset=0, dim1=-1, dim2=-2).sum(dim=-1)
    scale = (trace / var1).unsqueeze(dim=-1).unsqueeze(dim=-1)

    # 6. Recover translation.
    t = mu2 - scale * torch.matmul(R, mu1)

    # 7. Error:
    S1_hat = scale * torch.matmul(R, S1) + t

    return S1_hat.permute(0, 2, 1)
//  [python]
def npu_op_exec(self, input1, some, compute_uv=False):
        output_u, output_s, output_v = torch.svd(input1, some, compute_uv)
        output_u = output_u.cpu()
        output_s = output_s.cpu()
        output_v = output_v.cpu()
        return output_u, output_s, output_v
//  [python]
def npu_op_exec(self, input1, some, compute_uv=False):
        output_u, output_s, output_v = torch.linalg.svd(input1, some, compute_uv)
        output_u = output_u.cpu()
        output_s = output_s.cpu()
        output_v = output_v.cpu()
        return output_u, output_s, output_v
//  [python]
def SVDR_w(beforerot,afterrot,scores):# beforerot afterrot Scene2,Scene1
    weight=torch.diag(scores)
    H=torch.matmul(torch.matmul(torch.transpose(afterrot),weight),beforerot)
    U,Sigma,VT=torch.svd(H)
    return torch.matmul(U,VT)
//  [python]
def SVDR_w(beforerot,afterrot,scores):# beforerot afterrot Scene2,Scene1
    weight=torch.diag(scores)
    H=torch.matmul(torch.matmul(torch.transpose(afterrot),weight),beforerot)
    U,Sigma,VT=torch.linalg.svd(H)
    return torch.matmul(U,VT)
//  [python]
def adaptive_mera_update(mps, beta, chi, tol=1e-12, maxiter=50):
    """ update the isometry using iterative SVD update with line search
        mps: the original cMPS
        beta: inverse temperature
        chi: target bond dimension
        return the compressed cMPS
    """
    P = energy_cut(mps, chi)
    last = 9.9e9
    step = 0
    while step < maxiter:
        mps_new = mps.project(P.requires_grad_())
        loss = ln_ovlp(mps_new, mps, beta) - 0.5 * ln_ovlp(mps_new, mps_new.detach(), beta) 
        diff = abs(loss.item() - last)

        #print('adaptive', step, loss.item() - 0.5*ln_ovlp(mps, mps, beta).item())

        if (diff < tol): break

        print(step, end='\r')

        grad = torch.autograd.grad(loss, P)[0]
        last = loss.item() 
        Fidel0 = loss.item() 
        Fidel_test = 1e99

        step += 1
    
        U, _, V = torch.svd(grad)
        #https://mathoverflow.net/questions/262560/natural-ways-of-interpolating-unitary-matrices
        #https://groups.google.com/forum/#!topic/manopttoolbox/2zhx67doXaU
        #interpolate between unitary matrices
        theta = np.pi
        proceed = False
        while proceed == False:
            theta = theta / 2
            if theta < np.pi / 1.9**12: 
                theta = 0
                P_test = P.data
            else:
                P_test = interpolate_cut(U@V.t(), P.data, theta)

            #mix = np.sin(theta) * U@V.t() + np.cos(theta) * P.data
            ##then retraction back to unitary
            #U, _, V = torch.svd(mix)
            #P_test = U@V.t()

            mps_test = mps.project(P_test)
            Fidel1_test = Fidelity(mps_test, mps, beta)
            if Fidel1_test > Fidel0 or np.isclose(theta, 0):
                P = P_test
                proceed=True

    return mps_new
//  [python]
def adaptive_mera_update(mps, beta, chi, tol=1e-12, maxiter=50):
    """ update the isometry using iterative SVD update with line search
        mps: the original cMPS
        beta: inverse temperature
        chi: target bond dimension
        return the compressed cMPS
    """
    P = energy_cut(mps, chi)
    last = 9.9e9
    step = 0
    while step < maxiter:
        mps_new = mps.project(P.requires_grad_())
        loss = ln_ovlp(mps_new, mps, beta) - 0.5 * ln_ovlp(mps_new, mps_new.detach(), beta) 
        diff = abs(loss.item() - last)

        #print('adaptive', step, loss.item() - 0.5*ln_ovlp(mps, mps, beta).item())

        if (diff < tol): break

        print(step, end='\r')

        grad = torch.autograd.grad(loss, P)[0]
        last = loss.item() 
        Fidel0 = loss.item() 
        Fidel_test = 1e99

        step += 1
    
        U, S, V = torch.linalg.svd(grad)
        #https://mathoverflow.net/questions/262560/natural-ways-of-interpolating-unitary-matrices
        #https://groups.google.com/forum/#!topic/manopttoolbox/2zhx67doXaU
        #interpolate between unitary matrices
        theta = np.pi
        proceed = False
        while proceed == False:
            theta = theta / 2
            if theta < np.pi / 1.9**12: 
                theta = 0
                P_test = P.data
            else:
                P_test = interpolate_cut(U@V.t(), P.data, theta)

            #mix = np.sin(theta) * U@V.t() + np.cos(theta) * P.data
            ##then retraction back to unitary
            #U, _, V = torch.svd(mix)
            #P_test = U@V.t()

            mps_test = mps.project(P_test)
            Fidel1_test = Fidelity(mps_test, mps, beta)
            if Fidel1_test > Fidel0 or np.isclose(theta, 0):
                P = P_test
                proceed=True

    return mps_new
//  [python]
def fit(self, source_data: torch.Tensor, target_data: torch.Tensor) -> Mapping[str, Any]:
        translation_matrix = torch.linalg.lstsq(source_data, target_data).solution
        translation_matrix = torch.as_tensor(translation_matrix, dtype=source_data.dtype, device=source_data.device)
        U, _, Vt = torch.svd(translation_matrix)
        translation_matrix = U @ Vt.T
        self.register_buffer("translation_matrix", translation_matrix)
        return {}