特征选择的遗传算法

遗传算法的定义

遗传算法(Genetic Algorithm, GA)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。其主要特点是直接对结构对象进行操作,不存在求导和函数连续性的限定;具有内在的隐并行性和更好的全局寻优能力;采用概率化的寻优方法,不需要确定的规则就能自动获取和指导优化的搜索空间,自适应地调整搜索方向。遗传算法以一种群体中的所有个体为对象,并利用随机化技术指导对一个被编码的参数空间进行高效搜索。其中,选择、交叉和变异构成了遗传算法的遗传操作;参数编码、初始群体的设定、适应度函数的设计、遗传操作设计、控制参数设定五个要素组成了遗传算法的核心内容。

遗传算法的执行过程

(1)初始化,t=0,随机地产生一个包含L条不同染色体的种群M(0);
(2) 计算当前种群M(t)中每一条染色体的适应度f(m)
(3) 按照选择概率p(f(m))对种群中的染色体进行采样,由采样出的染色体经过一定操作繁殖出下一代染色体,组成下一代的种群M(t+1);
(4) 直到达到终止条件,输出适应度最大的染色体作为找到的最优解。终止条件通

实现代码

GeneticAlgorithm.h

#include "GeneticAlgorithm.h"
#include <iostream>
using namespace std;
//自变量取值范围和种群向量定义
const VaribaleRange x_range[2] = {VaribaleRange(-3.0,12.1) ,VaribaleRange(4.1,5.8) };
vector<Individual> now_population; //M(t)种群
vector<Individual> mid_population; //中间种群
vector<Individual> next_population; //M(t)种群

double VaribaleRange::GetUpperValue() const {return var_upper_bound_;}
double VaribaleRange::GetLowerValue() const {return var_lower_bound_;}

void VaribaleRange::SetUpperValue(double upper_value) { var_upper_bound_ = upper_value; }

void VaribaleRange::SetLowerValue(double lower_value) { var_upper_bound_ = lower_value; }

Individual::Individual(double* variable_vector) {
	for (int i = 0; i < kVariableNum; i++) {

		if (variable_vector[i] >= x_range[i].GetLowerValue()&& variable_vector[i] <= x_range[i].GetUpperValue()) {
			variable_[i] = variable_vector[i];
		}
		else {
			cout << "not scale " << endl;
			exit(1);
		}
    }
	this->fitness_ = 0;
	this->fitness_probability_ = 0;
	this->sum_fitness_probability_ = 0;
}

double* Individual::GetVaribaleValue() {
	return variable_;
}


void Individual::ChangeFitness(const double& fitness) {
	 fitness_ = fitness;
}
void Individual::ChangeFitnessProbability( const double& fitness_probability) {
	 fitness_probability_ = fitness_probability;
}
void Individual::ChangeSumFitnessProbability(const double& sum_fitness_probability) {
	 sum_fitness_probability_ = sum_fitness_probability_;
}


double Individual::GetFitness() {
	return fitness_;
}
double Individual::GetFitnessProbability() {
	return fitness_probability_;
}
double Individual::GetSumFitnessProbability() {
	return sum_fitness_probability_;
}
void Individual::PrintVariableValue() {
	for (int i = 0; i < kVariableNum; i++) {
		cout << "var" << i+1 << "=" << variable_[i] << endl;
	}
}

void Initialize() {
	//产生指定范围内的随机变量
	double random_variable[kPopulationSize][kVariableNum];
	for (int col = 0; col < kVariableNum; col++) {
		default_random_engine engine(time(0));
		uniform_real_distribution<double> uniform_random(x_range[col].GetLowerValue(), x_range[col].GetUpperValue());
		for (int row = 0; row < kPopulationSize; row++) {
			random_variable[row][col] = uniform_random(engine);
		}

	}
	for (int i = 0; i < kPopulationSize; i++) {
		double individual_variable[kVariableNum];
		for (int j = 0; j < kVariableNum; j++) {
			individual_variable[j] = random_variable[i][j];
		}
		Individual individual(individual_variable);
		now_population.push_back(individual);
	}

	cout << "initialize a population " << endl;
	for (int row = 0; row < kPopulationSize; row++) {
		if (row%5 == 0) {
			cout << "individual" << row + 1 << ":";
			for (int col = 0; col < kVariableNum; col++) {
				cout << "x" << col + 1 << " = " << random_variable[row][col];
			}
			cout << endl;
		}
	}  
	
}

