优化算法 | 人工蜂群算法(附Python代码)

优化算法 | 人工蜂群算法(附Python代码)

今天为各位更新 人工蜂群算法(Artificial Bee Colony,ABC)的Python代码 ,之前我们在 MATLAB数学建模(十一) | 人工蜂群算法(附MATLAB代码) 这篇推文讲解了ABC算法的基本思想,忘记ABC算法的小伙伴可以点击上述链接复习一下。

目录

1.ABC算法基本步骤

2.ABC算法Python代码

3.ABC算法实例验证


1.ABC算法基本步骤

1)初始化各蜜源 X_i ; 设定参数 NP limit 以及最大迭代次数 maxIt ; 计数器初始化 it=1 ;
2)为蜜源 X_i 分配一只引领蜂,按式 v_{i d}=x_{i d}+\varphi\left(x_{i d}-x_{j d}\right) 进行搜索,产生新蜜源 V_i ;
3)依据式 f i t_{i}= \begin{cases}1 /\left(1+f_{i}\right), & f_{i} \geqslant 0 \\ 1+\operatorname{abs}\left(f_{i}\right), & \text { otherwise }\end{cases} 评价 V_i 的适应度,根据贪婪选择的方法确定保留的蜜源;
4)由式 p_{i}=f i t_{i} / \sum_{i=1}^{N P} f i t_{i} 计算引领蜂找到的蜜源被跟随的概率;
5)跟随峰采用与引领蜂相同的方式进行搜索,根据贪婪选择的方法确定保留的蜜源;
6)判断蜜源 是否满足被放弃的条件。如满足,对应的引领蜂角色变为侦察蜂,否则直接转到8);
7)侦察蜂根据式 X_{i}^{t+1}=\left\{\begin{array}{l} L_{d}+\operatorname{rand}(0,1)\left(U_{d}-L_{d}\right), \operatorname{trial}_{i} \geqslant \text { limit } \\ X_{i}^{t}, \operatorname{trial}_{i}<\text { limit } \end{array}\right. 随机产生新蜜源;
8) it=it+1 ; 判断算法是否满足终止条件,若满足则终止,输出最优解,否则转到2)。

更多关于ABC算法详细内容详见 MATLAB数学建模(十一) | 人工蜂群算法(附MATLAB代码)


2.ABC算法Python代码

整个ABC算法Python代码共包含两个.py文件,即artificial_bee_colony.py和app.py。**这里需要注意的是,需要各位自行安装ypstruct库,安装方法可以参考 pypi.org/project/ypstru **。

artificial_bee_colony.py文件如下所示:

import numpy as np
from ypstruct import structure
def run(problem, params):
    # 函数信息
    costfunc = problem.costfunc
    nvar = problem.nvar
    varmin = problem.varmin
    varmax = problem.varmax
    # 参数信息
    maxit = params.maxit
    npop = params.npop
    nonlooker = params.nonlooker
    limit = int(np.round(0.6*nvar*npop))
    a = params.a
    # 空的蜂群结构
    empty_bee = structure()
    empty_bee.position = None
    empty_bee.cost = None
    # 临时蜂群结构
    newbee = structure()
    newbee.position = None
    newbee.cost = None
    # 初始化全局最优解
    bestsol = empty_bee.deepcopy()
    bestsol.cost = np.inf
    # 种群初始化
    pop = empty_bee.repeat(npop)
    for i in range(npop):
        pop[i].position = np.random.uniform(varmin, varmax, nvar)
        pop[i].cost = costfunc(pop[i].position)
        if pop[i].cost < bestsol.cost:
            bestsol = pop[i].deepcopy()
    # 初始化每个个体的抛弃次数
    count = np.empty(npop)
    # 记录每一代中全局最优个体目标函数值
    bestcost = np.empty(maxit)
    # 人工蜂群算法主循环
    for it in range(maxit):
        # 引领蜂
        for i in range(npop):
            # 随机选择k,不等于i
            K = np.append(np.arange(0,i),np.arange(i+1,npop))
            k = K[np.random.randint(K.size)]
            # 定义加速系数
            phi = a * np.random.uniform(-1, 1, nvar)
            # 新的蜜蜂位置
            newbee.position = pop[i].position + phi * (pop[i].position - pop[k].position)
            # 计算新蜜蜂目标函数值
            newbee.cost = costfunc(newbee.position)
            # 通过比较目标函数值,更新第i个蜜蜂的位置
            if newbee.cost < pop[i].cost:
                pop[i] = newbee.deepcopy()
            else:
                count[i] += 1
        # 计算适应度值和选择概率
        fit = np.empty(npop)
        meancost = np.mean([pop[i].cost for i in range(npop)])
        for i in range(npop):
            fit[i] = np.exp(-pop[i].cost/meancost)     #将目标函数值转换为适应度值
        probs = fit / np.sum(fit)
        # 跟随蜂
        for m in range(nonlooker):
            # 通过轮盘赌的方式选择蜜源
            i = roulette_wheel_selection(probs)
            # 随机选择k,不等于i
            K = np.append(np.arange(0, i), np.arange(i + 1, npop))
            k = K[np.random.randint(K.size)]
            # 定义加速系数
            phi = a * np.random.uniform(-1, 1, nvar)
            # 新的蜜蜂位置
            newbee.position = pop[i].position + phi * (pop[i].position - pop[k].position)
            # 计算新蜜蜂目标函数值
            newbee.cost = costfunc(newbee.position)
            # 通过比较目标函数值,更新第i个蜜蜂的位置
            if newbee.cost < pop[i].cost:
                pop[i] = newbee.deepcopy()
            else:
                count[i] += 1
        # 侦察蜂
        for i in range(npop):
            if count[i] > limit:
                pop[i].position = np.random.uniform(varmin, varmax, nvar)
                pop[i].cost = costfunc(pop[i].position)
                count[i] = 0
        # 更新全局最优解
        for i in range(npop):
            if pop[i].cost < bestsol.cost:
                bestsol = pop[i].deepcopy()
        # 存储每一代全局最优解的目标函数值
        bestcost[it] = bestsol.cost
        # 展示迭代信息
        print("Iteration {}: Best Cost = {}".format(it, bestcost[it]))
    # 返回值
    out = structure()
    out.pop = pop
    out.bestsol = bestsol
    out.bestcost = bestcost
    return out
def roulette_wheel_selection(p):
    c = np.cumsum(p)
    r = sum(p) * np.random.rand()
    ind = np.argwhere(r <= c)
    return ind[0][0]

app.py文件如下所示:

import matplotlib.pyplot as plt
import numpy as np
from ypstruct import structure
import time
import artificial_bee_colony
start = time.time()         #运行开始时刻
# 测试函数
def sphere(x):
    return sum(x**2)
# 问题定义
problem = structure()
problem.costfunc = sphere
problem.nvar = 10
problem.varmin = -100 * np.ones(10)
problem.varmax = 100 * np.ones(10)
# ABC参数
params = structure()
params.maxit = 500
params.npop = 100
params.nonlooker = 100
params.a = 1
# 运行ABC
out = artificial_bee_colony.run(problem, params)
# 运行结果
plt.rcParams['font.sans-serif'] = ['KaiTi']  #设置字体为楷体
plt.plot(out.bestcost)
print("最优解:{}".format(out.bestsol))
end = time.time()              # 运行结束时刻
print('运行时间:{}s'.format(end-start))
plt.xlim(0, params.maxit)