383. Abstraction and Reasoning Challenge | abstraction-and-reasoning-challenge
恭喜大家,比赛终于结束了!比赛刚结束,我想稍微介绍一下我们团队“Puzzlemaster”获得第10名的解决方案。
我们的解决方案是由3个部分组成的集成方案,这3个部分分别解决了3组任务,且存在部分交集:
首先,我想感谢这些 Kernel(代码内核)的作者,他们从算法角度给了我很多启发:
当然还有我打开了1000次的那个 Kernel:
我们创建了一种领域特定语言(DSL),基于可以应用于网格的命令。我们的语言中有许多命令。每个命令都有几个在训练期间随机采样的参数。我们称之为“全局规则”(与下文描述的元胞自动机规则相对)。
命令示例:
所有括号中写的都是随机采样的参数。
在比赛结束时,我们在 DSL 中添加了“多网格”元素。例如,它可以拆分网格(例如通过上面的图形),对某些网格应用一些命令,然后将它们合并回来。这大大提升了我们的 LB 分数。
还有在先前命令之后应用的“元胞自动机(Cellular automata)”命令。关于元胞自动机的更多细节可以在这个 Kernel 中找到:Cellular Automata as a language for reasoning
我们的 DSL 包含几个随机参数化的 CA 规则。例如,检查直接邻居,检查有色角等。
因此,最终的 DSL 程序是一系列“全局”规则,然后对其结果应用 CA 规则。
我们解决方案中非常重要的一部分是 @artyomp 使用 C++ 实现的“全局”规则和“CA 规则”。他做得非常棒,将整个算法加速了100倍,使我们能够创建许多新规则,而不必太在意搜索空间的复杂性。如果没有 C++,我们可能只能解决我们所解决的一半测试任务。
实际上,它类似于 DSL and Genetic Algorithm applied to ARC 中的算法,但有许多启发式方法。我们的算法创建随机的程序序列,创建无性突变(尝试用新命令替换命令、插入新命令、删除命令)和“有性”突变(尝试连接2个程序的随机前缀和后缀,并在最后进行一些突变)。
如何衡量程序是否优秀?显然,我们应该衡量准确率(有多少单元格是正确的)。如果所有训练对的准确率等于1,我们就找到了解决方案。但是由于我们使用带有1个规则突变的遗传算法来寻找解决方案,我们可能需要更多的指标来允许种群更大。我的观察是我们应该小心,因为如果我们添加更多指标,算法更有可能创建一个包含许多命令的垃圾程序,它虽然能解决训练样本但过拟合了。
所以结果是我们最终选择的指标: