Генерация определенной симметричной матрицы - PullRequest
0 голосов
/ 20 декабря 2018

Я хочу, чтобы быстрый метод (одна строка в 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 ]

0 голосов
/ 20 декабря 2018

Вот один крошечный лайнер

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]])
0 голосов
/ 20 декабря 2018

Методы ниже могут быть не одной строкой, но они должны быть быстрыми!

метод 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)
0 голосов
/ 20 декабря 2018

@ У Савитру есть два превосходных ответа в 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
0 голосов
/ 20 декабря 2018

В 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

, что, на мой взгляд, несколько более эффективно.

...