Hill Climbing Algorithm

content

One, the problem example

Second, the violent solution

Third, the preferred mountain climbing algorithm

Fourth, the steepest mountain climbing algorithm

Five, different search starting points


One, the problem example

Find f(x,y)=e^{-x^2-y^2}+2e^{-(x-5)^2-(y-5)^2}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.

Guess you like

Origin blog.csdn.net/nameofcsdn/article/details/123146788