├── doc ├── figure_tsvd.JPG ├── manual 1.0.pdf ├── figure_functions_tproduct_1.0.JPG └── figure_functions_tproduct_2.0.JPG ├── tproduct toolbox 1.0 ├── teye.m ├── tran.m ├── tsn.m ├── bdiag.m ├── tinv.m ├── tnn.m ├── tprod.m ├── bcirc.m ├── tubalrank.m ├── tqr.m ├── prox_tnn.m ├── tsvd.m └── test.m ├── tproduct toolbox 2.0 (transform) ├── bdiag.m ├── bcirc.m ├── RandOrthMat.m ├── teye.m ├── tsn.m ├── tinv.m ├── tran.m ├── tprod.m ├── tnn.m ├── tmprod.m ├── tubalrank.m ├── lineartransform.m ├── inverselineartransform.m ├── basis_tube.m ├── basis_column.m ├── prox_tnn.m ├── tqr.m ├── unit_eijk.m ├── tsvd.m └── test.m └── README.md /doc/figure_tsvd.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canyilu/Tensor-tensor-product-toolbox/HEAD/doc/figure_tsvd.JPG -------------------------------------------------------------------------------- /doc/manual 1.0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canyilu/Tensor-tensor-product-toolbox/HEAD/doc/manual 1.0.pdf -------------------------------------------------------------------------------- /doc/figure_functions_tproduct_1.0.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canyilu/Tensor-tensor-product-toolbox/HEAD/doc/figure_functions_tproduct_1.0.JPG -------------------------------------------------------------------------------- /doc/figure_functions_tproduct_2.0.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canyilu/Tensor-tensor-product-toolbox/HEAD/doc/figure_functions_tproduct_2.0.JPG -------------------------------------------------------------------------------- /tproduct toolbox 1.0/teye.m: -------------------------------------------------------------------------------- 1 | function I = teye(n,n3) 2 | 3 | % 3 way identity tensor 4 | % I - n*n*n3 tensor 5 | % 6 | % version 1.0 - 18/06/2016 7 | % 8 | % Written by Canyi Lu (canyilu@gmail.com) 9 | % 10 | % 11 | % References: 12 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 13 | % June, 2018. https://github.com/canyilu/tproduct. 14 | % 15 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 16 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 17 | % Norm, arXiv preprint arXiv:1804.03728, 2018 18 | % 19 | 20 | I = zeros(n,n,n3); 21 | I(:,:,1) = eye(n); 22 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/tran.m: -------------------------------------------------------------------------------- 1 | function Xt = tran(X) 2 | 3 | % conjugate transpose of a 3 way tensor 4 | % X - n1*n2*n3 tensor 5 | % Xt - n2*n1*n3 tensor 6 | % 7 | % version 1.0 - 18/06/2016 8 | % 9 | % Written by Canyi Lu (canyilu@gmail.com) 10 | % 11 | % 12 | % References: 13 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 14 | % June, 2018. https://github.com/canyilu/tproduct. 15 | % 16 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 17 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 18 | % Norm, arXiv preprint arXiv:1804.03728, 2018 19 | % 20 | 21 | [n1,n2,n3] = size(X); 22 | Xt = zeros(n2,n1,n3); 23 | Xt(:,:,1) = X(:,:,1)'; 24 | for i = 2 : n3 25 | Xt(:,:,i) = X(:,:,n3-i+2)'; 26 | end 27 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/tsn.m: -------------------------------------------------------------------------------- 1 | function tsn = tsn(X) 2 | 3 | % Tensor spectral norm of a 3 way tensor 4 | % 5 | % X - n1*n2*n3 tensor 6 | % tsn - tensor spectral norm 7 | % 8 | % version 1.0 - 14/06/2018 9 | % version 1.1 - 28/04/2021 a more efficient version 10 | % 11 | % Written by Canyi Lu (canyilu@gmail.com) 12 | % 13 | % 14 | % References: 15 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 16 | % June, 2018. https://github.com/canyilu/tproduct. 17 | % 18 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 19 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 20 | % Norm, TPAMI, 2019 21 | % 22 | 23 | X = fft(X,[],3); 24 | tsn = 0; 25 | for i = 1 : ceil((size(X,3)+1)/2) 26 | tsn = max(tsn,norm(X(:,:,i),2)); 27 | end 28 | 29 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/bdiag.m: -------------------------------------------------------------------------------- 1 | function Xbdiag = bdiag(X) 2 | % 3 | % reformulate a 3 way tensor as a block diagonal matrix 4 | % X - n1*n2*n3 tensor 5 | % Xbdiag - (n1n3)*(n2n3) matrix 6 | % 7 | % version 1.0 - 18/06/2016 8 | % 9 | % Written by Canyi Lu (canyilu@gmail.com) 10 | % 11 | % 12 | % References: 13 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 14 | % June, 2018. https://github.com/canyilu/tproduct. 15 | % 16 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 17 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 18 | % Norm, TPAMI, 2019 19 | % 20 | 21 | [n1,n2,n3] = size(X); 22 | Xbdiag = zeros(n1*n3,n2*n3); 23 | 24 | for i = 1 : n3 25 | Xbdiag((i-1)*n1+1:i*n1,(i-1)*n2+1:i*n2) = X(:,:,i); 26 | end 27 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/bdiag.m: -------------------------------------------------------------------------------- 1 | function Xbdiag = bdiag(X) 2 | % 3 | % reformulate a 3 way tensor as a block diagonal matrix 4 | % X - n1*n2*n3 tensor 5 | % Xbdiag - (n1n3)*(n2n3) matrix 6 | % 7 | % version 1.0 - 18/06/2016 8 | % version 1.1 - 07/11/2018 9 | % 10 | % Written by Canyi Lu (canyilu@gmail.com) 11 | % 12 | % 13 | % References: 14 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 15 | % June, 2018. https://github.com/canyilu/tproduct. 16 | % 17 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 18 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 19 | % Norm, arXiv preprint arXiv:1804.03728, 2018 20 | % 21 | 22 | 23 | sizen = size(X); 24 | Xbdiag = zeros(sizen(1)*sizen(3),sizen(2)*sizen(3)); 25 | 26 | for i = 1 : sizen(3) 27 | Xbdiag((i-1)*sizen(1)+1:i*sizen(1),(i-1)*sizen(2)+1:i*sizen(2)) = X(:,:,i); 28 | end 29 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/tinv.m: -------------------------------------------------------------------------------- 1 | function X = tinv(X) 2 | 3 | % tinv(X) is the inverse of the tensor X of size n*n*n3. 4 | % A warning message is printed if X is badly scaled or 5 | % nearly singular. 6 | % 7 | % version 1.0 - 14/06/2018 8 | % version 1.1 - 28/04/2021 9 | % 10 | % Written by Canyi Lu (canyilu@gmail.com) 11 | % 12 | % References: 13 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 14 | % June, 2018. https://github.com/canyilu/tproduct. 15 | % 16 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 17 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 18 | % Norm, TPAMI, 2019 19 | % 20 | 21 | [n1,n2,n3] = size(X); 22 | if n1 ~= n2 23 | error('Error using tinv. Tensor must be square.'); 24 | end 25 | 26 | X = fft(X,[],3); 27 | I = eye(n1); 28 | halfn3 = ceil((n3+1)/2); 29 | for i = 1 : halfn3 30 | X(:,:,i) = X(:,:,i)\I; 31 | end 32 | for i = halfn3+1 : n3 33 | X(:,:,i) = conj(X(:,:,n3+2-i)); 34 | end 35 | X = ifft(X,[],3); 36 | 37 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/tnn.m: -------------------------------------------------------------------------------- 1 | function tnn = tnn(X) 2 | 3 | % Tensor nuclear norm of a 3 way tensor 4 | % 5 | % X - n1*n2*n3 tensor 6 | % tnn - tensor nuclear norm 7 | % 8 | % version 2.0 - 09/10/2017 9 | % 10 | % Written by Canyi Lu (canyilu@gmail.com) 11 | % 12 | % 13 | % References: 14 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 15 | % June, 2018. https://github.com/canyilu/tproduct. 16 | % 17 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 18 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 19 | % Norm, arXiv preprint arXiv:1804.03728, 2018 20 | % 21 | 22 | n3 = size(X,3); 23 | X = fft(X,[],3); 24 | tnn = 0; 25 | 26 | % i=1 27 | s = svd(X(:,:,1),'econ'); 28 | tnn = tnn+sum(s); 29 | 30 | % i=2,...,halfn3 31 | halfn3 = round(n3/2); 32 | for i = 2 : halfn3 33 | s = svd(X(:,:,i),'econ'); 34 | tnn = tnn+sum(s)*2; 35 | end 36 | 37 | % if n3 is even 38 | if mod(n3,2) == 0 39 | i = halfn3+1; 40 | s = svd(X(:,:,i),'econ'); 41 | tnn = tnn+sum(s); 42 | end 43 | tnn = tnn/n3; 44 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/bcirc.m: -------------------------------------------------------------------------------- 1 | function bX = bcirc(X) 2 | 3 | % The block circulant matrix of a 3 way tensor 4 | % 5 | % X - n1*n2*n3 tensor 6 | % 7 | % bX - block circulant matrix of size (n1*n3)*(n2*n3) 8 | % 9 | % version 1.0 - 15/09/2017 10 | % 11 | % Written by Canyi Lu (canyilu@gmail.com) 12 | % 13 | % We use the Corollary 4 in the paper 14 | % Brian J Olson, Steven W Shaw, Chengzhi Shi, Christophe Pierre, Robert G Parker, 15 | % Circulant matrices and their application to vibration analysis, Applied 16 | % Mechanics Reviews, 2014 17 | % 18 | % 19 | % References: 20 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 21 | % June, 2018. https://github.com/canyilu/tproduct. 22 | % 23 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 24 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 25 | % Norm, TPAMI, 2019 26 | % 27 | 28 | [n1,n2,n3] = size(X); 29 | s = eye(n3,n3); 30 | bX = zeros(n1*n3,n2*n3); 31 | for i = 1 : n3 32 | S = gallery('circul',s(i,:)')'; 33 | bX = bX + kron(S,X(:,:,i)); 34 | end -------------------------------------------------------------------------------- /tproduct toolbox 1.0/tprod.m: -------------------------------------------------------------------------------- 1 | function C = tprod(A,B) 2 | 3 | % Tensor-tensor product of two 3 way tensors: C = A*B 4 | % A - n1*n2*n3 tensor 5 | % B - n2*l*n3 tensor 6 | % C - n1*l*n3 tensor 7 | % 8 | % version 2.0 - 09/10/2017 9 | % version 2.1 - 28/04/2021 10 | % 11 | % Written by Canyi Lu (canyilu@gmail.com) 12 | % 13 | % 14 | % References: 15 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 16 | % June, 2018. https://github.com/canyilu/tproduct. 17 | % 18 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 19 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 20 | % Norm, TPAMI, 2019 21 | % 22 | 23 | [n1,n2,n3] = size(A); 24 | [m1,m2,m3] = size(B); 25 | 26 | if n2 ~= m1 || n3 ~= m3 27 | error('Inner tensor dimensions must agree.'); 28 | end 29 | 30 | A = fft(A,[],3); 31 | B = fft(B,[],3); 32 | C = zeros(n1,m2,n3); 33 | 34 | halfn3 = ceil((n3+1)/2); 35 | for i = 1 : halfn3 36 | C(:,:,i) = A(:,:,i)*B(:,:,i); 37 | end 38 | for i = halfn3+1 : n3 39 | C(:,:,i) = conj(C(:,:,n3+2-i)); 40 | end 41 | C = ifft(C,[],3); 42 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/bcirc.m: -------------------------------------------------------------------------------- 1 | function bX = bcirc(X) 2 | 3 | % The block circulant matrix of a 3 way tensor 4 | % 5 | % X - n1*n2*n3 tensor 6 | % 7 | % bX - block circulant matrix of size (n1*n3)*(n2*n3) 8 | % 9 | % version 1.0 - 15/09/2017 10 | % 11 | % Written by Canyi Lu (canyilu@gmail.com) 12 | % 13 | % We use the Corollary 4 in the paper 14 | % Brian J Olson, Steven W Shaw, Chengzhi Shi, Christophe Pierre, Robert G Parker, 15 | % Circulant matrices and their application to vibration analysis, Applied 16 | % Mechanics Reviews, 2014 17 | % 18 | % 19 | % References: 20 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 21 | % June, 2018. https://github.com/canyilu/tproduct. 22 | % 23 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 24 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 25 | % Norm, arXiv preprint arXiv:1804.03728, 2018 26 | % 27 | 28 | [n1,n2,n3] = size(X); 29 | s = eye(n3,n3); 30 | bX = zeros(n1*n3,n2*n3); 31 | for i = 1 : n3 32 | S = gallery('circul',s(i,:)')'; 33 | bX = bX + kron(S,X(:,:,i)); 34 | end 35 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/tubalrank.m: -------------------------------------------------------------------------------- 1 | function trank = tubalrank(X) 2 | 3 | % The tensor tubal rank of a 3 way tensor 4 | % 5 | % X - n1*n2*n3 tensor 6 | % trank - tensor tubal rank of X 7 | % 8 | % version 2.0 - 14/06/2018 9 | % version 2.1 - 28/04/2021 a more accurate version 10 | % 11 | % Written by Canyi Lu (canyilu@gmail.com) 12 | % 13 | % 14 | % References: 15 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 16 | % June, 2018. https://github.com/canyilu/tproduct. 17 | % 18 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 19 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 20 | % Norm, TPAMI, 2019 21 | % 22 | 23 | X = fft(X,[],3); 24 | [n1,n2,n3] = size(X); 25 | s = zeros(min(n1,n2),1); 26 | 27 | % i=1 28 | s = s + svd(X(:,:,1),'econ'); 29 | % i=2,...,halfn3 30 | halfn3 = round(n3/2); 31 | for i = 2 : halfn3 32 | s = s + svd(X(:,:,i),'econ')*2; 33 | end 34 | % if n3 is even 35 | if mod(n3,2) == 0 36 | i = halfn3+1; 37 | s = s + svd(X(:,:,i),'econ'); 38 | end 39 | s = s/n3^2; 40 | tol = max(n1,n2)*eps(max(s)); 41 | trank = sum(s > tol); 42 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/RandOrthMat.m: -------------------------------------------------------------------------------- 1 | function M=RandOrthMat(n, tol) 2 | % M = RANDORTHMAT(n) 3 | % generates a random n x n orthogonal real matrix. 4 | % 5 | % M = RANDORTHMAT(n,tol) 6 | % explicitly specifies a thresh value that measures linear dependence 7 | % of a newly formed column with the existing columns. Defaults to 1e-6. 8 | % 9 | % In this version the generated matrix distribution *is* uniform over the manifold 10 | % O(n) w.r.t. the induced R^(n^2) Lebesgue measure, at a slight computational 11 | % overhead (randn + normalization, as opposed to rand ). 12 | % 13 | % (c) Ofek Shilon , 2006. 14 | 15 | 16 | if nargin==1 17 | tol=1e-6; 18 | end 19 | 20 | M = zeros(n); % prealloc 21 | 22 | % gram-schmidt on random column vectors 23 | 24 | vi = randn(n,1); 25 | % the n-dimensional normal distribution has spherical symmetry, which implies 26 | % that after normalization the drawn vectors would be uniformly distributed on the 27 | % n-dimensional unit sphere. 28 | 29 | M(:,1) = vi ./ norm(vi); 30 | 31 | for i=2:n 32 | nrm = 0; 33 | while nrmn2, only the first n2 lateral slices of Q and the first n2 horizontal 9 | % slices of R are computed. If n1<=n2, this is the same as [Q,R] = tqr(X). 10 | % 11 | % version 1.0 - 14/06/2018 12 | % version 1.1 - 28/04/2021 13 | % 14 | % Written by Canyi Lu (canyilu@gmail.com) 15 | % 16 | % 17 | % References: 18 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 19 | % June, 2018. https://github.com/canyilu/tproduct. 20 | % 21 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 22 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 23 | % Norm, TPAMI, 2019 24 | % 25 | 26 | [n1,n2,n3] = size(X); 27 | X = fft(X,[],3); 28 | 29 | if n1>n2 && exist('opt', 'var') && strcmp(opt,'econ') == 1 30 | Q = zeros(n1,n2,n3); 31 | R = zeros(n2,n2,n3); 32 | halfn3 = ceil((n3+1)/2); 33 | for i = 1 : halfn3 34 | [Q(:,:,i),R(:,:,i)] = qr(X(:,:,i),0); 35 | end 36 | for i = halfn3+1 : n3 37 | Q(:,:,i) = conj(Q(:,:,n3+2-i)); 38 | R(:,:,i) = conj(R(:,:,n3+2-i)); 39 | end 40 | else 41 | Q = zeros(n1,n1,n3); 42 | R = zeros(n1,n2,n3); 43 | halfn3 = ceil((n3+1)/2); 44 | for i = 1 : halfn3 45 | [Q(:,:,i),R(:,:,i)] = qr(X(:,:,i)); 46 | end 47 | for i = halfn3+1 : n3 48 | Q(:,:,i) = conj(Q(:,:,n3+2-i)); 49 | R(:,:,i) = conj(R(:,:,n3+2-i)); 50 | end 51 | end 52 | 53 | Q = ifft(Q,[],3); 54 | R = ifft(R,[],3); 55 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/prox_tnn.m: -------------------------------------------------------------------------------- 1 | function [X,tnn,trank] = prox_tnn(Y,rho) 2 | 3 | % The proximal operator of the tensor nuclear norm of a 3 way tensor 4 | % 5 | % min_X rho*||X||_*+0.5*||X-Y||_F^2 6 | % 7 | % Y - n1*n2*n3 tensor 8 | % 9 | % X - n1*n2*n3 tensor 10 | % tnn - tensor nuclear norm of X 11 | % trank - tensor tubal rank of X 12 | % 13 | % version 2.1 - 14/06/2018 14 | % 15 | % Written by Canyi Lu (canyilu@gmail.com) 16 | % 17 | % 18 | % References: 19 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 20 | % June, 2018. https://github.com/canyilu/tproduct. 21 | % 22 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 23 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 24 | % Norm, arXiv preprint arXiv:1804.03728, 2018 25 | % 26 | 27 | [n1,n2,n3] = size(Y); 28 | max12 = max(n1,n2); 29 | X = zeros(n1,n2,n3); 30 | Y = fft(Y,[],3); 31 | tnn = 0; 32 | trank = 0; 33 | 34 | % first frontal slice 35 | [U,S,V] = svd(Y(:,:,1),'econ'); 36 | S = diag(S); 37 | S = max(S-rho,0); 38 | tol = max12*eps(max(S)); 39 | r = sum(S > tol); 40 | S = S(1:r); 41 | X(:,:,1) = U(:,1:r)*diag(S)*V(:,1:r)'; 42 | tnn = tnn+sum(S); 43 | trank = max(trank,r); 44 | 45 | % i=2,...,halfn3 46 | halfn3 = round(n3/2); 47 | for i = 2 : halfn3 48 | [U,S,V] = svd(Y(:,:,i),'econ'); 49 | S = diag(S); 50 | S = max(S-rho,0); 51 | tol = max12*eps(max(S)); 52 | r = sum(S > tol); 53 | S = S(1:r); 54 | X(:,:,i) = U(:,1:r)*diag(S)*V(:,1:r)'; 55 | X(:,:,n3+2-i) = conj(X(:,:,i)); 56 | tnn = tnn+sum(S)*2; 57 | trank = max(trank,r); 58 | end 59 | 60 | % if n3 is even 61 | if mod(n3,2) == 0 62 | i = halfn3+1; 63 | [U,S,V] = svd(Y(:,:,i),'econ'); 64 | S = diag(S); 65 | S = max(S-rho,0); 66 | tol = max12*eps(max(S)); 67 | r = sum(S > tol); 68 | S = S(1:r); 69 | X(:,:,i) = U(:,1:r)*diag(S)*V(:,1:r)'; 70 | tnn = tnn+sum(S); 71 | trank = max(trank,r); 72 | end 73 | tnn = tnn/n3; 74 | X = ifft(X,[],3); 75 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/teye.m: -------------------------------------------------------------------------------- 1 | function I = teye(n,n3,transform) 2 | 3 | % Identity tensor of size n*n*n3 under linear transform 4 | % 5 | % Input: 6 | % n, n3 - identity tensor of size n*n*n3 7 | % transform - a structure which defines the linear transform 8 | % transform.L: the linear transform of two types: 9 | % - type I: function handle, i.e., @fft, @dct 10 | % - type II: invertible matrix of size n3*n3 11 | % 12 | % transform.inverseL: the inverse linear transform of transform.L 13 | % - type I: function handle, i.e., @ifft, @idct 14 | % - type II: inverse matrix of transform.L 15 | % 16 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 17 | % L'*L=L*L'=l*I, for some l>0. 18 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 19 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 20 | % If not specified, fft is the default transform, i.e., 21 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 22 | % 23 | % 24 | % Output: 25 | % I - identity tensor of size n*n*n3 26 | % 27 | % 28 | % 29 | % See also lineartransform, inverselineartransform 30 | % 31 | % 32 | % References: 33 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 34 | % June, 2018. https://github.com/canyilu/tproduct. 35 | % 36 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 37 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 38 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 39 | % 40 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 41 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 42 | % 43 | % 44 | % version 1.0 - 01/02/2019 45 | % version 1.1 - 29/04/2021 46 | % 47 | % Written by Canyi Lu (canyilu@gmail.com) 48 | % 49 | 50 | if nargin < 3 51 | % fft is the default transform 52 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 53 | end 54 | I = zeros(n,n,n3); 55 | if isequal(transform.L,@fft) 56 | % fft transform 57 | I(:,:,1) = eye(n); 58 | else 59 | % other transform 60 | for i = 1 : n3 61 | I(:,:,i) = eye(n); 62 | end 63 | I = inverselineartransform(I,transform); 64 | end 65 | 66 | 67 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/tsn.m: -------------------------------------------------------------------------------- 1 | function tsn = tsn(A,transform) 2 | 3 | % Tensor spectral norm of a 3 way tensor under linear transform 4 | % 5 | % Input: 6 | % A - n1*n2*n3 tensor 7 | % transform - a structure which defines the linear transform 8 | % transform.L: the linear transform of two types: 9 | % - type I: function handle, i.e., @fft, @dct 10 | % - type II: invertible matrix of size n3*n3 11 | % 12 | % transform.inverseL: the inverse linear transform of transform.L 13 | % - type I: function handle, i.e., @ifft, @idct 14 | % - type II: inverse matrix of transform.L 15 | % 16 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 17 | % L'*L=L*L'=l*I, for some l>0. 18 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 19 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 20 | % If not specified, fft is the default transform, i.e., 21 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 22 | % 23 | % 24 | % Output: 25 | % tnn - tensor nuclear norm 26 | % 27 | % 28 | % 29 | % See also lineartransform, inverselineartransform 30 | % 31 | % 32 | % References: 33 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 34 | % June, 2018. https://github.com/canyilu/tproduct. 35 | % 36 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 37 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 38 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 39 | % 40 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 41 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 42 | % 43 | % 44 | % version 1.0 - 01/02/2019 45 | % version 1.1 - 29/04/2021 46 | % 47 | % Written by Canyi Lu (canyilu@gmail.com) 48 | % 49 | 50 | if nargin < 2 51 | % fft is the default transform 52 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 53 | end 54 | tsn = 0; 55 | if isequal(transform.L,@fft) 56 | % efficient computing for fft transform 57 | A = fft(A,[],3); 58 | for i = 1 : ceil((size(A,3)+1)/2) 59 | tsn = max(tsn,norm(A(:,:,i),2)); 60 | end 61 | else 62 | % other transform 63 | A = lineartransform(A,transform); 64 | for i = 1 : size(A,3) 65 | tsn = max(tsn,norm(A(:,:,i),2)); 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/tinv.m: -------------------------------------------------------------------------------- 1 | function A = tinv(A,transform) 2 | 3 | % The inverse of a 3 way tensor under linear transform 4 | % A warning message is printed if A is nearly singular 5 | % 6 | % Input: 7 | % A - n1*n2*n3 tensor 8 | % transform - a structure which defines the linear transform 9 | % transform.L: the linear transform of two types: 10 | % - type I: function handle, i.e., @fft, @dct 11 | % - type II: invertible matrix of size n3*n3 12 | % 13 | % transform.inverseL: the inverse linear transform of transform.L 14 | % - type I: function handle, i.e., @ifft, @idct 15 | % - type II: inverse matrix of transform.L 16 | % 17 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 18 | % L'*L=L*L'=l*I, for some l>0. 19 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 20 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 21 | % If not specified, fft is the default transform, i.e., 22 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 23 | % 24 | % 25 | % Output: 26 | % A - inverse of tensor A 27 | % 28 | % 29 | % 30 | % See also lineartransform, inverselineartransform 31 | % 32 | % 33 | % References: 34 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 35 | % June, 2018. https://github.com/canyilu/tproduct. 36 | % 37 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 38 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 39 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 40 | % 41 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 42 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 43 | % 44 | % 45 | % version 1.0 - 01/02/2019 46 | % version 1.1 - 29/04/2021 47 | % 48 | % Written by Canyi Lu (canyilu@gmail.com) 49 | % 50 | 51 | [n1,n2,n3] = size(A); 52 | if n1 ~= n2 53 | error('Error using tinv. Tensor must be square.'); 54 | end 55 | if nargin < 2 56 | % fft is the default transform 57 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 58 | end 59 | 60 | I = eye(n1); 61 | if isequal(transform.L,@fft) 62 | % efficient computing for fft transform 63 | A = fft(A,[],3); 64 | halfn3 = ceil((n3+1)/2); 65 | for i = 1 : halfn3 66 | A(:,:,i) = A(:,:,i)\I; 67 | end 68 | for i = halfn3+1 : n3 69 | A(:,:,i) = conj(A(:,:,n3+2-i)); 70 | end 71 | A = ifft(A,[],3); 72 | else 73 | % other transform 74 | A = lineartransform(A,transform); 75 | for i = 1 : n3 76 | A(:,:,i) = A(:,:,i)\I; 77 | end 78 | A = inverselineartransform(A,transform); 79 | end 80 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/tsvd.m: -------------------------------------------------------------------------------- 1 | function [U,S,V] = tsvd(X,opt) 2 | 3 | % [U,S,V] = tsvd(X,opt) computes a tensor SVD, i.e., X=U*S*V^*, where S 4 | % is a f-diagonal tensor, U and V are orthogonal tensors. 5 | % 6 | % 7 | % Input: 8 | % X - n1*n2*n3 tensor 9 | % opt - options for different outputs of U, S and V: 10 | % 'full': (default) produces full tensor SVD, i.e., X = U*S*V^*, where 11 | % U - n1*n1*n3 12 | % S - n1*n2*n3 13 | % V - n2*n2*n3 14 | % 'econ': produces the "economy size" decomposition. 15 | % Let m = min(n1,n2). Then, X = U*S*V^*, where 16 | % U - n1*m*n3 17 | % S - m*m*n3 18 | % V - n2*m*n3 19 | % 'skinny': produces the skinny tensor SVD. 20 | % Let r be the tensor tubal rank of X. Then, X = U*S*V^*, where 21 | % U - n1*r*n3 22 | % S - r*r*n3 23 | % V - n2*r*n3 24 | % 25 | % Output: U, S, V 26 | % 27 | % version 1.0 - 18/06/2016 28 | % version 2.0 - 09/10/2017 a more efficient version 29 | % version 2.1 - 13/06/2018 add a new input parameter option 30 | % version 2.2 - 28/04/2021 31 | % 32 | % Written by Canyi Lu (canyilu@gmail.com) 33 | % 34 | % 35 | % References: 36 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 37 | % June, 2018. https://github.com/canyilu/tproduct. 38 | % 39 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 40 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 41 | % Norm, TPAMI, 2019 42 | % 43 | 44 | if ~exist('opt', 'var') 45 | opt = 'full'; 46 | end 47 | 48 | [n1,n2,n3] = size(X); 49 | X = fft(X,[],3); 50 | if strcmp(opt,'skinny') == 1 || strcmp(opt,'econ') == 1 51 | min12 = min(n1,n2); 52 | U = zeros(n1,min12,n3); 53 | S = zeros(min12,min12,n3); 54 | V = zeros(n2,min12,n3); 55 | 56 | halfn3 = ceil((n3+1)/2); 57 | for i = 1 : halfn3 58 | [U(:,:,i),S(:,:,i),V(:,:,i)] = svd(X(:,:,i),'econ'); 59 | end 60 | for i = halfn3+1 : n3 61 | U(:,:,i) = conj(U(:,:,n3+2-i)); 62 | V(:,:,i) = conj(V(:,:,n3+2-i)); 63 | S(:,:,i) = S(:,:,n3+2-i); 64 | end 65 | 66 | if strcmp(opt,'skinny') == 1 67 | s1 = diag(sum(S,3))/n3^2; 68 | tol = max(n1,n2)*eps(max(s1)); 69 | trank = sum(s1 > tol); % tensor tubal rank 70 | U = U(:,1:trank,:); 71 | V = V(:,1:trank,:); 72 | S = S(1:trank,1:trank,:); 73 | end 74 | 75 | elseif strcmp(opt,'full') == 1 76 | U = zeros(n1,n1,n3); 77 | S = zeros(n1,n2,n3); 78 | V = zeros(n2,n2,n3); 79 | 80 | halfn3 = ceil((n3+1)/2); 81 | for i = 1 : halfn3 82 | [U(:,:,i),S(:,:,i),V(:,:,i)] = svd(X(:,:,i)); 83 | end 84 | for i = halfn3+1 : n3 85 | U(:,:,i) = conj(U(:,:,n3+2-i)); 86 | V(:,:,i) = conj(V(:,:,n3+2-i)); 87 | S(:,:,i) = S(:,:,n3+2-i); 88 | end 89 | end 90 | 91 | U = ifft(U,[],3); 92 | S = ifft(S,[],3); 93 | V = ifft(V,[],3); 94 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/tran.m: -------------------------------------------------------------------------------- 1 | function At = tran(A,transform) 2 | 3 | % The conjugate transpose of a 3 way tensor under linear transform 4 | % 5 | % Input: 6 | % A - n1*n2*n3 tensor 7 | % transform - a structure which defines the linear transform 8 | % transform.L: the linear transform of two types: 9 | % - type I: function handle, i.e., @fft, @dct 10 | % - type II: invertible matrix of size n3*n3 11 | % 12 | % transform.inverseL: the inverse linear transform of transform.L 13 | % - type I: function handle, i.e., @ifft, @idct 14 | % - type II: inverse matrix of transform.L 15 | % 16 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 17 | % L'*L=L*L'=l*I, for some l>0. 18 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 19 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 20 | % If not specified, fft is the default transform, i.e., 21 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 22 | % 23 | % 24 | % Output: At - n2*n1*n3 tensor 25 | % 26 | % 27 | % 28 | % See also lineartransform, inverselineartransform 29 | % 30 | % 31 | % References: 32 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 33 | % June, 2018. https://github.com/canyilu/tproduct. 34 | % 35 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 36 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 37 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 38 | % 39 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 40 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 41 | % 42 | % 43 | % version 1.0 - 01/02/2019 44 | % version 1.1 - 29/04/2021 45 | % 46 | % Written by Canyi Lu (canyilu@gmail.com) 47 | % 48 | 49 | [n1,n2,n3] = size(A); 50 | if nargin < 2 51 | % fft is the default transform 52 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 53 | end 54 | At = zeros(n2,n1,n3); 55 | if isequal(transform.L,@fft) 56 | % fft transform 57 | At(:,:,1) = A(:,:,1)'; 58 | for i = 2 : n3 59 | At(:,:,i) = A(:,:,n3-i+2)'; 60 | end 61 | elseif isa(transform.L,'function_handle') 62 | A = lineartransform(A,transform); 63 | for i = 1 : n3 64 | At(:,:,i) = A(:,:,i)'; 65 | end 66 | At = inverselineartransform(At,transform); 67 | elseif ismatrix(transform.L) 68 | if isreal(transform.L) 69 | % L is a real matrix 70 | for i = 1 : n3 71 | At(:,:,i) = A(:,:,i)'; 72 | end 73 | else 74 | % L is a complex matrix 75 | A = lineartransform(A,transform); 76 | for i = 1 : n3 77 | At(:,:,i) = A(:,:,i)'; 78 | end 79 | At = inverselineartransform(At,transform); 80 | end 81 | end 82 | 83 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/tprod.m: -------------------------------------------------------------------------------- 1 | function C = tprod(A,B,transform) 2 | 3 | % C = tprod(A,B,transform) computes the tensor-tensor product of two 3 way tensors A and B under linear transform 4 | % 5 | % Input: 6 | % A - n1*n2*n3 tensor 7 | % B - n2*m2*n3 tensor 8 | % transform - a structure which defines the linear transform 9 | % transform.L: the linear transform of two types: 10 | % - type I: function handle, i.e., @fft, @dct 11 | % - type II: invertible matrix of size n3*n3 12 | % 13 | % transform.inverseL: the inverse linear transform of transform.L 14 | % - type I: function handle, i.e., @ifft, @idct 15 | % - type II: inverse matrix of transform.L 16 | % 17 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 18 | % L'*L=L*L'=l*I, for some l>0. 19 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 20 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 21 | % If not specified, fft is the default transform, i.e., 22 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 23 | % 24 | % 25 | % Output: C - n1*m2*n3 tensor, C = A * B 26 | % 27 | % 28 | % 29 | % See also lineartransform, inverselineartransform 30 | % 31 | % 32 | % References: 33 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 34 | % June, 2018. https://github.com/canyilu/tproduct. 35 | % 36 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 37 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 38 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 39 | % 40 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 41 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 42 | % 43 | % 44 | % version 1.0 - 01/02/2019 45 | % version 1.1 - 29/04/2021 46 | % 47 | % Written by Canyi Lu (canyilu@gmail.com) 48 | % 49 | 50 | [n1,n2,n3] = size(A); 51 | [m1,m2,m3] = size(B); 52 | 53 | if n2 ~= m1 || n3 ~= m3 54 | error('Inner tensor dimensions must agree.'); 55 | end 56 | if nargin < 3 57 | % fft is the default transform 58 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 59 | end 60 | 61 | C = zeros(n1,m2,n3); 62 | if isequal(transform.L,@fft) 63 | % efficient computing for fft transform 64 | A = fft(A,[],3); 65 | B = fft(B,[],3); 66 | halfn3 = ceil((n3+1)/2); 67 | for i = 1 : halfn3 68 | C(:,:,i) = A(:,:,i)*B(:,:,i); 69 | end 70 | for i = halfn3+1 : n3 71 | C(:,:,i) = conj(C(:,:,n3+2-i)); 72 | end 73 | C = ifft(C,[],3); 74 | else 75 | % other transform 76 | A = lineartransform(A,transform); 77 | B = lineartransform(B,transform); 78 | for i = 1 : n3 79 | C(:,:,i) = A(:,:,i)*B(:,:,i); 80 | end 81 | C = inverselineartransform(C,transform); 82 | end 83 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/tnn.m: -------------------------------------------------------------------------------- 1 | function tnn = tnn(A,transform) 2 | 3 | % Tensor nuclear norm of a 3 way tensor under linear transform 4 | % 5 | % An error message is printed if the property L'*L=L*L'=l*I, for some l>0, 6 | % of the linear transform does not hold. 7 | % 8 | % Input: 9 | % A - n1*n2*n3 tensor 10 | % transform - a structure which defines the linear transform 11 | % transform.L: the linear transform of two types: 12 | % - type I: function handle, i.e., @fft, @dct 13 | % - type II: invertible matrix of size n3*n3 14 | % 15 | % transform.inverseL: the inverse linear transform of transform.L 16 | % - type I: function handle, i.e., @ifft, @idct 17 | % - type II: inverse matrix of transform.L 18 | % 19 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 20 | % L'*L=L*L'=l*I, for some l>0. 21 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 22 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 23 | % If not specified, fft is the default transform, i.e., 24 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 25 | % 26 | % 27 | % Output: 28 | % tnn - tensor nuclear norm 29 | % 30 | % 31 | % 32 | % See also lineartransform, inverselineartransform 33 | % 34 | % 35 | % References: 36 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 37 | % June, 2018. https://github.com/canyilu/tproduct. 38 | % 39 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 40 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 41 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 42 | % 43 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 44 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 45 | % 46 | % 47 | % version 1.0 - 01/02/2019 48 | % version 1.1 - 29/04/2021 49 | % 50 | % Written by Canyi Lu (canyilu@gmail.com) 51 | % 52 | 53 | n3 = size(A,3); 54 | if nargin == 2 55 | if transform.l < 0 56 | error("property L'*L=L*L'=l*I does not holds for some l>0."); 57 | end 58 | else 59 | % fft is the default transform 60 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 61 | end 62 | 63 | tnn = 0; 64 | if isequal(transform.L,@fft) 65 | % efficient computing for fft transform 66 | A = fft(A,[],3); 67 | % i=1 68 | s = svd(A(:,:,1),'econ'); 69 | tnn = tnn+sum(s); 70 | % i=2,...,halfn3 71 | halfn3 = round(n3/2); 72 | for i = 2 : halfn3 73 | s = svd(A(:,:,i),'econ'); 74 | tnn = tnn+sum(s)*2; 75 | end 76 | % if n3 is even 77 | if mod(n3,2) == 0 78 | i = halfn3+1; 79 | s = svd(A(:,:,i),'econ'); 80 | tnn = tnn+sum(s); 81 | end 82 | tnn = tnn/n3; 83 | else 84 | A = lineartransform(A,transform); 85 | for i = 1 : size(A,3) 86 | s = svd(A(:,:,i),'econ'); 87 | tnn = tnn+sum(s); 88 | end 89 | tnn = tnn/transform.l; 90 | end 91 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/tmprod.m: -------------------------------------------------------------------------------- 1 | function [S,iperm] = tmprod(T,U,mode,transpose,saveperm) 2 | %TMPROD Mode-n tensor-matrix product. 3 | % S = tmprod(T,U,mode) computes the tensor-matrix product of the tensor T 4 | % with the matrices U{1}, ..., U{N} along the modes mode(1), ..., 5 | % mode(N), respectively. Note that in this implementation, the vector 6 | % mode should contain distinct integers. The mode-n tensor-matrix 7 | % products are computed sequentially in a heuristically determined order. 8 | % A mode-n tensor-matrix product results in a new tensor S in which the 9 | % mode-n vectors of a given tensor T are premultiplied by a given matrix 10 | % U{n}, i.e., tens2mat(S,mode(n)) = U{n}*tens2mat(T,mode(n)). 11 | % 12 | % S = tmprod(T,U,mode,'T') and tmprod(T,U,mode,'H') apply the mode-n 13 | % tensor-matrix product using the transposed matrices U{n}.' and 14 | % conjugate transposed matrices U{n}' respectively along mode(n). 15 | % 16 | % [S,iperm] = tmprod(T,U,mode) and S = tmprod(T,U,mode,'saveperm') save 17 | % one permutation operation. In the former case, the tensor-matrix 18 | % product can then be recovered by permute(S,iperm). 19 | % 20 | % See also tens2mat, mat2tens, contract. 21 | 22 | % Authors: Laurent Sorber (Laurent.Sorber@cs.kuleuven.be), 23 | % Nick Vannieuwenhoven (Nick.Vannieuwenhoven@cs.kuleuven.be) 24 | % Marc Van Barel (Marc.VanBarel@cs.kuleuven.be) 25 | % Lieven De Lathauwer (Lieven.DeLathauwer@kuleuven-kulak.be) 26 | 27 | % Check arguments. 28 | if nargin < 4, transpose = 0; end 29 | if nargin < 5, saveperm = false; end 30 | if ischar(saveperm), saveperm = strcmpi(saveperm,'saveperm'); end 31 | switch transpose 32 | case {'T','H'}, m = [2 1]; 33 | otherwise, m = [1 2]; if nargin < 5, saveperm = transpose; end 34 | end 35 | if ~iscell(U), U = {U}; end 36 | if length(U) ~= length(mode) 37 | error('tmprod:NumberOfProducts','length(U) should be length(mode).'); 38 | end 39 | U = U(:)'; mode = mode(:)'; 40 | size_tens = ones(1,max(mode)); 41 | size_tens(1:ndims(T)) = size(T); 42 | if any(cellfun('size',U,m(2)) ~= size_tens(mode)) 43 | error('tmprod:U','size(T,mode(n)) should be size(U{n},%i).',m(2)); 44 | end 45 | 46 | % Sort the order of the mode-n products. 47 | [~,idx] = sort(size_tens(mode)./cellfun('size',U,m(1))); 48 | mode = mode(idx); 49 | U = U(idx); 50 | 51 | % Compute the complement of the set of modes. 52 | n = length(mode); 53 | N = length(size_tens); 54 | bits = ones(1,N); 55 | bits(mode) = 0; 56 | modec = 1:N; 57 | modec = modec(logical(bits(modec))); 58 | 59 | % Prepermute the tensor. 60 | perm = [mode modec]; 61 | size_tens = size_tens(perm); 62 | S = T; if any(mode ~= 1:n), S = permute(S,perm); end 63 | 64 | % Cycle through the n-mode products. 65 | for i = 1:n 66 | size_tens(1) = size(U{i},m(1)); 67 | switch transpose 68 | case 'T' 69 | S = reshape(U{i}.'*reshape(S,size(S,1),[]),size_tens); 70 | case 'H' 71 | S = reshape(U{i}'*reshape(S,size(S,1),[]),size_tens); 72 | otherwise 73 | S = reshape(U{i}*reshape(S,size(S,1),[]),size_tens); 74 | end 75 | if i < n 76 | S = permute(S,[2:N 1]); 77 | size_tens = size_tens([2:N 1]); 78 | end 79 | end 80 | 81 | % Inverse permute the tensor, unless the user intends to do so himself. 82 | iperm(perm([n:N 1:n-1])) = 1:N; 83 | if nargout <= 1 && ~saveperm, S = permute(S,iperm); end 84 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/tubalrank.m: -------------------------------------------------------------------------------- 1 | function trank = tubalrank(A,transform,tol) 2 | 3 | % The tensor tubal rank of a 3 way tensor under linear transform 4 | 5 | % Input: 6 | % A - n1*n2*n3 tensor 7 | % transform - a structure which defines the linear transform 8 | % transform.L: the linear transform of two types: 9 | % - type I: function handle, i.e., @fft, @dct 10 | % - type II: invertible matrix of size n3*n3 11 | % 12 | % transform.inverseL: the inverse linear transform of transform.L 13 | % - type I: function handle, i.e., @ifft, @idct 14 | % - type II: inverse matrix of transform.L 15 | % 16 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 17 | % L'*L=L*L'=l*I, for some l>0. 18 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 19 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 20 | % If not specified, fft is the default transform, i.e., 21 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 22 | % 23 | % 24 | % Output: 25 | % trank - tensor tubal rank 26 | % 27 | % 28 | % 29 | % See also tsvd, lineartransform, inverselineartransform 30 | % 31 | % 32 | % References: 33 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 34 | % June, 2018. https://github.com/canyilu/tproduct. 35 | % 36 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 37 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 38 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 39 | % 40 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 41 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 42 | % 43 | % 44 | % version 1.0 - 01/02/2019 45 | % version 1.1 - 29/04/2021 46 | % 47 | % Written by Canyi Lu (canyilu@gmail.com) 48 | % 49 | 50 | [n1,n2,n3] = size(A); 51 | if nargin < 2 52 | % fft is the default transform 53 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 54 | end 55 | 56 | s = zeros(min(n1,n2),1); 57 | if isequal(transform.L,@fft) 58 | % efficient computing for fft transform 59 | A = fft(A,[],3); 60 | % i=1 61 | s = svd(A(:,:,1),'econ'); 62 | % i=2,...,halfn3 63 | halfn3 = round(n3/2); 64 | for i = 2 : halfn3 65 | s = s + svd(A(:,:,i),'econ')*2; 66 | end 67 | % if n3 is even 68 | if mod(n3,2) == 0 69 | i = halfn3+1; 70 | s = s + svd(A(:,:,i),'econ'); 71 | end 72 | s = s/n3^2; 73 | if nargin < 3 74 | tol = max(n1,n2)*eps(max(s)); 75 | end 76 | trank = sum(s > tol); 77 | else 78 | % other transform 79 | A = lineartransform(A,transform); 80 | for i = 1 : n3 81 | s = s + svd(A(:,:,i),'econ'); 82 | end 83 | if transform.l > 0 84 | % property L'*L=L*L'=l*I, for some l>0, holds. 85 | s = s/n3/transform.l; 86 | else 87 | % the above property does not hold for transform L 88 | s = s/n3/norm(transform.L)^2; 89 | end 90 | if nargin < 3 91 | tol = 1e-10; 92 | end 93 | trank = sum(s > tol); 94 | end 95 | 96 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/lineartransform.m: -------------------------------------------------------------------------------- 1 | function A = lineartransform(A,transform) 2 | 3 | % perform linear transform on tensor A along 3rd dim 4 | % 5 | % A - n1*n2*n3 tensor 6 | % transform - a structure which defines the linear transform 7 | % transform.L: the linear transform of two types: 8 | % - type I: function handle, i.e., @fft, @dct 9 | % - type II: invertible matrix of size n3*n3 10 | % 11 | % transform.inverseL: the inverse linear transform of transform.L 12 | % - type I: function handle, i.e., @ifft, @idct 13 | % - type II: inverse matrix of transform.L 14 | % 15 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 16 | % L'*L=L*L'=l*I, for some l>0. 17 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 18 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 19 | % 20 | % 21 | % Examples: 22 | % n = 10; A = rand(n,n,n); A = lineartransform(A,transform); 23 | % Here transform is defined below: 24 | % 25 | % - linear transform as the funtion handle: 26 | % (1) fft: transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 27 | % A = lineartransform(A,transform) is equivalent to A = fft(A,[],3); 28 | % (2) dct: transform.L = @dct, transform.l = 1, transform.inverseL = @idct. 29 | % A = lineartransform(A,transform) is equivalent to A = dct(A,[],3); 30 | % - linear transform as the invertible matrix: transform.L = L, transform.l = l, transform.inverseL = inverseL, where 31 | % (1) matrix corresponding to discrete Fourier transform (equivalent to fft): L = dftmtx(n3); l = n3; inverseL = L'/l; 32 | % (2) matrix corresponding to discrete cosine transform (equivalent to dct): L = dct(eye(n3)); l = 1; inverseL = L'; 33 | % (3) random orthogonal real matrix: L = RandOrthMat(n3); l = 1; inverseL = L'; 34 | % (4) any invertible matrix, i.e., L = randn(n3); l = -1; inverseL = inv(L); 35 | % 36 | % 37 | % 38 | % See also inverselineartransform 39 | % 40 | % 41 | % References: 42 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 43 | % June, 2018. https://github.com/canyilu/tproduct. 44 | % 45 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 46 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 47 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 48 | % 49 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 50 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 51 | % 52 | % 53 | % version 1.0 - 01/02/2019 54 | % version 1.1 - 29/04/2021 55 | % 56 | % Written by Canyi Lu (canyilu@gmail.com) 57 | % 58 | 59 | if nargin < 2 60 | A = fft(A,[],3); % fft is the default transform 61 | elseif isa(transform.L,'function_handle') 62 | A = transform.L(A,[],3); 63 | elseif ismatrix(transform.L) 64 | n3 = size(A,3); 65 | [l1,l2] = size(transform.L); 66 | if l1 ~= l2 || l1 ~= n3 67 | error('Inner tensor dimensions must agree.'); 68 | end 69 | A = tmprod(A,transform.L,3); 70 | end 71 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/inverselineartransform.m: -------------------------------------------------------------------------------- 1 | function A = inverselineartransform(A,transform) 2 | 3 | % perform inverse transform of the given transform on tensor A along 3rd dim 4 | % 5 | % A - n1*n2*n3 tensor 6 | % transform - a structure which defines the linear transform 7 | % transform.L: the linear transform of two types: 8 | % - type I: function handle, i.e., @fft, @dct 9 | % - type II: invertible matrix of size n3*n3 10 | % 11 | % transform.inverseL: the inverse linear transform of transform.L 12 | % - type I: function handle, i.e., @ifft, @idct 13 | % - type II: inverse matrix of transform.L 14 | % 15 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 16 | % L'*L=L*L'=l*I, for some l>0. 17 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 18 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 19 | % 20 | % 21 | % Examples: 22 | % n = 10; A = rand(n,n,n); A = inverselineartransform(A,transform); 23 | % Here transform is defined below: 24 | % 25 | % - linear transform as the funtion handle: 26 | % (1) fft: transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 27 | % A = inverselineartransform(A,transform) is equivalent to A = ifft(A,[],3); 28 | % (2) dct: transform.L = @dct, transform.l = 1, transform.inverseL = @idct. 29 | % A = inverselineartransform(A,transform) is equivalent to A = idct(A,[],3); 30 | % - linear transform as the invertible matrix: transform.L = L, transform.l = l, transform.inverseL = inverseL, where 31 | % (1) matrix corresponding to discrete Fourier transform (equivalent to fft): L = dftmtx(n3); l = n3; inverseL = L'/l; 32 | % (2) matrix corresponding to discrete cosine transform (equivalent to dct): L = dct(eye(n3)); l = 1; inverseL = L'; 33 | % (3) random orthogonal real matrix: L = RandOrthMat(n3); l = 1; inverseL = L'; 34 | % (4) any invertible matrix, i.e., L = randn(n3); l = -1; inverseL = inv(L); 35 | % 36 | % 37 | % 38 | % See also lineartransform 39 | % 40 | % 41 | % References: 42 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 43 | % June, 2018. https://github.com/canyilu/tproduct. 44 | % 45 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 46 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 47 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 48 | % 49 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 50 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 51 | % 52 | % 53 | % version 1.0 - 01/02/2019 54 | % version 1.1 - 29/04/2021 55 | % 56 | % Written by Canyi Lu (canyilu@gmail.com) 57 | % 58 | 59 | if nargin < 2 60 | A = ifft(A,[],3); % fft is the default transform 61 | elseif isa(transform.L,'function_handle') 62 | A = transform.inverseL(A,[],3); 63 | elseif ismatrix(transform.L) 64 | n3 = size(A,3); 65 | [l1,l2] = size(transform.L); 66 | if l1 ~= l2 || l1 ~= n3 67 | error('Inner tensor dimensions must agree.'); 68 | end 69 | if transform.l > 0 70 | % property L'*L=L*L'=l*I, for some l>0, holds. Then, inv(L)=L'/l 71 | A = tmprod(A,transform.L'/transform.l,3); 72 | else 73 | % arbitrary invertible matrix without the above property 74 | if isfield(transform,'inverseL') 75 | A = tmprod(A,transform.inverseL,3); 76 | else 77 | A = tmprod(A,inv(transform.L),3); 78 | end 79 | end 80 | end 81 | 82 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/basis_tube.m: -------------------------------------------------------------------------------- 1 | function ek = basis_tube(k,n3,transform) 2 | 3 | % The tube basis under real linear transform, a tensor of size 1*1*n3 4 | % For fft, the tube basis ek is a tensor with the (1,1,k)-th entry 5 | % equaling 1 and the rest equaling 0, 6 | % i.e., [ek]_(1,1,k)=1 and 0 otherwise. 7 | % 8 | % For general real linear transform, the tube basis ek is a tensor 9 | % satisfying that L(ek) is with the (1,1,k)-th entry 10 | % equaling 1 and the rest equaling 0, 11 | % i.e., [L(ek)]_(1,1,k) = 1 and 0 otherwise. 12 | % 13 | % The definition of tube basis for fft can be found at our works [1][2]. 14 | % The definition of tube basis for general real linear transforms can be found at our work [3]. 15 | % 16 | % [1] Canyi Lu, et al., Exact Low Tubal Rank Tensor Recovery from Gaussian Measurements. IJCAI. 2018 17 | % [2] Canyi Lu, et al., Tensor Robust Principal Component Analysis with A New Tensor Nuclear Norm, TPAMI, 2019 18 | % [3] Canyi Lu, et al., Exact Recovery of Tensor Robust Principal Component Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 19 | % 20 | % 21 | % Remark: 22 | % The definitions of the tube basis for fft and general real linear 23 | % transforms are different. If fft is used as the linear transform L, 24 | % the resulted tube basis under L is different from the one defined 25 | % for fft. The tube basis is not defined for other complex transforms. 26 | % See more discussions in our work [3]. 27 | % 28 | % 29 | % 30 | % Input: 31 | % k - tube index of nonzero entry 32 | % n3 - tube basis is a tensor of size 1*1*n3 33 | % transform - a structure which defines the linear transform 34 | % transform.L: the linear transform of two types: 35 | % - type I: function handle, i.e., @fft, @dct 36 | % - type II: invertible matrix of size n3*n3 37 | % 38 | % transform.inverseL: the inverse linear transform of transform.L 39 | % - type I: function handle, i.e., @ifft, @idct 40 | % - type II: inverse matrix of transform.L 41 | % 42 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 43 | % L'*L=L*L'=l*I, for some l>0. 44 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 45 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 46 | % If not specified, fft is the default transform, i.e., 47 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 48 | % 49 | % 50 | % Output: ek 51 | % 52 | % 53 | % 54 | % See also basis_column, unit_eijk, lineartransform, inverselineartransform 55 | % 56 | % 57 | % References: 58 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 59 | % June, 2018. https://github.com/canyilu/tproduct. 60 | % 61 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 62 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 63 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 64 | % 65 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 66 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 67 | % 68 | % 69 | % version 1.0 - 01/02/2019 70 | % version 1.1 - 29/04/2021 71 | % 72 | % Written by Canyi Lu (canyilu@gmail.com) 73 | % 74 | 75 | if k > n3 76 | error('%d out of bound %d.', k, n3); 77 | end 78 | 79 | if nargin < 3 80 | % fft is the default transform 81 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 82 | end 83 | 84 | ek = zeros(1,1,n3); 85 | if isequal(transform.L,@fft) 86 | ek(1,1,k) = 1; % fft transform 87 | elseif isa(transform.L,'function_handle') 88 | ek(1,1,k) = 1; 89 | ek = inverselineartransform(ek,transform); 90 | elseif ismatrix(transform.L) 91 | if isreal(transform.L) 92 | % L is a real matrix 93 | ek(1,1,k) = 1; 94 | ek = inverselineartransform(ek,transform); 95 | else 96 | % L is a complex matrix 97 | error('the basis for complex matrix transform is not defined.'); 98 | end 99 | end 100 | 101 | -------------------------------------------------------------------------------- /tproduct toolbox 1.0/test.m: -------------------------------------------------------------------------------- 1 | 2 | % References: 3 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 4 | % June, 2018. https://github.com/canyilu/tproduct. 5 | % 6 | % Canyi Lu, Jiashi Feng, Yudong Chen, Wei Liu, Zhouchen Lin and Shuicheng 7 | % Yan, Tensor Robust Principal Component Analysis with A New Tensor Nuclear 8 | % Norm, arXiv preprint arXiv:1804.03728, 2018 9 | % 10 | % Written by Canyi Lu (canyilu@gmail.com) 11 | % 12 | 13 | clear 14 | 15 | %% discrete Fouriter transformation and FFT 16 | 17 | % FFT on vectors 18 | n = 5; 19 | v = rand(n,1); 20 | vbar1 = fft(v); 21 | F = dftmtx(n); 22 | vbar2 = F*v; 23 | difv = norm(vbar1-vbar2) 24 | 25 | circv = gallery('circul',v)'; % circulant matrix 26 | invF = F'/n; % inverse of F 27 | difv2 = norm(F*circv*invF -diag(vbar1),'fro') % diagonal property 28 | 29 | % FFT on tensors 30 | n1 = 3; 31 | n2 = 4; 32 | n3 = 5; 33 | A = rand(n1,n2,n3); 34 | F = dftmtx(n3); 35 | FI1 = kron(F,eye(n1)); 36 | FI2 = kron(inv(F),eye(n2)); 37 | diagAbar1 = FI1*bcirc(A)*FI2; % diagonal property 38 | Abar = fft(A,[],3); 39 | diagAbar2 = bdiag(Abar); 40 | difA = norm(diagAbar1(:)-diagAbar2(:)) 41 | 42 | 43 | %% tprod: tensor-tensor product 44 | n1 = 4; 45 | n2 = 5; 46 | n3 = 6; 47 | r = 2; 48 | A = rand(n1,r,n3); 49 | B = rand(r,n2,n3); 50 | C = tprod(A,B); 51 | 52 | I = teye(n1,n3); 53 | AI = tprod(I,A); 54 | difAI = norm(A(:)-AI(:)) 55 | 56 | 57 | %% tsvd: tensor singular value decomposition 58 | n1 = 4; 59 | n2 = 5; 60 | n3 = 6; 61 | r = 2; 62 | A = rand(n1,r,n3); 63 | B = rand(r,n2,n3); 64 | C = tprod(A,B); 65 | [U1,S1,V1] = tsvd(C); % full t-SVD 66 | C1 = tprod(tprod(U1,S1),tran(V1)); % C = U*S*V^* 67 | difC1 = norm(C(:)-C1(:)) 68 | difU1 = tprod(tran(U1),U1) - teye(n1,n3); % U^*U = I 69 | difU1 = norm(difU1(:)) 70 | difV1 = tprod(tran(V1),V1) - teye(n2,n3); % V^*V = I 71 | difV1 = norm(difV1(:)) 72 | 73 | [U2,S2,V2] = tsvd(C,'econ'); % "economy size" t-SVD 74 | C2 = tprod(tprod(U2,S2),tran(V2)); % C = U*S*V^* 75 | difC2 = norm(C(:)-C2(:)) 76 | difU2 = tprod(tran(U2),U2) - teye(min(n1,n2),n3); % U^*U = I 77 | difU2 = norm(difU2(:)) 78 | difV2 = tprod(tran(V2),V2) - teye(min(n1,n2),n3); % V^*V = I 79 | difV2 = norm(difV2(:)) 80 | 81 | 82 | [U3,S3,V3] = tsvd(C,'skinny'); % skinny t-SVD 83 | C3 = tprod(tprod(U3,S3),tran(V3)); % C = U*S*V^* 84 | difC3 = norm(C(:)-C3(:)) 85 | r = tubalrank(C); 86 | difU3 = tprod(tran(U3),U3) - teye(r,n3); % U^*U = I 87 | difU3 = norm(difU3(:)) 88 | difV3 = tprod(tran(V3),V3) - teye(r,n3); % V^*V = I 89 | difV3 = norm(difV3(:)) 90 | 91 | 92 | %% trank: tensor tubal rank 93 | n1 = 4; 94 | n2 = 5; 95 | n3 = 6; 96 | r = 2; 97 | A = rand(n1,r,n3); 98 | B = rand(r,n2,n3); 99 | C = tprod(A,B); 100 | trank = tubalrank(C); 101 | diftrank = trank - r 102 | 103 | 104 | %% tnn: tensor nuclear norm 105 | n1 = 4; 106 | n2 = 5; 107 | n3 = 6; 108 | A = rand(n1,n2,n3); 109 | 110 | tnnA1 = tnn(A); 111 | 112 | bcircA = bcirc(A); 113 | tnnA2 = sum(svd(bcircA,'econ'))/n3; 114 | 115 | Abar = fft(A,[],3); 116 | bdiagAbar = bdiag(Abar); 117 | tnnA3 = sum(svd(bdiagAbar,'econ'))/n3; 118 | 119 | diftnn1 = tnnA2-tnnA1 120 | diftnn2 = tnnA3-tnnA1 121 | 122 | %% tsn: tensor spectral norm 123 | n1 = 4; 124 | n2 = 5; 125 | n3 = 6; 126 | A = rand(n1,n2,n3); 127 | tsnA1 = tsn(A); 128 | 129 | bcircA = bcirc(A); 130 | tsnA2 = norm(bcircA,2); 131 | 132 | Abar = fft(A,[],3); 133 | bdiagAbar = bdiag(Abar); 134 | tsnA3 = norm(bdiagAbar,2); 135 | 136 | diftsn1 = tsnA2-tsnA1 137 | diftsn2 = tsnA3-tsnA1 138 | 139 | 140 | %% prox_tnn: proximal operator of tensor nuclear norm 141 | n1 = 4; 142 | n2 = 5; 143 | n3 = 6; 144 | A = rand(n1,n2,n3); 145 | 146 | tau = 10; 147 | X = prox_tnn(A,tau); 148 | tubalrank(X) 149 | 150 | 151 | %% tinv: inverse of a tensor 152 | n = 4; 153 | n3 = 6; 154 | A = rand(n,n,n3); 155 | Ainv = tinv(A); 156 | AAinv1 = tprod(A,Ainv); 157 | AAinv2 = tprod(Ainv,A); 158 | I = teye(n,n3); 159 | difinv1 = norm(AAinv1(:)-I(:)) 160 | difinv2 = norm(AAinv2(:)-I(:)) 161 | 162 | 163 | %% tqr: tensor QR factorization 164 | n1 = 6; 165 | n2 = 5; 166 | n3 = 6; 167 | A = rand(n1,n2,n3); 168 | if n1 > n2 169 | [Q,R] = tqr(A,'econ'); 170 | QtQ = tprod(tran(Q),Q); 171 | I = teye(n2,n3); 172 | diftqr1 = norm(QtQ(:)-I(:)) 173 | end 174 | 175 | [Q,R] = tqr(A); 176 | QtQ = tprod(tran(Q),Q); 177 | I = teye(n1,n3); 178 | diftqr2 = norm(QtQ(:)-I(:)) 179 | 180 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/basis_column.m: -------------------------------------------------------------------------------- 1 | function ei = basis_column(i,n,n3,transform) 2 | 3 | % The column basis under real linear transform, a tensor of size n*1*n3 4 | % For fft, the column basis ei is a tensor with the (i,1,1)-th entry 5 | % equaling 1 and the rest equaling 0, 6 | % i.e., [ei]_(i,1,1)=1 and 0 otherwise. 7 | % 8 | % For general real linear transform, the column basis ei is a tensor 9 | % satisfying that L(ei) is with the (i,1,:) tube being an all one 10 | % tube and the rest equaling 0, 11 | % i.e., [L(ei)]_(i,1,:) = 1 and 0 otherwise. 12 | % 13 | % The definition of column basis for fft can be found at our works [1][2]. 14 | % The definition of column basis for general real linear transforms can be found at our work [3]. 15 | % 16 | % [1] Canyi Lu, et al., Exact Low Tubal Rank Tensor Recovery from Gaussian Measurements. IJCAI. 2018 17 | % [2] Canyi Lu, et al., Tensor Robust Principal Component Analysis with A New Tensor Nuclear Norm, TPAMI, 2019 18 | % [3] Canyi Lu, et al., Exact Recovery of Tensor Robust Principal Component Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 19 | % 20 | % 21 | % Remark: 22 | % The definition of the column basis for general real linear 23 | % transforms is a generalization of the column basis for fft. If fft is 24 | % used as the linear transform L, the resulted column basis under L 25 | % reduces to the one defined for fft. The column basis is not defined 26 | % for other complex transforms. See more discussions in our work [3]. 27 | % 28 | % 29 | % 30 | % Input: 31 | % i - row index of nonzero entries 32 | % n, n3 - column basis is a tensor of size n*1*n3 33 | % transform - a structure which defines the linear transform 34 | % transform.L: the linear transform of two types: 35 | % - type I: function handle, i.e., @fft, @dct 36 | % - type II: invertible matrix of size n3*n3 37 | % 38 | % transform.inverseL: the inverse linear transform of transform.L 39 | % - type I: function handle, i.e., @ifft, @idct 40 | % - type II: inverse matrix of transform.L 41 | % 42 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 43 | % L'*L=L*L'=l*I, for some l>0. 44 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 45 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 46 | % If not specified, fft is the default transform, i.e., 47 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 48 | % 49 | % 50 | % Output: ei 51 | % 52 | % 53 | % 54 | % See also basis_tube, unit_eijk, lineartransform, inverselineartransform 55 | % 56 | % 57 | % References: 58 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 59 | % June, 2018. https://github.com/canyilu/tproduct. 60 | % 61 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 62 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 63 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 64 | % 65 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 66 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 67 | % 68 | % 69 | % version 1.0 - 01/02/2019 70 | % version 1.1 - 29/04/2021 71 | % 72 | % Written by Canyi Lu (canyilu@gmail.com) 73 | % 74 | 75 | if i > n 76 | error('%d out of bound %d.', i, n); 77 | end 78 | 79 | if nargin < 4 80 | % fft is the default transform 81 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 82 | end 83 | 84 | ei = zeros(n,1,n3); 85 | if isequal(transform.L,@fft) 86 | ei(i,1,1) = 1; % fft transform 87 | elseif isa(transform.L,'function_handle') 88 | ei(i,1,:) = ones(1,n3); 89 | ei = inverselineartransform(ei,transform); 90 | elseif ismatrix(transform.L) 91 | if isreal(transform.L) 92 | % L is a real matrix 93 | ei(i,1,:) = ones(1,n3); 94 | ei = inverselineartransform(ei,transform); 95 | else 96 | % L is a complex matrix 97 | error('the basis for complex matrix transform is not defined.'); 98 | end 99 | end 100 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/prox_tnn.m: -------------------------------------------------------------------------------- 1 | function [X, tnn] = prox_tnn(Y,rho,transform) 2 | 3 | % Tensor singular value thresholding (TSVT) which solves the following 4 | % problem (the proximal operator of the tensor nuclear norm under linear transform) 5 | % 6 | % min_X rho*||X||_*+0.5*||X-Y||_F^2 7 | % 8 | % An error message is printed if the property L'*L=L*L'=l*I, for some l>0, 9 | % of the linear transform does not hold. 10 | % 11 | % 12 | % Input: 13 | % Y - n1*n2*n3 tensor 14 | % rho - a constant > 0 15 | % transform - a structure which defines the linear transform 16 | % transform.L: the linear transform of two types: 17 | % - type I: function handle, i.e., @fft, @dct 18 | % - type II: invertible matrix of size n3*n3 19 | % 20 | % transform.inverseL: the inverse linear transform of transform.L 21 | % - type I: function handle, i.e., @ifft, @idct 22 | % - type II: inverse matrix of transform.L 23 | % 24 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 25 | % L'*L=L*L'=l*I, for some l>0. 26 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 27 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 28 | % If not specified, fft is the default transform, i.e., 29 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 30 | % 31 | % 32 | % Output: 33 | % X - the solution of tensor singular value thresholding 34 | % tnn - tensor nuclear norm of X 35 | % 36 | % 37 | % 38 | % See also tnn, tsvd, lineartransform, inverselineartransform 39 | % 40 | % 41 | % References: 42 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 43 | % June, 2018. https://github.com/canyilu/tproduct. 44 | % 45 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 46 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 47 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 48 | % 49 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 50 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 51 | % 52 | % 53 | % version 1.0 - 01/02/2019 54 | % version 1.1 - 29/04/2021 55 | % 56 | % Written by Canyi Lu (canyilu@gmail.com) 57 | % 58 | 59 | [n1,n2,n3] = size(Y); 60 | if nargin == 3 61 | if transform.l < 0 62 | error("property L'*L=L*L'=l*I does not holds for some l>0."); 63 | end 64 | else 65 | % fft is the default transform 66 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 67 | end 68 | 69 | X = zeros(n1,n2,n3); 70 | tnn = 0; 71 | if isequal(transform.L,@fft) 72 | % efficient computing for fft transform 73 | Y = fft(Y,[],3); 74 | % first frontal slice 75 | [U,S,V] = svd(Y(:,:,1),'econ'); 76 | S = diag(S); 77 | r = length(find(S>rho)); 78 | if r >= 1 79 | S = S(1:r)-rho; 80 | X(:,:,1) = U(:,1:r)*diag(S)*V(:,1:r)'; 81 | end 82 | tnn = tnn+sum(S); 83 | % i=2,...,halfn3 84 | halfn3 = round(n3/2); 85 | for i = 2 : halfn3 86 | [U,S,V] = svd(Y(:,:,i),'econ'); 87 | S = diag(S); 88 | r = length(find(S>rho)); 89 | if r >= 1 90 | S = S(1:r)-rho; 91 | X(:,:,i) = U(:,1:r)*diag(S)*V(:,1:r)'; 92 | end 93 | X(:,:,n3+2-i) = conj(X(:,:,i)); 94 | tnn = tnn+sum(S)*2; 95 | end 96 | % if n3 is even 97 | if mod(n3,2) == 0 98 | i = halfn3+1; 99 | [U,S,V] = svd(Y(:,:,i),'econ'); 100 | S = diag(S); 101 | r = length(find(S>rho)); 102 | if r >= 1 103 | S = S(1:r)-rho; 104 | X(:,:,i) = U(:,1:r)*diag(S)*V(:,1:r)'; 105 | end 106 | tnn = tnn+sum(S); 107 | end 108 | tnn = tnn/n3; 109 | X = ifft(X,[],3); 110 | else 111 | % other transform 112 | Y = lineartransform(Y,transform); 113 | for i = 1 : n3 114 | [U,S,V] = svd(Y(:,:,i),'econ'); 115 | S = diag(S); 116 | r = length(find(S>rho)); 117 | if r >= 1 118 | S = S(1:r)-rho; 119 | X(:,:,i) = U(:,1:r)*diag(S)*V(:,1:r)'; 120 | tnn = tnn+sum(S); 121 | end 122 | end 123 | tnn = tnn/transform.l; 124 | X = inverselineartransform(X,transform); 125 | end 126 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/tqr.m: -------------------------------------------------------------------------------- 1 | function [Q,R] = tqr(A,transform,opt) 2 | 3 | % Tensor orthogonal-triangular decomposition under linear transform 4 | % 5 | % [Q,R] = tqr(A,transform), where A is n1*n2*n3, produces an n1*n2*n3 upper triangular 6 | % tensor R and an n1*n1*n3 orthogonal tensor Q so that A = Q*R. 7 | % 8 | % [Q,R] = tqr(A,transform,'econ') produces the "economy size" decomposition. 9 | % If n1>n2, only the first n2 lateral slices of Q and the first n2 horizontal 10 | % slices of R are computed. If n1<=n2, this is the same as [Q,R] = tqr(A). 11 | % 12 | % 13 | % Input: 14 | % A - n1*n2*n3 tensor 15 | % transform - a structure which defines the linear transform 16 | % transform.L: the linear transform of two types: 17 | % - type I: function handle, i.e., @fft, @dct 18 | % - type II: invertible matrix of size n3*n3 19 | % 20 | % transform.inverseL: the inverse linear transform of transform.L 21 | % - type I: function handle, i.e., @ifft, @idct 22 | % - type II: inverse matrix of transform.L 23 | % 24 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 25 | % L'*L=L*L'=l*I, for some l>0. 26 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 27 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 28 | % If not specified, fft is the default transform, i.e., 29 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 30 | % 31 | % opt - options for different outputs of Q and R: 32 | % - 'econ': produces the "economy size" decomposition. 33 | % - If not specified (default), produces full decomposition, i.e., A = Q*R, where 34 | % A - n1*n2*n3 35 | % Q - n1*n1*n3 36 | % R - n1*n2*n3 37 | % 38 | % 39 | % Output: Q, R 40 | % 41 | % 42 | % 43 | % See also lineartransform, inverselineartransform 44 | % 45 | % 46 | % References: 47 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 48 | % June, 2018. https://github.com/canyilu/tproduct. 49 | % 50 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 51 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 52 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 53 | % 54 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 55 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 56 | % 57 | % 58 | % version 1.0 - 01/02/2019 59 | % version 1.1 - 29/04/2021 60 | % 61 | % Written by Canyi Lu (canyilu@gmail.com) 62 | % 63 | 64 | [n1,n2,n3] = size(A); 65 | if nargin < 2 66 | % fft is the default transform 67 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 68 | end 69 | 70 | if isequal(transform.L,@fft) 71 | % efficient computing for fft transform 72 | A = fft(A,[],3); 73 | if n1>n2 && exist('opt', 'var') && strcmp(opt,'econ') == 1 74 | Q = zeros(n1,n2,n3); 75 | R = zeros(n2,n2,n3); 76 | halfn3 = ceil((n3+1)/2); 77 | for i = 1 : halfn3 78 | [Q(:,:,i),R(:,:,i)] = qr(A(:,:,i),0); 79 | end 80 | for i = halfn3+1 : n3 81 | Q(:,:,i) = conj(Q(:,:,n3+2-i)); 82 | R(:,:,i) = conj(R(:,:,n3+2-i)); 83 | end 84 | else 85 | Q = zeros(n1,n1,n3); 86 | R = zeros(n1,n2,n3); 87 | halfn3 = ceil((n3+1)/2); 88 | for i = 1 : halfn3 89 | [Q(:,:,i),R(:,:,i)] = qr(A(:,:,i)); 90 | end 91 | for i = halfn3+1 : n3 92 | Q(:,:,i) = conj(Q(:,:,n3+2-i)); 93 | R(:,:,i) = conj(R(:,:,n3+2-i)); 94 | end 95 | end 96 | Q = ifft(Q,[],3); 97 | R = ifft(R,[],3); 98 | else 99 | % other transform 100 | A = lineartransform(A,transform); 101 | if n1>n2 && exist('opt', 'var') && strcmp(opt,'econ') == 1 102 | Q = zeros(n1,n2,n3); 103 | R = zeros(n2,n2,n3); 104 | for i = 1 : n3 105 | [Q(:,:,i),R(:,:,i)] = qr(A(:,:,i),0); 106 | end 107 | else 108 | Q = zeros(n1,n1,n3); 109 | R = zeros(n1,n2,n3); 110 | for i = 1 : n3 111 | [Q(:,:,i),R(:,:,i)] = qr(A(:,:,i)); 112 | end 113 | end 114 | Q = inverselineartransform(Q,transform); 115 | R = inverselineartransform(R,transform); 116 | end 117 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/unit_eijk.m: -------------------------------------------------------------------------------- 1 | function eijk = unit_eijk(i,j,k,n1,n2,n3,transform) 2 | 3 | % Return the n1*n2*n3 sized tensor eijk which is related to the unit tensor under linear transform 4 | % For fft, eijk is the unit tensor with its (i,j,k)-th entry 5 | % equaling 1 and the rest equaling 0, 6 | % i.e., [eijk]_(i,j,k)=1 and 0 otherwise. 7 | % 8 | % 9 | % For general real linear transform, eijk satisfies that L(eijk) is the 10 | % unit tensor with its (i,j,k)-th entry 11 | % equaling 1 and the rest equaling 0, 12 | % i.e., [L(eijk)]_(i,j,k)=1 and 0 otherwise. 13 | % 14 | % The definition and property of the unit tensor for fft can be found at our works [1][2]. 15 | % The definition and property of the unit tensor for general real linear transforms can be found at our work [3]. 16 | % 17 | % [1] Canyi Lu, et al., Exact Low Tubal Rank Tensor Recovery from Gaussian Measurements. IJCAI. 2018 18 | % [2] Canyi Lu, et al., Tensor Robust Principal Component Analysis with A New Tensor Nuclear Norm, TPAMI, 2019 19 | % [3] Canyi Lu, et al., Exact Recovery of Tensor Robust Principal Component Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 20 | % 21 | % 22 | % Remark: 23 | % Tensor eijk has a property that eijk=ei*ek*ej^T, where ei and ej 24 | % are column basis and ek is the tube basis. Note that the 25 | % definitions of tube basis for fft and general real linear transform 26 | % are different. So the definitions of eijk for fft and general real 27 | % linear transforms are different. If fft is used as the linear 28 | % transform L, the resulted eijk under L is different from the one 29 | % defined for fft. Tensor eijk is not defined for other complex 30 | % transforms. See more discussions in our work [3]. 31 | % 32 | % 33 | % 34 | % Input: 35 | % i,j,k - index of nonzero entry of eijk or L(eijk) 36 | % n1,n2,n3 - eijk size n1*n2*n3 37 | % transform - a structure which defines the linear transform 38 | % transform.L: the linear transform of two types: 39 | % - type I: function handle, i.e., @fft, @dct 40 | % - type II: invertible matrix of size n3*n3 41 | % 42 | % transform.inverseL: the inverse linear transform of transform.L 43 | % - type I: function handle, i.e., @ifft, @idct 44 | % - type II: inverse matrix of transform.L 45 | % 46 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 47 | % L'*L=L*L'=l*I, for some l>0. 48 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 49 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 50 | % If not specified, fft is the default transform, i.e., 51 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 52 | % 53 | % 54 | % Output: eijk 55 | % 56 | % 57 | % 58 | % See also basis_column, basis_tube, lineartransform, inverselineartransform 59 | % 60 | % 61 | % References: 62 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 63 | % June, 2018. https://github.com/canyilu/tproduct. 64 | % 65 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 66 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 67 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 68 | % 69 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 70 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 71 | % 72 | % 73 | % version 1.0 - 01/02/2019 74 | % version 1.1 - 29/04/2021 75 | % 76 | % Written by Canyi Lu (canyilu@gmail.com) 77 | % 78 | 79 | if i > n1 80 | error('%d out of bound %d.', i, n1); 81 | elseif j > n2 82 | error('%d out of bound %d.', j, n2); 83 | elseif k > n3 84 | error('%d out of bound %d.', k, n3); 85 | end 86 | 87 | if nargin < 7 88 | % fft is the default transform 89 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 90 | end 91 | eijk = zeros(n1,n2,n3); 92 | if isequal(transform.L,@fft) 93 | eijk(i,j,k) = 1; % fft transform 94 | elseif isa(transform.L,'function_handle') 95 | eijk(i,j,k) = 1; 96 | eijk = inverselineartransform(eijk,transform); 97 | elseif ismatrix(transform.L) 98 | if isreal(transform.L) 99 | % L is a real matrix 100 | eijk(i,j,k) = 1; 101 | eijk = inverselineartransform(eijk,transform); 102 | else 103 | % L is a complex matrix 104 | error('the basis for complex matrix transform is not defined.'); 105 | end 106 | end 107 | 108 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/tsvd.m: -------------------------------------------------------------------------------- 1 | function [U,S,V] = tsvd(A,transform,opt) 2 | 3 | % [U,S,V] = tsvd(A,transform,opt) computes the tensor SVD under linear transform, i.e., A=U*S*V^*, where S 4 | % is a f-diagonal tensor, U and V are orthogonal under linear transform. 5 | % 6 | % 7 | % Input: 8 | % A - n1*n2*n3 tensor 9 | % transform - a structure which defines the linear transform 10 | % transform.L: the linear transform of two types: 11 | % - type I: function handle, i.e., @fft, @dct 12 | % - type II: invertible matrix of size n3*n3 13 | % 14 | % transform.inverseL: the inverse linear transform of transform.L 15 | % - type I: function handle, i.e., @ifft, @idct 16 | % - type II: inverse matrix of transform.L 17 | % 18 | % transform.l: a constant which indicates whether the following property holds for the linear transform or not: 19 | % L'*L=L*L'=l*I, for some l>0. 20 | % - transform.l > 0: indicates that the above property holds. Then we set transform.l = l. 21 | % - transform.l < 0: indicates that the above property does not hold. Then we can set transform.l = c, for any constant c < 0. 22 | % If not specified, fft is the default transform, i.e., 23 | % transform.L = @fft, transform.l = n3, transform.inverseL = @ifft. 24 | % 25 | % opt - options for different outputs of U, S and V: 26 | % 'full': (default) produces full tensor SVD, i.e., A = U*S*V^*, where 27 | % U - n1*n1*n3 28 | % S - n1*n2*n3 29 | % V - n2*n2*n3 30 | % 'econ': produces the "economy size" decomposition. 31 | % Let m = min(n1,n2). Then, A = U*S*V^*, where 32 | % U - n1*m*n3 33 | % S - m*m*n3 34 | % V - n2*m*n3 35 | % 'skinny': produces the skinny tensor SVD. 36 | % Let r be the tensor tubal rank of A. Then, A = U*S*V^*, where 37 | % U - n1*r*n3 38 | % S - r*r*n3 39 | % V - n2*r*n3 40 | % 41 | % 42 | % Output: U, S, V 43 | % 44 | % 45 | % 46 | % See also lineartransform, inverselineartransform 47 | % 48 | % 49 | % References: 50 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 51 | % June, 2018. https://github.com/canyilu/tproduct. 52 | % 53 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 54 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 55 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 56 | % 57 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 58 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 59 | % 60 | % 61 | % version 1.0 - 01/02/2019 62 | % version 1.1 - 29/04/2021 63 | % 64 | % Written by Canyi Lu (canyilu@gmail.com) 65 | % 66 | 67 | if nargin < 3 68 | opt = 'full'; 69 | end 70 | [n1,n2,n3] = size(A); 71 | if nargin < 2 72 | % fft is the default transform 73 | transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 74 | end 75 | 76 | if isequal(transform.L,@fft) 77 | % efficient computing for fft transform 78 | A = fft(A,[],3); 79 | if strcmp(opt,'skinny') == 1 || strcmp(opt,'econ') == 1 80 | min12 = min(n1,n2); 81 | U = zeros(n1,min12,n3); 82 | S = zeros(min12,min12,n3); 83 | V = zeros(n2,min12,n3); 84 | 85 | halfn3 = ceil((n3+1)/2); 86 | for i = 1 : halfn3 87 | [U(:,:,i),S(:,:,i),V(:,:,i)] = svd(A(:,:,i),'econ'); 88 | end 89 | for i = halfn3+1 : n3 90 | U(:,:,i) = conj(U(:,:,n3+2-i)); 91 | V(:,:,i) = conj(V(:,:,n3+2-i)); 92 | S(:,:,i) = S(:,:,n3+2-i); 93 | end 94 | if strcmp(opt,'skinny') == 1 95 | s1 = diag(sum(S,3))/n3^2; 96 | tol = max(n1,n2)*eps(max(s1)); 97 | trank = sum(s1 > tol); % tensor tubal rank 98 | U = U(:,1:trank,:); 99 | V = V(:,1:trank,:); 100 | S = S(1:trank,1:trank,:); 101 | end 102 | 103 | elseif strcmp(opt,'full') == 1 104 | U = zeros(n1,n1,n3); 105 | S = zeros(n1,n2,n3); 106 | V = zeros(n2,n2,n3); 107 | 108 | halfn3 = ceil((n3+1)/2); 109 | for i = 1 : halfn3 110 | [U(:,:,i),S(:,:,i),V(:,:,i)] = svd(A(:,:,i)); 111 | end 112 | for i = halfn3+1 : n3 113 | U(:,:,i) = conj(U(:,:,n3+2-i)); 114 | V(:,:,i) = conj(V(:,:,n3+2-i)); 115 | S(:,:,i) = S(:,:,n3+2-i); 116 | end 117 | end 118 | U = ifft(U,[],3); 119 | S = ifft(S,[],3); 120 | V = ifft(V,[],3); 121 | else 122 | % other transform 123 | A = lineartransform(A,transform); 124 | if strcmp(opt,'skinny') == 1 || strcmp(opt,'econ') == 1 125 | min12 = min(n1,n2); 126 | U = zeros(n1,min12,n3); 127 | S = zeros(min12,min12,n3); 128 | V = zeros(n2,min12,n3); 129 | for i = 1 : n3 130 | [U(:,:,i),S(:,:,i),V(:,:,i)] = svd(A(:,:,i),'econ'); 131 | end 132 | if strcmp(opt,'skinny') == 1 133 | if transform.l > 0 134 | % property L'*L=L*L'=l*I, for some l>0, holds. 135 | s1 = diag(sum(S,3))/n3/transform.l; 136 | else 137 | % the above property does not hold for transform L 138 | s1 = diag(sum(S,3))/n3/norm(transform.L)^2; 139 | end 140 | tol = 1e-10; 141 | trank = sum(s1 > tol); % tensor tubal rank 142 | U = U(:,1:trank,:); 143 | V = V(:,1:trank,:); 144 | S = S(1:trank,1:trank,:); 145 | end 146 | elseif strcmp(opt,'full') == 1 147 | U = zeros(n1,n1,n3); 148 | S = zeros(n1,n2,n3); 149 | V = zeros(n2,n2,n3); 150 | for i = 1 : n3 151 | [U(:,:,i),S(:,:,i),V(:,:,i)] = svd(A(:,:,i)); 152 | end 153 | end 154 | U = inverselineartransform(U,transform); 155 | S = inverselineartransform(S,transform); 156 | V = inverselineartransform(V,transform); 157 | end 158 | 159 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Tensor-Tensor Product Toolbox 2.0 (updated in April, 2021) 2 | 3 | ### 1. T-product Toolbox 1.0 4 | 5 | The tensor-tensor product (t-product) [1] is a natural generalization of matrix multiplication. Based on t-product, many operations on matrix can be extended to tensor cases, including tensor SVD (see an illustration in the figure below), tensor spectral norm, tensor nuclear norm [2] and many others. 6 |

