利用人工神经网络求解TSP问题---Hopfield 网络

问题:

—旅行商问题(Travelling Salesman Problem, 简记TSP,亦称货郎担问题):设有n个城市和距离矩阵D = [dij],其中dij表示城市i到城市j的距离,i, j = 1, 2 … n,则问题是要找出遍访每个城市恰好一次的一条回路并使其路径长度为最短。说明:

  1. 回路:从某个城市出发,最后回到这个城市。
  2. 数据说明:a) dantzig42 - 42 cities (Dantzig)

解题思路

解题思路:
Hopfield 神经网络是一种基于能量的神经网络模型,可以用于解决组合优化问题,基本思路如下:
能量函数设计:Hopfield 网络使用能量函数来描述系统的状态。在 TSP 中,这个能量函数反映了旅行路径的质量。路径越短,能量越低。对于 TSP,能量函数通常定义为旅行路径的长度或距离之和。网络的目标是通过调整状态来最小化这个能量函数,即找到一条最短路径。
状态表示:每个城市代表网络中的一个神经元。网络的状态是一个向量,每个元素对应一个城市的状态。在 TSP 中,每个元素可能表示一个城市是否被访问(通常使用二进制值表示,1表示已访问,0表示未访问)。
更新规则:Hopfield 网络采用迭代更新来最小化能量函数。更新过程中,根据能量函数的梯度调整网络的状态。在 TSP 中,可以根据当前路径长度来更新状态,使路径长度逐渐减小。
优化过程:初始化网络状态为一个随机解或初始路径。通过多次迭代更新状态,根据能量函数逐步调整状态,期望能收敛到一个局部最优解。
约束条件:在解决 TSP 时,需要确保路径是一条闭合路径,并且每个城市仅访问一次。在更新状态时,需要考虑这些约束条件,防止生成不合法的路径。
最终解析:最终得到的网络状态代表着优化后的路径。路径的选择可能是局部最优解,并非一定是全局最优解,这取决于网络的初始化和更新策略。

代码分析

HopfieldTSP 类:init 方法初始化 HopfieldTSP 类,接受距离矩阵和一些参数(学习率、阈值、迭代次数等)。calculate_weights 方法计算并存储连接权重,这些权重用于神经网络的更新和优化。energy 方法计算神经网络的能量。update 方法根据 Hopfield 网络的更新规则进行状态的更新。optimize 方法使用 Hopfield 网络优化状态,并返回优化后的状态。

reconstruct_path 函数:reconstruct_path 函数根据优化后的状态,重构旅行路径首先选择一个起始城市并将其添加到路径中然后根据优化状态选择下一个城市,并将其添加到路径中,直到所有城市都被访问过为止。确保回到起始城市,使得路径构成一个环路。
read_tsp_file 和 read_distance_matrix 函数:read_tsp_file 函数用于读取 TSP 文件,提取元数据,例如城市数量等。read_distance_matrix 函数用于读取包含城市之间距离信息的文件,创建距离矩阵。
主要执行部分:读取 TSP 文件获取元数据和距离矩阵。使用 HopfieldTSP 类创建一个实例,设定学习率、阈值和迭代次数,然后优化状态。使用 reconstruct_path 函数基于优化状态重构完整的路径。计算重构路径的最短距离,并打印出完整路径和最短距离。
整体思路是使用 Hopfield 神经网络优化状态,然后根据优化后的状态重构路径,并计算路径的最短距离。这个方法可能在解决 TSP 问题上得到次优解,因为 Hopfield 神经网络是一种启发式算法,无法保证获得全局最优解。


TSP数据

DANTZIG42 is a set of 42 cities, from TSPLIB.
The minimal tour has length 699. dantzig42.tsp,
the TSP specification of the data.
dantzig42_d.txt, the intercity distance table.
这里会给出自己虚构的数据集代码来进行实验,也会给出TSP数据代码

import numpy as np

class HopfieldTSP:
    def __init__(self, distance_matrix, learning_rate=0.1, threshold=0, epochs=1000):
        self.distance_matrix = distance_matrix
        self.num_cities = len(distance_matrix)
        self.weights = self._calculate_weights()
        self.learning_rate = learning_rate
        self.threshold = threshold
        self.epochs = epochs

    def _calculate_weights(self):
        weights = np.zeros((self.num_cities, self.num_cities))
        for i in range(self.num_cities):
            for j in range(self.num_cities):
                if i != j:
                    weights[i][j] = -self.distance_matrix[i][j]
        return weights

    def energy(self, state):
        total_energy = 0
        for i in range(self.num_cities):
            for j in range(self.num_cities):
                total_energy += self.weights[i][j] * state[i] * state[j]
        return total_energy / 2

    def update(self, state):
        for _ in range(self.epochs):
            i = np.random.randint(0, self.num_cities)
            state[i] = 1 if np.sum(self.weights[i] * state) > self.threshold else 0
        return state

    def optimize(self):
        initial_state = np.random.randint(0, 2, size=self.num_cities)
        state = initial_state.copy()
        optimized_state = self.update(state)
        return optimized_state

