前言: 

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

成功-失败算法(算法分析+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

总结:

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

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

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