public static int ContractByBest(nmsimplex_state_t state, int best, PZMath_vector xc, PZMath_multimin_function f) { /* Function contracts the simplex in respect to best valued corner. That is, all corners besides the best corner are moved. */ /* the xc vector is simply work space here */ PZMath_matrix x1 = state.x1; PZMath_vector y1 = state.y1; int i, j; double newval; for (i = 0; i < x1.RowCount; i++) { if (i != best) { for (j = 0; j < x1.ColumnCount; j++) { newval = 0.5 * (x1[i, j] + x1[best, j]); x1[i, j] = newval; } /* evaluate function in the new point */ x1.CopyRow2(i, xc); newval = f.FN_EVAL(xc); y1[i] = newval; } } return PZMath_errno.PZMath_SUCCESS; }
public int Init(PZMath_multimin_function f, PZMath_vector x, PZMath_vector step_size) { this.f = f; this.x.MemCopyFrom(x); return type.init(state, this.f, this.x, out this.size, step_size); }
public static int Init(object vstate, PZMath_multimin_function f, PZMath_vector x, out double size, PZMath_vector step_size) { int i; double val; PZMath_vector xtemp = (vstate as nmsimplex_state_t).ws1; /* first point is the original x0 */ val = f.FN_EVAL(x); (vstate as nmsimplex_state_t).x1.SetRow(0, x); (vstate as nmsimplex_state_t).y1[0] = val; /* following points are initialized to x0 + step_size */ for (i = 0; i < x.size; i++) { xtemp.MemCopyFrom(x); val = xtemp[i] + step_size[i]; xtemp[i] = val; val = f.FN_EVAL(xtemp); (vstate as nmsimplex_state_t).x1.SetRow(i + 1, xtemp); (vstate as nmsimplex_state_t).y1[i + 1] = val; } /* Initialize simplex size */ size = Size (vstate as nmsimplex_state_t); return PZMath_errno.PZMath_SUCCESS; }
public static double MoveCorner(double coeff, nmsimplex_state_t state, int corner, PZMath_vector xc, PZMath_multimin_function f) { /* moves a simplex corner scaled by coeff (negative value represents mirroring by the middle point of the "other" corner points) and gives new corner in xc and function value at xc as a return value */ PZMath_matrix x1 = state.x1; int i, j; double newval, mp; if (x1.RowCount < 2) { PZMath_errno.ERROR ("nmsimplex::MoveCorner(), simplex cannot have less than two corners!", PZMath_errno.PZMath_FAILURE); } for (j = 0; j < x1.ColumnCount; j++) { mp = 0.0; for (i = 0; i < x1.RowCount; i++) { if (i != corner) { mp += (x1[i, j]); } } mp /= (double) (x1.RowCount - 1); newval = mp - coeff * (mp - x1[corner, j]); xc[j] = newval; } newval = f.FN_EVAL(xc); return newval; }
public static int Iterate(object vstate, PZMath_multimin_function f, PZMath_vector x, out double size, out double fval) { /* Simplex iteration tries to minimize function f value */ /* Includes corrections from Ivo Alxneit <*****@*****.**> */ /* xc and xc2 vectors store tried corner point coordinates */ PZMath_vector xc = (vstate as nmsimplex_state_t).ws1; PZMath_vector xc2 = (vstate as nmsimplex_state_t).ws2; PZMath_vector y1 = (vstate as nmsimplex_state_t).y1; PZMath_matrix x1 = (vstate as nmsimplex_state_t).x1; int n = y1.size; int i; int hi = 0, s_hi = 0, lo = 0; double dhi, ds_hi, dlo; int status; double val, val2; /* get index of highest, second highest and lowest point */ dhi = ds_hi = dlo = y1[0]; for (i = 1; i < n; i++) { val = y1[i]; if (val < dlo) { dlo = val; lo = i; } else if (val > dhi) { ds_hi = dhi; s_hi = hi; dhi = val; hi = i; } else if (val > ds_hi) { ds_hi = val; s_hi = i; } } /* reflect the highest value */ val = MoveCorner (-1.0, vstate as nmsimplex_state_t, hi, xc, f); if (val < y1[lo]) { /* reflected point becomes lowest point, try expansion */ val2 = MoveCorner (-2.0, vstate as nmsimplex_state_t, hi, xc2, f); if (val2 < y1[lo]) { x1.SetRow(hi, xc2); y1[hi] = val2; } else { x1.SetRow(hi, xc); y1[hi] = val; } } /* reflection does not improve things enough */ else if (val > y1[s_hi]) { if (val <= y1[hi]) { /* if trial point is better than highest point, replace highest point */ x1.SetRow(hi, xc); y1[hi] = val; } /* try one dimensional contraction */ val2 = MoveCorner (0.5, vstate as nmsimplex_state_t, hi, xc2, f); if (val2 <= y1[hi]) { x1.SetRow(hi, xc2); y1[hi] = val2; } else { /* contract the whole simplex in respect to the best point */ status = ContractByBest (vstate as nmsimplex_state_t, lo, xc, f); if (status != 0) { PZMath_errno.ERROR("nmsimplex::Iterate(), nmsimplex_contract_by_best failed", PZMath_errno.PZMath_FAILURE); } } } else { /* trial point is better than second highest point. Replace highest point by it */ x1.SetRow(hi, xc); y1[hi] = val; } /* return lowest point of simplex as x */ lo = y1.MinIndex(); x1.CopyRow2(lo, x); fval = y1[lo]; /* Update simplex size */ size = Size (vstate as nmsimplex_state_t); return PZMath_errno.PZMath_SUCCESS; }
public static void TestMultiminNMSimplex() { int np = 2; TestMultiminNMSimplexParms parms = new TestMultiminNMSimplexParms(1.0, 2.0); PZMath_multimin_fminimizer_type T = new PZMath_multimin_fminimizer_type(); T.Init("PZMath_multimin_fminimizer_nmsimplex"); PZMath_multimin_fminimizer s = new PZMath_multimin_fminimizer(); /* Initial vertex size vector */ PZMath_vector ss = new PZMath_vector(np); PZMath_vector x; PZMath_multimin_function minex_func = new PZMath_multimin_function(); int iter = 0, i; int status; double size; /* Set all step sizes to 1 */ ss.SetAll(1.0); /* Starting point */ x = new PZMath_vector(np); x[0] = 5.0; x[1] = 7.0; /* Initialize method and iterate */ minex_func.f = new multimin_function(my_f); minex_func.n = np; minex_func.parms = parms; s.Alloc(T, np); s.Init(minex_func, x, ss); do { iter++; status = s.Iterate(); if (status > 0) break; size = s.Size(); status = s.TestSize (size, 1e-2); if (status == 0) { System.Console.WriteLine ("converged to minimum at"); } System.Console.Write (iter + " "); for (i = 0; i < np; i++) { System.Console.Write (s.x[i] + " "); } System.Console.WriteLine ("f() = " + s.fval + " size = " + size); } while (status == -2 && iter < 100); System.Console.ReadLine(); }