Hamming'i kullanarak hataları düzeltme (7,4)


19

Hamming (7,4) kodu 1950'ye kadar uzanır. O zamanlar Richard Hamming, Bell Laboratuarlarında matematikçi olarak çalıştı. Her Cuma Hamming, hesaplama makinelerini bir dizi hesaplama yapmak için ayarladı ve sonuçları bir sonraki Pazartesi günü topladı. Eşlik denetimlerini kullanarak, bu makineler hesaplama sırasında hataları algılayabildi. Sinir bozucu, çok sık hata mesajları aldığı için Hamming, hata tespitini geliştirmeye karar verdi ve ünlü Hamming kodlarını keşfetti.

Hamming Mekaniği (7,4)

Hamming kodlarının amacı, bir veri bitindeki veya bir eşlik bitindeki tek bitlik bir hata (bir bit çevrilir) saptanabilecek ve düzeltilebilecek şekilde bir dizi eşlik biti oluşturmaktır. Yalnızca birden çok hata oluşursa, Hamming kodu orijinal verileri kurtaramaz. Hiç bir hata fark etmeyebilir, hatta yanlış düzeltebilir. Bu nedenle, bu mücadelede sadece tek bitli hatalarla ilgileneceğiz.

Hamming kodlarına bir örnek olarak Hamming (7,4) koduna bakacağız. 4 bit veriye ek olarak , aşağıdaki denklemler kullanılarak hesaplanan d1, d2, d3, d43 parite bitini kullanır p1, p2, p3:

p1 = (d1 + d2 + d4) % 2
p2 = (d1 + d3 + d4) % 2
p3 = (d2 + d3 + d4) % 2

Sonuçta elde edilen kod sözcüğü (veri + eşlik bitleri) biçimindedir p1 p2 d1 p3 d2 d3 d4.

Bir hatayı tespit etmek şu şekilde çalışır. Parite bitlerini yeniden hesaplar ve alınan parite bitleriyle eşleşip eşleşmediğini kontrol edersiniz. Aşağıdaki tabloda, tek bitlik hataların her çeşidinin eşlik bitleriyle farklı bir eşleşme sağladığını görebilirsiniz. Bu nedenle, her bir tek bit hatası yerelleştirilebilir ve düzeltilebilir.

error in bit | p1 | p2 | d1 | p3 | d2 | d3 | d4 | no error
-------------|---------------------------------------------
p1 matches   | no | yes| no | yes| no | yes| no | yes
p2 matches   | yes| no | no | yes| yes| no | no | yes
p3 matches   | yes| yes| yes| no | no | no | no | yes

Misal

Verileriniz olsun 1011. Eşlik biti p1 = 1 + 0 + 1 = 0, p2 = 1 + 1 + 1 = 1ve p3 = 0 + 1 + 1 = 0. Verileri ve eşlik bitlerini birleştirdiğinizde kod kelimesini alırsınız 0110011.

data bits   |   1 011
parity bits | 01 0
--------------------
codeword    | 0110011

Bir iletim veya hesaplama sırasında 6. bitin (= 3. veri biti) ters çevrildiğini söyleyelim. Kelimeyi alırsınız 0110001. İddia edilen veriler 1001. Yine eşitlik bitlerini hesaplamak p1 = 1 + 0 + 1 = 0, p2 = 1 + 0 + 1 = 0, p3 = 0 + 0 + 1 = 1. Yalnızca p1kod kelimesinin eşlik bitleriyle eşleşir 0110001. Bu nedenle bir hata oluştu. Yukarıdaki tabloya bakarak, hatanın meydana geldiğini d3ve orijinal verileri kurtarabileceğinizi söyler 1011.

Meydan okuma:

Bir sözcük (7 bit) alan bir işlev veya program yazın, bitlerden biri yanlış olabilir ve orijinal verileri kurtarın. Girdi (STDIN, komut satırı bağımsız değişkeni, bilgi istemi veya işlev bağımsız değişkeni aracılığıyla) biçimi, bir dize "0110001", bir liste veya [0, 1, 1, 0, 0, 0, 1]MSB'de bir dizi veya bir tam sayı olabilir 0b0110001 = 49. Yukarıda açıklandığı gibi, girdinin sırası p1 p2 d1 p3 d2 d3 d4. Çıktı (dönüş değeri veya STDOUT aracılığıyla) aynı formatta, ancak sırayla olmalıdır d1 d2 d3 d4. Yalnızca 4 veri bitini döndürün / çıkarın.

Bu kod golfü. Bu nedenle en kısa kod kazanır.

Test senaryoları:

1110000 -> 1000  # no error
1100000 -> 1000  # error at 1st data bit
1111011 -> 1111  # error at 2nd data bit
0110001 -> 1011  # error at 3rd data bit (example)
1011011 -> 1010  # error at 4th data bit
0101001 -> 0001  # error at 1st parity bit
1010000 -> 1000  # error at 2nd parity bit
0100010 -> 0010  # error at 3rd parity bit


1
Son parite bitinin ilk veri bitinden sonra verilmesinin belirli bir nedeni var mı?
xnor

