出门游玩,运用百度api 和蚁群算法 ,解决基于现实实时数据的 旅行商问题

# 导入相关的包
# -- coding: utf-8 --**
import requests #HTTP请求
import time
import re
import json # 用于解析Json
import pandas as pd # 用于处理数据(数据分析相关的同学必须会的包)
import pandas
import csv
import re
import time
import json
from urllib.request import urlopen
import urllib
import random
import copy
import sys
import tkinter  # //GUI模块
import threading
from functools import reduce
from geopy.distance import geodesic
import numpy as np

'''https://blog.csdn.net/Fuel_Ming/article/details/117193433'''

'https://blog.csdn.net/Fuel_Ming/article/details/117193433'

开发简易文档:

需求:

给定指定地点,获取最短路径问题 ,也就是解决现实生活中的旅行商问题

实现步骤:
1.调用百度api,获取各个地点的经纬度(关于百度api的使用请查阅最后的引用文献)
2.将各个地点经纬度换算为distance 单位: km 并获得cost loss ,默认为对应的最佳公交地铁时间花费,
3.采用蚁群算法获取最短路径

以下为程序生成的实际显示
在这里插入图片描述

在这里插入图片描述

df = pd.DataFrame(['广东工业大学(大学城校区)','广州市鲁迅纪念馆','广州天河宜家',
'广州五仙观',
'广州Lavie拉维电影公馆',
'广州近代史博物馆',
'广州余荫山房 番禺区',
])

df.columns = ['location']
ak = 'pOSMq456AFQuZyYfTlCBGcB8GG2VakRm'
def get_result(x,ak):
    """

    :param x: 传入一个字符串类型的地点
    :return: ([坐标],类别,置信度)
    """
    Post_url = "https://api.map.baidu.com/geocoding/v3/?address=" + x + f"&output=json&ak={ak}&callback=showLocation"
    Post_data = {
        'address' : x
    }
    se = requests.session()
    Text = se.post(Post_url, data=Post_data).text.replace("'", '"').replace('/ ', '/')[27:-1]
    jsonValue = json.loads(Text) # 转化为Json对象
    if ("result" in jsonValue):
        return  (jsonValue['result']['location']['lng'],jsonValue['result']['location']['lat']),jsonValue['result']['level'],jsonValue['result']['confidence']
    else: return  ''
result = {
    'name' :df['location'].values,
    'position' : [],
    'category' : [],
    'confidence' : []
}
for value in df.values:
    tmp = get_result(value[0],ak)
    if tmp != '':
        result['position'].append(tmp[0])
        result['category'].append(tmp[1])
        result['confidence'].append(tmp[2])
result
{'name': array(['广东工业大学(大学城校区)', '广州市鲁迅纪念馆', '广州天河宜家', '广州五仙观', '广州Lavie拉维电影公馆',
        '广州近代史博物馆', '广州余荫山房 番禺区'], dtype=object),
 'position': [(113.39959744237572, 23.045704807207507),
  (113.2841059860486, 23.13014496993394),
  (113.42238287179822, 23.111107776003106),
  (113.26630839796859, 23.126907167141244),
  (113.32622196190339, 23.101572988503353),
  (113.28977420398412, 23.13464065626514),
  (113.4019110989934, 23.017728378073617)],
 'category': ['教育', '旅游景点', '餐饮', '旅游景点', '休闲娱乐', '旅游景点', '旅游景点'],
 'confidence': [70, 50, 80, 50, 70, 50, 50]}
recoder = pd.DataFrame(result)
recoder
namepositioncategoryconfidence
0广东工业大学(大学城校区)(113.39959744237572, 23.045704807207507)教育70
1广州市鲁迅纪念馆(113.2841059860486, 23.13014496993394)旅游景点50
2广州天河宜家(113.42238287179822, 23.111107776003106)餐饮80
3广州五仙观(113.26630839796859, 23.126907167141244)旅游景点50
4广州Lavie拉维电影公馆(113.32622196190339, 23.101572988503353)休闲娱乐70
5广州近代史博物馆(113.28977420398412, 23.13464065626514)旅游景点50
6广州余荫山房 番禺区(113.4019110989934, 23.017728378073617)旅游景点50
names=['序号','起点纬度','起点经度','终点纬度','终点经度']
dataList = []  # 储存获取的路线数据
akn=0 # 使用第几个ak
for i , name1 in enumerate(recoder['name']):
    for j ,name2 in enumerate(recoder['name']):
        if name1 == name2:
            dataList.append([0,0,0,0,0,0,0])
            continue

        out_lat = recoder.at[i,'position'][1]
        out_lng = recoder.at[i,'position'][0]
        des_lat = recoder.at[j, 'position'][1]
        des_lng = recoder.at[j, 'position'][0]
        """
        # 获取驾车路径:常规路线规划(不考虑路况)
        以下是可选参数
        #  tactics =10不走高速;=11常规路线;=12距离较短;=13距离较短
        """
        url_drive = r"http://api.map.baidu.com/routematrix/v2/driving?output=json&origins={0},{1}&destinations={2},{3}&{4}&tactics=11&ak={4}".format(out_lat,out_lng,des_lat,des_lng,ak)
        result_drive = json.loads(urlopen(url_drive).read())  # json转dict
        status_drive = result_drive['status']
        if status_drive == 0:  # 状态码为0:无异常
            distance_drive = round(result_drive['result'][0]['distance']['value'] / 1000,3)  # 里程(k米)
            timesec_drive = round(result_drive['result'][0]['duration']['value'] /60,2)   # 耗时(分钟)


        elif status_drive == 302 or status_drive == 210 or status_drive == 201:  # 302:额度不足;210:IP验证未通过
            distance_drive = timesec_drive = 'AK错误'
        else:
            distance_drive = timesec_drive = '请求错误'


        """
        ### 以下是乘车规划
        可选参数
        tac_bus = r'&tactics_incity=0'
        # 市内公交换乘策略 可选,默认为0      0推荐;1少换乘;2少步行;3不坐地铁;4时间短;5地铁优先
        city_bus = r'&tactics_intercity=0'
        # 跨城公交换乘策略  可选,默认为0    0时间短;1出发早;2价格低;
        city_type = r'&trans_type_intercity=0'
        # 跨城交通方式策略  可选,默认为0  0火车优先;1飞机优先;2大巴优先;
        """
        url_bus = r'http://api.map.baidu.com/direction/v2/transit?output=json&origin={0},{1}&destination={2},{3}&{4}&ak={4}'.format(out_lat,out_lng,des_lat,des_lng,ak)
        result_bus = json.loads(urlopen(url_bus).read())
        status_bus = result_bus['status']
        if status_bus == 0:
            rsls = result_bus['result']['routes']
            if rsls == []:    # 无方案时状态也为0,但只返回一个空list
                distance_bus = timesec_bus = cost_bus = '无公交方案'
            else:
                distance_bus = round(result_bus['result']['routes'][0]['distance'] / 1000,3)  # 乘车路线距离总长(km)
                timesec_bus = round(result_bus['result']['routes'][0]['duration'] / 60,2)  # 乘车时间(分钟)
                cost_bus = result_bus['result']['routes'][0]['price']  # 乘车费用(元)
        elif status_bus == 302 or status_bus == 210 or status_bus == 201:
            distance_bus = timesec_bus = cost_bus = 'AK错误'

        elif status_bus == 1001:
            distance_bus = timesec_bus = cost_bus = '无公交方案'
        else:  # 其他类型状态码(服务器错误)
            distance_bus = timesec_bus = cost_bus = '请求错误'

        dataList.append([status_drive,distance_drive,timesec_drive,status_bus,distance_bus,timesec_bus,cost_bus])

