diff --git a/src/GeneticAlgorithm/ChromosomeFactory.cpp b/src/GeneticAlgorithm/ChromosomeFactory.cpp index 8a14fa78a75f430c46328df2fde0747f3a80d8b6..7f02ae81e58830c185d1d023a5619aca37ac2807 100644 --- a/src/GeneticAlgorithm/ChromosomeFactory.cpp +++ b/src/GeneticAlgorithm/ChromosomeFactory.cpp @@ -31,4 +31,12 @@ namespace GeneticAlgorithm { return new Chromosome(lengthOfData); } + Chromosome* ChromosomeFactory::buildFromChromosome(Chromosome* existsChromosome) { + Chromosome* result = this->buildEmpty(existsChromosome->getLength()); + for (unsigned long i = 0; i < result->getLength(); i++) { + result->setGene(i, existsChromosome->getGene(i)); + } + return result; + } + } diff --git a/src/GeneticAlgorithm/ChromosomeFactory.h b/src/GeneticAlgorithm/ChromosomeFactory.h index ab27e75db5f3e368e4bbc13cf9e038563d617ad5..330992c3d1bf43ba702fbabebc0abb38eaee652f 100644 --- a/src/GeneticAlgorithm/ChromosomeFactory.h +++ b/src/GeneticAlgorithm/ChromosomeFactory.h @@ -42,6 +42,14 @@ namespace GeneticAlgorithm { */ Chromosome* buildEmpty(unsigned long lengthOfData); + /** + * 拷贝式创建 + * + * @param Chromosome* existsChromosome + * @return Chromosome* + */ + Chromosome* buildFromChromosome(Chromosome* existsChromosome); + }; } diff --git a/src/GeneticAlgorithm/MainProcess.cpp b/src/GeneticAlgorithm/MainProcess.cpp index b729bf8be3b666c5d05fbcc842537dab0b59bc4d..991374ffe6c84bfc421bf3d6ddb8bbd01c820e79 100644 --- a/src/GeneticAlgorithm/MainProcess.cpp +++ b/src/GeneticAlgorithm/MainProcess.cpp @@ -60,6 +60,49 @@ namespace GeneticAlgorithm { } } + void MainProcess::runContinue( + unsigned long maxLoop, // 这一次的最大迭代次数 + long double stopFitness, // 达到多大的适应度就立刻停止迭代 + unsigned long keep, // 每次迭代保留多少个上一代的个体 + long double r // 基因突变的概率 + ) { + using namespace std; + if (nullptr == this->population || nullptr == this->selectedChromosome || nullptr == this->newChromosome) { + return; + } + if (1 == this->keep && keep > 1) { // 之前是keep=1的话,会因为优化而不会排序 + this->keep = keep; + this->sort(); // 先排序避免后满淘汰掉较优解 + } else { + this->keep = keep; + } + this->kill = this->numberOfChromosome - keep; + // 尺寸发生变化,删除旧的再申请新空间 + delete[] this->selectedChromosome; + delete[] this->newChromosome; + this->selectedChromosome = new Chromosome*[2 * this->kill]; + this->newChromosome = new Chromosome*[this->kill]; + this->r = r; + unsigned long i = 0; + while (i < maxLoop && this->maxFitness < stopFitness) { + this->select(); + this->crossover(); + this->mutation(); + this->generated(); + this->sort(); + this->maxFitness = this->population->getMaxFitnessChromosome()->getFitness(); + this->loopNow++; + if (this->debug) { + cout << "代数=" << this->loopNow << ", 最大适应度=" << this->maxFitness << ", 个体信息="; + this->population->getMaxFitnessChromosome()->dump(); + } + i++; + } + if (this->debug) { + cout << "结束。" << endl; + } + } + void MainProcess::setDebug(bool enableDebug) { this->debug = enableDebug; } @@ -72,6 +115,20 @@ namespace GeneticAlgorithm { return this->maxFitness; } + Chromosome* MainProcess::getMaxFitnessChromosome() { + return this->population->getMaxFitnessChromosome(); + } + + void MainProcess::replaceChromosome(Chromosome* chromosome) { + Chromosome* max = this->population->getMaxFitnessChromosome(); + for (unsigned long offset = this->numberOfChromosome - 1; offset + 2 > 1; offset--) { + if ((void*)this->population->getChromosome(offset) != (void*)max) { + this->population->replaceChromosome(offset, chromosome); + return; + } + } + } + void MainProcess::init() { this->population = PopulationFactory().buildRandomPopulation(this->numberOfChromosome, this->lengthOfChromosome, this->min, this->max); this->loopNow = 0; diff --git a/src/GeneticAlgorithm/MainProcess.h b/src/GeneticAlgorithm/MainProcess.h index d8d886f235ddec9cf438a6d861c09f392c3783ce..3820743b2e4c0539afeedf7e7a6747e06214963d 100644 --- a/src/GeneticAlgorithm/MainProcess.h +++ b/src/GeneticAlgorithm/MainProcess.h @@ -28,14 +28,23 @@ namespace GeneticAlgorithm { unsigned long keep, // 每次迭代保留多少个上一代的个体 long double r // 基因突变的概率 ); - + // 继续运行 + void runContinue( + unsigned long maxLoop, // 这一次的最大迭代次数 + long double stopFitness, // 达到多大的适应度就立刻停止迭代 + unsigned long keep, // 每次迭代保留多少个上一代的个体 + long double r // 基因突变的概率 + ); // 设置debug模式,为true的时候打印调试信息 void setDebug(bool enableDebug); // 获取迭代次数。如果在一开始初始化的那代种群就达到停止的条件,那么返回0 unsigned long getLoopNumber(); // 获取最大的适应度 long double getMaxFitness(); - + // 获取Fitness最大值的Chromosome + Chromosome* getMaxFitnessChromosome(); + // 替换一个不是最好的个体为指定的个体 + void replaceChromosome(Chromosome* chromosome); private: // 染色体or个体的数量 unsigned long numberOfChromosome; diff --git a/src/GeneticAlgorithm/Multithreading.cpp b/src/GeneticAlgorithm/Multithreading.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3019de6d9ad366052f365029f06446f29c521fc1 --- /dev/null +++ b/src/GeneticAlgorithm/Multithreading.cpp @@ -0,0 +1,132 @@ +#include "MainProcess.h" +#include "Multithreading.h" +#include "Chromosome.h" +#include "ChromosomeFactory.h" +#include "Utils/GlobalCppRandomEngine.h" +#include +#include + +namespace GeneticAlgorithm { + + Multithreading::Multithreading(unsigned long threadNumber) { + if (threadNumber < 1) { + throw "threadNumber < 1"; + } + this->threadNumber = threadNumber; + this->process = new MainProcess*[threadNumber]; + for (unsigned long i = 0; i < threadNumber; i++) { + this->process[i] = new MainProcess(); + } + } + + Multithreading::~Multithreading() { + for (unsigned long i = 0; i < this->threadNumber; i++) { + delete this->process[i]; + } + delete[] process; + } + + void Multithreading::run( + unsigned long numberOfChromosome, + unsigned long lengthOfChromosome, + long double min, + long double max, + unsigned long maxLoop, + long double stopFitness, + unsigned long keep, + long double r + ) { + using namespace std; + jthread** threads = new jthread*[this->threadNumber]; + for (unsigned long i = 0; i < this->threadNumber; i++) { + threads[i] = new jthread([]( + MainProcess* process, + unsigned long numberOfChromosome, + unsigned long lengthOfChromosome, + long double min, + long double max, + unsigned long maxLoop, + long double stopFitness, + unsigned long keep, + long double r + ) { + process->run(numberOfChromosome, lengthOfChromosome, min, max, maxLoop, stopFitness, keep, r); + }, this->process[i], numberOfChromosome, lengthOfChromosome, min, max, maxLoop, stopFitness, keep, r); + } + for (unsigned long i = 0; i < this->threadNumber; i++) { + delete threads[i]; + } + delete[] threads; + } + + void Multithreading::runContinue( + unsigned long maxLoop, // 这一次的最大迭代次数 + long double stopFitness, // 达到多大的适应度就立刻停止迭代 + unsigned long keep, // 每次迭代保留多少个上一代的个体 + long double r // 基因突变的概率 + ) { + using namespace std; + jthread** threads = new jthread*[this->threadNumber]; + for (unsigned long i = 0; i < this->threadNumber; i++) { + threads[i] = new jthread([]( + MainProcess* process, + unsigned long maxLoop, + long double stopFitness, + unsigned long keep, + long double r + ) { + process->runContinue(maxLoop, stopFitness, keep, r); + }, this->process[i], maxLoop, stopFitness, keep, r); + } + for (unsigned long i = 0; i < this->threadNumber; i++) { + delete threads[i]; + } + delete[] threads; + } + + void Multithreading::exchange() { + if (1 == this->threadNumber) { + return; + } + ChromosomeFactory factory = ChromosomeFactory(); + Chromosome** chromosomeData = new Chromosome*[this->threadNumber]; + for (unsigned long i = 0; i < this->threadNumber; i++) { + chromosomeData[i] = factory.buildFromChromosome(this->process[i]->getMaxFitnessChromosome()); + } + unsigned long select; + Chromosome* tmp; + for (unsigned long i = 0; i < this->threadNumber - 1; i++) { + std::uniform_int_distribution ran(i, this->threadNumber - 1); + select = ran(Utils::GlobalCppRandomEngine::engine); + tmp = chromosomeData[select]; + chromosomeData[select] = chromosomeData[i]; + chromosomeData[i] = tmp; + } + for (unsigned long i = 0; i < this->threadNumber; i++) { + this->process[i]->replaceChromosome(chromosomeData[i]); + } + delete[] chromosomeData; + } + + void Multithreading::setDebug(bool enableDebug) { + for (unsigned long i = 0; i < this->threadNumber; i++) { + this->process[i]->setDebug(enableDebug); + } + } + + unsigned long Multithreading::getLoopNumber() { + return this->process[0]->getLoopNumber(); + } + + long double Multithreading::getMaxFitness() { + long double f = this->process[0]->getMaxFitness(); + long double tmp; + for (unsigned long i = 1; i < this->threadNumber; i++) { + tmp = this->process[i]->getMaxFitness(); + if (tmp > f) { + f = tmp; + } + } + return f; + } +} diff --git a/src/GeneticAlgorithm/Multithreading.h b/src/GeneticAlgorithm/Multithreading.h new file mode 100644 index 0000000000000000000000000000000000000000..2cd02b489def67685037eff5c7630c53dbcc52f2 --- /dev/null +++ b/src/GeneticAlgorithm/Multithreading.h @@ -0,0 +1,55 @@ +#ifndef GENETICALGORITHM_MULTITHREADING_H +#define GENETICALGORITHM_MULTITHREADING_H + +#include "MainProcess.h" +#include "Multithreading.h" + +namespace GeneticAlgorithm { + + /** + * 多线程主流程 + */ + class Multithreading { + public: + // 构造方法 + Multithreading(unsigned long threadNumber); + // 销毁对象 + ~Multithreading(); + + // 主流程运行 + void run( + unsigned long numberOfChromosome, // 种群中个体数量 + unsigned long lengthOfChromosome, // 每个个体的基因长度 + long double min, // 一开始初始种群时,随机数范围最小值 + long double max, // 一开始初始种群时,随机数范围最大值 + unsigned long maxLoop, // 最大迭代次数 + long double stopFitness, // 达到多大的适应度就立刻停止迭代 + unsigned long keep, // 每次迭代保留多少个上一代的个体 + long double r // 基因突变的概率 + ); + // 继续运行 + void runContinue( + unsigned long maxLoop, // 这一次的最大迭代次数 + long double stopFitness, // 达到多大的适应度就立刻停止迭代 + unsigned long keep, // 每次迭代保留多少个上一代的个体 + long double r // 基因突变的概率 + ); + // 种群间最好个体随机复制性交换 + void exchange(); + // 设置debug模式,为true的时候打印调试信息 + void setDebug(bool enableDebug); + // 获取迭代次数。如果在一开始初始化的那代种群就达到停止的条件,那么返回0 + unsigned long getLoopNumber(); + // 获取最大的适应度 + long double getMaxFitness(); + + private: + // 线程数 + unsigned long threadNumber; + // MainProcess对象 + MainProcess** process = nullptr; + }; + +} + +#endif diff --git a/src/main.cpp b/src/main.cpp index 9b6fde4bdfb0ca356f3778085b575b7d0d6322d6..5dbea1895d3df3f1084e5e9ff0a9248063f7ff98 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,3 +27,30 @@ int main() ); return 0; } + +/* 多线程版本使用示例 + +int main() +{ + Multithreading mainProcess = Multithreading(4); + mainProcess.setDebug(false); + mainProcess.run( + 50, // 种群大小 + 2, // 染色体长度 + -2.048, // 初始范围 + 2.048, // 初始范围 + 0, // 最大迭代次数 + 99.9999, // 停止迭代适应度 + 5, // 每次迭代保留多少个上一代的高适应度个体 + 0.015 // 变异概率,随便变动范围系数 + ); + cout << "Max fitness=" << mainProcess.getMaxFitness() << endl; + for (int i = 0; i < 100; i++) { + //mainProcess.exchange(); + mainProcess.runContinue(50, 99.9999, 5, 0.015); + cout << i << ",Max fitness=" << mainProcess.getMaxFitness() << endl; + } + return 0; +} + +*/