Matlab中的稀疏随机矩阵,其值不同于[0,1]

时间:2015-05-16 21:44:06

标签: matlab random sparse-matrix

如何在Matlab中创建一个稀疏随机矩阵,其值范围不同于默认[0,1],比如[-1,1]?我尝试过的两件事显然不起作用:

p = 2 * sprand(5,5,0.1) - 1

返回

>> p = -1.0000 -1.0000 -1.0000 -1.0000 -1.0000
       -1.0000 -1.0000 -1.0000 -1.0000 -1.0000  
       -1.0000 -1.0000 -1.0000 -1.0000 -1.0000
       -1.0000 -1.0000 -0.4850 -1.0000 -1.0000
        0.6814 -1.0000 -1.0000 -1.0000 -1.0000

p = ceil(sprand(5,5,0.1));
p(find(p)) = 2 * rand(5) - 1;
full(p)

返回

>> ans =          0  0       0  0  0 
                  0  0       0  0  0
                  0  0       0  0  0
                  0  0  0.3112  0  0
             0.3112  0       0  0  0

我想要一个不涉及任何循环的解决方案,只使用矩阵操作或内置Matlab函数。

2 个答案:

答案 0 :(得分:0)

实际上我找到了一种方法:

>> p = sprand(5,5,0.1)
>> d = 2 * rand(5) - 1
>> p(find(p)) = d(find(p))

这使用sprand生成稀疏结构randthe canonical way移动随机值的范围,得到5x5矩阵,其值在[-1,1]范围内],然后find函数找到具有非零值的稀疏矩阵的线性索引,并使用这些索引从随机矩阵中分配相应的值。

我看到的唯一缺点是你仍然必须生成完整的随机矩阵,所以我仍然想知道如何更有效地做到这一点。

答案 1 :(得分:0)

不必丢弃sprand的均匀随机变量,并分配第二个随机值的完整矩阵。我是这样使用logical indexingnonzeros

p = sprand(5,5,0.1);
p(p~=0) = 2*nonzeros(p)-1;

或者,您可以这样做(对于使用R2015a的一些简单测试中的大型数组来说有点慢):

p = sprand(5,5,0.1);
ne0 = (p~=0);
p(ne0) = 2*p(ne0)-1;

对于非常旧版本的Matlab中的稀疏数组,可能不支持逻辑索引。在这种情况下,您可以使用find

p = sprand(5,5,0.1);
p(find(p)) = 2*nonzeros(p)-1;

最后,您还可以使用randpermind2subrandsparse实现自己的功能:

function R = sprand11(m,n,density)
%SPRAND11  Sparse random matrix distributed on the interval (-1,1)
idx = randperm(m*n,round(density*m*n));     % Find random indices
[i,j] = ind2sub([m n],idx);                 % Convert linear indices subscripts
R = sparse(i,j,2*rand(1,numel(idx))-1,m,n); % Create sparse random matrix

我不确定这是否正是sprand在引擎盖下的实施方式,但它应该是接近的。它的速度也是上述解决方案的两倍。


所有这些选项都避免生成完整的M-by-N矩阵或将p转换为完全然后再转换为稀疏。如果你不介意暂时创建一个大的完整矩阵,那么禁食方法(假设你有足够的内存)可能是这样的:

function R = sprand11(m,n,density)
idx = randperm(m*n,round(density*m*n)); % Find random indices
R = zeros(m,n);
R(idx) = 2*rand(1,numel(idx))-1;        % Create random matrix
R = sparse(R);                          % Convert to sparse