寻找一种将攀爬保持颜色分配给墙壁扇区的算法

计算科学 优化 算法 迭代法
2021-11-25 12:15:23

我早些时候在stackoverflow上发布了这个问题,在那里它被关闭为题外话。我希望它能在这里生存。

在我们的攀岩馆,路线需要不时重新设置。以下规则适用:

  • 我们有不同数量的不同颜色的攀登架。- 当一条路线设置在一个扇区中时,不得在该扇区或附近扇区中设置其他具有相同颜色的路径,以免混淆。
  • 在一个区域中必须避免某些颜色组合,例如白色/灰色或红色/粉红色。
  • 目标是在每个扇区中有四条路线,如果四条路线违反上述规则,那就少了。

到目前为止,我已经尝试了两种不同的方法。第一个是模拟退火,我用随机的颜色图案(但具有给定的颜色权重)初始化墙壁,并计算每种颜色组合的坏度。还计算了一个扇区与其相邻扇区之间的组合的这种不良情况。在每次迭代中,来自最差扇区的随机选择的路线与随机选择的其他扇区的路线交换。这显示了某种收敛,但结果不可用(即结果状态包含具有双色或三色的扇区)。

然后我从对面处理问题,从一堵空墙开始。这一次,每种颜色都有一个浓度从一个扇区衰减到相邻扇区。相似颜色的浓度也增加了,即红色路线增加了一个扇区和附近的橙色浓度。加权随机颜色源(桶)给了我墙的下一种颜色,它被放置在这种颜色浓度最低的区域。如果浓度高于某个阈值,则不添加颜色(而是放回桶中)。这是部分成功,因为结果状态不包含任何双色 - 但某些扇区为空或仅包含一种颜色。

那么:根据上述规则,解决这个问题的合适算法是什么?我很乐意在需要时添加更多信息。


编辑 1 - 更多信息:

  • 我的测试用例有 15 个扇区,
  • 每个扇区应包含 4 条路线
  • 真正的健身房有 3 栋建筑,每栋建筑平均有 50 个扇区
  • 有些扇区围绕柱子排列,有些则由屋顶连接
  • 我们有大约 10 种不同的保持颜色
  • 扇区的高度在 6(初学者部分)和 20 米(13 垂直 + 7 屋顶)之间变化,因此它们消耗不同数量的货舱。但是,平均值约为 12,这可以认为是恒定的。
  • 每种颜色数量有限,数量不等
  • 有些颜色更容易,有些更难(即我们可以创建一条任何难度的黄色路线,而为孩子们创建一条非常简单的橙色路线几乎是不可能的)
  • 有些部门“更容易”,所以应该去那里简单的颜色(这是可选的,我们的路线设置器可以在广泛的范围内使事情变得更难或更容易)。
  • 我们可以有把握地说哪些颜色在一个扇区或相邻扇区中可以很好地搭配在一起,而哪些组合则不能。有一些惊喜,例如白色和黑色(糟糕的组合):两者都变成灰色,而橡胶(鞋子)或粉笔(手)留在它们上面。
  • 一些保持颜色是紫色/白色(条纹图案)等组合。

编辑 2:关于遗传算法的一些问题

我现在下载并编译了 ParadisEO,甚至得到了我的 IDE(我正在使用 Code::Blocks)来编译 QuickStart 示例。ParadisEO 提供具有单目标和多目标遗传算法的遗传算法。GertVdE 建议计算每个扇区的适应度,并将所有扇区适应度的总和最大化作为一个目标。我是否也可以通过多目标遗传算法最大化每个部门的适应度?那将是大约 50 个目标。

另外,我正在努力定义一个合理的交叉函数。由于每种颜色的最大数量是固定的,交叉会导致非法状态。如果我允许的数量超过之前给定的最大数量,则整体模式可能会收敛为较少“麻烦”组合的重复,其中麻烦的颜色已被丢弃。另一方面,我也可以丢弃多余的颜色,直到达到最大值,使交叉函数不保守。

