C#, Numerical Calculation - Calculation Method and C# Source Program of Minimization Simplex (Downhill) Algorithm Based on Simulated Annealing

1 Simulated annealing

The simulated annealing algorithm is actually an algorithm similar to bionics, which imitates the process of physical annealing.
When we make steel, if we condense rapidly, the state at this time is unstable, the arrangement of atoms is disorderly, and the energy is very high. And if we let the molten steel condense slowly and cool down very slowly, then the state at this time is very stable, and each molecule tends to the position with the lowest energy. The simulated annealing algorithm just uses the principle of the physical annealing process to solve the minimum value of an optimization target (objective function).

The simulated annealing algorithm is derived from the principle of solid annealing. It is a probability-based algorithm. The solid is heated to a sufficiently high temperature and then allowed to cool slowly. When heated, the internal particles of the solid become disordered with the temperature rise, and the internal energy increases. Large, and the particles gradually become orderly when cooling slowly, reaching an equilibrium state at each temperature, and finally reaching the ground state at room temperature, and the internal energy is reduced to the minimum.
 

2 Simulated annealing algorithm

The simulated annealing algorithm (Simulated Annealing, SA) was first proposed by Metropolis et al. in 1953. After Kirkpatrick et al first used the simulated annealing algorithm to solve combinatorial optimization problems in 1983, it was published in Science. It is still widely used until today, this article will introduce the code implementation of C# in detail.
 

3 simplex method

The simplex method is an algorithm for solving linear programming problems. The "simplex" in this name is a concept in algebraic topology.
In practical problems, the variable x is multidimensional, and there are many more constraints than examples. This requires A once-and-for-all algorithm can obtain a positive solution through a computer, and the simplex method is such an algorithm. The simplex method was first proposed by George Dantzig in 1947. The simplex method is of cross-age significance for solving linear programming problems. In fact, it is not only for linear programming, but also relies heavily on simplex in the process of solving nonlinear programming problems. Law, George Dantzig himself is also known as the 'father of linear programming', he is the prototype of the Hollywood movie "Mind Catcher".
 

4 C# source program

using System;

namespace Legalsoft.Truffer
{     /// <summary>     /// Downhill simplex minimization with simulated annealing     /// Downhill simplex minimization with simulated annealing     /// </summary>     public class Amebsa     {         public RealValueFun funk;






        public Ranq1 ran;
        private int mpts { get; set; }
        private int ndim { get; set; }
        private double[] pb { get; set; }
        private double[] y { get; set; }
        private double[,] p { get; set; }
        private double ftol { get; }
        private double yb { get; set; }
        private double tt { get; set; }

        public Amebsa(double[] point, double del, RealValueFun funkk, double ftoll)
        {
            this.funk = funkk;
            this.ran = new Ranq1(1234);
            this.ftol = ftoll;
            this.yb = double.MaxValue;
            this.ndim = point.Length;
            this.pb = new double[ndim];
            this.mpts = ndim + 1;
            this.y = new double[mpts];
            this.p = new double[mpts, ndim];
            for (int i = 0; i < mpts; i++)
            {
                for (int j = 0; j < ndim; j++)
                {
                    p[i, j] = point[j];
                }
                if (i != 0)
                {
                    p[i, i - 1] += del;
                }
            }
            inity();
        }

        public Amebsa(double[] point, double[] dels, RealValueFun funkk, double ftoll)
        {
            this.funk = funkk;
            this.ran = new Ranq1(1234);
            this.ftol = ftoll;
            this.yb = double.MaxValue;
            this.ndim = point.Length;
            this.pb = new double[ndim];
            this.mpts = ndim + 1;
            this.y = new double[mpts];
            this.p = new double[mpts, ndim];
            for (int i = 0; i < mpts; i++)
            {
                for (int j = 0; j < ndim; j++)
                {
                    p[i, j] = point[j];
                }
                if (i != 0)
                {
                    p[i, i - 1] += dels[i - 1];
                }
            }
            inity();
        }

        public Amebsa(double[,] pp, RealValueFun funkk, double ftoll)
        {
            this.funk = funkk;
            this.ran = new Ranq1(1234);
            this.ftol = ftoll;
            this.yb = double.MaxValue;
            this.ndim = pp.GetLength(1);
            this.pb = new double[ndim];
            this.mpts = pp.GetLength(0);
            this.y = new double[mpts];
            this.p = pp;

            inity();
        }

        public void inity()
        {
            double[] x = new double[ndim];
            for (int i = 0; i < mpts; i++)
            {
                for (int j = 0; j < ndim; j++)
                {
                    x[j] = p[i, j];
                }
                y[i] = funk.funk(x);
            }
        }

        public bool anneal(ref int iter, double temperature)
        {             double[] psum = new double[ndim];             tt = -temperature;             get_psum(p, psum);             for (; ; )             {                 int ilo = 0;                 int ihi = 1;                 double ylo = y[0] + tt * Math.Log(ran.double());                 double ynhi = ylo;                 double yhi = y[1] + tt * Math.Log(ran.double());                 if (ylo > yhi)                 {                     ihi = 0;                     ilo = 1;                     ynhi = yhi;                     yhi = ylo;
















                    ylo = ynhi;
                }
                for (int i = 3; i <= mpts; i++)
                {
                    double yt = y[i - 1] + tt * Math.Log(ran.doub());
                    if (yt <= ylo)
                    {
                        ilo = i - 1;
                        ylo = yt;
                    }
                    if (yt > yhi)
                    {
                        ynhi = yhi;
                        ihi = i - 1;
                        yhi = yt;
                    }
                    else if (yt > ynhi)
                    {
                        ynhi = yt;
                    }
                }
                double rtol = 2.0 * Math.Abs(yhi - ylo) / (Math.Abs(yhi) + Math.Abs(ylo));
                if (rtol < ftol || iter < 0)
                {
                    Globals.SWAP(ref y[0], ref y[ilo]);
                    for (int n = 0; n < ndim; n++)
                    {
                        Globals.SWAP(ref p[0, n], ref p[ilo, n]);
                    }
                    if (rtol < ftol)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                route -= 2;
                double ytry = amotsa(p, y, psum, ihi, ref yhi, -1.0);
                if (ytry <= ylo)
                {                     ytry = amotsa(p, y, psum, ihi, ref yhi, 2.0);                 }                 else if (ytry >= ynhi)                 {                     double ysave = yhi;                     ytry = amotsa(p, y, psum, ihi, ref yhi, 0.5);                     if (ytry >= ysave)                     {                         for (int i = 0; i < mpts; i++)                         {










                            if (i != ilo)
                            {                                 for (int j = 0; j < ndim; j++)                                 {                                     psum[j] = 0.5 * (p[i, j] + p[ilo, j]);                                     p[i, j] = psum[j];                                 }                                 y[i] = funk.funk(psum);                             }                         }                         route -= ndim;                         get_psum(p, psum);                     }                 }                 else                 {














                    ++iter;
                }
            }
        }

        public void get_psum(double[,] p, double[] psum)
        {             for (int n = 0; n < ndim; n++)             {                 double sum = 0.0;                 for (int m = 0; m < mpts; m++)                 {                     sum += p[m, n];                 }                 psum[n] = sum;             }         }









        public double amotsa(double[,] p, double[] y, double[] psum, int ihi, ref double yhi, double fac)
        {
            double[] ptry = new double[ndim];
            double fac1 = (1.0 - fac) / ndim;
            double fac2 = fac1 - fac;
            for (int j = 0; j < ndim; j++)
            {
                ptry[j] = psum[j] * fac1 - p[ihi, j] * fac2;
            }
            double ytry = funk.funk(ptry);
            if (ytry <= yb)
            {
                for (int j = 0; j < ndim; j++)
                {
                    pb[j] = ptry[j];
                }
                yb = ytry;
            }
            double yflu = ytry -- tt * Math.Log(ran.doub());
            if ( yflu < yhi )
            {                 y [ yhi ] = ytry ;                 yhi = yflu;                 for (int j = 0; j < free; j++)                 {                     psum[j] += ptry[j] - p[ihi, j];                     p [ two , j ] = ptry [ j ] ;                 }             }             return yflu ;         }     } }












 

Guess you like

Origin blog.csdn.net/beijinghorn/article/details/132128352