人工蜂群算法的python实现

    科技2025-05-20  40

    对于网上的一些蜂群算法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()

     

    Processed: 0.011, SQL: 8