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");

        }

}

 

 

 

你可能感兴趣的:(算法)