//计算个体适应值.individual.fitness
//f(x1,x2) = 21.5+x1*sin(4pi*x1)+x2*sin(20pi*x2))为适应度计算函数
void CaculaFitnness() {
	double individual_fitness = 0;
	double individual_variable[kVariableNum];
	for (int row = 0; row < kPopulationSize; row++) {
		for (int col = 0; col < kVariableNum; col++) {
			individual_variable[col] = now_population.at(row).GetVaribaleValue()[col];//学习知识
		}
		individual_fitness = 21.5 + individual_variable[0] * sin(4 * kPI*individual_variable[0])
			+ individual_variable[1] * sin(20 * kPI*individual_variable[1]);
		now_population.at(row).ChangeFitness(individual_fitness);
	}
	//cout << "function CaculaFitnness runs end" << endl;
}

void CalculaFitnessProbability() {
	double sum_fitness = 0; //适应值累加和
	double temp = 0;
	for (int row = 0; row < kPopulationSize; row++) {
		sum_fitness += now_population.at(row).GetFitness();
	}
	for (int row = 0; row < kPopulationSize; row++) {
		temp = now_population.at(row).GetFitness() / sum_fitness;
		now_population.at(row).ChangeFitnessProbability(temp);
	}
	//cout << "function CalculaFitnessProbability runs end" << endl;
}
void CalculaSumFitnessProbability() {
	double current_sum_fitness_Pro = 0;
	for (int i = 0; i < kPopulationSize; i++) {
		current_sum_fitness_Pro += now_population.at(i).GetFitnessProbability();
		now_population.at(i).ChangeSumFitnessProbability(current_sum_fitness_Pro);
	}
	//cout << "function CalculaSumFitnessProbability runs end" << endl;
}
void SelectPopulation() {
	//随机生成0到1的小数
	double random_array[kPopulationSize];
	default_random_engine engine(time(0));
	uniform_real_distribution<double> uniform_random(0,1);
	
	for (int rounds = 0; rounds < kPopulationSize; rounds++) {
		for (int i = 1; i < kPopulationSize; i++) {
			if (random_array[rounds] < now_population.at(i - 1).GetSumFitnessProbability()) {
				mid_population.push_back(now_population.at(i - 1));
			}
			if (random_array[rounds] >= now_population.at(i - 1).GetSumFitnessProbability()
				&& random_array[rounds] <= now_population.at(i).GetSumFitnessProbability()) {
				mid_population.push_back(now_population.at(i));
			}
		}
		
	}
	now_population.clear();
	//cout << "number of mid_population:" << mid_population.size();
}
double Scand() {//随机产生0到1的小数
	int N = rand() % 999;
    return double(N) / 1000.0;//随机产生0到1的小数
}


