File size: 3,646 Bytes
ca1888b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python
"""
random.py

Tools related to randomness

"""
from __future__ import absolute_import

import os
import sys
import numpy as np
import random

import core_scripts.other_tools.display as nii_display

__author__ = "Xin Wang"
__email__ = "wangxin@nii.ac.jp"
__copyright__ = "Copyright 2021, Xin Wang"

##############
# Shuffling tools
##############

def f_shuffle_slice_inplace(input_list, slice_start=None, slice_stop=None):
    """ shuffle_slice(input_list, slice_start, slice_stop)
    
    Shuffling input list (in place) in the range specified by slice_start
    and slice_stop.

    Based on Knuth shuffling 
    https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

    input
    -----
      input_list: list
      slice_start: int, start idx of the range to be shuffled
      slice_end: int, end idx of the range to be shuffled
      
      Both slice_start and slice_end should be in the style of python index
      e.g., shuffle_slice(input_list, 0, N) will shuffle the slice input[0:N]
    
      When slice_start / slice_stop is None,
      slice_start = 0 / slice_stop = len(input_list)

    output
    ------
      none: shuffling is done in place
    """
    if slice_start is None or slice_start < 0:
        slice_start = 0 
    if slice_stop is None or slice_stop > len(input_list):
        slice_stop = len(input_list)
        
    idx = slice_start
    while (idx < slice_stop - 1):
        idx_swap = random.randrange(idx, slice_stop)
        # naive swap
        tmp = input_list[idx_swap]
        input_list[idx_swap] = input_list[idx]
        input_list[idx] = tmp
        idx += 1
    return

def f_shuffle_in_block_inplace(input_list, block_size):
    """
    f_shuffle_in_block_inplace(input_list, block_size)
    
    Shuffle the input list (in place) by dividing the list input blocks and 
    shuffling within each block
    
    Example:
    >>> data = [1,2,3,4,5,6]
    >>> random_tools.f_shuffle_in_block_inplace(data, 3)
    >>> data
    [3, 1, 2, 5, 4, 6]

    input
    -----
      input_list: input list
      block_size: int
    
    output
    ------
      None: shuffling is done in place
    """
    if block_size <= 1:
        # no need to shuffle if block size if 1
        return
    else:
        list_length = len(input_list)
        # range( -(- x // y) ) -> int(ceil(x / y))
        for iter_idx in range( -(-list_length // block_size) ):
            # shuffle within each block
            f_shuffle_slice_inplace(
                input_list, iter_idx * block_size, (iter_idx+1) * block_size)
        return

def f_shuffle_blocks_inplace(input_list, block_size):
    """ 
    f_shuffle_blocks_inplace(input_list, block_size)
    
    Shuffle the input list (in place) by dividing the list input blocks and 
    shuffling blocks
    
    Example:
     >> data = np.arange(1, 7)
     >> f_shuffle_blocks_inplace(data, 3)
     >> print(data)
     [4 5 6 1 2 3]

    input
    -----
      input_list: input list
      block_size: int
    
    output
    ------
      None: shuffling is done in place
    """
    # new list
    tmp_list = input_list.copy()

    block_number = len(input_list) // block_size
    
    shuffle_block_idx = [x for x in range(block_number)]
    random.shuffle(shuffle_block_idx)

    new_idx = None
    for iter_idx in range(block_size * block_number):
        block_idx = iter_idx // block_size
        in_block_idx = iter_idx % block_size
        new_idx = shuffle_block_idx[block_idx] * block_size + in_block_idx
        input_list[iter_idx] = tmp_list[new_idx]
    return

if __name__ == "__main__":
    print("Definition of randomness tools")