码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2017-11-12 23:03:31      阅读:297      评论:0      收藏:0      [点我收藏+]

标签:程序   delete   遍历   默认   lis   可变   方法   mat   bubble   

本文没有对遗传算法的原理做过多的解释 基础知识可以参考下面的博客:
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

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

标签:程序   delete   遍历   默认   lis   可变   方法   mat   bubble   

原文地址:http://www.cnblogs.com/newneul/p/7823219.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!