I'm looking for a fast way to sort a list in reverse order in Prolog. Algorithmically it should perform as quickly as standard sort, but the options that I've come up with are much slower, for obvious reasons.
Predicate rsort1/2
sorts and then reverses.
rsort1(L1, L2) :-
sort(L1, Tmp),
reverse(Tmp, L2).
Predicate rsort2/2
uses predsort/3
with a custom comparator.
rsort2(L1, L2) :-
开发者_如何学JAVA predsort(reverse_compare, L1, L2).
reverse_compare(Delta, E1, E2) :-
compare(Delta, E2, E1).
To test their performance I've generated a huge random list like this:
?- 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|...].
These are the runtimes for the standard sort
:
?- 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|...].
... for 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|...].
... and for 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|...].
Can I do better than rsort1
and rsort2
speedwise?
If you're after a sorting routine that is portable (i.e., defined using PROLOG), then you probably won't be able to implement anything faster (or as fast, with a need to reverse the sort order) than those predicates that execute sorting routines natively in C/C++, such as sort/2
or msort/2
.
If speed is of overriding concern here, you could of course write your own non-portable predicate with an external definition to do the reverse sorting. For example, the SWI-PL C++ interface could be used (see the examples there) to write a C++ definition of rsort/2
, perhaps using the comparison predicates also implemented in C++.
Similarly, you could also write rsort/2
in C using the SWI-PL C interface. src/pl-list.c
in the SWI-PROLOG source contains implementations of the sorting methods (namely nat_sort()
) which is used for sort/2
, msort/2
and keysort/2
. To implement rsort/2
, you might only need to follow their implementation and tweak/reverse the interpretation of calls to compare()
which describes the standard order of terms.
define predicates:
1. get lowest number in a list.
2. deleting an item in a list.
3. merging two lists.
4. sorting a list by
a) getting the lowest
b) deleting the lowest in a list
c) sort the new list without the lowest (recursion)
with the base rule orderlist([X],[X]).
精彩评论