Η εξέλιξη της ισχύος των υπολογιστών και του αντίστοιχου θεωρητικού υπόβαθρου μας έχει επιτρέψει να εξετάζουμε διαφορετικές προσεγγίσεις επίλυσης προβλημάτων με υπολογιστή που να βασίζονται όχι στο να κάνουν την αρχιτεκτονική του υπολογιστή προσιτή στον άνθρωπο, αλλά στο να κάνουν τη διατύπωση των προβλημάτων από τον άνθρωπο προσιτή στον υπολογιστή. Έτσι, τόσο ο συναρτησιακός όσο και ο λογικός προγραμματισμός επιτρέπουν τη διατύπωση του προβλήματος που πρέπει να επιλυθεί με βάση έναν συμβολισμό και αφήνουν στον υπολογιστή να λύσει το πρόβλημα με βάση τη διατύπωσή του. Η βάση του λογικού προγραμματισμού μπορεί να διατυπωθεί ως εξής:
Παράδειγμα 1 (ορισμός σχέσεων ανάμεσα σε ακέραιούς):
sum(0, 0, 0). sum(0, 1, 1). sum(1, 0, 1). sum(1, 1, 2).
Παράδειγμα 2 (ορισμός σχέσεων ανάμεσα σε ανθρώπους):
father(anthi, giannis). father(petros, giannis). father(thanasis, giannis). father(iro, giannis). father(nikos, thanasis). father(giorgos, thanasis). mother(anthi, maria).Οι λέξεις nikos, petros, anthi, στο παραπάνω παράδειγμα είναι σταθερές της γλώσσας (όπως και οι ακέραιοι στο προηγούμενο). Ονομάζονται άτομα (atoms) και γράφονται με αρχικό μικρό γράμμα.
Με βάση τα παραπάνω γεγονότα μπορούμε να εκτελέσουμε ερωτήσεις για να μάθουμε αν μια σχέση είναι αληθής ή ψευδής. Όταν η Arity Prolog βρει μια αληθή λύση στην ερώτησή μας μας εμφανίζει το σύμβολο ->. Στο σημείο εκείνο μπορούμε να πατήσουμε Enter για να δηλώσουμε πως μας ικανοποιεί η λύση, ή ; για να δηλώσουμε πως θέλουμε να δούμε και άλλες λύσεις. Παράδειγμα:
?- sum(0, 0, 0). -> yes ?- sum(1, 1, 2). -> yes ?- sum(1, 1, 0). no ?- sum(5, 3, 9). no
?- sum(1, 1, X). X = 2 yes ?- sum(X, 1, X). no ?- sum(X, X, 2). X = 1 yes ?- father(iro, X). X = giannis yes ?- father(X, Y). X = anthi Y = giannis ->; X = petros Y = giannis ->; X = thanasis Y = giannis ->; X = iro Y = giannis ->; X = nikos Y = thanasis -> yes
Με βάση τις μεταβλητές μπορούμε ακόμα να ορίσουμε και γενικευμένα γεγονότα (universal facts). Για παράδειγμα για να ορίσουμε πως όλοι αγαπούν τη Μαίρη γράφουμε:
loves(X, mairi).
Με βάση τα παραπάνω μπορούμε να ορίσουμε τη δομή δεδομένων της Prolog, τον όρο. Οι όροι ορίζονται αναδρομικά. Ένας όρος μπορεί να είναι:
sum(0, 0, 1) car(color(red), engine(1600), abs, speed(172), doors(2,2,1)) loves(X, Y)
?- sum(0, 1, 1), sum(1, 1, 2). yes ?- sum(0, 1, 1), sum(1, 1, 3). noΜπορούμε να ορίσουμε ακόμα κανόνες με βάση ένα γεγονός και κάποιες σχετικές ερωτήσεις με την παρακάτω σύνταξη:
a :- b1, b2, bn.Ο κανόνας διαβάζεται ως εξής: ισχύει το a αν ισχύει το b1 και το b2 και το bn. Αν ορίσουμε παραπάνω από έναν κανόνα για το ίδιο γεγονός τότε οι κανόνες ισχύουν διαζευκτικά (αρκεί να ισχύει ένας).
Παράδειγμα:
parent(X, Y) :- father(X, Y). parent(X, Y) :- mother(X, Y). ?- parent(anthi, X). X = giannis ->; X = maria yes ?- parent(X, giannis). X = anthi ->; X = petros ->; X = thanasis ->; X = iro ->; no
Παράδειγμα:
grandfather(X, Y) :- father(Z, X), father(Y, Z). ?- grandfather(X, Y). X = giannis Y = nikos ->; X = giannis Y = giorgos ->; no
nat(0). nat(s(X)) :- nat(X). ?- nat(0). yes ?- nat(s(0)). yes ?- nat(s(s(s(s(0))))). yes ?- nat(X). X = 0 ->; X = s(0) ->; X = s(s(0)) ->; X = s(s(s(0))) ->; X = s(s(s(s(0)))) -> X = s(s(s(s(s(0))))) ->; X = s(s(s(s(s(s(0)))))) ->; X = s(s(s(s(s(s(s(0))))))) ->; X = s(s(s(s(s(s(s(s(0)))))))) ->; X = s(s(s(s(s(s(s(s(s(0))))))))) ->; X = s(s(s(s(s(s(s(s(s(s(0)))))))))) -> ...Με βάση τον ορισμό αυτό μπορούμε να ορίσουμε μια σχέση διάταξης:
less(0, X) :- nat(X). less(s(X), s(Y)) :- less(X, Y). ?- less(s(0), 0). no ?- less(s(0), s(s(0))). yes ?- less(X, s(s(s(s(0))))). X = 0 ->; X = s(0) ->; X = s(s(0)) ->; X = s(s(s(0))) ->; X = s(s(s(s(0)))) ->; noΜε παρόμοιο τρόπο μπορούμε να ορίσουμε και την πρόσθεση:
plus(0, X, X) :- nat(X). plus(s(X), Y, s(Z)) :- plus(X, Y, Z).Είναι αξιοσημείωτο πως το κατηγόρημα της πρόσθεσης με τη μορφή που έχει οριστεί μπορεί να υπολογίσει άθροισμα, διαφορά, όρους που δημιουργούν ένα άθροισμα, ή να ελέγξει αν ένα άθροισμα είναι αληθές:
?- plus(s(0), s(0), X). X = s(s(0)) yes ?- plus(s(0), X, s(s(s(0)))). X = s(s(0)) yes ?- plus(X, Y, s(s(0))). X = 0 Y = s(s(0)) ->; X = s(0) Y = s(0) ->; X = s(s(0)) Y = 0 ->; no ?- plus(s(0), 0, 0). noΜε τη χρήση του αθροίσματος μπορούμε να ορίσουμε και το γινόμενο:
times(0, X, 0) times(s(X), Y, Z) :- times(X, Y, W), plus(W, Y, Z).Το κατηγόρημα για το γινόμενο που έχει οριστεί με τον τρόπο αυτό έχει και αυτό παρόμοια ευελιξία:
?- times(s(s(0)), s(s(s(0))), X). X = s(s(s(s(s(s(0)))))) yes ?- times(X, s(s(0)), s(s(s(s(0))))). X = s(s(0)) ->. yes ?- times(X, Y, s(s(s(s(0))))). X = s(0) Y = s(s(s(s(0)))) ->; X = s(s(0)) Y = s(s(0)) ->; ?- times(s(0), s(0), s(0)). yes
?- is(X, 1 + 2). X = 3 ?- is(2, 1 + 1). yes ?- is(Y, 3 * 8 + 4 / 5). Y = 24.8 yes ?- is(2, X + X). no
quicksort([X|Xs], Ys) :- partition(Xs, X, L, B), quicksort(L, Ls), quicksort(B, Bs), append(Ls, [X | Bs], Ys). quicksort([], []). partition([X|Xs], Y, [X|Ls], Bs) :- X =< Y, partition(Xs, Y, Ls, Bs). partition([X|Xs], Y, Ls, [X|Bs]) :- X > Y, partition(Xs, Y, Ls, Bs). partition([], Y, [], []). append([], X, X). append([H | T], X, [H | Z]) :- append(T, X, Z). ?- quicksort([4,2,8,12,1,7], X). X = [1,2,4,7,8,12] ->. yes
polynomial(X, X). polynomial(N, X) :- number(N). polynomial(sum(A, B), X) :- polynomial(A, X), polynomial(B, X). polynomial(diff(A, B), X) :- polynomial(A, X), polynomial(B, X). polynomial(prod(A, B), X) :- polynomial(A, X), polynomial(B, X). polynomial(quot(A, B), X) :- polynomial(A, X), number(B). polynomial(pow(A, B), X) :- polynomial(A, X), integer(B).Ερωτήσεις:
?- p(sum(x, 1), x). ->. yes ?- p(sum(x, 1), y). no ?- polynomial(sum(prod(5,pow(x, 2)), prod(2, x)), x). ->. yes ?- polynomial(sum(prod(5,pow(x, 2)), pow(y, 3)), x). no ?- polynomial(sum(prod(5,pow(x, 2.1)), prod(2, x)), x). no
polynomial_value(P, X, V).όπου:
Παράδειγμα:
?- polynomial_value(prod(5, pow(x, 3)), 3, X). X = 135 -> yes ?- polynomial_value(sum(prod(5, pow(x, 3)), prod(x, 5)), 4, X). X = 340 ->. yesΤην ύψωση ενός αριθμού σε δύναμη μπορείτε να την ορίσετε ως εξής:
raise(X, 0, 1). raise(X, N, Y) :- N2 is N - 1, raise(X, N2, K), Y is K * X.