8 int mma_verbose = 0; /* > 0 for verbose output */
10 #define MIN(a,b) ((a) < (b) ? (a) : (b))
11 #define MAX(a,b) ((a) > (b) ? (a) : (b))
13 /* magic minimum value for rho in MMA ... the 2002 paper says it should
14 be a "fixed, strictly positive `small' number, e.g. 1e-5"
15 ... grrr, I hate these magic numbers, which seem like they
16 should depend on the objective function in some way */
17 #define MMA_RHOMIN 1e-5
19 nlopt_result mma_minimize(int n, nlopt_func f, void *f_data,
20 const double *lb, const double *ub, /* bounds */
21 double *x, /* in: initial guess, out: minimizer */
25 nlopt_result ret = NLOPT_SUCCESS;
26 double *xcur, rho, *sigma, *dfdx, *dfdx_cur, *xprev, *xprevprev, fcur;
29 sigma = (double *) malloc(sizeof(double) * 6*n);
30 if (!sigma) return NLOPT_OUT_OF_MEMORY;
35 xprevprev = xprev + n;
36 for (j = 0; j < n; ++j)
37 sigma[j] = 0.5 * (ub[j] - lb[j]);
40 fcur = *minf = f(n, x, dfdx, f_data);
41 memcpy(xcur, x, sizeof(double) * n);
43 while (1) { /* outer iterations */
45 if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED;
46 else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED;
47 else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED;
48 if (ret != NLOPT_SUCCESS) goto done;
49 if (++k > 1) memcpy(xprevprev, xprev, sizeof(double) * n);
50 memcpy(xprev, xcur, sizeof(double) * n);
52 while (1) { /* inner iterations */
53 double gcur = *minf, w = 0;
54 for (j = 0; j < n; ++j) {
55 /* because we have no constraint functions, minimizing
56 the MMA approximate function can be done analytically */
57 double dx = -sigma[j]*sigma[j]*dfdx[j]
58 / (2*sigma[j]*fabs(dfdx[j]) + rho);
60 if (xcur[j] > x[j] + 0.9*sigma[j])
61 xcur[j] = x[j] + 0.9*sigma[j];
62 else if (xcur[j] < x[j] - 0.9*sigma[j])
63 xcur[j] = x[j] - 0.9*sigma[j];
64 if (xcur[j] > ub[j]) xcur[j] = ub[j];
65 else if (xcur[j] < lb[j]) xcur[j] = lb[j];
67 gcur += (sigma[j]*sigma[j]*dfdx[j]*dx
68 + sigma[j]*fabs(dfdx[j])*dx*dx
69 + 0.5*rho*dx*dx) / (sigma[j]*sigma[j]-dx*dx);
70 w += 0.5*rho*dx*dx / (sigma[j]*sigma[j]-dx*dx);
73 fcur = f(n, xcur, dfdx_cur, f_data);
77 memcpy(x, xcur, sizeof(double)*n);
78 memcpy(dfdx, dfdx_cur, sizeof(double)*n);
80 if (nlopt_stop_evals(stop)) ret = NLOPT_MAXEVAL_REACHED;
81 else if (nlopt_stop_time(stop)) ret = NLOPT_MAXTIME_REACHED;
82 else if (*minf < stop->minf_max) ret = NLOPT_MINF_MAX_REACHED;
83 if (ret != NLOPT_SUCCESS) goto done;
85 if (gcur >= fcur) break;
86 rho = MIN(10*rho, 1.1 * (rho + (fcur - gcur) / w));
88 printf("MMA inner iteration: rho -> %g\n", rho);
91 if (nlopt_stop_ftol(stop, fcur, fprev))
92 ret = NLOPT_FTOL_REACHED;
93 if (nlopt_stop_x(stop, xcur, xprev))
94 ret = NLOPT_XTOL_REACHED;
95 if (ret != NLOPT_SUCCESS) goto done;
97 /* update rho and sigma for iteration k+1 */
98 rho = MAX(0.1 * rho, MMA_RHOMIN);
100 printf("MMA outer iteration: rho -> %g\n", rho);
102 for (j = 0; j < n; ++j) {
103 double dx2 = (xcur[j]-xprev[j]) * (xprev[j]-xprevprev[j]);
104 double gam = dx2 < 0 ? 0.7 : (dx2 > 0 ? 1.2 : 1);
106 sigma[j] = MIN(sigma[j], 10*(ub[j]-lb[j]));
107 sigma[j] = MAX(sigma[j], 0.01*(ub[j]-lb[j]));