【发布时间】:2010-12-05 08:51:28
【问题描述】:
我正在尝试用Genetic algorithm 解决Travelling Salesman Problem (TSP)。我的基因组是图中顶点的排列(推销员的路径)。
我应该如何对我的基因组执行交叉操作?
在哪里可以找到我的问题在 C# 中的实现?
【问题讨论】:
标签: c# algorithm artificial-intelligence genetic-algorithm traveling-salesman
我正在尝试用Genetic algorithm 解决Travelling Salesman Problem (TSP)。我的基因组是图中顶点的排列(推销员的路径)。
我应该如何对我的基因组执行交叉操作?
在哪里可以找到我的问题在 C# 中的实现?
【问题讨论】:
标签: c# algorithm artificial-intelligence genetic-algorithm traveling-salesman
您应该检查 Gokturk Ucoluk 的“Genetic Algorithm Solution of the TSP Avoiding Special Crossover and Mutation”。它概述了用于排列的特殊交叉运算符,并提出了一种巧妙的排列表示,该表示可以与标准交叉很好地配合使用(即交叉两个排列总是产生两个排列)。
关键的见解是将排列表示为其反转序列,即对于每个元素i,在a[i] 中存储在排列中i 左侧有多少大于i 的元素。与直接表示不同,a[i] 的唯一约束是局部的,即a[i] 不能大于N - i。这意味着两个有效反转序列的简单交叉总是会产生两个有效反转序列 - 不需要对重复元素进行特殊处理。
【讨论】:
与其使用标准的 GA 交叉技术(如outlined by MusiGenesis),不如使用ordered cross-over for the Travelling Salesman problem。
通常的方法对于 TSP 来说效果不佳,因为适应度函数对进化路线中不同城市的相对位置非常敏感,而不是它们的绝对位置。例如,如果您要访问所有欧洲首都,那么最短的路线实际上并不取决于您是访问布拉迪斯拉发 1 号、2 号还是 9 号。更重要的是您访问它immediately before or immediately after visiting Vienna,而不是访问赫尔辛基、雅典和介于两者之间的其他 6 个首都。
当然,作为mjv also points out,传统的跨界也会在你的路线中引入重复。如果一个父节点的位置为 2,而另一个父节点的位置为 14,则交叉可能会导致一条进化路线访问巴黎两次(并错过另一个城市),而另一条进化路线根本不访问它。有序交叉遗传算子不存在这个问题。它保留元素并修改排序。
【讨论】:
这里是 a C# program 方法,可以满足您的需求。
关于实现交叉的兴趣(或缺乏兴趣),这一切都取决于您的实现将使用的特定选择逻辑(和/或评估函数本身,例如它包括对改进速度的评估)。在许多情况下,交叉操作会“从砧板上解救”一些解决方案,这些解决方案在图表的某个区域是有效/最佳的,但在其他区域却以某种方式“卡住”了。这并不是说如果整个算法足够慢并且覆盖了解决方案空间的很大一部分,则可能不会重新发现相同的解决方案,但是交叉也可能会增加这些发现(和/或让您陷入困境另一个局部最小值 ;-) )
与研究 GA 的人没有直接关系但值得注意的是 original "ultimate" experiment in GA 由 Alderman 教授(以 RSA 闻名)在 GA 中进行的原始“终极”实验,他使用了实际的 DNA 分子 [进入 C 程序 - 只是开玩笑] 来解决一个相关的图问题,即哈密顿图。
编辑:在重新阅读该问题时,我明白您为什么要问这个问题,或者更准确地说为什么您想要“不,您不想跨界”回复强> ;-)
您的 genonme 直接与图 本身相关联(这没什么错,先验),但这带来了障碍,即大多数交叉衍生品将不可行,因为他们可能有重复的节点(访问同一个城市两次或更多)并且缺少节点(未能访问某些城市)......此外,可行的交叉将影响相似的图表,因此可能只是增加搜索,与会发现什么突变...
嗯...那么也许交叉,在这个特定的实现中不会对算法有太大帮助(实际上会占用它的大部分 CPU 来创建、测试和经常丢弃交叉的后代,通过提供更多的迭代和较慢的冷却速度来更好地使用 CPU...)。除非!你找到了一种执行交叉操作的聪明方法;-)
【讨论】:
交叉的目的是通过汇集新的基因组组合来扩展进化搜索空间。
进化过程所需的唯一真正标准是交叉产物包含双亲的部分并代表有效的基因组。
只有你知道你的算法的有效性规则,所以只有你可以指定一个有效的交叉方法(除非你想分享更多关于你的基因组结构的验证规则的细节)。
【讨论】:
这是我在 GA for TSP 中所谓的“部分映射交叉”方法的确切实现。
Here 是一篇从理论上解释部分映射交叉的论文,下面是我的代码。
//construct a new individual with the genes of the parents
//method used is cross over mapping
//note that Individual datastrucuture contains an integer array called Genes which //contains the route.
//
public Individual Breed(Individual father, Individual mother)
{
int[] genes = new int[father.Genes.Length];
int[] map = new int[father.Genes.Length + 1]; //create a map to map the indices
int crossoverPoint1 = rand.Next(1, father.Genes.Length - 2); //select 2 crossoverpoints, without the first and last nodes, cuz they are always thje same
int crossoverPoint2 = rand.Next(1, father.Genes.Length - 2);
father.Genes.CopyTo(genes, 0); //give child all genes from the father
for (int i = 0; i < genes.Length; i++) //create the map
{
map[genes[i]] = i;
}
//int[] genesToCopy = new int[Math.Abs(crossoverPoint1 - crossoverPoint2)]; //allocate space for the mother genes to copy
if (crossoverPoint1 > crossoverPoint2) //if point 1 is bigger than point 2 swap them
{
int temp = crossoverPoint1;
crossoverPoint1 = crossoverPoint2;
crossoverPoint2 = temp;
}
//Console.WriteLine("copy mother genes into father genes from {0} to {1}", crossoverPoint1, crossoverPoint2);
for (int i = crossoverPoint1; i <= crossoverPoint2; i++) //from index one to the 2nd
{
int value = mother.Genes[i];
int t = genes[map[value]]; //swap the genes in the child
genes[map[value]] = genes[i];
genes[i] = t;
t = map[genes[map[value]]]; //swap the indices in the map
map[genes[map[value]]] = map[genes[i]];
map[genes[i]] = t;
}
Individual child = new Individual(genes);
return child;
}
【讨论】:
在我上大学的第一门课程时,我正在计算各种 GA 算子对解的收敛性的影响(大约花了 30 页)。我记得,交叉不是 TSP 的最佳解决方案,更合适的解决方案是突变,即顶点子序列的反转。
示例:
之前:ABCDEFGH
之后:AFEDCBGH
【讨论】:
遗传算法中的“交叉”只是指混合两个“遗传序列”的任意方式,每个“遗传序列”代表问题的特定解决方案(序列如何映射到解决方案取决于您)。因此,例如,假设您有一个由以下两个序列组成的群体:
AAAAAAAAAA
BBBBBBBBBB
重组这两个“父”序列的一种方法是随机选择一个交叉点(例如位置 3),从而产生这两个“子”序列:
AAABBBBBBB
BBBAAAAAAA
或者,您可以随机选择两个交叉点(例如,3 和 8),从而产生这两个序列:
AAABBBBBAA
BBBAAAAABB
为了有趣和额外的可变性,您还可以引入偶尔点突变的可能性:
AAABBBABAA
BBBAAAAABB
对于如何在遗传算法中实现交叉并没有真正的硬性规则,就像生物世界中的进化没有任何硬性的规则一样。任何有效的,有效的。
【讨论】: