From 98122591877aef28b861e167eb7fd5b60db2239a Mon Sep 17 00:00:00 2001 From: stevenj Date: Sun, 31 Aug 2008 14:11:21 -0400 Subject: [PATCH] added corner optimization test case, average #evaluations darcs-hash:20080831181121-c8de0-84e1ad830abe38d212aca8b8791312d30b105489.gz --- test/testfuncs.c | 25 +++++++++++++- test/testfuncs.h | 2 +- test/testopt.cpp | 89 ++++++++++++++++++++++++++++-------------------- 3 files changed, 77 insertions(+), 39 deletions(-) diff --git a/test/testfuncs.c b/test/testfuncs.c index 09f7d55..272a163 100644 --- a/test/testfuncs.c +++ b/test/testfuncs.c @@ -370,6 +370,26 @@ static const double osc1d_lb[1] = {-5}; static const double osc1d_ub[1] = {5}; static const double osc1d_xmin[1] = {1.23456789}; +/****************************************************************************/ +static double corner4d_f(int n, const double *x, double *grad, void *data) +{ + UNUSED(data); + UNUSED(n); + double u = x[0] + x[1] * x[2] * sin(2 * x[3]); + double v = x[0] + 2*sin(u); + if (grad) { + grad[0] = 2*v * (1 + 2*cos(u)); + grad[1] = 2*v * 2*cos(u) * x[2] * sin(2*x[3]) + 0.1; + grad[2] = 2*v * 2*cos(u) * x[1] * sin(2*x[3]) + 0.1; + grad[3] = 2*v * 2*cos(u) * x[1]*x[2] * cos(2*x[3]) * 2 + 0.1; + } + RETURN(1 + v*v + 0.1*(x[1]+x[2]+x[3])); +} + +static const double corner4d_lb[4] = {0,0,0,0}; +static const double corner4d_ub[4] = {1,1,1,1}; +static const double corner4d_xmin[4] = {0,0,0,0}; + /****************************************************************************/ /****************************************************************************/ @@ -433,5 +453,8 @@ const testfunc testfuncs[NTESTFUNCS] = { -176.541793, "Hansen function" }, { osc1d_f, NULL, 1, 1, osc1d_lb, osc1d_ub, osc1d_xmin, - -1.0, "1d oscillating function with a single minimum" } + -1.0, "1d oscillating function with a single minimum" }, + { corner4d_f, NULL, 1, 4, + corner4d_lb, corner4d_ub, corner4d_xmin, + 1.0, "4d function with minimum at corner" } }; diff --git a/test/testfuncs.h b/test/testfuncs.h index 63ea3da..b20ea88 100644 --- a/test/testfuncs.h +++ b/test/testfuncs.h @@ -18,7 +18,7 @@ typedef struct { const char *name; } testfunc; -#define NTESTFUNCS 20 +#define NTESTFUNCS 21 extern const testfunc testfuncs[NTESTFUNCS]; extern int testfuncs_verbose; diff --git a/test/testopt.cpp b/test/testopt.cpp index a58ca00..71ac50a 100644 --- a/test/testopt.cpp +++ b/test/testopt.cpp @@ -46,6 +46,8 @@ static int test_function(int ifunc) double *x, minf, minf_max, f0, *xtabs, *lb, *ub; nlopt_result ret; double start = nlopt_seconds(); + int total_count = 0; + double total_err = 0, max_err = 0; if (ifunc < 0 || ifunc >= NTESTFUNCS) { fprintf(stderr, "testopt: invalid function %d\n", ifunc); @@ -89,42 +91,43 @@ static int test_function(int ifunc) printf("]\n"); } + for (iter = 0; iter < iterations; ++iter) { + double val; + testfuncs_counter = 0; - printf("Starting guess x = ["); - for (i = 0; i < func.n; ++i) { - if (center_start) - x[i] = (ub[i] + lb[i]) * 0.5; - else if (xinit_tol < 0) { /* random starting point near center of box */ - double dx = (ub[i] - lb[i]) * 0.25; - double xm = 0.5 * (ub[i] + lb[i]); - x[i] = nlopt_urand(xm - dx, xm + dx); - } - else { - x[i] = nlopt_urand(-xinit_tol, xinit_tol) - + (1 + nlopt_urand(-xinit_tol, xinit_tol)) * func.xmin[i]; - if (x[i] > ub[i]) x[i] = ub[i]; - else if (x[i] < lb[i]) x[i] = lb[i]; - } - printf(" %g", x[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"); + printf("Starting guess x = ["); 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)); + if (center_start) + x[i] = (ub[i] + lb[i]) * 0.5; + else if (xinit_tol < 0) { /* random starting point near center of box */ + double dx = (ub[i] - lb[i]) * 0.25; + double xm = 0.5 * (ub[i] + lb[i]); + x[i] = nlopt_urand(xm - dx, xm + dx); + } + else { + x[i] = nlopt_urand(-xinit_tol, xinit_tol) + + (1 + nlopt_urand(-xinit_tol, xinit_tol)) * func.xmin[i]; + if (x[i] > ub[i]) x[i] = ub[i]; + else if (x[i] < lb[i]) x[i] = lb[i]; + } + printf(" %g", x[i]); } - } - - for (iter = 0; iter < iterations; ++iter) { - testfuncs_counter = 0; + printf("]\n"); + f0 = func.f(func.n, x, x + func.n, func.f_data); + printf("Starting function value = %g\n", f0); + + if (iter > 0 && 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)); + } + } + ret = nlopt_minimize(algorithm, func.n, func.f, func.f_data, lb, ub, @@ -139,16 +142,28 @@ static int test_function(int ifunc) } printf("Found minimum f = %g after %d evaluations.\n", minf, testfuncs_counter); + total_count += testfuncs_counter; printf("Minimum at x = ["); for (i = 0; i < func.n; ++i) printf(" %g", x[i]); printf("]\n"); printf("|f - minf| = %g, |f - minf| / |minf| = %e\n", fabs(minf - func.minf), fabs(minf - func.minf) / fabs(func.minf)); + total_err += fabs(minf - func.minf); + if (fabs(minf - func.minf) > max_err) + max_err = fabs(minf - func.minf); + printf("vs. global minimum f = %g at x = [", func.minf); + for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]); + printf("]\n"); + + val = func.f(func.n, x, NULL, func.f_data); + if (val != minf) { + fprintf(stderr, "Mismatch %g between returned minf=%g and f(x) = %g\n", + minf - val, minf, val); + return 0; + } } - printf("vs. global minimum f = %g at x = [", func.minf); - for (i = 0; i < func.n; ++i) printf(" %g", func.xmin[i]); - printf("]\n"); - + printf("average #evaluations = %g\naverage |f-minf| = %g, max |f-minf| = %g\n", total_count * 1.0 / iterations, total_err / iterations, max_err); + free(x); return 1; } -- 2.30.2