How can you use it?
May 19, 2023 · View on GitHub
This repository presents a quadratic strict weak ordering check. Strict weak ordering for a comparator and set means that it satisfies the conditions for all :
- Irreflexivity: must be false
- Antisymmetry: implies
- Transitivity: if and then
- Two objects x and y are equivalent if both and are false. Then transitivity of equivalence should be met.
Naive algorithm for steps 3 and 4 require comparisons. However, there are faster algorithms to do that. In order to check if set satisfies this condition, we are going to do the following:
-
Sort with some algorithm that correctly sorts it if 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 does not satisfy strict weak ordering.
-
If it's sorted, use the following algorithm:
-
Find the minimal such that . If no such , set P to SIZE.
-
For all check and , i.e. all elements before are equivalent.
-
For all and , check and , i.e. all elements separated by 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 . Assume we eliminate elements on each iteration and thus we made
O(x_$1^{2}$ + x_1(|S| - x_1) + x_$2^{2}$ + x_2(|S| - x_1 - x_2) + \ldots) = O(x_1|S| + x_2|S| + \ldots) = O(|S| \times |S|)comparisons.
How can you use it?
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 elements without hurting too much performance.
Sortcheck repository found a lot of problems out there and this can contribute to find even more.
Proof
If strict weak ordering is met, the algorithm obviously returns TRUE. Assume it returns TRUE and strict weak ordering is not met.
Claim 1. If , then
Assume and . Then there is a moment when at step 1 exceeds element for the first time. Then it holds
$0 < j - \mathrm{removed index} = J < P$
Then element with index and is checked at steps 2 or 3 and the opposite condition holds.
Claim 2. is false
If it's true, then .
Claim 3. and implies
Assume the opposite, i.e. and and . According to claim 1, we have .
Find which exceeds element for the first time. Then at that step we have
- If exceeds element , then step 2 should return false
- If exceeds element , then step 2 should return false
- It means . Then for , holds the desired condition.
Claim 4. Assymetry implies
Obviously holds from claim 1: otherwise.
Claim 5. Transitivity of equivalence also holds
It means that , and , and , and , and ( or ).
Without loss of generality assume (also means according to claim 1). If , then
- Find first which exceeds element at position
- If , then according to step 2.
- If , then
- If , then according to step 3.
- If , then according to step 3.
If , then
- Find first which exceeds element at position
- If , then and
- If , then