matlab 广义的find()与多个占用一个向量化版本

ozxc1zmp  于 2023-06-23  发布在  Matlab
关注(0)|答案(2)|浏览(119)

我有下面的过程,其中N个粒子在M个格子中处理。每个盒子可以被任意数量的粒子占据。我把晶格的状态存储在一个向量中。
例如,状态向量[1 1 1 0]表示盒1中的1个粒子,盒2中的1个粒子,盒3中的1个粒子,盒4中的0个粒子。而状态向量[2 1 3 0]表示盒1中的2个粒子,盒2中的1个粒子,盒3中的3个粒子,以及盒4中的0个粒子。
从这个矢量中,我提取粒子在不同矢量中的位置,以进行进一步的计算。因此,对于状态[1110](N<=M),位置向量是[123],这在Matlab中使用:

pos=find([1 1 1 0])

对于像[2 1 3 0](N>M)的更一般情况向量,位置向量是[1 1 2 3 3 3]。我通过一个自定义的Matlab函数来实现这一点

pos=findGeneral([2 1 3 0])

这个函数的代码是

function [position]=findGeneral(state,N)

if 1*isempty(state(state>=2))==0  
    r=find(state);
    state=state(state~=0);        
    position=zeros(1,N);
    t=cell(1,length(r));    
    for i=1:length(r)
        t{i}=r(i)*ones(1,state(i));
    end
    position(1:N)=cell2mat(t);    
else
    position=find(state);    
end

end

当我的状态向量是一个gpuArray时,我试图运行这个函数,但显然,cell 2 mat()与gpuArrays参数不兼容。
有没有一种方法可以向量化我的代码的第7- 11行,这样我就可以摆脱for循环和cellarray了?

rlcwz9us

rlcwz9us1#

您可以使用以下命令从“位置”转到“状态”

position = [1 1 2 3 3 3];
state = sum( position.' == (1:4) );
% state = [2, 1, 3, 0]

您可以使用以下操作从“状态”转到“位置”

state = [2, 1, 3, 0];
position = repelem( 1:numel(state), state );
% position = [1, 1, 2, 3, 3, 3]

未在gpuArray上测试(仅在普通数组上),但从docs来看,gpuArray似乎支持numelrepelemsum

tquggr8v

tquggr8v2#

与Wolfie回答相反,我提供了函数findGeneral的简化版本,如下所示

1.模拟数据

ns=10
s=randi([0 3],1,ns) % s same as state
N=sum(s)

2.findGeneral内容

y=[];
fork=1:1:ns
  s2=s(k);
  if s2==0
    y=[y 0];
  end
  while s2
    y=[y k];
    s2=s2-1;
  end
end

findGeneral的返回值是y,与问题中的position相同。

相关问题