本文基于下面的最值问题进行求解:
m a x f ( x 1 , x 2 ) = 21.5 + x 1 s i n ( 4 π x 1 ) + x 2 s i n ( 20 π x 2 ) \ max f(x_1,x_2)=21.5+x_1sin(4\pi x_1)+x_2sin(20\pi x_2) maxf(x1,x2)=21.5+x1sin(4πx1)+x2sin(20πx2)
− 3.0 ≤ x 1 ≤ 12.1 \ -3.0\le x_1\le 12.1 −3.0≤x1≤12.1
4.1 ≤ x 2 ≤ 5.8 \ 4.1\le x_2\le 5.8 4.1≤x2≤5.8
精度要求 ϵ = 1 0 − 4 \epsilon=10^{-4} ϵ=10−4
二进制编码、实数编码、整数编码、排列编码、有限状态机编码、树编码……(本例中我们采用二进制编码,需要对应解码)
x ∈ [ a , b ] \ x \in[a,b] x∈[a,b],精度要求不小于 1 0 − α \ 10^{-\alpha} 10−α.
编码公式: 2 m − 1 − 1 < ( b − a ) ∗ 1 0 α ≤ 2 m − 1 \ 2^{m-1}-1<(b-a)*10^\alpha\le2^{m-1} 2m−1−1<(b−a)∗10α≤2m−1,根据取值范围即可求出共需要多少位二进制数才能满足精度要求
解码公式: y = a + ( b − a ) ∗ x 2 m − 1 \ y=a+(b-a)*\frac{x}{2^m-1} y=a+(b−a)∗2m−1x(其中 x \ x x为无符号二进制换算成十进制之后的值)
本例中,按照精度要求及取值范围, x 1 \ x_1 x1需要18位二进制编码, x 2 \ x_2 x2需要15位二进制编码。
以下为初始化部分代码:
//初始化种群
void init()
{
double p=0.5;
//srand(time(0));
for(int i=0;iRAND_MAX/2)
s.append("1");
else
s.append("0");
}
pop.push_back(s);
}
}
即按照解码公式进行解码之后带入函数中计算 f ( x 1 , x 2 ) \ f(x_1,x_2) f(x1,x2)的值,即为本例的适应度值。相关代码如下(individual为自定义结构体,包含当前计算个体对应的 x 1 , x 2 , f \ x_1,x_2,f x1,x2,f三个值:
//计算适应度值
individual Fitness(string s)
{
individual T;
double x1a = -3.0;
double x1b = 12.1;
double x2a = 4.1;
double x2b = 5.8;
string s1 = s.substr(0,18);
string s2 = s.substr(18,15);
int t1 = Transform(s1);
int t2 = Transform(s2);
T.x1 = x1a+(x1b-x1a)*t1/(pow(2.0,18)-1);
T.x2 = x2a+(x2b-x2a)*t2/(pow(2.0,15)-1);
T.fit = 21.5+T.x1*sin(4*PI*T.x1) +T.x2*sin(20*PI*T.x2);
return T;
}
某种规则:本例使用轮盘赌选择(根据每个个体适应度所占总适应度的比例,以及产生随机数的大小,选择出一部分个体进入交叉池,这样适应度大的的个体会有更大的可能性被选为父母进行交叉,优良基因得以保留下去)
下面是轮盘赌选择部分代码:
//轮盘赌选择
vector choose(vector population,int x)
{
//srand(time(0));
double fitness_sum=0;
vector q;
vector indi_vec;
vector result;
double p=0;
vector random;
for (int i = 0; i < x; i++)
{
double r = rand();
random.push_back(r / (double)RAND_MAX);
}
for(int i=0;iq[j] && random[i] <= q[j + 1])
{
result.push_back(population[j + 1]);
break;
}
}
}
return result;
}
交叉算子:单点交叉、两点交叉、多点交叉、均匀交叉、部分匹配交叉、顺序交叉、循环交叉、二维交叉……
本例使用两点交叉做为交叉算子,在一对个体上选择两个相同的点位,切断之后进行交换即产生两个后代,下面是交叉部分代码:
//两点交叉
vector crossover(vectorpopulation)
{
//srand(time(0));
vector result;
for(int i=0;i+1 i2)
{
string sub1 = s1.substr(i2, i1 - i2);
string sub2 = s2.substr(i2, i1 - i2);
s1.replace(i2, i1 - i2, sub2);
s2.replace(i2, i1 - i2, sub1);
result.push_back(s1);
result.push_back(s2);
}
else
{
result.push_back(s1);
result.push_back(s2);
}
}
}
else
{
result.push_back(s1);
result.push_back(s2);
}
}
return result;
}
变异算子:单点变异、对换变异、移位变异、插入便宜、均匀变异、正态变异、非一致变异……
本例使用单点变异作为变异算子,即产生随机数,将对应位上的二进制编码取反即可,下面为变异部分代码:
//单点变异
string mutation(string s)
{
//srand(time(0));
for(int i=0;i<33;i++)
{
double r = rand();
if (r
step4:用选择算子从集合 p ( t ) U O ( t ) \ p(t)UO(t) p(t)UO(t)中选出下一代种群 p ( t + 1 ) \ p(t+1) p(t+1),令 t = t + 1 \ t=t+1 t=t+1;
此步骤同样用轮盘赌选择作为选择算子选出进入下一代中的个体
step5:如算法满足终止条件,则输出 p ( t + 1 ) \ p(t+1) p(t+1)中具有最大适应度值的个体作为最优解,中止算法。否则,进入步骤2.
终止条件:要么迭代代数达到限制范围,要么很多代后的最好个体没有继续改进即可停止。
以下为全部代码(一般在运行到300+代时即可达到最优解):
#include "stdafx.h"
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define NUMBER 20
#define PI 3.14159265358979323
vector pop;
double pc = 0.5;
double pm = 0.1;
string max_s;
//个体结构体
struct individual
{
double x1=0;
double x2=0;
double fit=0;
};
//初始化种群
void init()
{
double p=0.5;
//srand(time(0));
for(int i=0;iRAND_MAX/2)
s.append("1");
else
s.append("0");
}
pop.push_back(s);
}
}
//二进制字符串转换成整形
int Transform(string s)
{
int n =0;
for(int i = 0; i choose(vector population,int x)
{
//srand(time(0));
double fitness_sum=0;
vector q;
vector indi_vec;
vector result;
double p=0;
vector random;
for (int i = 0; i < x; i++)
{
double r = rand();
random.push_back(r / (double)RAND_MAX);
}
for(int i=0;iq[j] && random[i] <= q[j + 1])
{
result.push_back(population[j + 1]);
break;
}
}
}
return result;
}
//两点交叉
vector crossover(vectorpopulation)
{
//srand(time(0));
vector result;
for(int i=0;i+1 i2)
{
string sub1 = s1.substr(i2, i1 - i2);
string sub2 = s2.substr(i2, i1 - i2);
s1.replace(i2, i1 - i2, sub2);
s2.replace(i2, i1 - i2, sub1);
result.push_back(s1);
result.push_back(s2);
}
else
{
result.push_back(s1);
result.push_back(s2);
}
}
}
else
{
result.push_back(s1);
result.push_back(s2);
}
}
return result;
}
//单点变异
string mutation(string s)
{
//srand(time(0));
for(int i=0;i<33;i++)
{
double r = rand();
if (r generation)
{
individual max;
for (int i = 0; i < generation.size(); i++)
{
individual Ind = Fitness(generation[i]);
if (Ind.fit>max.fit)
{
max = Ind;
max_s = generation[i];
}
}
return max;
}
int main(int argc, _TCHAR* argv[])
{
srand(time(0));
individual Max;
init();
int j = 0;
double MAX = 0;
while (j < 5000)
{
vector pop1, pop2, pop3, pop_new;
pop1 = choose(pop,NUMBER);
pop2 = crossover(pop1);
double max1 = 0;
double max2 = 0;
string s1;
string s2;
for (int i = 0; i < pop2.size(); i++)
{
string s = mutation(pop2[i]);
pop3.push_back(s);
double d = Fitness(pop2[i]).fit;
if ( d> max1)
{
s1 = pop2[i];
max1 = d;
}
}
for (int i = 0; i < pop3.size(); i++)
{
double d = Fitness(pop3[i]).fit;
if (d > max2)
{
s2 = pop3[i];
max2 = d;
}
}
pop_new = choose(pop, NUMBER-2);
pop_new.push_back(s1);
pop_new.push_back(s2);
pop = pop_new;
individual max = print_(pop);
if (max.fit > Max.fit)
{
cout << j + 1 << ":" << max.x1 << ";" << max.x2 << ";" << max.fit << endl;
Max = max;
pop.push_back(max_s);
}
else
cout << j + 1 << ":" << Max.x1 << ";" << Max.x2 << ";" << Max.fit << endl;
j++;
}
system("pause");
return 0;
}
你可能感兴趣的:(日常学习)