从3个向量及其原始坐标中生成三胞胎对的所有可能组合

时间:2018-08-01 12:00:32

标签: matlab performance permutation combinatorics matrix-indexing

给定3个行向量A,B,C,在Matlab中,我想生成矩阵D,该矩阵报告A,B,C中三胞胎对的所有可能组合以及它们在{{1 }}。

我写了一个代码,可以完成我想要的。由于我正在尽力优化代码(代码应重复数百万次),因此我想知道您是否可以想到更有效的解决方案。例如,在我的代码中,我没有预先分配矩阵A,B,C,因为我不知道如何获取每对三胞胎的索引,而且效率不高。

以下代码将对其进行更好的解释:

D

1 个答案:

答案 0 :(得分:1)

填充矩阵Context的最后一个嵌套的for循环可以提高效率。 OP在他们的声明中很明显:

  

“例如,在我的代码中,我没有预先分配矩阵D,因为我不知道如何获取每对三联索引,这效率不高。” < / p>

我们可以通过注意到OP在其关于矩阵D(即D)的最终大小的注释中暗示一种模式来对这些循环中的许多工作进行向量化。对于从事过系列和序列工作的人来说,第一个维度看起来很熟悉。它是Triangle Numbers的公式。

牢记这一点,我们可以看到在最终结果中,前3列(以及第7到9列)重复了23次,然后重复了22次,依此类推,而第4到6列(以及10到12列) )是Generate the matrix D of dimension [sT*(sT-1)/2]x[12]的最后23行,T/Tcoord的最后22行,依此类推。在代码中,我们有:

T/Tcoord

使用D1 = zeros(sT * (sT - 1) / 2, 12); s = 1; e = sT - 1; for w = 1:(sT - 1) D1(s:e,[1:3,7:9]) = repmat([T(w,:),Tcoord(w,:)], sT - w, 1); D1(s:e,[4:6,10:12]) = [T((w+1):sT,:),Tcoord((w+1):sT,:)]; s = e + 1; e = e + (sT - (w + 1)); end tic将每种方法运行200次,我们发现效率几乎提高了toc

35%

如果我们使输入向量更大,我们将看到效率得到更大的提高。以下是在以下向量上对每种方法运行15次的结果:

% OP's setup code goes here

tic
for i=1:200
    D=[];
    for w=1:sA*sB*sC
        for r=w+1:sA*sB*sC
            D=[D; T(w,:) T(r,:) Tcoord(w,:) Tcoord(r,:)];
        end
    end
end
toc

tic
for i = 1:200
    D1 = zeros(sT * (sT - 1) / 2, 12);
    s = 1;
    e = sT - 1;

    for w = 1:(sT - 1)
        D1(s:e,[1:3,7:9]) = repmat([T(w,:),Tcoord(w,:)], sT - w, 1);
        D1(s:e,[4:6,10:12]) = [T((w+1):sT,:),Tcoord((w+1):sT,:)];
        s = e + 1;
        e = e + (sT - (w + 1));
    end
end
toc

% Gives same result
isequal(D, D1)

% Timing for 200 runs on 24 total combinations
Elapsed time is 2.09613 seconds.
Elapsed time is 1.35988 seconds.
ans = 1

那快十倍以上。输入向量的大小越大,差距就成倍地增加。

A=[1 2 3 4 23];
B=[-4 -2 5 74];
C=[8 9 -3 0];

% Timing for 15 run on 80 total combinations
Elapsed time is 4.00448 seconds.
Elapsed time is 0.379919 seconds.
ans = 1

那快大约75倍!!!


更新

OP在评论中给出了更好的答案:

A=[1 2 3 4 23];
B=[-4 -2 5 74 28];
C=[8 9 -3 0 -100 -5];

% Timing for 1 run on 150 total combinations
Elapsed time is 3.63065 seconds.
Elapsed time is 0.0481789 seconds.
ans = 1

这是我基准测试的代码:

indices=nchoosek((1:1:sT),2);
D=[T(indices(:,1),:) T(indices(:,2),:) Tcoord(indices(:,1),:) Tcoord(indices(:,2),:)];

结果如下:

clear 
A=[1 2 3 4 23 24 25 26];
B=[-4 -2 5 74 28 10 11 12 13];
C=[8 9 -3 0 -100 -5 60 120];

sA=size(A,2);
sB=size(B,2);
sC=size(C,2);
sT=sA*sB*sC;

tic
for i = 1:10
    [ca, cb, cc] = ndgrid(A, B, C);
    T = [ca(:), cb(:), cc(:)];
    [ca, cb, cc] = ndgrid(1:sA, 1:sB, 1:sC);
    Tcoord = [ca(:), cb(:), cc(:)];

    D1 = zeros(sT * (sT - 1) / 2, 12);
    s = 1;
    e = sT - 1;

    for w = 1:(sT - 1)
        D1(s:e,[1:3,7:9]) = repmat([T(w,:),Tcoord(w,:)], sT - w, 1);
        D1(s:e,[4:6,10:12]) = [T((w+1):sT,:),Tcoord((w+1):sT,:)];
        s = e + 1;
        e = e + (sT - (w + 1));
    end
end
toc

tic
for i = 1:10
    indices=nchoosek((1:1:sT),2);
    D=[T(indices(:,1),:) T(indices(:,2),:) Tcoord(indices(:,1),:) Tcoord(indices(:,2),:)];
end
toc

isequal(D, D1)

我提供的改进解决方案在很大程度上优于原始解决方案,但与OP的更新解决方案不匹配。我可能会补充说,订单速度更快而且非常优雅。