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