用Java编写的GA
我正在尝试根据我从《游戏程序员的人工智能技术》一书中学到的技术编写一种遗传算法,该算法对人口的基因使用二进制编码和适应度比例选择(也称为轮盘赌选择)在程序内以二维数组形式随机生成。
我最近遇到了一段伪代码并尝试实现它,但是在我需要做的具体事情上遇到一些问题。我已经检查了很多书籍和一些开源代码,但仍在努力取得进展。 我知道我必须获得总体适应度的总和,在总和和零之间选择一个随机数,然后如果该数字大于父母则覆盖它,但我正在努力实施这些想法。
任何对实现这些想法的帮助都将非常感激,因为我的 Java 还很生疏。
I am attempting to write a Genetic Algorithm based on techniques I had picked up from the book "AI Techniques for Game Programmers" that uses a binary encoding and fitness proportionate selection (also known as roulette wheel selection) on the genes of the population that are randomly generated within the program in a two-dimensional array.
I recently came across a piece of pseudocode and have tried to implement it, but have come across some problems with the specifics of what I need to be doing. I've checked a number of books and some open-source code and am still struggling to progress.
I understand that I have to get the sum of the total fitness of the population, pick a random number between the sum and zero, then if the number is greater than the parents to overwrite it, but I am struggling with the implementation of these ideas.
Any help in the implementation of these ideas would be very much appreciated as my Java is rusty.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
以下是 GA 的完整概要。我确保非常详细,以便可以轻松地将其编码为 C/Java/Python/..
请注意,目前您缺少适应度函数(取决于领域)。交叉将是一个简单的单点交叉(因为您使用的是二进制表示)。突变可能是简单的随机翻转。
编辑:
考虑到您当前的代码结构和符号,我已经在 Java 中实现了上述伪代码(请记住,我更喜欢 ac/c++ 而不是 java)。请注意,这绝不是最有效或最完整的实现,我承认我写得相当快:
Individual.java
Population.java
The following is a complete outline of the GA. I made sure to be very detailed so it can be easily coded to C/Java/Python/..
Note that currently you're missing a fitness function (depends on the domain). The crossover would be a simple one point crossover (since you are using a binary representation). Mutation could be a simple flip of a bit at random.
EDIT:
I have implemented the above pseudocode in Java taking into consideration your current code structure and notations (keep in mind i am more of a c/c++ guy than java). Note this is in no way the most efficient or complete implementation, I admit I wrote it rather quickly:
Individual.java
Population.java
为什么不使用像 JGAP 这样的开源框架:http://jgap.sf.net
Why not use an open-source Framework like JGAP: http://jgap.sf.net
实现该算法,从而减少在选择过程中迭代数组中每个元素的需要:
请注意,您只需要在复制阶段开始时创建适应度数组,然后可以多次重复使用它来在 O(log N) 时间内执行选择。
顺便说一句,请注意锦标赛选择更容易实施!
I have implemented this algorithm by creating a "cumulative fitness array" and binary search, thus reducing the need to iterate through each element in the array during the selection:
Note that you only need to create the fitness array at the start of the reproduction phase, and can then re-use it multiple times to perform selections in O(log N) time.
As an aside, note that tournament selection is far easier to implement!
您正在寻找的概念称为“轮盘赌选择”。你还没有一个既定的适应度函数(你可能是在暗示每个个体的适应度是其染色体的积分值),但是当你做一个总体计划是:对
还有其他等效的实现,但总体思路是按照与其适应度成正比的概率来选择成员。
编辑:
关于健身功能的一些注意事项。染色体的表示(在您的例子中为 32 位整数)独立于用于评估它的适应度函数。例如,二进制编码通常将染色体视为打包成适当大小的整数值的一组位域。然后可以通过适当的位掩码操作来完成交叉和变异。如果您有兴趣,我可以发布一些简单的 GA 代码(用 C 和 Python 编写),它使用按位运算来实现这些函数。我不确定您对这些语言的适应程度如何。
The concept you're looking for is called "roulette wheel selection." You don't have an established fitness function yet (you may be implying that the fitness of each individual is the integral value of its chromosome), but when you do a general plan is:
There are other equivalent implementations, but the general idea is to select members with a probability proportional to their fitness.
Edit:
A few notes on fitness functions. The representation of a chromosome (in your case as a 32-bit integer) is independent of the fitness function used to evaluate it. For example, binary encodings typically treat the chromosome as a set of bitfields packed into an integral value of appropriate size. Crossover and mutation can then be accomplished by the appropriate bit-masking operations. If you're interested, I can post some simple GA code I have laying around (in C and Python) which uses bitwise operations to implement these functions. I'm not sure how comfortable you are with these languages.
我用 java 做了一个可扩展的实现,其中操作符和单独的结构由一起工作的接口很好地定义。 Github repo 这里 https://github.com/juanmf/ga
它对每个运算符都有一个标准实现,以及具有特定个人/群体结构和健康度计的示例问题实现。示例问题实施是在 20 支球队和预算限制中找到一支拥有球员的优秀足球队。
为了使其适应您当前的问题,您需要提供这些接口的实现:
在
pkg juanmf.grandt
中,您有示例问题实现类以及如何发布它们,如下面的代码片段所示。要发布实现,您只需从该 Spring bean 返回正确的类:
Crosser 运算符对于同一技术有两种实现,一种是顺序实现,一种是并发,其性能远远优于顺序。
可以指定停止条件。如果没有给出,它有一个默认的停止条件,在100代后停止,没有任何改进(这里你必须小心精英主义者,不要失去每一代最好的,以便有效地触发这个停止条件)。
因此,如果有人愿意尝试,我很乐意提供帮助。
欢迎任何人提供建议,以及更好的操作员实现:D 或任何改进的拉取请求。
I made an extensible implementation in java, in which operators and individual structure is well defined by interfaces that work together. Github repo here https://github.com/juanmf/ga
It has a standard implementation for each operator, and an example problem implementation with a particular Individual/Population structure and a Fitness meter. The example problem Implementation is to find the a good soccer team with players among 20 teams and a budget restriction.
To adapt it to your current problem you need to provide implementations of these interfaces:
In
pkg juanmf.grandt
you have the example problem implementation classes, and how to publish them, as shown in the code snippet below.To publish you implementations you just have to return the proper classes from this Spring beans:
Crosser operator has two implementations for the same technique, one sequential and one concurrent which outperforms sequential by far.
Stop condition can be specified. If none is given, it has a default stop condition that stops after 100 generations with no improvements (here you must be careful with elitist, not to loose the best of each generation so as to trigger this stop condition effectively).
So if anyone is willing to give it a try, I'd be glad to help.
Anyone is welcome to offer suggestions, and better yet operator implementations :D or any improving pull request.
有关轮盘赌选择的其他问题应该有所帮助:
在第一个中,我试图解释轮盘赌轮是如何工作的。在第二个例子中,Jarod Elliott 提供了一些伪代码。结合 Adamski 对高效实现的描述,这些应该足以让一些东西发挥作用。
These other questions about roulette wheel selection should help:
In the first one, I've tried to explain how the roulette wheel works. In the second, Jarod Elliott has provided some pseudocode. Combined with Adamski's description of an efficient implementation, these should be sufficient to get something working.
只是有一点值得一提。轮盘赌选择(如伪代码中所示)不适用于最小化问题 - 然而,它对于最大化问题有效。
由于选择最适合个体的方式,最小化情况将不成立。详细信息参见:计算智能:第二版
Just a point worth mentioning. The Roulette wheel selection (as indicated in the pseudo-code) will not work for minimization problems - it is, however, valid for maximization problems.
Due to the manner in which the most fit individual is selected, the minimization case will not hold. Details are provided in: Computational Intelligence: 2nd edition