Constraint Logical Programming



Ähnliche Dokumente
Primzahlen und RSA-Verschlüsselung

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Professionelle Seminare im Bereich MS-Office

1. Man schreibe die folgenden Aussagen jeweils in einen normalen Satz um. Zum Beispiel kann man die Aussage:

Grundlagen der Theoretischen Informatik, SoSe 2008

Repetitionsaufgaben Wurzelgleichungen

Informationsblatt Induktionsbeweis

7 Rechnen mit Polynomen

1 Mathematische Grundlagen

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Die Gleichung A x = a hat für A 0 die eindeutig bestimmte Lösung. Für A=0 und a 0 existiert keine Lösung.

Zeichen bei Zahlen entschlüsseln

Lineare Gleichungssysteme

Dossier: Rechnungen und Lieferscheine in Word

Handbuch ECDL 2003 Basic Modul 5: Datenbank Grundlagen von relationalen Datenbanken

Übungen für Woche 10

Musterlösungen zur Linearen Algebra II Blatt 5

50. Mathematik-Olympiade 2. Stufe (Regionalrunde) Klasse Lösung 10 Punkte

Der Aufruf von DM_in_Euro 1.40 sollte die Ausgabe 1.40 DM = Euro ergeben.

Unterrichtsmaterialien in digitaler und in gedruckter Form. Auszug aus: Übungsbuch für den Grundkurs mit Tipps und Lösungen: Analysis

Würfelt man dabei je genau 10 - mal eine 1, 2, 3, 4, 5 und 6, so beträgt die Anzahl. der verschiedenen Reihenfolgen, in denen man dies tun kann, 60!.

Austausch- bzw. Übergangsprozesse und Gleichgewichtsverteilungen

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

EINFACHES HAUSHALT- KASSABUCH

Lineare Funktionen. 1 Proportionale Funktionen Definition Eigenschaften Steigungsdreieck 3

1 topologisches Sortieren

Theoretische Grundlagen der Informatik WS 09/10

3. LINEARE GLEICHUNGSSYSTEME

Übungen Programmieren 1 Felix Rohrer. Übungen

Kapitel 3 Frames Seite 1

GEVITAS Farben-Reaktionstest

Die Erstellung eigener Strukturprofile

Arbeiten mit UMLed und Delphi

Grundlagen der höheren Mathematik Einige Hinweise zum Lösen von Gleichungen

HANDBUCH PHOENIX II - DOKUMENTENVERWALTUNG

Zahlen und das Hüten von Geheimnissen (G. Wiese, 23. April 2009)

1 Vom Problem zum Programm

Im Jahr t = 0 hat eine Stadt Einwohner. Nach 15 Jahren hat sich die Einwohnerzahl verdoppelt. z(t) = at + b

1 Einleitung. Lernziele. Symbolleiste für den Schnellzugriff anpassen. Notizenseiten drucken. eine Präsentation abwärtskompatibel speichern

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

ARCO Software - Anleitung zur Umstellung der MWSt

Jede Zahl muss dabei einzeln umgerechnet werden. Beginnen wir also ganz am Anfang mit der Zahl,192.

Lineare Gleichungssysteme

Sowohl die Malstreifen als auch die Neperschen Streifen können auch in anderen Stellenwertsystemen verwendet werden.

In diesem Tutorial lernen Sie, wie Sie einen Termin erfassen und verschiedene Einstellungen zu einem Termin vornehmen können.

a n auf Konvergenz. Berechnen der ersten paar Folgenglieder liefert:

Excel Pivot-Tabellen 2010 effektiv

Rekursionen. Georg Anegg 25. November Methoden und Techniken an Beispielen erklärt

Tangentengleichung. Wie lautet die Geradengleichung für die Tangente, y T =? Antwort:

Dieser Ablauf soll eine Hilfe für die tägliche Arbeit mit der SMS Bestätigung im Millennium darstellen.

LU-Zerlegung. Zusätze zum Gelben Rechenbuch. Peter Furlan. Verlag Martina Furlan. Inhaltsverzeichnis. 1 Definitionen.

14 Schmiegeparabel und Freunde, Taylor-Reihe

Mediator 9 - Lernprogramm

Das RSA-Verschlüsselungsverfahren 1 Christian Vollmer

Lassen Sie sich dieses sensationelle Projekt Schritt für Schritt erklären:

Novell Client. Anleitung. zur Verfügung gestellt durch: ZID Dezentrale Systeme. Februar ZID Dezentrale Systeme

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter

GLIEDERUNG UND BASISGLIEDERUNG. 2010/03/09 BMD Systemhaus GmbH, Steyr Vervielfältigung bedarf der ausdrücklichen Genehmigung durch BMD!

Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten

Bauteilattribute als Sachdaten anzeigen

CAQ Software für Ihr Qualitätsmanagement. Ablauf für die Erfassung der Fehler in der Fertigung

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Einführung in. Logische Schaltungen

Zahlenwinkel: Forscherkarte 1. alleine. Zahlenwinkel: Forschertipp 1

Abituraufgabe zur Stochastik, Hessen 2009, Grundkurs (TR)

Einrichten einer Festplatte mit FDISK unter Windows 95/98/98SE/Me

Access [basics] Rechnen in Berichten. Beispieldatenbank. Datensatzweise berechnen. Berechnung im Textfeld. Reporting in Berichten Rechnen in Berichten

OECD Programme for International Student Assessment PISA Lösungen der Beispielaufgaben aus dem Mathematiktest. Deutschland

Erstellen von x-y-diagrammen in OpenOffice.calc

geben. Die Wahrscheinlichkeit von 100% ist hier demnach nur der Gehen wir einmal davon aus, dass die von uns angenommenen

Microsoft Excel 2010 Mehrfachoperation

Software Engineering Klassendiagramme Assoziationen

TECHNISCHE UNIVERSITÄT MÜNCHEN

Ihr Mandant möchte einen neuen Gesellschafter aufnehmen. In welcher Höhe wäre eine Vergütung inklusive Tantieme steuerrechtlich zulässig?

OSD-Branchenprogramm. OSD-Version Was ist neu? EDV-Power für Holzverarbeiter

V 2 B, C, D Drinks. Möglicher Lösungsweg a) Gleichungssystem: 300x y = x + 500y = 597,5 2x3 Matrix: Energydrink 0,7 Mineralwasser 0,775,

SEP 114. Design by Contract

Kapitalerhöhung - Verbuchung

Ist Excel das richtige Tool für FMEA? Steve Murphy, Marc Schaeffers

Updatehinweise für die Version forma 5.5.5

Einführung in die Java- Programmierung

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Second Steps in eport 2.0 So ordern Sie Credits und Berichte

Binärdarstellung von Fliesskommazahlen

Informatik 2 Labor 2 Programmieren in MATLAB Georg Richter

Programmierkurs Java

Zur drittletzten Zeile scrollen

Fehler und Probleme bei Auswahl und Installation eines Dokumentenmanagement Systems

Stundenerfassung Version 1.8

Güte von Tests. die Wahrscheinlichkeit für den Fehler 2. Art bei der Testentscheidung, nämlich. falsch ist. Darauf haben wir bereits im Kapitel über

Urlaubsregel in David

Einführung in die Algebra

Was meinen die Leute eigentlich mit: Grexit?

Klausur WS 2006/07 Programmiersprache Java Objektorientierte Programmierung II 15. März 2007

Anzeige von eingescannten Rechnungen

FAQ Spielvorbereitung Startspieler: Wer ist Startspieler?

Skript und Aufgabensammlung Terme und Gleichungen Mathefritz Verlag Jörg Christmann Nur zum Privaten Gebrauch! Alle Rechte vorbehalten!

Der Zwei-Quadrate-Satz von Fermat

Wurzeln als Potenzen mit gebrochenen Exponenten. Vorkurs, Mathematik

Transkript:

Constraint Logical Programming Betreuer: Thomas Ströder Proseminar: Fortgeschrittene Programmierkonzepte in Java, Haskell und Prolog Rene Niewianda, Martin Breuer 15. Juni 2015 1 Einleitung: Das Ziel dieses Vortrags ist, grundlegende Strukturen der Constraint Programmierung am Beispiel der Constraint-Theorie für finite Domains kennen zu lernen. Dabei betrachten wir die Auswertung der Constraints und vergleichen Programmieraufwand sowie die Laufzeit von normalen, uns bekannten Logikprogrammen und Logikprogrammen mit Constraints unter Verwendung der Prolog Implementierung SWI-Prolog. Inhaltlich orientieren wir uns an den Vorlesungsnotizen der Vorlesung Logikprogrammierung [Gie13]. 1.1 Was ist ein Constraint? Ein Constraint ist eine Einschränkung, Bedingung oder Relation zwischen Termen. Diese Terme sind einfache logische Formeln, z. B. X #= Y+1 oder {X*X=Y}, wobei das # und die geschweiften Klammern der Notation in Prolog entsprechen. Wie genau diese Ausdrücke ausgewertet werden bzw. wann sie wahr sein sollen, wird in einer so genannten Constraint-Theorie festgelegt. 1.2 Constraint-Theorie Eine Constraint-Theorie ist eine Erweiterung der in einem Logikprogramm vorhandenen Prädikate. Würde man eine leere Constraint-Theorie verwenden, so würde das Programm einem normalen, uns bekannten Logikprogramm entsprechen. In Prolog gibt es mehrere Constraint-Theorien, u. a. eine für reelle Zahlen ( CLPR ) und eine für ganze Zahlen ( CLP(FD) ), wobei CLP für Constraint Logical Programming, R für Real und FD für Finite Domain steht. In der Constraint-Theorie CLPR werden reelle Zahlen durch Fließkommazahlen repräsentiert. Eine genaue Darstellung aller reeller Zahlen ist folglich nicht möglich. Diese Erweiterungen sind als Module in Prolog verfügbar. Sie lassen sich einfach über :-use module(library(clpr)). 1

