蚁群算法是一种经典的传统人工智能算法,早在上个世纪90年代就提出了。网络中已经有很多教材与教程,这里不再复述。
推荐《人工智能导论》(第四版),王万良编著,其6.7章节将蚁群算法讲的非常简单清楚。
网上也有很多matlab版本,java版本的蚁群算法模板。
笔者周日为了练习编码能力,完成了python版本的蚁群算法。文末附上github开源代码网址,项目中有测试样例与实验数据。
self.Maximum = np.inf # 设定最大值
self.readCitMapfromTxt()
self.citymap = np.array(np.full((self.mapSize,self.mapSize),self.Maximum)) # citymap[i][j] 表示 城市i,j的距离
self.visionDistsnce = np.array(np.full((self.mapSize, self.mapSize),0)) # 能见度 是 距离的倒数
self.antNumber = 50 # 蚁群规模
self.initialInfomationRemain = 100 # 初始化的信息素
self.informationMap = np.array(np.full((self.mapSize, self.mapSize), self.initialInfomationRemain))
self.alpha = 1 # a值,a越大,说明该蚂蚁更倾向于走其他蚂蚁走过的路径
self.beta = 5 # b值,b越大,说明该蚂蚁更倾向于局部信息作出判断,达成局部最优解
self.rho = 0.9 # Rho值,信息素残留常数
self.heuristicRate = 1 # 启发式的比例
self.infomationFadeOutRate = 1 - self.rho # 信息素挥发率,越大,之前搜索过的路径再被搜索的概率也大,
# 越小,提高随机性与全局搜索能力,但是算法收敛程度降低
self.Q = 100 # Q值,为一圈下来,一只蚂蚁能释放出的信息素的数量
self.iterateNumber = 30 # 设计迭代次数
self.antLoopDistance = [0 for i in range(self.antNumber)] # 蚂蚁跑完一圈后的路程
self.minDistance = 1e9 # 最短路径的长度
self.minDistanceTrace = [] # 存最短路径的序列
self.ant = [] # 记录蚂蚁的轨迹
随机放置蚂蚁
# 初始化蚂蚁的位置
def setAnt(self):
for i in range(self.antNumber):
startCity = random.randint(0,self.mapSize-1) # 闭区间
self.ant.append([startCity])
每次迭代,信息素会褪去
# 信息素褪去
def informationFadeOut(self):
for i in range(len(self.informationMap)):
for j in range(len(self.informationMap[i])):
self.informationMap[i][j] *= self.rho
在信息素褪去后再根据每只蚂蚁的路劲来更新信息素地图
# 更新信息素
def updateInformationMap(self):
# 计算第i只蚂蚁更新的信息素
for i in range(self.antNumber):
informationAllocation = np.array(np.full((self.mapSize, self.mapSize), float(0)))
for j in range(len(self.ant[i])):
# 起始城市与末位城市相连
if j == 0:
self.informationMap[self.ant[i][j]][self.ant[i][-1]] += self.Q * self.citymap[self.ant[i][j]][self.ant[i][-1]] / self.antLoopDistance[i]
self.informationMap[self.ant[i][-1]][self.ant[i][j]] += self.Q * self.citymap[self.ant[i][-1]][self.ant[i][j]] / self.antLoopDistance[i]
else:
self.informationMap[self.ant[i][j]][self.ant[i][j-1]] += self.Q * self.citymap[self.ant[i][j]][self.ant[i][j-1]] / self.antLoopDistance[i]
self.informationMap[self.ant[i][j-1]][self.ant[i][j]] += self.Q * self.citymap[self.ant[i][j-1]][self.ant[i][j]] / self.antLoopDistance[i]
每次迭代,要清理历史路径等重要参数
# 更新重要信息
def updateAntInformation(self):
for i in range(self.antNumber):
startCity = self.ant[i][0]
del self.ant[i][:]
self.ant[i].append(startCity)
self.antLoopDistance[i] = 0
# print(self.ant[i])
# 蚂蚁做路径选择
def antChoice(self,antNumber):
curruntCity = self.ant[antNumber][-1]
visitedCity = set(self.ant[antNumber])
allowedCity = set(range(0,self.mapSize)) - visitedCity
# 计算启发式参数,距离越近概率越大
distanceSum = float(0)
for city in allowedCity:
distanceSum += self.citymap[curruntCity][city]
# 启发式初始为0
heuristic = np.array(np.full((self.mapSize), float(0)))
for city in allowedCity:
heuristic[city] = self.heuristicRate * distanceSum / self.citymap[curruntCity][city]
# 计算该蚂蚁所有可能性
posibility = [float(0) for i in range(self.mapSize)]
posibilitySum = float(0)
for city in allowedCity:
posibility[city] = np.power(self.informationMap[curruntCity][city],self.alpha) * np.power(heuristic[city],self.beta)
posibilitySum += posibility[city]
# 计算最后可能性
finalPosibility = [float(0) for i in range(self.mapSize)]
for city in allowedCity:
finalPosibility[city] = posibility[city] / posibilitySum
# 最后根据可能性中随机选择
# 此处存在问题
anchor = random.random()
psum = float(0)
for choiceCity in range(self.mapSize) :
if psum < anchor and ( psum + finalPosibility[choiceCity] ) > anchor :
return choiceCity
psum += finalPosibility[choiceCity]
return allowedCity.pop()
此函数按照迭代次数要求,整合了上诉各个功能
# 蚁群算法主要函数
def doACO(self):
self.setAnt()
for l in range(self.iterateNumber):
print("In "+str(l)+" iteration!")
# 蚂蚁i开始依次搜索
for i in range(self.antNumber):
# 蚂蚁i没有跑圈就继续搜索
while len(self.ant[i]) < self.mapSize:
# 蚂蚁根据信息素和启发式选择下一个城市
choiceCity = self.antChoice(i)
self.antLoopDistance[i] += self.citymap[self.ant[i][-1]][choiceCity]
self.ant[i].append(choiceCity)
# 蚂蚁i已经走到了一圈
self.antLoopDistance[i] += self.citymap[self.ant[i][0]][self.ant[i][-1]]
if self.antLoopDistance[i] < self.minDistance :
self.minDistance = self.antLoopDistance[i]
print("min ant " + str(i)+ " trace as :" ,self.ant[i])
self.minDistanceTrace = self.ant[i].copy()
# 所有蚂蚁搜索完了,信息素褪去
self.informationFadeOut()
# 蚂蚁搜索完了要留下,新的信息素
self.updateInformationMap()
# 更新重要信息
self.updateAntInformation()
print("Finish search!")
print("Min distance is :", self.minDistance)
# print("Trace is :",self.minDistanceTrace)
print("Trace is :")
for i in self.minDistanceTrace:
print(self.cityNumber[i], end=' ')
GayHubGithub传送门