Это можно сделать без циклов, но я, как правило, не уверен, что это такая замечательная идея из-за значительно увеличенного времени выполнения.
Основная идея c относительно просто: поскольку тензорные присваивания всегда присваивают последний элемент, достаточно отсортировать ваши кортежи по M
в порядке убывания, согласно соответствующим значениям, хранящимся в списке значений (назовем его v
).
Чтобы сделать это в pytorch, давайте рассмотрим следующий пример:
import torch as t
X = t.randn([3, 3]) # Random matrix of size 3x3
v = t.tensor([1, 2, 3])
M = t.tensor([[0, 2, 0],
[1, 2, 1]]) # accessing the elements described above
# Showcase pytorch's result with "naive" tensor assignment:
X[tuple(M)] = v # This would assign the value 3 to position (0, 1)
# To correct behavior, sort v in decreasing order.
v_desc = v.sort(decreasing=True)
# v now contains both the values and the indices of original position
print(v_desc)
# torch.return_types.sort(
# values=tensor([3, 2, 1]),
# indices=tensor([2, 1, 0]))
# Access M in the correct order:
M_desc = M[:, v_desc.indices]
# Finally assign correct order:
X[tuple(M_desc)] = v_desc
Опять же, это относительно сложно, потому что оно включает в себя сортировку значений и «перестановку» тензоров. Вы, безусловно, можете сэкономить хотя бы часть памяти, если будете выполнять операции на месте, что я не принимал во внимание для удобства чтения.
В качестве ответа на вопрос, можно ли это сделать и без сортировки, я вполне уверен, что ответ будет «нет»; тензорные присваивания могут быть выполнены только для довольно простых условных выражений, но не более сложных, как того требуют ваши взаимозависимые условные выражения.