Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

📚 The CoCalc Library - books, templates and other resources

132928 views
License: OTHER
1
%!TEX root = Programmierparadigmen.tex
2
\chapter{Prolog}
3
\index{Prolog|(}
4
5
Prolog ist eine Programmiersprache, die das logische Programmierparadigma
6
befolgt.
7
8
Eine interaktive Prolog-Sitzung startet man mit \texttt{swipl}.
9
10
In Prolog definiert man Terme.
11
\section{Erste Schritte}
12
\subsection{Hello World}
13
Speichere folgenden Quelltext als \texttt{hello-world.pl}:
14
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=hello-world.hs]{prolog}{scripts/prolog/hello-world.pl}
15
16
Kompiliere ihn mit \texttt{gplc hello-world.pl}. Es wird eine
17
ausführbare Datei erzeugt.
18
19
\section{Syntax}
20
In Prolog gibt es Prädikate, die Werte haben. Prädikate werden immer klein geschrieben.
21
So kann das Prädikat \texttt{farbe} mit den Werten \texttt{rot}, \texttt{gruen},
22
\texttt{blau}, \texttt{gelb} - welche auch immer klein geschrieben werden - wie
23
folgt definiert werden:
24
25
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/praedikat-farbe.pl}
26
27
\begin{itemize}
28
\item Terme werden durch \texttt{,} mit einem logischem \textbf{und} verknüpft.
29
\item Ungleichheit wird durch \texttt{\=} ausgedrückt.
30
\end{itemize}
31
32
So ist folgendes Prädikat \texttt{nachbar(X, Y)} genau dann wahr, wenn $X$
33
und $Y$ Farben sind und $X \neq Y$ gilt:
34
35
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/simple-term.pl}
36
37
\subsection{Kommentare}\xindex{Kommentare (Prolog)}
38
Prolog kennt zwei Kommentar-Typen:
39
40
\begin{itemize}
41
\item Zeilen-Kommentare, die mit \verb+%+ beginnen
42
\item Block-Kommentare, diem durch \verb+/* ... */+ markiert werden.
43
\end{itemize}
44
45
\subsection{= und ==}\xindex{= (Prolog)}\xindex{== (Prolog)}
46
In Prolog entspricht \texttt{=} dem Prädikat \texttt{=/2}. Das Prädikat \texttt{<a> = <b>} wird
47
erfüllt, wenn die beiden Terme \texttt{<a>} und \texttt{<b>} unifiziert werden
48
können.
49
50
Das Prädikat \texttt{<a> == <b>} ist im Gegensatz dazu jedoch nur erfüllt, wenn
51
die beiden Terme bereits identisch sind.
52
53
\begin{beispiel}[= und ==]
54
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/equal.pl}
55
\end{beispiel}
56
57
Weitere Informationen: \url{http://stackoverflow.com/a/8220315/562769}
58
59
\subsection{! (Cut)}\xindex{"! (Cut, Prolog)}%
60
Das \texttt{!} wird in Prolog als \textit{cut} bezeichnet. Ein Cut verhindert
61
Backtracking nach dem cut.
62
63
Die Klauseln eines Prädikates werden von Prolog von links nach rechts evaluiert.
64
Prolog bindet einen Wert an eine Variable in der linkesten Klausel. Wenn diese
65
Klausel als \texttt{true} ausgewertet wird, dann versucht Prolog die nächste
66
Klausel auszuwerten. Falls nicht, wird eine neuer Wert an die momentan
67
betrachtete Klausel gebunden.
68
69
Da Klauseln über logische UND verbunden sind, führt eine nicht erfüllbare
70
Klausel dazu, dass das gesamte Prädikat als \texttt{false} evaluiert wird.
71
72
Der cut ist ein Gate: Sind die Klauseln vor dem cut ein mal wahr, werden die
73
Werte festgelegt.
74
75
\subsection{Arithmetik}
76
Die Auswertung artihmetischer Ausdrücke muss in Prolog explizit durch \texttt{is}
77
durchgeführt werden:
78
79
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/arithmetik.pl}
80
81
Dabei müssen alle Variablen, die im Term rechts von \texttt{is} vorkommen,
82
istanziiert sein:
83
84
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/arithmetik-fail.pl}
85
86
Arithmetische Ausdrücke können mit \texttt{=:= , =\textbackslash= , < , <= , > , >=}
87
verglichen werden.
88
89
\begin{beispiel}[Arithmetik in Prolog\footnotemark]
90
\begin{bspenum}
91
\item \inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/even.pl}\xindex{even (Prolog)@\texttt{even} (Prolog)}
92
\item \inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/fibonacci2.pl}\xindex{Prolog!Fibonacci}
93
\end{bspenum}
94
\end{beispiel}
95
\footnotetext{WS 2013 / 2014, Folie 237f}
96
97
\subsection{Listen}
98
Das Atom \texttt{[]} ist die leere Liste.
99
100
Mit der Syntax \texttt{[K|R]} wird eine Liste in den Listekopf \texttt{K} und
101
den Rest der Liste \texttt{R} gesplitet:
102
103
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/liste-basic.pl}
104
105
Einen Test \texttt{member(X, Liste)}, der \texttt{True} zurückgibt wenn \texttt{X}
106
in \texttt{Liste} vorkommt, realisiert man wie folgt:
107
108
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/liste-member.pl}\xindex{member}
109
110
Eine Regel \texttt{append(A, B, C)}, die die Listen \texttt{A} und \texttt{B}
111
zusammenfügt und als Liste \texttt{C} speichert, kann
112
wie folgt erstellt werden:
113
114
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/liste-append.pl}
115
116
Die erste Regel besagt, dass das Hinzufügen der leeren Liste zu einer Liste
117
\texttt{L} immer noch die Liste \texttt{L} ist.
118
119
Die zweite Regel besagt: Wenn die Liste \texttt{R} und \texttt{L} die Liste \texttt{T}
120
ergeben, dann ergibt die Liste, deren Kopf \texttt{X} ist und deren Rumpf \texttt{R}
121
ist zusammen mit der Liste \texttt{L} die Liste mit dem Kopf \texttt{X} und dem
122
Rumpf \texttt{T}.
123
124
\xindex{split}Übergibt man \texttt{append(X,Y,[1,2,3,4,5])}, so werden durch Reerfüllung alle
125
Möglichkeiten durchgegangen, wie man die Liste \texttt{[1,2,3,4,5]} splitten kann.
126
127
Die Länge einer Liste \texttt{L} kann durch folgendes Prädikat ermittelt werden:\xindex{length(?List, ?Int)@\texttt{length(?List, ?Int)}}%
128
129
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/list-length.pl}
130
131
\underline{Hinweis}: Da es das Prädikat \texttt{length(?List, ?Int)} bereits gibt,
132
musste dieses Prädikat \texttt{lengthof} genannt werden.
133
134
Weitere nützliche Standard-Listenprädikate sind:\xindex{sort(+List, -Sorted)@\texttt{sort(+List, -Sorted)}}
135
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/standard-list-predicates.pl}
136
137
\underline{Hinweis}: \texttt{sort} entfernt Duplikate, \texttt{msort} hingegen nicht.
138
139
Eine Liste kann mit \texttt{rev/2}\xindex{rev/2@\texttt{rev/2}} umgedreht werden:
140
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/reverse-list.pl}
141
142
\subsection{Bäume}
143
Bäume können in Prolog wie folgt erstellt werden:
144
145
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/binary-tree-example.pl}
146
147
\begin{figure}[htp]
148
\centering
149
\input{figures/binary-tree.tex}
150
\caption{Binärbaum \texttt{T2}}
151
\label{fig:binary-tree-t2}
152
\end{figure}
153
154
Dabei ist
155
\begin{itemize}
156
\item \texttt{T0} der einzelne Knoten \texttt{a},
157
\item \texttt{T1} der Baum, der \texttt{a} als Wurzel und \texttt{b} und
158
\texttt{c} als Kinder hat,
159
\item \texttt{T2} ist in \cref{fig:binary-tree-t2} dargestellt und
160
\item \texttt{T3} ist der leere Baum.
161
\end{itemize}
162
163
Die folgenden Prädikate stammen von \url{https://sites.google.com/site/prologsite/prolog-problems/4}:
164
165
\subsection{Binärbaum-Check}
166
Das folgende Prädikate \texttt{istree/1} überprüft, ob es sich bei dem Parameter
167
um einen Binärbaum handelt:
168
169
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/istree.pl}
170
171
\subsection{Balancierte Binärbaumkonstruktion}
172
Das folgende Prädikate \texttt{cbal\_tree(n, T)} erstellt einen balancierten
173
Binärbaum mit \texttt{n} Knoten in \texttt{T}:
174
175
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/balancedtreeconstruction.pl}
176
177
\section{Beispiele}
178
\subsection{Humans}
179
Erstelle folgende Datei:
180
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=human.pro]{prolog}{scripts/prolog/human.pro}
181
182
Kompiliere diese mit
183
\inputminted[numbersep=5pt, tabsize=4]{bash}{scripts/prolog/human.sh}
184
185
Dabei wird eine \texttt{a.out} Datei erzeugt, die man wie folgt
186
nutzen kann:
187
\inputminted[numbersep=5pt, tabsize=4]{bash}{scripts/prolog/human-2.sh}
188
189
\subsection{Splits}
190
\inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=splits.pl]{prolog}{scripts/prolog/splits.pl}
191
192
Dieses skript soll man \texttt{swipl -f test.pl} aufrufen. Dann erhält man:
193
194
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/splits.sh}
195
196
\subsection{Delete}\xindex{remove}\xindex{delete}%
197
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/delete.pl}
198
199
% \subsection{Zebrarätsel}
200
% Folgendes Rätsel wurde von \url{https://de.wikipedia.org/w/index.php?title=Zebrar%C3%A4tsel&oldid=126585006}
201
% entnommen:
202
203
% \begin{enumerate}
204
% \item Es gibt fünf Häuser.
205
% \item Der Engländer wohnt im roten Haus.
206
% \item Der Spanier hat einen Hund.
207
% \item Kaffee wird im grünen Haus getrunken.
208
% \item Der Ukrainer trinkt Tee.
209
% \item Das grüne Haus ist direkt rechts vom weißen Haus.
210
% \item Der Raucher von Altem-Gold-Zigaretten hält Schnecken als Haustiere.
211
% \item Die Zigaretten der Marke Kools werden im gelben Haus geraucht.
212
% \item Milch wird im mittleren Haus getrunken.
213
% \item Der Norweger wohnt im ersten Haus.
214
% \item Der Mann, der Chesterfields raucht, wohnt neben dem Mann mit dem Fuchs.
215
% \item Die Marke Kools wird geraucht im Haus neben dem Haus mit dem Pferd.
216
% \item Der Lucky-Strike-Raucher trinkt am liebsten Orangensaft.
217
% \item Der Japaner raucht Zigaretten der Marke Parliaments.
218
% \item Der Norweger wohnt neben dem blauen Haus.
219
% \end{enumerate}
220
221
% Wer trinkt Wasser? Wem gehört das Zebra?
222
223
% \inputminted[linenos, numbersep=5pt, tabsize=4, frame=lines, label=zebraraetsel.pro]{prolog}{scripts/prolog/zebraraetsel.pro}
224
225
% TODO: Zebrarätzel hinzufügen
226
227
\subsection{Zahlen generieren}
228
Folgendes Skript generiert durch reerfüllung die Zahlen $1, \dots, 10$:
229
230
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/zahlen-bis-10.pl}
231
232
\subsection{Reguläre ausdrücke}
233
Folgendes Beispiel stammt aus der Programmierparadigmenklausur vom WS 2013/2014
234
bei Prof. Dr. Snelting:
235
236
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/regex.pl}
237
238
\subsection{Coffeetime 01: Two Bases}
239
240
\inputminted[numbersep=5pt, tabsize=4]{prolog}{scripts/prolog/01-two-bases.prolog}
241
242
\section{Weitere Informationen}
243
\begin{itemize}
244
\item \href{http://wiki.ubuntuusers.de/Prolog}{\path{wiki.ubuntuusers.de/Prolog}}: Hinweise zur Installation von Prolog unter Ubuntu
245
\item \url{http://www.swi-prolog.org/}
246
\end{itemize}
247
\index{Prolog|)}
248
249