前言:
本文记录了自己在智能算法课程作业的实现代码设计,简单实现了遗传算法,所有代码为自己梳理了算法流程之后原创实现的!!!仅供参考,如果觉得有任何问题可以留言讨论~
别人的代码可以参考一些关键环节的实现,但是整体的框架设计以及具体实现还是要自己动手完成才有意义!!
另附
在查资料阶段参考的比较好的相关博客文章分享如下:
算法流程理解
c++实现参考
C++实现参考2
问题描述:
遗传算法实现流程
一、程序设计
1、辅助类设计
A)个体类
通过类成员函数以及构造函数,实现个体的编码与适应值计算等
class Individual {
public:
double x;
double y;
vector<int>code;
double fitness;
double FitRatio;
void init() {
for (int i = 0; i < Len; i++) {
double r = rand();
int x = (r < RAND_MAX / 2) ? 0 : 1;
code.push_back(x);
}
}
double GetFitness() {
return fitness = f(x, y);
}
void decode() {
double ansX = 0, ansY = 0;
for (int i = 0; i < LenX1; i++)
ansX = ansX * 2 + code[i];
for (int i = LenX1; i < Len; i++)
ansY = ansY * 2 + code[i];
x = xl + (xr - xl) * ansX / (pow(2, LenX1) - 1);
y = yl + (yr - yl) * ansY / (pow(2, LenX2) - 1);
}
Individual() {
init();
decode();
GetFitness();
FitRatio = 0;
}
};
B) 种群类
通过类成员函数以及将个体类对象作为成员,实现种群的初始化,以及选择交叉变异等一系列操作等
class Group {
public:
vector<Individual*>Current;
vector<Individual*>Next;
int CBestNo;
double CBestVal; int NBestNo;
double NBestVal;
Group() {
CBestNo = -1;
NBestNo = -1;
NBestVal = -100;
CBestVal = -100;
double sum = 0; CBestVal = -100;
for (int i = 0; i < N; i++) {
Individual* p = new Individual();
double tem = p->fitness;
sum += tem;
if (tem > CBestVal) {
CBestNo = i; CBestVal = tem;
}
Current.push_back(p);
}
for (int i = 0; i < N; i++)
Current[i]->FitRatio = Current[i]->fitness / sum;
}
void Selection() {
for (int i = 0; i < N; i++) {
int n = 0;
double pos = ran(seed);
double CheckPos = 0;
while (1) {
CheckPos += Current[n]->FitRatio;
if (CheckPos >= pos)break;
n++;
}
Next.push_back(Current[n]);
}
}
void Cross() {
vector<Individual*>Participants;
for (int i = 0; i < N; i++) {
if (ran(seed) < Pcross)Participants.push_back(Next[i]);
}
int num = Participants.size();
for (int i = 1; i < num; i += 2) {
int dot = (rand() / RAND_MAX) *Len;
int tem;
for (int j = 0; j < dot; j++) {
tem = Participants[i - 1]->code[j];
Participants[i - 1]->code[j] = Participants[i]->code[j];
Participants[i]->code[j] = tem;
}
}
}
void Mutate() {
NBestVal = -100;
double tem;
for (int i = 0; i < N; i++) {
for (int j = 0; j < Len; j++) {
if (ran(seed) < Pmutate)Next[i]->code[j] = !Next[i]->code[j];
}
Next[i]->decode();
tem = Next[i]->GetFitness();
if (tem > NBestVal) {
NBestNo = i;
NBestVal = tem;
}
}
}
void Evolute() {
Selection();
Cross();
Mutate();
if (NBestVal > CBestVal) {
double sum = 0;
for (int i = 0; i < N; i++) {
sum += Next[i]->fitness;
Current[i] = Next[i];
Next[i] = nullptr;
}
for (int i = 0; i < N; i++)
Current[i]->FitRatio = Current[i]->fitness / sum;
Next.resize(0);
CBestNo = NBestNo;
CBestVal = NBestVal;
}
}
};
2、求解染色体长度函数:
根据精度设置,得到所需的染色体长度:
void GetLen() {
double XRange = (xr - xl) * pow(10, precision);
int m = 1;
while (1) {
if (pow(2, m) - 1 >= XRange)break;
m++;
}
double YRange = (yr - yl) * pow(10, precision);
int n = 1;
while (1) {
if (pow(2, n) - 1 >= YRange)break;
n++;
}
LenX1 = m;
LenX2 = n;
Len = m + n;
}
3、个体编码(二进制编码)
void init() {
for (int i = 0; i < Len; i++) {
double r = rand();
int x = (r < RAND_MAX / 2) ? 0 : 1;
code.push_back(x);
}
}
注意此处0,1的随机数生成不可以使用!!!
srand((int)time(0));
int x=rand()%2;
由于每一次循环产生的随机序列都是一样的,这样会使得后面对于种群初始化的时候,每一个个体的编码都是一样的
对应的解码函数:
void decode() {
double ansX = 0, ansY = 0;
for (int i = 0; i < LenX1; i++)
ansX = ansX * 2 + code[i];
for (int i = LenX1; i < Len; i++)
ansY = ansY * 2 + code[i];
x = xl + (xr - xl) * ansX / (pow(2, LenX1) - 1);
y = yl + (yr - yl) * ansY / (pow(2, LenX2) - 1);
}
注意如何实现了限制解码之后的数始终在所限制的变量范围内
4、适应度函数
double GetFitness() {
return fitness = f(x, y);
}//个体Individual类的函数
double f(double x, double y) {
return 21.5 + x * sin(4 * Pi * x) + y * sin(20 * Pi * y);// 单独定义的函数
}
5、种群初始化
Group() {
CBestNo = -1;
NBestNo = -1;
NBestVal = -100;
CBestVal = -100;
double sum = 0; CBestVal = -100;
for (int i = 0; i < N; i++) {
Individual* p = new Individual();
double tem = p->fitness;
sum += tem;
if (tem > CBestVal) {
CBestNo = i; CBestVal = tem;
}
Current.push_back(p);
}
for (int i = 0; i < N; i++)
Current[i]->FitRatio = Current[i]->fitness / sum;
}
6、选择(轮盘赌)
void Selection() {
for (int i = 0; i < N; i++) {
int n = 0;
double pos = ran(seed);
double CheckPos = 0;
while (1) {
CheckPos += Current[n]->FitRatio;
if (CheckPos >= pos)break;
n++;
}
Next.push_back(Current[n]);
}
}
7、单点交叉
void Cross() {
vector<Individual*>Participants;
for (int i = 0; i < N; i++) {
if (ran(seed) < Pcross)Participants.push_back(Next[i]);
}
int num = Participants.size();
for (int i = 1; i < num; i += 2) {
int dot = (rand() / RAND_MAX) *Len;
int tem;
for (int j = 0; j < dot; j++) {
tem = Participants[i - 1]->code[j];
Participants[i - 1]->code[j] = Participants[i]->code[j];
Participants[i]->code[j] = tem;
}
}
}
8、变异
void Mutate() {
NBestVal = -100;
double tem;
for (int i = 0; i < N; i++) {
for (int j = 0; j < Len; j++)
if (ran(seed) < Pmutate)Next[i]->code[j] = !Next[i]->code[j];
Next[i]->decode();
tem = Next[i]->GetFitness();
if (tem > NBestVal) {
NBestNo = i;
NBestVal = tem;
}
}
}
9、种群进化
void Evolute() {
Selection();
Cross();
Mutate();
if (NBestVal > CBestVal) {
double sum = 0;
for (int i = 0; i < N; i++) {
sum += Next[i]->fitness;
Current[i] = Next[i];
Next[i] = nullptr;
}
for (int i = 0; i < N; i++)
Current[i]->FitRatio = Current[i]->fitness / sum;
Next.resize(0);
CBestNo = NBestNo;
CBestVal = NBestVal;
}
}
二、问题求解
1、给定参数
完整代码
#include <iostream>
#include<vector>
#include <cmath>
#include<algorithm>
#include<ctime>
#include<random>
#include<cstdlib>
using namespace std;
const double Pi = 3.14159265358979323846;
const double Pcross = 0.7;const double Pmutate = 0.07;const int GMax = 2000;const int N = 100;
int Len;
int LenX1;
int LenX2;
int precision = 4;
double xl = -3.0, xr = 12.1, yl = 4.1, yr = 5.8;
default_random_engine seed(time(0));
uniform_real_distribution<double> ran(0, 1);
void GetLen() {
double XRange = (xr - xl) * pow(10, precision);
int m = 1;
while (1) {
if (pow(2, m) - 1 >= XRange)break;
m++;
}
double YRange = (yr - yl) * pow(10, precision);
int n = 1;
while (1) {
if (pow(2, n) - 1 >= YRange)break;
n++;
}
LenX1 = m;
LenX2 = n;
Len = m + n;
}
double f(double x, double y) {
return 21.5 + x * sin(4 * Pi * x) + y * sin(20 * Pi * y);
}
class Individual {
public:
double x;
double y;
vector<int>code;
double fitness;
double FitRatio;
void init() {
for (int i = 0; i < Len; i++) {
double r = rand();
int x = (r < RAND_MAX / 2) ? 0 : 1;
code.push_back(x);
}
}
double GetFitness() {
return fitness = f(x, y);
}
void decode() {
double ansX = 0, ansY = 0;
for (int i = 0; i < LenX1; i++)
ansX = ansX * 2 + code[i];
for (int i = LenX1; i < Len; i++)
ansY = ansY * 2 + code[i];
x = xl + (xr - xl) * ansX / (pow(2, LenX1) - 1);
y = yl + (yr - yl) * ansY / (pow(2, LenX2) - 1);
}
Individual() {
init();
decode();
GetFitness();
FitRatio = 0;
}
};
class Group {
public:
vector<Individual*>Current;
vector<Individual*>Next;
int CBestNo;
double CBestVal; int NBestNo;
double NBestVal;
Group() {
CBestNo = -1;
NBestNo = -1;
NBestVal = -100;
CBestVal = -100;
double sum = 0; CBestVal = -100;
for (int i = 0; i < N; i++) {
Individual* p = new Individual();
double tem = p->fitness;
sum += tem;
if (tem > CBestVal) {
CBestNo = i; CBestVal = tem;
}
Current.push_back(p);
}
for (int i = 0; i < N; i++)
Current[i]->FitRatio = Current[i]->fitness / sum;
}
void Selection() {
for (int i = 0; i < N; i++) {
int n = 0;
double pos = ran(seed);
double CheckPos = 0;
while (1) {
CheckPos += Current[n]->FitRatio;
if (CheckPos >= pos)break;
n++;
}
Next.push_back(Current[n]);
}
}
void Cross() {
vector<Individual*>Participants;
for (int i = 0; i < N; i++) {
if (ran(seed) < Pcross)Participants.push_back(Next[i]);
}
int num = Participants.size();
for (int i = 1; i < num; i += 2) {
int dot = (rand() / RAND_MAX) *Len;
int tem;
for (int j = 0; j < dot; j++) {
tem = Participants[i - 1]->code[j];
Participants[i - 1]->code[j] = Participants[i]->code[j];
Participants[i]->code[j] = tem;
}
}
}
void Mutate() {
NBestVal = -100;
double tem;
for (int i = 0; i < N; i++) {
for (int j = 0; j < Len; j++)
if (ran(seed) < Pmutate)Next[i]->code[j] = !Next[i]->code[j];
Next[i]->decode();
tem = Next[i]->GetFitness();
if (tem > NBestVal) {
NBestNo = i;
NBestVal = tem;
}
}
}
void Evolute() {
Selection();
Cross();
Mutate();
if (NBestVal > CBestVal) {
double sum = 0;
for (int i = 0; i < N; i++) {
sum += Next[i]->fitness;
Current[i] = Next[i];
Next[i] = nullptr;
}
for (int i = 0; i < N; i++)
Current[i]->FitRatio = Current[i]->fitness / sum;
Next.resize(0);
CBestNo = NBestNo;
CBestVal = NBestVal;
}
}
};
int main() {
GetLen();
Group generation;
for (int i = 0; i < GMax; i++)
generation.Evolute();
cout << "BestVal: " << generation.CBestVal << " with X1= " << generation.Current[generation.CBestNo]->x << ",X2= " << generation.Current[generation.CBestNo]->y << endl;
}
2、调查参数
完整代码
主函数不一样
int main() {
GetLen();
ofstream fout1("Ans.txt");//完整记录的文件
ofstream fout2("BestVal.txt"); //记录答案的文件(按照python列表的格式,方便后续可视化)
fout2 << "结果是:[ "<<endl;
fout1 << "Pc" << '\t' << "Pm" << '\t' << "BestVal" << endl;
for (double i = 0.1; i < 1; i+=0.1) {
Pcross = i;
for (double j = 0.01; j <0.1; j+=0.01) {
Pmutate = j;
double ans = 0;
for (int k = 0; k < 30; k++) {
Group generation;
for (int i = 0; i < GMax; i++)
generation.Evolute();
ans += generation.CBestVal;
}
ans /= 30;
fout1 << Pcross << '\t' << Pmutate << '\t' << ans << endl;
fout2 << ans << ", "<<endl;
cout << Pcross << '\t' << Pmutate << '\t' << ans << endl;
}
}
fout1.close();
fout2.close();
}