oder :- use module(library(clpfd)). in ein Logikprogramm einbinden. Bei den hier aufgeführten Beispielen sei die jeweilige Constraint-Theorie stets konsultiert. Weitere Beispiele für Constraints sind: CLP(FD) CLPR X #= Y+1 {X = Y + 1} X #>= Y*10 {X >= Y*10} X #\= Y {X =\= Y} X*X #\= Y + 1 {X*X =\= Y+1} 2 Die Constraint-Theorie CLP(FD) 2.1 Die Auswertung mit Finite Domains in SWI-Prolog Bei einem Logikprogramm mit Constraints, werden die Relationen zwischen den Variablen oder Termen gesammelt und vereinfacht. Die gesammelten Constraints bzw. Relationen werden daraufhin durch den Constraint-Solver ausgewertet. Wir betrachten nun anhand eines Beispiels, wie der Constraint-Solver eine Konjunktion von Constraints auswertet, wobei das Sammeln der Constraints in diesem Beispiel trivial ist (ein komplexeres Beispiel zum Sammeln der Constraints ist in 3.3 zu finden):? X1 #> X2, X2 #> 5, X1 #< 8. Für jede Variable (X 1,..., X n ) der Constraints werden Domains (D 1,..., D n ), wobei n die Anzahl der Variablen der Constraints ist, angelegt, die zuerst alle auf Z gesetzt werden. Normale Prädikate werden hierbei insofern umgeschrieben, dass ihre Variablen nicht, wie bei der normalen Logikprogrammierung, direkt unifiziert, sondern durch Constraints ersetzt werden. Vereinfachend gesagt wird für eine Variable eines normalen Prädikats eine Domain angelegt. Wir durchlaufen die Constraints solange, bis sich die Domains nicht mehr ändern, wobei wir die Domains an die Bedingungen anpassen: Zuerst setzen wir die Domains D 1 = Z und D 2 = Z. Wenn wir nun den ersten Constraint X1 #> X2 betrachten, fällt auf, dass die Domains nicht verändert werden müssen, da wir nur den ersten Constraint isoliert betrachten. Betrachten wir hingegen den zweiten Constraint, so ändern sich die Domains auf D 1 = Z und D 2 = {6, 7,.., }. Beim dritten Constraint X1 #< 8 werden wiederum die Domains eingeschränkt: D 1 = {,.., 7} und D 2 = {6, 7,.., }. Nun beginnen wir bei den Constraints von vorne und prüfen, ob die Domains verändert werden müssen. Wir durchlaufen die Constraints mehrmals, um die Zusammenhänge zwischen den Variablen zu erfassen. Mit dem ersten Constraint X1 #> X2 folgt nun: D 1 = {7} und D 2 = {6}. Falls keine Änderungen beim wiederholten isolierten Betrachten der einzelnen Constraints stattfinden und alle Domains nicht leer sind, nennt 2

