# Nussinov-Algorithmus

Der Nussinov-Algorithmus ist ein einfacher Algorithmus zur Berechnung der maximal möglichen Anzahl von Basenpaaren in einer RNA-Sequenz und einer oder mehrerer möglicher Sekundärstrukturen dieser RNA-Sequenz. Wegen seiner einfachen Modell-Annahmen ist seine biologische Bedeutung gering, er wird aber in der Didaktik der Bioinformatik als einfaches Beispiel für dynamische Programmierung verwendet und dient als Ausgangspunkt für komplexere Modelle.

## Algorithmus
### Modell

Der Algorithmus modelliert eine RNA-Sequenz $s$ und die Basenpaare innerhalb dieser Sequenz als einen planaren Graphen, das heißt ohne Pseudoknoten. Zwischen den Basen eines einzigen Basenpaares liegt mindestens eine weitere Base, d. h., die Schleife einer Haarnadelstruktur besteht aus mindestens einer Base.
Gegeben ist die Sequenz $s$ der einzelnen Basen als eine Zeichenkette mit der Länge $n$. Dabei bezeichnet $s[i]$ das Zeichen an der Stelle $i$ und $s[i..j]$ die Teil-Sequenz der Zeichen von der Stelle $i$ bis zur Stelle $j$. Damit ist $s[i..i]$ gleichbedeutend mit $s[i]$ und $s[1..n]$ ist $s$. Weiters sei $s[i..i-1]$ eine leere Zeichenkette der Länge 0.
Die Matrix $N[i,j]$ der Größe $n\times n$ enthält die die Anzahl der maximal möglichen Basenpaare der Teilsequenzen $s[i..j]$ für $i\leq j$ der Sequenz $s$. Das Matrixelement $N[1,n]$ bezeichnet dementsprechend die Anzahl der maximal möglichen Basenpaare für die gesamte Sequenz.
Die Funktion $\sigma (i,j)$ ergibt 1, wenn $s[i]$ und $s[j]$ komplementäre Basen sind, sonst 0.
Pseudoknoten sind im Modell nicht erlaubt, d. h., für zwei Basenpaare $(s[a];s[b])$ und $(s[c];s[d])$ gilt $a<b<c<d$ oder $a>b>c>d$

### Zerlegung in kleinere Teil-Probleme

Die Elemente der Matrix $N$ werden berechnet, indem zuerst angenommen wird, alle Elemente bis auf das Element $N[1,n]$, das die Sequenz $s[1,n]$ beschreibt, seien bekannt. Die Sequenz $s[1,n]$ kann gebildet werden, indem der Sequenz $s[1,n-1]$ die Base $s[n]$ angehängt wird. Diese Base kann nun entweder mit einem anderen Element der Sequenz ein Basenpaar bilden oder nicht:
* Falls kein Basenpaar gebildet wird, so muss $N[1,n]=N[1,n-1]$ sein und das Problem ist gelöst.
* Falls ein Basenpaar gebildet wird, so kann dieses Basenpaar zwischen $s[n]$ und einer der Basen aus der Teil-Sequenz $s[1..n-2]$ gebildet werden. Angenommen, das Basenpaar bildet sich zwischen $s[k]$ und $s[n]$ mit $i\leq k\leq n-2$ so teilt sich die Sequenz in die weiteren Teile $s[1..k-1]$ und $s[k+1..n-1]$. Für diese beiden Teile kann wiederum die Anzahl der maximal möglichen Basenpaare berechnet werden, indem der Algorithmus für diese Teile von Neuem begonnen wird. Die Summe der beiden Teile plus dem zwischen $s[k]$ und $s[n]$ gebildete Basenpaar ergibt einen möglichen Kandidaten-Wert für die Maximale Summe. Der Wert für $N[1,n]$ soll maximal werden, also muss für jedes erlaubte $1\leq k\leq n-2$ die Kandidaten berechnet werden. Der höchste so erreichbare Wert garantiert, dass auch $N[1,n]$ maximal wird. Somit ist
    $N[1,n]=\max {\begin{Bmatrix}\max _{1<k<n-1}(N[1,k-1]+N[k+1,n-1]+1)\cdot \sigma (k,n)&\\N[2,n-1]\cdot \sigma (1,n)&\end{Bmatrix}}$
und das Problem ist ebenfalls gelöst. Der untere Term der Maximalwertsberechnung behandelt den Sonderfall eines Basenpaares zwischen dem ersten und dem letzten Element der Sequenz, wodurch eine der Teilsequenzen leer ist ($s[0,0]$). Beide gelisteten Möglichkeiten werden überprüft und die höhere so erreichbare Anzahl an Basenpaaren ist das Ergebnis der Berechnung.
Der Algorithmus verkleinert die Sequenz auf diese Weise in immer kleinere Teil-Sequenzen, bis diese sofort berechnet werden können. Die Zwischenergebnisse werden dann zur Berechnung der nächstgrößeren Teil-Sequenzen verwendet.

### Initialisierung

