通信系统仿真

崔春雷

目录

  • 1 第一单元: MATLAB基础
    • 1.1 课程说明与资料
      • 1.1.1 作业参考答案
      • 1.1.2 移动22级作业答案
    • 1.2 MATLAB安装与运行环境
      • 1.2.1 MATLAB介绍
    • 1.3 基本数据类型:数值类型
    • 1.4 基本数据类型:字符类型
    • 1.5 数据类型转换与输出
    • 1.6 数组与矩阵基础
      • 1.6.1 矩阵运算进阶
    • 1.7 数组与矩阵常用函数
    • 1.8 matlab中的逻辑运算
    • 1.9 实验: MATLAB常用数学函数
      • 1.9.1 实验 作业答案
    • 1.10 元胞数组
    • 1.11 结构体数组
      • 1.11.1 结构体进阶
      • 1.11.2 元胞数组与结构体数组对比
      • 1.11.3 map 容器
    • 1.12 附录:MATLAB常用基础命令
    • 1.13 拓展内容:实时脚本
      • 1.13.1 实时脚本示例
    • 1.14 课程作业与答案
      • 1.14.1 《通信系统仿真》期末考试
  • 2 第二单元:Matlab 程序设计
    • 2.1 顺序结构程序
    • 2.2 分支结构—— if语句
    • 2.3 分支结构—— switch语句
    • 2.4 循环结构—— while语句
    • 2.5 循环结构—— for语句
    • 2.6 图像处理基础
    • 2.7 Matlab的函数
      • 2.7.1 函数内容的课外扩展
    • 2.8 本章实验:for循环的应用
      • 2.8.1 素数问题
        • 2.8.1.1 素数的螺旋线排列
      • 2.8.2 3X+1猜想
      • 2.8.3 7 行代码计算 π
    • 2.9 排序算法
      • 2.9.1 冒泡排序
      • 2.9.2 选择排序
      • 2.9.3 插入排序
      • 2.9.4 快速排序
      • 2.9.5 基数排序
      • 2.9.6 计数排序
      • 2.9.7 堆排序
    • 2.10 动态规划算法
      • 2.10.1 动态规划编程实例
      • 2.10.2 动态规划:01背包问题
      • 2.10.3 动态规划常见题目分析
      • 2.10.4 动态规划题目分析2
    • 2.11 常用算法简介
      • 2.11.1 剪枝算法
      • 2.11.2 二分查找
      • 2.11.3 递归算法
      • 2.11.4 回溯算法
        • 2.11.4.1 Leetcode回溯题目合集
        • 2.11.4.2 回溯算法总结
        • 2.11.4.3 回溯法解数独问题
        • 2.11.4.4 DFS与BFS
          • 2.11.4.4.1 DFS/BFS原理
          • 2.11.4.4.2 BFS的应用:Dijkstra算法
      • 2.11.5 n 皇后问题专题
      • 2.11.6 双指针算法
      • 2.11.7 数组模拟链表(约瑟夫环)
      • 2.11.8 Hash(哈希表)
      • 2.11.9 图论与路径规划
        • 2.11.9.1 迪杰斯特拉算法
        • 2.11.9.2 A*算法
          • 2.11.9.2.1 A*算法的MATLAB实现
        • 2.11.9.3 RRT路径规划算法
          • 2.11.9.3.1 RRT算法 MATLAB代码
          • 2.11.9.3.2 参考资料
      • 2.11.10 数据结构
        • 2.11.10.1 数据结构例题
      • 2.11.11 前缀和 差分 双指针
      • 2.11.12 位运算
      • 2.11.13 常用算法代码模板
    • 2.12 练习题库
    • 2.13 code
      • 2.13.1 简易计算器gui代码
      • 2.13.2 五子棋
      • 2.13.3 连连看小游戏
      • 2.13.4 递归算法与汉诺塔
      • 2.13.5 有理数的小数循环节
    • 2.14 MATLAB编程风格
      • 2.14.1 向量化编程专题
  • 3 第三单元:Matlab 图形图像处理
    • 3.1 二维图形绘图基础
    • 3.2 二维图形绘图进阶
    • 3.3 三维图形绘图
      • 3.3.1 MATLAB绘图小结
        • 3.3.1.1 用matlab绘制好看图像
    • 3.4 MATLAB高级绘图
    • 3.5 文件操作
    • 3.6 Matlab图像处理进阶
      • 3.6.1 补充:Matlab图像处理常用函数
      • 3.6.2 RGB/HSV/HSI颜色模型
      • 3.6.3 图片切换动画效果
      • 3.6.4 图像连通域标记
      • 3.6.5 图像旋转与插值
      • 3.6.6 图像的形态学
      • 3.6.7 空间滤波
        • 3.6.7.1 图像中常见的噪声类型与滤波方法
        • 3.6.7.2 matlab中的滤波函数
        • 3.6.7.3 BM3D 去噪算法
        • 3.6.7.4 双边滤波
      • 3.6.8 图像的频域处理
    • 3.7 本章总结
    • 3.8 实验 : matlab 绘图练习1
    • 3.9 实验: matlab 绘图练习2
    • 3.10 实验 :数学函数图像绘制
    • 3.11 实验:绘图综合练习
    • 3.12 实验:曲线拟合
    • 3.13 实验:牛顿法求解方程的根
    • 3.14 实验:信号的傅里叶变换
      • 3.14.1 傅里叶变换、小波变换、希尔伯特变换
      • 3.14.2 新建目录
    • 3.15 课外补充:图像处理基础1
    • 3.16 课外补充:图像处理基础2
    • 3.17 课外补充:图像处理基础3
    • 3.18 课外补充:PYTHON基础
  • 4 第五单元:MATLAB通信仿真
    • 4.1 现代通信系统的介绍
    • 4.2 模拟通信系统的仿真原理
    • 4.3 HDB3编解码的仿真实现
    • 4.4 SIMULINK和其模块简介
    • 4.5 数字通信系统的仿真原理
    • 4.6 模拟通信系统Simulink仿真
    • 4.7 数字通信系统Simulink仿真
    • 4.8 音频信号测处理与仿真
    • 4.9 图像数字水印技术
      • 4.9.1 三角函数到傅里叶变换再到语音识别与数字水印
    • 4.10 信息系统与算法
      • 4.10.1 递归算法
        • 4.10.1.1 递归与堆栈的关系
      • 4.10.2 哈希表
      • 4.10.3 双指针算法
        • 4.10.3.1 双指针算法实战
        • 4.10.3.2 双指针进阶:滑动窗口算法
      • 4.10.4 字符串匹配 KMP算法
        • 4.10.4.1 字符串匹配B-M算法
      • 4.10.5 快速傅里叶变换
      • 4.10.6 回溯算法
      • 4.10.7 动态规划
      • 4.10.8 分治算法
      • 4.10.9 Dijkstra算法
  • 5 第六单元: systemview通信仿真
    • 5.1 SystemView概述
    • 5.2 模拟通信系统 数字系统的仿真分析
    • 5.3 SystemView通信系统仿真进阶
    • 5.4 新建课程目录
  • 6 第四单元:MATLAB高级应用
    • 6.1 符号运算基础
      • 6.1.1 利用Matlab自动推导公式
    • 6.2 Matlab中的数值计算
      • 6.2.1 积分的计算
      • 6.2.2 龙格库塔:常微分方程的数值解法
      • 6.2.3 fmincon函数与非线性方程最小值
    • 6.3 统计、拟合、插值
      • 6.3.1 协方差与相关系数
    • 6.4 GUI设计初步
    • 6.5 matlab GUI界面编程
      • 6.5.1 gui实例
      • 6.5.2 gui编程中常用函数
      • 6.5.3 App Designer入门
    • 6.6 实验:GUI设计图像空间变换系统
    • 6.7 作业:利用GUI设计 计算器、信号发生器等
    • 6.8 MTALB数据导入方法
    • 6.9 课外补充:MATLAB的App会取代GUI吗?
    • 6.10 模拟退火算法matlab实现
    • 6.11 遗传算法的Matlab实现
      • 6.11.1 进化算法(Evolutionary Algorithm)及相关函数介绍
    • 6.12 粒子群算法 matlab实现
      • 6.12.1 粒子群算法及MATLAB实例仿真
    • 6.13 BP网络的应用
    • 6.14 matlab 结构体
    • 6.15 群智能算法合集
  • 7 拓展知识
    • 7.1 什么是算法的时间复杂度?
    • 7.2 Notepad++使用教程
    • 7.3 MATLAB常用函数总结
    • 7.4 MATLAB常用知识点总结
    • 7.5 MATLAB命令大全
    • 7.6 视频:MATLAB官方基础教程
    • 7.7 经典书籍:Matlab2012经典超强教程
    • 7.8 经典书籍:MATLAB揭秘(自学宝典)
    • 7.9 经典资料:MATLAB N个实用技巧
    • 7.10 Matlab编程小技巧
    • 7.11 寻优算法
      • 7.11.1 Dijkstra算法python实现
    • 7.12 PYTHON基础教程
      • 7.12.1 Python进阶
      • 7.12.2 Python小技巧
      • 7.12.3 Python总结
        • 7.12.3.1 Python循环语句总结
        • 7.12.3.2 24个顶级Python库
        • 7.12.3.3 魔法函数
      • 7.12.4 廖雪峰python
      • 7.12.5 正则表达式基础
      • 7.12.6 numpy
        • 7.12.6.1 101道Numpy习题
        • 7.12.6.2 Numpy简要语法教程
        • 7.12.6.3 Numpy实现全连接神经网络 (手写数字识别)
        • 7.12.6.4 图解NumPy
      • 7.12.7 matplotlib
        • 7.12.7.1 matplotlib练习50题
        • 7.12.7.2 Matplotlib速查表
        • 7.12.7.3 Matplotlib 实操指南
      • 7.12.8 Python3 模块 import
      • 7.12.9 Python 小项目
    • 7.13 参考资源:数据结构与算法
      • 7.13.1 十大经典排序算法总结
    • 7.14 机器学习概述
      • 7.14.1 反向传播算法
        • 7.14.1.1 反向传播的数学原理
      • 7.14.2 极大似然估计
        • 7.14.2.1 极大似然估计与最小二乘法
      • 7.14.3 Batch Normalization
        • 7.14.3.1 Batch Normalization&Dropout浅析
        • 7.14.3.2 ​BN层的梯度反向传播计算
        • 7.14.3.3 Batch Size的大小与神经网络的性能
        • 7.14.3.4 标准化和归一化
      • 7.14.4 主成分分析PCA与SVD奇异值分解
        • 7.14.4.1 岭回归 与 PCA
        • 7.14.4.2 PCA原理推导
        • 7.14.4.3 PCA原理新解
        • 7.14.4.4 svd
        • 7.14.4.5 PCA数学原理
      • 7.14.5 正则化
        • 7.14.5.1 L1、L2正则化和过拟合 总结
        • 7.14.5.2 L1 和 L2 正则化的直观解释
      • 7.14.6 SVM
        • 7.14.6.1 从零推导支持向量机(SVM)
        • 7.14.6.2 支持向量机(SVM)介绍
        • 7.14.6.3 SVM推导与实战
        • 7.14.6.4 支持向量机的直观理解
        • 7.14.6.5 浅显易懂的支持向量机SVM
      • 7.14.7 线性回归
      • 7.14.8 逻辑回归
      • 7.14.9 BP算法
        • 7.14.9.1 万能逼近——神经网络拟合任意函数原理
      • 7.14.10 激活与池化
        • 7.14.10.1 激活函数与损失函数 小结
      • 7.14.11 深度学习简述
        • 7.14.11.1 MATLAB2020深度学习实例
      • 7.14.12 损失函数与误差反向传播
        • 7.14.12.1 梯度下降与损失函数
      • 7.14.13 深度学习优化问题
      • 7.14.14 梯度下降法
        • 7.14.14.1 各类梯度下降算法的Python实现
        • 7.14.14.2 梯度下降的直观理解
        • 7.14.14.3 动量、RMSProp、Adam
      • 7.14.15 卷积的概念
        • 7.14.15.1 卷积的矩阵化算法
      • 7.14.16 局部连接
      • 7.14.17 RNN
      • 7.14.18 LSTM
      • 7.14.19 CNN-四大经典CNN技术浅析
      • 7.14.20 熵(Entropy)与交叉熵
      • 7.14.21 softmax函数详解
      • 7.14.22 自编码算法详细理解与代码实现
      • 7.14.23 pytorch
        • 7.14.23.1 ​PyTorch简介
          • 7.14.23.1.1 Pytorch快速入门资料
        • 7.14.23.2 CNN的PyTorch实现
        • 7.14.23.3 pytorch总结
        • 7.14.23.4 PyTorch trick 集锦
        • 7.14.23.5 在PyTorch上加载自定义数据集
        • 7.14.23.6 实战:Pytorch识别验证码
        • 7.14.23.7 实战:Transformer的最简洁pytorch实现
        • 7.14.23.8 使用PyTorch实现神经网络分类
      • 7.14.24 卷积神经网络CNN概述
        • 7.14.24.1 CNN 简易原理
        • 7.14.24.2 卷积神经网络CNN原理详解
        • 7.14.24.3 自己手写一个卷积神经网络
        • 7.14.24.4 CNN反向传播算法
        • 7.14.24.5 卷积计算、作用与思想
        • 7.14.24.6 用卷积神经网络CNN识别手写数字集
        • 7.14.24.7 卷积 池化 参数的计算
        • 7.14.24.8 im2col方法实现卷积算法
        • 7.14.24.9 卷积核的梯度计算
        • 7.14.24.10 卷积层反向传播推导及实现
        • 7.14.24.11 反向传输算法
          • 7.14.24.11.1 resnet残差网络
        • 7.14.24.12 CNN反向传播的MATLAB实现
      • 7.14.25 神经网络的调参技巧
      • 7.14.26 BP神经网络
        • 7.14.26.1 零开始搭建bp神经网络
        • 7.14.26.2 MATLAB自带的bp工具箱
        • 7.14.26.3 神经网络中偏置(bias)的作用
      • 7.14.27 聚类分析 k-means
        • 7.14.27.1 matlab做聚类分析(k-means)
        • 7.14.27.2 聚类模型探讨综述
        • 7.14.27.3 5种经典聚类算法
      • 7.14.28 深度学习的一些概念
      • 7.14.29 人工智能简述:AI的过去和现在
      • 7.14.30 k-NN(k近邻算法)
      • 7.14.31 神经网络中的优化器:BGD、SGD、MBGD、Momentum
      • 7.14.32 卷积神经网络的经典网络总结
        • 7.14.32.1 卷积神经网络中十大拍案叫绝的操作
      • 7.14.33 GAN 对抗样本攻击
      • 7.14.34 蒙特卡洛模拟
      • 7.14.35 dropout与随机部分连接
      • 7.14.36 Jupyter 等 IDE概览
      • 7.14.37 分类算法常用评价指标
      • 7.14.38 Inception 网络与不变性
      • 7.14.39 卷积神经网络的可视化
      • 7.14.40 隐马尔可夫模型HMM
        • 7.14.40.1 马尔科夫链
    • 7.15 MATLAB音频处理
      • 7.15.1 python处理音频信号
    • 7.16 图像处理
      • 7.16.1 图像处理中的指标
    • 7.17 代码集
    • 7.18 论文写作与阅读方法
      • 7.18.1 期刊投稿攻略
      • 7.18.2 论文排版教程
      • 7.18.3 SCI-HUB论文下载技巧
      • 7.18.4 几种论文写作神器,提高写作效率
      • 7.18.5 latex入门
      • 7.18.6 LaTeX教程
    • 7.19 机器学习常用的网站以及资源
      • 7.19.1 很详细的ML&DL学习博客
    • 7.20 SymPy 符号计算基本教程
  • 8 程序设计数学基础
    • 8.1 编程数学基础
      • 8.1.1 概率的历史
      • 8.1.2 概率
        • 8.1.2.1 常见概率分布
          • 8.1.2.1.1 二维正态分布
        • 8.1.2.2 蒙特卡罗方法
        • 8.1.2.3 置信区间
        • 8.1.2.4 协方差与相关系数
      • 8.1.3 矩阵 向量求导法则
      • 8.1.4 雅可比矩阵 海森矩阵
      • 8.1.5 矩阵的几种分解方式
      • 8.1.6 行列式和代数余子式
      • 8.1.7 向量
      • 8.1.8 矩阵的基本运算
      • 8.1.9 矩阵分析
      • 8.1.10 矩阵的LU分解
      • 8.1.11 矩阵奇异值分解(SVD)
        • 8.1.11.1 SVD分解2
        • 8.1.11.2 SVD分解逐步推导
        • 8.1.11.3 奇异值与特征值的意义
      • 8.1.12 随机向量
        • 8.1.12.1 随机过程简述
      • 8.1.13 投影矩阵和最小二乘
      • 8.1.14 知乎数学精选集
        • 8.1.14.1 高数问题集
      • 8.1.15 小波变换
      • 8.1.16 程序设计数学基础1:高等数学
      • 8.1.17 程序设计数学基础2:线性代数
      • 8.1.18 程序设计数学基础3:概率论和数理统计
      • 8.1.19 向量的距离与相似度计算
      • 8.1.20 复数
      • 8.1.21 高等数学——幂级数
      • 8.1.22 无穷小的本质
      • 8.1.23 数列极限和收敛性
      • 8.1.24 不定积分技巧总结
    • 8.2 有趣的数学题目
    • 8.3 高等数学
      • 8.3.1 泰勒级数
  • 9 路径规划与智能算法
    • 9.1 常见路径规划算法简介
    • 9.2 Dijkstra算法详细
  • 10 教学文档
    • 10.1 授课计划
    • 10.2 课程标准
