代码:
#导入模块
from sympy import *
import sympy as sp #将导入的模块重新定义一个名字以便后续的程序进行使用
from numpy import *
import numpy as np#定义主要的处理函数
def main():#x1,x2:目标函数变量;alpha:步长因子;f:目标函数;a,b:目标函数不同变量的解;dif_x1,dif_x2:目标函数偏导函数#x_solver:目标函数变量解组成的矩阵;x_fun:包含alpha的迭代解函数组成的矩阵# dif_x11,dif_x22:目标函数偏导函数;f_x_diff:目标函数偏导函数值组成的矩阵;# f_alpha_diff:对alpha求偏导得到的函数;alpha_solver:α的解;k:迭代的次数#x_solver_k1:作为第k+1次迭代的解;x_solver_k:作为第k次迭代的解k = 0x1,x2,alpha = symbols("x1,x2,alpha",real = True)#将变量符号化,否则会出错f = 8*x1**2 + 4*x1*x2 + 5*x2**2 #定义目标函数a = 10b=10 #定义目标函数的初始解的两维解f_solver = 8*a**2 + 4*a*b + 5*b**2#得到给定初始解下的目标函数值dif_x1 = sp.diff(f,x1)dif_x2 = sp.diff(f,x2) #目标函数对不同变量进行求偏导,得到偏导函数dif_x11 = dif_x1.subs({x1: a, x2: b})dif_x22 = dif_x2.subs({x1: a, x2: b}) # 将目标函数的初始解代入到偏导函数中得到具体的偏导函数值print("------------------------------第<%s>次迭代------------------------------" % k)print("目标函数解为:%s,目标函数值为:%s,梯度向量长度:<%s>\n"% ( [[a],[b]], f_solver,(dif_x11**2 + dif_x22**2)**0.5))while True:k = k + 1x_solver = np.array([[a],[b]]) #将目标函数的初始解定义为2行1列的数组x_solver = np.mat(x_solver)#将数组转化为矩阵dif_x11 = dif_x1.subs({x1:x_solver[0,0],x2:x_solver[1,0]})dif_x22 = dif_x2.subs({x1:x_solver[0,0],x2:x_solver[1,0]})#将目标函数的初始解代入到偏导函数中得到具体的偏导函数值f_x_diff = np.array([[dif_x11],[dif_x22]])#将偏导函数值定义为数组f_x_diff = np.mat(f_x_diff)#将数组转化为矩阵x_fun = x_solver - alpha*f_x_diff#迭代公式得到新的解f = 8*x_fun[0,0]**2 + 4*x_fun[0,0]*x_fun[1,0] + 5*x_fun[1,0]**2 #将新得到的解带入到目标函数得到只包含alpha的一元函数f_alpha_diff = sp.diff(f,alpha) #对函数进行求导alpha_dict = solve([f_alpha_diff],[alpha]) #由于极值点处的导数为0,因此求解其方程得到alpha,返回的是一个字典{alpha: 149/2650}alpha_solver = alpha_dict[alpha]#取值操作x_solver_k1 = x_solver - alpha_solver * f_x_diff#通过迭代得到下一步的解矩阵a = float(x_solver_k1[0,0])b = float(x_solver_k1[1,0])#取得解矩阵的解f_solver = 8*a**2 + 4*a*b + 5*b**2x_solver_k = x_solver_k1 # 将上一次解保留下来,作为终止条件的判断dif_x11 = dif_x1.subs({x1:a,x2:b})dif_x22 = dif_x2.subs({x1:a,x2:b})#将目标函数的初始解代入到偏导函数中得到具体的偏导函数值f_diff_solver = (dif_x11 ** 2 + dif_x22 ** 2) ** 0.5#得到梯度向量的模长print("------------------------------第<%s>次迭代------------------------------" % k)print("目标函数解为:<%s>,目标函数值为:<%s>,梯度向量长度:<%s>\n"%(x_solver_k1,float(f_solver),float(f_diff_solver)))if f_diff_solver < 0.01:#判断是否满足迭代终止条件breakif __name__ == '__main__':main()
结果:
------------------------------第<0>次迭代------------------------------
目标函数解为:[[10], [10]],目标函数值为:1700,梯度向量长度:<244.131112314674>------------------------------第<1>次迭代------------------------------
目标函数解为:<[[-66/53][564/265]]>,目标函数值为:<24.452830188679243>,梯度向量长度:<19.898988777347018>------------------------------第<2>次迭代------------------------------
目标函数解为:<[[0.143840177580469][0.143840177580462]]>,目标函数值为:<0.3517299436684602>,梯度向量长度:<3.5115862548259504>------------------------------第<3>次迭代------------------------------
目标函数解为:<[[-0.0179121730571876][0.0306135321341049]]>,目标函数值为:<0.0050592897557630336>,梯度向量长度:<0.28622740794050416>------------------------------第<4>次迭代------------------------------
目标函数解为:<[[0.00206899966863705][0.00206899966863635]]>,目标函数值为:<7.277291368992362e-05>,梯度向量长度:<0.050510719048299235>------------------------------第<5>次迭代------------------------------
目标函数解为:<[[-0.000257649015339521][0.000440345589853036]]>,目标函数值为:<1.046766882819546e-06>,梯度向量长度:<0.004117100118651557>进程已结束,退出代码0