计算两个坐标轴点的距离
例如:
from geopy.distance import geodesic
distance = geodesic((39.995304, 116.308264), (40.003304, 116.326759)).km
round(distance,2) 保留两位小数

dataList = np.array(dataList).reshape(len(recoder),len(recoder),-1)
'''【驾车状态, 自驾距离km,花费时间(分钟),推荐的公交状态,公交地铁距离 km,花费时间(分钟),金钱(元)'''
dataList_name = ['status_drive','distance_drive','timesec_drive','status_bus','distance_bus','timesec_bus','cost_bus']
dataList
array([[[  0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ],
        [  0.   ,  27.548,  40.15 ,   0.   ,  23.899,  67.03 ,   6.   ],
        [  0.   ,  18.95 ,  32.88 ,   0.   ,  13.49 ,  37.17 ,   5.   ],
        [  0.   ,  27.542,  44.32 ,   0.   ,  23.796,  72.62 ,   6.   ],
        [  0.   ,  19.801,  34.47 ,   0.   ,  15.236,  42.08 ,   5.   ],
        [  0.   ,  26.529,  43.72 ,   0.   ,  22.802,  64.42 ,   6.   ],
        [  0.   ,  15.492,  31.33 ,   0.   ,  11.445,  52.15 ,   5.   ]],

       [[  0.   ,  26.815,  39.47 ,   0.   ,  23.901,  68.03 ,   6.   ],
        [  0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ],
        [  0.   ,  15.521,  24.8  ,   0.   ,  18.993,  50.32 ,   5.   ],
        [  0.   ,   2.164,   8.27 ,   0.   ,   2.503,  23.43 ,   3.   ],
        [  0.   ,   9.285,  17.82 ,   0.   ,   8.915,  39.63 ,   2.   ],
        [  0.   ,   1.229,   4.17 ,   0.   ,   2.308,  22.25 ,   2.   ],
        [  0.   ,  33.633,  46.63 ,   0.   ,  27.912, 122.25 ,  -1.   ]],

       [[  0.   ,  17.501,  33.45 ,   0.   ,  13.492,  38.17 ,   5.   ],
        [  0.   ,  16.072,  34.05 ,   0.   ,  16.606,  44.97 ,   5.   ],
        [  0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ],
        [  0.   ,  17.769,  39.62 ,   0.   ,  19.003,  54.43 ,   5.   ],
        [  0.   ,  14.477,  33.3  ,   0.   ,  13.277,  30.68 ,   4.   ],
        [  0.   ,  15.053,  35.4  ,   0.   ,  15.509,  42.35 ,   5.   ],
        [  0.   ,  24.319,  40.85 ,   0.   ,  21.462,  70.03 ,   8.   ]],

       [[  0.   ,  28.996,  43.4  ,   0.   ,  23.795,  73.62 ,   6.   ],
        [  0.   ,   2.776,  11.35 ,   0.   ,   2.516,  23.1  ,   1.   ],
        [  0.   ,  17.702,  28.93 ,   0.   ,  19.003,  54.43 ,   5.   ],
        [  0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ],
        [  0.   ,  11.466,  21.7  ,   0.   ,   8.515,  45.77 ,   2.   ],
        [  0.   ,   3.06 ,  12.75 ,   0.   ,   3.582,  35.27 ,   2.   ],
        [  0.   ,  35.814,  51.15 ,   0.   ,  41.005, 141.15 ,   8.   ]],

       [[  0.   ,  18.501,  34.62 ,   0.   ,  15.235,  43.08 ,   5.   ],
        [  0.   ,   9.576,  25.33 ,   0.   ,  10.04 ,  47.1  ,   2.   ],
        [  0.   ,  13.024,  27.88 ,   0.   ,  13.276,  30.68 ,   4.   ],
        [  0.   ,  10.918,  30.15 ,   0.   ,  10.872,  54.63 ,   2.   ],
        [  0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ],
        [  0.   ,   9.687,  25.7  ,   0.   ,   8.773,  29.92 ,   3.   ],
        [  0.   ,  25.319,  42.9  ,   0.   ,  22.579,  69.72 ,   6.   ]],

       [[  0.   ,  25.766,  35.6  ,   0.   ,  22.805,  65.42 ,   6.   ],
        [  0.   ,   1.591,   4.68 ,   0.   ,   1.549,  23.33 ,   2.   ],
        [  0.   ,  14.472,  21.5  ,   0.   ,  14.753,  60.   ,  -1.   ],
        [  0.   ,   3.614,  11.85 ,   0.   ,   3.785,  34.93 ,   2.   ],
        [  0.   ,   8.236,  14.63 ,   0.   ,   8.775,  30.92 ,   3.   ],
        [  0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ],
        [  0.   ,  32.584,  42.62 ,   0.   ,  42.179, 157.82 ,   8.   ]],

       [[  0.   ,  18.927,  31.95 ,   0.   ,   8.338,  53.65 ,   4.   ],
        [  0.   ,  30.291,  44.87 ,   0.   ,  28.957, 123.95 ,  -1.   ],
        [  0.   ,  21.689,  33.18 ,   0.   ,  21.858,  68.93 ,  -1.   ],
        [  0.   ,  26.861,  49.48 ,   0.   ,  28.142, 112.42 ,  -1.   ],
        [  0.   ,  22.922,  40.9  ,   0.   ,  22.14 , 111.58 ,   6.   ],
        [  0.   ,  29.272,  47.62 ,   0.   ,  29.316, 129.08 ,  -1.   ],
        [  0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ,   0.   ]]])
