基于连续Hopfield神经网络优化——旅行商问题优化计算

news2024/10/6 6:05:39

        大家好,我是带我去滑雪!

        利用神经网络解决组合优化问题是神经网络应用的一个重要方面。所谓组合优化问题,就是在给定约束条件下,使目标函数极小(或极大)的变量组合问题。将Hopfield网络应用于求解组合优化问题,把目标函数转化为网络的能量函数,把问题的变量对应到网络的状态,这样,当网络的能量函数收敛于极小值时,问题的最优解也随之求出。由于神经网络是并行计算的,其计算量不随维数的增加而发生指数性“爆炸”,因而对于组合优化问题的高速计算特别有效。典型的组合优化问题有旅行商问题、0-1背包问题、装箱问题、图着色问题、聚类问题等问题。这些问题的描述都非常简单,但优化求解很困难,其主要原因是求解这些问题的算法运行时,需要极长的运行时间和极大的存储空间。

        本期使用连续Hopfield神经网络实现旅行商问题优化计算。

一、问题与模型设计 

(1)问题描述

       旅行商问题,(Traveling Saleman Problem,TSP)是VRP的特例,由于Gaery[1]已证明TSP问题是NP难题,因此,VRP也属于NP难题。旅行商问题(TSP)又译为旅行推销员问题、货郎担问题,简称为TSP问题,是最基本的路线问题,该问题是在寻求单一旅行者由起点出发,通过所有给定的需求点之后,最后再回到原点的最小路径成本。

        现对于一个城市数量为10的TSP问题,要求设计一个可以对其组合优化的连续型Hopfield神经网络模型,利用改模型可以快速地找到最优(或者近似最优)的一条路线。

(2)模型建立思路

        由于连续型Hopfield神经网络具有优化计算的特性,因此将TSP问题的目标函数(即最短路径)与网络的能量函数相对应,将经过的城市顺序与网络的神经元状态相对应。这样,由连续型Hopfield神经网络的稳定性定理知,当网络的能量函数趋于最小值时,网络的神经元状态也趋于平衡点,此时对应的城市顺序即为最佳的路线。

(3)设计步骤

       模型映射:为了将TSP问题映射为一个神经网络的动态过程,Hopfield神经网络采取换位矩阵的表示方式,用NxN的矩阵表示商人访问N个城市。对于N个城市TSP问题,使用NxN个神经元来实现,而每行每列只能有一个1,其余都是0,矩阵中1的和为N,该矩阵成为换位矩阵。

        构造网络能量函数和动态方程:设计的Hopfield神经网络的能量函数与目标函数(即最短路径)相对应的。同时,考虑到有效解的实际意义,即换位矩阵的每行每列都只能有一个1。因此,网络的能量函数包含目标项和约束项两部分。

        初始化网络:Hopfield神经网络迭代过程对网络的能量函数及动态方程的系数十分敏感,在总结前人经验及多次实验的基础上,网络输入初始化选取如下:A=200,D=100,采样时间设置为0.0001,迭代次数为10000。

       优化计算:当网络的结果及参数设计完成后,迭代优化计算的过程就变得非常简单,具体步骤:

步骤1:导入N个城市的位置坐标并计算城市之间的距离;

步骤2:网络初始化;

步骤3:计算能量函数;

步骤4:判断迭代次数是否结束,若迭代次数大于10000,则终止。

二、代码实现

(1)清空环境变量、声明全局变量

clear all
clc
global A D

(2)城市位置导入并计算城市间距离

load city_location
distance = dist(citys,citys');

(3)初始化网络

N = size(citys,1);
A = 200;
D = 100;
U0 = 0.1;
step = 0.0001;
delta = 2 * rand(N,N) - 1;
U = U0 * log(N-1) + delta;
V = (1 + tansig(U/U0))/2;
iter_num = 10000;
E = zeros(1,iter_num);

 (4)寻优迭代

        寻优迭代过程包括动态方程计算、输入神经元状态更新、输出神经元状态更新、能量函数计算四个步骤。 

for k = 1:iter_num  
    dU = diff_u(V,distance);
    U = U + dU*step;
    V = (1 + tansig(U/U0))/2;
    e = energy(V,distance);
    E(k) = e;  
end

(5)动态方程计算

function du=diff_u(V,d)
global A D
n=size(V,1);
sum_x=repmat(sum(V,2)-1,1,n);
sum_i=repmat(sum(V,1)-1,n,1);
V_temp=V(:,2:n);
V_temp=[V_temp V(:,1)];
sum_d=d*V_temp;
du=-A*sum_x-A*sum_i-D*sum_d;

(6)能量函数计算

function E=energy(V,d)
global A D
n=size(V,1);
sum_x=sumsqr(sum(V,2)-1);
sum_i=sumsqr(sum(V,1)-1);
V_temp=V(:,2:n);
V_temp=[V_temp V(:,1)];
sum_d=d*V_temp;
sum_d=sum(sum(V.*sum_d));
E=0.5*(A*sum_x+A*sum_i+D*sum_d);

(7)主函数

[rows,cols] = size(V);
V1 = zeros(rows,cols);
[V_max,V_ind] = max(V);
for j = 1:cols
    V1(V_ind(j),j) = 1;
end
C = sum(V1,1);
R = sum(V1,2);
flag = isequal(C,ones(1,N)) & isequal(R',ones(1,N));

%% 结果显示
if flag == 1
   % 计算初始路径长度
   sort_rand = randperm(N);
   citys_rand = citys(sort_rand,:);
   Length_init = dist(citys_rand(1,:),citys_rand(end,:)');
   for i = 2:size(citys_rand,1)
       Length_init = Length_init+dist(citys_rand(i-1,:),citys_rand(i,:)');
   end
   % 绘制初始路径
   figure(1)
   plot([citys_rand(:,1);citys_rand(1,1)],[citys_rand(:,2);citys_rand(1,2)],'o-')
   for i = 1:length(citys)
       text(citys(i,1),citys(i,2),['   ' num2str(i)])
   end
   text(citys_rand(1,1),citys_rand(1,2),['       起点' ])
   text(citys_rand(end,1),citys_rand(end,2),['       终点' ])
   title(['优化前路径(长度:' num2str(Length_init) ')'])
   axis([0 1 0 1])
   grid on
   xlabel('城市位置横坐标')
   ylabel('城市位置纵坐标')
   % 计算最优路径长度
   [V1_max,V1_ind] = max(V1);
   citys_end = citys(V1_ind,:);
   Length_end = dist(citys_end(1,:),citys_end(end,:)');
   for i = 2:size(citys_end,1)
       Length_end = Length_end+dist(citys_end(i-1,:),citys_end(i,:)');
   end
   disp('最优路径矩阵');V1
   % 绘制最优路径
   figure(2)
   plot([citys_end(:,1);citys_end(1,1)],...
       [citys_end(:,2);citys_end(1,2)],'o-')
   for i = 1:length(citys)
       text(citys(i,1),citys(i,2),['  ' num2str(i)])
   end
   text(citys_end(1,1),citys_end(1,2),['       起点' ])
   text(citys_end(end,1),citys_end(end,2),['       终点' ])
   title(['优化后路径(长度:' num2str(Length_end) ')'])
   axis([0 1 0 1])
   grid on
   xlabel('城市位置横坐标')
   ylabel('城市位置纵坐标')
   % 绘制能量函数变化曲线
   figure(3)
   plot(1:iter_num,E);
   ylim([0 2000])
   title(['能量函数变化曲线(最优能量:' num2str(E(end)) ')']);
   xlabel('迭代次数');
   ylabel('能量函数');
else
   disp('寻优路径无效');
end

(8)结果输出

       优化前的路径:

      优化后的路径图:

      优化后的路径距离相比于没有优化的路径距离更短。

      能量函数变化曲线:

       结果表明:利用Hopfield神经网络 ,可以快速准确地解决TSP问题。同理,对于其他利用枚举法会产生“组合爆炸”的组合优化问题,利用连续型Hopfield神经网络也可以进行优化计算。

需要数据集的家人们可以去百度网盘(永久有效)获取:

链接:
提取码:2138 


更多优质内容持续发布中,请移步主页查看。

   点赞+关注,下次不迷路!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1204917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos7 升级到 Centos8 教程以及关于dnf包管理工具的若干问题解决方案

目录 为什么升级一、参考文档二、升级步骤三、安装git编码错误缓存问题安装git依赖冲突问题解决办法 为什么升级 jenkins 2.4版本需要CentOS8 一、参考文档 点我 二、升级步骤 1.安装epel源 yum -y install epel-release2.安装rpmconf和yum-utils yum -y install rpmco…

死锁(JAVA)

死锁在多线程代码中是非常严重的BUG,一旦代码中出现死锁就会导致线程卡死。 当单个线程连续两次对同一个对象进行加锁操作时,如果该锁是不可重入锁就会发生死锁(线程卡死) 两个线程两把锁,如果出现这种情况也是会发生…

瑞吉外卖Day02

小张推荐:瑞吉外卖Day01,瑞吉外卖Day03 1.登陆功能 1.1结果封装类 导入返回结果类R此类是一个通用结果类。服务端响应的所有结果最终都会包装成此种类型返回给前端页面 注意属性名,莫要写错,不然与前端很难对接!!&…

Docker 中的端口

Docker 中的端口 0.0.0.0:8080->80/tcp ,主机(即运行 Docker 的机器)监听8080端口,如果有请求转发到容器的 80 端口上去。 详细解释一下: 0.0.0.0:8080->80/tcp :这是一个端口映射规则。 0.0.0.0:80…

Leetcode—202.快乐数【简单】

2023每日刷题(二十八) Leetcode—202.快乐数 快慢指针思想 通过手玩2,可以发现 会走入一个循环,并且fast和slow会在一个数字相遇,以下也大概花了一下推倒出来了。如果slow不是因为1和fast相等的,就说明它…

消息队列中的事务是什么呢?

消息队列中的事务是什么呢? 说到事务,肯定会优先想到数据库中的事务。在数据库中需要事务,是为了保证数据的一致性、完整性、持久性和隔离性。它可以将数据库中的一组操作合并为一个不可分割的工作单元,要么全部执行成功&#xf…

​软考-高级-系统架构设计师教程(清华第2版)【第4章 信息安全技术基础知识(P160~189)-思维导图】​

软考-高级-系统架构设计师教程(清华第2版)【第4章 信息安全技术基础知识(P160~189)-思维导图】 课本里章节里所有蓝色字体的思维导图

【沐风老师】3dMax使用克隆修改器插件创建旋转楼梯教程

3DMAX克隆修改器插件,它通过增量平移、旋转和缩放输入几何体来创建对象的副本。在某些方面,它类似于 3dMax 的内置“阵列”工具,但有一个主要优点 -克隆修改器是完全参数化的,因此您可以随时更改重复项的数量及其分布。其他功能包…

mapboxGL中的底图切换

概述 底图切换,这么简单的功能还要写一篇文章?值得的,为什么这么说呢?因为mapboxGL的矢量底图有上百个,不同的底图用的样式、图层的名称、图层的内容、字体库、图标库都不一样,尤其是当地图上已经叠加了很…

展会预告 | 图扑邀您相约高交会-全球清洁能源创新博览会

第二十五届中国国际高新技术成果交易会(简称“高交会”)将在深圳盛大开幕。高交会由商务部、科学技术部、工业和信息化部、国家发展改革委、农业农村部、国家知识产权局、中国科学院、中国工程院和深圳市人民政府共同举办。是目前中国规模最大、最具影响力的科技类展会。 图扑软…

【LittleXi】C程序预处理、编译、汇编、链接步骤

【LittleXi】C程序预处理、编译、汇编、链接步骤 C程序 #include<stdio.h> int main(){int x1,y1;printf("xy%d",xy); }1、预处理 将头文件引入进来、除去注释、宏定义下放 执行指令 g -E esc.c -o esc.i 2、编译 将处理好的代码编译为汇编代码.s 执行…

AI优秀企业案例——机器人流程自动化:达观数据RPA

通过学习业内领先公司的最佳实践&#xff0c;我们可以更好地将它们应用到我们自己的公司和业务中。特别是第三部分&#xff0c;提供了大量应用案例&#xff0c;让我们一起期待看到这些案例的结尾。 1.简介 达观数据是一家专注于智能文本机器人的国家高新技术企业&#xff0c;…

Flink SQL -- 反压

1、测试反压&#xff1a; 1、反压&#xff1a; 指的是下游消费数据的速度比上游产生数据的速度要小时会出现反压&#xff0c;下游导致上游的Task反压。 2、测试反压&#xff1a;使用的是DataGen CREATE TABLE words (word STRING ) WITH (connector datagen,rows-per-second…

C# 使用AForge调用摄像头

C# 使用AForge调用摄像头 安装AForge使用AForge控件示例代码 AForge官网 安装AForge Visual Studio 2022>项目>管理NuGet程序包&#xff0c;搜索AForge并依次安装作者为AForge.NET的多个关联组件。 使用AForge控件 安装AForge组件完成后&#xff0c;工具箱会新增AF…

【反编译系列】一、反编译 .so 文件(IDA Pro)

文章目录 【反编译系列】一、反编译 .so 文件&#xff08;IDA Pro&#xff09;1. 介绍2. 反编译Reference 【反编译系列】一、反编译 .so 文件&#xff08;IDA Pro&#xff09; 1. 介绍 .so 文件是共享对象文件&#xff08;Shared Object file&#xff09;的一种形式&#xf…

【Cookie 和 session 的区别】

会话&#xff08;Session&#xff09; 跟踪是Web程序中常用的技术&#xff0c;用来跟踪用户的整个会话。cookie和session都是用来跟踪浏览器用户身份的会话方式。Cookie通过在客户端记录信息确定用户身份&#xff0c;Session通过在服务器端记录信息确定用户身份。 我们目前使用…

网络之路25:VLAN进阶实验-Super VLAN

正文共&#xff1a;1333 字 13 图&#xff0c;预估阅读时间&#xff1a;1 分钟 目录 网络之路第一章&#xff1a;Windows系统中的网络 0、序言 1、Windows系统中的网络1.1、桌面中的网卡1.2、命令行中的网卡1.3、路由表1.4、家用路由器 网络之路第二章&#xff1a;认识企业设备…

【verilog】verilog语法刷题知识点总结

verilog语法刷题知识点总结 1.状态机2.任务和函数的区别3.case&#xff0c;casez和casex4.随机数产生关键字5.运算符优先级6.运算符的特殊注意点及特殊运算符(1)移位运算符(2)等式运算符(3)动态位宽截取运算符(4)求余运算符&#xff08;%&#xff09; 7.testbench知识点8.乘法器…

CTFSHOW -SQL 注入

重新来做一遍 争取不看wp web171 基本联合注入 拿到题目我们已经知道了是sql注入 所以我们可以直接开始 第一题 不会难道哪里去 所以我们直接进行注入即可 1 and 12-- 1 and 11-- 实现闭合 -1unionselect1,2,3--%2b 查看字段数-1unionselect1,database(),3--%2b 查看数据…

【vue】虚拟dom的原理是什么?手写实现虚拟dom !

1.虚拟dom的原理 虚拟 DOM 是对 DOM 的抽象&#xff0c;本质上就是用 JavaScript 对象来描述 DOM 结构。Vue.js 中关于虚拟 DOM 的实现主要进行了以下几个步骤&#xff1a; 1.生成虚拟 DOM&#xff1a; Vue.js 使用 render 函数来依据模板代码生成虚拟 DOM。在这个过程中&a…