This repository presents a quadratic strict weak ordering check. Strict weak
ordering for a comparator
- Irreflexivity:
$comp(x, x)$ must be false - Antisymmetry:
$comp(x, y)$ implies$!comp(y, x)$ - Transitivity: if
$comp(x, y)$ and$comp(y, z)$ then$comp(x, z)$ - Two objects x and y are equivalent if both
$comp(x, y)$ and$comp(y, x)$ are false. Then transitivity of equivalence should be met.
Naive algorithm for steps 3 and 4 require
-
Sort
$S$ with some algorithm that correctly sorts it if$S$ satisfies strict weak ordering. And does not fail if it does not satisfy it. Bubble sort or heap sort should be good. -
Check that the range is sorted. If it's not, we know that
$S$ does not satisfy strict weak ordering. -
If it's sorted, use the following algorithm:
-
Find the minimal
$P$ such that$S[0] < S[P]$ . If no such$P$ , set P to SIZE. -
For all
$A < B < P$ check$(!comp(S[A], S[B])$ and$!comp(S[B], S[A]))$ , i.e. all elements before$P$ are equivalent. -
For all
$A < P$ and$B \geq P$ , check$(comp(S[A], S[B])$ and$!comp(S[B], S[A]))$ , i.e. all elements separated by$P$ follows transitivity. -
Remove the first P elements from S. Go to step 2.
If any condition at step 2 and 3 is not met, return FALSE. It means strict weak ordering is not met.
The runtime of this algorithm is
comparisons.
This functions can be used for testing the properties of the passed ranges. Suggested APIs:
bool strict_weak_ordering_check(first, last, settings, comp)
settings
, comp
arguments are not mandatory. We support C++11. settings
support .prior_sort
and some other
implementation defined arguments. See test for examples.
$ clang++ test.cpp -g -std=c++11 -O3 -o test
$ clang++ -g fuzz.cpp -fsanitize=address,fuzzer -std=c++11 -O3 -o fuzz
In standard libraries this can be used to check if the range satisfies strict weak ordering for a sampled range of
Sortcheck repository found a lot of problems out there and this can contribute to find even more.
If strict weak ordering is met, the algorithm obviously returns TRUE. Assume it returns TRUE and strict weak ordering is not met.
Assume
Then element with index
If it's true, then
Assume the opposite, i.e.
Find
$comp(S[i - \mathrm{removed index}], S[j - \mathrm{removed index}])$ - If
$P$ exceeds element$j$ , then step 2 should return false $comp(S[j - \mathrm{removed index}], S[k - \mathrm{removed index}])$ - If
$P$ exceeds element$k$ , then step 2 should return false - It means
$P < j - \mathrm{removed index} < k - \mathrm{removed index}$ . Then for$A = i - \mathrm{removed index}$ ,$B = k - \mathrm{removed index}$ holds the desired condition.
Obviously holds from claim 1:
It means that
Without loss of generality assume
- Find first
$P$ which exceeds element at position$I$ - If
$P > K$ , then$!comp(S[I], S[K])$ according to step 2. - If
$P \leq K$ , then- If
$P > J$ , then$comp(S[J], S[K])$ according to step 3. - If
$P \leq J$ , then$comp(S[I], S[J])$ according to step 3.
- If
If
- Find first
$P$ which exceeds element at position$J$ - If
$K < P$ , then$I < K < P$ and$!comp(S[I], S[K])$ - If
$K \geq P$ , then$comp(S[J], S[K])$