| 
 | 
	
    
 
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册  
 
x
 
 本帖最后由 pulbieup 于 2020-9-24 14:04 编辑 9 g% Z/ Z$ g" X# Z 
 
( k# i  i' l5 w在看C++实现之前,请先看一下NSGA-II算法概述:NSGA-II多目标遗传算法概述* J; C2 Q6 L( I 
 
. N  r/ R) \  \5 @3 U& ^- X* F 
% `# P! L6 N* TNSGA-Ⅱ就是在第一代非支配排序遗传算法的基础上改进而来,其改进主要是针对如上所述的三个方面: 
5 A, ]* T1 R  K  D+ }1 n: ]①提出了快速非支配排序算法,一方面降低了计算的复杂度,另一方面它将父代种群跟子代种群进行合并,使得下一代的种群从双倍的空间中进行选取,从而保留了最为优秀的所有个体; 
( ?- `/ f5 w- b* v- y4 w5 o②引进精英策略,保证某些优良的种群个体在进化过程中不会被丢弃,从而提高了优化结果的精度; 
' B+ [0 E  O; d( u. n$ d9 h. @③采用拥挤度和拥挤度比较算子,不但克服了NSGA中需要人为指定共享参数的缺陷,而且将其作为种群中个体间的比较标准,使得准Pareto域中的个体能均匀地扩展到整个Pareto域,保证了种群的多样性。% s. Z2 C# q  l5 M 
# e( P  `! P3 Z/ C0 _ 
头文件: 
  Q% E+ m( l' ?6 z8 @# C* I. v8 S! h8 E5 z3 e% S: v6 T/ S( E) F 
- #include<stdio.h>
 - #include<stdlib.h>
 - #include<Windows.h>
 - #include<math.h>
 - #include<time.h>
 - #include<iostream>
 - #define Dimension 2//基因维数,在这里即ZDT1问题xi的i的最大值
 - #define popsize 100//种群大小
 - #define generation 500 //繁衍代数
 - #define URAND (rand()/(RAND_MAX+1.0))//产生随机数
 - int temp1[popsize];//临时数组
 - int mark[popsize];//标记数组
 - //以上两个数组用于产生新的子代
 - using namespace std;8 ^5 Y! h3 g! }& ^! p* J5 s5 L
 
 
  
) X# z! F. ]5 `/ ?) o* b 
  {' G; K/ c: Y, J7 B. m2 x个体的类声明: 
8 J6 T5 S+ n2 R; U 
6 s- N, s+ A) d$ v' O. v5 d) l3 H- class individual
 - {
 - public:
 -     double value[Dimension];//xi的值
 -     int sp[2*popsize];
 -     //被支配个体集合SP。该量是可行解空间中所有被个体p支配的个体组成的集合。
 -     int np;
 -     //支配个数np。该量是在可行解空间中可以支配个体p的所以个体的数量。
 -     int is_dominated;//集合sp的个数
 -     void init();//初始化个体
 -     int rank;//优先级,Pareto级别为当前最高级
 -     double crowding_distance;//拥挤距离
 -     double fvalue[2];//ZDT1问题目标函数的值
 -     void f_count();//计算fvalue的值
 - };
 
% A2 ?# R8 k: c7 t; B$ S) h 
  
