matlab:一个棘手的矢量化,带有一个包含 2 个嵌套循环的函数

matlab: a tricky vectorization with a function enclosed with 2 nested loops

我正在经历一段非常艰难的向量化以下代码,不幸的是你需要查看它以了解发生了什么。

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

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

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

完全vectorized approach is certainly possible using 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)