通过嵌套循环构造Matlab数组

时间:2020-09-11 16:55:15

标签: matlab

假设我有三个维度为A_1的矩阵A_2A_3mxn,其中mn很大。这些矩阵严格包含正数。

我想构造一个尺寸为check的矩阵mx1,使得对于每个i=1,...,m

check(i)=1,如果存在 j,k,这样

A_1(i,1)+A_2(j,1)+A_3(k,1)<=quantile(A_1(i,2:end)+A_2(j,2:end)+A_3(k,3:end), 0.95)

在我的情况下,m大(m=10^5)和n=500。因此,我希望您能帮助您找到一种有效的方法。


下面我重现一个示例。我强加了m比实际小,并报告了我构建check的不完整且可能效率不高的尝试。

clear
rng default
m=4;
n=500;
A_1=betarnd(1,2,m,n);
A_2=betarnd(1,2,m,n);
A_3=betarnd(1,2,m,n);
check=zeros(m,1);
for i=1:m
    for j=1:m
        for k=1:m
            if A_1(i,1)+A_2(j,1)+A_3(k,1)<=quantile(A_1(i,2:end)+A_2(j,2:end)+A_3(k,2:end), 0.95)
              check(i)=1;
              STOP TO LOOP OVER j AND k, MOVE TO THE NEXT i (INCOMPLETE!)              
           else
            KEEP SEARCHING FOR j,k SUCH THAT THE CONDITION IS SATISFIED (INCOMPLETE!) 
           end
       end
    end
end

2 个答案:

答案 0 :(得分:4)

给定标量x和向量v,表达式x <=quantile (v, .95)可以写成sum( x > v) < Q,其中Q = .95 * numel(v) *。

还可以在循环之前对A_1进行拆分,以避免额外的索引编制。 此外,可以去除最内层的循环,从而有利于向量化。

Af_1 = A_1(:,1);
Af_2 = A_2(:,1);
Af_3 = A_3(:,1);
As_1 = A_1(:,2:end);
As_2 = A_2(:,2:end);
As_3 = A_3(:,2:end);
Q = .95 * (n -1);
for i=1:m
    for j=1:m
        if any (sum (Af_1(i) + Af_2(j) + Af_3 > As_1(i,:) + As_2(j,:) + As_3, 2) < Q)
            check(i) = 1;
            break; 
        end             
    end
end

通过重新排列不等式和预计算中涉及的表达式,可以实现更多优化:

lhs = A_3(:,1) - A_3(:,2:end);
lhsi = A_1(:,1) - A_1(:,2:end);
rhsj = A_2(:,2:end) - A_2(:,1);
Q = .95 * (n - 1);
for i=1:m
    LHS = lhs + lhsi(i,:);
    for j=1:m
        if any (sum (LHS > rhsj(j,:), 2) < Q)
            check(i) = 1;
            break; 
        end             
    end
end
  • 请注意,由于quantile计算中使用的方法,您得到的结果可能会略有不同。

答案 1 :(得分:0)

选项1: 由于所有数字均为正数,因此您可以进行一些优化。只有将A1添加到混合中,才能使95%更高-如果在右侧找到j的最大95%的kA2+A3,前两个元素的总和,您可以简单地为每个i取。

maxDif = -inf;
for j = 1 : m
   for k = 1 : m
      newDif = quantile(A_2..., 0.95) - A_2(j,1)-A_3(k,1);
      maxDif = max(newDif, maxDif);
   end
end

即使速度太慢,也可以先获取maxDifA2maxDifA3,然后估计maxDif将用于那些特定的jk值并进行计算。

现在,对于某些数字,您将得到maxDif > A_1,那么check为1。对于某些数字,您将得到maxDif + quantile(A1, 0.95) < A_1,这里check为0(如果您通过分别计算A2和A3来估算maxDif,则不正确!)。不幸的是,对于某些(大多数?)而言,您将获得介于两者之间的值,这对您完全没有帮助。然后剩下的就是选项2(它也更简单):

选项2: 如果您可以在右侧保存求和A_2+A_3,则可以节省一些时间,因为对于每个不同的i都会重复该计算,但是这需要大量内存。但是quantile还是更昂贵的操作,因此您不会节省很多时间。类似于

for j = 1 : m
for k = 1 : m
A23R(j,k,:) = A2(j,:)+A3(k,:); % Unlikely to fit in memory.
end
end

然后,您可以使用A23R执行循环,并避免对每个i重复该总和。