testopt.cpp 4.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
#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
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif
#endif

#include "nlopt.h"
#include "testfuncs.h"

static double urand(double a, double b)
{
  return a + (rand() * (b - a) / RAND_MAX);
}

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;

static int test_function(int ifunc)
{
  testfunc func;
  int i;
  double *x, fmin, f0;
S
stevenj 已提交
42
  nlopt_result ret;
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
  
  if (ifunc < 0 || ifunc >= NTESTFUNCS) {
    fprintf(stderr, "testopt: invalid function %d\n", ifunc);
    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)
    printf(" %g", x[i] = urand(func.lb[i], func.ub[i]));
  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 已提交
82 83 84 85 86 87 88 89
  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);
  printf("return code %d from nlopt_minimize\n", ret);
  if (ret < 0) {
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
    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"
	  "     -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;
  
  srand((unsigned) time(NULL));
  testfuncs_verbose = 0;
  
  while ((c = getopt(argc, argv, "hvra:o:e:")) != -1)
    switch (c) {
    case 'h':
      usage(stdout);
      return EXIT_SUCCESS;
    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);
	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;
}