void Hybridization() {
	int num = 0;  //记录次数
	double random_probability = 0.0;
	srand((unsigned)time(NULL));//根据系统时间设置随机数种子
	double father_arr[kVariableNum], mother_arr[kVariableNum];
	while (num < kPopulationSize) {
		random_probability = Scand();
		if (random_probability < kOverlappingProbability) {
			for (int i = 0; i < kVariableNum; i++) {
				father_arr[i] = mid_population.at(num).GetVaribaleValue()[i];
				mother_arr[i] = mid_population.at(num+1).GetVaribaleValue()[i];
			}
			int x1_overlap_pos, x2_overlap_pos;//记录基因交换位置
			int temp1[kLength1], temp2[kLength2];//基因交换临时数组
			double new_var1[2], new_var2[2];
			bool x1_over_scale = false;
			bool x2_over_scale = false;
			for (int j = 0; j < kVariableNum; j++) {
				//杂交个体的变量1
				if (j == 0) {
					bitset<kLength1> bit_arr1((father_arr[j] + 3.0) * pow(10,6));
					bitset<kLength1> bit_arr2((mother_arr[j] + 3.0) * pow(10,6));
					x1_overlap_pos = rand() % kLength1;//确定交叉位置
					//单点交叉
					for (int k = 0; k < x1_overlap_pos; k++) {
						temp1[k] = bit_arr1[k];
					}
					for (int k = 0; k < x1_overlap_pos; k++) {
						bit_arr1[k] = bit_arr2[k];
					}
					for (int k = 0; k < x1_overlap_pos; k++) {
						bit_arr2[k] = temp1[k];
					}
					new_var1[j] = double(bit_arr1.to_ullong()) / pow(10, 6) - 3.0;
					new_var2[j] = double(bit_arr1.to_ullong()) / pow(10, 6) - 3.0;
					//检查是否超出范围。
					if (new_var1[j] < x_range[j].GetLowerValue() || new_var1[j] > x_range[j].GetUpperValue()
						|| new_var2[j] < x_range[j].GetLowerValue() || new_var2[j] > x_range[j].GetUpperValue()) {
						x1_over_scale = true;
						break;
					}
				}
				//杂交个体的变量2
				if (j == 1) {
					bitset<kLength2> bit_father_x2((father_arr[j] + 3.0) * pow(10, 6));
					bitset<kLength2> bit_mother_x2((mother_arr[j] + 3.0) * pow(10, 6));
					x2_overlap_pos = rand() % kLength2;//确定交叉位置
					//单点交叉
					for (int k = 0; k < x2_overlap_pos; k++) {
						temp1[k] = bit_father_x2[k];
					}
					for (int k = 0; k < x2_overlap_pos; k++) {
						bit_father_x2[k] = bit_mother_x2[k];
					}
					for (int k = 0; k < x2_overlap_pos; k++) {
						bit_mother_x2[k] = temp1[k];
					}
					new_var1[j] = double(bit_father_x2.to_ullong()) / pow(10, 6) - 3.0;
					new_var2[j] = double(bit_mother_x2.to_ullong()) / pow(10, 6) - 3.0;
					//检查是否超出范围。
					if (new_var1[j] < x_range[j].GetLowerValue() 
						|| new_var1[j] > x_range[j].GetUpperValue()
						|| new_var2[j] < x_range[j].GetLowerValue() 
						|| new_var2[j] > x_range[j].GetUpperValue()) {
						x2_over_scale = true;
						break;
					}

				}
				/*/
				cout << " after hybridization " << num +1 << endl;
				cout << "individual1:"<< num <<" x1 = " << new_var1[0] << ", x2 = " << new_var1[1] << endl;
				cout << "individual1:"<< num +1 <<" x1 = " << new_var1[0] << ", x2 = " << new_var1[1] << endl;
				*/
			}
			if (x1_over_scale == false && x2_over_scale ==false) {
				Individual new_child1(new_var1);
				Individual new_child2(new_var2);
				next_population.push_back(new_child1);
				next_population.push_back(new_child2);
			}
			else {
				next_population.push_back(mid_population.at(num));
				next_population.push_back(mid_population.at(num + 1));
			}
		}
		else {
			next_population.push_back(mid_population.at(num));
			next_population.push_back(mid_population.at(num + 1));
		}
		num += 2;
	}
	mid_population.clear();
	//cout << next_population.size() << endl;
	/*/
	cout << "numbers of element in next_population is : " << next_population.size() << endl;
	for (int row = 0; row < kPopulationSize; row++) {
		if (row % 5 == 0) {
			cout << "individual" << row + 1 << ":";
			for (int col = 0; col < kVariableNum; col++) {
				cout << " x" << col + 1 << " = " <<next_population.at(row).GetVaribaleValue()[col];
			}
			cout << endl;
		}
	}
	*/
}
void Variation() {
	int num = 0;
	while (num < kPopulationSize) {
		double random_variation_probability = Scand();
		if (random_variation_probability < kVariationProbability) {
			double variable[2];
			bool is_over_scale = false;
			int x1_variation_pos, x2_variation_pos;
			variable[0] = next_population.at(num).GetVaribaleValue()[0];
			variable[1] = next_population.at(num).GetVaribaleValue()[1];
			bitset<kLength1> bit_arr1(((variable[0] + 3.0)* pow(10, 6)));
			bitset<kLength2> bit_arr2(((variable[0]) * pow(10, 6)));
			x1_variation_pos = rand() % kLength1;
			x2_variation_pos = rand() % kLength2;
			//新知识,改变位状态
			bit_arr1.flip(x1_variation_pos);
			bit_arr2.flip(x2_variation_pos);
			variable[0] = double(bit_arr1.to_ullong()) / pow(10, 6) - 3.0;
			variable[1] = double(bit_arr2.to_ullong()) / pow(10, 6);
			if (variable[0] < x_range[0].GetLowerValue()
				|| variable[0] > x_range[0].GetUpperValue()
				|| variable[1] < x_range[1].GetLowerValue()
				|| variable[1] > x_range[1].GetUpperValue()) {
				is_over_scale = true;
			}
			if (is_over_scale == false) {
				Individual individual(variable);
				now_population.push_back(individual);
			}
			if (is_over_scale == true) {
				now_population.push_back(next_population.at(num));
			}
		}
		else {
			now_population.push_back(next_population.at(num));

		}
		num++;
	}

	next_population.clear();
	//cout << now_population.size();

}


