本文沒有對遺傳算法的原理做過多的解釋 基礎知識可以參考下面的博客:
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染色體序列:\n "<<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("\n第1輛車:\n"); 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("\n\n第%d輛車:\n ",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("\n\n GA算法運行時間:%.4f秒 \n",duration); 804 printf("\n 迭代次數:%d \n",iterations); 805 printf("\n 種群大小:%d \n",Population_size); 806 807 return 0; 808 809 }
下面是試驗圖片:
如果讀者想要數據,可以與我聯系,或者直接到下面網址下載完整工程
http://download.csdn.net/my
歡迎大家關注我的微信公眾號「佛系師兄」,里面會更新一些相關的技術文章。
比如
「反復研究好幾遍,我才發現關於 CMake 變量還可以這樣理解!」
更多好的文章會優先在里面不定期分享!打開微信客戶端,掃描下方二維碼即可關注!