蚁群算法python实现

import tkinter
from functools import reduce
import time

import numpy as np

"""
蚁群算法ACO python实现
1.0版本
sugarMei
2020 5-27

"""

# 初始化参数
'''
alpha:信息素影响的强度大小
beta:可见度影响的强度大小
rho:信息素挥发因子
q:常数 用于计算每次一次遍历后的信息素强度变化程度
eta:从i城市到j城市的可见度
distance_graph:城市i到j的距离dij
pheromone:信息素矩阵 pij表示城市i到j城市的边的信息素的大小
path:路径表 pj表示第j只蚂蚁的路径表
length:记录一次循环中每个蚂蚁的路径长度li
'''
alpha, beta, rho, q, generation, generations = 1, 2, 0.5, 100, 0, 300
cities, ants = 50, 75
distance_x = [
    178, 272, 176, 171, 650, 499, 267, 703, 408, 437, 491, 74, 532,
    416, 626, 42, 271, 359, 163, 508, 229, 576, 147, 560, 35, 714,
    757, 517, 64, 314, 675, 690, 391, 628, 87, 240, 705, 699, 258,
    428, 614, 36, 360, 482, 666, 597, 209, 201, 492, 294]
distance_y = [
    170, 395, 198, 151, 242, 556, 57, 401, 305, 421, 267, 105, 525,
    381, 244, 330, 395, 169, 141, 380, 153, 442, 528, 329, 232, 48,
    498, 265, 343, 120, 165, 50, 433, 63, 491, 275, 348, 222, 288,
    490, 213, 524, 244, 114, 104, 552, 70, 425, 227, 331]

distance_graph = np.zeros((cities, cities))
# 画图
root = tkinter.Tk()
canvas = tkinter.Canvas(
    root,
    width=800,
    height=600,
    bg="#EBEBEB",  # 背景白色
    xscrollincrement=1,
    yscrollincrement=1
)
canvas.pack(expand=tkinter.YES, fill=tkinter.BOTH)
r = 5
nodes = []  # 节点坐标
nodes2 = []  # 节点对象
# 初始化城市节点
filename = tkinter.PhotoImage(file="/Users/sugarmei/PycharmProjects/sugarmei/es/city.png")

for i in range(len(distance_x)):
    # 在画布上随机初始坐标
    x = distance_x[i]
    y = distance_y[i]
    nodes.append((x, y))
    # 生成节点椭圆,半径为self.__r
    node = canvas.create_image(x, y, image=filename, tags="node")
    # node = canvas.create_oval(x - r,
    #                           y - r, x + r, y + r,
    #                           fill="#ff0000",  # 填充红色
    #                           outline="#000000",  # 轮廓白色
    #                           tags="node",
    #                           )
    nodes2.append(node)
    # 显示坐标
    canvas.create_text(x, y-20,  # 使用create_text方法在坐标(302,77)处绘制文字
                       text='',  # 所绘制文字的内容
                       fill='black'  # 所绘制文字的颜色为灰色
                       )


def title(s):
    root.title(s)


# 将节点按order顺序连线
def line(order):
    # 删除原线
    canvas.delete("line")

    def line2(i1, i2):
        p1, p2 = nodes[i1], nodes[i2]
        canvas.create_line(p1, p2, fill="#000000", tags="line")
        return i2

    # order[-1]为初始值
    reduce(line2, order, order[-1])


# 计算城市之间的距离
for i in range(cities):
    for j in range(cities):
        temp_distance = pow((distance_x[i] - distance_x[j]), 2) + pow((distance_y[i] - distance_y[j]), 2)
        temp_distance = pow(temp_distance, 0.5)
        distance_graph[i][j] = temp_distance
eta = 1.0 / (distance_graph + np.diag([1e10] * cities))
pheromone = np.ones((cities, cities))
path = np.zeros((ants, cities), dtype=np.int)
# 最佳路径
best_path = []
best_length = np.inf

while generation < generations:
    # 初始化蚂蚁位置
    if ants < cities:
        path[:, 0] = np.random.permutation(cities)[:ants]
    else:
        path[:cities, 0] = np.random.permutation(cities)[:]
        path[cities:, 0] = np.random.permutation(cities)[:ants - cities]
    length = np.zeros(ants)
    # 计算第k只蚂蚁从i城市到达j城市的概率
    for k in range(ants):
        visited = path[k, 0]
        unvisited = set(range(cities))
        unvisited.remove(visited)

        for i in range(1, cities):
            l_unvisited = list(unvisited)
            prob_next_city = np.zeros(len(l_unvisited))
            for j in range(len(l_unvisited)):
                prob_next_city[j] = pow(pheromone[visited][l_unvisited[j]], alpha) * pow(eta[visited][l_unvisited[j]],
                                                                                         beta)
            prob_next_city = prob_next_city / sum(prob_next_city)
            temp_prob = np.random.random()
            cur_prob = 0
            next_city = -1
            # 轮盘赌算法
            for p in range(len(prob_next_city)):
                cur_prob += prob_next_city[p]
                # 第p个城市赌成功
                if cur_prob >= temp_prob:
                    next_city = l_unvisited[p]
                    break
            unvisited.remove(next_city)
            path[k, i] = next_city
            length[k] += distance_graph[visited][next_city]
            visited = next_city
        length[k] += distance_graph[visited][path[k, 0]]
    # 调整最短长度和最佳路径
    if length.min() < best_length:
        best_length = length.min()
        best_path = path[length.argmin()]
        line(best_path)
    root.title("ACO 第 " + str(generation) + " 次迭代" + " 当前最短长度:" + str(best_length))
    root.update()

    # time.sleep(10)
    # 本轮遍历一次全部城市结束 调整信息素强度
    tmp_pheromone = np.zeros((cities, cities))
    for i in range(ants):
        for j in range(cities - 1):
            # 使用了蚁环算法
            # length[i]为第i只蚂蚁当前次遍历的路径长度 作为整体信息进行信息素的更新
            tmp_pheromone[path[i, j]][path[i, j + 1]] += q / length[i]
            # 从j城市到i城市的距离dji与dij一致 因此信息素浓度一致
            if tmp_pheromone[path[i, j + 1]][path[i, j]] < tmp_pheromone[path[i, j]][path[i, j + 1]]:
                tmp_pheromone[path[i, j + 1]][path[i, j]] = tmp_pheromone[path[i, j]][path[i, j + 1]]
        tmp_pheromone[path[i, cities - 1]][path[i, 0]] += q / length[i]
        # 蚁密算法
        # tmp_pheromone[path[i, j]][path[i, j + 1]] += q
        # tmp_pheromone[path[i, cities - 1]][path[i, 0]] += q
        # 蚁量算法 与当前城市之间距离成反比
        # tmp_pheromone[path[i, j]][path[i, j + 1]] += q / distance_graph[path[i, j]][path[i, j + 1]]
        # tmp_pheromone[path[i, cities - 1]][path[i, 0]] += q / distance_graph[path[i, cities - 1]][path[i, 0]]
    # 更新从i到j城市的路径的信息素浓度
    pheromone = (1 - rho) * pheromone + tmp_pheromone
    generation += 1
    print("当前迭代次数:", generation, "当前最短长度:", best_length)

print("迭代次数:", generations)
print("最佳路径:", best_path)
print("最短长度:", best_length)

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值