模拟退火算法matlab实现

模拟退火算法与matlab实现


  • 模拟退火算法原理

模拟退火(simulated annealing,SA)算法的思想最早是由Metropolis等提出的。其出发点是基于物理中固体物质的退火过程与一般的组合优化问题之间的相似性。模拟退火法是一种通用的优化算法,其物理退火过程由以下三部分组成:

(1)加温过程。其目的是增强粒子的热运动,使其偏离平衡位置。当温度足够高时,固体将熔为液体,从而消除系统原先存在的非均匀状态。

(2)等温过程。对于与周围环境交换热量而温度不变的封闭系统,系统状态的自发变化总是朝自由能减少的方向进行的,当自由能达到最小时,系统达到平衡状态。

(3)冷却过程。使粒子热运动减弱,系统能量下降,得到晶体结构。

其中,加温过程对应算法的设定初温,等温过程对应算法的Metropolis抽样过程,冷却过程对应控制参数的下降。这里能量的变化就是目标函数,要得到的最优解就是能量最低态。Metropolis准则是SA算法收敛于全局最优解的关键所在,Metropolis准则以一定的概率接受恶化解,这样就使算法跳离局部最优的陷阱。

模拟退火算法为求解传统方法难处理的TSP问题提供了一个有效的途径和通用框架,并逐渐发展成一种迭代自适应启发式概率性搜索算法。模拟退火算法可以用以求解不同的非线性问题,对不可微甚至不连续的函数优化,能以较大概率求得全局优化解。该算法还具有较强的鲁棒性、全局收敛性、隐含并行性及广泛的适应性,并且能处理不同类型的优化设计变量(离散的、连续的和混合型的),不需要任何的辅助信息,对目标函数和约束函数没有任何要求。利用Metropolis算法并适当地控制温度下降过程,在优化问题中具有很强的竞争力,本章主要研究基于模拟退火算法的TSP算法。

  • 算法步骤

