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;
        }
예제 #6
0
        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();
        }