人工蜂群算法的python实现

对于网上的一些蜂群算法python实现的代码,笔者认为多数不够简洁易懂且可扩展性和可修改性不足,干脆自己实现一个吧(虽然可能也存在上述问题...)。蜂群算法原理较简单,在此不再赘述,可参考这篇博客,且其中的C++代码比较好理解。

代码如下(python3.6,画图需要matplotlib包):

import math
import random
import matplotlib.pyplot as plt

from typing import List


class ProblemModel:

    def __init__(self, bounds=None):
        self.bounds = bounds

    def getIndependentVar(self):
        if self.bounds is not None:
            independentVar = []
            for bound in self.bounds:
                independentVar.append(bound[0] + random.random() * (bound[1] - bound[0]))
            return independentVar
        else:
            pass

    def getNewVar(self, var_1, var_2):
        if self.bounds is not None:
            newVar = []
            step_random = random.random()
            for v_1, v_2 in zip(var_1, var_2):
                newVar.append(v_1 + step_random * (v_2 - v_1))
            return newVar
        else:
            pass

    def getValue(self, variable):
        if len(variable) == 2:
            x = variable[0]
            y = variable[1]
            return 1+(x**2+y**2)/4000-(math.cos(x)*math.cos(y/math.sqrt(2)))
            # return -(x**2-10*math.cos(2*math.pi*x)+10)+(y**2-10*math.cos(2*math.pi*y)+10)
            # return -20*math.exp(-0.2*math.sqrt((x**2+y**2)/2))-math.exp((math.cos(2*math.pi*x)+math.cos(2*math.pi*y))/2)+20+math.e
        else:
            return 1


class NectarSource:
    problem_src = None  # static variable

    def __init__(self, position):
        self.position = position
        self.value = self.problem_src.getValue(position)
        if self.value >= 0:
            self.fitness = 1/(1+self.value)
        else:
            self.fitness = 1+math.fabs(self.value)
        # this definition of fitness means looking for the minimum
        self.trail = 0


class ABCAlgor:
    LIMIT = 10  # If the num of times a source not be updated is more than this, then give up.

    def __init__(self, problem, employedNum, onlookerNum, maxIteration):
        NectarSource.problem_src = problem
        self.problem = problem  # type:ProblemModel
        self.employedNum = employedNum
        self.onlookerNum = onlookerNum
        self.maxIteration = maxIteration
        self.nectarSrc = []  # type:List[NectarSource]
        self.bestNectar = NectarSource(self.problem.getIndependentVar())
        self.resultRecord = []
        for i in range(self.employedNum):
            self.nectarSrc.append(NectarSource(self.problem.getIndependentVar()))

    def updateNectarSrc(self, index):
        # produce a new nectar; if new.fit>old.fit: replace the old; else: old.trail++;
        src = self.nectarSrc[index]
        src_another = random.choice(self.nectarSrc)  # type:NectarSource
        while src_another is src:
            src_another = random.choice(self.nectarSrc)
        src_new = NectarSource(self.problem.getNewVar(src.position, src_another.position))
        if src_new.fitness > src.fitness:
            self.nectarSrc[index] = src_new
        else:
            self.nectarSrc[index].trail += 1

    def employedProcedure(self):
        length = len(self.nectarSrc)  # len(self.nectarSrc) may be changed in self.updateNectarSrc
        for i in range(length):
            self.updateNectarSrc(i)

    def onlookerProcedure(self):
        sum_fitness = 0
        for src in self.nectarSrc:
            sum_fitness += src.fitness
        length = len(self.nectarSrc)
        for i in range(length):
            probability_fit = self.nectarSrc[i].fitness/sum_fitness
            for onlookerBee in range(self.onlookerNum):
                if random.random() < probability_fit:
                    self.updateNectarSrc(i)

    def updateBestNectar(self):
        # use the fitness to select the best, if the problem is finding the max, change the definition of fitness
        for src in self.nectarSrc:
            if src.fitness > self.bestNectar.fitness:
                self.bestNectar = src

    def scoutProcedure(self):
        length = len(self.nectarSrc)
        for i in range(length):
            if self.nectarSrc[i].trail >= self.LIMIT:
                self.nectarSrc[i] = NectarSource(self.problem.getIndependentVar())

    def solve(self):
        for i in range(self.maxIteration):
            self.employedProcedure()
            self.onlookerProcedure()
            self.updateBestNectar()
            self.scoutProcedure()
            self.updateBestNectar()
            self.resultRecord.append(self.bestNectar.value)

    def showResult(self):
        for result in self.resultRecord:
            print(result)
        print('best solution:', self.bestNectar.position)
        print('best value:', self.bestNectar.value)
        plt.plot(self.resultRecord)
        plt.title('result curve')
        plt.tight_layout()
        plt.show()


if __name__ == '__main__':
    beesNum = 100
    employedNum = int(beesNum/2)
    onlookerNum = int(beesNum/2)
    maxIteration = 200
    problem = ProblemModel(bounds=[[-10, 10], [-10, 10]])
    abcSolution = ABCAlgor(problem, employedNum, onlookerNum, maxIteration)
    abcSolution.solve()
    abcSolution.showResult()

 

  • 7
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值