zoukankan      html  css  js  c++  java
  • TSP_遗传算法求解

    head.h

    #define N 10
    
    class Generation
    {
    public:
        int state[4][N+1];//染色体---种群规模为4,有10个城市
        float loadlength[4];//染色体的路径长度
        float Fitness[4];//适应度
        float SPro[4];//选择概率
        float AcPro[4];//累积概率
        int ChoiceNum[4];//选择次数
      
        Generation()
        {
            int i;
            for(i=0;i<4;i++)
                for(int j=0;j<N+1;j++)
                    state[i][j]=-1;
            for(i=0;i<4;i++)
            {
                loadlength[i]=0;
                Fitness[i]=0;
                SPro[i]=0;
                AcPro[i]=0;
                ChoiceNum[i]=0;
            }
        }  
    };
    class Point
    {
    public:
        int x;
        int y;
        Point(int a,int b)
        {
            x=a; 
            y=b; 
        }
    };
    
    void RAND(double *r);
    Generation Init(Generation G);//初始化群体
    void count_distance();//计算各个城市之间的直线距离
    float count_loadlegth(Generation* G);//计算路径长度
    void count_fitness(Generation* G);//计算适应度 
    void count_pro(Generation* G);//计算选择概率和累计概率
    void count_choiceNum(Generation* G);//计算被选中的次数
    void addtoopen(Generation G);
    void Copy_Generation(Generation* G1,Generation G0);//根据被选中次数复制上一代染色体
    void Variation(Generation *G1);
    void Cross(Generation *G1);

    Main.cpp

    #include<iostream>
    #include"head.h"
    using namespace std;
    #define N 10
    
    Generation OPEN[5000];//队列-----(数据保护)每一代各染色体的情况
    int OPhead=0,OPtail=0,openlen=5000;
    float Distance[N][N]={0};//存储各个城市之间的直线距离
    float MinShort=3000;//最短路径长度
    int MinShortLoad[N+1]={0};//最短路径
    
    int main()
    {
        int i;
        //计算各个城市之间的直线距离
        count_distance();    
        
        Generation G0,G1;
        G0=Init(G0);//初始种群 
        G1=G0;
        int GNUM=0;
        while(MinShort>167)
        {
            G0=G1;
            printf("第%d代染色体情况:\n",GNUM);
            count_loadlegth(&G0);//计算路径长度        
            printf("已搜索到的路径中最短为: %f\n",MinShort);
            printf("已搜索到的路径中最短路径: ");
            for(i=0;i<N+1;i++)
                printf("%d ",MinShortLoad[i]);
            printf("\n");
    
            count_fitness(&G0);//计算适应度        
            count_pro(&G0);    //计算选择概率和累计概率        
            count_choiceNum(&G0);//计算被选中的次数
            addtoopen(G0);//保护每一代的记录
         
    
            printf("下一代:\n");
            //复制
            printf("复制后:\n");    
            Copy_Generation(&G1,G0);//根据被选中次数复制上一代染色体G0
            //交叉
            printf("交叉后:\n");
            Cross(&G1);///////////
            //变异    
            if(GNUM%5==0)//每5代(20条染色体)里变异一次(约0.5条染色体变异)-----变异率2.5%
            {
                printf("变异后:\n");
                Variation(&G1);    
            }
    
            printf("\n\n");
            GNUM++;
        }
        return 0;    
    }

    Function.cpp

    #include<iostream>
    #include<stdlib.h>//for rand(),srand()
    #include<time.h> //for time()
    #include<math.h>
    #include<string.h>
    #include"head.h"
    #define N 10
    
    extern Generation OPEN[5000];//队列-----(数据保护)每一代各染色体的情况
    extern int OPhead,OPtail,openlen;
    extern float Distance[N][N];//存储各个城市之间的直线距离
    extern float MinShort;//最短路径长度
    extern int MinShortLoad[N+1];//最短路径
    
    
    void count_distance()
    {
        //各个城市的位置坐标
        Point Position[N]={ Point(87,7),Point(91,38),Point(83,46),Point(71,44),Point(64,60),
                            Point(68,58),Point(83,69),Point(87,76),Point(74,78),Point(71,71)
                            //Point(58,69),Point(54,62),Point(51,67),Point(37,84),Point(41,94),
                            //Point(2,99),Point(7,64),Point(22,60)//,Point(25,62),Point(18,54)
                            //Point(4,50),Point(13,40),Point(18,40),Point(24,42),Point(25,38),
                            //Point(41,26),Point(45,21),Point(44,35),Point(58,35),Point(62,32)
                            };
    
        int i,j;  
        for(i=0;i<N;i++)
            for(j=0;j<N;j++)
                Distance[i][j]=sqrt(pow(Position[i].x-Position[j].x,2)+pow(Position[i].y-Position[j].y,2)); 
    }
    Generation Init(Generation G)
    {
        int i,j;
        int Arr[4][N+1]={0};
        /*={{7,8,9,4,5,6,1,2,3,0,7},//
            {9,8,7,3,2,1,6,5,4,0,9},//
            {1,3,5,7,9,2,4,6,8,0,1},//
            {0,1,2,3,4,5,6,7,8,9,0}};// //初始四条路径*/
        for(i=0;i<4;i++)//产生随机初始种群
        {
            for(j=0;j<N;j++)//j---已经得到的序列个数
            {
                int temp=rand()%N;
                for(int t=0;t<j ;t++)
                    if(temp==Arr[i][t])
                    { temp=rand()%N;  t=-1;  }
    
                Arr[i][j]=temp;
            }
            Arr[i][N]=Arr[i][0];
        }
    
        for(i=0;i<4;i++)
            for(j=0;j<N+1;j++)
                 G.state[i][j]=Arr[i][j];//初始化第0代的的种群状态
        return G;    
    }
    float count_loadlegth(Generation* G)//计算路径长度
    {
        int i,j;
        float Short=10000.0;
        int Snum;
        for(i=0;i<4;i++)
        {
            float DistanceAdd=0.0;
            for(j=0;j<N;j++)//11-1
            {
                int c1=(*G).state[i][j];
                int c2=(*G).state[i][j+1];
                DistanceAdd += Distance[c1][c2];
            }
            (*G).loadlength[i]=DistanceAdd;
            if(DistanceAdd<Short)  
            {    Short=DistanceAdd ;  Snum=i;  } 
        }
        for(i=0;i<4;i++)
        {
            for(j=0;j<N+1;j++)
                printf("%d ",(*G).state[i][j]);
            printf("   ----路径长: %f\n",(*G).loadlength[i]);
        }
    
        printf("最短路径为:  ");
        for(j=0;j<N+1;j++)    
            printf("%d  ",(*G).state[Snum][j]);
        printf("\n最短路径长: ---%f\n",Short);//输出当代最短路径
        if(Short<MinShort)//获取全局最短路径长度及其最短路径
        {
            MinShort=Short;
            for(j=0;j<N+1;j++)
                MinShortLoad[j]=(*G).state[Snum][j];
        }
    
        return Short;//返回当代最短路径
    }
    void count_fitness(Generation* G)//计算适应度
    {
        for(int i=0;i<4;i++)
            (*G).Fitness[i]=(float)1000/(*G).loadlength[i];//计算得每个染色体的适应度((float)10000用于调整数值)
    }
    void count_pro(Generation* G)//计算选择概率和累计概率    
    {
        int i;
        float ALL_fitness=(*G).Fitness[0]+(*G).Fitness[1]+(*G).Fitness[2]+(*G).Fitness[3];
        for(i=0;i<4;i++)//选择概率
            (*G).SPro[i]=(*G).Fitness[i]/ALL_fitness;
    
        for(i=0;i<4;i++)//累计概率
        {
            if(i==0) (*G).AcPro[i]=(*G).SPro[i];
            else     (*G).AcPro[i]=(*G).SPro[i]+(*G).AcPro[i-1];
        }
    }
    void RAND(double *r)//产生随机数
    {
        //获得当前的时间作为随机数的种子//seed=time(0)
        srand(time(0));//两次获取随机数时间之差大于1s产生的随机数才会不同
        int i;
        for(i=0;i<4;i++)
        {
            r[i]=(double)rand()/(double)RAND_MAX;//RAND_MAX=32767
        }
    }
    void count_choiceNum(Generation* G)//计算被选中的次数
    {
        //产生随机数
        double r[4]={0.0};
        RAND(&r[0]);    
    
        int i,j;
        for(i=0;i<4;i++)
            for(j=0;j<4;j++)//对于每一个随机概率
            {
                if(i==0)
                {    
                    if(r[j]<(*G).AcPro[i])
                        (*G).ChoiceNum[i]++;
                }
                else
                {
                    if(r[j]>=(*G).AcPro[i-1] && r[j]<(*G).AcPro[i] )
                        (*G).ChoiceNum[i]++;
                }
            }
        printf("被选中的次数: ");
        for(i=0;i<4;i++)
            printf("%d ",(*G).ChoiceNum[i]);
        printf("\n");
    }
    void addtoopen(Generation G)
    {
        OPEN[OPtail++]=G; //向尾部添加节点 
        OPtail = OPtail%openlen;
    }

    Cross.cpp(交叉)

    #include<iostream>
    #include<stdlib.h>//for rand(),srand()
    #include<time.h> //for time()
    #include"head.h"
    #define N 10
    
    extern Generation OPEN[5000];//队列-----(数据保护)每一代各染色体的情况
    extern int OPhead,OPtail,openlen;
    extern float Distance[N][N];//存储各个城市之间的直线距离
    
    
    //交叉
    void Cross(Generation *G1)
    {
        int i;
        char OffSpr_A[N+1]={0},OffSpr_B[N+1]={0}, OffSpr_C[N+1]={0},OffSpr_D[N+1]={0};//记录交叉序列
        int kk;
    
        //*****获取1、2号后的交叉**************************//
        Generation Gt=*G1;//保护G1
        int C=rand()%N;//获取随机城市代号
        //int CV=C;//保护C
        OffSpr_A[0]=C;//将城市C加入记录---第1个子孙
        int count=N;//对前10个基因进行交叉(最后一个是重复的城市)
        kk=1;
        while(count!=1)
        {
            int Ra,Rb;
            for(i=0;i<N;i++)//求城市C在Gt.state[0][]、Gt.state[1][]中的下标位置
            {    
                if(Gt.state[0][i]==C)  Ra=i;//记录下标    
                if(Gt.state[1][i]==C)  Rb=i;
            }
            //printf("随机起始城市: %d---下标: %d %d  ",C,Ra,Rb);        
            int Cright_A,Cright_B;
            for(i=(Ra+1)%N; ;)/////////寻找C在G1.state[0][]中的右城市号
            {
                if(Gt.state[0][i]!=-1)
                {    Cright_A=Gt.state[0][i];  break;  }
                i=(i+1)%N;
            }
            //printf("右城市A:%d  ",Cright_A);
            for(i=(Rb+1)%N; ;)/////////寻找C在G1.state[1][]中的右城市号
            {
                if(Gt.state[1][i]!=-1)
                {   Cright_B=Gt.state[1][i];  break;  }
                i=(i+1)%N;
            }
            //printf("右城市B:%d\n",Cright_B);
    
            float da,db;
            da=Distance[C][Cright_A];
            db=Distance[C][Cright_B];
            if(da<=db) 
            {    
                OffSpr_A[kk++]=Cright_A;//加入记录        
                C=Cright_A;
            }else
            {
                OffSpr_A[kk++]=Cright_B;            
                C=Cright_B;
            }
            Gt.state[0][Ra]=-1;//删除城市G1.state[0][Ra]---标记为-1
            Gt.state[1][Rb]=-1;
    
            count--;
        }
        OffSpr_A[N]=OffSpr_A[0];//最后一个城市与第一个城市相同
        
    
        Gt=*G1;//保护G1
        //C=CV;
        C=rand()%N;//获取随机城市代号
        OffSpr_B[0]=C;//第2个子孙
        count=N;
        kk=1;
        while(count!=1)
        {
            int Ra,Rb;
            for(i=0;i<N;i++)//求城市C在Gt.state[0][]、Gt.state[1][]中的下标位置
            {    
                if(Gt.state[0][i]==C)  Ra=i;//记录下标    
                if(Gt.state[1][i]==C)  Rb=i;
            }
            //printf("随机起始城市: %d---%d %d  ",C,Ra,Rb);        
            int Cleft_A,Cleft_B;
            for(i=(Ra-1+N)%N; ;)/////////寻找C在G1.state[0][]中的左城市号
            {
                if(Gt.state[0][i]!=-1)
                {    Cleft_A=Gt.state[0][i];  break;  }
                i=(i-1+N)%N;
            }
            //printf("右城市A:%d  ",Cleft_A);
            for(i=(Rb-1+N)%N; ;)/////////寻找C在G1.state[1][]中的左城市号
            {
                if(Gt.state[1][i]!=-1)
                {   Cleft_B=Gt.state[1][i];  break;  }
                i=(i-1+N)%N;
            }
            //printf("右城市B:%d\n",Cleft_B);
    
            float da,db;
            da=Distance[C][Cleft_A];
            db=Distance[C][Cleft_B];
            if(da<=db) 
            {    
                OffSpr_B[kk++]=Cleft_A;//加入记录    
                C=Cleft_A;
            }else
            {
                OffSpr_B[kk++]=Cleft_B;
                C=Cleft_B;
            }
            Gt.state[0][Ra]=-1;//删除城市G1.state[0][Ra]---标记为-1
            Gt.state[1][Rb]=-1;
    
            count--;
        }
        OffSpr_B[N]=OffSpr_B[0];//最后一个城市与第一个城市相同
        //////////////////////////////////////////////////////
    
    
    
        //*****获取3、4号后代的交叉**************************//
        Gt=*G1;//保护G1
        C=rand()%N;//获取随机城市代号
        //CV=C;//保护C
        OffSpr_C[0]=C;//将城市C加入记录---第3个子孙
        count=N;
        kk=1;
        while(count!=1)
        {
            int Ra,Rb;
            for(i=0;i<N;i++)//求城市C在Gt.state[0][]、Gt.state[1][]中的下标位置
            {    
                if(Gt.state[2][i]==C)  Ra=i;//记录下标    
                if(Gt.state[3][i]==C)  Rb=i;
            }
            //printf("随机起始城市: %d---%d %d  ",C,Ra,Rb);        
            int Cright_A,Cright_B;
            for(i=(Ra+1)%N; ;)/////////寻找C在G1.state[0][]中的右城市号
            {
                if(Gt.state[2][i]!=-1)
                {    Cright_A=Gt.state[2][i];  break;  }
                i=(i+1)%N;
            }
            //printf("右城市A:%d  ",Cright_A);
            for(i=(Rb+1)%N; ;)/////////寻找C在G1.state[1][]中的右城市号
            {
                if(Gt.state[3][i]!=-1)
                {   Cright_B=Gt.state[3][i];  break;  }
                i=(i+1)%N;
            }
            //printf("右城市B:%d\n",Cright_B);
    
            float da,db;
            da=Distance[C][Cright_A];
            db=Distance[C][Cright_B];
            if(da<=db) 
            {    
                OffSpr_C[kk++]=Cright_A;//加入记录        
                C=Cright_A;
            }else
            {
                OffSpr_C[kk++]=Cright_B;
                C=Cright_B;
            }
            Gt.state[2][Ra]=-1;//删除城市G1.state[0][Ra]---标记为-1
            Gt.state[3][Rb]=-1;
    
            count--;
        }
        OffSpr_C[N]=OffSpr_C[0];//最后一个城市与第一个城市相同
    
    
        Gt=*G1;//保护G1
        //C=CV;
        C=rand()%N;//获取随机城市代号
        OffSpr_D[0]=C;//第4个子孙
        count=N;    
        kk=1;
        while(count!=1)
        {
            int Ra,Rb;
            for(i=0;i<N;i++)//求城市C在Gt.state[0][]、Gt.state[1][]中的下标位置
            {    
                if(Gt.state[2][i]==C)  Ra=i;//记录下标    
                if(Gt.state[3][i]==C)  Rb=i;
            }
            //printf("随机起始城市: %d---%d %d  ",C,Ra,Rb);        
            int Cleft_A,Cleft_B;
            for(i=(Ra-1+N)%N; ;)/////////寻找C在G1.state[0][]中的左城市号
            {
                if(Gt.state[2][i]!=-1)
                {    Cleft_A=Gt.state[2][i];  break;  }
                i=(i-1+N)%N;
            }
            //printf("右城市A:%d  ",Cleft_A);
            for(i=(Rb-1+N)%N; ;)/////////寻找C在G1.state[1][]中的左城市号
            {
                if(Gt.state[3][i]!=-1)
                {   Cleft_B=Gt.state[3][i];  break;  }
                i=(i-1+N)%N;
            }
            //printf("右城市B:%d\n",Cleft_B);
    
            float da,db;
            da=Distance[C][Cleft_A];
            db=Distance[C][Cleft_B];
            if(da<=db) 
            {    
                OffSpr_D[kk++]=Cleft_A;//加入记录            
                C=Cleft_A;
            }else
            {
                OffSpr_D[kk++]=Cleft_B;            
                C=Cleft_B;
            }
            Gt.state[2][Ra]=-1;//删除城市G1.state[0][Ra]---标记为-1
            Gt.state[3][Rb]=-1;
    
            count--;
        }
        OffSpr_D[N]=OffSpr_D[0];//最后一个城市与第一个城市相同
        //////////////////////////////////////////////
    
    
        
        for(i=0;i<N+1;i++)//将交叉得到的序列复制回G1
            (*G1).state[0][i]=OffSpr_A[i];
        for(i=0;i<N+1;i++)
            (*G1).state[1][i]=OffSpr_B[i];
        for(i=0;i<N+1;i++)
            (*G1).state[2][i]=OffSpr_C[i];
        for(i=0;i<N+1;i++)
            (*G1).state[3][i]=OffSpr_D[i];
    
        for(i=0;i<4;i++)
        {    
            for(int j=0;j<N+1;j++)
                printf("%d ",(*G1).state[i][j]);
            printf("\n");
        }
    
    }

    Copy_Variation.cpp(复制和变异)

    #include<iostream>
    #include<stdlib.h>//for rand(),srand()
    #include<time.h> //for time()
    #include<math.h>
    #include<string.h>
    #include"head.h"
    #define N 10
    
    extern Generation OPEN[5000];//队列-----(数据保护)每一代各染色体的情况
    extern int OPhead,OPtail,openlen;
    extern float Distance[N][N];//存储各个城市之间的直线距离
    extern float MinShort;//最短路径长度
    extern int MinShortLoad[N+1];//最短路径
    
    void Copy_Generation(Generation* G1,Generation G0)//根据被选中次数复制上一代染色体G0
    {    
        int i,j;
        int k=0;
        float maxloadlen=0;//选取路径最长的用MinShortLoad[]替换
        int maxindex;
        for(i=0;i<4;i++)
            if(G0.loadlength[i]>maxloadlen)
            {
                maxloadlen=G0.loadlength[i];
                maxindex=i;//记录最长路径下标
            }
        for(j=0;j<N+1;j++)
            G0.state[i][j]=MinShortLoad[j];//替换最长的路径为搜索过的最短路径
    
        for(i=0;i<4;i++)//对于G0的每一个染色体
            for(j=0;j<G0.ChoiceNum[i];j++)//根据被选中次数复制G0染色体
            {
                for(int t=0;t<N+1;t++)
                    (*G1).state[k][t]=G0.state[i][t];
                k++;
            }
        
        for(i=0;i<3;i++)//交换子染色体的位置(减少相同染色体相邻)
        {
            for(int k=0;k<N+1;k++) 
                if((*G1).state[i][k]!=(*G1).state[i+1][k])//判断第[i]个和第[i+1]个是否相同
                    break;
            if(k==N+1)//相邻染色体相同
            {
                char temp[N+1]={0};        
                for(j=0;j<N+1;j++)  temp[j]=(*G1).state[i+1][j];
                for(j=0;j<N+1;j++)  (*G1).state[i+1][j]=(*G1).state[(i+2)%4][j];
                for(j=0;j<N+1;j++)  (*G1).state[(i+2)%4][j]=temp[j];
            }
        }
    
        for(i=0;i<4;i++)//输出复制后的情况
        {    
            for(j=0;j<N+1;j++)
                printf("%d ",(*G1).state[i][j]);
            printf("\n");
        }
    } 
    
    
    
    
    
    void Variation(Generation *G1)
    {
            int i,j;
    
            int k=rand()%4;//取其中一条进行变异
            int R=rand()%N;//产生随机起始城市下标
            //printf("%d %d\n",k,R);
            //printf("随机起始城市: %d\n",(*G1).state[k][R]);
    
            float D=10000;
            int City=0;
            for(i=0;i<N;i++)//寻找距离起始城市最近的非邻城市
            {
                if(i!=(*G1).state[k][R] && i!=(*G1).state[k][(R-1+N)%N] && i!=(*G1).state[k][(R+1)%N])
                    if(Distance[ (*G1).state[k][R] ][i]<D)
                    {
                        D=Distance[ (*G1).state[k][R] ][i];//取离城市G1.state[0][R]最小距离
                        City=i;//距离最近的城市号
                    }
            }
            //printf("最近城市: %d   距离: %f\n",City,D);
    
            //倒位
            int Sindex=(R+1)%N;//从随机起始城市的--右边城市开始进行倒位
            int Eindex;
            for(i=0;i<N;i++)//扫描染色体
                if((*G1).state[k][i]==City)
                    Eindex=i;
            if(Sindex>Eindex) //保证起点下标<终点下标
            {
               int temp=Sindex;
               Sindex=Eindex;
               Eindex=temp;
            }
            //printf("起点下标: %d   终点下标: %d\n",Sindex,Eindex);
            for(i=Sindex,j=Eindex;i<j;i++,j--)
            {
                int temp=(*G1).state[k][i];
                (*G1).state[k][i]=(*G1).state[k][j];
                (*G1).state[k][j]=temp;
            }
            (*G1).state[k][N]=(*G1).state[k][0];
            
    
            for(i=0;i<4;i++)
            {    
                for(j=0;j<N+1;j++)
                    printf("%d ",(*G1).state[i][j]);
                printf("\n");
            }
    }
  • 相关阅读:
    一些鲜为人知的编程真相
    一些鲜为人知的编程真相
    Ruby 1.9不会杀死Python
    Boost.Asio和ACE之间关于Socket编程的比较
    Effective C++第17条:要在单独的语句中使用智能指针来存储由new创建的对象
    Ruby 1.9不会杀死Python
    Boost智能指针——weak_ptr
    对象生死劫 - 构造函数和析构函数的异常
    Protocol Buffers:Google 的数据交换格式
    根据出生日期计算年龄
  • 原文地址:https://www.cnblogs.com/IThaitian/p/2726559.html
Copyright © 2011-2022 走看看