SA算法实现过程如下(以最小化问题为例):

【1】初始化:取初始温度 [公式] 足够大,令 [公式] ,任取初始解 [公式] ,确定每个 [公式] 时的迭代次数,即Metropolis链长 [公式] 。

【2】对当前温度 [公式] 和 [公式] ,重复步骤【3】-【6】。

【3】对当前解 [公式] 随机扰动产生一个新解 [公式] 。

【4】计算 [公式] 的增量 [公式] ,其中 [公式] 为 [公式] 的代价函数。

【5】若 [公式] ,则接受 [公式] 作为新的当前解,即 [公式] ;否则计算 [公式] 的接受概率 [公式] ,即随机产生 [公式] 区间上均匀分布的随机数rand,若 [公式],也接受 [公式] 作为新的当前解, [公式] ;否则保留当前解 [公式] 。

【6】如果满足终止条件Stop,则输出当前解 [公式] 为最优解,结束程序。终止条件Stop通常为:在连续若干个Metropolis链中新解 [公式] 都没有被接受时终止算法,或是设定结束温度。否则按衰减函数衰减 [公式] 后返回步骤【2】。

以上步骤称为Metropolis过程。逐渐降低控制温度,重复Metropolis过程,直至满足结束准则Stop,求出最优解。





  • TSP问题(旅行商问题)

