7 #define MIN(a,b) ((a) < (b) ? (a) : (b))
8 #define MAX(a,b) ((a) > (b) ? (a) : (b))
10 /* magic minimum value for rho in MMA ... the 2002 paper says it should
11 be a "fixed, strictly positive `small' number, e.g. 1e-5"
12 ... grrr, I hate these magic numbers, which seem like they
13 should depend on the objective function in some way */
14 #define MMA_RHOMIN 1e-5
16 nlopt_result mma_minimize(int n, nlopt_func f, void *f_data,
17 const double *lb, const double *ub, /* bounds */
18 double *x, /* in: initial guess, out: minimizer */
22 nlopt_result ret = NLOPT_SUCCESS;
23 double *xcur, rho, *sigma, *dfdx, *dfdx_cur, *xprev, *xprevprev, fcur;
26 sigma = (double *) malloc(sizeof(double) * 6*n);
27 if (!sigma) return NLOPT_OUT_OF_MEMORY;
32 xprevprev = xprev + n;
33 for (j = 0; j < n; ++j)
34 sigma[j] = 0.5 * (ub[j] - lb[j]);
37 fcur = *minf = f(n, x, dfdx, f_data);
38 memcpy(xcur, x, sizeof(double) * n);
40 while (1) { /* outer iterations */
42 if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED;
43 else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED;
44 else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED;
45 if (ret != NLOPT_SUCCESS) goto done;
46 if (++k > 1) memcpy(xprevprev, xprev, sizeof(double) * n);
47 memcpy(xprev, xcur, sizeof(double) * n);
49 while (1) { /* inner iterations */
50 double gcur = *minf, w = 0;
51 for (j = 0; j < n; ++j) {
52 /* because we have no constraint functions, minimizing
53 the MMA approximate function can be done analytically */
54 double dx = -sigma[j]*sigma[j]*dfdx[j]
55 / (2*sigma[j]*fabs(dfdx[j]) + rho);
57 if (xcur[j] > x[j] + 0.9*sigma[j])
58 xcur[j] = x[j] + 0.9*sigma[j];
59 else if (xcur[j] < x[j] - 0.9*sigma[j])
60 xcur[j] = x[j] - 0.9*sigma[j];
61 if (xcur[j] > ub[j]) xcur[j] = ub[j];
62 else if (xcur[j] < lb[j]) xcur[j] = lb[j];
64 gcur += (sigma[j]*sigma[j]*dfdx[j]*dx
65 + sigma[j]*fabs(dfdx[j])*dx*dx
66 + 0.5*rho*dx*dx) / (sigma[j]*sigma[j]-dx*dx);
67 w += 0.5*rho*dx*dx / (sigma[j]*sigma[j]-dx*dx);
70 fcur = f(n, xcur, dfdx_cur, f_data);
74 memcpy(x, xcur, sizeof(double)*n);
75 memcpy(dfdx, dfdx_cur, sizeof(double)*n);
77 if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED;
78 else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED;
79 else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED;
80 if (ret != NLOPT_SUCCESS) goto done;
82 if (gcur >= fcur) break;
83 rho = MIN(10*rho, 1.1 * (rho + (fcur - gcur) / w));
86 if (nlopt_stop_ftol(stop, fcur, fprev))
87 ret = NLOPT_FTOL_REACHED;
88 if (nlopt_stop_x(stop, xcur, xprev))
89 ret = NLOPT_XTOL_REACHED;
90 if (ret != NLOPT_SUCCESS) goto done;
92 /* update rho and sigma for iteration k+1 */
93 rho = MAX(0.1 * rho, MMA_RHOMIN);
95 for (j = 0; j < n; ++j) {
96 double dx2 = (xcur[j]-xprev[j]) * (xprev[j]-xprevprev[j]);
97 double gam = dx2 < 0 ? 0.7 : (dx2 > 0 ? 1.2 : 1);
99 sigma[j] = MIN(sigma[j], 10*(ub[j]-lb[j]));
100 sigma[j] = MAX(sigma[j], 0.01*(ub[j]-lb[j]));