牛顿法求极值

1,问题叙述

用牛顿法求解下面问题

牛顿法求极值_第1张图片

 

初始点取为x_{0}=(-2,-1)=(-2,-1),请输出第10次和第50次迭代的结果,f()和, f().

2,详细实现:

2.1、导入依赖包

import math

import matplotlib.pyplot as plt

import numpy as np

from sympy import *

import xlwt

x1,x2,t = symbols('x1,x2,t')#设置变量符号

2.2、定义函数表达式,海森矩阵

def func():

    return x1**6/3 -2.1*x1**4 +4*x1**2 -x1*x2 -4*x2**2 + 4*x2**4

def haisen(func):

    H_mat = []

    H_mat.append(diff(diff(func,x1),x1))

    H_mat.append(diff(diff(func,x1),x2))

    H_mat.append(diff(diff(func,x2),x1))

    H_mat.append(diff(diff(func,x2),x2))

    return np.array(H_mat).reshape((2,2))

2.3、设计函数,求海森矩阵在data处的值 ,data存放x1和x2的值

def compute_haisen_value(haisen,data):

    res = np.zeros_like(haisen)

    for i in range(2):

        for j in range(2):

            res[i][j] = haisen[i][j].subs(x1,data[0]).subs(x2,data[1])

    return res

2.4、 设计函数,求原函数在data处的梯度,data同上。

def grad(data):

    f = func()

    df = [diff(f,x1),diff(f,x2)]

    res = np.zeros_like(df)

    for i in range(len(df)):

        item = df[i]

        res[i] = item.subs(x1,data[0]).subs(x2,data[1])

    return np.array(res)

2.5、一维搜索函数,t0为初值,h为搜索跨度,sigma是判断循环终止的条件,可视为精度。 

def one_dim_search(func,t0,h,sigma):

    value1 = func.subs(t,t0)

    delta = sigma

    while(True):

        value2 = func.subs(t,t0+h)



        if(value2<=value1):

            t0 += h

            h *= 2

            value1 = value2

            continue

        else:

            if(abs(h)<=sigma):

                res = t0 + h

                break

            else:

                h *= -0.25

                continue

    return res

 2.6、牛顿法迭代求极小值,sigma同上;x0为初值,应为1x2的列表,包含x1和x2的初值;k为迭代次数

def iterration(sigma,x0,k):

    x0 = np.array(x0)

    loc_x = [x0[0]]

    loc_y = [x0[1]]

    f = func()

    value = [f.subs(x1, x0[0]).subs(x2, x0[1])]

    haisen_mat = haisen(f)

    grad_vec = grad(x0)

    haisen_vec = np.array(compute_haisen_value(haisen_mat,x0))

    grad_len = math.sqrt(pow(grad_vec[0], 2) + pow(grad_vec[1], 2))

    while(k>0):

        k -= 1

        p = -np.dot(haisen_vec,grad_vec)

        p /= max(p[0],p[1])

        new_x = x0 + t*p

        gt = f.subs(x1,new_x[0]).subs(x2,new_x[1])

        t_min = one_dim_search(gt,0,0.1,sigma)

        x0 = x0 + t_min*p

        grad_vec = grad(x0)

        haisen_vec = np.array(compute_haisen_value(haisen_mat,x0))

        grad_len = math.sqrt(pow(grad_vec[0], 2) + pow(grad_vec[1], 2))



        loc_x.append(x0[0])

        loc_y.append(x0[1])

        value.append(f.subs(x1, x0[0]).subs(x2, x0[1]))

    print("\nlastvalue:",f.subs(x1,x0[0]).subs(x2,x0[1]))



    plt.plot(loc_x, loc_y)

    plt.show()

    return loc_x, loc_y, value

2.7、主函数,分别调用iteration获得结果集,将其写入到表格文件中。 

if __name__ == '__main__':

    #绘制迭代10次的结果,图像和具体值表格。

    work_book = xlwt.Workbook()  #生成工作簿对象

    loc_x, loc_y, value = iterration(0.0001, [-2, -1], 10)  #获得列表形式的结果集

    sheet1 = work_book.add_sheet(u'迭代10', cell_overwrite_ok=True)  #生成表一     

    sheet1.write(0, 1, 'x')  #列属性名,下同

    sheet1.write(0, 1, 'y')

    sheet1.write(0, 1, '值')

    for i in range(0, len(loc_x)):

        sheet1.write(i + 1, 0, float(round(loc_x[i], 7)))  #第一列为x坐标,保留7位小数

        sheet1.write(i + 1, 1, float(round(loc_y[i], 7)))  #第二列为y坐标,保留7位小数

        sheet1.write(i + 1, 2, float(round(value[i], 7)))  #第三列为函数值,保留7位小数

    #绘制迭代50次的结果,图像和具体值表格。

    loc_x2, loc_y2, value2 = iterration(0.0001, [-2, -1], 50)

    sheet2 = work_book.add_sheet(u'迭代50', cell_overwrite_ok=True)

    sheet2.write(0, 1, 'x')

    sheet2.write(0, 1, 'y')

    sheet2.write(0, 1, '值')

    for i in range(0, len(loc_x2)):

        sheet2.write(i + 1, 0, float(round(loc_x2[i], 7)))

        sheet2.write(i + 1, 1, float(round(loc_y2[i], 7)))

        sheet2.write(i + 1, 2, float(round(value2[i], 7)))

    work_book.save('牛顿法.csv')

 

3,实验结果

3.1、迭代结果图:

牛顿法求极值_第2张图片

3.2、详细结果列表:

牛顿法求极值_第3张图片

第10次迭代:(-0.09301,-0.70874)     -1.03145

第50次迭代:(-0.09223,-0.71172)     -1.0316

你可能感兴趣的:(python,算法,大数据,列表,excel)