Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimal Batcher odd-even merge networks for sizes different than 2^n

These days, I have been trying to implement sorting networks up to size 32 with a minimal number of compare-exchange units (optimal in size, not in depth). As of now, I have been able to use the following resources to generate my networks:

  • Sorting networks 0 thru 16: Perl's Algorithm::Networksort module with "Best" algorithm. Unfortunately, it only provides the best known networks until size 16.

  • Sorting networks 17 thru 23: Using Symmetry and Evolutionary Search to Minimize Sorting Networks by Valsalam and Miikkulainen.

The paper Finding Better Sorting Networks by Baddar gives the minimal number of compare-exchange units known to be needed for sorting networks 0 to 32 (not up-to-date since Valsalam and Miikkulainen provide better algorithms for the sizes 17, 18, 19, 20, 21 and 22) and the method used to find them: basically, one has to split the array to sort in two, then sort both halves using the best known sorting networks for these sizes before merging them using an odd-even merge network (which corresponds to the merge step of Batcher's odd-even mergesort).

The Wikipedia page gives the following Python implementation for Batcher's odd-even mergesort:

def oddeven_merge(lo, hi, r):
    step = r * 2
    if step < hi - lo:
        yield from oddeven_merge(lo, hi, step)
        yield from oddeven_merge(lo + r, hi, step)
        yield from [(i, i + r) for i in range(lo + r, hi - r, step)]
    else:
        yield (lo, lo + r)

def oddeven_merge_sort_range(lo, hi):
    """ sort the part of x with indices between lo and hi.

    Note: endpoints (lo and hi) are included.
    """
    if (hi - lo) >= 1:
        # if there is more than one element, split the input
        # down the middle and first sort the first and second
        # half, followed by merging them.
        mid = lo + ((hi - lo) // 2)
        yield from oddeven_merge_sort_range(lo, mid)
        yield from oddeven_merge_sort_range(mid + 1, hi)
        yield from oddeven_merge(lo, hi, 1)

def oddeven_merge_sort(length):
    """ "length" is the length of the list to be sorted.
    Returns a list of pairs of indices starting with 0 """
    yield from oddeven_merge_sort_range(0, length - 1)

The oddeven_merge step is already isolated, so it was easy to use it alone to generate the pairs of indices needed to merge the two sorted halves of the original array. However, this implementation only works when the size of the array is a power of 2. Therefore, it only allowed me to find the minimal known number of compare-exchange units needed for a sorting network of size 32. Removing the indices pairs with the highest index allowed me to find the equivalent sorting network of size 31, but removing more pairs didn't yield the best known results for sizes smaller than 31.

Perl's Algorithm::Networksort module provides an alternative Batcher's odd-even mergesort implementation that works with arrays of any size, not only powers of 2. Therefore, I decided to have a look at it to see whether I could extract the merging step from the algorithm. Here is the Python equivalent (it also corresponds to the algorithm as described by Knuth in The Art of Computer Programming vol. 3):

def oddeven_merge_sort(length):
    t = math.ceil(math.log2(length))

    p = 2 ** (t - 1)

    while p > 0:
        q = 2 ** (t - 1)
        r = 0
        d = p

        while d > 0:
            for i in range(length - d):
                if i & p == r:
                    yield (i, i + d)

            d = q - p
            q //= 2
            r = p
        p //= 2

Unfortunately, this algorithm seems a bit cryptic to my eyes, and I wasn't able to extract the merging part from it at all. I managed to derive a merging network that gave me the minimal known number of compare-exchange units needed for a sorting network of size 24 but the trick I used didn't scale to any other sizes (and from my understanding, it was definitely not an odd-even merge).

I have tried a couple more things to adapt the merge step from Batcher's odd-even mergesort for arrays whose size is not a power of two, but I wasn't able to find the best-known sorting networks for sizes 25, 26, 27, 28, 29 and 30. How can I derive this merge step to find the missing pieces of the puzzle?

like image 342
Morwenn Avatar asked Oct 24 '15 16:10

Morwenn


People also ask

How many Subproblems does merge sort divide a problem of size n into?

Merge sort time complexity analysis Conquer part: We are recursively solving two sub-problems, each of size n/2.

What is the best time complexity of merge sort?

The list of size N is divided into a max of Logn parts, and the merging of all sublists into a single list takes O(N) time, the worst-case run time of this algorithm is O(nLogn) Best Case Time Complexity: O(n*log n) Worst Case Time Complexity: O(n*log n) Average Time Complexity: O(n*log n) The time complexity of ...

What is the best suited Big O notation for merge?

Overall time complexity of Merge sort is O(nLogn). It is more efficient as it is in worst case also the runtime is O(nlogn) The space complexity of Merge sort is O(n).

How do merge sort work with odd numbers?

The way Merge Sort works is: An initial array is divided into two roughly equal parts. If the array has an odd number of elements, one of those "halves" is by one element larger than the other. The subarrays are divided over and over again into halves until you end up with arrays that have only one element each.


1 Answers

The Perl algorithm mentions in a comment that it's algorithm 5.2.2M in Knuth's Searching and Sorting.

In turn, Knuth mentions that it merges the sorted sequences together with when p = 1. So to generate your pairs that merge the sequence for any N you simply run the algorithm with p = 1:

def oddeven_merge_step(length):
    t = math.ceil(math.log2(length))
    q = 2 ** (t - 1)
    r = 0
    d = 1

    while d > 0:
        for i in range(length - d):
            if i & 1 == r:
                yield (i, i + d)

        d = q - 1
        q //= 2
        r = 1

Note that Batcher's Odd-Even merge step expects the sorted sequences interleaved (even, odd, even, ...), but produces a sorted sequence that is contiguous.

For example for N = 25 it generates the following network:

network

like image 85
orlp Avatar answered Oct 06 '22 03:10

orlp