, X! U( B& ~3 q! }; z! G- @* W6 r8 H2 I2 f3 u3 @ 
群体的类声明:4 F) m8 B6 `& R. ~/ Y- ?, K* O% ^ 
. H8 K0 C8 x8 z9 Z3 ] 
- class population
 - {
 - public:
 -     population();//类初始化
 -     individual P[popsize];
 -     individual Q[popsize];
 -     individual R[2*popsize];
 -     void set_p_q();
 -     //随机产生一个初始父代P,在此基础上采用二元锦标赛选择、
 -     //交叉和变异操作产生子代Q。P和Q群体规模均为popsize
 -     //将Pt和Qt并入到Rt中(初始时t=0),对Rt进行快速非支配解排序,
 -     //构造其所有不同等级的非支配解集F1、F2........
 -     int Rnum;
 -     int Pnum;
 -     int Qnum;
 -     //P,Q,R中元素的个数
 -     void make_new_pop();//产生新的子代
 -     void fast_nondominated_sort();//快速非支配排序
 -     void calu_crowding_distance(int i);//拥挤距离计算
 -     void f_sort(int i);//对拥挤距离降序排列
 -     void maincal();//主要操作
 -     int choice(int a,int b);
 -     //两个个体属于不同等级的非支配解集,优先考虑等级序号较小的
 -     //若两个个体属于同一等级的非支配解集,优先考虑拥挤距离较大的
 -     int len[2*popsize];//各个变异交叉后的群体Fi的长度的集合
 -     int len_f;//整个群体rank值
 - };) x/ {; J* i) B4 [$ t
 
 
  
9 E5 @- n6 E; T" x3 e: D& I! E4 _3 v 
全局变量及部分函数声明: 
2 w3 \8 G7 T- m2 t5 }0 G* D* H$ w& D! h/ G; k% { 
- individual F[2*popsize][2*popsize];
 - double rand_real(double low,double high)
 - //产生随机实数
 - {
 -     double h;
 -     h=(high-low)*URAND+low+0.001;
 -     if(h>=high)
 -         h=high-0.001;
 -     return h;
 - }
 - int rand_int(int low,int high)
 - //产生随机整数
 - {
 -     return int((high-low+1)*URAND)+low;
 - }
 
+ u8 v* Q; Z9 s! A$ c  , b6 n5 ~: t, t' o2 f- ]2 ? 
 
+ J1 b+ Y& J( A& E4 Y+ B6 N, X% y, c. F关于排序函数qsort 
' R& S: J9 A4 w$ s 
' n9 y$ U. S3 k, {0 Tvoid qsort( void *base, size_t num, size_t width, int (__cdecl *compare ) 
" Y+ {- D' A3 z# S利用qsort对F数组按照cmp3排序 
4 |, n) c+ u' Y" D# g! H7 a' Q8 W, F. ^$ v) d' U# b7 s 
- int cmp1(const void *a,const void *b)
 - //目标函数f1的升序排序
 - {
 -     const individual *e=(const individual *)a;
 -     const individual *f=(const individual *)b;
 -     if(e->fvalue[0]==f->fvalue[0])
 -         return 0;
 -     else if(e->fvalue[0]<f->fvalue[0])
 -         return -1;
 -     else return 1;
 - }
 - int cmp2(const void *a,const void *b)
 - //目标函数f2的升序排序
 - {
 -     const individual *e=(const individual *)a;
 -     const individual *f=(const individual *)b;
 -     if(e->fvalue[1]==f->fvalue[1])
 -         return 0;
 -     else if(e->fvalue[1]<f->fvalue[1])
 -         return -1;
 -     else return 1;
 - }
 - int cmp_c_d(const void *a,const void *b)
 - //对拥挤距离降序排序
 - {
 -     const individual *e=(const individual *)a;
 -     const individual *f=(const individual *)b;
 -     if(e->crowding_distance==f->crowding_distance)
 -         return 0;
 -     else if(e->crowding_distance<f->crowding_distance)
 -         return 1;
 -     else
 -         return -1;
 - }
 - void population::f_sort(int i)
 - {
 - int n;
 - n=len;
 - qsort(F,n,sizeof(individual),cmp_c_d);
 - }
 
- T: |  _) D0 A0 H  9 s4 m3 G4 K5 W% O 
 
5 N5 |" Y7 Z; U+ \) _- i! g% H群的初始化: 
' }! D, i6 `7 f, p/ N3 z  a& U% X$ c6 w1 G3 N( x) S 
- population::population()
 - {
 -     int i;
 -     for(i=0;i<popsize;i++)
 -     {
 -         P.init();
 -     }
 -     for(i=0;i<popsize;i++)
 -     {
 -         P.f_count();
 -     }
 -     Pnum=popsize;
 -     Qnum=0;
 -     Rnum=0;
 - }
 
