Prolog.tex 9.0 KB

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