Source code for lmpy.randomize.swap

"""Module containing Gotelli swap method for randomizing a PAM."""
import numpy as np

from lmpy.matrix import Matrix

MAX_TRIES_WITHOUT_SWAP = 1000000


# .............................................................................
[docs]def swap_randomize(matrix, num_swaps, max_tries=MAX_TRIES_WITHOUT_SWAP): """Randomize a PAM matrix using the Gotelli swap method. Args: matrix (Matrix): A Lifemapper matrix object with binary elements num_swaps (int): The number of swaps to perform max_tries (int): The maximum number of attempts to swap before failing. Returns: Matrix: A randomized matrix. Raises: Exception: Raised when the maximum number of tries is reached without swapping. Todo: Allow num_swaps to be specified as a percentage of the matrix fill. """ mtx_headers = matrix.get_headers() swapped_mtx = matrix.copy().astype(int) counter = 0 num_tries = 0 row_len, col_len = matrix.shape # num_tries is a safety to kill the loop if nothing is ever found while counter < num_swaps and num_tries < max_tries: num_tries += 1 column1 = np.random.randint(0, col_len) column2 = np.random.randint(0, col_len) row1 = np.random.randint(0, row_len) while column2 == column1: column2 = np.random.randint(0, col_len) first_corner = swapped_mtx[row1][column1] if first_corner ^ swapped_mtx[row1][column2]: row2 = np.random.randint(0, row_len) while row2 == row1: row2 = np.random.randint(0, row_len) if (first_corner ^ swapped_mtx[row2][column1]) and ( not (first_corner) ^ swapped_mtx[row2][column2] ): swapped_mtx[row1][column2] = first_corner swapped_mtx[row2][column1] = first_corner swapped_mtx[row2][column2] = not first_corner swapped_mtx[row1][column1] = not first_corner counter += 1 num_tries = 0 if num_tries >= max_tries: # pragma: no cover raise Exception('Reached maximum number of tries without finding suitable swap') return Matrix(swapped_mtx, headers=mtx_headers)
# .............................................................................
[docs]def trial_swap(matrix, num_trials=None): """Randomize a PAM matrix using the trial swap method. Args: matrix (Matrix): A Lifemapper matrix object with binary elements. num_trials (int): The number of trials to perform. Returns: Matrix: A randomized matrix. Todo: Allow num_swaps to be specified as a percentage of the matrix fill """ mtx_headers = matrix.get_headers() swapped_mtx = matrix.copy().astype(int) row_len, col_len = matrix.shape if num_trials is None: num_trials = matrix.size for _ in range(num_trials): column1 = np.random.randint(0, col_len) column2 = np.random.randint(0, col_len) row1 = np.random.randint(0, row_len) while column2 == column1: column2 = np.random.randint(0, col_len) first_corner = swapped_mtx[row1][column1] if first_corner ^ swapped_mtx[row1][column2]: row2 = np.random.randint(0, row_len) while row2 == row1: row2 = np.random.randint(0, row_len) if (first_corner ^ swapped_mtx[row2][column1]) and ( not (first_corner) ^ swapped_mtx[row2][column2] ): swapped_mtx[row1][column2] = first_corner swapped_mtx[row2][column1] = first_corner swapped_mtx[row2][column2] = not first_corner swapped_mtx[row1][column1] = not first_corner return Matrix(swapped_mtx, headers=mtx_headers)
# ............................................................................. __all__ = ['swap_randomize', 'trial_swap']