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

 

 

 

posted on 2012-10-16 19:34  IThinktan  阅读(328)  评论(0编辑  收藏  举报

导航