# -*- coding: utf-8 -*-
# author: 'boliang'
# date: 2018/4/15 21:49
import math
import matplotlib.pyplot as plt
import numpy as np
class Solution_golds(object):
def __init__(self, fun=None, a=0, b=0, epsilon=1e-5, deta=1e-4):
if fun == None:
return
self.reset(fun, a, b, epsilon, deta)
def reset(self, fun, a=0, b=0, epsilon=1e-5, deta=1e-4):
self.__fun_str = fun
self.__fun = lambda x: eval(fun)
self.__t = (math.sqrt(5) - 1) / 2
if a == 0 and b == 0:
a, b = self.__get_section(0, 0.5)
self.__p = a + (1 - self.__t) * (b - a)
self.__q = a + self.__t * (b - a)
self.__epsilon = epsilon
self.__deta = deta
self.__a = a
self.__b = b
self.__pCal = self.__fun(self.__p)
self.__qCal = self.__fun(self.__q)
# 进退法, 获得极小值点的搜索区间
def __get_section(self, alpha, h):
ak = alpha
k = 0
cal_k = self.__fun(ak)
while True:
akp = ak + h
cal_kp = self.__fun(akp)
if cal_kp < cal_k:
h = 2 * h
alpha = ak
ak = akp
cal_k = cal_kp
k += 1
else:
if k == 0:
# 反向搜索
h = -h
alpha = akp
akp = ak
cal_kp = cal_k
k = 1
else:
break
return [min(alpha, akp), max(alpha, akp)]
def __draw_image(self, min_x, min_y):
X = np.arange(self.__a-5, self.__b+5, 0.01)
Y = list(map(lambda x: self.__fun(x), X))
plt.plot(X, Y)
plt.title(self.__fun_str, fontSize=16)
plt.xlabel('X', fontSize=16)
plt.ylabel('Y', fontSize=16)
plt.text(min_x, min_y, 'X', color='red', fontSize=14)
plt.text(min_x+0.382, min_y-0.618, '({:.4f}, {:.4f})'.format(min_x, min_y), fontSize=14)
plt.show()
def run(self):
step = 1
while abs(self.__b - self.__a) > self.__deta:
if self.__pCal <= self.__qCal:
if abs(self.__q - self.__a) <= self.__epsilon:
break
else:
self.__b = self.__q
self.__qCal = self.__pCal
self.__q = self.__p
self.__p = self.__a + (1-self.__t)*(self.__b - self.__a)
self.__pCal = self.__fun(self.__p)
else:
if abs(self.__b - self.__p) <= self.__epsilon:
break
else:
self.__a = self.__p
self.__pCal = self.__qCal
self.__p = self.__q
self.__q = self.__a + self.__t*(self.__b - self.__a)
self.__qCal = self.__fun(self.__q)
step += 1
min_x = self.__p if self.__pCal < self.__qCal else self.__q
min_y = self.__fun(min_x)
result = {
'极小值点为:': min_x,
'极小值为:': min_y,
'迭代次数为:': step,
'|b-a|:': abs(self.__b - self.__a),
'|fun(b)-fun(a)|:': abs(self.__fun(self.__b) - self.__fun(self.__a))
}
for key, value in result.items():
print(key, value)
self.__draw_image(min_x, min_y)
if __name__ == '__main__':
a = 0
b = 1
epsilon = 1e-5
deta = 1e-4
Solution_golds('x**2 - math.sin(x)', a, b, epsilon, deta).run()
Comments