矢量化矩阵中不同对角线的总和

时间:2010-05-19 08:00:08

标签: matlab matrix dynamic-programming vectorization

我想要矢量化以下MATLAB代码。我认为它必须简单,但我发现它令人困惑。

r = some constant less than m or n
[m,n] = size(C);
S = zeros(m-r,n-r);
for i=1:m-r+1
    for j=1:n-r+1
        S(i,j) = sum(diag(C(i:i+r-1,j:j+r-1)));
    end
end

代码从另一个得分表 C 计算动态编程算法的分数表 S
对角线求和是为所有可能的片段(大小为r)生成用于生成 C 的单个数据片段的分数。

提前感谢您的任何答案!对不起,如果这个显而易见......

注意
内置的conv2比convnfft更快,因为我的眼睛(r)非常小(5 <= r <= 20)。 convnfft.m表明r应该> 20表示任何利益。

4 个答案:

答案 0 :(得分:10)

如果我理解正确,你试图计算C的每个子数组的对角线和,你已经删除了C的最后一行和一列(如果你不应该删除行/ col,你需要循环到m-r + 1,你需要将整个数组C传递给我的解决方案中的函数。)

您可以通过convolution执行此操作,如下所示:

S = conv2(C(1:end-1,1:end-1),eye(r),'valid');

如果C和r很大,您可能需要查看Matlab文件交换中的CONVNFFT以加快计算速度。

答案 1 :(得分:3)

基于JS的概念,以及评论中指出的Jonas,可以使用IM2COL和一些数组操作在两行中完成:

B = im2col(C, [r r], 'sliding');
S = reshape( sum(B(1:r+1:end,:)), size(C)-r+1 );

基本上B包含矩阵C上大小为r-by-r的所有滑块的元素。然后我们采用每个块B(1:r+1:end,:)的对角线上的元素,计算它们的总和,并将结果重新整形为预期的大小。


将此与Jonas基于卷积的解决方案相比较,这不执行任何矩阵乘法,只进行索引...

答案 2 :(得分:2)

我认为您可能需要将C重新排列成3D矩阵,然后再将其与其中一个维度相加。我很快就会回答。

修改

我没有找到一种方法来干净利落地进行矢量化,但我确实找到了函数accumarray,这可能会有所帮助。我回家时会更详细地看一下。

修改#2

使用线性索引找到了一个更简单的解决方案,但这可能是内存密集型的。

在C(1,1)处,我们想要求和的指数是1 + [0,m + 1,2 * m + 2,3 * m + 3,4 * m + 4,...],或(0:r-1)+(0:m:(r-1)* m)

sum_ind = (0:r-1)+(0:m:(r-1)*m);

通过r矩阵创建S_offset,(mr)by(nr),使得S_offset(:,:,1)= 0,S_offset(:,,2)= m + 1,S_offset( :,:,3)= 2 * m + 2,依此类推。

S_offset = permute(repmat( sum_ind, [m-r, 1, n-r] ), [1, 3, 2]);

创建S_base,一个基数组地址矩阵,将从中计算偏移量。

S_base = reshape(1:m*n,[m n]);
S_base = repmat(S_base(1:m-r,1:n-r), [1, 1, r]);

最后,使用S_base+S_offset来解决C的值。

S = sum(C(S_base+S_offset), 3);

当然,您可以使用bsxfun和其他方法来提高效率;在这里,我选择将其列出来以保持清晰。我还没有对此进行基准测试,以了解它与双循环方法的对比情况;我需要先回家吃晚餐!

答案 3 :(得分:1)

这是你要找的吗?此函数添加对角线并将它们放入一个向量中,类似于函数“sum”如何将矩阵中的所有列相加并将它们放入向量中。

function [diagSum] = diagSumCalc(squareMatrix, LLUR0_ULLR1)
% 
% Input: squareMatrix: A square matrix.
%        LLUR0_ULLR1:  LowerLeft to UpperRight addition = 0     
%                      UpperLeft to LowerRight addition = 1
% 
% Output: diagSum: A vector of the sum of the diagnols of the matrix.
% 
% Example: 
% 
% >> squareMatrix = [1 2 3; 
%                    4 5 6;
%                    7 8 9];
% 
% >> diagSum = diagSumCalc(squareMatrix, 0);
% 
% diagSum = 
% 
%       1 6 15 14 9
% 
% >> diagSum = diagSumCalc(squareMatrix, 1);
% 
% diagSum = 
% 
%       7 12 15 8 3
% 
% Written by M. Phillips
% Oct. 16th, 2013
% MIT Open Source Copywrite
% Contact mphillips@hmc.edu fmi.
% 

if (nargin < 2)
    disp('Error on input. Needs two inputs.');
    return;
end

if (LLUR0_ULLR1 ~= 0 && LLUR0_ULLR1~= 1)
    disp('Error on input. Only accepts 0 or 1 as input for second condition.');
    return;
end

[M, N] = size(squareMatrix);

if (M ~= N)
    disp('Error on input. Only accepts a square matrix as input.');
    return;
end

diagSum = zeros(1, M+N-1);

if LLUR0_ULLR1 == 1
    squareMatrix = rot90(squareMatrix, -1);
end

for i = 1:length(diagSum)
    if i <= M
        countUp = 1;
        countDown = i;
        while countDown ~= 0
            diagSum(i) = squareMatrix(countUp, countDown) + diagSum(i);
            countUp = countUp+1;
            countDown = countDown-1;
        end
    end
    if i > M
        countUp = i-M+1;
        countDown = M;
        while countUp ~= M+1
            diagSum(i) = squareMatrix(countUp, countDown) + diagSum(i);
            countUp = countUp+1;
            countDown = countDown-1;
        end
    end
end

干杯