TSP问题是典型的NP完全问题,即其最坏情况下的时间复杂度随着问题规模的增大按指数方式增长,到目前为止还未找到一个多项式时间的有效算法。

TSP问题可描述为:已知 [公式] 个城市相互之间的距离,某一旅行商从某个城市出发访问每个城市一次且仅一次,最后回到出发城市,如何安排才使其所走路线最短。简言之,就是寻找一条最短的遍历 [公式] 个城市的路径,或者说搜索自然子集 [公式] ( [公式] 的元素表示对 [公式] 个城市的编号)的一个排列 [公式] ,使

[公式]

取最小值,其中 [公式] 表示城市 [公式] 到城市 [公式] 的距离。

TSP问题并不仅仅是旅行商问题,其他许多的NP完全问题也可以归结为TSP问题,如邮路问题、装配线上的螺母问题和产品的生产安排问题等,使得TSP问题的有效求解具有重要意义。

  • 例题

假定14个城市的位置坐标如表所列。寻找出一条最短的遍历14个城市的路径。





算法实现:

【1】设置主要控制参数

降温速率 [公式] 、初始温度 [公式] 、结束温度 [公式] 以及链长 [公式] 。

【2】初始解

对于 [公式] 个城市的TSP问题,得到的解就是对 [公式] 的一个排序,其中每个数字为对应城市的编号,如对10个城市的TSP问题 [公式] ,则 [公式] 就是一个合法的解,采用产生随机排列的方法产生一个初始解 [公式] 。

