我试图在Prolog CLP中编写地图着色程序。这是到目前为止的代码。请任何人在这里帮助我。这里有什么问题。我想在这里替换maplist函数。任何帮助表示赞赏。
:- use_module(library(clpfd)).
regions(Rs):-
Rs = [R1,R2,R3,R4,R5,R6],
% neighbouring regions have different
dif(R1, R2),
dif(R1, R3),
dif(R1, R4),
dif(R1,R6),
dif(R2, R3),
dif(R2, R5),
dif(R3, R4),
dif(R3,R5),
dif(R3, R6),
dif(R4, R5),
dif(R4, R6),
maplist(color, Rs).
color(red).
color(green).
color(blue).
color(yellow).
最佳答案
确实是这样:发布的代码已经可以在提供dif/2
的任何Prolog系统中使用。
但是,将CLP(FD)约束用于此类组合任务时有明显的优势。
让我告诉你我的意思。首先,这是任务的简单CLP(FD)公式:
地区(Rs):-
Rs = [A,B,C,D,E,F],
Rs ins 0..3,
A#\ = B,A#\ = C,A#\ = D,
A#\ = F,B#\ = C,B#\ = E,
C#\ = D,C#\ = E,C#\ = F,
D#\ = E,D#\ =F。
我只有:
更改了变量的可读性(R1
→A
,R2
→B
等)
用CLP(FD)约束dif/2
替换(#\=)/2
完全是因为整数0..3而不是原子,所以CLP(FD)约束完全适用。请注意,有限域上的任何问题都可以映射为整数,因此CLP(FD)约束始终是此类任务的合适选择。
首先,让我们尝试最一般的查询,看看原则上的答案是什么样的:
α-区域。
Rs = [_640,_646,_652,_658,_664,_670],
_640 in 0..3,
_640#\ = _ 670,
_640#\ = _ 658,
_640#\ = _ 652,
_640#\ = _ 646,
等等
这似乎还可以。约束求解器以剩余目标作为响应。另外,我们看到我们的关系终止并且实际上是确定性的,这很高兴知道。标记变量将保留终止行为,因此我们不会在程序的其他部分意外地陷入循环。
我们可以通过标记变量轻松获得具体的解决方案:
α-区域(Rs),标签(Rs)。
Rs = [0、1、2、1、0、3]。
在此,每个整数对应于唯一的颜色。我将使这些解决方案更易于阅读,以便更好地阅读。
现在要说了!
或更确切地说:点!
CLP(FD)约束提供了dif/2
所没有的功能,即约束传播。
在这种情况下,我们最初有以下情况:
在这里,每个小点代表一种颜色,我们仍然可以将其用于其所在区域。首先,约束求解器没有排除任何颜色,因此我们在所有区域中找到每个选项。
如果我们仅将一种区域分配为固定颜色,情况将发生巨大变化:
α-区域([A,B,C,D,E,F]),F = 0。
F = 0,
1..3中的A,
A#\ = D,
A#\ = C,
A#\ = B,
1..3中的D,
D#\ = E,
C#\ = D,
E在0..3中,
C#\ = E,
B#\ = E,
1..3中的C,
B#\ = C,
0..3中的B
我只添加了一个统一(F = 0
),这导致约束求解器从所有相邻区域修剪此选项:
现在,我仅再发布一个附加的统一:
α-区域([A,B,C,D,E,F]),F = 0,C = 1。
C = 1
F = 0,
2..3中的A,
A#\ = D,
A#\ = B,
D在2..3中,
D#\ = E,
E在0 \ /2..3中,
B#\ = E,
B在0 \ /2..3。
再次自动执行(即约束求解器为您完成)删除了许多其他可能的分配:
仅执行一项战略任务(我将其留为练习来找出其中一项),就可以得出以下情况:
现在,剩下的唯一选择就是如何为尚未分配任何固定颜色的单个剩余区域着色。显而易见,现在两种允许的颜色都可以解决整个任务。dif/2
也会修剪搜索空间。但是,CLP(FD)约束对变量的实际域执行此功能强大的修剪。这意味着根本不需要尝试许多值。此外,基于此推理,约束求解器可以更智能地选择接下来标记的变量,从而在许多情况下进一步提高了性能。
关于prolog - CLP(FD), map 着色,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42589509/