Ayrılabilir tamsayılı 2D filtre katsayılarını ayırmanın hızlı / verimli yolu


21

Belirli bir tamsayı katsayılarının bir 2B çekirdeğinin tamsayı katsayıları olan iki 1B çekirdeğe ayrılıp ayrılmayacağını hızlı bir şekilde belirlemek isterim. Örneğin

 2   3   2
 4   6   4
 2   3   2

ayrılabilir

 2   3   2

ve

 1
 2
 1

Ayrılabilirlik için gerçek test, tamsayı aritmetiği kullanılarak oldukça basit görünmektedir, ancak tamsayı katsayıları olan 1B filtrelere ayrışmanın daha zor bir problem olduğu kanıtlanmıştır. Zorluk, satırlar veya sütunlar arasındaki oranların tamsayı olmayan (rasyonel fraksiyonlar) olabileceğinden kaynaklanıyor gibi görünmektedir, örneğin yukarıdaki örnekte 2, 1/2, 3/2 ve 2/3 oranlarına sahibiz.

SVD gibi ağır bir görev yaklaşımı kullanmak istemiyorum, çünkü (a) benim ihtiyaçlarım için nispeten hesaplamalı olarak pahalı ve (b) yine de tamsayı katsayılarını belirlemek için mutlaka yardımcı olmuyor .

Herhangi bir fikir ?


DAHA FAZLA BİLGİ

Katsayılar pozitif, negatif veya sıfır olabilir ve 1D vektörlerinden birinin veya her ikisinin toplamının sıfır olduğu patolojik durumlar olabilir;

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

ayrılabilir

 1  -2   1

ve

-1
 0
 1

1
Üniversitede bunu tekrar çözmeye çalıştığımı hatırlıyorum. Neredeyse başardım, ama nasıl olduğunu hatırlamıyorum. =) Şimdi bahsettiğiniz hakkında düşünmekten vazgeçemiyorum!
Phonon

@Fonon: heh - düşünmeye devam et - bu konuda biraz ilham alabilirim. ;-)
Paul R

Aynı şeyi yapmak mümkün değil mi, çift veya değişken değerler için?
Diego Catalano

@DiegoCatalano: Denis'in aşağıdaki cevabını ve math.stackexchange.com adresindeki bağlantılarını görün. - Bunun kayan nokta katsayılarının daha genel olması için işe yarayacağını düşünüyorum.
Paul R

@PaulR, Bir e-posta ile nasıl iletişim kurabilirim? Teşekkür ederim.
Royi

Yanıtlar:


11

@PhononCevabını aldım ve biraz değiştirdim, böylece GCD yaklaşımını satır / sütun toplamlarından ziyade sadece üst satırda ve sol sütunda kullanır. Bu patolojik vakaları biraz daha iyi ele alıyor gibi görünüyor. Üst satır veya sol sütunun tümü sıfır ise yine başarısız olabilir, ancak bu durumlarda bu yöntemi uygulamadan önce kontrol edilebilir.

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

Bunun için özgün fikirler için @Phononve teşekkür ederiz @Jason R.


10

Anladım! MATLAB kodunu göndermek, bu gece veya yarın için bir açıklama gönderecektir.

% 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

Teşekkürler - bu harika - Dün gece katsayıları vb. Çarpanlara ayırmayı düşünerek uyanık yatıyordum ama sadece GCD'yi kullanmak çok daha basit ve zarif. Ne yazık ki hala demirlemek için bir kırışıklık var - hem pozitif hem de negatif katsayılarla çalışması gerekir ve bu, örneğin dejenere vakalara yol açabilir A=[-2 1 0 -1 2]; B=[2 -3 6 0 -1]; M=A'*B;. Buradaki sorun sum(A) = 0böyle Sb = [0 0 0 0 0]. Algoritmanızı değiştirmeyi deneyeceğim, böylece katsayıların mutlak değerlerinin toplamını kullanır ve bunun yardımcı olup olmadığına bakın. Yardımın için tekrar teşekkürler.
Paul R

Tamam - hala GCDs almak ve kullanarak ölçeklendirme yapabilirsiniz gibi görünüyor abs(M), ie Sa=abs(M)*ones(N,1); Sb=ones(1,N)*abs(M);ve sonra yukarıdaki gibi devam eder, ancak henüz işaretlerini geri nasıl göremez Sa, Sbsonunda. Yukarıdaki orijinal sorudaki problemi gösteren patolojik bir örnek ekledim.
Paul R

Sanırım şimdi çalışan bir çözümüm var - ayrı bir cevap olarak göndermiştim, ancak temel fikir için kredi size gidiyor. Tekrar teşekkürler !
Paul R

7

Belki de problemi önemsizleştiriyorum, fakat senin yapabileceğin gibi görünüyor:

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

    • aja0jrj
    • rj
    • rjaja0j0x
    • aja0
  • x

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

En zarif yöntem değildir ve daha iyi bir yol olması muhtemeldir, ancak çalışması gerekir, uygulanması oldukça basittir ve mütevazı boyuttaki matrisler için nispeten hızlı olmalıdır.


Teşekkürler - Ben ayrıntılara tıkılmadan önce muhtemelen bu yönde ilerliyordum. Bu yöntemi kullanarak her zaman bir çözüme varacağınız benim için% 100 net değil, ama yine de, muhtemelen bunu kodlamalı ve birkaç örnekle denemeliyim. Hangisinin "en iyi" çözümü getirdiğini görmek için hem satır hem de sütun olarak uygulanması gerekebileceğine dair bir ipucum var. Ayrıntıları açıklamaya zaman ayırdığınız için teşekkürler - Bununla meşgul olacağım ve nasıl sonuçlanacağını size bildireceğim.
Paul R

Satırların ilk öğelerinin en büyük ortak bölenini bulamadınız mı ve temel vektörünüzü belirlemek için bunu kullanamaz mıydınız?
Jim Clay,

@JimClay: Evet, bu işlevselliğe sahipseniz, sonunda yaptığınız şey etkilidir.
Jason R,

3

xyzA|Axyz|
x y z
yzxx y z x y z ... sırayla.

( Yaklaşık-bir-konvolüsyondan-bir-toplamdan-toplam-ayrıştırılabilir-konvolüsyonların matem.stackexchange üzerindeki.


1
Açıklanamayan bağlantılarla soruları cevaplamamaya çalışın. Cevabınıza gerekli detayları açıklamak ve sadece referans için bağlantıyı eklemek daha iyidir; bu şekilde bağlantı koparsa, cevabın temel detayları hala oradadır.
Sam Maloney

@SamMaloney: Bunun neden gerekli olduğuna dair hiçbir neden göremiyorum. Bağlantı her şeyi ayrıntılı olarak açıklar. Hala soru cevap aramada görünecektir. Yani neden olmasın?
Naresh,

1
@Naresh, yalnızca borsanın sitelerinin hedeflerinden biri, gelecekteki referans için cevaplanmış soruların bir havuzunu oluşturmak olduğu için bahsediyorum. Bu özel bağlantının başka bir SE sitesine ait olduğunu ve oldukça güvenli olması gerektiğini anladığım halde, birkaç yıldan beri hala çalışan bağlantılara güvenmemek en iyi yöntemdir. . Enformasyon şey bağlantılı soruya bir sorun olsa bile korunur güvence altına alacak cevap bu "iki kolay yöntemlerle genel hatlarını verilmesi olarak ben bunu daha cevapları linkleri ilişkin en iyi uygulamalar hakkında genel bir yorumun oldu gerçi söyledi.
Sam Maloney
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.