Генерация определенной симметричной матрицы
Я хочу, чтобы быстрый метод (одна строка, в Python NumPy или Matlab) генерировать конкретную симметричную матрицу, зная ее размеры и параметр a
,
Эта матрица должна иметь 1-a
по диагонали и в другом месте:
1-a a a a ....... a
a 1-a a ........... a
a a 1-a a a
a . .
. . .
. 1-a a
a .......................... 1-a
4 ответа
В MATLAB вы можете сделать:
a*ones(n,n) + (1-2*a)*diag(ones(n,1))
где n
это размер вашей матрицы.
Если вы можете жить с двумя строками, вы также можете сделать:
A = a*ones(n,n);
A(1:n+1:end) = 1-a; %this sets the diagonal entries
который я считаю немного более эффективным.
Вот такой крошечный лайнер
a = 0.7
n = 4
np.where(np.eye(n), 1-a, a)
# array([[0.3, 0.7, 0.7, 0.7],
# [0.7, 0.3, 0.7, 0.7],
# [0.7, 0.7, 0.3, 0.7],
# [0.7, 0.7, 0.7, 0.3]])
Если скорость вызывает беспокойство, то я рекомендую
res = np.full((n, n), a)
np.einsum('ii->i', res)[:] = 1-a
res
# array([[0.3, 0.7, 0.7, 0.7],
# [0.7, 0.3, 0.7, 0.7],
# [0.7, 0.7, 0.3, 0.7],
# [0.7, 0.7, 0.7, 0.3]])
У @Savithru есть два превосходных ответа в Matlab. Здесь я просто хочу сделать это для удовольствия....
РЕДАКТИРОВАТЬ: Удивительно, repmat
с последующим reshape
на самом деле быстрее, чем сложение. В следующем примере различные методы, в том числе методы Савитру, синхронизируются и сравниваются.
n = 1e4;
a = 2;
timeit(@() reshape([repmat([1-a, a*ones(1,n)], 1,n-1),1-a], n,n))
timeit(@() a*ones(n,n) + (1-2*a)*eye(n))
timeit(@() a*ones(n,n) + (1-2*a)*diag(ones(n,1)))
timeit(@() testf(a,n))
function y = testf(a,n)
A = a*ones(n,n);
A(1:n+1:end) = 1-a;
y = A;
end
ans =
0.7034
ans =
1.0010
ans =
1.0091
ans =
0.4209
Методы, приведенные ниже, могут не содержать 1 строку, но они должны быть быстрыми!
Метод 1: создать массив с np.ones
и заполните fill_diagonal
с numpy
, ты можешь использовать np.ones
а также np.fill_diagonal
:
a = 5
size = 5
arr = np.ones((size,size)) * a
np.fill_diagonal(arr, a-1)
>>> arr
array([[4., 5., 5., 5., 5.],
[5., 4., 5., 5., 5.],
[5., 5., 4., 5., 5.],
[5., 5., 5., 4., 5.],
[5., 5., 5., 5., 4.]])
Способ 2: заполните диагональ np.diag_indices
вместо:
В качестве альтернативы, используя np.diag_indices
:
arr = np.ones((size,size)) * a
di = np.diag_indices(size)
arr[di] = a-1
Метод 3: создать массив с np.full
Вы также можете создать оригинальный массив, используя np.full
вместо np.ones
:
arr = np.full((size,size), a)
np.fill_diagonal(arr, a-1)
# or:
# arr = np.full((size,size), a)
# np.fill_diagonal(arr, a-1)