2
@xnor Matematiksel olarak, parite bitlerinin bulunduğu konumda herhangi bir fark yaratmaz. Tarihsel olarak ikisinin güçleri üzerine yerleştirilirler. Hamming (15,11) 1, 2, 4 ve 8 pozisyonlarında parite bitlerine sahiptir.
Jakube

4
@xnor İkinci [is_p3_wrong][is_p2_wrong][is_p1_wrong]tabanı alırsanız , sözcükteki yanlış bitin konumunu verir. (Söz konusu tabloya dayanarak.) Bu muhtemelen bazı algoritmalar için yararlı olacaktır.
randomra

Çok güzel :) Bir kelime (7 bit) alan bir fonksiyon veya program yazın, bunlardan biri yanlış olabilir, [...] "Sanırım bitlerden biri yanlış olabilir ama siz aslında sözcüklerden birinin olabileceğini söyle.

@Lembik Elbette, netleştirdi.
Jakube

Yanıtlar:


6

Oktav, 70 66 55 bayt

Bu işlev F, kod çözme matrisini Hkurar, hatayı bulur ve hatanın konumunu düzeltir (eğer varsa). Sonra doğru veri bitlerini döndürüyor. Giriş standart bir satır vektörüdür.

@Jakube nerede yerine Matlab'in Octave kullanmalıdır önerdi olabilir tekrar kısa 11 bayt her şeyi yapar ifadeler üzerine endekslerini kullanın:

F=@(c)xor(c,1:7==bi2de(mod(c*de2bi(1:7,3),2)))([3,5:7])

Aşağıdaki ifadelerde doğrudan endekslemeyi kullanamayacağınız için Matlab'daki en kısa çözüm . (Bu elbette Octave'de de işe yarıyor.) Add / mod2'nin yerine xor:

f=@(c)c([3,5:7]);F=@(c)f(xor(c,1:7==bi2de(mod(c*de2bi(1:7,3),2))))

Eski:

f=@(c)c([3,5:7]);F=@(c)f(mod(c+(1:7==bi2de(mod(c*de2bi(1:7,3),2))),2))

Teşekkür ederim, ama bu çalışmıyor, maalesef sadece bu şekilde değişkenlere erişebilirsiniz ...
flawr

1
Matlab yüklü değil, sadece http://octave-online.net/çalıştığı yerde kullandım . Belki dili değiştirebilir?
Jakube

Oh, zaten oktavın bunu yapabileceğinden şüpheleniyordum, ama sonra elbette dili değiştireceğim, çok teşekkür ederim!
flawr

14

Piet 50x11 = 550

resim açıklamasını buraya girin

codel boyutu 15'dir.


4
Sorunun bağlamı göz önüne alındığında bunu sevdim.

1
@Optimizer "kodek boyutu" aslında bir piet programının büyütme faktörüdür. Burada, daha kolay görünürlük sağlamak için her mantıksal piksel (veya kod çözücü) 15x15 bloğa genişletildi. Demek istediğim, "kod boyutu" değil
captncraig

ah ..... benim kötü.
Optimizer

8

Python, 79

f=lambda x,n=0,e=3:e&~-e and f(x,n+1,(n&8)*14^(n&4)*19^(n&2)*21^n%2*105^x)or~-n

Girdi ve çıktıları sağ tarafta en az anlamlı bit olan sayılar olarak al.

Hata kurtarmayı denemek yerine, nverilenlerden bir bit uzakta bir kodlama alana kadar 0'dan 15'e kadar olası her mesajı kodlamayı deneriz . Özyineleme nişe yarayan ve döndürene kadar artmaya devam eder . Açık bir sonlandırma olmamasına rağmen, 16 döngü içinde sona ermelidir.

İfade (n&8)*14^(n&4)*19^(n&2)*21^n%2*105Hamming matrisini bitsel olarak uygular.

Tek bir hatayı kontrol etmek için, verilen mesajı bilgisayarlı bir mesajla xor eveya klasik bit hilesi ile iki (veya 0) güç olup olmadığını kontrol ederiz e&~-e==0. Ancak, ebir lambda içindeki değişkeni gerçekten atayamayız ve bu ifadede iki kez atıfta bulunuruz, bu yüzden onu bir sonraki özyinelemeli adım için isteğe bağlı bir argüman olarak geçirmenin bir hackini yaparız.


7

JavaScript (ES6), 92 87 81

MSB'de tamsayı alma ve döndürme fonksiyonu.
Uygulama @randomra yorumunu takiben basittir:

  • calc p3wrong | p2wrong | p1wrong (satır 2,3,4)
  • yanlış biti çevirmek için bir bit maskesi olarak kullanın (satır 1),
  • sonra sadece veri bitlerini döndür (son satır)
F=w=>(w^=128>>(
  (w^w*2^w*4^w/2)&4|
  (w/8^w^w*2^w/16)&2|
  (w/16^w/4^w^w/64)&1
))&7|w/2&8

Frefox / FireBug konsolunda test et

;[0b1110000,0b1100000,0b1111011,0b0110001,
0b1011011,0b0101001,0b1010000,0b0100010]
.map(x=>x.toString(2)+'->'+F(x).toString(2))

