Hamming(7,4)を使用してエラーを修正


19

Hamming(7,4)コードは1950年に遡ります。当時、Richard HammingはBell Labsで数学者として働いていました。毎週金曜日、ハミングは一連の計算を実行するように計算機を設定し、次の月曜日に結果を収集しました。パリティチェックを使用して、これらのマシンは計算中にエラーを検出できました。ハミングはエラーメッセージを頻繁に受信するため、エラー検出を改善することを決め、有名なハミングコードを発見しました。

ハミングの力学(7,4)

ハミングコードの目標は、データビットまたはパリティビットのシングルビットエラー(1ビットが反転)を検出して修正できるように、重複するパリティビットのセットを作成することです。複数のエラーが発生した場合のみ、ハミングコードは元のデータの回復に失敗します。エラーにまったく気付かないか、誤って修正することさえありません。したがって、この課題では、シングルビットエラーのみを扱います。

ハミングコードの例として、ハミング(7,4)コードを見てみましょう。4ビットのデータに加えて、次の式を使用して計算さd1, d2, d3, d4れる3つのパリティビットp1, p2, p3を使用します。

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

結果のコードワード(データ+パリティビット)はの形式p1 p2 d1 p3 d2 d3 d4です。

エラーの検出は次のように機能します。パリティビットを再計算し、受信したパリティビットと一致するかどうかを確認します。次の表では、あらゆる種類のシングルビットエラーが、パリティビットの異なる一致をもたらすことがわかります。したがって、すべてのシングルビットエラーをローカライズおよび修正できます。

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

データをにしましょう1011。パリティビットはp1 = 1 + 0 + 1 = 0p2 = 1 + 1 + 1 = 1およびp3 = 0 + 1 + 1 = 0です。データとパリティビットを組み合わせると、コードワードが得られます0110011

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

送信中または計算中に、6番目のビット(= 3番目のデータビット)が反転したとしましょう。あなたは言葉を受け取り0110001ます。疑わしい受信データは1001です。あなたは再びパリティビットを計算しp1 = 1 + 0 + 1 = 0p2 = 1 + 0 + 1 = 0p3 = 0 + 0 + 1 = 1p1コードワードのパリティビットのみに一致します0110001。したがって、エラーが発生しました。上の表を見ると、エラーが発生したことがわかりd3、元のデータを復元できます1011

チャレンジ:

ワード(7ビット)を受け取る関数またはプログラムを作成します。ビットの1つが間違っている可能性があり、元のデータを復元します。入力(STDIN、コマンドライン引数、プロンプト、または関数引数による)形式は、文字列"0110001"、リスト、配列、[0, 1, 1, 0, 0, 0, 1]またはMSBの整数0b0110001 = 49です。上記のように、入力の順序はp1 p2 d1 p3 d2 d3 d4です。出力(戻り値またはSTDOUT経由)は同じ形式である必要がありますが、順序はd1 d2 d3 d4。4データビットのみを返す/出力します。

これはコードゴルフです。したがって、最短のコードが優先されます。

テストケース:

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
最後のパリティビットが最初のデータビットの後に指定される特別な理由はありますか?
xnor

2
@xnor数学的には、パリティビットがどの位置にあるかに違いはありません。歴史的に、それらは2の累乗の位置に配置されます。たとえば、Hamming(15,11)は、位置
1、2、4

4
@xnor [is_p3_wrong][is_p2_wrong][is_p1_wrong]2 を基数とする場合、単語の誤ったビットの位置を示します。(質問の表に基づきます。)これはおそらく、いくつかのアルゴリズムに役立つでしょう。
-randomra

非常に良い:)「関数(またはプログラム)を書いて、単語(7ビット)を受け取ると、そのうちの1つが間違っている可能性があります、[...]」実際に言葉の一つがそうかもしれないと言う。

@Lembik Sure、それを明確にした。
ジャクベ

回答:


6

オクターブ、70 66 55バイト

この関数Fは、デコードマトリックスを設定し、Hエラーを見つけ、エラーの位置を修正します(エラーがある場合)。次に、正しいデータビットを返します。入力は標準の行ベクトルです。

@Jakubeは、式にインデックスを使用できる Matlabの代わりにOctaveを使用することを提案しました。これにより、全体が11バイト短くなります:

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

以下は、式でインデックスを直接使用できないため、Matlabで最も短いソリューションです。(これはもちろんOctaveでも機能します。)addition / mod2をxor次のように置き換えることができました:

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

