Home > tt2 > @tt_tensor > round.m

round

PURPOSE ^

Approximate TT-tensor with another one with specified accuracy

SYNOPSIS ^

function [tt]=round(tt,varargin)

DESCRIPTION ^

Approximate TT-tensor with another one with specified accuracy
   [TT]=ROUND(TT,EPS) Approximate TT-tensor with relative accuracy EPS

   [TT]=ROUND(TT,EPS,RMAX) Approximate TT-tensor with relative accuracy 
   EPS and maximal rank RMAX. RMAX can be array of ranks or a number


 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
---------------------------

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [tt]=round(tt,varargin)
0002 %Approximate TT-tensor with another one with specified accuracy
0003 %   [TT]=ROUND(TT,EPS) Approximate TT-tensor with relative accuracy EPS
0004 %
0005 %   [TT]=ROUND(TT,EPS,RMAX) Approximate TT-tensor with relative accuracy
0006 %   EPS and maximal rank RMAX. RMAX can be array of ranks or a number
0007 %
0008 %
0009 % TT-Toolbox 2.2, 2009-2012
0010 %
0011 %This is TT Toolbox, written by Ivan Oseledets et al.
0012 %Institute of Numerical Mathematics, Moscow, Russia
0013 %webpage: http://spring.inm.ras.ru/osel
0014 %
0015 %For all questions, bugs and suggestions please mail
0016 %ivan.oseledets@gmail.com
0017 %---------------------------
0018 
0019 %
0020 if (nargin == 2 )
0021   eps=varargin{1};
0022   rmax=prod(size(tt));
0023 elseif ( nargin == 3 )
0024   eps=varargin{1};
0025   rmax=varargin{2};
0026 end
0027 d=tt.d;
0028 n=tt.n;
0029 r=tt.r;
0030 if (numel(rmax) == 1 )
0031   rmax=rmax*ones(d+1,1); 
0032 end
0033 pos=tt.ps;
0034 cr=tt.core;
0035 pos1=1;
0036 nrm=zeros(d,1);
0037 core0=cr(1:r(1)*n(1)*r(2));
0038 %Orthogonalization from left-to-tight
0039 for i=1:d-1
0040    core0=reshape(core0,[r(i)*n(i),r(i+1)]);
0041    [core0,ru]=qr(core0,0); nrm(i+1)=norm(ru,'fro');
0042    if (nrm(i+1)~=0)
0043     ru=ru./nrm(i+1);
0044    end;
0045    core1=cr(pos(i+1):pos(i+2)-1);
0046    core1=reshape(core1,[r(i+1),n(i+1)*r(i+2)]);
0047    core1=ru*core1;
0048    r(i+1)=size(core0,2);
0049    cr(pos1:pos1-1+r(i)*n(i)*r(i+1))=core0(:);
0050    cr(pos1+r(i)*n(i)*r(i+1):pos1+r(i)*n(i)*r(i+1)+r(i+1)*n(i+1)*r(i+2)-1)=core1(:);
0051    core0=core1;
0052    pos1=pos1+r(i)*n(i)*r(i+1);
0053 end
0054 pos1=pos1+r(d)*n(d)*r(d+1)-1;
0055 cr=cr(1:pos1); %Truncate storage if required
0056  ep=eps/sqrt(d-1);
0057 pos=cumsum([1;n.*r(1:d).*r(2:d+1)]); 
0058 core0=cr(pos1-r(d)*n(d)*r(d+1)+1:pos1);
0059  for i=d:-1:2
0060      %core0=core(pos(i):pos(i+1)-1);
0061      core1=cr(pos(i-1):pos(i)-1); 
0062      core0=reshape(core0,[r(i),n(i)*r(i+1)]);
0063      core1=reshape(core1,[r(i-1)*n(i-1),r(i)]);
0064      [u,s,v]=svd(core0,'econ');
0065      s=diag(s); r1=my_chop2(s,norm(s)*ep);
0066      r1=min(r1,rmax(i));
0067      u=u(:,1:r1);s=s(1:r1); v=v(:,1:r1);
0068      u=u*diag(s);
0069      r(i)=r1;
0070      core1=core1*u;
0071      core0=v';
0072      cr(pos1-r(i)*n(i)*r(i+1)+1:pos1)=core0(:);
0073      cr(pos1-r(i)*n(i)*r(i+1)-r(i-1)*n(i-1)*r(i)+1:pos1-r(i)*n(i)*r(i+1))=core1(:);
0074      %cr=core(pos(i):pos(i+1)-1);
0075      pos1=pos1-r(i)*n(i)*r(i+1);
0076      core0=core1;
0077  end
0078  pos1=pos1-r(1)*n(1)*r(2);
0079  cr=cr(pos1+1:numel(cr)); %Truncate unwanted elements;
0080  tt.r=r;
0081  tt.ps=cumsum([1;tt.n.*tt.r(1:d).*tt.r(2:d+1)]);
0082  pp=cr(1:r(1)*n(1)*r(2));
0083  nrm(1)=norm(pp,'fro');
0084  if (nrm(1)~=0)
0085      pp = pp./nrm(1);
0086  end;
0087  cr(1:r(1)*n(1)*r(2))=pp;
0088  %Now a simple trick: balance the product of numbers;
0089  %All cores are orthogonal except the first one. Thus, we know the norm
0090  nrm0=sum(log(abs(nrm))); 
0091  nrm0=nrm0/d; nrm0=exp(nrm0);
0092  if (nrm0~=0)
0093      %Construct normalization of norm
0094      for i=1:d-1
0095          nrm(i+1)=nrm(i+1)*nrm(i)/nrm0;
0096          nrm(i)=nrm0;
0097      end
0098  end;
0099  %Finally redistribute the norm
0100  ps=tt.ps;
0101  for i=1:d
0102     core1=cr(ps(i):ps(i+1)-1);
0103     core1=core1*nrm(i);
0104     cr(ps(i):ps(i+1)-1)=core1;
0105  end
0106  tt.core=cr;
0107 return
0108 end

Generated on Wed 08-Feb-2012 18:20:24 by m2html © 2005