GA(C++代码实现)——背包问题

GA(C++代码实现)——背包问题

引用博客:https://www.cnblogs.com/suchang/p/10550181.html

本文是在上面那篇博客的基础上用遗传算法解决背包问题,并用C++加以实现。
遗传算法的具体讲解因为时间有限,暂时不加解释,网上也有很多,大家也可以看看上面那篇博客。
然后我就只展示一下代码。因为我还只是个C++小白,如果大家有什么问题可以在评论区讨论交流,谢谢大家。
主函数

#include"GA.h"
using namespace std;

int main()
{
	genetic_algorithm();
	system("pause");
}

头文件

#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<fstream>
#include<regex>
#include<random>
#include<iomanip>
using namespace std;

const int NP = 100;  //种群规模
const int L = 10;   //物品件数
const double Pc = 0.8;//交叉率
const double Pm = 0.05;//变异率
const int G = 1000;  //最大遗传代数
const int V = 300;  //背包容量
const int afa = 2;  //惩罚函数系数


class Individual //定义个体类
{
private:
	bool gene[L];//基因值
	double fitness;//适应值
	double Rfitness;//适应值概率
	double Sumfitness;//累加概率
public:
    Individual();
    Individual(bool* m_Variable);//默认构造函数
    //Individual(double* m_Variable);//构造函数
    bool* Getgene();//获取变量值
    void Chafitness(const double m_fitness);//修改适应值
    void ChaRfitness(const double m_ReFitness);//修改适应值概率
    void ChaSumfitness(const double m_SumFitness);//修改累加概率
    double Getfitness()const;//获取适应值
    double GetRfitness()const;//获取适应值概率
    double GetSumfitness()const;//获取累加概率
    ~Individual(); //析构函数
};
void input();//读取文件
void Initialize();//随机初始化种群,得到第一代个体
void CaculaFitness();//计算个体的适应值
void CaculaReFitness();//计算个体的适应值概率
void CalculaSumFitness();//计算累加个体概率
void seclect();//种群选择
double Scand();//随机产生0到49的随机整数
void crossing();//杂交
void variating();//变异
void genetic_algorithm();//遗传算法

我之所以加了一个读取文件的一个函数,是因为我觉得大家有些数据很庞大,可能是.data,.txt这样的文件,如果不需要读文件的同学最好也把自己的 数据存到一个.txt文件中来运行,否则改动会很大。
GA.cpp

#include"GA.h"

vector<vector<int>> C; //存放物品体积和价值
vector<int> temp_line;
string line;
vector<Individual> nowpopulation;//P(t)种群
vector<Individual> midpopulation;//中间种群,存放轮盘选择后的优秀个体
vector<Individual> nextpopulation;//P(t+1)种群


Individual::Individual()
{

}
Individual::Individual(bool* m_Variable)
{
	//初始化时默认适应值等值为0
	for (int i = 0; i < L; i++)
	{
		gene[i] = m_Variable[i];
	}
	this->fitness = 0;
	this->Rfitness = 0;
	this->Sumfitness = 0;
}
bool* Individual::Getgene()//获取基因值
{
    return gene;
}
double Individual::Getfitness()const//获取适应值
{
    return fitness;
}
double Individual::GetRfitness()const //获取适应值概率
{
    return Rfitness;
}
double Individual::GetSumfitness()const//获取累加概率
{
    return Sumfitness;
}
void Individual::Chafitness(const double m_fitness)//修改适应值
{
    this->fitness = m_fitness;
}
void Individual::ChaRfitness(const double m_ReFitness)//修改适应值概率
{
    this->Rfitness = m_ReFitness;
}
void Individual::ChaSumfitness(const double m_SumFitness)//修改累加概率
{
    this->Sumfitness = m_SumFitness;
}
Individual::~Individual()
{

}

//读取文件
void input()
{
	ifstream in("package.txt");  //读入文件
	regex pat_regex("[[:digit:]]+");  //匹配原则,这里代表一个或多个数字
	while (getline(in, line))
	{  //按行读取
		for (sregex_iterator it(line.begin(), line.end(), pat_regex), end_it; it != end_it; ++it) {  //表达式匹配,匹配一行中所有满足条件的字符
			cout << it->str() << " ";  //输出匹配成功的数据
			temp_line.push_back(stoi(it->str()));  //将数据转化为int型并存入一维vector中
		}
		cout << endl;
		C.push_back(temp_line);  //保存所有数据
		temp_line.clear();
	}
}

//随机初始化种群,得到第一代个体
void Initialize()
{
	bool X1[NP][L];//使用矩阵保存随机数的变量值
	for (int i = 0; i < NP; i++)
	{
		bool tempL[L];
		for (int j = 0; j < L; j++)
		{
			X1[i][j] = rand() % 2;
			tempL[j] = X1[i][j];
			//cout << tempL[j] << " ";
		}
		//cout << endl;
		Individual V1(tempL);//通过有参构造函数输入类中,形成一个染色体
		nowpopulation.push_back(V1);
	}
}

//计算个体的适应值
void CaculaFitness()
{
	int X2[L];
	for (int i = 0; i < NP; i++)
	{
		double tempF = 0;
		double Totalsize = 0;
		for (int j = 0; j < L; j++)
		{
			X2[j] = nowpopulation.at(i).Getgene()[j];
			tempF += X2[j]*C[1][j];
			Totalsize += X2[j] * C[0][j];
		}
		if (Totalsize <= V)
		{
			nowpopulation.at(i).Chafitness(tempF);
		}
		else
		{
			tempF = tempF - afa * (Totalsize - V);
		}
		nowpopulation.at(i).Chafitness(tempF);
	}
}

//计算个体的适应值概率
void CaculaReFitness()
{
	double tempsum = 0;//适应值累加器
	double tempf = 0;
	for (int i = 0; i < NP; i++)//计算出适应值之和
	{
		tempsum += nowpopulation.at(i).Getfitness();
	}
	for (int j = 0; j < L; j++)
	{
		tempf = nowpopulation.at(j).Getfitness() / tempsum;//计算概率
		nowpopulation.at(j).ChaRfitness(tempf);//修改个体的适应度概率
	}
}

//计算累加个体概率
void CalculaSumFitness()
{
	double summation = 0;//累加器
	for (int k = 0; k < NP; k++)
	{
		summation += nowpopulation.at(k).GetRfitness();
		nowpopulation.at(k).ChaSumfitness(summation);//当前累加结果赋值
	}
}

//种群选择
void seclect()
{
	//随机生生成0到1的小数
	double array[NP];//随机数保存变量
	default_random_engine e(time(0));//引擎,生成随机序列,#include<random>
	uniform_real_distribution<double> u(0.0, 1.0); //分布 #include<random>
	for (int i = 0; i < NP; i++)
		array[i] = u(e);
	for (int i = 0; i < NP; i++)
	{
		for (int j = 1; j < NP; j++)
		{
			if (array[i] < nowpopulation[j - 1].GetSumfitness())
			{
				midpopulation.push_back(nowpopulation.at(j - 1));//加入中间种群
			}
			if (array[i] >= nowpopulation.at(j - 1).GetSumfitness() && array[i] <= nowpopulation.at(j).GetSumfitness())
			{
				midpopulation.push_back(nowpopulation.at(j));//加入中间种群
			}
		}
	}
	nowpopulation.clear();//清空nowpopulation
}

随机产生0到1的数
double Scand()
{
	int N = rand() % 999;
	return double(N) / 1000.0;;//随机产生0到1的小数
}

//杂交
void crossing()
{
	int num = 0;//记录次数
	double corss = 0.0;//保存随机产生的概率值
	srand((unsigned)time(NULL));//根据系统时间设置随机数种子,设置一次随机种子就行
	bool array1[L], array2[L];//临时存储父亲和母亲的变量值
	while (num < NP - 1)
	{
		corss = Scand();
		if (corss < Pc)
		{
			bool tempL[L];  //生成一个随机的基因
			bool tempc;     //随机的点
			for (int i = 0; i < L; i++)
			{
				tempL[i] = rand() % 2;
			}
			for (int i = 0; i < L; i++)
			{
				array1[i] = midpopulation.at(num).Getgene()[i];      //父亲的自变量
				array2[i] = midpopulation.at(num + 1).Getgene()[i];  //母亲自变量
			}
			for (int j = 0; j < L; j++)
			{
				if (tempL[j]==1)   //进行单点交叉
				{
					tempc = array2[j];
					array2[j] = array1[j];
					array1[j] = tempc;
				}
			}
			Individual V2(array1);
			Individual V3(array2);
			nextpopulation.push_back(V2);
			nextpopulation.push_back(V3);
		}
		else//否则直接遗传给下一代nextpopulation
		{
			nextpopulation.push_back(midpopulation.at(num));//生成一个新的个体并且加入到nextpopulation中
			nextpopulation.push_back(midpopulation.at(num + 1));
		}
		num += 2;
	}
	midpopulation.clear();//清空midpopulation
}

//变异
void variating()
{
	int num = 0;
	while (num < NP)
	{
		bool array3[L];
		for (int i = 0; i < L; i++)
		{
			array3[i] = nextpopulation.at(num).Getgene()[i];
		}
		for (int j = 0; j < L; j++)
		{
			double vari = Scand();
			if (vari < Pm)
			{
				if (array3[j])
				{
					array3[j] == 0;
				}
				else
				{
					array3[j] == 1;
				}
			}
		}
		Individual V4(array3);
		nowpopulation.push_back(V4);
		num++;
	}
}
//测试函数
void test01(int k)
{
	cout << setw(10) << "属性值" << setw(20) << "Fitness" << endl;
	for (int i = 0; i < NP; i++)
	{
		for (int j = 0; j < L; j++)
		{
			cout << nowpopulation.at(i).Getgene()[j] << " ";
		}
		cout <<setw(8)<< nowpopulation.at(i).Getfitness() << " " << endl;
	}
	cout << "最优策略:";
	for (int j = 0; j < L; j++)
	{
		cout << nowpopulation.at(k).Getgene()[j] << " ";
	}
	cout << endl;
	cout << "maxFitness:" << nowpopulation.at(k).Getfitness() << endl;
}
//遗传算法
void genetic_algorithm()
{
	input();
	Initialize();//初始化种群,随机生成第一代个体
	//进化500代
	for (int i = 0; i < G; i++)
	{
		CaculaFitness();//适应度计算
		CaculaReFitness();//适应度概率计算
		CalculaSumFitness();//计算累加个体概率
		seclect();//选择
		crossing();//杂交
		variating();//变异
	}
	CaculaFitness();//适应度计算
	double maxfitness = nowpopulation.at(0).Getfitness();
	int maxid = 0;
	int k;
	for (k = 0; k < NP; k++)
	{
		if (maxfitness < nowpopulation.at(k).Getfitness())
		{
			maxfitness = nowpopulation.at(k).Getfitness();
			maxid = k;
		}
	}
	test01(maxid);
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值