Quantcast
Channel: Active questions tagged python - Stack Overflow
Viewing all articles
Browse latest Browse all 14155

Find two rectangles with maximum sum

$
0
0

emphasized textIt is possible to find a rectangle in a large n by n matrix of integers that has the maximum sum reasonably quickly. There is an O(n^3) time algorithm as described here and here for example. There is also fast code.

import numpy as npimport timeimport numbanumba.config.DISABLE_JIT = Falsedef _gt(s=0.0):    return time.perf_counter() - s@numba.njit(cache=True)def kadane(arr, n):    # initialize subarray_sum, max_subarray_sum and    subarray_sum = 0    max_subarray_sum = np.int32(-2147483648)    # Just some initial value to check    # for all negative values case    finish = -1    # local variable    local_start = 0    for i in range(n):        subarray_sum += arr[i]        if subarray_sum < 0:            subarray_sum = 0            local_start = i + 1        elif subarray_sum > max_subarray_sum:            max_subarray_sum = subarray_sum            start = local_start            finish = i    # There is at-least one    # non-negative number    if finish != -1:        return max_subarray_sum, start, finish    # raise AssertionError('Untested code block')    # Special Case: When all numbers    # in arr[] are negative    max_subarray_sum = arr[0]    start = finish = 0    # Find the maximum element in array    for i in range(1, n):        if arr[i] > max_subarray_sum:            max_subarray_sum = arr[i]            start = finish = i    return max_subarray_sum, start, finish# The main function that finds maximum subarray_sum rectangle in M@numba.njit(cache=True, parallel=True)def findMaxsubarray_sum(M):    num_rows, num_cols = M.shape    out_pos_arr = np.empty((num_cols * num_cols, 4), dtype=np.int32)    out_sum_arr = np.full((num_cols * num_cols,), np.int32(-2147483648), dtype=np.int32)    # Set the left column    for left in numba.prange(num_cols):        # Initialize all elements of temp as 0        temp = np.zeros(num_rows, dtype=np.int_)        # Set the right column for the left        # column set by outer loop        for right in range(left, num_cols):            temp += M[:num_rows, right]            subarray_sum, start, finish = kadane(temp, num_rows)            out_sum_arr[left * num_cols + right] = subarray_sum            out_pos_arr[left * num_cols + right, :] = np.array((left, right, start, finish))    max_pos = np.argmax(out_sum_arr)    finalLeft, finalRight, finalTop, finalBottom = out_pos_arr[max_pos]    max_subarray_sum = out_sum_arr[max_pos]    return finalTop, finalLeft, finalBottom, finalRight, max_subarray_sumdef _main():    # First loop may have numba compilations    #   second loop shows true-er performance    run_sum = 0.0    loop_count = 10    for i in range(loop_count):        rng = np.random.default_rng(seed=42)        N = 800        # N = 1700        square = rng.integers(-3, 4, (N, N), dtype=np.int32)        # square = rng.integers(-30, -4, (N, N))        s = _gt()        finalTop, finalLeft, finalBottom, finalRight, max_subarray_sum = findMaxsubarray_sum(square)        run_time = _gt(s)        print(f'Run time: {N},{run_time:8.6f}')        # Don't count numba compilation time        if i > 0:            run_sum += run_time        if False:            print("(Top, Left)", "(", finalTop, finalLeft, ")")            print("(Bottom, Right)", "(", finalBottom, finalRight, ")")            print("Max subarray_sum is:", max_subarray_sum)            print()    print(f'Average speed: {run_sum / (loop_count - 1):.5f}')if __name__ == '__main__':    _main()

I would like to find a pair of rectangles where the sum of the integers covered is maximal. Double counting is not allowed (that is an integer at a given coordinate is only counted once). I am happy if we restrict the problem to non-overlapping rectangles if it makes it easier to do quickly.

How can you do that?


Viewing all articles
Browse latest Browse all 14155

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>