Skip to content

Commit fd13fcc

Browse files
committed
Test Manilla's criterion 5: M(aX) <= |X| + M(X)
1 parent 8f2b816 commit fd13fcc

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

docs/Measures-of-presortedness.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Measures of presortedness were formally defined by H. Mannila in *Measures of pr
1414
> 4. If every element of *X* is smaller than every element of *Y*, then *M*(*XY*) ≤ *M*(*X*) + *M*(*Y*)
1515
> 5. *M*(⟨*x**X*) ≤ |*X*| + *M*(*X*) for every element *x* of the domain
1616
17-
A few measures of presortedness described in the research papers actually return 1 when *X* is already sorted, thus violating the first property above. We implement those measures in a such way that they return 0 instead, generally by subtracting 1 from the result of the described operation.
17+
A few measures of presortedness described below do not fully satisfy all of the criteria above: instead of sctrictly following Mannila, **cpp-sort** takes a broader approach similar to that of O. Petersson and A. Moffat in *A framework for adaptive sorting*, and includes more measures of disorder found in the relevant literature. For legibility, some measures that are normally defined as returning 1 when *X* is already sorted, are implemented here in a such way that they return 0 instead (generally by subtracting 1 from the result of the described operation).
1818

1919
### Partial ordering of measures of presortedness
2020

@@ -170,6 +170,8 @@ Computes the number of elements in *X* that are not in their sorted position, wh
170170

171171
`max_for_size`: |*X*| when every element in *X* is one element away from its sorted position.
172172

173+
**Note:** *Ham* does not respect Mannila's criterion 5: $Ham(\langle 4, 1, 2, 3 \rangle) \not \le |\langle 1, 2, 3 \rangle| + Ham(\langle 1, 2, 3 \rangle)$.
174+
173175
### *Inv*
174176

175177
```cpp
@@ -235,6 +237,8 @@ When there isn't enough extra memory available, `probe::osc` falls back to an in
235237

236238
`max_for_size`: (|*X*| * (|*X*| - 2) - 1) / 2 when the values in *X* are strongly oscillating.
237239

240+
**Note:** *Osc* does not respect Mannila's criterion 5: $Osc(\langle 2, 4, 1, 3, 1, 3 \rangle) \not \le |\langle 4, 1, 3, 1, 3 \rangle| + Osc(\langle 4, 1, 3, 1, 3 \rangle)$, though it is possible that it only happens when equivalent elements are involved.
241+
238242
***WARNING:** the O(n²) fallback of `probe::osc` is deprecated since version 1.12.0 and removed in version 2.0.0.*
239243

240244
*Changed in version 1.12.0:* `probe::osc` is now O(n log n) instead of O(n²) but now also requires O(n) memory. The O(n²) is kept for backward compatibility but will be removed in the future.
@@ -289,6 +293,8 @@ Spearman's footrule distance: sum of distances between the position of individua
289293

290294
`max_for_size`: |*X*|²/2 when *X* is sorted in reverse order.
291295

296+
**Note:** *Spear* does not respect Mannila's criterion 5: $Spear(\langle 4, 1, 2, 3 \rangle) \not \le |\langle 1, 2, 3 \rangle| + Spear(\langle 1, 2, 3 \rangle)$.
297+
292298
*New in version 1.17.0*
293299

294300
### *SUS*

tests/probes/every_probe_common.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <type_traits>
77
#include <vector>
88
#include <catch2/catch_template_test_macros.hpp>
9+
#include <rapidcheck.h>
10+
#include <rapidcheck/catch.h>
911
#include <cpp-sort/probes.h>
1012

1113
//
@@ -27,6 +29,7 @@ TEMPLATE_TEST_CASE( "test every probe with all_equal distribution", "[probe]",
2729
decltype(cppsort::probe::spear),
2830
decltype(cppsort::probe::sus) )
2931
{
32+
// First property formalized by Mannila
3033
// Ensure that all measures of presortedness return 0 when
3134
// given a collection where all elements are equal
3235

@@ -51,6 +54,7 @@ TEMPLATE_TEST_CASE( "test every probe with a sorted collection", "[probe]",
5154
decltype(cppsort::probe::spear),
5255
decltype(cppsort::probe::sus) )
5356
{
57+
// First property formalized by Mannila
5458
// Ensure that all measures of presortedness return 0 when
5559
// given a collection where all elements are sorted
5660

@@ -76,6 +80,7 @@ TEMPLATE_TEST_CASE( "test every probe with a 0 or 1 element", "[probe]",
7680
decltype(cppsort::probe::spear),
7781
decltype(cppsort::probe::sus) )
7882
{
83+
// First property formalized by Mannila
7984
// Ensure that all measures of presortedness return 0 when
8085
// given a collection with 0 or 1 element
8186

@@ -95,3 +100,28 @@ TEMPLATE_TEST_CASE( "test every probe with a 0 or 1 element", "[probe]",
95100
CHECK( presortedness == 0 );
96101
}
97102
}
103+
104+
TEMPLATE_TEST_CASE( "test M(aX) <= |X| + M(X) for most probes M", "[probe]",
105+
decltype(cppsort::probe::block),
106+
decltype(cppsort::probe::dis),
107+
decltype(cppsort::probe::enc),
108+
decltype(cppsort::probe::exc),
109+
decltype(cppsort::probe::inv),
110+
decltype(cppsort::probe::max),
111+
decltype(cppsort::probe::mono),
112+
decltype(cppsort::probe::rem),
113+
decltype(cppsort::probe::runs),
114+
decltype(cppsort::probe::sus) )
115+
{
116+
// Fifth property formalized by Mannila
117+
// The following probes don't satisfy it: ham, osc, spear
118+
119+
rc::prop("M(⟨a⟩X) ≤ |X| + M(X)", [](const std::vector<int>& sequence) {
120+
std::decay_t<TestType> mop;
121+
auto size = static_cast<std::vector<int>::difference_type>(sequence.size());
122+
if (size <= 2) {
123+
return true;
124+
}
125+
return mop(sequence) <= (size - 1) + mop(sequence.begin() + 1, sequence.end());
126+
});
127+
}

0 commit comments

Comments
 (0)