testopt.cpp 5.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "config.h"

#ifdef HAVE_UNISTD_H
#  include <unistd.h>
#endif
#ifdef HAVE_GETOPT_H
#  include <getopt.h>
#endif

#include "nlopt.h"
15
#include "nlopt-util.h"
16 17 18
#include "testfuncs.h"

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 21 22
static int maxeval = 1000;
static double maxtime = 0.0;

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
static void listalgs(FILE *f)
{
  int i;
  fprintf(f, "Available algorithms:\n");
  for (i = 0; i < NLOPT_NUM_ALGORITHMS; ++i)
    fprintf(f, "  %2d: %s\n", i, nlopt_algorithm_name((nlopt_algorithm) i));
}

static void listfuncs(FILE *f)
{
  int i;
  fprintf(f, "Available objective functions:\n");
  for (i = 0; i < NTESTFUNCS; ++i)
    fprintf(f, "  %2d: %s (%d dims)\n", i, testfuncs[i].name, testfuncs[i].n);
}

39 40 41 42
static int test_function(int ifunc)
{
  testfunc func;
  int i;
43
  double *x, fmin, f0, *xtabs;
S
stevenj 已提交
44
  nlopt_result ret;
45
  double start = nlopt_seconds();
46 47 48
  
  if (ifunc < 0 || ifunc >= NTESTFUNCS) {
    fprintf(stderr, "testopt: invalid function %d\n", ifunc);
49
    listfuncs(stderr);
50 51 52 53 54 55 56 57 58
    return 0;
  }
  func = testfuncs[ifunc];
  if (!func.has_gradient && algorithm >= NLOPT_GLOBAL_STOGO) {
    fprintf(stderr, 
	    "testopt: A function with gradients is required for %s\n",
	    nlopt_algorithm_name(algorithm));
    return 0;
  }
59
  x = (double *) malloc(sizeof(double) * func.n * 3);
60 61
  if (!x) { fprintf(stderr, "testopt: Out of memory!\n"); return 0; }

62 63 64
  xtabs = x + func.n * 2;
  for (i = 0; i < func.n; ++i) xtabs[i] = xtol_abs;

65 66 67 68 69 70
  
  printf("-----------------------------------------------------------\n");
  printf("Optimizing %s (%d dims) using %s algorithm\n",
	 func.name, func.n, nlopt_algorithm_name(algorithm));
  printf("Starting guess x = [");
  for (i = 0; i < func.n; ++i)
71
    printf(" %g", x[i] = nlopt_urand(func.lb[i], func.ub[i]));
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
  printf("]\n");
  f0 = func.f(func.n, x, x + func.n, func.f_data);
  printf("Starting function value = %g\n", f0);

  if (testfuncs_verbose && func.has_gradient) {
    printf("checking gradient:\n");
    for (i = 0; i < func.n; ++i) {
      double f;
      x[i] *= 1 + 1e-6;
      f = func.f(func.n, x, NULL, func.f_data);
      x[i] /= 1 + 1e-6;
      printf("  grad[%d] = %g vs. numerical derivative %g\n",
	     i, x[i + func.n], (f - f0) / (x[i] * 1e-6));
    }
  }

  testfuncs_counter = 0;
S
stevenj 已提交
89 90 91 92
  ret = nlopt_minimize(algorithm,
		       func.n, func.f, func.f_data,
		       func.lb, func.ub,
		       x, &fmin,
93
		       fmin_max, ftol_rel, ftol_abs, xtol_rel, xtabs,
S
stevenj 已提交
94
		       maxeval, maxtime);
95
  printf("finished after %g seconds.\n", nlopt_seconds() - start);
S
stevenj 已提交
96 97
  printf("return code %d from nlopt_minimize\n", ret);
  if (ret < 0) {
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    fprintf(stderr, "testopt: error in nlopt_minimize\n");
    return 0;
  }
  printf("Found minimum f = %g after %d evaluations.\n", 
	 fmin, testfuncs_counter);
  printf("Minimum at x = [");
  for (i = 0; i < func.n; ++i) printf(" %g", x[i]);
  printf("]\n");
  printf("vs. global minimum f = %g at x = [", func.fmin);
  for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]);
  printf("]\n");
  printf("|f - fmin| = %g, |f - fmin| / |fmin| = %e\n",
	 fabs(fmin - func.fmin), fabs(fmin - func.fmin) / fabs(func.fmin));
  
  free(x);
  return 1;
}

static void usage(FILE *f)
{
  fprintf(f, "Usage: testopt [OPTIONS]\n"
	  "Options:\n"
	  "     -h : print this help\n"
121
	  "     -L : list available algorithms and objective functions\n"
122 123 124 125
	  "     -v : verbose mode\n"
	  " -r <s> : use random seed <s> for starting guesses\n"
	  " -a <n> : use optimization algorithm <n>\n"
	  " -o <n> : use objective function <n>\n"
126 127 128 129 130 131 132 133
	  " -e <n> : use at most <n> evals (default: %d, 0 to disable)\n"
	  " -t <t> : use at most <t> seconds (default: disabled)\n"
	  " -x <t> : relative tolerance <t> on x (default: disabled)\n"
	  " -X <t> : absolute tolerance <t> on x (default: disabled)\n"
	  " -f <t> : relative tolerance <t> on f (default: disabled)\n"
	  " -F <t> : absolute tolerance <t> on f (default: disabled)\n"
	  " -m <m> : minimize f until <m> is reached (default: disabled)\n"
	  , maxeval);
134 135 136 137 138 139
}

int main(int argc, char **argv)
{
  int c;
  
140
  nlopt_srand_time();
141 142
  testfuncs_verbose = 0;
  
S
whoops  
stevenj 已提交
143 144 145
  if (argc <= 1)
    usage(stdout);
  
146
  while ((c = getopt(argc, argv, "hLvr:a:o:e:t:x:X:f:F:m:")) != -1)
147 148 149 150
    switch (c) {
    case 'h':
      usage(stdout);
      return EXIT_SUCCESS;
151 152 153 154
    case 'L':
      listalgs(stdout);
      listfuncs(stdout);
      return EXIT_SUCCESS;
155 156 157 158
    case 'v':
      testfuncs_verbose = 1;
      break;
    case 'r':
159
      nlopt_srand((unsigned long) atoi(optarg));
160 161 162 163 164
      break;
    case 'a':
      c = atoi(optarg);
      if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) {
	fprintf(stderr, "testopt: invalid algorithm %d\n", c);
165
	listalgs(stderr);
166 167 168 169 170 171 172 173 174 175 176
	return EXIT_FAILURE;
      }
      algorithm = (nlopt_algorithm) c;
      break;
    case 'o':
      if (!test_function(atoi(optarg)))
	return EXIT_FAILURE;
      break;
    case 'e':
      maxeval = atoi(optarg);
      break;
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
    case 't':
      maxtime = atof(optarg);
      break;
    case 'x':
      xtol_rel = atof(optarg);
      break;
    case 'X':
      xtol_abs = atof(optarg);
      break;
    case 'f':
      ftol_rel = atof(optarg);
      break;
    case 'F':
      ftol_abs = atof(optarg);
      break;
    case 'm':
      fmin_max = atof(optarg);
      break;
195 196 197 198 199 200 201 202
    default:
      fprintf(stderr, "harminv: invalid argument -%c\n", c);
      usage(stderr);
      return EXIT_FAILURE;
    }
  
  return EXIT_SUCCESS;
}