Sorting 快速反向排序(SWI)Prolog

Sorting 快速反向排序(SWI)Prolog,sorting,prolog,Sorting,Prolog,我正在寻找一种在Prolog中按相反顺序对列表进行排序的快速方法。从算法上讲,它应该和标准排序一样快,但我提出的选项要慢得多,原因很明显 谓词rsort1/2排序,然后反转 rsort1(L1, L2) :- sort(L1, Tmp), reverse(Tmp, L2). 谓词rsort2/2使用带有自定义比较器的predsort/3 rsort2(L1, L2) :- predsort(reverse_compare, L1, L2). reverse_compa

我正在寻找一种在Prolog中按相反顺序对列表进行排序的快速方法。从算法上讲,它应该和标准排序一样快,但我提出的选项要慢得多,原因很明显

谓词
rsort1/2
排序,然后反转

rsort1(L1, L2) :-
    sort(L1, Tmp),
    reverse(Tmp, L2).
谓词
rsort2/2
使用带有自定义比较器的
predsort/3

rsort2(L1, L2) :-
    predsort(reverse_compare, L1, L2).

reverse_compare(Delta, E1, E2) :-
    compare(Delta, E2, E1).
为了测试它们的性能,我生成了一个巨大的随机列表,如下所示:

?- Size = 1234567,
   findall(N, (between(1, Size, _), N is random(Size)), Ns),
   assert(test_list(Ns)).
Size = 1234567,
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258|...].
以下是标准
排序的运行时:

?- test_list(Ns), time(sort(Ns, NsS)).
% 2 inferences, 7.550 CPU in 8.534 seconds (88% CPU, 0 Lips)
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258, 625628|...],
NsS = [0, 1, 3, 5, 8, 10, 12, 14, 16|...].
。。。对于
rsort1

?- test_list(Ns), time(rsort1(Ns, NsS)).
% 779,895 inferences, 8.310 CPU in 9.011 seconds (92% CPU, 93850 Lips)
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258, 625628|...],
NsS = [1234564, 1234563, 1234562, 1234558, 1234557, 1234556, 1234555|...].
。。。对于
rsort2

?- test_list(Ns), time(rsort2(Ns, NsS)).
% 92,768,484 inferences, 67.990 CPU in 97.666 seconds (70% CPU, 1364443 Lips)
Ns = [183677, 351963, 737135, 246842, 22754, 1176800, 1036258, 625628|...],
NsS = [1234564, 1234563, 1234562, 1234558, 1234557, 1234556, 1234555|...].

我能比
rsort1
rsort2
speedwise做得更好吗?

如果您要的是一个可移植的排序例程(即,使用PROLOG定义),那么您可能无法实现比那些在C/C++中本机执行排序例程的谓词更快(或者更快,需要反转排序顺序),例如
sort/2
msort/2

如果这里最关心的是速度,那么当然可以使用外部定义编写自己的不可移植谓词来执行反向排序。例如,可以使用(参见示例)编写一个C++代码定义:<代码> rSt/ 2 < /C>,也许使用C++中实现的。p> 同样,您也可以使用SWI-PL C接口在C中编写
rsort/2
。在SWI-PROLOG中,源代码包含排序方法的实现(即
nat_sort()
),用于
sort/2
msort/2
keysort/2
。要实现
rsort/2
,您可能只需要遵循它们的实现并调整/反转对
compare()
调用的解释,该调用描述了术语的标准顺序

定义谓词:
1.获取列表中的最低数字
2.删除列表中的项目
3.合并两个列表
4.按排序列表
a) 获取最低的
b) 删除列表中最低的
c) 对新列表进行排序,但不使用最低值(递归)

使用基本规则医嘱列表([X],[X])。

考虑使用不同的输入进行基准测试。许多排序算法在其输入“已按顺序”时表现“最佳”,而在其输入与正确顺序相反时表现“最差”,这可能解释了您在
rsort2
@aschepler中看到的大部分差异谢谢,我现在正在测试随机输入,但是它没有任何变化……predsort/3速度较慢,因为它不是内置的(它是用SWI中的Prolog编写的,而sort/2和keysort/2是用C编写的)。使用keysort/2通常比predsort/3快,但需要密钥的辅助(全局)堆栈空间。该算法效率非常低。快速排序或合并排序更容易在prolog中实现,而且速度更快。。。尽管纯prolog版本无法击败内置版本。