優化算法(四)蟻羣算法

import numpy as np
import matplotlib.pyplot as plt


# 計算距離和
def distance_sum(point, distances):
    res = 0.
    for index in range(len(point)-1):
        res += distances[point[index]][point[index+1]]
    return res


# 獲取選擇下一城市的權重字典
def right(begin, unvisited, matrix, distances, alpha, beta, Q):

    # 計算權重
    data = dict()
    for end in unvisited:
        data[end] = ((Q / distances[begin][end]) ** beta) * (matrix[begin][end] ** alpha)

    # 權重和
    s = sum(data.values())

    # 權重字典
    for index in unvisited:
        data[index] = data[index] / s
    return data


# 通過權重字典選擇下一城市
def next(right_dict):

    # 獲取概率
    p = np.random.random()

    # 概率求和
    ps = 0.

    # 獲取下一座城市
    last = 0
    for index in right_dict:
        last = index
        ps += right_dict[index]
        if p < ps:
            return index
    return last


def ACO(x, y, m=150, n=60, alpha=1, beta=5, Q=1, rho=0.1):

    # 城市數量
    city_num = len(x)

    # 城市編號
    city = [i for i in range(city_num)]

    # 構造節點
    points = []
    for i in city:
        points.append((x[i], y[i]))

    # 計算間距
    distances = np.zeros((city_num, city_num))
    for i in range(city_num):
        for j in range(city_num):
            distance = (points[i][0] - points[j][0]) ** 2 + (points[i][1] - points[j][1]) ** 2
            distance = np.sqrt(distance)
            distances[i][j] = distance

    # 初始化最優解
    pg = [i for i in range(city_num)]

    # 初始化信息素濃度
    pheromonetable = np.ones((city_num, city_num))

    # 主循環
    for i in range(m):

        # 每一次主循環的蟻羣路徑
        paths = np.zeros((city_num, city_num))

        for j in range(n):

            # 起點
            begin = np.random.randint(0, city_num)

            # 記錄個體路徑
            temp = [begin]

            # 未訪問的城市列表
            unvisited = city[:]
            unvisited.remove(begin)

            while len(unvisited) > 0:

                # 計算下一個訪問的城市
                rights = right(begin, unvisited, pheromonetable, distances, alpha, beta, Q)
                next_city = next(rights)

                # 記錄路徑
                paths[begin][next_city] += 1
                temp.append(next_city)

                # 設置禁忌表
                unvisited.remove(next_city)

                # 重置起點
                begin = next_city

            # 更新最優解
            if distance_sum(temp, distances) < distance_sum(pg, distances):
                pg = temp[:]

        # 更新信息素
        pheromonetable *= (1 - rho)
        for v in range(city_num):
            for u in range(city_num):
                if v != u:
                    pheromonetable[v][u] += (paths[v][u] * (Q / distances[v][u]))

        print((i, distance_sum(pg, distances)))

    return pg


# 準備數據
number = 100
x = np.round(np.random.rand(number) * 100)
y = np.round(np.random.rand(number) * 100)
plt.plot(x, y, '.')

# 轉換爲點集
points = []
for i in range(number):
    points.append((x[i], y[i]))

# 蟻羣算法
pg = ACO(x, y)

# 結果可視化
xx = []
yy = []
for i in pg:
    xx.append(points[i][0])
    yy.append(points[i][1])

plt.plot(xx, yy)
plt.show()
plt.cla()

蟻羣算法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章