From 30e19dacb59ee685b337714177022cd1ea326a5c Mon Sep 17 00:00:00 2001 From: Harsheet Kakar <42893005+HarsheetKakar@users.noreply.github.com> Date: Mon, 30 Mar 2020 19:53:29 +0530 Subject: [PATCH] Bricksort parallel implemented (#221) --- .../linear_data_structures/__init__.py | 3 +- .../linear_data_structures/algorithms.py | 72 ++++++++++++++++++- .../tests/test_algorithms.py | 6 +- 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/pydatastructs/linear_data_structures/__init__.py b/pydatastructs/linear_data_structures/__init__.py index 510c421e3..eb9cee095 100644 --- a/pydatastructs/linear_data_structures/__init__.py +++ b/pydatastructs/linear_data_structures/__init__.py @@ -22,6 +22,7 @@ from .algorithms import ( merge_sort_parallel, - brick_sort + brick_sort, + brick_sort_parallel ) __all__.extend(algorithms.__all__) diff --git a/pydatastructs/linear_data_structures/algorithms.py b/pydatastructs/linear_data_structures/algorithms.py index b556d7e7f..dc3d8d6ff 100644 --- a/pydatastructs/linear_data_structures/algorithms.py +++ b/pydatastructs/linear_data_structures/algorithms.py @@ -6,7 +6,8 @@ __all__ = [ 'merge_sort_parallel', - 'brick_sort' + 'brick_sort', + 'brick_sort_parallel' ] def _merge(array, sl, el, sr, er, end, comp): @@ -163,3 +164,72 @@ def brick_sort(array, **kwargs): if _check_type(array, DynamicArray): array._modify(force=True) + +def _brick_sort_swap(array, i, j, comp, is_sorted): + if _comp(array[j], array[i], comp): + array[i], array[j] = array[j], array[i] + is_sorted[0] = False + +def brick_sort_parallel(array, num_threads, **kwargs): + """ + Implements Concurrent Brick Sort / Odd Even sorting algorithm + + Parameters + ========== + + array: Array/list + The array which is to be sorted. + num_threads: int + The maximum number of threads + to be used for sorting. + start: int + The starting index of the portion + which is to be sorted. + Optional, by default 0 + end: int + The ending index of the portion which + is to be sorted. + Optional, by default the index + of the last position filled. + comp: lambda/function + The comparator which is to be used + for sorting. If the function returns + False then only swapping is performed. + Optional, by default, less than or + equal to is used for comparing two + values. + + Examples + ======== + + >>> from pydatastructs import OneDimensionalArray, brick_sort_parallel + >>> arr = OneDimensionalArray(int,[3, 2, 1]) + >>> brick_sort_parallel(arr, num_threads=5) + >>> [arr[0], arr[1], arr[2]] + [1, 2, 3] + >>> brick_sort_parallel(arr, num_threads=5, comp=lambda u, v: u > v) + >>> [arr[0], arr[1], arr[2]] + [3, 2, 1] + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Odd%E2%80%93even_sort + """ + + start = kwargs.get('start', 0) + end = kwargs.get('end', len(array) - 1) + comp = kwargs.get("comp", lambda u, v: u <= v) + + is_sorted = [False] + with ThreadPoolExecutor(max_workers=num_threads) as Executor: + while is_sorted[0] is False: + is_sorted[0] = True + for i in range(start + 1, end, 2): + Executor.submit(_brick_sort_swap, array, i, i + 1, comp, is_sorted).result() + + for i in range(start, end, 2): + Executor.submit(_brick_sort_swap, array, i, i + 1, comp, is_sorted).result() + + if _check_type(array, DynamicArray): + array._modify(force=True) diff --git a/pydatastructs/linear_data_structures/tests/test_algorithms.py b/pydatastructs/linear_data_structures/tests/test_algorithms.py index ef14b2ec4..f590b5628 100644 --- a/pydatastructs/linear_data_structures/tests/test_algorithms.py +++ b/pydatastructs/linear_data_structures/tests/test_algorithms.py @@ -1,6 +1,7 @@ from pydatastructs import ( merge_sort_parallel, DynamicOneDimensionalArray, - OneDimensionalArray, brick_sort) + OneDimensionalArray, brick_sort, brick_sort_parallel) + import random def _test_common_sort(sort, *args, **kwargs): @@ -44,3 +45,6 @@ def test_merge_sort_parallel(): def test_brick_sort(): _test_common_sort(brick_sort) + +def test_brick_sort_parallel(): + _test_common_sort(brick_sort_parallel, num_threads=3)