Reputation: 861
I want a fast method (one line, in python numpy or matlab) to generate a specific symmetric Matrix knowing it dimensions and a parameter a
.
This matrix should have 1-a
on the diagonal and a elsewhere:
1-a a a a ....... a
a 1-a a ........... a
a a 1-a a a
a . .
. . .
. 1-a a
a .......................... 1-a
Upvotes: 0
Views: 108
Reputation: 53029
Here is a numpy one liner
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]])
If speed is a concern then I recommend
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]])
Upvotes: 2
Reputation: 2983
@Savithru has two excellent answers in Matlab. Here I just want to do it for fun....
EDIT: Surprisingly, repmat
followed by reshape
is actually faster than addition. In the following example, different methods, including Savithru's, are timed and compared.
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
Upvotes: 2
Reputation: 745
In MATLAB you can do:
a*ones(n,n) + (1-2*a)*diag(ones(n,1))
where n
is the size of your matrix.
If you can live with two lines, you could also do:
A = a*ones(n,n);
A(1:n+1:end) = 1-a; %this sets the diagonal entries
which I think is slightly more efficient.
Upvotes: 3
Reputation: 51335
The methods below might not be 1 line, but they should be fast!
np.ones
and fill with fill_diagonal
with numpy
, you can use np.ones
and 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.]])
np.diag_indices
instead:Alternatively, using np.diag_indices
:
arr = np.ones((size,size)) * a
di = np.diag_indices(size)
arr[di] = a-1
np.full
You can also create the original array using np.full
instead of 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)
Upvotes: 1