chiark / gitweb /
added test program and some test objectives
[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 #if TIME_WITH_SYS_TIME
14 # include <sys/time.h>
15 # include <time.h>
16 #else
17 # if HAVE_SYS_TIME_H
18 #  include <sys/time.h>
19 # else
20 #  include <time.h>
21 # endif
22 #endif
23
24 #include "nlopt.h"
25 #include "testfuncs.h"
26
27 static double urand(double a, double b)
28 {
29   return a + (rand() * (b - a) / RAND_MAX);
30 }
31
32 static nlopt_algorithm algorithm = NLOPT_GLOBAL_DIRECT;
33 static double ftol_rel = 0, ftol_abs = 0, xtol_rel = 0;
34 static int maxeval = 1000;
35 static double maxtime = 0.0;
36
37 static int test_function(int ifunc)
38 {
39   testfunc func;
40   int i;
41   double *x, fmin, f0;
42   
43   if (ifunc < 0 || ifunc >= NTESTFUNCS) {
44     fprintf(stderr, "testopt: invalid function %d\n", ifunc);
45     return 0;
46   }
47   func = testfuncs[ifunc];
48   if (!func.has_gradient && algorithm >= NLOPT_GLOBAL_STOGO) {
49     fprintf(stderr, 
50             "testopt: A function with gradients is required for %s\n",
51             nlopt_algorithm_name(algorithm));
52     return 0;
53   }
54   x = (double *) malloc(sizeof(double) * func.n * 2);
55   if (!x) { fprintf(stderr, "testopt: Out of memory!\n"); return 0; }
56
57   
58   printf("-----------------------------------------------------------\n");
59   printf("Optimizing %s (%d dims) using %s algorithm\n",
60          func.name, func.n, nlopt_algorithm_name(algorithm));
61   printf("Starting guess x = [");
62   for (i = 0; i < func.n; ++i)
63     printf(" %g", x[i] = urand(func.lb[i], func.ub[i]));
64   printf("]\n");
65   f0 = func.f(func.n, x, x + func.n, func.f_data);
66   printf("Starting function value = %g\n", f0);
67
68   if (testfuncs_verbose && func.has_gradient) {
69     printf("checking gradient:\n");
70     for (i = 0; i < func.n; ++i) {
71       double f;
72       x[i] *= 1 + 1e-6;
73       f = func.f(func.n, x, NULL, func.f_data);
74       x[i] /= 1 + 1e-6;
75       printf("  grad[%d] = %g vs. numerical derivative %g\n",
76              i, x[i + func.n], (f - f0) / (x[i] * 1e-6));
77     }
78   }
79
80   testfuncs_counter = 0;
81   if (nlopt_minimize(algorithm,
82                      func.n, func.f, func.f_data,
83                      func.lb, func.ub,
84                      x, &fmin,
85                      HUGE_VAL, ftol_rel, ftol_abs, xtol_rel, NULL,
86                      maxeval, maxtime) < 0) {
87     fprintf(stderr, "testopt: error in nlopt_minimize\n");
88     return 0;
89   }
90   printf("Found minimum f = %g after %d evaluations.\n", 
91          fmin, testfuncs_counter);
92   printf("Minimum at x = [");
93   for (i = 0; i < func.n; ++i) printf(" %g", x[i]);
94   printf("]\n");
95   printf("vs. global minimum f = %g at x = [", func.fmin);
96   for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]);
97   printf("]\n");
98   printf("|f - fmin| = %g, |f - fmin| / |fmin| = %e\n",
99          fabs(fmin - func.fmin), fabs(fmin - func.fmin) / fabs(func.fmin));
100   
101   free(x);
102   return 1;
103 }
104
105 static void usage(FILE *f)
106 {
107   fprintf(f, "Usage: testopt [OPTIONS]\n"
108           "Options:\n"
109           "     -h : print this help\n"
110           "     -v : verbose mode\n"
111           " -r <s> : use random seed <s> for starting guesses\n"
112           " -a <n> : use optimization algorithm <n>\n"
113           " -o <n> : use objective function <n>\n"
114           " -e <n> : use at most <n> evals (default: %d)\n",
115           maxeval);
116 }
117
118 int main(int argc, char **argv)
119 {
120   int c;
121   
122   srand((unsigned) time(NULL));
123   testfuncs_verbose = 0;
124   
125   while ((c = getopt(argc, argv, "hvra:o:e:")) != -1)
126     switch (c) {
127     case 'h':
128       usage(stdout);
129       return EXIT_SUCCESS;
130     case 'v':
131       testfuncs_verbose = 1;
132       break;
133     case 'r':
134       srand((unsigned) atoi(optarg));
135       break;
136     case 'a':
137       c = atoi(optarg);
138       if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) {
139         fprintf(stderr, "testopt: invalid algorithm %d\n", c);
140         return EXIT_FAILURE;
141       }
142       algorithm = (nlopt_algorithm) c;
143       break;
144     case 'o':
145       if (!test_function(atoi(optarg)))
146         return EXIT_FAILURE;
147       break;
148     case 'e':
149       maxeval = atoi(optarg);
150       break;
151     default:
152       fprintf(stderr, "harminv: invalid argument -%c\n", c);
153       usage(stderr);
154       return EXIT_FAILURE;
155     }
156   
157   return EXIT_SUCCESS;
158 }