man die Konjunktion der Constraints pfadkonsistent. Als letztes wird also die Pfadkonsistenz geprüft und somit folgt (da die Domains nicht leer sind), dass die Lösungen der Anfrage X1 = 7 und X2 = 6 sind.? X1 #> X2, X2 #> 5, X1 #< 8. X1 = 7, X2 = 6. Falls die Auswertung leere Domains als Ergebnis haben sollte, so wird die Anfrage mit false. beantwortet. Als Notation für unendlich große und kleine Werte werden die Schlüsselwörter sup und inf als Ergebnis ausgegeben. Einen Vorteil, den wir hier sehen, ist die Bidirektionalität der Constraints, d. h. wir müssen während der Implementierung der Prädikate nicht wissen, welche Werte wir gegeben haben bzw. berechnen wollen, da wir lediglich Zusammenhänge bzw. Relationen zwischen den Variablen festlegen. Bei der Logikprogrammierung ohne Constraints muss z. B. beim infix Prädikat is/2 die rechte Seite komplett ausgewertet sein. Hierzu betrachten wir ein Beispiel, welches sowohl in Standard-Prolog als auch mit Constraints implementiert wurde: Ohne Constraints: minuszehn (X, Y) : Y i s X 1 0. Stellen wir nun eine Anfrage an das Programm, bei der uns die Variable Y bekannt und X unbekannt ist, erhalten wir einen Instanziierungsfehler:? minuszehn (X, 1 0 ). ERROR: i s / 2 : Arguments are not s u f f i c i e n t l y i n s t a n t i a t e d Betrachten wir nun das bidirektionale Programm mit Constraints: : use module ( l i b r a r y ( c l p f d ) ). minuszehnc (X, Y) : Y #= X 10. So können wir ohne weiteres die gleiche Anfrage stellen und erhalten ein sinnvolles Ergebnis:? minuszehnc (X, 1 0 ). X = 2 0. Ein dadurch entstandener Vorteil ist, dass sich die Constraint Programme universeller einsetzen und wiederverwenden lassen. Ist die Berechnung einer Variable X, die nur von Y abhängig ist, deutlich schwerer zu implementieren, als die Berechnung von Y, so können wir mithilfe von Constraints die andere Richtung implementieren. Dadurch könnte z. B. vermieden werden komplexe arithmetische Operationen zu verwenden. Dies führt zu einer deutlichen Verbesserung des Programmierkomforts bzw. einer Vereinfachung der Problemlösung. Siehe hierzu auch das Beispiel in 5.1. 3

2.2 Nützliche Prädikate von CLP(FD) In der Constraint-Theorie CLP(FD) sind verschiedene Prädikate implementiert, die einem das Lösen von kombinatorischen Problemen ermöglichen bzw. deutlich erleichtern. Wir wollen nun ein paar der nützlichsten Prädikate der CLP(FD) Constraint-Theorie betrachten. Ein besonderes Augenmerk soll auf Prädikate gelegt werden, die Eigenschaften bzw. Bedingungen an Listen stellen. Um eine Liste XS von Zahlen zwischen 1 und 30 zu erzeugen, benutzen wir den Constraint XS ins 1..30, der besagt, dass jedes Element von XS einen Wert zwischen 1 und 30 besitzt. Wollen wir nun die Anzahl der Elemente auf einen Beispielwert von 9 festlegen, so können wir das vordefinierte Prolog Prädikat length(xs, 9) verwenden. An dieser Stelle soll betont werden, dass length/2 kein Prädikat von CLP(FD) ist und es lediglich zum Instanziieren der Liste benötigt wird. Wenn wir die Anfrage length(xs,9), XS ins 1..30. stellen, so erhalten wir eine Liste, wobei für jedes Element lediglich in 1..30 angegeben wird. Möchten wir jedoch konkrete Werte für jedes Element haben, so können wir dies mit label/1 lösen, sodass Prolog nun statt Wertebereichen konkrete Werte liefert:? length (XS, 9 ), XS i n s 1.. 3 0, l a b e l (XS ). XS = [ 1, 1, 1, 1, 1, 1, 1, 1, 1 ] Zu beachten ist bei der Nutzung von label/1, dass die Menge der möglichen Werte für eine Variable endlich sein muss. Falls die Menge unendlich ist, so liefert die Anfrage einen Fehler. Ein solcher Fehler könnte wie folgt aussehen:? X1 #> 3, X1 i n i n f.. sup, l a b e l ( [ X1 ] ). ERROR: Arguments are not s u f f i c i e n t l y i n s t a n t i a t e d Wenn für X1 jedoch eine feste obere Schranke gewählt wird, könnte folgende Ausgabe erfolgen:? X1 #> 3, X1 i n i n f.. 6, l a b e l ( [ X1 ] ). X1 = 4 ; X1 = 5 ; X1 = 6. Nun wollen wir jedoch paarweise unterschiedliche Werte in unserer Liste vorfinden. Um dies zu realisieren, gibt es das Prädikat all different/1, welches angewandt auf unsere Liste dafür sorgt, dass alle Werte paarweise unterschiedlich sind:? length (XS, 9 ), XS i n s 1.. 3 0, a l l d i f f e r e n t (XS), l a b e l (XS ). XS = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]. Angenommen uns wäre wichtig, dass die Summe der Elemente größer als 100 sein sollte, so ließe sich dies mit dem Prädikat sum/3 realisieren, wobei der erste Parameter die Liste, der Zweite eine Relation (#=, #>, #<, usw.) und 4

