testopt.cpp 4.5 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 19 20 21 22
#include "testfuncs.h"

static nlopt_algorithm algorithm = NLOPT_GLOBAL_DIRECT;
static double ftol_rel = 0, ftol_abs = 0, xtol_rel = 0;
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 43
static int test_function(int ifunc)
{
  testfunc func;
  int i;
  double *x, fmin, f0;
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 59 60 61 62 63 64 65 66 67
    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;
  }
  x = (double *) malloc(sizeof(double) * func.n * 2);
  if (!x) { fprintf(stderr, "testopt: Out of memory!\n"); return 0; }

  
  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)
68
    printf(" %g", x[i] = nlopt_urand(func.lb[i], func.ub[i]));
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
  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 已提交
86 87 88 89 90 91
  ret = nlopt_minimize(algorithm,
		       func.n, func.f, func.f_data,
		       func.lb, func.ub,
		       x, &fmin,
		       HUGE_VAL, ftol_rel, ftol_abs, xtol_rel, NULL,
		       maxeval, maxtime);
92
  printf("finished after %g seconds.\n", nlopt_seconds() - start);
S
stevenj 已提交
93 94
  printf("return code %d from nlopt_minimize\n", ret);
  if (ret < 0) {
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
    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"
118
	  "     -L : list available algorithms and objective functions\n"
119 120 121 122 123 124 125 126 127 128 129 130
	  "     -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"
	  " -e <n> : use at most <n> evals (default: %d)\n",
	  maxeval);
}

int main(int argc, char **argv)
{
  int c;
  
131
  nlopt_srand_time();
132 133
  testfuncs_verbose = 0;
  
S
whoops  
stevenj 已提交
134 135 136
  if (argc <= 1)
    usage(stdout);
  
137
  while ((c = getopt(argc, argv, "hLvra:o:e:")) != -1)
138 139 140 141
    switch (c) {
    case 'h':
      usage(stdout);
      return EXIT_SUCCESS;
142 143 144 145
    case 'L':
      listalgs(stdout);
      listfuncs(stdout);
      return EXIT_SUCCESS;
146 147 148 149 150 151 152 153 154 155
    case 'v':
      testfuncs_verbose = 1;
      break;
    case 'r':
      srand((unsigned) atoi(optarg));
      break;
    case 'a':
      c = atoi(optarg);
      if (c < 0 || c >= NLOPT_NUM_ALGORITHMS) {
	fprintf(stderr, "testopt: invalid algorithm %d\n", c);
156
	listalgs(stderr);
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
	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;
    default:
      fprintf(stderr, "harminv: invalid argument -%c\n", c);
      usage(stderr);
      return EXIT_FAILURE;
    }
  
  return EXIT_SUCCESS;
}