⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tsp.c

📁 用C编写的粒子群寻优的优化算法
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************                          TSP.c  -  description                             -------------------    begin                : mer mar 5 2003    copyright            : (C) 2003 by     email                : Maurice.Clerc@WriteMe.com ***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************/ //================================================= DISPLAY_GRAPHvoid     display_graph(struct graph G){  int i,j; for (i=0;i<G.N;i++) { printf( "\n%i /",i+1); for (j=0;j<G.N;j++)    printf(" %.0f",G.v[i][j]); }}/*------------------------------------------------------------------- READ_GRAPH */struct graph read_graph(FILE *file, int trace){/* TSPLIB MATRIX format. One value/line. First value = number of nodeseach value = arc value. If <0 => no arc*/char			bidon[50];char			comment[100];double         delta;char			edge_weight_format[30];char			edge_weight_type[30];struct graph	Gt;int 			i,j;char			name[20];char			type[20];float         zzz;printf("\nI am reading the graph");fscanf(file," %s %s\n",bidon,name);fscanf(file," %s %s\n",bidon,type);	fscanf(file," %s %s\n",bidon,comment);	fscanf(file,"%s %i\n",bidon,&Gt.N); // dimension	fscanf(file,"%s %s\n",bidon,edge_weight_type);	fscanf(file,"%s %s\n",bidon,edge_weight_format);	fscanf(file,"%s\n",bidon);	printf("\n Name: %s, type: %s, (%s)",name,type,comment);	printf("\n Number of nodes: %i",Gt.N);	printf("\n %s %s\n",edge_weight_type,edge_weight_format);	if (edge_weight_type[0]=='E' && edge_weight_format[0]=='F')		{		for (i=0;i<Gt.N;i++)			{                for (j=0;j<Gt.N;j++)				{                        fscanf(file,"%e ",&zzz);                            Gt.v[i][j]=zzz;					if (trace>2) printf(" %f",Gt.v[i][j]);				}			Gt.v[i][i]=0;			}    for (i=0;i<Gt.N;i++)			{			for (j=0;j<Gt.N;j++)				{                       if (Gt.v[i][j]>0) Gt.v[i][j]=integer_coeff*Gt.v[i][j];                       }                    }  if (integer_coeff!=1) printf("\nWARNING. I have multiplied all arc values by %f",integer_coeff);		return Gt;		}   printf("\nERROR by reading graph");  return Gt;}//====================================================== SEQUENCE_SIMILARint   sequence_similar(struct seq s1,struct seq s2){ /* Check if two sequences are globally similar: - same first value - same last value - same  set of values (not taking order into account) return 0 if false, 1 if true */ int           i; int           j;int            size;   if (s1.s[0]!=s2.s[0]) return 0;   size=s1.size;   if (s1.s[size-1]!=s2.s[size-1]) return 0;   if (size!=s2.size) return 0;   //printf("\n\n"); for (i=0;i<s1.size;i++) printf(" %i",s1.s[i] );  printf("\n");  for (i=0;i<s1.size;i++) printf(" %i",s2.s[i] );   for (i=1;i<size-1;i++)   {           for (j=0;j<size-1;j++)           {              if(s1.s[i]==s2.s[j]) goto next_i;           }            return 0;    next_i:;   }  //printf("\n sequence_similar OK"); return 1;}//====================================================== SEQUENCE_SUBSTstruct   particle    sequence_subst(struct particle p1, struct particle p2,int size_max){/* s1= position of p1, s2=position of p2 In s2, look for a sub sequence ss2 (size>=4) that is globally similar to one (ss1) in s1 and so that s1/ss1=>ss2 is a better sequence (smaller total  length regarding graph G).  f1 is the total length of the sequence s1. return: the new better sequence, after substitution G is a global variable. WARNING: each sequence is supposed to be a permutation of the G nodes, beginning in 0 plus again the node 0 at the end (cycle). */  double f1,f2;  float  GN2; int        i; int        ij; int        im; int        j; int        k; int        km; int        kl; int        l; int        m; struct  particle p1t; struct particle ptemp; struct  seq   s1,s2, ss1,ss2; int        sim; int        size; double  zzz; GN2=G.N/2; s1=p1.x; s2=p2.best_x;   p1t=p1;  size=4;  loop:    ss1.size=size;  ss2.size=size;   for (i=0;i<G.N;i++)    // Try all subsequences of size "size" and G.N-size   {      for (j=0;j<size;j++)      {           ij=i+j;         if (ij>=G.N) ij=ij-G.N;         ss1.s[j]=s1.s[ij];    // Build a subsequence in s1, for particle p1                                    // It begins on i in particle p1      }       for (k=0;k<G.N;k++)  // For the second particle ...       {                  for (l=0;l<size;l++)                  {                      kl=k+l;                      if(kl>=G.N) kl= kl-G.N;                     ss2.s[l]=s2.s[kl];    // ... build a subsequence in s2                                                // It begins on k in particle p2                  }                  sim=sequence_similar(ss1,ss2); // Compare the subsequences                  if (sim==1)  // Globally the same                  {  //printf("\n size %i  ",size);                     // Check if it is better                     ptemp.x=ss1;                     ptemp.x.s[size]=ss1.s[size-1];   // WARNING. All diagonal terms of G must be equal to 0                                                                 // Normally, it is done in read_graph                      f1=  f(ptemp,-1,-1);                      ptemp.x=ss2;                      ptemp.x.s[size]=ss2.s[size-1];                      f2=  f(ptemp,-1,-1);                      if (f2<f1)  // Replace ss1 by ss2                      {                           p1t.x=s1;                           for (m=0; m<ss2.size;m++)                           {                              im=i+m;                              if(im>=G.N) im=im-G.N;                              p1t.x.s[im]=ss2.s[m];                           }                            p1t.f=p1.f-f1+f2;  // Update the f-value                              if (trace>1)                                 printf("\nsequence_subst. size %i, %f  => %f. ==> %f",size,f1,f2, p1t.f);                           goto end_subs; // It is not allowed to replace both the sequence                                                   // and its complementary: it would mean just replace                                                   // p1.x by p2.best_x. Not interesting.                        }                        if (p2.best_f-f2<p1.f-f1) // The complementary susbsequence is better                        {                           p1t.x=s2;                           for (m=0; m<ss1.size;m++)                           {                              km=k+m;                              if(km>=G.N) km=km-G.N;                              p1t.x.s[km]=ss1.s[m]; // Keep ss1                           }                           p1t.f=p2.best_f-f2+f1;   // Update the f-value                            if (trace>1)                               printf("\nsequence_subst. size %i, %f  => %f, ==> %f",G.N-size,p1.f-f1,p2.best_f-f2,p1t.f);                           goto end_subs;                        }                        goto end_sim;                    end_subs:                        // Eventually update memory and return                           // if ( p1t.f< p1t.best_f)                           if ( p1t.f<best_best.best_f)                           {                             if (trace>1)                                 printf("\n        sequence_subst %f ==> %f",p1.f,p1t.f);                              p1t.best_x=p1t.x;                              p1t.best_f=p1t.f;                              // Eventually rotate                              if (p1t.x.s[0]!=0) p1t.x=rotate(p1t.x,0);                              return p1t;                           }                    end_sim:;                     }   // end sim==1       } // next k   }    // next i  size=size+1;   if (size<=GN2) goto loop;  // Try a longer subsequence   else   {     if (trace>1)         printf("\n       sequence_subst. size [4...%i] ==> no improvement", size-1);      return p1; // No possible improvement   }}  //===================================================================== SPLICE_AROUNDstruct   particle   splice_around(struct swarm sw, struct particle p, int hood_type,int hood_size) {   /* The particle looks at all its neighbours (or the whole swarm),   and tries to improve itself, by substituying a sequence in its position.   "hood" is a global variable (neighbourhood size))   "size_max" is global variable    */struct seq hood_rank;int   i;float  h2;int   j;int   k;struct   particle pt;int         size;if (splice_around_option==1) goto hood; // The whole swarm // Look, compare and eventually move// if (splice_around_option==0 )     size=sw.size; //else  size=(G.N*splice_around_option)/100;      for(k=0;k<size;k++)      {         if (k==p.rank) continue;               pt=sequence_subst(p,sw.p[k],size_max);          if (pt.best_f<best_best.best_f) return pt; // Stop asa enough improvement         //if (pt.best_f<p.best_f) return pt; // Stop asa there is improvement      } printf("\n splice=> NO improvement"); return pt;  hood: // Case hood_type==0 (social hood)/*--------------------- Neighbourhood. Super simple method: nearest by the rank */     if (hood_type!=0)    printf("\nWARNING. splice_around: physical neighbourhood not yet written. I use social one");// Build the neighbourhood k=0; h2=(float)hood_size/2;	for (i=1;i<h2;i++)		{		j=p.rank+i;		if (j>sw.size-1) {j=j-sw.size;}         hood_rank.s[k]=j;         k=k+1;		}	for (i=1;i<h2;i++)		{		j=p.rank-i;		if (j<0) {j=sw.size+j;}         hood_rank.s[k]=j;         k=k+1;		}      hood_rank.size=k; // printf("\n hood_size %i, hood_rank.size %i",hood_size,k);           //for (k=0;k<hood_rank.size;k++) printf("\n  hood_rank.s[%i]  %i",k,hood_rank.s[k]); // Look, compare and eventually move      for(k=0;k<hood_rank.size;k++)      {        pt=sequence_subst(p,sw.p[hood_rank.s[k]],size_max); //printf("\n splice_around. %f %f %f %f",p.f,p.best_f,pt.f,pt.best_f);          if (pt.best_f<best_best.best_f) return pt;          // if (pt.best_f<p.best_f) return pt; // Stop asa there is improvement      }    printf("\n splice=> NO improvement");  return pt; } //------------------------------------------------------------------- ALEA_VELOCITYstruct velocity	alea_velocity(int N){int				i;struct velocity vt;//vt.size=alea(1,N);vt.size=N;for (i=0;i<vt.size;i++)	{	vt.comp[i][0]=alea(0,G.N-1);	vt.comp[i][1]=alea_diff(0,G.N-1,vt.comp[i][0]);	}//display_velocity(vt);return vt;}// ------------------------------------------------------------------- AUTO_MOVEstruct particle auto_move(struct particle p,int type, int monotony, int levelling,int trace)/* The particle moves slowly, looking for a better position */{int               b,d,f;int 			i,j,k;int               improv;int				levelling0;int                  loop,loop_max;struct particle	pt,pt1;struct velocity v;if (trace>1)	printf("\n Auto-move type %i for particle %i. Size %i \n",type,p.rank+1,p.x.size);pt=p; // loop_max=G.N; loop_max=1;if (type==0) // Lazy Descent Method	{      for(loop=0;loop<loop_max;loop++)      {	for (i=0;i<G.N;i++) // Move at random.		{		pt.v=alea_velocity(1);		pt=pos_plus_vel(pt,pt.v,monotony,1,levelling);		if(pt.best_f<p.best_f) // Stop as soon as a better position is found			{			return pt;			}		}  }	if (trace>1) {printf("\n auto move => no move ");display_position(p,1);}	return p;	}if (type==1) // Energetic	{	next_step1:	for (i=0;i<G.N;i++) // Move at random		{		pt.v=alea_velocity(1);  // Just one transposition (switch)		pt1=pos_plus_vel(pt,pt.v,monotony,1,levelling);		if(pt1.best_f<pt.best_f) // Move as long as a better position is found			{			pt=pt1;			goto next_step1;			}		}	return pt;	} if (type==6) goto three_opt;//same_best_threshif (type>=2 && type<=5) /*				Check all immediate physical neighbours.            If one is better, move,            if (type=3 or 5) check again			*/	levelling0=levelling;if (type>2) levelling0=1;	v.size=1;   improv=0;	next_step2:	for (j=0;j<G.N-1;j++)  // For each neighbour		{		v.comp[0][0]=j;		for (k=j+1;k<G.N;k++)			{			v.comp[0][1]=k;			pt1=pos_plus_vel(pt,v,monotony,1,levelling);			if((levelling==0 && pt1.best_f<pt.best_f) || (levelling>0 && f_levelling(G,pt,pt1)<pt.fl)) // Move towards the best neighbour				{				if (trace>1)					{printf("\n auto move => ");display_position(pt,1);}				pt=pt1;                     improv=1;				if (type==3 || type==5) goto next_step2;				}			}		}      if (improv==0)      {      	if (trace>1) {printf("\n auto move => no move ");display_position(p,1);}	return p;      }   else	return pt; three_opt: if (trace>1)    printf("\n auto_move, 3-opt"); //scanf("%i",&b); v.size=3;    for (b=0;b<G.N;b++)    {       v.comp[0][0]= p.x.s[b];       for (d=0;d<G.N;d++)       {          v.comp[1][0]= p.x.s[d];          v.comp[0][1]= p.x.s[d];          for (f=0;f<G.N;f++)          {             v.comp[2][0]= p.x.s[f];             v.comp[1][1]= p.x.s[f];              v.comp[2][1]= p.x.s[b];          pt=pos_plus_vel(pt,v,0,0,0);		if(pt.f<p.f) // Stop as soon as a better position is found		{			return pt;		}           } // f       } // d    }  // b    return pt;}/*------------------------------------------------------------- COEFF_POS_MINUS_POS */struct velocity	coeff_pos_minus_pos(struct particle p1,struct particle p2,double coeff,int monotony,int equiv_v, int trace)	/* Applying v to p2 gives p1, or, in short, p2+v=p1, or v=p1-p2	and, after coeff*v	monotony = 1  => we have p1.f<=p2.f and we want, for each intermediate position p(t),							p(t).f<=p(t-1).f	monotony = 2  => coeff*v is computed in order to keep a "monotony" according to the distance						between the two particles	*/{int 			i,j,k,n1,nt;int				GN;struct particle pt;struct velocity vt;double			d0,d;if (trace>2) printf("\n\n coeff_pos_minus_pos, particles %i and %i",p1.rank+1,p2.rank+1);if (p1.rank>=0 && (p1.rank==p2.rank)) {vt.size=0; return vt;}; // If it is the same particle, of course the velocity is nullvt.size=0;pt=p2;GN=p2.x.size;if (trace>2)	{	printf("\n coeff_pos_minus_pos, GN %i",GN);	display_position(p1,0);	display_position(p2,0);	}if (pt.x.s[0]!=0) pt.x=rotate(pt.x,0); /* To be sure the particle description begins on node 1 */if (p1.x.s[0]!=0)	{	printf("\n ERROR. coeff_pos_minus_pos. The first node of the particle %i is %i. Must be 1",p1.rank,1+p1.x.s[0]);   return vt;	}for (i=1;i<GN-1;i++) // For each node of pt, at rank i ...	{	nt=pt.x.s[i];	n1=p1.x.s[i];	for (j=i;j<GN;j++) // ... look for its rank in p1...			{			if (p1.x.s[j]==nt) // ... finds it at rank j				{				if (j!=i) // .. if it is not the same rank ...					{					pt.x.s[i]=n1; // ... change the node in pt ...					vt.comp[vt.size][0]=n1;								// ... then, looks for the node of p1 in pt					for (k=i+1;k<GN;k++)						{						if (pt.x.s[k]==n1)							{							pt.x.s[k]=nt;							vt.comp[vt.size][1]=nt;							vt.size=vt.size+1;							if (vt.size>Vmax)								goto stop;							goto next_node;							}						}					printf("\n ERROR. Don't find %i after rank %i in particle %i",n1,i+1, pt.rank);					return vt;					}				}			}	next_node:;	}if (trace>2) {printf ("\n vt before coeff");display_velocity(vt);printf("\n");}vt=coeff_times_vel(vt,coeff,equiv_v,trace);//printf("\n monotony %i",monotony);if (trace>2) {printf ("\n vt after coeff");display_velocity(vt);printf("\n");}if (monotony!=2)	return vt;//----------------------==========================================	d0=distance(p2,p1,type_dist); // Initial distance, with no coeffif (d0==0) return vt;if (coeff==1) return vt;//printf("\n     dist. %f",d0);if (coeff<1)	{	update_coeff:	pt=pos_plus_vel(p2,vt,0,1,0);	d=distance(pt,p1,type_dist);	if (d<=d0) // OK for monotony (decreasing distance)		{		return vt;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -