main.cpp
#include "SA.h"
int main() {
SA a(100);
SA b(a);
b.init_gragh();
b.rand_n();
b.SimulatedAnnealing();
b.print_result();
system("Pause");
return 0;
}
SA.h
#ifndef SIMULATEDANNEALING_SA_H
#define SIMULATEDANNEALING_SA_H
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;
#define R_EARTH 6370
#define L 2000
#define AT 0.99
#define T 1
int cmp(const void *a, const void *b);
struct element{
double x,y;
int index;
};
struct Rand{
int data;
int index;
};
class SA {
private:
int num_city;
int best_value;
double **arc;
int *best_path;
int *cur_path;
int *temp_2opt;
double **city_xy;
int *new_path;
element *city;
public:
SA(int n);
SA();
SA(const SA& c);
virtual ~SA();
void init_gragh();
void rand_n();
void two_opt();
void SimulatedAnnealing();
void print_result();
};
SA.cpp
#include "SA.h"
SA::SA(int n){
this->num_city=n;
this->arc= new double *[this->num_city];
this->city_xy=new double *[2];
this->best_path= new int[this->num_city+1];
this->temp_2opt=new int[this->num_city+1];
this->cur_path=new int[this->num_city+1];
this->city=new element[this->num_city];
this->new_path=new int[this->num_city+1];
this->best_value=0;
for(int i=0;i<this->num_city;i++)
{
this->arc[i]=new double[this->num_city];
for(int j=0;j<this->num_city;j++)
this->arc[i][j]=INT_MAX;
}
for(int i=0;i<this->num_city;i++)
{
this->city_xy[i]=new double [2];
for(int j=0;j<2;j++)
this->city_xy[i][j]=0;
}
fstream file("data.txt");
if(!file.is_open())
cout<<"文件未成功读取"<<endl;
for(int i=0;i<this->num_city;i++)
for(int j=0;j<2;j++)
file>>this->city_xy[i][j];
file.close();
for(int i=0;i<this->num_city;++i){
this->city[i].x=this->city_xy[i][0];
this->city[i].y=this->city_xy[i][1];
this->city[i].index=i;
}
}
SA::SA(const SA &c) {
this->num_city=c.num_city;
this->best_value=c.best_value;
this->best_path=new int[this->num_city+1];
*best_path=*(c.best_path);
this->cur_path= new int[this->num_city+1];
*cur_path=*(c.cur_path);
this->temp_2opt=new int[this->num_city+1];
*temp_2opt=*(c.temp_2opt);
this->new_path=new int[this->num_city+1];
*new_path=*(c.new_path);
this->arc= new double*[this->num_city];
this->city_xy=new double*[2];
for(int i=0;i<this->num_city;i++)
{
this->arc[i]=new double[this->num_city];
for(int j=0;j<this->num_city;++j)
this->arc[i][j]=c.arc[i][j];
this->city_xy[i]=new double[2];
for(int k=0;k<2;k++)
this->city_xy[i][k]=c.city_xy[i][k];
}
this->city=new element[this->num_city];
for(int i=0;i<this->num_city;i++)
{
this->city[i].x=this->city_xy[i][0];
this->city[i].y=this->city_xy[i][1];
this->city[i].index=i;
}
}
SA::~SA() {
delete []best_path;
delete []cur_path;
delete []temp_2opt;
delete []new_path;
for(int i=0;i<this->num_city;++i) {
delete []this->arc[i];
}
for(int i=0;i<2;i++)
delete []this->city_xy[i];
delete []arc;
delete []city_xy;
delete []city;
}
void SA::init_gragh() {
for(int i=0;i<this->num_city;i++){
for(int j=0;j<this->num_city;j++){
this->arc[i][j]=R_EARTH*acos(sin(this->city[i].y)*sin(this->city[j].y)+cos(this->city[i].y)*cos(this->city[j].y)*cos(this->city[j].x-this->city[i].x));
}
}
}
int cmp(const void *a, const void *b) {
return ((Rand*)a)->data-((Rand*)b)->data;
}
void SA::rand_n() {
double curent=0.00,best;
int *temp;
for(int k=0;k<1000;k++) {
srand((int) time(0));
temp=new int[this->num_city+1];
Rand *ele;
ele = new Rand[this->num_city];
for (int i = 0; i < this->num_city; ++i) {
ele[i].data = rand();
ele[i].index = i;
}
qsort(ele, this->num_city, sizeof(ele[0]), cmp);
for (int i = 0; i < this->num_city; ++i) {
temp[i]=ele[i].index;
}
temp[this->num_city]=temp[0];
delete[]ele;
for (int i = 0; i < this->num_city; ++i) {
curent = curent + this->arc[temp[i]][temp[i + 1]];
}
if(k==0) {
best = curent;
for (int i = 0; i <= this->num_city; ++i)
this->cur_path[i]=temp[i];
}
else
{
if(curent<best) {
best = curent;
for (int i = 0; i <= this->num_city; ++i)
this->cur_path[i]=temp[i];
}
}
memmove(this->temp_2opt,this->cur_path, sizeof(int)*(this->num_city+1));
delete []temp;
}
}
void SA::two_opt() {
srand((int)time(0));
int n1,n2,left,right;
n1=rand()%this->num_city;
do{
n2=rand()%this->num_city;
}while(n1==n2);
if(n1<n2)
{
left=n1;
right=n2;
} else{
left=n2;
right=n1;
}
while(left<right){
swap(this->temp_2opt[left],this->temp_2opt[right]);
left++;
right--;
}
this->temp_2opt[this->num_city]=this->temp_2opt[0];
}
void SA::SimulatedAnnealing() {
int t=T;
double best=0,curent;
memmove(this->best_path,this->cur_path, sizeof(int)*(this->num_city+1));
for(int i=0;i<this->num_city;++i)
best=best+this->arc[this->cur_path[i]][this->cur_path[i+1]];
curent=best;
for(int i=0;i<1000;i++)
{
double temp_best=curent;
double df;
srand((int)time(0));
for(int j=0;j<this->num_city*this->num_city;++j)
{
double temp_num=0;
SA::two_opt();
for(int k=0;k<this->num_city;k++)
temp_num=temp_num+this->arc[this->temp_2opt[k]][this->temp_2opt[k + 1]];
if(temp_num<curent){
temp_best=temp_num;
memmove(this->new_path,this->temp_2opt, sizeof(int)*(this->num_city+1));
}
}
df=temp_best-curent;
if(df<0){
curent=temp_best;
best=temp_best;
memmove(this->best_path,this->new_path, sizeof(int)*(this->num_city+1));
memmove(this->cur_path,this->new_path, sizeof(int)*(this->num_city+1));
memmove(this->temp_2opt,this->new_path, sizeof(int)*(this->num_city+1));
}else{
if(exp(-df/t)>(double)rand()/RAND_MAX && exp(-df/t)<1)
{
curent=temp_best;
memmove(this->cur_path,this->new_path, sizeof(int)*(this->num_city+1));
memmove(this->temp_2opt,this->new_path, sizeof(int)*(this->num_city+1));
}
}
t=t*AT;
}
this->best_value=best;
}
void SA::print_result() {
cout<<"this best value is "<<this->best_value<<endl;
for(int i=0;i<=this->num_city;i++)
if(i<this->num_city)
cout<<this->best_path[i]<<"->";
else
cout<<this->best_path[i];
}