采用直接法进行不精确一维搜索

简介

前面介绍的一维搜索算法都是精确搜索,实际计算中一般没有必要做到精确的一维搜索。相比于精确的一维搜索方法,不精确的一维搜素方法收敛的更快,并且计算压力更小。不精确一维搜索基本思想即 m i n φ ( λ ) = f ( x ( k ) + λ s ( k ) ) min \varphi(\lambda)=f(\bm{x}^{(k)}+\lambda \bm{s}^{(k)}) minφ(λ)=f(x(k)+λs(k)),要求 f ( x ( k + 1 ) ) f(\bm{x}^{(k+1)}) f(x(k+1)) f ( x ( k ) ) f(\bm{x}^{(k)}) f(x(k))下降一定的数量,同时在新点 x ( k + 1 ) = x ( k ) + λ k s ( k ) \bm{x}^{(k+1)}=\bm{x}^{(k)}+\lambda_k\bm{s}^{(k)} x(k+1)=x(k)+λks(k)处沿方向 s ( k ) \bm{s}^{(k)} s(k)的方向导数值比在 x ( k ) \bm{x}^{(k)} x(k)点沿 s ( k ) \bm{s}^{(k)} s(k)方向的方向导数值大一定的数量,采用 − ▽ f ( x ( k ) ) T s ( k ) > 0 -\bigtriangledown f(\bm{x}^{(k)})^{T}\bm{s}^{(k)}>0 f(x(k))Ts(k)>0来度量。
常用的不精确搜索准则为Wolfe-Powell准则,对于给定的常数 c 1 , c 2 , 0 < c 1 < c 2 < 1 c_1,c_2,0<c_1<c_2<1 c1,c2,0<c1<c2<1,要求满足如下两个条件:

  1. f ( x ( k ) ) − f ( x ( k + 1 ) ) ⩾ − c 1 λ k ▽ f ( x ( k ) ) T s ( k ) f(\bm{x}^{(k)})-f(\bm{x}^{(k+1)})\geqslant-c_1\lambda_k\bigtriangledown f(\bm{x}^{(k)})^{T}\bm{s}^{(k)} f(x(k))f(x(k+1))c1λkf(x(k))Ts(k)
  2. ▽ f ( x ( k + 1 ) ) T s ( k ) ⩾ c 2 ▽ f ( x ( k ) ) T s ( k ) \bigtriangledown f(\bm{x}^{(k+1)})^{T}\bm{s}^{(k)}\geqslant c_2\bigtriangledown f(\bm{x}^{(k)})^{T}\bm{s}^{(k)} f(x(k+1))Ts(k)c2f(x(k))Ts(k)

假设 f ( x ) f(x) f(x)的一阶导数函数为 g ( x ) g(x) g(x),则不精确搜索算法直接法的计算步骤如下:

  1. 给定 c 1 ∈ ( 0 , 1 ) , c 2 ∈ ( c 1 , 1 ) c_1\in(0, 1), c_2\in(c_1, 1) c1(0,1),c2(c1,1),令 a = 0 , b = + ∞ a=0, b=+\infty a=0,b=+ λ = 1 \lambda=1 λ=1 i = 0 i=0 i=0;
  2. x ( k + 1 ) = x ( k ) + λ k s ( k ) \bm{x}^{(k+1)}=\bm{x}^{(k)}+\lambda_k\bm{s}^{(k)} x(k+1)=x(k)+λks(k),计算 f ( x k + 1 ) f(\bm{x}^{k+1}) f(xk+1) g ( x k + 1 ) g(\bm{x}^{k+1}) g(xk+1),若 λ \lambda λ满足条件1和2,则计算结束,令 λ k = λ \lambda_k=\lambda λk=λ;否则令 i = i + 1 i=i+1 i=i+1,若 λ \lambda λ不满足条件1,则转到步骤3;若 λ \lambda λ满足条件1,不满足条件2,则步骤4;
  3. b = λ , λ = ( λ + a ) / 2 b=\lambda, \lambda=(\lambda+a)/2 b=λ,λ=(λ+a)/2,返回步骤2;
  4. a = λ , λ = m i n ( 2 λ , ( λ + b ) / 2 ) a=\lambda, \lambda=min({2\lambda, (\lambda+b)/2}) a=λ,λ=min(2λ,(λ+b)/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的极小值点。由于这是一个一维问题,需要明白的是我们搜索方向是沿着x轴正向还是负向即设置 s s s为正还是为负,设置 c 1 = 0.1 , c 2 = 0.7 , a = 0 , b = + ∞ , λ = 1 , x 0 = 10.5 , s = − 1 c_1=0.1, c_2=0.7, a=0, b=+\infty, \lambda=1, x_0=10.5, s=-1 c1=0.1,c2=0.7,a=0,b=+,λ=1,x0=10.5,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_direct_method(c1, c2, a, b, lam, x, s):
    """
    采用直接法进行不精确搜索
    :param x: 初始点列向量
    :param s: 方向向量,列向量
    :param c1: 给定常数
    :param c2: 给定常数
    :param a: 区间左端点
    :param b: 区间右端点
    :param lam: 步长
    """
    i = 0
    while True:
        f_x = cal_fun_f(x)
        d_x = derivative_cal_f1(x)
        x_ = x+lam*s  # 下一个迭代点
        f_x_ = cal_fun_f(x_)
        d_x_ = derivative_cal_f1(x_)
        rule1_judge = wolfe_powell_rule1(f_x, f_x_, c1, lam, d_x, s)
        rule2_judge = wolfe_powell_rule2(d_x_, s, c2, d_x)
        if rule1_judge and rule2_judge:
            return x_, lam
        else:
            i += 1
            if not rule1_judge:
                b = lam
                lam = (lam+a)/2
            if rule1_judge and rule2_judge == False:
                a = lam
                lam = min(2*lam, (lam+b)/2)

def main_loop(c1, c2, a, b, lam, x, s, gap):
    """
    将不精确搜索得到的迭代点和搜索步长进行循环,求解极小值
    :param x: 初始点列向量
    :param s: 方向向量,列向量
    :param c1: 给定常数
    :param c2: 给定常数
    :param a: 区间左端点
    :param b: 区间右端点
    :param lam: 步长
    """
    i = 0
    while True:
        x, lam = imprecise_direct_method(c1, c2, a, b, lam, x, s)
        i += 1
        print(f"第{i}次迭代极小值点,迭代步长", x, lam)
        if abs(derivative_cal_f1(x)) < gap:
            break

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

输出结果如下:

1次迭代极小值点,迭代步长 8.5 22次迭代极小值点,迭代步长 6.5 23次迭代极小值点,迭代步长 4.5 24次迭代极小值点,迭代步长 4.0 0.5

可以看到收敛速度还是比较快的,但是有个问题是, c 1 , c 2 c_1,c_2 c1,c2的取值对收敛效果影响较大,很可能不收敛于极小值点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知情人士黄某

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

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

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

打赏作者

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

抵扣说明:

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

余额充值