使用遗传算法求解函数最大值 下载本文

内容发布更新时间 : 2024/4/29 1:04:17星期一 下面是文章的全部内容请认真阅读。

更新最优值。

改进之后的效果如下所示,显然比之前更优,且实验结果显示对于前面对比实验中的参数值,这里只需要较小的参数(如迭代次数只需2000次)值即可稳定收敛到此最大值,可知改进非常有效。

增加输出精度之后为,于是得到最优的结果为2.894471354862841

源代码

改进后的源代码如下:

#include #include #include #include #include using namespace std;

// 程序欲分配内存的数组大小

const int mxn = 10000; // 最大的种群规模 const int mxlen = 1000;

// 遗传算法关键参数 const int N = 200; const int len = 30;

// 种群的个体数

// 每个个体的染色体的长度,x和y各占一半 // 交叉操作时多点交叉的交叉点个数 // 最大的染色体长度

const int crossnum = 4;

const int maxGeneration = 2000; // 最大进化代数

const double probCross = 0.85;

// 个体的染色体类 class Chromosome { public: };

double bestval;

// 交叉概率

const double probMutation = 0.15; // 变异概率

bool g[mxlen]; // 二进制编码的编码数组 Chromosome() { }

Chromosome(const Chromosome& c) // 拷贝构造函数,进行深复制 { }

void operator=(const Chromosome& c) // 重载=号,进行深复制 { }

for (int i = 0; i < len; i++) g[i] = c.g[i]; for (int i = 0; i < len; i++) g[i] = c.g[i]; for (int i = 0; i < len; i++) g[i] = rand() % 2;

// 默认构造函数,构造随机染色体

// 记录当前所得的最优值

// 个体的种群,辅助数组

Chromosome bestC; // 记录当前最优值对应的个体染色体 Chromosome group[mxn], temGroup[mxn];

// 目标函数

double f(double x, double y) { }

// 解码函数,从染色体得到x和y的值

void decode(const Chromosome& c, double& x, double &y) {

double num = pow(2.0, len / 2.0); int tem = 0;

for (int i = len - 1, q = 1; i >= len / 2; i--)

tem += c.g[i] * q, q = q * 2; y = 1 + (2 - 1) / num * tem; tem = 0;

for (int i = len / 2 - 1, q = 1; i >= 0; i--)

tem += c.g[i] * q, q = q * 2; x = 1 + (2 - 1) / num * tem;

return x * sin(6 * y) + y * cos(8 * x);

}

// 适应度函数,为避免负值,把目标函数加一个正数 double fitness(const Chromosome& c) { }

// 辅助函数,生成0-1之间的随机小数 double inline random01() { }

// 选择操作

void select(Chromosome group[mxn]) {

// 计算每个个体的选择概率 double fitnessVal[mxn];

for (int i = 0; i < N; i++) fitnessVal[i] = fitness(group[i]); double sum = 0;

for (int i = 0; i < N; i++) sum += fitnessVal[i]; double prob[mxn];

for (int i = 0; i < N; i++) prob[i] = fitnessVal[i] / sum; // 随机选择N个个体组成新种群 int selectId[mxn];

for (int i = 1; i < N; i++) prob[i] += prob[i-1]; for (int i = 0; i < N; i++) {

// 使用轮盘赌算法选择个体

double randNum = random01(); int j;

for (j = 0; j < N - 1; j++) { }

if (j == N - 1)

selectId[i] = j; if (randNum < prob[j]) { }

selectId[i] = j; break;

return rand() % 10000 / 10000.0; double x, y; decode(c, x, y); return f(x, y) + 5;

}

}

// 把种群更新为新选择的个体集合 for (int i = 0; i < N; i++) for (int i = 0; i < N; i++)

temGroup[i] = group[i];

group[i] = temGroup[selectId[i]];

// 交叉操作,使用多点交叉

void crossover(Chromosome& c1, Chromosome& c2) { }

// 变异操作

void mutate(Chromosome& c) { }

// 获取种群最优个体

int getOptimal(Chromosome group[mxn], double& x, double& y, double& val) {

// 计算适应值,遍历得到最优值并进行解码 double fitnessVal[mxn]; // 随机选择一位进行翻转 int i = rand() % len; c.g[i] = !c.g[i]; // 生成交叉点位置,并排序 int crosspoint[mxn];

for(int i = 0; i < crossnum; i++) crosspoint[i] = rand() % len; sort(crosspoint, crosspoint+crossnum); // 进行交叉 bool flag = 0;

for(int i = 0, j = 0; i < len; i++) { }

if(!flag) { }

// 如果若干个交叉点重合,则效果叠加 // 偶数个交叉点效果相当于没有交叉点

while(j < crossnum && i == crosspoint[j]) { }

j++;

flag = !flag;

swap(c1.g[i], c2.g[i]); if (i == crosspoint[j])

}

for (int i = 0; i < N; i++) fitnessVal[i] = fitness(group[i]); int id = 0;

for (int i = 1; i < N; i++)

if (fitnessVal[i] > fitnessVal[id])

id = i;

decode(group[id], x, y); val = f(x, y); return id;

// 遗传算法总代码

void GA(double& x, double& y, double& val) {

//

bestC = group[getOptimal(group, x, y, bestval)];

// 控制进化代数

for (int g = 0; g < maxGeneration; g++) {

// 选择操作 select(group); // 根据交叉概率进行交叉

for (int i = 0, pre = -1; i < N; i++) { }

// 根据变异概率进行变异

for (int i = 0; i < N; i++)

if (random01() < probMutation)

mutate(group[i]); if (random01() < probCross) { }

if (pre == -1) { }

crossover(group[pre], group[i]); pre = -1; pre = i; else

// 初始化种群

for (int i = 0; i < N; i++)

group[i] = Chromosome();