【问题标题】:Delete same submatrices in a bigger matrix. Matlab删除更大矩阵中的相同子矩阵。 MATLAB
【发布时间】:2016-09-23 01:16:23
【问题描述】:

我想分析更大矩阵中的 2x2 块,如果其中两个块相同,则删除它们。我尝试自己编写的代码看起来有点像这样(C 是一个有 2 个列的大矩阵):

n=size(C,1);

for k=1:2:(n-3)
    for l=(k+2):2:(n-1)

        if C(k:k+1,1:2)==C(l:l+1,1:2);

        C([l,l+1],:)=[];

        else
        end
    end
end

我遇到的问题是,matlab 在删除 C 中的行时没有“注意到” C 的大小正在缩小。这意味着最终代码会遇到问题,因为它要求在一个太高的维度上进行相等检查。我怎样才能避免它?有更好的方法吗?

我也尝试过围绕“独特”命令。但这仅适用于行。我需要 2x2 段(从奇数行开始)。

完整(原始)代码在这里:

A=[1,0;0,1i];
B=1/sqrt(2)*[1,1;1,-1];

C=[0,0;0,0];

C(1:2,1:2)=A(1:2,1:2);
C(3:4,1:2)=B(1:2,1:2);


for m=1:20

d=size(C,1)

C_A=C*A;
C_B=C*B;

s_a=size(C_A);
s_a=s_a(1,1);
s_b=size(C_B);
s_b=s_b(1,1);

C((d+1):(d+s_a),1:2)=C_A(1:s_a,1:2);
C((d+s_a+1):(d+s_a+s_b),1:2)=C_B(1:s_b,1:2);

n=size(C,1);

for k=1:2:(n-3)
    for l=(k+2):2:(n-1)

        if C(k:k+1,1:2)==C(l:l+1,1:2);

        C([l,l+1],:)=[];

        else
        end
    end
end

new_n=size(C,1)

if d==new_n
    error('Done')
else
end 
end

【问题讨论】:

  • 你能展示一些示例数据和预期输出吗?目前尚不清楚当您从矩阵中间“移除”一个 2 x 2 块时会发生什么
  • @Suever 他们说 C 是 nx2 矩阵;本来我也在想同样的事情

标签: matlab matrix


【解决方案1】:

要使您的代码按原样工作,请先反转l 循环的方向:

    for l = (size(C,1)-1):-2:(k+2)

这样,每次增加k 时,您都会从末尾删除并重新计算最大索引。但是您仍然会遇到k 循环的问题,因此只需将其更改为while 循环即可。此外,使用== 比较 2x2 矩阵会给您 4 个值,这可能不是您想要的。如果两个矩阵具有相同的值,则使用 isequal 将为您提供一个布尔值。

k = 1;
while (k < size(C,1))
    for l = (size(C,1)-1):-2:(k+2)
        if isequal(C(k:k+1,1:2), C(l:l+1,1:2))
            C([l,l+1],:) = [];
        end
    end
    k = k + 2;
end

或者,您可以通过将每个 2x2 子矩阵重新排列成一行来使用 unique

D = reshape(C.', 4, []).';
U = unique(D, 'rows');
C = reshape(U.', 2, []).';

如果您正在处理浮点值,那么比较它们的相等性绝不是一个好主意;浮点值的有限精度总是会给你带来麻烦。为了解决这个问题,您可以创建一个函数来比较容差内的相等性。

isequalTol=@(a,b,tol) all(abs(a-b) < tol);

此函数适用于标量、向量或矩阵。现在您定义一个容差并将isequal 替换为isequalTol

tol = eps(1);
k = 1;
while (k < size(C,1))
    for l = (size(C,1)-1):-2:(k+2)
        if isequalTol(C(k:k+1,1:2), C(l:l+1,1:2), tol)   % equal within tolerance
            C([l,l+1],:) = [];
        end
    end
    k = k + 2;
end

【讨论】:

  • 谢谢,这看起来不错!我试过这个,它不会产生错误。但是,它不会为我产生预期的结果。解释我想要做什么:我试图找到由两个矩阵 A 和 B 生成的组中的所有矩阵。我将在此处发布完整的代码。无论如何,如果您让 m 从 1 变为 2,您可以看到程序在生成的 C 中已经缺少两个相等的子矩阵。即 C(3:4,1:2) 和 C(25:26,1: 2)。是因为舍入错误吗? github.com/DerDoctorFelix/matrix-code/blob/master/matrixtest.m
  • @DerFelix 是的,这很可能是舍入错误。你永远不想检查浮点值是否相等。请编辑您的原始问题以包含您的实际代码。
  • 将原始代码编辑到问题中(没有您的修复)。是否可以在误差范围内进行检查?
  • @DerFelix 我添加了一个函数来替换 isequal 以适应您的情况。您必须确定 tol 的正确值。
  • 谢谢!这正是我所需要的,并导致了预期的结果。非常感谢您抽出宝贵时间来帮助我!
【解决方案2】:

与使用掩码来防止 while 循环的烧杯的方法略有不同。如果您以后想对重复值做任何事情,这种方法会更可取。

CMask = ones(size(C)); %Create mask; anything with a 1 will be part of final answer, zeros will be left out
for ii = 1:2:size(C,1)
    for jj = ii+2:2:size(C,1)
        CMask(jj:jj+1,:) = CMask(jj,1) && ~isequal(C(ii:ii+1,:),C(jj:jj+1,:))) %If the two sections are equal, make CMask zeros in the lower section. && is required so that we don't overwrite 0s with 1s
    end
end
COut = reshape(C(CMask),[],2);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-21
    • 2013-06-18
    相关资源
    最近更新 更多