我为最近的问题
Segregating Lists in Prolog提供了以下基于clpfd的代码:
list_evens_odds([],[],[]).
list_evens_odds([X|Xs],[X|Es],Os) :-
X mod 2 #= 0,
list_evens_odds(Xs,Es,Os).
list_evens_odds([X|Xs],Es,[X|Os]) :-
X mod 2 #= 1,
list_evens_odds(Xs,Es,Os).
它简洁明了,但可以留下许多不必要的选择点.考虑:
?- list_evens_odds([1,2,3,4,5,6,7],Es,Os).
上面的查询为[1,2,3,4,5,6,7]中的每个非奇数项留下了无用的选择点.
替代实施
使用Prolog union for A U B U C中@false演示的具体化技术可以减少不必要的选择点的数量.实施可能会改为:
list_evens_odds([],[],[]).
list_evens_odds([X|Xs],Es,Os) :-
if_(#<=>(X mod 2 #= 0), (Es=[X|Es0],Os= Os0),
(Es= Es0, Os=[X|Os0])),
list_evens_odds(Xs,Es0,Os0).
要直接与clpfd-reification交互,if_ / 3的实现可以像这样进行调整:
if_( C_1, Then_0, Else_0) :-
call(C_1,Truth01),
indomain(Truth01),
( Truth01 == 1 -> Then_0 ; Truth01 == 0, Else_0 ).
当然,(=)/ 3也需要适应这个惯例.
底线
所以我想知道:使用0和1作为真值而不是假和真是一个好主意?
我在那条路上错过了什么问题?请帮忙!先感谢您!
最佳答案 在SWI-Prolog中,您可以使用zcompare / 3:
:- use_module(library(clpfd)).
list_evens_odds([], [], []).
list_evens_odds([X|Xs], Es, Os) :-
Mod #= X mod 2,
zcompare(Ord, 0, Mod),
ord_(Ord, X, Es0, Es, Os0, Os),
list_evens_odds(Xs, Es0, Os0).
ord_(=, X, Es0, [X|Es0], Os, Os).
ord_(<, X, Es, Es, Os0, [X|Os0]).
示例查询:
?- list_evens_odds([1,2,3,4,5,6,7], Es, Os).
Es = [2, 4, 6],
Os = [1, 3, 5, 7].