def reconstruct_path(optimized_state):
    remaining_cities = list(range(len(optimized_state)))  # 所有城市的索引列表
    path = []  # 存储路径
    current_city = np.random.choice(remaining_cities)  # 随机选择一个起始城市
    path.append(current_city)
    remaining_cities.remove(current_city)

    while remaining_cities:
        next_city = np.argmax(optimized_state[current_city])  # 选择下一个城市
        if next_city in remaining_cities:
            optimized_state[current_city] = 0  # 防止重复访问同一个城市
            path.append(next_city)
            remaining_cities.remove(next_city)
            current_city = next_city
        else:
            # 如果城市已经访问过,寻找一个未访问的城市
            for city in range(len(optimized_state)):
                if city in remaining_cities:
                    current_city = city
                    path.append(current_city)
                    remaining_cities.remove(current_city)
                    break

    # 确保回到起始城市
    path.append(path[0])

    return path

这里定义了一个HopfieldTSP模型,reconstruct_path 函数根据优化后的状态,确保每一个城市都被访问到。

def read_tsp_file(filename):
    metadata = {}
    with open(filename, 'r') as file:
        lines = file.readlines()
        for line in lines:
            if line.startswith("DIMENSION"):
                metadata["num_cities"] = int(line.split(":")[1])
            # 可以根据需要解析其他元数据
            
    return metadata

def read_distance_matrix(filename, num_cities):
    with open(filename, 'r') as file:
        lines = file.readlines()
    
    distance_matrix = []
    for line in lines:
        row = [int(dist) for dist in line.strip().split()]
        distance_matrix.append(row)
    
    return distance_matrix


num_cities=42

'''
# 创建自己的距离矩阵 
num_cities = 5
custom_distance_matrix = np.array([
    [0, 10, 20, 15, 30],   # 城市0到其他城市的距离
    [10, 0, 25, 20, 35],   # 城市1到其他城市的距离
    [20, 25, 0, 12, 28],   # 城市2到其他城市的距离
    [15, 20, 12, 0, 22],   # 城市3到其他城市的距离
    [30, 35, 28, 22, 0]    # 城市4到其他城市的距离
])

# 使用自定义距离矩阵创建HopfieldTSP实例
hopfield_tsp = HopfieldTSP(custom_distance_matrix, learning_rate=0.5, threshold=0.3, epochs=100)
optimized_state = hopfield_tsp.optimize()

# 重建最优路径
full_path = reconstruct_path(optimized_state)
shortest_distance = sum(custom_distance_matrix[full_path[i]][full_path[i + 1]] for i in range(len(full_path) - 1))

print("完整路径:", full_path)
print("最短距离:", shortest_distance)
'''

distance_matrix = read_distance_matrix("dantzig42_d.txt",42) #不使用tsp文件
#tsp_metadata = read_tsp_file("dantzig42.tsp")  使用tsp文件
#distance_matrix = read_distance_matrix("dantzig42_d.txt", tsp_metadata["num_cities"]) 使用tsp文件
hopfield_tsp = HopfieldTSP(distance_matrix, learning_rate=0.5, threshold=0.3, epochs=1000)
optimized_state = hopfield_tsp.optimize()

full_path = reconstruct_path(optimized_state)
shortest_distance = sum(distance_matrix[full_path[i]][full_path[i + 1]] for i in range(len(full_path) - 1))
print("最佳状态":optimized_state)
print("完整路径:", full_path)
print("最短距离:", shortest_distance)


读取数据,并求出最短路径

总代码

这里采取了虚构的数据集
利用人工神经网络求解TSP问题---Hopfield 网络_第1张图片
下述代码块运行结果如上。
利用人工神经网络求解TSP问题---Hopfield 网络_第2张图片
读取的数据运行结果如上。

import numpy as np

