rbmatlab 0.10.01
general/gplmm.m
Go to the documentation of this file.
00001 function [xnew, resnorm, residual, exitflag, output, tempsols] = gplmm(funptr, x0, params)
00002 % function [vnew, resnorm, residual, output, exitflags] = gplmm(funptr, vold, params)
00003 % Global projected Levenberg-Marquard method
00004 
00005 if ~isfield(params, 'beta')
00006   params.beta = 0.1;
00007 end
00008 if ~isfield(params, 'sigma')
00009   params.sigma = 1e-4;
00010 end
00011 if ~isfield(params, 'gamma')
00012   params.gamma = 0.999995;
00013 end
00014 if ~isfield(params, 'mu')
00015   params.mu = 1;
00016 end
00017 if ~isfield(params, 'TolFun')
00018   params.TolFun = 1e-10;
00019 end
00020 if ~isfield(params, 'TolLineSearch')
00021   params.TolLineSearch = 1e-10;
00022 end
00023 if ~isfield(params, 'TolFuncCount')
00024   params.TolFuncCount = 1000;
00025 end
00026 if ~isfield(params, 'TolRes')
00027   params.TolRes = 1e-8;
00028 end
00029 if ~isfield(params, 'TolChange')
00030   params.TolChange = 1e-13;
00031 end
00032 if ~isfield(params, 'maxIter')
00033   params.maxIter = 300;
00034 end
00035 if ~isfield(params, 'rho')
00036   params.rho = 1e-8;
00037 end
00038 if ~isfield(params, 'armijo_p')
00039   params.armijo_p = 2.1;
00040 end
00041 if isfield(params, 'HessFun')
00042   compute_hess_matrix = 0;
00043 else
00044   compute_hess_matrix = 1;
00045 end
00046 
00047 if ~isfield(params, 'debug')
00048   params.debug = false;
00049 end
00050 
00051 
00052 tempsols = [];
00053 xnew = [];
00054 xold = x0;
00055 k = 0;
00056 Fold = inf;
00057 stepsizes = [];
00058 foms = [];
00059 resmaxes = [];
00060 imaxes = [];
00061 
00062 [F, J] = funptr(xold);
00063 %J = computed_jacobian(J, xold, funptr);
00064 [n, m] = size(J);
00065 f  = sum(F.*F);
00066 nF = sqrt(f);
00067 funcI = 1;
00068 
00069 while true;
00070 
00071   % function converged to zero
00072   [max_F, max_i] = max(abs(F));
00073   imaxes = [imaxes, max_i];
00074   resmaxes = [resmaxes, max_F];
00075   disp(['i = ', num2str(imaxes(end)), ' max = ', num2str(resmaxes(end))]);
00076   if resmaxes(end) < params.TolRes
00077     disp(resmaxes(end));
00078     exitflag = 1;
00079     if isempty(xnew)
00080       xnew = xold;
00081     end
00082     disp('Found solution.');
00083     disp(resmaxes(end));
00084 %    pause;
00085     break;
00086   end
00087 
00088   % change in residual too small
00089   if max(abs(F-Fold)) < params.TolChange
00090     exitflag = 3;
00091     disp('Change in residual too small');
00092     break;
00093   end
00094 
00095   %one_rows = find(xold(1:400) > 1-100*eps);
00096 %  if ~isempty(one_rows)
00097 %      keyboard;
00098 %  end
00099   %  TI = repmat(one_rows', m, 1);
00100   %  TI = TI(:);
00101   %  TJ = repmat((1:m)', 1, length(one_rows));
00102   %  TJ = TJ(:);
00103   %  T  = sparse(TI, TJ, ones(1, length(one_rows)*m), n, m);
00104 
00105   %J(sub2ind([n, m], one_rows, one_rows)) = 0;
00106 %  J(:, one_rows) = 0; %= %J - (J & T);
00107 
00108   % gradient f
00109   gf = J'*F;
00110 
00111   setup.type = 'nofill';
00112   setup.milu = 'row';
00113   setup.droptol = 1e-4;
00114   if isempty(xnew)
00115     if compute_hess_matrix
00116       Hess = J' * J;
00117 %      [L,U] = ilu(Hess, setup);
00118 %      dkU = gmres(@(X) Hess * X, -gf, 3, 1e-10, min(2500, m), L, U);
00119 %      dkU = cgs(Hess, -gf, [], [], L, U);
00120       dkU = Hess \ (-gf);
00121     else
00122 %      [HessTemp, precond] = params.HessFun(params, J, [], []);
00123       HessFunWrap = @(X) params.HessFun(params, J, [], X);
00124       dkU = bicgstab(HessFunWrap, -gf, 1e-12, 600);%,
00125 %      precond.L,precond.U);
00126 %      dkU = cgs(HessFunWrap, -gf, [], 300);
00127 %      dkU = gmres(HessFunWrap, -gf, [], 1e-12, min(2500, m));%, precond.L, precond.U);
00128     end
00129     if condest(Hess) > 1e-12
00130       xnew = params.Px(xold + dkU);
00131     else
00132       xnew = xold;
00133     end
00134     Fold = funptr(xnew);
00135   end
00136   muk = min(params.mu * (Fold'*Fold), 1) / (k+1);
00137 
00138   % first order optimalities
00139   foms = [foms, max(gf)];
00140 
00141   if max(abs(Fold)) > params.TolRes
00142     if compute_hess_matrix
00143       Hess = J' * J + muk .* speye(m,m);
00144 %      [L,U] = ilu(Hess, setup);
00145 %      dkU = bicgstab(Hess, -gf, 1e-10, 600, L, U);
00146 %      dkU = gmres(Hess, -gf, 2, 1e-10, min(2500, m), L, U);
00147       dkU = Hess \ (-gf);
00148     else
00149   %    [HessTemp, precond] = params.HessFun(params, J, [], []);
00150       HessFunWrap = @(X) params.HessFun(params, J, [], X) + muk .* X;
00151       dkU = gmres(HessFunWrap, -gf, 2, 1e-12, min(2500, m));%, precond.L, precond.U);
00152     end
00153   end
00154   pxnext = params.Px(xold + dkU);
00155 
00156   [Fcand, Jcand] = funptr(pxnext);
00157 %  Jcand = computed_jacobian(Jcand, pxnext, funptr);
00158   if params.debug
00159     [OK, ok_mat] = check_jacobian(pxnext, funptr, Jcand);
00160   end
00161 
00162   funcI = funcI + 1;
00163   fcand  = sum(Fcand.*Fcand);
00164   nFcand = sqrt(fcand);
00165 
00166   armijo_sk = pxnext - xold;
00167   if nFcand <= params.gamma * nF
00168     % found local iteration
00169     Fold = F;
00170     F    = Fcand;
00171     f    = fcand;
00172     nF   = nFcand;
00173     J    = Jcand;
00174     xnew = pxnext;
00175 
00176   else
00177     if gf' * armijo_sk <= - params.rho * norm(armijo_sk)^params.armijo_p
00178       % type line search direction
00179       sdir = armijo_sk;
00180 %      disp('armijo');
00181     else
00182       % projected gradient line search direction
00183       sdir = -gf;
00184 %      disp('gradient');
00185     end
00186 
00187     tkc = 1;
00188     while true
00189       % line search too small
00190       if tkc < params.TolLineSearch
00191         exitflag = -4;
00192         tk = 0;
00193         disp('Line search failed.');
00194         break;
00195       end
00196 
00197       xktkc  = params.Px(xold + tkc*sdir);
00198 
00199       [Fxktkc, J] = funptr(xktkc);
00200 %      J = computed_jacobian(J, xktkc, funptr);
00201       funcI = funcI + 1;
00202 
00203       if sum(Fxktkc.*Fxktkc) <= f + params.sigma * gf' * (xktkc - xold);
00204         Fold = F;
00205         F    = Fxktkc;
00206         f    = sum(F.*F);
00207         nF   = sqrt(f);
00208 
00209         xnew = xktkc;
00210         tk   = tkc;
00211         break;
00212       else
00213         tkc = tkc * params.beta;
00214       end
00215     end
00216     if tk == 0
00217       break;
00218     end
00219   end
00220 
00221   stepsizes = [stepsizes, norm(xnew - xold)];
00222   % x change to small
00223   if max(abs(xnew - xold)) < params.TolChange
00224     exitflag = 2;
00225     disp('Step change too small.');
00226     break;
00227   end
00228   xold = xnew;
00229 
00230   tempsols = [tempsols, xold];
00231 
00232   % too many iterations
00233   k    = k+1;
00234   if k > params.maxIter
00235     exitflag = 0;
00236     disp('Maximum number of iterations exceeded.');
00237     break;
00238   end
00239 
00240   if funcI > params.TolFuncCount
00241     exitflag = -1;
00242     disp('Maximum number of function evaluations exceeded.');
00243     break;
00244   end
00245 
00246 end
00247 
00248 resnorm              = f;
00249 residual             = F;
00250 output.iterations    = k;
00251 output.funcCount     = funcI;
00252 output.stepsize      = stepsizes;
00253 output.firstorderopt = foms;
00254 output.resmax        = resmaxes;
00255 
00256 %if nargout == 6
00257 %  tempsols = PCA_fixspace(tempsols, [], [], 2);
00258 %end
00259 
00260 end
00261 
00262 function jac_comp = computed_jacobian(jac_test, X, fun)
00263   jac_comp = zeros(size(jac_test));
00264 
00265   for j = 1:size(jac_test, 2);
00266     addend = zeros(size(X));
00267     addend(j) = 1e-10;
00268     jac_comp(:,j) = 1/(2e-10) .* (fun(X + addend) - fun(X - addend));
00269   end
00270 end
00271 function [OK, ok_mat] = check_jacobian(Utest, fun, jac_test, epsilon)
00272 
00273   if nargin <= 3
00274     epsilon = 5e-2;
00275   end
00276 
00277   jac_comp = computed_jacobian(jac_test, Utest, fun);
00278 
00279   nz_elements = abs(jac_comp) > 1e6*eps;
00280   ok_mat = zeros(size(jac_test));
00281   ok_mat(nz_elements) = abs(jac_comp(nz_elements) - jac_test(nz_elements))./(abs(jac_comp(nz_elements))) > epsilon;
00282   ok_mat = ok_mat + (nz_elements) - (abs(full(jac_test)) > 100*eps);
00283   OK = all(~ok_mat(:));
00284 
00285   if ~OK
00286     disp('Jacobian incorrect: ');
00287     keyboard;
00288   end
00289 end
All Classes Namespaces Files Functions Variables