【发布时间】:2015-06-12 02:27:41
【问题描述】:
我为最近的问题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 作为真值而不是false 和true 是个好主意吗?
我错过了那条路上的问题吗?请帮忙!提前谢谢!
【问题讨论】:
-
快速修复
..., X mod 2 #= M, if_(M=0, ...。另外,您可以给另一个if_/3取另一个名字,例如if0_/3
标签: prolog clpfd reification