如何在 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 l
、m
、o
等来表示 变量的名称,我现在推理对。此外,我冒昧地用 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.
我有以下谓词:
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 l
、m
、o
等来表示 变量的名称,我现在推理对。此外,我冒昧地用 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.