Mercurial > octave
comparison scripts/optimization/sqp.m @ 31653:972dcc46bb41
sqp.m: Ignore missing lower/upper bounds (bug #32008)
* sqp.m: Avoid setting lower and upper bounds to +/-realmax when
unspecified in the function call. Set bounds to +/-Inf in main
function. Update constraint subfunction to correctly return empty
distance to constraint when bounds are unspecified.
author | Julien Bect <julien.bect@supelec.fr> |
---|---|
date | Thu, 08 Dec 2022 15:23:29 -0500 |
parents | c05ef94a2bbc |
children | 5f11de0e7440 |
comparison
equal
deleted
inserted
replaced
31652:a18897e4c7b5 | 31653:972dcc46bb41 |
---|---|
119 ## The fifth and sixth arguments, @var{lb} and @var{ub}, contain lower and | 119 ## The fifth and sixth arguments, @var{lb} and @var{ub}, contain lower and |
120 ## upper bounds on @var{x}. These must be consistent with the equality and | 120 ## upper bounds on @var{x}. These must be consistent with the equality and |
121 ## inequality constraints @var{g} and @var{h}. If the arguments are vectors | 121 ## inequality constraints @var{g} and @var{h}. If the arguments are vectors |
122 ## then @var{x}(i) is bound by @var{lb}(i) and @var{ub}(i). A bound can also | 122 ## then @var{x}(i) is bound by @var{lb}(i) and @var{ub}(i). A bound can also |
123 ## be a scalar in which case all elements of @var{x} will share the same | 123 ## be a scalar in which case all elements of @var{x} will share the same |
124 ## bound. If only one bound (lb, ub) is specified then the other will | 124 ## bound. |
125 ## default to (-@var{realmax}, +@var{realmax}). | |
126 ## | 125 ## |
127 ## The seventh argument @var{maxiter} specifies the maximum number of | 126 ## The seventh argument @var{maxiter} specifies the maximum number of |
128 ## iterations. The default value is 100. | 127 ## iterations. The default value is 100. |
129 ## | 128 ## |
130 ## The eighth argument @var{tolerance} specifies the tolerance for the stopping | 129 ## The eighth argument @var{tolerance} specifies the tolerance for the stopping |
286 endif | 285 endif |
287 else | 286 else |
288 ## constraint inequality function with bounds present | 287 ## constraint inequality function with bounds present |
289 lb_idx = ub_idx = true (size (x0)); | 288 lb_idx = ub_idx = true (size (x0)); |
290 ub_grad = - (lb_grad = eye (rows (x0))); | 289 ub_grad = - (lb_grad = eye (rows (x0))); |
290 | |
291 ## if unspecified set ub and lb to +/-Inf, preserving single type | |
292 if (isempty (lb)) | |
293 if (isa (x0, "single")) | |
294 lb = - inf (size (x0), "single"); | |
295 else | |
296 lb = - inf (size (x0)); | |
297 endif | |
298 endif | |
299 | |
291 if (isvector (lb)) | 300 if (isvector (lb)) |
292 globals.lb = tmp_lb = lb(:); | 301 lb = lb(:); |
293 lb_idx(:) = tmp_idx = (lb != -Inf); | 302 lb_idx(:) = (lb != -Inf); |
294 globals.lb = globals.lb(tmp_idx, 1); | 303 globals.lb = lb(lb_idx, 1); |
295 lb_grad = lb_grad(lb_idx, :); | 304 lb_grad = lb_grad(lb_idx, :); |
296 elseif (isempty (lb)) | |
297 if (isa (x0, "single")) | |
298 globals.lb = tmp_lb = -realmax ("single"); | |
299 else | |
300 globals.lb = tmp_lb = -realmax (); | |
301 endif | |
302 else | 305 else |
303 error ("sqp: invalid lower bound"); | 306 error ("sqp: invalid lower bound"); |
304 endif | 307 endif |
305 | 308 |
309 if (isempty (ub)) | |
310 if (isa (x0, "single")) | |
311 ub = inf (size (x0), "single"); | |
312 else | |
313 ub = inf (size (x0)); | |
314 endif | |
315 endif | |
316 | |
306 if (isvector (ub)) | 317 if (isvector (ub)) |
307 globals.ub = tmp_ub = ub(:); | 318 ub = ub(:); |
308 ub_idx(:) = tmp_idx = (ub != Inf); | 319 ub_idx(:) = (ub != Inf); |
309 globals.ub = globals.ub(tmp_idx, 1); | 320 globals.ub = ub(ub_idx, 1); |
310 ub_grad = ub_grad(ub_idx, :); | 321 ub_grad = ub_grad(ub_idx, :); |
311 elseif (isempty (ub)) | |
312 if (isa (x0, "single")) | |
313 globals.ub = tmp_ub = realmax ("single"); | |
314 else | |
315 globals.ub = tmp_ub = realmax (); | |
316 endif | |
317 else | 322 else |
318 error ("sqp: invalid upper bound"); | 323 error ("sqp: invalid upper bound"); |
319 endif | 324 endif |
320 | 325 |
321 if (any (tmp_lb > tmp_ub)) | 326 if (any (globals.lb > globals.ub)) |
322 error ("sqp: upper bound smaller than lower bound"); | 327 error ("sqp: upper bound smaller than lower bound"); |
323 endif | 328 endif |
324 bounds_grad = [lb_grad; ub_grad]; | 329 bounds_grad = [lb_grad; ub_grad]; |
325 ci_fcn = @(x) cf_ub_lb (x, lb_idx, ub_idx, globals); | 330 ci_fcn = @(x) cf_ub_lb (x, lb_idx, ub_idx, globals); |
326 ci_grd = @(x) cigrad_ub_lb (x, bounds_grad, globals); | 331 ci_grd = @(x) cigrad_ub_lb (x, bounds_grad, globals); |
703 | 708 |
704 endfunction | 709 endfunction |
705 | 710 |
706 | 711 |
707 function res = cf_ub_lb (x, lbidx, ubidx, globals) | 712 function res = cf_ub_lb (x, lbidx, ubidx, globals) |
708 | 713 ## function returning constraint evaluated at x, and distance between ub/lb |
709 ## combine constraint function with ub and lb | 714 ## and x, when they are specified (otherwise return empty) |
710 if (isempty (globals.cifcn)) | 715 |
711 res = [x(lbidx,1)-globals.lb; globals.ub-x(ubidx,1)]; | 716 ## inequality constraints |
712 else | 717 if (! isempty (globals.cifcn)) |
713 res = [feval(globals.cifcn,x); x(lbidx,1)-globals.lb; | 718 ci = feval (globals.cifcn, x); |
714 globals.ub-x(ubidx,1)]; | 719 else |
715 endif | 720 ci = []; |
721 endif | |
722 | |
723 ## lower bounds | |
724 if (! isempty (globals.lb)) | |
725 lb = x(lbidx, 1) - globals.lb; | |
726 else | |
727 lb = []; | |
728 endif | |
729 | |
730 ## upper bounds | |
731 if (! isempty (globals.ub)) | |
732 ub = globals.ub - x(ubidx, 1); | |
733 else | |
734 ub = []; | |
735 end | |
736 | |
737 res = [ci; lb; ub]; | |
716 | 738 |
717 endfunction | 739 endfunction |
718 | 740 |
719 | 741 |
720 function res = cigrad_ub_lb (x, bgrad, globals) | 742 function res = cigrad_ub_lb (x, bgrad, globals) |