prolog中列表对中的最小元素速度较慢

prolog中列表对中的最小元素速度较慢,prolog,failure-slice,Prolog,Failure Slice,我在GNU Prolog中有这段代码,我不知道为什么50个元素的成对列表速度慢: pairwise_min( [X], X ) :- !. pairwise_min( [(A,B)|T], (A,B) ) :- pairwise_min( T, (_,B1) ), B1 > B, !. pairwise_min( [(_,B)|T], (A1,B1) ) :- pairwise_min( T, (A1,B1) ), B1 =< B, !

我在GNU Prolog中有这段代码,我不知道为什么50个元素的成对列表速度慢:

pairwise_min( [X], X ) :- !.
pairwise_min( [(A,B)|T], (A,B) ) :-
    pairwise_min( T, (_,B1) ),
    B1 > B,
    !.
pairwise_min( [(_,B)|T], (A1,B1) ) :-
    pairwise_min( T, (A1,B1) ),
    B1 =< B,
    !.

如何快速找到该最小值?

跟踪时,您可以快速发现问题:

?- trace, pairwise_min( [(25,25),(24,24),(23,23),(22,22),(21,21),(20,20),(19,19),(18,18),(17,17),(16,16),(15,15),(14,14),(13,13),(12,12),(11,11),(10,10),(9,9),(8,8),(7,7),(6,6),(5,5),(4,4),(3,3),(2,2),(1,1)], X ).
   Call: (7) pairwise_min([ (25, 25), (24, 24), (23, 23), (22, 22), (21, 21), (20, 20), (19, 19), (..., ...)|...], _G737) ? 
   ... snip ...
   Call: (30) pairwise_min([ (2, 2), (1, 1)], (_G1065, _G1066)) ? 
   Call: (31) pairwise_min([ (1, 1)], (_G1068, _G1069)) ? 
   Exit: (31) pairwise_min([ (1, 1)], (1, 1)) ? 
   Call: (31) 1>2 ? 
   Fail: (31) 1>2 ? 
   Redo: (30) pairwise_min([ (2, 2), (1, 1)], (_G1065, _G1066)) ? 
   Call: (31) pairwise_min([ (1, 1)], (_G1065, _G1066)) ? 
   Exit: (31) pairwise_min([ (1, 1)], (1, 1)) ? 
   Call: (31) 1=<2 ? 
   Exit: (31) 1=<2 ? 
   Exit: (30) pairwise_min([ (2, 2), (1, 1)], (1, 1)) ? 
   Call: (30) 1>3 ? 
   Fail: (30) 1>3 ? 
   Redo: (29) pairwise_min([ (3, 3), (2, 2), (1, 1)], (_G1062, _G1063)) ? 
   Call: (30) pairwise_min([ (2, 2), (1, 1)], (_G1062, _G1063)) ? 
   Call: (31) pairwise_min([ (1, 1)], (_G1068, _G1069)) ? 
   Exit: (31) pairwise_min([ (1, 1)], (1, 1)) ? 
   Call: (31) 1>2 ? 
   Fail: (31) 1>2 ? 
   Redo: (30) pairwise_min([ (2, 2), (1, 1)], (_G1062, _G1063)) ? 
   Call: (31) pairwise_min([ (1, 1)], (_G1062, _G1063)) ? 
   Exit: (31) pairwise_min([ (1, 1)], (1, 1)) ? 
   Call: (31) 1=<2 ? 
   Exit: (31) 1=<2 ? 
对我来说,可读性的一个重要障碍是,我并不真正了解你试图用成对最小值实现什么样的排序。但无论如何,将来将其提取到自己的谓词中是个好主意。我对你的最低要求没有信心;
@最小值(Xs,X,Min)不是真的吗
; 最小值(Xs,MinSoFar,Min))。

如果不是这样,您可以编写自己的谓词
minu pair/2
来比较两个对,并使用它来代替
@一个非常简单的定义,不是优化的,而是相当快的

pairwise_min(L, (A,B)) :-
    select((A,B), L, R),
    \+ ( member((A1,B1), R), B1 < B ).
成对最小值(L,(A,B)):- 选择((A,B),L,R), \+(构件((A1,B1),R),B1

无论如何,研究代码的性能将是理解Prolog的执行模型的一个非常好的方法

,从某种意义上说,您很幸运找到了正确的查询。想象一下,你会选择一个升序列表。在这种情况下,您目前会体验到一个更快的程序。但在演示日,降序名单会毁了你的表演

要了解实际发生的情况,只查看程序的一个非常小的片段通常非常有用。既然你们的削减基本上是绿色削减,我们可以这样做,即使他们在场。我将在您的计划中添加
false
目标。不要期望这个片段有任何意义。它已经没有了。但是,它向我们展示了Prolog必须探索的搜索空间:

pairwise_min( [X], X ) :- false, !. pairwise_min( [(A,B)|T], (A,B) ) :- pairwise_min( T, (_,B1) ), false B1 > B, !. pairwise_min( [(_,B)|T], (A1,B1) ) :- pairwise_min( T, (A1,B1) ), false B1 =< B, !. 两两最小值([X],X):-false!。 两两最小值([(A,B)| T],(A,B)):- 成对最小(T,(,B1)),假 B1>B, !. 两两最小值([(B)T],(A1,B1)):- 成对最小(T,(A1,B1)),假 B1=
minimum([X|Xs], Min) :- minimum(Xs, X, Min).
minimum([], Min, Min).
minimum([X|Xs], MinSoFar, Min) :-
    (X @< MinSoFar -> minimum(Xs,        X, Min)
                    ; minimum(Xs, MinSoFar, Min)).
pairwise_min(L, (A,B)) :-
    select((A,B), L, R),
    \+ ( member((A1,B1), R), B1 < B ).
pairwise_min( [X], X ) :- false, !. pairwise_min( [(A,B)|T], (A,B) ) :- pairwise_min( T, (_,B1) ), false B1 > B, !. pairwise_min( [(_,B)|T], (A1,B1) ) :- pairwise_min( T, (A1,B1) ), false B1 =< B, !.