(我对遗传算法完全陌生)

2个回答

我将使用遗传算法方法解决上述问题。您将每个解决方案编码为整数向量:

  • 假设每个扇区的最大路线数量为 M(您选择);假设 N 个扇区
  • 创建一个大小为 M*N 的编码向量,其中每个段代表一个扇区,段中的每个项目代表一个路线
  • 通过整数值、索引分配颜色;使用 0 作为无路由(允许比 M 更少的路由)
  • 对于每个颜色索引,具有 RGB 值

然后,您将适应度函数定义为每个扇区中的最小色差和扇区中的路由数量(向量中零点的数量)的加权和。您可以使用Paradiseo框架或Inspyred来实现遗传算法。

这是我当前实现的简要概述,我将尝试坚持概念而不涉及语言细节。我使用了ParadisEO 框架,它是用于遗传算法的 C++ 模板库,并在这里和那里添加了一些提升。

攀爬保持颜色

保持颜色作为一对颜色名称和数量存储在 XML 文件中。在文件中找到的数量被加起来并标准化。这使得可以将数量表示为可以使用此颜色设置的路线的总数或百分比。为每种颜色分配一个 ID,从 1 开始。零是为“空”路线保留的。

颜色组合惩罚

有些颜色在一个扇区或相邻扇区不能很好地搭配在一起。每个不太好的颜色组合都由两个颜色名称(如在前面的 XML 文件中,见上文)和任意“坏”描述。在内部,坏值存储在一个由颜色 ID 索引的矩阵中。

Wall 是派生自 ParadisEO 的基因组表示类的类,因此 ParadisEO 可以对其进行操作和评估,但添加了更多功能。每个基因通过 ID 代表一种路线颜色(包括零或空)。扇区由一对基因索引表示,因此每个扇区都有开始和结束。我首先使用了基因的迭代器,但是 Wall 对象必须是可复制构造的,这将使迭代器无效,而无需额外的工作。目前,所有扇区都有 4 条路线,但将来可以配置。

墙上还有一个颜色桶。此存储桶包含每种颜色的计数器,按照颜色 XML 文件中的说明进行分发。颜色计数加起来就是墙中路线的总数。一种颜色可以从桶中取出,减少计数器,也可以放回,增加计数器。

仅当扇区尚未包含该颜色时,才能将颜色添加到扇区(添加颜色时该扇区必须保持“合法”)。

评估运算符

评估算子使用上述坏度矩阵对扇区中的所有坏度值求和。每个扇区的值都存储在适应度向量中(这也是 Wall 类的一部分),因此这是一个多目标 GA。如果有必要,我可能会改变它。

两点交叉算子

交叉算子采用两个父母,创建每个(后代)的副本,然后通过重新组合整个扇区来执行两点交叉这样做的好处是扇区仍然合法(没有双色)。任何交叉操作(对于这个问题)的缺点是,如果颜色聚集在父代中,则生成的后代可能包含过多的颜色。添加了修复功能,可随机删除多余的路线(颜色为零)。因此,后代的路线少于修复改变后代的父母。

突变1:添加路线

后代路线的潜在减少由“添加路线”操作员解释。它从墙的桶中提取一种颜色并将其添加到某处。如果这不是合法操作,则它什么也不做(有时剩余颜色没有合法位置)。

突变2:随机交换

交换两个随机扇区的两条随机路由。生成这对交换,直到得到的扇区合法,然后执行交换。

突变3:转变

许多扇区向左移动一位。

我现在没时间了,但我可能会在以后添加更多信息。特别是评估非常简单,并且组件被编程为conecpt的证明。GA 确实在一定程度上优化了 Wall,但结果还没有准备好实际使用。我相信当我与路由设置者交谈并且有更多的评估规则可用时,这会有所改善。图片在可用时也会出现。