1.1 Definitionen

Wir betrachten {0,1}n, die Menge aller Bitstrings der Länge n. Darauf ist ein Abstandsmaß definiert, der Hammingabstand:

dH(x,y):=|{i[n] | xiyi}| ,

also die Anzahl der Stellen, an denen x und y sich unterscheiden. Wir wollen Datenpakete der Länge m codieren als Pakete der Länge nm, sodass wir erkennen können, wenn bei der Übertragung Fehler aufgetreten sind, solange weniger als d der n Stellen fehlerhaft sind. Wir bezeichnen hier x{0,1}m als Nachricht oder Urwort und E(x) als das Codewort. Die Länge n der Codewörter heißt Blocklänge des Codes. Formal also wollen wir eine Codierfunktion

E:{0,1}m{0,1}n

so dass sich E(x) und E(y) in mindestens d Stellen unterscheiden:

x,y{0,1}m,xy: dH(E(x),E(y))d.

Wir definieren den Minimalabstand von E als

Δ(E):=minxy{0,1}mdH(E(x),E(y)) .

Üblicherweise wollen wir, dass Δ(E) proportional zur Blocklänge n sind (z.B. weil wir erwarten, dass maximal jedes zehnte Bit korrumpiert wird). Daher betrachten wir δ(E):=Δ(E)/n, den relativen Minimalabstand. Je größer dieser ist, desto besser. Der zweite Parameter eines Codes, der uns interessiert, ist die Rate, die misst, wie viele Nutzbits wir pro gesendetem Bit haben:

R(E):=mn .

Eine Rate R(E)=1/2 beispielsweise würde bedeuten, dass ein Codewort doppelt so lang ist wie ein Urwort. Auch bei R(E) gilt: je größer, desto besser. Üblicherweise sind wir nicht mit einem konkreten E:{0,1}m{0,1}n zufrieden, sondern wollen eine Lösung, die skalierbar ist; die uns erlaubt, beliebig lange Pakete zu codieren. Also eine Familie von Codes E1,E2, mit Em:{0,1}m{0,1}n(m), wobei nun die Blocklänge n(m) von m abhängt. Oft sind wir allerdings schlampig und sprechen nur von einem Code E:{0,1}m{0,1}n statt einer Familie (Em)m1 von Codes.

Ziel. Wir wollen einen Code E:{0,1}m{0,1}n oder besser gesagt eine Familie von Codes Em:{0,1}m{0,1}n(m) mit folgenden Eigenschaften:

  1. δ(Em)δ: der Code soll also einen konstanten Anteil fehlerhafter Bits tolerieren (d.h. erkennen) können;
  2. R(Em)r: die Anzahl der gesendeten Bits (n) sind proportional zur Anzahl der Nutzbits (m);
  3. E soll effizient berechenbar sein, also zum Beispiel in Zeit poly(m).
  4. Wir wollen die Umkehrfunktion E1 effizient berechnen können. Und noch mehr: für ein Wort z{0,1}n wollen wir effizient entscheiden können, ob zimg(E) liegt, ob z also ein Codewort ist und wenn ja, welchem Urwort x es entspricht, also E(x)=z.
  5. Noch mehr: falls es ein Codewort zimg(E) gibt mit dH(z,z)<1/2 (es kann höchstens ein solches geben), dann wollen wir z und das x{0,1}m mit E(x)=z effizient finden können. Wir wollen den Fehler also nicht nur erkennen, sondern auch korrigieren können.

Codes als Teilmenge C{0,1}n

Fürs erste interessieren uns nur die kombinatorischen Eigenschaften (1) und (2) der obigen Liste, also Rate und Abstand eines Codes. In diesem Falle ist es einfacher, die Menge der Codewörter img(E) als Teilmenge C{0,1}n zu betrachten und {0,1}m und E fürs erste zu vergessen. Solange wir uns in diesem kombinatorischen Kontext befinden, ist ein Code einfach das: eine Teilmenge C{0,1}n.

Die Abstand von C ist nun ganz analog definiert als

Δ(C):=min{dH(x,y) | x,yC,xy} .

Wie definieren wir die Rate? Den Wert m gibt es ja nicht mehr. Im obigen Setting, also mit E, gilt C=img(E) und |C|=2m (da E injektiv ist, zumindest solange Δ(E)1 gilt). Daher m=log2|C|, und somit definieren wir die Rate als

R(C):=log2|C|n .

Codes über einem größeren Alphabet

Obwohl auf einem Computer oder bei den meisten Netzwerkprotokollen schlussendlich doch alles binär codiert wird, ist es nützlich, Codes über einem größeren Alphabet zu studieren. Also

E:Σ1mΣ2n .

Hamming-Abstand und Minimalabstand können wie zuvor definiert werden. Allerdings kann man die Rate nun nicht mehr als m/n definieren. Wenn zum Beispiel Σ1={0,1} und Σ2={00,01,10,11} und wir E:Σ12Σ21 via E(x,y)=xy definieren, dann ist Δ(E)=1 und die Rate R(E) wäre m/n=2/1=1. Wir hätten also eine Rate größer als 1, was unsinnig ist. Der Punkt: je größer Σ ist, desto mehr Information trägt ein einzelnes Element daraus, und die Rate sollte das entsprechend reflektieren. Daher:

R(E):=mlog|Σ1|nlog|Σ2| .

Für Σ1=Σ2={0,1} stimmt das mit der vorherigen, obigen Definition überein. Eine andere Sichtweise: solagne E:AB injektiv ist, gilt |img(A)|=|A| und wir definieren die Rate von E als

log2|A|log2|B| ,

also der (logarithmische) Anteil des Wertebereichs, der von E tatsächlich genutzt wird.