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 nlopt_result nlopt_minimize(
110 nlopt_algorithm algorithm,
111 int n, nlopt_func f, void *f_data,
112 const double *lb, const double *ub, /* bounds */
113 double *x, /* in: initial guess, out: minimizer */
114 double *fmin, /* out: minimum */
115 double fmin_max, double ftol_rel, double ftol_abs,
116 double xtol_rel, const double *xtol_abs,
117 int maxeval, double maxtime)
126 /* make sure rand generator is inited */
127 if (!nlopt_srand_called)
128 nlopt_srand_time(); /* default is non-deterministic */
130 /* check bound constraints */
131 for (i = 0; i < n; ++i)
132 if (lb[i] > ub[i] || x[i] < lb[i] || x[i] > ub[i])
133 return NLOPT_INVALID_ARGS;
136 case NLOPT_GLOBAL_DIRECT:
137 case NLOPT_GLOBAL_DIRECT_L:
138 switch (direct_optimize(f_direct, &d, n, lb, ub, x, fmin,
139 maxeval, 500, ftol_rel, ftol_abs,
141 DIRECT_UNKNOWN_FGLOBAL, -1.0,
143 algorithm == NLOPT_GLOBAL_DIRECT
145 : DIRECT_GABLONSKY)) {
146 case DIRECT_INVALID_BOUNDS:
147 case DIRECT_MAXFEVAL_TOOBIG:
148 case DIRECT_INVALID_ARGS:
149 return NLOPT_INVALID_ARGS;
150 case DIRECT_INIT_FAILED:
151 case DIRECT_SAMPLEPOINTS_FAILED:
152 case DIRECT_SAMPLE_FAILED:
153 return NLOPT_FAILURE;
154 case DIRECT_MAXFEVAL_EXCEEDED:
155 case DIRECT_MAXITER_EXCEEDED:
156 return NLOPT_MAXEVAL_REACHED;
157 case DIRECT_GLOBAL_FOUND:
158 return NLOPT_SUCCESS;
160 case DIRECT_SIGMATOL:
161 return NLOPT_XTOL_REACHED;
162 case DIRECT_OUT_OF_MEMORY:
163 return NLOPT_OUT_OF_MEMORY;
167 case NLOPT_GLOBAL_STOGO:
168 if (!stogo_minimize(n, f, f_data, x, fmin, lb, ub,
170 return NLOPT_FAILURE;
173 case NLOPT_LOCAL_SUBPLEX: {
175 double *scale = (double *) malloc(sizeof(double) * n);
176 if (!scale) return NLOPT_OUT_OF_MEMORY;
177 for (i = 0; i < n; ++i) {
178 if (!my_isinf(ub[i]) && !my_isinf(lb[i]))
179 scale[i] = (ub[i] - lb[i]) * 0.01;
180 else if (!my_isinf(lb[i]) && x[i] > lb[i])
181 scale[i] = (x[i] - lb[i]) * 0.01;
182 else if (!my_isinf(ub[i]) && x[i] < ub[i])
183 scale[i] = (ub[i] - x[i]) * 0.01;
185 scale[i] = 0.01 * x[i] + 0.0001;
187 iret = subplex(f_subplex, fmin, x, n, &d, xtol_rel, maxeval,
188 fmin_max, !my_isinf(fmin_max), scale);
191 case -2: return NLOPT_INVALID_ARGS;
192 case -1: return NLOPT_MAXEVAL_REACHED;
193 case 0: return NLOPT_XTOL_REACHED;
194 case 1: return NLOPT_SUCCESS;
195 case 2: return NLOPT_FMIN_MAX_REACHED;
200 case NLOPT_LOCAL_LBFGS: {
201 int iret, *nbd = (int *) malloc(sizeof(int) * n);
202 if (!nbd) return NLOPT_OUT_OF_MEMORY;
203 for (i = 0; i < n; ++i) {
204 int linf = my_isinf(lb[i]) && lb[i] < 0;
205 int uinf = my_isinf(ub[i]) && ub[i] > 0;
206 nbd[i] = linf && uinf ? 0 : (uinf ? 1 : (linf ? 3 : 2));
208 iret = lbfgsb_minimize(n, f, f_data, x, nbd, lb, ub,
209 MIN(n, 5), 0.0, ftol_rel,
210 xtol_abs ? *xtol_abs : xtol_rel,
215 case -1: return NLOPT_INVALID_ARGS;
216 case -2: default: return NLOPT_FAILURE;
220 *fmin = f(n, x, NULL, f_data);
222 case 5: return NLOPT_MAXEVAL_REACHED;
223 case 2: return NLOPT_XTOL_REACHED;
224 case 1: return NLOPT_FTOL_REACHED;
225 default: return NLOPT_SUCCESS;
232 return NLOPT_INVALID_ARGS;
235 return NLOPT_SUCCESS;