物化整合问题

时间:2015-04-07 13:10:52

标签: prolog clpfd reification

我为最近的问题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也需要适应这一惯例。

底线

所以我想知道:使用01作为真值而不是falsetrue是一个好主意吗?

我在这条路上错过了什么问题?请帮忙!提前谢谢!

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].

答案 1 :(得分:1)

我已经重新考虑过我的建议&#34;重复使用&#34; if_/3的{​​{1}},我觉得我现在通过它看得更清楚了。

@ false和@lurker的评论以及@mat的回答在帮助我的理解方面得到了公平的分享。谢谢!

&#34;见解&#34;我获得的并不是戏剧性的;我还想和你分享:

  1. 像我一样调整if_/3是可行的,也可能与某些LOC相同。
  2. 然而,它混合了两个在程序上彼此完全不同的概念:默认情况下,clpfd传播然后延迟。具体的术语平等OTOH立即强制选择。
  3. 将这两个用例分开是更清晰的。当然,&#34;清洁确实紧挨着敬虔&#34; ...

答案 2 :(得分:0)

直接的解决方案(适用于任何可恢复的clp(fd)条件)似乎是

:- use_module(library(clpfd)).

list_evens_odds([],[],[]).
list_evens_odds([X|Xs],Es,Os) :-
   B #<==> (X mod 2 #= 0),
   freeze(B, (B=1 -> Es=[X|Es0],Os=Os0 ; Es=Es0,Os=[X|Os0])),
   list_evens_odds(Xs,Es0,Os0).

将0/1或真/假用作真值并不重要。算术求解器中首选0/1约定的原因很简单,就是你可以很容易地在算术约束中重用真值。加起来等等。