Files
mercury/tests/hard_coded/stable_sort.m
Mark Brown db259026ac Provide better documentation on how (not) to use the random number
Estimated hours taken: 1.5
Branches: main

library/random.m:
	Provide better documentation on how (not) to use the random number
	generator in the standard library.  Generators of this kind are
	very sensitive to the way in which they are used, and if used
	in a way not anticipated they can give very poor results.

	XXX The standard library really should provide a better quality RNG.
	There is still a place for quick and dirty RNGs like this one,
	though, provided users are given adequate information about the
	pitfalls.

	One of the pitfalls to avoid is that you shouldn't use mod (or rem)
	to reduce a number down to some desired range, you should use
	something like div.  We therefore provide a predicate that does
	this the prescribed way.  We also provide a predicate that is
	similar to randmax, but returns the number of distinct random
	numbers that can be generated instead of the maximum.

	Fix random__permutation to avoid the above pitfall.

	Replace some occurrences of is/2 with =/2.

NEWS:
	Mention the new predicate.

tests/hard_coded/Mmakefile:
tests/hard_coded/random_permutation.exp:
tests/hard_coded/random_permutation.m:
	A test case for random__permutation.  We don't test that the
	result is "random", but we at least test that it is a permutation.

tests/hard_coded/random_simple.exp:
tests/hard_coded/random_simple.m:
	A simple test that checks for off-by-one errors in random__random/5.

tests/hard_coded/stable_sort.m:
tests/hard_coded/test_bitset.exp:
tests/hard_coded/test_bitset.m:
	Fix these tests to avoid the above pitfall.  The bitset tester also
	needed to be modified so that it doesn't output anything that may
	depend on the particular random sequence generated.
2002-09-26 06:11:39 +00:00

89 lines
2.1 KiB
Mathematica

:- module stable_sort.
:- interface.
:- import_module io.
:- pred main(io__state::di, io__state::uo) is det.
:- implementation.
:- import_module list, random, int, bool.
main -->
{ generate_random_list(42, List) },
% io__write(List),
% io__nl,
% io__write(sort(List) `with_type` list({int, int})),
% io__nl,
{ sort_is_stable(List, Stable) },
(
{ Stable = yes },
io__write_string("list__sort/3 appears stable\n")
;
{ Stable = no },
io__write_string("list__sort/3 is not stable\n")
).
:- pred generate_random_list(int, list({int, int})).
:- mode generate_random_list(in, out) is det.
generate_random_list(Seed, List) :-
random__init(Seed, RS),
%
% We generate random integers from 0 to 9. The list length
% must be large enough to ensure that there are plenty of
% duplications, otherwise the test is trivial.
%
Count = 100,
generate_random_list_2(Count, [], List, RS, _).
:- pred generate_random_list_2(int, list({int, int}), list({int, int}),
random__supply, random__supply).
:- mode generate_random_list_2(in, in, out, mdi, muo) is det.
generate_random_list_2(Count, List0, List) -->
(
{ Count > 0 }
->
random(0, 10, R1),
random(0, 10, R2),
generate_random_list_2(Count - 1, [{R1, R2} | List0], List)
;
{ List = List0 }
).
:- pred sort_is_stable(list({int, int}), bool).
:- mode sort_is_stable(in, out) is det.
sort_is_stable(Unsorted, Stable) :-
%
% If the sort is stable then sorting on the second component
% followed by sorting on the first component should give a
% fully sorted result.
%
list__sort(compare_second, Unsorted, SortedOnSecond),
list__sort(compare_first, SortedOnSecond, SortedOnSecondThenFirst),
%
% Check the result is fully sorted.
%
list__sort(Unsorted, Sorted),
(
SortedOnSecondThenFirst = Sorted
->
Stable = yes
;
Stable = no
).
:- pred compare_first({int, int}, {int, int}, comparison_result).
:- mode compare_first(in, in, out) is det.
compare_first({A, _}, {B, _}, Res) :-
compare(Res, A, B).
:- pred compare_second({int, int}, {int, int}, comparison_result).
:- mode compare_second(in, in, out) is det.
compare_second({_, A}, {_, B}, Res) :-
compare(Res, A, B).