【问题标题】:matlab: a tricky vectorization with a function enclosed with 2 nested loopsmatlab:一个带有 2 个嵌套循环的函数的棘手向量化
【发布时间】:2015-03-15 17:29:52
【问题描述】:

我在对以下代码进行矢量化处理时非常困难,不幸的是,您需要查看它以了解发生了什么。

简而言之,此函数比较一组数据行并创建一个比较关系矩阵。两个嵌套循环调用内部函数(即compare_weights())来比较数据行中的某些特定列。比较函数根据嵌套的if-then-else 决策返回0-11。所以,这里是主循环--

data = rand(4);
disp(data)
[nrow,~] = size(data);
mat = zeros(nrow,nrow);
% fill only the upper triangular of mat
for i = 1:nrow
    for j = i + 1:nrow
        if(i ~= j) 
            % compare_weights() is a function with some nested 
            % if-then-else, that compares the values of 1st,2nd and 
            % 4th columns in data and populates the matrix mat.
            mat(i, j) = ...
                compare_weights(data(i,1:2), data(i,4), ...
                                data(j,1:2), data(j,4));
        end
    end
end
% after the loop, the mat contains the weight comparison relations
% among all the rows in data.
disp(mat)

而内部函数compare_weights() 看起来像这样--

function [ val ] = compare_weights(w1,v1,w2,v2)
%   This function takes the values w1, v1, w2, v2 tuple
%   and does some comparisons, according to the decision
%   this returns -1, 1 or 0.
if(v1 < 0 && v2 < 0)
    if(v1 > v2)
        val = 1 ;
        return ;
    elseif(v1 < v2)
        val = -1 ;
        return ;
    else
        val = 0;
        return ;
    end
else
    if(v1 < 0 && v2 == 0)
        val = -1 ;
        return ;
    elseif(v1 == 0 && v2 < 0)
            val = 1  ;
            return ;
    else
        if(all(w1 > w2))
            val = -1 ;
            return ;
        elseif(all(w1 < w2))
            val = 1 ;
            return ;
        else
            val = 0 ;
            return ;
        end
    end
end
end

在执行代码时,您应该在mat 中获得这种值--

0    -1    -1     0
0     0    -1     0
0     0     0     1
0     0     0     0

data 为 --

0.5958    0.8310    0.2471    0.5445
0.5004    0.2755    0.4761    0.6410
0.1435    0.1618    0.5691    0.3250
0.9514    0.2711    0.2264    0.1543

我不知道如何对其进行矢量化,甚至不确定它是否可以矢量化。任何指针都会非常有帮助。

【问题讨论】:

  • 在同一代码中使用data(row,1:2)data(col,1:2) 非常令人困惑,因为rowcol 都引用...行!
  • @CrazyRat 是的,抱歉,row/col 实际上是指matrow/col :-(,已更正。

标签: matlab matrix vectorization


【解决方案1】:

一个完整的vectorized approach 当然可以使用bsxfun 一次性覆盖all iterationsall IF conditional statements。这是一个这样的实现 -

%// Collect the relevant column data from input array
n = 2;
d1n = data(:,1:n);
d4 = data(:,4);

%// Logical array corrresponding to starting IF conditional statement
startif = bsxfun(@and,d4<0,d4.'<0)  %//'

%// Create logical arrays of the three IF-ElSE parts
ifelse1 = bsxfun(@gt,d4,d4.') - bsxfun(@lt,d4,d4.')

ifelse2 = -bsxfun(@and,d4<0,d4'==0) + bsxfun(@and,d4==0,d4'<0)

ifelse3 = -all(bsxfun(@gt,permute(d1n,[1 3 2]),permute(d1n,[3 1 2])),3) + ...
            all(bsxfun(@lt,permute(d1n,[1 3 2]),permute(d1n,[3 1 2])),3)

%// Get the output taking care of all the conditionals
out = startif.*ifelse1 + (~startif).*(ifelse2 + (ifelse2==0).*ifelse3)

%// You want to skip the lower triangular elements from input data
out = triu(out)

【讨论】:

  • 这太酷了,而且速度极快,你是怎么想出这种矢量化的?但是我仍然难以理解整个计算,您能否在每条语句后添加一个小解释?有没有实现这种技巧的指导方针?还是这种壮举只能靠实践?
  • 还有一个问题,当d1..d2 不完全是两列时,我该如何扩展它,假设它们是nd1, d2, ..., dn
  • @ramgorur 针对一般情况编辑了代码!是的,这一切都与实践有关!关于解释,重点关注此向量化代码中的 Ifelse1/2/3 部分,并将它们与原始代码中的相应部分进行匹配。然后在原始代码中查找其余的 If 条件,并尝试想象它们必须如何绕过这些 if-else 部分。这应该会更容易理解!
猜你喜欢
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多