Home > tt2 > solve > dmrg_solve2.m

dmrg_solve2

PURPOSE ^

Solution of linear systems in TT-format via DMRG iteration

SYNOPSIS ^

function [x, sweeps]=dmrg_solve2(A, y, eps,varargin)

DESCRIPTION ^

Solution of linear systems in TT-format via DMRG iteration
   [X,SWEEPS]=DMRG_SOLVE2(A,Y,EPS,OPTIONS) Attempts to solve the linear
   system A*X = Y with accuracy EPS using the two-sided DMRG iteration.
   Matrix A has to be given in the TT-format, right-hand side Y should be
   given in the TT-format also. Options are provided in form
   'PropertyName1',PropertyValue1,'PropertyName2',PropertyValue2 and so
   on. The parameters are set to default (in brackets in the following) 
   The list of option names and default values are:
       o x0 - initial approximation [random rank-2 tensor] 
       o P - preconditioner  [I]
       o nswp - maximal number of DMRG sweeps [10]
       o rmax - maximal TT-rank of the solution [1000]
       o verb - verbosity level, 0-silent, 1-sweep info, 2-block info [1]
       o max_full_size - maximal size of the local matrix to full solver 
       [2500]
       o local_prec: Local preconditioner, 'als' - ALS-Richardson
       iteration, 'selfprec' (Saad selfpreconditioner) ['als']
       o prec_compr - compression for local precs [1e-3]
       o prec_tol - tolerance for local precs [1e-1]
       o prec_iters - number of local iterations [15]
       o use_self_prec - Use self_prec [ true | {false} ]
       o gmres_iters - number of local gmres restarts [2]
       o nrestart - dimension of local gmres [40]
       Example:
           d=8; f=8; 
           mat=tt_qlaplace_dd(d*ones(1,f)); %Laplace in the QTT-format
           rhs=tt_ones(2,d*f); Right-hand side of all ones
           sol=dmrg_solve2(mat,rhs,1e-6);


 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:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [x, sweeps]=dmrg_solve2(A, y, eps,varargin)
