Wprowadzenie

advertisement
Wprowadzenie do Sztucznej Inteligencji
Laboratorium lista 0.3
Elementy języka Prolog: termy, listy i operacje
na listach
Przemysław Kobylański
Część I
Wprowadzenie
1
Termy
Jedyną strukturą danych w Prologu są termy.
Termy dzielą się na proste (zmienne i stałe) oraz złożone.
Zmienne zapisywane są w Prologu jako identyfikatory rozpoczynające się od
wielkiej litery. Szczególną zmienną jest zmienna anonimowa (bez nazwy) oznaczana
_ (znak podkreślenia).
Stałe w Prologu pisane są małą literą albo jako dowolny ciąg znaków ujęty w
apostrofy. Szczególną stałą jest para kwadratowych nawiasów.
Stałymi są również liczby całkowite1 i rzeczywiste (zapisywane w standardzie
IEEE).
Termy złożone składają się z funktora i wykazu jego argumentów ujętych w
nawiasy:
funktor(arg1 , arg2 , . . . , argn ).
Przykłady termów:
zmienne X, Szerokosc, Ojciec, Poprzednik, XYZ123, _
stałe a, janek, ’to rowniez jest stala’, -12, -3.16e-12, []
złożone opiekun(’klasa 1A’), ojciec(matka(jacek)), bracia(jacek, placek)
2
Listy
Szczególną rolę w Prologu odgrywa dwuargumentowy funktor . (kropka). Służy on
do tworzenia list i łączy pierwszy element listy (nazywany głową) z listą pozostałych
elementów (nazywaną ogonem).
Przykłady list:
lista pusta
lista jednoelementowa złożona ze stałej a
lista dwuelementowa złożona ze stałych a i b
lista jednoelementowa o dowolnym elemencie
lista dwuelementowa o identycznych elementach
lista co najmniej dwuelementowa
1W
SWI-Prologu dowolnie długiej reprezentacji.
1
[]
.(a,
.(a,
.(_,
.(X,
.(_,
[])
.(b, []))
[])
.(X, []))
.(_, _))
Notacja list z użyciem kropki jest nieczytelna, dlatego wprowadzono w Prologu
notację z nawiasami kwadratowymi:
lista pusta
lista jednoelementowa złożona ze stałej a
lista dwuelementowa złożona ze stałych a i b
lista jednoelementowa o dowolnym elemencie
lista dwuelementowa o identycznych elementach
lista co najmniej dwuelementowa
[]
[a]
[a, b]
[_]
[X, X]
[_, _ | _]
W ostatnim z powyższych przykładów użyto operatora | (pionowa kreska), który
oddziela elementy listy od listy pozostałych elementów.
3
Operacje na listach
W Prologu dostępnych jest wiele predykatów operujących na listach. Najważniejsze
z nich, to:
member(X, L) spełnione gdy X jest elementem listy L,
select(X, L1, L2) spełnione gdy lista L2 powstaje z listy L1 przez usunięcie elementu X,
append(L1, L2, L) spełnione gdy lista L jest połączeniem listy L1 z listą L2.
Poniższy dialog pokazuje jak działają powyższe predykaty (identyfikatory _Gnnn
są nazwami zmiennych wprowadzonych przez system Prolog podczas wnioskowania):
?- member(b, [a, b, c]).
true .
?- member(d, [a, b, c]).
false.
?- member(X, [a, b, c]).
X = a ;
X = b ;
X = c ;
false.
?- member(a, X).
X = [a|_G246] ;
X = [_G245, a|_G249] ;
X = [_G245, _G248, a|_G252] ;
X = [_G245, _G248, _G251, a|_G255] ;
...
?- select(c, [a, b, c, d, e], X).
X = [a, b, d, e] .
?- select(X, [a, b, c], L).
X = a,
L = [b, c] ;
X = b,
L = [a, c] ;
X = c,
L = [a, b] ;
false.
?- select(a, X, [1, 2, 3]).
X = [a, 1, 2, 3] ;
2
X = [1, a, 2, 3] ;
X = [1, 2, a, 3] ;
X = [1, 2, 3, a] ;
false.
?- append([1, 2, 3], [a, b, c], X).
X = [1, 2, 3, a, b, c].
?- append(X, Y, [a, b, c]).
X = [],
Y = [a, b, c] ;
X = [a],
Y = [b, c] ;
X = [a, b],
Y = [c] ;
X = [a, b, c],
Y = [] ;
false.
?- L = [a, b, c, a, b, c], append(L1, [b | L2], L).
L = [a, b, c, a, b, c],
L1 = [a],
L2 = [c, a, b, c] ;
L = [a, b, c, a, b, c],
L1 = [a, b, c, a],
L2 = [c] ;
false.
Przy definiowaniu predykatów przydatna może być negacja warunku. Oto przykład predykatu sprawdzającego czy dwie listy są rozłączne, tzn. nie mają wspólnego
elementu (zwróć uwagę na odstęp między operatorem \+ a negowanym warunkiem):
rozlaczne(A, B) :\+ (member(X, A), member(X, B)).
Powyższa reguła mówi tyle, że listy A i B są rozłączne, jeśli nie jest prawdą, że
pewien element X jest jednocześnie na liście A i na liście B.
Część II
Zadania i polecenia
Zadanie 1
Napisz predykat my_member(X, L), który będzie działał dokładnie tak samo
jak member(X, L) (pisząc my_member nie korzystaj z innych predykatów).
Zadanie 2
Napisz predykat my_select(X, L1, L2), który będzie działał dokładnie tak samo
jak select(X, L1, L2) (pisząc my_select nie korzystaj z innych predykatów).
Zadanie 3
Napisz predykat my_append(L1, L2, L), który będzie działał dokładnie tak samo
jak append(L1, L2, L) (pisząc my_append nie korzystaj z innych predykatów).
3
Zadanie 4
Predykat member(Element, Lista) jest spełniony, gdy Element występuje co
najmniej jeden raz na liście Lista.
Napisz predykat jednokrotnie(Element, Lista), który jest spełniony przez
element występujący dokładnie jeden raz na liście.
?- jednokrotnie(a, [b, a, b, c,
false.
?- jednokrotnie(X, [b, a, b, c,
X = c ;
false.
a, b]).
a, b]).
Uwaga: można skorzystać z negacji warunku zapisywanej w Prologu jako \+
Warunek.
Zadanie 5
Napisz predykat dwukrotnie(Element, Lista), który jest spełniony przez element
występujący dokładnie dwa razy na liście.
?- dwukrotnie(b, [b, a, b, c,
false.
?- dwukrotnie(X, [b, a, b, c,
X = a ;
false.
a, b]).
a, b]).
Zadanie 6
Napisz predykat para(X, L) gdy na liście L występują obok siebie dwie kolejne
takie same wartości X ale nie trzy kolejne.
?- para(X, [1, 2, 2, 3, 3, 3, 4, 4, 5]).
X = 2 ;
X = 4 ;
false.
?- para(X, [1, 2, 2, 1, 1, 2, 2, 2]).
X = 1 ;
false.
Zadanie 7
Napisz predykat niemalejace(L), który dla danej listy liczb jest spełniony, jeśli
liczby na liście L są w porządku niemalejącym.
Zadanie 8
Napisz predykat permutacja(L1, L2), który jest spełniony gdy lista L2 jest permutacją listy L1.
?- permutacja([1,2,3], X).
X = [1,2,3] ? ;
X = [1,3,2] ? ;
4
X = [2,1,3]
X = [2,3,1]
X = [3,1,2]
X = [3,2,1]
false.
?
?
?
?
;
;
;
;
Zadanie 9
Napisz predykat glupie_sortowanie(L1, L2), który dla danej listy liczb L1 znajduje taką jej permutację L2, że lista liczb L2 jest uporządkowana.
Policz predykatem time/1 czas głupiego sortowania listy liczb [10, 9, 8, 7, 6, 5, 4, 3, 2, 1].
Zadanie 10*
Napisz predykat cykl(L1, L2), który jest spełniony gdy lista L2 jest permutacją listy L1 o dokładnie jednym cyklu (poczytaj o rozkładzie permutacji na cykle).
?- cykl([1,2,3], [2, 3, 1]).
true.
?- cykl([1,2,3], [2, 1, 3]).
false.
?- cykl([1,2,3], X).
X = [2,3,1] ? ;
X = [3,1,2] ? ;
false.
Zadanie 11**
Napisz predykat cykle(K, L1, L2), który jest spełniony gdy lista L2 jest permutacją listy L1 o dokładnie K cyklach.
?- cykle(2,
X = [1,3,2]
X = [2,1,3]
X = [3,2,1]
false.
?- cykle(K,
K = 3,
X = [1,2,3]
K = 2,
X = [1,3,2]
K = 2,
X = [2,1,3]
K = 1,
X = [2,3,1]
K = 2,
X = [3,2,1]
K = 1,
X = [3,1,2]
false.
?- cykle(K,
[1, 2, 3], X).
? ;
? ;
? ;
[1, 2, 3], X).
? ;
? ;
? ;
? ;
? ;
? ;
[1, 2, 3, 4, 5], [4, 2, 5, 1, 3]).
5
K = 3 ? ;
false.
6
Download