content
Third, the preferred mountain climbing algorithm
Fourth, the steepest mountain climbing algorithm
Five, different search starting points
One, the problem example
Find the maximum value of the function.
We can draw the image with python
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
def func(X, Y, x_move=0, y_move=0):
def mul(X, Y, alis=1):
return alis * np.exp(-(X * X + Y * Y))
return mul(X, Y) + mul(X - x_move, Y - y_move, 2)
def show(X, Y):
fig = plt.figure()
ax = Axes3D(fig)
X, Y = np.meshgrid(X, Y)
Z = func(X, Y, 5, 5)
plt.title("demo_hill_climbing")
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='rainbow', )
ax.set_xlabel('x label', color='r')
ax.set_ylabel('y label', color='g')
ax.set_zlabel('z label', color='b')
plt.show()
if __name__ == '__main__':
X = np.arange(-5, 10, 0.1)
Y = np.arange(-5, 10, 0.1)
show(X,Y)
Second, the violent solution
find the maximum value of an integer-level argument
double f(double x, double y)
{
double a = -x * x - y * y;
double b = -(x - 5)*(x - 5) - (y - 5)*(y - 5);
return exp(a) + 2 * exp(b);
}
int main()
{
double ans = 0;
for (int i = -5; i <= 10; i++)for (int j = -5; j <= 10; j++) {
if (ans < f(i, j)) {
ans = f(i, j);
cout << i << " " << j << " " << ans<<endl;
}
}
cout << ans;
return 0;
}
output:
...omitting the first few lines
-3 0 0.00012341
-2 -2 0.000335463
-2 -1 0.00673795
-2 0 0.0183156
-1 -1 0.135335
-1 0 0.367879
0 0 1
5 5 2
That is, around (5,5) is the first peak, and around (0,0) is the second peak.
Algorithm flaws:
(1) Large amount of calculation and low efficiency
(2) To ask for a more precise value, it is more complicated
Third, the preferred mountain climbing algorithm
The preferred hill-climbing algorithm is to select 4 neighbors at a time, choose the best point from them, and continue until you reach a certain peak.
int dx[] = { 0, 1, -1, 0, 0 };
int dy[] = { 0, 0, 0, 1, -1 };
int main()
{
double x = 1, y = 5, d = 0.1;
while (true)
{
int ansDir = 0;
for (int dire = 1; dire < sizeof(dx) / sizeof(dx[0]); dire++)
{
if (f(x + d * dx[dire], y + d * dy[dire]) > f(x + d * dx[ansDir], y + d * dy[ansDir]))ansDir = dire;
}
x += d * dx[ansDir], y += d * dy[ansDir];
cout << x << " " << y << " " << f(x, y) << endl;
if (ansDir == 0)break;
}
return 0;
}
output:
1.1 5 4.95923e-07
1.2 5 1.07107e-06
1.3 5 2.26746e-06
1.4 5 4.70515e-06
1.5 5 9.57024e-06
1.6 5 1.90803e-05
1.7 5 3.72875e-05
1.8 5 7.14257e-05
1.9 5 0.00013411
2 5 0.00024682
2.1 5 0.00044526
2.2 5 0.000787338
2.3 5 0.00136466
2.4 5 0.00231846
2.5 5 0.00386091
2.6 5 0.00630222
2.7 5 0.0100835
2.8 5 0.0158141
2.9 5 0.0243104
3 5 0.0366313 3.1
5 0.0541037 3.2
3.5 5 0.17811146
5 5 0.281717 3.7 5 0.369039 3.8 5 0.473856 3.9 5 0.596395
4 5 0.735759
4.1 5 0.889716
4.2 5 1.05458
4.3 5 1.22525
4.4 5 1.39535
4.5 5 1.5576
4.6 5 1.70429
4.7 5 1.82786
4.8 5 1.92158
4.9 5 1.9801
5 5 2
5 5 2
Fourth, the steepest mountain climbing algorithm
Each time, not only four neighbors are selected, but all points in one neighborhood are selected each time, and the optimal point is selected from them.
int main()
{
double x = 1, y = 5, d = 0.1;
while (true)
{
int ai = 0, aj = 0;
for (int i = -3; i < 3; i++)for (int j = -3; j < 3; j++)
{
if (f(x + d * i, y + d * j) > f(x + d * ai, y + d * aj))ai = i, aj = j;
}
x += d * ai, y += d * aj;
cout << x << " " << y << " " << f(x, y) << endl;
if (ai == 0 && aj == 0)break;
}
return 0;
}
output:
1.2 5 1.07107e-06
1.4 5 4.70515e-06
1.6 5 1.90803e-05
1.8 5 7.14257e-05
2 5 0.00024682
2.2 5 0.000787338
2.4 5 0.00231846
2.6 5 0.00630222
2.8 5 0.0158141
3 5 0.0366313
3.2 5 0.0783278
3.4 5 0.154609
3.6 5 0.281717
3.8 5 0.473856
4 5 0.735759
4.2 5 1.05458
4.4 5 1.39535
4.6 5 1.70429
4.8 5 1.92158
5 5 2
5 5 2
There are fewer iterations, but more computation per iteration.
Five, different search starting points
If the search starting point is replaced by (1,1):
int main()
{
double x = 1, y = 1, d = 0.1;
while (true)
{
int ansDir = 0;
for (int dire = 1; dire < sizeof(dx) / sizeof(dx[0]); dire++)
{
if (f(x + d * dx[dire], y + d * dy[dire]) > f(x + d * dx[ansDir], y + d * dy[ansDir]))ansDir = dire;
}
x += d * dx[ansDir], y += d * dy[ansDir];
cout << x << " " << y << " " << f(x, y) << endl;
if (ansDir == 0)break;
}
return 0;
}
Output result:
0.9 1 0.163654
0.9 0.9 0.197899
0.8 0.9 0.23457
0.8 0.8 0.278037
0.7 0.8 0.323033
0.7 0.7 0.375311
0.6 0.7 0.427415
0.6 0.6 0.486752
0.5 0.6 0.543351
0.5 0.5 0.606531 0.4
0.5 0.66365 0.4
0.4 0.72614980 0.3
0.216 0.4 0.4 0.951229 0.1 0.1 0.980199 1.38778e-16 0.1 0.99005 1.38778e-16 1.38778e-16 1 1.38778e-16 1.38778e-16 1
The local optimal solution (0,0) obtained is not the global optimal solution, and even the steepest mountain climbing algorithm will reach this point.
To try to avoid this situation, other algorithms are required.