采用二次插值法进行不精确一维搜索

简介

上次介绍了不精确一维搜索的概念和准则,以及采用直接法进行不精确一维搜索的实例,本次介绍采用二次插值法来进行不精确一维搜索的方法。 φ ( λ ) = f ( x k + λ s k ) \varphi(\lambda)=f(\bm{x}^{k}+\lambda\bm{s}^{k}) φ(λ)=f(xk+λsk),若已知点 ( λ 1 , φ 1 ) , ( λ 2 , φ 2 ) , (\lambda_1, \varphi_1),(\lambda_2,\varphi_2), (λ1,φ1),(λ2,φ2),,则可由抛物线法进行一维搜索那节的内容可知,可采用抛物线方程 g ( λ ) = a λ 2 + b λ + c g(\lambda)=a\lambda^{2}+b\lambda+c g(λ)=aλ2++c来近似曲线,可推导得到近似极小点的计算公式如下: λ ^ = λ 1 + 1 2 ( λ 2 − λ 2 ) / [ 1 + φ 1 − φ 2 ( λ 2 − λ 2 ) φ 1 ′ ] \hat{\lambda}=\lambda_1+\frac{1}{2}(\lambda_2-\lambda_2)/\lbrack1+\frac{\varphi_1-\varphi_2}{(\lambda_2-\lambda_2)\varphi_1^{'}}\rbrack λ^=λ1+21(λ2λ2)/[1+(λ2λ2)φ1φ1φ2]
具体实施步骤如下:

  1. 给定 c 1 ∈ ( 0 , 1 ) , c 2 ∈ ( c 1 , 1 ) , T > 0 c_1\in(0, 1), c_2\in(c_1, 1), T>0 c1(0,1),c2(c1,1),T>0,令 λ 1 = 0 , λ 2 = 1 , λ 3 = + ∞ , i = 0 \lambda_1=0, \lambda_2=1, \lambda_3=+\infty, i=0 λ1=0,λ2=1,λ3=+,i=0;
  2. λ 2 \lambda_2 λ2满足条件1、2(具体条件见不精确一维搜索),则令 λ k = λ 2 \lambda_k=\lambda_2 λk=λ2,计算终止;否则转步骤3;
  3. 计算 φ 1 , φ 2 , φ 1 ′ = ▽ f ( x k + λ 1 s k ) T s k \varphi_1, \varphi_2, \varphi_1^{'}=\bigtriangledown f(\bm{x}^{k}+\lambda_1\bm{s}^{k})^T\bm{s}^{k} φ1,φ2,φ1=f(xk+λ1sk)Tsk λ ^ \hat{\lambda} λ^,令 i = i + 1 i=i+1 i=i+1;
  4. λ 1 < λ ^ < λ 2 \lambda_1<\hat{\lambda}<\lambda_2 λ1<λ^<λ2,则令 λ 3 = λ 2 \lambda_3=\lambda_2 λ3=λ2 λ 2 = λ ^ \lambda_2=\hat{\lambda} λ2=λ^,返回步骤2;若 λ 2 ⩽ λ ^ < λ 3 \lambda_2\leqslant\hat{\lambda}<\lambda_3 λ2λ^<λ3,则令 λ 1 = λ 2 , λ 2 = λ ^ \lambda_1=\lambda_2,\lambda_2=\hat{\lambda} λ1=λ2,λ2=λ^,返回步骤2;否则返回步骤5;
  5. λ ^ ⩽ λ 1 \hat{\lambda}\leqslant\lambda_1 λ^λ1,则令 λ ^ = λ 1 + T △ λ \hat{\lambda}=\lambda_1+T\triangle\lambda λ^=λ1+Tλ;若 λ ^ ⩾ λ 3 \hat{\lambda}\geqslant\lambda_3 λ^λ3,则令 λ ^ = λ 3 − T △ λ , △ λ = λ 3 − λ 1 \hat{\lambda}=\lambda_3-T\triangle\lambda,\triangle\lambda=\lambda_3-\lambda_1 λ^=λ3Tλ,λ=λ3λ1,令 λ 2 = λ ^ \lambda_2=\hat{\lambda} λ2=λ^,返回步骤2。

优化问题

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的极小值点。设置参数 c 1 = 0.5 , c 2 = 0.7 , T = 0.1 , λ 1 = 0 , λ 2 = 1 , λ 3 = + ∞ , x = 11 , s = − 1 c_1=0.5, c_2=0.7, T=0.1, \lambda_1=0, \lambda_2=1, \lambda_3=+\infty,x=11,s=-1 c1=0.5,c2=0.7,T=0.1,λ1=0,λ2=1,λ3=+,x=11,s=1,计算程序如下:

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

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

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

def wolfe_powell_rule1(f_x, f_x_, c1, lam, d_x, s):
    """
    判断准则1
    :param f_x:k点函数值
    :param f_x_:k+1点函数值
    :param c1:给定常数
    :param lam:步长
    :param d_x:k点一阶导数
    :param s:方向向量
    :return:
    """
    if (f_x-f_x_) >= (-c1*lam*d_x*s):
        return True
    else:
        return False

def wolfe_powell_rule2(d_x_, s, c2, d_x):
    """
    判断准则2
    :param d_x_: k+1点一阶导数
    :param s: k点方向导数
    :param c2: 给定常数
    :param d_x: k点一阶导数
    """
    if (d_x_*s) >= (c2*d_x*s):
        return True
    else:
        return False

def imprecise_parabolic_method(c1, c2, T, lam1, lam2, lam3, x, s):
    """
    采用二次插值法进行不精确一维搜索
    :param T: 大于0
    :param c1:给定常数
    :param c2:给定常数
    :param lam1:步长区间左端点
    :param lam2:步长
    :param lam3:步长区间右端点
    :param x:初始点
    :param s:方向向量
    """
    i = 0
    while True:
        temp_x = x
        x2 = x+lam2*s
        f_x = cal_fun_f(x)
        f_x2 = cal_fun_f(x2)
        d_x = derivative_cal_f1(x)
        d_x2 = derivative_cal_f1(x2)
        rule1_judge = wolfe_powell_rule1(f_x, f_x2, c1, lam2, d_x, s)
        rule2_judge = wolfe_powell_rule2(d_x2, s, c2, d_x)
        # print(f"第{i}迭代点,步长", x2, lam2)
        if rule1_judge and rule2_judge:
            return x2, lam2
        else:
            x1 = x + lam1 * s
            f_x1 = cal_fun_f(x1)
            d_x1 = derivative_cal_f1(x1)
            d_lam1 = d_x1*s
            lam = lam1 + 0.5*(lam2 - lam1)/(1 + (f_x1 - f_x2) / ((lam2 - lam1) * d_lam1))
            i += 1
            if lam < 0:
                return x, lam
            elif lam1 < lam < lam2:
                lam3 = lam2
                lam2 = lam
            elif lam2 <= lam < lam3:
                lam1 = lam2
                lam2 = lam
            elif lam <= lam1:
                delta_lam = lam3-lam1
                lam = lam1+T*delta_lam
                lam2 = lam
            else:
                delta_lam = lam3 - lam1
                lam = lam3-T*delta_lam
                lam2 = lam

def main_loop(c1, c2, T, lam1, lam2, lam3, x, s, gap):
    i = 0
    while True:
        x, lam = imprecise_parabolic_method(c1, c2, T, lam1, lam2, lam3, x, s)
        i += 1
        print(f"第{i}次迭代极小值点,迭代步长", x, lam)
        if abs(derivative_cal_f1(x)) < gap or lam<0:
            break

if __name__ == "__main__":
    main_loop(0.5, 0.7, 0.1, 0, 1, float("inf"), 11, -1, 1e-3)

计算结果如下:

1次迭代极小值点,迭代步长 7.608378870673952 3.39162112932604832次迭代极小值点,迭代步长 6.608378870673952 13次迭代极小值点,迭代步长 5.608378870673952 14次迭代极小值点,迭代步长 4.608378870673952 15次迭代极小值点,迭代步长 4.048639983992185 0.5597388866817676次迭代极小值点,迭代步长 4.000335997451437 0.048303986540748137次迭代极小值点,迭代步长 4.00000001612566 0.0003359813257768087

但是这个计算结果并不稳定,更改初始点和参数之后,收敛结果改变的比较明显,读者自行甄别。

  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知情人士黄某

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

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

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

打赏作者

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

抵扣说明:

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

余额充值