LaptrinhLogic2

Download Report

Transcript LaptrinhLogic2

Lập trình logic và ràng buộc
(Logic Programming and Constraint)
Ts. Lê Mạnh Hải
Khoa CNTT,
ĐH Kỹ thuật Công nghệ TP HCM
1
Bài 2: Kỹ thuật lập trình
• Mục tiêu:
–
–
–
–
Các kỹ thuật xử lý danh sách
Các phép toán
Xử lý CSDL
Nhập xuất qua tập tin
2
Xử lý danh sách
Danh sách (list) là cấu trúc dữ liệu quan trọng.
• Biểu diễn danh sách [X], [a,b,c], [], [Head|Tail].
• Các vị từ build-in (/doc/Manual/lists.html‘)
–
–
–
–
–
–
–
member(?Elem, ?List), delete(+List1, @Elem, -List2)
append(?List1, ?List2, ?List1AndList2),
select(?Elem, ?List1, ?List2)
nextto(?X, ?Y, ?List), last(?List, ?Last)
nth0(?Index, ?List, ?Elem), nth1(?Index, ?List, ?Elem)
max_member(-Max, +List), min_member(-Max, +List),
sum_list(+List, -Sum)
3
Kiểm tra hoạt động
1 ?- member(3,[2,4,3,5]).
true .
2 ?- member([3],[2,4,3,5]).
false.
3 ?- member(3,[2,4,[3,2],5]).
false.
4 ?- member([3,_],[2,4,[3,2],5]).
true .
5 ?- member([3|T],[2,4,[3,2],5]).
T = [2] .
6 ?- delete([2,4,3,5],3,X).
X = [2, 4, 5].
4
Kiểm tra hoạt động
1 ?- append([2,4,5],[3,4,5,6],X).
X = [2, 4, 5, 3, 4, 5, 6].
4 ?- select(3,[2,3,4],X).
X = [2, 4] .
5 ?- last([a,f,d,b,c],X).
X = c.
Hãy tìm phần tử đứng thứ 3 trong danh sách
6 ?- nextto(3,X,[2,4,3,5,6]).
X=5.
Hãy tìm phần tử đứng trước số 4 trong danh sách sau
[3,5,4,6,8,4,7].
7 ?- sum_list([3,5,4,6,8,4,7],X).
X = 37.
5
• Ví dụ1:
– Viết chương trình đếm số phần tử của 1 danh sách
size([],0).
size([H|T],N) :- size(T,N1), N is N1+1.
37 ?- size([a,3,d,4,v],X).
X = 5.
• Bài tập 1: tính tổng một danh sách (mysum)
6
Các phép tính số học
Các phép tính số học +,-,* và /.
Các phép so sánh <, >, =<, >=, =:= (equals), =\=
Ví dụ:
?- 5<7,integer(4).
true.
?- 4+3=:=7.
true.
7
Suy diễn lùi (BackTracking)
Chẳng hạn ta có định nghĩa vi từ bigger sau
bigger(N,M):N < M, write(‘The bigger number is ‘), write(M).
bigger(N,M):N > M, write(‘The bigger number is ‘), write(N).
bigger(N,M):N =:= M, write(‘Numbers are the same‘).
Bây giờ ta truy vấn
?- bigger(5,4).
Prolog làm gì?
8
Tìm vị từ
?- bigger(5,4).
bigger(N,M):N < M,
write(‘The bigger number is ‘), write(M).
bigger(N,M):N > M,
write(‘The bigger number is ‘), write(N).
bigger(N,M):N =:= M,
write(‘Numbers are the same‘).
9
bigger(5,4).
bigger(5,4):- Backtrack
5 < 4,  fails
write(‘The bigger number is ‘),
write(M).
bigger(N,M):N > M,
write(‘The bigger number is ‘),
write(N).
bigger(N,M):N =:= M,
write(‘Numbers are the same‘).
10
|?- bigger(5,4).
bigger(N,M):N < M,
write(‘The bigger number is ‘),
write(M).
bigger(5,4):5 > 4,  succeeds, go on with body.
write(‘The bigger number is ‘), write(N).
bigger(N,M):Đến dấu chấm
N =:= M,
write(‘Numbers are the same‘). = thành công
11
Backtracking – Suy diễn lùi
?- bigger(5,5).
 If our query only matches the final clause
