Simulated Annealing Minimization: Single variable polynomial C++ source code.

Finding the minimum of x^2-9x+20 through simulated annealing:
This is a very simple example problem. Most people that are interested in simulated annealing probably could figure out the answer without even a pen and paper, so this is just to explore the method.

This process is a simulation of cooling metal to settle the structure to a stable formation. In this case we are settling a point into what is hopefully a global minimum of a polynomial.

The general idea:

  1. Start with a random x value and find that point on the graph.
  2. Test a random point just to the right or left of that point.
    • New point has a lower value: (possibly closer to a minimum)
      • Accept and save it.
    • Value is higher:
      • There is a chance for it to be accepted based on the current simulated temperature. The higher the temperature, the higher the chance it will be accepted.
        (This chance allows for the saved point to get out of local minimums and makes the global minimum have the highest chance of containing the point)
  3. Repeat from 2 until the simulated temperature is blow some preset threshold.
    (typically a very large number of iterations.)
  4. Output the current point and the value at that point.

Read more to see the code.

Note:
To find the minimum of another single variable function, just change the content of the function at the top, E(x).

For functions with more variables, you’ll have to add the new variables to the code as well as adjust them every iteration. For each new variable you will have to add a new line similar to “double xNew = x + ((rand()/(double)RAND_MAX)*2 – 1);” and save the new values in new variables named something like x2New.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <random>
#include <time.h>
 
using namespace std;
 
double E( double x)
{
     return x * x - 9 * x + 20;
}
 
int main()
{
     srand ( time (NULL));
 
     const double e = 2.718281828;
     const double lambda = 0.7;
 
     double x = ( rand ()/( double )RAND_MAX)*100;
     cout << "Initial x == " << x << endl;
 
     double L = E(x);
 
     for ( double T = 100; T > 0.00005; T *= lambda)
     {
         for ( int i=0;i<200; i++)
         {
             double xNew = x + (( rand ()/( double )RAND_MAX)*2 - 1);
             double LNew = E(xNew);
 
             if (LNew < L || ( rand ()/( double )RAND_MAX) <= pow (e,-(LNew-L)/T))
             {
                 L = LNew;
                 x = xNew;
             }
         }
     }
 
     cout << "x == " << x << ", E(x) == " << E(x) << endl;
 
     return 0;
}
 
// Output:
//Initial x == 70.4794
//x == 4.49043, E(x) == -0.249908

Of course the exact solution is:
E(x) = x^2 – 9x + 20
E’(x) = 2x – 9 = 0
=> 2x = 9
=> x = 4.5

E(4.5) = (4.5)^2-9(4.5)+20
= 20.25 – 40.5 + 20
= -0.25

That program’s result is pretty close to the exact answer, not bad for a glorified guess and check.

This code is an adaption of code I found here. It solves a two variable problem, but the approach is the same.

你可能感兴趣的:(Simulated Annealing Minimization: Single variable polynomial C++ source code.)