# '''计算每两个城市间的distance  得到邻接矩阵'''
# from geopy.distance import geodesic
# adj_matrix = []
# for i , name1 in enumerate(recoder['name']):
#     for j ,name2 in enumerate(recoder['name']):
#         if name1 == name2:
#             distance = np.inf
#             adj_matrix.append(distance)
#         else:
#             distance = geodesic((recoder['position'][i][1],recoder['position'][i][0]),
#                                 (recoder['position'][j][1],recoder['position'][j][0])).km  # 转换为国外的维度和经度
#
#             distance = round(distance,2) # 保留2位有效
#             adj_matrix.append(distance)
# adj_matrix = np.array(adj_matrix).reshape(len(recoder),len(recoder))
#
#
# new_data = pd.DataFrame(adj_matrix)
# new_data.columns = recoder['name']
# new_data.insert(loc =0 ,column=' ',value=recoder['name'])
# new_data.to_excel('test.xlsx')
# new_data

将经纬度映射到 0-1 空间然后映射到画布空间
width,height

recoder
namepositioncategoryconfidence
0广东工业大学(大学城校区)(113.39959744237572, 23.045704807207507)教育70
1广州市鲁迅纪念馆(113.2841059860486, 23.13014496993394)旅游景点50
2广州天河宜家(113.42238287179822, 23.111107776003106)餐饮80
3广州五仙观(113.26630839796859, 23.126907167141244)旅游景点50
4广州Lavie拉维电影公馆(113.32622196190339, 23.101572988503353)休闲娱乐70
5广州近代史博物馆(113.28977420398412, 23.13464065626514)旅游景点50
6广州余荫山房 番禺区(113.4019110989934, 23.017728378073617)旅游景点50
from pyecharts.charts import Geo
from pyecharts import options
from pyecharts.globals import GeoType

g = Geo().add_schema(maptype="广州")
for i in range(len(result['name'])):
    g.add_coordinate(result['name'][i], result['position'][i][0], result['position'][i][1])
    data_pair = [(result['name'][i],1)]
    g.add('',data_pair, type_=GeoType.EFFECT_SCATTER, symbol_size=20)
g.set_series_opts(label_opts=options.LabelOpts(is_show=False))
g.set_global_opts(title_opts=options.TitleOpts(title="pyecharts地图标点测试"))
g.render_notebook()



