Matlab - 创建两个数组,考虑两个对象的所有可能值

时间:2017-06-06 19:56:14

标签: matlab matrix matrix-multiplication

我有两个物理对象。"我用两个不同的阵列代表他们的位置。

•对象1仅在xy平面中移动

•对象2在所有三个物理维度上移动

目标:对四个for循环进行矢量化而不会扭曲数据。此外,目的是对对象1的所有可能值执行此操作以与对象2进行比较。

以下是代码段:

Npos = 21;
Nsam = 200;

% dummy initialisation    
AX = rand(1, Npos);
AY = zeros(1, Npos);
AZ = rand(1, Npos);
Bx = rand(Nsam);
By = rand(Nsam);
Bz = rand(Nsam);

for qx = 1 : Npos
    for yx = 1 : Npos
        for zx = 1 : Nsam
            for cx = 1 : Nsam
                Tx2Array( qx, yx, zx, cx ) = sqrt( ( AX( qx ) - Bx( zx, cx ) ).^2 + ( AY( yx ) - By( zx, cx ) ).^2 + ( AZ( yx ) - Bz( zx, cx ) ).^2 );
            end
        end
    end
end
% Result is a 21 x 21 x 200 x 200 matrix filled with all real numbers

图例

AX,AY,AZ是1 x 21个数组,代表对象1的(x,y = 0,z)

AY全部为零,但仍然包含可读性(因此没有第五个循环!)

Bx,By,Bz都是200 x 200数组,代表对象2的(x,y,z)

Npos = 21; Nsam = 200;

上面使用的公式是:

sqrt( (a1-b1)^2 + (a2-b2)^2 + (a3-b3)^2 )

3 个答案:

答案 0 :(得分:3)

如果您有统计工具箱,则可以使用pdist2计算对象1的每个坐标与对象2的每个坐标之间的距离:

[X1, Z1] = ndgrid(AX(:), AZ(:));   % X1 and Z1 will be 21x21
D = pdist2([X1(:), zeros(size(X1(:))), Z1(:)], [Bx(:), By(:), Bz(:)]);

在这种情况下,输出将是441 x 40,000数组,其中D(i, j)为您提供对象1的点i与对象2的点j之间的距离,两者均使用线性索引。

答案 1 :(得分:1)

您可以通过将zxcx替换为:来避免使用内部循环,如下所示:

Tx2Array = zeros(Npos, Npos, Nsam, Nsam); % preallocate memory
for qx = 1 : Npos
    for yx = 1 : Npos
        Tx2Array( qx, yx, :, : ) = sqrt( ( AX( qx ) - Bx( :, : ) ).^2 + ( AY( yx ) - By( :, : ) ).^2 + ( AZ( yx ) - Bz( :, : ) ).^2 );
    end
end

通过这种方式,最大尺寸被矢量化。因此,最大的改进已经完成。

通过将B*转换为4D并为A*矩阵生成网格,您甚至可以删除所有for循环,如下所示:

[AX_, AZ_] = meshgrid(AX, AZ);
AX_ = AX_';
AZ_ = AZ_';
AY_ = zeros(Npos);

Bx_(1, 1, :, :) = Bx;
By_(1, 1, :, :) = By;
Bz_(1, 1, :, :) = Bz;

Tx2Array2 = sqrt( ( AX_ - Bx_ ).^2 + ( AY_ - By_ ).^2 + ( AZ_ - Bz_ ).^2 );

您可以使用以下检查检查结果是否相同:

max(max(max(max(abs(Tx2Array - Tx2Array2))))) < eps

答案 2 :(得分:1)

如果数组已正确初始化,您的任务将非常简单:

使用正确的尺寸初始化数组

AX = rand( Npos,1);
AY = zeros(1, Npos);
AZ = rand(1, Npos);
Bx = rand(1,1,Nsam,Nsam);
By = rand(1,1,Nsam,Nsam);
Bz = rand(1,1,Nsam,Nsam);

然后在MATLAB r2016b / Octave中你可以简单地写:

Tx2Array = sqrt( ( AX - Bx ).^2 + ( AY - By ).^2 + ( AZ - Bz ).^2 );

在r2016b之前,您可以使用bsxfun

Tx2Array = sqrt(bsxfun(@plus,bsxfun(@plus,bsxfun(@minus,AX , Bx).^2,bsxfun(@minus,AY , By).^2),bsxfun(@minus,AZ , Bz).^2));