15 #define USE_FEENABLEEXCEPT 0
16 #if USE_FEENABLEEXCEPT
18 extern "C" int feenableexcept (int EXCEPTS);
23 #include "nlopt-util.h"
24 #include "testfuncs.h"
26 static nlopt_algorithm algorithm = NLOPT_GN_DIRECT_L;
27 static double ftol_rel = 0, ftol_abs = 0, xtol_rel = 0, xtol_abs = 0, minf_max_delta = -HUGE_VAL;
28 static int maxeval = 1000, iterations = 1, center_start = 0;
29 static double maxtime = 0.0;
30 static double xinit_tol = -1;
31 static int force_constraints = 0;
33 static void listalgs(FILE *f)
36 fprintf(f, "Available algorithms:\n");
37 for (i = 0; i < NLOPT_NUM_ALGORITHMS; ++i)
38 fprintf(f, " %2d: %s\n", i, nlopt_algorithm_name((nlopt_algorithm) i));
41 static void listfuncs(FILE *f)
44 fprintf(f, "Available objective functions:\n");
45 for (i = 0; i < NTESTFUNCS; ++i)
46 fprintf(f, " %2d: %s (%d dims)\n", i, testfuncs[i].name, testfuncs[i].n);
50 const double *lb, *ub;
55 static double bounds_wrap_func(int n, const double *x, double *grad, void *d_)
57 bounds_wrap_data *d = (bounds_wrap_data *) d_;
59 for (i = 0; i < n; ++i)
60 if (x[i] < d->lb[i] || x[i] > d->ub[i])
63 fprintf(stderr, "WARNING: bounds violated by x[%d] = %g\n", i, x[i]);
64 return d->f(n, x, grad, d->f_data);
67 static int test_function(int ifunc)
71 double *x, minf, minf_max, f0, *xtabs, *lb, *ub;
73 double start = nlopt_seconds();
74 int total_count = 0, max_count = 0, min_count = 1<<30;
75 double total_err = 0, max_err = 0;
78 if (ifunc < 0 || ifunc >= NTESTFUNCS) {
79 fprintf(stderr, "testopt: invalid function %d\n", ifunc);
83 func = testfuncs[ifunc];
84 x = (double *) malloc(sizeof(double) * func.n * 5);
85 if (!x) { fprintf(stderr, "testopt: Out of memory!\n"); return 0; }
89 xtabs = x + func.n * 2;
93 bw.f_data = func.f_data;
95 for (i = 0; i < func.n; ++i) xtabs[i] = xtol_abs;
96 minf_max = minf_max_delta > (-HUGE_VAL) ? minf_max_delta + func.minf : (-HUGE_VAL);
98 printf("-----------------------------------------------------------\n");
99 printf("Optimizing %s (%d dims) using %s algorithm\n",
100 func.name, func.n, nlopt_algorithm_name(algorithm));
101 printf("lower bounds at lb = [");
102 for (i = 0; i < func.n; ++i) printf(" %g", func.lb[i]);
104 printf("upper bounds at ub = [");
105 for (i = 0; i < func.n; ++i) printf(" %g", func.ub[i]);
107 memcpy(lb, func.lb, func.n * sizeof(double));
108 memcpy(ub, func.ub, func.n * sizeof(double));
109 if (force_constraints) {
110 for (i = 0; i < func.n; ++i) {
111 if (nlopt_iurand(2) == 0)
112 ub[i] = nlopt_urand(lb[i], func.xmin[i]);
114 lb[i] = nlopt_urand(func.xmin[i], ub[i]);
116 printf("adjusted lower bounds at lb = [");
117 for (i = 0; i < func.n; ++i) printf(" %g", lb[i]);
119 printf("adjusted upper bounds at ub = [");
120 for (i = 0; i < func.n; ++i) printf(" %g", ub[i]);
124 if (fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf) > 1e-8) {
125 fprintf(stderr, "BUG: function does not achieve given lower bound!\n");
126 fprintf(stderr, "f(%g", func.xmin[0]);
127 for (i = 1; i < func.n; ++i) fprintf(stderr, ", %g", func.xmin[i]);
128 fprintf(stderr, ") = %0.16g instead of %0.16g, |diff| = %g\n",
129 func.f(func.n, func.xmin, 0, func.f_data), func.minf,
130 fabs(func.f(func.n, func.xmin, 0, func.f_data) - func.minf));
134 for (iter = 0; iter < iterations; ++iter) {
136 testfuncs_counter = 0;
138 printf("Starting guess x = [");
139 for (i = 0; i < func.n; ++i) {
141 x[i] = (ub[i] + lb[i]) * 0.5;
142 else if (xinit_tol < 0) { /* random starting point near center of box */
143 double dx = (ub[i] - lb[i]) * 0.25;
144 double xm = 0.5 * (ub[i] + lb[i]);
145 x[i] = nlopt_urand(xm - dx, xm + dx);
148 x[i] = nlopt_urand(-xinit_tol, xinit_tol)
149 + (1 + nlopt_urand(-xinit_tol, xinit_tol)) * func.xmin[i];
150 if (x[i] > ub[i]) x[i] = ub[i];
151 else if (x[i] < lb[i]) x[i] = lb[i];
156 f0 = func.f(func.n, x, x + func.n, func.f_data);
157 printf("Starting function value = %g\n", f0);
159 if (iter == 0 && testfuncs_verbose && func.has_gradient) {
160 printf("checking gradient:\n");
161 for (i = 0; i < func.n; ++i) {
164 f = func.f(func.n, x, NULL, func.f_data);
166 printf(" grad[%d] = %g vs. numerical derivative %g\n",
167 i, x[i + func.n], (f - f0) / (x[i] * 1e-6));
171 ret = nlopt_minimize(algorithm,
172 func.n, bounds_wrap_func, &bw,
175 minf_max, ftol_rel, ftol_abs, xtol_rel, xtabs,
177 printf("finished after %g seconds.\n", nlopt_seconds() - start);
178 printf("return code %d from nlopt_minimize\n", ret);
179 if (ret < 0 && ret != NLOPT_ROUNDOFF_LIMITED) {
180 fprintf(stderr, "testopt: error in nlopt_minimize\n");
183 printf("Found minimum f = %g after %d evaluations.\n",
184 minf, testfuncs_counter);
185 total_count += testfuncs_counter;
186 if (testfuncs_counter > max_count) max_count = testfuncs_counter;
187 if (testfuncs_counter < min_count) min_count = testfuncs_counter;
188 printf("Minimum at x = [");
189 for (i = 0; i < func.n; ++i) printf(" %g", x[i]);
191 printf("|f - minf| = %g, |f - minf| / |minf| = %e\n",
192 fabs(minf - func.minf), fabs(minf - func.minf) / fabs(func.minf));
193 total_err += fabs(minf - func.minf);
194 if (fabs(minf - func.minf) > max_err)
195 max_err = fabs(minf - func.minf);
196 printf("vs. global minimum f = %g at x = [", func.minf);
197 for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]);
200 val = func.f(func.n, x, NULL, func.f_data);
202 fprintf(stderr, "Mismatch %g between returned minf=%g and f(x) = %g\n",
203 minf - val, minf, val);
208 printf("average #evaluations = %g (%d-%d)\naverage |f-minf| = %g, max |f-minf| = %g\n", total_count * 1.0 / iterations, min_count, max_count, total_err / iterations, max_err);
214 static void usage(FILE *f)
216 fprintf(f, "Usage: testopt [OPTIONS]\n"
218 " -h : print this help\n"
219 " -L : list available algorithms and objective functions\n"
220 " -v : verbose mode\n"
221 " -a <n> : use optimization algorithm <n>\n"
222 " -o <n> : use objective function <n>\n"
223 " -0 <x> : starting guess within <x> + (1+<x>) * optimum\n"
224 " -c : starting guess at center of cell\n"
225 " -C : put optimum outside of bound constraints\n"
226 " -e <n> : use at most <n> evals (default: %d, 0 to disable)\n"
227 " -t <t> : use at most <t> seconds (default: disabled)\n"
228 " -x <t> : relative tolerance <t> on x (default: disabled)\n"
229 " -X <t> : absolute tolerance <t> on x (default: disabled)\n"
230 " -f <t> : relative tolerance <t> on f (default: disabled)\n"
231 " -F <t> : absolute tolerance <t> on f (default: disabled)\n"
232 " -m <m> : stop when minf+<m> is reached (default: disabled)\n"
233 " -i <n> : iterate optimization <n> times (default: 1)\n"
234 " -r <s> : use random seed <s> for starting guesses\n"
238 int main(int argc, char **argv)
243 testfuncs_verbose = 0;
248 #if USE_FEENABLEEXCEPT
249 feenableexcept(FE_INVALID);
252 while ((c = getopt(argc, argv, "hLvCc0:r:a:o:i:e:t:x:X:f:F:m:")) != -1)
262 testfuncs_verbose = 1;
265 force_constraints = 1;
268 nlopt_srand((unsigned long) atoi(optarg));
272 if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) {
273 fprintf(stderr, "testopt: invalid algorithm %d\n", c);
277 algorithm = (nlopt_algorithm) c;
280 if (!test_function(atoi(optarg)))
284 maxeval = atoi(optarg);
287 iterations = atoi(optarg);
290 maxtime = atof(optarg);
293 xtol_rel = atof(optarg);
296 xtol_abs = atof(optarg);
299 ftol_rel = atof(optarg);
302 ftol_abs = atof(optarg);
305 minf_max_delta = atof(optarg);
312 xinit_tol = atof(optarg);
315 fprintf(stderr, "harminv: invalid argument -%c\n", c);