'''
ALPHA:信息启发因子,值越大,则蚂蚁选择之前走过的路径可能性就越大
      ,值越小,则蚁群搜索范围就会减少,容易陷入局部最优
BETA:Beta值越大,蚁群越就容易选择局部较短路径,这时算法收敛速度会
     加快,但是随机性不高,容易得到局部的相对最优
'''
(ALPHA, BETA, RHO, Q) = (1.0, 2.0, 0.5, 100.0)
# 城市数,蚁群
(city_num, ant_num) = (len(recoder),len(recoder))


'''可以优化的一点,分布采用真实分布,实现步骤,归一化,映射到0-1空间,再将经纬度,映射到画布空间的相对位置'''
abstract_position = []
for i ,value in enumerate(recoder['position']):
    value = list(value)
    abstract_position.append(value)
abstract_position = np.array(abstract_position)
# 归一化映射位置关系
abstract_position[:, 0] =  (abstract_position[:, 0] - np.min(abstract_position[:, 0]))/(np.max(abstract_position[:, 0]) - np.min(abstract_position[:,
0])) * 500 + 200
abstract_position[:, 1] = 1000 - (abstract_position[:, 1] - np.min(abstract_position[:, 1]))/(np.max(abstract_position[:, 1]) - np.min(abstract_position[:,
1])) * 500 - 200  # + bias 偏置
abstract_position = np.ceil(abstract_position)

distance_x = [x[0] for x in abstract_position]
distance_y  = [y[1] for y in abstract_position]

# 城市距离和信息素
distance_graph = [[0.0 for col in range(city_num)] for raw in range(city_num)]
pheromone_graph = [[1.0 for col in range(city_num)] for raw in range(city_num)]



# ----------- 蚂蚁 -----------
class Ant(object):

    # 初始化
    def __init__(self, ID):

        self.ID = ID  # ID
        self.__clean_data()  # 随机初始化出生点

    # 初始数据
    def __clean_data(self):

        self.path = []  # 当前蚂蚁的路径
        self.total_distance = 0.0  # 当前路径的总距离
        self.move_count = 0  # 移动次数
        self.current_city = -1  # 当前停留的城市
        self.open_table_city = [True for i in range(city_num)]  # 探索城市的状态

        city_index = random.randint(0, city_num - 1)  # 随机初始出生点
        self.current_city = city_index
        self.path.append(city_index)
        self.open_table_city[city_index] = False
        self.move_count = 1

    # 选择下一个城市
    def __choice_next_city(self):

        next_city = -1
        select_citys_prob = [0.0 for i in range(city_num)]  # 存储去下个城市的概率
        total_prob = 0.0

        # 获取去下一个城市的概率
        for i in range(city_num):
            if self.open_table_city[i]:
                try:
                    # 计算概率:与信息素浓度成正比,与距离成反比
                    select_citys_prob[i] = pow(pheromone_graph[self.current_city][i], ALPHA) * pow(
                        (1.0 / distance_graph[self.current_city][i]), BETA)
                    total_prob += select_citys_prob[i]
                except ZeroDivisionError as e:
                    print('Ant ID: {ID}, current city: {current}, target city: {target}'.format(ID=self.ID,
                                                                                                current=self.current_city,
                                                                                                target=i))
                    sys.exit(1)

        # 轮盘选择城市
        if total_prob > 0.0:
            # 产生一个随机概率,0.0-total_prob
            temp_prob = random.uniform(0.0, total_prob)
            for i in range(city_num):
                if self.open_table_city[i]:
                    # 轮次相减
                    temp_prob -= select_citys_prob[i]
                    if temp_prob < 0.0:
                        next_city = i
                        break

        # 未从概率产生,顺序选择一个未访问城市
        # if next_city == -1:
        #     for i in range(city_num):
        #         if self.open_table_city[i]:
        #             next_city = i
        #             break

        if (next_city == -1):
            next_city = random.randint(0, city_num - 1)
            while ((self.open_table_city[next_city]) == False):  # if==False,说明已经遍历过了
                next_city = random.randint(0, city_num - 1)

        # 返回下一个城市序号
        return next_city

    # 计算路径总距离
    def __cal_total_distance(self):

        temp_distance = 0.0

        for i in range(1, city_num):
            start, end = self.path[i], self.path[i - 1]
            temp_distance += distance_graph[start][end]

        # 回路
        end = self.path[0]
        temp_distance += distance_graph[start][end]
        self.total_distance = temp_distance

    # 移动操作
    def __move(self, next_city):

        self.path.append(next_city)
        self.open_table_city[next_city] = False
        self.total_distance += distance_graph[self.current_city][next_city]
        self.current_city = next_city
        self.move_count += 1

    # 搜索路径
    def search_path(self):

        # 初始化数据
        self.__clean_data()

        # 搜素路径,遍历完所有城市为止
        while self.move_count < city_num:
            # 移动到下一个城市
            next_city = self.__choice_next_city()
            self.__move(next_city)

        # 计算路径总长度
        self.__cal_total_distance()


