使用退火算法来解决最优路径的思考

使用退火算法来解决最优路径的思考

  • 概述
    旅行商问题一直认为是一个NP问题,除了穷举外,没有最优解,只有近似解

  • 解决方案
    下面提供了使用一个网上使用模拟退火算法来做的代码

    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <algorithm>
    #include <stdio.h>
    #include <time.h>
    #include <math.h>
     
    #define N     30      //城市数量
    #define T     3000    //初始温度
    #define EPS   1e-8    //终止温度
    #define DELTA 0.98    //温度衰减率
    #define LIMIT 10000   //概率选择上限
    #define OLOOP 1000    //外循环次数
    #define ILOOP 15000   //内循环次数
     
    using namespace std;
     
    //定义路线结构体
    struct Path
    {
    	int citys[N];
    	double len;
    };
     
    //定义城市点坐标
    struct Point
    {
    	double x, y;
    };
     
    Path path;        //记录最优路径
    Point p[N];       //每个城市的坐标
    double w[N][N];   //两两城市之间路径长度
    int nCase;        //测试次数
     
    double dist(Point A, Point B)
    {
    	return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
    }
     
    void GetDist(Point p[], int n)
    {
    	for(int i = 0; i < n; i++)
    		for(int j = i + 1; j < n; j++)
    			w[i][j] = w[j][i] = dist(p[i], p[j]);
    }
     
    void Input(Point p[], int &n)
    {
    	scanf("%d", &n);
    	for(int i = 0; i < n; i++)
    		scanf("%lf %lf", &p[i].x, &p[i].y);
    }
     
    void Init(int n)
    {
    	nCase = 0;
    	path.len = 0;
    	for(int i = 0; i < n; i++)
    	{
    		path.citys[i] = i;
    		if(i != n - 1)
    		{
    			printf("%d--->", i);
    			path.len += w[i][i + 1];
    		}
    		else
    			printf("%d\n", i);
    	}
    	printf("\nInit path length is : %.3lf\n", path.len);
    }
     
    void Print(Path t, int n)
    {
    	printf("Path is : ");
    	for(int i = 0; i < n; i++)
    	{
    		if(i != n - 1)
    			printf("%d-->", t.citys[i]);
    		else 
    			printf("%d\n", t.citys[i]);
    	}
    	printf("\nThe path length is : %.3lf\n", t.len);
    }
     
    Path GetNext(Path p, int n)
    {
    	Path ans = p;
        int x = (int)(n * (rand() / (RAND_MAX + 1.0)));
    	int y = (int)(n * (rand() / (RAND_MAX + 1.0)));
    	while(x == y)
    	{
    		x = (int)(n * (rand() / (RAND_MAX + 1.0)));
    		y = (int)(n * (rand() / (RAND_MAX + 1.0)));
    	}
    	swap(ans.citys[x], ans.citys[y]);
        ans.len = 0;
    	for(int i = 0; i < n - 1; i++)
    		ans.len += w[ans.citys[i]][ans.citys[i + 1]];
    	cout << "nCase = " << nCase << endl;
    	Print(ans, n);
    	nCase++;
    	return ans;
    }
     
    void SA(int n)
    {
    	double t = T;
    	srand(time(NULL));
    	Path curPath = path;
    	Path newPath = path;
    	int P_L = 0;
    	int P_F = 0;
    	while(1)       //外循环,主要更新参数t,模拟退火过程
    	{
    		for(int i = 0; i < ILOOP; i++)    //内循环,寻找在一定温度下的最优值
    		{
    			newPath = GetNext(curPath, n);
    			double dE = newPath.len - curPath.len;
    			if(dE < 0)   //如果找到更优值,直接更新
    			{
    				curPath = newPath;
    				P_L = 0;
    				P_F = 0;
    			}
    			else
    			{
    				double rd = rand() / (RAND_MAX + 1.0);    
    				if(exp(dE / t) > rd && exp(dE / t) < 1)   //如果找到比当前更差的解,以一定概率接受该解,并且这个概率会越来越小
    					curPath = newPath;
    				P_L++;
    			}
    			if(P_L > LIMIT)
    			{
    				P_F++;
    				break;
    			}
    		}
    		if(curPath.len < newPath.len)
    			path = curPath;
    		if(P_F > OLOOP || t < EPS)
    			break;
    		t *= DELTA;
    	}
    }
     
    int main()
    {
    	freopen("TSP.data", "r", stdin);
    	int n;
    	Input(p, n);
    	GetDist(p, n);
    	Init(n);
    	SA(n);
    	Print(path, n);
        printf("Total test times is : %d\n", nCase);
    	return 0;
    }
    
  • 效果

在这里插入图片描述

  • 局限性
  1. 不支持大数据量,如果有几十万个城市,这个内存都很难支持
  2. 算法实在太耗时了,有很大改善区间
  3. 不够灵活,如不可制定入口和出口
  • 实际运用场景
  1. 高尔球场开小车捡球
  2. PCB板钻孔的路径规划
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值