24. Störungssichere Übertragung
Contents
Nachdem wir letztes Mal über fälschungssichere Übertragung und Kryptographie gesprochen haben, wollen wir heute über störungssichere Übertragung sprechen.
1. Bilder von den Voyager-Sonden
Zunächst sollten wir klären, wo man das einsetzen kann. Also die Voyager-Sonden wurden vor 75 Jahren in Richtung Neptun und jenseits des Sonnensystems losgeschickt, um Erkundungen des Weltraums auch dort zu ermöglichen. Zum einen hatten die Sonden ein paar Aufzeichnungen von der Menschheit auf der Erde (in den 1970ern) mit und zum anderen sind Kameras und starke Sendeanlagen in den Sonden eingebaut. Mithilfe von Solarkollektoren und radionukleid-Batterien erhalten die Sonden Strom, um Signale zu Erde zurück zu senden. Das Problem ist aber, dass aufgrund der großen Entfernungen und auch aufgrund von Sonnenstürmen, diese Signale meist nicht fehlerfrei auf der Erde ankommen.
Wenn man sich an das Rauschen von UKW- und Mittelwellenradio erinnert, dann kann das selbst für die Kommunikation innerhalb eines Kontinents ein Problem werden. Eine Verbesserung wurde bereits mit digitalen Signalen erreicht, d.h. hier ist nicht mehr die Frage, ob das Signal, welches um Größenordnungen geringer ist und von Rauschen übertönt, nun halb- oder viertel so groß ist, sondern lediglich, ob die ankommende Schwingung 0 oder 1 codiert. Dadurch kann man auch bei mittelschlechtem Signal-Rausch-Verhältnis die Informationen noch gut entnehmen. Was aber, wenn selbst das digitale Signal durch Rauschen verfälfscht wird?
Eine vergleichbare Situation liegt bei der Langzeitspeicherung von Computerdaten vor. Früher wurden die auf Magnetbänder gespeichert, die ebenfalls eine Folge von 0en und 1en kodierten. Zwischendurch verwendete man magnetische Festplatten, heute werden flash-ROMs verwendet. Gemeinsam ist, dass eine Folge von 0en und 1en gespeichtert ist und man zum einen verifizieren sollte, dass die nicht gestört wurde, also Rauschen enthalten ist, und zum anderen, falls Rauschen enthalten ist, schauen, ob und wie man das Original-Signal rekonstruieren kann.
2. Eine Einfache Idee
Wenn man nicht sicher ist, ob ein Signal 100% fehlerfrei übertragen wird, dann kann man das gleiche Signal einfach 2-mal übertragen und anschließend vergleichen, ob das Ergebnis übereinstimmt. Leider verdoppelt man damit die Länge der übertragenen Nachricht.
Wenn man außerdem im Falle leichter Fehler auch noch das korrekte Signal wiedergewinnen will, kann man das ursprüngliche Signal 3-mal übertragen und dann schauen, ob 1) alle 3 Versionen gleich sind (nur dann wurde vollkommen fehlerfrei übertragen) und 2) bei 1 abweichenden Versionen das Mehrheitssignal verwenden. Das ganze gibt natürlich nur Sinn, wenn man digitale Signale verwendet, da bei Analogen Signalen warscheinlich 3 verschiedene Versionen ankommen werden und den Mittelwert zu bilden, die Fehler nur auf ca. $1/\sqrt3$ reduziert. Leider hat man hierfür das Signal 3-mal so lang gemacht, was für Sonden mit geringer verfügbarer Energie ein Problem sein kann.
Bleibt die Frage, ob man das auch effizienter hinbekommt.
3. Reed-Solomon-Kodierung
Hierzu hatten I.S. Reed und G. Solomon eine zündende Idee aus dem Bereich der Algebra. Das Grundprinzip ist zunächst, dass man nicht einzelne bits/Bytes oder ganze Zahlen verschlüsselt, sondern gleich Gruppen von $d+1$ Zahlen. Wenn jetzt $d=5$ und wir statt 6 Zahlen, 8 Zahlen übermitteln, dann ist das Signal nur um 30% länger geworden, aber mit dem richtigen Verfahren kann man sowohl auf Übertragungsfehler testen als auch einfache Fehler korrigieren.
Bild 1: Interpolation, Polynom, das durch Stützpunkte geht.
Das Prinzip ist folgendes: Man kann die $d+1$ Zahlen als die Koeffizienten eines Polynoms (in 1 Variable) vom Grad $d$ schreiben. Aber wie kann man dieses Polynom übertragen? Dazu überlegt man sich, dass ein Polynom $y=p(x)= a_0+a_1x+a_2x^2+\dotsm+a_dx^d$ durch $d+1$ Punkte in der Ebene eindeutig bestimmt ist. Dabei müssen nur die $x$-Koordinaten der Punkte verschieden sein. Wenn man statt $d+1$ Punkten sogar $d+2$ Punkte verwendet, hat man 1 zusätzliche Gleichung zur Kontrolle. Wenn man schließlich $d+3$ Punkte verwendet, kann man probieren, ob davon $d+2$ Punkte auf einem Polynom vom Grad $d$ liegen. Dieses ist dann das richtige Polynom und falls genau 1 Punkt vom Polynom abweicht, weiß man dass wahrscheinlich nur 1 Übertragungsfehler vorkam.
Also was muss man jetzt übertragen?
Wir einigen uns zunächst auf $d+3$ Stützstellen, also die $x$-Werte der Punkte. Dann übertragen wir die Werte $y_k:=p(x_k)$ für diese $0\le k\le d+2$ Stützstellen, also $d+3$ Werte um $d+1$ Koeffizienten zu verschlüsseln.
3.1 Wie sieht das in einem Algorithmus aus?
Dazu nimmt man einfach die Stützstellen $0, 1, -1, 2, -2, 3, -3, \dots$ und bildet das lineare Gleichungssystem:
$$\begin{array}{ccccc} a_0 &+0a_1 &+0a_2 &+\dots &+0a_d &= y_0 \\ a_0 &+1a_1 &+1a_2 &+\dots &+1a_d &= y_1 \\ a_0 &-1a_1 &+1a_2 &-+\dots &+(-1)^da_d &= y_{-1} \\ \dots \\ a_0 &\pm ka_1 &+k^2a_2 &-+\dots &+(\mp k)^da_d &= y_{\mp k} \end{array}$$
Um zu sehen, dass dieses Gleichungssystem immer eine eindeutige Lösung hat, kann man zeigen, dass die Koeffizientenmatrix $$ \left(\begin{array}{ccccc} 1 & x_0 & x_0^2 & \dots & x_0^d \\ 1 & x_1 & x_1^2 & \dots & x_1^d \\ 1 & x_2 & x_2^2 & \dots & x_2^d \\ \vdots \\ 1 & x_d & x_d^2 & \dots & x_d^d \end{array}\right) $$ invertierbar ist, z.B. indem man zeigt, dass die Determinante $\prod_{i<j} (x_j-x_i)\ne0$ ist, solange die Stützstellen verschieden sind.
Wenn du wissen willst, wie man ein solches Gleichungssystem löst, solltest du dich an den Unterricht der 11./12. Klasse halten. Prinzipiell gibt es verschiedene Verfahren, besonders, wenn man nicht zu viele unbekannte Koeffizienten hat. Man kann mit den leichteren Gleichungen anfangen, z.B. $a_0=y_0$ und dieses Ergebnis in die anderen Gleichungen einsetzen, um dann weiter $a_1, a_2, \dots$ zu bestimmen. Oder man kann geeignete Vielfache einer Gleichung von den anderen abziehen, sodass man nur noch $d$ Gleichungen mit $d$ Unbekannten hat und dann entsprechend weiter verfahren. Oder man kann auch 2 Gleichungen nach 1 Variablen auflösen und die Terme gleichsetzen.
Ein systematischer Weg ist das Gauss-Verfahren. Man schreibt die Koeffizienten der $d+1$ Gleichungen und ihre rechten Seiten in eine Matrix und macht dann Zeilenumformungen nach folgendem Schema:
-
Zeilen vertauschen – dabei ändert sich zwar die Reihenfolge der Gleichungen, nicht aber die Lösung für die Koeffizienten,
-
eine Zeile mit eine Zahl ungleich 0 multiplizieren – dabei ändert sich zwar diese Zeile, aber nicht die Lösung (man könnte ja die Zeile wieder durch diese Zahl dividieren),
-
Das Vielfache einer Zeile zu einer anderen Zeile addieren (Gauss Eliminierung) – wenn die 2 Gleichungen vorher gegolten haben, dann gelten die 2 Gleichungen jetzt immer noch.
Die Frage ist noch, wie man das systematisch macht, damit man die Lösungen am Ende ablesen kann:
Zunächst tauschen wir die Zeile mit dem betragsgrößten Koeffizienten von $a_0$ nach oben und dividieren diese Zeile durch diesen Koeffizienten. Dadurch erreichen wir, dass die 1. Zeile mit $1$ beginnt. Jetzt multiplizieren wir diese 1. Zeile der Reihe nach mit den restlichen Koeffizienten von $a_0$ und ziehen sie von der entsprechdenen Zeile ab. Dadurch erreichen wir folgende Struktur:
$$\left(\begin{array}{cccc|c} 1 & * & * & \dots & * \\ 0 & * & * & \dots & * \\ 0 & * & * & \dots & * \\ \vdots \\ 0 & * & * & \dots & * \end{array}\right)$$
Warum ist das besser?
Weil wir in den Zeilen $2\dots d+1$ jetzt nur noch $d$ Variablen haben und wenn wir diese kennen, aus der 1. Zeile $a_0$ berechnen können.
Jetzt verfahren wir mit den Zeilen $2\dots d+1$ ab der Spalte 2 entsprechend und erreichen:
$$\left(\begin{array}{ccccc|c} 1 & * & * & * & \dots & * \\ 0 & 1 & * & * & \dots & * \\ 0 & 0 & * & * & \dots & * \\ \vdots&*& & & \dots & * \\ 0 & 0 & * & * & \dots & * \end{array}\right) $$
Entsprechend verfahren wir mit den Zeilen $3\dots d+1$ ab Spalte $3$ und so weiter, bis wir die Matrix auf obere Dreiecksgestalt gebracht haben:
$$\left(\begin{array}{ccccc|c} 1 & * & * & * & \dots & * \\ 0 & 1 & * & * & \dots & * \\ 0 & 0 & 1 & * & \dots & * \\ \vdots&& & \ddots & \dots & * \\ 0 & \dots&& & 1 & * \end{array}\right) $$
Jetzt kann man aus der unteren Zeile den Koeffizient $a_d= * $ ablesen. Entsprechend kann man diese Koeffizienten rückwärts von den restlichen Gleichungen abziehen, also die letzte Zeile mit den Koeffizienten der letzten Spalte (vor dem $|$) multiplizieren und von der jeweiligen Zeile abziehen. Nacheinander erhält man dabei die Schritte:
$$\left(\begin{array}{ccccccc|c} 1 & * & * & & \dots && 0 & * \\ 0 & 1 & * & & \dots && 0 & * \\ \vdots& &\ddots&*&\dots& * & 0 & * \\ 0 & \dots & & & & 0 & 1 & * \end{array}\right) $$
$$\left(\begin{array}{ccccccc|c} 1 & * & * & & \dots&0& 0 & * \\ 0 & 1 & * & & \dots&0& 0 & * \\ \vdots& &\ddots&*&\dots& 1 & 0 & * \\ 0 & \dots & & & & 0 & 1 & * \end{array}\right) $$
$$\left(\begin{array}{cccc|c} 1 & 0 & \dots & 0 & * \\ 0 & 1 & 0 & \vdots & * \\ \vdots& &\ddots& 0 & * \\ 0 & \dots & 0 & 1 & * \end{array}\right) $$
Schließlich kann man aus der Diagonalform der Koeffizientenmatrix die Lösung $a_0, a_1, \ldots, a_d$ ablesen.
Wenn man zusätzliche Punkte hat, kann man der Matrix weitere Zeilen anfügen. Dadurch wird die Diagonale natürlich nicht länger, stattdessen erhält man weitere Zeilen, deren sämtliche Koeffizienten sich auf 0 reduzieren lassen. Wenn für die auch die rechten Seiten (hinter dem $|$) 0 sind, dann ist das konsistent. Wenn allerdings in einer der 2 zusätzlichen Zeilen die rechte Seite nicht 0 ist, dann ist das ein Übertragungsfehler. Wenn es nur 1 ist, dann hat man die konsistenten Zeilen gefunden und die (wahrscheinlich) richtigen Koeffizienten $a_0, a_1, \ldots, a_d$ bestimmt. Wenn mehr als 1 Zeile inkonsistent ist, dann hat man eine falsche Zeile verwendet und muss noch einmal von vorn beginnen. Jetzt bleibt nur hartnäckiges Probieren, man muss jeweils 1 der oberen Zeilen weglassen und schauen, ob das restliche System sich konsistent lösen lässt. Wenn man eine solche Kombination gefunden hat, dann hat man die Übertragung noch entschlüsselt.
In einem Kotlin-Programm sieht das wie folgt aus: Zunächst sollten wir Matritzen definieren:
|
|
Dann sollten wir den Lösungsansatz hinschreiben:
|
|
Die Funktion decode
nimmt d+3
Stützstellen (die xs
) entgegen sowie $k * (d+3)$ übertragene Werte (die ys
). Aus denen berechnet sie die Originalwerte eine $k * (d+1)$ Matrix. Da nicht sicher ist, dass man alle Koeffizienten decodieren kann, gibt die Funktion zusätzlich noch die Liste mit den erfolgreich dekodierten Spalten zurück (ein true
in den Spalten, die erfolgreich dekodiert wurden).
Dann brauchen wir noch die 2 Schritte beim Lösen des Gleichungssystems:
|
|
Die Funktion gaussEliminate
hat einen zusätzlichen Parameter limit :Boolean
der angibt, ob ein möglicherweise überbestimmtes Gleichungssystem so stabil wie möglich gelöst werden soll (limit=false
, d.h. auf alle Zeilen zurückgreifen) oder ob wir zur Eliminierung nur die ersten d
Zeilen einsetzen wollen. Wir brauchen das letztere (limit=true
), weil wir ja wissen wollen, ob das System aus den ersten d+1
Zeilen lösbar ist und maximal 1 Widerspruch ergibt (in den 2 Kontrollzeilen).
Um das Ganze zu testen, können wir einfache Textnachrichten verschlüsseln:
|
|
Und schließlich brauchen wir noch die Kodiervorschrift:
|
|
3.2 Funktioniert das auch?
Du solltest vielleicht das obige Programm mit einem einfachen Text probieren. Die NASA (Weltraumbehörde der USA) hat dazu einen Prototypen geschrieben, der ein Bild kodiert, dann mit Rauschen kopiert und das “Übertragene” wieder dekodiert.
Bild 2: Als Beleg, dass ihr Algorithmus tatsächlich Bilder vor Rauschen schützen kann, hat die NASA das berühmte Bild der Mona-Lisa mit Rauschen wie auf 200AE Wegstrecke simuliert einmal direkt übertragen und einmal mit dem Reed-Solomon Code (rechts). © 2021 Sun Xiaoli, NASA.
Man kann jetzt natürlich behaupten, dass man auch im linken Bild noch die Frau erkennen kann, aber leider sind die Bilder von fernen Planeten nicht so leicht zu entziffern. Aufgrund der extrem ungleichmäßigen Beleuchtung kann es große Kontraste und scharfe Hell-Dunkel-Kanten geben und erst wenn das gesamte Bild nahezu fehlerfrei entschlüsselt ist, kann man versuchen, das aufgenommene zu verstehen.
PS: Es gibt natürlich auch noch weitere Anwendungen: Neben den Laser-Disks (CD, DVD, BD) auch das Digitalradio (DAB) sowie Digitalfernsehen.
Weiterführende Literatur
[1] Wikipedia: wiki > Reed-Solomon-Code.
[2] J. Cepelewicz: How Mathematical Curves Power Cryptography, Quantamagazine 2022.
[3] S.B. Wicker, V.K. Bhargava: Reed Solomon Codes Applications, Wiley, 1999, ISBN 0-7803-5391-9.