rbmatlab 0.10.01
general/newton_raphson.m
Go to the documentation of this file.
00001 function [xnew, resnorm, residual, exitflag, output] = newton_raphson(funptr, x0, params)
00002 % function [vnew, resnorm, residual, exitflags, output] = newton_raphson(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, 'gamma')
00009   params.gamma = 0.999995;
00010 end
00011 if ~isfield(params, 'sigma')
00012   params.sigma = 1e-4;
00013 end
00014 if ~isfield(params, 'TolLineSearch')
00015   params.TolLineSearch = 1e-10;
00016 end
00017 if ~isfield(params, 'TolFuncCount')
00018   params.TolFuncCount = inf;
00019 end
00020 if ~isfield(params, 'TolRes')
00021   params.TolRes = 1e-8;
00022 end
00023 if ~isfield(params, 'TolChange')
00024   params.TolChange = 1e-10;
00025 end
00026 if ~isfield(params, 'maxIter')
00027   params.maxIter = inf;
00028 end
00029 
00030 if ~isfield(params, 'debug')
00031   params.debug = false;
00032 end
00033 
00034 xnew = [];
00035 xold = x0;
00036 k = 0;
00037 Fold = inf;
00038 stepsizes = [];
00039 foms = [];
00040 resmaxes = [];
00041 imaxes = [];
00042 
00043 [F, J] = funptr(xold);
00044 %J = computed_jacobian(J, xold, funptr);
00045 [n, m] = size(J);
00046 f  = sum(F.*F);
00047 nF = sqrt(f);
00048 funcI = 1;
00049 
00050 while true;
00051 
00052   % function converged to zero
00053   [max_F, max_i] = max(abs(F));
00054   imaxes = [imaxes, max_i];
00055   resmaxes = [resmaxes, max_F];
00056   disp(['i = ', num2str(imaxes(end)), ' max = ', num2str(resmaxes(end))]);
00057   if resmaxes(end) < params.TolRes
00058     disp(resmaxes(end));
00059     exitflag = 1;
00060     if isempty(xnew)
00061       xnew = xold;
00062     end
00063     disp('Found solution.');
00064     disp(resmaxes(end));
00065 %    pause;
00066     break;
00067   end
00068 
00069   % change in residual too small
00070   if max(abs(F-Fold)) < params.TolChange
00071     exitflag = 3;
00072     disp('Change in residual too small');
00073     break;
00074   end
00075 
00076   %one_rows = find(xold(1:400) > 1-100*eps);
00077 %  if ~isempty(one_rows)
00078 %      keyboard;
00079 %  end
00080   %  TI = repmat(one_rows', m, 1);
00081   %  TI = TI(:);
00082   %  TJ = repmat((1:m)', 1, length(one_rows));
00083   %  TJ = TJ(:);
00084   %  T  = sparse(TI, TJ, ones(1, length(one_rows)*m), n, m);
00085 
00086   %J(sub2ind([n, m], one_rows, one_rows)) = 0;
00087 %  J(:, one_rows) = 0; %= %J - (J & T);
00088 
00089   gf = J'*F;
00090   defect = (J) \ -F;
00091   xnew = params.Px(xold + defect);
00092 
00093   % first order optimalities
00094   foms = [foms, max(gf)];
00095 
00096   [Fnew, Jnew] = funptr(xnew);
00097   fnew  = sum(Fnew.*Fnew);
00098   nFnew = sqrt(fnew);
00099   funcI = funcI + 1;
00100 
00101   if params.debug
00102     [OK, ok_mat] = check_jacobian(pxnext, funptr, Jcand);
00103   end
00104 
00105   if nFnew <= params.gamma * nF
00106     % found local iteration
00107     Fold = F;
00108     F    = Fnew;
00109     f    = fnew;
00110     nF   = nFnew;
00111     J    = Jnew;
00112 
00113   else
00114     tkc = params.beta;
00115     while true
00116       % line search too small
00117       if tkc < params.TolLineSearch
00118         exitflag = -4;
00119         tk = 0;
00120         disp('Line search failed.');
00121         break;
00122       end
00123 
00124       xnew  = params.Px(xold + tkc*defect);
00125 
00126       [Fnew, Jnew] = funptr(xnew);
00127       fnew  = sum(Fnew.*Fnew);
00128       nFnew = sqrt(fnew);
00129       funcI = funcI + 1;
00130 
00131       if sum(Fnew.*Fnew) <= f + params.sigma * gf' * defect
00132         Fold = F;
00133         F    = Fnew;
00134         f    = fnew;
00135         nF   = nFnew;
00136 
00137         tk   = tkc;
00138         break;
00139       else
00140         tkc = tkc * params.beta;
00141       end
00142     end
00143     if tk == 0
00144       break;
00145     end
00146   end
00147 
00148   stepsizes = [stepsizes, norm(xnew - xold)];
00149   % x change to small
00150   if max(abs(xnew - xold)) < params.TolChange
00151     exitflag = 2;
00152     disp('Step change too small.');
00153     break;
00154   end
00155   xold = xnew;
00156 
00157 %  tempsols = [tempsols, xold];
00158 
00159   % too many iterations
00160   k    = k+1;
00161   if k > params.maxIter
00162     exitflag = 0;
00163     disp('Maximum number of iterations exceeded.');
00164     break;
00165   end
00166 
00167   if funcI > params.TolFuncCount
00168     exitflag = -1;
00169     disp('Maximum number of function evaluations exceeded.');
00170     break;
00171   end
00172 
00173 end
00174 
00175 resnorm              = f;
00176 residual             = F;
00177 output.iterations    = k;
00178 output.funcCount     = funcI;
00179 output.stepsize      = stepsizes;
00180 output.firstorderopt = foms;
00181 output.resmax        = resmaxes;
00182 
00183 %if nargout == 6
00184 %  tempsols = PCA_fixspace(tempsols, [], [], 2);
00185 %end
00186 
00187 end
00188 
00189 function jac_comp = computed_jacobian(jac_test, X, fun)
00190   jac_comp = zeros(size(jac_test));
00191 
00192   for j = 1:size(jac_test, 2);
00193     addend = zeros(size(X));
00194     addend(j) = 1e-10;
00195     jac_comp(:,j) = 1/(2e-10) .* (fun(X + addend) - fun(X - addend));
00196   end
00197 end
00198 function [OK, ok_mat] = check_jacobian(Utest, fun, jac_test, epsilon)
00199 
00200   if nargin <= 3
00201     epsilon = 5e-2;
00202   end
00203 
00204   jac_comp = computed_jacobian(jac_test, Utest, fun);
00205 
00206   nz_elements = abs(jac_comp) > 1e6*eps;
00207   ok_mat = zeros(size(jac_test));
00208   ok_mat(nz_elements) = abs(jac_comp(nz_elements) - jac_test(nz_elements))./(abs(jac_comp(nz_elements))) > epsilon;
00209   ok_mat = ok_mat + (nz_elements) - (abs(full(jac_test)) > 100*eps);
00210   OK = all(~ok_mat(:));
00211 
00212   if ~OK
00213     disp('Jacobian incorrect: ');
00214     keyboard;
00215   end
00216 end
All Classes Namespaces Files Functions Variables