2
0
Fork 0
mirror of https://github.com/MartinThoma/LaTeX-examples.git synced 2025-04-26 06:48:04 +02:00

Remove trailing spaces

The commands

find . -type f -name '*.md' -exec sed --in-place 's/[[:space:]]\+$//' {} \+

and

find . -type f -name '*.tex' -exec sed --in-place 's/[[:space:]]\+$//' {} \+

were used to do so.
This commit is contained in:
Martin Thoma 2015-10-14 14:25:34 +02:00
parent c578b25d2f
commit 7740f0147f
538 changed files with 3496 additions and 3496 deletions

View file

@ -79,12 +79,12 @@ In C gibt es keinen direkten Support für Booleans.
\subsection{Logische Operatoren}
\begin{table}[H]
\centering
\centering
\begin{tabular}{CCCC}
UND & ODER & Wahr & Falsch \\ \hline\hline
\&\& & || & 1 & 0 \\[4ex]
GLEICH & UNGLEICH & NICHT & ~ \\ \hline\hline
== & != & ! & ~ \\
== & != & ! & ~ \\
\end{tabular}
\caption{Logische Operatoren in C}\xindex{Logische Operatoren!C}
\end{table}

View file

@ -17,10 +17,10 @@ Jedoch gibt es verschiedene Ebenen der Interpretation bzw. Übersetzung:
\item \textbf{Vollständige Übersetzung}: C, C++, Fortran
\end{enumerate}
Zu sagen, dass Python eine interpretierte Sprache ist, ist in etwa so korrekt
Zu sagen, dass Python eine interpretierte Sprache ist, ist in etwa so korrekt
wie zu sagen, dass die Bibel ein Hardcover-Buch ist.\footnote{Quelle: stackoverflow.com/a/2998544, danke Alex Martelli für diesen Vergleich.}
Reine Interpretierer lesen den Quelltext Anweisung für Anweisung und führen
Reine Interpretierer lesen den Quelltext Anweisung für Anweisung und führen
diese direkt aus.
\todo[inline]{Bild}
@ -57,7 +57,7 @@ Laufzeitübersetzung. Folgendes sind Vor- bzw. Nachteile von Just-in-time Compil
\begin{itemize}
\item Der C-Code ist 83 Byte groß,
\item der Java-Codee ist 123 Byte groß,
\item der Java-Codee ist 123 Byte groß,
\item der generierte Java Bytecode ist 416 Byte groß und
\item der erzeugt Maschinencode aus C ist 8565 Byte groß.
\end{itemize}
@ -107,10 +107,10 @@ zusammengefasst werden.
TODO: Bild einfügen
Zu jedem regulären Ausdruck im Sinne der theoretischen Informatik kann ein
nichtdeterministischer Automat generiert werden. Dieser kann mittels
Potenzmengenkonstruktion\footnote{\url{http://martin-thoma.com/potenzmengenkonstruktion/}}
in einen deterministischen Automaten überführen. Dieser kann dann mittels
Zu jedem regulären Ausdruck im Sinne der theoretischen Informatik kann ein
nichtdeterministischer Automat generiert werden. Dieser kann mittels
Potenzmengenkonstruktion\footnote{\url{http://martin-thoma.com/potenzmengenkonstruktion/}}
in einen deterministischen Automaten überführen. Dieser kann dann mittels
Äquivalenzklassen minimiert werden.
\todo[inline]{Alle Schritte beschreiben}
@ -124,7 +124,7 @@ Eine Flex-Datei besteht aus 3 Teilen, die durch \texttt{\%\%} getrennt werden:
\begin{verbatim}
Definitionen: Definiere Namen
%%
Regeln: Definiere reguläre Ausdrücke und
Regeln: Definiere reguläre Ausdrücke und
zugehörige Aktionen (= Code)
%%
Code: zusätzlicher Code
@ -153,8 +153,8 @@ Code: zusätzlicher Code
\section{Syntaktische Analyse}\xindex{Analyse!syntaktische}%
In der syntaktischen Analyse wird überprüft, ob die Tokenfolge zur
kontextfreien Sprache\todo{Warum kontextfrei?} gehört. Außerdem soll die
In der syntaktischen Analyse wird überprüft, ob die Tokenfolge zur
kontextfreien Sprache\todo{Warum kontextfrei?} gehört. Außerdem soll die
hierarchische Struktur der Eingabe erkannt werden.\todo{Was ist gemeint?}
Ausgegeben wird ein \textbf{abstrakter Syntaxbaum}\xindex{Syntaxbaum!abstrakter}.
@ -227,7 +227,7 @@ Dabei sind viele Optimierungen vorstellbar. Ein paar davon sind:
\end{itemize}
\section{Codegenerierung}
Der letzte Schritt besteht darin, aus dem generiertem Zwischencode den
Der letzte Schritt besteht darin, aus dem generiertem Zwischencode den
Maschinencode oder Assembler zu erstellen. Dabei muss folgendes beachtet werden:
\begin{itemize}
\item \textbf{Konventionen}: Wie werden z.~B. im Laufzeitsystem Methoden aufgerufen?
@ -246,7 +246,7 @@ Maschinencode oder Assembler zu erstellen. Dabei muss folgendes beachtet werden:
Dann heißt $\tilde{x} \in (\Sigma \cup \Set{\#})^+$ ein $k$-\textbf{Anfang} von $x$,
wenn gilt:
\[\tilde{x} =
\[\tilde{x} =
\begin{cases}
x\# &\text{falls } x = x_1 \dots x_m \text{ und } m < k\\
x_1 \dots x_k &\text{sonst}
@ -292,12 +292,12 @@ Maschinencode oder Assembler zu erstellen. Dabei muss folgendes beachtet werden:
\end{defenum}
\end{definition}
Die $\First_k(x)$-Menge beinhaltet also alle Terminalfolgen, die entweder $k$
Die $\First_k(x)$-Menge beinhaltet also alle Terminalfolgen, die entweder $k$
Terminale lang sind oder kürzer sind und dafür mit \# enden und die zugleich
der Anfang von Ableitungen von $x$ sind.
Die $\Follow_k(x)$-Menge hingegen hat alle Terminalfolgen der Länge $k$ oder kürzer
und dafür mit \# am Ende, die aus einer Ableitung des Startsymbols $S \Rightarrow^* mxy$
und dafür mit \# am Ende, die aus einer Ableitung des Startsymbols $S \Rightarrow^* mxy$
auf die Teilfolge $x$ folgen können.
Mit der $\Follow_k(x)$-Menge kann man also zu jedem Zeitpunkt sagen, was momentan

View file

@ -56,14 +56,14 @@ Man schreibt:
\end{beispiel}
\begin{definition}[Kontextfreie Grammatik]\xindex{Grammatik!Kontextfreie}%
Eine Grammatik $(\Sigma, V, P, S)$ heißt \textbf{kontextfrei}, wenn für
Eine Grammatik $(\Sigma, V, P, S)$ heißt \textbf{kontextfrei}, wenn für
jede Produktion $p: I \rightarrow r$ gilt: $I \in V$.
\end{definition}
\begin{definition}[Sprache]\xindex{Sprache}%
Sei $G = (\Sigma, V, P, S)$ eine Grammatik. Dann ist
\[L(G) := \Set{\omega \in \Sigma^* | S \Rightarrow^* \omega}\]
die Menge aller in der Grammatik ableitbaren Wörtern. $L(G)$ heißt Sprache
die Menge aller in der Grammatik ableitbaren Wörtern. $L(G)$ heißt Sprache
der Grammatik $G$.
\end{definition}
@ -114,5 +114,5 @@ bezeichnet wird.
\begin{satz}
Für linksrekursive, kontextfreie Grammatiken $G$ gilt:
\[\forall k \in \mathbb{N}: G \notin \SLL(k)\]
\[\forall k \in \mathbb{N}: G \notin \SLL(k)\]
\end{satz}

View file

@ -1,7 +1,7 @@
%!TEX root = Programmierparadigmen.tex
\chapter{Haskell}
\index{Haskell|(}
Haskell ist eine funktionale Programmiersprache, die 1990 in Version~1.0 veröffentlicht
Haskell ist eine funktionale Programmiersprache, die 1990 in Version~1.0 veröffentlicht
wurde. Namensgeber ist Haskell Brooks Curry, der die mathematischen Grundlagen der funktionalen Programmierung entwickelte.
Wichtige Konzepte sind:
@ -13,8 +13,8 @@ Wichtige Konzepte sind:
\item Typinferenz
\end{enumerate}
Haskell kann mit \enquote{Glasgow Haskell Compiler} mittels
\texttt{ghci} interpretiert und mittels
Haskell kann mit \enquote{Glasgow Haskell Compiler} mittels
\texttt{ghci} interpretiert und mittels
\section{Erste Schritte}
Haskell kann unter \href{http://www.haskell.org/platform/}{\path{www.haskell.org/platform/}}
@ -41,7 +41,7 @@ definiert:
\inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/einfaches-beispiel-klammern.hs}
Die Funktionsdeklarationen mit den Typen sind nicht notwendig, da
Die Funktionsdeklarationen mit den Typen sind nicht notwendig, da
die Typen aus den benutzten Funktionen abgeleitet werden.
Zu lesen ist die Deklaration wie folgt:
@ -113,7 +113,7 @@ den Index 0.
\inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/listenoperationen.sh}
\subsubsection{List-Comprehensions}\xindex{List-Comprehension}%
List-Comprehensions sind kurzschreibweisen für Listen, die sich an
List-Comprehensions sind kurzschreibweisen für Listen, die sich an
der Mengenschreibweise in der Mathematik orientieren. So entspricht
die Menge
\begin{align*}
@ -176,12 +176,12 @@ Das doppelte Plus (\texttt{++}) wird verwendet um Listen mit einander zu verbind
\subsection{Logische Operatoren}\xindex{Haskell!Logische Operatoren}
\begin{table}[H]
\centering
\centering
\begin{tabular}{CCCC}
UND & ODER & Wahr & Falsch \\ \hline\hline
\&\& & || & True & False \\[4ex]
GLEICH & UNGLEICH & NICHT & ~ \\ \hline\hline
== & /= & not & ~ \\
== & /= & not & ~ \\
\end{tabular}
\caption{Logische Operatoren in Haskell}\xindex{Logische Operatoren!Haskell}
\end{table}
@ -191,7 +191,7 @@ Das doppelte Plus (\texttt{++}) wird verwendet um Listen mit einander zu verbind
Haskell kennt einige Basis-Typen:
\begin{itemize}
\item \textbf{Int}: Ganze Zahlen. Der Zahlenbereich kann je nach Implementierung variieren,
aber der Haskell-Standart garantiert, dass das Intervall
aber der Haskell-Standart garantiert, dass das Intervall
$[-2^{29}, 2^{29}-1]$ abgedeckt wird.
\item \textbf{Integer}: beliebig große ganze Zahlen
\item \textbf{Float}: Fließkommazahlen
@ -257,7 +257,7 @@ Haskell wertet Ausdrücke nur aus, wenn es nötig ist.
\begin{itemize}
\item Die leere Liste ergibt sortiert die leere Liste.
\item Wähle das erste Element \texttt{p} als Pivotelement und
teile die restliche Liste \texttt{ps} in kleinere und
teile die restliche Liste \texttt{ps} in kleinere und
gleiche sowie in größere Elemente mit \texttt{filter} auf.
Konkateniere diese beiden Listen mit \texttt{++}.
\end{itemize}
@ -314,7 +314,7 @@ Einen allgemeinen Baum so:
Hier ist \texttt{t} der polymorphe Typ des Baumes. \texttt{t} gibt also an welche
Elemente der Baum enthält.
Man kann auf einem solchen Baum auch eine Variante von \texttt{map} und
Man kann auf einem solchen Baum auch eine Variante von \texttt{map} und
\texttt{reduce} definieren,
also eine Funktion \texttt{mapT}, die eine weitere Funktion \texttt{f} auf jeden
Knoten anwendet:

View file

@ -107,7 +107,7 @@ Weitere if-Abfragen haben das Schema
\item $1 + 2$ nutzt die Infix-Notation.
\item $f\ a\ b$ nutzt die polnische Notation.
\item Wir der Ausdruck $1 + 2 \cdot 3$ in Infix-Notation ohne Operatoren-Präzedenz
ausgewertet, so gilt:
ausgewertet, so gilt:
\[1 + 2 \cdot 3 = 9\]
Wird er mit Operatoren-Präzendenz ausgewertet, so gilt:
\[1 + 2 \cdot 3 = 7\]
@ -124,7 +124,7 @@ Weitere if-Abfragen haben das Schema
\begin{bemerkung}[Eigenschaften der Prä- und Postfixnotation]
\begin{bemenum}
\item Die Reihenfolge der Operanden kann beibehalten und gleichzeitig
auf Klammern verzichtet werden, ohne dass sich das Ergebnis
auf Klammern verzichtet werden, ohne dass sich das Ergebnis
verändert.
\item Die Infix-Notation kann in einer Worst-Case Laufzeit von $\mathcal{O}(n)$,
wobei $n$ die Anzahl der Tokens ist mittels des

View file

@ -10,10 +10,10 @@ die auf mehreren Prozessoren laufen.
\texttt{Interface Runnable}\xindex{Runnable}\\
\-\hspace{0.8cm}$\leftharpoonup$ \texttt{java.lang.Thread}%
\begin{itemize}
\item Methods:
\item Methods:
\begin{itemize}
\item \texttt{void run()}: When an object implementing interface
Runnable is used to create a thread, starting the thread causes the
\item \texttt{void run()}: When an object implementing interface
Runnable is used to create a thread, starting the thread causes the
object's run method to be called in that separately executing thread.
\end{itemize}
\end{itemize}
@ -37,12 +37,12 @@ die auf mehreren Prozessoren laufen.
\texttt{Interface Callable<V>}\xindex{Callable}\\
\-\hspace{0.8cm}$\leftharpoonup$ \texttt{java.util.concurrent}
\begin{itemize}
\item Parameter:
\item Parameter:
\begin{itemize}
\item \texttt{V} - the result type of method \texttt{call()}
\end{itemize}
\item Ermöglicht die Rückgabe von Ergebnissen
\end{itemize}
\end{itemize}
\begin{beispiel}[Callable\footnotemark]
\inputminted[numbersep=5pt, tabsize=4]{java}{scripts/java/callable-example.java}

View file

@ -52,7 +52,7 @@ Die Funktionsapplikation sei linksassoziativ. Es gilt also:
\end{definition}
\begin{definition}[$\alpha$-Äquivalenz]\xindex{Reduktion!Alpha ($\alpha$)}\xindex{Äquivalenz!Alpha ($\alpha$)}%
Zwei Terme $T_1, T_2$ heißen $\alpha$-Äquivalent, wenn $T_1$ durch
Zwei Terme $T_1, T_2$ heißen $\alpha$-Äquivalent, wenn $T_1$ durch
konsistente Umbenennung in $T_2$ überführt werden kann.
Man schreibt dann: $T_1 \overset{\alpha}{=} T_2$.
@ -115,7 +115,7 @@ Das bezeichnet die Lazy-Evaluation von booleschen Ausdrücken.
\begin{beispiel}[Sharing]
In dem Ausdruck \texttt{(plus, (fac, 42), (fac, 42))} muss der Teilausdruck
\texttt{(fac, 42)} nicht zwei mal ausgewertet werden, wenn er Seiteneffektfrei
\texttt{(fac, 42)} nicht zwei mal ausgewertet werden, wenn er Seiteneffektfrei
ist.
\end{beispiel}
@ -128,7 +128,7 @@ Die Call-By-Value Auswertungsreihenfolge wird in C und Java verwendet.
Auch in Haskell werden arithmetische Ausdrücke in der Call-By-Name Auswertungsreihenfolge reduziert.
\section{Church-Zahlen}\xindex{Church-Zahlen}
Im $\lambda$-Kalkül lässt sich jeder mathematische Ausdruck darstellen, also
Im $\lambda$-Kalkül lässt sich jeder mathematische Ausdruck darstellen, also
insbesondere beispielsweise auch $\lambda x. x+3$. Aber \enquote{$3$} und
\enquote{$+$} ist hier noch nicht das $\lambda$-Kalkül.
@ -152,7 +152,7 @@ Auch die gewohnten Operationen lassen sich so darstellen.
\succ :&= \lambda n f z. f (n f z)\\
&= \lambda n. (\lambda f (\lambda z f (n f z)))
\end{align*}
Dabei ist $n$ die Zahl.
Dabei ist $n$ die Zahl.
Will man diese Funktion anwenden, sieht das wie folgt aus:
\begin{align*}
@ -223,7 +223,7 @@ zurückgibt:
\begin{beispiel}[Fixpunkt]
\begin{bspenum}
\item $f_1: \mdr \rightarrow \mdr; f(x) = x^2 \Rightarrow x_1 = 0$ ist
\item $f_1: \mdr \rightarrow \mdr; f(x) = x^2 \Rightarrow x_1 = 0$ ist
Fixpunkt von $f$, da $f(0) = 0$. $x_2 = 1$ ist der einzige weitere
Fixpunkt dieser Funktion.
\item $f_2: \mdn \rightarrow \mdn$ hat ganz $\mdn$ als Fixpunkte, also

View file

@ -6,7 +6,7 @@ Folgendes ist von \url{http://de.wikipedia.org/wiki/Pr%C3%A4dikatenlogik_erster_
Die Prädikatenlogik erster Stufe ist ein Teilgebiet der mathematischen Logik. Sie befasst sich mit der Struktur gewisser mathematischer Ausdrücke und dem logischen Schließen, mit dem man von derartigen Ausdrücken zu anderen gelangt. Dabei gelingt es, sowohl die Sprache als auch das Schließen rein syntaktisch, das heißt ohne Bezug zu mathematischen Bedeutungen, zu definieren.
[...]
Wir beschreiben hier die verwendete Sprache auf rein syntaktische Weise, das heißt wir legen die betrachteten Zeichenketten, die wir Ausdrücke der Sprache nennen wollen, ohne Bezug auf ihre Bedeutung fest.
Wir beschreiben hier die verwendete Sprache auf rein syntaktische Weise, das heißt wir legen die betrachteten Zeichenketten, die wir Ausdrücke der Sprache nennen wollen, ohne Bezug auf ihre Bedeutung fest.
\subsection{Symbole}
Eine Sprache erster Stufe wird aus folgenden Symbolen aufgebaut:
@ -14,8 +14,8 @@ Eine Sprache erster Stufe wird aus folgenden Symbolen aufgebaut:
\begin{itemize}
\item $\forall, \exists, \land, \lor, \rightarrow, \leftrightarrow, \neg, (, ), \equiv$
\item sogenannte Variablensymbole $v_0,v_1,v_2,\ldots$,
\item eine (möglicherweise leere) Menge $\mathcal C$ von Konstantensymbolen,
\item eine (möglicherweise leere) Menge $\mathcal F$ von Funktionssymbolen,
\item eine (möglicherweise leere) Menge $\mathcal C$ von Konstantensymbolen,
\item eine (möglicherweise leere) Menge $\mathcal F$ von Funktionssymbolen,
\item eine (möglicherweise leere) Menge $\mathcal R$ von Relationssymbolen.
\end{itemize}

View file

@ -2,14 +2,14 @@
\chapter{MPI}
\index{MPI|(}
Message Passing Interface (kurz: MPI) ist ein Standard,
der den Nachrichtenaustausch bei parallelen Berechnungen auf
Message Passing Interface (kurz: MPI) ist ein Standard,
der den Nachrichtenaustausch bei parallelen Berechnungen auf
verteilten Computersystemen beschreibt.
Prozesse kommunizieren in MPI über sog. \textit{Kommunikatoren}. Ein Kommunikator
(\texttt{MPI\_Comm}\xindex{MPI\_Comm@\texttt{MPI\_Comm}})
definiert eine Menge an Prozessen, die miteinander kommunizieren können. In dieser
Prozessgruppe hat jeder Prozess einen eindeutigen \textit{rank}\xindex{rank} über den die Prozesse
Prozessgruppe hat jeder Prozess einen eindeutigen \textit{rank}\xindex{rank} über den die Prozesse
sich identifizieren können.
\section{Erste Schritte}
@ -71,12 +71,12 @@ Senden einer Nachricht an einen anderen Prozeß innerhalb eines Kommunikators. (
\textbf{Parameter}
\begin{itemize}
\item \textbf{buf}: Anfangsadresse des Sendepuffers
\item \textbf{count}: Anzahl der Elemente des Sendepuffers (nichtnegativ)
\item \textbf{buf}: Anfangsadresse des Sendepuffers
\item \textbf{count}: Anzahl der Elemente des Sendepuffers (nichtnegativ)
\item \textbf{datatype}: Typ der Elemente des Sendepuffers (handle) (vgl. \cpageref{sec:MPI-Datatypes})
\item \textbf{dest}: Rang des Empfängerprozesses in comm (integer)
\item \textbf{tag}: message tag zur Unterscheidung verschiedener Nachrichten;
Ein Kommunikationsvorgang wird durch ein Tripel (Sender, Empfänger, tag) eindeutig beschrieben.
\item \textbf{tag}: message tag zur Unterscheidung verschiedener Nachrichten;
Ein Kommunikationsvorgang wird durch ein Tripel (Sender, Empfänger, tag) eindeutig beschrieben.
\item \textbf{comm}: Kommunikator (handle)
\end{itemize}
@ -86,7 +86,7 @@ Ein Kommunikationsvorgang wird durch ein Tripel (Sender, Empfänger, tag) eindeu
\goodbreak
\rule{\textwidth}{0.4pt}\xindex{MPI\_Recv@\texttt{MPI\_Recv}}%
\inputminted[numbersep=5pt, tabsize=4]{c}{scripts/mpi/mpi-receive.c}
Empfangen einer Nachricht (blockierend)
Empfangen einer Nachricht (blockierend)
\textbf{Parameter}
\begin{itemize}
@ -96,7 +96,7 @@ Empfangen einer Nachricht (blockierend)
\item \textbf{source}: Rang des Senderprozesses in comm oder \texttt{MPI\_ANY\_SOURCE}
\item \textbf{tag}: message tag zur Unterscheidung verschiedener Nachrichten
Ein Kommunikationsvorgang wird durch ein Tripel (Sender, Empfänger, tag) eindeutig beschrieben. Um Nachrichten mit beliebigen tags zu empfangen, benutzt man die Konstante \texttt{MPI\_ANY\_TAG}.
\item \textbf{comm}: Kommunikator (handle)
\item \textbf{comm}: Kommunikator (handle)
\item \textbf{status}: Status, welcher source und tag angibt (\texttt{MPI\_Status}).
Soll dieser Status ignoriert werden, kann \texttt{MPI\_STATUS\_IGNORE}\xindex{MPI\_STATUS\_IGNORE@\texttt{MPI\_STATUS\_IGNORE}} angegeben werden.
\end{itemize}
@ -131,7 +131,7 @@ Teilt Daten von jedem Prozeß einer Gruppe an alle anderen auf.
\textbf{Input-Parameter}
\begin{itemize}
\item \textbf{sendbuf}: Startadresse des Sendepuffers
\item \textbf{sendbuf}: Startadresse des Sendepuffers
\item \textbf{sendcount}: Anzahl der Elemente im Sendepuffer
\item \textbf{sendtype}: Typ der Elemente des Sendepuffers (handle) (vgl. \cpageref{sec:MPI-Datatypes})
\item \textbf{recvcount}: Anzahl der Elemente, die von jedem einzelnen Prozeß empfangen werden
@ -150,12 +150,12 @@ Teilt Daten von jedem Prozeß einer Gruppe an alle anderen auf.
\goodbreak
\rule{\textwidth}{0.4pt}\xindex{MPI\_Bcast@\texttt{MPI\_Bcast}}%
\inputminted[numbersep=5pt, tabsize=4]{c}{scripts/mpi/mpi-bcast.c}
Sendet eine Nachricht vom Prozess \texttt{root} an alle anderen Prozesse des
Sendet eine Nachricht vom Prozess \texttt{root} an alle anderen Prozesse des
angegebenen Kommunikators.
\textbf{Parameter}
\begin{itemize}
\item \textbf{buffer}: Startadresse des Datenpuffers
\item \textbf{buffer}: Startadresse des Datenpuffers
\item \textbf{count}: Anzahl der Elemente im Puffer
\item \textbf{datatype}: Typ der Pufferelemente (handle) (vgl. \cpageref{sec:MPI-Datatypes})
\item \textbf{root}: Wurzelprozeß; der, welcher sendet
@ -169,10 +169,10 @@ Verteilt Daten vom Prozess \texttt{root} unter alle anderen Prozesse in der Grup
\textbf{Input-Parameter}
\begin{itemize}
\item \textbf{sendbuf}: Anfangsadresse des Sendepuffers (Wert ist lediglich für \texttt{root} signifikant)
\item \textbf{sendcount}: Anzahl der Elemente, die jeder Prozeß geschickt bekommen soll (integer)
\item \textbf{sendbuf}: Anfangsadresse des Sendepuffers (Wert ist lediglich für \texttt{root} signifikant)
\item \textbf{sendcount}: Anzahl der Elemente, die jeder Prozeß geschickt bekommen soll (integer)
\item \textbf{sendtype}: Typ der Elemente in sendbuf (handle) (vgl. \cpageref{sec:MPI-Datatypes})
\item \textbf{recvcount}: Anzahl der Elemente im Empfangspuffer. Meist ist es günstig, recvcount = sendcount zu wählen.
\item \textbf{recvcount}: Anzahl der Elemente im Empfangspuffer. Meist ist es günstig, recvcount = sendcount zu wählen.
\item \textbf{recvtype}: Typ der Elemente des Empfangspuffers (handle) (vgl. \cpageref{sec:MPI-Datatypes})
\item \textbf{root}: Rang des Prozesses in comm, der die Daten versendet
\item \textbf{comm}: Kommunikator (handle)
@ -190,10 +190,10 @@ Sammelt Daten, die in einer Prozeßgruppe verteilt sind, ein und verteilt das Re
\textbf{Input-Parameter}
\begin{itemize}
\item \textbf{sendbuf}: Startadresse des Sendepuffers
\item \textbf{sendbuf}: Startadresse des Sendepuffers
\item \textbf{sendcount}: Anzahl der Elemente im Sendepuffer
\item \textbf{sendtype}: Datentyp der Elemente des Sendepuffers (handle) (vgl. \cpageref{sec:MPI-Datatypes})
\item \textbf{recvcount}: Anzahl der Elemente, die jeder einzelne Prozeß sendet (integer)
\item \textbf{recvcount}: Anzahl der Elemente, die jeder einzelne Prozeß sendet (integer)
\item \textbf{recvtype}: Datentyp der Elemente im Empfangspuffer (handle) (vgl. \cpageref{sec:MPI-Datatypes})
\item \textbf{comm}: Kommunikator (handle)
\end{itemize}
@ -216,7 +216,7 @@ Sammelt Daten, die in einer Prozeßgruppe verteilt sind, ein.
\item \textbf{sendbuf}: Startadresse des Sendepuffers
\item \textbf{sendcount}: Anzahl der Elemente im Sendepuffer
\item \textbf{sendtype}: Datentyp der Elemente des Sendepuffers (handle)
\item \textbf{recvcount}: Anzahl der Elemente, die jeder einzelne Prozeß sendet (nur für \texttt{root} signifikant)
\item \textbf{recvcount}: Anzahl der Elemente, die jeder einzelne Prozeß sendet (nur für \texttt{root} signifikant)
\item \textbf{recvtype}: Typ der Elemente im Empfangspuffer (handle) (nur für \texttt{root} signifikant) (vgl. \cpageref{sec:MPI-Datatypes})
\item \textbf{root}: Rang des empfangenden Prozesses in \texttt{comm}
\item \textbf{comm}: Kommunikator (handle)

View file

@ -2,8 +2,8 @@
\chapter{Parallelität}
\index{Parallelität|(}
Systeme mit mehreren Prozessoren sind heutzutage weit verbreitet. Inzwischen
sind sowohl in Desktop-PCs als auch Laptops, Tablets und Smartphones
\enquote{Multicore-CPUs} verbaut. Daher sollten auch Programmierer in der Lage
sind sowohl in Desktop-PCs als auch Laptops, Tablets und Smartphones
\enquote{Multicore-CPUs} verbaut. Daher sollten auch Programmierer in der Lage
sein, Programme für mehrere Kerne zu entwickeln.
Parallelverarbeitung kann auf mehreren Ebenen statt finden:
@ -37,14 +37,14 @@ vermittelt.
\section{Architekturen}
Es gibt zwei Ansätze, wie man Parallelrechner entwickeln kann:
\begin{itemize}
\item \textbf{Gemeinsamer Speicher}: In diesem Fall kann jeder Prozessor
\item \textbf{Gemeinsamer Speicher}: In diesem Fall kann jeder Prozessor
jede Speicherzelle ansprechen. Dies ist bei Multicore-CPUs der Fall.
\item \textbf{Verteilter Speicher}: Es ist auch möglich, dass jeder Prozessor
seinen eigenen Speicher hat, der nur ihm zugänglich ist. In diesem Fall
schicken die Prozessoren Nachrichten (engl. \textit{message passing}\xindex{message passing}). Diese Technik wird in Clustern eingesetzt.
\end{itemize}
Eine weitere Art, wie man Parallelverarbeitung klassifizieren kann, ist anhand
Eine weitere Art, wie man Parallelverarbeitung klassifizieren kann, ist anhand
der verwendeten Architektur. Der der üblichen, sequentiellen Art der Programmierung,
bei der jeder Befehl nach einander ausgeführt wird, liegt die sog.
\textbf{Von-Neumann-Architektur}\xindex{Von-Neumann-Architektur} zugrunde.
@ -91,7 +91,7 @@ MISD ist nicht so richtig sinnvoll.
\item ausschließlich Probleme aus $\mathcal{P}$, also: $\mathcal{NC} \subseteq \mathcal{P}$
\end{bspenum}
Es ist nicht klar, ob $\mathcal{P} \subseteq \mathcal{NC}$ gilt. Bisher
Es ist nicht klar, ob $\mathcal{P} \subseteq \mathcal{NC}$ gilt. Bisher
wurde also noch kein Problem $P \in \mathcal{P}$ gefunden mit $P \notin \mathcal{NC}$.
\end{beispiel}
@ -126,7 +126,7 @@ Die Prozesskommunikation wird durch einige Probleme erschwert:
\end{beispiel}
\begin{definition}[Semaphore]\xindex{Semaphore}%
Eine Semaphore $S=(c, r, f, L)$ ist eine Datenstruktur, die aus einer Ganzzahl, den beiden
Eine Semaphore $S=(c, r, f, L)$ ist eine Datenstruktur, die aus einer Ganzzahl, den beiden
atomaren Operationen $r$ = \enquote{reservieren probieren} und $f$ = \enquote{freigeben}
sowie einer Liste $L$ besteht.
@ -142,12 +142,12 @@ Die Prozesskommunikation wird durch einige Probleme erschwert:
Semaphoren können eingesetzt werden um Wettlaufsituationen zu verhindern.
\begin{definition}[Monitor]\xindex{Monitor}%
Ein Monitor $M = (m, c)$ ist ein Tupel, wobei $m$ ein Mutex und $c$ eine
Ein Monitor $M = (m, c)$ ist ein Tupel, wobei $m$ ein Mutex und $c$ eine
Bedingung ist.
\end{definition}
Monitore können mit einer Semaphore, bei der $c=1$ ist, implementiert werden.
Monitore sorgen dafür, dass auf die Methoden der Objekte, die sie repräsentieren,
Monitore können mit einer Semaphore, bei der $c=1$ ist, implementiert werden.
Monitore sorgen dafür, dass auf die Methoden der Objekte, die sie repräsentieren,
zu jedem Zeitpunkt nur ein mal ausgeführt werden können. Sie sorgen also für
\textit{gegenseitigen Ausschluss}.
@ -191,7 +191,7 @@ Interessante Stichwörder sind noch:
\end{itemize}
\section{Message Passing Modell}
Das Message Passing Modell ist eine Art, wie man parallel laufende Programme
Das Message Passing Modell ist eine Art, wie man parallel laufende Programme
schreiben kann. Dabei tauschen die Prozesse Nachrichten aus um die Arbeit zu
verteilen.

View file

@ -93,10 +93,10 @@
\renewcommand{\headrulewidth}{0pt}
}
\hypersetup{
pdfauthor = {Martin Thoma},
pdfkeywords = {Programmierparadigmen},
pdftitle = {Programmierparadigmen}
\hypersetup{
pdfauthor = {Martin Thoma},
pdfkeywords = {Programmierparadigmen},
pdftitle = {Programmierparadigmen}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The patch for minted: http://tex.stackexchange.com/a/168021/5645
@ -178,9 +178,9 @@
%\clearpage
\input{Abkuerzungen}
\clearpage
\input{Definitionen}
\input{Definitionen}
\clearpage
\input{Symbolverzeichnis}
\input{Symbolverzeichnis}
\clearpage
\addcontentsline{toc}{chapter}{Stichwortverzeichnis}
\renewcommand{\indexname}{Stichwortverzeichnis}

View file

@ -9,7 +9,7 @@
Ein Beispiel für eine Sprachspezifikation ist die \textit{Java Language Specification}.\footnote{Zu finden unter \url{http://docs.oracle.com/javase/specs/}} Obwohl es kein guter Stil ist, ist auch
eine Referenzimplementierung eine Form der Spezifikation.
Im Folgenden wird darauf eingegangen, anhand welcher Kriterien man
Im Folgenden wird darauf eingegangen, anhand welcher Kriterien man
Programmiersprachen unterscheiden kann.
\section{Abstraktion}
@ -18,7 +18,7 @@ Wie nah ist sie an einer mathematisch / algorithmischen Beschreibung?
\begin{definition}\xindex{Maschinensprache}\xindex{Befehlssatz}%
Eine \textbf{Maschinensprache} beinhaltet ausschließlich Instruktionen, die direkt
von einer CPU ausgeführt werden können. Die Menge dieser Instruktionen
von einer CPU ausgeführt werden können. Die Menge dieser Instruktionen
sowie deren Syntax wird \textbf{Befehlssatz} genannt.
\end{definition}
@ -49,8 +49,8 @@ Wie nah ist sie an einer mathematisch / algorithmischen Beschreibung?
\end{beispiel}
\begin{definition}[Domänenspezifische Sprache]\xindex{Sprache!domänenspezifische}%
Eine domänenspezifische Sprache (engl. domain-specific language; kurz DSL)
ist eine formale Sprache, die für ein bestimmtes Problemfeld
Eine domänenspezifische Sprache (engl. domain-specific language; kurz DSL)
ist eine formale Sprache, die für ein bestimmtes Problemfeld
entworfen wurde.
\end{definition}
@ -68,7 +68,7 @@ man Probleme löst.
\begin{definition}[Imperatives Paradigma]\xindex{Programmierung!imperative}%
In der \textit{imperativen Programmierung} betrachtet man Programme als
eine Folge von Anweisungen, die vorgibt auf welche Art etwas
eine Folge von Anweisungen, die vorgibt auf welche Art etwas
Schritt für Schritt gemacht werden soll.
\end{definition}
@ -80,7 +80,7 @@ man Probleme löst.
\begin{definition}[Prozedurales Paradigma]\xindex{Programmierung!prozedurale}%
Die prozeduralen Programmierung ist eine Erweiterung des imperativen
Programmierparadigmas, bei dem man versucht die Probleme in
Programmierparadigmas, bei dem man versucht die Probleme in
kleinere Teilprobleme zu zerlegen.
\end{definition}
@ -106,7 +106,7 @@ Wichtige Vorteile von funktionalen Programmiersprachen sind:
\end{itemize}
\begin{definition}[Logisches Paradigma]\xindex{Programmierung!logische}%
Das \textbf{logische Programmierparadigma} baut auf der formalen Logik auf.
Das \textbf{logische Programmierparadigma} baut auf der formalen Logik auf.
Man verwendet \textbf{Fakten} und \textbf{Regeln}
und einen Inferenzalgorithmus um Probleme zu lösen.
\end{definition}
@ -129,7 +129,7 @@ Programmiersprachen können anhand der Art ihrer Typisierung unterschieden werde
\end{definition}
\begin{beispiel}[Typisierungsstärke]
Die stärke der Typisierung ist abhängig von dem Anwendungszenario. So hat C im
Die stärke der Typisierung ist abhängig von dem Anwendungszenario. So hat C im
Gegensatz zu Python, Java oder Haskell beispielsweise keine booleschen Datentypen.
Im Gegensatz zu Haskell hat Java keine GADTs\footnote{generalized algebraic data type}.
@ -154,9 +154,9 @@ Programmiersprachen können anhand der Art ihrer Typisierung unterschieden werde
\begin{definition}[Statische und dynamische Typisierung]\xindex{Typisierung!statische}\xindex{Typisierung!dynamische}%
\begin{defenum}
\item Eine Programmiersprache heißt \textbf{statisch typisiert}, wenn eine
\item Eine Programmiersprache heißt \textbf{statisch typisiert}, wenn eine
Variable niemals ihren Typ ändern kann.
\item Eine Programmiersprache heißt \textbf{dynamisch typisiert}, wenn eine
\item Eine Programmiersprache heißt \textbf{dynamisch typisiert}, wenn eine
Variable ihren Typ ändern kann.
\end{defenum}
\end{definition}
@ -188,7 +188,7 @@ als Container vor.
\begin{definition}[Explizite und implizite Typisierung]\xindex{Typisierung!explizite}\xindex{Typisierung!implizite}%
Sei $X$ eine Programmiersprache.
\begin{defenum}
\item $X$ heißt \textbf{explizit typisiert}, wenn für jede
\item $X$ heißt \textbf{explizit typisiert}, wenn für jede
Variable der Typ explizit genannt wird.
\item $X$ heißt \textbf{implizit typisiert}, wenn der Typ einer
Variable aus den verwendeten Operationen abgeleitet werden kann.
@ -219,7 +219,7 @@ Vorteile impliziter Typisierung sind:
\begin{definition}[Duck-Typing und strukturelle Typisierung]\xindex{Duck-Typing}\xindex{Typisierung!strukturelle}%
\begin{defenum}
\item Eine Programmiersprache verwendet \textbf{Duck-Typing}, wenn die Parameter einer
\item Eine Programmiersprache verwendet \textbf{Duck-Typing}, wenn die Parameter einer
Methode nicht durch die explizite Angabe von Typen festgelegt werden, sondern
durch die Art wie die Parameter verwendet werden.
\item Eine Programmiersprache verwendet \textbf{strukturelle Typisierung}, wenn die
@ -228,7 +228,7 @@ Vorteile impliziter Typisierung sind:
\end{defenum}
\end{definition}
Strukturelle Typsierung wird auch \textit{typsicheres Duck-Typing} genannt.
Strukturelle Typsierung wird auch \textit{typsicheres Duck-Typing} genannt.
Der Satz, den man im Zusammenhang mit Duck-Typing immer höhrt, ist
\enquote{When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.}
@ -269,11 +269,11 @@ Meistens meint man insbesondere unerwünschte oder überaschende Zustandsänderu
A_1 &= \left(X, Y, f(b) \right)\\
A_2 &= \left(a, b, Z \right)
\end{align*}
Großbuchstaben stehen dabei für Variablen und Kleinbuchstaben für atomare
Großbuchstaben stehen dabei für Variablen und Kleinbuchstaben für atomare
Ausdrücke.
Ersetzt man in $A_1$ nun $X$ durch $a$, $Y$ durch $b$ und in $A_2$
die Variable $Z$ durch $f\left(b\right)$, so sind sie gleich oder
Ersetzt man in $A_1$ nun $X$ durch $a$, $Y$ durch $b$ und in $A_2$
die Variable $Z$ durch $f\left(b\right)$, so sind sie gleich oder
\enquote{unifiziert}. Man erhält
\begin{align*}
@ -286,7 +286,7 @@ Meistens meint man insbesondere unerwünschte oder überaschende Zustandsänderu
\end{beispiel}
\begin{definition}[Allgemeinster Unifikator]\xindex{Unifikator!allgemeinster}%
Ein Unifikator $\sigma$ heißt \textit{allgemeinster Unifikator}, wenn
Ein Unifikator $\sigma$ heißt \textit{allgemeinster Unifikator}, wenn
es für jeden Unifikator $\gamma$ eine Substitution $\delta$ mit
\[\gamma = \delta \circ \sigma\]
gibt.
@ -297,7 +297,7 @@ Meistens meint man insbesondere unerwünschte oder überaschende Zustandsänderu
\[C = \Set{f(a,D) = Y, X = g(b), g(Z) = X}\]
eine Menge von Gleichungen über Terme.
Dann ist
Dann ist
\[\gamma = [Y \text{\pointer} f(a,b), D \text{\pointer} b, X \text{\pointer} g(b), Z \text{\pointer} b]\]
ein Unifikator für $C$. Jedoch ist
\[\sigma = [Y \text{\pointer} f(a,D), X \text{\pointer} g(b), Z \text{\pointer} b]\]

View file

@ -39,7 +39,7 @@
\end{bspenum}
\end{beispiel}
Ein Problem von rekursiven Funktionen in Computerprogrammen ist der
Ein Problem von rekursiven Funktionen in Computerprogrammen ist der
Speicherbedarf. Für jeden rekursiven Aufruf müssen alle lokalen Variablen
der aufrufenden Funktion (\enquote{stack frame}) gespeichert bleiben,
bis der rekursive Aufruf beendet ist. Im Fall der Fibonacci-Funktion
@ -47,7 +47,7 @@ sieht ist der Call-Stack in \cref{fig:fib-callstack} abgebildet.
\begin{figure}[htp]
\centering
\includegraphics*[width=0.5\linewidth, keepaspectratio]{figures/fib-callstack.png}
\includegraphics*[width=0.5\linewidth, keepaspectratio]{figures/fib-callstack.png}
\caption{Call-Stack der Fibonacci-Funktion}
\label{fig:fib-callstack}
\end{figure}
@ -108,7 +108,7 @@ Auf Englisch heißen endrekursive Funktionen \textit{tail recursive}.
\end{bspenum}
\end{beispiel}
Wenn eine rekursive Funktion nicht terminiert oder wenn
Wenn eine rekursive Funktion nicht terminiert oder wenn
\index{Rekursion|)}
\section{Backtracking}
@ -135,14 +135,14 @@ Bekannte Beispiele sind:
\texttt{map} wendet \texttt{function} auf jedes einzelne
Element aus \texttt{list} an.
\item \texttt{filter(function, list)}\xindex{filter}\\
\texttt{filter} gibt eine Liste aus Elementen zurück, für
\texttt{filter} gibt eine Liste aus Elementen zurück, für
die \texttt{function} mit \texttt{true} evaluiert.
\item \texttt{reduce(function, list)}\xindex{reduce}\\
\texttt{function} ist für zwei Elemente aus \texttt{list}
definiert und gibt ein Element des gleichen Typs zurück.
Nun steckt \texttt{reduce} zuerst zwei Elemente aus \texttt{list}
in \texttt{function}, merkt sich dann das Ergebnis und nimmt
so lange weitere Elemente aus \texttt{list}, bis jedes
so lange weitere Elemente aus \texttt{list}, bis jedes
Element genommen wurde.\\
Bei \texttt{reduce} ist die Assoziativität wichtig (vgl. \cpageref{bsp:foldl-und-foldr})
\end{itemize}

View file

@ -19,7 +19,7 @@ ausführbare Datei erzeugt.
\section{Syntax}
In Prolog gibt es Prädikate, die Werte haben. Prädikate werden immer klein geschrieben.
So kann das Prädikat \texttt{farbe} mit den Werten \texttt{rot}, \texttt{gruen},
\texttt{blau}, \texttt{gelb} - welche auch immer klein geschrieben werden - wie
\texttt{blau}, \texttt{gelb} - welche auch immer klein geschrieben werden - wie
folgt definiert werden:
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/praedikat-farbe.pl}
@ -78,7 +78,7 @@ durchgeführt werden:
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/arithmetik.pl}
Dabei müssen alle Variablen, die im Term rechts von \texttt{is} vorkommen,
Dabei müssen alle Variablen, die im Term rechts von \texttt{is} vorkommen,
istanziiert sein:
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/arithmetik-fail.pl}
@ -107,13 +107,13 @@ in \texttt{Liste} vorkommt, realisiert man wie folgt:
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/liste-member.pl}\xindex{member}
Eine Regel \texttt{append(A, B, C)}, die die Listen \texttt{A} und \texttt{B}
Eine Regel \texttt{append(A, B, C)}, die die Listen \texttt{A} und \texttt{B}
zusammenfügt und als Liste \texttt{C} speichert, kann
wie folgt erstellt werden:
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/liste-append.pl}
Die erste Regel besagt, dass das Hinzufügen der leeren Liste zu einer Liste
Die erste Regel besagt, dass das Hinzufügen der leeren Liste zu einer Liste
\texttt{L} immer noch die Liste \texttt{L} ist.
Die zweite Regel besagt: Wenn die Liste \texttt{R} und \texttt{L} die Liste \texttt{T}
@ -128,7 +128,7 @@ Die Länge einer Liste \texttt{L} kann durch folgendes Prädikat ermittelt werde
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/list-length.pl}
\underline{Hinweis}: Da es das Prädikat \texttt{length(?List, ?Int)} bereits gibt,
\underline{Hinweis}: Da es das Prädikat \texttt{length(?List, ?Int)} bereits gibt,
musste dieses Prädikat \texttt{lengthof} genannt werden.
Weitere nützliche Standard-Listenprädikate sind:\xindex{sort(+List, -Sorted)@\texttt{sort(+List, -Sorted)}}
@ -151,10 +151,10 @@ Bäume können in Prolog wie folgt erstellt werden:
\label{fig:binary-tree-t2}
\end{figure}
Dabei ist
Dabei ist
\begin{itemize}
\item \texttt{T0} der einzelne Knoten \texttt{a},
\item \texttt{T1} der Baum, der \texttt{a} als Wurzel und \texttt{b} und
\item \texttt{T1} der Baum, der \texttt{a} als Wurzel und \texttt{b} und
\texttt{c} als Kinder hat,
\item \texttt{T2} ist in \cref{fig:binary-tree-t2} dargestellt und
\item \texttt{T3} ist der leere Baum.
@ -169,7 +169,7 @@ um einen Binärbaum handelt:
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/istree.pl}
\subsection{Balancierte Binärbaumkonstruktion}
Das folgende Prädikate \texttt{cbal\_tree(n, T)} erstellt einen balancierten
Das folgende Prädikate \texttt{cbal\_tree(n, T)} erstellt einen balancierten
Binärbaum mit \texttt{n} Knoten in \texttt{T}:
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/balancedtreeconstruction.pl}

View file

@ -84,12 +84,12 @@ Listen können erstellt und durchgegangen werden:
\subsection{Logische Operatoren}
\begin{table}[H]
\centering
\centering
\begin{tabular}{CCCC}
UND & ODER & Wahr & Falsch \\ \hline\hline
\&\& & || & true & false \\[4ex]
GLEICH & UNGLEICH & NICHT & ~ \\ \hline\hline
== & != & ! & ~ \\
== & != & ! & ~ \\
\end{tabular}
\caption{Logische Operatoren in Scala}\xindex{Logische Operatoren!Scala}
\end{table}

View file

@ -21,7 +21,7 @@
\texttt{bool} durch ein einzelnes Bit repräsentiert werden oder eine Bitfolge
zugrunde liegen.
Auf Typen sind Operationen definiert. So kann man auf numerischen Typen eine
Auf Typen sind Operationen definiert. So kann man auf numerischen Typen eine
Addition (+), eine Subtraktion (-), eine Multiplikation (*) und eine Division (/)
definieren.\\
Ich schreibe hier bewusst \enquote{eine} Multiplikation und nicht \enquote{die}
@ -40,7 +40,7 @@ unterschiedlich wählen.
\underline{Hinweis:} Üblicherweise werden kleine griechische Buchstaben ($\alpha, \beta, \tau_1, \tau_2, \dots$) als Typvariablen gewählt.
Genau wie Typen bestimmte Operationen haben, die auf ihnen definiert sind,
Genau wie Typen bestimmte Operationen haben, die auf ihnen definiert sind,
kann man sagen, dass Operationen bestimmte Typen, auf die diese Anwendbar sind. So ist
\[\alpha+\beta\]
für numerische $\alpha$ und $\beta$ wohldefiniert, auch wenn $\alpha$ und $\beta$ boolesch sind
@ -97,7 +97,7 @@ Wichtig ist, dass man sich von unten nach oben vorarbeitet.
Dabei ist der lange Strich kein Bruchstrich, sondern ein Symbol der Logik das als
\textbf{Schlussstrich}\xindex{Schlussstrich} bezeichnet wird. Dabei ist der
\textbf{Schlussstrich}\xindex{Schlussstrich} bezeichnet wird. Dabei ist der
Zähler als Voraussetzung und der Nenner als Schlussfolgerung zu verstehen.
\begin{definition}[Typsubstituition]\xindex{Typsubstituition}%
@ -140,21 +140,21 @@ Das Programm $P = \text{let } f = \lambda x.\ 2 \text{ in } f\ (f\ \text{\texttt
ist eine polymorphe Hilfsfunktion, da sie beliebige Werte auf 2 Abbildet.
Auch solche Ausdrücke sollen typisierbar sein.
Die Kodierung
Die Kodierung
\[\text{let } x = t_1 \text{ in } t_2\]
ist bedeutungsgleich mit
\[(\lambda x.\ t_2) t_1\]
Das Problem ist, dass
Das Problem ist, dass
\[P = \lambda f. \ f (f\ \text{\texttt{true}})\ (\lambda x.\ 2)\]
so nicht typisierbar ist, da in
\[\ABS \frac{f: \tau_f \vdash f\ (f\ \text{\texttt{true}}): \dots}{\vdash \lambda f.\ f\ (f\ \text{\texttt{true}}): \dots}\]
müsste
müsste
\[\tau_f = \text{bool} \rightarrow \text{int}\]
und zugleich
\[\tau_f = \text{int} \rightarrow \text{int}\]
in den Typkontext eingetragen werden. Dies ist jedoch nicht möglich. Stattdessen
wird
wird
\[\text{let} x = t_1 \text{ in } t_2\]
als neues Konstrukt im $\lambda$-Kalkül erlaubt.
@ -219,7 +219,7 @@ Im Folgenden wird die Typinferenz für einige $\lambda$-Funktionen durchgeführt
\subsection[$\lambda x.\ \lambda y.\ x\ y$]{$\lambda x.\ \lambda y.\ x\ y$\footnote{Lösung von Übungsblatt 6, WS 2013 / 2014}}
Gesucht ist ein Typ $\tau$, sodass sich $\vdash \lambda x.\ \lambda y.\ x\ y: \tau$
mit einem Ableitungsbaum nachweisen lässt. Es gibt mehrere solche $\tau$, aber
wir suchen das allgemeinste. Die Regeln unseres Typsystems (siehe \cpageref{def:typsystem-t1})
wir suchen das allgemeinste. Die Regeln unseres Typsystems (siehe \cpageref{def:typsystem-t1})
sind \textit{syntaxgerichtet}, d.~h. zu jedem $\lambda$-(Teil)-Term gibt es genau
eine passende Regel.
@ -229,7 +229,7 @@ von folgender Gestalt ist. Dabei sind $\alpha_i$ Platzhalter:
\[\ABS \frac{\ABS\frac{\textstyle\APP \frac{\textstyle\VAR \frac{(x: \alpha_2, y: \alpha_4)\ (x) = \alpha_6}{x: \alpha_2, y: \alpha_4 \vdash x: \alpha_6}\ \ \VAR \frac{(x:\alpha_2, y: \alpha_4)\ (y) = \alpha_7}{x: \alpha_2, y: \alpha_4 \vdash y : \alpha_7}}{\textstyle x: \alpha_2, y: \alpha_4 \vdash x\ y: \alpha_5}}{x:\alpha_2 \vdash \lambda y.\ x\ y\ :\ \alpha_3}}{\vdash \lambda x.\ \lambda \ y.\ x\ y: \alpha_1}\]
Das was wir haben wollen steht am Ende, also unter dem unterstem Schlussstrich.
Dann bedeutet die letzte Zeile
Dann bedeutet die letzte Zeile
\[\vdash \lambda x.\ \lambda \ y.\ x\ y: \alpha_1\]
Ohne (weitere) Voraussetzungen lässt sich sagen, dass der Term
@ -247,7 +247,7 @@ Diese Zeile ist so zu lesen: Mit der Voraussetzung, dass $x$ vom Typ $\alpha_2$
ist, lässt sich syntaktisch Folgern, dass der Term $\lambda y.\ x\ y$ vom
Typ $\alpha_3$ ist.
\underline{Hinweis:} Alles was in Zeile $i$ dem $\vdash$ steht, steht auch in
\underline{Hinweis:} Alles was in Zeile $i$ dem $\vdash$ steht, steht auch in
jedem \enquote{Nenner} in Zeile $j < i$ vor jedem einzelnen $\vdash$.
Folgende Typgleichungen $C$ lassen sich aus dem Ableitungsbaum ablesen:
@ -286,7 +286,7 @@ Zuerst erstellt man den Ableitungsbaum:
Dies ergibt die Constraint-Menge
\begin{align}
C&= \Set{\alpha_1 = \alpha_2 \rightarrow \alpha_3} &\text{$\ABS$-Regel}\label{eq:bsp2.c1}\\
C&= \Set{\alpha_1 = \alpha_2 \rightarrow \alpha_3} &\text{$\ABS$-Regel}\label{eq:bsp2.c1}\\
&\cup \Set{\alpha_5 = \alpha_4 \rightarrow \alpha_3} &\text{$\APP$-Regel}\label{eq:bsp2.c2}\\
&\cup \Set{\alpha_5 = \alpha_2} &\text{Linke $\VAR$-Regel}\label{eq:bsp2.c3}\\
&\cup \Set{\alpha_4 = \alpha_2} &\text{Rechte $\VAR$-Regel}\label{eq:bsp2.c4}
@ -299,6 +299,6 @@ Also lässt sich \cref{eq:bsp2.c2} umformulieren:
\[\alpha_2 = \alpha_2 \rightarrow \alpha_3\]
Offensichtlich ist diese Bedingung nicht erfüllbar. Daher ist ist die Selbstapplikation
nicht typisierbar. Dies würde im Unifikationsalgorithmus
nicht typisierbar. Dies würde im Unifikationsalgorithmus
(vgl. \cref{alg:klassischer-unifikationsalgorithmus})
durch den \textit{occur check} festgestellt werden.

View file

@ -1,7 +1,7 @@
%!TEX root = Programmierparadigmen.tex
\chapter*{Vorwort}
Dieses Skript wird/wurde im Wintersemester 2013/2014
von Martin Thoma zur Vorlesung von Prof.~Dr.~Snelting und Jun.-Prof.~Dr.~Hummel
von Martin Thoma zur Vorlesung von Prof.~Dr.~Snelting und Jun.-Prof.~Dr.~Hummel
geschrieben. Dazu wurden
die Folien von Prof.~Dr.~Snelting und Jun.-Prof.~Dr.~Hummel benutzt, die Struktur
sowie einige Beispiele, Definitionen und Sätze übernommen.
@ -30,7 +30,7 @@ geschickt werden.
\section*{Erforderliche Vorkenntnisse}
Grundlegende Kenntnisse vom Programmieren, insbesondere mit Java,
wie sie am KIT in \enquote{Programmieren} vermittelt werden, werden
vorausgesetzt. Außerdem könnte ein grundlegendes Verständnis für
vorausgesetzt. Außerdem könnte ein grundlegendes Verständnis für
das $\mathcal{O}$-Kalkül aus \enquote{Grundbegriffe der Informatik} hilfreich sein.
Die Unifikation wird wohl auch in \enquote{Formale Systeme}

View file

@ -8,12 +8,12 @@ Wie in Scala sind auch in X10 Funktionen First-Class Citizens.
X10 nutzt das PGAS-Modell:
\begin{definition}[PGAS\footnotemark]\xindex{PGAS}%
PGAS (partitioned global address space) ist ein Programmiermodell für
Mehrprozessorsysteme und massiv parallele Rechner. Dabei wird der globale
Adressbereich des Arbeitsspeichers logisch unterteilt. Jeder Prozessor
bekommt jeweils einen dieser Adressbereiche als lokalen Speicher zugeteilt.
Trotzdem können alle Prozessoren auf jede Speicherzelle zugreifen, wobei auf
den lokalen Speicher mit wesentlich höherer Geschwindigkeit zugegriffen
PGAS (partitioned global address space) ist ein Programmiermodell für
Mehrprozessorsysteme und massiv parallele Rechner. Dabei wird der globale
Adressbereich des Arbeitsspeichers logisch unterteilt. Jeder Prozessor
bekommt jeweils einen dieser Adressbereiche als lokalen Speicher zugeteilt.
Trotzdem können alle Prozessoren auf jede Speicherzelle zugreifen, wobei auf
den lokalen Speicher mit wesentlich höherer Geschwindigkeit zugegriffen
werden kann als auf den von anderen Prozessoren.
\end{definition}
\footnotetext{\url{https://de.wikipedia.org/wiki/PGAS}}
@ -50,12 +50,12 @@ Eine Besonderheit sind sog. \textit{Constrianed types}\xindex{types!constrained}
\subsection{Logische Operatoren}
\begin{table}[H]
\centering
\centering
\begin{tabular}{CCCC}
UND & ODER & Wahr & Falsch \\ \hline\hline
\&\& & || & true & false \\[4ex]
GLEICH & UNGLEICH & NICHT & ~ \\ \hline\hline
== & != & ! & ~ \\
== & != & ! & ~ \\
\end{tabular}
\caption{Logische Operatoren in X10}\xindex{Logische Operatoren!X10}
\end{table}
@ -107,7 +107,7 @@ Es wird eine Deep-Copy des lokalen Objektgraphen auf den place \texttt{p} erstel
\inputminted[numbersep=5pt, tabsize=4]{scala}{scripts/x10/at-example.x10}
\section{Datentypen}
Byte, UByte, Short, UShort, Char, Int, UInt, Long, ULong, Float, Double, Boolean,
Byte, UByte, Short, UShort, Char, Int, UInt, Long, ULong, Float, Double, Boolean,
Complex, String, Point, Region, Dist, Array
\subsection{Arrays}%

View file

@ -20,7 +20,7 @@
\node[node] (MonadPlus) {\textbf{MonadPlus}\\IO, (), Maybe}; &
\node[node] (Functor) {\textbf{Functor}\\IO, (), Maybe}; &
\\
};
};
\draw[edge] (Eq) -- (Ord);
\draw[edge] (Eq) -- (Num);
\draw[edge] (Show) -- (Num);