模拟退火(SA)搜索算法

2024-04-21 18:32

本文主要是介绍模拟退火(SA)搜索算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

所谓的爬山算法实际上就是简单的贪心算法,贪心算法通过从当前解的临近空间选择一个最优的解作为新的当前解,因此这个解很有可能是局部最优解,而不是全局最优的。因为A的领域周围没有比他更优的解了。

 

模拟退火搜索通过允许向不好的状态移动来避开局部最值点,但频率逐渐降低。它是一种基于蒙特卡洛思想设计的近似求解最优化问题的方法。

伪代码如下:

  choose an initial solution X0  randomly                      //随机的选择一个初始解X0
  give an initial temperature T0 , X ← X0, T ← T0       //初始化温度T0
  while the stop criterion is not yet satisfied do            //停止准则不满足则
   {   for i ← 1 to  L do                                                  //Markov 链的长度 L
        {  pick a solution  X'∈N(X) randomly                  //随机选择临域内一个解X',为逃离局部最值点
           Δf ← f(X')-f(X)                                                   //后续节点-当前节点
           if Δf<0  then  X ← X'                                         
           else  X ← X' with  probability exp(- Δf/T)  }        //  以exp(- Δf/T)的接受概率接受X'
   T← g(T)    //generally, T ← aT    }                             //温度下降
  return X
 

void SimulatedAnnealing()

{

  蒙特卡洛随机产生一个初始解X0;

     初始化温度T、迭代次数L、降温系数TA、迭代误差E

      for(int i=0;i<L;i++)//退火过程

     {

     计算与新解所对应的目标函数差df;

     if(df<0)

        接受当前的解X′作为新解X;

     else

       以概率exp(-Δt′/T)接受X′作为新的当前解X;

     T = AT * T ; //降温退火

     }

}

模æéç«ç®æ³çåçãä¼ç¼ºç¹ãæµç¨ãåºç¨å®ä¾
 

#include<iostream>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<time.h>
#include<stdlib.h>
#include<stdio.h> 
//#include <windows.h>#define MAX 10000
#define INF 10000000 
#define E 0.000000001  // 迭代误差 
#define L 40000    // 迭代次数 
#define AT 0.999   // 降温系数 
#define T 1       // 初始温度 #define N 5//城市个数
using namespace std; struct element{     //用来排序的数据结构 int data;  // 数据 int index;  // 序号 
};int tsp(int d[][N], int n, double e,int l,double at,double t,int s0[]);  //利用模拟退火算法求解最短路径 
int cmp(const void *a,const void *b); //升序排列 
void rand_of_n(int a[],int n);  //产生 1-n 的随机排列并存到 a[] 中
int random(int m,int n);
//int dis[MAX][MAX];   // d[i][j] 表示客户i到客户j的距离,0 表示起始点 int dis[N][N]={0,1,57,20,81, 1,0,59,49,36, 57,59,0,90,82, 20,49,90,0,75, 81,36,82,75,0 };void rand_of_n(int a[],int n){int i;struct element ele[MAX];srand((int)time(0));  // 初始化随机数种子 for(i=0;i<n;i++){ele[i].data=rand();  // 随机生成一个数 ele[i].index=i+1;}qsort(ele,n,sizeof(ele[0]),cmp);  //排序 for(i=0;i<n;i++){a[i]=ele[i].index;}
}int random(int m,int n){   //产生m-n的随机数int a;double x=(double)rand()/RAND_MAX;a=(int)(x*(n-m)+0.5)+m;return a;
}	int cmp(const void *a,const void *b){   // 升序排序return((struct element*)a)->data - ((struct element*)b)->data;
}int tsp(int d[][N], int n, double e,int l,double at,double t,int s0[]){int i,j,s[N],sum,temp;sum=INF; for(i=0;i<1000;i++){  //利用蒙特卡洛方法产生初始解rand_of_n(&s[1],n);s[0]=0; s[n+1]=0;  //第一个和最后一个点为起始点 temp=0;for(j=0;j<=n;j++)temp=temp+d[s[j]][s[j+1]];if(temp<sum){for(j=0;j<=n+1;j++)s0[j]=s[j];sum=temp;} }for(i=0;i<l;i++){    //退火过程 int c1,c2;c1=random(1,n);c2=random(1,n);if(c1>c2){int temp=c2; c2=c1; c1=temp;} if(c1==c2)continue;int df=d[s0[c1-1]][s0[c2]] + d[s0[c1]][s0[c2+1]] - d[s0[c1-1]][s0[c1]] - d[s0[c2]][s0[c2+1]]; //计算代价函数if(df<0){  //接受准则while(c1<c2){ int temp=s0[c2]; s0[c2]=s0[c1]; s0[c1]=temp;c1++;c2--;}sum=sum+df;} else if(exp(-df/t)>((double)rand()/RAND_MAX)){while(c1<c2){int temp=s0[c2]; s0[c2]=s0[c1]; s0[c1]=temp;c1++;c2--;}sum=sum+df;}t=t*at;//线性降温if(t<e)break;}return sum;
}int main(){//DWORD start, stop;int i,j;int sum,sum0,s0[MAX]; sum0=0;   //顺序遍历时的路程 for(i=0;i<N;i++){sum0=sum0+dis[i][i+1];}sum0=sum0+dis[N][0];sum=tsp(dis,N, E,L,AT,T,s0);for(i=1;i<=N;i++)cout<<s0[i]<<" ";cout<<endl; 	printf("模拟节点个数 %d\n", N);return 0; 
}

缺点:收敛速度慢、不能保证得到全局最优值。

增加获得全局最优值的可能性:

  1. 增加模拟运行的时间(迭代次数);
  2. 多次重新启动,重置所有变量并开始新的SA,从不同搜索区域的位置开始。

 

 

 

 

这篇关于模拟退火(SA)搜索算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/923763

相关文章

模拟退火判断一个圆是否可以放在一个多边形内

/*给定n个点的一个多边形,一个圆的半径,判断圆是否可以放在多边形里*//* ***********************************************Author :rabbitCreated Time :2014/7/3 22:46:38File Name :2.cpp**********************************************

模拟退火求n个点到某点距离和最短

/*找出一个点使得这个店到n个点的最长距离最短,即求最小覆盖圆的半径用一个点往各个方向扩展,如果结果更优,则继续以当前步长扩展,否则缩小步长*/#include<stdio.h>#include<math.h>#include<string.h>const double pi = acos(-1.0);struct point {double x,y;}p[1010];int

基于SA模拟退火算法的多车辆TSP问题求解matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述        基于SA模拟退火算法的多车辆TSP问题求解matlab仿真,三个车辆分别搜索其对应的最短路径,仿真后得到路线规划图和SA收敛曲线。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 (完整程序运行后无水印)

SA(模拟退火)优化算法MATLAB源码详细中文注解

以优化SVM算法的参数c和g为例,对SA(模拟退火)算法MATLAB源码进行了逐行中文注解。 完整程序和示例文件地址:http://download.csdn.net/detail/u013337691/9644107 链接:http://pan.baidu.com/s/1i5G0gPB 密码:4ge8 % 使用模拟退火法寻优SVM中的参数c和g% 使用METROPOLIS接受准则%%

算法-搜索算法:二分查找(Binary Search)【前置条件:待查数据集必须是有序结构,可以右重复元素】【时间复杂度:O(logn)】

搜索:是在一个项目集合中找到一个特定项目的算法过程。搜索通常的答案是真的或假的,因为该项目是否存在。 搜索的几种常见方法:顺序/线性查找、二分法查找、二叉树查找、哈希查找 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;缺点是要求待查表: 必须采用顺序存储结构;必须按关键字大小有序排列;插入删除困难; 二分查找/折半查找方法适用于不经常变动而查找频繁的有序列表: 首先,假设

旋转排序:搜索算法

搜索旋转排序数组的算法设计 引言 在计算机科学的世界中,二分搜索算法被广泛认为是处理已排序数组查找任务的高效工具。 它通过不断将搜索范围缩小一半的方式,快速定位到所需元素的位置,这种方法的时间复杂度仅为O(log n),使得它在处理大型数据集时表现出色。 然而,这种传统方法面临一个显著的挑战:当数组经历旋转后,原有的排序顺序被打乱,二分搜索的效率和有效性便会大打折扣。 为了解决旋转排序数

模拟退火TSP问题

模拟退火算法在求解最优值问题上有很大的优势,前面一篇博文介绍了用模拟退火算法实现求函数的最大、最小值问题。本文主要介绍如何用python实现模拟退火在TSP(旅行商)问题中的应用,源代码请移步pySA。网络上有不少文章介绍模拟退火TSP应用,可以对比着看。我们对实现的算法进行了测试,动态可视化更加形象。 1. TSP 问题描述 这个问题实际上就是求解最小路劲的问题,不过目前pySA实现还

模拟退火算法求函数最大、小值——python实现

模拟退火算法(Simulate Anneal,SA)是一种通用概率演算法,用来在一个大的搜寻空间内找寻命题的最优解。模拟退火是由S.Kirkpatrick, C.D.Gelatt和M.P.Vecchi在1983年所发明的。V.Černý在1985年也独立发明此演算法。模拟退火算法是解决TSP问题的有效方法之一。 模拟退火的出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似性。模拟退

【智能算法应用】基于融合改进A星-麻雀搜索算法求解六边形栅格地图路径规划

目录 1.算法原理2.结果展示3.参考文献4.代码获取 1.算法原理 【智能算法】麻雀搜索算法(SSA)原理及实现 六边形栅格地图 分析一下地图: 六边形栅格地图上移动可以看做6领域运动,偶数列与奇数列移动方式有所差异,将六边形栅格地图与二维栅格地图做映射可以发现: 偶数列移动方式:上、下、左、右、左下、右下奇数列移动方式:上、下、左、右、左上、右上 因此需要对基础

【递归深搜之记忆化搜索算法】

1. 斐波那契数 解法一:递归 class Solution {public:int fib(int n) {return dfs(n);}int dfs(int n){if(n == 0 || n == 1)return n;return dfs(n - 1) + dfs(n - 2);}}; 解法二:记忆化搜索 class Solution {int nums[31];