mirror of
https://github.com/2martens/uni.git
synced 2026-05-07 03:46:25 +02:00
Compare commits
44 Commits
opti_blatt
...
opti_blatt
| Author | SHA1 | Date | |
|---|---|---|---|
| 3a318ef2d5 | |||
| 41bdc1bda9 | |||
| a014ffffc7 | |||
| c60b690fec | |||
| f80e11ffe2 | |||
| 3e085ffbe6 | |||
| c455d2197f | |||
| 5eb9ddf2b0 | |||
| 49c5280378 | |||
| 529c7f5118 | |||
| f46c1a2343 | |||
| 1fb66470a3 | |||
| 56ec9ad594 | |||
| c5eac0cfe6 | |||
| 9ac5743b02 | |||
| f15872f6c9 | |||
| 6692df5e06 | |||
| bf01572c41 | |||
| 5dc58682c0 | |||
| c3a7be5d6c | |||
| 0f91b6e7f6 | |||
| 4064c37dbf | |||
| 055079d9d5 | |||
| 91adc86eb1 | |||
| 1f678826c5 | |||
| ca49021373 | |||
| a4ae405911 | |||
| 920ab0bf84 | |||
| 4ee9ab9602 | |||
| d299eb9b75 | |||
| 7ce281fc18 | |||
| 7858f854c0 | |||
| 70f76a6fa6 | |||
| 8ca065840a | |||
| 16427f493d | |||
| 8a6f1fe0f8 | |||
| 87f5d72027 | |||
| d958bd7614 | |||
| 281923ed54 | |||
| 3a824a2af6 | |||
| dd9776f693 | |||
| c9445024a6 | |||
| 1e7da0db62 | |||
| 81ab70be51 |
152
ad/AD-Gruppe_8_Koehler_Krabbe_Martens_Blatt7.tex
Normal file
152
ad/AD-Gruppe_8_Koehler_Krabbe_Martens_Blatt7.tex
Normal file
@ -0,0 +1,152 @@
|
||||
\documentclass[10pt,a4paper,oneside,ngerman,numbers=noenddot]{scrartcl}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[ngerman]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{bytefield}
|
||||
\usepackage{paralist}
|
||||
\usepackage{gauss}
|
||||
\usepackage{pgfplots}
|
||||
\usepackage{textcomp}
|
||||
\usepackage[locale=DE,exponent-product=\cdot,detect-all]{siunitx}
|
||||
\usepackage{tikz}
|
||||
\usepackage{algpseudocode}
|
||||
\usepackage{algorithm}
|
||||
%\usepackage{algorithmic}
|
||||
%\usepackage{minted}
|
||||
\usetikzlibrary{automata,matrix,fadings,calc,positioning,decorations.pathreplacing,arrows,decorations.markings}
|
||||
\usepackage{polynom}
|
||||
\polyset{style=C, div=:,vars=x}
|
||||
\pgfplotsset{compat=1.8}
|
||||
\pagenumbering{arabic}
|
||||
\def\thesection{\arabic{section})}
|
||||
\def\thesubsection{(\alph{subsection})}
|
||||
\def\thesubsubsection{(\roman{subsubsection})}
|
||||
\makeatletter
|
||||
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{%
|
||||
\hskip -\arraycolsep
|
||||
\let\@ifnextchar\new@ifnextchar
|
||||
\array{#1}}
|
||||
\makeatother
|
||||
\parskip 12pt plus 1pt minus 1pt
|
||||
\parindent 0pt
|
||||
|
||||
\begin{document}
|
||||
\author{Reinhard Köhler (6425686), Tronje Krabbe (6435002), \\
|
||||
Jim Martens (6420323)}
|
||||
\title{Hausaufgaben zum 22. Januar}
|
||||
\subtitle{Gruppe 8}
|
||||
\maketitle
|
||||
|
||||
\section{} %1
|
||||
\subsection{} %a
|
||||
\[
|
||||
(F, H), (E, G), (D, F), (C, E), (E, F), (I, J), (C, B), (B, A), (G, I)
|
||||
\]
|
||||
\subsection{} %b
|
||||
\begin{tikzpicture}
|
||||
\node (A) {$A^{1}$};
|
||||
\node (B) [below=of A] {$B^{0}$};
|
||||
\node (C) [above right=of A] {$C^{3}$};
|
||||
\node (D) [below=of C] {$D^{0}$};
|
||||
\node (E) [right=of D] {$E^{1}$};
|
||||
\node (F) [below=of E] {$F^{0}$};
|
||||
\node (G) [right=of E] {$G^{2}$};
|
||||
\node (H) [below=of G] {$H^{0}$};
|
||||
\node (I) [right=of H] {$I^{1}$};
|
||||
\node (J) [below=of I] {$J^{0}$};
|
||||
|
||||
\path[->,line width=1pt]
|
||||
(B) edge (A)
|
||||
(D) edge (C)
|
||||
(F) edge (E)
|
||||
(H) edge (G)
|
||||
(J) edge (I)
|
||||
(E) edge (C)
|
||||
(I) edge (G)
|
||||
(A) edge (C)
|
||||
(G) edge (C);
|
||||
\end{tikzpicture}
|
||||
\subsection{} %c
|
||||
\[
|
||||
(A, B), (B, G), (E, G), (C, E), (E, F), (F, H), (D, F), (A, I), (I, J)
|
||||
\]
|
||||
\subsection{} %d
|
||||
Beim Algorithmus von Prim wird zunächst eine for-Schleife über alle Knoten durchlaufen, welche damit die Laufzeit $\mathcal{O}(|V|)$ hat. Hinzu kommt eine while-Schleife über eine Queue mit initial $|V|$ Einträgen. Damit wird die while-Schleife genau $|V|$ mal durchlaufen, da in jedem Durchgang ein Eintrag entfernt wird. Die Operation deletemin hat eine Laufzeit von $\mathcal{O}(\log V)$, womit die Aufrufe von deletemin insgesamt $\mathcal{O}(V \cdot \log V)$ Zeit erfordern.
|
||||
|
||||
Die for each Schleife wird \underline{insgesamt} $2|E|$ mal ausgeführt, was $\mathcal{O}(E)$ entspricht. Die decreasekey-Operation hat eine Laufzeit von $\mathcal{O}(\log V)$, womit sich insgesamt eine Laufzeit von $\mathcal{O}(V + V \cdot \log V + E \cdot \log V) = \mathcal{O}(E \cdot \log V)$ ergibt.
|
||||
|
||||
\section{} %2
|
||||
\begin{algorithmic}[1]
|
||||
\Function{CanBeDivided}{s}
|
||||
\State $l \gets \Call{Length}{s}$
|
||||
\If{\Call{Dict}{s} = 1}
|
||||
\State \Return 1
|
||||
\ElsIf{$l$ = 0}
|
||||
\State \Return 0
|
||||
\Else
|
||||
\State $Q \gets \Call{CreateQueue}$
|
||||
\For{$i = 1 ... l-1$}
|
||||
\If{\Call{Dict}{$s_{1}...s_{i}$} = 1}
|
||||
\State $Q.enqueue(i+1)$
|
||||
\EndIf
|
||||
\EndFor
|
||||
\State $result \gets 0$
|
||||
\While{Q not empty}
|
||||
\State $pos \gets Q.dequeue()$
|
||||
\If{$!result$}
|
||||
\State $result \gets \Call{CanBeDivided}{s_{pos}...s_{l}}$
|
||||
\EndIf
|
||||
\EndWhile
|
||||
\State \Return $result$
|
||||
\EndIf
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
||||
\setcounter{section}{6}
|
||||
\section{} %7
|
||||
\setcounter{subsection}{4}
|
||||
\subsection{} %e
|
||||
\begin{tikzpicture}
|
||||
\node (592) {6};
|
||||
\node (301) [right=of 592] {3};
|
||||
\node (297) [right=of 301] {4};
|
||||
\node (170) [right=of 297] {2};
|
||||
\node (92) [right=of 170] {1};
|
||||
\node (87) [right=of 92] {5};
|
||||
\node (86) [right=of 87] {0};
|
||||
\node (79) [right=of 86] {8};
|
||||
\node (69) [right=of 79] {9};
|
||||
\node (68) [right=of 69] {7};
|
||||
|
||||
\node[state] (137) [above right=1 and 0.3 of 69] {137};
|
||||
\node[state] (165) [above right=1 and 0.3 of 86] {165};
|
||||
\node[state] (179) [above right=1 and 0.3 of 92] {179};
|
||||
\node[state] (302) [above right=of 165] {302};
|
||||
\node[state] (349) [above left=of 179] {349};
|
||||
\node[state] (598) [above right=1 and 0.3 of 301] {598};
|
||||
\node[state] (651) [above right=2 and 3 of 349] {651};
|
||||
\node[state] (1190) [above left=of 598] {1190};
|
||||
\node[state] (1841) [above left=of 651] {1841};
|
||||
|
||||
\path (69) edge (137)
|
||||
(68) edge (137)
|
||||
(86) edge (165)
|
||||
(79) edge (165)
|
||||
(92) edge (179)
|
||||
(87) edge (179)
|
||||
(165) edge (302)
|
||||
(137) edge (302)
|
||||
(170) edge (349)
|
||||
(179) edge (349)
|
||||
(301) edge (598)
|
||||
(297) edge (598)
|
||||
(592) edge (1190)
|
||||
(598) edge (1190)
|
||||
(349) edge (651)
|
||||
(302) edge (651)
|
||||
(1190) edge (1841)
|
||||
(651) edge (1841);
|
||||
\end{tikzpicture}
|
||||
\end{document}
|
||||
611
ad/Zusammenfassung.tex
Normal file
611
ad/Zusammenfassung.tex
Normal file
@ -0,0 +1,611 @@
|
||||
\documentclass[10pt,a4paper,oneside,ngerman,numbers=noenddot]{scrartcl}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[ngerman]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{bytefield}
|
||||
\usepackage{paralist}
|
||||
\usepackage{gauss}
|
||||
\usepackage{pgfplots}
|
||||
\usepackage{textcomp}
|
||||
\usepackage[locale=DE,exponent-product=\cdot,detect-all]{siunitx}
|
||||
\usepackage{tikz}
|
||||
\usepackage{algpseudocode}
|
||||
\usepackage{algorithm}
|
||||
\usepackage{mathtools}
|
||||
\usepackage{hyperref}
|
||||
%\usepackage{algorithmic}
|
||||
%\usepackage{minted}
|
||||
\usetikzlibrary{automata,matrix,fadings,calc,positioning,decorations.pathreplacing,arrows,decorations.markings}
|
||||
\usepackage{polynom}
|
||||
\polyset{style=C, div=:,vars=x}
|
||||
\pgfplotsset{compat=1.8}
|
||||
\pagenumbering{arabic}
|
||||
%\def\thesection{\arabic{section})}
|
||||
%\def\thesubsection{(\alph{subsection})}
|
||||
%\def\thesubsubsection{(\roman{subsubsection})}
|
||||
\makeatletter
|
||||
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{%
|
||||
\hskip -\arraycolsep
|
||||
\let\@ifnextchar\new@ifnextchar
|
||||
\array{#1}}
|
||||
\makeatother
|
||||
\parskip 12pt plus 1pt minus 1pt
|
||||
\parindent 0pt
|
||||
|
||||
\DeclarePairedDelimiter\abs{\lvert}{\rvert}%
|
||||
\DeclarePairedDelimiter{\ceil}{\lceil}{\rceil}
|
||||
|
||||
%switch starred and non-starred (auto-size)
|
||||
\makeatletter
|
||||
\let\oldabs\abs
|
||||
\def\abs{\@ifstar{\oldabs}{\oldabs*}}
|
||||
\makeatother
|
||||
|
||||
\hypersetup{
|
||||
colorlinks,
|
||||
citecolor=black,
|
||||
filecolor=black,
|
||||
linkcolor=black,
|
||||
urlcolor=black
|
||||
}
|
||||
|
||||
\begin{document}
|
||||
\author{Jim Martens}
|
||||
\title{Zusammenfassung AD}
|
||||
\maketitle
|
||||
|
||||
\section*{Disclaimer}
|
||||
|
||||
Diese Zusammenfassung setzt ein Belegen der AD-Veranstaltung voraus. Es kann den Besuch der Vorlesungen und Übungen durch das Semester hinweg nicht ersetzen und erhebt auch keinen Anspruch auf Vollständigkeit. Diese Zusammenfassung bezieht sich auf den Stoff der AD-Veranstaltung im Wintersemester 2013/2014 von Frau Luxburg.
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{Landau--Notation}
|
||||
|
||||
Es gibt fünf verschiedene Abschätzungen für die asymptotische Laufzeit eines Algorithmus.
|
||||
|
||||
\[
|
||||
\mathcal{O}, o, \omega, \theta, \Omega
|
||||
\]
|
||||
|
||||
$\mathcal{O}$ gibt die obere Schranke der Laufzeit an. Ein Algorithmus, der in $\mathcal{O}(n)$ liegt, hat demnach eine asymptotische Laufzeit von höchstens $n$. $\mathcal{O}$ wird am häufigsten benutzt, weswegen die gesamte Notation häufig auch O-Notation genannt wird.
|
||||
|
||||
$o$ verhält sich ähnlich, weist aber einen kleinen Unterschied auf. Ein Algorithmus in $o(n)$ wächst asymptotisch echt langsamer als $n$.
|
||||
|
||||
$\theta$ gibt eine genaue Laufzeit an. Ein Algorithmus in $\theta(n)$ wächst asymptotisch genauso schnell wie $n$.
|
||||
|
||||
$\omega$ ist das Gegenstück zu $o$ für die untere Schranke. Ein Algorithmus in $\omega(n)$ wächst echt schneller als $n$.
|
||||
|
||||
$\Omega$ schließlich ist das Gegenstück zu $\mathcal{O}$ für die untere Schranke. Ein Algorithmus in $\Omega(n)$ wächst mindestens so schnell wie $n$.
|
||||
|
||||
Bei der Landau--Notation fallen Konstanten und niedrigere Potenzen weg. Ein Algorithmus mit der konkreten Laufzeit von $45n^{2} + 100n$ liegt demnach in $\mathcal{O}(n^{2})$.
|
||||
|
||||
Geht es um den Vergleich zweier Algorithmen und ist die Laufzeit nicht eindeutig feststellbar, dann hilft es den Limes zu bilden. Dabei gelten folgende Regeln.
|
||||
|
||||
\begin{alignat*}{2}
|
||||
f \in \mathcal{O}(g):& \limsup_{n \rightarrow \infty} \abs{\frac{f(n)}{g(n)}} &<& \infty \\
|
||||
f \in o(g):& \lim_{n \rightarrow \infty} \abs{\frac{f(n)}{g(n)}} &=& 0 \\
|
||||
f \in \Omega(g) :& \liminf_{n \rightarrow \infty} \abs{\frac{f(n)}{g(n)}} &>& 0 \\
|
||||
f \in \omega(g) :& \liminf_{n \rightarrow \infty} \abs{\frac{f(n)}{g(n)}} &=& \infty \\
|
||||
f \in \theta(g) :& 0 < \liminf_{n \rightarrow \infty} \abs{\frac{f(n)}{g(n)}} \leq \limsup_{n \rightarrow \infty} \abs{\frac{f(n)}{g(n)}} &<& \infty
|
||||
\end{alignat*}
|
||||
|
||||
\section{Mastertheorem}
|
||||
|
||||
Das Mastertheorem gehört ebenso wie die Landau--Notation zur Komplexitätstheorie und wird benutzt, um Algorithmen in Komplexität einzuteilen. Es ist jedoch wichtig zu beachten, dass es nur auf ganz bestimmte Algorithmen anwendbar ist. So kann es nur für divide-and-conquer Algorithmen benutzt werden, bei denen sich die Größe der Subprobleme in jedem Rekursionsschritt um einen festen Faktor verkleinert.
|
||||
|
||||
Das Mastertheorem behandelt Rekurrenzgleichungen dieser Form:
|
||||
|
||||
\[
|
||||
T(n) = a \cdot T\left(\ceil*{\frac{n}{b}} \right) + \mathcal{O}(n^{d})
|
||||
\]
|
||||
|
||||
In dieser Formel steht $a$ für die Anzahl der Subprobleme pro Rekursionsschritt, $b$ für den Faktor, um den sich die Subprobleme pro Schritt verkleinern, $\mathcal{O}(n^{d})$ für die Kosten des Algorithmus, die nicht in der Rekursion liegen und $n$ für die Größe des Gesamtproblems. Dabei gelten diese formalen Bedingungen für die Variablen:
|
||||
|
||||
\[
|
||||
a \geq 1, b > 1
|
||||
\]
|
||||
|
||||
Hat man solch eine Rekurrenzgleichung gefunden, so kann man daraus die Komplexität berechnen.
|
||||
|
||||
\[
|
||||
T(n) = \begin{cases}
|
||||
\mathcal{O}(n^{d}) &, \text{wenn}\, d > \log_{b}(a) \\
|
||||
\mathcal{O}(n^{d} \cdot \log(n)) &, \text{wenn}\, d = \log_{b}(a) \\
|
||||
\mathcal{O}(n^{\log_{b}(a)}) &, \text{wenn}\, d < \log_{b}(a)
|
||||
\end{cases}
|
||||
\]
|
||||
|
||||
Die Komplexität der rekursiven Berechnung der Fibonacci-Zahlen beispielsweise lässt sich nicht mit dem Mastertheorem berechnen, da sich die Größe der Subprobleme pro Rekursionsschritt nicht um einen festen Faktor verkleinern.
|
||||
|
||||
\section{Datenstrukturen}
|
||||
|
||||
\subsection{Listen}
|
||||
|
||||
Es gibt zwei unterschiedliche Arten von Listen. Zum Einen gibt es Single-Linked-Lists, die nur in eine Richtung verbunden sind. Will man das letzte Element der Liste finden, muss man demnach vom Kopfelement die gesamte Liste durchgehen, um das letzte Element zu finden. Zum Anderen gibt es die Double-Linked-Lists, die in beide Richtungen verbunden sind. Dort kann man sich in beide Richtungen bewegen und spart damit Suchzeit, wenn man ein Element am Ende der Liste sucht.
|
||||
|
||||
Neben diesen zwei grundsätzlichen Arten von Listen gibt es noch unterschiedliche Ausführungsvarianten. In der Praxis trifft man meistens auf Listen, die ein dediziertes Kopf- und Schlusselement haben, welches keinen eigentlichen Wert enthält. Diese "`Wächterknoten"' verhindern eine Reihe von Problemen (siehe SE 1). Desweiteren gibt es noch für Double-Linked-Lists die Variante mit einem und nicht zwei solcher Wächterknoten. Dabei zeigt das letzte Element der Liste wieder auf den Wächterknoten, wodurch ein Ring entsteht.
|
||||
|
||||
\subsection{Bäume}
|
||||
|
||||
Bäume sind eine besondere Art von Graphen, die keine Zyklen enthalten und ungerichtet sind. Bäume haben einen Wurzelknoten und ein oder mehrere Blätter (Knoten ohne Kindknoten). Jeder Knoten hat entweder Kindknoten oder ist ein Blatt. Bei einem Baum mit einem einzigen Knoten ist dieser sowohl Wurzel als auch Blatt.
|
||||
|
||||
Es gibt für t-näre Bäume eine Sprachregelung, die festlegt wie ein solcher Baum heißt. Bei einem vollen (engl.: full) Baum hat jeder Knoten bis auf die Blätter t Kindknoten. Auf der untersten Ebene finden sich also $t^{h}$ Knoten, wobei $h$ die Höhe des Baumes bezeichnet. Die Wurzelebene ist mit Höhe $0$ versehen. Ein vollständiger Baum (engl.: complete) ist bis auf die unterste Ebene wie ein voller Baum. Auf der untersten Ebene befinden sich $1$ bis $t^{h}$ Blätter, die von links nach rechts angeordnet sind.
|
||||
|
||||
Die Gesamtanzahl an Knoten entspricht bei einem vollen Baum $t^{h+1}-1$ und bei einem vollständigen Baum $t^{h} - 1 + c : 1 \leq c \leq t^{h}$. Die Höhe des Baumes wiederum lässt sich aus der gesamten Anzahl der Knoten berechnen. Bei einem vollen Baum entspricht die Höhe des Baumes, wenn $n$ die Anzahl der Knoten symbolisiert, $\log_{t}(n+1) - 1$. Für einen vollständigen Baum entspricht es $\ceil*{\log_{t}(n+1)-1}$.
|
||||
|
||||
\subsection{Stack}
|
||||
|
||||
Ein Stack ist nach dem LIFO--Prinzip organisiert und unterstützt zwei Operationen, die je nach Literatur anders heißen. Die erste Operation erlaubt das Einfügen eines Elementes in den Stack (\texttt{Insert(e)} bzw. \texttt{Push(e)}) und die zweite Operation erlaubt das Entnehmen des zuletzt eingefügten Elementes (\texttt{Delete()} bzw. \texttt{Pop()}).
|
||||
|
||||
Ein Stack könnte sinnvoll mit einem Array implementiert werden.
|
||||
|
||||
\subsection{Queue}
|
||||
|
||||
Eine Queue arbeitet nach dem FIFO--Prinzip und unterstützt ebenso zwei Operationen. Die erste fügt ein Element in die Queue ein (\texttt{Insert(e)} bzw. \texttt{Enqueue(e)}) und die zweite Operation entfernt das vorderste Element in der Queue (\texttt{Delete()} bzw. \texttt{Dequeue()}).
|
||||
|
||||
Queues können sinnvoll als Double--Linked--Lists implementiert werden. Alternativ könnte man ein Array nehmen, bei dem man sich immer merkt welche Position gerade vorne und welche hinten ist.
|
||||
|
||||
Es gibt Abwandlungen der Queue, die das FIFO--Prinzip verletzen. Dies sind sogenannte Priority Queues, die das vorderste Element nach einer Sortierung bestimmen. Beispielsweise sorgt eine Min-Priority-Queue dafür, dass immer das Element mit dem geringsten Wert ganz vorne steht.
|
||||
|
||||
\subsection{Heap}
|
||||
|
||||
Ein Heap ist ein besonderer Baum, der nach bestimmten Kriterien sortiert ist. Bei einem Max--Heap befindet sich an der Wurzel der Knoten mit dem höchsten Wert und alle Kindknoten haben kleinere Werte. Dies gilt aber nicht nur für die Wurzel, sondern die Kindknoten jedes Knotens haben kleinere Werte als der Knoten, von dem sie Kinder sind.
|
||||
|
||||
Für einen Heap sind fünf Operationen definiert. Die Operation \texttt{Heapify} geht vom gewählten Knoten zu den Blättern und tauscht den Knoten so lange herunter, bis die Heapeigenschaft für den gesamten Heap unter dem Knoten wieder gilt. Die Operation erfordert gültige Heaps unter dem Knoten. Das bedeutet, dass die Subbäume für sich (mit den Kindern des Knotens als Wurzelknoten) gültige Heaps sind. Die worst case Laufzeit ist $\mathcal{O}(\log n)$.
|
||||
|
||||
Die zweite Operation \texttt{BuildMaxHeap} geht von den Blättern zum Wurzelknoten und stellt die Heapeigenschaft her. Dabei wird \texttt{Heapify} auf jeden Knoten ausgeführt. In jeder Ebene wird von rechts nach links vorgegangen, angefangen bei dem am weitesten unten rechts stehenden Knoten. Effektiv passiert auf Blattebene jedoch nichts, da diese keine Kindknoten haben, mit denen sie vertauscht werden könnten. Die Laufzeit beträgt $\mathcal{O}(n)$.
|
||||
|
||||
Die dritte Operation ist \texttt{ExtractMax}. Die Operation entfernt den Wurzelknoten und zieht den am weitesten rechts unten stehenden Knoten zur Wurzelposition und wendet \texttt{Heapify} auf diesen Knoten an. Die Laufzeit beträgt $\mathcal{O}(\log n)$.
|
||||
|
||||
Die vierte Operation heißt \texttt{DecreaseKey} und setzt den betreffenden Knoten auf den gewählten geringeren Wert und wendet \texttt{Heapify} auf diesen Knoten an. Die Laufzeit beträgt $\mathcal{O}(\log n)$.
|
||||
|
||||
Das Gegenstück dazu ist \texttt{IncreaseKey}, welches nach dem Verändern des Wertes die Operation \texttt{BuildMaxHeap} ausführt. Die Laufzeit beträgt $\mathcal{O}(\log n)$.
|
||||
|
||||
\section{Hashing}
|
||||
|
||||
Hashing hat das Ziel eine große Menge an Werten auf eine kleinere Menge abzubilden. Eine der einfachsten Hashfunktionen ist die modulo-Funktion für ganze Zahlen.
|
||||
|
||||
Die Zielmenge wird durch ein Array repräsentiert, wobei die Indizes für die Werte stehen, auf die abgebildet wird. Wenn auf eine kleinere Menge abgebildet wird, sind Kollisionen natürlich unvermeidlich. Dies wird dadurch gehandhabt, dass jedes Arrayelement eine Liste ist, in die alle Werte eingetragen werden, die auf den zugehörigen Index gehasht werden.
|
||||
|
||||
Das Ziel ist natürlich die Anzahl an Kollisionen pro Index möglichst klein zu halten und möglichst gleichmäßig zu hashen. Aus diesen Anforderungen ergibt sich, dass es bessere und schlechtere Hashfunktionen gibt. Allerdings gibt es keine perfekte Hashfunktion, sondern je nach Anwendungsgebiet kommen andere Funktionen in Betracht.
|
||||
|
||||
Eine mögliche Strategie der Kollisionsvermeidung ist das Weiterlaufen bis zum nächsten freien Index. Kommt man am Ende des Arrays an, wird wieder von vorne begonnen.
|
||||
|
||||
\section{Sortierverfahren}
|
||||
|
||||
\subsection{Selection Sort}
|
||||
|
||||
Selection Sort kann man sich gut mit Karten veranschaulichen. Man hat eine Menge an Karten offen vor sich liegen und nimmt nacheinander die Karten in die Hand, beginnend mit der niedrigsten Karte, und reiht sie dort von links nach rechts auf. Die Laufzeit beträgt im worst case $\mathcal{O}(n^{2})$.
|
||||
|
||||
\subsection{Insertion Sort}
|
||||
|
||||
Insertion Sort wendet man zum Beispiel bei Skat meist intuitiv an. Man hat eine Menge an verdeckten Karten, zieht nacheinander die jeweils höchste Karte und reiht sie entsprechend in die Hand ein, wobei die niedrigste Karte links und die höchstwertige Karte rechts ist. Die worst case Laufzeit beträgt hier ebenfalls $\mathcal{O}(n^{2})$.
|
||||
|
||||
\subsection{Bubble Sort}
|
||||
|
||||
Bubble Sort ist trotz gleicher worst case Laufzeit deutlich arbeitsaufwendiger für Menschen. Denn bereits bei 4 Werten ergeben sich 16 Durchgänge, um die Werte korrekt zu sortieren.
|
||||
|
||||
Die beste Erklärung des Sortierverfahrens bietet der Pseudocode.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{Bubblesort}{A}
|
||||
\For{i $\gets$ 1 to A.length - 1}
|
||||
\For{j $\gets$ A.length downto i + 1}
|
||||
\If{A[j] < A[j - 1]}
|
||||
\State exchange A[j] with A[j - 1]
|
||||
\EndIf
|
||||
\EndFor
|
||||
\EndFor
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
||||
|
||||
\subsection{Merge Sort}
|
||||
|
||||
Merge Sort ist mit einer worst case Laufzeit von $\mathcal{O}(n \cdot \log n)$ eines der besten vergleichsbasierten Sortierverfahren. Man nehme eine Reihe von Werten und sehe sie als einzelne Elemente an. Nun verbindet man immer zwei Elemente miteinander und bringt sie gleich in die richtige Reihenfolge. Dabei geht man rigoros von links nach rechts. Man verbindet demnach das erste und zweite Element, das dritte und vierte Element usw. Ist man damit fertig, verbindet man jeweils zwei dieser Zweierpärchen und sortiert alle enthaltenen Elemente in die richtige Reihenfolge. Auch dies wiederholt man für alle Pärchen. Diesen Vorgang wiederholt man nun solange bis am Ende nur noch eine korrekt sortierte Liste herauskommt.
|
||||
|
||||
Merge Sort kann man auch als Divide--and--conquer Verfahren bezeichnen. Es ergibt sich die folgende Rekurrenzgleichung.
|
||||
|
||||
\[
|
||||
T(n) = 2 \cdot T\left(\frac{n}{2}\right) + \mathcal{O}(n)
|
||||
\]
|
||||
|
||||
\subsection{Heap Sort}
|
||||
|
||||
Heap Sort macht sich die Heapeigenschaft zunutze und speichert alle Elemente in einem Heap. Somit lässt sich der höchste Wert (Max--Heap) einfach auslesen.
|
||||
|
||||
Der Pseudocode liest sich folgendermaßen:
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Function{HeapSort}{A}
|
||||
\State n $\gets$ \Call{length}{A}
|
||||
\State B $\gets$ empty array of length n
|
||||
\State H $\gets$ \Call{BuildMaxHeap}{A}
|
||||
\For{i $\gets$ 1 to n}
|
||||
\State B(n - i) $\gets$ \Call{ExtractMax}{H}
|
||||
\EndFor
|
||||
\State \Return B
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
||||
|
||||
Das Verfahren hat eine Laufzeit von $\mathcal{O}(n \cdot \log n)$, die sowohl die sowohl worst case als auch best case Laufzeit ist.
|
||||
|
||||
\subsection{Quick Sort}
|
||||
|
||||
Quick Sort funktioniert ähnlich wie Merge Sort, nur dass es mit einer kompletten Liste anfängt und dann immer weiter aufteilt und am Ende nur noch zusammenfügen muss. Dies funktioniert durch die Wahl eines Pivotelementes. Im Idealfall teilt es die Liste in zwei gleichgroße Teillisten. Die worst case Laufzeit beträgt $\mathcal{O}(n^{2})$. In den meisten Fällen benötigt Quick Sort jedoch nur $\mathcal{O}(n \cdot \log n)$.
|
||||
|
||||
Trotz der vermeintlich schlechten Laufzeit wird Quick Sort in der Praxis viel eingesetzt, da es in der Praxis auch auf die Konstanten ankommt, die in der Landau--Notation weggelassen werden. Quick Sort hat vergleichsweise kleine Konstanten wohingegen andere Verfahren mit einer besseren worst case Laufzeit meist größere Konstanten haben.
|
||||
|
||||
\subsection{Counting Sort}
|
||||
|
||||
Counting Sort ist ein Sortierverfahren, welches nicht vergleichsbasiert ist. Es gibt zwei prominente Implementationsmöglichkeiten. Die erste Möglichkeit ist ein Array mit Countern. Die zweite Möglichkeit ist ein Array mit Listen. Im Folgenden bezeichne K den höchsten Wert in der zu sortierenden Liste (nicht unbedingt die Datenstruktur in der diese Liste an Werten gespeichert ist).
|
||||
|
||||
Zunächst der Pseudocode für die erste Variante.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Function{CountingSort}{A}
|
||||
\State n $\gets$ \Call{length}{A}
|
||||
\State Allocate array B with length K, initialize each cell with 0
|
||||
\For{i $\gets$ 1 to n}
|
||||
\State B[A[i]] $\gets$ B[A[i]] + 1
|
||||
\EndFor
|
||||
\State C $\gets$ empty list
|
||||
\For{key, count in B}
|
||||
\While{count > 0}
|
||||
\State C.append(key)
|
||||
\State count $\gets$ count - 1
|
||||
\EndWhile
|
||||
\EndFor
|
||||
\State \Return C
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
||||
|
||||
Die zweite For-Schleife ist nur zum Erstellen der sortierten Liste. Die Laufzeit beträgt K für das Initialisieren des Arrays B, n für die erste For-Schleife, K für die zweite For-Schleife und maximal n für die While-Schleife. Dabei ist jedoch zu berücksichtigen, dass die While-Schleife insgesamt über alle Iterationen der For-Schleife nur n--mal aufgerufen wird, denn die Summe aller Counts entspricht der Länge der zu sortierenden Liste an Zahlen. Die Gesamtlaufzeit ist demnach $\mathcal{O}(K + n + n)$ bzw. $\mathcal{O}(K + 2n)$. Die Laufzeit K der zweiten For-Schleife ist hier nicht berücksichtigt, da die While-Schleife insgesamt nur n--mal aufgerufen wird und in den übrigen Fällen in der For-Schleife nichts ausgeführt wird. Nach den Regeln der Landau--Notation entfällt hier das zweite n bzw. die Konstante, da es nichts an der asymptotischen Laufzeit verändert. Die Gesamtlaufzeit ist damit $\mathcal{O}(K + n)$.
|
||||
|
||||
Die zweite Variante mit Listen im Array wird etwas anders implementiert, hat aber die gleiche Laufzeit.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Function{CountingSort}{A}
|
||||
\State n $\gets$ \Call{length}{A}
|
||||
\State Allocate array B with length K, initialize each cell with an empty list
|
||||
\For{i $\gets$ 1 to n}
|
||||
\State B[A[i]].append(A[i])
|
||||
\EndFor
|
||||
\State \Return concatenation of B[1], B[2], ..., B[K]
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
||||
|
||||
Die Laufzeit beträgt hier K für das Initialisieren von B und n für die For-Schleife. Insgesamt ergibt sich somit $\mathcal{O}(n + K)$.
|
||||
|
||||
\subsection{Radix Sort}
|
||||
|
||||
Radix Sort ist im Prinzip Counting Sort mit ein paar Veränderungen. Die obere Grenze der Zahlen kann riesig sein ($K = \omega(n)$). Um dem beizukommen stellt man sich jede Zahl als ein String vor. Zunächst werden die Zahlen nach der letzten Ziffer sortiert, dann nach der zweitletzten und so weiter. Dieses Verfahren setzt Counting Sort in der zweiten Variante voraus.
|
||||
|
||||
Da stets nur nach Ziffern sortiert wird, kann man die Arraylänge auf 10 begrenzen, denn es gibt nur 10 Ziffern. Demzufolge braucht man auch bei einem K von einer Million nur ein Array von 10, um alle Zahlen nach der letzten Ziffer dort einzusortieren in Listen.
|
||||
|
||||
Als Beispiel nehme man die Zahlen 10, 3, 5, 15, 20, 7 , 11 und 13. Diese werden in der Reihenfolge ihres Erscheinens sortiert und ergeben folgendes Bild im Array B.
|
||||
|
||||
\begin{alignat*}{1}
|
||||
B[0]:& 10 \rightarrow 20 \\
|
||||
B[1]:& 11 \\
|
||||
B[2]:& \\
|
||||
B[3]:& 3 \rightarrow 13 \\
|
||||
B[4]:& \\
|
||||
B[5]:& 5 \rightarrow 15 \\
|
||||
B[6]:& \\
|
||||
B[7]:& 7 \\
|
||||
B[8]:& \\
|
||||
B[9]:&
|
||||
\end{alignat*}
|
||||
|
||||
Im zweiten Schritt wird nun das Array und in jeder Zelle die Liste von vorne bis hinten durchgegangen und die jeweils aktuelle Zahl wird dann nach der zweitletzten Ziffer in ein Array C einsortiert. Zahlen mit weniger Ziffern (in diesem Fall die einstelligen Zahlen) werden bei der 0 einsortiert. Am Ende ergibt sich die richtige Reihenfolge und es müssen nur noch alle Zahlen konkateniert werden, um das Ergebnis zu erhalten.
|
||||
|
||||
Allerdings kann Radix Sort auch auf andere Zahlensysteme angewendet werden. Dann ist die Menge an möglichen Ziffern nicht gleich 10. Daher wird die Anzahl an möglichen Ziffern mit k bezeichnet und die Laufzeit zum Sortieren nach einer Ziffernposition ist dementsprechend $\theta(n + k)$. Counting Sort muss n--mal ausgeführt werden und das Array mit den Listen muss k lang sein und initialisiert werden. Dies ist jedoch nur ein Durchgang. Für die insgesamte Laufzeit von Radix Sort wird eine weitere Variable namens d benötigt, die die maximal mögliche Anzahl an Ziffern in einer Zahl bezeichnet (nicht zu verwechseln mit der Menge der möglichen Ziffern). Die Laufzeit beträgt sodann auch $\theta(d(n + k))$.
|
||||
|
||||
In unserem Beispiel oben ist k konstant und d ebenso. Demnach fallen beide Weg und es bleibt $\mathcal{O}(n)$ übrig. Wenn k konstant bleibt, aber d in logarithmische Abhängigkeit zu n gestellt wird, dann ergibt sich eine Laufzeit von $\mathcal{O}(n \cdot \log n)$. Ist d sogar gleich n, dann benötigt Radix Sort $\mathcal{O}(n^{2})$.
|
||||
|
||||
Warum wird Radix Sort dann überhaupt benutzt? Mithilfe von einigen Modifikationen kann man eine lineare Laufzeit erreichen und zwar als worst case. Dies ist möglich mit dem Block-based Radix Sort. Allerdings muss man vorher wissen in welchen Bereich die zu sortierenden Zahlen fallen. Genaueres siehe AD-Folienskript.
|
||||
|
||||
\subsection{Bucket Sort}
|
||||
|
||||
Bucket Sort wird zur Sortierung von reellen Zahlen verwendet, die gleichmäßig im Intervall [0,1] vorkommen. Angenommen man bekommt ein Eingabearray der Länge n, dann kann man das Intervall in n Buckets gleicher Länge zerteilen, wobei Bucket i alle Schlüsselwerte des Intervalls $\left[\frac{i}{n}, \frac{(i + 1)}{n}\right[$ enthält.
|
||||
|
||||
Die durchschnittliche Laufzeit beträgt $\mathcal{O}(n)$ und die worst case Laufzeit beträgt $\mathcal{O}(n \cdot \log n)$.
|
||||
|
||||
\subsection{Stabilität von Sortierverfahren}
|
||||
|
||||
Die Angabe "`wie in AD"' bedeutet, dass die in AD verwendete Variante gemeint ist und es andere Varianten gibt, bei denen das Gegenteilige gilt.
|
||||
|
||||
\begin{tabular}{c|c}
|
||||
Verfahren & stabil \\
|
||||
\hline
|
||||
Merge Sort & ja \\
|
||||
Quick Sort & ja, wie in AD \\
|
||||
Insertion Sort & nein, wie in AD \\
|
||||
Selection Sort & nein, wie in AD \\
|
||||
Heap Sort & nein \\
|
||||
Bubble Sort & ja \\
|
||||
Counting Sort & ja, in der zweiten Variante
|
||||
\end{tabular}
|
||||
|
||||
\subsection{Lower bound}
|
||||
|
||||
Für alle vergleichsbasierten Sortierverfahren gilt, dass sie eine worst case Laufzeit von $\Omega(n \cdot \log n)$ haben.
|
||||
|
||||
\section{Binäre Suchbäume}
|
||||
|
||||
Binäre Suchbäume haben eine besondere Struktur, die das Suchen erleichtert. Alle linken Kindknoten sind kleiner oder gleich des Elternknoten und alle rechten Kindknoten sind größer oder gleich des Elternknoten. Diese Bedingung gilt für alle Knoten mit Kindern.
|
||||
|
||||
Aufgrund dessen ist das Einfügen in solch einen Baum relativ deterministisch. Das Löschen gestaltet sich da schon etwas komplizierter.
|
||||
|
||||
Zunächst werden jedoch die Operationen der Reihe nach durchgegangen. Die erste Operation ist \texttt{Tree-Search} mit folgendem Pseudocode.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Function{Tree-Search}{x, k}
|
||||
\If{x == NIL or k == x.key}
|
||||
\State \Return x
|
||||
\EndIf
|
||||
\If {k < x.key}
|
||||
\State \Return \Call{Tree-Search}{x.left, k}
|
||||
\Else
|
||||
\State \Return \Call{Tree-Search}{x.right, k}
|
||||
\EndIf
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
||||
|
||||
Die Laufzeit beträgt $\mathcal{O}(h)$, wobei h die Höhe des Baumes angibt.
|
||||
|
||||
Das Minimum des Baumes kann gefunden werden, indem immer das linke Kind genommen wird bis ein Blatt erreicht wird. Dieses Blatt ist das minimale Element des Baumes. Die Laufzeit beträgt ebenso $\mathcal{O}(h)$. Das Maximum findet man analog, nur dass man dort immer das rechte Kind benutzt.
|
||||
|
||||
Die zweite Operation ist \texttt{Inorder-Tree-Walk} mit diesem Pseudocode.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{Inorder-Tree-Walk}{x}
|
||||
\If{x $\neq$ NIL}
|
||||
\State \Call{Inorder-Tree-Walk}{x.left}
|
||||
\State \Call{print}{x.key}
|
||||
\State \Call{Inorder-Tree-Walk}{x.right}
|
||||
\EndIf
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
||||
|
||||
Sie hat eine Laufzeit von $\theta(n)$.
|
||||
|
||||
Nun kommen wir zum Einfügen von Elementen. Für das Einfügen wird der Baum einfach heruntergegangen und das neue Element an der richtigen Stelle eingefügt. Die Laufzeit beträgt hier ebenso $\mathcal{O}(h)$.
|
||||
|
||||
Für das Entfernen eines Blattes ist es vergleichsweise einfach. Das Blatt kann einfach entfernt werden. Wenn ein Knoten nur einen linken oder nur einen rechten Kindknoten hat, dann können diese einfach an die Position des zu löschenden Knoten rücken. Hat der zu löschende Knoten jedoch sowohl einen linken als auch einen rechten Kindknoten, dann muss dessen Nachfolger gefunden werden. Dafür wird der am weitesten links stehende Knoten im rechten Teilbaum (mit dem rechten Kind des zu löschenden Knoten als Wurzel) herangezogen. Dieser wird dann an die Stelle des zu löschenden Knoten gesetzt und dessen rechtes Kind (falls vorhanden) wird an die Stelle von dem Nachfolger gesetzt.
|
||||
|
||||
Den Nachfolger zu finden dauert $\mathcal{O}(h)$. Der Rest passiert in konstanter Zeit, sodass die insgesamte Dauer ebenfalls $\mathcal{O}(h)$ ist. Da alle Operationen nur $\mathcal{O}(h)$ benötigen, wäre es natürlich von Interesse das h so klein wie möglich zu haben. Da kommen balancierte Bäume ins Spiel. Bei balancierten Bäumen unterscheidet sich die Höhe der beiden Teilbäume unter einem Knoten um maximal 1 (Bedingung gilt für alle Knoten).
|
||||
|
||||
\subsection{AVL Bäume}
|
||||
|
||||
AVL Bäume unterstützen Operationen, um die Balanciertheit wiederherzustellen. Allerdings ist dies nicht klausurrelevant, da Frau Luxburg diesen Bereich selber nicht sonderlich versteht.
|
||||
|
||||
Dennoch wird hier eine kurze Information zu den Operationen gegeben. Die Operationen heißen \texttt{RightRotate} und \texttt{LeftRotate} und benötigen jeweils nur konstante Zeit. Wird die Balanciertheit eines Baumes durch eine Einfüge- oder Löschoperation verletzt, dann müssen maximal Balancieroperationen ausgeführt werden, um die Balanciertheit wiederherzustellen.
|
||||
|
||||
Die Laufzeit vom Einfügen in einen solchen balancierten Baum beträgt $\mathcal{O}(\log n)$. Das Standardeinfügen benötigt $\mathcal{O}(\log n)$, das checken der Balanciertheit dauert ebenfalls $\mathcal{O}(\log n)$ und für die Wiederherstellung der Balanciertheit werden maximal zwei Rotationen in je konstanter Zeit ausgeführt.
|
||||
|
||||
\subsection{Red-black tree}
|
||||
|
||||
Ein Red-black tree hat folgende Eigenschaften.
|
||||
|
||||
\begin{itemize}
|
||||
\item jeder Knoten ist gefärbt (schwarz/rot)
|
||||
\item Wurzel und Blätter sind schwarz
|
||||
\item roter Knoten hat zwei schwarze Kinder
|
||||
\item von jedem Knoten aus haben alle Pfade zu den Blättern die gleiche Anzahl schwarze Knoten
|
||||
\item ein schwarzer Knoten kann sowohl schwarze als auch rote Kinder haben
|
||||
\end{itemize}
|
||||
|
||||
\section{Binäre Suche}
|
||||
|
||||
Bei der binären Suche hat man ein sortiertes Array gegeben. Nun schaut man sich immer das mittlere Element an und wenn dies kleiner dem gesuchten Element ist, dann wird die binäre Suche auf den rechten Teilbereich des Arrays angewendet. Ist das mittlere Element größer, so wird die binäre Suche auf den linken Teil angewendet und wenn das mittlere Element dem gesuchten Element entspricht, dann wird die Indexposition zurückgegeben. Wird das gesuchte Element nicht gefunden, dann wird \texttt{not\_found} zurückgegeben.
|
||||
|
||||
Der Pseudocode sieht folgendermaßen aus.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Function{BinarySearch}{A, value}
|
||||
\State low $\gets$ 0
|
||||
\State high $\gets$ N - 1
|
||||
\While{low $\leq$ high}
|
||||
\State mid $\gets$ (low + high) / 2
|
||||
\If{A[mid] > value}
|
||||
\State high $\gets$ mid - 1
|
||||
\ElsIf{A[mid] < value}
|
||||
\State low $\gets$ mid + 1
|
||||
\Else
|
||||
\State \Return mid
|
||||
\EndIf
|
||||
\EndWhile
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
||||
|
||||
Die Laufzeit beträgt $\mathcal{O}(\log n)$.
|
||||
|
||||
Es gibt jedoch auch noch andere Varianten der binären Suche, wie eine rekursive Variante und eine Variante, bei der, wenn das gesuchte Element nicht vorhanden ist, die Position zurückgegeben wird, bei der das gesuchte Element eingefügt werden kann, sodass das Array weiterhin sortiert ist.
|
||||
|
||||
\section{Graphen}
|
||||
|
||||
Bei dem Abschnitt über Bäume wurden Graphen kurz angeschnitten. Hier wird sich jetzt ausführlicher mit ihnen beschäftigt. Es gibt verschiedene Arten von Graphen.
|
||||
|
||||
Graphen können ungerichtet oder gerichtet sein und sie können gewichtet oder ungewichtet sein. Allerdings ist ein ungewichteter Graph äquivalent mit einem gewichteten Graphen, bei dem alle Kanten das Gewicht 1 haben. Ein ungerichteter Graph kann in einen gleichwertigen gerichteten Graphen überführt werden, indem jede Kante durch eine Hin- und Rückkante ersetzt wird.
|
||||
|
||||
Der Grad eines Knotens kann in einem ungerichteten Graphen durch folgende Formel errechnet werden.
|
||||
|
||||
\[
|
||||
Grad(u) = \sum\limits_{v \in V} w(u, v)
|
||||
\]
|
||||
|
||||
Bei einem gerichteten Graphen gibt es zwei Grade bei einem Knoten. Der Eingangsgrad und der Ausgangsgrad. Beide können folgendermaßen berechnet werden.
|
||||
|
||||
\begin{alignat*}{1}
|
||||
Grad-in(u) =& \sum\limits_{v \in V} w(v, u) \\
|
||||
Grad-out(u) =& \sum\limits_{v \in V} w(u, v)
|
||||
\end{alignat*}
|
||||
|
||||
Pfade sind eine beliebige Abfolge von Kanten. Ein Pfad ist ein Zyklus, wenn ein Knoten sowohl Anfangs- als auch Endknoten ist. Ein Pfad ist einfach (engl.: simple), wenn jeder Knoten nur einmal vorkommt.
|
||||
|
||||
Man kann Graphen in zusammenhängende und nicht zusammenhängende Graphen unterteilen. Dabei wird ein Graph als zusammenhängend bezeichnet, wenn von jedem Knoten zu jedem anderen Knoten ein Pfad gefunden werden kann (ungerichteter Graph). Ein gerichteter Graph heißt stark zusammenhängend, wenn von jedem Knoten zu jedem anderen ein gerichteter Pfad gefunden werden kann. Ein gerichteter Graph ist schwach zusammenhängend, wenn der zugehörige ungerichtete Graph zusammenhängend ist.
|
||||
|
||||
Eine Zusammenhangskomponente ist ein Teilgraph des Graphen und ist zusammenhängend. In einem zusammenhängenden Graphen gibt es nur eine Zusammenhangskomponente. In einem gerichteten Graphen sind die starken Zusammenhangskomponenten interessant. Dies sind Teilgraphen des Graphen, die stark zusammenhängend sind. Ein Graph kann schwach zusammenhängend sein und dennoch mehrere starke Zusammenhangskomponenten haben.
|
||||
|
||||
In einem vollständigen Graph ist jeder Knoten mit jedem anderen Knoten durch eine Kante verbunden.
|
||||
|
||||
Die Kanten eines Graphen können mithilfe von Adjazenzlisten oder einer Adjazenzmatrix dargestellt werden.
|
||||
|
||||
Desweiteren kann ein Graph dicht sein (engl.: dense). Dies bedeutet, dass der Graph sehr viele Kanten hat (ungefähr $|V|^{2}$). Außerdem kann ein Graph dünn sein (engl.: sparse). Dies bedeutet, dass der Graph sehr wenige Kanten hat.
|
||||
|
||||
\section{Graphalgorithmen}
|
||||
|
||||
\subsection{Bellman--Ford}
|
||||
|
||||
Der Bellman-Ford Algorithmus hat folgenden Pseudocode, der bereits eindrücklich zeigen sollte, wie der Algorithmus funktioniert.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Function{BellmanFord}{G, s}
|
||||
\State \Call{InitializeSingleSource}{G, s}
|
||||
\For{i $\gets$ 1 to |V| - 1}
|
||||
\ForAll{edges (u, v) $\in$ E}
|
||||
\State \Call{Relax}{u, v}
|
||||
\EndFor
|
||||
\EndFor
|
||||
\ForAll{edges (u, v) $\in$ E}
|
||||
\If{v.dist > u.dist + w(u, v)} \Comment{auf negativen Zyklus prüfen}
|
||||
\State \Return false
|
||||
\EndIf
|
||||
\EndFor
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
||||
|
||||
Die Laufzeit ist wenig verwunderlich: $\mathcal{O}(|V| \cdot |E|)$.
|
||||
|
||||
Der Algorithmus wird benutzt, um kürzeste Wege zu berechnen. Genauer wird er für das Single--Source--Shortest--Path--Problem verwendet.
|
||||
|
||||
\subsection{Dijkstra}
|
||||
|
||||
Dijkstra gibt es in zwei Variationen. Beide verhalten sich gleich, haben aber Unterschiede in der Laufzeit. Die naive Variante hat diesen Pseudocode.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{DijkstraNaive}{G, w, s}
|
||||
\State S $\gets$ {s}
|
||||
\State d(s) $\gets$ 0
|
||||
\While{S $\neq$ V}
|
||||
\State U $\gets$ {u $\not\in$ S | u neighbour of a vertex $\in$ S}
|
||||
\ForAll{u $\in$ U}
|
||||
\ForAll{\Call{pre}{u} $\in$ S that are predecessors of u}
|
||||
\State d'(u, \Call{pre}{u}) $\gets$ d(\Call{pre}{u}) + w(\Call{pre}{u}, u)
|
||||
\EndFor
|
||||
\EndFor
|
||||
\State $u^{*} \gets$ argmin\{d'(u, \Call{pre}{u}) | u $\in$ U, \Call{pre}{u} $\in$ S\}
|
||||
\State d($u^{*}$) $\gets$ d'($u^{*}$)
|
||||
\State S $\gets$ S $\cup$ \{$u^{*}$\}
|
||||
\EndWhile
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
||||
|
||||
Die Laufzeit der naiven Variante beträgt $\mathcal{O}(|V| \cdot |E|)$.
|
||||
|
||||
Die zweite Variante ist die Implementation mit der Min--Priority--Queue. Der Pseudocode dieser Variante folgt.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{Dijkstra}{G, w, s}
|
||||
\State Q $\gets$ (V, V.dist)
|
||||
\While{Q $\neq \empty$}
|
||||
\State u $\gets$ \Call{Extract}{Q}
|
||||
\ForAll{v adjacent to u}
|
||||
\State \Call{Relax}{u, v} and update the keys in Q accordingly
|
||||
\EndFor
|
||||
\EndWhile
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
||||
|
||||
Die Laufzeit mit der Min--Priority--Queue hängt von der Implementation der Queue ab. Bei einem naiven Array beträgt die Laufzeit $\mathcal{O}(n^{2})$. Bei der Implementation mit einem binären Heap sind es nur noch $\mathcal{O}((V + E)\log V)$. Bei der Implementation mit einem t-nären Heap sind es $\mathcal{O}\left((|V| \cdot t + |E|)\frac{\log V}{\log t}\right)$. Die beste Laufzeit kann mit einem Fibonacci Heap erreicht werden: $\mathcal{O}(V \log V + E)$.
|
||||
|
||||
Wenn der Graph dicht ist, dann sollte die Arrayimplementation genommen werden. Wenn der Graph dünn ist, dann sollte die Heapimplementation bevorzugt werden. Wenn der Graph sehr dünn ist (|E| = $\Omega(|V|)$) bekommen wir die Laufzeit $\mathcal{O}(|V| \log |V|)$.
|
||||
|
||||
Auch dieser Algorithmus gehört zum Single--Source--Shortest--Path--Problem.
|
||||
|
||||
\subsection{Floyd--Warshall}
|
||||
|
||||
Floyd--Warshall ist ein Graphalgorithmus, mit dem man die kürzesten Pfade von jedem Knoten zu jedem Knoten herausfinden kann (All--Pairs--Shortest--Path--Problem). Der Pseudocode ist folgender.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Function{FloydWarshall}{}
|
||||
\State n $\gets$ |V|
|
||||
\State $D^{(0)} \gets$ new $n \times n$ matrix with all values being $\infty$
|
||||
\ForAll{v $\in$ V}
|
||||
\State $d_{0}(v,v) \gets$ 0
|
||||
\EndFor
|
||||
\ForAll{(u,v) $\in$ E}
|
||||
\State $d_{0}(u,v) \gets$ w(u,v)
|
||||
\EndFor
|
||||
\For{k $\gets$ 1 to n}
|
||||
\State $D^{k} \gets$ new $n \times n$ matrix
|
||||
\For{s $\gets$ 1 to n}
|
||||
\For{t $\gets$ 1 to n}
|
||||
\State $d_{k}(s, t) \gets$ min\{$d_{k-1}(s, t)$, $d_{k-1}(s, k) + d_{k-1}(k, t)$\}
|
||||
\EndFor
|
||||
\EndFor
|
||||
\EndFor
|
||||
\State \Return $D^{(n)}$
|
||||
\EndFunction
|
||||
\end{algorithmic}
|
||||
|
||||
Die Laufzeit beträgt $\mathcal{O}(|V|^{3})$.
|
||||
|
||||
\subsection{Bidirektionaler Dijkstra}
|
||||
|
||||
Der Bidirektionale Dijkstra besteht aus zwei Dijkstra--Algorithmen, die wechselweise ausgeführt werden. Der erste Dijkstra startet beim Startknoten und der zweite Dijkstra startet beim Zielknoten. Beide Algorithmen sind ganz normale Dijkstra--Algorithmen, die solange laufen bis ein Algorithmus einen Knoten aufnimmt, der bereits von dem anderen Algorithmus aufgenommen wurde.
|
||||
|
||||
Der kürzeste Pfad muss aber nicht über diesen Knoten laufen.
|
||||
|
||||
\subsection{A*--Suche}
|
||||
|
||||
$A^{*}$--Suche ist ein modifizierter Dijkstra--Algorithmus. Für jeden Knoten gibt es einen Wert, der die Entfernung zum Ziel angibt. Diese Entfernung muss nicht immer exakt sein, sodass auch eine untere Grenze wie die Luftlinienentfernung hinreichend ist.
|
||||
|
||||
Diese Entfernung wird bei der Auswahl des nächsten Knotens berücksichtigt. Der Knoten mit dem geringsten Abstand zum Startknoten plus der abgeschätzten Entfernung zum Ziel wird als nächstes ausgewählt.
|
||||
|
||||
\subsection{SCC--Algorithmus}
|
||||
|
||||
Der SCC--Algorithmus wird zum Bestimmen von starken Zusammenhangskomponenten beynutzt. Der Algorithmus kann in Worten wie folgt beschrieben werden.
|
||||
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{SCC}{G}
|
||||
\State Call \Call{DFS}{G} to compute the finishing times \Call{f}{u}
|
||||
\State Compute the reverse graph $G^{t}$
|
||||
\State Call \Call{DFS}{$G^{t}$}, where the vertices in the main loop are considered in order of decreasing \Call{f}{u}
|
||||
\State Output the subsets that have been discovered by the individual calls of DFS--Visit
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
||||
|
||||
Die Laufzeit beträgt insgesamt $\mathcal{O}(|V| + |E|)$.
|
||||
|
||||
\subsection{Kruskals Algorithmus}
|
||||
|
||||
Kruskals Algorithmus geht die Kanten in nicht absteigender Reihenfolge durch und nimmt alle Kanten auf, die keinen Zyklus ergeben.
|
||||
|
||||
\subsection{Prims Algorithmus}
|
||||
|
||||
Prims Algorithmus beginnt bei einem Startknoten, der zu Beginn einziger Bestandteil der Menge $S$ ist. Prim fügt in jedem Schritt eine Kante hinzu, die $S$ mit $V \setminus S$ verbindet und von allen potentiellen Kanten die mit dem geringsten Gewicht ist.
|
||||
|
||||
\section{Dynamisches Programmieren}
|
||||
|
||||
%TODO
|
||||
|
||||
\section{Edit distance}
|
||||
|
||||
%TODO
|
||||
|
||||
\[
|
||||
E(i, j) = min\begin{cases}
|
||||
E(i - 1, j) + 1 \\
|
||||
E(i, j - 1) + 1 \\
|
||||
E(i - 1, j - 1) + \mathrm{1}_{x[i] \neq y[j]}
|
||||
\end{cases}
|
||||
\]
|
||||
\end{document}
|
||||
209
gdb/G62B6_Dittrich-Lindemann-Martens.tex
Normal file
209
gdb/G62B6_Dittrich-Lindemann-Martens.tex
Normal file
@ -0,0 +1,209 @@
|
||||
\documentclass[ngerman]{gdb-aufgabenblatt}
|
||||
\RequirePackage[utf8]{inputenc}
|
||||
\renewcommand{\Aufgabenblatt}{6}
|
||||
\renewcommand{\Ausgabedatum}{Mi. 08.01.2014}
|
||||
\renewcommand{\Abgabedatum}{Do. 23.01.2014}
|
||||
\renewcommand{\Gruppe}{Tim Dittrich, Sebastian Lindemann, Jim Martens}
|
||||
|
||||
% define how the sections are rendered
|
||||
\def\thesection{Aufgabe \arabic{section}:}
|
||||
\def\thesubsection{\alph{subsection})}
|
||||
\def\thesubsubsection{\roman{subsubsection})}
|
||||
|
||||
\usetikzlibrary{positioning}
|
||||
\usetikzlibrary{shadows}
|
||||
|
||||
\begin{document}
|
||||
\section{B-Bäume}
|
||||
\subsection{} %a
|
||||
42 kann einfach eingefügt werden. Zum Einfügen von 6 wird der Baum gesplittet. Damit ergibt sich dieser Baum:
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {13};
|
||||
\node (1-l) [below left=of root] {9};
|
||||
\node (1-r) [below right=of root] {37 42};
|
||||
\node (2-l) [below left=of 1-l] {6};
|
||||
\node (2-r) [below right=of 1-l] {11};
|
||||
\path[->,line width=1pt]
|
||||
(root) edge (1-l)
|
||||
(root) edge (1-r)
|
||||
(1-l) edge (2-l)
|
||||
(1-l) edge (2-r);
|
||||
\end{tikzpicture}
|
||||
|
||||
12 kann wieder einfach eingefügt werden. Bei 25 muss der Baum wieder gesplittet werden, womit sich dieser Baum ergibt:
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {13};
|
||||
\node (1-l) [below left=1 and 2 of root] {9};
|
||||
\node (1-r) [below right=1 and 2 of root] {37};
|
||||
\node (2-l) [below left=of 1-l] {6};
|
||||
\node (2-r) [below right=of 1-l] {11 12};
|
||||
\node (2-rl) [below left=of 1-r] {25};
|
||||
\node (2-rr) [below right=of 1-r] {42};
|
||||
\path[->,line width=1pt]
|
||||
(root) edge (1-l)
|
||||
(root) edge (1-r)
|
||||
(1-l) edge (2-l)
|
||||
(1-l) edge (2-r)
|
||||
(1-r) edge (2-rl)
|
||||
(1-r) edge (2-rr);
|
||||
\end{tikzpicture}
|
||||
\subsection{} %b
|
||||
Für das Löschen von 17 wird der Baum ausgeglichen. Es ergibt sich dieser Baum:
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {11 38};
|
||||
\node (1-l) [below left=1 and 2 of root] {4 7};
|
||||
\node (1-m) [below=of root] {13 29};
|
||||
\node (1-r) [below right=1 and 2 of root] {49 50};
|
||||
\path[->,line width=1pt]
|
||||
(root) edge (1-l)
|
||||
(root) edge (1-r)
|
||||
(root) edge (1-m);
|
||||
\end{tikzpicture}
|
||||
|
||||
29 kann mit Mischen gelöscht werden. Es ergibt sich dieser Baum:
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {11 13};
|
||||
\node (1-l) [below left=1 and 2 of root] {4 7};
|
||||
\node (1-r) [below right=1 and 2 of root] {38 49 50};
|
||||
\path[->,line width=1pt]
|
||||
(root) edge (1-l)
|
||||
(root) edge (1-r);
|
||||
\end{tikzpicture}
|
||||
|
||||
49 kann einfach gelöscht werden. 7 kann nicht mehr gelöscht werden, ohne die Bedingungen eines B-Baumes zu verletzen. Nach dem Löschen von 7 blieben noch 5 Schlüssel übrig. Da pro Knoten mindestens 2 und maximal 4 Schlüssel eingetragen sein dürfen, wäre die einzige Lösung einen Knoten mit 2 und einen mit 3 Einträgen zu haben. Dies widerspräche aber der Voraussetzung, dass die Wurzel mindestens 2 Söhne hat, sofern sie kein Blatt ist. Daher ist diese Operation nicht möglich.
|
||||
|
||||
Wenn jedoch 7 und 4 zusammen gelöscht würden, dann ergäbe sich dieser Baum:
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {11 13 38 50};
|
||||
\end{tikzpicture}
|
||||
\section{Berechnungen in B-Bäumen}
|
||||
\subsection{} %a
|
||||
\subsubsection{} %i
|
||||
Der Baum kann minimal 6 Einträge und maximal 24 Einträge haben.
|
||||
\subsubsection{} %ii
|
||||
\[
|
||||
\frac{z_{max}}{n_{max}}
|
||||
\]
|
||||
\subsection{} %b
|
||||
\subsubsection{} %i
|
||||
maximale Belegung von Bäumen der angegebenen Klasse nach Höhe:
|
||||
|
||||
\begin{itemize}
|
||||
\item h=1: 6
|
||||
\item h=2: 48
|
||||
\item h=3: 348
|
||||
\end{itemize}
|
||||
|
||||
Demnach muss der B-Baum mindestens eine Höhe von 3 haben, um alle Datensätze fassen zu können.
|
||||
\subsubsection{} %ii
|
||||
|
||||
minimale Belegung von Bäumen der angegebenen Klasse nach Höhe:
|
||||
|
||||
\begin{itemize}
|
||||
\item h=1: 3
|
||||
\item h=2: 9
|
||||
\item h=3: 33
|
||||
\item h=4: 141
|
||||
\end{itemize}
|
||||
|
||||
Demnach kann der B-Baum maximal eine Höhe von 4 haben, um alle Datensätze fassen zu können.
|
||||
\section{B*-Bäume}
|
||||
\subsection{} %a
|
||||
64 kann einfach eingefügt werden. Beim Einfügen von 3 wird gesplittet:
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {5 9};
|
||||
\node (1-l) [below left=1 and 2 of root] {1 3 5};
|
||||
\node (1-m) [below=of root] {7 8};
|
||||
\node (1-r) [below right=1 and 2 of root] {40 53 61 64};
|
||||
|
||||
\path[->,line width=1pt] (root) edge (1-l)
|
||||
(root) edge (1-m)
|
||||
(root) edge (1-r);
|
||||
\end{tikzpicture}
|
||||
|
||||
6 kann einfach eingefügt werden. Beim Einfügen von 80 wird gesplittet:
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {5 9 61};
|
||||
\node (1-l) [below left=1 and 4 of root] {1 3 5 6};
|
||||
\node (1-ml) [below left=1 and 0.5 of root] {7 8};
|
||||
\node (1-mr) [below right=1 and 0.5 of root] {40 53 61};
|
||||
\node (1-r) [below right=1 and 4 of root] {64 80};
|
||||
|
||||
\path[->,line width=1pt] (root) edge (1-l)
|
||||
(root) edge (1-ml)
|
||||
(root) edge (1-mr)
|
||||
(root) edge (1-r);
|
||||
\end{tikzpicture}
|
||||
\subsection{} %b
|
||||
14 wird einfach gelöscht.
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {54};
|
||||
\node (1-l) [below left=1 and 2 of root] {34 40};
|
||||
\node (1-r) [below right=1 and 2 of root] {66};
|
||||
\node (2-ll) [below left=1 and 1 of 1-l] {12};
|
||||
\node (2-lm) [below=of 1-l] {38};
|
||||
\node (2-lr) [below right=1 and 1 of 1-l] {44 46};
|
||||
\node (2-rl) [below left=1 and 1 of 1-r] {68};
|
||||
\node (2-rr) [below right=1 and 1 of 1-r] {86};
|
||||
\path[->,line width=1pt] (root) edge (1-l)
|
||||
(root) edge (1-r)
|
||||
(1-l) edge (2-ll)
|
||||
(1-l) edge (2-lm)
|
||||
(1-l) edge (2-lr)
|
||||
(1-r) edge (2-rl)
|
||||
(1-r) edge (2-rr);
|
||||
\end{tikzpicture}
|
||||
|
||||
38 kann einfach gelöscht werden.
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {54};
|
||||
\node (1-l) [below left=1 and 2 of root] {34 40};
|
||||
\node (1-r) [below right=1 and 2 of root] {66};
|
||||
\node (2-ll) [below left=1 and 1 of 1-l] {12};
|
||||
\node (2-lr) [below right=1 and 1 of 1-l] {44 46};
|
||||
\node (2-rl) [below left=1 and 1 of 1-r] {68};
|
||||
\node (2-rr) [below right=1 and 1 of 1-r] {86};
|
||||
\path[->,line width=1pt] (root) edge (1-l)
|
||||
(root) edge (1-r)
|
||||
(1-l) edge (2-ll)
|
||||
(1-l) edge (2-lr)
|
||||
(1-r) edge (2-rl)
|
||||
(1-r) edge (2-rr);
|
||||
\end{tikzpicture}
|
||||
|
||||
12 kann durch Mischen gelöscht werden.
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {54 66};
|
||||
\node (1-l) [below left=1 and 1 of root] {44 46};
|
||||
\node (1-r) [below right=1 and 1 of root] {68 86};
|
||||
\path[->,line width=1pt] (root) edge (1-l)
|
||||
(root) edge (1-r);
|
||||
\end{tikzpicture}
|
||||
|
||||
44 kann einfach gelöscht werden.
|
||||
|
||||
\begin{tikzpicture}
|
||||
\node (root) {54 66};
|
||||
\node (1-l) [below left=1 and 1 of root] {46};
|
||||
\node (1-r) [below right=1 and 1 of root] {68 86};
|
||||
\path[->,line width=1pt] (root) edge (1-l)
|
||||
(root) edge (1-r);
|
||||
\end{tikzpicture}
|
||||
\section{Normalformenlehre}
|
||||
\subsubsection{} %i
|
||||
Die Schlüsselkanidaten von R bezüglich F sind B und A,D.
|
||||
\subsubsection{} %ii
|
||||
Die Nicht-Primärattribute von R bezüglich F sind E und C.
|
||||
\subsubsection{} %iii
|
||||
C hängt partiell von A,D ab, aber nicht von B. Daher befindet sich die Relation nicht in der zweiten Normalform und damit auch nicht in der dritten. Da jedes der Attribute in R atomar ist, befindet sich R in der ersten Normalform.
|
||||
\end{document}
|
||||
@ -74,6 +74,7 @@ Stephan Niendorf (6242417)}
|
||||
\node (bCap) [below=0.1 of b] {(s, +, 5)};
|
||||
\node (cCap) [below=0.1 of c] {(s, +, 6)};
|
||||
\node (dCap) [below=0.1 of d] {(b, +, 5)};
|
||||
\node (eCap) [below=0.1 of e] {(b, +, 2)};
|
||||
\node (tCap) [above=0.1 of t] {(d, +, 5)};
|
||||
\path[->] (s) edge node [above left] {3(3)} (a)
|
||||
(s) edge[line width=2pt] node [below] {0(5)} (b)
|
||||
@ -171,7 +172,7 @@ b = 0, n = 0, s = 381/56, m = 0
|
||||
In das verlinkte Tool wird folgendes eingegeben:
|
||||
\begin{verbatim}
|
||||
Minimize p = 3x1 + 24x2 + 13x3 + 9x4 + 20x5 + 19x6 subject to
|
||||
110x1 + 205x2 + 160x3 + 160x3 + 420x5 + 260x6 >= 2000
|
||||
110x1 + 205x2 + 160x3 + 160x4 + 420x5 + 260x6 >= 2000
|
||||
4x1 + 32x2 + 13x3 + 8x4 + 4x5 + 14x6 >= 55
|
||||
2x1 + 12x2 + 54x3 + 285x4 + 22x5 + 80x6 >= 800
|
||||
x1 <= 4
|
||||
@ -189,8 +190,7 @@ x6 >= 0
|
||||
\end{verbatim}
|
||||
Die Ausgabe ist:
|
||||
\begin{verbatim}
|
||||
Optimal Solution: p = 46621/380; x1 = 4, x2 = 0, x3 = 5/4,
|
||||
x4 = 347/190, x5 = 2, x6 = 2
|
||||
Optimal Solution: p = 185/2; x1 = 4, x2 = 0, x3 = 0, x4 = 9/2, x5 = 2, x6 = 0
|
||||
\end{verbatim}
|
||||
\subsection{} %d
|
||||
In das verlinkte Tool wird folgendes eingegeben:
|
||||
|
||||
75
optimierung/Uebungsblatt13.tex
Normal file
75
optimierung/Uebungsblatt13.tex
Normal file
@ -0,0 +1,75 @@
|
||||
\documentclass[10pt,a4paper,oneside,ngerman,numbers=noenddot]{scrartcl}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[ngerman]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{paralist}
|
||||
\usepackage{gauss}
|
||||
\usepackage{pgfplots}
|
||||
\usepackage[locale=DE,exponent-product=\cdot,detect-all]{siunitx}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{matrix,fadings,calc,positioning,decorations.pathreplacing,arrows,decorations.markings}
|
||||
\usepackage{polynom}
|
||||
\usepackage{multirow}
|
||||
\polyset{style=C, div=:,vars=x}
|
||||
\pgfplotsset{compat=1.8}
|
||||
\pagenumbering{arabic}
|
||||
% ensures that paragraphs are separated by empty lines
|
||||
\parskip 12pt plus 1pt minus 1pt
|
||||
\parindent 0pt
|
||||
% define how the sections are rendered
|
||||
\def\thesection{\arabic{section})}
|
||||
\def\thesubsection{\alph{subsection})}
|
||||
\def\thesubsubsection{(\roman{subsubsection})}
|
||||
% some matrix magic
|
||||
\makeatletter
|
||||
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{%
|
||||
\hskip -\arraycolsep
|
||||
\let\@ifnextchar\new@ifnextchar
|
||||
\array{#1}}
|
||||
\makeatother
|
||||
|
||||
\begin{document}
|
||||
\author{Jan Branitz (6326955), Jim Martens (6420323),\\
|
||||
Stephan Niendorf (6242417)}
|
||||
\title{Hausaufgaben zum 27. Januar}
|
||||
\maketitle
|
||||
|
||||
\section{} %1
|
||||
\begin{tabular}{|c||c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}
|
||||
\hline
|
||||
7 & 0 & 0 & 0 & 2 & 2 & 4 & 4 & 5 & 6 & 6 & 7 & 8 & 9 & 10 & 10 & 11 & 11 & 11 & 13 & \underline{13} \\
|
||||
\hline
|
||||
6 & 0 & 0 & 0 & 0 & 2 & 4 & 4 & 5 & 6 & 6 & 6 & 7 & 9 & 10 & 10 & 11 & 11 & 11 & 12 & \underline{13} \\
|
||||
\hline
|
||||
5 & 0 & 0 & 0 & 0 & 2 & 2 & 3 & 5 & 6 & 6 & 6 & 7 & 8 & 8 & 9 & 11 & 11 & 11 & 11 & \underline{13} \\
|
||||
\hline
|
||||
4 & 0 & 0 & 0 & 0 & 2 & 2 & 3 & 5 & 5 & 5 & 5 & \underline{7} & 7 & 8 & 8 & 8 & 8 & 9 & 11 & \underline{11} \\
|
||||
\hline
|
||||
3 & 0 & 0 & 0 & 0 & 2 & 2 & \underline{3} & 3 & 3 & 3 & 5 & \underline{6} & 6 & 6 & 6 & 8 & 8 & 9 & 9 & 9 \\
|
||||
\hline
|
||||
2 & 0 & 0 & 0 & 0 & 0 & 0 & \underline{3} & 3 & 3 & 3 & 3 & 6 & 6 & 6 & 6 & 6 & 6 & 9 & 9 & 9 \\
|
||||
\hline
|
||||
1 & 0 & 0 & 0 & 0 & 0 & 0 & \underline{3} & 3 & 3 & 3 & 3 & 3 & 3 & 3 & 3 & 3 & 3 & 3 & 3 & 3 \\
|
||||
\hline
|
||||
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
|
||||
\hline
|
||||
\hline
|
||||
& 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 & 15 & 16 & 17 & 18 & 19 \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
|
||||
Der Rucksack ist mit den Items 1, 4 und 5 gefüllt.
|
||||
\section{} %2
|
||||
\begin{tabular}{c|c|c|c|c|c}
|
||||
& s & a & b & c & d \\
|
||||
\hline
|
||||
0 & 0 - & $\infty$ - & $\infty$ - & $\infty$ - & $\infty$ - \\
|
||||
1 & 0 - & 6 s & 4 s & 2 b & 2 a \\
|
||||
2 & 0 - & 6 s & 3 d & 1 b & 2 a \\
|
||||
3 & 0 - & 6 s & 3 d & 1 b & 2 a \\
|
||||
4 & 0 - & 6 s & 3 d & 1 b & 2 a
|
||||
\end{tabular}
|
||||
\end{document}
|
||||
@ -93,7 +93,7 @@ Stephan Niendorf (6242417)}
|
||||
3 \cdot 0 + 0 \cdot 1 - 1 \cdot 1 + 3 \cdot 2 &=& 5 &\geq & 5 \\
|
||||
1 \cdot 0 + 3 \cdot 1 + 2 \cdot 1 - 1 \cdot 2 &=& 3 &\geq & 3
|
||||
\end{alignat*}
|
||||
Wie zu erkennen ist, sind alle drei Ungleichungen mit Gleichheit erfüllt.D amit gelten die komplementären Schlupfbedingungen, womit bestätigt ist, dass die gefundenen Lösungen optimal sind.
|
||||
Wie zu erkennen ist, sind alle drei Ungleichungen mit Gleichheit erfüllt. Damit gelten die komplementären Schlupfbedingungen, womit bestätigt ist, dass die gefundenen Lösungen optimal sind.
|
||||
\subsection{} %b
|
||||
Das duale Problem (D):
|
||||
\begin{alignat*}{3}
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
\documentclass[14pt]{beamer}
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Meta informations:
|
||||
\newcommand{\trauthor}{Horst Hansen}
|
||||
\newcommand{\trtype}{} %{Proseminar} %{Seminar} %{Workshop}
|
||||
\newcommand{\trcourse}{Knowledge Processing with Neural Networks}
|
||||
\newcommand{\trtitle}{Neural Networks for Artificial Agents}
|
||||
\newcommand{\trmatrikelnummer}{6543210}
|
||||
\newcommand{\tremail}{hansen@informatik.uni-hamburg.de}
|
||||
\newcommand{\trinstitute}{Dept. Informatik -- Knowledge Technology, WTM}
|
||||
\newcommand{\trwebsiteordate}{{http://www.informatik.uni-hamburg.de/WTM/}}
|
||||
\newcommand{\trauthor}{Jim Martens}
|
||||
\newcommand{\trtype}{Proseminar} %{Proseminar} %{Seminar} %{Workshop}
|
||||
\newcommand{\trcourse}{Proseminar Artificial Intelligence}
|
||||
\newcommand{\trtitle}{Methods for understanding natural language}
|
||||
\newcommand{\trmatrikelnummer}{6420323}
|
||||
\newcommand{\tremail}{2martens@informatik.uni-hamburg.de}
|
||||
\newcommand{\trinstitute}{}
|
||||
\newcommand{\trwebsiteordate}{26.02.2014}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Languages:
|
||||
@ -53,6 +53,8 @@
|
||||
\usepackage{fancybox} % Gleichungen einrahmen
|
||||
\usepackage{fancyhdr} % Paket zur schickeren der Gestaltung der
|
||||
\usepackage{graphicx} % Inclusion of graphics
|
||||
\usepackage{tikz}
|
||||
%\usepackage{wrapfig}
|
||||
%\usepackage{latexsym} % Special symbols
|
||||
\usepackage{longtable} % Allow tables over several parges
|
||||
\usepackage{listings} % Nicer source code listings
|
||||
@ -102,7 +104,7 @@
|
||||
|
||||
%\lstloadlanguages{C} % Set the default language for listings
|
||||
\DeclareGraphicsExtensions{.pdf,.svg,.jpg,.png,.eps} % first try pdf, then eps, png and jpg
|
||||
\graphicspath{{./src/}} % Path to a folder where all pictures are located
|
||||
\graphicspath{{./src/} {/home/jim/Pictures/}} % Path to a folder where all pictures are located
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Costom Definitions:
|
||||
@ -125,9 +127,9 @@
|
||||
\end{beamercolorbox}
|
||||
|
||||
\vfill
|
||||
\begin{beamercolorbox}[ht=8ex,center]{}
|
||||
\includegraphics[width=0.20\paperwidth]{wtmIcon.pdf}
|
||||
\end{beamercolorbox}%
|
||||
%\begin{beamercolorbox}[ht=8ex,center]{}
|
||||
% \includegraphics[width=0.20\paperwidth]{wtmIcon.pdf}
|
||||
%\end{beamercolorbox}%
|
||||
\begin{beamercolorbox}[sep=8pt,center,colsep=-4bp,rounded=true,shadow=true]{institute}
|
||||
\usebeamerfont{institute}\trwebsiteordate
|
||||
\end{beamercolorbox}
|
||||
@ -193,15 +195,15 @@
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Display of TOCs:
|
||||
\AtBeginSection[]
|
||||
{
|
||||
\setcounter{tocdepth}{2}
|
||||
\frame
|
||||
{
|
||||
\frametitle{Outline}
|
||||
\tableofcontents[currentsection]
|
||||
}
|
||||
}
|
||||
%\AtBeginSection[]
|
||||
%{
|
||||
% \setcounter{tocdepth}{2}
|
||||
% \frame
|
||||
% {
|
||||
% \frametitle{Outline}
|
||||
% \tableofcontents[currentsection]
|
||||
% }
|
||||
%}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Document:
|
||||
@ -213,74 +215,197 @@
|
||||
\end{frame}
|
||||
%\setcounter{framenumber}{0}
|
||||
|
||||
\frame{
|
||||
\frametitle{Outline}
|
||||
\tableofcontents
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%
|
||||
% Your Content
|
||||
|
||||
\section{Motivation and Question}
|
||||
\section*{Motivation and Question}
|
||||
|
||||
\frame[t]{
|
||||
\frametitle{Motivation}
|
||||
\begin{frame}[t]{Motivation}
|
||||
\begin{columns}[t]
|
||||
\begin{column}{0.5\textwidth}
|
||||
\begin{itemize}
|
||||
\item Add your motivation here
|
||||
\item<2-> Dialogue in computer games
|
||||
\begin{itemize}
|
||||
\item Maybe with some details
|
||||
\item<3-> spoken
|
||||
\item<4-> written
|
||||
\end{itemize}
|
||||
\item<5-> Ambiguity
|
||||
\item<5-> Disambiguation
|
||||
%\item Use references \textsuperscript{[Author, 2010]}
|
||||
\end{itemize}
|
||||
\end{column}
|
||||
\begin{column}{68mm}\centering
|
||||
\begin{pgfpicture}{0cm}{3cm}{1cm}{0cm}
|
||||
\pgfbox[center,center]{\includegraphics[scale=0.15]{massEffectDialogScreenshot}}
|
||||
\end{pgfpicture}
|
||||
\end{column}
|
||||
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}{Outline}
|
||||
\tableofcontents
|
||||
\end{frame}
|
||||
|
||||
\section{Definitions}
|
||||
|
||||
\begin{frame}[t]{Definitions}
|
||||
\begin{itemize}
|
||||
\item but not too much
|
||||
\item Syntax
|
||||
\begin{itemize}
|
||||
\item Describes the sentence structure (e.g. simple subject--predicate--object order) and kind (e.g. declarative, question, order)
|
||||
\end{itemize}
|
||||
\item Grammar
|
||||
\begin{itemize}
|
||||
\item Specifies valid sentences
|
||||
\end{itemize}
|
||||
\item Semantics
|
||||
\begin{itemize}
|
||||
\item Meaning of the written words
|
||||
\end{itemize}
|
||||
\item Pragmatics
|
||||
\begin{itemize}
|
||||
\item Meaning of words in a given context or actual meaning
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\item Use references \textsuperscript{[Author, 2010]}
|
||||
\end{frame}
|
||||
|
||||
\section{Syntactic Parsing}
|
||||
|
||||
\begin{frame}[t,fragile]{Lexicon}
|
||||
\begin{columns}[t]
|
||||
\begin{column}{0.5\textwidth}
|
||||
\begin{itemize}
|
||||
\item Allowed words \textsuperscript{[Russel, 2009]}
|
||||
\item Probabilities
|
||||
\end{itemize}
|
||||
}
|
||||
\end{column}
|
||||
\begin{column}{0.5\textwidth}
|
||||
Example:
|
||||
\begin{alignat*}{2}
|
||||
Noun &\rightarrow && \text{tree [1.00]} \\
|
||||
Verb &\rightarrow && \text{is [1.00]} \\
|
||||
Adjective &\rightarrow && \text{high [1.00]} \\
|
||||
Article &\rightarrow && \text{the [1.00]} \\
|
||||
\end{alignat*}
|
||||
\end{column}
|
||||
\end{columns}
|
||||
\end{frame}
|
||||
|
||||
\section{Basics and Definition}
|
||||
\begin{frame}[t]{Grammar}
|
||||
\begin{itemize}
|
||||
\item Combines words into valid phrases \textsuperscript{[Russel, 2009]}
|
||||
\item Base for all kinds of parsing
|
||||
\item Probabilities
|
||||
\item Defines valid syntax
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
\begin{frame}[t,fragile]{Grammar}
|
||||
Example:
|
||||
\begin{alignat*}{2}
|
||||
S \;&\rightarrow &\; NP\;\;VP \;&[1.00] \\
|
||||
NP \;&\rightarrow &\; A\;N \;&[1.00]\\
|
||||
A \;&\rightarrow &\; Article\;&[1.00]\\
|
||||
N \;&\rightarrow &\; Noun\;&[1.00]\\
|
||||
VP \;&\rightarrow &\; Verb \;&[0.40] \\
|
||||
\;&|&\; VP\;Adjs \;&[0.60] \\
|
||||
Adjs \;&\rightarrow &\; Adjective \;&[0.80] \\
|
||||
\;&|&\; Adjective\;Adjs \;&[0.20]
|
||||
\end{alignat*}
|
||||
\end{frame}
|
||||
|
||||
\section{Approach}
|
||||
\begin{frame}[t]{Cocke Younger Kasami (CYK)}
|
||||
\begin{itemize}
|
||||
\item Named after inventors \textsuperscript{[Russel, 2009]}
|
||||
\begin{itemize}
|
||||
\item John Cocke (1925--2002)
|
||||
\item Daniel H. Younger
|
||||
\item Tadeo Kasami (1930--2007)
|
||||
\end{itemize}
|
||||
\item Dynamic programming parsing algorithm \textsuperscript{[Russel, 2009]}
|
||||
\item Works only with grammars in CNF \textsuperscript{[Russel, 2009]}
|
||||
\item Probabilities serve as disambiguation \textsuperscript{[Russel, 2009]}
|
||||
\item Best algorithm for general CFGs \textsuperscript{[Russel, 2009]}
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[t]{CYK Example}
|
||||
\centering
|
||||
\begin{tabular}{|c|c|c|c|}
|
||||
\hline
|
||||
X & start & length & p \\
|
||||
\hline
|
||||
\hline
|
||||
A & 1 & 1 & 1.00 \\
|
||||
\hline
|
||||
N & 2 & 1 & 1.00 \\
|
||||
\hline
|
||||
VP & 3 & 1 & 0.40 \\
|
||||
\hline
|
||||
Adjs & 4 & 1 & 0.80 \\
|
||||
\hline
|
||||
Adjs & 5 & 1 & 0.80 \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{frame}
|
||||
|
||||
\section{Semantic Analysis}
|
||||
|
||||
\begin{frame}[t]{Semantic Analysis}
|
||||
\begin{itemize}
|
||||
\item Syntax-driven semantic analysis \textsuperscript{[Jurafsky, 2009]}
|
||||
\item Syntax representation
|
||||
\begin{itemize}
|
||||
\item Parse trees \textsuperscript{[Jurafsky, 2009]}
|
||||
\item Dependency structures \textsuperscript{[Jurafsky, 2009]}
|
||||
\item etc
|
||||
\end{itemize}
|
||||
\item First--Order Logic
|
||||
\item Lambda notation
|
||||
\item Semantic attachments
|
||||
\item Meaning representation
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[t,fragile]{Semantic Analysis}
|
||||
Example of semantic attachment:
|
||||
\[
|
||||
A \rightarrow the \;\{\lambda x.\lambda P.\exists x.P(x)\}
|
||||
\]
|
||||
Example of meaning representation:
|
||||
\[
|
||||
\exists x.Tree(x) \Rightarrow \exists a.Very(a) \wedge HighThing(a, x)
|
||||
\]
|
||||
\end{frame}
|
||||
|
||||
\section{Results}
|
||||
|
||||
\section{Conclusion}
|
||||
|
||||
\frame[t]
|
||||
{
|
||||
\frametitle{Conclusion}
|
||||
|
||||
Novelty and contribution of this work:
|
||||
\begin{frame}[t]{Conclusion}
|
||||
\begin{itemize}
|
||||
\item Sum up the approach
|
||||
\item Sum op the results
|
||||
\item ...
|
||||
\item Show that it solves the question
|
||||
\item Ambiguity remains large problem
|
||||
\item Parsing and semantic analysis need restriction
|
||||
\item Context is key
|
||||
\end{itemize}
|
||||
|
||||
\mbox{ }
|
||||
|
||||
Open Questions:
|
||||
\begin{itemize}
|
||||
\item Something
|
||||
\item ... is always missing
|
||||
\end{itemize}
|
||||
}
|
||||
\end{frame}
|
||||
|
||||
%%%%%%%%%%%%%%
|
||||
|
||||
\frame[c]{
|
||||
\frametitle{The End}
|
||||
\begin{center}
|
||||
\begin{frame}[c]{The End}
|
||||
\begin{center}
|
||||
Thank you for your attention.\\[1ex]
|
||||
Any question?\\[5ex]
|
||||
\end{center}
|
||||
Any questions?\\[5ex]
|
||||
\end{center}
|
||||
\footnotesize
|
||||
Literature:
|
||||
\begin{itemize}
|
||||
\item Author , Author , Author, and Author. Name of the conference paper. \emph{In: Proceedings of the Conference Name}, 2008
|
||||
\item Author, Author, and Author. Name of the Article. \emph{Name of the Journal}, 42:111-133, 2010
|
||||
\item Author, and Author. \emph{Name of the Book}. Publisher, 2009
|
||||
\item Daniel Jurafsky and James H. Martin. \emph{Speech and Language processing}. Pearson, 2009
|
||||
\item Stuart J. Russel and Peter Norvig. \emph{Artificial intelligence: A Modern Approach}. Pearson, 2009
|
||||
\end{itemize}
|
||||
}
|
||||
Pictures:
|
||||
\begin{itemize}
|
||||
\item Motivation: Mass Effect 1 Screenshot from IGN.com
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
||||
\end{document}
|
||||
|
||||
154
prosem/notices.txt
Normal file
154
prosem/notices.txt
Normal file
@ -0,0 +1,154 @@
|
||||
Method for understanding natural language
|
||||
=========================================
|
||||
|
||||
title slide: present title and lead to motivation (Why is it interesting?)
|
||||
-----------
|
||||
|
||||
Motivation
|
||||
----------
|
||||
|
||||
- explain Mass Effect 1 screenshot (short and concise without story details)
|
||||
-1- it's a dialogue with predefined options
|
||||
- click
|
||||
-1- what about a game where I can freely decide what I say?
|
||||
-1- speech recognition would be necessary
|
||||
- but there are also other kinds of dialogue in computer games
|
||||
-2- Shroud of the Avatar uses a dialogue box (similar to chat bot) to enter your sentences
|
||||
-2- the NPCs react appropriately
|
||||
-2- behind the hood they just use keyword searching
|
||||
- click
|
||||
- if this is developed further, you come pretty quickly to the methods used to understand natural language
|
||||
- but there is an imminent problem: Ambiguity (click)
|
||||
- Disambiguation is used to address ambiguity
|
||||
|
||||
Outline
|
||||
-------
|
||||
|
||||
- start with some basic definitions
|
||||
- then Syntactic Parsing which is the key aspect of this presentation
|
||||
- Semantic Analysis is next but only the key points are presented
|
||||
- Conclusion (refers to critical discussion in paper)
|
||||
|
||||
Definitions
|
||||
-----------
|
||||
|
||||
syntax: describes sentence structure (for example subject-predicate-object order) and kind (declarative, question, order)
|
||||
|
||||
grammar: specifies valid sentences
|
||||
|
||||
semantics: meaning of the written words
|
||||
|
||||
pragmatics: meaning of words in a given context/actual meaning
|
||||
|
||||
- explain ambiguity on semantic level with the word "order"
|
||||
- as you can see this ambiguity can easily be resolved if the context is given
|
||||
- but without the context, the word "order" has different possible meanings
|
||||
- which one to choose?
|
||||
- that's a question that belongs to the semantic analysis
|
||||
|
||||
Syntactic Parsing (Lexicon)
|
||||
---------------------------
|
||||
|
||||
- first we come to syntactic parsing
|
||||
- a lexicon is very important there
|
||||
- it defines the set of allowed words divided into categories
|
||||
- open and closed categories
|
||||
-1- open: new words are added constantly, complete list not feasible
|
||||
-1- closed: change over course of centuries, complete list possible
|
||||
|
||||
- each word is attached a probability
|
||||
- all probabilities in one category sum up to 1
|
||||
|
||||
Syntactic Parsing (Grammar)
|
||||
---------------------------
|
||||
|
||||
- the grammar is somewhat the brother of the lexicon
|
||||
- defines how the allowed words can be brought into a sentence structure
|
||||
- contains multiple rules
|
||||
- base for all kinds of parsing as every algorithm must be able to determine if the input is valid
|
||||
|
||||
- in our case the grammar is a "Probabilistic context free grammar"
|
||||
-1- it has probabilities for each rule
|
||||
-1- the probabilities of all rules starting with the same non-terminal sum up to 1
|
||||
|
||||
- click
|
||||
|
||||
- this is example from paper
|
||||
- it's a very simplistic grammar that does only allow the simplest forms of sentences
|
||||
- Article, Noun, Verb, Adjective stand for a word from these categories in lexicon
|
||||
- as you can see the probabilities of the VP and Adjs rules sum up to 1 each
|
||||
- these probabilities are used to calculate the total probability of a parse tree in the (click) Cocke-Younger-Kasami or short CYK algorithm
|
||||
|
||||
Syntactic Parsing (CYK)
|
||||
-----------------------
|
||||
|
||||
- it is named after the inventors John Cocke, Daniel H. Younger and Tadeo Kasami
|
||||
- Cocke was awarded the ACM Turing Award and National Medal of Science of the United States
|
||||
- Kasami was the first to publish the ideas of the CYK algorithm
|
||||
|
||||
- it's a dynamic programming parsing algorithm
|
||||
-1- in short: it utilizes the results from earlier iterations
|
||||
- it's got the drawback that it only works with grammars in CNF
|
||||
-2- in theory no problem as every CFG can be converted to CNF without loss in expressiveness
|
||||
-2- in practice it poses non-trivial problems as the resulting trees do not fit to original grammar
|
||||
-2- solution to this is a modification of the CYK algorithm to handle unit productions (A->C->B) directly (Jurafsky Chapter 13 Section 4 Page 475)
|
||||
|
||||
- probabilities are used for disambiguation (if two things are possible, the one with higher probability does make probably more sense and comes closer to the intended meaning)
|
||||
- probabilities are gained from a treebank (like Penn Treebank)
|
||||
|
||||
- CYK is the best algorithm for general CFGs
|
||||
|
||||
- click
|
||||
|
||||
- here's an example for the table used by CYK to determine parse trees (excerpt from table in paper)
|
||||
- begins with length 1 and looks at every word (here it's the sentence "The tree is very high")
|
||||
- next it looks at length 2, 3, 4 and finally 5
|
||||
|
||||
- in the end there should be at least one entry in the table with S in column X, 1 in start and 5 in length.
|
||||
- If there is no such entry and the algorithm was performed correctly, the input is not valid.
|
||||
- if there is more than one such entry, there are multiple parse trees and therefore we have ambiguity
|
||||
- the probability is then used to decide which one is used to determine the parse tree (for example with the help of backpointers)
|
||||
|
||||
- this parse tree is then given to (click) the Semantic Analysis
|
||||
|
||||
Semantic Analysis
|
||||
-----------------
|
||||
|
||||
- there are multiple approaches for Semantic Analysis, the syntax-driven is presented
|
||||
- it requires a syntax representation as input
|
||||
-1- can be parse trees
|
||||
-1- but also dependency structures or other things
|
||||
|
||||
- the analysis utilizes First-Order Logic
|
||||
-2- connectives: and, or, implies
|
||||
-2- quantifiers: for all, exists
|
||||
-2- predicates, functions, variables
|
||||
|
||||
- and lambda notation (example can be seen in paper)
|
||||
|
||||
- the grammar is augmented with semantic attachments (click)
|
||||
- these are now combined starting with S and going down
|
||||
- in the example of the paper, the final meaning representation is this (showing on representation on slide)
|
||||
- one can also see here the elements of the logic (at least partially)
|
||||
- the whole process (step-by-step) can be seen in the paper
|
||||
|
||||
- the meaning representation can then be computationally used to react to the input
|
||||
|
||||
- click
|
||||
|
||||
Conclusion
|
||||
----------
|
||||
|
||||
- even though there are means to minimize ambiguity like probabilities, it is by far not possible to use the full grammar of a natural language (with no hint of the context, there are meany parses that make syntactically sense but not necessarily context-wise)
|
||||
- there is simply to much ambiguity and the known methods of disambiguation don't solve the problem completely
|
||||
- a restriction of the context and allowed words is therefore necessary to be able to parse and/or compute the meaning
|
||||
|
||||
- if we manage to find a way to tell the computer the context without hardcoding it by limiting the input, the problem could be solved altogether
|
||||
- cognitive inspired methods could be the key here
|
||||
|
||||
- click
|
||||
|
||||
End
|
||||
---
|
||||
|
||||
Thank you for your attention
|
||||
File diff suppressed because one or more lines are too long
@ -8,7 +8,7 @@
|
||||
\newcommand{\trmatrikelnummer}{6420323}
|
||||
\newcommand{\tremail}{2martens@informatik.uni-hamburg.de}
|
||||
\newcommand{\trarbeitsbereich}{Knowledge Technology, WTM}
|
||||
\newcommand{\trdate}{10.02.2014}
|
||||
\newcommand{\trdate}{26.01.2014}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Languages:
|
||||
@ -27,7 +27,8 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Bind packages:
|
||||
\usepackage{acronym} % Acronyms
|
||||
\usepackage{algorithmic} % Algorithms and Pseudocode
|
||||
%\usepackage{algorithmic} % Algorithms and Pseudocode
|
||||
\usepackage{algpseudocode}
|
||||
\usepackage{algorithm} % Algorithms and Pseudocode
|
||||
\usepackage{amsfonts} % AMS Math Packet (Fonts)
|
||||
\usepackage{amsmath} % AMS Math Packet
|
||||
@ -60,6 +61,10 @@
|
||||
\usepackage{tabularx} % Tables with fixed width but variable rows
|
||||
\usepackage{url,xspace,boxedminipage} % Accurate display of URLs
|
||||
|
||||
\usepackage{float}
|
||||
\floatstyle{boxed}
|
||||
\restylefloat{figure}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Configurationen:
|
||||
|
||||
@ -170,10 +175,10 @@
|
||||
|
||||
% Abstract gives a brief summary of the main points of a paper:
|
||||
\section*{Abstract}
|
||||
Syntactic parsing and semantic analysis are two important methods for understanding natural language. Each of them has their individual strengths and weaknesses. But both of them have major issues with ambiguity once a restricted environment is left. Understanding unrestricted natural language is therefore far from being reached.
|
||||
Syntactic parsing and semantic analysis are two important methods for understanding natural language. Each of them has their individual strengths and weaknesses. But both of them have major issues with ambiguity once a restricted environment is left.
|
||||
|
||||
% Lists:
|
||||
\setcounter{tocdepth}{2} % depth of the table of contents (for Seminars 2 is recommented)
|
||||
\setcounter{tocdepth}{2} % depth of the table of contents (for Seminars 2 is recommended)
|
||||
\tableofcontents
|
||||
\pagenumbering{arabic}
|
||||
\clearpage
|
||||
@ -190,31 +195,157 @@
|
||||
|
||||
It's the dream of many Science-Fiction fans: A fully sentient AI. Let's ignore for a moment all the odds that are against it (morality, physics, etc.) and concentrate on one aspect that is mandatory for even much less ambitious dreams. Imagine a computer game in which you can talk natural language to the NPC counterparts so that they react appropriately to it. Well maybe that is still too ambitious. What about writing what you want to say? In that case the computer needs to understand what you are writing so that it can react to it.
|
||||
|
||||
This process of understanding natural language contains multiple methods. The first one is the syntactic parsing, the second one the semantic analysis. Syntactic parsing relies on a grammar that describes the set of possible input, also called syntax. The syntax specifies what are allowed sentence structures and how these are built.
|
||||
The semantic analysis relies on the semantics of a given input. That means what the given input means. An example: ``You run around the bush''. The semantic meaning of this sentence is that you are running around a bush. The pragmatics define what is the intended meaning of an input. In this example it's not that you run around the bush but actually that you take a long time to get to the point in a discussion. It's a so called idiom. This difference between semantic meaning, where just the sentence as it is written is considered, and pragmatic meaning, where the intended meaning is considered, generates ambiguity that is easy for humans to resolve but difficult for computers. But even the pragmatics in this example are ambigious, because it depends on the context what it actually means. If two persons are walking around in a forest and one starts running around the bush, the sentence of this example, would have the semantic meaning as it's pragmatic meaning.
|
||||
The input in this case is plain text, following the grammar of a natural language like English. Without loss of generality it is assumed that the input is syntactically correct and follows the grammar of the natural language. The computer therefore gets a certain amount of text that follows a specified grammar. The grammar of modern English is assumed for the scope of this paper. With this information available, the computer still knows nothing about the meaning of the text. You could ask for a hot chocolate or you could write nasty things, it won't make a difference at this point.
|
||||
|
||||
In order to make the computer react properly to your input, it needs to understand and therefore process the input in the first place. This can be achieved by the usage of some methods for natural language understanding. For the scope of this paper ``natural language understanding'' contains all the methods used for understanding natural language. These include both methods to understand written natural language and methods used to understand spoken natural language. This paper looks closer at two of the methods used to understand written language. The first one is the syntactic parsing, the second one the semantic analysis. To understand how these methods work, you need to know the basic terminology of the subject matter. In the following paragraphs the terms syntax, semantics and pragmatics are explained with respect to the two mentioned methods.
|
||||
|
||||
The first method syntactic parsing relies on a grammar that describes the set of possible input, also called syntax. The syntax specifies what are allowed sentence structures and how these are built.
|
||||
|
||||
The semantic analysis relies on the semantics of a given input. That means what the given input means. An example: ``You run around the bush''. The semantic meaning of this sentence is that you are running around a bush.
|
||||
The pragmatics though define what is the intended meaning of an input. In this example it's not that you run around the bush but actually that you take a long time to get to the point in a discussion. It's a so called idiom. This difference between semantic meaning, where just the sentence as it is written is considered, and pragmatic meaning, where the intended meaning is considered, generates ambiguity that is easy for humans to resolve but difficult for computers. But even the pragmatics in this example are ambiguous, because it depends on the context what it actually means. If two persons are walking around in a forest and one starts running around the bush, the pragmatic meaning of the sentence in this example would be the previously mentioned semantic meaning.
|
||||
|
||||
On top of that the semantic meaning itself isn't always clear either. Sometimes words have multiple meanings, so that even the semantic meaning can have different possible interpretations.
|
||||
|
||||
The basic terminology should be clear by now. Whenever there are additional prerequisites to understand a method, these are explained in the section of that method.
|
||||
|
||||
Before the actual evaluation of the methods starts, the usage of the result of both methods is shortly described. After both syntactic parsing and semantic analysis have been executed, in this order, you have a semantic representation of the input. This representation could be used for example for an interface to a knowledge database where the user just inserts the question and gets an appropriate answer.
|
||||
|
||||
But there are other possible use cases as well. The two described methods could be used in a chatbot.
|
||||
|
||||
In this paper both syntactic parsing and semantic analysis are presented. After the presentation of the methods, they are critically discussed to finally come to a conclusion.
|
||||
|
||||
\section{Evaluation of methods}
|
||||
\label{sec:evalMethods}
|
||||
|
||||
Syntactic parsing and semantic analysis offer each a broad range of approaches. In this paper the ``syntax-driven semantic analysis''\cite[p.~617]{Jurafsky2009} is evaluated. It's especially interesting because it utilizes the output of the syntactic parsing to analyze the meaning. Therefore the two methods can be lined up in chronological order. First comes the syntactic parsing and then the semantic analysis. The methods are presented here in the same order.
|
||||
|
||||
They will be explained with the help of an example. Let's take the sentence ``The tree is very high''. For every method the theory is introduced first and the practical application with the example comes after it.
|
||||
|
||||
\subsection{Syntactic Parsing}
|
||||
\label{subSec:syntacticParsing}
|
||||
Syntactic Parsing is used to create parse trees. These can be used for grammar checks in a text editor: ``A sentence that cannot be parsed may have grammatical errors''\cite[p.~461]{Jurafsky2009b}. But they more likely ``serve as an important intermediate stage of representation for semantic analysis''\cite[p.~461]{Jurafsky2009b}. There are different algorithms available to create such trees. The CYK\footnote{named after inventors John Cocke, Daniel Younger and Tadeo Kasami} algorithm will be explained further. But before the CYK algorithm is explained, the reason for its existance is presented.
|
||||
Syntactic Parsing is used to create parse trees. These can be used for grammar checks in a text editor: ``A sentence that cannot be parsed may have grammatical errors''\cite[p.~461]{Jurafsky2009b}. But they more likely ``serve as an important intermediate stage of representation for semantic analysis''\cite[p.~461]{Jurafsky2009b}. There are different algorithms available to create such trees. The CYK\footnote{named after inventors John Cocke, Daniel Younger and Tadeo Kasami\cite[p.~893]{Russel2010}} algorithm will be explained further. But before the CYK algorithm is explained, the reason for its existance is presented.
|
||||
|
||||
\begin{figure}
|
||||
\begin{alignat*}{2}
|
||||
Noun &\rightarrow && \text{tree [1.00]} \\
|
||||
Verb &\rightarrow && \text{is [1.00]} \\
|
||||
Adjective &\rightarrow && \text{high [0.50]} \;|\; \text{very [0.50]} \\
|
||||
Article &\rightarrow && \text{the [1.00]} \\
|
||||
\end{alignat*}
|
||||
\caption{The lexicon for $\varepsilon_{0}$. The sum of the probabilities for each category is 1.}
|
||||
\label{fig:lexicon}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\begin{alignat*}{3}
|
||||
\varepsilon_{0}:& S \;&\rightarrow &\; NP\;\;VP \;&[1.00]&\; \text{The tree + is very high} \\
|
||||
& NP \;&\rightarrow &\; A\;N \;&[1.00]&\; \text{The + tree}\\
|
||||
& A \;&\rightarrow &\; Article\;&[1.00]&\; \text{the}\\
|
||||
& N \;&\rightarrow &\; Noun\;&[1.00]&\; \text{tree}\\
|
||||
& VP \;&\rightarrow &\; Verb \;&[0.40]&\; \text{is} \\
|
||||
& \;&|&\; VP\;Adjs \;&[0.60]&\; \text{is + very high} \\
|
||||
& Adjs \;&\rightarrow &\; Adjective \;&[0.80]&\; \text{very} \\
|
||||
& \;&|&\; Adjective\;Adjs \;&[0.20]&\; \text{very + high}
|
||||
\end{alignat*}
|
||||
|
||||
\caption{The grammar for $\varepsilon_{0}$ with example phrases for each rule. The syntactic categories are sentence (S), noun phrase (NP), verb phrase (VP), article (A), noun (N) and list of adjectives (Adjs). The categories article and noun have been added to allow a CNF grammar.}
|
||||
\label{fig:grammar}
|
||||
\end{figure}
|
||||
|
||||
\subsubsection*{Bottom-up and Top-down}
|
||||
\label{subSubSec:bottomUpTopDown}
|
||||
|
||||
There are two classical ways of parsing a sentence. The one is bottom-up and the other one is top-down. Both approaches have their own advantages and disadvantages. In addition the ambiguity creates problems. To implement bottom-up and top-down search algorithms in the face of ambiguity, ``an agenda-based backtracking strategy''\cite[p.~468]{Jurafsky2009b} is used. The problem here is that every time the parser recognizes that the current parse tree is wrong, it has to backtrack and explore other parts of the sentence. This creates a huge amount of work duplication and is therefore inefficient.
|
||||
|
||||
\subsubsection*{CYK algorithm}
|
||||
\label{subSubSec:cykAlgorithm}
|
||||
|
||||
A solution to these problems is offered by ``dynamic programming parsing methods''\cite[p.~469]{Jurafsky2009b}. The CYK algorithm is one of multiple algorithms based on dynamic programming.
|
||||
|
||||
The CYK does only work with grammars in the Chomsky Normal Form (CNF). Every context-free grammar can be converted to CNF without loss in expressiveness. Therefore this restriction does no harm but simplifies the parsing. For information on how context-free grammars can be converted to CNF, refer to Jurafsky\cite{Jurafsky2009b}.
|
||||
|
||||
CYK requires $\mathcal{O}(n^{2}m)$ space for the $P$ table (a table with probabilities), where ``$m$ is the number of nonterminal symbols in the grammar''\cite[p.~893]{Russel2010}, and uses $\mathcal{O}(n^{3}m)$ time. ``$m$ is constant for a particular grammar, [so it] is commonly described as $\mathcal{O}(n^{3})$''\cite[p.~893]{Russel2010}. There is no algorithm that is better than CYK for general context-free grammars\cite{Russel2010}.
|
||||
CYK requires $\mathcal{O}(n^{2}m)$ space for the $P$ table (a table with probabilities), where ``$m$ is the number of nonterminal symbols in the grammar''\cite[p.~893]{Russel2010}, and uses $\mathcal{O}(n^{3}m)$ time. ``$m$ is constant for a particular grammar, [so it] is commonly described as $\mathcal{O}(n^{3})$''\cite[p.~893]{Russel2010}. But these values are of no value if there is no benchmark. How good is $\mathcal{O}(n^{3})$ in comparison? To give a better idea of the relations, here a small comparison to the ``Earley Algorithm''\cite[p.~477]{Jurafsky2009b}. The Earley algorithm performs better with all unambiguous grammars.\cite{Li} It has the same upper bound in time but in most cases it is quicker. Furthermore it has a space complexity of $\mathcal{O}(n)$ which is definitely better than CYK.\cite{Li} For ambiguous grammars though the Earley algorithm uses more space than CYK and the real space used is dependent on the length of the input.\cite{Li} In time complexity the CYK algorithm can only compete with Earley if ambiguous grammars are used.\cite{Li} But CYK is still of use for parsing of natural language, because natural language grammars are always ambiguous. Therefore there is no algorithm that is better than CYK for general context-free grammars.\cite{Russel2010}
|
||||
|
||||
But how does CYK work? CYK doesn't examine all parse trees. It just examines the most probable one and computes the probability of that tree. All the other parse trees are present in the $P$ table and could be enumerated with a little work (in exponential time). But the strength and beauty of CYK is, that they don't have to be enumerated. CYK defines ``the complete state space defined by the `apply grammar rule' operator''\cite[p.~894]{Russel2010}. You can search just a part of this space with $A^{*}$ search.\cite{Russel2010} ``With the $A^{*}$ algorithm [...] the first parse found will be the most probable''\cite[p.~895]{Russel2010}.
|
||||
But how does CYK work? CYK doesn't examine all parse trees. It just examines the most probable one and computes the probability of that tree. All the other parse trees are present in the $P$ table and could be enumerated with a little work (in exponential time). But the strength and beauty of CYK is, that they don't have to be enumerated. CYK defines ``the complete state space defined by the `apply grammar rule' operator''\cite[p.~894]{Russel2010}. You can search just a part of this space with $A^{*}$ search.\cite{Russel2010} ``With the $A^{*}$ algorithm [...] the first parse found will be the most probable''\cite[p.~895]{Russel2010}. The actual pseudo code can be found in figure 23.5 in Russel\cite[p.~894]{Russel2010}.
|
||||
|
||||
\subsubsection*{Treebank}
|
||||
\label{subSubSec:treebank}
|
||||
|
||||
But these probabilities need to be learned from somewhere. This somewhere is usually a ``treebank''\cite[p.~895]{Russel2010}, which contains a corpus of correctly parsed sentences. The best known is the Penn Treebank\cite{Russel2010}, which ``consists of 3 million words which have been annotated with part of speech and parse-tree structure, using human labor assisted by some automated tools''\cite[p.~895]{Russel2010}. The probabilities are then computed by counting and smoothing in the given data.\cite{Russel2010} There are other ways to learn the probabilities that are more difficult. For more information refer to Russel\cite{Russel2010}.
|
||||
|
||||
\subsubsection*{Application}
|
||||
\label{subSubSec:application}
|
||||
|
||||
Now it is time to use the CYK algorithm with our example. For this case a restricted language called $\varepsilon_{0}$ is defined that is suitable to form one sentence about a tree. Next a lexicon (figure \ref{fig:lexicon}), ``or list of allowable words''\cite[p.~890]{Russel2010}, is defined. Furthermore a grammar (figure \ref{fig:grammar}) for $\varepsilon_{0}$ is defined. The lexicon and the grammar are based upon the lexicon and grammar in figures 23.1 and 23.2 of \cite{Russel2010} respectively.
|
||||
|
||||
The CYK algorithm is given the words and the grammar and returns the table $P$ containing the probabilities for the whole sentence and it's subsequences.\cite{Russel2010} The pseudo code can bee seen in algorithm \ref{alg:cyk}.
|
||||
|
||||
\begin{algorithm}
|
||||
\caption{Application of CYK for our problem}
|
||||
\label{alg:cyk}
|
||||
\begin{algorithmic}[1]
|
||||
\Procedure{CYK-Parse}{$words, grammar$}
|
||||
\State $N \gets \Call{Length}{Words}$\Comment{N = 5}
|
||||
\State $M \gets$ the number of nonterminal symbols in $grammar$\Comment{M = 6}
|
||||
\State $P \gets$ an array of size [M, N, N], initially all 0
|
||||
\For{$i = 1$ to $N$}
|
||||
\ForAll{rules of form ($X \rightarrow words_{i}[p]$)}
|
||||
\State $P[X, i, 1] \gets p$
|
||||
\EndFor
|
||||
\EndFor
|
||||
\For{$length = 2$ to $N$}
|
||||
\For{$start = 1$ to $N - length + 1$}
|
||||
\For{$len1 = 1$ to $N - 1$}
|
||||
\State $len2 \gets length - len1$
|
||||
\ForAll{rules of the form ($X \rightarrow$ $Y$ $Z$ [$p$])}
|
||||
\State $P[X, start, length] \gets \Call{Max}{P[X, start, length], P[Y, start, len1] \times P[Z, start + len1, len2] \times p}$
|
||||
|
||||
\EndFor
|
||||
\EndFor
|
||||
\EndFor
|
||||
\EndFor
|
||||
\State \Return $P$
|
||||
\EndProcedure
|
||||
\end{algorithmic}
|
||||
\end{algorithm}
|
||||
|
||||
The resulting P table is depicted in table \ref{tab:p}. As you can see in the table there is just one possible parse for the whole sentence. In linear form the sentence can be parsed as [$S$ [$NP$ [$A$ the] [$N$ tree]][$VP$ [$VP$ is][$Adjs$ [$Adjs$ very][$Adjs$ high]]]. With this information given a parse tree could be easily constructed.
|
||||
|
||||
\begin{table}
|
||||
\caption{Table of probabilities from the CYK parse. The entries with probability 0 have been left out.}
|
||||
\label{tab:p}
|
||||
\centering
|
||||
\begin{tabular}{|c|c|c|c|}
|
||||
\hline
|
||||
X & start & length & p \\
|
||||
\hline
|
||||
\hline
|
||||
A & 1 & 1 & 1.00 \\
|
||||
\hline
|
||||
N & 2 & 1 & 1.00 \\
|
||||
\hline
|
||||
VP & 3 & 1 & 0.40 \\
|
||||
\hline
|
||||
Adjs & 4 & 1 & 0.80 \\
|
||||
\hline
|
||||
Adjs & 5 & 1 & 0.80 \\
|
||||
\hline
|
||||
NP & 1 & 2 & 1.00 \\
|
||||
\hline
|
||||
VP & 3 & 2 & 0.192 \\
|
||||
\hline
|
||||
Adjs & 4 & 2 & 0.128 \\
|
||||
\hline
|
||||
S & 1 & 3 & 0.40 \\
|
||||
\hline
|
||||
VP & 3 & 3 & 0.09216 \\
|
||||
\hline
|
||||
S & 1 & 4 & 0.192 \\
|
||||
\hline
|
||||
S & 1 & 5 & 0.09216 \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
\subsection{Semantic Analysis}
|
||||
\label{subSec:semanticAnalysis}
|
||||
|
||||
@ -222,9 +353,15 @@
|
||||
|
||||
Therefore context-free grammar rules are augmented with ``semantic attachments''\cite[p.~618]{Jurafsky2009}. Every word and syntactic structure in a sentence gets such a semantic attachment. The tree with syntactic components is now traversed in a bottom-up manner. On the way the semantic attachments are combined to finally produce ``First-Order Logic''\cite[p.~589]{Jurafsky2009a} that can be interpreted in a meaningful way. This procedure has some prerequisites that will be explained first.
|
||||
|
||||
\subsubsection*{First-Order Logic}
|
||||
\label{subSubSec:firstOrderLogic}
|
||||
|
||||
The mentioned \textit{First-Order Logic} can be represented by a context-free grammar specification. It is beyond this paper to describe this specification completely. Jurafsky\cite{Jurafsky2009a} provides a detailed picture of the specification with all elements in figure 17.3. The most important aspects of this specification are explained here. The logic provides terms which can be functions, constants and variables. Functions have a term as argument. Syntactically they are the same as single-argument predicates. But functions represent one unique object.
|
||||
Predicates can have multiple terms as arguments. In addition the logic provides quantifiers ($\forall, \exists$) and connectives ($\wedge, \vee, \Rightarrow$).
|
||||
|
||||
\subsubsection*{Lambda notation}
|
||||
\label{subSubSec:lambdaNotation}
|
||||
|
||||
Another prerequisite is the ``lambda notation''\cite[p.~593]{Jurafsky2009a}. A simple example of this notation is an expression of the following form\footnote{examples taken from Jurafsky\cite[pp.~593-594]{Jurafsky2009a}}:
|
||||
\[
|
||||
\lambda x.P(x)
|
||||
@ -237,7 +374,7 @@
|
||||
&P(A)&
|
||||
\end{alignat*}
|
||||
|
||||
Those expressions can be extended to $n$ such $\lambda$s. An example is this expression:
|
||||
Those expressions can be extended to $n$ such $\lambda$s. An example is this expression (where $x$ and $y$ denote things from which a distance to each other can be calculated):
|
||||
\[
|
||||
\lambda x.\lambda y.Near(x,y)
|
||||
\]
|
||||
@ -251,61 +388,122 @@
|
||||
|
||||
This technique is called ``currying''\cite[p.~594]{Jurafsky2009a} and is used to convert ``a predicate with multiple arguments into a sequence of single-argument predicates''\cite[p.~594]{Jurafsky2009a}.
|
||||
|
||||
After the prerequisites are now explained, it is time to start with the actual syntax-driven semantic analysis. It will be shown with an example provided by Jurafsky. Assume the sentence \textit{Every restaurant closed}. ``The target representation for this example should be the following''\cite[p.~621]{Jurafsky2009}.
|
||||
\subsubsection*{Syntax-driven semantic analysis}
|
||||
\label{subSubSec:syntaxDrivenSemanticAnalysis}
|
||||
|
||||
\begin{equation}
|
||||
\label{eq:tarRep}
|
||||
\forall x \,Restaurant(x) \Rightarrow \exists e \,Closed(e) \wedge ClosedThing(e,x)
|
||||
\end{equation}
|
||||
After the prerequisites are now explained, it is time to start with the actual syntax-driven semantic analysis. It is shown with the previously introduced example and starts there, where the syntactic parsing left.
|
||||
|
||||
The first step is to determine what the meaning representation of \textit{Every restaurant} should be. \textit{Every} is responsible for the $\forall$ quantifier and \textit{restaurant} specifies the category over which is quantified. This is called the ``restriction''\cite[p.~622]{Jurafsky2009} of the noun phrase. The meaning representation could be $\forall x\,Restaurant(x)$. It is a valid logical formula but it doesn't make much sense. ``It says that everything is a restaurant.''\cite[p.~622]{Jurafsky2009} ``Noun phrases like [this] are [usually] embedded in expressions that [say] something about the universally quantified variable. That is, we're probably trying to \textit{say something} about all restaurants. This notion is traditionally referred to as the \textit{NP}'s nuclear scope''\cite[p.~622]{Jurafsky2009}. In the given example, the nuclear scope is \textit{closed}. To represent this notion in the target representation, a dummy predicate $Q$ is added, which results in this expression:
|
||||
\[
|
||||
\forall x\,Restaurant(x) \Rightarrow Q(x)
|
||||
\]
|
||||
To replace $Q$ with something meaningful, the $\lambda$ notation is needed.
|
||||
\[
|
||||
\lambda Q.\forall x\,Restaurant(x) \Rightarrow Q(x)
|
||||
\]
|
||||
After more generalization, this is the result:
|
||||
\[
|
||||
\lambda P.\lambda Q.\forall x\,P(x) \Rightarrow Q(x)
|
||||
\]
|
||||
What happened? The descriptor \textit{every} gets this last expression as semantic attachment. The noun \textit{restaurant} gets $\lambda x.Restaurant(x)$. When combined, the second expression is the result. The verb is still missing. Therefore the verb \textit{closed} gets the following expression.
|
||||
\[
|
||||
\lambda x.\exists e\,Closed(e) \wedge ClosedThing(e,x)
|
||||
\]
|
||||
After combining the formulas of the verb and the noun phrase, the previously shown target representation\eqref{eq:tarRep} is the result.
|
||||
The grammar rules have to be augmented with the semantic attachments. This process goes through all involed rules in a bottom-up way. To remind you of the sentence, here it is again: ``The tree is very high''. The first rule is the $A$ rule, which produces ``The''. The article implies that are is exactly one entity which is therefore easily identified. If there were multiple entities of the same type, ``the'' won't be enough to specify which entity is meant.
|
||||
|
||||
\[
|
||||
A \rightarrow the \;\{\lambda x.\lambda P.\exists x.P(x)\}
|
||||
\]
|
||||
|
||||
The next rule is the one responsible for ``tree''.
|
||||
|
||||
\[
|
||||
N \rightarrow tree \;\{\lambda x.Tree(x)\}
|
||||
\]
|
||||
|
||||
NP is the combination of the two previous rules and will therefore have to combine the meaning somehow. This is done by using the N semantic attachment as argument for the A attachment.
|
||||
|
||||
\[
|
||||
NP \rightarrow A\;N \;\{A.sem(N.sem)\}
|
||||
\]
|
||||
|
||||
Next are the Adjs rules. The first is the one that handles ``very''.
|
||||
|
||||
\[
|
||||
Adjs \rightarrow very \;\{\lambda x.Very(x)\}
|
||||
\]
|
||||
|
||||
It states that there is an adjective that is increased in meaning by ``very''. The rule for ``high'' gets augmented with an attachment that describes a thing that is high.
|
||||
|
||||
\[
|
||||
Adjs \rightarrow high \;\{\lambda x.HighThing(a, x)\}
|
||||
\]
|
||||
|
||||
Here the x stands for an entity that is high. Another Adjs rule brings these two together. To differentiate the semantic attachments of the previous two Adjs rules, the affected adjective is noted in square brackets.
|
||||
|
||||
\[
|
||||
Adjs \rightarrow Adjs\;Adjs \;\{\lambda x.\exists a.Adjs[very].sem(a) \wedge Adjs[high].sem(x) \}
|
||||
\]
|
||||
|
||||
The VP rules are next to be augmented. First comes the one that is responsible for ``is''. ``is'' implies that there is an entity with a state.
|
||||
|
||||
\[
|
||||
VP \rightarrow is \;\{\lambda P.\lambda Q.Q(x) \Rightarrow P(x)\}
|
||||
\]
|
||||
|
||||
In the next step the VP rule for ``is'' and the adjectives are combined. Here applies the same as for the Adjs case. As there are two VP rules, the ``is'' rule is identified by the verb in square brackes. As there are no square brackets after Adjs in the following attachment, the Adjs rule, that combines the adjective rules, is meant.
|
||||
|
||||
\[
|
||||
VP \rightarrow VP\;Adjs \;\{VP[is].sem(Adjs.sem)\}
|
||||
\]
|
||||
|
||||
Last comes the S rule that combines both NP and VP. VP means the rule that combines the ``is'' rule and the Adjs rules.
|
||||
|
||||
\[
|
||||
S \rightarrow NP\;\;VP \;\{VP.sem(NP.sem)\}
|
||||
\]
|
||||
|
||||
With the semantic attachments in place, the final meaning representation can easily be retrieved. The replacement happens from top to bottom, by starting with the semantic attachment from S and going down to the semantic attachments of the rules that produce the actual output. The critical part is the $\lambda$-reduction in the first VP rule. The intermediate steps are shown below.
|
||||
|
||||
\begin{alignat*}{1}
|
||||
\lambda P.\lambda Q.Q(x) \Rightarrow P(x)(\lambda x.\exists a.Adjs[very].sem(a) \wedge Adjs[high].sem(x)) \\
|
||||
\lambda Q.Q(x) \Rightarrow \lambda x.\exists a.Adjs[very].sem(a) \wedge Adjs[high].sem(x)(x) \\
|
||||
\lambda Q.Q(x) \Rightarrow \exists a.Adjs[very].sem(a) \wedge Adjs[high].sem(x) \\
|
||||
\lambda Q.Q(x) \Rightarrow \exists a.\lambda x.Very(x)(a) \wedge Adjs[high].sem(x) \\
|
||||
\lambda Q.Q(x) \Rightarrow \exists a.Very(a) \wedge \lambda x.HighThing(a, x)(x) \\
|
||||
\lambda Q.Q(x) \Rightarrow \exists a.Very(a) \wedge HighThing(a, x) \\
|
||||
\intertext{inserting the NP attachments}
|
||||
\lambda Q.Q(x) \Rightarrow \exists a.Very(a) \wedge HighThing(a, x)(\lambda x.\lambda P.\exists x.P(x)) \\
|
||||
\lambda x.\lambda P.\exists x.P(x)(x) \Rightarrow \exists a.Very(a) \wedge HighThing(a, x)(\lambda x.Tree(x)) \\
|
||||
\exists x.\lambda x.Tree(x)(x) \Rightarrow \exists a.Very(a) \wedge HighThing(a, x) \\
|
||||
\exists x.Tree(x) \Rightarrow \exists a.Very(a) \wedge HighThing(a, x)
|
||||
\end{alignat*}
|
||||
|
||||
The final meaning representation is therefore the following.
|
||||
|
||||
\[
|
||||
\exists x.Tree(x) \Rightarrow \exists a.Very(a) \wedge HighThing(a, x)
|
||||
\]
|
||||
|
||||
If you translate this logic into words, it'd be something similar to this: ``There is a tree that is a high thing, a very high thing''. This complete run-through from the syntactic parsing up to the meaning representation hopefully showed the two presented methods in action and let you understand them better. Furthermore this overarching example should have put you in the situation to follow a critical discussion, which is next in the paper.
|
||||
|
||||
This example is just one of many, but it shows how semantic meaning can be attached to syntactic components. Furthermore it should be clear now, how semantic analysis in a syntax-driven approach works.
|
||||
\section{Critical discussion}
|
||||
\label{sec:critDiscussion}
|
||||
|
||||
%TODO back up every claim (reference after first sentence)
|
||||
|
||||
Now that both methods have been presented with one selected approach each, it is time to discuss them critically. The CYK algorithm solves many problems like ambiguity; at least to a certain degree. But it also is problematic, because of the restriction to CNF. While in theory every context-free grammar can be converted to CNF, in practice it poses ``some non-trivial problems''\cite[p.~475]{Jurafsky2009b}. One of this problems can be explored in conjunction with the second presented method (semantic analysis). ``[T]he conversion to CNF will complicate any syntax-driven approach to semantic analysis''\cite[p.~475]{Jurafsky2009b}. A solution to this problem is some kind of post-processing in which the trees are converted back to the original grammar.\cite{Jurafsky2009b} Another option is to use a more complex dynamic programming algorithm that accepts any kind of context-free grammar. Such an algorithm is the ``Earley Algorithm''\cite[p.~477]{Jurafsky2009b}.
|
||||
|
||||
The syntax-driven semantic analysis, as it has been presented, is a powerful method that is easy to understand. But it has one essential problem. It relies upon an existing set of grammar rules with semantic attachments to them. In a real world example such a table would contain thousands of grammar rules. While it is relatively easy to compute the final meaning representation with such a given table, it is very hard to create the table in the first place. The difficulty to create this table is split into two main issues. The first one being that you must find a grammar specification that fits all your use cases. This problem applies for the syntactic parsing as well. The second issue is that one has to find out the semantic attachments to the grammar rules.
|
||||
The syntax-driven semantic analysis, as it has been presented, is a powerful method that is easy to understand. But it has one essential problem. It relies upon an existing set of grammar rules with semantic attachments to them. In a real world example such a table would contain thousands of grammar rules.\cite{Russel2010} While it is relatively easy to compute the final meaning representation with such a given table, it is very hard to create the table in the first place. The difficulty to create this table is split into two main issues. The first one being that you must find a grammar specification that fits all your use cases. This problem applies for the syntactic parsing as well. The second issue is that one has to find out the semantic attachments to the grammar rules.
|
||||
|
||||
This initial workload to create a state, in which the semantic analysis works, is a unique effort. In a restricted environment with a limited set of words and topics, this workload is of low importance. Even if it takes one month to create such a table by hand or by computing it, the subsequent analysis of input based on this table is rather quick and the initial workload is therefore acceptable. But this is only true for restricted environments. If someone tried to use syntax-driven semantic analysis for the complete language of modern English, the creation of such a table would outweigh any possible usage.
|
||||
This initial workload to create a state, in which the semantic analysis works, is a unique effort.\cite{Jurafsky2009} A restricted environment has a limited set of words and topics compared to an unrestricted environment. An example is a flight check-in automaton that only needs to process a subset of the full English grammar. Therefore this workload is of low importance in such an environment. Even if it takes one month to create such a table by hand or by computing it, the subsequent analysis of input based on this table is rather quick and the initial workload is therefore acceptable. But this is only true for restricted environments. If someone tried to use syntax-driven semantic analysis for the complete language of modern English, the creation of such a table would outweigh any possible usage.
|
||||
|
||||
%TODO three options: add reference to claim, introduce necessary knowledge prior to this point or drop it
|
||||
|
||||
Comparing the complexity of the two methods it shows a mirror-like image. For the parsing the creation of the grammar is comparatively easy. The presented CYK algorithm works with context-free grammars which are a very restricted set compared to natural languages. But even within these context-free grammars there are ambiguities inside the texts themselves. The creation of the parse trees is therefore more of a problem.
|
||||
|
||||
Syntax-driven semantic analysis on the other hand requires a decent amount of work to add semantic attachments to grammar rules. But once this has been done, it works very fast.
|
||||
Syntax-driven semantic analysis on the other hand requires a decent amount of work to add semantic attachments to grammar rules.\cite{Jurafsky2009} But once this has been done, it works very fast.
|
||||
|
||||
Both methods require a unique work for one specific usage. This unique workload is the grammar creation for the parsing and the extension of the grammar with semantic attachments for the semantic analysis. The less restricted the usage environment, the more complex the initial workload becomes. The same is true for the recurring workload inside one specific usage.
|
||||
Both methods require an initial workload for every usage domain. This unique workload is the grammar creation for the parsing and the extension of the grammar with semantic attachments for the semantic analysis. The less restricted the usage environment, the more complex the initial workload becomes. The same is true for the recurring workload for every actual usage inside one usage domain.
|
||||
|
||||
Judging by the state-of-the-art of computer technology, parsing does still pose a significant challenge once the restricted field of programming languages is left. The semantic analysis as the second method in the chain has therefore even more problems to date. As the presented syntax-driven approach does only work with parse trees, a semantic analysis can only be undertaken once the syntactic parsing succeeds.
|
||||
Judging by the state-of-the-art of computer technology, parsing does still pose a significant challenge once the restricted field of programming languages is left. The semantic analysis as the second method in the chain has therefore even more problems to date. As the presented syntax-driven approach does only work with syntactic representations\cite{Jurafsky2009}, a semantic analysis can only be undertaken once the syntactic parsing succeeds.
|
||||
|
||||
The ambiguity remains one of the bigges issues for both methods. Especially the syntax-driven semantic analysis does only consider the semantic meaning alone. It's not it's fault as the analysis doesn't know the context. The presented approach looks at each sentence in a sandbox. The generated meaning representations are therefore only of limited use for a less restricted grammar.
|
||||
|
||||
\section{Conclusion}
|
||||
\label{sec:concl}
|
||||
|
||||
Syntactic parsing is an important method on the way to understand natural language. The usage of dynamic programming algorithms circumvents many of the issues that classical top-down or bottom-up parsing algorithms face. Ambiguity is the most prominent of those issues. The best algorithm for context-free grammars is the CYK algorithm, which is a dynamic programming algorithm. But in practice it is very restricted, because it only works with grammars in CNF. But there are more complex dynamic programming algorithms that allow any kind of context-free grammar.
|
||||
Syntactic parsing is an important method on the way to understand natural language. The usage of dynamic programming algorithms circumvents many of the issues that classical top-down or bottom-up parsing algorithms face. Ambiguity is the most prominent of those issues. The best algorithm for context-free grammars is the CYK algorithm, which is a dynamic programming algorithm. But in practice it is very restricted, because it only works with grammars in CNF. But there are more complex dynamic programming algorithms that allow any kind of context-free grammar. Such an algorithm is the ``Earley Algorithm''\cite[p.~477]{Jurafsky2009b} which was already introduced in the critical discussion.
|
||||
|
||||
Semantic analysis is the second method in the chain to understand natural language and therefore important as well. There are different approaches to the analysis. One of them is the syntax-driven approach that depends on parse trees. This dependency creates a delay effect: As long as a certain peace of text cannot be parsed, it definitely can't be analyzed for it's semantic meaning either. This is not an issue for restricted environments like programming languages or a very restricted subset of a natural language's grammar. But it is a major issue for real natural language, because there already the parsing does pose significant challenges.
|
||||
Semantic analysis is the second method in the chain to understand natural language, as it is presented here, and therefore important as well. There are different approaches to the analysis. One of them is the syntax-driven approach that depends on parse trees. This dependency creates a delay effect: As long as a certain peace of text cannot be parsed, it definitely can't be analyzed for it's semantic meaning either. This is not an issue for restricted environments like programming languages or a very restricted subset of a natural language's grammar. But it is a major issue for real natural language, because there already the parsing does pose significant challenges.
|
||||
|
||||
Looking into the future both methods require substantial improvements on the algorithm side to reach a point where understanding non-restricted natural languages becomes possible. But as it is right now it is not possible to create dialog systems that interact fully natural with humans. To make any kind of language interaction, the set of possible words and sentence structures must be restricted. But even if that is given (like in a flight check-in automaton), the computer has only a finite set of possible cases. The programmer can add tons of if-clauses or comparable statements to check for different cases but in the end it's all finite so that many of the user inputs must lead to the same output or no output at all. This fact has led to the current situation in which the most interaction with a computer happens via a restricted interface in which the user can only choose from a limited set of options (by clicking on a button, selecting an item of a list, etc.).
|
||||
|
||||
In addition the ambiguity of natural language is a major issue. Going back to the example in the introduction, the syntax-driven semantic analysis does only work properly if the semantic meaning of the input has no ambiguity. But even than the generated meaning representation does not represent the pragmatic meaning. A dialog system is therefore far from being reached, because every input of a human can have dozens of different meanings. The intended meaning can sometimes depend on a thought that this human had while typing the input. As the computer doesn't have the ability to read thoughts, it would be impossible for the computer to determine the intended meaning of the input.
|
||||
Furthermore the ambiguity of natural language is a major issue. The solution to it could lie in the understanding of the context. Even though natural language is full of ambiguity, we manage to communicate very successfully. Therefore the solution to ambiguity lies probably somewhere in our brain functionality. Cognitively-inspired methods that don't use traditional AI and First--Order logic but instead are inspired by our brain and try to understand and model natural language based on the context, might as well be the solution to ambiguity altogether. The method presented by Gnjatovic\cite{Gnjatovic2012} could be such a method.
|
||||
|
||||
In a mission critical environment this ambiguity could lead to catastrophic results, because the computer, simply put, ``didn't get it''. This risk limits the usability of natural language communication with a computer for propably a long time to a very restricted set of use cases.
|
||||
|
||||
|
||||
248
se3/G08_B10_Jim-2martens_Britta-2noack_Jan-Simon-0giesel.rkt
Normal file
248
se3/G08_B10_Jim-2martens_Britta-2noack_Jan-Simon-0giesel.rkt
Normal file
@ -0,0 +1,248 @@
|
||||
#lang lazy
|
||||
|
||||
#|
|
||||
SE 3 Funktional Blatt 10
|
||||
Abgebende: Jim 2martens, Britta 2noack, Jan-Simon 0giesel
|
||||
|#
|
||||
|
||||
; 1)
|
||||
|
||||
; 1.1
|
||||
(define (every pred xs)
|
||||
(foldl (λ (x best) (and x best))
|
||||
#t
|
||||
(map pred xs))
|
||||
)
|
||||
|
||||
(define (some pred xs)
|
||||
(foldl (λ (x best)
|
||||
(if [pred x]
|
||||
x
|
||||
best))
|
||||
#f
|
||||
xs)
|
||||
)
|
||||
|
||||
; 1.2
|
||||
(define (symmetrisch? r)
|
||||
(every (λ (x)
|
||||
(some (λ (y)
|
||||
(and (eq? (cdr y)
|
||||
(car x))
|
||||
(eq? (car y)
|
||||
(cdr x))))
|
||||
r))
|
||||
r))
|
||||
|
||||
(define (asymmetrisch? r)
|
||||
(every (λ (x)
|
||||
(let ((t1 (some (λ (y)
|
||||
(and (eq? (cdr y)
|
||||
(car x))
|
||||
(eq? (car y)
|
||||
(cdr x)))
|
||||
))))
|
||||
r))))
|
||||
|
||||
(define (reflexiv? r)
|
||||
(every (λ (x)
|
||||
(and (some (λ (y)
|
||||
(and (eq? (car y)
|
||||
(car x))
|
||||
(eq? (cdr y)
|
||||
(car x))))
|
||||
r)
|
||||
(some (λ (y)
|
||||
(and (eq? (car y)
|
||||
(cdr x))
|
||||
(eq? (cdr y)
|
||||
(cdr x))))
|
||||
r)))
|
||||
r))
|
||||
|
||||
(define (transitiv? r)
|
||||
(every (λ (x)
|
||||
(let ((t1 (some (λ (y)
|
||||
(and (eq? (cdr x)
|
||||
(car y))
|
||||
(not (eq? (cdr x)
|
||||
(cdr y)))))
|
||||
r)))
|
||||
(if t1
|
||||
(some (λ (z)
|
||||
(and (eq? (car x)
|
||||
(car z))
|
||||
(eq? (cdr t1)
|
||||
(cdr z))))
|
||||
r)
|
||||
#t)))
|
||||
r))
|
||||
|
||||
(define (aequi? r)
|
||||
(and (reflexiv? r)
|
||||
(symmetrisch? r)
|
||||
(transitiv? r)))
|
||||
|
||||
(define (ord? r)
|
||||
(and (reflexiv? r)
|
||||
(not (symmetrisch? r))
|
||||
(transitiv? r)))
|
||||
; 2)
|
||||
|
||||
; 1.
|
||||
(define (Kreuzprodukt m1 m2)
|
||||
(letrec ((inner (λ (x ys acc)
|
||||
(if (empty? ys)
|
||||
acc
|
||||
(inner x
|
||||
(cdr ys)
|
||||
(cons (list x
|
||||
(car ys))
|
||||
acc)))))
|
||||
(outer (λ (xs ys acc)
|
||||
(if (empty? xs)
|
||||
acc
|
||||
(outer (cdr xs)
|
||||
ys
|
||||
(inner (car xs)
|
||||
ys
|
||||
acc))))))
|
||||
(outer (reverse m1) (reverse m2) '())))
|
||||
|
||||
; 2.
|
||||
|
||||
;(define (Produkt xs)
|
||||
|
||||
; 3.
|
||||
; abhängig von k machen.
|
||||
(define (Kombination k M)
|
||||
(letrec ((inner (λ (x ys acc)
|
||||
(if (empty? ys)
|
||||
acc
|
||||
(inner x
|
||||
(cdr ys)
|
||||
(cons (list x (car ys))
|
||||
acc)))))
|
||||
(outer (λ (xs acc)
|
||||
(if (empty? xs)
|
||||
acc
|
||||
(outer (cdr xs)
|
||||
(inner (car xs)
|
||||
(cdr xs)
|
||||
acc))))))
|
||||
(reverse (outer M '()))))
|
||||
|
||||
|
||||
; 3)
|
||||
|
||||
; 1.
|
||||
|
||||
; (a) -> -1, weil 2-3 = -1 und -1 < 2 und -1 >= -1
|
||||
; (b) -> '(+ -2 2), weil quasi-quote und (- 2 4) dennoch ausgeführt wird (wg. ,)
|
||||
; (c) -> Alle, weil Alle erstes Element der Liste
|
||||
; (d) -> '(auf (dem See))
|
||||
; (e) -> '(Listen sind einfach)
|
||||
; (f) -> '(Paare . auch)
|
||||
; (g) -> #t, da beide Listen gleiche Werte haben
|
||||
; (h) -> #f, da die beiden Listen nicht identisch sind
|
||||
; (i) -> '(1 8 27)
|
||||
; (j) -> '(1 3 5)
|
||||
; (k) -> 2, da 2 < 6
|
||||
; (l) -> #t, da 2 = 2
|
||||
|
||||
; 2.
|
||||
|
||||
; *a* hat ein wohldefinierten Wert und evaluiert zu 10
|
||||
; (+ *a* *b*) hat keinen wohldefinierten Wert
|
||||
; (+ (eval *a*) (eval *b*)) hat keinen wohldefinierten Wert
|
||||
; (and (> *a* 10) (> *b* 3)) hat wohldefinierten Wert und evaluiert zu #f
|
||||
; (or (> *a* 10) (/ *a* 0)) hat keinen wohldefinierten Wert
|
||||
; (+ 2 (merke 3)) hat keinen wohldefinierten Wert
|
||||
; (+ 2 ((merke 3))) hat einen wohldefinierten Wert und evaluiert zu 5
|
||||
; (test 4) hat keinen wohldefinierten Wert
|
||||
|
||||
; 3.
|
||||
; (a)
|
||||
(+ (* 3 4) (* 5 6))
|
||||
; (b)
|
||||
(define wurzel (λ (x) (sqrt (- 1 (sqr (sin x))))))
|
||||
|
||||
; 4.
|
||||
(define (c a b)
|
||||
(sqrt (+ (sqr a) (sqr b))))
|
||||
(define (mythan a)
|
||||
(/ (sin a)
|
||||
(sqrt (- 1 (sqr (sin a))))))
|
||||
|
||||
; 5.
|
||||
; (a)
|
||||
(- (+ 1 (/ 4 2)) 1)
|
||||
; (b)
|
||||
(/ (- 2 (/ (+ 1 3) (+ 3 (* 2 3)))) (sqrt 3))
|
||||
|
||||
; 6.
|
||||
; (1 + 2 + 3) * (2 - 3 - (2 - 1))
|
||||
|
||||
; 7.
|
||||
(define (laengen xss)
|
||||
(map length xss))
|
||||
|
||||
(define (laengenRekEnd xss)
|
||||
(letrec ((rec (λ (xs acc)
|
||||
(if (empty? xs)
|
||||
acc
|
||||
(rec (cdr xs)
|
||||
(cons (length (car xs))
|
||||
acc))))))
|
||||
(reverse (rec xss '()))))
|
||||
|
||||
(define (laengenRekNorm xss)
|
||||
(if (empty? xss)
|
||||
'()
|
||||
(cons (length (car xss))
|
||||
(laengenRekNorm (cdr xss)))))
|
||||
|
||||
|
||||
; 8.
|
||||
; (a)
|
||||
(define (make-length value unit)
|
||||
(list value unit))
|
||||
; (b)
|
||||
(define (value-of-length len)
|
||||
(car len))
|
||||
(define (unit-of-length len)
|
||||
(cadr len))
|
||||
; (c)
|
||||
(define (scale-length len fac)
|
||||
(list (* (car len) fac) (cadr len)))
|
||||
; (d)
|
||||
(define *conversiontable* ;
|
||||
'( ; (unit . factor)
|
||||
(m . 1)
|
||||
(cm . 0.01)
|
||||
(mm . 0.001)
|
||||
(km . 1000)
|
||||
(inch . 0.0254)
|
||||
(feet . 0.3048)
|
||||
(yard . 0.9144)))
|
||||
(define (factor unit)
|
||||
(cdr (assoc unit *conversiontable*)))
|
||||
(define (length->meter len)
|
||||
(list (car (scale-length len (factor (cadr len))))
|
||||
'm))
|
||||
(define (length< len1 len2)
|
||||
(< (car (length->meter len1)) (car (length->meter len2))))
|
||||
(define (length= len1 len2)
|
||||
(= (car (length->meter len1)) (car (length->meter len2))))
|
||||
(define (length+ len1 len2)
|
||||
(list (+ (car (length->meter len1)) (car (length->meter len2)))
|
||||
'm))
|
||||
(define (length- len1 len2)
|
||||
(list (- (car (length->meter len1)) (car (length->meter len2)))
|
||||
'm))
|
||||
; (e)
|
||||
(define xs '((6 km) (2 feet) (1 cm) (3 inch)))
|
||||
|
||||
(map length->meter xs)
|
||||
(filter (λ (x) (< (car x) 1)) (map length->meter xs))
|
||||
(foldl (λ (x best) (+ (car x) best)) 0 (map length->meter xs))
|
||||
95
se3/G08_B11_Jim-2martens_Britta-2noack_Jan-Simon-0giesel.rkt
Normal file
95
se3/G08_B11_Jim-2martens_Britta-2noack_Jan-Simon-0giesel.rkt
Normal file
@ -0,0 +1,95 @@
|
||||
#lang lazy
|
||||
|
||||
#|
|
||||
SE 3 Funktional Blatt 11
|
||||
Abgebende: Jim 2martens, Britta 2noack, Jan-Simon 0giesel
|
||||
|#
|
||||
|
||||
(require (lib "prologDB.ss" "se3-bib" "prolog")
|
||||
(lib "unify.ss" "se3-bib" "prolog")
|
||||
(lib "prolog.ss" "se3-bib" "prolog")
|
||||
(lib "prologInScheme.ss" "se3-bib" "prolog"))
|
||||
(require racket/stream)
|
||||
|
||||
; 1)
|
||||
|
||||
; 1.1
|
||||
|
||||
; Ausdruck1 | Variablenbindungen:
|
||||
; Ausdruck2
|
||||
|
||||
; (gebaeude ?Haus weiss) | '((?Farbe . weiss) (?Haus . Informatikum))
|
||||
; (gebaeude Informatikum ?Farbe)
|
||||
|
||||
; (Karten ((k Pik As) (k Herz Dame))) | #f
|
||||
; (Karten ((k Pik As) (k Herz Koenig)))
|
||||
|
||||
; (Karten ((k Pik As) (k Herz Dame))) | '((?Farbe . Dame))
|
||||
; (Karten ((k Pik As) (k Herz ?Farbe)))
|
||||
|
||||
; (Karten ((k Pik As) (k Herz Dame))) | '((?Farbe . Dame))
|
||||
; (Karten ((k Pik As) (k Herz ?Farbe)))
|
||||
|
||||
; (Karten ((k Pik As) . ?andere)) | '((?andere (k Herz Koenig) (k Kreuz Dame)))
|
||||
; (Karten ((k Pik As) (k Herz Koenig) (k Kreuz Dame)))
|
||||
|
||||
; (Paar (k ?farbe As) (k Pik ?wert)) | '((?wert . As) (?farbe . Pik))
|
||||
; (Paar (k Pik ?wert) (k ?farbe As))
|
||||
|
||||
; (Paar (k ?farbe As) (k Pik ?wert2)) | '((?wert2 . As) (?wert . As) (?farbe . Pik))
|
||||
; (Paar (k Pik ?wert) (k ?farbe ?wert))
|
||||
|
||||
; 1.2
|
||||
(<- (ausleihe "K 110" 100))
|
||||
(<- (ausleihe "P 30" 102))
|
||||
(<- (ausleihe "P 32" 104))
|
||||
(<- (ausleihe "P 50" 104))
|
||||
; (vorbestellung Signatur Lesernummer)
|
||||
(<- (vorbestellung "K 110" 104))
|
||||
(<- (vorbestellung "K 110" 102))
|
||||
(<- (vorbestellung "P 30" 100))
|
||||
(<- (vorbestellung "P 30" 104))
|
||||
; (leser Name Vorname Lesernummer Geburtsjahr)
|
||||
(<- (leser Neugierig Nena 100 1989))
|
||||
(<- (leser Linux Leo 102 1990))
|
||||
(<- (leser Luator Eva 104 1988))
|
||||
|
||||
; 1.
|
||||
; Im interactions view laufen alle Abfragen. Einige jedoch laufen nicht hier.
|
||||
|
||||
|
||||
;(?- (ausleihe "K 110" ?))
|
||||
|
||||
; 2.
|
||||
;(?- (leser Linux Leo ?lesernummer ?))
|
||||
|
||||
; 3.
|
||||
;(?- (vorbestellung "P 30" ?lesernummer)
|
||||
; (leser ?nachname ?vorname ?lesernummer ?))
|
||||
|
||||
; 4.
|
||||
;(?- (test (< ?jahr 1954))
|
||||
; (leser ?nachname ?vorname ?lesernummer ?geburtsjahr)
|
||||
; (ausleihe ? ?lesernummer))
|
||||
|
||||
; 5.
|
||||
;(?- (leser ?nachname ?vorname ?lesernummer ?)
|
||||
; (count ?c (ausleihe ? ?lesernummer))
|
||||
; (test (> ?c 1)))
|
||||
|
||||
; 2)
|
||||
|
||||
(define memo-fac (memo fac))
|
||||
|
||||
; 3)
|
||||
(define natNumb (in-naturals 1))
|
||||
(define evilSeven (stream-map (λ (x)
|
||||
(if (or
|
||||
(= [modulo x 7] 0)
|
||||
(pair? (member #\7
|
||||
(string->list (number->string x)))))
|
||||
'sum
|
||||
x))
|
||||
natNumb))
|
||||
|
||||
|
||||
72
se3/G08_B12_Jim-2martens_Britta-2noack_Jan-Simon-0giesel.rkt
Normal file
72
se3/G08_B12_Jim-2martens_Britta-2noack_Jan-Simon-0giesel.rkt
Normal file
@ -0,0 +1,72 @@
|
||||
#lang racket
|
||||
|
||||
#|
|
||||
SE 3 Funktional Blatt 12
|
||||
Abgebende: Jim 2martens, Britta 2noack, Jan-Simon 0giesel
|
||||
|#
|
||||
|
||||
; 1)
|
||||
|
||||
; 1.
|
||||
(define (wert-rec xs)
|
||||
(letrec ((rec (λ (ys potenz acc)
|
||||
(if (empty? ys)
|
||||
acc
|
||||
(rec
|
||||
(cdr ys)
|
||||
(+ 1 potenz)
|
||||
(+ (* (car ys) (expt 10 potenz)) acc))))))
|
||||
(rec xs 0 0)))
|
||||
; 2.
|
||||
(define (wert-higher xs)
|
||||
(foldl
|
||||
+
|
||||
0
|
||||
(map * xs
|
||||
(let ((l (length xs)))
|
||||
(letrec ((rec (λ (x acc)
|
||||
(if (= x 0) acc
|
||||
(rec (- x 1)
|
||||
(cons
|
||||
(expt 10 (- x 1))
|
||||
acc))))))
|
||||
(rec l '()))))
|
||||
))
|
||||
|
||||
; 2)
|
||||
|
||||
; 2.1
|
||||
(define kryptoStructure
|
||||
'((A . 1)
|
||||
(B . 2)
|
||||
(C . 3)
|
||||
(D . 4)
|
||||
(E . 5)
|
||||
(F . 6)
|
||||
(G . 7)
|
||||
(H . 8)
|
||||
(I . 9)
|
||||
(J . 10)
|
||||
(K . 11)
|
||||
(L . 12)
|
||||
(M . 13)
|
||||
(N . 14)
|
||||
(O . 15)
|
||||
(P . 16)
|
||||
(Q . 17)
|
||||
(R . 18)
|
||||
(S . 19)
|
||||
(T . 20)
|
||||
(U . 21)
|
||||
(V . 22)
|
||||
(W . 23)
|
||||
(X . 24)
|
||||
(Y . 25)
|
||||
(Z . 26)))
|
||||
|
||||
(define (key->wert key struktur)
|
||||
(cdr (assoc key struktur)))
|
||||
|
||||
; 2.2
|
||||
|
||||
(andmap (λ (x) #t) '(1 2 3))
|
||||
31
se3/probeklausur0809.rkt
Normal file
31
se3/probeklausur0809.rkt
Normal file
@ -0,0 +1,31 @@
|
||||
#lang swindle
|
||||
|
||||
(require swindle/setf
|
||||
swindle/misc)
|
||||
|
||||
; CLOS
|
||||
|
||||
(defclass* messgeraet ())
|
||||
(defgeneric* einheit ((messgeraet))
|
||||
:combination generic-append-combination)
|
||||
(defgeneric* messwert ((messgeraet))
|
||||
:combination generic-append-combination)
|
||||
(defgeneric* genauigkeit ((messgeraet))
|
||||
:combination generic-min-combination)
|
||||
|
||||
(defclass* thermometer (messgeraet))
|
||||
(defclass* barometer (messgeraet))
|
||||
(defclass* regenmesser (messgeraet))
|
||||
|
||||
(defclass* wetterstation (thermometer barometer regenmesser))
|
||||
|
||||
; Logik
|
||||
|
||||
(?- (kamera ?kamID ? ? 24 ?))
|
||||
(?- (kamera ?kamID ? ? 18 ?)
|
||||
(angebot ?kamID ? ?preis))
|
||||
(?- (anbieter ?anbID ?anbName ?lieferzeit ? ?)
|
||||
(test (<= ?lieferzeit 1))
|
||||
(angebot ?kamID ?anbID ?)
|
||||
(kamera ?kamID ?kameraname ?hersteller ? ?))
|
||||
|
||||
Reference in New Issue
Block a user