如何避免矩阵的所有排列相乘的for循环?

我有以下代码:

  N=8;
  K=10;
  a=zeros(1,N^(K-1));
  b=zeros(1,N^(K-1));

  for ii=1:K
    p0{ii}=rand(1,N);
    p1{ii}=rand(1,N);
  end

  k=1;
  for j1=1:N
    for j3=1:N
      for j4=1:N
        for j5=1:N
          for j6=1:N
            for j7=1:N
              for j8=1:N
                for j9=1:N
                  for j10=1:N
                    a(k)=p0{1}(j1)*p0{3}(j3)*p0{4}(j4)*p0{5}(j5)*p0{6}(j6)*p0{7}(j7)*p0{8}(j8)*p0{9}(j9)*p0{10}(j10);
                    b(k)=p1{1}(j1)*p1{3}(j3)*p1{4}(j4)*p1{5}(j5)*p1{6}(j6)*p1{7}(j7)*p1{8}(j8)*p1{9}(j9)*p1{10}(j10);
                    k=k+1;
                  end
                end
              end
            end
          end
        end
      end
    end
    end

我无法为N=8评估此代码,因为这需要花费很多时间。 p0p1是大小为KxN的矩阵。嵌套的for循环将省略p0p1的一行,此处第二行对应于索引j2。其余矩阵元素彼此相乘。因此,为了获得向量N^(K-1)a,总共要进行b个乘法。

  

是否有任何方法可以在不使用for循环的情况下或至少在合理的时间内执行此操作?

smile2010cool123 回答:如何避免矩阵的所有排列相乘的for循环?

基本上,您只是将每个p0(或p1)单元格中的每个元素彼此相乘。使用reshapeelement-wise multiplication中的一些魔术,可以简化为一个循环。

让我们看一下以下代码:

N = 3;
K = 10;

for ii = 1:K
  p0{ii} = rand(1,N);
  p1{ii} = rand(1,N);
end  

a = zeros(1,N^(K-1));
b = zeros(1,N^(K-1));

%for ii = 1:K
%  p0{ii} = rand(1,randi(N));
%  p1{ii} = rand(1,randi(N));
%end

tic;
k = 1;
for j1 = 1:N
  for j3 = 1:N
    for j4 = 1:N
      for j5 = 1:N
        for j6 = 1:N
          for j7 = 1:N
            for j8 = 1:N
              for j9 = 1:N
                for j10 = 1:N
                  a(k) = p0{1}(j1)*p0{3}(j3)*p0{4}(j4)*p0{5}(j5)*p0{6}(j6)*p0{7}(j7)*p0{8}(j8)*p0{9}(j9)*p0{10}(j10);
                  b(k) = p1{1}(j1)*p1{3}(j3)*p1{4}(j4)*p1{5}(j5)*p1{6}(j6)*p1{7}(j7)*p1{8}(j8)*p1{9}(j9)*p1{10}(j10);
                  k = k+1;
                end
              end
            end
          end
        end
      end
    end
  end
end
toc;

tic;
aa = p0{1};
bb = p1{1};
% For MATLAB versions R2016 and newer:
for jj = 3:K
  aa = reshape(aa .* p0{jj}.',1,numel(aa) .* numel(p0{jj}));
  bb = reshape(bb .* p1{jj}.',numel(bb) .* numel(p1{jj}));
end
% For MATLAB versions before R2016b: 
%for jj = 3:K
%  aa = reshape(bsxfun(@times,aa,p0{jj}.'),numel(aa) .* numel(p0{jj}));
%  bb = reshape(bsxfun(@times,bb,p1{jj}.'),numel(bb) .* numel(p1{jj}));
%end
toc;

numel(find(aa ~= a))
numel(find(bb ~= b))

输出:

Elapsed time is 2.39744 seconds.
Elapsed time is 0.00070405 seconds.
ans = 0
ans = 0

似乎aaa以及bbb实际上是相等的,并且所提出的解决方案要快得多。我仅为解决方案测试了N = 8

Elapsed time is 1.54249 seconds.

如果通过取消注释相应的行来替换p0p1的初始化,您将看到我的解决方案还允许每个p0(或{{1} }) 细胞。注意:由于硬编码,这不适用于您的初始解决方案,因此无法在此处进行比较。

另外,请注意,p1在这里也是硬编码的。如果应该省略其他部分,则必须进行相应的修改!

希望有帮助!

本文链接:https://www.f2er.com/3167848.html

大家都在问