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)
57 nlopt_destroy(opt->local_opt);
65 nlopt_opt NLOPT_STDCALL nlopt_create(nlopt_algorithm algorithm, unsigned n)
69 if (((int) algorithm) < 0 || algorithm >= NLOPT_NUM_ALGORITHMS)
72 opt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s));
74 opt->algorithm = algorithm;
80 opt->munge_on_destroy = opt->munge_on_copy = NULL;
82 opt->lb = opt->ub = NULL;
83 opt->m = opt->m_alloc = 0;
85 opt->p = opt->p_alloc = 0;
88 opt->stopval = -HUGE_VAL;
89 opt->ftol_rel = opt->ftol_abs = 0;
96 opt->force_stop_child = NULL;
98 opt->local_opt = NULL;
99 opt->stochastic_population = 0;
100 opt->vector_storage = 0;
106 opt->lb = (double *) calloc(n, sizeof(double));
109 opt->ub = (double *) calloc(n, sizeof(double));
112 opt->xtol_abs = (double *) calloc(n, sizeof(double));
115 nlopt_set_lower_bounds1(opt, -HUGE_VAL);
116 nlopt_set_upper_bounds1(opt, +HUGE_VAL);
117 nlopt_set_xtol_abs1(opt, 0.0);
128 nlopt_opt NLOPT_STDCALL nlopt_copy(const nlopt_opt opt)
130 nlopt_opt nopt = NULL;
134 nopt = (nlopt_opt) malloc(sizeof(struct nlopt_opt_s));
136 nopt->lb = nopt->ub = nopt->xtol_abs = NULL;
137 nopt->fc = nopt->h = NULL;
138 nopt->m_alloc = nopt->p_alloc = 0;
139 nopt->local_opt = NULL;
143 nopt->force_stop_child = NULL;
145 munge = nopt->munge_on_copy;
146 if (munge && nopt->f_data)
147 if (!(nopt->f_data = munge(nopt->f_data)))
151 nopt->lb = (double *) malloc(sizeof(double) * (opt->n));
154 nopt->ub = (double *) malloc(sizeof(double) * (opt->n));
157 nopt->xtol_abs = (double *) malloc(sizeof(double) * (opt->n));
161 memcpy(nopt->lb, opt->lb, sizeof(double) * (opt->n));
162 memcpy(nopt->ub, opt->ub, sizeof(double) * (opt->n));
163 memcpy(nopt->xtol_abs, opt->xtol_abs, sizeof(double) * (opt->n));
167 nopt->m_alloc = opt->m;
168 nopt->fc = (nlopt_constraint *) malloc(sizeof(nlopt_constraint)
172 memcpy(nopt->fc, opt->fc, sizeof(nlopt_constraint) * (opt->m));
173 for (i = 0; i < opt->m; ++i)
174 nopt->fc[i].tol = NULL;
176 for (i = 0; i < opt->m; ++i)
177 if (nopt->fc[i].f_data && !(nopt->fc[i].f_data = munge(nopt->fc[i].f_data)))
179 for (i = 0; i < opt->m; ++i)
180 if (opt->fc[i].tol) {
181 nopt->fc[i].tol = (double *) malloc(sizeof(double)
183 if (!nopt->fc[i].tol)
185 memcpy(nopt->fc[i].tol, opt->fc[i].tol, sizeof(double) * nopt->fc[i].m);
190 nopt->p_alloc = opt->p;
191 nopt->h = (nlopt_constraint *) malloc(sizeof(nlopt_constraint)
195 memcpy(nopt->h, opt->h, sizeof(nlopt_constraint) * (opt->p));
196 for (i = 0; i < opt->p; ++i)
197 nopt->h[i].tol = NULL;
199 for (i = 0; i < opt->p; ++i)
200 if (nopt->h[i].f_data && !(nopt->h[i].f_data = munge(nopt->h[i].f_data)))
202 for (i = 0; i < opt->p; ++i)
204 nopt->h[i].tol = (double *) malloc(sizeof(double)
208 memcpy(nopt->h[i].tol, opt->h[i].tol, sizeof(double) * nopt->h[i].m);
212 if (opt->local_opt) {
213 nopt->local_opt = nlopt_copy(opt->local_opt);
214 if (!nopt->local_opt)
219 nopt->dx = (double *) malloc(sizeof(double) * (opt->n));
222 memcpy(nopt->dx, opt->dx, sizeof(double) * (opt->n));
228 nopt->munge_on_destroy = NULL; /* better to leak mem than crash */
233 /*************************************************************************/
235 nlopt_result NLOPT_STDCALL nlopt_set_precond_min_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data)
238 nlopt_unset_errmsg(opt);
239 if (opt->munge_on_destroy)
240 opt->munge_on_destroy(opt->f_data);
242 opt->f_data = f_data;
245 if (nlopt_isinf(opt->stopval) && opt->stopval > 0)
246 opt->stopval = -HUGE_VAL; /* switch default from max to min */
247 return NLOPT_SUCCESS;
249 return NLOPT_INVALID_ARGS;
252 nlopt_result NLOPT_STDCALL nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data)
254 return nlopt_set_precond_min_objective(opt, f, NULL, f_data);
257 nlopt_result NLOPT_STDCALL nlopt_set_precond_max_objective(nlopt_opt opt, nlopt_func f, nlopt_precond pre, void *f_data)
260 nlopt_unset_errmsg(opt);
261 if (opt->munge_on_destroy)
262 opt->munge_on_destroy(opt->f_data);
264 opt->f_data = f_data;
267 if (nlopt_isinf(opt->stopval) && opt->stopval < 0)
268 opt->stopval = +HUGE_VAL; /* switch default from min to max */
269 return NLOPT_SUCCESS;
271 return NLOPT_INVALID_ARGS;
274 nlopt_result NLOPT_STDCALL nlopt_set_max_objective(nlopt_opt opt, nlopt_func f, void *f_data)
276 return nlopt_set_precond_max_objective(opt, f, NULL, f_data);
279 /*************************************************************************/
281 nlopt_result NLOPT_STDCALL nlopt_set_lower_bounds(nlopt_opt opt, const double *lb)
283 nlopt_unset_errmsg(opt);
284 if (opt && (opt->n == 0 || lb)) {
287 memcpy(opt->lb, lb, sizeof(double) * (opt->n));
288 for (i = 0; i < opt->n; ++i)
289 if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
290 opt->lb[i] = opt->ub[i];
291 return NLOPT_SUCCESS;
293 return NLOPT_INVALID_ARGS;
296 nlopt_result NLOPT_STDCALL nlopt_set_lower_bounds1(nlopt_opt opt, double lb)
298 nlopt_unset_errmsg(opt);
301 for (i = 0; i < opt->n; ++i) {
303 if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
304 opt->lb[i] = opt->ub[i];
306 return NLOPT_SUCCESS;
308 return NLOPT_INVALID_ARGS;
311 nlopt_result NLOPT_STDCALL nlopt_get_lower_bounds(const nlopt_opt opt, double *lb)
313 nlopt_unset_errmsg(opt);
314 if (opt && (opt->n == 0 || lb)) {
315 memcpy(lb, opt->lb, sizeof(double) * (opt->n));
316 return NLOPT_SUCCESS;
318 return NLOPT_INVALID_ARGS;
321 nlopt_result NLOPT_STDCALL nlopt_set_upper_bounds(nlopt_opt opt, const double *ub)
323 nlopt_unset_errmsg(opt);
324 if (opt && (opt->n == 0 || ub)) {
327 memcpy(opt->ub, ub, sizeof(double) * (opt->n));
328 for (i = 0; i < opt->n; ++i)
329 if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
330 opt->ub[i] = opt->lb[i];
331 return NLOPT_SUCCESS;
333 return NLOPT_INVALID_ARGS;
336 nlopt_result NLOPT_STDCALL nlopt_set_upper_bounds1(nlopt_opt opt, double ub)
338 nlopt_unset_errmsg(opt);
341 for (i = 0; i < opt->n; ++i) {
343 if (opt->lb[i] < opt->ub[i] && nlopt_istiny(opt->ub[i] - opt->lb[i]))
344 opt->ub[i] = opt->lb[i];
346 return NLOPT_SUCCESS;
348 return NLOPT_INVALID_ARGS;
351 nlopt_result NLOPT_STDCALL nlopt_get_upper_bounds(const nlopt_opt opt, double *ub)
353 nlopt_unset_errmsg(opt);
354 if (opt && (opt->n == 0 || ub)) {
355 memcpy(ub, opt->ub, sizeof(double) * (opt->n));
356 return NLOPT_SUCCESS;
358 return NLOPT_INVALID_ARGS;
361 /*************************************************************************/
363 #define AUGLAG_ALG(a) ((a) == NLOPT_AUGLAG || \
364 (a) == NLOPT_AUGLAG_EQ || \
365 (a) == NLOPT_LN_AUGLAG || \
366 (a) == NLOPT_LN_AUGLAG_EQ || \
367 (a) == NLOPT_LD_AUGLAG || \
368 (a) == NLOPT_LD_AUGLAG_EQ)
370 nlopt_result NLOPT_STDCALL nlopt_remove_inequality_constraints(nlopt_opt opt)
373 nlopt_unset_errmsg(opt);
375 return NLOPT_INVALID_ARGS;
376 if (opt->munge_on_destroy) {
377 nlopt_munge munge = opt->munge_on_destroy;
378 for (i = 0; i < opt->m; ++i)
379 munge(opt->fc[i].f_data);
381 for (i = 0; i < opt->m; ++i)
382 free(opt->fc[i].tol);
385 opt->m = opt->m_alloc = 0;
386 return NLOPT_SUCCESS;
389 static nlopt_result add_constraint(nlopt_opt opt,
390 unsigned *m, unsigned *m_alloc, nlopt_constraint ** c, unsigned fm, nlopt_func fc, nlopt_mfunc mfc, nlopt_precond pre, void *fc_data, const double *tol)
395 if ((fc && mfc) || (fc && fm != 1) || (!fc && !mfc))
396 return NLOPT_INVALID_ARGS;
398 for (i = 0; i < fm; ++i)
400 return ERR(NLOPT_INVALID_ARGS, opt, "negative constraint tolerance");
402 tolcopy = (double *) malloc(sizeof(double) * fm);
404 return NLOPT_OUT_OF_MEMORY;
406 memcpy(tolcopy, tol, sizeof(double) * fm);
408 for (i = 0; i < fm; ++i)
413 /* allocate by repeated doubling so that
414 we end up with O(log m) mallocs rather than O(m). */
416 *c = (nlopt_constraint *) realloc(*c, sizeof(nlopt_constraint)
421 return NLOPT_OUT_OF_MEMORY;
427 (*c)[*m - 1].pre = pre;
428 (*c)[*m - 1].mf = mfc;
429 (*c)[*m - 1].f_data = fc_data;
430 (*c)[*m - 1].tol = tolcopy;
431 return NLOPT_SUCCESS;
434 static int inequality_ok(nlopt_algorithm algorithm)
436 /* nonlinear constraints are only supported with some algorithms */
437 return (algorithm == NLOPT_LD_MMA || algorithm == NLOPT_LD_CCSAQ || algorithm == NLOPT_LD_SLSQP || algorithm == NLOPT_LN_COBYLA || AUGLAG_ALG(algorithm)
438 || algorithm == NLOPT_GN_ISRES || algorithm == NLOPT_GN_ORIG_DIRECT || algorithm == NLOPT_GN_ORIG_DIRECT_L || algorithm == NLOPT_GN_AGS);
441 nlopt_result NLOPT_STDCALL nlopt_add_inequality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc fc, void *fc_data, const double *tol)
444 nlopt_unset_errmsg(opt);
445 if (!m) { /* empty constraints are always ok */
446 if (opt && opt->munge_on_destroy)
447 opt->munge_on_destroy(fc_data);
448 return NLOPT_SUCCESS;
451 ret = NLOPT_INVALID_ARGS;
452 else if (!inequality_ok(opt->algorithm))
453 ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
455 ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc, m, NULL, fc, NULL, fc_data, tol);
456 if (ret < 0 && opt && opt->munge_on_destroy)
457 opt->munge_on_destroy(fc_data);
461 nlopt_result NLOPT_STDCALL nlopt_add_precond_inequality_constraint(nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, double tol)
464 nlopt_unset_errmsg(opt);
466 ret = NLOPT_INVALID_ARGS;
467 else if (!inequality_ok(opt->algorithm))
468 ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
470 ret = add_constraint(opt, &opt->m, &opt->m_alloc, &opt->fc, 1, fc, NULL, pre, fc_data, &tol);
471 if (ret < 0 && opt && opt->munge_on_destroy)
472 opt->munge_on_destroy(fc_data);
476 nlopt_result NLOPT_STDCALL nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol)
478 return nlopt_add_precond_inequality_constraint(opt, fc, NULL, fc_data, tol);
481 nlopt_result NLOPT_STDCALL nlopt_remove_equality_constraints(nlopt_opt opt)
484 nlopt_unset_errmsg(opt);
486 return NLOPT_INVALID_ARGS;
487 if (opt->munge_on_destroy) {
488 nlopt_munge munge = opt->munge_on_destroy;
489 for (i = 0; i < opt->p; ++i)
490 munge(opt->h[i].f_data);
492 for (i = 0; i < opt->p; ++i)
496 opt->p = opt->p_alloc = 0;
497 return NLOPT_SUCCESS;
500 static int equality_ok(nlopt_algorithm algorithm)
502 /* equality constraints (h(x) = 0) only via some algorithms */
503 return (AUGLAG_ALG(algorithm)
504 || algorithm == NLOPT_LD_SLSQP || algorithm == NLOPT_GN_ISRES || algorithm == NLOPT_LN_COBYLA);
507 nlopt_result NLOPT_STDCALL nlopt_add_equality_mconstraint(nlopt_opt opt, unsigned m, nlopt_mfunc fc, void *fc_data, const double *tol)
510 nlopt_unset_errmsg(opt);
511 if (!m) { /* empty constraints are always ok */
512 if (opt && opt->munge_on_destroy)
513 opt->munge_on_destroy(fc_data);
514 return NLOPT_SUCCESS;
517 ret = NLOPT_INVALID_ARGS;
518 else if (!equality_ok(opt->algorithm))
519 ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
520 else if (nlopt_count_constraints(opt->p, opt->h) + m > opt->n)
521 ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints");
523 ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h, m, NULL, fc, NULL, fc_data, tol);
524 if (ret < 0 && opt && opt->munge_on_destroy)
525 opt->munge_on_destroy(fc_data);
529 nlopt_result NLOPT_STDCALL nlopt_add_precond_equality_constraint(nlopt_opt opt, nlopt_func fc, nlopt_precond pre, void *fc_data, double tol)
532 nlopt_unset_errmsg(opt);
534 ret = NLOPT_INVALID_ARGS;
535 else if (!equality_ok(opt->algorithm))
536 ret = ERR(NLOPT_INVALID_ARGS, opt, "invalid algorithm for constraints");
537 else if (nlopt_count_constraints(opt->p, opt->h) + 1 > opt->n)
538 ret = ERR(NLOPT_INVALID_ARGS, opt, "too many equality constraints");
540 ret = add_constraint(opt, &opt->p, &opt->p_alloc, &opt->h, 1, fc, NULL, pre, fc_data, &tol);
541 if (ret < 0 && opt && opt->munge_on_destroy)
542 opt->munge_on_destroy(fc_data);
546 nlopt_result NLOPT_STDCALL nlopt_add_equality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol)
548 return nlopt_add_precond_equality_constraint(opt, fc, NULL, fc_data, tol);
551 /*************************************************************************/
553 #define SET(param, T, arg) \
554 nlopt_result NLOPT_STDCALL nlopt_set_##param(nlopt_opt opt, T arg) \
557 nlopt_unset_errmsg(opt); \
559 return NLOPT_SUCCESS; \
561 return NLOPT_INVALID_ARGS; \
565 #define GET(param, T, arg) T NLOPT_STDCALL \
566 nlopt_get_##param(const nlopt_opt opt) { \
570 #define GETSET(param, T, arg) GET(param, T, arg) SET(param, T, arg)
572 GETSET(stopval, double, stopval)
574 GETSET(ftol_rel, double, ftol_rel) GETSET(ftol_abs, double, ftol_abs) GETSET(xtol_rel, double, xtol_rel)
575 nlopt_result NLOPT_STDCALL nlopt_set_xtol_abs(nlopt_opt opt, const double *xtol_abs)
578 nlopt_unset_errmsg(opt);
579 memcpy(opt->xtol_abs, xtol_abs, opt->n * sizeof(double));
580 return NLOPT_SUCCESS;
582 return NLOPT_INVALID_ARGS;
585 nlopt_result NLOPT_STDCALL nlopt_set_xtol_abs1(nlopt_opt opt, double xtol_abs)
589 nlopt_unset_errmsg(opt);
590 for (i = 0; i < opt->n; ++i)
591 opt->xtol_abs[i] = xtol_abs;
592 return NLOPT_SUCCESS;
594 return NLOPT_INVALID_ARGS;
597 nlopt_result NLOPT_STDCALL nlopt_get_xtol_abs(const nlopt_opt opt, double *xtol_abs)
599 memcpy(xtol_abs, opt->xtol_abs, opt->n * sizeof(double));
600 return NLOPT_SUCCESS;
603 GETSET(maxeval, int, maxeval)
605 GET(numevals, int, numevals)
606 GETSET(maxtime, double, maxtime)
608 /*************************************************************************/
609 nlopt_result NLOPT_STDCALL nlopt_set_force_stop(nlopt_opt opt, int force_stop)
612 nlopt_unset_errmsg(opt);
613 opt->force_stop = force_stop;
614 if (opt->force_stop_child)
615 return nlopt_set_force_stop(opt->force_stop_child, force_stop);
616 return NLOPT_SUCCESS;
618 return NLOPT_INVALID_ARGS;
621 GET(force_stop, int, force_stop)
622 nlopt_result NLOPT_STDCALL nlopt_force_stop(nlopt_opt opt)
624 return nlopt_set_force_stop(opt, 1);
627 /*************************************************************************/
629 GET(algorithm, nlopt_algorithm, algorithm)
630 GET(dimension, unsigned, n)
632 /*************************************************************************/
633 nlopt_result NLOPT_STDCALL nlopt_set_local_optimizer(nlopt_opt opt, const nlopt_opt local_opt)
636 nlopt_unset_errmsg(opt);
637 if (local_opt && local_opt->n != opt->n)
638 return ERR(NLOPT_INVALID_ARGS, opt, "dimension mismatch in local optimizer");
639 nlopt_destroy(opt->local_opt);
640 opt->local_opt = nlopt_copy(local_opt);
643 return NLOPT_OUT_OF_MEMORY;
644 nlopt_set_lower_bounds(opt->local_opt, opt->lb);
645 nlopt_set_upper_bounds(opt->local_opt, opt->ub);
646 nlopt_remove_inequality_constraints(opt->local_opt);
647 nlopt_remove_equality_constraints(opt->local_opt);
648 nlopt_set_min_objective(opt->local_opt, NULL, NULL);
649 nlopt_set_munge(opt->local_opt, NULL, NULL);
650 opt->local_opt->force_stop = 0;
652 return NLOPT_SUCCESS;
654 return NLOPT_INVALID_ARGS;
657 /*************************************************************************/
659 GETSET(population, unsigned, stochastic_population)
660 GETSET(vector_storage, unsigned, vector_storage)
662 /*************************************************************************/
663 nlopt_result NLOPT_STDCALL nlopt_set_initial_step1(nlopt_opt opt, double dx)
667 return NLOPT_INVALID_ARGS;
668 nlopt_unset_errmsg(opt);
670 return ERR(NLOPT_INVALID_ARGS, opt, "zero step size");
671 if (!opt->dx && opt->n > 0) {
672 opt->dx = (double *) malloc(sizeof(double) * (opt->n));
674 return NLOPT_OUT_OF_MEMORY;
676 for (i = 0; i < opt->n; ++i)
678 return NLOPT_SUCCESS;
681 nlopt_result NLOPT_STDCALL nlopt_set_initial_step(nlopt_opt opt, const double *dx)
685 return NLOPT_INVALID_ARGS;
686 nlopt_unset_errmsg(opt);
690 return NLOPT_SUCCESS;
692 for (i = 0; i < opt->n; ++i)
694 return ERR(NLOPT_INVALID_ARGS, opt, "zero step size");
695 if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY)
696 return NLOPT_OUT_OF_MEMORY;
697 memcpy(opt->dx, dx, sizeof(double) * (opt->n));
698 return NLOPT_SUCCESS;
701 nlopt_result NLOPT_STDCALL nlopt_get_initial_step(const nlopt_opt opt, const double *x, double *dx)
704 return NLOPT_INVALID_ARGS;
705 nlopt_unset_errmsg(opt);
707 return NLOPT_SUCCESS;
709 nlopt_opt o = (nlopt_opt) opt; /* discard const temporarily */
710 nlopt_result ret = nlopt_set_default_initial_step(o, x);
711 if (ret != NLOPT_SUCCESS)
713 memcpy(dx, o->dx, sizeof(double) * (opt->n));
715 o->dx = NULL; /* don't save, since x-dependent */
717 memcpy(dx, opt->dx, sizeof(double) * (opt->n));
718 return NLOPT_SUCCESS;
721 nlopt_result NLOPT_STDCALL nlopt_set_default_initial_step(nlopt_opt opt, const double *x)
723 const double *lb, *ub;
726 nlopt_unset_errmsg(opt);
728 return NLOPT_INVALID_ARGS;
732 if (!opt->dx && nlopt_set_initial_step1(opt, 1) == NLOPT_OUT_OF_MEMORY)
733 return NLOPT_OUT_OF_MEMORY;
735 /* crude heuristics for initial step size of nonderivative algorithms */
736 for (i = 0; i < opt->n; ++i) {
737 double step = HUGE_VAL;
739 if (!nlopt_isinf(ub[i]) && !nlopt_isinf(lb[i])
740 && (ub[i] - lb[i]) * 0.25 < step && ub[i] > lb[i])
741 step = (ub[i] - lb[i]) * 0.25;
742 if (!nlopt_isinf(ub[i])
743 && ub[i] - x[i] < step && ub[i] > x[i])
744 step = (ub[i] - x[i]) * 0.75;
745 if (!nlopt_isinf(lb[i])
746 && x[i] - lb[i] < step && x[i] > lb[i])
747 step = (x[i] - lb[i]) * 0.75;
749 if (nlopt_isinf(step)) {
750 if (!nlopt_isinf(ub[i])
751 && fabs(ub[i] - x[i]) < fabs(step))
752 step = (ub[i] - x[i]) * 1.1;
753 if (!nlopt_isinf(lb[i])
754 && fabs(x[i] - lb[i]) < fabs(step))
755 step = (x[i] - lb[i]) * 1.1;
757 if (nlopt_isinf(step) || nlopt_istiny(step)) {
760 if (nlopt_isinf(step) || step == 0.0)
765 return NLOPT_SUCCESS;
768 /*************************************************************************/
770 void NLOPT_STDCALL nlopt_set_munge(nlopt_opt opt, nlopt_munge munge_on_destroy, nlopt_munge munge_on_copy)
773 opt->munge_on_destroy = munge_on_destroy;
774 opt->munge_on_copy = munge_on_copy;
778 void NLOPT_STDCALL nlopt_munge_data(nlopt_opt opt, nlopt_munge2 munge, void *data)
782 opt->f_data = munge(opt->f_data, data);
783 for (i = 0; i < opt->m; ++i)
784 opt->fc[i].f_data = munge(opt->fc[i].f_data, data);
785 for (i = 0; i < opt->p; ++i)
786 opt->h[i].f_data = munge(opt->h[i].f_data, data);
790 /*************************************************************************/
792 const char *nlopt_set_errmsg(nlopt_opt opt, const char *format, ...)
795 va_start(ap, format);
796 opt->errmsg = nlopt_vsprintf(opt->errmsg, format, ap);
801 void nlopt_unset_errmsg(nlopt_opt opt)
809 const char *nlopt_get_errmsg(nlopt_opt opt)
814 /*************************************************************************/