采用三次插值法进行一维搜索

简介

三次插值法是用a,b两点处的函数值 f ( a ) , f ( b ) f(a),f(b) f(a),f(b)和导数值 f ′ ( a ) , f ′ ( b ) f^{'}(a),f^{'}(b) f(a),f(b)来构造三次插值多项式,并以 g ( x ) g(x) g(x)的极小点作为 f ( x ) f(x) f(x)的近似极小点。为了保证 f ( x ) f(x) f(x)的极小点 x ∗ ∈ [ a , b ] x^{*}\in[a,b] x[a,b],假定 f ( x ) ∈ C 1 f(x)\in C^{1} f(x)C1,并满足 a < b , f ′ ( a ) < 0 , f ′ ( b ) > 0 a<b,f^{'}(a)<0,f^{'}(b)>0 a<b,f(a)<0,f(b)>0插值多项式为: g ( x ) = α ( x − a ) 3 + β ( x − a ) 2 + γ ( x − a ) + δ g(x)=\alpha(x-a)^{3}+\beta(x-a)^{2}+\gamma(x-a)+\delta g(x)=α(xa)3+β(xa)2+γ(xa)+δ由插值条件可知 α , β , γ , δ \alpha,\beta,\gamma,\delta α,β,γ,δ应该满足下式: { δ = f ( a ) γ = f ′ ( a ) α ( b − a ) 3 + β ( b − a ) 2 + γ ( b − a ) + δ = f ( b ) 3 α ( b − a ) 2 + 2 β ( b − a ) + γ = f ′ ( b ) \left\{\begin{aligned}&\delta=f(a)\\& \gamma=f^{'}(a)\\&\alpha(b-a)^{3}+\beta(b-a)^{2}+\gamma(b-a)+\delta=f(b)\\&3\alpha(b-a)^{2}+2\beta(b-a)+\gamma=f^{'}(b)\end{aligned}\right. δ=f(a)γ=f(a)α(ba)3+β(ba)2+γ(ba)+δ=f(b)3α(ba)2+2β(ba)+γ=f(b)
通过推导可得近似极小点 x ‾ \overline{x} x的计算公式如下: x ‾ = a − γ β + β 2 − 3 α γ \overline{x}=a-\frac{\gamma}{\beta+\sqrt{\beta^{2}-3\alpha\gamma}} x=aβ+β23αγ γ
其中 α , β \alpha,\beta α,β的计算公式如下: { u = f ( b ) − δ b − a − γ v = f ′ ( b ) − γ β = 3 u − v b − a α = v − 2 u ( b − a ) 2 \left\{\begin{aligned}&u=\frac{f(b)-\delta}{b-a}-\gamma\\&v=f^{'}(b)-\gamma\\&\beta=\frac{3u-v}{b-a}\\&\alpha=\frac{v-2u}{(b-a)^{2}}\end{aligned}\right. u=baf(b)δγv=f(b)γβ=ba3uvα=(ba)2v2u
∣ f ′ ( x ‾ ) ∣ < ε \lvert f^{'}(\overline{x})\lvert<\varepsilon f(x)<ε时, ε \varepsilon ε为给定的收敛精度, x ∗ ≈ x ‾ x^{*}\approx\overline{x} xx;若 f ′ ( x ‾ ) > 0 f^{'}(\overline{x})>0 f(x)>0,用 x ‾ \overline{x} x取代 b b b;若 f ′ ( x ‾ ) < 0 f^{'}(\overline{x})<0 f(x)<0,用 x ‾ \overline{x} x取代 a a a,不断迭代直至满足收敛条件。

优化问题

抛物线法相同,求 f ( x ) = x 4 − 4 x 3 − 6 x 2 − 16 x + 4 f(x)=x^{4}-4x^{3}-6x^{2}-16x+4 f(x)=x44x36x216x+4的极小值点。由于 f ( 0 ) = 4 , f ′ ( 0 ) = − 16 , f ( 10 ) = 5244 , f ′ ( 10 ) = 2664 f(0)=4,f^{'}(0)=-16,f(10)=5244,f^{'}(10)=2664 f(0)=4,f(0)=16,f(10)=5244,f(10)=2664,因此,选取为 a = 0 , b = 10 a=0,b=10 a=0,b=10,收敛精度 ε = 1 e − 3 \varepsilon=1e-3 ε=1e3,计算程序如下:

import sys
def cal_fun_f(x):
    """
    函数值计算函数
    """
    return x**4-4*x**3-6*x**2-16*x+4

def derivative_cal_f(x):
    """
    一阶导数计算函数
    """
    return 4*x**3-12*x**2-12*x-16

def derivative_cal_f2(x):
    """
    二阶导数计算函数
    """
    return 12*x**2-24*x-12

def get_iteration_point(a, b):
    """
    得到迭代点
    :param a:
    :param b:
    """
    delta = cal_fun_f(a)
    gamma = derivative_cal_f(a)
    f_b = cal_fun_f(b)
    d_b = cal_fun_f(b)
    u = (f_b-delta)/(b-a)-gamma
    v = d_b-gamma
    beta = (3*u-v)/(b-a)
    alpha = (v-2*u)/(b-a)**2
    return a-gamma/(beta+(beta**2-3*alpha*gamma)**0.5)


def cubic_interpolation(a, b, gap):
    """
    采用三次插值法求解一维函数的极小值点
    :param gap: 收敛精度
    :param a: 区间左端点
    :param b: 区间右端点
    """
    # 检查是否满足假设
    if (a<b) and (derivative_cal_f(a) < 0) and (derivative_cal_f(b) > 0):
        pass
    else:
        sys.exit("输入条件不满足假设")
    i = 0
    x = get_iteration_point(a, b)
    print(f"第{i}次迭代极小值点", x)
    while abs(derivative_cal_f(x)) > gap:
        if derivative_cal_f(x) > 0:
            b = x
        else:
            a = x
        x = get_iteration_point(a, b)
        i += 1
        print(f"第{i}次迭代极小值点", x)

    # 检验二阶导数是否满足
    print(f"极小值点的二阶导数", derivative_cal_f2(x))

if __name__ == "__main__":
    cubic_interpolation(0, 10, 1e-3)

结果如下:

31次迭代极小值点 3.999883353263262732次迭代极小值点 3.99991318130301833次迭代极小值点 3.99993538170210534次迭代极小值点 3.99995190510937535次迭代极小值点 3.999964203279195636次迭代极小值点 3.999973356688685537次迭代极小值点 3.999980169501149438次迭代极小值点 3.999985240235082639次迭代极小值点 3.999989014356277
极小值点的二阶导数 83.99920903510015

可以看到成功找到了极小值点4.

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知情人士黄某

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值