void GeneticAlgorithm() {
    Initialize(); //初始化种群
	
	for (int round = 0; round < kEvolutionAlgebra; round++) {
		if (round % 50 == 0) {
			cout << "round " << round << endl;

			CaculaFitnness(); //计算个体的适应值
			CalculaFitnessProbability();//计算个体的适应值概率
			CalculaSumFitnessProbability();//计算累加概率
			SelectPopulation();
			Hybridization();
			Variation();
		}
	}
	cout << "Evolution end" << endl;
	CaculaFitnness();
	double max_fitness = now_population.at(0).GetFitness();
	int max_fitness_individual_id;
	for (int k = 1; k < kPopulationSize; k++) {
		if (now_population.at(k).GetFitness() > max_fitness) {
			max_fitness = now_population.at(k).GetFitness();
			max_fitness_individual_id = k;
		}
	}
	//新知识点
	cout << "x1" << setw(10) << "x2" << setw(15) << "fitness" << endl;
	for (int k = 1; k < kPopulationSize; k++) {
		cout << now_population.at(k).GetVaribaleValue()[0] 
			<< setw(10) << now_population.at(k).GetVaribaleValue()[1]
			<< setw(10) << now_population.at(k).GetFitness() << endl;
	}
	cout << "x1=" << now_population.at(max_fitness_individual_id).GetVaribaleValue()[0] << ", " 
		 << "x2=" << now_population.at(max_fitness_individual_id).GetVaribaleValue()[1] 
		 << "when max fitness"<< max_fitness << endl;
}

GeneticAlgorithm.cpp

#pragma once //保证文件只被编译一次

#ifndef GENETICALGORUTHM_H
#define GENETICALGORUTHM_H
#include <random>
#include <vector>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <bitset>
#include <iomanip>  
using namespace std;

const double kPI = 3.14159;  //
const int kPopulationSize = 50; //种群规模
const int kEvolutionAlgebra = 500; //进化代数
const double kOverlappingProbability = 0.805; //交叉概率
const double kVariationProbability = 0.050; //变异概率
const int kLength1 = 24; //精确到6为小鼠,用24位二进制编码;
const int kLength2 = 23;
const int kVariableNum =  2; //变量个数
//自变量取值范围类,适用于多个变量
class VaribaleRange {
 public:
   VaribaleRange() {
     var_upper_bound_ = 1.0;
     var_lower_bound_ = 0.0;
   }
   VaribaleRange(double lower_value, double upper_value) {
     var_upper_bound_ = upper_value;
     var_lower_bound_ = lower_value;
   }
   double GetUpperValue() const;
   double GetLowerValue() const;
   void SetUpperValue(double upper_value);
   void SetLowerValue(double lower_value);

 private:
  double var_upper_bound_;
  double var_lower_bound_;

};

//定义个体类
class Individual {
 public:
  Individual() {}
  Individual(double* variable_vector);
  double* GetVaribaleValue();
  void ChangeFitness(const double& fitness);
  void ChangeFitnessProbability(const double& fitness_probability);
  void ChangeSumFitnessProbability(const double& sum_fitness_probability);
  double GetFitness();
  double GetFitnessProbability();
  double GetSumFitnessProbability();
  void PrintVariableValue();
 private:
  double variable_[kVariableNum];//存放变量x1,x2
  double fitness_; //个体适应值
  double fitness_probability_;//适应值概率
  double sum_fitness_probability_;//总适应值概率
};

void Initialize();//随机初始化种群,得到第一代个体
void CaculaFitnness(); //计算个体的适应值
void CalculaFitnessProbability();//计算个体的适应值概率
void CalculaSumFitnessProbability();//计算累加概率
void SelectPopulation(); //选择种群
void Hybridization(); //杂交
void Variation(); //变异
void GeneticAlgorithm(); //遗传算法

double Scand();
#endif

main.cpp

#include "GeneticAlgorithm.h"
int main() {
  //1.test class VariableRange
    /*
    VaribaleRange x_range(-1, 2);
    cout << "upper = " << x_range.GetUpperValue() << endl;
    cout << "lower = " << x_range.GetLowerValue() << endl;
  */
  //2/test class Individual
	/*
	double arr1[2] = { 1.1, 4.5 };
	Individual individual1(arr1);
	individual1.PrintVariableValue();
    */
	GeneticAlgorithm();
	system("pause");
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值