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