- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
首先,我不想问这样一个含糊不清的问题,但我已经无计可施了。我正在尝试为旅行商经典 CS 问题制作遗传算法。
我已尝试很好地注释我的代码,以使每个步骤都清楚地表明我正在尝试做什么。
我有一个包含城市索引和 x,y 坐标的结构节点对象。我正在从文件中读取城市列表,并将结构节点的数组和它们的数量传递给我的函数。
如有任何疑问,欢迎提问。 gui 每大约 1000 次迭代更新一次,它肯定会发生变化,但似乎永远不会变得更好,即使我运行了很长时间的世代数也是如此!
此外,如果您感到困惑,我将距离作为 uint64_t 返回,以获得比 double 更好的准确性和可移植性,但在执行适应度函数时我将它们转换为 double 类型。 (这一切都有效,我已经验证过了)
关于为什么它不会变得更好,你能找出任何错误吗?
void GeneticAlgorithm(struct Node *cities, uint64_t *count)
{
//1 - pick initial random permutations for the population size
int populationSize =(*count)>10? ((*count)/5) : *count;
fprintf(stderr, "Population Size: %d\n", populationSize);
//population consists of populationSize elements (an element being a path)
struct Node population[populationSize][*count];
srand (time(NULL));
//Get Initial Paths
uint64_t i;
//iterate over pop. size
for(i=0; i<populationSize; i++){
//fill out path for each population
int j;
for(j=0; j<*count; j++){
int element = rand() % (int)(*count); // 0-count
while(hasBeenVisited(&cities[element]) == 0){
element = rand() % (int)(*count);
}
memcpy ( &(population[i][j]), &(cities[element]), sizeof(struct Node) );
setVisited(&cities[element]);
}
for(j=0;j<*count; j++){
(&cities[j])->visited = 0;
}
}
int j;
//Now, we have our population of randomly selected paths
struct Node children[populationSize][*count];
int generation, crossover;
uint64_t Distances[populationSize];
uint64_t TotalDistance = 0;
srand(time(NULL));
//Iterate over each generation. Basic idea is to do fitness function, generate
//probability for each, do selection and fill up children array until it has
//the same populationSize elements as original population, perhaps do a mutation,
//and replace population array.
for(generation=0; generation < 5; generation++){
/* Get Distance of Each Path and Total Sum of Distances */
TotalDistance = 0;
for(j=0; j<populationSize; j++){
Distances[j] = 0;
for(i=0; i<*count; i++){
if(i==((*count)-1)){
Distances[j] += distance(&(population[j][0]), &(population[j][i]));
}
else{
Distances[j] += distance(&(population[j][i]), &(population[j][i+1]));
}
}
TotalDistance += Distances[j];
}
/* FITNESS FUNCTION */
//Evaluate each of the population according to the fitness function (distance through the path)
double probability[*count];
double sumProbabilities = 0.0;
char tempDistanceString[32];
trimUintDigits(&TotalDistance);
uintcharf(tempDistanceString, TotalDistance);
double dTotalDistance = strtod(tempDistanceString, NULL);
for(i=0; i<populationSize; i++){
char buf[32];
//Distances are uint64_t, need to ensure 7 decimal place accuracy (trimuint does this)
//and uintcharf converts to a decimal representation in a string
trimUintDigits(&Distances[i]);
uintcharf(buf, Distances[i]);
double individualDistance = strtod(buf, NULL);
probability[i] = sumProbabilities + (individualDistance / totalDistance);
sumProbabilities += probability[i];
}
//set children to all 0 (will replace population)
memset(&children, 0, sizeof(struct Node)*populationSize*(*count));
double r;
int numChildren = 0;
//Iterate until number of children = current population size
while(numChildren < populationSize){
//0 <= r <=1
r = ((double) rand() / (RAND_MAX));
if(r>0.7){ //Doesn't always crossover!
memcpy(&children[numChildren], &population[numChildren], sizeof(struct Node) * (*count));
numChildren++;
continue;
}
r = ((double) rand() / (RAND_MAX));
r *= sumProbabilities;
double nextProb = 0;
//Pick the two parents for procreation, according to the roulette wheel probability
int par1=-1, par2=-1;
while(par1==-1){
for(i=0; i<populationSize; i++){
if(i==populationSize-1){
nextProb=probability[0];
}
else{
nextProb = probability[i+1];
}
if((r > probability[i]) && (r < nextProb)){
par1 = i;
break;
}
}
r = ((double) rand() / (RAND_MAX));
r *= sumProbabilities;
}
r = ((double) rand() / (RAND_MAX));
r*= sumProbabilities;
while(par2==-1){
for(i=0; i<populationSize; i++){
if(i==populationSize-1){
nextProb=probability[0];
}
else{
nextProb = probability[i+1];
}
if((par1 !=i) && (r > probability[i]) && (r < nextProb)){
par2 = i;
break;
}
}
r = ((double) rand() / (RAND_MAX));
r*= sumProbabilities;
}
//Pick my two parents
struct Node *parentOne = &(population[par1]);
struct Node *parentTwo = &(population[par2]);
//Picking a random number of genes from parent two, add them to the child.
//Then, iterate through parent 1 and add missing nodes to the child
int GenesFromParentTwo = rand() % (*count-1) + 1;
if(GenesFromParentTwo < 0 || GenesFromParentTwo > *count){
GenesFromParentTwo = 1;
}
//Copy First 'GenesFromParentTwo' Nodes From Parent 2 to Child
memcpy(&children[numChildren], &parentTwo[0], sizeof(struct Node)*GenesFromParentTwo);
int indicesContained[GenesFromParentTwo];
for(i=0; i<GenesFromParentTwo; i++){
indicesContained[i] = (int)children[numChildren][i].index;
}
//Copy Remaining Missing nodes from Parent 1 to Child
int numInsertions = 0;
for(i=*count; i>0; i--){
if(isContained(indicesContained, &parentOne[i], &GenesFromParentTwo)){
continue;
}
numInsertions++;
memcpy(&children[numChildren][GenesFromParentTwo-1+numInsertions], &parentOne[i], sizeof(struct Node));
}
numChildren++;
} //End crossover
//Replace Population with Children
for(i=0; i<populationSize; i++){
memcpy(&population[i], &children[i], sizeof(struct Node) * (*count));
}
//Mutate?
for(i=0; i<populationSize; i++){
for(j=0; j<*count; j++){
r = ((double) rand() / (RAND_MAX));
r *= 100;
//0 <= r <= 100
if(r <= 0.001 ){
//Mutate!
if(j==*count-1){
struct Node temp;
memcpy(&temp, &population[i][j], sizeof(struct Node));
memcpy(&population[i][j], &population[i][0], sizeof(struct Node));
memcpy(&population[i][0], &temp, sizeof(struct Node));
}
else{
struct Node temp;
memcpy(&temp, &population[i][j], sizeof(struct Node));
memcpy(&population[i][j], &population[i][j+1], sizeof(struct Node));
memcpy(&population[i][j+1], &temp, sizeof(struct Node));
}
}
}
}
//After crossing over each generation, pick the best and send to GUI
if(generation % 10000 == 0)
{
uint64_t shortestGenDistance = UINT64_MAX;
int elShortest = -0;
for (j = 0; j < populationSize; j++)
{
uint64_t tempDistance = 0;
for (i = 0; i < *count; i++)
{
if (i == *count - 1)
{
tempDistance += distance(&(population[j][0]), &(population[j][i]));
}
else
{
tempDistance += distance(&(population[j][i]), &(population[j][i + 1]));
}
}
if (tempDistance < shortestGenDistance)
{
shortestGenDistance = tempDistance;
elShortest = j;
}
}
char buffer[8192];
push_node_array_to_json(buffer, &population[elShortest][0], count, generation + 1);
push(buffer);
}
} //End Generations
} //End algorithm
最佳答案
应用于(对称)TSP 的遗传算法通常使用 EdgeRecombinationCrossover (ERX)、基于锦标赛的选择(而不是适应度比例选择)和 2-opt 突变(你似乎使用了相当具有破坏性的交换突变)工作得很好在 TSP 上)。对于 50 到 1000 个城市之间的问题实例,人口规模在 100 到 1000 之间,锦标赛组规模在 2 到 10 之间,你应该在 200-500 代内得到合理的结果。我觉得你的变异概率太低了,我会用1-5%。
求解 TSP 的遗传算法可能如下所示(C# 伪代码):
const uint seed = 0;
const int popSize = 100;
const int generations = 500;
const double mutationRate = 0.05;
var tsp = new TravelingSalesmanProblem(/*...*/);
var random = new Random(seed);
var population = new int[popSize];
var qualities = new double[popSize];
var nextGen = new int[popSize];
var nextQual = new double[popSize];
for (int i = 0; i < popSize; i++) {
population[i] = Enumerable.Range(0, tsp.Cities).Shuffle().ToArray();
qualities[i] = tsp.Evaluate(population[i]);
}
var bestQuality = qualities.Min();
var bestQualityGeneration = 0;
for (int g = 0; g < generations; g++) {
var parents = population.SampleTournament(random, 2 * popSize, qualities, groupSize: 3).ToArray();
for (int i = 0; i < popSize; i++) {
nextGen[i] = EdgeRecombinationCrossover.Apply(random, parents[i * 2], parents[i * 2 + 1]);
if (random.NextDouble() < mutationRate) TwoOptManipulator.Apply(random, nextGen[i]);
nextQual[i] = tsp.Evaluate(nextGen[i]);
if (nextQual[i] < bestQuality) {
bestQuality = nextQual[i];
bestQualityGeneration = g;
}
}
Array.Copy(nextGen, population, popSize);
Array.Copy(nextQual, qualities, popSize);
}
但一般来说,GA 并不是解决 TSP 的首选算法。 TSP 通常可以通过使用 2-opt 移动的局部搜索很好地解决。如果您通常使用使用 k-opt 移动的可变邻居下降,则可以进一步提高质量。 Lin-kerninghan 是一个非常先进的解决 TSP 的软件,它们确实使用遗传算法作为元级优化器来交叉和变异使用 k-opt 局部搜索获得的局部最优值。应用于局部最优的 GA 比应用于整个解决方案空间更有效。但是,您需要确保将多样性保护添加到 GA 中,否则人口可能会迅速崩溃到相同的解决方案。遗传局部搜索技术通常仅在它们有很大不同时才接受对种群的新解决方案。
关于c - 为什么我的遗传算法不会收敛,或者至少不会变得更好一点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33597326/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!