1 /* Copyright (c) 2007-2014 Massachusetts Institute of Technology
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #include "nlopt-internal.h"
32 #define ERR(err, opt, msg) (nlopt_set_errmsg(opt, msg) ? err : err)
34 /*************************************************************************/
36 void NLOPT_STDCALL nlopt_destroy(nlopt_opt opt)
40 if (opt->munge_on_destroy) {
41 nlopt_munge munge = opt->munge_on_destroy;
43 for (i = 0; i < opt->m; ++i)
44 munge(opt->fc[i].f_data);
45 for (i = 0; i < opt->p; ++i)
46 munge(opt->h[i].f_data);
48 for (i = 0; i < opt->m; ++i)
50 for (i = 0; i < opt->p; ++i)
52 free(opt->lb); free(opt->ub);
56 nlopt_destroy(opt->local_opt);
64 nlopt_opt NLOPT_STDCALL nlopt_create(nlopt_algorithm algorithm, unsigned n)
68 if (((int) algorithm) < 0 || algorithm >= NLOPT_NUM_ALGORITHMS)
71 opt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s));
73 opt->algorithm = algorithm;
75 opt->f = NULL; opt->f_data = NULL; opt->pre = NULL;
77 opt->munge_on_destroy = opt->munge_on_copy = NULL;
79 opt->lb = opt->ub = NULL;
80 opt->m = opt->m_alloc = 0;
82 opt->p = opt->p_alloc = 0;
85 opt->stopval = -HUGE_VAL;
86 opt->ftol_rel = opt->ftol_abs = 0;
87 opt->xtol_rel = 0; opt->xtol_abs = NULL;
92 opt->force_stop_child = NULL;
94 opt->local_opt = NULL;
95 opt->stochastic_population = 0;
96 opt->vector_storage = 0;
102 opt->lb = (double *) calloc(n, sizeof(double));
103 if (!opt->lb) goto oom;
104 opt->ub = (double *) calloc(n, sizeof(double));
105 if (!opt->ub) goto oom;
106 opt->xtol_abs = (double *) calloc(n, sizeof(double));
107 if (!opt->xtol_abs) goto oom;
108 nlopt_set_lower_bounds1(opt, -HUGE_VAL);
109 nlopt_set_upper_bounds1(opt, +HUGE_VAL);
110 nlopt_set_xtol_abs1(opt, 0.0);
121 nlopt_opt NLOPT_STDCALL nlopt_copy(const nlopt_opt opt)
123 nlopt_opt nopt = NULL;
127 nopt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s));
129 nopt->lb = nopt->ub = nopt->xtol_abs = NULL;
130 nopt->fc = nopt->h = NULL;
131 nopt->m_alloc = nopt->p_alloc = 0;
132 nopt->local_opt = NULL;
136 nopt->force_stop_child = NULL;
138 munge = nopt->munge_on_copy;
139 if (munge && nopt->f_data)
140 if (!(nopt->f_data = munge(nopt->f_data))) goto oom;
143 nopt->lb = (double *) malloc(sizeof(double) * (opt->n));
144 if (!opt->lb) goto oom;
145 nopt->ub = (double *) malloc(sizeof(double) * (opt->n));
146 if (!opt->ub) goto oom;
147 nopt->xtol_abs = (double *) malloc(sizeof(double) * (opt->n));
148 if (!opt->xtol_abs) goto oom;
150 memcpy(nopt->lb, opt->lb, sizeof(double) * (opt->n));
151 memcpy(nopt->ub, opt->ub, sizeof(double) * (opt->n));
152 memcpy(nopt->xtol_abs, opt->xtol_abs, sizeof(double) * (opt->n));
156 nopt->m_alloc = opt->m;
157 nopt->fc = (nlopt_constraint *) malloc(sizeof(nlopt_constraint)
159 if (!nopt->fc) goto oom;
160 memcpy(nopt->fc, opt->fc, sizeof(nlopt_constraint) * (opt->m));
161 for (i = 0; i < opt->m; ++i) nopt->fc[i].tol = NULL;
163 for (i = 0; i < opt->m; ++i)
164 if (nopt->fc[i].f_data &&
166 = munge(nopt->fc[i].f_data)))
168 for (i = 0; i < opt->m; ++i)
169 if (opt->fc[i].tol) {
170 nopt->fc[i].tol = (double *) malloc(sizeof(double)
172 if (!nopt->fc[i].tol) goto oom;
173 memcpy(nopt->fc[i].tol, opt->fc[i].tol,
174 sizeof(double) * nopt->fc[i].m);
179 nopt->p_alloc = opt->p;
180 nopt->h = (nlopt_constraint *) malloc(sizeof(nlopt_constraint)
182 if (!nopt->h) goto oom;
183 memcpy(nopt->h, opt->h, sizeof(nlopt_constraint) * (opt->p));
184 for (i = 0; i < opt->p; ++i) nopt->h[i].tol = NULL;
186 for (i = 0; i < opt->p; ++i)
187 if (nopt->h[i].f_data &&
189 = munge(nopt->h[i].f_data)))
191 for (i = 0; i < opt->p; ++i)
193 nopt->h[i].tol = (double *) malloc(sizeof(double)
195 if (!nopt->h[i].tol) goto oom;
196 memcpy(nopt->h[i].tol, opt->h[i].tol,
197 sizeof(double) * nopt->h[i].m);
201 if (opt->local_opt) {
202 nopt->local_opt = nlopt_copy(opt->local_opt);
203 if (!nopt->local_opt) goto oom;
207 nopt->dx = (double *) malloc(sizeof(double) * (opt->n));
208 if (!nopt->dx) goto oom;
209 memcpy(nopt->dx, opt->dx, sizeof(double) * (opt->n));
215 nopt->munge_on_destroy = NULL; /* better to leak mem than crash */
220 /*************************************************************************/
222 nlopt_result NLOPT_STDCALL nlopt_set_precond_min_objective(nlopt_opt opt,
228 nlopt_unset_errmsg(opt);
229 if (opt->munge_on_destroy) opt->munge_on_destroy(opt->f_data);
230 opt->f = f; opt->f_data = f_data; opt->pre = pre;
232 if (nlopt_isinf(opt->stopval) && opt->stopval > 0)
233 opt->stopval = -HUGE_VAL; /* switch default from max to min */
234 return NLOPT_SUCCESS;
236 return NLOPT_INVALID_ARGS;
239 nlopt_result NLOPT_STDCALL nlopt_set_min_objective(nlopt_opt opt,
240 nlopt_func f, void *f_data)
242 return nlopt_set_precond_min_objective(opt, f, NULL, f_data);
245 nlopt_result NLOPT_STDCALL nlopt_set_precond_max_objective(nlopt_opt opt,
251 nlopt_unset_errmsg(opt);
252 if (opt->munge_on_destroy) opt->munge_on_destroy(opt->f_data);
253 opt->f = f; opt->f_data = f_data; opt->pre = pre;
255 if (nlopt_isinf(opt->stopval) && opt->stopval < 0)
256 opt->stopval = +HUGE_VAL; /* switch default from min to max */
257 return NLOPT_SUCCESS;
259 return NLOPT_INVALID_ARGS;
262 nlopt_result NLOPT_STDCALL nlopt_set_max_objective(nlopt_opt opt,
263 nlopt_func f, void *f_data)
265 return nlopt_set_precond_max_objective(opt, f, NULL, f_data);
268 /*************************************************************************/
271 NLOPT_STDCALL nlopt_set_lower_bounds(nlopt_opt opt, const double *lb)
273 nlopt_unset_errmsg(opt);
274 if (opt && (opt->n == 0 || lb)) {
277 memcpy(opt->lb, lb, sizeof(double) * (opt->n));
278 for (i = 0; i < opt->n; ++i)
279 if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
280 opt->lb[i] = opt->ub[i];
281 return NLOPT_SUCCESS;
283 return NLOPT_INVALID_ARGS;
287 NLOPT_STDCALL nlopt_set_lower_bounds1(nlopt_opt opt, double lb)
289 nlopt_unset_errmsg(opt);
292 for (i = 0; i < opt->n; ++i) {
294 if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
295 opt->lb[i] = opt->ub[i];
297 return NLOPT_SUCCESS;
299 return NLOPT_INVALID_ARGS;
303 NLOPT_STDCALL nlopt_get_lower_bounds(const nlopt_opt opt, double *lb)
305 nlopt_unset_errmsg(opt);
306 if (opt && (opt->n == 0 || lb)) {
307 memcpy(lb, opt->lb, sizeof(double) * (opt->n));
308 return NLOPT_SUCCESS;
310 return NLOPT_INVALID_ARGS;
314 NLOPT_STDCALL nlopt_set_upper_bounds(nlopt_opt opt, const double *ub)
316 nlopt_unset_errmsg(opt);
317 if (opt && (opt->n == 0 || ub)) {
320 memcpy(opt->ub, ub, sizeof(double) * (opt->n));
321 for (i = 0; i < opt->n; ++i)
322 if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
323 opt->ub[i] = opt->lb[i];
324 return NLOPT_SUCCESS;
326 return NLOPT_INVALID_ARGS;
330 NLOPT_STDCALL nlopt_set_upper_bounds1(nlopt_opt opt, double ub)
332 nlopt_unset_errmsg(opt);
335 for (i = 0; i < opt->n; ++i) {
337 if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
338 opt->ub[i] = opt->lb[i];
340 return NLOPT_SUCCESS;
342 return NLOPT_INVALID_ARGS;
346 NLOPT_STDCALL nlopt_get_upper_bounds(const nlopt_opt opt, double *ub)
348 nlopt_unset_errmsg(opt);
349 if (opt && (opt->n == 0 || ub)) {
350 memcpy(ub, opt->ub, sizeof(double) * (opt->n));
351 return NLOPT_SUCCESS;
353 return NLOPT_INVALID_ARGS;
356 /*************************************************************************/
358 #define AUGLAG_ALG(a) ((a) == NLOPT_AUGLAG || \
359 (a) == NLOPT_AUGLAG_EQ || \
360 (a) == NLOPT_LN_AUGLAG || \
361 (a) == NLOPT_LN_AUGLAG_EQ || \
362 (a) == NLOPT_LD_AUGLAG || \
363 (a) == NLOPT_LD_AUGLAG_EQ)
366 NLOPT_STDCALL nlopt_remove_inequality_constraints(nlopt_opt opt)
369 nlopt_unset_errmsg(opt);
370 if (!opt) return NLOPT_INVALID_ARGS;
371 if (opt->munge_on_destroy) {
372 nlopt_munge munge = opt->munge_on_destroy;
373 for (i = 0; i < opt->m; ++i)
374 munge(opt->fc[i].f_data);
376 for (i = 0; i < opt->m; ++i)
377 free(opt->fc[i].tol);
380 opt->m = opt->m_alloc = 0;
381 return NLOPT_SUCCESS;
384 static nlopt_result add_constraint(nlopt_opt opt,
385 unsigned *m, unsigned *m_alloc,
386 nlopt_constraint **c,
387 unsigned fm, nlopt_func fc, nlopt_mfunc mfc,
395 if ((fc && mfc) || (fc && fm != 1) || (!fc && !mfc))
396 return NLOPT_INVALID_ARGS;
398 for (i = 0; i < fm; ++i) if (tol[i] < 0)
399 return ERR(NLOPT_INVALID_ARGS, opt, "negative constraint tolerance");
401 tolcopy = (double *) malloc(sizeof(double) * fm);
402 if (fm && !tolcopy) return NLOPT_OUT_OF_MEMORY;
404 memcpy(tolcopy, tol, sizeof(double) * fm);
406 for (i = 0; i < fm; ++i) tolcopy[i] = 0;
410 /* allocate by repeated doubling so that
411 we end up with O(log m) mallocs rather than O(m). */
413 *c = (nlopt_constraint *) realloc(*c,
414 sizeof(nlopt_constraint)
419 return NLOPT_OUT_OF_MEMORY;
425 (*c)[*m - 1].pre = pre;
426 (*c)[*m - 1].mf = mfc;
427 (*c)[*m - 1].f_data = fc_data;
428 (*c)[*m - 1].tol = tolcopy;
429 return NLOPT_SUCCESS;
432 static int inequality_ok(nlopt_algorithm algorithm) {
433 /* nonlinear constraints are only supported with some algorithms */
434 return (algorithm == NLOPT_LD_MMA || algorithm == NLOPT_LD_CCSAQ
435 || algorithm == NLOPT_LD_SLSQP
436 || algorithm == NLOPT_LN_COBYLA
437 || AUGLAG_ALG(algorithm)
438 || algorithm == NLOPT_GN_ISRES
439 || algorithm == NLOPT_GN_ORIG_DIRECT
440 || algorithm == NLOPT_GN_ORIG_DIRECT_L);
444 NLOPT_STDCALL nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m,
445 nlopt_mfunc fc, void *fc_data,
449 nlopt_unset_errmsg(opt);
450 if (!m) { /* empty constraints are always ok */
451 if (opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data);
452 return NLOPT_SUCCESS;
454 if (!opt) ret = NLOPT_INVALID_ARGS;
455 else if (!inequality_ok(opt->algorithm))
456 ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
457 else ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc,
458 m, NULL, fc, NULL, fc_data, tol);
459 if (ret < 0 && opt && opt->munge_on_destroy)
460 opt->munge_on_destroy(fc_data);
465 NLOPT_STDCALL nlopt_add_precond_inequality_constraint(nlopt_opt opt,
472 nlopt_unset_errmsg(opt);
473 if (!opt) ret = NLOPT_INVALID_ARGS;
474 else if (!inequality_ok(opt->algorithm))
475 ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
476 else ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc,
477 1, fc, NULL, pre, fc_data, &tol);
478 if (ret < 0 && opt && opt->munge_on_destroy)
479 opt->munge_on_destroy(fc_data);
484 NLOPT_STDCALL nlopt_add_inequality_constraint(nlopt_opt opt,
485 nlopt_func fc, void *fc_data,
488 return nlopt_add_precond_inequality_constraint(opt, fc, NULL, fc_data,
493 NLOPT_STDCALL nlopt_remove_equality_constraints(nlopt_opt opt)
496 nlopt_unset_errmsg(opt);
497 if (!opt) return NLOPT_INVALID_ARGS;
498 if (opt->munge_on_destroy) {
499 nlopt_munge munge = opt->munge_on_destroy;
500 for (i = 0; i < opt->p; ++i)
501 munge(opt->h[i].f_data);
503 for (i = 0; i < opt->p; ++i)
507 opt->p = opt->p_alloc = 0;
508 return NLOPT_SUCCESS;
511 static int equality_ok(nlopt_algorithm algorithm) {
512 /* equality constraints (h(x) = 0) only via some algorithms */
513 return (AUGLAG_ALG(algorithm)
514 || algorithm == NLOPT_LD_SLSQP
515 || algorithm == NLOPT_GN_ISRES
516 || algorithm == NLOPT_LN_COBYLA);
520 NLOPT_STDCALL nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m,
521 nlopt_mfunc fc, void *fc_data,
525 nlopt_unset_errmsg(opt);
526 if (!m) { /* empty constraints are always ok */
527 if (opt && opt->munge_on_destroy) opt->munge_on_destroy(fc_data);
528 return NLOPT_SUCCESS;
530 if (!opt) ret = NLOPT_INVALID_ARGS;
531 else if (!equality_ok(opt->algorithm))
532 ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
533 else if (nlopt_count_constraints(opt->p, opt->h) + m > opt->n)
534 ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints");
535 else ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h,
536 m, NULL, fc, NULL, fc_data, tol);
537 if (ret < 0 && opt && opt->munge_on_destroy)
538 opt->munge_on_destroy(fc_data);
543 NLOPT_STDCALL nlopt_add_precond_equality_constraint(nlopt_opt opt,
550 nlopt_unset_errmsg(opt);
551 if (!opt) ret = NLOPT_INVALID_ARGS;
552 else if (!equality_ok(opt->algorithm))
553 ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
554 else if (nlopt_count_constraints(opt->p, opt->h) + 1 > opt->n)
555 ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints");
556 else ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h,
557 1, fc, NULL, pre, fc_data, &tol);
558 if (ret < 0 && opt && opt->munge_on_destroy)
559 opt->munge_on_destroy(fc_data);
564 NLOPT_STDCALL nlopt_add_equality_constraint(nlopt_opt opt,
565 nlopt_func fc, void *fc_data,
568 return nlopt_add_precond_equality_constraint(opt, fc, NULL, fc_data, tol);
571 /*************************************************************************/
573 #define SET(param, T, arg) \
574 nlopt_result NLOPT_STDCALL nlopt_set_##param(nlopt_opt opt, T arg) \
577 nlopt_unset_errmsg(opt); \
579 return NLOPT_SUCCESS; \
581 return NLOPT_INVALID_ARGS; \
585 #define GET(param, T, arg) T NLOPT_STDCALL \
586 nlopt_get_##param(const nlopt_opt opt) { \
590 #define GETSET(param, T, arg) GET(param, T, arg) SET(param, T, arg)
592 GETSET(stopval, double, stopval)
594 GETSET(ftol_rel, double, ftol_rel)
595 GETSET(ftol_abs, double, ftol_abs)
596 GETSET(xtol_rel, double, xtol_rel)
599 NLOPT_STDCALL nlopt_set_xtol_abs(nlopt_opt opt, const double *xtol_abs)
602 nlopt_unset_errmsg(opt);
603 memcpy(opt->xtol_abs, xtol_abs, opt->n * sizeof(double));
604 return NLOPT_SUCCESS;
606 return NLOPT_INVALID_ARGS;
610 NLOPT_STDCALL nlopt_set_xtol_abs1(nlopt_opt opt, double xtol_abs)
614 nlopt_unset_errmsg(opt);
615 for (i = 0; i < opt->n; ++i)
616 opt->xtol_abs[i] = xtol_abs;
617 return NLOPT_SUCCESS;
619 return NLOPT_INVALID_ARGS;
623 NLOPT_STDCALL nlopt_get_xtol_abs(const nlopt_opt opt, double *xtol_abs)
625 memcpy(xtol_abs, opt->xtol_abs, opt->n * sizeof(double));
626 return NLOPT_SUCCESS;
629 GETSET(maxeval, int, maxeval)
631 GETSET(numevals, int, numevals)
633 GETSET(maxtime, double, maxtime)
635 /*************************************************************************/
638 NLOPT_STDCALL nlopt_set_force_stop(nlopt_opt opt, int force_stop)
641 nlopt_unset_errmsg(opt);
642 opt->force_stop = force_stop;
643 if (opt->force_stop_child)
644 return nlopt_set_force_stop(opt->force_stop_child, force_stop);
645 return NLOPT_SUCCESS;
647 return NLOPT_INVALID_ARGS;
650 GET(force_stop, int, force_stop)
651 nlopt_result NLOPT_STDCALL nlopt_force_stop(nlopt_opt opt) {
652 return nlopt_set_force_stop(opt, 1);
655 /*************************************************************************/
657 GET(algorithm, nlopt_algorithm, algorithm)
658 GET(dimension, unsigned, n)
660 /*************************************************************************/
663 NLOPT_STDCALL nlopt_set_local_optimizer(nlopt_opt opt,
664 const nlopt_opt local_opt)
667 nlopt_unset_errmsg(opt);
668 if (local_opt && local_opt->n != opt->n)
669 return ERR(NLOPT_INVALID_ARGS, opt, "dimension mismatch in local optimizer");
670 nlopt_destroy(opt->local_opt);
671 opt->local_opt = nlopt_copy(local_opt);
673 if (!opt->local_opt) return NLOPT_OUT_OF_MEMORY;
674 nlopt_set_lower_bounds(opt->local_opt, opt->lb);
675 nlopt_set_upper_bounds(opt->local_opt, opt->ub);
676 nlopt_remove_inequality_constraints(opt->local_opt);
677 nlopt_remove_equality_constraints(opt->local_opt);
678 nlopt_set_min_objective(opt->local_opt, NULL, NULL);
679 nlopt_set_munge(opt->local_opt, NULL, NULL);
680 opt->local_opt->force_stop = 0;
682 return NLOPT_SUCCESS;
684 return NLOPT_INVALID_ARGS;
687 /*************************************************************************/
689 GETSET(population, unsigned, stochastic_population)
690 GETSET(vector_storage, unsigned, vector_storage)
692 /*************************************************************************/
694 nlopt_result NLOPT_STDCALL nlopt_set_initial_step1(nlopt_opt opt, double dx)
697 if (!opt) return NLOPT_INVALID_ARGS;
698 nlopt_unset_errmsg(opt);
699 if (dx == 0) return ERR(NLOPT_INVALID_ARGS, opt, "zero step size");
700 if (!opt->dx && opt->n > 0) {
701 opt->dx = (double *) malloc(sizeof(double) * (opt->n));
702 if (!opt->dx) return NLOPT_OUT_OF_MEMORY;
704 for (i = 0; i < opt->n; ++i) opt->dx[i] = dx;
705 return NLOPT_SUCCESS;
709 NLOPT_STDCALL nlopt_set_initial_step(nlopt_opt opt, const double *dx)
712 if (!opt) return NLOPT_INVALID_ARGS;
713 nlopt_unset_errmsg(opt);
715 free(opt->dx); opt->dx = NULL;
716 return NLOPT_SUCCESS;
718 for (i = 0; i < opt->n; ++i)
719 if (dx[i] == 0) return ERR(NLOPT_INVALID_ARGS, opt, "zero step size");
720 if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY)
721 return NLOPT_OUT_OF_MEMORY;
722 memcpy(opt->dx, dx, sizeof(double) * (opt->n));
723 return NLOPT_SUCCESS;
727 NLOPT_STDCALL nlopt_get_initial_step(const nlopt_opt opt, const double *x,
730 if (!opt) return NLOPT_INVALID_ARGS;
731 nlopt_unset_errmsg(opt);
732 if (!opt->n) return NLOPT_SUCCESS;
734 nlopt_opt o = (nlopt_opt) opt; /* discard const temporarily */
735 nlopt_result ret = nlopt_set_default_initial_step(o, x);
736 if (ret != NLOPT_SUCCESS) return ret;
737 memcpy(dx, o->dx, sizeof(double) * (opt->n));
738 free(o->dx); o->dx = NULL; /* don't save, since x-dependent */
741 memcpy(dx, opt->dx, sizeof(double) * (opt->n));
742 return NLOPT_SUCCESS;
746 NLOPT_STDCALL nlopt_set_default_initial_step(nlopt_opt opt, const double *x)
748 const double *lb, *ub;
751 nlopt_unset_errmsg(opt);
752 if (!opt || !x) return NLOPT_INVALID_ARGS;
753 lb = opt->lb; ub = opt->ub;
755 if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY)
756 return NLOPT_OUT_OF_MEMORY;
758 /* crude heuristics for initial step size of nonderivative algorithms */
759 for (i = 0; i < opt->n; ++i) {
760 double step = HUGE_VAL;
762 if (!nlopt_isinf(ub[i]) && !nlopt_isinf(lb[i])
763 && (ub[i] - lb[i]) * 0.25 < step && ub[i] > lb[i])
764 step = (ub[i] - lb[i]) * 0.25;
765 if (!nlopt_isinf(ub[i])
766 && ub[i] - x[i] < step && ub[i] > x[i])
767 step = (ub[i] - x[i]) * 0.75;
768 if (!nlopt_isinf(lb[i])
769 && x[i] - lb[i] < step && x[i] > lb[i])
770 step = (x[i] - lb[i]) * 0.75;
772 if (nlopt_isinf(step)) {
773 if (!nlopt_isinf(ub[i])
774 && fabs(ub[i] - x[i]) < fabs(step))
775 step = (ub[i] - x[i]) * 1.1;
776 if (!nlopt_isinf(lb[i])
777 && fabs(x[i] - lb[i]) < fabs(step))
778 step = (x[i] - lb[i]) * 1.1;
780 if (nlopt_isinf(step) || nlopt_istiny(step)) {
783 if (nlopt_isinf(step) || step == 0.0)
788 return NLOPT_SUCCESS;
791 /*************************************************************************/
793 void NLOPT_STDCALL nlopt_set_munge(nlopt_opt opt,
794 nlopt_munge munge_on_destroy,
795 nlopt_munge munge_on_copy) {
797 opt->munge_on_destroy = munge_on_destroy;
798 opt->munge_on_copy = munge_on_copy;
802 void NLOPT_STDCALL nlopt_munge_data(nlopt_opt opt,
803 nlopt_munge2 munge, void *data) {
806 opt->f_data = munge(opt->f_data, data);
807 for (i = 0; i < opt->m; ++i)
808 opt->fc[i].f_data = munge(opt->fc[i].f_data, data);
809 for (i = 0; i < opt->p; ++i)
810 opt->h[i].f_data = munge(opt->h[i].f_data, data);
814 /*************************************************************************/
816 const char *nlopt_set_errmsg(nlopt_opt opt, const char *format, ...)
819 va_start(ap, format);
820 opt->errmsg = nlopt_vsprintf(opt->errmsg, format, ap);
825 void nlopt_unset_errmsg(nlopt_opt opt)
833 const char *nlopt_get_errmsg(nlopt_opt opt)
838 /*************************************************************************/