Можно ли в этом случае использовать itertools для неопределенного числа измерений? - PullRequest
0 голосов
/ 03 февраля 2019

Это мой код, работающий с dim = 3, но я бы хотел, чтобы он работал для любой размерности без необходимости вручную редактировать код.

Я бы хотел иметь возможность изменять размерность между 3 и20 в конечном итоге без необходимости вручную создавать рекламные циклы.Я смотрел на itertools, но не знаю, как выбрать правильные значения из кортежей, созданных itertools.product(), в квадрат и сложить для моего оператора if.

arrayshape = (width * 2 + 1,) * dim
funcspace = np.zeros(shape=arrayshape, dtype='b')

x1 = list(range(-int(width), int(width + 1)))
x2 = x1
x3 = x1

for i in range(len(x1)):
    for j in range(len(x2)):
        for k in range(len(x3)):
            if round(np.sqrt(x1[i] ** 2 + x2[j] ** 2 + x3[k] ** 2)) in ranges:
                funcspace[i][j][k] = 1

1 Ответ

0 голосов
/ 03 февраля 2019

Вы можете использовать product на enumerate ваших векторов, что даст значение и индекс:

for ((i,v1),(j,v2),(k,v3)) in itertools.product(enumerate(x1),enumerate(x2),enumerate(x3)):
    if round(np.sqrt(v1**2+v2**2+v3**2)) in ranges:
            funcspace[i][j][k]=1

в качестве бонуса, вы избавитесь от непифонической конструкции range(len()).

Я подготовил более общий случай, когда у вас есть вектор векторов.Это немного сложнее читать, потому что распаковка не выполняется в цикле for.

Квадратная сумма выполняется с использованием sum для 1 индекса (значения), и если условие соответствует, мыЦикл пока мы не найдем «более глубокий» список, чтобы установить значение 1.

for t in itertools.product(*(enumerate(x) for x in x_list)):
    # compute the squared sum of values
    sqsum = sum(v[1]**2 for v in t)
    if round(sqsum) in ranges:
        # traverse the dimensions except the last one
        deeper_list = funcspace
        for i in range(len(t)-1):
            deeper_list = deeper_list[t[i][0]]
        # set the flag using the last dimension list
        deeper_list[t[-1][0]] = 1

, как отмечено в комментариях, так как x1, кажется, повторяется, вы можете заменить первое утверждение на:

for t in itertools.product(enumerate(x1), repeat=dim):

В других комментариях говорится, что, поскольку funcspace - пустая цифра ndarray, мы можем упростить цикл «set to 1», передав список индексов:

funcspace[[x[0] for x in t]] = 1
...