进化优化算法--第二章:爬山法

算法2.1: 最快上升爬山法

x0 <- 随机生成的个体
while not ( 终止准则)
    计算x0的适应度f(x0)
    For 每一个解的特征 q=1,2,,...n
        xq <- x0 
        用一个随机变异替换xq的第q个特征
        计算xq的适应度f(xq)
    获取下一个更优的解:
    寻找使f(xq)最大的xq, 令其等于x',  x' <- argmax(f(xq)): q 属于[0,n]
    if x0 != x' then
        x0 <- x'
    else:
        x0 保持不变
   

算法理解:该算法比较保守,每次只变化解的一个特征,并用某一个最好的特征变化来代替当前的解

终止准则:1. 迭代次数  2. 迭代解之间的差距和迭代次数,如迭代多少次之后,并且每次迭代解之间差距很小的时候就可以终止

代码实现及仿真:

def objective_function(x, y):
    c = 2 * math.pi
    sum1 = 0
    sum2 = 0
    term1 = -0.2 * math.sqrt((x ** 2 + y ** 2) / 2)
    term2 = math.exp((math.cos(c * x) + math.cos(c * y)) / 2)
    y = math.exp(1) - 20 * math.exp(term1) - term2
    return y


def fastest_climb_mountains(func, times=1000):
    """ fastest climb mountains algorithm """
    x = [-5, 5]
    x0 = [rd.uniform(-5, 5), rd.uniform(-5, 5)]
    i = 1
    res = []

    while i <= times:
        f_x0 = func(x0[0], x0[1])
        f_xq = [0, 0]
        xq_1 = copy.deepcopy(x0)
        xq_2 = copy.deepcopy(x0)
        xq = [xq_1, xq_2]
        for j in range(2):
            xq[j][j] = rd.uniform(-5, 5)
            f_xq[j] = func(xq[j][0], xq[j][1])

        xq.append(x0)
        f_xq.append(f_x0)
        min_index = np.nanargmin(f_xq)
        new_f_x0 = f_xq[min_index]
        new_x0 = xq[min_index]
        if new_f_x0 != f_x0:
            x0 = copy.deepcopy(new_x0)
        res.append(func(x0[0], x0[1]))
        i += 1
    x_i = np.linspace(0, times, times)
    plt.title("Ackley function")
    plt.xlabel("x axis number of iterations")
    plt.ylabel("y axis objective value")
    plt.plot(x_i, res)
    plt.show()



if __name__ == '__main__':
    fastest_climb_mountains(objective_function)

仿真结果:

算法2.2: 依次上升爬山法

x0 <- 随机生成的个体
while not ( 终止准则)
    计算x0的适应度f(x0)
    replaceFlag = false
    For 每一个解的特征 q=1,2,,...n
        xq <- x0 
        用一个随机变异替换xq的第q个特征
        计算xq的适应度f(xq)
        if f(xq) > f(x0):
            x0 <- xq
            replaceFlag = true
        endif
    获取下一个更优的解:
    寻找使f(xq)最大的xq, 令其等于x',  x' <- argmax(f(xq)): q 属于[0,n]
    if not replaceFlag then
        x0 保持不变
    endif 

        

算法理解:该算法比较贪婪,每次只变化解的一个特征,只要变化的某一个特征比当前解好,那么就会替换当前的解

def ascending_climb_mountains(func, times=1000):
    x = [-5, 5]
    x0 = [rd.uniform(-5, 5), rd.uniform(-5, 5)]
    i = 1
    res = []
    while i <= times:
        f_x0 = func(x0[0], x0[1])
        minf = f_x0
        for j in range(2):
            xq = copy.deepcopy(x0)
            xq[j] = rd.uniform(-5, 5)
            f_xq = func(xq[0], xq[1])
            if f_xq < f_x0:
                x0 = copy.deepcopy(xq)
                f_x0 = func(x0[0], x0[1])
                replace = True
        res.append(f_x0)
        i += 1
    x_i = np.linspace(0, times, times)
    plt.title("Ackley function")
    plt.xlabel("x axis number of iterations")
    plt.ylabel("y axis objective value")
    plt.plot(x_i, res)
    plt.show()

相同的例子,算法2.2的仿真结果如下:

算法2.3: 随机变异爬山法

x0 <- 随机生成的个体
while not ( 终止准则)
    计算x0的适应度f(x0)
    q <- 从[1,n] 中随机选择解的特征
    x1 <- x0
    用一个随机变异的值替换x1的第q个特征
    计算x1的适应度f(x1)
    if f(x1) > f(x0):
            x0 <- x1
    endif

        

算法实现:

def random_mutation_climb_mountains(func, times=1000):
    x = [-5, 5]
    x0 = [rd.uniform(-5, 5), rd.uniform(-5, 5)]
    i = 1
    res = []
    while i <= times:
        f_x0 = func(x0[0], x0[1])
        q = rd.randint(0, 1)
        x1 = copy.deepcopy(x0)
        x1[q] = rd.uniform(-5, 5)
        f_x1 = func(x1[0], x1[1])
        if f_x1 < f_x0:
            x0 = copy.deepcopy(x1)
        f_x0 = func(x0[0], x0[1])
        res.append(f_x0)
        i += 1
    x_i = np.linspace(0, times, times)
    plt.title("Ackley function")
    plt.xlabel("x axis number of iterations")
    plt.ylabel("y axis objective value")
    plt.plot(x_i, res)
    plt.show()

算法理解:随机变异每次随机的选取变异的特征,每次迭代只需要计算一次适应度的值。

算法2.4: 自适应爬山法

初始化 pm 属于 [0,1] 作为变异概率
x0 <- 随机生成的个体
while not ( 终止准则)
    计算x0的适应度f(x0)
    x1 <- x0
    For 每一个解的特征 q = 1,2,3...,n
        生成一个均匀分布的随机数r 属于[0, 1]
        if r < pm then
            用一个随机变异替换x1的第q个特征
        endif
    计算x1的适应度f(x1)
    if f(x1) > f(x0):
            x0 <- x1
    endif

算法实现: 

def adaptive_climb_mountains(func, times=1000, pm=0.3):
    x = [-5, 5]
    x0 = [rd.uniform(-5, 5), rd.uniform(-5, 5)]
    i = 1
    res = []
    f_x0 = func(x0[0], x0[1])
    while i <= times:
        x1 = copy.deepcopy(x0)
        for j in range(2):
            r = rd.uniform(0, 1)
            if r < pm:
                x1[j] = rd.uniform(-5, 5)
        f_x1 = func(x1[0], x1[1])
        if f_x1 < f_x0:
            x0 = copy.deepcopy(x1)
        f_x0 = func(x0[0], x0[1])
        res.append(f_x0)
        i += 1
    x_i = np.linspace(0, times, times)
    plt.title(f"Ackley function, pm={pm}")
    plt.xlabel("x axis number of iterations")
    plt.ylabel("y axis objective value")
    plt.plot(x_i, res)
    plt.show()

试验结果:

总结:爬山法可以用来求解确定性方法无法求解的优化问题,也跟更容易得到全局解,只要迭代次数足够多,但是每次的收敛速度可能是不一样的(将相同的代码运行多次,收敛速度不同,但是最后都收敛到了最优解

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值