二次分配问题(遗传算法求解)
2023-12-27 22:12:52
    		遗传算的思想和求解方式,请移步看博客遗传算法(GA)概述_遗传算法提供了一种求解复杂系统优化问题的通用框架,不依赖于问题的具体领域-CSDN博客
QAP 的解决思想可以概括为以下步骤:
编码表示:设计一个适当的编码方式来表示问题的解。在 QAP 中,可以使用排列(permutation)来表示物体的分配方案。每个位置上的值代表物体在目标位置上的分配情况。
初始种群生成:使用随机方式或启发式方法生成初始种群。初始种群由一组个体组成,每个个体都是问题解的一个可能方案(即一个排列)。
适应度评估:根据问题的目标函数(成本函数或距离函数)计算每个个体的适应度值。适应度值表示个体在问题中的优劣程度。
选择操作:使用选择算子(如轮盘赌选择、锦标赛选择等)从当前种群中选择一部分个体作为父代,用于产生下一代的后代。
交叉操作:通过交叉操作(如单点交叉、多点交叉等),将选中的父代个体组合生成新的后代个体。
变异操作:对新生成的后代个体进行变异操作,引入随机性,以增加搜索空间的探索能力。
更新种群:根据选择、交叉和变异操作生成的后代个体,更新当前种群,形成下一代种群。
终止条件判断:检查是否满足终止条件,如达到最大迭代次数、适应度达到目标值等。如果满足条件,算法终止;否则,返回第4步。
输出结果:根据终止条件确定的最优个体,作为最终的解决方案输出。
代码方面依然使用了上篇文章所使用的类的思想,代码如下
#ifndef GA_SEARCH_H
#define GA_SEARCH_H
#include "QAPSolver.h"
class GASearch : public QAPSolver
{
public:
    GASearch(const std::vector<std::vector<int>>& flowMatrix_, const std::vector<std::vector<int>>& distanceMatrix_) : QAPSolver(flowMatrix_, distanceMatrix_) {};
    void execute() override;
    /// <summary>
    /// 初始化参数
    /// </summary>
    /// <param name="popSize_">种群大小</param>
    /// <param name="maxIterations_">最大迭代次数</param>
    /// <param name="mutationRate_">变异概率</param>
    void init(int popSize_, int maxIterations_, double mutationRate_,double crossoverRate_,int tournamentSize_);
private:
    int popSize; // 种群大小
    int maxIterations; // 最大迭代次数
    int tournamentSize;
    double mutationRate; // 变异概率
    double crossoverRate;
    // 设计种群
    struct Individual
    {
        // 排列方式
        std::vector<int> permutation;
        //适应度
        int fitness;
        Individual() :fitness(0) {}
    };
    // 初始化种群
    std::vector<Individual> init_population();
    //变异操作
    void mutation(Individual& individual);
    /// <summary>
    /// 在群落中寻找最佳解
    /// </summary>
    /// <param name="populations"></param>
    void findBestIndividual(const std::vector<Individual>& populations);
    // 交叉操作
    Individual crossover(const Individual& parent1, const Individual& parent2);
    // 选择操作 使用的时锦标赛
    Individual tournamentSelection(const std::vector<Individual>& populations);
    // 更新种群
    std::vector<Individual> updatePopulation(const std::vector<Individual>& populations);
};
#endif // !GA_SEARCH_H
.cpp文件如下
#include "GASearch.h"
void GASearch::execute()
{
	
	std::vector<Individual> populations =  init_population();
	for (int index = 0; index < maxIterations; index++)
	{
		for (auto& individual : populations)
		{
			individual.fitness = calculateCost(individual.permutation);
		}
		populations = updatePopulation(populations);
	}
	findBestIndividual(populations);
}
void GASearch::init(int popSize_, int maxIterations_, double mutationRate_, double crossoverRate_, int tournamentSize_)
{
	popSize = popSize_;
	maxIterations = maxIterations_;
	mutationRate = mutationRate_;
	crossoverRate = crossoverRate_;
	tournamentSize = tournamentSize_;
}
std::vector<GASearch::Individual> GASearch::init_population()
{
	std::vector<Individual> populations(popSize);
	for (auto& individual : populations)
	{
		individual.permutation.resize(dimension);
		std::iota(individual.permutation.begin(), individual.permutation.end(), 0);
		std::shuffle(individual.permutation.begin(), individual.permutation.end(), gen);
	}
	return populations;
}
void GASearch::mutation(Individual& individual)
{
	std::uniform_int_distribution<int> indexDist(0, dimension - 1);
	for (int i = 0; i < dimension; i++)
	{
		if (rand01() < mutationRate)
		{
			int index1 = indexDist(gen);
			int index2 = indexDist(gen);
			std::swap(individual.permutation[index1], individual.permutation[index2]);
		}
	}
	
}
void GASearch::findBestIndividual(const std::vector<Individual>& populations)
{
	Individual bestIndividual;
	for (const auto& individual : populations) {
		if (bestIndividual.fitness == 0 || individual.fitness < bestIndividual.fitness) {
			bestSolution = individual.permutation;
		}
	}
}
GASearch::Individual GASearch::crossover(const Individual& parent1, const Individual& parent2)
{
	std::uniform_int_distribution<int> indexDist(0, dimension - 1);
	int index1 = indexDist(gen);
	int index2 = indexDist(gen);
	if (index1 > index2) {
		std::swap(index1, index2);
	}
	Individual child;
	child.permutation.resize(dimension);
	std::vector<int> mapping(dimension, -1);
	for (int i = index1; i <= index2; ++i) {
		child.permutation[i] = parent1.permutation[i];
		mapping[parent1.permutation[i]] = parent2.permutation[i];
	}
	for (int i = 0; i < dimension; ++i) {
		if (i >= index1 && i <= index2) {
			continue;
		}
		int allele = parent2.permutation[i];
		while (mapping[allele] != -1) {
			allele = mapping[allele];
		}
		child.permutation[i] = allele;
	}
	return child;
}
GASearch::Individual GASearch::tournamentSelection(const std::vector<Individual>& populations)
{
	std::uniform_int_distribution<int> indexDist(0, populations.size() - 1);
	Individual bestIndividual;
	for (int i = 0; i < tournamentSize; i++)
	{
		int index = indexDist(gen);
		const Individual& condidate = populations[index];
		if (bestIndividual.fitness == 0 || condidate.fitness < bestIndividual.fitness)
		{
			bestIndividual = condidate;
		}
	}
	return bestIndividual;
}
std::vector<GASearch::Individual> GASearch::updatePopulation(const std::vector<Individual>& populations)
{
	//定义新的种群群
	std::vector<Individual> newPoulations;
	while (newPoulations.size() < popSize)
	{
		Individual parent1 = tournamentSelection(populations);
		if (rand01() < crossoverRate)
		{
			Individual parent2 = tournamentSelection(populations);
			Individual child = crossover(parent1, parent2);
			mutation(child);
			child.fitness = calculateCost(child.permutation);
			newPoulations.push_back(child);
		}
		else
		{
			newPoulations.push_back(parent1);
		}
		return newPoulations;
	}
}
运行结果
    			文章来源:https://blog.csdn.net/qq_39591612/article/details/135255223
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
    	本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!