matlab:一个棘手的矢量化,带有一个包含 2 个嵌套循环的函数
matlab: a tricky vectorization with a function enclosed with 2 nested loops
我正在经历一段非常艰难的向量化以下代码,不幸的是你需要查看它以了解发生了什么。
简而言之,这个函数比较一组数据行并创建一个比较关系矩阵。两个嵌套循环调用内部函数(即 compare_weights()
)来比较数据行中的某些特定列。比较函数returns0
、-1
或1
根据嵌套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 iterations
和all 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)
我正在经历一段非常艰难的向量化以下代码,不幸的是你需要查看它以了解发生了什么。
简而言之,这个函数比较一组数据行并创建一个比较关系矩阵。两个嵌套循环调用内部函数(即 compare_weights()
)来比较数据行中的某些特定列。比较函数returns0
、-1
或1
根据嵌套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 iterations
和all 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)