0002 %Solution of linear systems in TT-format via DMRG iteration
0003 %   [X,SWEEPS]=DMRG_SOLVE2(A,Y,EPS,OPTIONS) Attempts to solve the linear
0004 %   system A*X = Y with accuracy EPS using the two-sided DMRG iteration.
0005 %   Matrix A has to be given in the TT-format, right-hand side Y should be
0006 %   given in the TT-format also. Options are provided in form
0007 %   'PropertyName1',PropertyValue1,'PropertyName2',PropertyValue2 and so
0008 %   on. The parameters are set to default (in brackets in the following)
0009 %   The list of option names and default values are:
0010 %       o x0 - initial approximation [random rank-2 tensor]
0011 %       o P - preconditioner  [I]
0012 %       o nswp - maximal number of DMRG sweeps [10]
0013 %       o rmax - maximal TT-rank of the solution [1000]
0014 %       o verb - verbosity level, 0-silent, 1-sweep info, 2-block info [1]
0015 %       o max_full_size - maximal size of the local matrix to full solver
0016 %       [2500]
0017 %       o local_prec: Local preconditioner, 'als' - ALS-Richardson
0018 %       iteration, 'selfprec' (Saad selfpreconditioner) ['als']
0019 %       o prec_compr - compression for local precs [1e-3]
0020 %       o prec_tol - tolerance for local precs [1e-1]
0021 %       o prec_iters - number of local iterations [15]
0022 %       o use_self_prec - Use self_prec [ true | {false} ]
0023 %       o gmres_iters - number of local gmres restarts [2]
0024 %       o nrestart - dimension of local gmres [40]
0025 %       Example:
0026 %           d=8; f=8;
0027 %           mat=tt_qlaplace_dd(d*ones(1,f)); %Laplace in the QTT-format
0028 %           rhs=tt_ones(2,d*f); Right-hand side of all ones
0029 %           sol=dmrg_solve2(mat,rhs,1e-6);
0030 %
0031 %
0032 % TT-Toolbox 2.2, 2009-2012
0033 %
0034 %This is TT Toolbox, written by Ivan Oseledets et al.
0035 %Institute of Numerical Mathematics, Moscow, Russia
0036 %webpage: http://spring.inm.ras.ru/osel
0037 %
0038 %For all questions, bugs and suggestions please mail
0039 %ivan.oseledets@gmail.com
0040 %---------------------------
0041 
0042 
0043 % Inner parameters
0044 max_full_size=2500;
0045 prec_compr=1e-3;
0046 prec_tol=1e-1;
0047 prec_iters=10;
0048 
0049 dropsweeps=1;
0050 ddpow = 0.1; % stepsize for d-power in truncations
0051 min_dpow = 1; % Minimal d-power for truncation
0052 ddrank = 1; % stepsize for additional rank
0053 min_drank = 1; % Minimal additional rank
0054 d_pow_check = 0; % d-power for checking the convergence
0055 bot_conv = 0.1; % bottom convergence factor - if better, we can decrease dpow and drank
0056 top_conv = 0.99; % top convergence factor - if worse, we have to increase dpow and drank
0057 
0058 bs_treshold = 0.0001*0; % Treshold from the previous residual to consider a local system as "bad"
0059 trunc_to_true = 1.5; % Truncation error to true residual treshold
0060 
0061 use_self_prec=false;
0062 nswp=10;
0063 nrestart=40;
0064 gmres_iters=2;
0065 % local_prec = 'als';
0066 local_prec = 'selfprec';
0067 local_format = 'full';
0068 % local_format = 'tt';
0069 rmax=1000;
0070 tol=eps;
0071 verb=1;
0072 kickrank = 2;
0073 x0=[];
0074 P=[];
0075 for i=1:2:length(varargin)-1
0076     switch lower(varargin{i})
0077         case 'nswp'
0078             nswp=varargin{i+1};
0079         case 'rmax'
0080             rmax=lower(varargin{i+1});
0081         case 'x0'
0082             x0=varargin{i+1};
0083         case 'verb'
0084             verb=varargin{i+1};
0085         case 'p'
0086             P=varargin{i+1};
0087         case 'tol'
0088             tol=varargin{i+1};
0089         case 'local_prec'
0090             local_prec=varargin{i+1};
0091         case 'nrestart'
0092             nrestart=varargin{i+1};
0093         case 'gmres_iters'
0094             gmres_iters=varargin{i+1};
0095         case 'kickrank'
0096             kickrank=varargin{i+1};
0097         case  'max_full_size'
0098             max_full_size=varargin{i+1};
0099         case 'prec_compr'
0100             prec_compr=varargin{i+1};
0101         case 'prec_tol'
0102             prec_tol=varargin{i+1};
0103         case 'prec_iters'
0104             prec_iters=varargin{i+1};
0105         case 'use_self_prec'
0106             use_self_prec=varargin{i+1};
0107         case 'ddpow'
0108             ddpow=varargin{i+1};
0109         case 'ddrank'
0110             ddrank=varargin{i+1};
0111         case 'd_pow_check'
0112             d_pow_check=varargin{i+1};
0113         case 'bot_conv'
0114             bot_conv=varargin{i+1};
0115         case 'top_conv'
0116             top_conv=varargin{i+1};
0117         case 'min_dpow'
0118             min_dpow=varargin{i+1};
0119         case 'min_drank'
0120             min_drank=varargin{i+1};
0121         otherwise
0122             error('Unrecognized option: %s\n',varargin{i});
0123     end
0124 end
0125 
0126 input_is_tt_tensor = 0;
0127 
0128 if ( isa(y,'tt_tensor') )
0129   y=core(y);
0130   input_is_tt_tensor = 1;
0131 end
0132 
0133 if (isa(y, 'tt_tensor'))
0134     y=core(y);
0135     input_is_tt_tensor = 1;
0136 end;
0137 if ( isa(A,'tt_matrix') )
0138 %   ttA=A.tt;
0139 %   dA=ttA.d;
0140   A=core(A);
0141   input_is_tt_tensor = 1;
0142   %if (isempty(x0))
0143   %    x0=tt_random(tt_size(y), A.tt.d, 2);
0144   %end;
0145 % else
0146 %    dA=numel(A);
0147    % if (isempty(x0))
0148    %     x0=tt_random(tt_size(y), max(size(A)), 2);
0149    % end;
0150 end
0151 %   x0=tt_random(tt_size(y),dA,2);
0152 if (isempty(x0))
0153     x0=tt_random(tt_size(y), max(size(y)), 2);
0154 end;
0155 if ( isa(P,'tt_matrix') )
0156   P=core(P);
0157   input_is_tt_tensor = 1;
0158 end;
0159 if ( isa(x0,'tt_tensor') )
0160   x0=core(x0);
0161   input_is_tt_tensor = 1;
0162 end
0163 
0164 %nrmF=sqrt(tt_dot(y,y));
0165 
0166 d=size(A,1);
0167 
0168 if ( isempty(P) )
0169    P = core(tt_eye(tt_size(y), d));
0170 end
0171 x=x0;
0172 
0173 x{1}=reshape(x{1}, size(x{1},1), 1, size(x{1},2));
0174 y{1}=reshape(y{1}, size(y{1},1), 1, size(y{1},2));
0175 A{1}=reshape(A{1}, size(A{1},1),size(A{1},2), 1, size(A{1},3)); %Bydlocode (@)
0176 P{1}=reshape(P{1}, size(P{1},1),size(P{1},2), 1, size(P{1},3));
0177 
0178 phA = cell(d,1);
0179 phy = cell(d,1);
0180 dx_old = ones(d,1);
0181 dx = zeros(d,1);
0182 % artificial rank additions
0183 drank = ones(d,1)*min_drank;
0184 % d-power for stronger compression eps./(d.^dpows)
0185 dpows = ones(d,1)*min_dpow;
0186 
0187 %  chkvec = tt_random(tt_size(y), max(size(y)), kickrank);
0188 %  chkvec{1}=reshape(chkvec{1}, size(chkvec{1},1), 1, size(chkvec{1},2));
0189 %  phAchk = cell(d,1);
0190 %  phychk = cell(d,1);
0191 
0192 sol_hist = cell(3,1);
0193 sol_hist{1}=x;
0194 max_res_old = 0;
0195 last_sweep = false;
0196 for swp=1:nswp
0197 %     z = x;
0198     % 1-to-d orthogonalization
0199     rvx = 1; rnewx=1; phAold=1; phyold=1;
0200 
0201     for i=1:d-1
0202         cre = x{i};
0203         n1 = size(cre,1); rx1 = size(cre,2); rx2 = size(cre,3);
0204         cre = reshape(permute(cre, [2 1 3]), rx1, n1*rx2);
0205         cre = rvx*cre; % size rnew,n1,rx2
0206         rx1=rnewx;
0207         cre = reshape(cre, rx1*n1, rx2);
0208         [q,rvx]=qr(cre,0); % size rx1*n1,r2new - r2new,rx2
0209         rnewx = min(rx1*n1, rx2);
0210         x{i}=permute(reshape(q, rx1, n1, rnewx), [2 1 3]);
0211 
0212         % Now, update phi. phA=X' PA X, phY = X' PY
0213         a1 = A{i};
0214         n1=size(a1,1); m1=size(a1,2); ra1=size(a1,3); ra2=size(a1,4);
0215         p1 = P{i};
0216         k1=size(p1,1); rp1=size(p1,3); rp2=size(p1,4);
0217         y1 = y{i};
0218         ry1=size(y1,2); ry2=size(y1,3);
0219         x1 = x{i};
0220 
0221         rxm1=size(x1,2); rxm2=size(x1,3); rxn1=rxm1; rxn2=rxm2;
0222         phAold = reshape(phAold, rxn1*rp1*ra1, rxm1);
0223         x1 = reshape(permute(x1, [2 1 3]), rxm1, m1*rxm2);
0224         phAold=phAold*x1; % size rxn1*rp1*ra1*m1*rxm2
0225         phAold=reshape(phAold, rxn1, rp1, ra1, m1, rxm2);
0226         phAold=reshape(permute(phAold, [1 2 5 4 3]), rxn1*rp1*rxm2, m1*ra1);
0227         a1 = reshape(permute(a1, [2 3 1 4]), m1*ra1, n1*ra2);
0228         phAold=phAold*a1; % size rxn1*rp1*rxm2*n1*ra2
0229         phAold=reshape(phAold, rxn1, rp1, rxm2, n1, ra2);
0230         phAold=reshape(permute(phAold, [1 3 5 4 2]), rxn1*rxm2*ra2, n1*rp1);
0231         p1 = reshape(permute(p1, [2 3 1 4]), n1*rp1, k1*rp2);
0232         phAold=phAold*p1; % size rxn1*rxm2*ra2*k1*rp2
0233         phAold=reshape(phAold, rxn1, rxm2, ra2, k1, rp2);
0234         phAold=reshape(permute(phAold, [2 5 3 4 1]), rxm2*rp2*ra2, k1*rxn1);
0235         x1 = reshape(x{i}, k1*rxn1, rxn2);
0236         phAold=phAold*conj(x1); % size rxm2*rp2*ra2*rxn2 <--- complex conjugate!
0237         phAold = reshape(phAold, rxm2, rp2, ra2, rxn2);
0238         phAold = permute(phAold, [4 2 3 1]); % we need rxn2,rp2,ra2,rxm2
0239         phA{i}=phAold;
0240 
0241         phyold = reshape(phyold, rxn1*rp1, ry1);
0242         y1 = reshape(permute(y1, [2 1 3]), ry1, n1*ry2);
0243         phyold=phyold*y1; % size rxn1*rp1*n1*ry2
0244         phyold = reshape(phyold, rxn1, rp1, n1, ry2);
0245         phyold=reshape(permute(phyold, [1 4 3 2]), rxn1*ry2, n1*rp1);
0246         p1=reshape(permute(P{i}, [2 3 1 4]), n1*rp1, k1*rp2);
0247         phyold=phyold*p1; % size rxn1*ry2*k1*rp2
0248         phyold=reshape(phyold, rxn1, ry2, k1, rp2);
0249         phyold=reshape(permute(phyold, [4 2 3 1]), rp2*ry2, k1*rxn1);
0250         x1=reshape(x{i}, k1*rxn1, rxn2);
0251         phyold=phyold*conj(x1); % size rp2*ry2*rxn2 <--- complex conjugate!
0252         phyold=permute(reshape(phyold, rp2, ry2, rxn2), [3 1 2]);
0253         phy{i}=phyold;
0254     end;
0255     % convolve rv with the last cre
0256     cre = x{d};
0257     n1 = size(cre,1); rx1 = size(cre,2); rx2 = size(cre,3);
0258     cre = reshape(permute(cre, [2 1 3]), rx1, n1*rx2);
0259     cre = rvx*cre; % size rnew,n1,rx2
0260     x{d}=permute(reshape(cre, rnewx, n1, rx2), [2 1 3]);
0261 
0262     % Now, start the d-to-1 DMRG iteration
0263     max_res = 0;
0264     phAold=1; phyold=1;
0265 
0266     for i=d:-1:2
0267         a2=A{i}; a1=A{i-1}; ra1=size(a1,3); ra2=size(a1,4); ra3=size(a2,4);
0268         n1 = size(a1,1); m1=size(a1,2); n2=size(a2,1); m2=size(a2,2);
0269         p2=P{i}; p1=P{i-1}; rp1=size(p1,3); rp2=size(p1,4); rp3=size(p2,4);
0270         k1 = size(p1,1); k2=size(p2,1);
0271 
0272         y1=y{i-1}; y2=y{i}; ry1=size(y1,2); ry2=size(y1,3); ry3=size(y2,3);
0273         x1=x{i-1}; x2=x{i}; rx1=size(x1,2); rx2=size(x1,3); rx3=size(x2,3);
0274 
0275         % Compute RHS: phy{i-2}*P1*y1*y2*P2*phyold
0276         if (i>2)
0277             rhs1 = phy{i-2};
0278         else
0279             rhs1=1;
0280         end;
0281         rhs1 = reshape(rhs1, rx1*rp1, ry1);
0282         y1 = reshape(permute(y1, [2 1 3]), ry1, n1*ry2);
0283         rhs1 = rhs1*y1; % size rx1*rp1*n1*ry2
0284         rhs1 = reshape(rhs1, rx1, rp1, n1, ry2);
0285         rhs1=reshape(permute(rhs1, [1 4 3 2]), rx1*ry2, n1*rp1);
0286         p1 = reshape(permute(p1, [2 3 1 4]), n1*rp1, k1*rp2);
0287         rhs1=rhs1*p1; % size rx1*ry2*k1*rp2
0288         rhs1=reshape(rhs1, rx1, ry2, k1, rp2);
0289         rhs1=reshape(permute(rhs1, [1 3 4 2]), rx1*k1, rp2*ry2);
0290 
0291         y2=reshape(permute(y2, [2 1 3]), ry2*n2, ry3);
0292         phyold2 = reshape(phyold, rx3*rp3, ry3);
0293         rhs2 = y2*(phyold2.'); % size ry2*n2, rx3*rp3
0294         rhs2 = reshape(rhs2, ry2, n2, rx3, rp3);
0295         rhs2 = permute(rhs2, [1 3 2 4]);
0296         rhs2 = reshape(rhs2, ry2*rx3, n2*rp3);
0297         p2 = reshape(permute(p2, [2 4 1 3]), n2*rp3, k2*rp2);
0298         rhs2 = rhs2*p2; % size ry2*rx3, k2*rp2
0299         rhs2 = reshape(rhs2, ry2, rx3, k2, rp2);
0300         rhs2 = permute(rhs2, [4 1 3 2]);
0301         rhs2 = reshape(rhs2, rp2*ry2, k2*rx3);
0302 
0303         if (strcmp(local_format, 'full'))
0304             rhs = rhs1*rhs2;
0305             rhs = reshape(rhs, rx1*k1*k2*rx3, 1);
0306         else
0307             rhs = cell(2,1);
0308             rhs{1} = rhs1;
0309             rhs{2} = rhs2.';
0310         end;
0311 
0312         rxn1=rx1; rxn3=rx3;
0313         rxm1=rx1; rxm2=rx2; rxm3=rx3;
0314         if (i>2)
0315             B = phA{i-2};
0316         else
0317             B=1;
0318         end;
0319         B = reshape(B, rxn1, rp1, ra1, rxm1);
0320         B = reshape(permute(B, [1 4 2 3]), rxn1*rxm1*rp1, ra1);
0321         a1 = reshape(permute(A{i-1}, [3 2 1 4]), ra1, m1*n1*ra2);
0322         B = B*a1; % size rxn1*rxm1*rp1*m1*n1*ra2
0323         B = reshape(B, rxn1,rxm1,rp1,m1,n1,ra2);
0324         B = permute(B, [1 2 4 6 3 5]);
0325         B = reshape(B, rxn1*rxm1*m1*ra2, rp1*n1);
0326         p1 = reshape(permute(P{i-1}, [3 2 1 4]), rp1*n1, k1*rp2);
0327         B = B*p1; % size rxn1*rxm1*m1*ra2*k1*rp2
0328         B = reshape(B, rxn1,rxm1,m1,ra2,k1,rp2);
0329         B = permute(B, [1 5 2 3 6 4]);
0330         B = reshape(B, rxn1*k1*rxm1*m1, rp2*ra2);
0331 %         This is the first term of tensor-structured matrix B \otimes B2
0332 %         Now, the second
0333         B2 = permute(phAold, [1 2 4 3]);
0334         B2 = reshape(B2, rxn3*rp3*rxm3, ra3);
0335         a2 = reshape(A{i}, n2*m2*ra2, ra3);
0336         B2 = B2*(a2.'); % size rxn3*rp3*rxm3*n2*m2*ra2
0337         B2 = reshape(B2, rxn3, rp3, rxm3, n2, m2, ra2);
0338         B2 = permute(B2, [1 3 5 6 4 2]);
0339         B2 = reshape(B2, rxn3*rxm3*m2*ra2, n2*rp3);
0340         p2 = reshape(permute(P{i}, [2 4 1 3]), n2*rp3, k2*rp2);
0341         B2 = B2*p2; % size rxn3*rxm3*m2*ra2*k2*rp2
0342         B2 = reshape(B2, rxn3, rxm3, m2, ra2, k2, rp2);
0343         B2 = permute(B2, [5 1 3 2 6 4]);
0344         B2 = reshape(B2, k2*rxn3*m2*rxm3, rp2*ra2);
0345         % Now, compress inner rank rp2*ra2 --- what is this ???
0346         %Modify it by random noise, since sometime MATLAB QR
0347         %fails
0348         %B2=B2+max(abs(B2(:)))*randn(size(B2))*1e-16; Kill all humans for
0349         %such code
0350 
0351 %         [Q,R]=qr(B2,0);
0352 %
0353 %         rnew = min(k2*rxn3*m2*rxm3, rp2*ra2);
0354 %         B2 = reshape(Q, k2*rxn3*m2*rxm3, rnew);
0355 %         B = B*(R.'); % size rxn1*rxm1*k1*m1*rnew
0356 %
0357 %         B = reshape(B, rxn1*k1*rxm1*m1, rnew);
0358 %         [U,S,V]=svd(B, 'econ');
0359 %         S = diag(S);
0360 %         rB = my_chop2(S, 1e-12*norm(S)); % We don't know the cond(B), so let's obtain almost exact compression
0361 %         B = U(:,1:rB);
0362 %         V = V(:,1:rB)*diag(S(1:rB)); % size rnew*rB
0363 %         B2 = B2*conj(V); % size k2*rxn3*m2*rxm3*rB
0364         rB=rp2*ra2;
0365         MatVec='bfun2';
0366         if (((rxn1*k1*k2*rxn3<max_full_size))||(rB>max(rxn1*k1, rxn3*k2)))&&(strcmp(local_format, 'full'))
0367             MatVec='full';
0368             if (rxn1*k1*k2*rxn3>max_full_size)
0369                 MatVec='half-full';
0370             end;
0371             B = B*(B2.'); % size rxn1*k1*rxm1*m1*k2*rxn3*m2*rxm3
0372             B = reshape(B, rxn1,k1,rxm1,m1,k2,rxn3,m2,rxm3);
0373             B = permute(B, [1 2 5 6 3 4 7 8]);
0374             B = reshape(B, rxn1*k1*k2*rxn3, rxm1*m1*m2*rxm3);
0375         else
0376             B1 = reshape(B, rxn1*k1, rxm1*m1, rB);
0377             B2 = reshape(B2, k2*rxn3, m2*rxm3, rB);
0378             B=cell(2,1);
0379             B{1}=B1;
0380             B{2}=B2;
0381         end;
0382 
0383         % Form previous solution
0384         x1 = reshape(permute(x{i-1}, [2 1 3]), rxm1*m1, rxm2);
0385         x2 = reshape(permute(x{i}, [2 1 3]), rxm2, m2*rxm3);
0386         if (strcmp(local_format, 'full'))
0387             sol_prev = x1*x2;
0388             sol_prev = reshape(sol_prev, rxm1*m1*m2*rxm3, 1);
0389         else
0390             sol_prev = cell(2,1);
0391             sol_prev{1} = x1;
0392             sol_prev{2} = x2.';
0393         end;
0394 
0395         real_tol = (tol/(d^dpows(i)))/trunc_to_true;
0396 
0397         if (strcmp(local_format, 'tt'))
0398             mv = @(vec,eps,mr)bfun3(B,vec,eps,mr);
0399         else
0400             if (strcmp(MatVec, 'bfun2'))
0401                 mv=@(vec)bfun2(B, vec, rxm1,m1,m2,rxm3,rxn1,k1,k2,rxn3);
0402                 %mv1=@(vec)bfun2(B, vec, rxm1,m1,m2,rxm3,rxn1,k1,k2,rxn3)+tau(i)*vec;
0403             else
0404                 mv = @(vec)(B*vec);
0405                 %mv1 = @(vec)(B*vec+tau(i)*vec);
0406             end;
0407         end;
0408 
0409         % Check the previous residual
0410         if (strcmp(local_format, 'tt'))
0411             res_prev = mv(sol_prev, [], []);
0412             normf = exp(0.5*tt_dot2(rhs, rhs));
0413             res_prev = tt_dist3(res_prev, rhs)/normf;
0414         else
0415             res_prev = mv(sol_prev);
0416             normf = norm(rhs);
0417             res_prev = norm(res_prev - rhs)/normf;
0418         end;
0419 
0420         % We will solve the system only if res_prev>0.1*max_res_prev
0421         if (~last_sweep)&&(res_prev>bs_treshold*max_res_old)
0422             if (strcmp(MatVec,'full'))
0423                 %             sol = pinv(B)*rhs;
0424                 %             sol = (B'*B+tol^2*max(max(abs(B'*B)))*eye(size(B)))\(B'*rhs);
0425                 sol = B \ rhs;
0426                 %             sol = (B'*B)\(B'*rhs);
0427                 res=B*sol;
0428                 res_true = norm(res-rhs)/norm(rhs);
0429             else
0430                 %Ax_{k+1}+tau*x_k=rhs+tau*x_k
0431                 %(Ax_{k+1}+tau*I)x_{k+1}=rhs+tau*x_k
0432 %                 [sol_new,flg] = gmres(mv1, rhs+tau(i)*sol_prev, nrestart, real_tol, 2, [], [], sol_prev);
0433 %                 if( flg == 0)
0434 %                     tau(i)=tau(i)/10;
0435 %                 else
0436 %                     tau(i)=tau(i)*4;
0437 %                 end
0438                 if (strcmp(local_format, 'full'))
0439                     [sol_new,flg] = gmres(mv, rhs, nrestart, real_tol, 2, [], [], sol_prev);
0440                     %[dsol,flg]=gmres(mv, rhs-mv(sol_prev), nrestart, 1.0/8, 2, [], [], zeros(size(sol_prev)));
0441                     %sol_new=sol_prev+dsol;
0442                     res_new=norm(mv(sol_new)-rhs)/normf;
0443                     conv_factor=(res_new/res_prev);
0444                     if (res_new*(conv_factor)>real_tol && use_self_prec && strcmp(MatVec, 'bfun2')) % we need a prec.
0445                         if (strcmp(local_prec, 'selfprec'))
0446                             iB=tt_minres_selfprec(B, prec_tol, prec_compr, prec_iters, 'right');
0447 
0448                             resid = rhs-mv(sol_new);
0449                             [dsol,flg] = gmres(@(vec)bfun2(B, bfun2(iB,vec,rxm1,m1,m2,rxm3,rxn1,k1,k2,rxn3),...
0450                                 rxm1,m1,m2,rxm3,rxn1,k1,k2,rxn3), resid, nrestart, real_tol/res_new, gmres_iters);
0451                             dsol = bfun2(iB,dsol,rxm1,m1,m2,rxm3,rxn1,k1,k2,rxn3);
0452                             sol = sol_new+dsol;
0453 
0454                         end;
0455                         if (strcmp(local_prec, 'als'))
0456                             sol = als_solve_rx_2(B, rhs, real_tol, [], sol_new);
0457                         end;
0458                     else
0459                         [sol,flg] = gmres(mv, rhs, nrestart, real_tol, gmres_iters, [], [], sol_new);
0460                     end;
0461                     if (flg>0)
0462                         fprintf('-warn- gmres did not converge at block %d\n', i);
0463                     end;                    
0464 
0465                     res=mv(sol);
0466                     res_true = norm(res-rhs)/normf;
0467                 else
0468                     sol_new = tt_gmres(mv, rhs, real_tol, 2, nrestart, real_tol, real_tol, [], [], [], sol_prev);
0469                     res_new=tt_dist3(mv(sol_new,[],[]),rhs)/normf;
0470                     conv_factor=(res_new/res_prev);
0471                     if (res_new*conv_factor>real_tol && use_self_prec && strcmp(MatVec, 'bfun2')) % we need a prec.
0472 %                         if (strcmp(local_prec, 'selfprec'))
0473                             iB=tt_minres_selfprec(B, prec_tol, prec_compr, prec_iters, 'right');
0474 
0475 %                             resid = tt_add(rhs, tt_scal(mv(sol_new,[],[]), -1));
0476 %                             resid = tt_compr2(resid, real_tol);
0477 
0478                             sol = tt_gmres(@(vec,eps,mr)bfun3(B, vec, eps, mr), rhs, real_tol, gmres_iters, nrestart, real_tol, real_tol, @(vec,eps,mr)bfun3(iB, vec, eps, mr), [], [], sol_new);
0479 %                             dsol = bfun3(iB,dsol,real_tol);
0480 %                             sol = tt_add(sol_new,dsol);
0481 %                             sol = tt_compr2(sol, real_tol);
0482 %                         end;
0483                     else
0484                         sol = tt_gmres(mv, rhs, real_tol, gmres_iters, nrestart, real_tol, real_tol, [], [], [], sol_new);
0485                     end;
0486                     res=mv(sol,[],[]);
0487                     res_true = tt_dist3(res,rhs)/normf;
0488                 end;
0489             end;
0490 
0491             if (strcmp(local_format, 'full'))
0492                 dx(i) = norm(sol-sol_prev,'fro')/norm(sol_prev,'fro');
0493             else
0494                 dx(i) = tt_dist3(sol, sol_prev)/exp(0.5*tt_dot2(sol,sol));
0495             end;
0496         else
0497             res_true = res_prev;
0498             dx(i)=0;
0499         sol = sol_prev;
0500         end;
0501 
0502         if (verb>1)
0503             fprintf('=dmrg_solve2= Sweep %d, block %d, res_true = %3.3e\n', swp, i, res_true);
0504         end;
0505         if ((res_true>res_prev/trunc_to_true))&&(res_true>real_tol)&&(~last_sweep)
0506         fprintf('--warn-- the residual damp by gmres was smaller than in the truncation\n');
0507 %             keyboard;
0508             sol = sol_prev;
0509             res_true = res_prev;
0510         end;
0511 
0512         if (res_prev>max_res)
0513             max_res = res_prev;
0514         end;
0515 
0516         if (verb>1)
0517         fprintf('=dmrg_solve2= Sweep %d, block %d, dx=%3.3e, res_prev = %3.3e\n', swp, i, dx(i), res_prev);
0518         end;
0519         if (strcmp(local_format, 'full'))
0520             nrmsol = norm(sol, 'fro');
0521         else
0522             nrmsol = exp(0.5*tt_dot2(sol,sol));
0523         end
0524         if (nrmsol==0)
0525             dx(i)=0;
0526         end;
0527 
0528         if (swp==1)
0529             dx_old(i)=dx(i);
0530         end;
0531 
0532         % The new core does not converge - increase rank
0533         if (dx(i)/dx_old(i)>top_conv)&&(dx(i)>eps/(d^d_pow_check))
0534             drank(i)=drank(i)+ddrank;
0535             dpows(i)=dpows(i)+ddpow;
0536         end;
0537         % The new core converges well - try to decrease rank
0538         if (dx(i)/dx_old(i)<bot_conv)||(dx(i)<eps/(d^d_pow_check))
0539             drank(i)=max(drank(i)-ddrank, min_drank);
0540             dpows(i)=max(dpows(i)-ddpow, min_dpow);
0541         end;
0542         % perform simple compression for the last sweep
0543         if (last_sweep)
0544             dpows(i)=min(0.5, min_dpow);
0545         end;
0546 
0547         if (res_prev>bs_treshold*max_res_old)&&(strcmp(local_format, 'full'))
0548             if (mod(swp,dropsweeps)~=0)&&(swp>1)&&(~last_sweep)
0549                 [u,s,v]=svd(sol-reshape(sol_prev,[rxm1*m1,m2*rxm3]),'econ');
0550             else
0551                 if (~last_sweep)
0552                     sol=reshape(sol,[rxm1*m1,m2*rxm3]);
0553                     [u,s,v]=svd(sol,'econ');
0554                 else
0555                     [x2,rv]=qr(x2.', 0);
0556                     x1 = x1*(rv.');
0557                     [u,s,v]=svd(x1, 'econ');
0558                     v = x2*v;
0559                 end;
0560             end;
0561             s = diag(s);
0562             flm=norm(s);
0563             %Truncation block. We have to make it smarter by binary search
0564             r0 = 1; rM = min(size(s,1),rmax); r = round((r0+rM)/2);
0565             while (rM-r0>2)
0566                 er0=norm(s(r+1:numel(s)));
0567                 if (mod(swp,dropsweeps)~=0)&&(swp>1)&&(~last_sweep)
0568                     sol = sol_prev+reshape(u(:,1:r)*diag(s(1:r))*(v(:,1:r))',rxm1*m1*m2*rxm3, 1);
0569                 else
0570                     sol = reshape(u(:,1:r)*diag(s(1:r))*(v(:,1:r))',rxm1*m1*m2*rxm3, 1);
0571                 end;
0572                 if (strcmp(MatVec,'full')||strcmp(MatVec,'half-full'))
0573                     resid = norm(B*sol-rhs)/norm(rhs);
0574                 else
0575                     resid = norm(bfun2(B,sol,rxm1,m1,m2,rxm3,rxn1,k1,k2,rxn3)-rhs)/norm(rhs);
0576                 end;
0577                 %             if ( verb>1 )
0578                 %             fprintf('=dmrg_solve2= sweep %d, block %d, r=%d, resid=%g, er0=%g, MatVec=%s, rB=%d\n', swp, i, r, resid, er0/flm, MatVec, rB);
0579                 %             end
0580                 if ((resid<max(res_true*trunc_to_true, eps/(d^dpows(i)))) ) %Value of the rank is OK
0581                     rM = r-1;
0582                     r = round((r0+rM)/2);
0583                 else %Is not OK.
0584                     r0 = r;
0585                     r = round((r0+rM)/2);
0586                 end;
0587             end
0588             r = r0;
0589             % Line search - if the rank is underestimated
0590             cursol = cell(2,1);
0591             cursol{1}=u(:,1:r);
0592             cursol{2}=conj(v(:,1:r))*diag(s(1:r));
0593             if (strcmp(MatVec,'full')||strcmp(MatVec,'half-full'))
0594                 resid = B*full(tt_tensor(cursol),rxm1*m1*m2*rxm3)-rhs;
0595                 %resid = B*reshape(tt_to_full(cursol), rxm1*m1*m2*rxm3, 1)-rhs;
0596             else
0597                 resid = full(tt_tensor(tt_mv(B,cursol)),rxm1*m1*m2*rxm3)-rhs;
0598                 %resid = reshape(tt_to_full(tt_mv(B,cursol)), rxm1*m1*m2*rxm3, 1)-rhs;
0599             end;
0600             while (r<min(size(s,1), rmax))
0601                 r=r+1;
0602                 er0=norm(s(r+1:numel(s)));
0603                 cursol{1}=u(:,r);
0604                 cursol{2}=conj(v(:,r))*s(r);
0605                 if (strcmp(MatVec,'full')||strcmp(MatVec,'half-full'))
0606                     resid = B*full(tt_tensor(cursol),rxm1*m1*m2*rxm3)+resid;
0607                     %resid = B*reshape(tt_to_full(cursol), rxm1*m1*m2*rxm3, 1) + resid;
0608 
0609                 else
0610                     resid = full(tt_tensor(tt_mv(B,cursol)),rxm1*m1*m2*rxm3)+resid;
0611                     %resid = reshape(tt_to_full(tt_mv(B,cursol)), rxm1*m1*m2*rxm3, 1)+resid;
0612 
0613                 end;
0614                 normres = norm(resid)/norm(rhs);
0615                 %             if ( verb>1 )
0616                 %                 fprintf('=dmrg_solve2= sweep %d, block %d, r=%d, resid=%g, er0=%g, MatVec=%s, rB=%d\n', swp, i, r, normres, er0/flm, MatVec, rB);
0617                 %             end
0618                 if ((normres<max(res_true*trunc_to_true, eps/(d^dpows(i)))) ) %Value of the rank is OK
0619                     break;
0620                 end;
0621             end;
0622 
0623             if (~last_sweep)
0624                 r = r+drank(i); % we want even larger ranks
0625             end;
0626 
0627             v = conj(v);
0628         else
0629             if (strcmp(local_format, 'tt'))
0630                 x1 = sol{1};
0631                 x2 = sol{2}.';
0632             end;
0633             % We do not have to decimate the whole supercore,
0634             % only one of factors, as we have the previous solution
0635             [v,rv]=qr(x2.',0); % size m2*rxm3, rxm2' - rxm2',rxm2
0636             r = size(v,2);
0637 % %             rxm2 = size(x2,2);
0638             u = x1*rv.';
0639             s = ones(r,1);
0640 %
0641 %             [u,s,v]=svd(x1, 'econ');
0642 %             v = x2*conj(v);
0643 %             s = diag(s);
0644 %             flm=norm(s);
0645 %             %Truncation block. We have to make it smarter by binary search
0646 %             r0 = 1; rM = min(size(s,1),rmax); r = round((r0+rM)/2);
0647 %             while (rM-r0>2)
0648 %                 er0=norm(s(r+1:numel(s)));
0649 %                 if (mod(swp,dropsweeps)~=0)&&(swp>1)&&(~last_sweep)
0650 %                     sol = sol_prev+reshape(u(:,1:r)*diag(s(1:r))*(v(:,1:r)).',rxm1*m1*m2*rxm3, 1);
0651 %                 else
0652 %                     sol = reshape(u(:,1:r)*diag(s(1:r))*(v(:,1:r)).',rxm1*m1*m2*rxm3, 1);
0653 %                 end;
0654 %                 if (strcmp(MatVec,'full'))
0655 %                     resid = norm(B*sol-rhs)/norm(rhs);
0656 %                 else
0657 %                     resid = norm(bfun2(B,sol,rxm1,m1,m2,rxm3,rxn1,k1,k2,rxn3)-rhs)/norm(rhs);
0658 %                 end;
0659 %                 if ((resid<max(res_true*trunc_to_true, eps/(d^dpows(i)))) ) %Value of the rank is OK
0660 %                     rM = r-1;
0661 %                     r = round((r0+rM)/2);
0662 %                 else %Is not OK.
0663 %                     r0 = r;
0664 %                     r = round((r0+rM)/2);
0665 %                 end;
0666 %             end
0667 %             r = r0;
0668 %             % Line search - if the rank is underestimated
0669 %             cursol = cell(2,1);
0670 %             cursol{1}=u(:,1:r);
0671 %             cursol{2}=v(:,1:r)*diag(s(1:r));
0672 %             if (strcmp(MatVec,'full'))
0673 %                 resid = B*reshape(tt_to_full(cursol), rxm1*m1*m2*rxm3, 1)-rhs;
0674 %             else
0675 %                 resid = reshape(tt_to_full(tt_mv(B,cursol)), rxm1*m1*m2*rxm3, 1)-rhs;
0676 %             end;
0677 %             while (r<min(size(s,1), rmax))
0678 %                 r=r+1;
0679 %                 er0=norm(s(r+1:numel(s)));
0680 %                 cursol{1}=u(:,r);
0681 %                 cursol{2}=v(:,r)*s(r);
0682 %                 if (strcmp(MatVec,'full'))
0683 %                     resid = resid + B*reshape(tt_to_full(cursol), rxm1*m1*m2*rxm3, 1);
0684 %                 else
0685 %                     resid = resid + reshape(tt_to_full(tt_mv(B,cursol)), rxm1*m1*m2*rxm3, 1);
0686 %                 end;
0687 %                 normres = norm(resid)/norm(rhs);
0688 %                 if ((normres<max(res_true*trunc_to_true, eps/(d^dpows(i)))) ) %Value of the rank is OK
0689 %                     break;
0690 %                 end;
0691 %             end;
0692         end;
0693         r = min(r, max(size(s))); % but not too large
0694         r = min(r,rmax);
0695 
0696         v = v(:,1:r);
0697         u = u(:,1:r)*diag(s(1:r));
0698 
0699         if ( verb>1 )
0700             fprintf('=dmrg_solve2= sweep %d, block %d, r=%d, resid=%g, er0=%g, MatVec=%s, rB=%d\n', swp, i, r, normres, er0/flm, MatVec, rB);
0701         end
0702 
0703         % Keep rank increasing for several iterations
0704         % It helps for problems with hundred dimensions
0705 %         if (mod(swp,dropsweeps)~=0)&&(dropflag==0)
0706 %             r = max(r, ryold);
0707 %         end;
0708 %         if (verb>1)
0709 %             fprintf('sweep %d, block %d, rank: %d, drop: %d\n', swp, i, r, dropflag);
0710 %         end;
0711 %         if (dropflag==1)&&(i==2)
0712 %             dropflag=0;
0713 %         end;
0714 
0715         % random kick %This is a production code, sir!
0716         %Replace by new stuff
0717 
0718         if (mod(swp,dropsweeps)~=0)&&(swp>1)&&(~last_sweep)
0719             u = [x1, u];
0720             v = [x2.', v];
0721             [v,rv]=qr(v,0);
0722             u = u*(rv.');
0723             r = size(v,2);
0724         else
0725             if (~last_sweep)
0726                 vr=randn(size(v,1),kickrank);
0727                 v=reort(v,vr);
0728                 radd=size(v,2)-r;
0729                 if ( radd > 0 )
0730                     ur=zeros(size(u,1),radd);
0731                     u=[u,ur];
0732                 end
0733                 r=r+radd;
0734             end;
0735         end;
0736 
0737         %v = [v, randn(size(v,1), kickrank)];
0738         %u = [u, zeros(size(u,1), kickrank)];
0739         %[v,rv] = qr(v,0);
0740         %r = size(v,2);
0741         %u = u*(rv.');
0742 
0743         x{i}=permute(reshape(v, m2, rxm3, r), [1 3 2]);
0744         x{i-1}=permute(reshape(u, rxm1, m1, r), [2 1 3]);
0745         rxm2=r; rxn2=r;
0746 
0747         if (verb>2)
0748             % check the residual
0749             n1 = size(A{1},1);
0750             ra1 = size(A{1},4);
0751             rx1 = size(x{1},3);
0752             ry1 = size(y{1},3);
0753             A{1}=squeeze(A{1});
0754             x{1}=squeeze(x{1});
0755             y{1}=squeeze(y{1});
0756             true_resid = tt_mv(A,x);
0757             true_resid = tt_dist3(true_resid, y)/sqrt(tt_dot(y,y));
0758             fprintf('=dmrg_solve2= Sweep %d, block %d, true_resid: %3.3e\n', swp, i, true_resid);
0759             A{1}=reshape(A{1}, n1, n1, 1, ra1);
0760             x{1}=reshape(x{1}, n1, 1, rx1);
0761             y{1}=reshape(y{1}, n1, 1, ry1);
0762         end;
0763 
0764 
0765 
0766         phAold = reshape(phAold, rxn3*rp3*ra3, rxm3);
0767         x2 = reshape(x{i}, m2*rxm2, rxm3);
0768         phAold = phAold*(x2.'); % size rxn3*rp3*ra3*m2*rxm2
0769         phAold = reshape(phAold, rxn3, rp3, ra3, m2, rxm2);
0770         phAold = permute(phAold, [1 2 5 4 3]);
0771         phAold = reshape(phAold, rxn3*rp3*rxm2, m2*ra3);
0772         a2 = reshape(permute(A{i}, [2 4 1 3]), m2*ra3, n2*ra2);
0773         phAold=phAold*a2; % size rxn3*rp3*rxm2*n2*ra2
0774         phAold=reshape(phAold, rxn3, rp3, rxm2, n2, ra2);
0775         phAold = permute(phAold, [1 3 5 4 2]);
0776         phAold = reshape(phAold, rxn3*rxm2*ra2, n2*rp3);
0777         p2 = reshape(permute(P{i}, [2 4 1 3]), n2*rp3, k2*rp2);
0778         phAold=phAold*p2; % size rxn3*rxm2*ra2*k2*rp2
0779         phAold=reshape(phAold, rxn3,rxm2,ra2,k2,rp2);
0780         phAold = permute(phAold, [2 3 5 1 4]);
0781         phAold = reshape(phAold, rxm2*ra2*rp2, rxn3*k2);
0782         x2 = reshape(permute(x{i}, [3 1 2]), rxn3*k2, rxn2);
0783         phAold = phAold*conj(x2); % size rxm2*ra2*rp2*rxn2 <-- cplx conjugate!
0784         phAold = permute(reshape(phAold, rxm2, ra2, rp2, rxn2), [4 3 2 1]);
0785 
0786         phyold = reshape(phyold, rxn3*rp3, ry3);
0787         y2 = reshape(y{i}, n2*ry2, ry3);
0788         phyold = phyold*(y2.'); % size rxn3*rp3*n2*ry2
0789         phyold = reshape(phyold, rxn3, rp3, n2, ry2);
0790         phyold = permute(phyold, [1 4 3 2]);
0791         phyold = reshape(phyold, rxn3*ry2, n2*rp3);
0792         p2 = reshape(permute(P{i}, [2 4 1 3]), n2*rp3, k2*rp2);
0793         phyold = phyold*p2; % size rxn3*ry2*k2*rp2
0794         phyold = reshape(phyold, rxn3, ry2, k2, rp2);
0795         phyold = permute(phyold, [4 2 1 3]);
0796         phyold = reshape(phyold, rp2*ry2, rxn3*k2);
0797         x2 = reshape(permute(x{i}, [3 1 2]), rxn3*k2, rxn2);
0798         phyold = phyold*conj(x2); % size rp2*ry2*rxn2 <-- cplx conjugate!
0799         phyold = permute(reshape(phyold, rp2, ry2, rxn2), [3 1 2]);
0800     end;
0801 
0802 %     sol_hist{3}=sol_hist{2};
0803 %     sol_hist{2}=sol_hist{1};
0804 %     sol_hist{1}=x;
0805 
0806     max_res_old = max_res;
0807     if (mod(swp,100)==0)
0808         max_res_old = 0;
0809     end;
0810 
0811 %     if (max_res>max_res_old)
0812 %         x = sol_hist{3};
0813 %     else
0814 %         max_res_old = max_res;
0815 %     end;
0816 
0817 %     if (max_res<tol*2*sqrt(d-1))
0818 %         dropflag = 1;
0819 %     end;
0820 %     if (mod(swp,chksweeps)==0)||(swp==1)
0821 %         x{1}=reshape(x{1}, size(x{1},1), size(x{1},3));
0822 %         reschk = norm(tt_tensor(x)-tt_tensor(x_prev))/sqrt(tt_dot(x,x));
0823 %         x_prev = x;
0824 %         x{1}=reshape(x{1}, size(x{1},1),1, size(x{1},2));
0825 %     end;
0826     if (verb>0)
0827         erank=0; sumn=0;
0828         for i=1:d
0829             erank = erank+size(x{i},1)*size(x{i},2)*size(x{i},3);
0830             sumn = sumn+size(x{i},1);
0831         end;
0832         erank = sqrt(erank/sumn);
0833 %         fprintf('===Sweep %d, res_%d: %3.3e, drop_next: %d, dx_max: %3.3e, res_max: %3.3e\n', swp, chksweeps,0, dropflag, dx_max, max_res);
0834         fprintf('=dmrg_solve2= Sweep %d, dx_max: %3.3e, res_max: %3.3e, erank: %g\n', swp, max(dx), max_res, erank);
0835     end;
0836     if (last_sweep)
0837         break;
0838     end;
0839     if (max_res<tol/(d^d_pow_check))||(swp==nswp-1)
0840         last_sweep=true;
0841 %         break;
0842     end;
0843 
0844     dx_old = dx;
0845 %     if (verb>0)
0846 %         fprintf('-=-=-=-=-= dx_max = %3.3e, res_max = %3.3e\n', dx_max, max_res);
0847 %     end;
0848 %     if (dx_max<tol*2)
0849 %     if (max_res<tol*2)
0850 %         break;
0851 %     end;
0852 %     keyboard;
0853 end;
0854 
0855 x{1}=reshape(x{1}, size(x{1},1), size(x{1},3));
0856 
0857 % x = tt_compr2(x, eps, rmax);
0858 
0859 if (input_is_tt_tensor)
0860   x=tt_tensor(x);
0861 end
0862 
0863 if (nargout>1)
0864     sweeps = swp;
0865 end;
0866 
0867 end
0868 
0869 function [y]=bfun2(B, x, rxm1, m1, m2, rxm3, rxn1, k1, k2, rxn3)
0870 % Computes (B{1} \otimes B{2})x
0871 % B{1} is of sizes rxn1*k1, rxm1*m1, rB
0872 % B{2} is of sizes k2*rxn3, m2*rxm3, rB
0873 rB=size(B{1},3);
0874 x = reshape(x, rxm1*m1, m2*rxm3);
0875 B1 = permute(B{1}, [3 1 2]);
0876 B1 = reshape(B1, rB*rxn1*k1, rxm1*m1);
0877 y = B1*x; % size rB*rxn1*k1,m2*rxm3
0878 y = reshape(y, rB, rxn1*k1, m2*rxm3);
0879 y = permute(y, [3 1 2]);
0880 y = reshape(y, m2*rxm3*rB, rxn1*k1);
0881 B2 = reshape(B{2}, k2*rxn3, m2*rxm3*rB);
0882 y = B2*y; % size k2*rxn3,rxn1*k1
0883 y = reshape(y.', rxn1*k1*k2*rxn3, 1);
0884 end
0885 
0886 
0887 function [y] = bfun3(A, x, eps, mr)
0888 % For the 2d--TT MatVec
0889 y = tt_mv(A, x);
0890 if (nargin<4)
0891     mr = [];
0892 end;
0893 if (nargin>2)&&(~isempty(eps))
0894     y = tt_compr2(y, eps, mr);
0895 end;
0896 
0897 end
0898

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