import numpy as np
import matplotlib.pyplot as plt
# 建立“螞蟻”類
class Ant(object):
def __init__(self, path):
self.path = path # 螞蟻當(dāng)前迭代整體路徑
self.length = self.calc_length(path) # 螞蟻當(dāng)前迭代整體路徑長度
def calc_length(self, path_): # path=[A, B, C, D, A]注意路徑閉環(huán)
length_ = 0
for i in range(len(path_) - 1):
delta = (path_[i].x - path_[i + 1].x, path_[i].y - path_[i + 1].y)
length_ += np.linalg.norm(delta)
return length_
@staticmethod
def calc_len(A, B): # 靜態(tài)方法,計算城市A與城市B之間的距離
return np.linalg.norm((A.x - B.x, A.y - B.y))
# 建立城市類
class City(object):
def __init__(self, x, y):
self.x = x
self.y = y
##建立路徑類
class Path(object):
def __init__(self, A): #A為起始路徑
self.path = [A, A]
def add_path(self, B): #追加路徑信息,方便計算整體路徑長度
self.path.append(B)
self.path[-1], self.path[-2] = self.path[-2], self.path[-1]
##path = [A,B,C,D,A]
# 構(gòu)建“蟻群算法”的主體
class ACO(object):
def __init__(self, ants_num=50, maxIter=300, alpha=1, beta=5, rho=0.1, Q=1):
self.ants_num = ants_num ##螞蟻個數(shù)
self.maxIter = maxIter ##蟻群最大迭代次數(shù)
self.alpha = alpha ##信息啟發(fā)因子
self.beta = beta ##期望啟發(fā)因子
self.rho = rho ##信息素揮發(fā)速度
self.Q = Q ##信息素強度
#########################
self.deal_data("coordinates.dat") ##提取所有城市的坐標信息
#########################
self.path_seed = np.zeros(self.ants_num).astype(int) # 記錄一次迭代過程中每個螞蟻的初始城市下標
self.ants_info = np.zeros((self.maxIter, self.ants_num)) ##記錄每一次迭代后的所有螞蟻的路徑長度信息
self.best_path = np.zeros(self.maxIter) # 記錄每次迭代后整個蟻群的“歷史”最短路徑長度
###########################
self.solve() # 完成算法的迭代更新
self.display() # 數(shù)據(jù)可視化展示
def deal_data(self, filename):
with open(filename, 'rt') as f:
temp_list = list(line.split() for line in f) # 臨時存儲提取出來的坐標信息
self.cities_num = len(temp_list) # 1. 獲取城市個數(shù)
self.cities = list(City(float(item[0]), float(item[1])) for item in temp_list) # 2. 構(gòu)建城市列表
self.city_dist_mat = np.zeros((self.cities_num, self.cities_num)) # 3. 構(gòu)建城市距離矩陣
for i in range(self.cities_num):
A = self.cities[i]
for j in range(i, self.cities_num):
B = self.cities[j]
self.city_dist_mat[i][j] = self.city_dist_mat[j][i] = Ant.calc_len(A, B)
self.phero_mat = np.ones((self.cities_num, self.cities_num)) ##4.初始化信息素矩陣,(信息素初始化不能為零)
self.eta_mat = 1 / (self.city_dist_mat + np.diag([np.inf] * self.cities_num)) ##5.初始化啟發(fā)函數(shù)矩陣
def solve(self):
iterNum = 0 ##當(dāng)前迭代次數(shù)
while iterNum < self.maxIter:
self.random_seed() ##使整個蟻群產(chǎn)生隨機的起始點
delta_phero_mat = np.zeros((self.cities_num, self.cities_num)) ##初始化每次迭代后的信息素增量
######################################################
for i in range(self.ants_num):
city_index1 = self.path_seed[i] #記錄每只螞蟻訪問的第一個城市下標
ant_path = Path(self.cities[city_index1]) #記錄每只螞蟻訪問過的城市
tabu = [city_index1] #記錄每只螞蟻訪問過的城市下標,禁忌城市下標列表
non_tabu = list(set(range(self.cities_num)) - set(tabu))
for j in range(self.cities_num - 1): ##對余下的城市進行訪問
up_proba = np.zeros(self.cities_num - len(tabu)) ##初始化狀態(tài)遷移概率的分子
for k in range(self.cities_num - len(tabu)):
up_proba[k] = np.power(self.phero_mat[city_index1][non_tabu[k]], self.alpha) * np.power(
self.eta_mat[city_index1][non_tabu[k]], self.beta)
proba = up_proba / sum(up_proba) ##每條可能子路徑的狀態(tài)遷移概率
while True: # 提取出下一城市的下標
random_num = np.random.rand()
index_need = np.where(proba > random_num)[0]
if len(index_need) > 0:
city_index2 = non_tabu[index_need[0]]
break
ant_path.add_path(self.cities[city_index2])
tabu.append(city_index2)
non_tabu = list(set(range(self.cities_num)) - set(tabu))
city_index1 = city_index2
self.ants_info[iterNum][i] = Ant(ant_path.path).length
if iterNum == 0 and i == 0: ##完成對最佳路徑的記錄
self.best_cities = ant_path.path
else:
if self.ants_info[iterNum][i] < Ant(self.best_cities).length:
self.best_cities = ant_path.path
tabu.append(tabu[0]) ##每次迭代完成之后,使禁忌城市下標列表形成完整閉環(huán)
for l in range(self.cities_num):
delta_phero_mat[tabu[l]][tabu[l + 1]] += self.Q / self.ants_info[iterNum][i]
self.best_path[iterNum] = Ant(self.best_cities).length
self.update_phero_mat(delta_phero_mat) ##更新信息素矩陣
iterNum += 1 ##更新迭代次數(shù)
def update_phero_mat(self, delta):
self.phero_mat = (1 - self.rho) * self.phero_mat + delta
def random_seed(self): # 產(chǎn)生隨機的起始點表,盡量保證所有螞蟻的起始點不同
if self.ants_num <= self.cities_num: # 螞蟻數(shù)<=城市數(shù)
self.path_seed[:] = np.random.permutation(range(self.cities_num))[:self.ants_num];
else: #螞蟻數(shù) > 城市數(shù)
self.path_seed[:self.cities_num] = np.random.permutation(range(self.cities_num))
temp_index = self.cities_num
while temp_index + self.cities_num <= self.ants_num:
self.path_seed[temp_index:temp_index + self.cities_num] = np.random.permutation(range(self.cities_num))
temp_index += self.cities_num
temp_left = self.ants_num % self.cities_num
if temp_left != 0:
self.path_seed[temp_index:] = np.random.permutation(range(self.cities_num))[:temp_left]
def display(self): ##數(shù)據(jù)可視化
plt.figure(figsize=(6, 10))
plt.subplot(211)
plt.plot(self.ants_info, 'g.')
plt.plot(self.best_path, 'r-', label='history_best')
plt.xlabel("Iteration")
plt.ylabel("length")
plt.legend()
plt.subplot(212)
plt.plot(list(city.x for city in self.best_cities), list(city.y for city in self.best_cities), 'g-')
plt.plot(list(city.x for city in self.best_cities), list(city.y for city in self.best_cities), 'r.')
plt.xlabel("x")
plt.ylabel("y")
plt.savefig("Ant.png", dpi=500)
plt.show()
plt.close()
蟻群算法代碼
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 問題描述 ??該問題來源于參加某知名外企的校招面試。根據(jù)面試官描述,一塊木板有數(shù)百個小孔(坐標已知),現(xiàn)在需要通過...
- 引言 按照上一章的算法流程,本章給出一個自己用Java代碼及面向?qū)ο笏悸穼崿F(xiàn)的蟻群算法。盡量追求代碼的質(zhì)量、可讀性...
- 姓名:彭帥 學(xué)號:17021210850 【嵌牛導(dǎo)讀】:蟻群算法(ACO)是受自然界中螞蟻搜索食物行為的啟發(fā),是一...