rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
gplmm.m
Go to the documentation of this file.
1 function [xnew, resnorm, residual, exitflag, output, tempsols] = gplmm(funptr, x0, params)
2 % function [vnew, resnorm, residual, output, exitflags] = gplmm(funptr, vold, params)
3 % Global projected Levenberg-Marquard method
4 
5 if ~isfield(params, 'beta')
6  params.beta = 0.1;
7 end
8 if ~isfield(params, 'sigma')
9  params.sigma = 1e-4;
10 end
11 if ~isfield(params, 'gamma')
12  params.gamma = 0.999995;
13 end
14 if ~isfield(params, 'mu')
15  params.mu = 1;
16 end
17 if ~isfield(params, 'TolFun')
18  params.TolFun = 1e-10;
19 end
20 if ~isfield(params, 'TolLineSearch')
21  params.TolLineSearch = 1e-10;
22 end
23 if ~isfield(params, 'TolFuncCount')
24  params.TolFuncCount = 1000;
25 end
26 if ~isfield(params, 'TolRes')
27  params.TolRes = 1e-8;
28 end
29 if ~isfield(params, 'TolChange')
30  params.TolChange = 1e-13;
31 end
32 if ~isfield(params, 'maxIter')
33  params.maxIter = 300;
34 end
35 if ~isfield(params, 'rho')
36  params.rho = 1e-8;
37 end
38 if ~isfield(params, 'armijo_p')
39  params.armijo_p = 2.1;
40 end
41 if isfield(params, 'HessFun')
42  compute_hess_matrix = 0;
43 else
44  compute_hess_matrix = 1;
45 end
46 
47 if ~isfield(params, 'debug')
48  params.debug = false;
49 end
50 
51 
52 tempsols = [];
53 xnew = [];
54 xold = x0;
55 k = 0;
56 Fold = inf;
57 stepsizes = [];
58 foms = [];
59 resmaxes = [];
60 imaxes = [];
61 
62 [F, J] = funptr(xold);
63 %J = computed_jacobian(J, xold, funptr);
64 [n, m] = size(J);
65 f = sum(F.*F);
66 nF = sqrt(f);
67 funcI = 1;
68 
69 while true;
70 
71  % function converged to zero
72  [max_F, max_i] = max(abs(F));
73  imaxes = [imaxes, max_i];
74  resmaxes = [resmaxes, max_F];
75  disp(['i = ', num2str(imaxes(end)), ' max = ', num2str(resmaxes(end))]);
76  if resmaxes(end) < params.TolRes
77  disp(resmaxes(end));
78  exitflag = 1;
79  if isempty(xnew)
80  xnew = xold;
81  end
82  disp('Found solution.');
83  disp(resmaxes(end));
84 % pause;
85  break;
86  end
87 
88  % change in residual too small
89  if max(abs(F-Fold)) < params.TolChange
90  exitflag = 3;
91  disp('Change in residual too small');
92  break;
93  end
94 
95  %one_rows = find(xold(1:400) > 1-100*eps);
96 % if ~isempty(one_rows)
97 % keyboard;
98 % end
99  % TI = repmat(one_rows', m, 1);
100  % TI = TI(:);
101  % TJ = repmat((1:m)', 1, length(one_rows));
102  % TJ = TJ(:);
103  % T = sparse(TI, TJ, ones(1, length(one_rows)*m), n, m);
104 
105  %J(sub2ind([n, m], one_rows, one_rows)) = 0;
106 % J(:, one_rows) = 0; %= %J - (J & T);
107 
108  % gradient f
109  gf = J'*F;
110 
111  setup.type = 'nofill';
112  setup.milu = 'row';
113  setup.droptol = 1e-4;
114  if isempty(xnew)
115  if compute_hess_matrix
116  Hess = J' * J;
117 % [L,U] = ilu(Hess, setup);
118 % dkU = gmres(@(X) Hess * X, -gf, 3, 1e-10, min(2500, m), L, U);
119 % dkU = cgs(Hess, -gf, [], [], L, U);
120  dkU = Hess \ (-gf);
121  else
122 % [HessTemp, precond] = params.HessFun(params, J, [], []);
123  HessFunWrap = @(X) params.HessFun(params, J, [], X);
124  dkU = bicgstab(HessFunWrap, -gf, 1e-12, 600);%,
125 % precond.L,precond.U);
126 % dkU = cgs(HessFunWrap, -gf, [], 300);
127 % dkU = gmres(HessFunWrap, -gf, [], 1e-12, min(2500, m));%, precond.L, precond.U);
128  end
129  if condest(Hess) > 1e-12
130  xnew = params.Px(xold + dkU);
131  else
132  xnew = xold;
133  end
134  Fold = funptr(xnew);
135  end
136  muk = min(params.mu * (Fold'*Fold), 1) / (k+1);
137 
138  % first order optimalities
139  foms = [foms, max(gf)];
140 
141  if max(abs(Fold)) > params.TolRes
142  if compute_hess_matrix
143  Hess = J' * J + muk .* speye(m,m);
144 % [L,U] = ilu(Hess, setup);
145 % dkU = bicgstab(Hess, -gf, 1e-10, 600, L, U);
146 % dkU = gmres(Hess, -gf, 2, 1e-10, min(2500, m), L, U);
147  dkU = Hess \ (-gf);
148  else
149  % [HessTemp, precond] = params.HessFun(params, J, [], []);
150  HessFunWrap = @(X) params.HessFun(params, J, [], X) + muk .* X;
151  dkU = gmres(HessFunWrap, -gf, 2, 1e-12, min(2500, m));%, precond.L, precond.U);
152  end
153  end
154  pxnext = params.Px(xold + dkU);
155 
156  [Fcand, Jcand] = funptr(pxnext);
157 % Jcand = computed_jacobian(Jcand, pxnext, funptr);
158  if params.debug
159  [OK, ok_mat] = check_jacobian(pxnext, funptr, Jcand);
160  end
161 
162  funcI = funcI + 1;
163  fcand = sum(Fcand.*Fcand);
164  nFcand = sqrt(fcand);
165 
166  armijo_sk = pxnext - xold;
167  if nFcand <= params.gamma * nF
168  % found local iteration
169  Fold = F;
170  F = Fcand;
171  f = fcand;
172  nF = nFcand;
173  J = Jcand;
174  xnew = pxnext;
175 
176  else
177  if gf' * armijo_sk <= - params.rho * norm(armijo_sk)^params.armijo_p
178  % type line search direction
179  sdir = armijo_sk;
180 % disp('armijo');
181  else
182  % projected gradient line search direction
183  sdir = -gf;
184 % disp('gradient');
185  end
186 
187  tkc = 1;
188  while true
189  % line search too small
190  if tkc < params.TolLineSearch
191  exitflag = -4;
192  tk = 0;
193  disp('Line search failed.');
194  break;
195  end
196 
197  xktkc = params.Px(xold + tkc*sdir);
198 
199  [Fxktkc, J] = funptr(xktkc);
200 % J = computed_jacobian(J, xktkc, funptr);
201  funcI = funcI + 1;
202 
203  if sum(Fxktkc.*Fxktkc) <= f + params.sigma * gf' * (xktkc - xold);
204  Fold = F;
205  F = Fxktkc;
206  f = sum(F.*F);
207  nF = sqrt(f);
208 
209  xnew = xktkc;
210  tk = tkc;
211  break;
212  else
213  tkc = tkc * params.beta;
214  end
215  end
216  if tk == 0
217  break;
218  end
219  end
220 
221  stepsizes = [stepsizes, norm(xnew - xold)];
222  % x change to small
223  if max(abs(xnew - xold)) < params.TolChange
224  exitflag = 2;
225  disp('Step change too small.');
226  break;
227  end
228  xold = xnew;
229 
230  tempsols = [tempsols, xold];
231 
232  % too many iterations
233  k = k+1;
234  if k > params.maxIter
235  exitflag = 0;
236  disp('Maximum number of iterations exceeded.');
237  break;
238  end
239 
240  if funcI > params.TolFuncCount
241  exitflag = -1;
242  disp('Maximum number of function evaluations exceeded.');
243  break;
244  end
245 
246 end
247 
248 resnorm = f;
249 residual = F;
250 output.iterations = k;
251 output.funcCount = funcI;
252 output.stepsize = stepsizes;
253 output.firstorderopt = foms;
254 output.resmax = resmaxes;
255 
256 %if nargout == 6
257 % tempsols = PCA_fixspace(tempsols, [], [], 2);
258 %end
259 
260 end
261 
262 function jac_comp = computed_jacobian(jac_test, X, fun)
263  jac_comp = zeros(size(jac_test));
264 
265  for j = 1:size(jac_test, 2);
266  addend = zeros(size(X));
267  addend(j) = 1e-10;
268  jac_comp(:,j) = 1/(2e-10) .* (fun(X + addend) - fun(X - addend));
269  end
270 end
271 function [OK, ok_mat] = check_jacobian(Utest, fun, jac_test, epsilon)
272 
273  if nargin <= 3
274  epsilon = 5e-2;
275  end
276 
277  jac_comp = computed_jacobian(jac_test, Utest, fun);
278 
279  nz_elements = abs(jac_comp) > 1e6*eps;
280  ok_mat = zeros(size(jac_test));
281  ok_mat(nz_elements) = abs(jac_comp(nz_elements) - jac_test(nz_elements))./(abs(jac_comp(nz_elements))) > epsilon;
282  ok_mat = ok_mat + (nz_elements) - (abs(full(jac_test)) > 100*eps);
283  OK = all(~ok_mat(:));
284 
285  if ~OK
286  disp('Jacobian incorrect: ');
287  keyboard;
288  end
289 end
function [ xnew , resnorm , residual , exitflag , output , tempsols ] = gplmm(funptr, x0, params)
Global projected Levenberg-Marquard method.
Definition: gplmm.m:17