Tensor rounding in TT1.0 format [TT]=TT_COMPR2(TT,EPS) Reapproximates the given TT-tensor with prescribed accuracy EPS. Please avoid its usage: it will be removed in future releases. Use round() from the object-oriented version TT-Toolbox 2.2, 2009-2012 This is TT Toolbox, written by Ivan Oseledets et al. Institute of Numerical Mathematics, Moscow, Russia webpage: http://spring.inm.ras.ru/osel For all questions, bugs and suggestions please mail ivan.oseledets@gmail.com ---------------------------
0001 function [tt] = tt_compr2(tt,eps, max_r) 0002 %Tensor rounding in TT1.0 format 0003 % [TT]=TT_COMPR2(TT,EPS) Reapproximates the given TT-tensor with 0004 % prescribed accuracy EPS. Please avoid its usage: it will be removed in 0005 % future releases. Use round() from the object-oriented version 0006 % 0007 % 0008 % TT-Toolbox 2.2, 2009-2012 0009 % 0010 %This is TT Toolbox, written by Ivan Oseledets et al. 0011 %Institute of Numerical Mathematics, Moscow, Russia 0012 %webpage: http://spring.inm.ras.ru/osel 0013 % 0014 %For all questions, bugs and suggestions please mail 0015 %ivan.oseledets@gmail.com 0016 %--------------------------- 0017 0018 d = size(tt,1); 0019 %First, estimate the logarithm of the squared norm, and then --- the norm 0020 %of each core :-) 0021 nrm_full=tt_dot2(tt,tt); 0022 nrm1=nrm_full/(2*d); nrm1=exp(nrm1); 0023 0024 exists_max_r=1; 0025 if ((nargin<3)||(isempty(max_r))) 0026 exists_max_r=0; 0027 end; 0028 0029 if ( nrm_full < log(1e-200) ) %Something really small 0030 n=size(tt{1},1); 0031 tt{1}=zeros(n,1); 0032 n=size(tt{d},1); 0033 tt{d}=ones(n,1); 0034 for i=2:d-1 0035 n=size(tt{i},1); 0036 tt{i}=ones(n,1,1); 0037 end 0038 return 0039 end 0040 %nrmf=zeros(d,1); %Place to store the norms of QR-factors 0041 %first, we orthogonalize the tensor from right to left until the first mode 0042 mat=tt{d}; 0043 [q,rv]=qr(mat,0); rv=rv./nrm1; q=q.*nrm1; 0044 tt{d}=q; 0045 for i=(d-1):-1:2 0046 tt{i} = ten_conv(tt{i},3,conj(rv')); 0047 ncur=size(tt{i},1); 0048 r2=size(tt{i},2); 0049 r3=size(tt{i},3); 0050 core=permute(tt{i},[1,3,2]); 0051 core=reshape(core,[ncur*r3,r2]); 0052 [tt{i},rv]=qr(core,0); rv=rv./nrm1; 0053 rnew=min(r2,ncur*r3); 0054 tt{i}=reshape(tt{i}.*nrm1,[ncur,r3,rnew]); 0055 tt{i}=permute(tt{i},[1,3,2]); 0056 end 0057 tt{1}=tt{1}*conj(rv'); 0058 %nrmf(1)=norm(tt{1},'fro'); 0059 %nrm_full=sum(log(nrmf(1:d))); nrm1=nrm_full/d; nrm1=exp(nrm1); %This would 0060 %be the norm of each core 0061 %Now gradually start compression from the left, using the knowledge 0062 %of norms 0063 mat=tt{1}; 0064 %return; 0065 mat(abs(mat)<1e-300)=0; 0066 [u0,s0,ru]=svd(mat,0); 0067 %If no scaling factors were taken out, 0068 %then everything would be simple --- nrm=norm(diag(s0)) is the norm, 0069 %singular values are filtered at absolute accuracy eps*nrm/sqrt(d-1) 0070 %Here the "True" s0 matrix is up to factor of product of nrm(2:d) 0071 %so for it we can filter the singular values just at 0072 %eps*nrmf(1)/sqrt{d-1} 0073 %nrmf(1)=norm(diag(s0)); 0074 %nrm=norm(diag(s0)); 0075 eps1=eps*norm(diag(s0))/sqrt(d-1); %This is the absolute accuracy to filter with 0076 %r0=my_chop2(diag(s0),eps1); 0077 r0=numel(find(s0>eps1)); 0078 if (exists_max_r) r0 = min(r0, max_r); end; 0079 %keyboard; 0080 %r0=rank(mat,eps1); 0081 u0=u0(:,1:r0); 0082 s0=diag(s0); 0083 s0=s0(1:r0); % -eps1*sign(s0); 0084 ru=ru(:,1:r0)*diag(s0)./nrm1; %This should be scaled properly 0085 %ru=ru; 0086 tt{1}=u0.*nrm1; %Now it is properly scaled 0087 for i=2:d-1 0088 %Convolve tt{i} over the second index 0089 % fprintf('norm_tt{%d}=%g, norm_ru = %g\n', i, norm(reshape(tt{i}, size(tt{i},1)*size(tt{i},2), size(tt{i},3)), 'fro'), norm(ru,'fro')); 0090 tt{i}=ten_conv(tt{i},2,conj(ru)); 0091 ncur=size(tt{i},1); 0092 r2=size(tt{i},2); 0093 r3=size(tt{i},3); 0094 core=reshape(tt{i},[ncur*r2,r3]); 0095 %r=rank(core,eps1); 0096 %keyboard; 0097 core(abs(core)<1e-300)=0; 0098 [u0,s0,ru]=svd(core,0); 0099 0100 nrm=norm(diag(s0)); 0101 eps1=eps*nrm/sqrt(d-1); %Nothing more 0102 %keyboard; 0103 %r=my_chop2(diag(s0),eps1); 0104 r=numel(find(s0>eps1)); 0105 if (exists_max_r) r = min(r, max_r); end; 0106 u0=u0(:,1:r); 0107 s0=(s0(1:r,1:r))./nrm1; 0108 ru=ru(:,1:r)*s0; 0109 core=u0.*nrm1; 0110 tt{i}=reshape(core,[ncur,r2,r]); 0111 end 0112 tt{d}=tt{d}*conj(ru); 0113 return 0114 end