蟻群算法代碼

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ù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容