zoukankan      html  css  js  c++  java
  • 转:遗传算法解决TSP问题

    1.编码

    这篇文章中遗传算法对TSP问题的解空间编码是十进制编码。如果有十个城市,编码可以如下:

    0 1 2 3 4 5 6 7 8 9

    这条编码代表着一条路径,先经过0,再经过1,依次下去。

    2.选择

    选择操作仍然是轮盘赌模型,虽然不会出现路径长度为负数的情况,但是需要考虑与上篇文章不同的是求的是最小值。因此在代码中概率的计算为:

    3.交叉

    4.变异

    变异操作就是交换两个城市,例如:

    0 1 2 3 4

    0 2 1 3 4

    5.代码实现

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<math.h>
    #include<time.h>
    #include<Windows.h>
    #include<fstream>
    #include<iostream>
    using namespace std;
    
    const int cities = 10;  //城市的个数
    const int MAXX = 100;   //迭代次数
    const double pc = 0.8;  //交配概率
    const double pm = 0.05; //变异概率
    const int num = 10;  //种群的大小
    
    int bestsolution;//最优染色体
    double distance1[cities][cities];//城市之间的距离
    
    struct group  //染色体的结构
    {
        int city[cities];//城市的顺序
        double adapt;//适应度
        double p;//在种群中的幸存概率
    }group[num],grouptemp[num];
    
    struct point{
        double x,y;
    }Cpoint[cities];
    
    //随机产生cities个城市之间的相互距离
    void init()
    {/*
        int i,j;
        memset(distance,0,sizeof(distance));
        srand((unsigned)time(NULL));
        for(i=0;i<cities;i++)
        {
            for(j=i+1;j<cities;j++)
            {
               distance[i][j]=rand()%100;
               distance[j][i]=distance[i][j];
            }
        }
        //打印距离矩阵
        printf("城市的距离矩阵如下
    ");
        for(i=0;i<cities;i++)
        {
            for(j=0;j<cities;j++)
            printf("%4d",distance[i][j]);
            printf("
    ");
        }*/
        ifstream f1("C:\city.txt",ios::in);
        for(int i = 0; i < cities; i++){
            //if(ll % 2 != 0)
                f1 >> Cpoint[i].x;
            //if(ll % 2 == 0)
                f1 >> Cpoint[i].y;
            //ll++;
        }
        f1.close();
        double tmp1 = 0.0;
        for(int m = 0; m < cities; m++){
            for(int n = 0; n < cities; n++){
                if(m == n)
                    distance1[m][n] = 0;
                else{
                    tmp1 = sqrt(pow(Cpoint[m].x - Cpoint[n].x,2) + pow(Cpoint[m].y - Cpoint[n].y,2));
                    distance1[m][n] = tmp1;
                    distance1[n][m] = tmp1;
                }
            }
        }
        //打印距离矩阵
        printf("城市的距离矩阵如下
    ");
        for(int i = 0; i < cities; i++)
        {
            for(int j = 0; j<cities; j++){
                cout << distance1[i][j] << ' ';
            }
            cout << endl;
        }
    }
    //随机产生初试群
    void groupproduce()
    {
        int i,j,t,k,flag;
    
        for(i = 0; i < num; i++)  //初始化
            for(j = 0; j < cities; j++)
                group[i].city[j]=-1;
    
        srand((unsigned)time(NULL));
        for(i = 0; i < num; i++)
        {
            //产生10个不相同的数字
            for(j = 0; j < cities;)
            {
                t = rand() % cities;
                flag = 1;
                for(k = 0; k < j; k++)
                {
                    if(group[i].city[k] == t)
                    {
                        flag = 0;
                        break;
                    }
                }
                if(flag)
                {
                    group[i].city[j] = t;
                    j++;
                }
            }
        }
        //打印种群基因
        printf("初始的种群
    ");
        for(i = 0; i < num; i++)
        {
            for(j = 0; j < cities; j++)
                printf("%4d",group[i].city[j]);
            printf("
    ");
        }
    }
    //评价函数,找出最优染色体
    void pingjia()
    {
        int i,j;
        int n1,n2;
        double sumdistance;
        int biggestsum = 0;
        double biggestp = 0;
        for(i = 0; i < num; i++)
        {
            sumdistance = 0;
            for(j = 1; j < cities; j++)
            {
                n1 = group[i].city[j-1];
                n2 = group[i].city[j];
                sumdistance += distance1[n1][n2];
            }
            sumdistance += distance1[group[i].city[cities-1]][group[i].city[0]];
            group[i].adapt = sumdistance; //每条染色体的路径总和
            //printf("%d",group[i].adapt);
            biggestsum += sumdistance; //种群的总路径
        }
        //计算染色体的幸存能力,路劲越短生存概率越大
        for(i = 0; i < num; i++)
        {
            group[i].p = 1 - (double)group[i].adapt / (double)biggestsum; 
            
            biggestp += group[i].p;
            //printf("%s","  ");
        }
        //printf("%f",biggestp);
        for(i = 0; i < num; i++){
            
            group[i].p = group[i].p / biggestp;
    
        }//在种群中的幸存概率,总和为1
        //求最佳路径
    
        bestsolution = 0;
        for(i = 0;i < num; i++)
            if(group[i].p > group[bestsolution].p)
                bestsolution = i;
        //打印适应度
        /*for(i = 0; i < num; i++)
            cout << "染色体" << i << "的路径之和与生存概率分别为" << group[i].adapt << "和" << group[i].p;
            //printf("染色体%d的路径之和与生存概率分别为%4d  %.4f
    ",i,group[i].adapt,group[i].p);
        cout << "当前种群的最优染色体是" << bestsolution << "号染色体" << endl;
        //printf("当前种群的最优染色体是%d号染色体
    ",bestsolution);*/
    }
    //选择
    void xuanze()
    {
        int i,j,temp;
        double gradient[num];//梯度概率
        double xuanze[num];//选择染色体的随机概率
        int xuan[num];//选择了的染色体
        //初始化梯度概率
        for(i = 0; i < num; i++)
        {
            gradient[i] = 0.0;
            xuanze[i] = 0.0;
        }
        gradient[0] = group[0].p;
    
        for(i = 1; i < num; i++)
            gradient[i] = gradient[i-1]+group[i].p;
    
        srand((unsigned)time(NULL));
        //随机产生染色体的存活概率
        for(i = 0; i < num; i++)
        {
            xuanze[i] = (rand()%100);
            xuanze[i] /= 100;
        }
        //选择能生存的染色体
        for( i = 0; i < num; i++)
        {
            for(j = 0; j < num; j++)
            {
                if(xuanze[i] < gradient[j])
                {
                    xuan[i] = j; //第i个位置存放第j个染色体
                    break;
                }
            }
        }
        //拷贝种群
        for(i = 0; i < num; i++)
        {
            grouptemp[i].adapt = group[i].adapt;
            grouptemp[i].p = group[i].p;
            for(j = 0; j < cities; j++)
            grouptemp[i].city[j] = group[i].city[j];
        }
        //数据更新
        for(i = 0; i < num; i++)
        {
            temp = xuan[i];
            group[i].adapt = grouptemp[temp].adapt;
            group[i].p = grouptemp[temp].p;
            for(j = 0; j < cities; j++)
                group[i].city[j] = grouptemp[temp].city[j];
        }
        //用于测试
        /*
        printf("<------------------------------->
    ");
        for(i=0;i<num;i++)
        {
            for(j=0;j<cities;j++)
            printf("%4d",group[i].city[j]);
            printf("
    ");
            printf("染色体%d的路径之和与生存概率分别为%4d  %.4f
    ",i,group[i].adapt,group[i].p);
        }
        */
    }
    
    //交配,对每个染色体产生交配概率,满足交配率的染色体进行交配  
    void  jiaopei()  
    {  
        int i,j,k,kk;  
        int t;//参与交配的染色体的个数  
        int point1,point2,temp;//交配断点  
        int pointnum;  
        int temp1,temp2;  
        int map1[cities],map2[cities];  
        double jiaopeip[num];//染色体的交配概率  
        int jiaopeiflag[num];//染色体的可交配情况  
        int kkk,flag=0;  
        //初始化  
        for(i = 0; i < num; i++)  
        {  
            jiaopeiflag[i] = 0;  
        }  
        //随机产生交配概率  
        srand((unsigned)time(NULL));  
        for(i = 0; i < num; i++)  
        {  
            jiaopeip[i] = (rand()%100);  
            jiaopeip[i] /= 100;  
        }  
        //确定可以交配的染色体  
        t = 0;  
        for(i = 0; i < num; i++)  
        {  
            if(jiaopeip[i] < pc)  
            {  
                jiaopeiflag[i] = 1;  
                t++;  
            }  
        }  
        t = t/2 * 2;//t必须为偶数,产生t/2个0-9交配断点  
        srand((unsigned)time(NULL));  
        temp1 = 0;     //temp1号染色体和temp2染色体交配  
        for(i = 0; i < t/2; i++)  //如果有5个染色体需要交配,但是实际上t/2代表只有4个染色体会真正的交配,剩下的1个再加上5个不需要交配的染色体直接进入下一代。
        {  
            point1 = rand() % cities;//交配点1  
            point2 = rand() % cities;//交配点2  
            //选出一个需要交配的染色体1  
            for(j = temp1;j < num; j++)  
            {  
                if(jiaopeiflag[j] == 1)  
                {  
                    temp1 = j;  
                    break;  
                }  
            }  
            //选出另一个需要交配的染色体2与1交配  
            for(j = temp1+1; j < num; j++)  
            {  
                if(jiaopeiflag[j] == 1)  
                {  
                    temp2 = j;  
                    break;  
                }  
            }  
            //进行基因交配  
            if(point1 > point2) //保证point1<=point2  
            {  
                temp = point1;  
                point1 = point2;  
                point2 = temp;  
            }  
            //初始化  
            memset(map1,-1,sizeof(map1));  
            memset(map2,-1,sizeof(map2));  
            //断点之间的基因产生映射  
            for(k = point1; k <= point2; k++)  
            {  
                map1[group[temp1].city[k]] = group[temp2].city[k];  
                map2[group[temp2].city[k]] = group[temp1].city[k];  
            }  
            //断点两边的基因互换  
            for(k = 0; k < point1; k++)  
            {  
                temp = group[temp1].city[k];  
                group[temp1].city[k] = group[temp2].city[k];  
                group[temp2].city[k] = temp;  
            }  
            for(k = point2+1; k < cities; k++)  
            {  
                temp = group[temp1].city[k];  
                group[temp1].city[k] = group[temp2].city[k];  
                group[temp2].city[k] = temp;  
            }  
            //printf("处理冲突---------------------
    ");  
            //处理染色体1产生的冲突基因  
            for(k = 0; k < point1; k++)  
            {  
                for(kk = point1; kk <= point2; kk++)  
                {  
                    if(group[temp1].city[k] == group[temp1].city[kk])  
                    {  
                        group[temp1].city[k] = map1[group[temp1].city[k]];  //如果相等则进行映射操作
                        //find  
                        for(kkk = point1;kkk <= point2; kkk++)  
                        {  
                            if(group[temp1].city[k] == group[temp1].city[kkk])  //考虑如果映射一次仍然具有相同的城市,则再进行一次映射操作
                            {  
                                flag = 1;  
                                break;  
                            }  
                        }  
                        if(flag == 1)  //flag不断判断同一染色体中是否还存在相同的城市
                        {  
                            kk = point1 - 1;  
                            flag = 0;  
                        }  
                        else  
                        {  
                            flag = 0;  
                            break;  
                        }  
                    }  
                }  
                  
            }  
            for(k = point2+1; k < cities; k++)  
            {  
                for(kk = point1; kk <= point2; kk++)  
                {  
                    if(group[temp1].city[k] == group[temp1].city[kk])  
                    {  
                        group[temp1].city[k] = map1[group[temp1].city[k]];  
                        //find  
                        for(kkk = point1;kkk <= point2; kkk++)  
                        {  
                            if(group[temp1].city[k] == group[temp1].city[kkk])  
                            {  
                                flag = 1;  
                                break;  
                            }  
                        }  
                        if(flag == 1)  
                        {  
                            kk = point1 - 1;  
                            flag = 0;  
                        }  
                        else  
                        {  
                            flag = 0;  
                            break;  
                        }  
                    }  
                }  
            }  
            //处理2染色体产生的冲突基因  
            for(k = 0;k < point1; k++)  
            {  
                for(kk = point1; kk <= point2; kk++)  
                {  
                    if(group[temp2].city[k] == group[temp2].city[kk])  
                    {  
                        group[temp2].city[k] = map2[group[temp2].city[k]];  
                        //find  
                        for(kkk = point1;kkk <= point2; kkk++)  
                        {  
                            if(group[temp2].city[k] == group[temp2].city[kkk])  
                            {  
                                flag = 1;  
                                break;  
                            }  
                        }  
                        if(flag == 1)  
                        {  
                            kk = point1 - 1;  
                            flag = 0;  
                        }  
                        else  
                        {  
                            flag = 0;  
                            break;  
                        }  
                    }  
                }  
            }  
            for(k = point2+1; k < cities; k++)  
            {  
                for(kk = point1; kk <= point2; kk++)  
                {  
                    if(group[temp2].city[k] == group[temp2].city[kk])  
                    {  
                        group[temp2].city[k] = map2[group[temp2].city[k]];  
                        //find  
                        for(kkk = point1; kkk <= point2; kkk++)  
                        {  
                            if(group[temp2].city[k] == group[temp2].city[kkk])  
                            {  
                                flag = 1;  
                                break;  
                            }  
                        }  
                        if(flag == 1)  
                        {  
                            kk = point1 - 1;  
                            flag = 0;  
                        }  
                        else  
                        {  
                            flag = 0;  
                            break;  
                        }  
                    }  
                }  
            }  
            temp1 = temp2 + 1;  
        }  
    }
    
    
    void bianyi()
    {
        int i,j;
        int t;
        int temp1,temp2,point;
        double bianyip[num]; //染色体的变异概率
        int bianyiflag[num];//染色体的变异情况
        for(i = 0;i < num; i++)//初始化
        bianyiflag[i]=0;
        //随机产生变异概率
        srand((unsigned)time(NULL));
        for(i = 0; i < num; i++)
        {
            bianyip[i] = (rand()%100);
            bianyip[i] /= 100;
        }
        //确定可以变异的染色体
        t=0;
        for(i = 0; i < num; i++)
        {
            if(bianyip[i] < pm)
            {
                bianyiflag[i] = 1;
                t++;
            }
        }
        //变异操作,即交换染色体的两个节点
        srand((unsigned)time(NULL));
        for(i = 0; i < num; i++)
        {
            if(bianyiflag[i] == 1)
            {
                temp1 = rand() % 10;
                temp2 = rand() % 10;
                point = group[i].city[temp1];
                group[i].city[temp1] = group[i].city[temp2];
                group[i].city[temp2] = point;
            }
        }
    }
    int main()
    {
        int i,j,t;
        init();
        groupproduce();
        //初始种群评价
        pingjia();
        t=0;
        while(t++ < MAXX)
        {
             xuanze();
             jiaopei();
             bianyi();
             pingjia();
        }
        //最终种群的评价
        printf("
    输出最终的种群评价
    ");
        for(i = 0; i < num; i++)
        {
            for(j = 0;j < cities; j++)
            {
                printf("%4d",group[i].city[j]);
            }
            cout << "   adapt:" << group[i].adapt << "   p:" << group[i].p << endl;
            //printf("  adapt:%4d, p:%.4f
    ",group[i].adapt,group[i].p);
        }
        printf("最优解为%d号染色体
    ",bestsolution);
        system("pause");
        return 0;
    }

    6.结果显示

    我的城市为10个,坐标为

    41 94
    37 84
    53 67
    25 62
    7 64
    2 99
    68 58
    71 44
    54 62
    83 69

    输出结果如图:

    7.参考

    1.http://blog.csdn.net/mylovestart/article/details/8977005#cpp

    2.http://blog.csdn.net/yeruby/article/details/13161853

  • 相关阅读:
    383. Ransom Note
    598. Range Addition II
    453. Minimum Moves to Equal Array Elements
    492. Construct the Rectangle
    171. Excel Sheet Column Number
    697. Degree of an Array
    665. Nondecreasing Array
    视频网站使用H265编码能提高视频清晰度吗?
    现阶段的语音视频通话SDK需要解决哪些问题?
    企业远程高清会议平台视频会议系统在手机端使用的必备要求有哪些?
  • 原文地址:https://www.cnblogs.com/Key-Ky/p/3490991.html
Copyright © 2011-2022 走看看