From: stevenj Date: Wed, 18 Nov 2009 05:52:59 +0000 (-0500) Subject: added ISRES (compiles, but untested) X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=14e9e23d1811854ff312a4c26f14fbdf4731d821;p=nlopt.git added ISRES (compiles, but untested) darcs-hash:20091118055259-c8de0-1b704e09a6a759e72345cdd1833c9756e3880663.gz --- diff --git a/Makefile.am b/Makefile.am index f1d1e6f..6e67693 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,7 @@ CXX_DIRS = stogo CXX_LIBS = stogo/libstogo.la endif -SUBDIRS = util direct cdirect $(CXX_DIRS) praxis luksan crs mlsl mma cobyla newuoa lbfgs neldermead auglag bobyqa api . octave test +SUBDIRS = util direct cdirect $(CXX_DIRS) praxis luksan crs mlsl mma cobyla newuoa lbfgs neldermead auglag bobyqa isres api . octave test EXTRA_DIST = autogen.sh nlopt.pc.in m4 if WITH_NOCEDAL @@ -16,10 +16,12 @@ NOCEDAL_LBFGS=lbfgs/liblbfgs.la endif libnlopt@NLOPT_SUFFIX@_la_SOURCES = -libnlopt@NLOPT_SUFFIX@_la_LIBADD = \ -direct/libdirect.la cdirect/libcdirect.la $(CXX_LIBS) \ -praxis/libpraxis.la $(NOCEDAL_LBFGS) luksan/libluksan.la crs/libcrs.la \ -mlsl/libmlsl.la mma/libmma.la cobyla/libcobyla.la newuoa/libnewuoa.la neldermead/libneldermead.la auglag/libauglag.la bobyqa/libbobyqa.la api/libapi.la util/libutil.la +libnlopt@NLOPT_SUFFIX@_la_LIBADD = direct/libdirect.la \ +cdirect/libcdirect.la $(CXX_LIBS) praxis/libpraxis.la $(NOCEDAL_LBFGS) \ +luksan/libluksan.la crs/libcrs.la mlsl/libmlsl.la mma/libmma.la \ +cobyla/libcobyla.la newuoa/libnewuoa.la neldermead/libneldermead.la \ +auglag/libauglag.la bobyqa/libbobyqa.la isres/libisres.la \ +api/libapi.la util/libutil.la libnlopt@NLOPT_SUFFIX@_la_LDFLAGS = -no-undefined -version-info @SHARED_VERSION_INFO@ diff --git a/api/Makefile.am b/api/Makefile.am index 0683def..3e2f5ce 100644 --- a/api/Makefile.am +++ b/api/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = -I$(top_srcdir)/cdirect -I$(top_srcdir)/direct -I$(top_srcdir)/stogo -I$(top_srcdir)/praxis -I$(top_srcdir)/lbfgs -I$(top_srcdir)/luksan -I$(top_srcdir)/crs -I$(top_srcdir)/mlsl -I$(top_srcdir)/mma -I$(top_srcdir)/cobyla -I$(top_srcdir)/newuoa -I$(top_srcdir)/neldermead -I$(top_srcdir)/auglag -I$(top_srcdir)/bobyqa -I$(top_srcdir)/util +AM_CPPFLAGS = -I$(top_srcdir)/cdirect -I$(top_srcdir)/direct -I$(top_srcdir)/stogo -I$(top_srcdir)/praxis -I$(top_srcdir)/lbfgs -I$(top_srcdir)/luksan -I$(top_srcdir)/crs -I$(top_srcdir)/mlsl -I$(top_srcdir)/mma -I$(top_srcdir)/cobyla -I$(top_srcdir)/newuoa -I$(top_srcdir)/neldermead -I$(top_srcdir)/auglag -I$(top_srcdir)/bobyqa -I$(top_srcdir)/isres -I$(top_srcdir)/util include_HEADERS = nlopt.h nlopt.f noinst_LTLIBRARIES = libapi.la diff --git a/api/nlopt.c b/api/nlopt.c index 7a621aa..7255455 100644 --- a/api/nlopt.c +++ b/api/nlopt.c @@ -101,6 +101,7 @@ static const char nlopt_algorithm_names[NLOPT_NUM_ALGORITHMS][256] = { "Augmented Lagrangian method for equality constraints (local, no-derivative)", "Augmented Lagrangian method for equality constraints (local, derivative)", "BOBYQA bound-constrained optimization via quadratic models (local, no-derivative)", + "ISRES evolutionary constrained optimization (global, no-derivative)", }; const char *nlopt_algorithm_name(nlopt_algorithm a) @@ -224,6 +225,7 @@ static double f_direct(int n, const double *x, int *undefined, void *data_) #include "neldermead.h" #include "auglag.h" #include "bobyqa.h" +#include "isres.h" #define AUGLAG_ALG(a) ((a) == NLOPT_LN_AUGLAG || \ (a) == NLOPT_LN_AUGLAG_EQ || \ @@ -295,11 +297,11 @@ static nlopt_result nlopt_minimize_( /* nonlinear constraints are only supported with some algorithms */ if (m != 0 && algorithm != NLOPT_LD_MMA && algorithm != NLOPT_LN_COBYLA - && !AUGLAG_ALG(algorithm)) + && !AUGLAG_ALG(algorithm) && algorithm != NLOPT_GN_ISRES) return NLOPT_INVALID_ARGS; /* nonlinear equality constraints (h(x) = 0) only via some algorithms */ - if (p != 0 && !AUGLAG_ALG(algorithm)) + if (p != 0 && !AUGLAG_ALG(algorithm) && algorithm != NLOPT_GN_ISRES) return NLOPT_INVALID_ARGS; d.f = f; @@ -552,6 +554,13 @@ static nlopt_result nlopt_minimize_( local_search_alg_deriv, algorithm == NLOPT_LD_AUGLAG_EQ); + case NLOPT_GN_ISRES: + return isres_minimize(n, f, f_data, + m, fc, fc_data, fc_datum_size, + p, h, h_data, h_datum_size, + lb, ub, x, minf, &stop, + 0); + default: return NLOPT_INVALID_ARGS; } diff --git a/api/nlopt.h b/api/nlopt.h index e434941..2e2d38d 100644 --- a/api/nlopt.h +++ b/api/nlopt.h @@ -109,6 +109,8 @@ typedef enum { NLOPT_LN_BOBYQA, + NLOPT_GN_ISRES, + NLOPT_NUM_ALGORITHMS /* not an algorithm, just the number of them */ } nlopt_algorithm; diff --git a/configure.ac b/configure.ac index 6b7fca3..8aea692 100644 --- a/configure.ac +++ b/configure.ac @@ -319,6 +319,7 @@ AC_CONFIG_FILES([ neldermead/Makefile auglag/Makefile bobyqa/Makefile + isres/Makefile test/Makefile ]) diff --git a/isres/Makefile.am b/isres/Makefile.am new file mode 100644 index 0000000..d819248 --- /dev/null +++ b/isres/Makefile.am @@ -0,0 +1,6 @@ +AM_CPPFLAGS = -I$(top_srcdir)/util -I$(top_srcdir)/api + +noinst_LTLIBRARIES = libisres.la +libisres_la_SOURCES = isres.c isres.h + +EXTRA_DIST = README diff --git a/isres/README b/isres/README new file mode 100644 index 0000000..c396213 --- /dev/null +++ b/isres/README @@ -0,0 +1,23 @@ +This is my implementation of the "Improved Stochastic Ranking +Evolution Strategy" (ISRES) algorithm for nonlinearly-constrained +global optimization, based on the method described in: + + Thomas Philip Runarsson and Xin Yao, "Search biases in constrained + evolutionary optimization," IEEE Trans. on Systems, Man, and Cybernetics + Part C: Applications and Reviews, vol. 35 (no. 2), pp. 233-243 (2005). + +It is a refinement of an earlier method described in: + + Thomas P. Runarsson and Xin Yao, "Stochastic ranking for constrained + evolutionary optimization," IEEE Trans. Evolutionary Computation, + vol. 4 (no. 3), pp. 284-294 (2000). + +This is an independent implementation by S. G. Johnson (2009) based +on the papers above. Runarsson also has his own Matlab implemention +available from his web page: http://www3.hi.is/~tpr + +It is under the same MIT license as the rest of my code in NLopt (see +../COPYRIGHT). + +Steven G. Johnson +November 2009 diff --git a/isres/isres.c b/isres/isres.c new file mode 100644 index 0000000..e6bf7aa --- /dev/null +++ b/isres/isres.c @@ -0,0 +1,246 @@ +/* Copyright (c) 2009 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "isres.h" + +/* Improved Stochastic Ranking Evolution Strategy (ISRES) algorithm + for nonlinearly-constrained global optimization, based on + the method described in: + + Thomas Philip Runarsson and Xin Yao, "Search biases in constrained + evolutionary optimization," IEEE Trans. on Systems, Man, and Cybernetics + Part C: Applications and Reviews, vol. 35 (no. 2), pp. 233-243 (2005). + + It is a refinement of an earlier method described in: + + Thomas P. Runarsson and Xin Yao, "Stochastic ranking for constrained + evolutionary optimization," IEEE Trans. Evolutionary Computation, + vol. 4 (no. 3), pp. 284-294 (2000). + + This is an independent implementation by S. G. Johnson (2009) based + on the papers above. Runarsson also has his own Matlab implemention + available from his web page: http://www3.hi.is/~tpr +*/ + +static int key_compare(void *keys_, const void *a_, const void *b_) +{ + const double *keys = (const double *) keys_; + const int *a = (const int *) a_; + const int *b = (const int *) b_; + return keys[*a] < keys[*b] ? -1 : (keys[*a] > keys[*b] ? +1 : 0); +} + +nlopt_result isres_minimize(int n, nlopt_func f, void *f_data, + int m, nlopt_func fc, /* fc <= 0 constraints */ + void *fc_data_, ptrdiff_t fc_datum_size, + int p, nlopt_func h, /* h == 0 constraints */ + void *h_data_, ptrdiff_t h_datum_size, + const double *lb, const double *ub, /* bounds */ + double *x, /* in: initial guess, out: minimizer */ + double *minf, + nlopt_stopping *stop, + int population) /* pop. size (= 0 for default) */ +{ + const double ALPHA = 0.2; /* smoothing factor from paper */ + const double GAMMA = 0.85; /* step-reduction factor from paper */ + const double PHI = 1.0; /* expected rate of convergence, from paper */ + const double PF = 0.45; /* fitness probability, from paper */ + const double SURVIVOR = 1.0/7.0; /* survivor fraction, from paper */ + int survivors; + nlopt_result ret = NLOPT_SUCCESS; + char *fc_data = (char *) fc_data_; + char *h_data = (char *) h_data_; + double *sigmas = 0, *xs; /* population-by-n arrays (row-major) */ + double *fval; /* population array of function vals */ + double *penalty; /* population array of penalty vals */ + double *x0; + int *irank = 0; + int k, i, j, c; + int mp = m + p; + double minf_penalty = HUGE_VAL; + double taup, tau; + + if (!population) population = 20 * (n + 1); + if (population < 1) return NLOPT_INVALID_ARGS; + survivors = ceil(population * SURVIVOR); + + taup = PHI / sqrt(2*n); + tau = PHI / sqrt(2*sqrt(n)); + + /* we don't handle unbounded search regions */ + for (j = 0; j < n; ++j) if (nlopt_isinf(lb[j]) || nlopt_isinf(ub[j])) + return NLOPT_INVALID_ARGS; + + sigmas = (double*) malloc(sizeof(double) * (population*n*2 + + population + + population + + n)); + if (!sigmas) return NLOPT_OUT_OF_MEMORY; + xs = sigmas + population*n; + fval = xs + population*n; + penalty = fval + population; + x0 = penalty + population; + + irank = (int*) malloc(sizeof(int) * population); + if (!irank) { ret = NLOPT_OUT_OF_MEMORY; goto done; } + + for (k = 0; k < population; ++k) { + for (j = 0; j < n; ++j) { + sigmas[k*n+j] = (ub[j] - lb[j]) / sqrt(n); + xs[k*n+j] = nlopt_urand(lb[j], ub[j]); + } + } + memcpy(xs, x, sizeof(double) * n); /* use input x for xs_0 */ + + while (1) { /* each loop body = one generation */ + int all_feasible = 1; + + /* evaluate f and constraint violations for whole population */ + for (k = 0; k < population; ++k) { + double gval; + stop->nevals++; + fval[k] = f(n, xs + k*n, NULL, f_data); + penalty[k] = 0; + for (c = 0; c < m; ++c) { /* inequality constraints */ + gval = fc(n, xs + k*n, NULL, + fc_data + c * fc_datum_size); + if (gval < 0) gval = 0; + penalty[k] += gval*gval; + } + for (c = m; c < mp; ++c) { /* equality constraints */ + gval = h(n, xs + k*n, NULL, + h_data + (c-m) * h_datum_size); + penalty[k] += gval*gval; + } + if (penalty[k] > 0) all_feasible = 0; + + /* convergence criteria (FIXME: improve?) */ + + if (penalty[k] <= minf_penalty && fval[k] <= *minf + && (penalty[k] != minf_penalty || fval[k] != *minf)) { + if (fval[k] < stop->minf_max && penalty[k] == 0) + ret = NLOPT_MINF_MAX_REACHED; + else if (nlopt_stop_f(stop, fval[k], *minf) + && nlopt_stop_f(stop, penalty[k], minf_penalty)) + ret = NLOPT_FTOL_REACHED; + else if (nlopt_stop_x(stop, xs+k*n, x)) + ret = NLOPT_XTOL_REACHED; + memcpy(x, xs+k*n, sizeof(double)*n); + *minf = fval[k]; + minf_penalty = penalty[k]; + if (ret != NLOPT_SUCCESS) goto done; + } + + if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED; + else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED; + if (ret != NLOPT_SUCCESS) goto done; + } + + /* "selection" step: rank the population */ + for (k = 0; k < population; ++k) irank[k] = k; + if (all_feasible) /* special case: rank by objective function */ + nlopt_qsort_r(irank, population, sizeof(int), fval,key_compare); + else { + /* Runarsson & Yao's stochastic ranking of the population */ + for (i = 0; i < population; ++i) { + int swapped = 0; + for (j = 0; j < population-1; ++j) { + double u = nlopt_urand(0,1); + if (u < PF || (penalty[irank[j]] == 0 + && penalty[irank[j+1]] == 0)) { + if (fval[irank[j]] > fval[irank[j+1]]) { + int irankj = irank[j]; + irank[j] = irank[j+1]; + irank[j+1] = irankj; + swapped = 1; + } + } + else if (penalty[irank[j]] > penalty[irank[j+1]]) { + int irankj = irank[j]; + irank[j] = irank[j+1]; + irank[j+1] = irankj; + swapped = 1; + } + } + if (!swapped) break; + } + } + + /* evolve the population: + differential evolution for the best survivors, + and standard mutation of the best survivors for the rest: */ + for (k = survivors; k < population; ++k) { /* standard mutation */ + double taup_rand = taup * nlopt_nrand(0,1); + int rk = irank[k], ri; + i = k % survivors; + ri = irank[i]; + for (j = 0; j < n; ++j) { + double sigmamax = (ub[j] - lb[j]) / sqrt(n); + sigmas[rk*n+j] = sigmas[ri*n+j] + * exp(taup_rand + tau*nlopt_nrand(0,1)); + if (sigmas[rk*n+j] > sigmamax) + sigmas[rk*n+j] = sigmamax; + do { + xs[rk*n+j] = xs[ri*n+j] + + sigmas[rk*n+j] * nlopt_nrand(0,1); + } while (xs[rk*n+j] < lb[j] || xs[rk*n+j] > ub[j]); + sigmas[rk*n+j] = sigmas[ri*n+j] + ALPHA*(sigmas[rk*n+j] + - sigmas[ri*n+j]); + } + } + memcpy(x0, xs, n * sizeof(double)); + for (k = 0; k+1 < survivors; ++k) { /* differential variation */ + int rk = irank[k]; + for (j = 0; j < n; ++j) + xs[rk*n+j] += GAMMA * (x0[j] - xs[(k+1)*n+j]); + } + /* standard mutation for last survivor and for any + survivor components that are now outside the bounds */ + for (k = 0; k < survivors; ++k) { + double taup_rand = taup * nlopt_nrand(0,1); + int rk = irank[k]; + for (j = 0; j < n; ++j) if (k == survivors - 1 + || xs[rk*n+j] < lb[j] + || xs[rk*n+j] > ub[j]) { + double sigmamax = (ub[j] - lb[j]) / sqrt(n); + double xi = xs[rk*n+j]; + double sigi = sigmas[rk*n+j]; + sigmas[rk*n+j] *= exp(taup_rand + tau*nlopt_nrand(0,1)); + if (sigmas[rk*n+j] > sigmamax) + sigmas[rk*n+j] = sigmamax; + do { + xs[rk*n+j] = xi + sigmas[rk*n+j] * nlopt_nrand(0,1); + } while (xs[rk*n+j] < lb[j] || xs[rk*n+j] > ub[j]); + sigmas[rk*n+j] = sigi + ALPHA * (sigmas[rk*n+j] - sigi); + } + } + } + +done: + if (irank) free(irank); + if (sigmas) free(sigmas); + return ret; +} diff --git a/isres/isres.h b/isres/isres.h new file mode 100644 index 0000000..bd506fa --- /dev/null +++ b/isres/isres.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2007-2008 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ISRES_H +#define ISRES_H + +#include "nlopt.h" +#include "nlopt-util.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +nlopt_result isres_minimize(int n, nlopt_func f, void *f_data, + int m, nlopt_func fc, /* fc <= 0 constraints */ + void *fc_data_, ptrdiff_t fc_datum_size, + int p, nlopt_func h, /* h == 0 constraints */ + void *h_data_, ptrdiff_t h_datum_size, + const double *lb, const double *ub, /* bounds */ + double *x, /* in: initial guess, out: minimizer */ + double *minf, + nlopt_stopping *stop, + int population); /* init. population */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif + diff --git a/util/mt19937ar.c b/util/mt19937ar.c index 2e82376..5485129 100644 --- a/util/mt19937ar.c +++ b/util/mt19937ar.c @@ -10,7 +10,8 @@ Modified 2007 by Steven G. Johnson for use with NLopt (to avoid namespace pollution, use uint32_t instead of unsigned long, - and add the urand function). + and add the urand function). Modified 2009 to add normal-distributed + random numbers. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,15 +30,16 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. Any feedback is very welcome. @@ -206,6 +208,26 @@ int nlopt_iurand(int n) return(nlopt_genrand_int32() % n); } +/* normal-distributed random numbers with the given mean and std. deviation, + added by SGJ */ +double nlopt_nrand(double mean, double stddev) +{ + // Box-Muller algorithm to generate Gaussian from uniform + // see Knuth vol II algorithm P, sec. 3.4.1 + double v1, v2, s; + do { + v1 = nlopt_urand(-1, 1); + v2 = nlopt_urand(-1, 1); + s = v1*v1 + v2*v2; + } while (s >= 1.0); + if (s == 0) { + return mean; + } + else { + return mean + v1 * sqrt(-2 * log(s) / s) * stddev; + } +} + #if 0 #include int main(void) diff --git a/util/nlopt-util.h b/util/nlopt-util.h index 7a1875b..861914d 100644 --- a/util/nlopt-util.h +++ b/util/nlopt-util.h @@ -52,6 +52,7 @@ extern unsigned long nlopt_time_seed(void); extern void nlopt_init_genrand(unsigned long s); extern double nlopt_urand(double a, double b); extern int nlopt_iurand(int n); +extern double nlopt_nrand(double mean, double stddev); /* Sobol' low-discrepancy-sequence generation */ typedef struct nlopt_soboldata_s *nlopt_sobol;