chiark / gitweb /
supported more stopping criteria in subplex (still a little too pessimistic)
[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 = -HUGE_VAL;
20 static int maxeval = 1000;
21 static double maxtime = 0.0;
22
23 static void listalgs(FILE *f)
24 {
25   int i;
26   fprintf(f, "Available algorithms:\n");
27   for (i = 0; i < NLOPT_NUM_ALGORITHMS; ++i)
28     fprintf(f, "  %2d: %s\n", i, nlopt_algorithm_name((nlopt_algorithm) i));
29 }
30
31 static void listfuncs(FILE *f)
32 {
33   int i;
34   fprintf(f, "Available objective functions:\n");
35   for (i = 0; i < NTESTFUNCS; ++i)
36     fprintf(f, "  %2d: %s (%d dims)\n", i, testfuncs[i].name, testfuncs[i].n);
37 }
38
39 static int test_function(int ifunc)
40 {
41   testfunc func;
42   int i;
43   double *x, fmin, f0, *xtabs;
44   nlopt_result ret;
45   double start = nlopt_seconds();
46   
47   if (ifunc < 0 || ifunc >= NTESTFUNCS) {
48     fprintf(stderr, "testopt: invalid function %d\n", ifunc);
49     listfuncs(stderr);
50     return 0;
51   }
52   func = testfuncs[ifunc];
53   if (!func.has_gradient && algorithm >= NLOPT_GLOBAL_STOGO) {
54     fprintf(stderr, 
55             "testopt: A function with gradients is required for %s\n",
56             nlopt_algorithm_name(algorithm));
57     return 0;
58   }
59   x = (double *) malloc(sizeof(double) * func.n * 3);
60   if (!x) { fprintf(stderr, "testopt: Out of memory!\n"); return 0; }
61
62   xtabs = x + func.n * 2;
63   for (i = 0; i < func.n; ++i) xtabs[i] = xtol_abs;
64
65   
66   printf("-----------------------------------------------------------\n");
67   printf("Optimizing %s (%d dims) using %s algorithm\n",
68          func.name, func.n, nlopt_algorithm_name(algorithm));
69   printf("Starting guess x = [");
70   for (i = 0; i < func.n; ++i)
71     printf(" %g", x[i] = nlopt_urand(func.lb[i], func.ub[i]));
72   printf("]\n");
73   f0 = func.f(func.n, x, x + func.n, func.f_data);
74   printf("Starting function value = %g\n", f0);
75
76   if (testfuncs_verbose && func.has_gradient) {
77     printf("checking gradient:\n");
78     for (i = 0; i < func.n; ++i) {
79       double f;
80       x[i] *= 1 + 1e-6;
81       f = func.f(func.n, x, NULL, func.f_data);
82       x[i] /= 1 + 1e-6;
83       printf("  grad[%d] = %g vs. numerical derivative %g\n",
84              i, x[i + func.n], (f - f0) / (x[i] * 1e-6));
85     }
86   }
87
88   testfuncs_counter = 0;
89   ret = nlopt_minimize(algorithm,
90                        func.n, func.f, func.f_data,
91                        func.lb, func.ub,
92                        x, &fmin,
93                        fmin_max, ftol_rel, ftol_abs, xtol_rel, xtabs,
94                        maxeval, maxtime);
95   printf("finished after %g seconds.\n", nlopt_seconds() - start);
96   printf("return code %d from nlopt_minimize\n", ret);
97   if (ret < 0) {
98     fprintf(stderr, "testopt: error in nlopt_minimize\n");
99     return 0;
100   }
101   printf("Found minimum f = %g after %d evaluations.\n", 
102          fmin, testfuncs_counter);
103   printf("Minimum at x = [");
104   for (i = 0; i < func.n; ++i) printf(" %g", x[i]);
105   printf("]\n");
106   printf("vs. global minimum f = %g at x = [", func.fmin);
107   for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]);
108   printf("]\n");
109   printf("|f - fmin| = %g, |f - fmin| / |fmin| = %e\n",
110          fabs(fmin - func.fmin), fabs(fmin - func.fmin) / fabs(func.fmin));
111   
112   free(x);
113   return 1;
114 }
115
116 static void usage(FILE *f)
117 {
118   fprintf(f, "Usage: testopt [OPTIONS]\n"
119           "Options:\n"
120           "     -h : print this help\n"
121           "     -L : list available algorithms and objective functions\n"
122           "     -v : verbose mode\n"
123           " -r <s> : use random seed <s> for starting guesses\n"
124           " -a <n> : use optimization algorithm <n>\n"
125           " -o <n> : use objective function <n>\n"
126           " -e <n> : use at most <n> evals (default: %d, 0 to disable)\n"
127           " -t <t> : use at most <t> seconds (default: disabled)\n"
128           " -x <t> : relative tolerance <t> on x (default: disabled)\n"
129           " -X <t> : absolute tolerance <t> on x (default: disabled)\n"
130           " -f <t> : relative tolerance <t> on f (default: disabled)\n"
131           " -F <t> : absolute tolerance <t> on f (default: disabled)\n"
132           " -m <m> : minimize f until <m> is reached (default: disabled)\n"
133           , maxeval);
134 }
135
136 int main(int argc, char **argv)
137 {
138   int c;
139   
140   nlopt_srand_time();
141   testfuncs_verbose = 0;
142   
143   if (argc <= 1)
144     usage(stdout);
145   
146   while ((c = getopt(argc, argv, "hLvr:a:o:e:t:x:X:f:F:m:")) != -1)
147     switch (c) {
148     case 'h':
149       usage(stdout);
150       return EXIT_SUCCESS;
151     case 'L':
152       listalgs(stdout);
153       listfuncs(stdout);
154       return EXIT_SUCCESS;
155     case 'v':
156       testfuncs_verbose = 1;
157       break;
158     case 'r':
159       nlopt_srand((unsigned long) atoi(optarg));
160       break;
161     case 'a':
162       c = atoi(optarg);
163       if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) {
164         fprintf(stderr, "testopt: invalid algorithm %d\n", c);
165         listalgs(stderr);
166         return EXIT_FAILURE;
167       }
168       algorithm = (nlopt_algorithm) c;
169       break;
170     case 'o':
171       if (!test_function(atoi(optarg)))
172         return EXIT_FAILURE;
173       break;
174     case 'e':
175       maxeval = atoi(optarg);
176       break;
177     case 't':
178       maxtime = atof(optarg);
179       break;
180     case 'x':
181       xtol_rel = atof(optarg);
182       break;
183     case 'X':
184       xtol_abs = atof(optarg);
185       break;
186     case 'f':
187       ftol_rel = atof(optarg);
188       break;
189     case 'F':
190       ftol_abs = atof(optarg);
191       break;
192     case 'm':
193       fmin_max = atof(optarg);
194       break;
195     default:
196       fprintf(stderr, "harminv: invalid argument -%c\n", c);
197       usage(stderr);
198       return EXIT_FAILURE;
199     }
200   
201   return EXIT_SUCCESS;
202 }