如何在Prolog中对输出进行排序?

时间:2017-01-22 10:43:21

标签: prolog prolog-toplevel

我有以下谓词:

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和独立脚本中执行此操作。

1 个答案:

答案 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.

请注意,我现在使用原子 lmo等来表示名称变量,我现在推理。此外,我已经冒昧地用约束来表达这一切,因此我们受益于约束传播,而不必尝试每个排列。使用约束,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.