(原創)遺傳算法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染色體序列:\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 }
View Code

下面是試驗圖片:

如果讀者想要數據,可以與我聯系,或者直接到下面網址下載完整工程

http://download.csdn.net/my

 

歡迎大家關注我的微信公眾號「佛系師兄」,里面會更新一些相關的技術文章。

比如

反復研究好幾遍,我才發現關於 CMake 變量還可以這樣理解!

更多好的文章會優先在里面不定期分享!打開微信客戶端,掃描下方二維碼即可關注!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM