chiark / gitweb /
bug fix in grosenbrock gradient (no wonder StoGO etc. were so bad for this functioon)
[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_GN_DIRECT_L;
19 static double ftol_rel = 0, ftol_abs = 0, xtol_rel = 0, xtol_abs = 0, minf_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, minf, minf_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   x = (double *) malloc(sizeof(double) * func.n * 3);
55   if (!x) { fprintf(stderr, "testopt: Out of memory!\n"); return 0; }
56
57   xtabs = x + func.n * 2;
58   for (i = 0; i < func.n; ++i) xtabs[i] = xtol_abs;
59   minf_max = minf_max_delta > (-HUGE_VAL) ? minf_max_delta + func.minf : (-HUGE_VAL);
60   
61   printf("-----------------------------------------------------------\n");
62   printf("Optimizing %s (%d dims) using %s algorithm\n",
63          func.name, func.n, nlopt_algorithm_name(algorithm));
64   printf("lower bounds at lb = [");
65   for (i = 0; i < func.n; ++i) printf(" %g", func.lb[i]);
66   printf("]\n");
67   printf("upper bounds at ub = [");
68   for (i = 0; i < func.n; ++i) printf(" %g", func.ub[i]);
69   printf("]\n");
70
71
72   printf("Starting guess x = [");
73   for (i = 0; i < func.n; ++i) {
74     if (center_start)
75       x[i] = (func.ub[i] + func.lb[i]) * 0.5;
76     else if (xinit_tol < 0) { /* random starting point near center of box */
77       double dx = (func.ub[i] - func.lb[i]) * 0.25;
78       double xm = 0.5 * (func.ub[i] + func.lb[i]);
79       x[i] = nlopt_urand(xm - dx, xm + dx);
80     }
81     else {
82       x[i] = nlopt_urand(-xinit_tol, xinit_tol)
83         + (1 + nlopt_urand(-xinit_tol, xinit_tol)) * func.xmin[i];
84       if (x[i] > func.ub[i]) x[i] = func.ub[i];
85       else if (x[i] < func.lb[i]) x[i] = func.lb[i];
86     }
87     printf(" %g", x[i]);
88   }
89   printf("]\n");
90   f0 = func.f(func.n, x, x + func.n, func.f_data);
91   printf("Starting function value = %g\n", f0);
92
93   if (testfuncs_verbose && func.has_gradient) {
94     printf("checking gradient:\n");
95     for (i = 0; i < func.n; ++i) {
96       double f;
97       x[i] *= 1 + 1e-6;
98       f = func.f(func.n, x, NULL, func.f_data);
99       x[i] /= 1 + 1e-6;
100       printf("  grad[%d] = %g vs. numerical derivative %g\n",
101              i, x[i + func.n], (f - f0) / (x[i] * 1e-6));
102     }
103   }
104
105   for (iter = 0; iter < iterations; ++iter) {
106     testfuncs_counter = 0;
107     ret = nlopt_minimize(algorithm,
108                          func.n, func.f, func.f_data,
109                          func.lb, func.ub,
110                          x, &minf,
111                          minf_max, ftol_rel, ftol_abs, xtol_rel, xtabs,
112                          maxeval, maxtime);
113     printf("finished after %g seconds.\n", nlopt_seconds() - start);
114     printf("return code %d from nlopt_minimize\n", ret);
115     if (ret < 0) {
116       fprintf(stderr, "testopt: error in nlopt_minimize\n");
117       return 0;
118     }
119     printf("Found minimum f = %g after %d evaluations.\n", 
120            minf, testfuncs_counter);
121     printf("Minimum at x = [");
122     for (i = 0; i < func.n; ++i) printf(" %g", x[i]);
123     printf("]\n");
124     printf("|f - minf| = %g, |f - minf| / |minf| = %e\n",
125            fabs(minf - func.minf), fabs(minf - func.minf) / fabs(func.minf));
126   }
127   printf("vs. global minimum f = %g at x = [", func.minf);
128   for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]);
129   printf("]\n");
130   
131   free(x);
132   return 1;
133 }
134
135 static void usage(FILE *f)
136 {
137   fprintf(f, "Usage: testopt [OPTIONS]\n"
138           "Options:\n"
139           "     -h : print this help\n"
140           "     -L : list available algorithms and objective functions\n"
141           "     -v : verbose mode\n"
142           " -a <n> : use optimization algorithm <n>\n"
143           " -o <n> : use objective function <n>\n"
144           " -0 <x> : starting guess within <x> + (1+<x>) * optimum\n"
145           "     -c : starting guess at center of cell\n"
146           " -e <n> : use at most <n> evals (default: %d, 0 to disable)\n"
147           " -t <t> : use at most <t> seconds (default: disabled)\n"
148           " -x <t> : relative tolerance <t> on x (default: disabled)\n"
149           " -X <t> : absolute tolerance <t> on x (default: disabled)\n"
150           " -f <t> : relative tolerance <t> on f (default: disabled)\n"
151           " -F <t> : absolute tolerance <t> on f (default: disabled)\n"
152           " -m <m> : stop when minf+<m> is reached (default: disabled)\n"
153           " -i <n> : iterate optimization <n> times (default: 1)\n"
154           " -r <s> : use random seed <s> for starting guesses\n"
155           , maxeval);
156 }
157
158 int main(int argc, char **argv)
159 {
160   int c;
161   
162   nlopt_srand_time();
163   testfuncs_verbose = 0;
164   
165   if (argc <= 1)
166     usage(stdout);
167   
168   while ((c = getopt(argc, argv, "hLvc0:r:a:o:i:e:t:x:X:f:F:m:")) != -1)
169     switch (c) {
170     case 'h':
171       usage(stdout);
172       return EXIT_SUCCESS;
173     case 'L':
174       listalgs(stdout);
175       listfuncs(stdout);
176       return EXIT_SUCCESS;
177     case 'v':
178       testfuncs_verbose = 1;
179       break;
180     case 'r':
181       nlopt_srand((unsigned long) atoi(optarg));
182       break;
183     case 'a':
184       c = atoi(optarg);
185       if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) {
186         fprintf(stderr, "testopt: invalid algorithm %d\n", c);
187         listalgs(stderr);
188         return EXIT_FAILURE;
189       }
190       algorithm = (nlopt_algorithm) c;
191       break;
192     case 'o':
193       if (!test_function(atoi(optarg)))
194         return EXIT_FAILURE;
195       break;
196     case 'e':
197       maxeval = atoi(optarg);
198       break;
199     case 'i':
200       iterations = atoi(optarg);
201       break;
202     case 't':
203       maxtime = atof(optarg);
204       break;
205     case 'x':
206       xtol_rel = atof(optarg);
207       break;
208     case 'X':
209       xtol_abs = atof(optarg);
210       break;
211     case 'f':
212       ftol_rel = atof(optarg);
213       break;
214     case 'F':
215       ftol_abs = atof(optarg);
216       break;
217     case 'm':
218       minf_max_delta = atof(optarg);
219       break;
220     case 'c':
221       center_start = 1;
222       break;
223     case '0':
224       center_start = 0;
225       xinit_tol = atof(optarg);
226       break;
227     default:
228       fprintf(stderr, "harminv: invalid argument -%c\n", c);
229       usage(stderr);
230       return EXIT_FAILURE;
231     }
232   
233   return EXIT_SUCCESS;
234 }