(第2版,修正了错别字-希望大家...)
哈Ha!
现在他坐在那里,为一个朋友制作了遗传算法的原型。 启发分享,以及其他一些想法...
给定(客户订购):在某个
王国中,仓库有100个牢房。 货物在里面。 如何取数量X以便将所有涉及的单元排空? 嗯,也就是说,您具有一个单元格类型[34、10、32、32、33、41、44、4、28、23、22、28、29、14、28、15、38、49、30、24, 18、9、15、8、17、9、2、7、30、29、29、2、28、23、19、4、15、30、38、3、14、21、43、50、29, 14,17,12,25,15,23,28,47,38,29,7,36,45,25,6,25,11,10,1,19,37,24,27,50,12, 1,1,44,22,48,13,46,49,11,33,29,4,19,33,12,3,47,27,26,45,40,37,21,2,8, 41,5,1,9,5]-如何拨号,例如40
好吧,你可以破产,肯定有什么聪明的,但是你可以用遗传算法来解决...
第一个问题:为什么要动脑筋,因为如果您只浏览列表,则需要从前两个单元格中提取-但是,第二个将是其余的。 而且您不必走太远。 但是要知道,客户是一位完美主义者,他希望它像药房一样。 大概在一个值得金重的牢房仓库里。 它发生了。
第二个问题:如果按升序排序,则肯定可以刷更多的单元格...在我们的示例中,有很多单元格少于十个单元格。 可能,客户也不想;)我也遇到过这样的人:我是老板。 他们告诉您-这样做,不要问问题。
(嗯,不是我的客户,否则我将再次对人的思想失去信心...)
好吧,上帝与他同在,每个人都有自己的优先级...然后我们将讨论遗传算法-我们必须以某种方式解决该问题...我们将用Java编写。
对于那些以前从未真正听说过的人:模仿自然母亲。
- 编码行为
- 我们借助合适的基准来检查每个选项的工作情况
- 最好地将其属性传递给下一代
在自然界的最后一步,有两个组成部分:交换(染色体相同部分之间的字符交换)和突变(遗传密码的自发改变)。 嗨,高中;)
仅此而已。 我们将编码从哪个单元格获取,从哪个单元格获取。 我们有100个单元,这意味着我们的染色体将包含100个真/假元素,为此我选择了String,其中将写入零和一。 当然,他们将是100。
基准测试是此过程中最重要的事情。 大自然正在寻找一个利基市场,而计算机自然将在基准测试中寻找一个漏洞,以愚弄它并生存下来。 太好了,说实话...
说了这么多,像这样:
private static int benchmark(String chromosome, boolean verbose) { int sum = 0; char[] cArr = chromosome.toCharArray(); for (int i = 0; i < cnt_bins; i++) { if (cArr[i] == '1') { sum += stock[i]; if (verbose) System.out.println("storage bin " + i + ":\t+" + stock[i] + "\t= " + sum); } if (sum == target_qty) { return 0; } } return Math.abs(target_qty - sum); }
这个想法是,我们离期望的数字40越远,效果越差。 如果我们获得40分,那么我们在染色体上不会走得更远,我们赢了。 当然,我们将按升序排序-罚分越少越好。
第一代是随机创建的:
实际上,由于遗传算法可以达到目标,但并不总是可以实现,因此限制世代数很重要。
for (int generationNo = 0; generationNo < maxGenerationCnt; generationNo++) {
排序,留下最好的:
...
我们繁殖繁殖,恢复人口规模。 也就是说,我们随机选择父母,组合相同的符号(如果幸运的话,请参阅交换标志),变异(变异标志),等待奇迹...
好吧,这是给你一个奇迹:目标值:40
库存:[34、10、32、32、33、41、44、4、28、23、22、28、29、14、28、15、38、49、30、24、18、9、15、8 ,17、9、2、7、30、29、29、2、28、23、19、4、15、30、38、3、14、21、43、50、29、14、17、12、25 ,15,23,28,47,38,29,7,36,45,25,6,25,11,10,1,19,37,24,27,50,12,1,1,44,22 ,48、13、46、49、11、33、29、4、19、33、12、3、47、27、26、45、40、37、21、2、8、41、5、1、9 ,5]
第0代; 最好/最后一个父母/最坏:705/991/1580
第1代; 最好/最后一个父母/最差:576/846/1175
第2代; 最好/最后一个父母/最坏:451/722/1108
第三代; 最好/最后一个父母/最差:0/613/904
找到解决方案
储物箱7:+4 = 4
储物箱10:+22 = 26
储物箱13:+14 = 40
这是整个代码 package ypk; import java.io.IOException; import java.io.StringWriter; import java.util.AbstractMap.SimpleEntry; import java.util.stream.Collectors; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; public class YPK { private static int generation_size = 1000; private static int best_size = 200; private static int cnt_bins = 100; private static int max_stock = 50; private static double exchange_rate = .2; private static double mutation_rate = .01; private static Random rnd = new Random(); private static int target_qty = rnd.nextInt(cnt_bins * max_stock / 5);
最后:如果您混淆了参数-太多的突变,太小的人口规模等等。 -会停滞甚至产生所有最差的结果。
顺便说一句,这个问题通常已经随机解决了,不需要下一代:)如果您想使计算机的寿命复杂化,请从基准中删除此回报:
if (sum == target_qty) { return 0; }
这会使任务复杂化,并使计算机遭受一些冲击。
祝你好运
m_OO_m