der Letzte ein Ausdruck ist, zu dem die Summe der Elemente in Relation stehen soll:? length (XS, 9 ), XS i n s 1.. 3 0, a l l d i f f e r e n t (XS), sum(xs,# >,100), l a b e l (XS ). XS = [ 1, 2, 3, 4, 5, 6, 21, 29, 3 0 ]. Wir haben nun den Gedanken gefasst, dass wir an sechster Stelle in der Liste unbedingt eine 13 haben möchten, so können wir dies mit dem Prädikat element(6,xs,13) festlegen:? length (XS, 9 ), XS i n s 1.. 3 0, element ( 6, XS, 13), a l l d i f f e r e n t (XS), sum(xs, #=, 100), l a b e l (XS ). XS = [ 1, 2, 3, 4, 5, 13, 14, 28, 3 0 ]. Weitere Prädikate für fortgeschrittenere Anwendungsgebiete (z. B. endliche Automaten) sind in dem SWI-Prolog Manual [Tri12] 1 zu finden, welches auch als Quelle für diesen Abschnitt verwendet wurde. 2.3 Mechanismen zur Verbesserung der Laufzeit Um die Performance der CLP(FD) Auswertung zu verbessern, werden arithmetische Constraints zur Kompilezeit überschrieben, sodass lower-level Prädikate wann immer möglich benutzt werden (Übersetzung aus [Tri]). Somit wird die Performance des Constraint solvers mithilfe von Low-Level-Code automatisch verbessert. Da der SWI-Prolog Finite Domain Constraint Solver in Prolog implementiert ist, steht die Performance der Auswertung in Relation zur Performance des unterliegenden Prolog Systems. Dies hat den Nachteil, dass sich ein ineffizientes Grundsystem auf die endgültige Performance des Constraint-Solvers auswirkt. Es existieren effizientere Systeme als SWI-Prolog, der Vorteil dieses Systems ist jedoch, dass es mit großen ganzzahligen Werten rechnen kann [Tri12]. 3 Vergleich von Prolog mit und ohne Constraints Im Folgendem wollen wir durch den Vergleich an einem konkreten Beispiel die Unterschiede zwischen Prolog mit und ohne Constraints untersuchen. Dazu betrachten wir das N-Damen Problem. 3.1 Das N-Damen Problem Kern dieses Problems ist es, n Damen auf einem n*n großen Schachfeld zu platzieren, ohne dass sie sich gegenseitig schlagen können. Das heißt, dass in den Spalten und Zeilen des Feldes jeweils nur eine Dame stehen darf. Zusätzlich dürfen auch keine Damen auf der gleichen Diagonalen stehen. 1 http://www.swi-prolog.org/pldoc/man?section=clpfd 5

Abbildung 1: Zugrichtungen Wir betrachten zunächst die trivialen Fälle: 1,2,3 Damen. Bei einer Dame ist die Lösung offensichtlich, da es nur ein Feld und eine Dame gibt. Die Fälle mit zwei bzw. drei Damen sind nicht lösbar, da es keine Möglichkeit gibt, die Damen mit Berücksichtigung der oben beschriebenen Regeln zu platzieren. (a) 1-Dame (b) 2-Damen (c) 3-Damen(1) (d) 3-Damen(2) Abbildung 2: Triviale Fälle Im Folgenden werden wir das Schachfeld mit den platzierten Damen als Liste auffassen, sodass der Platz einer Zahl in der Liste die jeweilige Spalte auf dem Feld angibt und die Zahl selbst die Zeile. Hier ein Beispiel zur Liste [5,2,4,1,3] : Abbildung 3: 6

3.2 Lösung des Problems mit Constraints : use module ( l i b r a r y ( c l p f d ) ). queens (N, L) : length (L,N), L i n s 1.. N, a l l d i f f e r e n t (L) s a f e (L), l a b e l (L ). s a f e ( [ ] ). s a f e ( [X Xs ] ) : s a f e b e t w e e n (X, Xs, 1 ), s a f e ( Xs ). s a f e b e t w e e n (X, [ ],M). s a f e b e t w e e n (X, [ Y Ys ],M) : n o a t t a c k (X,Y,M), M1 #= M + 1, s a f e b e t w e e n (X, Ys,M1). n o a t t a c k (X,Y,N) : X+N #\= Y, X N #\= Y. Programmcode siehe [Gie13]. Die folgenden Erklärungen orientieren sich an [Gie13]. Die Eingabe für dieses Programm ist queens(n,l), wobei N die Größe des Feldes bzw. die Anzahl der Damen angibt und L die Liste mit deren Positionen. Wir überprüfen mit dem vordefinierten Prädikat lenght/2, ob L die korrekte Länge, also N hat. Die drei Prädikate +Vars ins +Domains, all different() und label/1 sind in der clpfd-bibliothek vordefiniert. Mit ins wird überprüft, ob die Zahlen in L im Bereich 1 bis N liegen, sodass zusammen mit length/2 sichergestellt wird, dass die Höhe und Breite des Feldes eingehalten wird. Mit dem Prädikat all different/1 wird sichergestellt, dass keine zwei Damen in derselben Zeile stehen. Zusammen mit dem allgemeinen Aufbau der Liste L ist so sichergestellt, dass sich keine Damen auf Geraden schlagen können. Durch das Prädikat safe/1 wird die letzte Anforderung an L geprüft, dass keine zwei Damen auf der selben Diagonalen stehen. Dazu werden alle Spalten rechts einer Dame überprüft. Hier werden die beiden Hilfsprädikate safe between/3 und no attack/3 verwendet. safe between(x,l,m) wird wahr, wenn die Dame in der Zeile X die Dame in der Zeile L, welche M Spalten entfernt ist, nicht schlagen kann. Dazu wird zusätzlich das Prädikat no attack/3 verwendet, um dies sicherzustellen. no attack(x,y,n) wird wahr, wenn die Dame X nicht auf der Diagonalen der Dame Y steht, welche N Spalten entfernt ist. Dieses Programm ist bidirektional, d.h. es kann sowohl zu einer Liste das entsprechende N bestimmen (wobei die Liste auf Richtigkeit geprüft wird) 7

als auch aus einem N die entsprechenden Ergebnislisten bestimmen. Für N=4 ist die Ein- und Ausgabe :? queens ( 4,L ). L = [ 2, 4, 1, 3 ] ; L = [ 3, 1, 4, 2 ] ; f a l s e. 3.3 Auswertung am Beispiel von N = 4 In Prolog werden die Prädikate der Reihe nach von links nach rechts und von oben nach unten abgearbeitet, sodass bei der Anfrage?-queens(4,L). folgende Schritte durchgeführt werden: Als ersten Schritt erzeugen wir mithilfe von length/2 eine Liste der Länge vier, die als Elemente Variablen enthält und später die Position einer Dame in der jeweiligen Spalte repräsentiert. Damit wir die folgenden Ausgaben von SWI-Prolog besser lesen können, wurden die ausgegebenen Variablennamen (z. B. G4888) durch besser lesbare (z. B. X1) ersetzt:? length (L, 4 ). L = [ X1, X2, X3, X4 ]. Da die Nummer der Zeile, in der sich eine Dame befinden kann, zwischen 1 und 4 bewegt, reduzieren wir den Wertebereich der Variablen auf 1 bis 4:? length (L, 4 ), L i n s 1.. 4. L = [ X1, X2, X3, X4 ], X1 i n 1.. 4, X2 i n 1.. 4, X3 i n 1.. 4, X4 i n 1.. 4. Nun stellen wir sicher, dass sich keine Dame in der gleichen Zeile befindet, indem wir mit all different/1 die paarweise Unterschiedlichkeit der Einträge sichern:? length (L, 4 ), L i n s 1.. 4, a l l d i f f e r e n t (L ). L = [ X1, X2, X3, X4 ], X1 i n 1.. 4, a l l d i f f e r e n t ( [ X1, X2, X3, X4 ] ), X2 i n 1.. 4, X3 i n 1.. 4, X4 i n 1.. 4. Wir sehen nun, dass Prolog für den ersten Listeneintrag Werte von eins bis vier zulässt und von dort ausgehend mit all different/1 gleiche Werte ausschließt. Im nächsten Schritt stellen wir sicher, dass sich in einer Diagonalen nur eine Dame befindet, wobei hier wiederum Ungleichungen gesammelt werden: 8

? length (L, 4 ), L i n s 1.. 4, a l l d i f f e r e n t (L), s a f e (L ). L = [ X1, X2, X3, X4 ], X1 i n 1.. 4, X1#\=X4+3, X4#\=X1+3, X1#\=X3+2, X3#\=X1+2, X1#\=X2+1, X2#\=X1+1, a l l d i f f e r e n t ( [ X1, X2, X3, X4 ] ), X4 i n 1.. 4, X3#\=X4+1, X4#\=X3+1, X2#\=X4+2, X4#\=X2+2, X3 i n 1.. 4, X2#\=X3+1, X3#\=X2+1, X2 i n 1.. 4. Im letzten Schritt, nachdem wir alle Relationen zwischen den Variablen aufgestellt haben, lassen wir uns mithilfe von label/1 konkrete Werte ausgeben. Für die Berechnung der jeweiligen Werte ist der Constraint-Solver 2 zuständig, der, wenn wir mit einem Semikolon erzwingen, dass weitere Werte gesucht werden, diese unter Zuhilfenahme von Backtracking findet:? length (L, 4 ), L i n s 1.. 4, a l l d i f f e r e n t (L), s a f e (L), l a b e l (L ). L = [ 2, 4, 1, 3 ] ; L = [ 3, 1, 4, 2 ] ; f a l s e. 3.4 Vergleich mit einer constraintfreien Lösung Um die Unterschiede des gerade vorgestellten Programms zu dem Programm mit Constraints zu verdeutlichen, werden wir es mit dem folgendem constraintfreien Programm vergleichen. e r z l i s t e n ( [ 1 ], 1 ). e r z l i s t e n ( [N XS ],N) : NMO i s N 1, e r z l i s t e n (XS,NMO),!. queens (N, L) : length (L,N), e r z l i s t e n (R,N), permutation (L,R), s a f e (L ). s a f e ( [ ] ). s a f e ( [X Xs ] ) : s a f e b e t w e e n (X, Xs, 1 ), s a f e ( Xs ). s a f e b e t w e e n (X, [ ], M). s a f e b e t w e e n (X, [ Y Ys ],M) : n o a t t a c k (X,Y,M), M1 i s M + 1, s a f e b e t w e e n (X, Ys,M1). n o a t t a c k (X,Y,N) : R i s (X+N), Y \== R,Q i s X N, Y \== Q. Zuerst werden wir die Funktionsweise grob umreißen und danach die Vorteile der Constraint-Lösung hervorheben. Dieses Programm ist, wie das Constraint-Programm, bidirektional. Dies kann nicht bei allen constraintfreien Programmen sichergestellt werden, da 2 Wie der Solver im Einzelnen funktioniert, wurde bereits im Abschnitt 2.1 beispielhaft erklärt. 9

es darauf ankommt, wie die einzelnen Prädikate konstruiert sind bzw. verwendet werden. Hier wurden Constraints wie #= in is Prädikate umgewandelt. is ist jedoch unidirektional, was hier aber keinen Unterschied macht, da das Prädikat safe/1 in beiden Fällen nur in eine Richtung aufgerufen wird. Die Constraints +Vars ins +Domains, all different/1 und label/1 wurden durch eine Kombination der Prädikate erzlisten/2 und permutation/2 ersetzt. erzlisten(l,n) wird wahr, wenn die Liste L die Elemente von 1 bis N in absteigender Reihenfolge enthält.? e r z l i s t e n (L, 4 ) L = [ 4, 3, 2, 1 ] Der Cut am Ende der Funktion verhindert lediglich das Auftreten von Fehlern. Da es nur ein mögliches richtiges Ergebnis gibt, würde eine Fortsetzung der Suche nicht mehr terminieren. Das vordefinierte Prädikat permutation(r,l) ist wahr, wenn R eine Permutation von L ist. Diese beiden Prädikate zusammen erzeugen nacheinander alle Listen der Länge N mit den Elementen von 1 bis N. Diese sind wichtig für den Schritt von einem N zu einer Liste. Um von einer Liste zu einem N zu kommen, wird mit dem Prädikat length/2 sichergestellt, welches zuerst die Länge der Liste misst, dass erzlisten/2 ausreichend instanziiert ist (was unerlässlich für Bidirektionalität ist). Im Rest des Codes sind lediglich die Rechnungen ersetzt worden, was aber in diesem Fall, wie gerade beschrieben, keinen Unterschied macht. Betrachten wir einen weiteren Unterschied der beiden Programme und zwar die Laufzeiten. Dieser Unterschied zeigt sich deutlich durch Tests mit verschiedenen Eingaben. Wir verwenden time/1, um die Zeit zu messen. Wir betrachten nur die Zeit bis zum ersten Ergebnis: N Mit C. Ohne C. 1 0.000s 0.000s 4 0.000s 0.000s 5 0.000s 0.000s 10 0.005s 0.145s 11 0.005s 0.980s 12 0.012s 9.8s 13 0.007s 93s 14 0.073s 1327s 10

Hier zeigt sich klar und deutlich, dass durch Constraints die Auswertung bestimmter Prädikate optimiert wird, sodass sie nicht wie in der constraintfreien Lösung wie ein reines Logikprogramm ausgewertet werden. Die schnelle Zunahme der Laufzeit lässt sich dadurch erklären, dass es N! verschiedene Listen gibt und das Programm alle nacheinander überprüft, bis es eine richtige Lösung gefunden hat. Es ist noch anzumerken, dass je nachdem, wie das Programm implementiert ist, die Laufzeit variieren kann, da die Reihenfolge, in der die Listen überprüft werden, eine große Rolle spielt. 4 Fazit Wie wir gesehen haben, haben Constraints viele Vorteile gegenüber normaler Logikprogrammierung. Es ist meistens intuitiver zu programmieren, da man nicht prüfen muss, ob bei jeder Eingabevariation alle Prädikate ausreichend instanziiert sind. Es reicht meist aus, dies für eine Richtung zu tun. Der Rest wird dann durch die Bidirektionalität der Constraints übernommen. Das erhöht die Wiederverwendbarkeit, wie bereits oben erwähnt. Durch diese Vorteile und die Tatsache, dass viele häufig verwendeten Prädikate bereits vordefiniert sind, werden die Programme in sich und Programme, die die Prädikate weiter verwenden, leichter lesbar, da man nicht alle Prädikate erst erschließen muss. Ein weiterer nicht zu vernachlässigender Vorteil ist die Laufzeit, welche vor allem bei komplexen Programmen und Anfragen eine Rolle spielt, da die Programme um ein vielfaches schneller laufen. Abschließend lässt sich also sagen, dass Constraints für die Arithmetik in Prolog eine nötige und sinnvolle Erweiterung darstellen. Da wir bisher nur die Constraint-Theorie CLP(FD) betrachtet haben, wollen wir noch einen kurzen Blick auf eine andere Theorie werfen. 5 Ausblick 5.1 Constraint Logical Programming over Rationals C B Abbildung 4: A Wir betrachten nun ein Anwendungsbeispiel für Constraints mit rationalen bzw. reellen Zahlen, welches wir bereits in dem Kurzvortrag kennen gelernt haben. Wir wollen Seitenlängen eines rechtwinkligen Dreiecks mithilfe des Satzes von Pythagoras (A 2 + B 2 = C 2 ) bestimmen. Dabei sind die Bezeichnungen der jeweiligen Seiten wie in Abbildung 4 gewählt. Die Relation zwischen den Variablen ist hierbei nicht linear. In der Gleichung müssen immer zwei von drei Va- 11

riablen gegeben sein, damit wir die Gleichung eindeutig lösen können. In unserem Beispiel betrachten wir nun eine mögliche Implementierung mit Constraints, wobei wir auch negative Werte für Strecken zulassen: : use module ( l i b r a r y ( c l p r ) ). pyt (A, B, C) : { C C = A A + B B}. Hier haben wir zuerst das Modul für die Constraint-Theorie CLPR geladen und das Prädikat pyt/3 definiert, welches den Satz des Pythagoras implementiert, indem eine Relation zwischen den Variablen angegeben wird. Hier sehen wir wiederum, dass im Gegensatz zum Prädikat is/2 die linke Seite des Ausdrucks eine Formel enthalten darf. Wir können nun eine Anfrage an unser Programm stellen:? pyt ( 1,X, 4 ). X = 3. 872983346207417. Angenommen wir wollen dieses Problem ohne Constraints lösen, so könnte eine Implementierung wie folgt aussehen: pytn (A, B,C) : C i s s q r t (A A+B B ). Solange wir C berechnen möchten, gibt es kein Problem, wenn wir allerdings B oder A berechnen wollen, erhalten wir Instanziierungsfehler:? pytn ( 1, 2,X). X = 2. 23606797749979.? pytn ( 1,X, 3 ). ERROR: i s / 2 : Arguments are not s u f f i c i e n t l y i n s t a n t i a t e d Um dieses Problem zu lösen, müssten wir für jede Kombination von gegebenen Variablen ein eigenes Prädikat implementieren. Des Weiteren ist hier der Nachteil, dass die Grundrechenarten nicht mehr ausreichen und wir komplexere arithmetische Operationen benötigen. Dies führt zu einem deutlich höheren Entwicklungsaufwand und erschwert die Lösung des Problems. Literatur [Gie13] Jürgen Giesl. Logikprogrammierung, sommersemester 2013, lehrund forschungsgebiet informatik 2, rwth aachen. pages 118 136, 2013. [Tri] Markus Triska. library(clpfd): Constraint logical programming over finite domains. http://www.swi-prolog.org/man/clpfd.html. [Tri12] Markus Triska. The finite domain constraint solver of SWI-Prolog. In FLOPS, volume 7294 of LNCS, pages 307 316, 2012. 12