Die Teil-Sequenzen $s[i,i+1]$ der Länge 2, $s[i,i]$ der Länge 1 und $s[i,i-1]$ der Länge 0 enthalten maximal 0 Basenpaare:
    $N[i,i+1]=0$ für $1\leq i<n$
    $N[i,i]=0$ für $1\leq i\leq n$
    $N[i,i-1]=0$ für $1<i\leq n$

### Rekursion

Für die weiteren Elemente der Matrix gilt, unter der Voraussetzung, dass $N[i,0]=0$:
    $N[i,j]=\max {\begin{Bmatrix}N[i,j-1]&\\\max _{i\leq k<j-1}(N[i,k-1]+N[k+1,j-1]+1)\cdot \sigma (k,j))&\end{Bmatrix}}$ mit $1\leq i<n,1<j<n,i<j-1$
Das Element $N[i,j]$ der Matrix $N$ ist nach Beendigung des Algorithmus die maximal mögliche Anzahl von Basenpaaren des Substrings $s[i..j]$ von $s$. Also ist die maximal mögliche Anzahl von Basenpaaren der gesamten Eingabesequenz $s$ in $N[1,n-1]$ gespeichert.
Die Fallunterscheidung in der Rekursion unterscheidet zwei Fälle. Entweder wird der Substring $s[i..j-1]$, für den schon die maximal mögliche Anzahl von Basenpaaren schon berechnet wurde, um eine Base erweitert, welche nicht mit einer anderen Base paart. Oder die Base $s[j]$ paart mit einer komplementären Base im Substring $s[i..j-1]$. Im zweiten Fall existieren $k$ mögliche Basen, mit denen $s[j]$ ein Basenpaar bilden könnte. Die Wahl der zu $s[j]$ komplementären Base teilt den Substring $s[i..j-1]$ in zwei Substrings $s[i..k-1]$ und $s[k+1..j-1]$, für die die maximale mögliche Anzahl von Basenpaaren rekursiv berechnet wird. Die Funktion $\sigma (k,j)$ hat den Wert $1$, wenn die Base $s[k]$ komplementär zu $s[j]$ ist, ansonsten $0$.
Die Fallunterscheidung entspricht der kontextfreien Grammatik
    $X=X.\mid X(X)\mid \epsilon$
wobei ein $.$ eine ungepaarte Base bezeichnet und die Klammern Platzhalter für alle möglichen komplementären Basenpaare darstellen. Nach dieser Grammatik können alle Strukturen, über die der Nussinov-Algorithmus optimiert, abgeleitet werden.
Die Sekundärstrukturen, welche die maximalen Basenpaare enthalten, können durch Backtracking von der Zelle $N[0,n-1]$ erzeugt werden. Das heißt, es werden die Pfade durch die Matrix zurückverfolgt, die zu dem optimalen Ergebnis in $N[i,n-1]$ führen und in Abhängigkeit dieser Pfade werden die optimalen Sekundärstrukturen erzeugt.

## Effizienz

Der Algorithmus verwendet eine Matrix mit ${\tfrac {1}{2}}n(n+1)+n-1$ Einträgen, für jeden Eintrag wird über ${\mathcal {O}}(n)$ Elemente optimiert. Der Speicherbedarf liegt also in der Komplexitätsklasse ${\mathcal {O}}(n^{2})$ und die Laufzeit in ${\mathcal {O}}(n^{3})$.

## Abgrenzung

Die obige Spezifikation der Matrix-Rekurrenzen entspricht der Darstellung in Nussinov, 1978. Teilweise bezeichnet neuere Literatur eine Abwandlung dieser Rekurrenzen als Nussinov-Algorithmus (z. B. Durbin, 2006). In Durbin, 2006 besteht die Rekursion aus einer Unterscheidung von 4 Fällen. Diese Variation ändert nicht die Werte der berechneten Matrix $N$, allerdings repräsentieren dann mehrere unterschiedliche Pfade beim Backtracking eine Sekundärstruktur, da die geänderte Fallunterscheidung semantisch mehrdeutig ist.

## Biologische Relevanz

Die Sekundärstruktur, welche die maximale Anzahl von Basenpaaren enthält ist nicht unbedingt die Struktur, die in der Natur (in einer Zelle) auftritt. Ebenso treten in natürlichen RNA-Faltmustern sehr wohl Pseudoknoten auf, die vom Nussinov-Algorithmus von vornherein nicht beachtet werden. In der Praxis wird daher die Sekundärstruktur anders, beispielsweise mit dem Zuker-Algorithmus mit thermodynamischem Modell, vorhergesagt, was zu biologisch sinnvolleren Ergebnissen führt.
Trotzdem ist der Nussinov-Algorithmus von theoretischem Interesse in Forschung und Lehre. Beispielsweise wird in der Algorithmus verwendet, um die Waterman-Byers-Backtracking-Methode zum Backtracking von suboptimalen Strukturen exemplarisch an einer übersichtlichen Matrix-Rekursion zu beschreiben. Die Beschäftigung mit dem Algorithmus ist lehrreich, da er wie andere RNA-Strukturvorhersage-Algorithmen die Methode der dynamischen Programmierung verwendet, aber mit einer Matrix-Rekursion noch relativ einfach verständlich ist.