Mercurial > octave
annotate scripts/optimization/sqp.m @ 8047:d54f113aa983
Increase test script tolerances.
author | Thomas Treichl <Thomas.Treichl@gmx.net> |
---|---|
date | Thu, 21 Aug 2008 14:04:04 -0400 |
parents | df9519e9990c |
children | 17352ccd860e |
rev | line source |
---|---|
7017 | 1 ## Copyright (C) 2005, 2006, 2007 John W. Eaton |
5289 | 2 ## |
3 ## This file is part of Octave. | |
4 ## | |
5 ## Octave is free software; you can redistribute it and/or modify it | |
6 ## under the terms of the GNU General Public License as published by | |
7016 | 7 ## the Free Software Foundation; either version 3 of the License, or (at |
8 ## your option) any later version. | |
5289 | 9 ## |
10 ## Octave is distributed in the hope that it will be useful, but | |
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 ## General Public License for more details. | |
14 ## | |
15 ## You should have received a copy of the GNU General Public License | |
7016 | 16 ## along with Octave; see the file COPYING. If not, see |
17 ## <http://www.gnu.org/licenses/>. | |
5289 | 18 |
19 ## -*- texinfo -*- | |
20 ## @deftypefn {Function File} {[@var{x}, @var{obj}, @var{info}, @var{iter}, @var{nf}, @var{lambda}] =} sqp (@var{x}, @var{phi}, @var{g}, @var{h}) | |
21 ## Solve the nonlinear program | |
6741 | 22 ## @iftex |
23 ## @tex | |
24 ## $$ | |
25 ## \min_x \phi (x) | |
26 ## $$ | |
27 ## @end tex | |
28 ## @end iftex | |
29 ## @ifnottex | |
5289 | 30 ## |
31 ## @example | |
32 ## min phi (x) | |
33 ## x | |
34 ## @end example | |
35 ## | |
6741 | 36 ## @end ifnottex |
37 ## subject to | |
5289 | 38 ## @iftex |
39 ## @tex | |
6741 | 40 ## $$ |
41 ## g(x) = 0 \qquad h(x) \geq 0 | |
42 ## $$ | |
5289 | 43 ## @end tex |
44 ## @end iftex | |
6741 | 45 ## @ifnottex |
5289 | 46 ## |
47 ## @example | |
48 ## g(x) = 0 | |
49 ## h(x) >= 0 | |
50 ## @end example | |
6741 | 51 ## @end ifnottex |
5289 | 52 ## |
53 ## @noindent | |
54 ## using a successive quadratic programming method. | |
55 ## | |
56 ## The first argument is the initial guess for the vector @var{x}. | |
57 ## | |
7001 | 58 ## The second argument is a function handle pointing to the objective |
5289 | 59 ## function. The objective function must be of the form |
60 ## | |
61 ## @example | |
62 ## y = phi (x) | |
63 ## @end example | |
64 ## | |
65 ## @noindent | |
66 ## in which @var{x} is a vector and @var{y} is a scalar. | |
67 ## | |
68 ## The second argument may also be a 2- or 3-element cell array of | |
69 ## function handles. The first element should point to the objective | |
70 ## function, the second should point to a function that computes the | |
71 ## gradient of the objective function, and the third should point to a | |
72 ## function to compute the hessian of the objective function. If the | |
73 ## gradient function is not supplied, the gradient is computed by finite | |
74 ## differences. If the hessian function is not supplied, a BFGS update | |
75 ## formula is used to approximate the hessian. | |
76 ## | |
77 ## If supplied, the gradient function must be of the form | |
78 ## | |
79 ## @example | |
7031 | 80 ## g = gradient (x) |
5289 | 81 ## @end example |
82 ## | |
83 ## @noindent | |
84 ## in which @var{x} is a vector and @var{g} is a vector. | |
85 ## | |
86 ## If supplied, the hessian function must be of the form | |
87 ## | |
88 ## @example | |
7031 | 89 ## h = hessian (x) |
5289 | 90 ## @end example |
91 ## | |
92 ## @noindent | |
93 ## in which @var{x} is a vector and @var{h} is a matrix. | |
94 ## | |
95 ## The third and fourth arguments are function handles pointing to | |
96 ## functions that compute the equality constraints and the inequality | |
97 ## constraints, respectively. | |
98 ## | |
99 ## If your problem does not have equality (or inequality) constraints, | |
100 ## you may pass an empty matrix for @var{cef} (or @var{cif}). | |
101 ## | |
102 ## If supplied, the equality and inequality constraint functions must be | |
103 ## of the form | |
104 ## | |
105 ## @example | |
7031 | 106 ## r = f (x) |
5289 | 107 ## @end example |
108 ## | |
109 ## @noindent | |
110 ## in which @var{x} is a vector and @var{r} is a vector. | |
111 ## | |
112 ## The third and fourth arguments may also be 2-element cell arrays of | |
113 ## function handles. The first element should point to the constraint | |
114 ## function and the second should point to a function that computes the | |
115 ## gradient of the constraint function: | |
116 ## | |
6741 | 117 ## @iftex |
118 ## @tex | |
119 ## $$ | |
120 ## \Bigg( {\partial f(x) \over \partial x_1}, | |
121 ## {\partial f(x) \over \partial x_2}, \ldots, | |
122 ## {\partial f(x) \over \partial x_N} \Bigg)^T | |
123 ## $$ | |
124 ## @end tex | |
125 ## @end iftex | |
126 ## @ifnottex | |
5289 | 127 ## @example |
128 ## [ d f(x) d f(x) d f(x) ] | |
129 ## transpose ( [ ------ ----- ... ------ ] ) | |
130 ## [ dx_1 dx_2 dx_N ] | |
131 ## @end example | |
6741 | 132 ## @end ifnottex |
5289 | 133 ## |
134 ## Here is an example of calling @code{sqp}: | |
135 ## | |
136 ## @example | |
7031 | 137 ## function r = g (x) |
138 ## r = [ sumsq(x)-10; | |
139 ## x(2)*x(3)-5*x(4)*x(5); | |
140 ## x(1)^3+x(2)^3+1 ]; | |
141 ## endfunction | |
142 ## | |
143 ## function obj = phi (x) | |
144 ## obj = exp(prod(x)) - 0.5*(x(1)^3+x(2)^3+1)^2; | |
145 ## endfunction | |
5289 | 146 ## |
7031 | 147 ## x0 = [-1.8; 1.7; 1.9; -0.8; -0.8]; |
148 ## | |
149 ## [x, obj, info, iter, nf, lambda] = sqp (x0, @@phi, @@g, []) | |
5289 | 150 ## |
7031 | 151 ## x = |
152 ## | |
153 ## -1.71714 | |
154 ## 1.59571 | |
155 ## 1.82725 | |
156 ## -0.76364 | |
157 ## -0.76364 | |
5289 | 158 ## |
7031 | 159 ## obj = 0.053950 |
160 ## info = 101 | |
161 ## iter = 8 | |
162 ## nf = 10 | |
163 ## lambda = | |
164 ## | |
165 ## -0.0401627 | |
166 ## 0.0379578 | |
167 ## -0.0052227 | |
5289 | 168 ## @end example |
169 ## | |
170 ## The value returned in @var{info} may be one of the following: | |
171 ## @table @asis | |
172 ## @item 101 | |
173 ## The algorithm terminated because the norm of the last step was less | |
174 ## than @code{tol * norm (x))} (the value of tol is currently fixed at | |
175 ## @code{sqrt (eps)}---edit @file{sqp.m} to modify this value. | |
176 ## @item 102 | |
177 ## The BFGS update failed. | |
178 ## @item 103 | |
179 ## The maximum number of iterations was reached (the maximum number of | |
180 ## allowed iterations is currently fixed at 100---edit @file{sqp.m} to | |
181 ## increase this value). | |
182 ## @end table | |
5642 | 183 ## @seealso{qp} |
5289 | 184 ## @end deftypefn |
185 | |
6768 | 186 function [x, obj, info, iter, nf, lambda] = sqp (x, objf, cef, cif, lb, ub, maxiter, tolerance) |
5289 | 187 |
6768 | 188 global __sqp_nfun__; |
5289 | 189 global __sqp_obj_fun__; |
190 global __sqp_ce_fun__; | |
191 global __sqp_ci_fun__; | |
6768 | 192 global __sqp_cif__; |
193 global __sqp_cifcn__; | |
5289 | 194 |
6768 | 195 if (nargin >= 2 && nargin <= 8 && nargin != 5) |
5289 | 196 |
197 ## Choose an initial NxN symmetric positive definite Hessan | |
198 ## approximation B. | |
199 | |
200 n = length (x); | |
201 | |
202 ## Evaluate objective function, constraints, and gradients at initial | |
203 ## value of x. | |
204 ## | |
205 ## obj_fun | |
206 ## obj_grad | |
207 ## ce_fun -- equality constraint functions | |
208 ## ci_fun -- inequality constraint functions | |
209 ## A == [grad_{x_1} cx_fun, grad_{x_2} cx_fun, ..., grad_{x_n} cx_fun]^T | |
210 | |
211 obj_grd = @fd_obj_grd; | |
212 have_hess = 0; | |
213 if (iscell (objf)) | |
214 if (length (objf) > 0) | |
215 __sqp_obj_fun__ = obj_fun = objf{1}; | |
216 if (length (objf) > 1) | |
217 obj_grd = objf{2}; | |
218 if (length (objf) > 2) | |
219 obj_hess = objf{3}; | |
220 have_hess = 1; | |
221 endif | |
222 endif | |
223 else | |
224 error ("sqp: invalid objective function"); | |
225 endif | |
226 else | |
227 __sqp_obj_fun__ = obj_fun = objf; | |
228 endif | |
229 | |
230 ce_fun = @empty_cf; | |
231 ce_grd = @empty_jac; | |
232 if (nargin > 2) | |
233 ce_grd = @fd_ce_jac; | |
234 if (iscell (cef)) | |
235 if (length (cef) > 0) | |
236 __sqp_ce_fun__ = ce_fun = cef{1}; | |
237 if (length (cef) > 1) | |
238 ce_grd = cef{2}; | |
239 endif | |
240 else | |
241 error ("sqp: invalid equality constraint function"); | |
242 endif | |
243 elseif (! isempty (cef)) | |
244 ce_fun = cef; | |
245 endif | |
246 endif | |
247 __sqp_ce_fun__ = ce_fun; | |
248 | |
249 ci_fun = @empty_cf; | |
250 ci_grd = @empty_jac; | |
6768 | 251 |
5289 | 252 if (nargin > 3) |
6768 | 253 ## constraint function given by user with possibly gradient |
254 __sqp_cif__ = cif; | |
255 ## constraint function given by user without gradient | |
256 __sqp_cifcn__ = @empty_cf; | |
257 if (iscell (__sqp_cif__)) | |
258 if (length (__sqp_cif__) > 0) | |
259 __sqp_cifcn__ = __sqp_cif__{1}; | |
260 endif | |
261 elseif (! isempty (__sqp_cif__)) | |
262 __sqp_cifcn__ = __sqp_cif__; | |
263 endif | |
264 | |
265 if (nargin < 5) | |
266 ci_grd = @fd_ci_jac; | |
267 if (iscell (cif)) | |
268 if (length (cif) > 0) | |
269 __sqp_ci_fun__ = ci_fun = cif{1}; | |
270 if (length (cif) > 1) | |
271 ci_grd = cif{2}; | |
272 endif | |
273 else | |
274 error ("sqp: invalid equality constraint function"); | |
5289 | 275 endif |
6768 | 276 elseif (! isempty (cif)) |
277 ci_fun = cif; | |
278 endif | |
279 else | |
280 global __sqp_lb__; | |
281 if (isvector (lb)) | |
282 __sqp_lb__ = lb; | |
283 elseif (isempty (lb)) | |
7795
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
284 if (isa (x, "single")) |
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
285 __sqp_lb__ = -realmax ("single"); |
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
286 else |
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
287 __sqp_lb__ = -realmax; |
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
288 endif |
5289 | 289 else |
6768 | 290 error ("sqp: invalid lower bound"); |
5289 | 291 endif |
6768 | 292 |
293 global __sqp_ub__; | |
294 if (isvector (ub)) | |
295 __sqp_ub__ = ub; | |
296 elseif (isempty (lb)) | |
7795
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
297 if (isa (x, "single")) |
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
298 __sqp_ub__ = realmax ("single"); |
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
299 else |
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
300 __sqp_ub__ = realmax; |
df9519e9990c
Handle single precision eps values
David Bateman <dbateman@free.fr>
parents:
7404
diff
changeset
|
301 endif |
6768 | 302 else |
303 error ("sqp: invalid upper bound"); | |
304 endif | |
305 | |
306 if (lb > ub) | |
307 error ("sqp: upper bound smaller than lower bound"); | |
308 endif | |
309 __sqp_ci_fun__ = ci_fun = @cf_ub_lb; | |
310 ci_grd = @cigrad_ub_lb; | |
311 endif | |
312 __sqp_ci_fun__ = ci_fun; | |
313 endif | |
314 | |
315 iter_max = 100; | |
316 if (nargin > 6 && ! isempty (maxiter)) | |
6921 | 317 if (isscalar (maxiter) && maxiter > 0 && round (maxiter) == maxiter) |
6768 | 318 iter_max = maxiter; |
319 else | |
320 error ("sqp: invalid number of maximum iterations"); | |
5289 | 321 endif |
322 endif | |
323 | |
6768 | 324 tol = sqrt (eps); |
325 if (nargin > 7 && ! isempty (tolerance)) | |
326 if (isscalar (tolerance) && tolerance > 0) | |
327 tol = tolerance; | |
328 else | |
329 error ("sqp: invalid value for tolerance"); | |
330 endif | |
331 endif | |
5289 | 332 |
333 iter = 0; | |
334 | |
335 obj = feval (obj_fun, x); | |
6768 | 336 __sqp_nfun__ = 1; |
5289 | 337 |
338 c = feval (obj_grd, x); | |
339 | |
6382 | 340 if (have_hess) |
341 B = feval (obj_hess, x); | |
342 else | |
343 B = eye (n, n); | |
344 endif | |
345 | |
5289 | 346 ce = feval (ce_fun, x); |
347 F = feval (ce_grd, x); | |
348 | |
349 ci = feval (ci_fun, x); | |
350 C = feval (ci_grd, x); | |
351 | |
352 A = [F; C]; | |
353 | |
354 ## Choose an initial lambda (x is provided by the caller). | |
355 | |
356 lambda = 100 * ones (rows (A), 1); | |
357 | |
358 qp_iter = 1; | |
359 alpha = 1; | |
360 | |
361 ## report (); | |
362 | |
6768 | 363 ## report (iter, qp_iter, alpha, __sqp_nfun__, obj); |
5289 | 364 |
6527 | 365 info = 0; |
366 | |
5289 | 367 while (++iter < iter_max) |
368 | |
369 ## Check convergence. This is just a simple check on the first | |
370 ## order necessary conditions. | |
371 | |
372 ## IDX is the indices of the active inequality constraints. | |
373 | |
374 nr_f = rows (F); | |
375 | |
376 lambda_e = lambda((1:nr_f)'); | |
377 lambda_i = lambda((nr_f+1:end)'); | |
378 | |
379 con = [ce; ci]; | |
380 | |
381 t0 = norm (c - A' * lambda); | |
382 t1 = norm (ce); | |
383 t2 = all (ci >= 0); | |
384 t3 = all (lambda_i >= 0); | |
385 t4 = norm (lambda .* con); | |
386 | |
387 if (t2 && t3 && max ([t0; t1; t4]) < tol) | |
388 break; | |
389 endif | |
390 | |
391 ## Compute search direction p by solving QP. | |
392 | |
393 g = -ce; | |
394 d = -ci; | |
395 | |
396 ## Discard inequality constraints that have -Inf bounds since those | |
397 ## will never be active. | |
398 idx = isinf (d) & d < 0; | |
399 d(idx) = []; | |
400 C(idx,:) = []; | |
401 | |
402 [p, obj_qp, INFO, lambda] = qp (x, B, c, F, g, [], [], d, C, | |
403 Inf * ones (size (d))); | |
404 | |
405 info = INFO.info; | |
406 | |
407 ## Check QP solution and attempt to recover if it has failed. | |
408 | |
409 ## Choose mu such that p is a descent direction for the chosen | |
410 ## merit function phi. | |
411 | |
412 [x_new, alpha, obj_new] = linesearch_L1 (x, p, obj_fun, obj_grd, | |
413 ce_fun, ci_fun, lambda, obj); | |
414 | |
415 ## Evaluate objective function, constraints, and gradients at | |
416 ## x_new. | |
417 | |
418 c_new = feval (obj_grd, x_new); | |
419 | |
420 ce_new = feval (ce_fun, x_new); | |
421 F_new = feval (ce_grd, x_new); | |
422 | |
423 ci_new = feval (ci_fun, x_new); | |
424 C_new = feval (ci_grd, x_new); | |
425 | |
426 A_new = [F_new; C_new]; | |
427 | |
428 ## Set | |
429 ## | |
430 ## s = alpha * p | |
431 ## y = grad_x L (x_new, lambda) - grad_x L (x, lambda}) | |
432 | |
433 y = c_new - c; | |
434 | |
435 if (! isempty (A)) | |
436 t = ((A_new - A)'*lambda); | |
437 y -= t; | |
438 endif | |
439 | |
440 delx = x_new - x; | |
441 | |
442 if (norm (delx) < tol * norm (x)) | |
443 info = 101; | |
444 break; | |
445 endif | |
446 | |
447 if (have_hess) | |
448 | |
449 B = feval (obj_hess, x); | |
450 | |
451 else | |
452 | |
453 ## Update B using a quasi-Newton formula. | |
454 | |
455 delxt = delx'; | |
456 | |
457 ## Damped BFGS. Or maybe we would actually want to use the Hessian | |
458 ## of the Lagrangian, computed directly. | |
459 | |
460 d1 = delxt*B*delx; | |
461 | |
462 t1 = 0.2 * d1; | |
463 t2 = delxt*y; | |
464 | |
465 if (t2 < t1) | |
466 theta = 0.8*d1/(d1 - t2); | |
467 else | |
468 theta = 1; | |
469 endif | |
470 | |
471 r = theta*y + (1-theta)*B*delx; | |
472 | |
473 d2 = delxt*r; | |
474 | |
475 if (d1 == 0 || d2 == 0) | |
476 info = 102; | |
477 break; | |
478 endif | |
479 | |
480 B = B - B*delx*delxt*B/d1 + r*r'/d2; | |
481 | |
482 endif | |
483 | |
484 x = x_new; | |
485 | |
486 obj = obj_new; | |
487 | |
488 c = c_new; | |
489 | |
490 ce = ce_new; | |
491 F = F_new; | |
492 | |
493 ci = ci_new; | |
494 C = C_new; | |
495 | |
496 A = A_new; | |
497 | |
6768 | 498 ## report (iter, qp_iter, alpha, __sqp_nfun__, obj); |
5289 | 499 |
500 endwhile | |
501 | |
502 if (iter >= iter_max) | |
503 info = 103; | |
504 endif | |
505 | |
6768 | 506 nf = __sqp_nfun__; |
5289 | 507 |
508 else | |
509 | |
6046 | 510 print_usage (); |
5289 | 511 |
512 endif | |
513 | |
7399 | 514 endfunction |
5289 | 515 |
516 | |
517 function [merit, obj] = phi_L1 (obj, obj_fun, ce_fun, ci_fun, x, mu) | |
518 | |
6768 | 519 global __sqp_nfun__; |
5289 | 520 |
521 ce = feval (ce_fun, x); | |
522 ci = feval (ci_fun, x); | |
523 | |
524 idx = ci < 0; | |
525 | |
526 con = [ce; ci(idx)]; | |
527 | |
528 if (isempty (obj)) | |
529 obj = feval (obj_fun, x); | |
6768 | 530 __sqp_nfun__++; |
5289 | 531 endif |
532 | |
533 merit = obj; | |
534 t = norm (con, 1) / mu; | |
535 | |
536 if (! isempty (t)) | |
537 merit += t; | |
538 endif | |
539 | |
7399 | 540 endfunction |
5289 | 541 |
542 | |
543 function [x_new, alpha, obj] = linesearch_L1 (x, p, obj_fun, obj_grd, | |
544 ce_fun, ci_fun, lambda, obj) | |
545 | |
546 ## Choose parameters | |
547 ## | |
548 ## eta in the range (0, 0.5) | |
549 ## tau in the range (0, 1) | |
550 | |
551 eta = 0.25; | |
552 tau = 0.5; | |
553 | |
554 delta_bar = sqrt (eps); | |
555 | |
556 if (isempty (lambda)) | |
557 mu = 1 / delta_bar; | |
558 else | |
559 mu = 1 / (norm (lambda, Inf) + delta_bar); | |
560 endif | |
561 | |
562 alpha = 1; | |
563 | |
564 c = feval (obj_grd, x); | |
565 ce = feval (ce_fun, x); | |
566 | |
567 [phi_x_mu, obj] = phi_L1 (obj, obj_fun, ce_fun, ci_fun, x, mu); | |
568 | |
569 D_phi_x_mu = c' * p; | |
570 d = feval (ci_fun, x); | |
571 ## only those elements of d corresponding | |
572 ## to violated constraints should be included. | |
573 idx = d < 0; | |
574 t = - norm ([ce; d(idx)], 1) / mu; | |
575 if (! isempty (t)) | |
576 D_phi_x_mu += t; | |
577 endif | |
578 | |
579 while (1) | |
580 [p1, obj] = phi_L1 ([], obj_fun, ce_fun, ci_fun, x+alpha*p, mu); | |
581 p2 = phi_x_mu+eta*alpha*D_phi_x_mu; | |
582 if (p1 > p2) | |
583 ## Reset alpha = tau_alpha * alpha for some tau_alpha in the | |
584 ## range (0, tau). | |
585 tau_alpha = 0.9 * tau; ## ?? | |
586 alpha = tau_alpha * alpha; | |
587 else | |
588 break; | |
589 endif | |
590 endwhile | |
591 | |
592 ## Set x_new = x + alpha * p; | |
593 | |
594 x_new = x + alpha * p; | |
595 | |
7399 | 596 endfunction |
5289 | 597 |
598 | |
599 function report (iter, qp_iter, alpha, nfun, obj) | |
600 | |
601 if (nargin == 0) | |
602 printf (" Itn ItQP Step Nfun Objective\n"); | |
603 else | |
604 printf ("%5d %4d %8.1g %5d %13.6e\n", iter, qp_iter, alpha, nfun, obj); | |
605 endif | |
606 | |
7399 | 607 endfunction |
5289 | 608 |
609 | |
610 function grd = fdgrd (f, x) | |
611 | |
612 if (! isempty (f)) | |
613 y0 = feval (f, x); | |
614 nx = length (x); | |
615 grd = zeros (nx, 1); | |
616 deltax = sqrt (eps); | |
617 for i = 1:nx | |
618 t = x(i); | |
619 x(i) += deltax; | |
620 grd(i) = (feval (f, x) - y0) / deltax; | |
621 x(i) = t; | |
622 endfor | |
623 else | |
624 grd = zeros (0, 1); | |
625 endif | |
626 | |
7399 | 627 endfunction |
5289 | 628 |
629 | |
630 function jac = fdjac (f, x) | |
6768 | 631 nx = length (x); |
5289 | 632 if (! isempty (f)) |
633 y0 = feval (f, x); | |
634 nf = length (y0); | |
635 nx = length (x); | |
636 jac = zeros (nf, nx); | |
637 deltax = sqrt (eps); | |
638 for i = 1:nx | |
639 t = x(i); | |
640 x(i) += deltax; | |
641 jac(:,i) = (feval (f, x) - y0) / deltax; | |
642 x(i) = t; | |
643 endfor | |
644 else | |
645 jac = zeros (0, nx); | |
646 endif | |
647 | |
7399 | 648 endfunction |
5289 | 649 |
650 | |
651 function grd = fd_obj_grd (x) | |
652 | |
653 global __sqp_obj_fun__; | |
654 | |
655 grd = fdgrd (__sqp_obj_fun__, x); | |
656 | |
7399 | 657 endfunction |
5289 | 658 |
659 | |
660 function res = empty_cf (x) | |
661 | |
662 res = zeros (0, 1); | |
663 | |
7399 | 664 endfunction |
5289 | 665 |
666 | |
667 function res = empty_jac (x) | |
668 | |
669 res = zeros (0, length (x)); | |
670 | |
7399 | 671 endfunction |
5289 | 672 |
673 | |
674 function jac = fd_ce_jac (x) | |
675 | |
676 global __sqp_ce_fun__; | |
677 | |
678 jac = fdjac (__sqp_ce_fun__, x); | |
679 | |
7399 | 680 endfunction |
5289 | 681 |
682 | |
683 function jac = fd_ci_jac (x) | |
684 | |
6768 | 685 global __sqp_cifcn__; |
686 ## __sqp_cifcn__ = constraint function without gradients and lb or ub | |
687 jac = fdjac (__sqp_cifcn__, x); | |
688 | |
7399 | 689 endfunction |
6768 | 690 |
7017 | 691 |
6768 | 692 function res = cf_ub_lb (x) |
5289 | 693 |
6768 | 694 ## combine constraint function with ub and lb |
695 global __sqp_cifcn__ __sqp_lb__ __sqp_ub__ | |
696 | |
697 res = [x-__sqp_lb__; __sqp_ub__-x]; | |
698 | |
699 if (! isempty (__sqp_cifcn__)) | |
700 res = [feval(__sqp_cifcn__,x); x-__sqp_lb__; __sqp_ub__-x]; | |
701 endif | |
5289 | 702 |
7399 | 703 endfunction |
6768 | 704 |
7017 | 705 |
6768 | 706 function res = cigrad_ub_lb (x) |
707 | |
708 global __sqp_cif__ | |
709 | |
710 res = [eye(numel(x)); -eye(numel(x))]; | |
711 | |
712 cigradfcn = @fd_ci_jac; | |
713 | |
714 if (iscell (__sqp_cif__) && length (__sqp_cif__) > 1) | |
715 cigradfcn = __sqp_cif__{2}; | |
716 endif | |
717 | |
718 if (! isempty (cigradfcn)) | |
719 res = [feval(cigradfcn,x); eye(numel(x)); -eye(numel(x))]; | |
720 endif | |
721 | |
7399 | 722 endfunction |
7361 | 723 |
7371 | 724 %!function r = g (x) |
725 %! r = [sumsq(x)-10; | |
726 %! x(2)*x(3)-5*x(4)*x(5); | |
727 %! x(1)^3+x(2)^3+1 ]; | |
7361 | 728 %! |
7371 | 729 %!function obj = phi (x) |
730 %! obj = exp(prod(x)) - 0.5*(x(1)^3+x(2)^3+1)^2; | |
7361 | 731 %! |
732 %!test | |
733 %! x0 = [-1.8; 1.7; 1.9; -0.8; -0.8]; | |
734 %! | |
7381 | 735 %! [x, obj, info, iter, nf, lambda] = sqp (x0, @phi, @g, []); |
7361 | 736 %! |
737 %! x_opt = [-1.717143501952599; | |
738 %! 1.595709610928535; | |
739 %! 1.827245880097156; | |
740 %! -0.763643103133572; | |
741 %! -0.763643068453300]; | |
742 %! | |
7371 | 743 %! obj_opt = 0.0539498477702739; |
7361 | 744 %! |
8047
d54f113aa983
Increase test script tolerances.
Thomas Treichl <Thomas.Treichl@gmx.net>
parents:
7795
diff
changeset
|
745 %! assert (all (abs (x-x_opt) < 5*sqrt (eps)) && abs (obj-obj_opt) < sqrt (eps)); |