旋转矩阵的行(如 GAUSS 函数旋转器)
Rotate the rows of a matrix (like GAUSS function rotater)
我目前正在将一些 GAUSS 代码移植到 Matlab 并且我一直在尝试使用 GAUSS "rotater" 函数。
旋转器的命令参考条目说:
- 用途 旋转矩阵的行
- 格式 y = rotater(x,r)
- 输入 x: N x K 待旋转矩阵。 r:指定旋转量的 N x 1 或 1 x 1 矩阵。
- 输出 y: N x K 旋转矩阵。
- 备注旋转是在矩阵的每一行内水平进行的。正旋转值将导致元素移动
向右。负旋转将导致元素移动到
左边。在任何一种情况下,被推离末尾的元素
该行将环绕到同一行的另一端。如果旋转值大于或等于 x 中的列数,则将使用 (r % cols(x)).
计算旋转值
示例 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
两次来完成:
- 通过用
bsxfun
减去 r
并使用 mod
来计算旋转的行索引。像往常一样,mod
需要从 0
开始的索引,而不是 1
。旋转后的行索引保留为从 0 开始,因为这对步骤 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
我目前正在将一些 GAUSS 代码移植到 Matlab 并且我一直在尝试使用 GAUSS "rotater" 函数。
旋转器的命令参考条目说:
- 用途 旋转矩阵的行
- 格式 y = rotater(x,r)
- 输入 x: N x K 待旋转矩阵。 r:指定旋转量的 N x 1 或 1 x 1 矩阵。
- 输出 y: N x K 旋转矩阵。
- 备注旋转是在矩阵的每一行内水平进行的。正旋转值将导致元素移动 向右。负旋转将导致元素移动到 左边。在任何一种情况下,被推离末尾的元素 该行将环绕到同一行的另一端。如果旋转值大于或等于 x 中的列数,则将使用 (r % cols(x)). 计算旋转值
示例 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
两次来完成:
- 通过用
bsxfun
减去r
并使用mod
来计算旋转的行索引。像往常一样,mod
需要从0
开始的索引,而不是1
。旋转后的行索引保留为从 0 开始,因为这对步骤 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