我不确定要选择哪个 SE 站点——stackoverflow 和 math 是候选者——但是因为我们可能会为这个问题编写一个软件,所以我决定在这里发布它。
在我们的攀岩馆中,我们面临的问题是相邻的墙壁区域可能不会使用相同(或相似)的攀岩支撑颜色。我正在寻找一种将攀爬保持颜色分配给墙壁扇区的算法。到目前为止,我们都是手动完成的,结果各不相同,有时甚至令人不快。这是我们的“规则”:
如果 A 区的路线为红色,则附近的区域(A-1 和 A+1)不得设置红色路线。优选地,不应在扇区 A-2 和 A+2 中设置具有该颜色的路线,除非路线设置者特别注意使路线不“接触”。
一个或相邻扇区的不同颜色应该“足够不同”。例如,不允许使用红色和粉色等组合,应避免使用红色和紫色。颜色互补并不是将它们组合在一个区域的真正理由,因为我们有红绿色盲的登山者(还有其他一些口味)。此外,还有白色和黑色等非颜色(也不要一起使用),荧光色和两种或三种颜色组合。但是,我们可以有把握地说哪些颜色组合可以很好地搭配在一起,哪些是应该避免的,哪些是不允许的。
一个扇区中最多可以有四个路由。应避免只有一两条路线的扇区。我们对每种颜色都有不同的数量,因此也必须考虑到这一点。扇区可以是圆形的(例如围绕一根柱子)或以其他方式相互连接(一根柱子和附近的墙壁由屋顶连接)。
是否有解决此类问题的通用方法?
编辑 1:
我已经实现了 mbeckish 的建议,并为这个问题编写了一个模拟退火算法。虽然我相信我的代码可以正常工作,但结果并不令人满意。
以下是一些细节:
- 有15个扇区,每个扇区有4条路线;
- 路线颜色有 10 种:3 原色、3 副色、黑色、白色、青绿色和紫罗兰色/白色(组合);
- 每种颜色的数量固定在每种颜色3到8条路线之间;
- 算法开始时颜色是“聚集的”;
- 我为每种可能的颜色组合定义了一个带有惩罚 (1e-2...1) 的矩阵;
- energy() 函数将每个扇区内和相邻扇区之间的所有惩罚相加;
- neighbour() 函数在两个不同扇区之间交换一对随机选择的路线(除非路线颜色相同,在这种情况下选择一对新的交换路线);
- T() 呈指数衰减
- P() 的实现方式与关于模拟退火的维基百科文章一样。
这将愉快地运行和交换,但结果总是包含具有两条相同颜色路线的扇区。不过,我想包括一个能量的“收敛”图(归一化;蓝色:当前,绿色:最佳)与迭代:
当我在开始算法之前对路线进行洗牌时,结果是相似的。这就像在不考虑惩罚的情况下进行一些预迭代。这是相同类型的图,预先洗牌,T() 衰减更快,使算法更贪婪,迭代次数更多:
编辑 2:neighbour() 函数现在从具有最高能量 (S1) 的扇区中选择一种随机颜色 (C1),并将其与来自随机其他扇区 (S2) 的随机颜色 (C2) 交换,除非 C1 已经包含在 S2 或 C2 中已包含在 S1 中。这会产生更好的结果,但它们仍然包含具有重复颜色的扇区。我现在会尝试想出一些不同的东西。