CLP(FD),地图着色

时间:2017-03-03 22:25:47

标签: prolog clpfd graph-coloring

我正在尝试在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).

3 个答案:

答案 0 :(得分:3)

确实如此:在提供dif/2的任何Prolog系统中,已发布的代码已经可以

但是,对于此类组合任务使用 CLP(FD)约束时有明显的优势。

让我告诉你我的意思。首先,这是一个直接的CLP(FD)任务的表述:

regions(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.

我只有:

  • 更改了变量的可读性(R1AR2B等。)
  • 用CLP(FD)约束dif/2
  • 替换(#\=)/2
  • 完全基于整数 0..3而不是原子,因此CLP(FD)约束完全适用。请注意,有限域上的任何问题都可以映射到整数,因此CLP(FD)约束始终是此类任务的合适选择。

首先,让我们尝试最常见的查询,看看原则上的答案是什么样的:

?- regions(Rs).
Rs = [_640, _646, _652, _658, _664, _670],
_640 in 0..3,
_640#\=_670,
_640#\=_658,
_640#\=_652,
_640#\=_646,
etc.

这似乎很好。约束求解器以残差目标响应。此外,我们看到我们的关系终止并且实际上是 deterministic ,这是非常好的。 标记变量将保留终止行为,因此我们不会意外地陷入程序其他部分的循环中。

我们可以通过标记变量轻松获得具体的解决方案

?- regions(Rs), label(Rs).
Rs = [0, 1, 2, 1, 0, 3] .

这里,每个整数对应一个唯一的颜色。我让这些解决方案变得更好,易于阅读。

现在重点!

或更确切地说:点!

CLP(FD)约束提供dif/2 的功能,即约束传播

在这种情况下,我们最初有以下情况:

Map colouring initial situation

这里,每个小点代表一种颜色,我们仍然可能用于它所在的区域。首先,约束求解器没有排除任何颜色,因此我们找到所有区域中的每个选项。

如果我们只将一个区域分配给固定颜色,则情况会发生

?- regions([A,B,C,D,E,F]), F = 0.
F = 0,
A in 1..3,
A#\=D,
A#\=C,
A#\=B,
D in 1..3,
D#\=E,
C#\=D,
E in 0..3,
C#\=E,
B#\=E,
C in 1..3,
B#\=C,
B in 0..3.

我只添加了统一(F = 0),这导致约束解算器从所有相邻区域修剪此选项:

Remaining options after a single assignment

现在,我只发布了一个附加统一:

?- regions([A,B,C,D,E,F]), F = 0, C = 1.
C = 1,
F = 0,
A in 2..3,
A#\=D,
A#\=B,
D in 2..3,
D#\=E,
E in 0\/2..3,
B#\=E,
B in 0\/2..3.

再次自动(即约束求解器为你做的)会删除许多其他可能的赋值:

enter image description here

只有一个战略任务(我将其留作练习以找出哪个),我们得到以下情况:

enter image description here

现在,剩下的唯一选择是如何为尚未分配任何固定颜色的单个剩余区域着色。很容易看出,现在两种可接受的颜色解决了整个任务。

dif/2也会修剪搜索空间。但是,CLP(FD)约束对变量的实际执行此强大的修剪。这意味着许多值根本不需要尝试。此外,基于这种推理,约束求解器可以更智能地选择标记为 next 的变量,这在许多情况下进一步提高了性能。

答案 1 :(得分:2)

您的计划没有任何问题。它适用于任何实现dif / 2的Prolog:

?- regions(Rs).
Rs = [red, green, blue, green, red, yellow] ;
Rs = [red, green, blue, green, yellow, yellow] ;
....

您也不需要库(clpfd)。

答案 2 :(得分:0)

您还可以使用answer set programming,即一些前向链接和选择运算符。这是一些代码:

:- use_module(library(basic/lists)).
:- use_module(library(minimal/delta)).

edge(r1, r2).
edge(r1, r3).
edge(r1, r4).
edge(r1, r6).
edge(r2, r3).
edge(r2, r5).
edge(r3, r4).
edge(r3, r5).
edge(r3, r6).
edge(r4, r5).
edge(r4, r6).

:- thread_local color/2, vertex/1.

post(color(X,red)); post(color(X,green));
post(color(X,blue)); post(color(X,yellow)) <= posted(vertex(X)).

fail <= posted(color(X,C)), posted(color(Y,C)), {edge(X,Y)}.

regions(Rs) :-
        post(vertex(r1)),
        post(vertex(r2)),
        post(vertex(r3)),
        post(vertex(r4)),
        post(vertex(r5)),
        post(vertex(r6)),
        maplist(color, [r1,r2,r3,r4,r5,r6], Rs).

上面的代码是即将发布的1.3.1版的预览。以上内容在运行时给出以下结果:

Jekejeke Prolog 3, Runtime Library 1.3.1
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- regions(X).
X = [red,green,blue,green,red,yellow] ;
X = [red,green,blue,green,yellow,yellow]
...