算法思想,模拟物理的退火过程。区别于爬山算法的关键在于,对于比当前差的解,不是直接舍弃,而是以一定的概率接受。
(主要框架:三个函数+两个准则)
给定初温t=t0,随机产生初始状态s=s0,令k=0;
Repeat
Repeat
产生新状态sj=Genete(s);
if min{1,exp[-(C(sj)-C(s))/tk]}>=randrom[0,1] s=sj;
Until 抽样稳定准则满足;
退温tk+1=update(tk)并令k=k+1;
Until算法终止准则满足;
输出算法搜索结果。
#include <iostream> #include <vector> #include <iterator> #include <algorithm> #include <ctime> #include <cmath> #include <fstream> #define CITYNUM 52 #define MAX 0x7fffffff using namespace std; struct Point { int x; int y; char name; }; //read the graph & compute the distance dist[i][j] void InitGraph(double dist[CITYNUM][CITYNUM],Point citys[CITYNUM]) { fstream fileRead; fileRead.open("coords.txt",ios::in); for(int i=0;i<CITYNUM;i++) { int temp; char ch; fileRead>>temp>>ch>>citys[i].x>>ch>>citys[i].y>>ch>>citys[i].name; //cout<<temp<<ch<<citys[i].x<<ch<<citys[i].y<<ch<<citys[i].name<<endl; } fileRead.close(); for(int i=0;i<CITYNUM;i++) { for(int j=0;j<CITYNUM;j++) { if(j!=i&&dist[i][j]==0) { double d2=(citys[i].x-citys[j].x)*(citys[i].x-citys[j].x)+(citys[i].y-citys[j].y)*(citys[i].y-citys[j].y); dist[i][j]=dist[j][i]=sqrt(d2); } } } } double Evalue(const vector<int> answer,double dist[CITYNUM][CITYNUM]) { double sum=0; for(int i=0;i<answer.size()-1;i++) { //cout<<answer[i]<<"->"<<answer[i+1]<<":"<<sum<<"+"<<dist[answer[i]][answer[i+1]]<<"="<<sum+dist[answer[i]][answer[i+1]]<<endl; sum+=dist[answer[i]][answer[i+1]]; } sum+=dist[answer[answer.size()-1]][answer[0]]; return sum; } void Swap(vector<int> &newAnswer,int first,int second) { newAnswer[first]=newAnswer[first]^newAnswer[second]; newAnswer[second]=newAnswer[first]^newAnswer[second]; newAnswer[first]=newAnswer[first]^newAnswer[second]; } void Reverse(vector<int> &newAnswer,int first,int second) { if(first>second) { first=first^second; second=first^second; first=first^second; } reverse(newAnswer.begin()+first,newAnswer.begin()+second); } void Save(const vector<int> minAnswer,Point citys[CITYNUM],double t0,double alpha,double te,double minSum) { fstream fileWrite; fileWrite.open("out.txt",ios::out|ios::app); fileWrite<<"起始温度:"<<t0<<",终止温度:"<<te<<",降温系数:"<<alpha<<",近似最优:"<<minSum<<endl; for(int i=0;i<minAnswer.size();i++) { fileWrite<<citys[minAnswer[i]].name<<"->"; } fileWrite<<citys[minAnswer[0]].name<<endl; fileWrite.close(); } void SimuAnne(double t0,double alpha,double te ) { vector<int> answer,newAnswer,minAnswer; int k=0;//记录循环次数 double t=t0; double sumDist=0,newSum=0,minSum=MAX; double dist[CITYNUM][CITYNUM]={0}; Point citys[CITYNUM];//city's coordinate InitGraph(dist,citys); //initial answer for(int i=0;i<CITYNUM;i++) { answer.push_back(i); } srand ( unsigned (time(0) ) ); random_shuffle(answer.begin(),answer.end()); sumDist=Evalue(answer,dist); minSum=sumDist; minAnswer.assign(newAnswer.begin(),newAnswer.end()); cout<<k<<" "<<minSum<<endl; copy(answer.begin(),answer.end(),ostream_iterator<int>(cout," "));cout<<endl;//输出answer while(t>te) { //srand ( unsigned (time(0) ) ); newAnswer.assign(answer.begin(),answer.end()); int first=0,second=0; //swap first & second first=rand()%CITYNUM; second=rand()%CITYNUM; if(first!=second) { //cout<<first<<"--"<<second<<endl; Swap(newAnswer,first,second);//产生新的状态 //Reverse(newAnswer,first,second);//产生新的状态 newSum=Evalue(newAnswer,dist); if(min(1.0,exp(-(newSum-sumDist)/t))>=(rand()%998)/997.0) { answer.assign(newAnswer.begin(),newAnswer.end()); sumDist=newSum; if(newSum<minSum) { minSum=newSum; minAnswer.assign(newAnswer.begin(),newAnswer.end()); cout<<k<<" "<<minSum<<endl; copy(answer.begin(),answer.end(),ostream_iterator<int>(cout," "));cout<<endl;//输出answer } k++; } t=t*alpha; } } Save(minAnswer,citys,t0,alpha,te,minSum); for(int i=0;i<minAnswer.size();i++) { cout<<citys[minAnswer[i]].name<<"->"; } cout<<citys[minAnswer[0]].name<<endl; } int main() { double t0=10000000;//起始温度 double alpha=0.999999;//降温系数 double te=0.000001;//截止温度 SimuAnne(t0,alpha,te); return 0; }
0,1,1,a 1,1,2,b 2,1,3,c 3,1,4,d 4,1,5,e 5,1,6,f 6,1,7,g 7,1,8,h 8,1,9,i 9,1,10,j 10,2,11,k 11,7,11,l 12,12,11,m 13,17,11,n 14,22,11,o 15,27,11,p 16,32,11,q 17,37,11,r 18,42,11,s 19,47,11,t 20,52,11,u 21,57,11,v 22,62,11,w 23,67,11,x 24,72,11,y 25,77,11,z 26,82,11,A 27,87,11,B 28,92,11,C 29,97,11,D 30,101,10,E 31,101,9,F 32,101,8,G 33,101,7,H 34,101,6,I 35,101,5,J 36,101,4,K 37,101,3,L 38,101,2,M 39,100,1,N 40,95,1,O 41,90,1,P 42,85,1,Q 43,80,1,R 44,75,1,S 45,70,1,T 46,65,1,U 47,60,1,V 48,55,1,W 49,50,1,X 50,45,1,Y 51,40,1,Z
以上算法,循环次数比较多。跟蚁群算法一比被虐成渣(有兴趣的话可以留言交流)。
起始温度:1e+007,终止温度:1e-006,降温系数:0.999999,近似最优:228.351 t->s->r->q->p->o->n->j->i->h->g->f->e->d->c->b->a->k->l->m->Z->Y->X->W->V->U->T->S->R->Q->P->O->N->M->L->K->J->I->H->G->F->E->D->C->B->A->z->y->x->w->v->u->t