bigger(N,M):N < M,
write(‘The bigger number is ‘), write(M).
bigger(N,M):N > M,
write(‘The bigger number is ‘), write(N).
bigger(5,5):5 =:= 5,  Đã biết trước là không xảy ra.
write(‘Numbers are the same‘).
Clauses should be ordered according to specificity
Most specific at top
Universally applicable at bottom
12
Đích trung gian
1) drinks(alan,beer).
2) likes(alan,coffee).
3) likes(heather,coffee).
4) likes(Person,Drink):drinks(Person,Drink).  Đích trung gian
5) likes(Person,Somebody):likes(Person,Drink),
 đệ quy
likes(Somebody,Drink). 
13
Đệ quy
• Một mệnh đề đệ quy là mệnh đề đệ quy là mệnh đề sử dụng
chính nó để định nghĩa nó.
• Một mệnh đề đệ quy sẽ bị lặp vô hạn nếu không có điều kiện
thoát. Vì vậy phải có định nghĩa trường hợp cụ thể không
đệ quy ngay trước mô tả đệ quy.
• Ví dụ: size([],0).
• Lập trình viên prolog thường sử dụng đệ quy gián tiếp
a(X):-b(Y).
b([]) is 1. %điều kiện thoát đệ quy bên dưới
b(Y):-a(X).
14
Ví dụ 2: Bài toán tháp Hà nội
Đế đặt nằm ngang; các cột thẳng đứng. Các đĩa đặt theo
thứ tự từ lớn đến nhỏ từ thấp lên cao; tạo nên một Tòa
tháp. Trò chơi đòi hỏi di chuyển các đĩa, bằng cách đặt
chúng vào cột bên cạnh, một đĩa trong một di chuyển,
theo luật sau:
I. -- Sau mỗi di chuyển, các đĩa đều nằm trên một, hai,
hoặc ba cột, theo thứ tự từ lớn đến nhỏ từ thấp đến cao.
II. -- Đĩa trên cùng của một trong ba cột đĩa được đặt vào
cột rỗng.
III. -- Đĩa trên cùng của một trong ba cột đĩa được đặt lên
một cột đĩa khác, nếu đĩa này nhỏ hơn các đĩa của cột này.
15
Lưu đoạn code sau vao file hanoi.pl
move(1,X,Y,_) :write('chuyen dia tren cung tu '),
write(X), write(' sang '),write(Y), nl.
move(N,X,Y,Z) :- N>1, M is N-1, move(M,X,Z,Y),
move(1,X,Y,_),move(M,Z,Y,X).
55 ?- [hanoi].
% hanoi compiled 0.00 sec, 1 clauses
true.
56 ?- move(5,giua,trai,phai).
chuyen dia tren cung tu giua sang trai
chuyen dia tren cung tu giua sang phai
chuyen dia tren cung tu trai sang phai
16
Cắt “!”
Giả sử có các vị từ a,b và c
a(X, Y) :- b(X), !, c(Y).
b(1). b(2). b(3).
c(1). c(2). c(3).
Truy vấn
?- a(Q,P). Sẽ hoạt động như thế nào
17
Cắt “!”
?- a(Q,P).
Q = P, P = 1 ;
Q = 1,
P=2;
Q = 1,
P = 3.
vì có dấu ! (cut)
18
Cắt “!”
• Cắt không làm thay đổi kết quả truy vấn
• Cắt chỉ giới hạn số phép quay lui khi điều
kiện ngay trước đó đã được thỏa mãn.
– Nhanh hơn
– Chống đệ quy vô hạn
19
Bài tập 2
Sắp xếp một danh sách theo thứ tự tăng dần.
• Bubble sort? QuickSort? MergeSort?
• Prolog “ưa” các giải thuật đệ quy => QS và MS dễ viết hơn!
20
Quicksort
quicksort([X|Xs],Ys) :partition(Xs,X,Left,Right),
quicksort(Left,Ls),
quicksort(Right,Rs),
append(Ls,[X|Rs],Ys).
quicksort([],[]).
partition([X|Xs],Y,[X|Ls],Rs) :X <= Y, partition(Xs,Y,Ls,Rs).
partition([X|Xs],Y,Ls,[X|Rs]) :X > Y, partition(Xs,Y,Ls,Rs).
partition([],Y,[],[]).
append([],Ys,Ys).
append([X|Xs],Ys,[X|Zs]) :- append(Xs,Ys,Zs).
21
Mergesort
mergesort([],[]). /* covers special case */
mergesort([A],[A]).
mergesort([A,B|R],S) :split([A,B|R],L1,L2), mergesort(L1,S1), mergesort(L2,S2),
merge(S1,S2,S). split([],[],[]). split([A],[A],[]).
split([A,B|R],[A|Ra],[B|Rb]) :- split(R,Ra,Rb). merge(A,[],A).
merge([],B,B). merge([A|Ra],[B|Rb],[A|M]) :- A =< B,
merge(Ra,[B|Rb],M).
merge([A|Ra],[B|Rb],[B|M]) :A > B, merge([A|Ra],Rb,M).
Truy vấn: ?- mergesort([4,3,6,5,9,1,7],S).
S=[1,3,4,5,6,7,9]
22
Bài tập
1. Viêt một chương trình để bỏ ba phần tử đầu của một danh
sách.
2. Định nghĩa hai vị từ :
even_length( List ) và odd_length( List ) để kiểm tra số các
phần tử của một danh sách là chẵn hay lẻ.
Ví dụ danh sách :
even_length([ a, b, c, d ]) là true
even_length([ a, b, c]) là false.
23
3. Viêt chương trình Prolog kiểm tra một danh sách có phải
là một tap hợp con của một danh sách khác không ?
?- subset2([4,3],[2,3,5,4]).
Yes
4. Viết chương trình Prolog tìm phần tử lớn nhất và phần tủ
nhỏ nhất trong một danh sách các số.
?- maxmin([3,1,5,2,7,3],Max,Min).
Max = 7
Min = 1
Yes
24
5. Viết chương trình Prolog kiểm tra hai danh
sách có rời nhau không
?- disjoint([a,b,c],[d,g,f,h]).
Yes
?- disjoint([a,b,c],[f,a]).
No
6. Viết chương trình Prolog tìm phần tử X đầu
tiên trong danh sách L
25
Bài kế tiếp
Cơ sở dữ liệu
Xuất nhập
26
Cơ sở dữ liệu
• Tổ chức cơ sở dữ liệu dưới dạng bảng
• Các bảng có mối liên kết (quan hệ ràng
buộc)
• Ví dụ: ‘bảng’ individual
individual( tom, smith, date(7, may, 1960),
work(microsoft, 30000) ).
individual( ann, smith, date(9, avril, 1962),
inactive).
27
• ‘bảng’ family
family(individual(…), individual(…), [individual(…)]). Với ám chỉ
ngôi 1 là chồng, ngôi 2 là vợ, ngôi 3 là danh sách các con.
family(individual( tom, smith, date(7, may, 1960),
work(microsoft, 30000) ),
individual( ann, smith, date(9, avril, 1962),inactive),
[ individual( roze, smith, date(16, june, 1991), inactive),
individual( eric, smith, date(23, march, 1993), inactive) ] ).
husban( X ) :- % X là chồng
family( X , _ , _ ).
wife( X ) :- % X là vợ
family( _, X , _ ).
children( X ) :- % X là một người con,
family( _, _ , Children ), member( X, Children ).
28
Ta định nghĩa một số vị từ để tiện truy vấn
exist( Individual ) :- % mọi thành viên của gia dình
husban( Individual ) ;
wife( Individual ) ;
chidren( Individual ). % dấu ; là hoặc, dấu , là và!!!
dateofbirth( individual( _ , _, Date , _ ), Date ).
salary( individual( _ , _, _ , work( _ , S ) ), S ).
salary( individual( _ , _, _ , inactive ), 0 ).
Tại sao phải có 2 định nghĩa salary?
29
Truy vấn dữ liệu
Các lệnh truy vấn sau đây sẽ trả lại những thông tin gì?
?- exist( individual( Firstname, Lastname, _ , _ ) ).
?- chidren( X ), dateofbirth( X, date( _ , _ , 1991 )).
?- wife( individual( Firstname, Lastname, _ , work( _, _ ) ) ).
Hãy viết các lệnh truy vấn các thông tin sau:
1. Tìm những người sinh trước 1975 không có việc làm
2. Tìm những người sinh trước 1970 có thu nhập trên 10000
3. Tìm những gia đình có trên 3 người con.
30