古い:

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

ありがとうございますが、これは機能しません。残念ながら、その方法でしか変数にアクセスできません
...-flawr

1
Matlabをインストールしておらずhttp://octave-online.net/、動作する場所のみを使用しました。言語を変更するかもしれませんか?
ジャクベ

ああ、私はすでにオクターブがそうすることを疑っていましたが、それからもちろん言語を変えるつもりです、どうもありがとう!
フレイ

14

ピート50x11 = 550

ここに画像の説明を入力してください

codelサイズは15です。サイズについてはあまり気にしませんが、すべてのテストに合格しました。


4
私はむしろ、問題のコンテキストを考えるとこれが好きです。

1
@Optimizerの「コーデルサイズ」は、本質的にはパイエットプログラムの拡大率です。ここでは、各論理ピクセル(またはコーデル)が15x15ブロックに拡張され、見やすくなりました。それは私が、ない「コードサイズ」を意味するものである
captncraig

ああ.....私の悪い。
オプティマイザー

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

右側に最下位ビットを持つ数値として入出力を取ります。

エラー回復を試みる代わりに、n与えられたものから1ビット離れたエンコードが得られるまで、0から15までの可能なすべてのメッセージをエンコードしようとします。再帰はn、動作するものを見つけて返すまで増加し続けます。明示的な終了はありませんが、16ループ以内で終了する必要があります。

この式(n&8)*14^(n&4)*19^(n&2)*21^n%2*105は、ハミング行列をビット単位で実装します。

単一のエラーをチェックするには、指定されたメッセージと計算されたメッセージを取得して取得eし、クラシックビットトリックで2のべき乗(または0)かどうかを確認しe&~-e==0ます。しかし、実際にeラムダ内の変数に代入することはできず、この式で変数を2回参照するため、次の再帰ステップにオプションの引数として渡すというハックを行います。


7

JavaScript(ES6)、92 87 81

MSBで整数を取得および返す関数。
実装は@randomraコメントに続くstraightforwrdです:

  • calc p3wrong | p2wrong | p1wrong(行2,3,4)
  • 不正なビットを反転させるビットマスクとして使用します(1行目)。
  • 次に、データビットのみを返します(最終行)
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コンソールでテストする

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

出力

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

1
私はあなたのコンパクトなビット単位操作ソリューションが本当に好きです=)
flawr

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)

いくつかの文字は印刷できないASCIIなので、ここにエスケープバージョンがあります。

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)

関数への入出力は整数として行われます。

有効なメッセージの数がわずか16であるという事実を利用して、それらをすべてハードコーディングしています。次に、それらのいずれかを取得するまで、さまざまなビットを反転させてみます。


3

Haskell、152バイト

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

使用法:a (1,1,1,1,0,1,1)どの出力(1,1,1,1)

簡単な解決策:p<x>一致しない場合は<x>、数値にビットを設定します。この数がある場合は356または7、対応するフリップフロッd<y>


コードの呼び出し方法に関するいくつかの指示を追加できますか(たとえば、ideone.comのようなオンラインコンパイラを使用して)。私は常にいくつかの奇妙なエラーを受け取ります(おそらく私のせいです)。
ジャクベ

@Jakube:コードをファイルに保存し、言いhamming.hs、Haskell REPL ghci:にロードしますghci hamming.hsa上記のように関数を呼び出します。私の知っているインタプリタのみオンラインHaskellは(tryhaskell.orgは)いくつかのより多くのコードが必要になりますlet a(p,q, ... 2-y in a (1,1,1,1,0,1,1)
nimi

3

IA-32マシンコード、36バイト

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

同等のCコード:

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は、各中間結果のパリティを自動的に計算します。jpパリティに応じてジャンプする、またはジャンプしない専用の命令があります。

チャレンジでは明示的に指定されませんでしたが、ハミングコードの便利な特性は、パリティビットを2進数として解釈できることです。この数値は、送信中にどのビットが損なわれたかを示します。実際、この数は1から始まり、0は送信エラーがなかったことを意味します。これは、1を左にシフトしerr_pos、次に右に1シフトすることで実装され1ます。

伝送エラーを修正した後、コードは必要な順序でデータビットを配置します。コードはサイズが最適化されており、最初はどのように機能するかが不明な場合があります。それを説明するために、私はで表しabcdデータビット、およびによってPQおよびRパリティビット。次に:

    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

アセンブリソース(fastcall入力、入力、ecx出力の規則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;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.