matlab coder:当它应该始终是 2-D 时,不能转置被错误地认为是 3-D 的矩阵

Posted

技术标签:

【中文标题】matlab coder:当它应该始终是 2-D 时,不能转置被错误地认为是 3-D 的矩阵【英文标题】:matlab coder: cannot transpose a matrix that is incorrectly deemed to be 3-D when it should always be 2-D 【发布时间】:2014-11-11 20:39:45 【问题描述】:

我有一个函数(代码如下),我希望将其转换为 MEX 文件。我正在尝试使用 matlab 编码器来做到这一点。

%% Inputs
dof = 3;
num_divs = 72;

ind_cr =
     0     0
     1     1
     1     2
     2     2
     1     3
     2     3
     3     3

ind_switch =
     1
     1
     1
     0
     1
     0
     0

len_stat_atoms =
           1
          72
        5184
          72
      373248
        5184
          72

num_stat_atoms =
   108
   111
   111
     3
   111
     3
     3

coordFile = 
    [3x1        double]
    [3x1        double]
    [3x72x3     double]
    [3x5184x3   double]
    [3x373248x4 double]

radii_cell = 
    [108x1x3      double]
    [111x72x3     double]
    [111x5184x3   double]
    [  3x72x3     double]
    [111x373248x4 double]
    [  3x5184x4   double]
    [  3x72x4     double]

stat_cell = 
    [3x1x108      double]
    [3x72x111     double]
    [3x5184x111   double]
    [3x72x3       double]
    [3x373248x111 double]
    [3x5184x3     double]
    [3x72x3       double]    


%% Code that calls function
for i = 1:(dof*(dof+1)/2+1)
    %% Load matrices
    radii_mat = radii_celli,1;
    stat_mat = stat_celli,1;
    if ind_switch(i)
        coordFile_mat = coordFileind_cr(i,2)+2;
    end
    %% Call the function
    potential_mat = func_test(i,coordFile_mat,radii_mat,stat_mat,...
        ind_cr,len_stat_atoms,num_stat_atoms,num_coord_atoms,...
        counter,num_divs,dof);
end


%% Function code
function potential_mat = func_test(i,coordFile_mat,radii_mat,stat_mat,...
    ind_cr,len_stat_atoms,num_stat_atoms,num_coord_atoms,...
    counter,num_divs,dof);

potential_mat = zeros(num_coord_atoms,num_divs^dof);
for j = 1:size(coordFile_mat,3)
    %% Compute distances
    a = zeros(3,len_stat_atoms(i));
    a = coordFile_mat(:,1:len_stat_atoms(i),j);

    b = zeros(3,len_stat_atoms(i),num_stat_atoms(i));
    b = repmat(a,[1 1 num_stat_atoms(i)]);

    c = zeros(1,len_stat_atoms(i),num_stat_atoms(i));
    c = sqrt(sum((b - stat_mat).^2,1));

    d = zeros(len_stat_atoms(i),num_stat_atoms(i));
    d = shiftdim(c,1);

    distances = zeros(num_stat_atoms(i),len_stat_atoms(i));
    distances = d';

    %% Compute ***es and potentials
    ***es = distances < radii_mat(:,:,j);
    potentials = zeros(size(distances));
    potentials(***es) = (1-(distances(***es)./radii_mat(find(***es)+numel(***es)*(j-1))).^6).^2;

    %% Iterate over nodes
    col = ind_cr(i,1); row = ind_cr(i,2);
    if col == 1
        ind_kron = repmat(1:size(potentials,2),[num_divs^(dof-row) 1]);
        potentials = potentials(:,ind_kron(:)');
    elseif row == dof
        vec_repmat = [1 num_divs^(col-1)];
        potentials = repmat(potentials,vec_repmat);
    elseif col > 0
        vec_repmat = [1 num_divs^(col-1)];
        ind_kron = repmat(1:size(potentials,2),[num_divs^(dof-row) 1]);
        potentials = repmat(potentials(:,ind_kron(:)'),vec_repmat);
    else
        potentials = repmat(sum(potentials),[1 num_divs^dof]);
    end
    counter = counter+1;
    potential_mat(counter,:) = sum(potentials,1);
end

end

问题出现在下面的第二行,因为它无法转置 ND 矩阵而引发错误。

d = shiftdim(c,1);
distances = d';

Matlab 编码器将c 的大小识别为1 x :? x :?,这是正确的。然后d = shiftdim(c,1) 行应该产生一个大小为:? x :? 的二维矩阵,然后我将其转置。但是,它无法正确移动d 的尺寸,并赋予它:? x :? x :? 的大小。这会导致转置错误。我该如何解决这个问题?此外,为了我自己的启迪,为什么matlab编码器无法正确分配我的变量的维度,具体是abcddistances

【问题讨论】:

【参考方案1】:

文档将其描述为Incompatibility with MATLAB in Determining Size of Variable-Size N-D Arrays(d 是在循环中创建的,因此似乎是可变大小):

对于可变大小的 N 维数组,size 函数在生成的代码中返回的结果可能与在 MATLAB 中不同。 在生成的代码中,size(A) 返回一个固定长度的输出,因为它不会丢弃可变大小 N 维数组的尾随单一维度。相比之下,MATLAB 中的 size(A) 返回一个可变长度的输出,因为它删除了尾随的单一维度

例如,如果数组A的形状是:?x:?x:?size(A,3)==1size(A)返回:

生成代码中的三元素向量 MATLAB 代码中的二元向量

上述文档中解决的问题与size 函数的使用有关。但是,在您的情况下,您只希望能够转置。解决方法是使用permute,因为转置是permute 的一般情况:

% after shiftdim:
distances = permute(d,[2 1 3])   % same as d' for 2d array, but handles 3d

您也可以完全删除shiftdim

distances = permute(c,[2 3 1])

另外,我对 Coder 没有太多经验,但它真的需要使用 zeros 进行所有这些初始化吗?它们似乎没有必要。

【讨论】:

以上是关于matlab coder:当它应该始终是 2-D 时,不能转置被错误地认为是 3-D 的矩阵的主要内容,如果未能解决你的问题,请参考以下文章

如何给matlab coder装license

MATLAB coder 支持的 csvread 函数

MATLAB Coder 中的多态性

为啥 strel 在 MATLAB Coder 中失败

具有外部 C++ 函数的 Matlab:coder.ceval 将结构传递给函数

使用 Matlab Coder 将 C 字符数组转换为 Matlab 字符串