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

📄 ga-tsp.cpp

📁 这是一个人工智能方面的算法程序
💻 CPP
字号:

//23020061152452 陈魁

#include <iostream.h>
#include <time.h>
#include <stdio.h>
#include <iomanip>
#include <fstream.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

int increase;                         //交叉时增加的个体数
double nfit=0;                        //设定总适应度=0    
#define MaxCityNum 50                 //设定最大城市数目为50 
int dist[MaxCityNum][MaxCityNum] ;   
 
typedef struct TSP
{    int road[50];            //road 数组来表示一个回路即是一个染色体,最大设定50
     double fit;               //fit为这个染色体的适应度
};

//-------------------------随机数发生器的类定义-----------------------------------------------
const unsigned long maxshort=65536L;
const unsigned long multiplier=1194211693L;
const unsigned long adder=12345L;

class RandomNumber
{  private:
      //当前种子
      unsigned long randSeed;
   public:
	  //构造函数,缺省值为0表示由系统自动产生种子
	   RandomNumber(unsigned long s=0);
	  //产生0~(n-1)之间的随机整数
	   unsigned short Random(unsigned long n);
	   //产生[0,1)之间的随机实数
	   double fRandom(void);
};
	    
//产生种子
RandomNumber::RandomNumber(unsigned long s)
{   if(s==0)
       randSeed=time(0);   //用系统时间产生种子
    else
	   randSeed=s;         //由用户提供种子
}

//产生0~(n-1)之间的随机整数

unsigned short RandomNumber::Random(unsigned long n)
{   randSeed=multiplier*randSeed+adder;
    return (unsigned short)((randSeed>>16)%n);
}

//产生[0,1)之间的随机实数

double RandomNumber::fRandom(void)
{  return Random(maxshort)/double(maxshort);
}
//-------------------------随机数发生器的类定义---------------------------------------------------

//----------------------------------------适应度计算-----------------------------------------------
double Calfit(int g[],int City_Num)  //g为一个染色体
{   
	double w=0;             //权值
    double fit;
	int s,e;

   // for(int k=1;k<=11;k++)  调试用
   // cout<<"g["<<k<<"]="<<g[k]<<endl; 

    for(int i=1;i<=City_Num;i++)
	{   s=g[i]; e=g[i+1];
		w = w + dist[s][e] ;                
	}
    fit=w;
    return double(100000)/fit;    //修改
}
//-----------------------------------------适应度计算-------------------------------------------

//-----------------------------------------存在判定---------------------------------------------
bool exist(int t,int e[],int cl1,int cl2)                     
{   bool flag = false; 
    for(int i=cl1;i<=cl2;i++)
	{  if(e[i]==t) flag = true;
    }
   return flag;
}
//-----------------------------------------存在判定----------------------------------------------

class GA
{ 
  friend bool Letstry(int City_Num,int popsize,int generation,double pc,double pm,bool show);  

  public:
	   int   popsize;                              // 种群大小  
	   double   pc;                                // 交叉率
	   double   pm;                                // 变异率	
	   int flag;                                  // 是否显示种群个体
  	 
	   TSP *x;                                 // 进化中间过程中进行处理
       TSP *y;                                 // 存放每代进化完成的结果

	   TSP  *Bestnow(TSP t[],int size);                   // 寻找当前最优的个体  
       TSP  *Initialize(int City_Num,int size,int show); // 初始化种群          
	   TSP  *Crossover(int City_Num,TSP y[],int size);             //交叉操作
	   TSP  *Mutation(int City_Num,TSP t[],int size);              //变异操作
       TSP  *Select(TSP t[],int size);                //选择操作
	                          
};
//-----------------------------------------GA类定义-----------------------------------------------

