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

How to sort output in Prolog?

我有以下谓词:

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

如果您想根据名称对名称进行排序,则必须跟踪变量与其 名称.

之间的关联

这是因为您在源代码中看到的变量名称在 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.

请注意,我现在使用 atoms lmo 等来表示 变量的名称,我现在推理。此外,我冒昧地用 constraints 来表达这一切,因此我们受益于约束 propagation 而不必尝试每个排列。使用约束,Prolog 引擎可以 删减 搜索的重要部分 space 而无需尝试。我使用 _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.