Hamilton问题求解-最近邻点法和最近插入法(Python实现)

简介: Hamilton问题求解-最近邻点法和最近插入法(Python实现)

Hamilton问题求解-最近邻点法和最近插入法

一、定义

1. 哈密顿通路

设G = < V , E >为一个图(有向图或者无向图)。G中经过的每个顶点一次且仅一次的通路称为哈密顿通路。(通路不一定回到起点,但一定穿过每个顶点一次且仅一次)

2. 哈密顿回路

设G = < V , E >为一个图(有向图或者无向图)。G中经过的每个顶点一次且仅一次的回路称为哈密顿回路。(回路要求穿过每个顶点一次后回到起点)

3. 性质

存在哈密顿通路(回路)的图一定是连通图

哈密顿通路是初级通路,哈密顿回路是初级回路

初级是通路(回路)指除了起点和终点之外,所有的顶点和边都互不相同的通路(回路)

若图G GG中存在哈密顿回路,则它一定存在哈密顿通路

只有哈密顿通路,无哈密顿回路的图不叫哈密顿图

二、判定定理

目前没有判定哈密顿图的简单充要条件

image.png

image.png

三、求解算法

1. 最近邻点法

算法思想:每次将离当前顶点最近的顶点加入,一般只能找到近似解,不能找到最优解

算法步骤

  • 从网络中找一个点做为起点
  • 从剩下的点中找一个离上一个点最近的点加入
  • 重复步骤2
  • 将最后加入的点与起点连接构成回路

2.最近插入法

最近插入法(Nearest Insertion)于1977年提出,用于解决TSP问题,可以得到相对最近邻点法更优的解。

算法步骤

image.png

四、Python源码实现

Hamilton.py

import numpy as np
class HamiltonUtil:
    def __init__(self, input_matrix):
        self.graph = input_matrix
        self.point_num = np.shape(self.graph)[0]
        self.HamSolve = []
        self.HamLength = 0
    def search_min(self, index, matrix):
        min_val = np.float('inf')
        for i in matrix:
            if self.graph[index][i - 1] < min_val:
                min_val = self.graph[index][i - 1]
        return min_val
    def find_match_vex(self, index, match_val):
        ret_index = 0
        for i in self.graph[index]:
            if i != match_val:
                ret_index += 1
            else:
                break
        return ret_index
    def find_index(self, vec, value):
        index = 0
        for i in vec:
            if i != value:
                index += 1
            else:
                break
        return index
    def clear_stack(self):
        self.HamSolve = []
        self.HamLength = 0
    def neibor_point(self):
        self.clear_stack()
        start = 1
        V = np.arange(1, self.point_num + 1, 1)
        self.HamSolve.append(start)
        V = np.delete(V, start - 1)
        BetweenPoint = start
        while np.shape(V)[0] != 0:
            VWeight = self.search_min(BetweenPoint - 1, V)
            Next = self.find_match_vex(BetweenPoint - 1, VWeight) + 1
            self.HamSolve.append(Next)
            V = np.setdiff1d(V, Next)
            self.HamLength = self.HamLength + VWeight
            BetweenPoint = Next
        self.HamSolve.append(start)
        self.HamLength = self.HamLength + self.graph[Next - 1][start - 1]
    def nearest_insertion(self):
        self.clear_stack()
        start = 1
        V = np.arange(1, self.point_num + 1, 1)
        self.HamSolve.append(start)
        V = np.setdiff1d(V, self.HamSolve)
        BetweenPoint = start
        VWeight = self.search_min(BetweenPoint - 1, V)
        Next = self.find_match_vex(BetweenPoint - 1, VWeight) + 1
        self.HamSolve.append(Next)
        self.HamSolve.append(start)
        V = np.setdiff1d(V, Next)
        self.HamLength = self.HamLength + VWeight + self.graph[Next - 1][start - 1]
        BetweenPoint = Next
        while np.shape(V)[0] != 0:
            HamPoint = list(set(self.HamSolve))
            NearestPoint = 0
            NearWeight = np.zeros((len(HamPoint),), dtype=float)
            NearPoint = np.zeros((len(HamPoint),), dtype=int)
            for i in range(len(HamPoint)):
                NearWeight[i] = self.search_min(HamPoint[i] - 1, V)
                NearPoint[i] = self.find_match_vex(HamPoint[i] - 1, NearWeight[i]) + 1
            NearestPoint = NearPoint[self.find_index(NearWeight, np.min(NearWeight))]
            HamIncrement = np.zeros((len(self.HamSolve) - 1,), dtype=float)
            for i in range(len(self.HamSolve) - 1):
                HamIncrement[i] = self.graph[self.HamSolve[i] - 1][NearestPoint - 1] + \
                                  self.graph[NearestPoint - 1][self.HamSolve[i + 1] - 1] - \
                                  self.graph[self.HamSolve[i] - 1][self.HamSolve[i + 1] - 1]
            MinHamIncrement = np.min(HamIncrement)
            InsertPoint = self.find_index(HamIncrement, MinHamIncrement) + 1
            self.HamSolve.insert(InsertPoint, NearestPoint)
            self.HamLength += MinHamIncrement
            V = np.setdiff1d(V, NearestPoint)

五、运行测试实例

main.py

from Hamilton import HamiltonUtil
import numpy as np
if __name__ == '__main__':
    E = np.array([[np.float('inf'), 10, 6, 8, 7, 15],
                  [10, np.float('inf'), 5, 20, 15, 16],
                  [6, 5, np.float('inf'), 14, 7, 8],
                  [8, 20, 14, np.float('inf'), 4, 12],
                  [7, 15, 7, 4, np.float('inf'), 6],
                  [15, 16, 8, 12, 6, np.float('inf')]], dtype=float)
    neibor_point = HamiltonUtil(E)
    # 最邻近点法
    neibor_point.neibor_point()
    print(neibor_point.HamSolve)
    print(neibor_point.HamLength)
    E = np.array([[np.float('inf'), 10, 6, 8, 7, 15],
                  [10, np.float('inf'), 5, 20, 15, 16],
                  [6, 5, np.float('inf'), 14, 7, 8],
                  [8, 20, 14, np.float('inf'), 4, 12],
                  [7, 15, 7, 4, np.float('inf'), 6],
                  [15, 16, 8, 12, 6, np.float('inf')]], dtype=float)
    nearest_insertion = HamiltonUtil(E)
    # 最近插值法
    nearest_insertion.nearest_insertion()
    print(nearest_insertion.HamSolve)
    print(nearest_insertion.HamLength)
相关文章
|
机器学习/深度学习 人工智能 监控
高质量人体检测与行人识别数据集-千张标注图片全解析已标注(目标检测任务数据集)分享
在计算机视觉和人工智能的发展浪潮中,人体检测与行人识别 是一个极具应用价值和研究意义的方向。从智能监控到自动驾驶,从智慧城市到公共安全,人体检测数据集的质量与规模往往直接决定了算法模型的性能。本文将围绕一个包含 上千张图片、已完成划分与标注 的 人体检测、行人识别数据集 展开介绍,帮助研究者和开发者快速了解该数据集的特点、优势及其适用场景。
|
机器学习/深度学习 数据采集 算法
一文速学-时间序列分析算法之一次移动平均法和二次移动平均法详解+实例代码
一文速学-时间序列分析算法之一次移动平均法和二次移动平均法详解+实例代码
3936 0
一文速学-时间序列分析算法之一次移动平均法和二次移动平均法详解+实例代码
|
5月前
|
机器学习/深度学习 算法 机器人
使用Koopman理论识别机器人动力学的非线性系统(Matlab代码实现)
使用Koopman理论识别机器人动力学的非线性系统(Matlab代码实现)
272 5
|
监控 安全 物联网
13位物联网卡与11位物联网卡有什么不同
物联网卡(IoT卡)的13位号码和11位号码之间存在一些关键差异。以下是针对这两者区别的详细操作步骤和解释:
|
Ubuntu Shell 网络安全
安装了ubuntu虚拟机后发现shell无法连接 ubuntu开启ssh连接
【8月更文挑战第23天】安装了ubuntu虚拟机后发现shell无法连接
1825 6
|
机器学习/深度学习 人工智能 文字识别
ultralytics YOLO11 全新发布!(原理介绍+代码详见+结构框图)
本文详细介绍YOLO11,包括其全新特性、代码实现及结构框图,并提供如何使用NEU-DET数据集进行训练的指南。YOLO11在前代基础上引入了新功能和改进,如C3k2、C2PSA模块和更轻量级的分类检测头,显著提升了模型的性能和灵活性。文中还对比了YOLO11与YOLOv8的区别,并展示了训练过程和结果的可视化
22784 0
|
消息中间件 存储 网络协议
操作系统的心脏:深入理解进程间通信(IPC)机制
在现代计算机系统中,操作系统扮演着至关重要的角色,而进程间通信(IPC)作为操作系统的核心功能之一,极大地影响着系统的性能和稳定性。本文将通过浅显易懂的语言,详细探讨进程间通信的基本原理、主要类型及其实际应用,旨在为读者提供一个清晰且全面的理解和认识。 ##
927 1
|
算法 定位技术
路径规划算法 - 求解最短路径 - A*(A-Star)算法
路径规划算法 - 求解最短路径 - A*(A-Star)算法
3573 1
`scipy.signal`模块是SciPy库中的一个子模块,它提供了信号处理、滤波、频谱分析等功能。这个模块包含了许多用于信号处理的函数和类,其中`butter()`和`filtfilt()`是两个常用的函数。
`scipy.signal`模块是SciPy库中的一个子模块,它提供了信号处理、滤波、频谱分析等功能。这个模块包含了许多用于信号处理的函数和类,其中`butter()`和`filtfilt()`是两个常用的函数。