生成特定的对称矩阵
Generating a specific Symmetric Matrix
我想要一个快速的方法(一行,在 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
在 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
我认为效率更高一些。
下面的方法可能不是 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.]])
方法二:用np.diag_indices
代替对角线填充:
或者,使用 np.diag_indices
:
arr = np.ones((size,size)) * a
di = np.diag_indices(size)
arr[di] = a-1
方法三:用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)
@Savithru 在 Matlab 中有两个很好的答案。在这里我只是想玩玩....
编辑:令人惊讶的是,repmat
后跟 reshape
实际上比加法更快。在以下示例中,对包括 Savithru 在内的不同方法进行了计时和比较。
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
这是一个 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]])
如果速度是一个问题,那么我建议
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]])
我想要一个快速的方法(一行,在 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
在 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
我认为效率更高一些。
下面的方法可能不是 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.]])
方法二:用np.diag_indices
代替对角线填充:
或者,使用 np.diag_indices
:
arr = np.ones((size,size)) * a
di = np.diag_indices(size)
arr[di] = a-1
方法三:用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)
@Savithru 在 Matlab 中有两个很好的答案。在这里我只是想玩玩....
编辑:令人惊讶的是,repmat
后跟 reshape
实际上比加法更快。在以下示例中,对包括 Savithru 在内的不同方法进行了计时和比较。
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
这是一个 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]])
如果速度是一个问题,那么我建议
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]])