文章给出旅行商问题的模拟退火算法的C++实现:
环境:win7 vc6.0
头文件:
#include
#include
#include
#include
#include
using namespace std;
全局变量的定义:
通过修改退火速度,初始温度可以得到不同程度的解
const int nCities = 99; //城市数量
const double SPEED = 0.98; //退火速度
const int INITIAL_TEMP = 1000; //初始温度
const int L = 100 * nCities; //Markov链的长度
double length_table[nCities][nCities]; // 城市距离
解得结构:
length 旅行商最终的路径长度
path 数组旅行商依次经过的城市
struct unit{
double length; //路径长度
int path[nCities]; //路径
};
下面是用到的函数:
初始化距离矩阵:
这里使用rand()函数随机生成数据,这样会使图的入度和出度不一致,可自己优化
//初始化距离矩阵
void init_dis(){
for(int i = 0; i < nCities; i++)
for(int j = 0; j < nCities; j++)
length_table[i][j] = rand() % 100; //随机生成城市距离
}
生成函数,随机产生一个初始解,这里随机选了一个开始点,然后依次构造path
//随机产生一个初始解,随机选一个初始点顺序构造path
void generate(unit &temp){
int j = 0;
int i = rand() % nCities;
while(j < nCities){
temp.path[j] = i;
j++;
i = (i + 1) % nCities;
}
}
交换法生成邻居
//交换法生成邻居
void getNewSolution(unit &p){
int i = rand() % nCities;
int j = rand() % nCities;
int temp = p.path[i];
p.path[i] = p.path[j];
p.path[j] = temp;
}
计算路径长度
//计算路径长度
void CalCulate_length(unit &p){
int j = 0;
p.length = 0;
for(j = 1; j < nCities; j++){
p.length += length_table[p.path[j - 1]][p.path[j]];
}
p.length += length_table[p.path[nCities - 1]][p.path[0]]; //最后一城市到起点
}
接受新解得规则,根据模拟退火算法有两种情况
//接受新解规则 两个情况
bool Accept(unit &bestone, unit &temp, double t){
if(bestone.length > temp.length)
return true;
else{
if((int)(exp((bestone.length - temp.length) / t) * 100) > (rand() % 101))
return true;
}
return false;
}
打印解
//打印解数组
void printp(unit p){
cout<<"旅行商的距离为:"<<p.length<<endl;
cout<<"经过的城市依次为:"<<endl;
for(int i = 0; i < nCities; i++)
{
cout<<p.path[i]<<" ";
if((i+1) % 10 == 0)
cout<<endl;
}
cout<<endl;
cout<<endl;
}
核心算法,TSP模拟退火的过程
//TSP模拟退火算法
void SA_TSP(){
srand(time(0));
int i =0;
double r = SPEED;
double t = INITIAL_TEMP;
const double t_min = 0.001;
unit temp;
unit bestone;
generate(temp);
CalCulate_length(temp);
memcpy(&bestone, &temp, sizeof(temp));
//打印初始解
printp(bestone);
while(t > t_min){
for(i = 0; i < L; i++){
getNewSolution(temp);
CalCulate_length(temp);
if(Accept(bestone, temp, t))
memcpy(&bestone, &temp, sizeof(unit));
else
memcpy(&temp, &bestone, sizeof(unit));
}
t *=r;//退火
}
//打印最终解
printp(bestone);
return;
}
最后是主函数
int main(){
init_dis();//初始化距离矩阵
SA_TSP();//打印解在函数中
return 0;
}