Это довольно другой подход к проблеме, но, поскольку вы, похоже, работаете с перестановками, я не уверен, что числовые различия имеют такое значение.Однако вы можете увидеть проблему с точки зрения перестановок, то есть переупорядочения векторов.Вместо разницы между двумя векторами вы можете рассмотреть перестановку, которая переносит вас от одного вектора к другому, и вместо добавления двух векторов вы можете рассмотреть возможность применения перестановки к вектору.Если вы хотите иметь параметр M
, возможно, это может быть количество раз, когда вы применяете перестановку?(при условии, что это неотрицательное целое число)
Вот основная идея того, как вы могли бы реализовать это:
import numpy as np
# Finds the permutation that takes you from vector a to vector b.
# Returns a vector p such that a[p] = b.
def permutation_diff(a, b):
p = np.zeros_like(a)
p[a] = np.arange(len(p), dtype=p.dtype)
return p[b]
# Applies permutation p to vector a, m times.
def permutation_apply(a, p, m=1):
out = a.copy()
for _ in range(m):
out = out[p]
return out
# Combination function
def combine(b, c, d, m):
return permutation_apply(b, permutation_diff(d, c), m)
# Test
b = np.array([3, 5, 1, 2, 9, 8, 0, 6, 7, 4])
c = np.array([2, 3, 8, 4, 5, 1, 0, 6, 9, 7])
d = np.array([6, 1, 9, 2, 7, 5, 8, 0, 3, 4])
m = 1
a = combine(b, c, d, m)
print(a)
# [2 7 0 4 8 5 6 3 1 9]
Поскольку вы работаете со многими векторами, расположенными в матрице, выможет предпочесть векторизованные версии вышеуказанных функций.Вы можете получить это с чем-то вроде этого (здесь я предполагаю, что M является фиксированным параметром для всего алгоритма, а не для отдельного человека):
import numpy as np
# Finds the permutations that takes you from vectors in a to vectors in b.
def permutation_diff_vec(a, b):
p = np.zeros_like(a)
i = np.arange(len(p))[:, np.newaxis]
p[i, a] = np.arange(p.shape[-1], dtype=p.dtype)
return p[i, b]
# Applies permutations in p to vectors a, m times.
def permutation_apply_vec(a, p, m=1):
out = a.copy()
i = np.arange(len(out))[:, np.newaxis]
for _ in range(m):
out = out[i, p]
return out
# Combination function
def combine_vec(b, c, d, m):
return permutation_apply_vec(b, permutation_diff_vec(d, c), m)
# Test
np.random.seed(100)
arr = np.array([[2, 8, 4, 9, 1, 6, 7, 3, 0, 5],
[3, 5, 1, 2, 9, 8, 0, 6, 7, 4],
[2, 3, 8, 4, 5, 1, 0, 6, 9, 7],
[6, 1, 9, 2, 7, 5, 8, 0, 3, 4]])
n = len(arr)
b = arr[np.random.choice(n, size=n)]
c = arr[np.random.choice(n, size=n)]
d = arr[np.random.choice(n, size=n)]
m = 1
arr[:] = combine_vec(b, c, d, m)
print(arr)
# [[3 6 0 2 5 1 4 7 8 9]
# [6 1 9 2 7 5 8 0 3 4]
# [6 9 2 3 5 0 4 1 8 7]
# [2 6 5 4 1 9 8 0 7 3]]