chiark / gitweb /
added 3 more test functions
[nlopt.git] / test / testopt.cpp
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <math.h>
4
5 #include "config.h"
6
7 #ifdef HAVE_UNISTD_H
8 #  include <unistd.h>
9 #endif
10 #ifdef HAVE_GETOPT_H
11 #  include <getopt.h>
12 #endif
13
14 #include "nlopt.h"
15 #include "nlopt-util.h"
16 #include "testfuncs.h"
17
18 static nlopt_algorithm algorithm = NLOPT_GLOBAL_DIRECT;
19 static double ftol_rel = 0, ftol_abs = 0, xtol_rel = 0, xtol_abs = 0, fmin_max_delta = -HUGE_VAL;
20 static int maxeval = 1000, iterations = 1, center_start = 0;
21 static double maxtime = 0.0;
22 static double xinit_tol = -1;
23
24 static void listalgs(FILE *f)
25 {
26   int i;
27   fprintf(f, "Available algorithms:\n");
28   for (i = 0; i < NLOPT_NUM_ALGORITHMS; ++i)
29     fprintf(f, "  %2d: %s\n", i, nlopt_algorithm_name((nlopt_algorithm) i));
30 }
31
32 static void listfuncs(FILE *f)
33 {
34   int i;
35   fprintf(f, "Available objective functions:\n");
36   for (i = 0; i < NTESTFUNCS; ++i)
37     fprintf(f, "  %2d: %s (%d dims)\n", i, testfuncs[i].name, testfuncs[i].n);
38 }
39
40 static int test_function(int ifunc)
41 {
42   testfunc func;
43   int i, iter;
44   double *x, fmin, fmin_max, f0, *xtabs;
45   nlopt_result ret;
46   double start = nlopt_seconds();
47   
48   if (ifunc < 0 || ifunc >= NTESTFUNCS) {
49     fprintf(stderr, "testopt: invalid function %d\n", ifunc);
50     listfuncs(stderr);
51     return 0;
52   }
53   func = testfuncs[ifunc];
54   if (!func.has_gradient && algorithm >= NLOPT_GLOBAL_STOGO) {
55     fprintf(stderr, 
56             "testopt: A function with gradients is required for %s\n",
57             nlopt_algorithm_name(algorithm));
58     return 0;
59   }
60   x = (double *) malloc(sizeof(double) * func.n * 3);
61   if (!x) { fprintf(stderr, "testopt: Out of memory!\n"); return 0; }
62
63   xtabs = x + func.n * 2;
64   for (i = 0; i < func.n; ++i) xtabs[i] = xtol_abs;
65   fmin_max = fmin_max_delta > (-HUGE_VAL) ? fmin_max_delta + func.fmin : (-HUGE_VAL);
66   
67   printf("-----------------------------------------------------------\n");
68   printf("Optimizing %s (%d dims) using %s algorithm\n",
69          func.name, func.n, nlopt_algorithm_name(algorithm));
70   printf("lower bounds at lb = [");
71   for (i = 0; i < func.n; ++i) printf(" %g", func.lb[i]);
72   printf("]\n");
73   printf("upper bounds at ub = [");
74   for (i = 0; i < func.n; ++i) printf(" %g", func.ub[i]);
75   printf("]\n");
76
77
78   printf("Starting guess x = [");
79   for (i = 0; i < func.n; ++i) {
80     if (center_start)
81       x[i] = (func.ub[i] + func.lb[i]) * 0.5;
82     else if (xinit_tol < 0) { /* random starting point near center of box */
83       double dx = (func.ub[i] - func.lb[i]) * 0.25;
84       double xm = 0.5 * (func.ub[i] + func.lb[i]);
85       x[i] = nlopt_urand(xm - dx, xm + dx);
86     }
87     else {
88       x[i] = nlopt_urand(-xinit_tol, xinit_tol)
89         + (1 + nlopt_urand(-xinit_tol, xinit_tol)) * func.xmin[i];
90       if (x[i] > func.ub[i]) x[i] = func.ub[i];
91       else if (x[i] < func.lb[i]) x[i] = func.lb[i];
92     }
93     printf(" %g", x[i]);
94   }
95   printf("]\n");
96   f0 = func.f(func.n, x, x + func.n, func.f_data);
97   printf("Starting function value = %g\n", f0);
98
99   if (testfuncs_verbose && func.has_gradient) {
100     printf("checking gradient:\n");
101     for (i = 0; i < func.n; ++i) {
102       double f;
103       x[i] *= 1 + 1e-6;
104       f = func.f(func.n, x, NULL, func.f_data);
105       x[i] /= 1 + 1e-6;
106       printf("  grad[%d] = %g vs. numerical derivative %g\n",
107              i, x[i + func.n], (f - f0) / (x[i] * 1e-6));
108     }
109   }
110
111   for (iter = 0; iter < iterations; ++iter) {
112     testfuncs_counter = 0;
113     ret = nlopt_minimize(algorithm,
114                          func.n, func.f, func.f_data,
115                          func.lb, func.ub,
116                          x, &fmin,
117                          fmin_max, ftol_rel, ftol_abs, xtol_rel, xtabs,
118                          maxeval, maxtime);
119     printf("finished after %g seconds.\n", nlopt_seconds() - start);
120     printf("return code %d from nlopt_minimize\n", ret);
121     if (ret < 0) {
122       fprintf(stderr, "testopt: error in nlopt_minimize\n");
123       return 0;
124     }
125     printf("Found minimum f = %g after %d evaluations.\n", 
126            fmin, testfuncs_counter);
127     printf("Minimum at x = [");
128     for (i = 0; i < func.n; ++i) printf(" %g", x[i]);
129     printf("]\n");
130     printf("|f - fmin| = %g, |f - fmin| / |fmin| = %e\n",
131            fabs(fmin - func.fmin), fabs(fmin - func.fmin) / fabs(func.fmin));
132   }
133   printf("vs. global minimum f = %g at x = [", func.fmin);
134   for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]);
135   printf("]\n");
136   
137   free(x);
138   return 1;
139 }
140
141 static void usage(FILE *f)
142 {
143   fprintf(f, "Usage: testopt [OPTIONS]\n"
144           "Options:\n"
145           "     -h : print this help\n"
146           "     -L : list available algorithms and objective functions\n"
147           "     -v : verbose mode\n"
148           " -a <n> : use optimization algorithm <n>\n"
149           " -o <n> : use objective function <n>\n"
150           " -0 <x> : starting guess within <x> + (1+<x>) * optimum\n"
151           "     -c : starting guess at center of cell\n"
152           " -e <n> : use at most <n> evals (default: %d, 0 to disable)\n"
153           " -t <t> : use at most <t> seconds (default: disabled)\n"
154           " -x <t> : relative tolerance <t> on x (default: disabled)\n"
155           " -X <t> : absolute tolerance <t> on x (default: disabled)\n"
156           " -f <t> : relative tolerance <t> on f (default: disabled)\n"
157           " -F <t> : absolute tolerance <t> on f (default: disabled)\n"
158           " -m <m> : stop when fmin+<m> is reached (default: disabled)\n"
159           " -i <n> : iterate optimization <n> times (default: 1)\n"
160           " -r <s> : use random seed <s> for starting guesses\n"
161           , maxeval);
162 }
163
164 int main(int argc, char **argv)
165 {
166   int c;
167   
168   nlopt_srand_time();
169   testfuncs_verbose = 0;
170   
171   if (argc <= 1)
172     usage(stdout);
173   
174   while ((c = getopt(argc, argv, "hLvc0:r:a:o:i:e:t:x:X:f:F:m:")) != -1)
175     switch (c) {
176     case 'h':
177       usage(stdout);
178       return EXIT_SUCCESS;
179     case 'L':
180       listalgs(stdout);
181       listfuncs(stdout);
182       return EXIT_SUCCESS;
183     case 'v':
184       testfuncs_verbose = 1;
185       break;
186     case 'r':
187       nlopt_srand((unsigned long) atoi(optarg));
188       break;
189     case 'a':
190       c = atoi(optarg);
191       if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) {
192         fprintf(stderr, "testopt: invalid algorithm %d\n", c);
193         listalgs(stderr);
194         return EXIT_FAILURE;
195       }
196       algorithm = (nlopt_algorithm) c;
197       break;
198     case 'o':
199       if (!test_function(atoi(optarg)))
200         return EXIT_FAILURE;
201       break;
202     case 'e':
203       maxeval = atoi(optarg);
204       break;
205     case 'i':
206       iterations = atoi(optarg);
207       break;
208     case 't':
209       maxtime = atof(optarg);
210       break;
211     case 'x':
212       xtol_rel = atof(optarg);
213       break;
214     case 'X':
215       xtol_abs = atof(optarg);
216       break;
217     case 'f':
218       ftol_rel = atof(optarg);
219       break;
220     case 'F':
221       ftol_abs = atof(optarg);
222       break;
223     case 'm':
224       fmin_max_delta = atof(optarg);
225       break;
226     case 'c':
227       center_start = 1;
228       break;
229     case '0':
230       center_start = 0;
231       xinit_tol = atof(optarg);
232       break;
233     default:
234       fprintf(stderr, "harminv: invalid argument -%c\n", c);
235       usage(stderr);
236       return EXIT_FAILURE;
237     }
238   
239   return EXIT_SUCCESS;
240 }