VNS求解TPS问题(python)

参考资料
变邻域搜索算法(VNS)迅速掌握
TSP问题–变邻域搜索(VNS)算法
搬运工。

import numpy as np
import random as re
import math
import copy
from multiprocessing import Pool as ThreadPool
import time


def read_data():
    f = open('att48.tsp/att48.txt', encoding='gbk')
    lines = f.readlines()
    count = 0
    cus_lon = []
    for line in lines:
        count += 1
        if count >= 7:
            str_ = line.strip().split()
            if str_[0] == 'EOF':
                break
            currentSolution.append(int(str_[0])-1)
            cus_lon.append([int(str_[1]), int(str_[2])])
    cus_lon = np.array(cus_lon)
    # 计算两点间的距离
    get_distance(cus_lon)


# 计算两点间距离
def get_distance(cus_lon):

    for i in range(len(cus_lon)):
        temp = cus_lon[i]
        # 伪欧氏距离在根号内除以了一个10
        dis_ = (((temp[0] - cus_lon[:, 0]) ** 2 + (temp[1] - cus_lon[:, 1]) ** 2) / 10)**0.5
        # dis_ = ((temp[0] - cus_lon[:, 0]) ** 2 + (temp[1] - cus_lon[:, 1]) ** 2)**0.5
        distMat.append(list(dis_))


def disCal(path):
    # global distMat
    dis = 0
    for i in range(len(path) - 1):
        dis += distMat[path[i]][path[i + 1]]
    dis += distMat[path[0]][path[-1]]
    return dis


# 抖动:将城市分成4块,扰动再组合
def sharking(solution):
    solution_ = []
    city_ = math.ceil(len(solution) / 4)
    for i in range(4):
        solution_.append(solution[i*city_:(i+1)*city_])

    sequence = [i for i in range(4)]
    re.shuffle(sequence)
    solution = []
    for se in sequence:
        solution += solution_[se]
    return solution


def variableNeighborhoodDescent(solution):
    i = 0
    dis, k = float('inf'), -1
    # 进行邻域搜索动作
    while i < 3:
        if i == 0:
            neiborSolution = neighborhoodOne(solution)
        elif i == 1:
            neiborSolution = neighborhoodTwo(solution)
        elif i == 2:
            neiborSolution = neighborhoodThree(solution)
        # 遍历找到的所有邻域,判断与当前解进行比较
        for j in range(len(neiborSolution)):
            if disCal(neiborSolution[j]) < dis:
                dis = disCal(neiborSolution[j])
                k = j
        # 多线程
        # pool_ = ThreadPool(7)
        # opt_val = pool_.map(disCal, neiborSolution)
        # pool_.close()  # 关闭进程池
        # pool_.join()
        # temp = min(opt_val)
        # if temp < dis:
        #     dis = temp
        #     k = opt_val.index(temp)

        if dis < disCal(solution):
            # 重新回到第一种邻域
            solution = neiborSolution[k]
            i = 0
        else:
            i += 1
    return disCal(solution), solution


# 邻域动作:两点互换(swap)
def neighborhoodOne(sol):
    neighbor = []
    for i in range(len(sol)):
        for j in range(i + 1, len(sol)):
            s = copy.deepcopy(sol)
            x = s[j]
            s[j] = s[i]
            s[i] = x
            neighbor.append(s)
    return neighbor


# 邻域动作:两点间反转(two_opt_swap)
def neighborhoodTwo(sol):
    neighbor = []
    for i in range(len(sol)):
        for j in range(i + 3, len(sol)):    # 这里j从i+3开始是为了不产生跟swap算子重复的解
            s = copy.deepcopy(sol)
            s1 = s[i:j+1]
            s1.reverse()
            s = s[:i] + s1 + s[j+1:]
            neighbor.append(s)
    return neighbor


# 邻域动作:two_h_opt_swap算子
def neighborhoodThree(sol):
    neighbor = []
    for i in range(len(sol)):
        for j in range(i+1, len(sol)):
            s = copy.deepcopy(sol)
            s = [s[i]] + [s[j]] + s[:i] + s[i+1:j] + s[j+1:]
            neighbor.append(s)
    return neighbor


currentSolution = []
distMat = []
city_size = len(currentSolution)
# 读取数据
read_data()
if __name__ == '__main__':
    st = time.time()
    # 参数定义
    # 随机产生初始解,当前解成本
    distMat = np.array(distMat)

    re.shuffle(currentSolution)
    shorterDistance = disCal(currentSolution)
    iterx, iterxMax = 0, 10
    while iterx < iterxMax:
        print(shorterDistance, " : ", currentSolution)
        # 抖动
        currentSolution = sharking(currentSolution)
        # VND
        currentDistance, currentSolution = variableNeighborhoodDescent(currentSolution)
        if currentDistance < shorterDistance:
            shorterDistance = currentDistance
            itrex = 0
        else:
            iterx += 1
    print(currentSolution)
    print(shorterDistance)
    print(time.time() - st)

测试数据来源:att48.tsp.gz

不知道为啥开了多线程反而更慢了。


仅供学习,侵权删。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值