5 #include "nlopt-util.h"
8 #define MIN(a,b) ((a) < (b) ? (a) : (b))
10 /*************************************************************************/
13 # define MY_INF INFINITY
15 # define MY_INF HUGE_VAL
18 static int my_isinf(double x) {
19 return fabs(x) >= HUGE_VAL * 0.99
27 static int my_isnan(double x) { return x != x; }
28 # define isnan my_isnan
31 /*************************************************************************/
33 void nlopt_version(int *major, int *minor, int *bugfix)
35 *major = MAJOR_VERSION;
36 *minor = MINOR_VERSION;
37 *bugfix = BUGFIX_VERSION;
40 /*************************************************************************/
42 static const char nlopt_algorithm_names[NLOPT_NUM_ALGORITHMS][128] = {
47 "Low-storage BFGS (LBFGS) (local)"
50 const char *nlopt_algorithm_name(nlopt_algorithm a)
52 if (a < 0 || a >= NLOPT_NUM_ALGORITHMS) return "UNKNOWN";
53 return nlopt_algorithm_names[a];
56 /*************************************************************************/
58 static int nlopt_srand_called = 0;
59 void nlopt_srand(unsigned long seed) {
60 nlopt_srand_called = 1;
61 nlopt_init_genrand(seed);
64 void nlopt_srand_time() {
65 nlopt_srand(nlopt_time_seed());
68 /*************************************************************************/
73 const double *lb, *ub;
78 static double f_subplex(int n, const double *x, void *data_)
81 nlopt_data *data = (nlopt_data *) data_;
84 /* subplex does not support bound constraints, but it supports
85 discontinuous objectives so we can just return Inf for invalid x */
86 for (i = 0; i < n; ++i)
87 if (x[i] < data->lb[i] || x[i] > data->ub[i])
90 f = data->f(n, x, NULL, data->f_data);
91 return (isnan(f) ? MY_INF : f);
96 static double f_direct(int n, const double *x, int *undefined, void *data_)
98 nlopt_data *data = (nlopt_data *) data_;
99 double f = data->f(n, x, NULL, data->f_data);
100 *undefined = isnan(f) || my_isinf(f);
105 #include "l-bfgs-b.h"
107 /*************************************************************************/
109 /* same as nlopt_minimize, but xtol_abs is required to be non-NULL */
110 static nlopt_result nlopt_minimize_(
111 nlopt_algorithm algorithm,
112 int n, nlopt_func f, void *f_data,
113 const double *lb, const double *ub, /* bounds */
114 double *x, /* in: initial guess, out: minimizer */
115 double *fmin, /* out: minimum */
116 double fmin_max, double ftol_rel, double ftol_abs,
117 double xtol_rel, const double *xtol_abs,
118 int maxeval, double maxtime)
129 /* make sure rand generator is inited */
130 if (!nlopt_srand_called)
131 nlopt_srand_time(); /* default is non-deterministic */
133 /* check bound constraints */
134 for (i = 0; i < n; ++i)
135 if (lb[i] > ub[i] || x[i] < lb[i] || x[i] > ub[i])
136 return NLOPT_INVALID_ARGS;
139 stop.fmin_max = (isnan(fmin_max) || (my_isinf(fmin_max) && fmin_max < 0))
140 ? -MY_INF : fmin_max;
141 stop.ftol_rel = ftol_rel;
142 stop.ftol_abs = ftol_abs;
143 stop.xtol_rel = xtol_rel;
144 stop.xtol_abs = xtol_abs;
146 stop.maxeval = maxeval;
147 stop.maxtime = maxtime;
148 stop.start = nlopt_seconds();
151 case NLOPT_GLOBAL_DIRECT:
152 case NLOPT_GLOBAL_DIRECT_L:
153 switch (direct_optimize(f_direct, &d, n, lb, ub, x, fmin,
154 maxeval, 500, ftol_rel, ftol_abs,
156 DIRECT_UNKNOWN_FGLOBAL, -1.0,
158 algorithm == NLOPT_GLOBAL_DIRECT
160 : DIRECT_GABLONSKY)) {
161 case DIRECT_INVALID_BOUNDS:
162 case DIRECT_MAXFEVAL_TOOBIG:
163 case DIRECT_INVALID_ARGS:
164 return NLOPT_INVALID_ARGS;
165 case DIRECT_INIT_FAILED:
166 case DIRECT_SAMPLEPOINTS_FAILED:
167 case DIRECT_SAMPLE_FAILED:
168 return NLOPT_FAILURE;
169 case DIRECT_MAXFEVAL_EXCEEDED:
170 case DIRECT_MAXITER_EXCEEDED:
171 return NLOPT_MAXEVAL_REACHED;
172 case DIRECT_GLOBAL_FOUND:
173 return NLOPT_SUCCESS;
175 case DIRECT_SIGMATOL:
176 return NLOPT_XTOL_REACHED;
177 case DIRECT_OUT_OF_MEMORY:
178 return NLOPT_OUT_OF_MEMORY;
182 case NLOPT_GLOBAL_STOGO:
183 if (!stogo_minimize(n, f, f_data, x, fmin, lb, ub,
185 return NLOPT_FAILURE;
188 case NLOPT_LOCAL_SUBPLEX: {
190 double *scale = (double *) malloc(sizeof(double) * n);
191 if (!scale) return NLOPT_OUT_OF_MEMORY;
192 for (i = 0; i < n; ++i) {
193 if (!my_isinf(ub[i]) && !my_isinf(lb[i]))
194 scale[i] = (ub[i] - lb[i]) * 0.01;
195 else if (!my_isinf(lb[i]) && x[i] > lb[i])
196 scale[i] = (x[i] - lb[i]) * 0.01;
197 else if (!my_isinf(ub[i]) && x[i] < ub[i])
198 scale[i] = (ub[i] - x[i]) * 0.01;
200 scale[i] = 0.01 * x[i] + 0.0001;
202 iret = subplex(f_subplex, fmin, x, n, &d, &stop, scale);
205 case -2: return NLOPT_INVALID_ARGS;
206 case -10: return NLOPT_MAXTIME_REACHED;
207 case -1: return NLOPT_MAXEVAL_REACHED;
208 case 0: return NLOPT_XTOL_REACHED;
209 case 1: return NLOPT_SUCCESS;
210 case 2: return NLOPT_FMIN_MAX_REACHED;
211 case 20: return NLOPT_FTOL_REACHED;
212 case -200: return NLOPT_OUT_OF_MEMORY;
213 default: return NLOPT_FAILURE; /* unknown return code */
218 case NLOPT_LOCAL_LBFGS: {
219 int iret, *nbd = (int *) malloc(sizeof(int) * n);
220 if (!nbd) return NLOPT_OUT_OF_MEMORY;
221 for (i = 0; i < n; ++i) {
222 int linf = my_isinf(lb[i]) && lb[i] < 0;
223 int uinf = my_isinf(ub[i]) && ub[i] > 0;
224 nbd[i] = linf && uinf ? 0 : (uinf ? 1 : (linf ? 3 : 2));
226 iret = lbfgsb_minimize(n, f, f_data, x, nbd, lb, ub,
227 MIN(n, 5), 0.0, ftol_rel,
228 xtol_abs ? *xtol_abs : xtol_rel,
233 case -1: return NLOPT_INVALID_ARGS;
234 case -2: default: return NLOPT_FAILURE;
238 *fmin = f(n, x, NULL, f_data);
240 case 5: return NLOPT_MAXEVAL_REACHED;
241 case 2: return NLOPT_XTOL_REACHED;
242 case 1: return NLOPT_FTOL_REACHED;
243 default: return NLOPT_SUCCESS;
250 return NLOPT_INVALID_ARGS;
253 return NLOPT_SUCCESS;
256 nlopt_result nlopt_minimize(
257 nlopt_algorithm algorithm,
258 int n, nlopt_func f, void *f_data,
259 const double *lb, const double *ub, /* bounds */
260 double *x, /* in: initial guess, out: minimizer */
261 double *fmin, /* out: minimum */
262 double fmin_max, double ftol_rel, double ftol_abs,
263 double xtol_rel, const double *xtol_abs,
264 int maxeval, double maxtime)
268 ret = nlopt_minimize_(algorithm, n, f, f_data, lb, ub,
269 x, fmin, fmin_max, ftol_rel, ftol_abs,
270 xtol_rel, xtol_abs, maxeval, maxtime);
273 double *xtol = (double *) malloc(sizeof(double) * n);
274 if (!xtol) return NLOPT_OUT_OF_MEMORY;
275 for (i = 0; i < n; ++i) xtol[i] = -1;
276 ret = nlopt_minimize_(algorithm, n, f, f_data, lb, ub,
277 x, fmin, fmin_max, ftol_rel, ftol_abs,
278 xtol_rel, xtol, maxeval, maxtime);