- t/ c; G5 [8 Q5 s6 `% e0 f  q 
  
. s/ B1 ~/ q- T4 o3 ~/ T0 \2 R9 x) v& p, D" {# E/ s 
个体初始化:! A6 K7 i. j( [+ B9 x 
+ D$ w% c$ m- k) S, P$ Z- _6 k- ^ 
- void individual::init()
 - {
 -     for(int i=0;i<Dimension;i++)
 -         value=rand_real(0.0,1.0);
 - }
 
' y4 H9 R/ ^& ^5 {  5 t& C' Y& h: w6 l/ Z1 b: g 
 
4 J: y' w& G) C. E! V  R9 Z 
& J  }. S" U1 i利用二进制锦标赛产生子代:. p' a1 ~: J/ K3 b( a" W# l- x 
 
3 k8 R& g" V" W% E+ I  M1、随机产生一个初始父代Po,在此基础上采用二元锦标赛选择、交叉和变异操作产生子代Qo, Po 和Qo群体规模均为N 
) \9 m8 n0 ~5 L" {2、将Pt和Qt并入到Rt中(初始时t=0),对Rt进行快速非支配解排序,构造其所有不同等级的非支配解集F1、F2……..  x+ g2 W, p3 c2 d2 a1 D: O- G 
3、按照需要计算Fi中所有个体的拥挤距离,并根据拥挤比较运算符构造Pt+1,直至Pt+1规模为N,图中的Fi为F3 
( X0 e0 T* K' J- f( F 
; b3 k! \) x4 ?. }
 
, w& ~& F) L$ ?5 Y0 C 
2 ?! `, u$ K! d8 C, w2 y  M 
; V) L& ?/ p7 Q6 S( I% F: } 
- void population::make_new_pop()
 - {
 -     int i,j,x,y,t1,t2,t3;
 -     double s,u,b;
 -     memset(mark,0,sizeof(mark));
 -     t3=0;
 -     while(t3<popsize/2)
 -     {
 -         while(t1=t2=rand_int(0,popsize-1),mark[t1]);
 -         while(t1==t2||mark[t2])
 -         {
 -             t2=rand_int(0,popsize-1);
 -         }
 -         t1=choice(t1,t2);
 -         temp1[t3++]=t1;
 -         mark[t1]=1;
 -     }
 -     for(i=0;i<popsize;i++)
 -     {
 -         s=rand_real(0.0,1.0);
 -         if(s<=0.9)
 -         {
 -             for(j=0;j<Dimension;j++)
 -             {
 -                 u=rand_real((0.0+1e-6),(1.0-1e-6));
 -                 if(u<=0.5)
 -                     b=pow(2*u,1.0/21);
 -                 else
 -                     b=1.0/pow(2*(1-u),1.0/21);
 -                 x=y=rand_int(0,popsize/2-1);
 -                 while(x==y)
 -                     y=rand_int(0,popsize/2-1);
 -                 Q.value[j]=1.0/2*((1-b)*P[temp1[x]].value[j]+(1+b)*P[temp1[y]].value[j]);
 -                 if(Q.value[j]<0)
 -                     Q.value[j]=1e-6;
 -                 else if(Q.value[j]>1)
 -                     Q.value[j]=1.0-(1e-6);
 -                 if(i+1<popsize)
 -                 {
 -                     Q[i+1].value[j]=1.0/2*((1+b)*P[temp1[x]].value[j]+(1-b)*P[temp1[y]].value[j]);
 -                     if(Q[i+1].value[j]<=0)
 -                         Q[i+1].value[j]=1e-6;
 -                     else if(Q[i+1].value[j]>1)
 -                         Q[i+1].value[j]=(1-1e-6);
 -                 }
 -             }
 -             i++;
 -         }
 -         else
 -         {
 -             for(j=0;j<Dimension;j++)
 -             {
 -                 x=rand_int(0,popsize/2-1);
 -                 u=rand_real(0.0+(1e-6),1.0-(1e-6));
 -                 if(u<0.5)
 -                     u=pow(2*u,1.0/21)-1;
 -                 else
 -                     u=1-pow(2*(1-u),1.0/21);
 -                 Q.value[j]=P[temp1[x]].value[j]+(1.0-0.0)*u;
 -                 if(Q.value[j]<0)
 -                     Q.value[j]=1e-6;
 -                 else if(Q.value[j]>1)
 -                     Q.value[j]=1-(1e-6);
 -             }
 -         }
 -     }
 -     Qnum=popsize;
 -     for(i=0;i<popsize;i++)
 -         Q.f_count();
 - }
 
! `0 Z9 r0 E9 e4 V4 ?4 P  % u) |, Q7 f% M3 M7 D 
 
/ e$ m! q5 F( ]7 E5 ~- void population::set_p_q()
 - {
 -     Rnum=0;
 -     Qnum=popsize;
 -     int i;
 -     for(i=0;i< Pnum;i++)
 -         R[Rnum++]=P;
 -     for(i=0;i<Qnum;i++)
 -         R[Rnum++]=Q;
 -     for(i=0;i<2*popsize;i++)
 -         R.f_count();
 - }1 k3 X8 F. ]" X- `" S7 X
 
  ' V1 }4 r. T+ I* y 
