Отслеживание того, какое подмножество вычислено, чтобы избежать смешивания результатов - PullRequest
0 голосов
/ 29 июня 2018

хитрое имя и непонятное имя ...

Моя проблема заключается в следующем:

import itertools

t0 = 0
tf = 1000000
# inputs_to_compute = list-like of size 2 to 6 of objects

results = [[] for i in range(len(inputs_to_compute))]

for subset in itertools.combinations(inputs_to_compute, 2):
    r1, r2 = compute(subset[0], subset[1], t0, tf)
    results[inputs_to_compute.index(subset[0])] += list(r1)
    results[inputs_to_compute.index(subset[1])] += list(r2)

Этот код создает столько списков результатов, сколько имеется входных данных. Каждый вход фактически связан со списком. Затем вычисление выполняется 2 на 2 (для каждого подмножества), и результат добавляется в соответствующий список.

Это работает хорошо, пока нет повторений во входных данных, потому что метод index возвращает первое вхождение элемента. Как я могу реализовать это по-другому (и эффективно, производительность является одной из основных проблем, с которыми я сталкиваюсь) таким образом, чтобы управлять копиями?

Пустой пример:

import itertools

def compute(x, y):
    return (x + y, x - y)

inputs_to_compute = [1, 1, 3]

results = [[] for i in range(len(inputs_to_compute))]

for subset in itertools.combinations(inputs_to_compute, 2):
    r1, r2 = compute(subset[0], subset[1])
    results[inputs_to_compute.index(subset[0])].append(r1)
    results[inputs_to_compute.index(subset[1])].append(r2)

Выход:

[[2, 0, 4, 4], [], [-2, -2]]

Ожидаемый результат:

# Iteration (1, 1): r1 = 2, r2 = 0
results = [[2], [0], []]
# Iteration (1, 3): r1 = 4, r2 = -2
results = [[2, 4], [0], [-2]]
# Iteration (1, 3): r1 = 4, r2 = -2
results = [[2, 4], [0, 4], [-2, -2]]

Ответы [ 3 ]

0 голосов
/ 29 июня 2018

Если я правильно понял, то вы хотите переключаться между повторными 1 с каждый раз, когда они возвращаются как часть subset.

Один из способов сделать это - создать словарь с элементом в качестве ключа и его индексами, хранящимися в списке. Как только мы получим этот диктант, мы можем применить itertools.cycle к списку и затем использовать next() для переключения между индексами элементов:

import itertools


def compute(x, y):
    return (x + y, x - y)

inputs_to_compute = [1, 1, 3]

indices = {}
for ind, item in enumerate(inputs_to_compute):
    indices.setdefault(item, []).append(ind)

for k, v in indices.items():
    indices[k] = itertools.cycle(v)

results = [[] for i in range(len(inputs_to_compute))]

for subset in itertools.combinations(inputs_to_compute, 2):
    r1, r2 = compute(subset[0], subset[1])
    results[next(indices[subset[0]])].append(r1)
    results[next(indices[subset[1]])].append(r2)

Выход:

>>> %run so.py

>>> results
[[2, 4], [0, 4], [-2, -2]]
0 голосов
/ 29 июня 2018

в документах у вас есть рецепт для комбинаций, которые используют перестановки [1]. вы просто изменяете его, чтобы вернуть индексы

import itertools

def compute(x, y):
    return (x + y, x - y)

def combinations(iterable, r):
    pool = tuple(iterable)
    n = len(pool)
    for indices in itertools.permutations(range(n), r):
        if sorted(indices) == list(indices):
            yield tuple(indices)

inputs_to_compute = [1, 1, 3]

results = [[] for i in range(len(inputs_to_compute))]
for i1, i2 in combinations(inputs_to_compute, 2):
    r1, r2 = compute(inputs_to_compute[i1], inputs_to_compute[i2])
    results[i1].append(r1)
    results[i2].append(r2)

print(results)

[1] https://docs.python.org/3/library/itertools.html#itertools.combinations

0 голосов
/ 29 июня 2018
for subset_with_indices in itertools.combinations(enumerate(inputs_to_compute), 2):
    i1,x1 = subset_with_indices[0]
    i2,x2 = subset_with_indices[1]
    r1, r2 = compute(x1, x2)
    results[i1].append(r1)
    results[i2].append(r2)
...