繁体   English   中英

CLP(FD),地图着色

[英]CLP(FD), Map 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).

确实是这样:发布的代码已经可以在任何提供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)约束(#\\=)/2替换了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.

这似乎还可以。 约束求解器以剩余目标作为响应。 另外,我们看到我们的关系终止并且实际上是确定性的 ,这非常令人高兴。 标记变量将保留终止行为,因此我们不会在程序的其他部分意外地陷入循环。

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

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

在此,每个整数对应于唯一的颜色。 我将使这些解决方案更易于阅读,以便更好地阅读。

现在要说了!

或更确切地说:点!

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

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

地图着色的初始情况

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

如果我们仅将一种区域分配为固定颜色,情况将发生巨大变化:

?- 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 ),这导致约束求解器从所有相邻区域修剪此选项:

一次分配后剩余的选项

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

?- 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.

再次自动执行 (即约束求解器为您完成),删除了许多其他可能的分配:

在此处输入图片说明

仅执行一项战略任务(我将其作为练习来找出其中一项),就可以得出以下情况:

在此处输入图片说明

现在,剩下的唯一选择就是如何为尚未分配任何固定颜色的单个剩余区域着色。 显而易见,现在两种允许的颜色可以解决整个任务。

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

您的程序没有任何问题。 它可以在任何实现dif / 2的Prolog中使用:

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

您也不需要library(clpfd)。

您还可以使用答案集编程 ,即一些前向链接和选择运算符。 这是一些代码:

:- 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]
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM