• (原创)遗传算法C++实现


    本文没有对遗传算法的原理做过多的解释 基础知识可以参考下面的博客:
    http://blog.csdn.net/u010451580/article/details/51178225
    本实验用到的变异用到下面网址上的方法,当然这个网址也很好的阐释了CVRP的解决方案:
    https://image.hanspub.org/Html/10-2620135_14395.htm
    本文所用交叉算法是部分交叉映射PMX,PMX基础知识请参考这个博客:
    http://blog.csdn.net/u012750702/article/details/54563515
    选择采用的是锦标赛法可参考下面的锦标赛博客的讲解:
    http://www.cnblogs.com/legend1130/archive/2016/03/29/5333087.html

                          遗传算法实验
    要求:
    车辆路径问题(VRP)是运筹学领域一个经典的组合优化问题,可以描述为:一定数量的客户,各自有不同数量的货物需求,配送中心向客户提供货物,由一个车队负责分送货物,组织适当的行车路线,目标是使得客户的需求得到满足,达到总配送路程最短的目的。(Cvrp 带有容量限制的)要求按GA算法思想设计VRPLIB中算例eil51的求解算法,并利用计算机语言实现设计的算法。实验数据网址:http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/vrp/

    本程序可以调节是否可用交叉和变异,及其参数值,以及锦标赛法选取的后代数目可在参数设置区进行调节(默认0.1倍种群大小) ,仅仅将下面的两个数据文件与GA.cpp文件放在一个工程目录下即可运行代码。

    capacity.txt  

    position.txt

    下面是实现的代码(Windows----IDE----DEVC++)

      1 /*
      2     Name: GA算法实现 车辆的CVRP问题 
      3     Copyright: 
      4     Author: GCJ NEW NEU Labotatry 
      5     Date: 12/11/17 20:49
      6     Description: 本文件和附加的参数capacity.txt和data.txt文档放在一个工程下即可,
      7                 然后修改readTxt()函数内部的路径即可运行成功 
      8     
      9 */
     10 
     11 #include <iostream>
     12 #include"time.h"
     13 #include<fstream>             
     14 #include<math.h>                 
     15 #include<stdlib.h>
     16 
     17 /*--------------------------------参数配置区---------------------------------------------------*/ 
     18 
     19 #define     CLIENT_NUM   50                  //客户数量 为50  1个配送中心 
     20 #define    CAPACITY     160                //车的容量为160   
     21 #define     Population_size  50          //种群大小
     22 #define     iterations           50            //迭代次数    
     23 
     24 #define  ISGA_crossover   1            //是否可交叉 1:交叉  0:不交叉 
     25 #define     PC                    0.7           //配置交叉率
     26 
     27 #define  ISmutate         1            //是否可变异 1: 变异  0:不变异 
     28 #define     PM                    0.1             //变异率 
     29 
     30 #define  IsChampionShip   1             //锦标赛参数是否可调节(默认值为0.1倍的种群大小) 1:可调 0:不可调 
     31 
     32 
     33 /*--------------------------------宏配置区---------------------------------------------------*/ 
     34 
     35 #define Min(x,y)      ( ( (x) < (y) ) ?(x):(y)  )
     36 #define Max(x,y)          ( ( (x) > (y) ) ?(x):(y)  )
     37 #define     f(x)  (x -1)                     //用f宏 作为index 因为在找商店的序号跟二维数组之间相差1 所以用f表示两者之间的映射 
     38 
     39 /*---锦标赛参数设置区---*/
     40 #ifdef ChampionShip
     41    double championShip = 0.2;            //自己可随意设置成0-1之间的小数 但是最好不要超过0.5 
     42 #endif
     43 
     44 typedef int ElementType;
     45 using namespace std;
     46 ElementType **Distance;                    //存储商店之间的距离 
     47 ElementType * Capacity;                    //存储车容量 
     48 typedef struct _rand{          
     49     int flag;                     
     50     ElementType num;
     51 }Rand;
     52  
     53 class Chromosome
     54 {
     55     public:
     56         Chromosome();                 
     57         Chromosome(int len );                    //length表示染色体的长度     
     58         virtual~Chromosome();                    //析构函数 
     59         Chromosome(const Chromosome&a);        //自定义拷贝构造函数  
     60         const Chromosome &operator =(const Chromosome & o ) ;
     61         
     62         void initialize() ;                       //初始化染色体 调用newRandom函数 产生1- length 的随机数 
     63         int  newRandom(int low,int high );  //随机产生 0- num 个不重复的数字   
     64         void evaluate();
     65     #if ISmutate
     66         void mutate();                                //采用逆转变异算子 
     67     #endif    
     68         //查看染色体内容的调试函数 
     69         void toprint(){            
     70          int i;
     71  //            cout<<"染色体内容"<<endl;
     72              for( i =0 ; i<CLIENT_NUM ; i++){
     73                    cout<<codespace[i]<<" ";
     74            }  
     75         }
     76         void printpath();                                            //打印最后的车辆安排路径 
     77         ElementType getFitness(){return this->fitness;}    //返回染色体适应值 
     78         int getLength(){ return length; }                    //获取染色体长度     
     79         int getCar(){return carNum; }                            //获取车的数量 
     80         int *codespace = NULL;                                    //编码空间 代表2-51商店的标号 
     81         
     82     private:
     83         int length;                                                    //染色体的长度 
     84         ElementType fitness;                                      //方便之后的数据的扩展 
     85         int carNum;                                                    //车数量 
     86 };
     87 typedef struct _Cross{
     88     ElementType one;
     89     ElementType two;
     90     int flag1 ;                    //标记找到的one 
     91     int flag2 ;                    //标记找到的two 
     92     _Cross():flag1(0),flag2(0){}  
     93 }Cross;                            //部分交叉映射需要用到的结构  记录映射关系 
     94 class GA
     95 {
     96     public:
     97         GA(){};
     98         GA(int popnum,int max);    //popnum 种群大小,max表示迭代次数 
     99         virtual~GA();
    100         GA(const GA&o);                                  //自定义拷贝构造函数  把指针的情况考虑进去了 
    101         const GA &operator =(const GA & o );      //自定义赋值函数  
    102         
    103         //成员函数 
    104         void initializePop();                          //初始化种群 
    105         void GArun();                                      //运行GA算法 
    106         void Insert_Sort (Chromosome * list,int len);        //种群中按照适应值从小到大排序 
    107         Chromosome &slectChromosome(Chromosome* pop);        //选择好的染色体用锦标赛法 返回引用的原因是 不需要拷贝构造 
    108 
    109     #if ISGA_crossover
    110         void crossoverChromosome( Chromosome &one,Chromosome &two);//染色体交叉 然后修补不符合编码规则的个体 
    111     #endif    
    112 
    113         int search(Cross *a,int num,ElementType b,ElementType *c,int opt);       //在Cross型的数组中寻找b  然后寻找后的结果存到c中 
    114         
    115         
    116         void printBestChromosome(){            
    117               
    118               cout<<endl<<"Best适应值: "<<best_chr.getFitness();
    119               cout<<endl<<"Best车数量: "<<best_chr.getCar()<<endl<<"Best染色体序列:
     "<<endl;
    120               
    121               best_chr.toprint();    
    122       }
    123         void printDebug(int i){    cout<<"正常输出"<<i<<endl;} //测试代码bug 
    124         void BubbleSort(int *list,int len)         //用来最后检测当前的染色体是不是顺序排列的 
    125         {
    126             int i,j,temp;
    127             for(i=0;i<len;i++)
    128                 for(j=0;j<len-i-1;j++)
    129                 {
    130                     if(list[j]>list[j+1])
    131                     {
    132                         temp=list[j];
    133                         list[j]=list[j+1];
    134                         list[j+1]=temp;
    135                     }
    136                 }
    137         }
    138         //成员变量 
    139         int length;                    //表示染色体的长度 此时没有用到  
    140         int popsize;                //种群的规模 
    141         int max_gen;                //种群的迭代次数 
    142         int elite_num;    
    143         Chromosome *old_pop;        //老的种群 
    144         Chromosome *new_pop;        //新产生的种群 
    145         Chromosome *pool_pop;    //种群池 
    146         Chromosome good_chr;        //好的染色体即 个体 
    147         Chromosome best_chr;        //最好的个体 
    148 };
    149 
    150 
    151 
    152 /*-------------------------------------------Chromosome(染色体)成员函数实现区-------------------------------------------------*/
    153 
    154 
    155 
    156 Chromosome::Chromosome():fitness(0),length(CLIENT_NUM),carNum(0){
    157     int i;
    158      codespace = new int[length ];        
    159     for(i = 0;i< length ;i++ ){
    160         codespace[i] = 0;                    //默认染色体的值为0 
    161     }
    162 }                 
    163 /*
    164     Description:  申请空间并初始化染色体  适应值默认为0 可选择染色体的长度 
    165 */
    166 Chromosome::Chromosome( int len):length(len),fitness(0),carNum(0) {
    167     int i;
    168     codespace = new int[len ];        
    169     for(i = 0;i< length ;i++ ){
    170         codespace[i] = 0;                  //默认染色体的值为0 
    171     }
    172 }
    173 /*
    174     Description: 拷贝构造函数 
    175 */
    176 Chromosome::Chromosome(const Chromosome&a){        //自定义拷贝构造函数  把指针的情况考虑进去了 
    177    int i; 
    178     codespace = new int[a.length];    
    179     for(i = 0;i< a.length ;i++ ){
    180         codespace[i] = a.codespace[i];             
    181     } 
    182     fitness = a.fitness;
    183     length = a.length;
    184     carNum = a.carNum;
    185 } 
    186 /*
    187     Description: 赋值构造函数 
    188 */
    189 const Chromosome& Chromosome::operator =(const Chromosome & o ) {    
    190     int i;
    191     for(i = 0; i< length;i++)                   //仅仅赋值 
    192           this->codespace[i] =o.codespace[i];
    193     this->fitness = o.fitness;
    194     this->carNum = o.carNum;
    195     return *this;
    196 } 
    197 /*
    198     Description: 析构函数 
    199 */
    200  Chromosome::~Chromosome(){
    201     delete codespace;                            //释放申请的资源 
    202 }
    203 /*
    204     Description: 随机产生 0- num 个不重复的数字 上下限   返回产生的序列 high 表示产生的最大数字 low最低数字 
    205 */
    206 int Chromosome::newRandom(int low,int high ) {
    207     Rand newrand[high - low +1];     //定义排列数字的那么大的数组 
    208     int record[high - low +1];     //记录产生的随机数 
    209     int i,j=0, rand1;
    210     int index;        
    211     int count = high- low +1;        //low - high 间的数字 目前剩下没有选取到的 数量 
    212     for( i =0;i< high-low +1;i++){
    213         newrand[i].num = low + i;  //先产生low - high顺序排列的数组 之后 用随机数的方式产生一个任意随机的排列 
    214         newrand[i].flag = 0;            //表示这个元素没有被随机的取到 
    215     }
    216     //随机产生0- num不重复的核心 
    217    while( (count !=0) && ( rand1 = rand()%(count)+1 )){
    218            count --;                   //剩余数量-- 
    219            for( i  = 0,index = 0; i < high-low +1 ; i++){  
    220                
    221             //如果被标记了 就继续寻找 
    222             if( newrand[i].flag )
    223             continue;
    224                index ++;                //表示 遍历有效元素的个数 
    225                if( index  == rand1  ){         
    226                    record[j] = newrand[i].num;
    227                    codespace[j] = newrand[i].num;
    228                    newrand[i].flag = 1;  //表示标记过了
    229                 j++; 
    230             }    
    231         }/*end for*/
    232     }/* end while*/
    233 }
    234 /*
    235     Description:  染色体初始化 
    236 */
    237 void Chromosome:: initialize() {
    238         newRandom(2,length+1);        //产生1-length 随机数 1-50 
    239 }    
    240 /*    
    241     Description: 对染色体的适值更新 
    242 */
    243 void Chromosome::evaluate() {
    244       int i ,carCount = 1,sumCapacity= 0;
    245       fitness = Distance[ 0 ][f(codespace[0]) ];
    246       for( i =0; i<length; i++ ){
    247                if(sumCapacity <= CAPACITY ){
    248                     sumCapacity += Capacity[ f(codespace[i]) ];  //2- 51 对应的 商店存储量 
    249                  
    250              }
    251              else{
    252                  i--;
    253                  sumCapacity = 0;
    254                  carCount++;
    255                  fitness += Distance[ 0 ][ f(codespace[i]) ];
    256              }    
    257       }
    258       //出来后 最后的车肯定不满  所以需要加上最后一个商店到0的距离 
    259         fitness += Distance[0][f(codespace[i-1])];
    260       for( i = 0; i< length -1 ; i ++)
    261                fitness += Distance[ Min( f(codespace[i]),f(codespace[i+1]) )][ Max( f(codespace[i]),f(codespace[i+1]) )  ];
    262       carNum = carCount;     
    263 }
    264 /*    
    265     Description: 染色体变异 50个 即产生0-49即可选择哪里变异 
    266 */
    267 #if ISmutate
    268 void Chromosome::mutate(){
    269     int rand1,rand2;
    270     double rand3;
    271     int i,j;
    272     ElementType * temp;
    273     int temp2,temp3;
    274    rand3 = (rand()%10)/9.0;        //产生0-1小数 
    275    if(rand3 < PM){
    276       //产生变异
    277        rand1 = (rand()%length);
    278       rand2 = (rand()%length); 
    279      while( (rand1 == rand2)) {
    280          rand2 = (rand()%length);
    281      } 
    282     temp3 = Max(rand1,rand2);
    283      temp2 = Min(rand1,rand2);
    284     temp = new int[temp3 - temp2+1];
    285   
    286     for( j=temp3-temp2 ,i =temp2; i<=temp3; j--,i++ ){
    287         temp[j] = codespace[i];
    288        }
    289        //交换
    290      for(j = 0,i =temp2;i<=temp3;j++,i++){
    291          codespace[i] = temp[j];
    292      } 
    293       delete temp;
    294    }/*end if*/    
    295 }
    296 #endif
    297 /*    
    298     Description: 打印路径
    299 */
    300 void Chromosome::printpath(){
    301     int i ,carCount = 1,sumCapacity= 0,j=0,k=0,l=0;
    302       fitness = Distance[ 0 ][f(codespace[0]) ];
    303       printf("
    第1辆车:
    ");
    304       for( j=0,i =0; i<length; i++ ){
    305           
    306                if(sumCapacity <= CAPACITY ){
    307                     sumCapacity += Capacity[ f(codespace[i]) ];  //2- 51 对应的 商店存储量 
    308                   cout<<codespace[i]<<" ";
    309              }
    310              else{
    311                  i--; 
    312                 printf("
    
    第%d辆车:
     ",carCount+1);
    313                  j++;
    314                  sumCapacity = 0;
    315                  carCount++;
    316                  fitness += Distance[ 0 ][ f(codespace[i]) ];
    317              }    
    318       }
    319       //出来后 最后的车肯定不满  所以需要加上最后一个商店到0的距离 
    320         fitness += Distance[0][f(codespace[i-1])];
    321       for( i = 0; i< length -1 ; i ++)
    322                fitness += Distance[ Min( f(codespace[i]),f(codespace[i+1]) )][ Max( f(codespace[i]),f(codespace[i+1]) )  ];
    323       carNum = carCount;     
    324       
    325 }   
    326 
    327 
    328 
    329 /*-------------------------------------------GA成员函数实现区----------------------------------------------------------*/
    330 
    331 
    332 
    333 GA::GA(int popnum,int max):popsize(popnum),length(CLIENT_NUM),max_gen(max),elite_num(0),old_pop(NULL),new_pop(NULL),pool_pop(NULL){
    334     old_pop = new Chromosome[popsize];     
    335     new_pop = new Chromosome[popsize];
    336     pool_pop = new Chromosome[popsize+elite_num] ;
    337 }
    338 /*
    339     Description: 拷贝构造函数  
    340 */
    341 GA::GA(const GA& o){
    342     int i;
    343     if(old_pop == NULL){
    344             old_pop = new Chromosome[popsize];
    345             new_pop = new Chromosome[popsize];
    346             pool_pop = new Chromosome[popsize+elite_num] ;
    347     }
    348     for( i = 0 ;i<o.popsize;i++){
    349         old_pop[i] = o.old_pop[i];
    350         new_pop[i] = o.new_pop[i];
    351         pool_pop[i] = o.pool_pop[i];
    352     }
    353     for( ;i<o.popsize+o.elite_num;i++){
    354         pool_pop[i] = o.pool_pop[i];
    355     }
    356     length = o.length;
    357     popsize = o.popsize;
    358     max_gen = o.max_gen;
    359     elite_num = o.elite_num;
    360     Chromosome good_chr = o.good_chr;
    361     Chromosome best_chr = o.best_chr;
    362 }
    363 /*
    364     Description: 赋值函数  
    365 */
    366 const GA& GA::operator =(const GA&o){
    367    int i;
    368     for( i = 0 ;i<o.popsize;i++){
    369         old_pop[i] = o.old_pop[i];
    370         new_pop[i] = o.new_pop[i];
    371         pool_pop[i] = o.pool_pop[i];
    372     }
    373     for( ;i<o.popsize+o.elite_num;i++){
    374         pool_pop[i] = o.pool_pop[i];
    375     }
    376     length = o.length;
    377     popsize = o.popsize;
    378     max_gen = o.max_gen;
    379     elite_num = o.elite_num;
    380     Chromosome good_chr = o.good_chr;
    381     Chromosome best_chr = o.best_chr;
    382 }
    383 /*
    384     Description:  析构函数
    385 */
    386 GA::~GA(){
    387    delete[]old_pop;
    388    delete[]new_pop;
    389    delete[]pool_pop;
    390 }
    391 /*
    392     Description: 初始化种群 
    393 */
    394 void GA::initializePop(){
    395     int i;
    396     for( i = 0;i<popsize;i++){
    397         old_pop[i].initialize();
    398         old_pop[i].evaluate();
    399     }
    400 }
    401 /*
    402     Description: 种群中按照适应值从小到大排序  
    403 */
    404 void GA::Insert_Sort (Chromosome * pop,int num)
    405 {
    406     //进行N-1轮插入过程
    407     int i,k;
    408     for(i=1; i<num; i++){
    409      //首先找到元素a[i]需要插入的位置
    410      
    411          int j=0;
    412          while( (pop[j].getFitness()< pop[i].getFitness() )  && (j <i ) )
    413                  j++;
    414                  
    415          //将元素插入到正确的位置
    416          if(i != j){  //如果i==j,说明a[i]刚好在正确的位置
    417              Chromosome temp = pop[i];
    418              for(k = i; k > j; k--){
    419                  pop[k] = pop[k-1];
    420              }
    421              pop[j] = temp;
    422          }
    423     }
    424 }    
    425 /*
    426     Description: 选择好的染色体用锦标赛法 默认以popsize *0.1 (可配置成可调) 百分之10的个体里 进行选择最好的个体  
    427 */ //在选择之前 因为已经排好序了 号码越小,代表个体越好 
    428 Chromosome& GA::slectChromosome(Chromosome* pop){
    429     int i;
    430     int rand1,rand2;
    431     ElementType small  = popsize-1; 
    432 #if ISChampionShip
    433     int num = popsize *championShip;
    434 #else
    435    int num = popsize * 0.1;
    436 #endif
    437 
    438     for( i =0 ; i< num;i++){
    439         rand1 = rand()%popsize;
    440         if( rand1 < small)
    441              small = rand1;
    442     }
    443     return pop[small];
    444 }
    445 /*
    446     Description: 在Cross型的数组中寻找b  然后寻找后的结果存到c中   为交叉做准备 
    447 */
    448 int GA::search( Cross *a,int num,ElementType b,ElementType *c,int opt){
    449     int i;
    450     if(opt == 0)//从1里面找 
    451     {
    452         for( i = 0 ; i < num;i++){
    453 
    454             if( (a[i].flag1 == 0)&&( b == a[i].one ) ){
    455                 *c = i;//记录找到的位置 
    456                 a[i].flag1 =1;
    457                 return 1;
    458            } 
    459         }
    460     
    461     }
    462     else if(opt == 1){
    463         //从2里面找 
    464         for( i = 0 ; i < num;i++){
    465             if( (a[i].flag2 == 0)&&( b == a[i].two ) ){
    466                 //找到了就做标记
    467                 a[i].flag2 = 1; 
    468                 *c = i;//记录找到的位置 
    469                 return 1;
    470            } 
    471       }
    472     }
    473     return 0;
    474 }
    475 /*
    476     Description: 交叉  然后修补不符合编码规则的个体 采用部分映射交叉 如果两代的个体相同 那么就必须产生另一种算法 
    477 */
    478 #if  ISGA_crossover
    479 void GA::crossoverChromosome( Chromosome &one,Chromosome &two){
    480    int rand1,rand2;                  //rand1 小   rand2 大 
    481     int i,j,k;    
    482     Cross * temp;
    483     Cross * table ;                  //保存映射的表
    484     int count= 0;                     //记录存在几个映射关系 
    485    int temp2,temp3;
    486    int emp2,emp3;
    487    int lastcount = 0;
    488    
    489    int opt = 1;    //开始选择2 
    490       //产生随机数选择交叉点 
    491        rand1 = (rand()%length);
    492       rand2 = (rand()%length); 
    493      while( rand1 == rand2) {
    494           rand2 = (rand()%length);
    495      } 
    496      
    497     temp2 = Min(rand1,rand2);
    498     temp3 = Max(rand1,rand2);
    499     emp2 = temp2;//新加变量 
    500     emp3 = temp3;
    501     temp = new Cross[temp3 - temp2+1];         //记录部分映射的位置元素 进行映射关系表的建立  
    502     table = new Cross[temp3 - temp2 +1];        //记录映射表 因为映射关系表 <= 此时申请的空间 
    503       
    504     for( j=0 ,i =temp2; i<=temp3; j++,i++ ){
    505         temp[j].one = one.codespace[i];
    506         temp[j].two = two.codespace[i];
    507        }
    508        //交换
    509      for(j = 0,i =temp2;i<=temp3;j++,i++){
    510          one.codespace[i] = temp[j].two;
    511          two.codespace[i] = temp[j].one;
    512      } 
    513     //建立映射表 在从剩下的表格中从新用这种方法再次寻找 
    514 again:for( k=0,j=0,i = 0; i< temp3-temp2+1;i++ ){
    515          int position;
    516          if( (temp[i].flag2 != 0) )                 //如果被找到了 那么就不找了 从新i++去找
    517         {
    518             continue;
    519        } 
    520               //找到了才做标记 
    521                //先从one 里找 
    522                k=0;
    523                opt = 1;
    524                if( search(temp,temp3-temp2+1,temp[i].one,&position,opt) ){
    525                    //找到了 
    526                    //做标记 
    527                
    528                    temp[i].flag1 = 1;
    529                    temp[i].flag2 = 1;
    530                     
    531                     temp[position].flag1 = 1; 
    532                       table[j].two = temp[i].two;
    533                     k = position;
    534                     
    535                     while( ( temp[i].two != temp[position].one ) && ( search(temp,temp3-temp2+1,temp[k].one,&position,opt) )  ){
    536                             //不相等 并且能够找到下一个 就继续找
    537                               k = position;
    538                             temp[position].flag1 = 1;        
    539                     }
    540                     
    541                     //退出循环有两种情况 1.相等 2 没有找到
    542                     if( temp[i].two == temp[position].one ) 
    543                          continue;
    544                    else{
    545                         //没有找到
    546                         table[j].one = temp[k].one; 
    547                         temp[k].flag1  =1;
    548                         count++;//映射数量
    549                         j++; 
    550                      }            
    551                 }else{//没有找到
    552                 
    553                    opt = 0;//返过来从1中找 
    554                     if( search(temp,temp3-temp2+1,temp[i].two,&position,opt) ){
    555                            //找到了 
    556                            //做标记 
    557                            temp[i].flag1 = 1;
    558                            temp[i].flag2 = 1;
    559                             
    560                             temp[position].flag2 = 1; 
    561                             table[j].one = temp[i].one;
    562                             k = position;
    563                             while( ( temp[i].one != temp[position].two ) && ( search(temp,temp3-temp2+1,temp[k].two,&position,opt) )  ){
    564                                     //不相等 并且能够找到下一个 就继续找 
    565                                       k = position;
    566                                     temp[position].flag2 = 1;
    567                             }
    568                             //退出循环有两种情况 1.相等 2 没有找到
    569                             if( temp[i].one == temp[position].two ) 
    570                                  continue;
    571                            else{
    572                                 //没有找到
    573                                 table[j].two = temp[k].two; 
    574                                 temp[k].flag2  =1;
    575                                 count++;//映射数量
    576                                 j++; 
    577                              }
    578                     }else{  //最后都没有找到 说明两个映射 没有循环
    579                          temp[i].flag1 = 1;
    580                          temp[i].flag2 = 1; 
    581                          table[j].two = temp[i].two;
    582                          table[j].one = temp[i].one;
    583                          j++;
    584                          count++;
    585                     }/*iner if else */             
    586                 } /*outer if else */
    587       }
    588    if(count >= 1)//需要第二次检查
    589     {//说明count>0 
    590            if(lastcount != count)//两次的值不相等就再次检查 直到两次的值都是固定不变的 
    591            {
    592                int flag = 0;
    593                lastcount =count;//记录上次的值 
    594                for( i =0 ; i< count;i++ )    //再次检查映射表 
    595                 {
    596                     temp[i].one = table[i].one;
    597                     temp[i].two = table[i].two; 
    598                     temp[i].flag1 = 0;        //标记清零 
    599                     temp[i].flag2 = 0; 
    600                     temp2 = 0 ;
    601                     temp3 = count-1; 
    602                     flag = 1;
    603                     
    604                 } 
    605                 if(flag ==1){
    606                     count = 0;
    607                     flag = 0;
    608                     goto again;
    609                 }
    610           } 
    611     }   
    612      for( i =0;i< emp2;i++){
    613          //修复前一段
    614          for(j=0;j<count;j++){
    615              if( one.codespace[i] == table[j].two ){
    616                   one.codespace[i] = table[j].one;
    617                  break;
    618              }
    619          } 
    620      }
    621      for( i =emp3+1;i< length;i++){
    622          for(j=0;j<count;j++){
    623              if(  one.codespace[i] == table[j].two ){
    624                  one.codespace[i] = table[j].one;
    625                  break;
    626              }
    627          } 
    628      }
    629     for( i =0;i< emp2;i++){
    630          //修复前一段
    631          for(j=0;j<count;j++){
    632              if( two.codespace[i] == table[j].one ){
    633                   two.codespace[i] = table[j].two;
    634                  break;
    635              }
    636          } 
    637      }
    638      for( i =emp3+1;i< length;i++){
    639          for(j=0;j<count;j++){
    640              if(  two.codespace[i] == table[j].one ){
    641                  two.codespace[i] = table[j].two;
    642                  break;
    643              }
    644          } 
    645      }
    646       
    647      delete temp;
    648      delete table;
    649 }
    650 #endif
    651  
    652 /*
    653     Description: 运行算法 
    654 */
    655 void GA::GArun(){   
    656       int i,gen;
    657       double rand1;
    658 
    659       //初始化种群 
    660       initializePop();
    661 
    662       //排序 按适应值从小到大排序
    663      Insert_Sort(old_pop,popsize);
    664    
    665       //保存好的个体
    666       good_chr = old_pop[0];
    667       best_chr = old_pop[0];
    668  
    669       //迭代  选择 交叉 变异
    670       for( gen =0; gen < max_gen;gen++){
    671                             
    672            //选择好的个体进入new_pop  
    673            for(i = 0; i< popsize;i++){
    674                //选择好的染色体的 函数返回值用值返回 这些个体会有相同的部分所以在交叉的过程中要考虑 
    675                new_pop[i] = slectChromosome(old_pop);
    676             }
    677             
    678           #if ISGA_crossover 
    679             //交叉
    680             for( i = 0;i<popsize/2;i++){
    681                 rand1 = (rand()%10)/9.0;
    682                 if( rand1 < PC ) {
    683                     crossoverChromosome( new_pop[2*i],new_pop[2*i+1] );//前后两个交叉 
    684                  }
    685             }
    686         #endif
    687         
    688         #if ISmutate            
    689             //对每个new_pop 中的个体 进行变异
    690             for( i =0 ;i< popsize ;i++){
    691                 new_pop[i].mutate();
    692             }
    693        #endif
    694         
    695             //种群中的单个染色体进行更新适应值
    696             for( i = 0 ; i< popsize ; i++){
    697                 new_pop[i].evaluate();
    698             }
    699     
    700             //将new_pop中的染色体 放到pool中,然后在从old_pop中选择elite_num个杰出的染色体 放到pool_pop中 
    701             for(i = 0; i <popsize;i++){
    702                 pool_pop[i] = new_pop[i];
    703             }
    704             for(i  = 0 ; i< elite_num; i++){
    705                 pool_pop[popsize +i] = old_pop[i];
    706             }
    707 
    708             //在按照适应值从小到大进行排序pool_pop
    709             Insert_Sort(pool_pop,popsize+elite_num);
    710             
    711             //old_pop = pool_pop中的前popsize个染色体
    712             for(i = 0;i< popsize;i++){
    713                     old_pop[i] = pool_pop[i];
    714             }
    715             
    716             //从old_pop中选择好的个体进行保存good_chr best_chr 
    717               good_chr = old_pop[0];
    718               if( good_chr.getFitness() < best_chr.getFitness())
    719                    best_chr = good_chr;//调用赋值函数 
    720       }/*for end*/
    721       //输出最好的染色体 
    722       
    723       best_chr.printpath();
    724       cout<<endl;
    725      printBestChromosome();
    726 }
    727 void readTxt()
    728 {
    729     int i,j;
    730     double temp1;
    731     int ShopNum = CLIENT_NUM +1;
    732     ElementType *x,*y,temp;                              //读入位置坐标 之后计算商店之间的距离 
    733    Distance = new int*[ShopNum];    
    734     Capacity = new int [ShopNum];     
    735 
    736    x = new int[ShopNum];
    737    y = new int[ShopNum];
    738     fstream  file("position.txt", ios::in);
    739    fstream  file2("capacity.txt",ios::in);
    740     if(!file.is_open() || !file2.is_open() ){
    741         cout << "Can not open the data file " << "遗传算法\position.txt or capacity.txt" << endl;
    742         exit(0);
    743    }
    744     else
    745          cout <<"The file has been opened without problems "<<"遗传算法\position.txt and capacity.txt"<<endl;    
    746     for( i = 0;i< ShopNum ; i++){
    747         Distance[i] = new int[ShopNum ];        //构造51 x 51 的矩阵  
    748     }   
    749     
    750     //将数据存入到 一维数组中 之 
    751     for( i =0; i< ShopNum; i++){
    752         file>>temp>>x[i]>>y[i];                         //存储距离 
    753         file2>>temp>>Capacity[i];                       //存储商店需求量 
    754     }
    755     for(i = 0;i< ShopNum;i++ ){                     //51x51大小的矩阵 存储距离 
    756         Distance[i][i] = 0;                             //对角线上的元素为0
    757         for(j = i+1;j< ShopNum;j++ ){
    758             temp1 = sqrt(pow(x[i] - x[j ], 2) + pow(y[i] - y[j ], 2));
    759             temp1 = (int )(temp1 + 0.5);
    760             Distance[i][j]  = temp1;
    761            Distance[j][i]  = temp1;
    762         } 
    763     }     
    764     file.close();
    765     file2.close();
    766     delete  x;    //释放空间 
    767     delete  y;
    768 }
    769 
    770 /*
    771     Description: 释放Distance 和Capacity指向的空间 
    772 */
    773 void freeMem(){
    774     int ShopNum = CLIENT_NUM+1;
    775     int i;
    776     for( i = 0;i< ShopNum ; i++){
    777         delete Distance [i];         
    778     }           
    779     delete Distance ;
    780     delete Capacity;
    781 }
    782 /*
    783     Description: main
    784 */
    785 int main(int argc, char** argv) {
    786     int i,b=0;
    787     int count=0;
    788     clock_t start, finish;
    789     double  duration;
    790 
    791     srand(unsigned(time(0)));                //置一个随机数种子 为了以后产生随机数 
    792     readTxt();                                    //从文件中读取 算法需要的数据  
    793     GA d(Population_size,iterations);   //用两个宏 配置种群和迭代次数 
    794     start = clock();
    795 
    796     //GA算法 
    797     d.GArun();
    798     
    799     //释放存储商店和车容量所占资源 
    800     freeMem();                                     
    801     finish = clock();
    802     duration = (double)(finish - start) / CLOCKS_PER_SEC;
    803     printf("
    
               GA算法运行时间:%.4f秒       
    ",duration);
    804     printf("
               迭代次数:%d       
    ",iterations);
    805     printf("
               种群大小:%d       
    ",Population_size);
    806                                     
    807     return 0;
    808     
    809 }
    View Code

    下面是试验图片:

    如果读者想要数据,可以与我联系,或者直接到下面网址下载完整工程

    http://download.csdn.net/my

    欢迎大家关注我的微信公众号「佛系师兄」,里面会更新一些相关的技术文章。

    比如

    反复研究好几遍,我才发现关于 CMake 变量还可以这样理解!

    更多好的文章会优先在里面不定期分享!打开微信客户端,扫描下方二维码即可关注!

  • 相关阅读:
    Python中return self的用法
    多分类问题的交叉熵计算
    Python爬虫之足球小将动漫(图片)下载
    Sklearn中二分类问题的交叉熵计算
    TensorFlow.js入门(一)一维向量的学习
    MySql 流程控制经典案列讲解
    MySql 流程控制
    MySql 函数
    MySql 存储过程
    MySql 视图
  • 原文地址:https://www.cnblogs.com/newneul/p/7823219.html
Copyright © 2020-2023  润新知