我有一个列表,其中所有对都由 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).
有人可以解释一下吗?谢谢。
最佳答案
你的实现有两个问题,首先事实不能从资本开始,所以:
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 nonmonotonic
这意味着您放置影响 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 !!
关于Prolog:计算变量使列表中的对全部不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47113535/