4. Sử dụng nhát cắt để phân loại dữ liệu
I.3.1. Phủ định bởi thất bạ
Trong Prolog, ta có thể nói được câu : «Marie thích tất cả loài động vật trừ loài rắn» hay không ?
Đối với vế thứ nhất, ta có thể dễ dàng dịch ra thành : Dù X là gì, Marie thích X nếu X là loài động vật :
enjoy( marie, X ) :- animal( X ).
Tuy nhiên cần loại trừ loài rắn. Lúc này ta cần dịch ra như sau :
Nếu X là loài rắn, thì «Marie thích X» là sai,
Nếu không, nếu X là loài động vật thì Marie thích X.
Những gì không đúng thì có thể sử dụng đích đặc biệt fail (thất bại) để luôn luôn sai, và cũng làm cho đích cha thất bại. Chương trình được viết lại như sau :
enjoy( marie, X ) :-
serpent( X ), !, fail. enjoy( marie, X ) :-
animal( X ).
Luật thứ nhất xử lý tình huống Marie không thích loài rắn : nếu X là loài rắn, thì nhát cắt sẽ ngăn sự quay lui (và do đó, luật thứ hai không được thực hiện), và đích fail sẽ gây ra thất bại. Ta có thể sử dụng dấu ; để viết cô đọng hai luật thành một luật như sau :
enjoy( marie, X ) :-
serpent( X ), !, fail; animal( X ).
Một cách tương tự, ta định nghĩa quan hệ khác nhau : diffĩrent( X, Y )
thoả mãn nếu X và Y là khác nhau. Do sự khác nhau có thể được diễn giải theo nhiều cách nên ta cần chỉ rõ như sau :
• X và Y không phải là các trực hằng (literal) đồng nhất,
• X và Y không thể khớp với nhau,
• Các giá trị của các biểu thức số học X và Y không thể bằng nhau. Ta nói rằng X và Y khác nhau do chúng không thể khớp được với nhau :
Nếu X và Y là đồng nhất, thì diffĩrent( X, Y ) thất bại, Nếu không, diffĩrent( X, Y ) thành công.
Ta sử dụng nhát cắt và đích fail để viết quan hệ này thành hai luật : diffĩrent( X, X ) :- !, fail.
126 Lập trình lägich trong Prolog
diffĩrent( X, Y ).
Hoặc viết lại thành một luật như sau : diffĩrent( X, Y ) :-
X = Y, !, fail; true.
Chú ý rằng đích true (đúng) luôn luôn thành công.
Từ đây, ta có thể định nghĩa vị từ not(Goal) cho phép kiểm tra đích không thoả mãn như sau :
Nếu Goal thoả mãn, thì not(Goal) thất bại, Nếu không, not(Goal) thành công.
Chương trình Prolog : not( P ) :-
P, !, fail; true.
Hầu hết các phiên bản Prolog hiện nay đều có vị từ not not(2 = 3).
Yes
?- not(2 = 2). No
Sử dụng vị từ not, ta có thể định nghĩa lại các quan hệ enjoy, diffĩrent và classe như sau :
enjoy( marie, X ) :- animal( X ), not (serpent( X )). diffĩrent( X, Y ) :- not( X = Y ). classe( X, combatif) :- bat( X, _ ), bat( _ , X ). classe( X, champion) :- bat( X _ ), not bat( _ , X ). classe( X, dilettante) :- bat( _ , X ), not bat( X, _ ).
Kỹ thuật lập trình Prolog 127