//----------------------------------------种群初始化----------------------------------------------
TSP *GA::Initialize(int City_Num, int size,int show)     //size种群规模。初始化size个可行解
{   
    static RandomNumber R;
    TSP *t=new TSP[size+1];
    int i=1;
	int b;
//	int temp;//tempchange;
	for(int k=0;k<=size;k++)                              //初始化种群数组,全部设为0
	{    for(int n=0;n<=City_Num+1;n++)
	        t[k].road[n]=0;
	}
	t[0].fit=0;
	
	while(i<=size)             
	{    int s[MaxCityNum+1];     
         for(int k=1;k<City_Num+1;k++)  s[k]=0;

		 for(int j=1;j<City_Num+1;j++)
		 {
            b=R.Random(City_Num)+1;
            while(s[b]!=0)
			{b=R.Random(City_Num)+1;
			}
			t[i].road[j] = b;
			s[b]=1;
			
		 }

		/*for(int k=1;k<=City_Num;k++) 
		{  t[i].road[k] = k; }                            //填充数组 

         for(int n=1;n<City_Num;n++)                      //随机交换
		{
             temp = R.Random(City_Num)+1;
             tempchange = t[i].road[n]; t[i].road[n] = t[i].road[temp]; t[i].road[temp] = tempchange;
		 }*/
	        t[i].road[City_Num+1] = t[i].road[1];                  //回到出发位置	       
	        t[i].fit = Calfit(t[i].road, City_Num);    
	        i++;
    }	
     if(show)
	 {      cout<<"初始化的种群为:"<<endl;                //输出初始种群
            for (k=0;k<=size;k++)
			{      for( int j=1;j<=City_Num+1;j++)              
			{        cout<<t[k].road[j]<<"  "; } 
                     cout<<"    t["<<k<<"].fit: "<<t[k].fit<<endl;       
	                 cout<<endl<<endl;
			}
	 }
    return t;
}
//----------------------------------------种群初始化----------------------------------------------

//-------------------------------------寻找当前最优解---------------------------------------------

TSP *GA::Bestnow(TSP t[],int size)
{   
	int best=0;
    double bestfit=t[0].fit; 
	for(int i=1;i<=popsize;i++)
	{  if(t[i].fit>bestfit)
	    {  bestfit=t[i].fit;
	        best=i;
	    }   
	}
    t[0]=t[best];
	return t;
}
//-------------------------------------寻找当前最优解---------------------------------------------

//-------------------------------------交叉操作----------------------------------------------------
TSP *GA::Crossover(int City_Num,TSP y[],int size)          // 按相对顺序进行交叉
{   
	increase = 1; 
    static RandomNumber R;
    double p1;                      
    int cl1,cl2,tempchange;                  //cl为crosslocation 即交叉位置(随机选取)
    int co;                                  //co为crossobject 即交叉对象(随机选取)
    TSP *x=new TSP[1000];

	for(int k=0;k<=size;k++)
	{  x[k]=y[k];}
    
    for(k=0;k<=size;k++)
	{      //cout<<"k="<<k<<endl;                         
        p1=R.fRandom();                      //生成随机数p1 
		 
        if(p1<pc)                            //随机数比交叉率小,则执行交叉操作
		{    
            cl1 = R.Random(City_Num)+1;      //交叉位置的随机选取
			cl2 = R.Random(City_Num)+1;
			while(cl1==cl2)  cl2 = R.Random(City_Num)+1;
			if(cl1>cl2)  { tempchange=cl1; cl1=cl2;cl2=tempchange;}      //保证cl1<cl2

            do{ co=R.Random(size+1);                 //交叉对象的随机选取(不是本身)                  
			}while(co==k);
		
		    for(int i=1;i<=City_Num;i++)            //先产生2个和父代一样的个体
				   {  
			           x[size+increase].road[i] = x[k].road[i];      
			           x[size+increase+1].road[i] = x[co].road[i];
				   }
		
			for(i=1;i<cl1;i++)                      //将要赋予新值的位置设置成0
			{   
				x[size+increase].road[i] = 0;      
			    x[size+increase+1].road[i] = 0;
			}
			for(i=cl2+1;i<=City_Num;i++)
			{  
				x[size+increase].road[i] = 0;      
			    x[size+increase+1].road[i] = 0;

			}
			
           int n=1,s=1;
           for(int m=1;m<City_Num+1;m++)      //  副本父代2个个体交叉变换
		   {      
               if(!exist(x[co].road[m],x[k].road,cl1,cl2))
			   {    
			     while(x[size+increase].road[n]!=0) {n++;}
				// cout<<"n="<<n<<endl;
			     x[size+increase].road[n] = x[co].road[m];
			   }

			   if(!exist(x[k].road[m],x[co].road,cl1,cl2))
			   {
                 while(x[size+increase+1].road[s]!=0) {s++;}
				 //cout<<"n="<<n<<endl;
                 x[size+increase+1].road[s] = x[k].road[m];
			   }

           }//for(m)
            x[size+increase].road[City_Num+1] = x[size+increase].road[1];
			x[size+increase+1].road[City_Num+1] =x[size+increase+1].road[1];
			
		    x[size+increase].fit=Calfit(x[size+increase].road,City_Num ); 
            x[size+increase+1].fit=Calfit(x[size+increase+1].road,City_Num); 
		    increase = increase+2;

		}//if(p1<pc)
			            
	}//for(k)
             
    increase = increase-1;

    delete y;

    return x;

}//Crossover
//-------------------------------------交叉操作--------------------------------------------------

//-------------------------------------变异操作---------------------------------------------------

TSP *GA::Mutation(int City_Num,TSP x[],int size)
{  
	TSP *t=new TSP[1000];
	static RandomNumber R;
    double p2;
	int ml1,ml2;
	int temp;
   	
	for (int k=0;k<=size+increase;k++)
	{  
       t[k]=x[k];
	}
    delete x;

     t[k]=t[0];                      //把当前最优解赋值给最后一元素,并参加变异过程
     increase = increase + 1;
	
	for (k=1;k<=size+increase;k++)   //t[0]本身不参加变异过程,保留当前最优,但是它的复制体参加                                        
	{     
		p2=R.fRandom();
         
	 if(p2<pm)
		{   
 			for(int i=1;i<=City_Num+1;i++)
			{   t[size+increase+1]=t[k]; }

                ml1 = R.Random(City_Num)+1;             //变异位置
                ml2 = R.Random(City_Num)+1;
				while(ml1==ml2) ml2= R.Random(City_Num)+1;

                temp=t[k].road[ml1]; t[k].road[ml1] = t[k].road[ml2];
				t[k].road[ml2] = temp;
				
				t[k].road[City_Num+1] = t[k].road[1];
                t[k].fit=Calfit(t[k].road,City_Num);                 
	  }
	}

    return t;
}
//-------------------------------------变异操作---------------------------------------------------

//-------------------------------------选择操作---------------------------------------------------
TSP *GA::Select(TSP t[],int size)
{ 
	 static RandomNumber R;
	 double point;
     double sumfit=0;
	 int i;

	 TSP *s=new TSP[size+1];
	 s[0]=t[0];

	 for(int k=1;k<=size+increase;k++)               //准备计算相对适应度    
	 {
         sumfit=sumfit+t[k].fit;
	 }
     
	 double *relative_fit=new double[size+increase+1];

	 for(k=1;k<=size+increase;k++)
	 {
		 relative_fit[k]=double(t[k].fit)/sumfit;
	 }
     
	 for(k=2;k<=size+increase;k++)
	 {   
		 relative_fit[k]=relative_fit[k-1]+relative_fit[k];	 
	 }


	 for(k=1;k<=size;k++)
	 {
          point=R.fRandom();
          i=0;
		  while(point>relative_fit[i])  { i++; }
		  s[k]=t[i];
	 }
     return s;
}

//-------------------------------------选择操作---------------------------------------------------