7 | 8 |

9 | 10 | The linear algebraic structure of tensors are similar to the matrix cases. We have tensor-tensor product, tensor SVD, tensor inverse and some other reated concepts extended from matrices. The detailed definitions of these tensor concepts, operations and tensor factorizations are given at https://canyilu.github.io/publications/2018-software-tproduct.pdf. We develop a Matlab toolbox to implement several basic operations on tensors based on t-product. See a list of implemented functions in t-product toolbox 1.0 below. 11 |

12 | 13 |

14 | 15 | ### 2. T-product Toolbox 2.0 16 | 17 | The original t-product [1] uses the discrete Fourier transform and uses the fast Fourier transform (FFT) for efficient computing. It is further generlaized to the t-product under arbitrary invertible linear transform in [2]. Thus, all the concepts (e.g., tsvd, tensor inverse) of t-product under FFT can be generalized to t-product under general linear transforms. If the linear transform satisfies where , then we can define a more general tensor nuclear norm induced by the t-product under this linear transform. Then we develop a more general Matlab toolbox to implement t-product under general linear transform. See a list of implemented functions in t-product toolbox 2.0 below. 18 |

19 | 20 |

21 | 22 | For the definitions of t-product and related concepts under linear transform, please refer to [2] and our works [6,7]. We will provide a document to give the details in the future. 23 | 24 | ### 3. Examples 25 | Simply run the following routine to test all the above functions: 26 | ```matlab 27 | test.m 28 | ``` 29 | 30 | ### 4. Citation 31 | 32 |

In citing this toolbox in your papers, please use the following references:

33 | 34 |
 35 | C. Lu. Tensor-Tensor Product Toolbox. Carnegie Mellon University, June 2018. https://github.com/canyilu/tproduct.
 36 | C. Lu, J. Feng, Y. Chen, W. Liu, Z. Lin, and S. Yan. Tensor robust principal component analysis with a new tensor
 37 | nuclear norm. IEEE Transactions on Pattern Analysis and Machine Intelligence, 2019.
 38 | C. Lu, X. Peng, and Y. Wei. Low-Rank Tensor Completion With a New Tensor Nuclear Norm Induced by Invertible Linear Transforms. IEEE International Conference on Computer Vision and Pattern Recognition (CVPR), 2019
 39 | 
40 | 41 |

The corresponding BiBTeX citations are given below:

42 |
 43 | @manual{lu2018tproduct,
 44 |   author       = {Lu, Canyi},
 45 |   title        = {Tensor-Tensor Product Toolbox},
 46 |   organization = {Carnegie Mellon University},
 47 |   month        = {June},
 48 |   year         = {2018},
 49 |   note         = {\url{https://github.com/canyilu/tproduct}}
 50 | }
 51 | @article{lu2018tensor,
 52 |   author       = {Lu, Canyi and Feng, Jiashi and Chen, Yudong and Liu, Wei and Lin, Zhouchen and Yan, Shuicheng},
 53 |   title        = {Tensor Robust Principal Component Analysis with A New Tensor Nuclear Norm},
 54 |   journal      = {IEEE Transactions on Pattern Analysis and Machine Intelligence},
 55 |   year         = {2019}
 56 | }
 57 | @inproceedings{lu2019tensor,
 58 |   author       = {Lu, Canyi and Peng, Xi and Wei, Yunchao},
 59 |   title        = {Low-Rank Tensor Completion With a New Tensor Nuclear Norm Induced by Invertible Linear Transforms},
 60 |   journal      = {CVPR},
 61 |   year         = {2019}
 62 | }
 63 | 
64 | 65 | 66 | ### 5. Version History 67 | - Version 1.0 was released on June, 2018. It implements the functions of t-product and related concepts under fast Fourier transform. 68 | - Version 2.0 was released on April, 2021. It implements the functions of t-product and related concepts under general invertible linear transform. The fast Fourier transform is the default transform. 69 | + Most functions are direct generalization from the fast Fourier transform to general linear transform, e.g., ```tprod```, ```tran```, ```teye```, ```tinv```, ```tsvd```, ```tubalrank```, ```tsn```, ```tnn```, ```prox_tnn``` and ```tqr```. 70 | + Some functions are new (not included in Version 1.0), e.g., ```basis_column```, ```basis_tube``` and ```unit_eijk```. 71 | + Some functions in Version 1.0 are updated, e.g., the setting of parameter tol in ```tubalrank``` and ```tsvd``` is updated, and ```tprod```, ```tsn```, ```tinv``` and ```tqr``` are updated. 72 | 73 | 74 | 75 | ### 6. Related Toolboxes 76 | The t-product toolbox has been applied in our works for tensor roubst PCA [3,4], low-rank tensor completion and low-rank tensor recovery from Gaussian measurements [5]. The t-product under linear transform has also been applied in tensor completion [6] and tensor robust PCA [7]. Some more models are included in LibADMM toolbox [8]. 77 | 83 | 84 | References 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 97 | 98 |
[1]M. E. Kilmer and C. D. Martin. Factorization strategies for third-order tensors. Linear Algebra and its Applications. 435(3):641–658, 2011.
[2]M. E. Kilmer and S. Aeron. Tensor-Tensor Products with Invertible Linear Transforms. Linear Algebra and its Applications. 2015.
[3]C. Lu, J. Feng, Y. Chen, W. Liu, Z. Lin, and S. Yan. Tensor robust principal component analysis with a new tensor nuclear norm. IEEE Transactions on Pattern Analysis and Machine Intelligence, 2019.
[4]C. Lu, J. Feng, Y. Chen, W. Liu, Z. Lin, and S. Yan. Tensor robust principal component analysis: Exact recovery of corrupted low-rank tensors via convex optimization. In IEEE International Conference on Computer Vision and Pattern Recognition, 2016.
[5]C. Lu, J. Feng, Z. Lin, and S. Yan. Exact low tubal rank tensor recovery from Gaussian measurements. In International Joint Conference on Artificial Intelligence, 2018.
[6]C. Lu, X. Peng, and Y. Wei. Low-Rank Tensor Completion With a New Tensor Nuclear Norm Induced by Invertible Linear Transforms. IEEE International Conference on Computer Vision and Pattern Recognition (CVPR), 2019.
[7]C. Lu. Exact Recovery of Tensor Robust Principal Component Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019.
[8]C. Lu, J. Feng, S. Yan, Z. Lin. A Unified Alternating Direction Method of Multipliers by Majorization Minimization. IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 40, pp. 527-541, 2018. 96 |
99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /tproduct toolbox 2.0 (transform)/test.m: -------------------------------------------------------------------------------- 1 | % 2 | % References: 3 | % 4 | % Canyi Lu, Tensor-Tensor Product Toolbox. Carnegie Mellon University. 5 | % June, 2018. https://github.com/canyilu/tproduct. 6 | % 7 | % Canyi Lu, Xi Peng, Yunchao Wei, Low-Rank Tensor Completion With a New Tensor 8 | % Nuclear Norm Induced by Invertible Linear Transforms. IEEE International 9 | % Conference on Computer Vision and Pattern Recognition (CVPR), 2019 10 | % 11 | % Canyi Lu, Pan Zhou. Exact Recovery of Tensor Robust Principal Component 12 | % Analysis under Linear Transforms. arXiv preprint arXiv:1907.08288. 2019 13 | % 14 | % 15 | % Written by Canyi Lu (canyilu@gmail.com) 16 | % 17 | 18 | clear 19 | %% tprod 20 | n1 = 2; 21 | n2 = 3; 22 | n3 = 5; 23 | m2 = 3; 24 | A = rand(n1,n2,n3); 25 | B = rand(n2,m2,n3); 26 | 27 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 28 | % transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 29 | % transform.L = dftmtx(n3); transform.l = n3; 30 | % transform.L = dct(eye(n3)); transform.l = 1; 31 | % transform.L = RandOrthMat(n3); transform.l = 1; 32 | transform.L = randn(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 33 | transform.L = randn(n3)+i*(rand(n3)-1); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 34 | 35 | C = tprod(A,B,transform); 36 | 37 | %% tran 38 | n1 = 2; 39 | n2 = 2; 40 | n3 = 2; 41 | A = rand(n1,n2,n3); 42 | 43 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 44 | transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 45 | % transform.L = dftmtx(n3); transform.l = n3; 46 | % transform.L = dct(eye(n3)); transform.l = 1; 47 | % transform.L = RandOrthMat(n3); transform.l = 1; 48 | % transform.L = randn(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 49 | transform.L = randn(n3)+i*rand(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 50 | 51 | At = tran(A,transform); 52 | 53 | %% teye 54 | n1 = 3; 55 | n2 = 3; 56 | n3 = 4; 57 | A = rand(n1,n2,n3); 58 | 59 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 60 | % transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 61 | % transform.L = dftmtx(n3); transform.l = n3; 62 | % transform.L = dct(eye(n3)); transform.l = 1; 63 | % transform.L = RandOrthMat(n3); transform.l = 1; 64 | % transform.L = randn(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 65 | transform.L = randn(n3)+i*rand(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 66 | 67 | I = teye(n1,n3,transform); 68 | AI1 = tprod(A,I,transform); 69 | AI2 = tprod(I,A,transform); 70 | dif_teye1 = norm(A(:)-AI1(:)) 71 | dif_teye2 = norm(A(:)-AI2(:)) 72 | 73 | %% tubalrank 74 | n1 = 15; 75 | n2 = 15; 76 | n3 = 200; 77 | r = 10; 78 | A = rand(n1,r,n3); 79 | B = rand(r,n2,n3); 80 | 81 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 82 | % transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 83 | % transform.L = dftmtx(n3); transform.l = n3; 84 | % transform.L = dct(eye(n3)); transform.l = 1; 85 | % transform.L = RandOrthMat(n3); transform.l = 1; 86 | transform.L = randn(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 87 | transform.L = randn(n3)+i*rand(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 88 | 89 | 90 | C = tprod(A,B,transform); 91 | trank = tubalrank(C,transform); 92 | dif_tubalrank = trank - r 93 | 94 | %% tsn 95 | n1 = 30; 96 | n2 = 40; 97 | n3 = 20; 98 | A = rand(n1,n2,n3); 99 | 100 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 101 | % transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 102 | % transform.L = dftmtx(n3); transform.l = n3; 103 | % transform.L = dct(eye(n3)); transform.l = 1; 104 | % transform.L = RandOrthMat(n3); transform.l = 1; 105 | transform.L = randn(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 106 | transform.L = randn(n3)+i*rand(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 107 | 108 | [U,S,V] = tsvd(A,transform,'skinny'); 109 | 110 | tsn1 = tsn(A,transform); 111 | Sbar = lineartransform(S,transform); 112 | tsn2 = max(Sbar(:)) 113 | dif_tsn = tsn1 - tsn2 114 | 115 | %% tnn 116 | n1 = 30; 117 | n2 = 40; 118 | n3 = 20; 119 | A = rand(n1,n2,n3); 120 | 121 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 122 | % transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 123 | % transform.L = dftmtx(n3); transform.l = n3; 124 | transform.L = dct(eye(n3)); transform.l = 1; 125 | 126 | [U,S,V] = tsvd(A,transform,'skinny'); 127 | 128 | tnn1 = tnn(A,transform); 129 | tnn2 = S.*teye(n1,n3,transform); tnn2 = sum(tnn2(:)); 130 | dif_tnn = tnn1-tnn2 131 | 132 | %% prox_tnn 133 | n1 = 5; 134 | n2 = 6; 135 | n3 = 4; 136 | A = rand(n1,n2,n3); 137 | 138 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 139 | transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 140 | % transform.L = dftmtx(n3); transform.l = n3; 141 | % transform.L = dct(eye(n3)); transform.l = 1; 142 | % transform.L = RandOrthMat(n3); transform.l = 1; 143 | 144 | rho = 0.5; 145 | prox = prox_tnn(A,rho,transform); 146 | 147 | %% tinv 148 | n1 = 9 149 | n2 = 9 150 | n3 = 10 151 | A = rand(n1,n2,n3); 152 | 153 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 154 | % transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 155 | % transform.L = dftmtx(n3); transform.l = n3; 156 | % transform.L = dct(eye(n3)); transform.l = 1; 157 | % transform.L = RandOrthMat(n3); transform.l = 1; 158 | transform.L = randn(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 159 | transform.L = randn(n3)+i*rand(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 160 | 161 | Ainv = tinv(A,transform); 162 | Ieye = teye(n1,n3,transform); 163 | AAinv1 = tprod(A,Ainv,transform); 164 | AAinv2 = tprod(Ainv,A,transform); 165 | 166 | res_inv1 = norm(Ieye(:)-AAinv1(:)) 167 | res_inv2 = norm(Ieye(:)-AAinv2(:)) 168 | 169 | %% tsvd 170 | n1 = 20; 171 | n2 = 27; 172 | n3 = 40; 173 | r = 10; 174 | 175 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 176 | % transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 177 | % transform.L = dftmtx(n3); transform.l = n3; 178 | % transform.L = dct(eye(n3)); transform.l = 1; 179 | % transform.L = RandOrthMat(n3); transform.l = 1; 180 | transform.L = randn(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 181 | transform.L = randn(n3)+i*rand(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 182 | 183 | A = rand(n1,r,n3); 184 | B = rand(r,n2,n3); 185 | C = tprod(A,B,transform); 186 | 187 | [U,S,V] = tsvd(C,transform,'skinny'); 188 | USV1 = tprod(U,S,transform); 189 | USV1 = tprod(USV1,tran(V,transform),transform); 190 | dif_tsvd1 = norm(C(:)-USV1(:)) 191 | dif_trank = r - size(U,2) 192 | 193 | [U,S,V] = tsvd(C,transform,'econ'); 194 | USV2 = tprod(U,S,transform); 195 | USV2 = tprod(USV2,tran(V,transform),transform); 196 | dif_tsvd2 = norm(C(:)-USV2(:)) 197 | 198 | [U,S,V] = tsvd(C,transform,'full'); 199 | USV3 = tprod(U,S,transform); 200 | USV3 = tprod(USV3,tran(V,transform),transform); 201 | dif_tsvd3 = norm(C(:)-USV3(:)) 202 | 203 | %% qr 204 | 205 | n1 = 20; 206 | n2 = 15; 207 | n3 = 12; 208 | A = rand(n1,n2,n3); 209 | 210 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 211 | % transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 212 | % transform.L = dftmtx(n3); transform.l = n3; 213 | % transform.L = dct(eye(n3)); transform.l = 1; 214 | % transform.L = RandOrthMat(n3); transform.l = 1; 215 | % transform.L = randn(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 216 | transform.L = randn(n3)+i*rand(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 217 | 218 | 219 | [Q,R] = tqr(A,transform,'econ'); 220 | QR = tprod(Q,R,transform); 221 | dif_qr1 = norm(A(:)-QR(:)) 222 | 223 | [Q,R] = tqr(A,transform); 224 | QR = tprod(Q,R,transform); 225 | dif_qr2 = norm(A(:)-QR(:)) 226 | 227 | %% basis_tube, basis_column, unit_eijk 228 | 229 | n1 = 5; 230 | n2 = 4; 231 | n3 = 4; 232 | 233 | i = 2; 234 | j = 2; 235 | k = 2; 236 | 237 | % transform.L = @fft; transform.l = n3; transform.inverseL = @ifft; 238 | % transform.L = @dct; transform.l = 1; transform.inverseL = @idct; 239 | % transform.L = dftmtx(n3); transform.l = n3; 240 | % transform.L = dct(eye(n3)); transform.l = 1; 241 | % transform.L = RandOrthMat(n3); transform.l = 1; 242 | transform.L = randn(n3); transform.l = -1; transform.inverseL = inv(transform.L); % arbitrary invertible matrix 243 | 244 | 245 | ek = basis_tube(k,n3,transform); 246 | Lek = lineartransform(ek,transform); 247 | 248 | ei = basis_column(i,n1,n3,transform); 249 | Lei = lineartransform(ei,transform); 250 | ej = basis_column(j,n2,n3,transform); 251 | 252 | eijk = tprod(ei,ek,transform); 253 | eijk = tprod(eijk,tran(ej,transform),transform); 254 | Leijk = lineartransform(eijk,transform); 255 | 256 | eijk2 = unit_eijk(i,j,k,n1,n2,n3,transform); 257 | Leijk2 = lineartransform(eijk2,transform); 258 | 259 | 260 | 261 | --------------------------------------------------------------------------------