【3】解变换生成新解

通过对当前解 [公式] 进行变换,产生新的路径数组即新解,这里采用的变换是产生随机数的方法来产生将要交换的两个城市,用二邻域变换法产生新的路径,即新的可行解 [公式] 。

例如 [公式] 时,产生两个 [公式] 范围内的随机整数 [公式] 和 [公式] ,确定两个位置,将其对换位置,如 [公式]





得到的新解为





【4】Metropolis准则

若路径长度函数为 [公式] ,则当前解的路径为 [公式] ,新解的路径为 [公式] ,路径差为 [公式] ,则Metropolis准则为

[公式]

如果 [公式] ,则以概率1接受新的路径;否则以概率 [公式] 接受新的路径。

【5】降温

利用降温速率 [公式] 进行降温,即 [公式] ,若 [公式] 小于结束温度,则停止迭代输出当前状态,否则继续迭代。


  • 程序实现

1.计算距离矩阵

利用给出的N个城市的坐标,算出N个城市的两两之间的距离,得到距离矩阵 [公式] 。

TSP_Distance.m

function distance = TSP_Distance(position_coordinates)
% 计算两两城市之间的距离
%输入 position_coordinates  各城市的位置坐标
%输出 distance  两两城市之间的距离
row = size(position_coordinates,1);
distance = zeros(row,row);
for i = 1:row
    for j = i+1:row
        distance(i,j) = ((position_coordinates(i,1)-position_coordinates(j,1))^2+(position_coordinates(i,2)-position_coordinates(j,2))^2)^0.5;
        distance(j,i) = distance(i,j);
    end
end



2.初始解

初始解的产生直接使用MATLAB自带的函数randperm。如城市个数为N,则产生初始解:

S1 = randperm(N);   
%  randperm返回行向量,其中包含从1到n(包括两者)之间的整数随机置换
%  随机产生一个初始路线



3.生成新解

TSP_New_Solution.m

function S2 = TSP_New_Solution(S1)
% 输入
% S1:当前解
% 输出
% S2:新解
N = length(S1);
S2 = S1;                
a = round(rand(1,2)*(N-1) + 1); %产生两个随机位置 用来交换
W = S2(a(1));
S2(a(1)) = S2(a(2));
S2(a(2)) = W;         %得到一个新路线



4.Metropolis准则函数

TSP_Metropolis.m

function [S,R] = TSP_Metropolis(S1,S2,distance,T)
% 输入
% S1:  当前解
% S2:   新解
% distance:    距离矩阵(两两城市的之间的距离)
% T:    当前温度
% 输出
% S:   下一个当前解
% R:   下一个当前解的路线距离
%
fS1 = TSP_Feasible_Solution_Path_Length(distance,S1);  %计算路线长度
N = length(S1);         %得到城市的个数
fS2 = TSP_Feasible_Solution_Path_Length(distance,S2);  %计算路线长度
df = fS2 - fS1;   %计算能力之差
if df < 0       %如果能力降低 接受新路线
    S = S2;
    R = fS2;
elseif exp(-df/T)>=rand   %以exp(-dC/T)概率接受新路线
    S = S2;
    R = fS2;
else        %不接受新路线
    S = S1;
    R = fS1;
end



5.画路线轨迹图

TSP_Draw_Path.m

function TSP_Draw_Path(Chrom,position_coordinates)
% 画路径函数
%输入
% Chrom  待画路径   
% position_coordinates      各城市坐标位置
R = [Chrom(1,:) Chrom(1,1)]; %一个随机解(个体)
figure;
hold on
plot(position_coordinates(:,1),position_coordinates(:,2),'o','color',[0.5,0.5,0.5])
plot(position_coordinates(Chrom(1,1),1),position_coordinates(Chrom(1,1),2),'rv','MarkerSize',20)
for i = 1:size(position_coordinates,1)
    text(position_coordinates(i,1)+0.05,position_coordinates(i,2)+0.05,num2str(i),'color',[1,0,0]);
end
A = position_coordinates(R,:);
row = size(A,1);
for i = 2:row
    [arrowx,arrowy] = dsxy2figxy(gca,A(i-1:i,1),A(i-1:i,2));%坐标转换
    annotation('textarrow',arrowx,arrowy,'HeadWidth',8,'color',[0,0,1]);
end
hold off
xlabel('横坐标')
ylabel('纵坐标')
title('轨迹图')
box on



6.输出路径函数

TSP_Output_Path.m

function p = TSP_Output_Path(Route)
% 输出路径函数
%输入:R 路径
Route = [Route,Route(1)];
N = length(Route);
p = num2str(Route(1));
for i=2:N
    p = [p,'—>',num2str(Route(i))];
end
disp(p)



7.可行解路线长度函数

TSP_Feasible_Solution_Path_Length.m

function length = TSP_Feasible_Solution_Path_Length(distance,Chrom)
% 计算各个体的路径长度
% 输入:
% D     两两城市之间的距离
% Chrom 个体的轨迹
[row,col] = size(distance);
NIND = size(Chrom,1);
length = zeros(NIND,1);
for i=1:NIND
    p = [Chrom(i,:) Chrom(i,1)];
    i1 = p(1:end-1);
    i2 = p(2:end);
    length(i,1) = sum(distance((i1-1)*col+i2));
end



8.坐标转换

dsxy2figxy.m

function varargout = dsxy2figxy(varargin)
if length(varargin{1}) == 1 && ishandle(varargin{1}) ...
                            && strcmp(get(varargin{1},'type'),'axes')   
    hAx = varargin{1};
    varargin = varargin(2:end);
else
    hAx = gca;
end
if length(varargin) == 1
    pos = varargin{1};
else
    [x,y] = deal(varargin{:});
end
axun = get(hAx,'Units');
set(hAx,'Units','normalized'); 
axpos = get(hAx,'Position');
axlim = axis(hAx);
axwidth = diff(axlim(1:2));
axheight = diff(axlim(3:4));
if exist('x','var')
    varargout{1} = (x - axlim(1)) * axpos(3) / axwidth + axpos(1);
    varargout{2} = (y - axlim(3)) * axpos(4) / axheight + axpos(2);
else
    pos(1) = (pos(1) - axlim(1)) / axwidth * axpos(3) + axpos(1);
    pos(2) = (pos(2) - axlim(3)) / axheight * axpos(4) + axpos(2);
    pos(3) = pos(3) * axpos(3) / axwidth;
    pos(4) = pos(4) * axpos(4 )/ axheight;
    varargout{1} = pos;
end
set(hAx,'Units',axun)


9.模拟退火算法主函数

TSP_SA_Main.m

clc;
clear;
close all;
%%
tic
T0 = 1000;   % 初始温度
Tend = 1e-3;  % 终止温度
L = 200;    % 各温度下的迭代次数(链长)
q = 0.9;    %降温速率
X=[16.4700   96.1000
   16.4700   94.4400
   20.0900   92.5400
   22.3900   93.3700
   25.2300   97.2400
   22.0000   96.0500
   20.4700   97.0200
   17.2000   96.2900
   16.3000   97.3800
   14.0500   98.1200
   16.5300   97.3800
   21.5200   95.5900
   19.4100   97.1300
   20.0900   92.5500];

%%
D = TSP_Distance(X);  %计算距离矩阵
N = size(D,1);    %城市的个数
%% 初始解
S1 = randperm(N);  %随机产生一个初始路线
%% 画出随机解的路径图
TSP_Draw_Path(S1,X)
pause(0.0001)
%% 输出随机解的路径和总距离
disp('初始种群中的一个随机值:')
TSP_Output_Path(S1);
Rlength = TSP_Feasible_Solution_Path_Length(D,S1);
disp(['总距离:',num2str(Rlength)]);
syms x;
%% 计算迭代的次数Time
Time = ceil(double(solve([1000*(0.9)^x==1e-3,num2str(Tend)])));
count = 0;        %迭代计数
Obj = zeros(Time,1);         %目标值矩阵初始化
track = zeros(Time,N);       %每代的最优路线矩阵初始化
%% 迭代
while T0 > Tend
    count = count + 1;     %更新迭代次数
    temp = zeros(L,N+1);
    for k = 1:L
        %% 产生新解
        S2 = TSP_New_Solution(S1);
        %% Metropolis法则判断是否接受新解
        [S1,R] = TSP_Metropolis(S1,S2,D,T0);  %Metropolis 抽样算法
        temp(k,:) = [S1 R];          %记录下一路线的及其路程
    end
    %% 记录每次迭代过程的最优路线
    [d0,index] = min(temp(:,end)); %找出当前温度下最优路线
    if count == 1 || d0 < Obj(count-1)
        Obj(count) = d0;           %如果当前温度下最优路程小于上一路程则记录当前路程
    else
        Obj(count) = Obj(count-1);%如果当前温度下最优路程大于上一路程则记录上一路程
    end
    track(count,:) = temp(index,1:end-1);  %记录当前温度的最优路线
    T0 = q*T0;     %降温
    fprintf(1,'%d\n',count)  %输出当前迭代次数
end
%% 优化过程迭代图
figure
plot(1:count,Obj)
xlabel('迭代次数')
ylabel('距离')
title('优化过程')

%% 最优解的路径图
TSP_Draw_Path(track(end,:),X)

%% 输出最优解的路线和总距离
disp('最优解:')
S = track(end,:);
p = TSP_Output_Path(S);
disp(['总距离:',num2str(TSP_Feasible_Solution_Path_Length(D,S))]);
disp('-------------------------------------------------------------')
toc




