Prolog:计算变量制作对列表中的所有不同

时间:2017-11-04 17:33:00

标签: prolog

我有一个列表,所有对都包含1..3,希望列表中的所有对彼此不同。例如,对于以下事实,预期结果是

[[1, 1], [1, 2], [2, 1], [1, 3], [2, 3], [3, 1], [3, 2], [2, 2], [3, 3]]

然而,使用我的函数,似乎Prolog没有派生出该变量,输出仍然是临时变量_4848而不是数字2.

[[1, 1], [1, 2], [2, 1], [1, 3], [_4848, 3], [3, 1], [3, 2], [2, 2], [3, 3]]

以下是我的功能参考:

Grid([[1,1],[1,2],[2,1],[1,3],[_,3],[3,1],[3,2],[2,2],[3,3]]).

completegrid(G) :- 
    append(G, Vs), 
    Vs ins 1..3,
    is_set(G).  

我用

运行它
Grid(G), completegrid(G).

有人可以解释一下吗?谢谢。

2 个答案:

答案 0 :(得分:4)

您的实施中存在两个问题,首先事实不能从资本开始:

Grid([[1,1],[1,2],[2,1],[1,3],[_,3],[3,1],[3,2],[2,2],[3,3]]).

应该是:

grid([[1,1],[1,2],[2,1],[1,3],[_,3],[3,1],[3,2],[2,2],[3,3]]).

否则会出现语法错误,与Grid(G), completegrid(G).相同应该是:grid(G), completegrid(G)

第二个也是最重要的错误是Vs ins 1..3在Vs的元素中设置约束,但不评估,因此变量将保留变量(约束为值1..3时实例化),您需要使用label/2进行实例化:

:- use_module(library(clpfd)).

grid([[1,1],[1,2],[2,1],[1,3],[_,3],[3,1],[3,2],[2,2],[3,3]]).

completegrid(G) :- 
  append(G, Vs), 
  Vs ins 1..3, label(Vs),
  is_set(G). 

示例:

?- grid(G), completegrid(G).
G = [[1, 1], [1, 2], [2, 1], [1, 3], [2, 3], [3, 1], [3, 2], [2, 2], [3, 3]] ;
false.

更重要的一点是:

  

is_set / 2是非单调的

这意味着您放置影响is_set/2参数的约束会影响谓词的行为,例如:

completegrid(G) :- 
  append(G, Vs), 
  Vs ins 1..3,
  is_set(G),label(Vs).
            ^^^^^^

现在尝试:

?- grid(G), completegrid(G).
G = [[1, 1], [1, 2], [2, 1], [1, 3], [1, 3], [3, 1], [3, 2], [2|...], [...|...]] [write]
G = [[1, 1], [1, 2], [2, 1], [1, 3], [1, 3], [3, 1], [3, 2], [2, 2], [3, 3]] ;%WRONG !!
G = [[1, 1], [1, 2], [2, 1], [1, 3], [2, 3], [3, 1], [3, 2], [2, 2], [3, 3]] ;
G = [[1, 1], [1, 2], [2, 1], [1, 3], [3, 3], [3, 1], [3, 2], [2, 2], [3, 3]]. %WRONG !!

答案 1 :(得分:1)

人们对clpfd犯下的一个常见错误就是:

X in 1..3

执行将值分配给X。它向X添加约束。如果我们在终端中写这个,我们得到:

?- use_module(library(clpfd)).
true.

?- X in 1..3.
X in 1..3.

只有当您使用变量列表调用label/1时,Prolog才会搜索变量的配置,以便验证这些约束。

由于您没有X,因此过去is_set/1的列表仍会包含一个自由变量。现在is_set对项目执行重复检查,但它仅检查术语是否完全相等。因此is_set([X,Y])被认为是真的,is_set([[1,2],[1,X]])也是如此。它添加X应与X不同的约束。

但是有一个dif/2谓词,允许用来表示差异约束。我们可以定义dif_all/1谓词:

dif_all([]).
dif_all([H|T]) :-
    maplist(dif(H),T),
    dif_all(T).

现在我们的程序可以改为:

completegrid(G) :- 
    append(G, Vs),
    Vs ins 1..3,
    dif_all(G),
    label(G).