コンピュータ科学と電気通信において、ハミング符号は線形誤り訂正符号の一種です。ハミング符号は1ビットおよび2ビットの誤りを検出したり、未訂正の誤りを検出せずに1ビットの誤りを訂正したりできます。対照的に、単純なパリティ符号は誤りを訂正できず、奇数ビットの誤りしか検出できません。ハミング符号は完全符号であり、ブロック長と最小距離が3である符号としては最高の訂正率を実現します。 [ 1 ]リチャード・W・ハミングは、パンチカードリーダーによって発生する誤りを自動的に訂正する方法として、1950年にハミング符号を発明しました。ハミングは、自身の最初の論文で、一般的なアイデアを詳しく説明しましたが、特に4ビットのデータに3ビットのパリティを追加するHamming(7,4)符号に焦点を当てました。[ 2 ]
数学的に言えば、ハミング符号はバイナリ線形符号の一種です。2 以上の任意の整数rに対して、ブロック長n = 2 r − 1、メッセージ長k = 2 r − r − 1の符号語が存在します。したがって、ハミング符号のレートはR = k / n = 1 − r / (2 r − 1)であり、これは最小距離が 3 (つまり、任意の符号語から他の任意の符号語へ移行するために必要な最小ビット変更数が 3 ) でブロック長が2 r − 1 の符号で可能な最大値です。ハミング符号のパリティ検査行列は、長さrの非ゼロのすべての列を列挙することによって構築されます。つまり、ハミング符号の双対符号は短縮アダマール符号、別名シンプレックス符号です。パリティ検査行列は、任意の 2 つの列がペアごとに線形独立であるという性質を持ちます。
ハミング符号はデータに追加できる冗長性が限られているため、エラー率が低い場合にのみエラーを検出および訂正できます。これは、ビットエラーが極めてまれでハミング符号が広く使用されているコンピュータメモリ(通常はRAM)の場合に当てはまります。この訂正システムを備えたメモリはECCメモリとして知られています。この文脈では、パリティビットが1つ追加された拡張ハミング符号がよく使用されます。拡張ハミング符号はハミング距離が4となり、デコーダは最大1ビットの1ビットエラーが発生した場合と任意の2ビットエラーが発生した場合を区別できます。この意味で、拡張ハミング符号は単一エラー訂正および二重エラー検出が可能であり、SECDEDと略されます。
ハミング符号の発明者であるリチャード・ハミングは、1940年代後半にベル研究所で、サイクルタイムが数秒の電気機械式リレー式コンピュータであるベル・モデルVの開発に携わっていました。入力は、幅7/8インチ、1行あたり最大6つの穴が開いたパンチ紙テープで行われました。平日は、リレーにエラーが検出されると、機械は停止してランプを点滅させ、オペレーターが問題を修正できるようにしました。営業時間外や週末など、オペレーターがいない時間帯は、機械はそのまま次の作業に進みました。
ハミングは週末も仕事をし、エラーが検出されたためにプログラムを最初からやり直さなければならないことにますます苛立ちを募らせていた。録音されたインタビューの中で、ハミングは「それで私は『くそっ、機械がエラーを検出できるなら、なぜエラーの位置を特定して修正できないんだ?』と言ったんだ」と語っている。[ 3 ]その後数年間、彼はエラー訂正の問題に取り組み、ますます強力なアルゴリズム群を開発した。1950年、彼は現在ハミング符号として知られるものを発表し、それは今日でもECCメモリなどのアプリケーションで使用されている。
ハミング符号以前には、いくつかの単純な誤り検出符号が使用されていたが、同じ容量オーバーヘッドでハミング符号ほど効果的なものはなかった。
パリティは、先行するデータにおける1(値が1のビット位置)の数が偶数か奇数かを示す1ビットを追加します。送信中に奇数個のビットが変更されると、メッセージのパリティが変更され、この時点でエラーを検出できます。ただし、変更されたビットがパリティビット自体である可能性もあります。最も一般的な慣例では、パリティ値が1の場合はデータに奇数個の1が含まれていることを示し、パリティ値が0の場合は偶数個の1が含まれていることを示します。変更されたビット数が偶数の場合、チェックビットは有効となり、エラーは検出されません。
さらに、パリティチェックでは、エラーを検出できたとしても、どのビットにエラーがあったかを特定することはできません。データはすべて破棄し、最初から再送信する必要があります。ノイズの多い伝送媒体では、正常な送信に長い時間がかかるか、あるいは送信が成功しない可能性もあります。しかし、パリティチェックは1ビットしか使用しないため品質は劣りますが、この方法はオーバーヘッドが最も少なくなります。
2/5コードは、正確に3つの0と2つの1からなる5ビットを使用する符号化方式です。0~9の数字を表すのに十分な組み合わせが可能です。この方式では、すべての単一ビットエラー、すべての奇数ビットエラー、および一部の偶数ビットエラー(例えば、両方の1ビットが反転している場合など)を検出できます。ただし、これらのエラーを訂正することはできません。
当時使用されていた別の符号では、データビットが正しく送信されたことを確認するために、各データビットを複数回繰り返していました。たとえば、送信するデータビットが 1 の場合、n = 3 の繰り返し符号では 111 が送信されます。受信した 3 ビットが同一でない場合、送信中にエラーが発生したことになります。チャネルが十分にクリーンであれば、ほとんどの場合、各 3 ビットで変化するのは 1 ビットだけです。したがって、001、010、および 100 はそれぞれ 0 ビットに対応し、110、101、および 011 は 1 ビットに対応します。同じ数字 ('0' または '1') の数が多いほど、データビットが何であるべきかがわかります。エラーが存在する場合に元のメッセージを復元できるこの能力を持つ符号は、誤り訂正符号として知られています。この 3 ビット繰り返し符号は、パリティビットが 2 個あり、データビットが2 2 − 2 − 1 = 1 個であるため、m = 2のハミング符号です。
しかし、このような符号では、すべてのエラーを正しく修復できるわけではありません。この例では、チャネルが2ビット反転して受信側が001を受信した場合、システムはエラーを検出しますが、元のビットが0であると結論付けてしまい、これは誤りです。ビット列のサイズを4に増やすと、すべての2ビットエラーを検出できますが、訂正することはできません(パリティビットの数が偶数であるため)。5ビットにすると、すべての2ビットエラーを検出および訂正できますが、すべての3ビットエラーを検出および訂正することはできません。
さらに、パリティビット列のサイズを大きくすることは非効率的であり、元のケースではスループットが3分の1に低下し、より多くのエラーを検出および訂正するために各ビットを複製する回数を増やすと、効率が著しく低下します。
メッセージに誤り訂正ビットをさらに追加し、それらのビットを、異なる誤りビットが異なるエラー結果を生み出すように配置できれば、不良ビットを特定できる。7ビットのメッセージでは、7種類の単一ビットエラーが発生する可能性があるため、3つのエラー制御ビットによって、エラーが発生したことだけでなく、どのビットがエラーの原因となったかを特定できる可能性がある。
ハミングは、2/5を含む既存の符号化方式を研究し、その概念を一般化した。まず、彼はブロック内のデータビット数と誤り訂正ビット数など、システムを記述するための命名法を開発した。例えば、パリティは任意のデータワードに1ビットを割り当てるため、 ASCIIワードが7ビットであると仮定すると、ハミングはこれを(8,7)コードと表現し、合計8ビットのうち7ビットがデータであるとした。同じ論理に従うと、繰り返しの例は(3,1)となる。符号化率は、2番目の数値を最初の数値で割った値であり、繰り返しの例では1/3となる。
ハミングは、2 ビット以上反転することによる問題にも気付き、これを「距離」と表現しました (現在では、彼の名にちなんでハミング距離と呼ばれています)。パリティの距離は 2 なので、1 ビット反転は検出できますが訂正できず、2 ビット反転は見えません。(3,1) 繰り返しの距離は 3 です。これは、目に見えるエラーのない別のコードワードを得るために、同じ 3 つのビットを反転する必要があるためです。1 ビットエラーを訂正することも、2 ビットエラーを検出できますが訂正することはできません。(4,1) 繰り返し (各ビットが 4 回繰り返される) の距離は 4 なので、3 ビット反転は検出できますが訂正できません。同じグループで 3 ビットが反転すると、訂正しようとすると間違ったコードワードが生成される場合があります。一般に、距離kのコードは、 k − 1 個のエラーを検出できますが訂正できません。
ハミングは、距離をできるだけ長くすることと、同時に符号化率をできるだけ高くすることという、二つの課題に同時に取り組んでいた。1940年代には、既存の符号を劇的に改善したいくつかの符号化方式を開発した。彼のすべてのシステムの鍵は、パリティビットが重なり合うようにすることで、データだけでなくパリティビット同士もチェックできるようにすることだった。
以下の一般的なアルゴリズムは、任意のビット数に対して単一誤り訂正(SEC)コードを生成します。基本的な考え方は、インデックスXOR( 1を含むすべてのビット位置のXOR)が0になるように誤り訂正ビットを選択することです。ここでは、位置1、10、100など(バイナリ)を誤り訂正ビットとして使用します。これにより、メッセージ全体のインデックスXORが0になるように誤り訂正ビットを設定できることが保証されます。受信側がインデックスXORが0の文字列を受信すれば、破損はなかったと判断できます。そうでない場合は、インデックスXORが破損したビットのインデックスを示します。
以下の記述からアルゴリズムを導き出すことができる。
エンコードするデータバイトが10011010の場合、データワード(パリティビットを表すためにアンダースコアを使用)は__1_001_1010となり、コードワードは011100101010となります。
パリティが偶数か奇数かは重要ではないが、エンコードとデコードの両方で同じ選択をしなければならない。
この一般的なルールは、視覚的に示すことができる。
図には符号化されたビットのうち20ビット(パリティビット5ビット、データビット15ビット)のみが表示されていますが、このパターンは無限に続きます。ハミング符号の重要な点は、視覚的に確認すると、任意のビットが固有のパリティビットのセットに含まれているということです。エラーをチェックするには、すべてのパリティビットをチェックします。エラーパターンはエラーシンドロームと呼ばれ、エラーのあるビットを特定します。すべてのパリティビットが正しければ、エラーはありません。そうでない場合は、エラーのあるパリティビットの位置の合計によって、エラーのあるビットが特定されます。たとえば、位置1、2、8のパリティビットがエラーを示している場合、ビット1+2+8=11がエラーです。1つのパリティビットのみがエラーを示している場合は、そのパリティビット自体がエラーです。
mビットのパリティでは、1 からカバーできます。パリティビットを割り引いた後、ビットはデータとして使用するために残ります。mが変化するにつれて、考えられるすべてのハミング符号が得られます。
ハミング符号の最小距離は3であり、これは復号器が単一ビットの誤りを検出して訂正できるものの、ある符号語の2ビット誤りと別の符号語の1ビット誤りを区別できないことを意味します。したがって、訂正を試みない限り、一部の2ビット誤りは1ビット誤りであるかのように誤って復号され、検出されないままになります。
この欠点を解消するために、ハミング符号にパリティビットを追加することで拡張できます。こうすることで、ハミング符号の最小距離を4に増やすことができ、デコーダは1ビットエラーと2ビットエラーを区別できるようになります。したがって、デコーダは1ビットエラーを検出して訂正できると同時に、2ビットエラーも検出(ただし訂正はしない)できます。デコーダがエラー訂正を試みない場合、3ビットエラーを確実に検出できます。デコーダがエラーを訂正する場合、一部の3ビットエラーが1ビットエラーと誤認され、誤った値に「訂正」されてしまいます。したがって、エラー訂正は、確実性(3ビットエラーを確実に検出できる能力)と回復力(1ビットエラーが発生しても動作を継続できる能力)のトレードオフとなります。
kビットのデータの場合、SECDED方式では以下が必要となります。
この拡張ハミング符号は、1961年のIBM 7030 Stretch [4]を皮切りに、コンピュータのメモリシステムで広く使われており、SECDED(またはSEC-DED、単誤り訂正、二重誤り検出の略)として知られています[ 5 ]。メモリシステムの一般的な形式には、(39,32)と(72,64)があります。(符号語長を2m -1の形式で使用する方が効率的ですが、既存のコンピュータのデータワードサイズが2のべき乗であるため、この選択はできません。ただし、通信システムやデータストレージシステムではこの利点が活かされています。) 21世紀のサーバーコンピュータは、通常SECDEDレベルの保護を維持していますが、ハミングの方法を使用せず、代わりに長い符号語(128~256ビットのデータ)と修正されたバランス型パリティチェックツリーを使用した設計に依存しています[ 4 ] 。(72,64)ハミング符号は、 Xilinx FPGAファミリを含む一部のハードウェア設計で今でも広く使われています[ 4 ] 。

1950年、ハミングは[7,4]ハミング符号を発表しました。これは、4ビットのデータに3ビットのパリティビットを追加することで、7ビットに符号化します。前述のように、1ビットエラーを検出して訂正することも、1ビットエラーと2ビットエラーの両方を検出(ただし訂正はしない)することも可能です。
全体的なパリティビットを追加すると、[8,4]拡張ハミング符号となり、1ビットエラーの検出と訂正、および2ビットエラーの検出(ただし訂正は不可)が可能になります。
マトリックス :={\begin{pmatrix}{\begin{array}{c|c}I_{k}&-A^{\text{T}}\\\end{array}}\end{pmatrix}}} は、 線形 ( n , k ) コードの (正準) 生成行列と呼ばれます。
そして :={\begin{pmatrix}{\begin{array}{c|c}A&I_{nk}\\\end{array}}\end{pmatrix}}} は パリティチェック行列と呼ばれます。
これは、標準形式(または系統形式)でのGとHの構成です。形式に関係なく、線形ブロック符号のGとH は以下を満たす必要があります。
、すべてゼロの行列。[ 6 ]
[7, 4, 3] = [ n , k , d ] = [2 m − 1, 2 m − 1 − m , 3]であるため、ハミング符号のパリティ検査行列Hは、ペアごとに独立な長さmのすべての列をリストすることによって構築されます。
したがって、Hは、左辺がすべての非ゼロのn組であり、行列の列におけるn組の順序は関係ない行列です。右辺は ( n − k )単位行列です。
したがって、G は、Hの左辺の転置行列と、 Gの左辺のk次元単位行列とを組み合わせることによってHから得ることができます。
コードジェネレーターマトリックスパリティチェックマトリックスは:
:={\begin{pmatrix}1&0&0&0&1&1&0\\0&1&0&0&1&0&1\\0&0&1&0&0&1&1\\0&0&0&1&1&1&1\end{pmatrix}}_{4,7}}
そして
:={\begin{pmatrix}1&1&0&1&1&0&0\\1&0&1&1&0&1&0\\0&1&1&1&0&0&1\end{pmatrix}}_{3,7}.}
最後に、これらの行列は、次の操作によって同等の非系統的コードに変換できます。[ 6 ]
上記の行列から、2 k = 2 4 = 16 個の符号語が得られます。バイナリデータビットの行ベクトルである。合言葉16個のデータベクトルのいずれに対しても標準行列積によって与えられるここで、加算演算は法2で行われます。
例えば、生成行列を使用する上記より、(合計にモジュロ2を適用した後)、

[7,4] ハミング符号は、(7,4) 符号化ワードの上にパリティビットを追加することで、[8,4] 符号に容易に拡張できます ( Hamming(7,4)を参照)。これは、改訂された行列で要約できます。
そして
Hは標準形式ではないことに注意してください。Gを得るには、基本行操作を使用して、Hと同等の系統形式の行列を得ることができます。
例えば、この行列の最初の行は、非系統形式のHの2行目と3行目の合計です。上記のハミング符号の系統的な構成を使用すると、行列Aは明らかであり、Gの系統形式は次のように記述されます。
Gの非体系的な形式は、(基本行操作を用いて)行簡約化することで、この行列に一致させることができる。
4行目を追加することで、実質的にすべてのコードワードビット(データとパリティ)の合計が4番目のパリティビットとして計算されます。
例えば、1011は (このセクションの冒頭で説明した G の非系統形式を使用して) 01 1 0 011 0にエンコードされます。ここで、青色の数字はデータ、赤色の数字は [7,4] ハミング符号のパリティ ビット、緑色の数字は [8,4] 符号によって追加されたパリティ ビットです。緑色の数字によって [7,4] 符号語のパリティが偶数になります。
最後に、最小距離が[7,4]符号の3から[8,4]符号の4に増加したことが示せる。したがって、この符号は[8,4]ハミング符号と定義できる。
[8,4] ハミング符号を復号するには、まずパリティビットを確認します。パリティビットがエラーを示している場合、単一誤り訂正([7,4] ハミング符号)によってエラー位置が示され、「エラーなし」の場合はパリティビットが示されます。パリティビットが正しい場合、単一誤り訂正によって2つのエラー位置の(ビットごとの)排他的論理和が示されます。位置が等しい場合(「エラーなし」)、2ビットエラーは発生していないか、または相殺されています。それ以外の場合は、2ビットエラーが発生しています。