Cách nhanh chóng / hiệu quả để phân tách các hệ số bộ lọc 2D nguyên có thể tách rời


21

Tôi muốn có thể nhanh chóng xác định xem một hạt nhân 2D có các hệ số nguyên có thể tách rời thành hai hạt nhân 1D với các hệ số nguyên hay không. Ví dụ

 2   3   2
 4   6   4
 2   3   2

có thể tách thành

 2   3   2

 1
 2
 1

Thử nghiệm thực tế về khả năng phân tách dường như khá đơn giản khi sử dụng số học số nguyên, nhưng việc phân tách thành các bộ lọc 1D với các hệ số nguyên đang chứng tỏ là một vấn đề khó khăn hơn. Khó khăn dường như nằm ở chỗ các tỷ lệ giữa các hàng hoặc cột có thể không phải là số nguyên (phân số hợp lý), ví dụ trong ví dụ trên, chúng ta có các tỷ lệ 2, 1/2, 3/2 và 2/3.

Tôi thực sự không muốn sử dụng một cách tiếp cận nhiệm vụ nặng nề như SVD bởi vì (a) nó tương đối tốn kém về mặt tính toán cho nhu cầu của tôi và (b) nó vẫn không nhất thiết giúp xác định các hệ số nguyên .

Có ý kiến ​​gì không?


THÊM THÔNG TIN

Các hệ số có thể dương, âm hoặc bằng 0 và có thể có các trường hợp bệnh lý trong đó tổng của một hoặc cả hai vectơ 1D bằng 0, ví dụ

-1   2  -1
 0   0   0
 1  -2   1

có thể tách thành

 1  -2   1

-1
 0
 1

1
Tôi nhớ đã cố gắng tìm ra cách trở lại trường đại học. Tôi gần như đã thành công, nhưng tôi không nhớ làm thế nào. =) Tôi không thể ngừng suy nghĩ về nó khi bạn đề cập đến nó!
Phonon

@Phonon: heh - hãy tiếp tục suy nghĩ - Tôi có thể sử dụng một số cảm hứng về điều này. ;-)
Paul R

Có thể làm điều tương tự nhưng đối với các giá trị kép hoặc float?
Diego Catalano

@DiegoCirthano: xem câu trả lời của Denis bên dưới và câu hỏi mà anh ấy liên kết đến trên math.stackexchange.com - Tôi nghĩ rằng nó có thể hoạt động cho trường hợp tổng quát hơn về các hệ số dấu phẩy động.
Paul R

@PaulR, Làm thế nào một người có thể liên lạc với bạn trên email? Cảm ơn bạn.
Royi

Câu trả lời:


11

Tôi đã đưa ra @Phononcâu trả lời và sửa đổi nó một chút để nó sử dụng cách tiếp cận GCD ở hàng trên cùng và cột bên trái, thay vì tổng các hàng / cột. Điều này dường như để xử lý các trường hợp bệnh lý tốt hơn một chút. Nó vẫn có thể thất bại nếu hàng trên cùng hoặc cột bên trái là tất cả các số 0, nhưng những trường hợp này có thể được kiểm tra trước khi áp dụng phương pháp này.

function [X, Y, valid] = separate(M)    % separate 2D kernel M into X and Y vectors 
  X = M(1, :);                          % init X = top row of M
  Y = M(:, 1);                          % init Y = left column of M
  nx = numel(X);                        % nx = no of columns in M
  ny = numel(Y);                        % ny = no of rows in M
  gx = X(1);                            % gx = GCD of top row
  for i = 2:nx
    gx = gcd(gx, X(i));
  end
  gy = Y(1);                            % gy = GCD of left column
  for i = 2:ny
    gy = gcd(gy, Y(i));
  end
  X = X / gx;                           % scale X by GCD of X
  Y = Y / gy;                           % scale Y by GCD of Y
  scale = M(1, 1) / (X(1) * Y(1));      % calculate scale factor
  X = X * scale;                        % apply scale factor to X
  valid = all(all((M == Y * X)));       % result valid if we get back our original M
end

Rất cám ơn @Phonon@Jason Rcho những ý tưởng ban đầu cho việc này.


10

Hiểu rồi! Đăng mã MATLAB, sẽ đăng một lời giải thích tối nay hoặc ngày mai

% Two original arrays
N = 3;
range = 800;
a = round( range*(rand(N,1)-0.5) )
b = round( range*(rand(1,N)-0.5) )

% Create a matrix;
M = a*b;
N = size(M,1);

% Sanity check
disp([num2str(rank(M)) ' <- this should be 1!']);

% Sum across rows and columns
Sa = M * ones(N,1);
Sb = ones(1,N) * M;

% Get rid of zeros
SSa = Sa( Sa~=0 );
SSb = Sb( Sb~=0 );

if isempty(SSa) | isempty(SSb)
    break;
end

% Sizes of array without zeros
Na = numel(SSa);
Nb = numel(SSb);

% Find Greatest Common Divisor of Sa and Sb.
Ga = SSa(1);
Gb = SSb(1);

for l=2:Na
    Ga = gcd(Ga,SSa(l));
end

for l=2:Nb
    Gb = gcd(Gb,SSb(l));
end

%Divide by the greatest common divisor
Sa = Sa / Ga;
Sb = Sb / Gb;

%Scale one of the vectors
MM = Sa * Sb;
Sa = Sa * (MM(1) / M(1));

