我有以下谓词:
soln(L,M,O,R,S,V) :-
permutation([L,M,O,R,S,V],[1,2,3,4,5,6]),
R=\=S+1,
R=\=S-1,
M=:=L+1,
O>M,
O<S.
当我从REPL调用它时,它打印出正确的答案:
?- soln(L,M,O,R,S,V).
L = 1,
M = 2,
O = 3,
R = 4,
S = 6,
V = 5 ;
L = 1,
M = 2,
O = 3,
R = 6,
S = 4,
V = 5 .
然而,对我来说更有用的是输出,其中变量根据它们的值排序;使用前面的例子,像[L,M,O,R,V,S], [L,M,O,S,V,R], ...
这样的东西是理想的。
我希望能够在REPL和独立脚本中执行此操作。
答案 0 :(得分:3)
如果要根据名称对名称进行排序,则必须跟踪变量与名称之间的关联。
这是因为您在Prolog程序中无法访问源代码中看到的变量名,因此您必须以Prolog中可访问的方式跟踪名称。
一种方法是跟踪Variable-Name
形式的对列表。这样,当变量绑定到某个值时,您仍然知道其预期的名称。
因此,我建议进行以下轻微改写:
:- use_module(library(clpfd)). solution(Pairs) :- Vs = [L,M,O,R,S,_V], Names = [l,m,o,r,s,v], pairs_keys_values(Pairs, Vs, Names), R #\= S+1, R #\= S-1, M #= L+1, O #> M, O #< S, Vs ins 1..6.
请注意,我现在使用原子 l
,m
,o
等来表示名称变量,我现在推理对。此外,我已经冒昧地用约束来表达这一切,因此我们受益于约束传播,而不必尝试每个排列。使用约束,Prolog引擎可以修剪搜索空间的重要部分,甚至无需尝试。我使用_V
来表示变量V
,因为此变量在其他任何地方都没有提及,因此使用V
会导致单例警告。
我们已经可以尝试了:
?- solution(Pairs), pairs_keys_values(Pairs, Vs, Names), label(Vs). Pairs = [1-l, 2-m, 3-o, 1-r, 4-s, 1-v], Vs = [1, 2, 3, 1, 4, 1], Names = [l, m, o, r, s, v] ; Pairs = [1-l, 2-m, 3-o, 1-r, 4-s, 2-v], Vs = [1, 2, 3, 1, 4, 2], Names = [l, m, o, r, s, v] ; Pairs = [1-l, 2-m, 3-o, 1-r, 4-s, 3-v], Vs = [1, 2, 3, 1, 4, 3], Names = [l, m, o, r, s, v] ; etc.
现在,要根据这些变量的值排序名称,请使用ISO谓词keysort/2
,它根据键对对进行排序,即,他们的第一个组成部分:
?- solution(Pairs0), pairs_keys_values(Pairs0, Vs0, Names0), label(Vs0), keysort(Pairs0, Pairs), pairs_values(Pairs, Names). Pairs0 = [1-l, 2-m, 3-o, 1-r, 4-s, 1-v], Vs0 = [1, 2, 3, 1, 4, 1], Names0 = [l, m, o, r, s, v], Pairs = [1-l, 1-r, 1-v, 2-m, 3-o, 4-s], Names = [l, r, v, m, o, s] ; Pairs0 = [1-l, 2-m, 3-o, 1-r, 4-s, 2-v], Vs0 = [1, 2, 3, 1, 4, 2], Names0 = [l, m, o, r, s, v], Pairs = [1-l, 1-r, 2-m, 2-v, 3-o, 4-s], Names = [l, r, m, v, o, s] ; Pairs0 = [1-l, 2-m, 3-o, 1-r, 4-s, 3-v], Vs0 = [1, 2, 3, 1, 4, 3], Names0 = [l, m, o, r, s, v], Pairs = [1-l, 1-r, 2-m, 3-o, 3-v, 4-s], Names = [l, r, m, o, v, s] ; Pairs0 = [1-l, 2-m, 3-o, 1-r, 4-s, 4-v], Vs0 = [1, 2, 3, 1, 4, 4], Names0 = [l, m, o, r, s, v], Pairs = [1-l, 1-r, 2-m, 3-o, 4-s, 4-v], Names = [l, r, m, o, s, v] ; etc.