二分法(算法分析+python代码解释)

前言: 

在前期,我们讨论了成功失败算法和黄金分割算法,那么这一期,我们来看看一种最为常见也最为简单的一维搜素方法——二分法

成功-失败算法(算法分析+python代码解释)icon-default.png?t=N7T8https://blog.csdn.net/m0_61209712/article/details/133940690

黄金分割算法(算法分析+python代码解释)icon-default.png?t=N7T8https://blog.csdn.net/m0_61209712/article/details/133973395

当对收敛速度要求不是很高并且函数性质较好时,我们就可以采用两分法。具体做法如下:

设函数f(x)在区间[a,b]上为具有一阶导数的单峰函数,且满足f'(a)< 0,f'(b)> 0。令x_{0}=\frac{a+b}{2},如果f'(x_{0})=0,则最优解为x^{*}=x_{0}。若f'(x_{0})< 0,则令a:= x_{0},区间被减半,重新开始。若f'(x_{0})> 0,则令b:= x_{0},区间被减半,重新开始,直到区间的长度小于事先给定的精度ε,或者\left | f'(x_{0}) \right |<ε为止

算法步骤:

步骤1:给定a,b,ε>0.

步骤2:计算x_{0}:= \frac{a+b}{2}

步骤3:如果\left | f'(x_{0}) \right |<ε或者\left | b-a \right |<ε,则转步骤4。否则若f'(x_{0})< 0,则令a:= x_{0},转步骤2;若f'(x_{0})> 0,则令b:= x_{0},转步骤2。

步骤4:停止,输出x_{0}

例题分析:

下面我们通过一道例题来加深一下对算法的认识。

例题:试用二分法求目标函数f(x)=x^{3}-2x+1的最优解。给定初始区间[0,2],收敛精度ε=0.004.

解:首先判断在给定区间内是否含有极点:

\because f'(x)=3x^{2}-2,f'(0)=-2,f'(2)=10

\therefore函数在该区间有极小值

第一次区间缩短计算过程:

x_{0}= \frac{a+b}{2}=1,f'(1)=1> 0,b:= x_{0}=1,又\left | b-a \right |>ε,开始下一次

第二次区间缩短计算过程:

x_{0}= \frac{a+b}{2}=\frac{1}{2},f'(\frac{1}{2})=-\frac{1}{2}< 0,a:= x_{0}=\frac{1}{2},又\left | b-a \right |>ε,开始下一次

第三次区间缩点计算过程:

x_{0}= \frac{a+b}{2}=\frac{3}{4},f'(\frac{3}{4})=-\frac{5}{16}< 0,a:= x_{0}=\frac{3}{4},又\left | b-a \right |>ε,开始下一次

------

第九次区间缩短计算过程:

x_{0}= \frac{a+b}{2}=\frac{209}{256},\left [ a,b \right ]=\left [ \frac{209}{256},\frac{105}{128} \right ],又\left | b-a \right |=\frac{1}{256}\approx 0.00391<ε,x^{*}=\frac{a+b}{2}=0.81836

算法代码:

'''
二分法算法
2023.10.9
'''
from sympy import *
x = symbols("x")
f_x = x ** 2 + 2 * x - 10
def run(a,b,ε):
    count = 0
    # 一阶求导
    first_grad = diff(f_x, x)
    # 判断给定区间内是否存在极小点
    if first_grad.subs({x: a})*first_grad.subs({x:b}) > 0:
        print("该函数在该区间不存在极小点,该函数在该区间单调")
        if f_x.subs({x:a}) > f_x.subs({x:b}):
            print("最小值在{}处取到".format(b),"为{}".format(f_x.subs({x:b})))
        elif f_x.subs({x:a}) < f_x.subs({x:b}):
            print("最小值在{}处取到".format(a),"为{}".format(f_x.subs({x:a})))
    else:
        print("该函数在该区间存在极小点")
        while abs(b-a) > ε:
            count = count+1
            print("第{}次迭代".format(count))
            x0 = (a+b)/2
            #print(x0)
            if first_grad.subs({x: x0}) > 0:
                b = x0
            elif first_grad.subs({x: x0}) < 0:
                a = x0
            elif first_grad.subs({x: x0}) == 0:
                print("该精度下的最优解是:%f" % x0)
                print("缩短之后的区间为:[%f,%f]" % (a, b))
                break
        print("缩短之后的区间为:[%f,%f]"%(a,b))
        print("该精度下的最优解是:%f"%x0)
        return x0
run(-1,5,0.0001)

用该代码所运算的结果为:

该函数在该区间存在极小点
第1次迭代
第2次迭代
第3次迭代
第4次迭代
第5次迭代
第6次迭代
第7次迭代
第8次迭代
第9次迭代
第10次迭代
第11次迭代
第12次迭代
第13次迭代
第14次迭代
第15次迭代
第16次迭代
缩短之后的区间为:[-1.000000,-0.999908]
该精度下的最优解是:-0.999908

总结:

在成功-失败算法和黄金分割算法的迭代过程中,仅仅利用了函数值就能够找到函数在某区间上的最小值,这样做固然简单方便,计算量也小,但是如果函数的性质比较好(比如已知函数的导数),我们就可以选用更为简单或者收敛速度更快的迭代算法——二分法。

(行文中若有纰漏,希望大家指正)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

背对人潮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值