1. 程式人生 > >(C/C++學習)19.單目標遺傳演算法的C程式實現

(C/C++學習)19.單目標遺傳演算法的C程式實現

說明:在學習生活中,經常會遇到各種各樣的最優問題,其中最常見的就是求某個多維(多個自變數)函式在各個自變數各取何值時的最大值或最小值;例如求函式 f(x) = (x-5)2+(y-6)2+(z-7)2 的最小值,當然,這個函式很簡單,很容易看出來,該函式的最小值為0,分別在三個自變數取5,6,7時取得最小值。但日常學習中的函式都是很複雜的,就算通過大量的計算,也不一定能準確地算出目標值以及在何時取得該目標值,因此,本文介紹一種基於單目標的遺傳演算法來解決此類問題。

1.遺傳演算法程式碼實現

遺傳演算法的相關概念,這裡不多說,網上一大堆,這裡只介紹本程式的實現過程,程式碼如下:

  1
#include<iostream> 2 #include<cstdlib> 3 #include<bitset> 4 #include<iomanip> 5 #include<time.h> 6 using namespace std; 7 #define Accurate 0.0005 8 //重要調節引數 9 const int L= 12; 10 //定義編碼的長度 11 12 float getfitness(float x,float y,float z) 13 //定義測試函式f(x) 14 { 15
float result; 16 result = -(x-8)*(x-14)+(y-7)*(y-4)-(z-1)*(z-17); 17 return result; 18 } 19 20 void Xover(float &a,float &b) 21 //定義交叉操作 22 { 23 a = a*100; 24 b = b*100; 25 int pos; 26 //隨機生成雜交點 即第幾個分量進行相互交換 27 pos=rand()%12+1; 28 //在n個分量中,隨機確定第pos個分量 29
int j,k; 30 j=pos; 31 k=pos; 32 bitset<L>e(a); 33 bitset<L>f(b); 34 bitset<L>g; 35 bitset<L>h; 36 37 for(int i=0;i<pos;i++) 38 { 39 if(e[i]==1) 40 g.set(i); 41 } 42 for(int i=0;i<pos;i++) 43 { 44 if(f[i]==1) 45 h.set(i); 46 } 47 for(j = pos;j<L;j++) 48 { 49 if(f[j]==1) 50 g.set(j); 51 } 52 for(k = pos;k<L;k++) 53 { 54 if(e[k]==1) 55 h.set(k); 56 } 57 a=(double)(g.to_ulong())/100.0; 58 b=(double)(h.to_ulong())/100.0; 59 } 60 61 62 int main() 63 { 64 int same = 0; //資料趨於穩定時的優化 65 srand(time(NULL)); //定義隨機數生成的種子 66 const int pop_size=16; //定義種群大小 67 int NG=2000; //指定種群最大的繁殖的代數 68 int t=0; //當前繁殖的代數 69 float p[pop_size]; //定義種群 70 float q[pop_size]; //定義繁殖種群 即種群的下一代 71 float p1[pop_size]; //新建種群及其後代 72 float q1[pop_size]; 73 float p2[pop_size]; //新建種群及其後代 74 float q2[pop_size]; 75 float sum; //總的適值 76 float thebest = 0; //總群最優質個體 77 float thebest1 = 0; 78 float thebest2 = 0; 79 float p_probability[pop_size];//適值概率 80 float pp[pop_size]; //適值概率區間陣列 81 float pro; //定義隨機生成的概率 82 float pc=0.90; //定義交叉的概率 83 float pm=0.4; //定義變異的概率 84 85 cout<<"the initial population:"<<endl<<endl; 86 87 for(int i=0; i<pop_size; i++) 88 //生成初始的第0代種群 89 { 90 p[i] = (rand()%50)/50.0*40.95; 91 p1[i] = (rand()%50)/50.0*40.95; 92 p2[i] = (rand()%50)/50.0*40.95; 93 } 94 95 cout<<" X :"; 96 for(int i=0; i<pop_size; i++) 97 //列印初始種群 98 { 99 if(i%8 == 0) 100 cout<<endl; 101 cout<<setw(8)<<p[i]<<" "; 102 } 103 cout<<endl<<endl; 104 105 cout<<" Y :"; 106 for(int i=0; i<pop_size; i++) 107 { 108 if(i%8 == 0) 109 cout<<endl; 110 cout<<setw(8)<<p1[i]<<" "; 111 } 112 113 cout<<endl<<endl; 114 115 cout<<" Z :"; 116 for(int i=0; i<pop_size; i++) 117 { 118 if(i%8 == 0) 119 cout<<endl; 120 cout<<setw(8)<<p2[i]<<" "; 121 } 122 123 cout<<endl<<endl; 124 cout<<"\t\t\t Get Result From Iteration"<<endl<<endl; 125 cout<<setw(15)<<right<<"iteration"<<right<<setw(15)<<"x1"<<right<<setw(15) 126 <<"x2"<<right<<setw(15)<<"x3"<<right<<setw(15)<<"fitness"<<endl<<endl; 127 128 while(t <= NG) 129 //設定繁殖條件 130 { 131 sum=0.0; 132 for(int i=0;i<pop_size;i++) 133 { 134 q[i] = p[i]; 135 q1[i] = p1[i]; 136 q2[i] = p2[i]; 137 } 138 for(int i=0;i<pop_size;i++) 139 { 140 if(getfitness(p[i],p1[i],p2[i]) > getfitness(thebest,thebest1,thebest2)) 141 { 142 thebest = p[i]; 143 thebest1 = p1[i]; 144 thebest2 = p2[i]; 145 } 146 sum += getfitness(p[i],p1[i],p2[i]); 147 } 148 149 for(int i=0;i<pop_size;i++) 150 //計算適值概率 151 { 152 p_probability[i]=getfitness(p[i],p1[i],p2[i])/sum; 153 if(i==0) 154 { 155 pp[i]=p_probability[i]; 156 } 157 else 158 { 159 pp[i]=p_probability[i]+pp[i-1]; 160 } 161 } 162 163 float max = getfitness(thebest,thebest1,thebest2); 164 165 for(int i = 0;i<pop_size;i++) 166 //根據適值概率選擇雙親 167 { 168 if(i == 0) 169 { 170 p[i] = thebest; 171 p1[i] = thebest1; 172 p2[i] = thebest2; 173 } 174 pro = rand()%1000/1000.0; 175 if(pro >= pp[0]&&pro < pp[1]) 176 { 177 p[i] = q[0]; 178 p1[i] = q1[0]; 179 p2[i] = q2[0]; 180 } 181 else if(pro >= pp[1]&&pro < pp[2]) 182 { 183 p[i] = q[1]; 184 p1[i] = q1[1]; 185 p2[i] = q2[1]; 186 } 187 else if(pro >= pp[2]&&pro < pp[3]) 188 { 189 p[i] = q[2]; 190 p1[i] = q1[2]; 191 p2[i] = q2[2]; 192 } 193 else if(pro >= pp[3]&&pro < pp[4]) 194 { 195 p[i] = q[3]; 196 p1[i] = q1[3]; 197 p2[i] = q2[3]; 198 } 199 else if(pro >= pp[4]&&pro < pp[5]) 200 { 201 p[i] = q[4]; 202 p1[i] = q1[4]; 203 p2[i] = q2[4]; 204 } 205 else 206 { 207 p[i] = q[5]; 208 p1[i] = q1[5]; 209 p2[i] = q2[5]; 210 } 211 } 212 213 214 int r=0; 215 int z=0; 216 for(int j=0;j<pop_size;j++) 217 //交叉運算元 218 { 219 pro=rand()%1000/1000.0; 220 if(pro < pc) 221 { 222 ++z; 223 if(z%2==0) 224 { 225 Xover(p[r],p[j]); 226 Xover(p1[r],p1[j]); 227 Xover(p2[r],p2[j]); 228 } 229 else 230 r = j; 231 } 232 } 233 234 for(int i=0;i<pop_size;i++) 235 //變異運算元 236 { 237 for(int j=0;j<L;j++) 238 { 239 pro=rand()%1000/1000.0; 240 //在【0,1】區間產生隨機數 241 if(pro < pm) 242 { 243 p[i] *= 100.0; 244 bitset<L>v(p[i]); 245 v.flip(j); 246 p[i]=v.to_ulong()/100.0; 247 } 248 } 249 for(int j = 0;j<L;j++) 250 { 251 pro=rand()%1000/1000.0; 252 //在【0,1】區間產生隨機數 253 if(pro < pm) 254 { 255 p1[i] *=100.0; 256 bitset<L>v(p1[i]); 257 v.flip(j); 258 p1[i]=v.to_ulong()/100.0; 259 } 260 } 261 for(int j = 0;j<L;j++) 262 { 263 pro=rand()%1000/1000.0; 264 //在【0,1】區間產生隨機數 265 if(pro < pm) 266 { 267 p2[i] *=100.0; 268 bitset<L>v(p2[i]); 269 v.flip(j); 270 p2[i]=v.to_ulong()/100.0; 271 } 272 } 273 } 274 float newmax = getfitness(thebest,thebest1,thebest2); 275 //資料趨於穩定時的優化 276 if(max == newmax) 277 same++; 278 if(same == 50) 279 { 280 same = 0; 281 for(int j = 0;j<pop_size;j++) 282 { 283 if(getfitness((p[j]+p[j]*Accurate),p1[j],p2[j]) > getfitness(p[j],p1[j],p2[j]) && (p[j]+p[j]*Accurate) < 40.95) 284 p[j] = p[j]+p[j]*Accurate; 285 else if(getfitness((p[j]-p[j]*Accurate),p1[j],p2[j]) > getfitness(p[j],p1[j],p2[j]) && (p[j]-p[j]*Accurate) > 0) 286 p[j] = p[j]-p[j]*Accurate; 287 if(getfitness(p[j],(p1[j]+p1[j]*Accurate),p2[j]) > getfitness(p[j],p1[j],p2[j]) && (p1[j]+p1[j]*Accurate) < 40.95) 288 p1[j] = p1[j]+p1[j]*Accurate; 289 else if(getfitness(p[j],(p1[j]-p1[j]*Accurate),p2[j]) > getfitness(p[j],p1[j],p2[j]) && (p1[j]-p1[j]*Accurate) > 0) 290 p1[j] = p1[j]-p1[j]*Accurate; 291 if(getfitness(p[j],p1[j],(p2[j]+p2[j]*Accurate)) > getfitness(p[j],p1[j],p2[j]) && (p2[j]+p2[j]*Accurate) < 40.95) 292 p[j] = p[j]+p[j]*Accurate; 293 else if(getfitness(p[j],p1[j],(p2[j]-p2[j]*Accurate)) > getfitness(p[j],p1[j],p2[j]) && (p2[j]-p2[j]*Accurate) > 0) 294 p[j] = p[j]-p[j]*Accurate; 295 } 296 } 297 cout<<"\r"; 298 t++; 299 cout<<setw(15)<<t<<setw(15)<<thebest<<setw(15)<<thebest1<<setw(15)<<thebest2<<setw(15) 300 <<getfitness(thebest,thebest1,thebest2); 301 } 302 cout<<endl<<endl; 303 cout<<"\t"<<"the best x1:"<<thebest<<"\t"<<"the best x2:"<<thebest1<<"\t"<<"the best x2:"<<thebest2<<endl<<endl; 304 cout<<"\t"<<"the best result : "<<getfitness(thebest,thebest1,thebest2); 305 return 0; 306 } 307 308
View Code

使用注意事項:

a.根據具體的目標函式修改評價函式方程,

b.根據具體的自變數的範圍來設計二進位制編碼的長度 L,每一代子代資料產生,要判斷其是否處於自變數的給定範圍,若否,重新生成。

c.Accurate 引數用於當目標函式趨於穩定狀態時的優化,即探測此時自變數該精度變化範圍內的目標函式變化情況,從而獲得更為優越的目標值。