PROLOG
Λίστες Οι λίστες είναι η σημαντικότερη δομή δεδομένων της Prolog. Μια λίστα είναι ένας δυναμικός μονοδιάστατος πίνακας με στοιχεία του αριθμούς, σύμβολα, σύνθετους όρους ή και άλλες λίστες. Τα στοιχεία μιας λίστας δεν είναι απαραίτητο να είναι του ίδιου τύπου. Τα στοιχεία μιας λίστας τοποθετούνται μέσα σε αγκύλες [ , ] και χωρίζονται μεταξύ τους με κόμμα “ , “ .
Λίστες Παραδείγματα Λιστών σε Prolog [maria, 8,ball, house]. [cat,point(1,2),[a ,b],d ]. Μια λίστα μπορεί να είναι: Κενή (δομή χωρίς όρους) η οποία συμβολίζεται με [] Μια δομή με δύο όρους :την κεφαλή (Head) που είναι το πρώτο στοιχείο της λίστας και την ουρά(tail) που είναι το υπόλοιπο τμήμα της λίστας.
Λίστες Δύο λίστες ενοποιούνται εφόσον έχουν τον ίδιο αριθμό στοιχείων και τα αντίστοιχα στοιχεία τους μπορούν να ενοποιηθούν. Λίστα 1 Λιστα 2 Ενοποίηση [a, b, c] [a,b,c,d] αποτυχία [X, Y] [a, b] [a,X] { b / X } [a,b] [a | X ] { [b] / X } [f(1), k, [m] ] [ f(X), Y, Z ] {1/X, k/Y, [m] /Z } [ f(X), Y| Z ] {1/X, k/Y, [[m]] /Z} [[a]] [X | Y] { [a] / X, []/Y }
Λίστες Το κατηγόρημα member παρακάτω ελέγχει εάν ένα στοιχείο (πρώτο όρισμα) ανήκει σε μία λίστα (το δεύτερο όρισμα): member(X, [ X | Y ] ). member(X, [ Head | Tail ] ) :- member(X, Tail). Ερωτήσεις στην Prolog ?- member( 2, [ 1, 2, 3] ). Yes ?- member(4, [ 1, 2, 3 ] ). No ?- member(X, [1, 2, 3]). X=1 X=2 X=3
Λίστες Το παρακάτω κατηγόρημα, last(X,L) επιστρέφει ως Χ το τελευταίο last(X, [X]). last(X, [ Head | Tail] ):- last(X,Tail). Μπορούμε να κάνουμε κλήσεις στο last/2 με το πρώτο όρισμα ελεύθερο και το δεύτερο δεσμευμένο. Για παράδειγμα: ?- last( Z, [2, 3, 4] ). Z=4 Εάν καλέσουμε το κατηγόρημα και με τα δύο ορίσματα δεσμευμένα, η απάντηση που θα πάρουμε θα είναι yes ή no, ανάλογα με το αν το πρώτο όρισμα είναι το τελευταίο στοιχείο της λίστα τους δεύτερου ορίσματος ή όχι
Λίστες Παραδείγματα: ?- last( 4, [2, 3, 4]) . Yes. no. Το κατηγόρημα last θα λειτουργήσει ακόμη και αν το καλέσουμε με το πρώτο όρισμα δεσμευμένο και το δεύτερο ελεύθερο! Σε αυτή την περίπτωση θα επιστρέψει (άπειρες στο πλήθος) λίστες των οποίων το τελευταίο στοιχείο είναι το πρώτο όρισμα. Μπορούμε ακόμη να το καλέσουμε και με τα δύο ορίσματα ελεύθερα. Σε αυτή την περίπτωση θα επιστρέψει (άπειρες στο πλήθος) λίστες των οποίων το τελευταίο στοιχείο είναι ενοποιημένο με το πρώτο όρισμα (μολονότι και τα δύο εξακολουθούν να είναι μεταβλητές).
Λίστες Η Συνένωση λιστών γίνεται με το κατηγόρημα append(L1,L2,L3), το οποίο επιτυγχάνει όταν η λίστα L3 είναι η ένωση (παράθεση) των L1 και L2. Η συνένωση μιας λίστας L2 με την κενή λίστα είναι η ίδια λίστα L2. append([ ], L2, L2). Η συνένωση μιας λίστας ενός στοιχείου και μιας λίστας L2 δίνεται από τον παρακάτω κανόνα: append([A], L2, [A|L2]).
Λίστες Παραδείγματα ?-append([a,b],[c,d],[a,b,c,d]). yes ?-append([a,b,c],[1,2,3],L). L=[a,b,c,1,2,3] ?-append([a,[b,c],d],[a,[ ],b],L). L=[a,[b,c],d,a,[ ],b] ?-append(L1,L2,[a,b,c]). L1=[], L2=[a,b,c];L1=[a] L2=[b,c],L1=[a,b] L2=[c]; L1=[a,b,c] L2=[ ]; no
Λίστες Η προσθήκη ενός στοιχείου στην αρχή μιας λίστας μπορεί να επιτευχθεί με τον ακόλουθο κανόνα add(List,Element,[Element|List]). Όπου List είναι η αρχική λίστα Element είναι το στοιχείο που θέλουμε να προσθέσουμε. [Element|List] είναι το αποτέλεσμα της προσθήκης.
Λίστες Η διαγραφή στοιχείων από μια λίστα γίνεται με το κατηγόρημα delete όπου Χ είναι ένα στοιχείο, L1 μια λίστα και L2 η λίστα L1 από την οποία έχουν εμφανιστεί όλες οι εμφανίσεις του Χ. Οι βασικές ιδέες είναι οι εξής:Εάν η L1 είναι κενή, τότε και η L2 είναι κενή: delete( X, [ ] , [ ] ). Εάν το στοιχείο Χ ταυτίζεται με το πρώτο στοιχείο της L1, τότε η L2 ισούται με την ουρά της L1, από την οποία όμως έχουν αφαιρεθεί όλα τα X. delete( X, [ X | T1], L2) :- delete(X, Τ1, L2).
Λίστες Θέλουμε να ορίσουμε το κατηγόρημα reverse(L1, L2), το οποίο Οι βασικές ιδέες είναι οι εξής: Η ανάστροφη της κενής λίστας είναι η κενή λίστα. reverse( [ ] , [ ] ) . Για να αναστρέψουμε την L1, ξεχωρίζουμε το πρώτο στοιχείο της H1 από την ουρά της T1, αναστρέφουμε την ουρά της και έστω RT1 η ανεστραμμένη ουρά. Τότε η L2 ισούται με την ένωση της RT2 και του στοιχείου H1. reverse( [ H1 | T1], L2):- reverse(T1, RT1), append(RT1, [H1], L2).
Λίστες Παραδείγματα ?-reverse([1,2,3,4],[4,3,1,2]). No Yes ?-reverse([a,b,c,d],L). L=[d, c, b, a].
Προβλημα Σκακίου Το πρόβλημα του σκακιού αφορά την εύρεση μιας διαδρομής του αλόγου σε μια σκακιερα N*N έτσι ώστε να επισκεφτεί όλα τα τετράγωνα της σκακιέρας χώρις να περάσει από το ίδιο τετράγωνο δυο φορές.Το πρόβλημα έχει λύση για σκακιέρες με μέγεθος μεγαλύτερο ή ίσο από 5 *5
Αναπαράσταση καταστάσεων Ο πιο απλός τρόπος αναπαράστασης είναι με τη μορφή λίστας κάθε στοιχείο της οποίας αναπαριστά ένα τετράγωνο με τη μορφή (X,Y) Η παραπάνω αναπαράσταση μπορεί να αποθηκευτεί σε ένα γεγονός της μορφής: chess_board( [ (1,1),(1,2),…,(5,4),(5,5)]).
Αναπαράσταση Τελεστών Οι επιτρεπτές κινήσεις του αλόγου για ένα τυχαίο τετράγωνο είναι 8 όπως φαίνεται στο σχήμα: Από το σχήμα προκύπτει ότι τα πιθανά επόμενα τετράγωνα από μια θέση προκύπτουν μεταβάλλοντας κάθε φορά τις συντεταγμένες κατα (+1,+2),(-1,+2),…(+2,+1).
Κινήσεις στην Σκακίερα go((Row,Col),(NRow,Ncol,_):- Row > 1, Col > 2, NRow is Row - 1, Ncol is Col – 2. go((Row,Col),(NRow,Ncol,N):- Ncol is Col + 2, Ncol =< N. Row > 2, Col > 1, NRow is Row - 2, Ncol is Col +1.
Κινήσεις στην σκακίερα go((Row,Col),(NRow,Ncol,N):- Row > 2, NRow is Row -2, Ncol is Col +1, Ncol =< N. Col > 2, Ncol is Col -2, NRow is Row +1, Ncol is Col +2, Ncol =< N, NRow =< N.
Κινήσεις στην σκακίερα go((Row,Col),(NRow,Ncol,N):- Col > 1, NRow is Row +2, Ncol is Col -1, NRow =< N. NRow is Row +2 Ncol is Col +1, NCol =< N,
Κινήσεις στην Σκακίερα Πλήρης τελεστής κίνησης είναι: Move(Here,Table,Next,NewTable,N):- go(Here,Next,N), delete(Next,Table,NewTable). here είναι το τετράγωνο που βρίσκεται το άλογο την δεδομένη χρονική στιγμή. Next το επόμενο τετράγωνο στο οποιο θα μετακινηθεί το άλογο. Table είναι η λίστα όλων τετραγώνων που απομένουν να επισκεφτεί. NewTable είναι η λίστα που προκύπτει αν από την Table αφαιρέσουμε το τετράγωνο Next.
Αλγόριθμος κατά Βάθος Κατά Βάθος Kn_tour([],_,[],_). Kn_tour(Table,Here,[Next|Answer],N):-Move(Here,Table,Next,NewTableN),Kn_tour(NewTable,Next,Answer,N). Η πρωτη είναι τερματική συνθήκη δηλαδή δηλωνει ότι δεν απομένουν άλλα τετράγωνα Η Δεύτερη είναι μια αναδρομική κλήση που επαναλαμβάνεται μέχρι να βρεθεί λύση.
Αναζήτηση Κατά Βάθος Chess_board([(1,1)|Table]),Kn_tour(Table,(1,1),Answer,5). Απάντηση στη Prolog [(2,3),(1,5),(3,4),(2,2),(1,4),(3,5),(5,4),(4,2),(2,1),(1,3),(2,5),(3,3),(4,1),(5,3),(4,5),(2,4),(1,2),(3,1),(5,2),(4,4),(3,2),(5,1),(4,3),(5,5)]
Αλγόριθμός Κατά Βάθος dfs(State, Solution, Solution):- goal(State). dfs(State, PathSoFar, Solution):- not(goal(State)), operator(State,Child), not(member(Child, PathSoFar)), dfs(Child, [Child|PathSoFar], Solution). godfs(Solution):- initial_state(IS), dfs(IS, [IS], Solution1), reverse(Solution1,Solution).