最优化作业第6章——无约束多维非线性规划方法

代码:

#导入模块
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 = 0
    x1,x2,alpha = symbols("x1,x2,alpha",real = True)#将变量符号化,否则会出错
    f = 8*x1**2 + 4*x1*x2 + 5*x2**2 #定义目标函数
    a = 10
    b=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 + 1
        x_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**2

        x_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:#判断是否满足迭代终止条件
            break

if __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