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:
parent
c578b25d2f
commit
7740f0147f
538 changed files with 3496 additions and 3496 deletions
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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]\]
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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.
|
|
@ -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}
|
||||
|
|
|
@ -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}%
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue