旋转矩阵的行(如 GAUSS 函数旋转器)

Rotate the rows of a matrix (like GAUSS function rotater)

我目前正在将一些 GAUSS 代码移植到 Matlab 并且我一直在尝试使用 GAUSS "rotater" 函数。

旋转器的命令参考条目说:

示例 1 (我在这里遵循 Matlab 的表示法,用直括号表示矩阵,用分号表示新的 ro)

如果 x = [1 2 3; 4 5 6], 和 r = [1; -1],则y = [3 1 2; 5 6 4]

示例 1

如果 x = [1 2 3; 4 5 6; 7 8 9; 10, 11, 12] 和 r = [0; 1; 2; 3], 那么 y = [1 2 3; 6 4 5; 8 9 7; 10 11 12]

也许有人在某处找到了类似的函数,或者可以给我建议如何编写它?

circshift 与您正在寻找的非常接近,除了 1) 它适用于列而不是行,以及 2) 它将整个矩阵移动相同的偏移量。

第一个很容易修复,我们只是转置。对于第二个,我还没有找到矢量化方法,但与此同时,这里有一个带有 for 循环的版本:

x = [1 2 3; 4 5 6; 7 8 9; 10 11 12]
r = [0 1 2 3]

B = x'

C = zeros(size(B));
for ii = 1:size(B,2)
  C(:,ii) = circshift(B(:,ii),r(ii));
end

y = C'

输出为:

x =

    1    2    3
    4    5    6
    7    8    9
   10   11   12

r =

   0   1   2   3

B =

    1    4    7   10
    2    5    8   11
    3    6    9   12

y =

    1    2    3
    6    4    5
    8    9    7
   10   11   12

这可以使用一个简单的 for 循环遍历每一行,以及一个来自 matlab 的名为“circshift”的函数来完成。

我创建了一个函数,它遍历每一行并对其应用适当的转换。可能有更有效的方法来实现这一点,但这种方式适用于您的示例。我创建了一个函数

function rotated_arr = GaussRotate(input_array, rotation_vector)
    [N,K] = size(input_array)

    %creates array for return values
    rotated_arr = zeros(N,K);

    %if the rotation vector is a scalar
    if (length(rotation_vector) == 1)
        %replicate the value once for each row
        rotation_vector = repmat(rotation_vector, [1,N]);
    end

    %if the rotation vector doesn't have as many entries as there are rows
    %in the input array
    if (length(rotation_vector) ~= N)
        disp('ERROR GaussRotate: rotation_vector is the wrong size')
        disp('if input_Array is NxK, rotation_vector must be Nx1 or 1x1')
        return
    end

    %for each row
    for idx=1:size(input_array,1)
        %shift the row by the appropriate number of columns
        %we use [0,shift] because we want to shift the columns, the row
        %stays where it is (even though this is a 1xN at this point we
        %still specify rows vs columns)
        rotated_arr(idx,:) = circshift(input_array(idx,:),[0,rotation_vector(idx)]);
    end

end

然后用你的例子简单地调用它

 x = [1 2 3; 4 5 6];
 r = [1; -1];
 y =  GaussRotate(x,r)
 %produces [3 1 2; 5 6 4]

 %I also made it support the 1x1 case
 r = [-1] 
 %this will shift all elements one column to the left
 y = GaussRotate(x,r)
 %produces [2 3 1; 5 6 4]

 x = [1 2 3; 4 5 6; 7 8 9; 10, 11, 12]
 r = [0; 1; 2; 3]
 y = GaussRotate(x,r)
 %produces  [1 2 3; 6 4 5; 8 9 7; 10 11 12]

这可以使用 bsxfun 两次来完成:

  1. 通过用 bsxfun 减去 r 并使用 mod 来计算旋转的行索引。像往常一样,mod 需要从 0 开始的索引,而不是 1。旋转后的行索引保留为从 0 开始,因为这对步骤 2 更方便。
  2. 再次使用 bsxfun 从列和旋转的行中获取 linear index。应用于 x 的线性索引给出 y

代码:

[s1 s2] = size(x);
rows = mod(bsxfun(@plus, 1:s2, -r(:))-1, s2);  % // step 1
y = x(bsxfun(@plus, rows*s1, (1:s1).'));       %'// step 2