这是一个复杂的问题。例如,我在R中有一个任意的正方形矩阵(也可以在Julia中)
> set.seed(420)
> A <- matrix(runif(16),nrow = 4,byrow = T)
> A
[,1] [,2] [,3] [,4]
[1,] 0.6055390 0.9702770 0.1744545 0.4757888
[2,] 0.7244812 0.8761027 0.3775037 0.6409362
[3,] 0.6546772 0.5062158 0.3033477 0.7162497
[4,] 0.2905202 0.1962252 0.3225786 0.8404279
我想将此矩阵转换为对称矩阵,以使对角线元素始终是A
矩阵的2个相应对角线元素中的最小值。在上述情况下,结果必须为:
[,1] [,2] [,3] [,4]
[1,] 0.6055390 0.7244812 0.1744545 0.2905202
[2,] 0.7244812 0.8761027 0.3775037 0.1962252
[3,] 0.1744545 0.3775037 0.3033477 0.3225786
[4,] 0.2905202 0.1962252 0.3225786 0.8404279
将是一种在Julia和/或R中对其进行编程的高效且不费时的方法。必须适用于任何种类的方阵。
答案 0 :(得分:2)
可能最好的方法是使用Rcpp
进行几个for循环,但是您也可以尝试一下:
idx <- A <= t(A)
A * idx + t(A) * (1L - idx)
修改
基本R解决方案在时间和内存方面都是低效的。如果您需要速度和/或内存,请使用Rcpp
函数,使矩阵对称。一个修改它,另一个返回一个副本。
library(Rcpp)
cppFunction('
void inplaceSymmetric(NumericMatrix A) {
for (int i = 1; i < A.nrow(); ++i)
for (int j = 0; j < i; ++j)
if (A(i, j) < A(j, i))
A(j, i) = A(i, j);
else
A(i, j) = A(j, i);
}')
cppFunction('
NumericMatrix copySymmetric(NumericMatrix A) {
NumericMatrix C = clone(A);
for (int i = 1; i < A.nrow(); ++i)
for (int j = 0; j < i; ++j)
if (A(i, j) < A(j, i))
C(j, i) = C(i, j);
else
C(i, j) = C(j, i);
return C;
}')
答案 1 :(得分:2)
在朱莉娅,单线是
B = [min(A[i,j], A[j,i]) for i in axes(A, 1), j in axes(A, 2)]
但是,这可以完成所需工作的两倍。以下方法效率更高,可以就地修改原始矩阵,并且如果矩阵不是正方形,则会生成一条不错的错误消息:
function symmetrize_min!(A::AbstractMatrix)
ax1 = axes(A, 1)
axes(A, 2) == ax1 || error("A must be square")
for j in ax1
for i in j+1:last(ax1)
A[i,j] = A[j,i] = min(A[i,j], A[j,i])
end
end
return A
end
在Julia中,有一项约定,函数修改其参数以!
结尾,作为对用户的警告。如果您不希望它修改A
,则可以在调用之前copy(A)
或进行一些小的更改:
function symmetrize_min(A::AbstractMatrix)
ax1 = axes(A, 1)
axes(A, 2) == ax1 || error("A must be square")
B = similar(A)
for j in ax1
B[j,j] = A[j,j]
for i in j+1:last(ax1)
B[i,j] = B[j,i] = min(A[i,j], A[j,i])
end
end
return B
end
在Julia中,您应该拥抱循环-循环很快。而且由于它们易于编写,看似复杂的问题也变得简单。