Çıktı

["1110000->1000", "1100000->1000", "1111011->1111", "110001->1011", "1011011->1010", "101001->1", "1010000->1000", "100010->10"]

1
Kompakt bitsel çalışma çözümünüzü gerçekten beğendim =)
Kusur

4

Python 2, 71

f=lambda i,b=3:i&7|i/2&8if chr(i)in'\0%*3<CLUZfip'else f(i^b/2,b*2)

Birkaç karakter yazdırılamaz ASCII olduğundan kaçan bir sürüm var:

f=lambda i,b=3:i&7|i/2&8if chr(i)in'\0\x0f\x16\x19%*3<CLUZfip\x7f'else f(i^b/2,b*2)

Fonksiyona giriş ve çıkış tamsayı olarak yapılır.

Geçerli mesaj sayısının sadece 16 olduğu gerçeğinden faydalanıyorum ve hepsini zor kodluyorum. Sonra bunlardan birini elde edene kadar farklı bitleri çevirmeye çalışıyorum.


3

Haskell, 152 bayt

a(p,q,d,r,e,f,g)=b$(d+e)#p+2*(d+f)#q+4*(e+f)#r where b 3=(1-d,e,f,g);b 5=(d,1-e,f,g);b 6=(d,e,1-f,g);b 7=(d,e,f,g-1);b _=(d,e,f,g);x#y=abs$(x+g)`mod`2-y

Kullanım: a (1,1,1,1,0,1,1)hangi çıkışlar(1,1,1,1)

Basit çözüm: p<x>eşleşmezse, biti <x>bir sayı olarak ayarlayın. Bu sayı , veya ise 3, karşılık geleni çevirin .567d<y>


Kodunuzu nasıl arayacağınıza ilişkin daha fazla talimat ekleyebilir misiniz (örneğin ideone.com gibi bir çevrimiçi derleyici kullanarak )? Her zaman garip hatalar alıyorum (büyük olasılıkla benim hatam).
Jakube

@Jakube: bir dosyaya kod tasarruf demek hamming.hsve Haskell REPL GHCi içine yüklemek: ghci hamming.hs. Fonksiyonu ayukarıda açıklandığı gibi çağırın . Bildiğim tek çevrimiçi haskell tercümanı ( tryhaskell.org ) biraz daha kod gerektiriyor:let a(p,q, ... 2-y in a (1,1,1,1,0,1,1)
nimi

3

IA-32 makine kodu, 36 bayt

HexDump:

33 c0 40 91 a8 55 7a 02 d0 e1 a8 66 7a 03 c0 e1
02 a8 78 7a 03 c1 e1 04 d0 e9 32 c1 24 74 04 04
c0 e8 03 c3

Eşdeğer C kodu:

unsigned parity(unsigned x)
{
    if (x == 0)
        return 0;
    else
        return x & 1 ^ parity(x >> 1);
}

unsigned fix(unsigned x)
{
    unsigned e1, e2, e3, err_pos, data;
    e1 = parity(x & 0x55);
    e2 = parity(x & 0x66);
    e3 = parity(x & 0x78);
    err_pos = e1 + e2 * 2 + e3 * 4;
    x ^= 1 << err_pos >> 1;
    data = x;
    data &= 0x74;
    data += 4;
    data >>= 3;
    return data;
}

x86 CPU, her ara sonucun paritesini otomatik olarak hesaplar. Özel bir talimatı varjpPariteye bağlı olarak atlayan veya atlamayan vardır.

Meydan okumada açıkça belirtilmemiştir, ancak çekiçleme kodlarının uygun özelliği, eşlik bitlerini ikili bir sayı olarak yorumlayabilmenizdir ve bu sayı iletim sırasında hangi bitin bozulduğunu gösterir. Aslında bu sayı 1 tabanlıdır, yani 0 iletim hatası yoktur. Bu, önce 1 err_possonra sağa kaydırarak uygulanır 1.

İletim hatasını düzelttikten sonra, kod veri bitlerini gereken sırada düzenler. Kod boyut için optimize edilmiştir ve ilk başta nasıl çalıştığı belirsiz olabilir. Bunu açıklamak için, ben tarafından ifade a, b, c, dveri bitleri, tarafından P, Qve Reşlik biti. Sonra:

    data = x;     // d  c  b  R  a  Q  P
    data &= 0x74; // d  c  b  0  a  0  0
    data += 4;    // d  c  b  a ~a  0  0
    data >>= 3;   // d  c  b  a

Montaj kaynağı ( fastcallgiriş ecx, çıkış ve çıkış dahil eax):

    xor eax, eax;
    inc eax;
    xchg eax, ecx;

    test al, 0x55;
    jp skip1;
    shl cl, 1;

skip1:
    test al, 0x66;
    jp skip2;
    shl cl, 2;

skip2:
    test al, 0x78;
    jp skip3;
    shl ecx, 4;

skip3:
    shr cl, 1;
    xor al, cl;

    and al, 0x74;
    add al, 4;
    shr al, 3;

    ret;
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.