& C8 z* Y2 R" N1 ]4 | 
ZDT1问题函数值的计算:: P! m* s- H5 S$ i 
5 }+ X$ f9 _4 W. i( j 
 
* d$ y% C+ _  g: R) [ 
 
( e1 F1 C8 S5 r* y* l- void individual::f_count()
 - {
 -     fvalue[0]=value[0];
 -     int i;
 -     double g=1,sum=0;
 -     for(i=1;i<Dimension;i++)
 -     {
 -         sum+=value;
 -     }
 -     sum+=9*(sum/(Dimension-1));
 -     g+=sum;
 -     fvalue[1]=g*(1-sqrt(value[0]/g));
 - }
 
" R  w# h1 t6 \' j8 T- }( c 
  
) A8 |; r, j* p6 `( e8 L4 n) ~9 ^( W+ j# \ 
判断目标函数值是否被支配: 
% a/ r: x' a3 L. Z' x4 i 
; F, V/ A3 N3 X- bool e_is_dominated(const individual &a,const individual &b)
 - {
 -     if((a.fvalue[0]<=b.fvalue[0])&&(a.fvalue[1]<=b.fvalue[1]))
 -     {
 -         if((a.fvalue[0]==b.fvalue[0])&&a.fvalue[1]==b.fvalue[1])
 -             return false;
 -         else
 -             return true;
 -     }
 -     else
 -         return false;
 - }/ q& O7 x* j) Z+ `) I1 J1 s
 
  ; L# `% n3 Q9 x% A, `& f6 G* T+ x 
 
3 h" D- D9 U1 G- g. M$ T9 Y2 E快速非支配排序法:重点!!!  `  [% ^! I  D: l 
9 m3 Y( y9 s! i+ l3 o 
- void population::fast_nondominated_sort()
 - {
 -     int i,j,k;
 -     individual H[2*popsize];
 -     int h_len=0;
 -     for(i=0;i<2*popsize;i++)
 -     {
 -         R.np=0;
 -         R.is_dominated=0;
 -         len=0;
 -     }
 -     for(i=0;i<2*popsize;i++)
 -     {
 -         for(j=0;j<2*popsize;j++)
 -         {
 -             if(i!=j)
 -             {
 -                 if(e_is_dominated(R,R[j]))
 -                     R.sp[R.is_dominated++]=j;
 -                 else if(e_is_dominated(R[j],R))
 -                     R.np+=1;
 -             }
 -         }
 -         if(R.np==0)
 -         {
 -             len_f=1;
 -             F[0][len[0]++]=R;
 -         }
 -     }
 -     i=0;
 -     while(len!=0)
 -     {
 -         h_len=0;
 -         for(j=0;j<len;j++)
 -         {
 -             for(k=0;k<F[j].is_dominated;k++)
 -             {
 -                 R[F[j].sp[k]].np--;
 -                 if(R[F[j].sp[k]].np==0)
 -                 {
 -                     H[h_len++]=R[F[j].sp[k]];
 -                     R[F[j].sp[k]].rank=i+2;
 -                 }
 -             }
 -         }
 -         i++;
 -         len=h_len;
 -         if(h_len!=0)
 -         {
 -             len_f++;
 -             for(j=0;j<len;j++)
 -                 F[j]=H[j];
 -         }
 -     }
 - }5 e, h. g. y+ }, C7 a1 Y6 e1 u
 
 
  