disp('Two arrays found:')
Sa
Sb
disp('Sa * Sb = ');
Sa*Sb
disp('Original = ');
M

Cảm ơn - điều này thật tuyệt - tôi đã thức trắng đêm qua để suy nghĩ về việc tính hệ số vv, nhưng chỉ cần sử dụng GCD như thế này thì đơn giản và thanh lịch hơn rất nhiều. Thật không may, vẫn còn một nếp nhăn để giải quyết - nó cần phải hoạt động với cả hệ số tích cực và tiêu cực và điều này có thể dẫn đến các trường hợp thoái hóa, ví dụ A=[-2 1 0 -1 2]; B=[2 -3 6 0 -1]; M=A'*B;. Vấn đề ở đây là sum(A) = 0như vậy Sb = [0 0 0 0 0]. Tôi sẽ thử sửa đổi thuật toán của bạn để nó sử dụng tổng các giá trị tuyệt đối của các hệ số và xem điều đó có giúp ích gì không. Cảm ơn một lần nữa vì sự giúp đỡ của bạn.
Paul R

OK - có vẻ như bạn vẫn có thể nhận được GCDs và thực hiện nhân rộng bằng cách sử dụng abs(M), ví dụ Sa=abs(M)*ones(N,1); Sb=ones(1,N)*abs(M);và sau đó tiếp tục như trên, nhưng tôi chưa thấy làm thế nào để khôi phục những dấu hiệu để Sa, Sbở cuối. Tôi đã thêm một ví dụ bệnh lý minh họa vấn đề trong câu hỏi ban đầu ở trên.
Paul R

Tôi nghĩ rằng tôi có một giải pháp hiệu quả ngay bây giờ - Tôi đã đăng nó dưới dạng một câu trả lời riêng biệt, nhưng khoản tín dụng dành cho bạn cho ý tưởng cơ bản. Cảm ơn một lần nữa!
Paul R

7

Có thể tôi tầm thường hóa vấn đề, nhưng có vẻ như bạn có thể:

  • NMAaii=0,1,,N1
  • j>0

    • aja0jrj
    • rj để xác định xem chúng có phải là hằng số không. Bạn sẽ cần cho phép một số dung sai trong so sánh này để cho phép làm tròn điểm nổi.
    • rjaja0j0x
    • aja0
  • x

xk,norm=xkmini=0N1xi
  • xnorm
    xscaled=Kxnorm,K=1,2,,M
    KM

Không phải là phương pháp tao nhã nhất, và có khả năng là có một cách tốt hơn, nhưng nó nên hoạt động, khá đơn giản để thực hiện và nên tương đối nhanh đối với các ma trận có kích thước khiêm tốn.


Cảm ơn - Tôi nghĩ rằng tôi có lẽ đã đi theo hướng như thế này trước khi tôi bị sa lầy vào các chi tiết. Tôi không rõ ràng 100% rằng tôi sẽ luôn tìm ra giải pháp bằng phương pháp này, nhưng dù sao, tôi có lẽ nên viết mã này và thử với một vài ví dụ. Tôi có linh cảm rằng nó có thể cần được áp dụng cả theo hàng và khôn ngoan theo cột để xem giải pháp nào mang lại giải pháp "tốt nhất". Cảm ơn bạn đã dành thời gian để đánh vần các chi tiết - Tôi sẽ bận rộn với nó và cho bạn biết làm thế nào nó hoạt động.
Paul R

Bạn không thể tìm được ước số chung lớn nhất của các phần tử đầu tiên của các hàng và sử dụng số đó để xác định vectơ cơ sở của bạn?
Jim Clay

@JimClay: Vâng, đó thực sự là những gì bạn đang làm ở cuối, nếu bạn có sẵn chức năng đó.
Jason R

3

xyzA|Axyz|
x y z
yzxx y z x y z ... lần lượt

(Từ gần đúng-một-tích chập-như-một-tổng-của-tách-kết luận trên math.stackexchange.)


1
Cố gắng không trả lời các câu hỏi với các liên kết không giải thích được. Tốt hơn là giải thích các chi tiết cần thiết trong câu trả lời của bạn và chỉ bao gồm liên kết để tham khảo; theo cách đó nếu liên kết phá vỡ các chi tiết cần thiết của câu trả lời vẫn còn đó.
Sam Maloney

@SamMaloney: Tôi thấy không có lý do tại sao điều đó lại cần thiết. Các liên kết giải thích mọi thứ chi tiết. Nó vẫn sẽ bật lên trong tìm kiếm Q & A. Vậy tại sao không?
Naresh

1
@Naresh Tôi chỉ đề cập đến nó vì một trong những mục tiêu của các trang web trao đổi ngăn xếp là xây dựng một kho lưu trữ các câu hỏi đã trả lời để tham khảo trong tương lai. Vì vậy, trong khi tôi hiểu rằng liên kết cụ thể này là đến một trang SE khác và nên khá an toàn, thì đó là cách tốt nhất để không dựa vào các liên kết vẫn hoạt động vài năm kể từ bây giờ. Đưa ra một phác thảo chung về "hai phương pháp dễ dàng" này trong câu trả lời sẽ đảm bảo thông tin được giữ lại ngay cả khi có điều gì đó xảy ra với câu hỏi được liên kết. Như tôi đã nói, đây là một nhận xét chung về các thực tiễn tốt nhất về liên kết trong câu trả lời.
Sam Maloney
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.