# ----------- TSP问题 -----------

class TSP(object):

    def __init__(self, root, width=1000, height=1000, n=city_num):

        # 创建画布
        self.root = root
        self.width = width
        self.height = height
        # 城市数目初始化为city_num
        self.n = n
        # tkinter.Canvas
        self.canvas = tkinter.Canvas(
            root,
            width=self.width,
            height=self.height,
            bg="#EBEBEB",  # 背景白色
            xscrollincrement=1,
            yscrollincrement=1
        )
        self.canvas.pack(expand=tkinter.YES, fill=tkinter.BOTH)
        self.title("TSP蚁群算法(n:初始化 e:开始搜索 s:停止搜索 q:退出程序)")
        self.__r = 5
        self.__lock = threading.RLock()  # 线程锁

        self.__bindEvents()
        self.new()

        # 计算地点之间的距离,也就是花费, 这里的度量默认采用了 地铁公交车的时间花费
        '''['status_drive','distance_drive','timesec_drive','status_bus','distance_bus','timesec_bus','cost_bus']'''
        for i,value0 in enumerate(dataList):
            for j,value1 in enumerate(value0):
                distance = value1[5]
                distance_graph[i][j] = distance

    # 按键响应程序
    def __bindEvents(self):

        self.root.bind("q", self.quite)  # 退出程序
        self.root.bind("n", self.new)  # 初始化
        self.root.bind("e", self.search_path)  # 开始搜索
        self.root.bind("s", self.stop)  # 停止搜索

    # 更改标题
    def title(self, s):

        self.root.title(s)

    # 初始化
    def new(self, evt=None):

        # 停止线程
        self.__lock.acquire()
        self.__running = False
        self.__lock.release()

        self.clear()  # 清除信息
        self.nodes = []  # 节点坐标
        self.nodes2 = []  # 节点对象

        # 初始化城市节点
        for i in range(self.n):
            # 在画布上标定虚拟坐标
            x = distance_x[i]
            y = distance_y[i]
            self.nodes.append((x, y))
            # 生成节点椭圆,半径为self.__r
            node = self.canvas.create_oval(x - self.__r,
                                           y - self.__r, x + self.__r, y + self.__r,
                                           fill="#ff0000",  # 填充红色
                                           outline="#000000",  # 轮廓白色
                                           tags="node",
                                           )
            self.nodes2.append(node)
            # 显示坐标
            self.canvas.create_text(x, y - 10,  # 使用create_text方法在坐标(302,77)处绘制文字
                                    text=f"{recoder['name'][i]}",  # 所绘制文字的内容
                                    fill='black'  # 所绘制文字的颜色为灰色
                                    )

        # 顺序连接城市
        # self.line(range(city_num))

        # 初始城市之间的距离和信息素
        for i in range(city_num):
            for j in range(city_num):
                pheromone_graph[i][j] = 1.0

        self.ants = [Ant(ID) for ID in range(ant_num)]  # 初始蚁群
        self.best_ant = Ant(-1)  # 初始最优解
        self.best_ant.total_distance = 1 << 31  # 初始最大距离
        self.iter = 1  # 初始化迭代次数

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


        def line2(i1, i2):
            p1, p2 = self.nodes[i1], self.nodes[i2]
            self.canvas.create_line(p1, p2, fill="#000000",tags="line")
            # # 显示线路花费时间
            # x = int((p1[0]+p2[0])/2)
            # y = int((p1[1]+p2[1])/2)
            #
            # self.canvas.create_text(x, y - 10,  # 使用create_text方法在坐标(302,77)处绘制文字
            #                         text=f"{}",  # 所绘制文字的内容
            #                         fill='black'  # 所绘制文字的颜色为灰色
            #                         )
            return i2

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

    # 清除画布
    def clear(self):
        for item in self.canvas.find_all():
            self.canvas.delete(item)

    # 退出程序
    def quite(self, evt):
        self.__lock.acquire()
        self.__running = False
        self.__lock.release()
        self.root.destroy()
        print(u"\n程序已退出...")
        sys.exit()

    # 停止搜索
    def stop(self, evt):
        self.__lock.acquire()
        self.__running = False
        self.__lock.release()

    # 开始搜索
    def search_path(self, evt=None):

        # 开启线程
        self.__lock.acquire()
        self.__running = True
        self.__lock.release()

        while self.__running:
            # 遍历每一只蚂蚁
            for ant in self.ants:
                # 搜索一条路径
                ant.search_path()
                # 与当前最优蚂蚁比较
                if ant.total_distance < self.best_ant.total_distance:
                    # 更新最优解
                    self.best_ant = copy.deepcopy(ant)
            # 更新信息素
            self.__update_pheromone_gragh()
            print(u"迭代次数:", self.iter, f"最佳{dataList_name[5]} (hours)", round(self.best_ant.total_distance / 60,2))
            # 连线
            self.line(self.best_ant.path)
            # 设置标题
            self.title("TSP蚁群算法(n:随机初始 e:开始搜索 s:停止搜索 q:退出程序) 迭代次数: %d" % self.iter)
            # 更新画布
            self.canvas.update()
            self.iter += 1

    # 更新信息素
    def __update_pheromone_gragh(self):

        # 获取每只蚂蚁在其路径上留下的信息素
        temp_pheromone = [[0.0 for col in range(city_num)] for raw in range(city_num)]
        for ant in self.ants:
            for i in range(1, city_num):
                start, end = ant.path[i - 1], ant.path[i]
                # 在路径上的每两个相邻城市间留下信息素,与路径总距离反比
                temp_pheromone[start][end] += Q / ant.total_distance
                temp_pheromone[end][start] = temp_pheromone[start][end]

        # 更新所有城市之间的信息素,旧信息素衰减加上新迭代信息素
        for i in range(city_num):
            for j in range(city_num):
                pheromone_graph[i][j] = pheromone_graph[i][j] * RHO + temp_pheromone[i][j]

    # 主循环
    def mainloop(self):
        self.root.mainloop()

