本文没有对遗传算法的原理做过多的解释 基础知识可以参考下面的博客:
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 }
下面是试验图片:
如果读者想要数据,可以与我联系,或者直接到下面网址下载完整工程
http://download.csdn.net/my
欢迎大家关注我的微信公众号「佛系师兄」,里面会更新一些相关的技术文章。
比如
「反复研究好几遍,我才发现关于 CMake 变量还可以这样理解!」
更多好的文章会优先在里面不定期分享!打开微信客户端,扫描下方二维码即可关注!