341 lines
9.8 KiB
Markdown
341 lines
9.8 KiB
Markdown
## 1. Dynamische Datenstrukturen
|
||
### Linked-List
|
||
$$self.address: A[i] $$
|
||
|
||
$$\longleftarrow prev.address \ | \ next.address\longrightarrow$$
|
||
### Stack
|
||
First-In; Last-Out
|
||
Add: "Push"
|
||
Remove: "Pop"
|
||
|
||
### Queue
|
||
First-In; First-Out
|
||
Add: "Enqueue"
|
||
Remove: "Dequeue"
|
||
### Binary-Tree
|
||
$$self.address : Value$$
|
||
$$\leftarrow left.address : \rightarrow right.address$$
|
||
|
||
### Graphen
|
||
#### Adjazenzmatrix
|
||
|
||
Von *Zeile* nach *Spalte* lesen. Wert vom Element ist das Gewicht dieser Verbindung, wenn alle $Gewichte = 1$, dann ungewichtet.
|
||
Wenn Symmetrische Matrix, dann Ungerichtet.
|
||
|
||
$$
|
||
\newcommand\T{\rlap{\text{to}}}
|
||
\begin{array}{cc}
|
||
& \T \\
|
||
\text{from} &
|
||
\begin{array}{c|cccc}
|
||
& v_0 & v_1 & v_2 & v_3 \\
|
||
\hline
|
||
v_0 & 0 & 1 & 1 & 0 \\
|
||
v_1 & 0 & 0 & 0 & 0 \\
|
||
v_2 & 0 & 1 & 0 & 0 \\
|
||
v_3 & 0 & 0 & 1 & 1 \\
|
||
\end{array}
|
||
\end{array}
|
||
$$
|
||
#### Adjazenzliste
|
||
Der **Header-Knoten**, geht zu allen Knoten in der Spalte.
|
||
$$
|
||
\begin{array}
|
||
& 1 & 2 & 3 & 4 \\
|
||
\hline
|
||
2 & 3 & 2 & 1 \\
|
||
4 \\
|
||
\end{array}
|
||
$$
|
||
|
||
## 2. Skipliste, Binary-Search-Tree, Shellsort
|
||
|
||
### Skipliste
|
||
|
||
$$
|
||
\begin{array}{l}
|
||
\text{Layer 2:} \quad H \rightarrow \phantom{E_1 \rightarrow E_2 \rightarrow} E_3 \rightarrow \phantom{E_4 \rightarrow E_5 \rightarrow} \text{NIL} \\
|
||
\\
|
||
\text{Layer 1:} \quad H \rightarrow E_1 \rightarrow \phantom{E_2 \rightarrow} E_3 \rightarrow \phantom{E_4 \rightarrow} E_5 \rightarrow \text{NIL} \\
|
||
\\
|
||
\text{Layer 0:} \quad H \rightarrow E_1 \rightarrow E_2 \rightarrow E_3 \rightarrow E_4 \rightarrow E_5 \rightarrow \text{NIL}
|
||
\end{array}
|
||
$$
|
||
### Binary Search Tree
|
||
>Linker Teilbaum *kleiner*, rechter Teilbaum *größer*
|
||
|
||
$$Tiefe = Max(\text{Anzahl Kanten nach unten})$$
|
||
|
||
**Suchen**
|
||
Richtung? -> Vergleich von beiden Kinder knoten
|
||
|
||
**Einfügen**
|
||
Gleich wie suchen
|
||
|
||
**Löschen**
|
||
Pointer umsetzen
|
||
|
||
### Shellsort
|
||
#### Insertionsort
|
||
**Schritt-für-Schritt:**
|
||
|
||
1. Beginne mit dem zweiten Element (Index 1) im Array. Das erste Element gilt als bereits sortiert.
|
||
2. Vergleiche das aktuelle Element mit den vorherigen Elementen.
|
||
3. Wenn das aktuelle Element kleiner als das verglichene Element ist, verschiebe das verglichene Element um eine Position nach rechts.
|
||
4. Wiederhole Schritt 3, bis du die richtige Position für das aktuelle Element gefunden hast.
|
||
5. Füge das aktuelle Element an der richtigen Stelle ein.
|
||
6. Gehe zum nächsten Element und wiederhole die Schritte 2–5, bis das Array sortiert ist.
|
||
|
||
**Beispiel:**
|
||
|
||
Angenommen, du hast das Array: [5, 2, 9, 1]
|
||
|
||
- Beginne mit 2 (Index 1). Vergleiche mit 5. Da 2 < 5, verschiebe 5 nach rechts und setze 2 an Index 0. Jetzt: [2, 5, 9, 1]
|
||
- Als Nächstes 9 (Index 2). Vergleiche mit 5. 9 > 5, also bleibt alles wie es ist.
|
||
- Als Nächstes 1 (Index 3). Vergleiche mit 9, 5 und 2. 1 < 9, 1 < 5, 1 < 2. Verschiebe alle drei nach rechts und setze 1 an Index 0. Jetzt: [1, 2, 5, 9]
|
||
|
||
#### Shellsort
|
||
##### Schrittweite
|
||
Wahrscheinlich in der Aufgabe gegeben, ansonsten die hier nehmen:
|
||
$$s_i = 2^i -1$$
|
||
|
||
- Mit Schrittweite in Sub-Arrays zerlegen.
|
||
- Diese Schritt-Arrays mit Insertionsort sortieren.
|
||
- Bei Schrittweite 1 Durchlauf endet die Sortierung.
|
||
|
||
## 3. Heaps und Heapsort
|
||
Ein heap ist ein binary tree, bei dem alle Elternknoten bei einem Max-Heap, größer Werden respektiv bei einem Min-Heap kleiner
|
||
|
||
Min-Heap = Oben das kleinste
|
||
Max-Heap = Oben das größte
|
||
|
||
Tiefe:
|
||
$$floor(\log_2(n))+1$$
|
||
|
||
Index von Kindern und Parent:
|
||
$$
|
||
\text{Children}:
|
||
\begin{cases}
|
||
2i & \text{Child 1} \\
|
||
|
||
2i+1 & \text{Child 2 }
|
||
\end{cases}
|
||
$$
|
||
$$Parent: floor\left(\frac{2i}{2}\right)$$
|
||
|
||
### Max/Min-Heap-Reparieren:
|
||
Man iteriert durch alle Elemente, außer die Blätter.
|
||
Folgendes Schema:
|
||
>**Breadth-First**: Man startet dem Letzten Element (Visuell unten rechts), das **Kinder** hat. Dann nach Links bis ende der Ebene und dann nach oben.
|
||
|
||
Das ist nur das Iterieren! Noch Reparieren!
|
||
```python
|
||
for e in Elements:
|
||
...
|
||
```
|
||
|
||
Schicht 1 $\longleftarrow\longleftarrow Root \longleftarrow \longleftarrow\Lsh$
|
||
Schicht 2 $\longleftarrow\longleftarrow e_1 \longleftarrow e_2 \longleftarrow\Lsh$
|
||
Schicht 3 $\leftarrow e_3 \leftarrow e_4 \leftarrow e_5 \leftarrow e_6 \leftarrow \text{START}$
|
||
...
|
||
Blätter ..................................................
|
||
|
||
Jedes Element das man anschaut wird dann *down-geshifted*. Im grunde Rekursives Max/Min im Dreieck.
|
||
1. Man vergleicht aktuelles Element mit den Kindern. (Wie so ein Dreieck)
|
||
```tikz
|
||
\begin{document}
|
||
\begin{tikzpicture}[level distance=1.5cm,
|
||
level 1/.style={sibling distance=3cm},
|
||
level 2/.style={sibling distance=1.5cm}]
|
||
\node {element}
|
||
child {node {child 1}}
|
||
child {node {child 2}};
|
||
\end{tikzpicture}
|
||
\end{document}
|
||
```
|
||
|
||
2. (Abbruchbedingung), Gehe zum nächsten Element ...
|
||
1. Max-Heap: Wenn $element$ das **größte** von den drei ist, i.e. $max([e, c1, c2]) = e$
|
||
2. Min-Heap: Wenn $element$ das **kleinste** von den drei ist, i.e. $min([e, c1, c2]) = e$
|
||
3. Wenn nicht, dann *tausche* mit dem größten (Max-Heap) / kleinsten (Min-Heap) der drei.
|
||
4. Wiederhole, bis Abbruchbedingung erreicht, oder am ende vom Baum, bzw. ganz unten.
|
||
|
||
#### Heap-Sort
|
||
0. (Vorrausgesetzt ist ein Valider-Heap)
|
||
1. Unten Rechts (Letztes Element im Heap-Array, ist ein Blatt btw.), mit dem ersten (Root) Tauschen, und es (bzw. previous Root) vom Heap entfernen.
|
||
2. Heap Reparieren indem man das neue Root element **down-shifted**, bis es wieder am richtigen platz ist, siehe vorherige erklärung.
|
||
|
||
## 4. Balancierte Bäume
|
||
Binärer Suchbaum
|
||
|
||
Max. Tiefe: $log_2(n)$
|
||
|
||
Jeder Knoten bekommt einen *Balancefaktor*, dieser Entspricht der Tiefe vom rechten, minus der Tiefe des linken Teilbaumes.
|
||
> Tiefe von einem (Teil)Baum, ist einfach die maximale Anzahl Kanten nach unten.
|
||
$$BAL(Knoten) = T(u_2) - T(u_1)$$
|
||
|
||
Dieser sollte entweder $\{-1; 0; 1\}$
|
||
## 5. Reelwertige Optimierung in einer Dimension
|
||
Bisektion mit Sampling. I.e. man macht Bisektion mehrere Male, mit anderen Intervallen.
|
||
Also z.B. komplettes intervall ist $I=[1, 10]$, und dort sind vielleicht 4 lokale Minima.
|
||
Dann macht man halt $$I_1=[1, 4], I_2=[4,7], I_3=[7, 10]$$
|
||
Und führt auf den Intervallen Bisektion aus und nimmt das beste Ergebnis.
|
||
|
||
Bei Newton: Einfach ganz Normal Newton mit Schrittweitensteuerung.
|
||
|
||
### Straf- (Penalty-) Funktionen
|
||
|
||
**Grundidee**
|
||
Mit einer Straffunktion $$p(x)$$ wird ein restringiertes Problem
|
||
|
||
$$
|
||
\text{Min } f(x), \qquad A \le x \le B
|
||
$$
|
||
|
||
auf ein *unrestringiertes* Problem
|
||
|
||
$$
|
||
\text{Min } \Phi(x) \;=\; f(x) + p(x)
|
||
$$
|
||
|
||
abgebildet. Die Strafe $$p(x)$$ ist null im gültigen Bereich und wächst quadratisch, sobald eine Schranke verletzt wird.
|
||
|
||
---
|
||
|
||
#### Quadratische Strafterme (2-mal diff'bar)
|
||
|
||
$$
|
||
p_1(x) \;=\; \beta (x-A)^2 \quad \text{für } x \ge A,\;\text{sonst }0,
|
||
$$
|
||
$$
|
||
p_2(x) \;=\; \beta (x-B)^2 \quad \text{für } x \le B,\;\text{sonst }0,
|
||
$$
|
||
|
||
$$
|
||
p(x) \;=\; p_1(x) + p_2(x), \qquad \beta>0.
|
||
$$
|
||
|
||
Je größer $\beta$, desto stärker die Strafe ⇒ höhere Genauigkeit am Rand, aber auch instabilere Newton-Schritte.
|
||
|
||
---
|
||
|
||
#### Beispiel
|
||
|
||
$$
|
||
\text{Min } f(x), \qquad 0 \le x \le 1.
|
||
$$
|
||
Strafterme
|
||
|
||
$$
|
||
p_1(x)=\beta x^2, \qquad p_2(x)=\beta (x-1)^2,
|
||
$$
|
||
|
||
Gesamtfunktion
|
||
|
||
$$
|
||
\Phi(x)=f(x) + p_1(x) + p_2(x).
|
||
$$
|
||
|
||
*Ableitungen einsetzen → Newton-Iteration mit $\Phi$ anstelle von $f$.*
|
||
|
||
## 6. Bivariate Lineare Programmierung
|
||
1. Nebenbedingungen Aufbauen (Ungleichungen)
|
||
2. Nach $y$ auflösen und einzeichnen (Aufpassen auf Umformung)
|
||
3. Lösung finden, indem die zu Optimierte Funktion folgendermaßen umgestellt wird.
|
||
|
||
|
||
$$min(x-y) \ |\ x=x_1, y=x_2$$
|
||
$$x-y=c \Rightarrow y = x-c$$
|
||
$$\lim_{c \ \rightarrow\ -\infty} \Rightarrow y=x+\infty $$
|
||
*Wenn $max(c)$, dann muss limes gegen $+\infty$ gehen!*
|
||
|
||
Das sollte dann ne Gerade geben, $c$ ist normalerweise nicht $\infty$, da die *Feasable-Region* es beschränkt, dann nimmt man den Rand oder Eckpunkt.
|
||
|
||
>**Achtung**: Werden beide Seiten einer Ungleichung mit einer negativen Zahl multipliziert oder durch eine negative Zahl dividiert, muss das Ungleichheitszeichen umgekehrt werden (z.B. aus $<$ wird $>$)
|
||
|
||
## 7. Reelwertige Optimierung in N Dimensionen
|
||
$$f(x_1, x_2,..., x_n)$$
|
||
$$ f'(x) \longrightarrow \nabla f(x)$$
|
||
$$f''(x) \longrightarrow H$$
|
||
### 7.2 Downhill-Simplex
|
||
|
||
Besteht aus n+1 Punkten
|
||
|
||
**Vorgehen**:
|
||
1. Berechne alle $f(x_0), f(x_1), \ ...$
|
||
2. Berechne Schwerpunkt (Durchschnitt von allen $x$)
|
||
3. Eine Operation ausführen
|
||
|
||
#### Reflection
|
||
Spiegelung des *schlechtesten* Punktes am Schwerpunkt
|
||
$$x_r = x_{n+1} + (x_{n+1}-\bar{x})$$
|
||
|
||
#### Expansion
|
||
Spiegelung aber *skaliert*
|
||
|
||
#### Contraction
|
||
|
||
#### Shrinkage
|
||
Zieht die schlechten Punkten zum besten Punkt.
|
||
I.e. halbiert die Entfernung zum besten Punkt.
|
||
|
||
#### Abbruch
|
||
$$f_{worst} - f_{best} < tol$$
|
||
$$\sqrt{mean((f_{x_i} -f_S)^2)} < tol$$
|
||
$$mean((f_{x_i} - mean([...f_x]))^2)$$
|
||
### 7.3 Newton
|
||
Für 1 Parameter:
|
||
$$x_{n+1} = x_n - \frac{f'(x)}{f''(x)}$$
|
||
|
||
Für 1< Parameter:
|
||
$$x_{x+1} = x_n - H^{-1}_n * \nabla f_n$$
|
||
|
||
Mit Schrittweitensteuerung:
|
||
$$x_{x+1} = x_n - c_i * H^{-1}_n * \nabla f_n$$
|
||
|
||
**1. Partielle Ableitungen**
|
||
$f_{xx}$ ist $f(x, y)$, zweimal partiell nach x abgeleitet. $f_{xy}$ wäre einmal nach $x$ und ein zweites mal nach $y$ abgeleitet.
|
||
$$
|
||
f_{xx} = \frac{\partial^{2} f}{\partial x^{2}},\qquad
|
||
f_{xy} = \frac{\partial^{2} f}{\partial x\,\partial y},\qquad
|
||
f_{yx} = \frac{\partial^{2} f}{\partial y\,\partial x},\qquad
|
||
f_{yy} = \frac{\partial^{2} f}{\partial y^{2}}.
|
||
$$
|
||
|
||
**2. Gradient**
|
||
Vektor mit $\text{1. Partieller Ableitung nach x}$ in der $x$ Komponente, respektive part. diff. y in y .
|
||
$$
|
||
\nabla f(x,y)=
|
||
\begin{pmatrix}
|
||
\displaystyle\frac{\partial f}{\partial x}\\[6pt]
|
||
\displaystyle\frac{\partial f}{\partial y}
|
||
\end{pmatrix}.
|
||
$$
|
||
|
||
|
||
**3. Hesse Matrix und Determinante**
|
||
$$
|
||
H=
|
||
\begin{pmatrix}
|
||
f_{xx} & f_{xy}\\
|
||
f_{yx} & f_{yy}
|
||
\end{pmatrix},
|
||
\qquad
|
||
\det H = f_{xx}\cdot f_{yy}-(f_{xy})^2.
|
||
$$
|
||
**4. Inverse Hesse-Matrix bestimmen**
|
||
|
||
$$
|
||
H^{-1}=\frac{1}{\det H}
|
||
\begin{pmatrix}
|
||
f_{yy} & -f_{xy}\\
|
||
-f_{xy} & f_{xx}
|
||
\end{pmatrix}.
|
||
$$
|
||
### 7.4 Steepest-Descent
|
||
Newton aber mit $H^{-1} \approx 1$. Btw. das $c$ ist wichtig, weil der Gradient nur ne Richtung ist.
|
||
$$x_{x+1} = x_n - c_i * \nabla f_n$$
|
||
|
||
|
||
|