Home > tt2 > cross > tt_rc2.m

tt_rc2

PURPOSE ^

[Y]=TT_RC2(D,N,ARR,ELEM_FUN,EPS,[OPTIONS])

SYNOPSIS ^

function [y]=tt_rc2(d,n,elem_fun,eps,varargin)

DESCRIPTION ^

[Y]=TT_RC2(D,N,ARR,ELEM_FUN,EPS,[OPTIONS])
The TT-Renormalization-Cross algorithm
input is: the dimension of the array d, the 
size vector n, the function that computes the prescribed element
of an array, accuracy parameter eps
and also additional arguments specified as 'rmax',10,'nswp',10
'verb',true and so on
 'x0', x0
The elem function has syntax elem_fun(ind); all other additional
information
has to be passed as "anonymous" arguments

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [y]=tt_rc2(d,n,elem_fun,eps,varargin)
0002 %[Y]=TT_RC2(D,N,ARR,ELEM_FUN,EPS,[OPTIONS])
0003 %The TT-Renormalization-Cross algorithm
0004 %input is: the dimension of the array d, the
0005 %size vector n, the function that computes the prescribed element
0006 %of an array, accuracy parameter eps
0007 %and also additional arguments specified as 'rmax',10,'nswp',10
0008 %'verb',true and so on
0009 % 'x0', x0
0010 %The elem function has syntax elem_fun(ind); all other additional
0011 %information
0012 %has to be passed as "anonymous" arguments
0013 
0014 %The algorithm. It needs left & right index sets to be initialized.
0015 %It needs supecores to be precomputed
0016 %It is a good idea to store also the supercores (there will be d-1,
0017 %i think) & update them; also certain indices maybe removed from the
0018 %index set?? we will not do that;
0019 %Two possibilities: current index contains maxvol submatrix;
0020 %If not, increase, increase & increase (maybe even beyond the rank!)
0021 %rank one subtraction can be made very stable
0022 
0023 
0024 %Default parameters
0025 if ( numel(n) == 1 )
0026   n=n*ones(1,d);
0027 end
0028 nswp=10;
0029 rmax=1000;
0030 x0=[];
0031 verb=true;
0032 vec=false; %If there is a vectorization in options, i.e. if elem_fun
0033 %supports vectorized computations of many elements at once
0034 for i=1:2:length(varargin)-1
0035     switch lower(varargin{i})
0036         case 'nswp'
0037             nswp=varargin{i+1};
0038         case 'rmax'
0039             rmax=lower(varargin{i+1});
0040         case 'x0'
0041             x0=varargin{i+1};
0042         case 'verb'
0043             verb=varargin{i+1};
0044         case 'vec'
0045             vec=varargin{i+1};
0046         otherwise
0047             error('Unrecognized option: %s\n',varargin{i});
0048     end
0049 end
0050 
0051 %The initial setup is done.
0052 
0053 %We need initial index sets. Say, the vector of all ones (he-he)
0054 %i_left;
0055 %r_left;
0056 %i_right;
0057 %r_right;
0058 i_left=cell(d,1);
0059 i_right=cell(d,1);
0060 r_left=cell(d,1);
0061 r_right=cell(d,1);
0062 ry=ones(d+1,1); %Initial ranks
0063 %Find fiber maximum
0064 ind=2*ones(d,1);
0065 ind=find_fiber_maximum(elem_fun,ind);
0066 for i=1:d
0067   i_left{i}=ind(i);
0068   i_right{i}=ind(i);
0069   r_left{i}=1;
0070   r_right{i}=1;
0071 end
0072 
0073 %Before we get the multiindex sets (helps to compute s-u-p-e-r-c-o-r-e-s)
0074 
0075 ind_left=get_multi_left(i_left,r_left,ry);
0076 ind_right=get_multi_right(i_right,r_right,ry);
0077 
0078 %Now we have to compute s-u-p-e-r-c-o-r-e-s (not cores!) using ind_left &
0079 %ind_right
0080 super_core=cell(d-1,1);
0081 for i=1:d-1 %There are d-1 s-u-p-e-r-c-o-r-e-s
0082    %Compute the index set for the i-th one
0083    index_set=zeros(d,ry(i),n(i),n(i+1),ry(i+2));
0084    if ( i == 1 )
0085        ileft=zeros(1,0);
0086    else
0087       ileft=ind_left{i-1};    
0088    end
0089    if ( i == d - 1 )
0090       iright = zeros(1,0);
0091    else
0092       iright=ind_right{i+2};
0093    end
0094    for s1=1:ry(i)
0095       for s2=1:ry(i+2)
0096         for i1=1:n(i)
0097            for i2=1:n(i+1)
0098               index_set(:,s1,i1,i2,s2)=[ileft(s1,:),i1,i2,iright(s2,:)];
0099            end
0100         end
0101       end
0102    end
0103    M=ry(i)*n(i)*n(i+1)*ry(i+2);
0104    index_set=reshape(index_set,[d,M]);
0105    if ( vec ) 
0106       super_core{i}=reshape(elem_fun(index_set),[ry(i),n(i),n(i+1),ry(i+2)]);
0107    else
0108        cur_core=zeros(M,1);
0109       for k=1:M
0110          cur_core(k)=elem_fun(index_set(:,k));
0111       end
0112       super_core{i}=reshape(cur_core,[ry(i),n(i),n(i+1),ry(i+2)]);
0113    end
0114    
0115 end
0116 %Initialization is done.
0117 %Now to the main iteration
0118 
0119 %Through all the s-u-p-e-r-c-o-r-e-s
0120 swp=1;
0121 dir='lr';
0122 i=1;
0123 while ( swp <= nswp )
0124    %The method acts as follows.
0125    %1) Test if the current supercore is well approximated by the
0126    %current cross
0127    %2) If yes, do nothing.
0128    %3) If no, add the required indices to the cross and perform
0129    %modifications of the s-u-p-e-r-c-o-r-e-s
0130    
0131    %Nikrena ne soobrajau
0132    %Bilo: (i1,i2,i3,i4,i5)
0133    %Pofiksili (i1,i2), uvelichili r2. Rashirilos' mnojestvo (i2,i3,i4,i5)
0134    %(nikomu ne nujno)
0135    %V seredine: (i1,i2) (i3,i4,i5)+ - uvelichilos' mojectvo
0136    %Kogda uvelichili (i3,i4,i5) viros ry(3), uvelichilos 1 superyadro
0137    cur_core=super_core{i}; 
0138    %we have to convert the pair i_left{i} & r_left{i} to the
0139    %index set for the matrix cur_core
0140    
0141    cur_core=reshape(cur_core,[ry(i)*n(i),n(i+1)*ry(i+2)]);
0142    %i1=get_full_ind(i_left{i},r_left{i});
0143    %i2=get_full_ind(i_right{i+1},r_right{i+1});
0144     %ry(i)*n(i)
0145     
0146     i1=r_left{i}+(i_left{i}-1)*ry(i); 
0147     i2=i_right{i+1}+(r_right{i+1}-1)*n(i+1);
0148   % if ( numel(i1)==2)
0149   %     if ( i1(1) == 2 && i1(2) == 2 )
0150   %   keyboard;
0151   %     end
0152   % end
0153   [i1,i2]=new_cross(cur_core,i1,i2,eps); 
0154        %Increase i_left{i} & i_right{i+1}
0155        [radd_left,iadd_left]=ind2sub([ry(i);n(i)],i1);
0156        [iadd_right,radd_right]=ind2sub([n(i+1);ry(i+2)],i2);
0157        i_left{i}=iadd_left;
0158        r_left{i}=radd_left;
0159        %if ( i == 8 )
0160        %    keyboard
0161        %end
0162        i_right{i+1}=iadd_right;
0163        r_right{i+1}=radd_right;
0164        ry(i+1)=numel(i1);
0165        %Zaglushka
0166        ind_left=get_multi_left(i_left,r_left,ry);
0167        
0168        ind_right=get_multi_right(i_right,r_right,ry);
0169        
0170       %   fprintf('Index set in question: \n');
0171       %   ind_left{3}
0172       % if ( i == 3 && swp == 2 )
0173       %   keyboard;
0174       % end
0175        %keyboard;
0176        if ( i > 1 ) 
0177          %Recompute supercore{i-1}
0178          super_core{i-1}=compute_supercore(i-1,elem_fun,d,n,ry,ind_left,ind_right,vec);
0179        end
0180        if ( i < d - 1)
0181          super_core{i+1}=compute_supercore(i+1,elem_fun,d,n,ry,ind_left,ind_right,vec);
0182          %Recompute supercore{i+1};
0183        end
0184 
0185    %Convert iadd1 to i_left and i_right format; compute new
0186    %ind_left{i+1},ind_right{i+1}
0187    if ( strcmp(dir,'lr') )
0188      if ( i == d-1 )
0189         dir='rl';
0190      else
0191         i=i+1;
0192      end
0193    else
0194      if ( i == 1 )
0195         dir ='lr';
0196         swp=swp+1;
0197      else
0198         i=i-1;
0199      end
0200    end
0201    fprintf('Step %d sweep %d rank=%3.1f \n',i,swp,mean(ry));
0202 end
0203 fprintf('Done! \n');
0204 keyboard;
0205 
0206 
0207 
0208 
0209 
0210 
0211 
0212 return
0213 end
0214 
0215 function [super_core]=compute_supercore(i,elem_fun,d,n,ry,ind_left,ind_right,vec)
0216 %[super_core]=compute_supercore(i,elem_fun,n,ry,ind_left,ind_right)
0217    index_set=zeros(d,ry(i),n(i),n(i+1),ry(i+2));
0218    if ( i == 1 )
0219        ileft=zeros(1,0);
0220    else
0221       ileft=ind_left{i-1};    
0222    end
0223    if ( i == d - 1 )
0224       iright = zeros(1,0);
0225    else
0226       iright=ind_right{i+2};
0227    end
0228    for s1=1:ry(i)
0229       for s2=1:ry(i+2)
0230         for i1=1:n(i)
0231            for i2=1:n(i+1)
0232               index_set(:,s1,i1,i2,s2)=[ileft(s1,:),i1,i2,iright(s2,:)];
0233            end
0234         end
0235       end
0236    end
0237    M=ry(i)*n(i)*n(i+1)*ry(i+2);
0238    index_set=reshape(index_set,[d,M]);
0239    if ( vec ) 
0240       super_core=reshape(elem_fun(index_set),[ry(i),n(i),n(i+1),ry(i+2)]);
0241    else
0242        cur_core=zeros(M,1);
0243       for k=1:M
0244          cur_core(k)=elem_fun(index_set(:,k));
0245       end
0246       super_core=reshape(cur_core,[ry(i),n(i),n(i+1),ry(i+2)]);
0247    end
0248    
0249 
0250 return
0251 end
0252 
0253 function [i1,i2]=new_cross(mat,i1,i2,eps)
0254 %[i1,i2]=enlarge_cross(mat,i1,i2,eps)
0255 %Tests whether the current index set gives a reasonable approximation
0256 %to the matrix, and enlarges the basis if necessary.
0257 %The method acts as follows.
0258 
0259 %A-C*A11^{-1} R
0260 
0261 %sbm=mat(i1,i2);
0262 %[u,s,v]=svd(sbm,'econ');
0263 %nrm=norm(mat);s=diag(s);
0264 %r=numel(find(
0265 %mat_save=mat;
0266 i1=[];
0267 i2=[];
0268 desirata=eps*norm(mat,'fro');
0269 er=norm(mat,'fro');
0270 while ( er > desirata )
0271    %Find maximal element in mat
0272    [~,ind]=max(abs(mat(:)));
0273    ind=tt_ind2sub(size(mat),ind);
0274    i=ind(1); j=ind(2);
0275     i1=[i1;i];
0276     i2=[i2;j];
0277     u1=mat(:,j); u2=mat(i,:);
0278     u1=u1/mat(i,j);
0279     mat=mat-u1*u2;
0280     er=norm(mat,'fro');
0281 end
0282 % i0=[i1;iadd1]; j0=[i2;iadd2];
0283 % sbm=mat_save(i0,j0);
0284 % ss=svd(sbm);
0285 % fprintf('%10.10e \n',ss)
0286 % sbm=mat_save(i1,i2);
0287 % fprintf('AND PREVIOUS \n');
0288 % ss=svd(sbm);
0289 % fprintf('%10.10e \n',ss)
0290 
0291 return
0292 end
0293 
0294 function [ind_left]=get_multi_left(i_left,r_left,ry)
0295 %[ind_left]=get_multi_left(i_left,r_left,ry)
0296 %Computes (all) left multiindex sets for a given compact representation
0297   d=numel(i_left);
0298   ind_left=cell(d,1);
0299   ind_left{1}=i_left{1};
0300   for i=2:d
0301       %ind_cur=zeros(
0302       %ind_cur is an array of size ry(i-1) x i
0303       ind_cur=zeros(ry(i+1),i);
0304       r_prev=r_left{i};
0305       ind_prev=ind_left{i-1};
0306       i_prev=i_left{i};
0307       for s=1:ry(i+1)
0308           %ind_prev(p1(s
0309          ind_cur(s,:)=[ind_prev(r_prev(s),:),i_prev(s)];
0310       end
0311       ind_left{i}=ind_cur;
0312   end
0313 return
0314 end
0315 
0316 function [ind_right]=get_multi_right(i_right,r_right,ry)
0317 %[ind_right]=get_multi_right(i_right,r_right,ry)
0318 %Computes (all) right multiindex sets for a given compact representation
0319   d=numel(i_right);
0320   ind_right=cell(d,1);
0321   ind_right{d}=i_right{d};
0322   for i=d-1:-1:1
0323       %ind_cur=zeros(
0324       %ind_cur is an array of size ry(i) x i
0325       ind_cur=zeros(ry(i),d-i+1);
0326       r_prev=r_right{i};
0327       ind_prev=ind_right{i+1};
0328       i_prev=i_right{i};
0329       for s=1:ry(i)
0330          ind_cur(s,:)=[i_prev(s), ind_prev(r_prev(s),:)];
0331       end
0332       ind_right{i}=ind_cur;
0333   end
0334 
0335 return
0336 end
0337 
0338 function [ind]=find_fiber_maximum(elem_fun,ind)
0339 %[ind]=find_fiber_maximum(elem_fun,ind)
0340 %Simple ALS method to compute (approximate) maximum in a tensor
0341 %In fact, need some non-zero
0342 %fact=2; %If the new one <= fact times larger than the previous, stop
0343 
0344 return
0345 end

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