8 f8 A9 P. p8 w6 C7 A# `; t+ N. z 
6 }# y+ T6 A- C/ w# \, Z4 H( l$ u+ M6 I9 S' y, @7 u 
计算拥挤距离:重点!!!具体解释见其他文章!!! 
/ w6 e( `7 s0 X6 M5 M  s( M. h/ t( M 
: a2 r0 X# K4 Z
 
 
0 [/ W2 x& t8 j' k/ `. l$ t3 B8 [% U. M 
; o+ L' X- z  o# _6 ? 
- void population::calu_crowding_distance(int i)
 - {
 -     int n=len;
 -     double m_max,m_min;
 -     int j;
 -     for(j=0;j<n;j++)
 -         F[j].crowding_distance=0;
 -     F[0].crowding_distance=F[n-1].crowding_distance=0xffffff;
 -     qsort(F,n,sizeof(individual),cmp1);
 -     m_max=-0xfffff;
 -     m_min=0xfffff;
 -     for(j=0;j<n;j++)
 -     {
 -         if(m_max<F[j].fvalue[0])
 -             m_max=F[j].fvalue[0];
 -         if(m_min>F[j].fvalue[0])
 -             m_min=F[j].fvalue[0];
 -     }
 -     for(j=1;j<n-1;j++)
 -         F[j].crowding_distance+=(F[j+1].fvalue[0]-F[j-1].fvalue[0])/(m_max-m_min);
 -     F[0].crowding_distance=F[n-1].crowding_distance=0xffffff;
 -     qsort(F,n,sizeof(individual),cmp2);
 -     m_max=-0xfffff;
 -     m_min=0xfffff;
 -     for(j=0;j<n;j++)
 -     {
 -         if(m_max<F[j].fvalue[1])
 -             m_max=F[j].fvalue[1];
 -         if(m_min>F[j].fvalue[1])
 -             m_min=F[j].fvalue[1];
 -     }
 -     for(j=1;j<n-1;j++)
 -         F[j].crowding_distance+=(F[j+1].fvalue[1]-F[j-1].fvalue[1])/(m_max-m_min);
 - }
 
6 x$ Q" A( l' q) _  ' V5 l7 o' m' V/ q% @1 v7 Y 
 
' ^& ]9 Z# g2 }采集多样性的选择:( h- T9 l% w5 j2 R* r  M 
& E! R5 G8 K& D& `0 y& K: X) s 
- int population::choice(int a,int b)
 - {
 -     if(P[a].rank<  P .rank)
 -         return a;
 -     else if(P[a].rank==P.rank)
 -     {
 -         if(P[a].crowding_distance>  P  .crowding_distance)
 -             return a;
 -         else
 -             return b;
 -     }
 -     else
 -         return b;
 - }
 
6 G! ]. q- i+ H9 A$ t0 o 
  
& S4 `) e; v* }, W, l$ b: ~) d3 x- J( M5 m- O 
4 Q/ g/ d7 K2 A 
主要操作函数:4 g( F, {  _) ^3 `' ~2 a. E 
  q- e0 i% ~, K- u- V# B% X3 s8 o/ q 
- void population::maincal()
 - {
 -     int s,i,j;
 -     s=generation;
 -     make_new_pop();
 -     while(s--)
 -     {
 -         printf("The %d generation\n",s);
 -         set_p_q();
 -         fast_nondominated_sort();
 -         Pnum=0;
 -         i=0;
 -         while(Pnum+len<=popsize)
 -         {
 -             calu_crowding_distance(i);
 -             for(j=0;j<len;j++)
 -                 P[Pnum++]=F[j];
 -             i++;
 -             if(i>=len_f)break;
 -         }
 -         if(i<len_f)
 -         {
 -             calu_crowding_distance(i);
 -             f_sort(i);
 -         }
 -         for(j=0;j<popsize-Pnum;j++)
 -             P[Pnum++]=F[j];
 -         make_new_pop();
 -     }
 - }
 
$ X! d+ ~- L; y% Z 
  
; t2 ^$ u4 T2 b6 C5 ?$ ]0 u7 N  \ 
主函数: 
; C4 y% w$ S! @7 \: U$ d; H 
0 y  c2 }" F1 Q' f- int main()
 - {
 -     FILE *p;
 -     p=fopen("d:\\My_NSGA2.txt","w+");
 -     srand((unsigned int)(time(0)));
 -     population pop;
 -     pop.maincal();
 -     int i,j;
 -     fprintf(p,"XuYi All Rights Reserved.\nWelcome to OmegaXYZ: www.omegaxyz.com\n");
 -     fprintf(p,"Problem ZDT1\n");
 -     fprintf(p,"\n");
 -     for(i=0;i<popsize;i++)
 -     {
 -         fprintf(p,"The %d generation situation:\n",i);
 -         for(j=1;j<=Dimension;j++)
 -         {
 -             fprintf(p,"x%d=%e  ",j,pop.P.value[j]);
 -         }
 -         fprintf(p,"\n");
 -         fprintf(p,"f1(x)=%f   f2(x)=%f\n",pop.P.fvalue[0],pop.P.fvalue[1]);
 -     }
 -     fclose(p);
 -     return 1;
 - }& J9 S( `. }* Y2 U. Q1 A& \4 k% Z
 
  6 U; l3 ?- Q1 q# ]) s6 {# [8 T 
 
+ n$ j7 f( m  E( Q6 n. n( E- W2 O; C6 W 
ZDT1问题图像及前沿面。 
& Y3 N  m& ~6 U6 P# H
 
 
2 {; z- g  v: `) C$ }% k1 _( A% M6 k. s; B; O# C7 ]) G% b 
 
; C9 H) x1 B4 O& j8 c$ h  G  Q 
 
2 O+ ]8 W! p( a3 ~5 f测试结果:+ D) h9 ]$ J, Z 
 
 |   
 
 
 
 |