Prolog Tutorial Μαθηματική Λογική
Προγράμματα στην Prolog Οι προτάσεις αυτές λέγονται προτάσεις Horn και αποτελούν υποσύνολο της λογικής πρώτης τάξης. Προτάσεις Horn A ← A0,A1,…,An : Για να δείξεις το Α πρέπει να δείξεις το Α0 και το Α1,…,και το Αν
Γεγονότα και Κανόνες Υπάρχουν δύο είδη προτάσεων σε ένα πρόγραμμα Prolog, τα γεγονότα και οι κανόνες. Τα γεγονότα εκφράζουν σχέσεις ανάμεσα στα αντικείμενα και αποτελούν κατά ένα τρόπο τα δεδομένα του προβλήματος, π.χ. father(george, mary). Οι κανόνες εκφράζουν γενικότερες σχέσεις ανάμεσα στα αντικείμενα οι οποίες ορίζονται με τη βοήθεια άλλων σχέσεων, π.χ. parent(X,Y):- father(X,Y). parent(X,Y):- mother(X,Y). Τα X, Y είναι μεταβλητές. Το σύμβολο :- εκφράζει το λογικό «ΑΝ»
Αλληλεπίδραση με την Prolog Ο χρήστης αλληλεπιδρά με ένα σύστημα Prolog, δίνοντας σε αυτό ερωτήσεις (queries), τις οποίες το σύστημα προσπαθεί να απαντήσει με βάση τα γεγονότα και τους κανόνες. Οι απαντήσεις που επιστρέφονται είναι είτε yes/no Αν η ερώτηση περιέχει μεταβλητές, κατάλληλες τιμές για τις μεταβλητές αυτές.
Παράδειγμα προγράμματος (1/3) father(george,mary). father(george,nick). father(peter,marina). mother(helen,mary). mother(helen,nick). mother(ann,marina). parent(X,Y):- father(X,Y). parent(X,Y):- mother(X,Y).
Παράδειγμα προγράμματος (2/3) Θεωρούμε ότι οι παραπάνω προτάσεις είναι αποθηκευμένες σε ένα απλό αρχείο κειμένου και ότι «φορτώθηκαν» σε κάποιο διερμηνευτή της Prolog. Πιθανές ερωτήσεις - απαντήσεις που μπορούν να γίνουν με βάση το παραπάνω πρόγραμμα είναι: ?- father(george,mary). - yes ?- father(george,marina). - no ?- father(peter,X). - X=marina
Παράδειγμα προγράμματος (3/3) ?- mother(X,marina). - X=ann ?- parent(george,X). - X=mary; - X=nick ?- parent(paul,X). - no ?- mother(X,Y). - X=helen, Y=maria; X=helen, Y=nick; X=ann, Y=marina; no
Σύνταξη της Prolog Τα στοιχεία της γλώσσας είναι οι όροι τα γεγονότα οι κανόνες οι ερωτήσεις Σχόλια Τα σχόλια στην Prolog εισάγονται είτε με τον χαρακτήρα “%”, είτε περικλείονται στους χαρακτήρες /* και */.
Όροι Όροι στην Prolog Απλοί Σύνθετοι Σταθερές Μεταβλητές Συναρτησιακό σύμβολο Ορίσματα άτομα αριθμοί Απλοί όροι Σύνθετοι όροι
Απλοί όροι Οι απλοί όροι είναι οι αριθμοί, τα άτομα και οι μεταβλητές. Οι αριθμοί έχουν τη συνηθισμένη μορφή, κοινή με τις υπόλοιπες γλώσσες προγραμματισμού. Τα άτομα είναι συμβολοσειρές, οι οποίες πρέπει απαραίτητα να ξεκινούν από πεζό γράμμα ή να περιλαμβάνονται σε μονά εισαγωγικά, π.χ. anna, x25, x_25, x_, ‘Tom’, ‘cd player’
Μεταβλητές (1/2) Οι μεταβλητές είναι συμβολοσειρές που μπορεί να περιέχουν γράμματα, ψηφία ή τον χαρακτήρα «_», και πρέπει πάντα να ξεκινούν με κεφαλαίο γράμμα ή με τον χαρακτήρα «_», π.χ. X, Result, Object2, _a23 Οι μεταβλητές που ξεκινούν με τον χαρακτήρα «_» ονομάζονται ανώνυμες μεταβλητές. Χρησιμοποιούνται στις περιπτώσεις που δεν μας ενδιαφέρει η τιμή που θα λάβει η συγκεκριμένη μεταβλητή, π.χ. ?- father(peter,_).
Μεταβλητές (2/2) Στην Prolog, σε μία μεταβλητή η οποία έχει πάρει μία τιμή δεν μπορεί να δοθεί νέα (non destructive assignment). Οι μεταβλητές στην Prolog δεν έχουν τύπο (typeless) και άρα δεν απαιτούν δηλώσεις και μπορούν να πάρουν σαν τιμή οποιοδήποτε όρο. Υπάρχουν μόνο τοπικές μεταβλητές, των οποίων η εμβέλεια είναι μέσα στον κανόνα που εμφανίζονται.
Σύνθετοι Όροι Οι σύνθετοι όροι είναι σύνθετες δομές με γενική μορφή f(k1,k2,…,kn) To f ονομάζεται συναρτησιακό σύμβολο (functor) τάξης n και τα k1,k2,…,kn λέγονται ορίσματα. Η τάξη είναι το πλήθος των ορισμάτων του σύνθετου όρου. Τα ορίσματα μπορεί να είναι είτε απλοί ή σύνθετοι όροι, π.χ. date(2,august,1997) triangle(point(4,2),point(6,4),point(7,1))
Γεγονότα Η πιο απλή μορφή προτάσεων Horn τα γεγονότα. Ένα γεγονός εκφράζει την απευθείας σχέση που συνδέει κάποια αντικείμενα. Αποτελείται από μία σχέση ή κατηγόρημα (predicate), το οποίο είναι ένα άτομο ακολουθούμενο από έναν οποιοδήποτε αριθμό παραμέτρων ή ορισμάτων σε παρενθέσεις. Σαν ορίσματα μπορούμε να έχουμε οποιοδήποτε όρο είτε απλό είτε σύνθετο. Το πλήθος των ορισμάτων ονομάζεται τάξη του γεγονότος. Παραδείγματα: student(john,class(a),grade(b)). Γεγονός τάξης 3 με κατηγόρημα student. room(48,top_floor). Γεγονός τάξης 2 με κατηγόρημα room. day_sunny. Γεγονός μηδενικής τάξης με κατηγόρημα day_sunny.
Σύνταξη γεγονότων Ένα γεγονός ακολουθείται πάντα από τελεία. Το τμήμα του γεγονότος που προηγείται της τελείας, δηλαδή το κατηγόρημα και τα ορίσματά του είναι ο ατομικός τύπος. Γεγονός + Ατομικός τύπος Τελεία + Κατηγόρημα Ορίσματα
Κανόνες Οι κανόνες (rules) είναι προτάσεις που ορίζουν νέες σχέσεις με τη βοήθεια άλλων σχέσεων που έχουν ήδη οριστεί. Οι κανόνες έχουν τη γενική μορφή: A:- B1,B2,…,Bn. (n>=1) Το Α ονομάζεται κεφαλή (head) του κανόνα και μπορεί να είναι οποιοσδήποτε ατομικός τύπος. Η κεφαλή διαχωρίζεται από το σώμα με τους χαρακτήρες «:-» οι οποίοι μπορούν να διβαστούν ως «αν». Τα Β1,Β2,…,Βn ονομάζονται σώμα (body) του κανόνα και είναι και αυτοί ατομικοί τύποι. Οι ατομικοί τύποι στο σώμα του κανόνα χωρίζονται συνήθως με κόμμα, ο οποίος δηλώνει λογική σύζευξη (λογικό «και»). Παράδειγμα brother(X,Y):- parent(Z,X),parent(Z,Y).
Ερωτήσεις Οι ερωτήσεις (queries) είναι η μέθοδος που χρησιμοποιείται στην Prolog για την εξαγωγή γνώσης από το πρόγραμμα. Η σύνταξη τους είναι ?- ατομικός τύπος. Ο ατομικός τύπος ονομάζεται κλήση (call) της ερώτησης Οι ερωτήσεις μπορούν να θεωρηθούν ως λογικές προτάσεις προς απόδειξη. Αν η προς απόδειξη ερώτηση ικανοποιείται, η απάντηση στην ερώτηση είναι θετική, και περιλαμβάνει τις τιμές για τις μεταβλητές που περιλαμβάνονται σε αυτή. Διαφορετικά το σύστημα απαντάει αρνητικά.
Απλές Ερωτήσεις Οι απλές ερωτήσεις περιέχουν μία μόνο κλήση. Παράδειγμα προγράμματος και απλών ερωτήσεων. big(bear). big(elephant). small(cat). brown(bear). gray(elephant). black(cat). Ερωτήσεις ?- brown(elephant). - no ?- big(X). - X=bear; X= elephant
Σύνθετες Ερωτήσεις Οι σύνθετες ερωτήσεις περιέχουν παραπάνω από μία κλήσεις. Οι κλήσεις αυτές χωρίζονται με κόμμα που εκφράζει το λογικό «και». Η απάντηση σε μία σύνθετη ερώτηση είναι καταφατική μόνο αν αληθεύουν οι επιμέρους κλήσεις που την αποτελούν. Παραδείγματα ?- small(X),gray(X). - no ?- big(X),gray(X). - X=elephant ?- big(X),black(Y). - X=bear Y=cat; X=elephant Y=cat
Εκτέλεση Προγραμμάτων Η εκτέλεση ενός προγράμματος ξεκινά με μία ερώτηση που υποβάλλει ο χρήστης και φτάνουμε σε λύση όταν έχουν εξαντληθεί όλες οι κλήσεις που αποτελούν την ερώτηση. Η απάντηση στην ερώτηση είναι το αποτέλεσμα του προγράμματος. Η ερώτηση που υποβάλλει ο χρήστης μπορεί να είναι απλή (να περιέχει μία κλήση) ή σύνθετη (σύζευξη πολλαπλών κλήσεων), π.χ. ?- friend(X,nick). ?- friend(X,nick), friend(X,john).
Βήματα εκτέλεσης Αν δεν υπάρχει άλλη κλήση στην ερώτηση του χρήστη τότε η εκτέλεση του προγράμματος τερματίζεται με επιτυχία και επιστρέφονται στον χρήστη οι τιμές των μεταβλητών που περιείχε η ερώτηση. Επιλέγονται με τη σειρά, από αριστερά προς τα δεξιά, οι κλήσεις της ερώτησης. Για κάθε κλήση, ο μηχανισμός ελέγχου αναλαμβάνει να βρει μία πρόταση του προγράμματος της οποίας η κεφαλή έχει το ίδιο κατηγόρημα και τάξη με αυτά της κλήσης. Η ερώτηση θεωρείται ότι απαντήθηκε όταν απαντηθούν επιτυχώς όλες οι κλήσεις της. Εφόσον οι κλήσεις περιέχουν κοινές μεταβλητές, θα πρέπει αυτές να πάρουν την ίδια τιμή.
Αναζήτηση προτάσεων (1/2) Για να ελέγξει η Prolog αν μία κλήση ικανοποιείται από μία πρόταση, χρησιμοποιεί ένα μηχανισμό ταυτοποίησης. Αυτός προσπαθεί να καταστήσει ταυτόσημες μία κλήση μιας ερώτησης και την κεφαλή μίας πρότασης, εκτελώντας τις ελάχιστες απαραίτητες αναθέσεις τιμών σε μεταβλητές (most general unifier). Όταν μία κλήση ταυτοποιείται με ένα από τα γεγονότα του προγράμματος τότε αυτή ικανοποιείται και απομακρύνεται από την ερώτηση. Αν η κλήση ταυτοποιείται με έναν κανόνα, τότε αυτή απομακρύνεται από την ερώτηση και τη θέση της παίρνει το σώμα του κανόνα αυτού.
Αναζήτηση προτάσεων (2/2) Αν στο πρόγραμμα υπάρχουν περισσότερες της μία προτάσεις με τις οποίες μπορεί να ταυτοποιηθεί μία κλήση, τότε ταυτοποιείται με την πρόταση που εμφανίζεται πρώτη στο πρόγραμμα. Το σημείο αυτό ονομάζεται σημείο οπισθοδρόμησης. Σε περίπτωση αποτυχίας εύρεσης λύσης ή σε περίπτωση που ο χρήστης ζητά και άλλη λύση, ο μηχανισμός οπισθοδρόμησης επιστρέφει στο τελευταίο σημείο οπισθοδρόμησης.
Κανόνες Ταυτοποίησης (1/2) Μία μεταβλητή που δεν έχει πάρει τιμή μπορεί να ταυτοποιηθεί με σταθερή, μεταβλητή ή σύνθετο όρο. Μία σταθερά μπορεί να ταυτοποιηθεί μόνο με τον εαυτό της. Ένας σύνθετος όρος μπορεί να ταυτοποιηθεί με έναν άλλο σύνθετο μόνο εφόσον έχουν το ίδιο συναρτησιακό σύμβολο και την ίδια τάξη, και με την προϋπόθεση ότι τα αντίστοιχα ορίσματά τους μπορούν να ταυτοποιηθούν.
Κανόνες Ταυτοποίησης (2/2) <σταθερά> c1 <μεταβλητή> X1 <σύνθετος όρος> f(t1,…,tν) επιτυχές αν c1==c2 {Χ1=c2} αποτυγχάνει X2 {Χ2=c1} {Χ1=Χ2} {Χ2=f(u1,…,um)} f(u1,…,uμ) {Χ1=f(t1,…,tn)} επιτυχές αν ν==μ και u1==t1,…,uμ==tν
Παράδειγμα εκτέλεσης προγράμματος (1/2) Έστω το πρόγραμμα greek(socrates). human(turing). human(socrates). fallible(X):- human(X). και έστω ότι τίθεται το ερώτημα. ?- fallible(Y),greek(Y).
Παράδειγμα εκτέλεσης προγράμματος (2/2) greek(socrates). human(turing). human(socrates). fallible(X):- human(X). ?-fallible(Y),greek(Y). {Y=X} ?-human(Y),greek(Y). {Y=turing} {Y=socrates} ?-greek(turing). ?-greek(socrates). αποτυγχάνει yes
Αναδρομή Με τον όρο αναδρομή εννοούμε τη δυνατότητα ένας κανόνας να περιέχει στο σώμα του μια κλήση προς τον εαυτό του. Οι κανόνες που χρησιμοποιούν αναδρομή ονομάζονται αναδρομικοί, ενώ αυτοί που δεν χρησιμοποιούν μη αναδρομικοί.
Παράδειγμα Αναδρομής (1/3) Έστω τα γεγονότα: parent(john,george). parent(john,nick). parent(jim,bill). parent(jim,jack). parent(gregory,john). parent(gregory,jim). parent(bob,gregory). parent(joseph,bob). Θέλουμε να ορίσουμε έναν κανόνα predecessor(X,Y), ο οποίος να αληθεύει αν ο Χ είναι πρόγονος του Υ.
Παράδειγμα Αναδρομής (2/3) Λύση με μη αναδρομικούς κανόνες: predecessor(X,Z):- parent(X,Z). predecessor(X,Z):- parent(X,Y),parent(Y,Z). predecessor(X,Z):- parent(X,Y1),parent(Y1,Y2), parent(Y2,Z). … Με αυτόν τον τρόπο δεν μπορούμε να ορίσουμε τη σχέση για πολύ μακρινούς απογόνους. Π.χ. στην ερώτηση ?- predecessor(X,george). X=john X=gregory X=bob
Παράδειγμα Αναδρομής (3/3) Λύση με αναδρομικούς κανόνες: predecessor(X,Z):- parent(X,Z). predecessor(X,Z):- parent(X,Y),predecessor(Y,Z). Παρατήρηση: .Όταν ένα κατηγόρημα ορίζεται αναδρομικά, εμφανίζεται πάντα με τουλάχιστον δύο κανόνες. Ο πρώτος συνήθως δεν περιέχει αναδρομική κλήση, λειτουργώντας σαν τερματική συνθήκη.
Λίστες Μία λίστα είναι μια ακολουθία από οποιονδήποτε αριθμό στοιχείων. Τα στοιχεία αυτά μπορεί να είναι απλοί όροι, σύνθετοι όροι ή ακόμα και άλλες λίστες. Τα στοιχεία μίας λίστας τοποθετούνται μέσα σε αγκύλες και χωρίζονται μεταξύ τους με κόμμα, π.χ. [dog,3,f(a,b),X,[1,2],s] Μία λίστα μπορεί να είναι: Κενή: μία δομή χωρίς όρους που συμβολίζεται με [] Μία δομή με δύο όρους: την κεφαλή (head) που είναι το πρώτο στοιχείο της λίστας και την ουρά (tail) που είναι το υπόλοιπο τμήμα της λίστας. Η κεφαλή μίας λίστας μπορεί να είναι οτιδήποτε. Η ουρά όμως πρέπει να είναι πάντα λίστα είτε κενή ή με τη δικιά της κεφαλή και ουρά, π.χ. στην παραπάνω λίστα dog είναι η κεφαλή και [f(a,b),X,[1,2],s] η ουρά.
Ταυτοποίηση λιστών Δύο λίστες ταυτοποιούνται εφόσον έχουν τον ίδιο αριθμό στοιχείων και τα αντίστοιχα στοιχεία μπορούν να ταυτοποιηθούν,π.χ. Λίστα1 Λίστα2 Ταυτοποίηση [a,b,c] [a,b,c,d] αποτυγχάνει [X,Y] [a,b] [a,X] {X=b} [a|X] {X=[b]} [f(l),k,[l]] [f(X),Y,Z] {X=l,Y=k,Z=[l]} [f(X),Y|Z] {X=l,Y=k,Z=[[l]]} [[a]] [X|Y] {X=[a],Y=[]}
Χειρισμός Λιστών (1/4) Εύρεση τελευταίου στοιχείου last(X,[X]). last(X,[Head|Tail]):-last(X,Tail). ?-last(c,[a,b,c]). Πρόταση 2 ?-last(c,[b,c]). Πρόταση 2 ?-last(c,[c]). Πρόταση 1 Πρόταση 2 ?-last(c,[]). YES fail
Χειρισμός Λιστών (2/4) Έλεγχος συμπερίληψης member(X,[X|Y]). member(X,[Head|Tail]):- member(X,Tail). Συνένωση λιστών append([],L,L). append([X|L1],L2,[X|L3]):- append(L1,L2,L3). Η συνένωση μίας λίστας L με μία κενή λίστα έχει ως αποτέλεσμα την ίδια τη λίστα. Αν η πρώτη λίστα δεν είναι κενή, μπορεί να χωριστεί σε κεφαλή και ουρά: [X|L1]. Τότε η συνένωση της λίστας [X|L1] και της L2 είναι η [X|L3] όπου L3 είναι το αποτέλεσμα της συνένωσης των λιστών L1 και L2.
Χειρισμός Λιστών (3/4) Προσθήκη στοιχείου στην αρχή μίας λίστας add(List,Element,[Element|List]). π.χ. ?-add([a,b,c,d],q,L). L=[q,a,b,c,d]; Προσθήκη στοιχείου σε οποιαδήποτε θέση στη λίστα add(List,Element,NewList):-append(List1,List2,List), append(List1,[Element|List2],Newlist). Έτσι: ?-add([a,b,c],q,L). L=[q,a,b,c]; L=[a,q,b,c]; L=[a,b,q,c]; L=[a,b,c,q]; no
Χειρισμός Λιστών (4/4) Αφαίρεση στοιχείων από μία λίστα delete(Element,List,NewList):-append(List1,[Element|List2],List), append(List1,List2,NewList). Αναστροφή λιστών reverse([],[]). reverse([Head|Tail],ReversedList):- reverse(Tail,ReversedTail), append(ReversedTail,[Head],ReversedList).
Τελεστές Σύγκρισης Οι τελεστές σύγκρισης χρησιμοποιούνται στα σώματα κανόνων, με σκοπό τον έλεγχο συνθηκών μεταξύ αριθμών και μεταβλητών Διαφορά μεταξύ = και =:= ?- 1+2 =:= 2+1. yes ?- 1+2 = 2+1. no ?- 1+A = B+2. A=2 B=1 Τελεστής Εξήγηση X > Y μεγαλύτερο X < Y μικρότερο X >= Y μεγαλύτερο / ίσο X =<Y μικρότερο / ίσο X =:= Y ισότητα X =/= Y ανισότητα
Παραδείγματα χρήσης τελεστών σύγκρισης Έλεγχος για το αν μία λίστα είναι ταξινομημένη sorted([]). sorted([_]). sorted([X,Y|List]):-X=<Y,sorted([Y|List]). Εύρεση μέγιστου στοιχείου λίστας list_max([X],X). list_max([X|Tail],M):-list_max(Tail,M1),max(X,M1,M). max(X,Y,X):-X>Y. max(X,Y,Y):-X=<Y.
Τελεστές αριθμητικών πράξεων Τελεστής Εξήγηση + πρόσθεση - αφαίρεση * πολλαπλ/μός / διαίρεση mod υπόλοιπο διαίρεσης ^ δύναμη
Τελεστής απόδοσης τιμής Η απόδοση των τιμών αριθμητικών εκφράσεων σε μεταβλητές δεν μπορεί να γίνει χρησιμοποιώντας των τελεστή = ?- X=3+4 X=3+4 Για απόδοση τιμής χρησιμοποιούμε τον τελεστή is ?- X is 3+4 X=7 Είναι προφανές ότι μπορούμε να χρησιμοποιούμε και μεταβλητές στην έκφραση που ακολουθεί στα δεξιά του τελεστή is. Σε αυτήν την περίπτωση θα πρέπει όλες οι μεταβλητές να έχουν πάρει τιμές τη στιγμή που θα εκτελεστεί ο τελεστής.
Παραδείγματα χρήσης τελεστών Μέγιστος Κοινός Διαιρετής gcd(X,X,X). gcd(X,Y,D):-X<Y, Y1=Y-X, gcd(X,Y1,D). gcd(X,Y,D):-X1 is X-Y, gcd(X1,Y,D). Άθροισμα στοιχείων λίστας sum_list([],0). sum_list([X|T],Sum):-sum_list(T,Sum1),Sum is Sum1+X. Εύρεση ν-οστού στοιχείου λίστας n_elem(1,[X|T},X). n_elem(N,[H|T],X):-N1 is N-1, n_elem(N1,T,X).
Διαδικασίες εισόδου / εξόδου Στην Prolog, η επικοινωνία μεταξύ χρήστη και προγράμματος γίνεται συνήθως με τη μορφή ερωτήσεων από την πλευρά του χρήστη και απαντήσεων από την πλευρά του συστήματος. Η Prolog όμως περιέχει και ειδικές ενσωματωμένες διαδικασίες (built-in procedures), οι οποίες διαβάζουν όρους ή χαρακτήρες από το προκαθορισμένο κανάλι εισόδου (πληκτρολόγιο / αρχείο) και επιστρέφουν το αποτέλεσμα στο προκαθορισμένο κανάλι εξόδου (οθόνη / αρχείο).
Είσοδος από το πληκτρολόγιο get(X): Διαβάζει τον επόμενο χαρακτήρα που πληκτρολογεί ο χρήστης. read(X): Διαβάζει τον επόμενο όρο που εισάγεται από το πληκτρολόγιο. Παραδείγματα: ?- get(X),get(Y). Αν ο χρήστης πληκτρολογήσει ab η απάντηση που θα επιστραφεί είναι: X=a, Y=b. ?- read(X). a. X=a a no (λείπει η τελεία) [l,k]. X=[l,k] ‘a bc. No (λείπει η δεξιά απόστροφος)
Έξοδος στην οθόνη put(X): Τυπώνει στην οθόνη τον χαρακτήρα Χ. write(X): Τυπώνει στην οθόνη τον όρο Χ. nl: Προκαλεί αλλαγή γραμμής. Παραδείγματα: ?- write(aaa),nl,write([1,2,3]),nl,write(f(k,l)). aaa [1,2,3] f(k,l) yes
Είσοδος / Έξοδος σε αρχεία Για την είσοδο / έξοδο όρων και χαρακτήρων σε αρχεία χρησιμοποιούνται τα ίδια κατηγορήματα. Το μόνο που απαιτείται είναι η ανακατεύθυνση των καναλιών εισόδου / εξόδου. see(filename): Ορίζει ως κανάλι εισόδου το αρχείο filename. seen: Ακυρώνει το κανάλι επικοινωνίας που ορίστηκε με την εντολή see και κλείνει όλα τα αρχεία εισόδου.. seeing: Επιστρέφει το τρέχον κανάλι εισόδου. tell(filename): Ορίζει ως κανάλι εξόδου το αρχείο filename. told: Ακυρώνει το κανάλι επικοινωνίας που ορίστηκε με την εντολή tell και κλείνει όλα τα αρχεία εξόδου.. telling: Επιστρέφει το τρέχον κανάλι εξόδου.
Παράδειγμα εισόδου / εξόδου σε αρχείο Το κατηγόρημα που ακολουθεί δέχεται σαν είσοδο μία λίστα με στοιχεία και τα γράφει σε ένα προκαθορισμένο αρχείο. out(L):- tell(‘myfile.txt’),write_list(L),told. write_list([]). write_list([H|T]):-write(H),nl,write_list(T).
Χειρισμός συμβολοσειρών Στην Prolog, η τακτική που ακολουθείται για το χειρισμό συμβολοσειρών είναι η μετατροπή τους σε λίστες και η χρήση κατηγορημάτων επεξεργασίας λιστών. Το κατηγόρημα που μετατρέπει μία συμβολοσειρά σε λίστα ASCII κωδικών είναι το: name(String,List). ?- name(abc,X). X=[97,98,99] Η συμβολοσειρά μπορεί να είναι άτομο ή αριθμός Αν το άτομο αρχίζει με κεφαλαίο ή περιέχει κενά, πρέπει να είναι τοποθετημένο σε απλά εισαγωγικά. Ένα άτομο ή αριθμός μέσα σε διπλά εισαγωγικά ισοδυναμεί με λίστα ASCII κωδικών.
Παράδειγμα χειρισμού συμβολοσειρών Το παρακάτω κατηγόρημα δέχεται σαν είσοδο δύο συμβολοσειρές και τις συνενώνει: strings_concatenate(Str1,Str2,Str):- name(Str1,L1),name(Str2,L2),append(L1,L2,L), name(Str,L).
Αποκοπή Η αποκοπή παρέχει στον προγραμματιστή τη δυνατότητα να «κλαδέψει» δυναμικά το δένδρο υπολογισμού που δημιουργεί η Prolog. Είναι ένας τρόπος ελέγχου του μηχανισμού οπισθοδρόμησης, ο οποίος απαγορεύει τη δημιουργία κλαδιών που ξέρουμε ότι δεν θα οδηγήσουν σε λύση. Η αποκοπή συμβολίζεται με το χαρακτήρα «!» και πετυχαίνει πάντα. Όταν ο μηχανισμός αναζήτησης της Prolog συναντήσει μία αποκοπή Αγνοούνται όλες οι προτάσεις που ανήκουν στη διαδικασία και έπονται της πρότασης που περιέχει την αποκοπή. Αγνοούνται όλες οι εναλλακτικές λύσεις των ατομικών τύπων που βρίσκονται πριν από την αποκοπή μέσα στο σώμα του κανόνα που εμφανίζεται.
Παράδειγμα με Αποκοπή ?-uncle(bob,Y). ?-brother(bob,Z),!,father(Z,Y). {Z=john} uncle(X,Y):- brother(X,Z),!,father(Z,Y). brother(X,Z),mother(Z,Y). brother(bob,john). brother(bob,nick). father(john,ann). ?-!,father(john,Y). ?- father(john,Y). {Y=ann}
Αποφυγή άσκοπων ελέγχων Έστω ότι θέλουμε να υλοποιήσουμε τη συνάρτηση: f(x)=0 if x<3 f(x)=2 if 3=<x<6 f(x)=4 if x>=6 Στο πρόγραμμα που ακολουθεί αποφεύγονται οι περιττοί έλεγχοι κατά την οπισθοδρόμηση αφού γνωρίσουμε εκ των προτέρων ότι μόνο μία από τις τρεις προτάσεις μπορεί να είναι αληθής κάθε φορά. f(X,0):- X<3, !. f(X,0):- X<3, !. f(X,2):- X>=3, X<6, !. f(X,2):- X<6, !. f(X,4):- X>=6, !. f(X,4). Πρόγραμμα1 Πρόγραμμα2
Είδη αποκοπών Μία αποκοπή είναι κόκκινη όταν κατά την αφαίρεσή της από το πρόγραμμα μεταβάλλεται η δηλωτική σημασία του προγράμματος. Π.χ. στο Πρόγραμμα2 οι αποκοπές είναι κόκκινες, αφού αν αφαιρεθούν το πρόγραμμα θα επιστρέψει διαφορετικά αποτελέσματα. Μία αποκοπή είναι πράσινη όταν δεν επηρεάζει τη δηλωτική σημασία του προγράμματος. Π.χ. στο Πρόγραμμα1 οι αποκοπές είναι πράσινες, αφού αν αφαιρεθούν το πρόγραμμα θα επιστρέψει τα ίδια αποτελέσματα σε περισσότερο χρόνο.
Αποκοπή και Άρνηση not_member(X,[]). Μία από τις σημαντικότερες χρήσεις της αποκοπής είναι η υλοποίηση της άρνησης σαν αποτυχία (negation as failure). Αυτό επιτυγχάνεται με τη χρήση του ενσωματωμένου κατηγορήματος fail της Prolog, το οποίο αποτυγχάνει πάντα. Ο συνδυασμός αποκοπής και επιτυχίας κάνει δυνατή την υλοποίηση κατηγορημάτων που περιέχουν την άρνηση. Για παράδειγμα το παρακάτω πρόγραμμα επιτυγχάνει όταν ένα στοιχείο δεν είναι μέλος μίας λίστας. not_member(X,[]). not_member(X,[X|_]):-!,fail. not_member(X,[_|Rest]):-not_member(X,Rest).
Υπόθεση του Κλειστού Κόσμου Η αρχή της άρνησης σαν αποτυχία βασίζεται στην Υπόθεση του Κλειστού Κόσμου (Closed World Assumption). Σύμφωνα με αυτή όλη η απαραίτητη πληροφορία για την επίλυση του προβλήματος περιέχεται στο πρόγραμμα και οτιδήποτε δεν περιέχεται σε αυτό θεωρείται λάθος (οποιαδήποτε σχέση δεν μπορεί να αποδειχθεί από το σύστημα θεωρείται ως εσφαλμένη). Η υλοποίηση του τελεστή άρνησης του λογικού προγραμματισμού (άρνηση σαν αποτυχία) γίνεται με τη βοήθεια του συνδυασμού αποκοπής και άρνησης. not(X):-X,!,fail. not(X).
Prolog engines XSB (http://xsb.sourceforge.net/) SWI-Prolog (http://www.swi-prolog.org) SISCtus Prolog (http://www.sics.se/isl/sicstuswww/site/index.html) ECLiPSe Prolog (http://eclipse.crosscoreop.com/) Quintus Prolog (http://www.sics.se/quintus/) YAP Prolog (http://www.ncc.up.pt/~vsc/Yap/) etc…
Περιβάλλον εργασίας XSB