//-------------------------------------友元函数---------------------------------------------------
bool Letstry(int City_Num,int popsize,int generation,double pc,double pm,int show)
{
   GA G;
   G.popsize=popsize;
   G.pc=pc;
   G.pm=pm;
   int flag;
   flag=show;
   G.flag=show;

   G.y=G.Initialize(City_Num,G.popsize,G.flag );
   G.y=G.Bestnow(G.y,G.popsize);

  for(int g=1;g<=generation;g++)
  { 
    G.x=G.Crossover(City_Num,G.y,G.popsize );
    
    G.x=G.Mutation(City_Num,G.x,G.popsize );
     	
    G.x=G.Bestnow(G.x,G.popsize);
  
     G.y=G.Select(G.x,G.popsize);

    if(flag)
	{	  cout<<endl;
          cout<<"第"<<g<<"代种群为:"<<endl;
   	for(int k=0;k<=popsize;k++)
      {    for( int l=1;l<=City_Num+1;l++)              
			          {cout<<G.y[k].road[l]<<"  ";}
			      cout<<"    y["<<k<<"].fit: "<<G.y[k].fit<<endl;
			      cout<<endl;      
       }
	}
    increase=1;
	cout<<endl<<"当前近似最优解="<<double(100000)/(G.y[0].fit)<<endl;
	
  }  
  G.y=G.Bestnow(G.y,G.popsize);
  
  cout<<endl<<"近似最优解="<<double(100000)/(G.y[0].fit)<<endl;
 
  for(int k=1;k<=City_Num+1;k++)
  cout<<G.y[0].road[k]<<" ";
  
  cout<<endl;
 
 //cout<<"nfit="<<nfit<<endl;
  nfit=nfit+G.y[0].fit;
// cout<<"nfit="<<nfit<<endl;
  return true;

}

//-------------------------------------友元函数---------------------------------------------------

void main()
{  
	int City_Num;
	int popsize;
    int generation;
    double pc;
    double pm;
	int show;
	int runtime;
//	double avefit;
    ifstream datafile;                      
    char fileName[10];
    
 

    cout<<"请输入城市的数目(29 or 42):";
	cin>>fileName;
    City_Num=atoi(fileName);
	
	
	 for(int k=0;k<City_Num+1;k++)                         //初始化邻接矩阵
         for(int t=0;t<City_Num+1;t++)
             dist[k][t]=0;
  datafile.open(strcat(fileName,".txt"));                  //打开文件   

 for(int i=1;i<City_Num+1;i++)                            //输入数据到矩阵
	{	for(int j=1;j<City_Num+1;j++)
		{	datafile>>dist[i][j];
			//dist[j][i]=dist[i][j];
		}
	}
 // for( k=1;k<City_Num+1;k++)
 //	  for(int l=1;l<City_Num+1;l++)
 //		  cout<<"dist["<<k<<"]["<<l<<"]="<<dist[k][l]<<" ";
	  cout<<endl;
   	 
    cout<<"请输入要初始的种群大小的规模(100~200):";
	cin>>popsize;
    cout<<endl;

	cout<<"请输入算法进行进化的代数:";
	cin>>generation;
    cout<<endl;
	
	do {
		cout<<"请输入要设置的交叉率pc(0.5~0.9):";
		cin>>pc;
	} while(pc>=1||pc<=0);
    cout<<endl;

	
    do {
		cout<<"请输入要设置的变异率pm(0.01-0.2):";
		cin>>pm;
	} while(pm>=1||pm<=0);
    cout<<endl;
    
    do{
		cout<<"是否显示每代的种群(0-否,1-是):";
		cin>>show;
    }while((show!=1)&&(show!=0));
	cout<<endl;

	do{
		cout<<"请输入要执行的次数:(1)";
        cin>>runtime;
	}while(runtime<=0);
    
  for(int n=1;n<=runtime;n++)
  {
	  Letstry(City_Num,popsize,generation,pc,pm,show);
	   
  }
  // cout<<"nfit="<<nfit<<endl;
  // avefit = double(runtime)/nfit;   
  //cout<<"路径最小值平均为:"<<avefit<<endl;
}

                                                                         //23020061152452 陈魁

⌨️ 快捷键说明

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