Создание пакетов с помощью itertools.islice - PullRequest
0 голосов
/ 29 июня 2018

Я пытаюсь использовать функции itertools.combinations и itertools.slice, чтобы создать ряд пакетов, для которых вычисления могут выполняться параллельно. Я использую следующую функцию для создания своих партий:

def construct_batches(n,k,batch_size):

    combinations_slices = []

    # Calculate number of batches
    n_batches = math.ceil(comb(n,k,exact=True)/batch_size)

    # Construct iterator for combinations
    combinations = itertools.combinations(range(n),k)

    while len(combinations_slices) < n_batches:
        combinations_slices.append(itertools.islice(combinations,batch_size))

    return combinations_slices

После выполнения некоторых вычислений я выясняю, какие партии и элементы актуальны. Таким образом, у меня есть список пакетов (например, batches = [2,3,1]) и список элементов (например, elements = [5,7,0]). К моему изумлению / ужасу питон имеет следующее поведение. Предположим, я хочу проверить, правильны ли мои кусочки. Тогда

combinations_slices = construct_batches(n,k,batch_size)

list(combinations_slices[0])
Out[491]: 
[(0, 1, 2, 3),
 (0, 1, 2, 4),
 (0, 1, 2, 5),
 (0, 1, 2, 6),
 (0, 1, 2, 7),
 (0, 1, 2, 8),
 (0, 1, 2, 9),
 (0, 1, 3, 4),
 (0, 1, 3, 5),
 (0, 1, 3, 6)]

list(combinations_slices[1])
Out[492]: 
[(0, 1, 3, 7),
 (0, 1, 3, 8),
 (0, 1, 3, 9),
 (0, 1, 4, 5),
 (0, 1, 4, 6),
 (0, 1, 4, 7),
 (0, 1, 4, 8),
 (0, 1, 4, 9),
 (0, 1, 5, 6),
 (0, 1, 5, 7)]

Это все мило и весело, показывает, что подход сработал. Однако, если я использую понимание списка, чтобы выбрать «соответствующие» партии как combinations_slices = [combinations_slices[i] for i in range(len(combinations_slices)) if i in batches], то результат будет (к сожалению):

combinations_slices = construct_batches(n,k,batch_size)

batches = [2,3,1]

combinations_slices = [combinations_slices[i] for i in range(len(combinations_slices)) if i in batches]

list(combinations_slices[0])
Out[509]: 
[(0, 1, 2, 3),
 (0, 1, 2, 4),
 (0, 1, 2, 5),
 (0, 1, 2, 6),
 (0, 1, 2, 7),
 (0, 1, 2, 8),
 (0, 1, 2, 9),
 (0, 1, 3, 4),
 (0, 1, 3, 5),
 (0, 1, 3, 6)]

list(combinations_slices[1])
Out[510]: 
[(0, 1, 3, 7),
 (0, 1, 3, 8),
 (0, 1, 3, 9),
 (0, 1, 4, 5),
 (0, 1, 4, 6),
 (0, 1, 4, 7),
 (0, 1, 4, 8),
 (0, 1, 4, 9),
 (0, 1, 5, 6),
 (0, 1, 5, 7)]

Есть ли способ получить желаемое поведение, не приводя все к спискам (как правило, эти списки комбинаций могут быть большими, так что мне не хватит памяти ...)? Предложения приветствуются ...

...