print(u"""
--------------------------------------------------------
    蚁群算法解决TPS问题程序
    程序中按提示键盘继续操作

--------------------------------------------------------
    """)
TSP(tkinter.Tk()).mainloop()
--------------------------------------------------------
    蚁群算法解决TPS问题程序
    程序中按提示键盘继续操作

--------------------------------------------------------
    
迭代次数: 1 最佳timesec_bus (hours) 5.04
迭代次数: 2 最佳timesec_bus (hours) 5.04
迭代次数: 3 最佳timesec_bus (hours) 4.94
迭代次数: 4 最佳timesec_bus (hours) 4.94
迭代次数: 5 最佳timesec_bus (hours) 4.94
迭代次数: 6 最佳timesec_bus (hours) 4.94
迭代次数: 7 最佳timesec_bus (hours) 4.94
迭代次数: 8 最佳timesec_bus (hours) 4.94
迭代次数: 9 最佳timesec_bus (hours) 4.94
迭代次数: 10 最佳timesec_bus (hours) 4.85
迭代次数: 11 最佳timesec_bus (hours) 4.85
迭代次数: 12 最佳timesec_bus (hours) 4.85
迭代次数: 13 最佳timesec_bus (hours) 4.85
迭代次数: 14 最佳timesec_bus (hours) 4.85
迭代次数: 15 最佳timesec_bus (hours) 4.85
迭代次数: 16 最佳timesec_bus (hours) 4.85
迭代次数: 17 最佳timesec_bus (hours) 4.85
迭代次数: 18 最佳timesec_bus (hours) 4.85
迭代次数: 19 最佳timesec_bus (hours) 4.84
迭代次数: 20 最佳timesec_bus (hours) 4.84
迭代次数: 21 最佳timesec_bus (hours) 4.84
迭代次数: 22 最佳timesec_bus (hours) 4.84
迭代次数: 23 最佳timesec_bus (hours) 4.84
迭代次数: 24 最佳timesec_bus (hours) 4.84
迭代次数: 25 最佳timesec_bus (hours) 4.84
迭代次数: 26 最佳timesec_bus (hours) 4.84
迭代次数: 27 最佳timesec_bus (hours) 4.84
迭代次数: 28 最佳timesec_bus (hours) 4.84
迭代次数: 29 最佳timesec_bus (hours) 4.84
迭代次数: 30 最佳timesec_bus (hours) 4.84
迭代次数: 31 最佳timesec_bus (hours) 4.84
迭代次数: 32 最佳timesec_bus (hours) 4.84
迭代次数: 33 最佳timesec_bus (hours) 4.84
迭代次数: 34 最佳timesec_bus (hours) 4.84
迭代次数: 35 最佳timesec_bus (hours) 4.84
迭代次数: 36 最佳timesec_bus (hours) 4.84
迭代次数: 37 最佳timesec_bus (hours) 4.84
迭代次数: 38 最佳timesec_bus (hours) 4.84
迭代次数: 39 最佳timesec_bus (hours) 4.84
迭代次数: 40 最佳timesec_bus (hours) 4.84
迭代次数: 41 最佳timesec_bus (hours) 4.84
迭代次数: 42 最佳timesec_bus (hours) 4.83
迭代次数: 43 最佳timesec_bus (hours) 4.83
迭代次数: 44 最佳timesec_bus (hours) 4.83
迭代次数: 45 最佳timesec_bus (hours) 4.83
迭代次数: 46 最佳timesec_bus (hours) 4.83
迭代次数: 47 最佳timesec_bus (hours) 4.83
迭代次数: 48 最佳timesec_bus (hours) 4.83
迭代次数: 49 最佳timesec_bus (hours) 4.83
迭代次数: 50 最佳timesec_bus (hours) 4.83
迭代次数: 51 最佳timesec_bus (hours) 4.83
迭代次数: 52 最佳timesec_bus (hours) 4.83
迭代次数: 53 最佳timesec_bus (hours) 4.83
迭代次数: 54 最佳timesec_bus (hours) 4.83
迭代次数: 55 最佳timesec_bus (hours) 4.83
迭代次数: 56 最佳timesec_bus (hours) 4.83
迭代次数: 57 最佳timesec_bus (hours) 4.83
迭代次数: 58 最佳timesec_bus (hours) 4.83
迭代次数: 59 最佳timesec_bus (hours) 4.83
迭代次数: 60 最佳timesec_bus (hours) 4.83
迭代次数: 61 最佳timesec_bus (hours) 4.83
迭代次数: 62 最佳timesec_bus (hours) 4.83

引用文献
CSDN 百度api获取个人ak
蚁群算法的实现

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林丿子轩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值