命令行窗口

初始种群中的一个随机值:
7—>4—>8—>2—>6—>11—>10—>14—>13—>9—>3—>12—>1—>5—>7
总距离:70.2021
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
最优解:
13—>7—>12—>6—>5—>4—>3—>14—>2—>1—>10—>9—>11—>8—>13
总距离:29.3405
-------------------------------------------------------------
时间已过 2.769450 秒。

随机路线图



进化过程



最优解路线图





================================================



一,算法简介

1.1 内容简介

对于某个问题而言,没有很好的办法可以直接求得它的最优解,又或是直接求解太复杂。此时,我们尝试随机带入一些值,想要试一下,撞一下大运,看看能不能撞出比较好的解出来。

1.2 算法实现的过程

第一步,我们将根据可控变量的取值范围,来随机选取初始值,这是初次试值

第二步,接下来的试值中,我们会给每一个变量,产生一个微小的变化量delta= [公式] (delta具体是多少,可以由用户决定。 [公式] 代表变化后的可控变量, [公式] 代表变化前的可控变量),当然变化后的每一个变量要求在取值范围以内。注意,这个微小变化量是随机取值的,但是要保证它的取值范围关于原点对称。

注意,可控变量可能不是一维的,可能是二维或者更高维度。此时 [公式] 为一个存储多个可控变量的向量。

第三步,我们自定义了的函数关系,这个函数是针对当前问题的,是变量到结果的映射。这个函数的输入端是向量 [公式] ,输出端是映射后的结果 [公式] 。假设 [公式] 映射后的结果是 [公式] ;[公式] 映射后的结果是 [公式]

对于 [公式] 我们提出如下要求:

1)如果新的结果更接近我们想要的结果(一般我们想要找到的是最值),我们就直接接受当前得到的 [公式] 及 [公式] 。

2)如果新的结果 [公式] 远离或者等于原来的结果,我们以一定概率 P 的去接受当前状态下的变量。假设 函数值的变化量 [公式] ,温度为 T (这是用户自己设置的一个量,用于调控算法在起始及过程当中的概率大小)。则 P 满足如下关系:

[公式]

并且,我们要求,如果你是以概率的方式接受了当前状态下的结果,那么在每次接受以后,温度将会下降,即 [公式] = [公式] * [公式] 。注意,T 的初始值是人为设定的, [公式] 也是人为设定的。

3)当 P 过于小的时候,或长时间找不到更优的解,那么结束算法。

1.3 重点讲解

1)不难发现,对于 P 而言,由于指数的分子恒为正,当指数分母趋于无穷大的时候,概率趋于1。这意味我们选择远离或者等于原来的结果的可能性会比较高。刚开始的时候,我们需要接触更多的区域,来试探解的结果,所以温度会设定的很高。随着算法的进行,温度逐渐降下来后,P 会逐渐变小。最后,我们能够得到一个尽可能接近最优解的解。

2)如何实现求解最大值呢?首先,使得 [公式],那么由于我们要求[公式],所以当 [公式] ,此时的 [公式] 是我们不想要的解,也就是我们想要更大的解。其次,写下一个判断函数 judge(dE,t),传入 [公式] 和 t ,其中,dE = [公式] 。当dE < 0 时,返回值1,代表接受结果;当dE ≥ 0 时,进行概率选择,依照概率返回值 1 或 0 。

该算法计算的就是最大值。如果我们使得[公式] ,就可以通过输入的extreme值来修改计算的最值了,当 extreme=1 时,计算最大值;当 extreme=-1 时,计算最小值。(注意,下面编程当中的 [公式] ,所以和这里刚好相反。)


二,算法的matlab编程

首先考虑一下算法的整体结构:输入端,循环处理的过程,输出端

输入端:

包括温度 T 、温度最小值 Tm 、温度下降系数 alpha 、变量矩阵 X 及其取值范围、自定义的函数 val()

变量矩阵 X 用于存储已知条件,它是一个 m*n 的矩阵,其中 m 代表已知点的个数,而 n 代表每个点的维度。

循环处理过程:

包括这几个部分,初始图像的绘制、初始值的求解、随机扰动的求解、是否采纳解的判断、绘图。

输出端:

主要需要最终的温度T,和最后得到的状态下的变量及其函数值


matlab编程

(原代码来源于zhuanlan.zhihu.com/p/33中的第二例,但是我将算法改进了一下,目的是使其更具有普遍性)

使用模拟退火算法求解到点集直线距离之和最短的点




%{
名称:模拟退火算法
用途:用于求某个函数的最值
输入:温度、温度最小值、温度下降系数、变量矩阵及其取值范围、自定义的函数val
输出:函数图像,以及最终得到的值y
注意:
%}

clc, clear
%用户输入参数
disp('请修改关于变量矩阵的自定义函数,初始及初始图像函数,还有循环过程中的绘图部分');
T_input=input('请以向量的形式依次输入tmp,tmp_min,alpha:');
tmp=T_input(1);tmp_min=T_input(2);alpha=T_input(3);
varied_data=input('请输入变量矩阵,每一列代表不同维度,每一行代表不同元素:');
extreme=input('需要计算最大值请输入-1,计算最小值请输入1:')

%实验参数,可以将上面内容注释掉,把这里取消注释进行实验
%tmp = 1000;
%tmp_min = 0.001;
%alpha = 0.98;
%extreme=-1;
%varied_data=[0 0;1.5 10;1.5 12; -2 11; -4 -8;-5  2;2 -1.5;4 -2.5;5 1;-2 -2;-3 8;3 6;-1.5 0;-2.5 0;0.1 0.2];

