通过嵌套循环构造Matlab数组

通过嵌套循环构造Matlab数组,matlab,Matlab,假设我有三个矩阵A_1,A_2,A_3,每个维度mxn,其中m和n都很大。这些矩阵包含严格的正数 我想构造一个矩阵检查的维度mx1,这样,对于每个I=1,…,m: 检查(i)=1如果存在j,k,则 A_1(i,1)+A_2(j,1)+A_3(k,1)选项1: 因为所有的数字都是正数,所以可以进行一些优化。如果将A1添加到组合中,则95%将更高-如果您在右侧找到A2+A3中最大95%的j和k,与前两个元素的总和相比,您可以简单地将其用于每个i maxDif = -inf; for j = 1 :

假设我有三个矩阵
A_1
A_2
A_3
,每个维度
mxn
,其中
m
n
都很大。这些矩阵包含严格的正数

我想构造一个矩阵
检查
的维度
mx1
,这样,对于每个
I=1,…,m

检查(i)=1
如果存在
j,k
,则

A_1(i,1)+A_2(j,1)+A_3(k,1)选项1:
因为所有的数字都是正数,所以可以进行一些优化。如果将
A1
添加到组合中,则95%将更高-如果您在右侧找到
A2+A3
中最大95%的
j
k
,与前两个元素的总和相比,您可以简单地将其用于每个
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
如果速度太慢,您可以首先获得
maxDifA2
maxDifA3
,然后估计
maxDif
将用于那些特定的
j
k
值,并进行计算

现在,对于一些数字,您将得到
maxDif>A_1
,然后
检查值为1。对于一些数字,您将得到
maxDif+分位数(A1,0.95)
,这里
检查
为0(如果您通过单独计算A2和A3估计
maxDif
,则这不是真的!)。对于一些人(大多数?)来说,不幸的是,你会得到介于两者之间的值,这一点都没有帮助。剩下的是选项2(它也更简单):

备选案文2: 如果可以将求和
A_2+A_3
保存在右侧,则可以节省一些时间,因为该计算会对每个不同的
i
重复,但这需要大量内存。但是
分位数
无论如何都是比较昂贵的操作,因此不会节省很多时间。类似于

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

然后,您可以使用A23R执行循环,并避免对给定标量
x
和向量
v
表达式
xv)
的每个
i
重复该和,其中
Q=.95*numel(v)
*

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
另外,
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
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);
对于i=1:m
对于j=1:m
如果有(总和(Af_1(i)+Af_2(j)+Af_3>As_1(i,:)+As_2(j,:)+As_3,2)
通过重新排列不等式和预计算中涉及的表达式,可以实现更多优化:

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
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);
对于i=1:m
LHS=LHS+lhsi(i,:);
对于j=1:m
如果有(总和(LHS>rhsj(j,:),2)
  • 请注意,由于计算中使用的方法,您可能会得到稍微不同的结果

什么是
A_2
A_3
?我没有看到它们被用于计算
check
。或者你的意思是
a2(j,…)
a3(k,…)
?谢谢。对不起,这是一个打字错误,是
检查
大小
mxn
还是
mx1
?您说它是
mxn
,但定义为
mx1
。谢谢。确切地说是mx1。你不能减少计算分位数的次数,这是这里最昂贵的操作。你也无法将其矢量化。到目前为止,我唯一能想到的优化是将索引移到循环之外:
A_1_1=A_1(:,1)
A_1=A_1(:,2:end)
。我认为这会使你的代码速度加快一点。也许不是,但值得一试。很好!取消对
分位数的调用肯定会节省大量时间!谢谢它仍然需要太多的时间。
j
的每次迭代需要
0.002秒
。因此,
i
的每次迭代需要
0.002*m=200秒
。因此,总的来说需要
0.002*m^2=20000000秒
。请注意,由于
break
的原因,与剩余
j
s相关的计算可能会被放弃,并且总时间可能小于您(最坏情况)的估计值。@user3285148我已更正了答案中的错误。表达式
sum(x=Q
更改为
sum(x>v)
并且代码被更新。@user3285148:您是否有任何迹象表明计算速度可能更快?您正在计算10^15个可能的组合,即使每个组合只需要一个时钟周期,您仍然会看到2 GHz=10^15/2.10^9=500000 s=5.8天。以及计算qua的可能性每个时钟周期超过500个值。。。