ABC拼图 – 约束满足问题

ABC是一种在5×5棋盘上的逻辑拼图。每行和每列必须恰好包含3个字母(A、B、C)和2个空格。此外,每行和每列都提供关于该行/列中第一个字母的信息。这并不意味着第一个字母就在第一个单元格中,而是指该行中的第一个字母(第一个字母前可能有空格)。这里是带有信息的棋盘。

我需要帮助来弄清楚每行和每列中第一个字母的约束条件。

我已经有了每行和每列的约束条件,但就是无法找出如何确定行或列中第一个字母的确切位置。以下是我目前的进展。

*注意,我用1、2、3分别代表A、B、C,我用”_”(单空格)和”__”(双空格)代表空单元格,以便仍然符合’AllDifferentConstraint’的要求。

from constraint import *if __name__ == "__main__":problem = Problem(BacktrackingSolver())variables = []for i in range(0, 25):    variables.append(i)domain= []for i in range(1,4):    domain.append(i)domain.append("_")domain.append("__")problem.addVariables(variables, domain)for row in range(5):    problem.addConstraint(AllDifferentConstraint(), [row * 5 + i for i in range(5)])for col in range(5):    problem.addConstraint(AllDifferentConstraint(), [col * 5 + i for i in range(5)])solution = problem.getSolution()print(solution)

回答:

免责声明:

  • 我的代码可能看起来有些过于复杂
  • 对于最近一直在做约束编程的人来说,这个库提供的约束集看起来很奇怪和/或不完整(与工业级的Gecode相比)
    • 我认为这个解决方案是一种权宜之计(但对于这个小问题来说已经足够了)
  • 我保留了你的大部分代码,但将空格改成了数字(8, 9)以便于更好地可视化

基本思路假设维度是预先固定的,对于你所寻找的约束条件,存在确切的5种有效情况,从切片的前端来看:

0: _  __ TARGET ...dontcare1: __ _  TARGET ...dontcare2: _  TARGET    ...dontcare3: __ TARGET    ...dontcare4: TARGET       ...dontcare

作为从SAT求解转向CP的人,我觉得用子句进行推理非常自然。上述内容可以很容易地用布尔逻辑表达(顺序与上述不同):

   (  pos0 = F                  )OR ( (pos0 = _ )  and (pos1 = F) )OR ( (pos0 = __)  and (pos1 = F) )OR ( (pos0 = __) and (pos1 = _  ) and (pos2 = F)OR ( (pos0 = _ )  and (pos1 = __ ) and (pos2 = F)

通常人们会使用一个实现良好的约束/传播器(使用SAT技术),但这个库缺少常用的东西。

但幸运的是,有FunctionConstraint来救场,它允许我们构建一个简单的传播器。这实际上是一个非常好的设计(对于小型且相对简单的问題)!

一些说明:

  • clause构建了我们的基于布尔逻辑的传播器(以非高效的方式)
  • rowclause根据我们的需求返回基于1d的索引
  • reverse让我们在约束需要从末端而不是前端作用时重用逻辑
  • 我们使用部分函数应用来使调用更加紧凑
  • numpy仅用作快速可视化工具(没有什么比从dict中推理矩阵解决方案更糟糕的了)

代码

""" ORIGINAL CODE """from constraint import *problem = Problem(BacktrackingSolver())variables = []for i in range(0, 25):    variables.append(i)domain= []for i in range(1,4):    domain.append(i)domain.append(8)domain.append(9)problem.addVariables(variables, domain)for row in range(5):    problem.addConstraint(AllDifferentConstraint(), [row * 5 + i for i in range(5)])for col in range(5):    problem.addConstraint(AllDifferentConstraint(), [col * 5 + i for i in range(5)])""" ADDITIONS """from functools import partial  def clause(target, p0, p1, p2, p3, p4):  wildcards = [8, 9]  return (p0 == target) or                                              \        ( (p0 in wildcards) and (p1 == target) ) or                    \        ( (p0 in wildcards) and (p1 in wildcards) and p2 == target ) row = lambda x: [x * 5 + i for i in range(5)]col = lambda x: [x + i * 5 for i in range(5)]reverse = lambda x: list(reversed(x))problem.addConstraint(partial(clause, 3), reverse(row(0))) # Cproblem.addConstraint(partial(clause, 2), reverse(row(1))) # Bproblem.addConstraint(partial(clause, 3), reverse(row(2))) # Cproblem.addConstraint(partial(clause, 1), row(2))          # Aproblem.addConstraint(partial(clause, 2), row(3))          # Bproblem.addConstraint(partial(clause, 1), col(0))          # Aproblem.addConstraint(partial(clause, 2), col(1))          # Bproblem.addConstraint(partial(clause, 1), col(3))          # Aproblem.addConstraint(partial(clause, 3), reverse(col(0))) # Cproblem.addConstraint(partial(clause, 3), reverse(col(2))) # Cproblem.addConstraint(partial(clause, 3), reverse(col(3))) # C""" SOLVE """solution = problem.getSolution()print(solution)""" VISUALIZE """import numpy as npmatrix = np.zeros((5, 5), dtype=int)matrix[np.unravel_index(range(5*5), (5,5))] = [solution[i] for i in range(5*5)]print(matrix)

输出

λ python C:\Tmp\constr.py{10: 9, 13: 3, 11: 1, 12: 2, 0: 9, 3: 1, 5: 1, 8: 2, 15: 9, 18: 8, 14: 8, 20: 3, 23: 9, 1: 2, 2: 8, 6: 9, 7: 3, 16: 2, 17: 3, 4: 3, 9: 8, 19: 1, 22: 8, 21: 2, 24: 1}[[9 2 8 1 3] [1 9 3 2 8] [9 1 2 3 8] [9 2 3 8 1] [3 2 8 9 1]]

结果出人意料地看起来是正确的 ;-), 与你最初的任务相比:

enter image description here

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注