draw_dist(varied_data);
[varied_data_new,tmp,counter]=tuihuo(tmp,tmp_min,alpha,varied_data,extreme);

%%
%此为自定义函数,不同题目需要有不同的自定义函数,用户需要自行修改
function [result] = val(varied_data,varied_single_data)
x=varied_data(:,1);
y=varied_data(:,2);
xx=varied_single_data(1);
yy=varied_single_data(2);
result = 0;
num_of_dots = length(x);
for i = 1:num_of_dots
   result = result + sqrt((xx - x(i))^2 + (yy - y(i))^2);
end
end

%%
%此为绘制初始图像的函数,针对不同的情况,用户需要自行更改
function []=draw_dist(varied_data)
x=varied_data(:,1);
y=varied_data(:,2);

x_min = floor(min(x));
y_min = floor(min(y));
x_max = ceil(max(x));
y_max = ceil(max(y));


resol = 10;
dx = x_min: 1/resol : x_max;
dy = y_min: 1/resol : y_max;

[xx, yy] = meshgrid(dx, dy);
zz = zeros(length(dy), length(dx));

for ii = 1:length(dx)
   for jj = 1:length(dy)
       zz(jj, ii) = val(varied_data,[dx(ii), dy(jj)]);
   end
end

contour(xx, yy, zz);
hold on;
scatter(x, y, 'MarkerFaceColor','blue');hold on;
end

%%
%退火的主体函数
function [varied_data_new,tmp,counter]=tuihuo(tmp,tmp_min,alpha,varied_data,extreme)
%判断变量维度及个数
[m,n]=size(varied_data);


%自动生成初始值并判断
for i=1:1:n
   varied_data_max(i)=max(varied_data(:,i));
   varied_data_min(i)=min(varied_data(:,i));
   varied_data_old(i) = (varied_data_max(i)-varied_data_min(i))*rand()+min(varied_data(:,i));%生成初始值
end

s_old = val(varied_data,varied_data_old);
s_new = s_old;

text_lt = text(0, 0, 'Init');

%计数器
counter = 0;

%退火的主体部分,一个循环
while(tmp > tmp_min)
   %随机扰动,需要保证扰动后的变量处于定义域内
   varied_new_mark=1;
   while(sum(varied_new_mark))
       for i=1:1:n
           delta(i) = rand() - 0.5;%此处可以自行更改大小
           varied_data_new(i)=varied_data_old(i) + delta(i);
           if(varied_data_new(i)<varied_data_min(i) || varied_data_new(i)>varied_data_max(i))
               varied_new_mark(i) = 1;%变量不能超出上下限
               break
           else
               varied_new_mark(i) = 0;
           end
       end
   end
   
   s_new = val(varied_data,varied_data_new);
   
   %求差值,extreme=1时,求最小值;=-1时,求最大值
   dE = (s_new - s_old)*extreme;
   
   %判断
   j = judge(dE, tmp);
   if(j)
       s_old = s_new;

       varied_data_old = varied_data_new;
   end
   
   %只有当dE < 0的情况下才降温
   if(dE < 0)
       %这里时循环过程中的绘图部分,请依照具体情况修改
       delete(text_lt);
       text_lt = text(-4, 6, {['Dist: ',num2str(s_old)];['Tmp: ', num2str(tmp)]});
       scatter(varied_data_old(1), varied_data_old(2), '.');%这里可以修改字符出现的位置
       pause(0.001);
       tmp = tmp * alpha;
   else
       counter = counter + 1;
   end
   
   %当接受更差的解的概率太小时,若又长时间找不到更优的解,那么退出循环,结束算法
   if(counter > 10000)%这里可以修改计数器的最大值
       break;
   end
end
end

%%
%{
名称:judge
用途:用于在随机扰动以后,判断是否选择这组数据
输入:扰动前后的变化量dE,退火温度t
输出:状态y,若y=1,为选择;y=0,为不选择
注意:
%}
function [y] = judge(dE, t)
 if(dE < 0)
   y = 1;
 else
   d = exp(-(dE / t));
   if(d > rand)
     y = 1;
   else
     y = 0;
   end
 end
end




========================================


         模拟退火算法求解TSP问题--Matlab实现


模拟退火算法简介





下面以一个实例来讲解模拟退火算法求解TSP问题



城市坐标



第一步就是加载城市坐标,然后处理





第二步计算各个城市之间的距离,并创建距离矩阵,我采用的各个城市之间距离的计算公式为





距离矩阵是一个对称矩阵,对称线上为0





第三步就是随机生成一条线路,取得路线的路径相对较小的一条线路





最后一步就是模拟退火过程

降温系数设置为at=0.999,即new——T=at X old——T,终止温度选为e=10E-30,T设置为1。

在相对路径距离较小的基础上随机选择两个城市号进行交换,组成新的路径





交换i和j两个城市的位置,同时i和j中间的城市倒换顺序交换后的路径为





得到两条路径的距离差为





接受准则就是





即当df<0时,也就是新路径距离比老路径距离小,否则就是依概率接受新路径。





然后就是降温了,也就是判断是否满足迭代条件,如果满足就停止迭代了





最后的运行结果就是





最后附上完整代码








参考:https://zhuanlan.zhihu.com/p/585495727