class HopfieldTSP:
    def __init__(self, distance_matrix, learning_rate=0.1, threshold=0, epochs=1000):
        self.distance_matrix = distance_matrix
        self.num_cities = len(distance_matrix)
        self.weights = self._calculate_weights()
        self.learning_rate = learning_rate
        self.threshold = threshold
        self.epochs = epochs

    def _calculate_weights(self):
        weights = np.zeros((self.num_cities, self.num_cities))
        for i in range(self.num_cities):
            for j in range(self.num_cities):
                if i != j:
                    weights[i][j] = -self.distance_matrix[i][j]
        return weights

    def energy(self, state):
        total_energy = 0
        for i in range(self.num_cities):
            for j in range(self.num_cities):
                total_energy += self.weights[i][j] * state[i] * state[j]
        return total_energy / 2

    def update(self, state):
        for _ in range(self.epochs):
            i = np.random.randint(0, self.num_cities)
            state[i] = 1 if np.sum(self.weights[i] * state) > self.threshold else 0
        return state

    def optimize(self):
        initial_state = np.random.randint(0, 2, size=self.num_cities)
        state = initial_state.copy()
        optimized_state = self.update(state)
        return optimized_state

def reconstruct_path(optimized_state):
    remaining_cities = list(range(len(optimized_state)))  # 所有城市的索引列表
    path = []  # 存储路径
    current_city = np.random.choice(remaining_cities)  # 随机选择一个起始城市
    path.append(current_city)
    remaining_cities.remove(current_city)

    while remaining_cities:
        next_city = np.argmax(optimized_state[current_city])  # 选择下一个城市
        if next_city in remaining_cities:
            optimized_state[current_city] = 0  # 防止重复访问同一个城市
            path.append(next_city)
            remaining_cities.remove(next_city)
            current_city = next_city
        else:
            # 如果城市已经访问过,寻找一个未访问的城市
            for city in range(len(optimized_state)):
                if city in remaining_cities:
                    current_city = city
                    path.append(current_city)
                    remaining_cities.remove(current_city)
                    break

    # 确保回到起始城市
    path.append(path[0])

    return path

def read_tsp_file(filename):
    metadata = {}
    with open(filename, 'r') as file:
        lines = file.readlines()
        for line in lines:
            if line.startswith("DIMENSION"):
                metadata["num_cities"] = int(line.split(":")[1])
            # 可以根据需要解析其他元数据
            
    return metadata

def read_distance_matrix(filename, num_cities):
    with open(filename, 'r') as file:
        lines = file.readlines()
    
    distance_matrix = []
    for line in lines:
        row = [int(dist) for dist in line.strip().split()]
        distance_matrix.append(row)
    
    return distance_matrix


num_cities=42


# 创建自己的距离矩阵 
num_cities = 5
custom_distance_matrix = np.array([
    [0, 10, 20, 15, 30],   # 城市0到其他城市的距离
    [10, 0, 25, 20, 35],   # 城市1到其他城市的距离
    [20, 25, 0, 12, 28],   # 城市2到其他城市的距离
    [15, 20, 12, 0, 22],   # 城市3到其他城市的距离
    [30, 35, 28, 22, 0]    # 城市4到其他城市的距离
])

# 使用自定义距离矩阵创建HopfieldTSP实例
hopfield_tsp = HopfieldTSP(custom_distance_matrix, learning_rate=0.5, threshold=0.3, epochs=100)
optimized_state = hopfield_tsp.optimize()

# 重建最优路径
full_path = reconstruct_path(optimized_state)
shortest_distance = sum(custom_distance_matrix[full_path[i]][full_path[i + 1]] for i in range(len(full_path) - 1))
print("优化状态",optimized_state)
print("完整路径:", full_path)
print("最短距离:", shortest_distance)


'''
distance_matrix = read_distance_matrix("dantzig42_d.txt",42) #不使用tsp文件
#tsp_metadata = read_tsp_file("dantzig42.tsp")  使用tsp文件
#distance_matrix = read_distance_matrix("dantzig42_d.txt", tsp_metadata["num_cities"]) 使用tsp文件
hopfield_tsp = HopfieldTSP(distance_matrix, learning_rate=0.5, threshold=0.3, epochs=1000)
optimized_state = hopfield_tsp.optimize()

full_path = reconstruct_path(optimized_state)
shortest_distance = sum(distance_matrix[full_path[i]][full_path[i + 1]] for i in range(len(full_path) - 1))

print("完整路径:", full_path)
print("最短距离:", shortest_distance)
'''

你可能感兴趣的:(计算智能,开发语言,python,人工智能,启发式算法)