You are on page 1of 211

TS.

PHAN HUY KHÁNH

Lập trình Lôgích


trong Prolog

NHÀ XUẤT BẢN ĐẠI HỌC QUỐC GIA HÀ NỘI


PHAN HUY KHÁNH

Lập trình Lôgích


trong Prolog
Prolog là ngôn ngữ lập trình lôgich (Prolog = PROgramming in LOGic) do GS.
A. Colmerauer đưa ra lần đầu tiên năm 1972 tại trường Đại học Marseille, nước
Pháp. Đến năm 1980, Prolog nhanh chóng được áp dụng rộng rãi, được người Nhật
chọn làm ngôn ngữ phát triển máy tính thế hệ 5. Prolog đã được cài đặt trên hầu hết
các dòng máy tính Unix/Linux, Macintosh, Windows.
Prolog còn được gọi là ngôn ngữ lập trình ký hiệu (symbolic programming) tương tự lập
trình hàm (functional programming), hay lập trình phi số (non-numerical programming).
Nguyên lý lập trình lôgich dựa trên phép suy diễn lôgích, liên quan đến những khái
niệm toán học như phép hợp nhất Herbrand, hợp giải Robinson, lôgich Horn, lôgich
vị từ bậc một (first order predicate logic), v.v...
Prolog rất thích hợp để giải quyết những bài toán liên quan đến các đối tượng và mối
quan hệ giữa chúng. Prolog được ứng dụng chủ yếu trong lĩnh vực trí tuệ nhân tạo
(Artificial Intelligence) như công nghệ xử lý tri thức, hệ chuyên gia, máy học, xử lý
ngôn ngữ, trò chơi, v.v...
Nội dung cuốn sách tập trung trình bày cơ sở lý thuyết và những kỹ thuật
lập trình cơ bản trong Prolog, rất thích hợp cho sinh viên các ngành tin học và những
bạn đọc muốn tìm hiểu về kỹ thuật lập trình ứng dụng trong lĩnh vực trí tuệ nhân tạo.
VỀ TÁC GIẢ :
Sinh viên K14, khoa Toán-Lý, trường ĐHBK Hà Nội. 1971-1976, đi bộ đội chiến
đấu tại miền Đông, Tây Nam Bộ. 1976-1979 xuất ngũ tiếp tục học K19. Năm 1979
tốt nghiệp kỹ sư ngành Toán máy tính. Từ 1979 đến nay giảng dạy tại khoa CNTT,
trường ĐHBK Đà Nẵng. Bảo vệ tiến sĩ năm 1991 tại Pháp. Làm post-doc tại GETA-
CLIPS, IMAGrenoble 1991-1992. Giữ chức chủ nhiệm khoa CNTT 1995-2000.
Những vấn đề nghiên cứu : xử lý ngôn ngữ, xử lý đa ngữ, lý thuyết tính toán, phân
tích và thiết kế hệ thống, e-learning.
E-mail: phanhuykhanh@dng.vnn.vn

.
LÅÌI NOÏI ÂÁÖU
Cuäún saïch naìy nhàòm cung cáúp cå såí lyï thuyãút vaì caïc phæång phaïp
láûp trçnh cå baín nháút cuía män hoüc «Láûp trçnh lägich» (Programming in Logic).
Ngæåìi âoüc seî âæåüc laìm quen våïi mäüt säú kyî thuáût láûp trçnh lägich âæåüc æïng duûng
tæång âäúi phäø biãún vaì chuí yãúu trong lénh væûc trê tuãû nhán taûo (Artificial
Intelligence) nhæ cäng nghãû xæí lyï tri thæïc, maïy hoüc, hãû chuyãn gia, xæí lyï ngän
ngæî tæû nhiãn, troì chåi, v.v...

Cuäún saïch gäöm nàm chæång vaì phuû luûc nhæ sau :
− Chæång 1 giåïi thiãûu ngän ngæî láûp trçnh Prolog lägich dæûa trãn lägich
Horn (Horn logic). Ngæåìi âoüc laìm quen våïi caïc kiãøu dæî liãûu cuía Prolog,
khaïi niãûm vãö luáût, sæû kiãûn vaì viãút caïc chæång trçnh Prolog âån giaín.
− Chæång 2 trçnh baìy caïc mæïc nghéa khaïc nhau cuía mäüt chæång trçnh
Prolog : nghéa lägich, nghéa khai baïo vaì nghéa thuí tuûc, caïch Prolog traí
låìi caïc cáu hoíi, caïch laìm thoaí maîn âêch.
− Chæång 3 trçnh baìy caïc pheïp toaïn säú hoüc, pheïp so saïnh vaì âënh nghéa
haìm sæí duûng pheïp âãû quy trong Prolog.
− Chæång 4 trçnh baìy cáúu truïc danh saïch vaì caïc pheïp xæí lyï cå baín trãn
danh saïch cuía Prolog.
− Chæång 5 trçnh baìy kyî thuáût láûp trçnh náng cao våïi Prolog.
− Pháön phuû luûc giåïi thiãûu ngän ngæî láûp trçnh SWI-Prolog, hæåïng dáùn
caïch caìi âàût sæí duûng pháön mãöm naìy vaì mäüt säú chæång trçnh vê duû tiãu
biãøu viãút trong SWI Prolog.

Cuäún saïch naìy duìng laìm giaïo trçnh cho sinh viãn ngaình Tin hoüc vaì caïc
âäüc giaí muäún tçm hiãøu thãm vãö kyî thuáût láûp trçnh cho lénh væûc trê tuãû nhán taûo.

Trong quaï trçnh biãn soaûn, taïc giaí âaî nháûn âæåüc tæì caïc baûn âäöng nghiãûp
nhiãöu âoïng goïp bäø êch vãö màût chuyãn män, nhæîng âäüng viãn khêch lãû vãö màût
tinh tháön, sæû giuïp âåî vãö biãn táûp âãø cuäún saïch âæåüc ra âåìi. Taïc giaí xin âæåüc
baìy toí loìng biãút ån sáu sàõc. Taïc giaí cuîng chán thaình caím ån moüi yï kiãún phã
bçnh âoïng goïp cuía baûn âoüc gáön xa vãö näüi dung cuía cuäún saïch naìy.

Âaì Nàông, ngaìy 27/05/2004


Taïc giaí.
MUÛC LUÛC

CHÆÅNG 1 MÅÍ ÂÁÖU VÃÖ NGÄN NGÆÎ PROLOG................................. 1


I. GIÅÏI THIÃÛU NGÄN NGÆÎ PROLOG ........................................ 1
I.1. Prolog laì ngän ngæî láûp trçnh lägich ........................................... 1
I.2. Cuï phaïp Prolog........................................................................... 2
I.2.1. Caïc thuáût ngæî ............................................................................. 2
I.2.2. Caïc kiãøu dæî liãûu Prolog .............................................................. 3
I.2.3. Chuï thêch .................................................................................... 4
II. CAÏC KIÃØU DÆÎ LIÃÛU SÅ CÁÚP CUÍA PROLOG......................... 5
II.1. Caïc kiãøu hàòng (træûc kiãûn) .......................................................... 5
II.1.1. Kiãøu hàòng säú ............................................................................... 5
II.1.2. Kiãøu hàòng lägich......................................................................... 5
II.1.3. Kiãøu hàòng chuäùi kyï tæû ................................................................ 5
II.1.4. Kiãøu hàòng nguyãn tæí .................................................................. 5
II.2. Biãún ............................................................................................. 6
III. SÆÛ KIÃÛN VAÌ LUÁÛT TRONG PROLOG .................................... 6
III.1. Xáy dæûng sæû kiãûn ........................................................................ 6
III.2. Xáy dæûng luáût ........................................................................... 10
III.2.1. Âënh nghéa luáût ........................................................................ 10
III.2.2. Âënh nghéa luáût âãû quy ............................................................ 15
III.2.3. Sæí duûng biãún trong Prolog ....................................................... 18
IV. KIÃØU DÆÎ LIÃÛU CÁÚU TRUÏC CUÍA PROLOG ......................... 19
IV.1. Âënh nghéa kiãøu cáúu truïc cuía Prolog ....................................... 19
IV.2. So saïnh vaì håüp nháút caïc haûng ................................................. 22
CHÆÅNG 2 NGÆÎ NGHÉA CUÍA CHÆÅNG TRÇNH PROLOG ..........31
I. QUAN HÃÛ GIÆÎA PROLOG VAÌ LÄGICH TOAÏN HOÜC .......... 31
II. CAÏC MÆÏC NGHÉA CUÍA CHÆÅNG TRÇNH PROLOG .......... 32
II.1. Nghéa khai baïo cuía chæång trçnh Prolog................................. 33
II.2. Khaïi niãûm vãö goïi mãûnh âãö ....................................................... 34

i
II.3. Nghéa lägich cuía caïc mãûnh âãö.................................................. 35
II.4. Nghéa thuí tuûc cuía Prolog ......................................................... 37
II.5. Täø håüp caïc yãúu täú khai baïo vaì thuí tuûc ..................................... 47
III. VÊ DUÛ : CON KHÈ VAÌ QUAÍ CHUÄÚI ....................................... 48
III.1. Phaït biãøu baìi toaïn .................................................................... 48
III.2. Giaíi baìi toaïn våïi Prolog............................................................ 49
III.3. Sàõp âàût thæï tæû caïc mãûnh âãö vaì caïc âêch .................................. 54
III.3.1. Nguy cå gàûp caïc voìng làûp vä haûn ............................................. 54
III.3.2. Thay âäøi thæï tæû mãûnh âãö vaì âêch trong chæång trçnh ............. 56
CHÆÅNG 3 CAÏC PHEÏP TOAÏN VAÌ SÄÚ HOÜC .......................................65
I. SÄÚ HOÜC .................................................................................... 65
I.1. Caïc pheïp toaïn säú hoüc ................................................................ 65
I.2. Biãøu thæïc säú hoüc ....................................................................... 65
I.3. Âënh nghéa caïc pheïp toaïn trong Prolog ................................... 68
II. CAÏC PHEÏP SO SAÏNH CUÍA PROLOG .................................... 73
II.1. Caïc pheïp so saïnh säú hoüc ........................................................... 73
II.2. Caïc pheïp so saïnh haûng............................................................. 75
II.3. Vë tæì xaïc âënh kiãøu ................................................................... 77
II.4. Mäüt säú vë tæì xæí lyï haûng ............................................................ 77
III. ÂËNH NGHÉA HAÌM ................................................................. 79
III.1. Âënh nghéa haìm sæí duûng âãû quy.............................................. 79
III.2. Täúi æu pheïp âãû quy................................................................... 87
III.3. Mäüt säú vê duû khaïc vãö âãû quy..................................................... 88
III.3.1. Tçm âæåìng âi trong mäüt âäö thë coï âënh hæåïng ........................ 88
III.3.2. Tênh âäüü daìi âæåìng âi trong mäüt âäö thë .................................... 89
III.3.3. Tênh gáön âuïng caïc chuäùi .......................................................... 90
CHÆÅNG 4 CÁÚU TRUÏC DANH SAÏCH.................................................95
I. BIÃØU DIÃÙN CÁÚU TRUÏC DANH SAÏCH .................................. 95
II. MÄÜT SÄÚ VË TÆÌ XÆÍ LYÏ DANH SAÏCH CUÍA PROLOG ........... 98
III. CAÏC THAO TAÏC CÅ BAÍN TRÃN DANH SAÏCH .................... 99
III.1. Xáy dæûng laûi mäüt säú vë tæì coï sàôn ............................................. 99
III.2. Hoaïn vë ................................................................................... 107

ii
III.3. Mäüt säú vê duû vãö danh saïch...................................................... 109
CHÆÅNG 5 KYÎ THUÁÛT LÁÛP TRÇNH PROLOG ..............................117
I. NHAÏT CÀÕT ............................................................................. 117
I.1. Khaïi niãûm nhaït càõt ................................................................ 117
I.2. Kyî thuáût sæí duûng nhaït càõt ..................................................... 118
I.3. Pheïp phuí âënh ........................................................................ 126
II. SÆÍ DUÛNG CAÏC CÁÚU TRUÏC .................................................. 131
II.1. Truy cáûp thäng tin cáúu truïc tæì mäüt cå såí dæî liãûu .................. 132
II.2. Træìu tæåüng hoaï dæî liãûu .......................................................... 136
II.3. Mä phoíng ätämat hæîu haûn ..................................................... 138
II.4. Vê duû : láûp kãú hoaûch âi du lëch bàòng maïy bay ....................... 144
II.5. Baìi toaïn taïm quán háûu .......................................................... 150
III. QUAÏ TRÇNH VAÌO-RA VAÌ LAÌM VIÃÛC VÅÏI TÃÛP .................. 163
III.1. Khaïi niãûm ............................................................................... 163
III.2. Laìm viãûc våïi caïc tãûp ................................................................ 164
III.3. ÆÏng duûng chãú âäü laìm viãûc våïi caïc tãûp .................................... 172
PHUÛ LUÛC A MÄÜT SÄÚ CHÆÅNG TRÇNH PROLOG..........................187
PHUÛ LUÛC B HÆÅÏNG DÁÙN SÆÍ DUÛNG SWI-PROLOG .....................194
I. GIÅÏI THIÃUU SWI-PROLOG............................................... 194
II. LAIM VIÃUC VÅÏI SWI-PROLOG......................................... 195
II.1. Âàût cáu hoíi .............................................................................. 195
II.2. Chaûy trçnh demo..................................................................... 196
II.3. Chaûy trçnh demo XPCE ......................................................... 197
II.4. Caïc lãûnh âån (Menu commands)............................................ 198
II.5. Soaûn thaío chæång trçnh.......................................................... 200
III. MÄÜT SÄÚ LÃÛNH SWI-PROLOG THÄNG DUÛNG.................. 201
TAÌI LIÃÛU THAM KHAÍO ............................................................................ 203

iii
CHÆÅNG 1

Måí âáö u vãö ngän ngæî Prolog


« A program is a theory (in some logic)
and computation is deduction from the theory »
J. A. Robinson
« Program = data structure + algorithm »
N. Wirth
« Algorithm = logic + control »
R. Kowalski

I. Giåïi thiãûu ngän ngæî Prolog


I.1. Prolog laì ngän ngæî láûp trçnh lägich

P rolog laì ngän ngæî âæåüc sæí duûng phäø biãún nháút trong doìng caïc ngän
ngæî láûp trçnh lägich (Prolog coï nghéa laì PROgramming in LOGic).
Ngän ngæî Prolog do giaïo sæ ngæåìi Phaïp Alain Colmerauer vaì nhoïm
nghiãn cæïu cuía äng âãö xuáút láön âáöu tiãn taûi træåìng Âaûi hoüc Marseille âáöu
nhæîng nàm 1970. Âãún nàm 1980, Prolog nhanh choïng âæåüc aïp duûng räüng raîi
åí cháu Áu, âæåüc ngæåìi Nháût choün laìm ngän ngæî phaït triãøn doìng maïy tênh
thãú hãû 5. Prolog âaî âæåüc caìi âàût trãn caïc maïy vi tênh Apple II, IBM-PC,
Macintosh.
Prolog coìn âæåüc goüi laì ngän ngæî láûp trçnh kyï hiãûu (symbolic programming)
tæång tæû caïc ngän ngæî láûp trçnh haìm (functional programming), hay láûp trçnh phi
säú (non-numerical programming). Prolog ráút thêch håüp âãø giaíi quyãút caïc baìi toaïn
liãn quan âãún caïc âäúi tæåüng (object) vaì mäúi quan hãû (relation) giæîa chuïng.
Prolog âæåüc sæí duûng phäø biãún trong lénh væûc trê tuãû nhán taûo. Nguyãn lyï
láûp trçnh lägich dæûa trãn caïc mãûnh âãö Horn (Horn logêc). Mäüt mãûnh âãö Horn
biãùu diãùn mäüt sæû kiãûn hay mäüt sæû viãûc naìo âoï laì âuïng hoàûc khäng âuïng, xaíy
ra hoàûc khäng xaíy ra (coï hoàûc khäng coï, v.v...).

1
2 Láûp trçnh logic trong Prolog

Vê duû I.1 : Sau âáy laì mäüt säú mãûnh âãö Horn :
1. Nãúu mäüt ngæåìi giaì maì (vaì) khän ngoan thç ngæåìi âoï haûnh phuïc.
2. Jim laì ngæåìi haûnh phuïc.
3. Nãúu X laì cha meû cuía Y vaì Y laì cha meû cuía Z thç X laì äng cuía Z.
4. Tom laì äng cuía Pat.
5. Táút caí moüi ngæåìi âãöu chãút (hoàûc Nãúu ai laì ngæåìi thç ai âoï phaíi chãút).
6. Socrat laì ngæåìi.
Trong caïc mãûnh âãö Horn åí trãn, caïc mãûnh âãö 1, 3, 5 âæåüc goüi laì caïc luáût
(rule), caïc mãûnh âãö coìn laûi âæåüc goüi laì caïc sæû kiãûn (fact). Mäüt chæång trçnh
lägich coï thãø âæåüc xem nhæ laì mäüt cå såí dæî liãûu gäöm caïc mãûnh âãö Horn, hoàûc
daûng luáût, hoàûc daûng sæû kiãûn, chàóng haûn nhæ táút caí caïc sæû kiãûn vaì luáût tæì 1
âãún 6 åí trãn. Ngæåìi sæí duûng (NSD) goüi chaûy mäüt chæång trçnh lägich bàòng
caïch âàût cáu hoíi (query/ question) truy váún trãn cå såí dæî liãûu naìy, chàóng
haûn cáu hoíi :
Socrat coï chãút khäng ?
(tæång âæång khàóng âënh Socrat chãút âuïng hay sai ?)
Mäüt hãû thäúng lägich seî thæûc hiãûn chæång trçnh theo caïch «suy luáûn»-tçm
kiãúm dæûa trãn väún «hiãøu biãút» âaî coï laì chæång trçnh - cå såí dæî liãûu, âãø minh
chæïng cáu hoíi laì mäüt khàóng âënh, laì âuïng (Yes) hoàûc sai (No). Våïi cáu hoíi
trãn, hãû thäúng tçm kiãúm trong cå såí dæî liãûu khàóng âënh Socrat chãút vaì «tçm
tháúy» luáût 5 thoaí maîn (vãú thç). Váûn duûng luáût 5, hãû thäúng nháûn âæåüc Socrat
laì ngæåìi (vãú nãúu) chênh laì sæû kiãûn 5. Tæì âoï, cáu traí låìi seî laì :
Yes
coï nghéa Socrat chãút laì âuïng.

I.2. Cuï phaïp Prolog


I.2.1. Caïc thuáût ngæî
Mäüt chæång trçnh Prolog laì mäüt cå såí dæî liãûu gäöm caïc mãûnh âãö (clause).
Mäùi mãûnh âãö âæåüc xáy dæûng tæì caïc vë tæì (predicat). Mäüt vë tæì laì mäüt phaït
biãøu naìo âoï vãö caïc âäúi tæåüng coï giaï trë chán âuïng (true) hoàûc sai (fail). Mäüt vë
tæì coï thãø coï caïc âäúi laì caïc nguyãn lägich (logic atom).
Måí âáöu vãö ngän ngæî Prolog 3

Mäùi nguyãn tæí (noïi goün) biãøu diãùn mäüt quan hãû giæîa caïc haûng (term).
Nhæ váûy, haûng vaì quan hãû giæîa caïc haûng taûo thaình mãûnh âãö.
Haûng âæåüc xem laì nhæîng âäúi tæåüng “dæî liãûu” trong mäüt trçnh Prolog.
Haûng coï thãø laì haûng så cáúp (elementary term) gäöm hàòng (constant), biãún
(variable) vaì caïc haûng phæïc håüp (compound term).
Caïc haûng phæïc håüp biãøu diãùn caïc âäúi tæåüng phæïc taûp cuía baìi toaïn cáön giaíi
quyãút thuäüc lénh væûc âang xeït. Haûng phæïc håüp laì mäüt haìm tæí (functor) coï
chæïa caïc âäúi (argument), coï daûng

Tãn_haìm_tæí(Âäúi_1, ..., Âäúi_n)


Tãn haìm tæí laì mäüt chuäùi chæî caïi vaì/hoàûc chuî säú âæåüc bàõt âáöu båíi mäüt chæî
caïi thæåìng. Caïc âäúi coï thãø laì biãún, haûng så cáúp, hoàûc haûng phæïc håüp. Trong
Prolog, haìm tæí âàûc biãût “.” (dáúu cháúm) biãøu diãùn cáúu truïc danh saïch (list).
Kiãøu dæî liãûu haìm tæí tæång tæû kiãøu baín ghi (record) vaì danh saïch (list) tæång
tæû kiãøu maíng (array) trong caïc ngän ngæî láûp trçnh mãûnh lãûnh (C, Pascal...).
Vê duû I.2 :
f(5, a, b).
student(robert, 1975, info, 2, address(6, 'mal juin', 'Caen')).
[a, b, c]

Mãûnh âãö coï thãø laì mäüt sæû kiãûn, mäüt luáût (hay quy tàõc), hay mäüt cáu hoíi.
Prolog quy æåïc viãút sau mäùi mãûnh âãö mäüt dáúu cháúm âãø kãút thuïc nhæ sau :
• Sæû kiãûn : < ... >. (tæång æïng våïi luáût < ... > :- true. )
• Luáût : < ... > :- < ... >.
• Cáu hoíi ?- < ... >. (åí chãú âäü tæång taïc coï dáúu nhàõc lãûnh)

I.2.2. Caïc kiãøu dæî liãûu Prolog


Hçnh 1.1. biãøu diãùn mäüt sæû phán låïp caïc kiãøu dæî liãûu trong Prolog gäöm
kiãøu dæî liãûu så cáúp vaì kiãøu dæî liãûu coï cáúu truïc. Sæû phán låïp naìy nháûn biãút
kiãøu cuía mäüt âäúi tæåüng nhåì bãö ngoaìi cuï phaïp.
Cuï phaïp cuía Prolog quy âënh mäùi kiãøu âäúi tæåüng coï mäüt daûng khaïc nhau.
Prolog khäng cáön cung cáúp mäüt thäng tin naìo khaïc âãø nháûn biãút kiãøu cuía
mäüt âäúi tæåüng. Trong Prolog, NSD khäng cáön khai baïo kiãøu dæî liãûu.
4 Láûp trçnh logic trong Prolog

kiãøu dæî liãûu

kiãøu så cáúp kiãøu phæïc håüp

hàòng biãún

säú chuäùi kyï tæû nguyãn tæí

Hçnh I.1. Caïc kiãøu dæî liãûu trong Prolog

Caïc kiãøu dæî liãûu Prolog âæåüc xáy dæûng tæì caïc kyï tæû ASCII :
• Caïc chæî caïi in hoa A, B, ..., Z vaì chæî caïi in thæåìng a, b, ..., z.
• Caïc chæî säú 0, 1, ..., 9.
• Caïc kyï tæû âàûc biãût, chàóng haûn + − ∗ / < > = : . & _ ∼.

I.2.3. Chuï thêch


Trong mäüt chæång trçnh Prolog, chuï thêch (comment) âæåüc âàût giæîa hai
càûp kyï hiãûu /* vaì */ (tæång tæû ngän ngæî C). Vê duû :
/∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/
/∗∗∗ Âáy laì mäüt chuï thêch ∗∗∗/
/∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/
Trong træåìng håüp muäún âàût mäüt chuï thêch ngàõn sau mäùi pháön khai baïo
Prolog cho âãún hãút doìng, coï thãø âàût træåïc mäüt kyï hiãûu %.
Vê duû :
%%%%%%%%%%%%%%%
% Âáy cuîng laì mäüt chuï thêch
%%%%%%%%%%%%%%%
Prolog seî boí qua táút caí caïc pháön chuï thêch trong thuí tuûc.
Måí âáöu vãö ngän ngæî Prolog 5

II. Caïc kiãøu dæî liãûu så cáúp cuía Prolog


II.1. Caïc kiãøu hàòng (træûc kiãûn)
II.1.1. Kiãøu hàòng säú
Prolog sæí duûng caí säú nguyãn vaì säú thæûc. Cuï phaïp cuía caïc säú nguyãn vaì säú
thæûc ráút âån giaín, chàóng haûn nhæ caïc vê duû sau :
1 1515 0 -97
3.14 -0.0035 100.2
Tuyì theo phiãn baín caìi âàût, Prolog coï thãø xæí lyï caïc miãön säú nguyãn vaì
miãön säú thæûc khaïc nhau. Vê duû trong phiãn baín Turbo Prolog, miãön säú
nguyãn cho pheïp tæì -32768 âãún 32767, miãön säú thæûc cho pheïp tæì ±1e-307
âãún ±1e+308. Caïc säú thæûc ráút khi âæåüc sæí duûng trong Prolog. Lyï do chuí yãúu åí
chäù Prolog laì ngän ngæî láûp trçnh kyï hiãûu, phi säú.
Caïc säú nguyãn thæåìng chè âæåüc sæí duûng khi cáön âãúm säú læåüng caïc pháön tæí
hiãûn diãûn trong mäüt danh saïch Prolog daûng [a1, a2, ..., an ].

II.1.2. Kiãøu hàòng lägich


Prolog sæí duûng hai hàòng lägich coï giaï trë laì true vaì fail. Thäng thæåìng caïc
hàòng lägich khäng âæåüc duìng nhæ tham säú maì âæåüc duìng nhæ caïc mãûnh âãö.
Hàòng fail thæåìng âæåüc duìng âãø taûo sinh låìi giaíi baìi toaïn.

II.1.3. Kiãøu hàòng chuäùi kyï tæû


Caïc hàòng laì chuäùi (string) caïc kyï tæû âæåüc âàût giæîa hai dáúu nhaïy keïp.
"Toto \#\{@ tata" chuäùi coï tuyì yï kyï tæû
"" chuäùi räùng (empty string)
"\"" chuäùi chè coï mäüt dáúu nhaïy keïp.
II.1.4. Kiãøu hàòng nguyãn tæí
Caïc hàòng nguyãn tæí Prolog laì chuäùi kyï tæû åí mäüt trong ba daûng nhæ sau :
(1) Chuäùi gäöm chæî caïi, chæî säú vaì kyï tæû _ luän luän âæåüc bàõt âáöu bàòng mäüt
chæî caïi in thæåìng.
newyork a_
nil x__y
x25 tom_cruise
6 Láûp trçnh logic trong Prolog

(2) Chuäùi caïc kyï tæû âàûc biãût :


<---> .:.
======> ::==
...
(3) chuäùi âàût giæîa hai dáúu nhaïy âån (quote) âæåüc bàõt âáöu bàòng chæî in
hoa, duìng phán biãût våïi caïc tãn biãún :
’Jerry’ ’Tom SMITH’

II.2. Biãún
Tãn biãún laì mäüt chuäùi kyï tæû gäöm chæî caïi, chæî säú, bàõt âáöu båíi chæî hoa
hoàûc dáúu gaûch dæåïi doìng :
X, Y, A
Result, List_of_members
_x23, _X, _, ...

III. Sæû kiãûn vaì luáût trong Prolog


III.1. Xáy dæûng sæû kiãûn
Vê duû III.1 : Quan hãû gia âçnh
Âãø xáy dæûng caïc sæû kiãûn trong mäüt chæång trçnh Prolog, ta láúy mäüt vê duû
vãöï. Ta xáy dæûng mäüt cáy gia hãû nhæ sau :

pam tom
parent
bob liz

ann pat tom bob

jim

(a) (b)
Hçnh III.1.Cáy gia hãû.
Måí âáöu vãö ngän ngæî Prolog 7

Trong cáy gia hãû (a), caïc nuït chè ngæåìi, coìn caïc muîi tãn chè quan hãû cha
meû cuía (parent of). Sæû kiãûn Tom laì cha meû cuía Bob âæåüc viãút thaình mäüt vë
tæì Prolog nhæ sau (chuï yï mãûnh âãö âæåüc kãút thuïc båíi mäüt dáúu cháúm) :
parent(tom, bob). % Chuï yï khäng coï dáúu caïch træåïc dáúu måí ngoàûc

ÅÍ âáy, vë tæì parent coï hai âäúi laì tom vaì bob. Ngæåìi ta coï thãø biãøu diãùn vë
tæì naìy båíi mäüt cáy nhæ trong Hçnh III.1 (b) : nuït gäúc laì tãn vë tæì, caïc nuït laï laï
caïc âäúi.
Tæì cáy gia hãû trãn âáy, coï thãø tiãúp tuûc viãút caïc vë tæì khaïc âãø nháûn âæåüc
mäüt chæång trçnh Prolog gäöm 6 vë tæì nhæ sau :
parent(pam, bob).
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).
parent(bob, pat).
parent(pat, jim).
Sau khi hãû thäúng Prolog nháûn âæåüc chæång trçnh naìy, thæûc cháút laì mäüt cå
såí dæî liãûu, ngæåìi ta coï thãø âàût ra caïc cáu hoíi liãn quan âãún quan hãû parent.
Vê duû cáu hoíi Bob coï phaíi laì cha meû cuía Pat âæåüc goî vaìo trong hãû thäúng âäúi
thoaûi Prolog (dáúu nhàõc ?-_) nhæ sau :
?- parent(bob, pat).
Sau khi tçm tháúy sæû kiãûn naìy trong chæång trçnh, Prolog traí låìi :
Yes
Ta tiãúp tuûc âàût cáu hoíi khaïc :
?- parent(liz, pat).
No
Båíi vç Prolog khäng tçm tháúy sæû kiãûn Liz laì ngæåìi meû cuía Pat trong
chæång trçnh. Tæång tæû, Prolog traí låìi No cho sæû kiãûn :
?- parent(tom, ben).
Vç tãn ben chæa âæåüc âæa vaìo trong chæång trçnh. Ta coï thãø tiãúp tuûc âàût
ra caïc cáu hoíi thuï vë khaïc. Chàóng haûn, ai laì cha (hay meû) cuía Liz ?
?- parent(X, liz).
Láön naìy, Prolog khäng traí låìi Yes hoàûc No, maì âæa ra mäüt giaï trë cuía X
laìm thoaí maîn cáu hoíi trãn âáy :
8 Láûp trçnh logic trong Prolog

X = tom
Âãø biãút âæåüc ai laì con cuía Bob, ta chè cáön viãút :
?- parent(bob, X).
Våïi cáu hoíi naìy, Prolog seî coï hai cáu traí låìi, âáöu tiãn laì :
X = ann ->;
Âãø biãút âæåüc cáu traí låìi tiãúp theo, trong háöu hãút caïc caìi âàût cuía Prolog,
NSD phaíi goî vaìo mäüt dáúu cháúm pháøy (;) sau -> (Arity Prolog) :
X = pat
Nãúu âaî hãút phæång aïn traí låìi maì váùn tiãúp tuûc yãu cáöu (;), Prolog traí låìi
No.
NSD coï thãø âàût caïc cáu hoíi täøng quaït hån, chàóng haûn : ai laì cha meû cuía
ai ? Noïi caïch khaïc, cáön tçm X vaì Y sao cho X laì cha meû cuía Y. Ta viãút nhæ
sau :
?- parent(X, Y).
Sau khi hiãøn thë cáu traí låìi âáöu tiãn, Prolog seî láön læåüt tçm kiãúm nhæîng
càûp cha meû − con thoaí maîn vaì láön læåüt hiãøn thë kãút quaí nãúu chæìng naìo NSD
coìn yãu cáöu cho âãún khi khäng coìn kãút quaí låìi giaíi naìo næîa (kãút thuïc båíi
Yes) :
X = pam
Y = bob ->;
X = tom
Y = bob ->;
X = tom
Y = liz ->;
X = bob
Y = ann ->;
X = bob
Y = pat ->;
X = pat
Y = jim
Yes
Tuyì theo caìi âàût Prolog, NSD coï thãø goî vaìo mäüt dáúu cháúm (.) hoàûc Enter
âãø cháúm dæït giæîa chæìng luäöng traí låìi.
Måí âáöu vãö ngän ngæî Prolog 9

Ta coï thãø tiãúp tuûc âæa ra nhæîng cáu hoíi phæïc taûp hån khaïc, chàóng haûn ai
laì äng (baì) cuía Jim ? Thæûc tãú, quan hãû äng − baì (grandparent) chæa âæåüc
âënh nghéa, cáön phaíi phán taïch cáu hoíi naìy thaình hai pháön så cáúp hån :
1. Ai laì cha (meû) cuía Jim ? Giaí sæí coï tãn laì Y.
2. Ai laì cha (meû) cuía Y ? Giaí sæí coï tãn laì X.

X
parent

Y grandparent

parent
jim

Hçnh III.2. Quan hãû äng baì âæåüc håüp thaình tæì hai quan hãû cha meû.

Luïc naìy, coï thãø viãút trong Prolog nhæ sau :


?- parent(Y, jim), parent(X, Y).
Prolog traí låìi :
Y = pat
X = bob
Yes
Cáu hoíi trãn âáy tæång æïng våïi cáu hoíi : tçm X vaì Y thoaí maîn :
parent(Y, jim)
vaì
parent(X, Y).
Nãúu thay âäøi thæï tæû hai thaình pháön cáu hoíi, thç nghéa lägich váùn khäng
thay âäøi vaì Prolog traí låìi cuìng kãút quaí (coï thãø thay âäøi vãö thæï tæû), nghéa laì
ta coï thãø âàût cáu hoíi nhæ sau :
?- parent(X, Y), parent(Y, jim).
X = bob
Y = âæåìng dáùn
Yes
Báy giåì ta âàût cáu hoíi ai laì chaïu cuía Tom ?
?- parent(tom, X), parent(X, Y).
X = bob
Y = ann->;
10 Láûp trçnh logic trong Prolog

X = bob
Y = pat ->;
No
Mäüt cáu hoíi khaïc coï thãø nhæ sau : Ann vaì Pat coï cuìng ngæåìi äng khäng ?
nghéa laì ta diãùn âaût thaình hai giai âoaûn :
1. Tçm X laì cha meû cuía Ann.
2. X tçm tháúy coï cuìng laì cha meû cuía Pat khäng ?
Cáu hoíi vaì traí låìi trong Prolog nhæ sau :
?- parent(X, ann), parent(X, pat).
X = bob
Trong Prolog, cáu hoíi coìn âæåüc goüi laì âêch (goal) cáön phải âæåüc thoaí maîn
(satisfy). Mäùi cáu hoíi âàût ra âäúi våïi cå såí dæî liãûu coï thãø tæång æïng våïi mäüt
hoàûc nhiãöu âêch. Chàóng haûn daîy caïc âêch :
parent(X, ann), parent(X, pat).
tæång æïng våïi cáu hoíi laì pheïp häüi (conjunction) cuía 2 mãûnh âãö :
X laì mäüt cha meû cuía Ann, vaì
X laì mäüt cha meû cuía Pat.
Nãúu cáu traí låìi laì Yes, thç coï nghéa âêch âaî âæåüc thoaí maîn, hay âaî thaình
cäng. Trong træåìng håüp ngæåüc laûi, cáu traí låìi laì No, coï nghéa âêch khäng âæåüc
thoaí maîn, hay âaî tháút baûi.
Nãúu coï nhiãöu cáu traí låìi cho mäüt cáu hoíi, Prolog seî âæa ra cáu traí låìi âáöu
tiãn vaì chåì yãu cáöu cuía NSD tiãúp tuûc.

III.2. Xáy dæûng luáût


III.2.1. Âënh nghéa luáût
Tæì chæång trçnh gia hãû trãn âáy, ta coï thãø dãù daìng bäø sung caïc thäng tin
khaïc, chàóng haûn bäø sung caïc sæû kiãûn vãö giåïi tênh (nam, næî) cuía nhæîng ngæåìi
âaî nãu tãn trong quan hãû parent nhæ sau :
woman(pam).
man(tom).
man(bob).
woman(liz).
woman(pat).
Måí âáöu vãö ngän ngæî Prolog 11
woman(ann).
man(jim).
Ta âaî âënh nghéa caïc quan hãû âån (unary) woman vaì man vç chuïng chè
liãn quan âãún mäüt âäúi tæåüng duy nháút. Coìn quan hãû parent laì nhë phán, vç
liãn quan âãún mäüt càûp âäúi tæåüng. Nhæ váûy, caïc quan hãû âån duìng âãø thiãút
láûp mäüt thuäüc tênh cuía mäüt âäúi tæåüng. Mãûnh âãö :
woman(pam).
âæåüc giaíi thêch : Pam laì næî. Tuy nhiãn, ta cuîng coï thãø sæí duûng quan hãû nhë
phán âãø âënh nghéa giåïi tênh :
sex(pam, female).
sex(tom, male).
sex(bob, male).
...
Báy giåì ta âæa vaìo mäüt quan hãû måïi child, âäúi ngæåüc våïi parent nhæ sau :
child(liz, tom).
Tæì âoï, ta âënh nghéa luáût måïi nhæ sau :
child(Y, X) :- parent(X, Y).
Luáût trãn âæåüc hiãøu laì :

Våïi moüi X vaì Y, hay Våïi moüi X vaì Y,


Y laì con cuía X nãúu nãúu X laì cha (hay meû) cuía Y thç
X laì cha (hay meû) cuía Y. Y laì con cuía X.
Coï sæû khaïc nhau cå baín giæîa sæû kiãûn vaì luáût. Mäüt sæû kiãûn, chàóng haûn :
parent(tom, liz).
laì mäüt âiãöu gç âoï luän âuïng, khäng coï âiãöu kiãûn gç raìng buäüc. Trong khi âoï,
caïc luáût liãn quan âãún caïc thuäüc tênh chè âæåüc thoaí maîn nãúu mäüt säú âiãöu
kiãûn naìo âoï âæåüc thoaí maîn. Mäùi luáût bao gäöm hai pháön:

• pháön bãn phaíi (RHS: Right Hand Side) chè âiãöu kiãûn, coìn âæåüc goüi laì
thán (body) cuía luáût, vaì

• pháön bãn traïi (LH: Left Hand Side S) chè kãút luáûn, coìn âæåüc goüi laì âáöu
(head) cuía luáût.
12 Láûp trçnh logic trong Prolog

Nãúu âiãöu kiãûn parent(X, Y) laì âuïng, thç child(Y, X) cuîng âuïng vaì laì háûu
quaí lägich cuía pheïp suy luáûn (inference).

child(Y, X) :- parent(X, Y).

âáöu thán

Cáu hoíi sau âáy giaíi thêch caïch Prolog sæí duûng caïc luáût : Liz coï phaíi laì
con cuía Tom khäng ?
?- child(liz, tom)
Thæûc tãú, trong chæång trçnh khäng coï sæû kiãûn naìo liãn quan âãún con, maì
ta phaíi tçm caïch aïp duûng caïc luáût. Luáût trãn âáy åí daûng täøng quaït våïi caïc âäúi
tæåüng X vaì Y báút kyì, maì ta laûi cáön caïc âäúi tæåüng cuû thãø liz vaì tom.
Ta cáön sæí duûng pheïp thãú (substitution) bàòng caïch gaïn giaï trë liz cho biãún
Y vaì tom cho X. Ngæåìi ta noïi ràòng caïc biãún X vaì Y âaî âæåüc raìng buäüc
(bound) :
X = tom
vaì
Y = liz
Luïc naìy, pháön âiãöu kiãûn coï giaï trë parent(tom, liz) vaì tråí thaình âêch con
(sub-goal) âãø Prolog thay thãú cho âêch child(liz, tom). Tuy nhiãn, âêch naìy
thoaí maîn vaì coï giaï trë Yes vç chênh laì sæû kiãûn âaî thiãút láûp trong chæång
trçnh.
Sau âáy, ta tiãúp tuûc bäø sung caïc quan hãû måïi. Quan hãû meû mother âæåüc
âënh nghéa nhæ sau (chuï yï dáúu pháøy chè pheïp häüi hay pheïp vaì lägich) :
mother(X, Y) :- parent(X, Y), woman(X).
âæåüc hiãøu laì :
Våïi moüi X vaì Y, X laì meû cuía Y nãúu
X laì cha (hay meû) cuía Y vaì X laì næî.
Âäö thë sau âáy minh hoaû viãûc âënh nghéa caïc quan hãû child, mother vaì
grandparent sæí duûng mäüt quan hãû khaïc :
Trong âäö thë, ngæåìi ta quy æåïc ràòng : caïc nuït tæång æïng våïi caïc âäúi tæåüng
(laì caïc âäúi cuía mäüt quan hãû). Caïc cung näúi caïc nuït tæång æïng våïi caïc quan hãû
Måí âáöu vãö ngän ngæî Prolog 13

nhë phán, âæåüc âënh hæåïng tæì âäúi thæï nháút âãún âäúi thæï hai cuía quan hãû.
Mäüt quan hãû âån âæåüc biãøu diãùn båíi tãn quan hãû tæång æïng våïi nhaîn cuía
âäúi tæåüng âoï. Caïc quan hãû cáön âënh nghéa âæåüc biãøu diãùn båíi caïc cung coï neït
âæït. Mäùi âäö thë âæåüc giaíi thêch nhæ sau : nãúu caïc quan hãû âæåüc chè båíi caïc
cung coï neït liãön âæåüc thoaí maîn, thç quan hãû biãøu diãùn båíi cung coï neït âæït
cuîng âæåüc thoaí maîn.
woman
X X X
parent child parent mother parent

Y Y Y grandparent

parent
Z

Hçnh III.3. Âënh nghéa quan hãû con, meû vaì äng baì sæí duûng mäüt quan hãû khaïc.

Nhæ váûy, quan hãû äng−baì grandparent âæåüc viãút nhæ sau :
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
Âãø thuáûn tiãûn cho viãûc âoüc chæång trçnh Prolog, ta coï thãø viãút mäüt luáût
trãn nhiãöu doìng, doìng âáöu tiãn laì pháön âáöu cuía luáût, caïc doìng tiãúp theo laì
pháön thán cuía luáût, mäùi âêch trãn mäüt doìng phán biãût. Báy giåì quan hãû
grandparent âæåüc viãút laûi nhæ sau :
grandparent(X, Z) :-
parent(X, Y),
parent(Y, Z).
Ta tiãúp tuûc âënh nghéa quan hãû chë em gaïi sister nhæ sau :
sister(X, Y) :- Våïi moüi X vaì Y, X laì mäüt chë (em) gaïi cuía Y nãúu
parent(Z, X), (1) X vaì Y coï cuìng cha (cuìng meû), vaì
parent(Z, Y),
woman(X). (2) X laì næî .

Z
parent parent

woman X Y
sister
Hçnh III.4. Âënh nghéa quan hãû chë (em) gaïi.
14 Láûp trçnh logic trong Prolog

Chuï yï caïch giaíi thêch âiãöu kiãûn X vaì Y coï cuìng cha meû : mäüt Z naìo âoï
phaíi laì mäüt cha meû cuía X, vaì cuîng Z âoï phaíi laì mäüt cha meû cuía Y.
Hay noïi mäüt caïch khaïc laì : Z1 laì mäüt cha meû cuía X, Z2 laì mäüt cha meû cuía
Y, vaì Z1 âäöng nháút våïi Z2.
An laì næî, Ann vaì Pat cuìng cha meû nãn Ann laì chë em gaïi cuía Pat, ta coï :
?- sister(ann, pat).
Yes
Ta cuîng coï thãø hoíi ai laì chë em gaïi cuía Pat nhæ sau :
?- sister(X, pat).
Prolog seî láön læåüt âæa ra hai cáu traí låìi :
X = ann ->;
X = pat ->.
Yes
Váûy thç Pat laûi laì em gaïi cuía chênh mçnh ?! Âiãöu naìy sai vç ta chæa giaíi
thêch roî trong âënh nghéa chë em gaïi. Nãúu chè dæûa vaìo âënh nghéa trãn âáy
thç cáu traí låìi cuía Prolog laì hoaìn toaìn håüp lyï. Prolog suy luáûn ràòng X vaì Y coï
thãø âäöng nháút våïi nhau, mäùi ngæåìi âaìn baì coï cuìng cha meû seî laì em gaïi cuía
chênh mçnh. Ta cáön sæía laûi âënh nghéa bàòng caïch thãm vaìo âiãöu kiãûn X vaì Y
khaïc nhau. Nhæ seî tháúy sau naìy, Prolog coï nhiãöu caïch âãø giaíi quyãút, tuy
nhiãn luïc naìy ta giaí sæí ràòng quan hãû :
different(X, Y)
âaî âæåüc Prolog nháûn biãút vaì âæåüc thoaí maîn nãúu vaì chè nãúu X vaì Y khäng
bàòng nhau. Âënh nghéa chë (em) gaïi måïi nhæ sau :
sister(X, Y) :-
parent(Z, X),
parent(Z, Y),
woman(X).
different(X, Y).
Vê duû III.2 : Ta láúy laûi vê duû cäø âiãøn sæí duûng hai tiãn âãö sau âáy :
Táút caí moüi ngæåìi âãöu chãút.
Socrate laì mäüt ngæåìi.
Ta viãút trong Prolog nhæ sau :
mortal(X) :- man(X).
man(socrate).
Måí âáöu vãö ngän ngæî Prolog 15

Mäüt âënh lyï âæåüc suy luáûn mäüt caïch lägich tæì hai tiãn âãö naìy laì Socrate
phaíi chãút. Ta âàût caïc cáu hoíi nhæ sau :
?- mortal(socrate).
Yes
Vê duû III.3 :
Âãø chè Paul cuîng laì ngæåìi, coìn Bonzo laì con váût, ta viãút caïc sæû kiãûn :
man(paul).
animal(bonzo).
Con ngæåìi coï thãø noïi vaì khäng phaíi laì loaûi váût, ta viãút luáût :
speak(X) :- man(X), not(animal(bonzo)).
Ta âàût caïc cáu hoíi nhæ sau :
?- speak(bonzo).
No
?- speak(paul).
Yes
Vê duû III.4 :
Ta âaî xáy dæûng caïc sæû kiãûn vaì caïc luáût coï daûng vë tæì chæïa tham âäúi, sau
âáy, ta láúy mäüt vê duû khaïc vãö sæû kiãûn vaì luáût khäng chæïa tham âäúi :
'It is sunny'.
'It is summer'.
'It is hot' :-
'It is summer', 'It is sunny'.
'It is cold' :-
'It is winter', 'It is snowing'.
Tæì chæång trçnh trãn, ta coï thãø âàût cáu hoíi :
?- 'It is hot'.
Yes
Cáu traí låìi 'It is hot' laì âuïng vç âaî coï caïc sæû kiãûn 'It is sunny' vaì 'It is
summer' trong chæång trçnh. Coìn cáu hoíi « ?- 'It is cold.' » coï cáu traí låìi sai.

III.2.2. Âënh nghéa luáût âãû quy


Báy giåì ta tiãúp tuûc thãm mäüt quan hãû måïi vaìo chæång trçnh. Quan hãû naìy
chè sæí duûng quan hãû parent, vaì chè coï hai luáût. Luáût thæï nháút âënh nghéa caïc
täø tiãn træûc tiãúp, luáût thæï hai âënh nghéa caïc täø tiãn giaïn tiãúp.
16 Láûp trçnh logic trong Prolog

Ta noïi ràòng X laì mäüt täø tiãn giaïn tiãúp cuía Z nãúu täön taûi mäüt liãn hãû cha
meû (äng baì) giæîa X vaì Z :

X X

parent ancestor parent

Z
(a) parent ancestor

parent
Y
(b)
Hçnh III.5. Quan hãû täø tiãn : (a) X laì täø tiãn træûc tiãúp cuía Z,
(b) X laì täø tiãn giaïn tiãúp cuía Z.
Trong cáy gia hãû åí Hçnh III.1, Tom laì täø tiãn træûc tiãúp cuía Liz, vaì täø tiãn
giaïn tiãúp cuía Pat. Ta âënh nghéa luáût 1 (täø tiãn træûc tiãúp) nhæ sau :
ancestor(X, Z) :- Våïi moüi X vaì Z,
parent(X, Z). X laì mäüt täø tiãn cuía Z nãúu
X laì cha meû cuía Z .
Âënh nghéa luáût 2 (täø tiãn giaïn tiãúp) phæïc taûp hån, trçnh Prolog tråí nãn
daìi doìng hån, mäùi khi caìng måí räüng mæïc täø tiãn háûu duãû nhæ chè ra trong
Hçnh III.6. Kãø caí luáût 1, ta coï quan hãû täø tiãn âæåüc âënh nghéa nhæ sau :
ancestor(X, Z) :- % luáût 1 âënh nghéa täø tiãn træûc tiãúp
parent(X, Z).
ancestor(X, Z) :- % luáût 2 : täø tiãn giaïn tiãúp laì äng baì (tam âaûi)
parent(X, Y),
parent(Y, Z).
ancestor(X, Z) :- % täø tiãn giaïn tiãúp laì cäú äng cäú baì (tæï âaûi)
parent(X, Y1),
parent(Y1, Y2),
parent(Y2, Z).
ancestor(X, Z) :- % nguî âaûi âäöng âæåìng
parent(X, Y1),
parent(Y1, Y2),
parent(Y2, Y3),
parent(Y3, Z).
...
Måí âáöu vãö ngän ngæî Prolog 17

X X X
parent parent

Y ancestor Y1 Y1

parent parent ancestor


Y2 ancestor
Z Y2
parent
Y3
Z
Z

Hçnh III.6. Caïc càûp täø tiãn háûu duãû giaïn tiãúp åí caïc mæïc khaïc nhau.

Tuy nhiãn, täön taûi mäüt caïch âënh nghéa täø tiãn giaïn tiãúp åí mæïc báút kyì nhåì
pheïp âãû quy (recursive) nhæ sau :
ancestor(X, Z) :- Våïi moüi X vaì Z,
parent(X, Z). X laì mäüt täø tiãn cuía Z nãúu
ancestor(X, Z) :- täön taûi Y sao cho
parent(X, Y), (1) X laì cha meû cuía Y vaì
ancestor(Y, Z).
(2) Y laì mäüt täø tiãn cuía Z.

ancestor
parent

X Y ... Z

ancestor

Hçnh III.7.Daûng âãû quy cuía quan hãû täø tiãn (âæåüc quay ngang cho thuáûn tiãûn).

?- ancestor(pam, X).
X = jim ->;
X = ann ->;
X = pat ->;
X = bob
Yes
Trong Prolog, háöu hãút caïc chæång trçnh phæïc taûp âãöu sæí duûng âãû quy, âãû
quy laì mäüt khaí nàng maûnh cuía Prolog.
18 Láûp trçnh logic trong Prolog

Cho âãún luïc naìy, ta âaî âënh nghéa nhiãöu quan hãû khaïc nhau (parent,
woman, man, grandparent, child, sister, mother vaì ancestor). Ta tháúy mäùi quan
hãû chè tæång æïng våïi mäüt mãûnh âãö, tuy nhiãn, quan hãû ancestor laûi coï hai
mãûnh âãö.
Ngæåìi ta noïi ràòng nhæîng mãûnh âãö naìy liãn quan (concern) âãún quan hãû
ancestor. Trong træåìng håüp táút caí caïc mãûnh âãö âãöu liãn quan âãún mäüt quan
hãû, ngæåìi ta nháûn âæåüc mäüt thuí tuûc (procedure).

III.2.3. Sæí duûng biãún trong Prolog


Khi tênh toaïn, NSD coï thãø thay thãú mäüt biãún trong mäüt mãûnh âãö båíi mäüt
âäúi tæåüng khaïc. Luïc naìy ta noïi biãún âaî bë raìng buäüc.
Caïc biãún xuáút hiãûn trong mäüt mãûnh âãö âæåüc goüi laì biãún tæû do. Ngæåìi ta
giaí thiãút ràòng caïc biãún laì âæåüc læåüng tæí toaìn thãø vaì âæåüc âoüc laì «våïi moüi».
Tuy hiãn coï nhiãöu caïch giaíi thêch khaïc nhau trong træåìng håüp caïc biãún chè
xuáút hiãûn trong pháön bãn phaíi cuía luáût. Vê duû :
haveachil(X) :- parent(X, Y).
coï thãø âæåüc âoüc nhæ sau :
(a) Våïi moüi X vaì Y,
nãúu X laì cha (hay meû) cuía Y thç X coï mäüt ngæåìi con.
(b) Våïi moüi X,
X coï mäüt ngæåìi con nãúu täön taûi mäüt Y sao cho X laì cha (hay meû)
cuía Y.
Khi mäüt biãún chè xuáút hiãûn mäüt láön trong mäüt mãûnh âãö thç khäng cáön âàût
tãn cho noï. Prolog cho pheïp sæí duûng caïc biãún nàûc danh (anonymous variable)
laì caïc biãún coï tãn chè laì mäüt dáúu gaûch dæåïi doìng _. Ta xeït vê duû sau :
have_a_child(X) :- parent(X, Y).
Luáût trãn nãu lãn ràòng våïi moüi X, X coï mäüt con nãúu X laì cha cuía mäüt Y
naìo âoï. Ta tháúy âêch have_a_child khäng phuû thuäüc gç vaìo tãn cuía con, vç váûy
coï thãø sæí duûng biãún nàûc danh nhæ sau :
have_a_child(X) :- parent(X, _).
Mäùi vë trê xuáút hiãûn dáúu gaûch dæåïi doìng _ trong mäüt mãûnh âãö tæång æïng
våïi mäüt biãún nàûc danh måïi. Vê duû nãúu ta muäún thãø hiãûn täön taûi mäüt ngæåìi
Måí âáöu vãö ngän ngæî Prolog 19

naìo âoï coï con nãúu täön taûi hai âäúi tæåüng sao cho mäüt âäúi tæåüng naìy laì cha cuía
âäúi tæåüng kia, thç ta coï thãø viãút :
someone_has_a_child :- parent(_, _).
Mãûnh âãö naìy tæång âæång våïi :
someone_has_a_child :- parent(X, Y).
nhæng hoaìn toaìn khaïc våïi :
someone_has_a_child :- parent(X, X).
Nãúu biãún nàûc danh xuáút hiãûn trong mäüt cáu hoíi, thç Prolog seî khäng hiãøn
thë giaï trë cuía biãún naìy trong kãút quaí traí vãö. Nãúu ta muäún tçm kiãúm nhæîng
ngæåìi coï con, maì khäng quan tám âãún tãn con laì gç, thç chè cáön viãút :
?- parent(X, _).
hoàûc tçm kiãúm nhæîng ngæåìi con, maì khäng quan tám âãún cha meû laì gç :
?- parent(_ , X).
Táöm væûc tæì væûng (lexical scope) cuía caïc biãún trong mäüt mãûnh âãö khäng
væåüt ra khoíi mãûnh âãö âoï. Coï nghéa laì nãúu, vê duû, biãún X15 xuáút hiãûn trong
hai mãûnh âãö khaïc nhau, thç seî tæång æïng våïi hai biãún phán biãût nhau. Trong
cuìng mäüt mãûnh âãö, X15 luän luän chè biãøu diãùn mäüt biãún. Tuy nhiãn âäúi våïi
caïc hàòng thç tçnh huäúng laûi khaïc : mäüt nguyãn tæí thãø hiãûn mäüt âäúi tæåüng
trong táút caí caïc mãûnh âãö, coï nghéa laì trong táút caí chæång trçnh.

IV. Kiãøu dæî liãûu cáúu truïc cuía Prolog


IV.1. Âënh nghéa kiãøu cáúu truïc cuía Prolog
Kiãøu dæî liãûu coï cáúu truïc, tæång tæû cáúu truïc baín ghi, laì âäúi tæåüng coï nhiãöu
thaình pháön, mäùi thaình pháön laûi coï thãø laì mäüt cáúu truïc. Prolog xem mäùi
thaình pháön nhæ laì mäüt âäúi tæåüng khi xæí lyï caïc cáúu truïc. Âãø täø håüp caïc thaình
pháön thaình mäüt âäúi tæåüng duy nháút, Prolog sæí duûng caïc haìm tæí.
Vê duû IV.1 :
Cáúu truïc gäöm caïc thaình pháön ngaìy thaïng nàm taûo ra haìm tæí date.
Ngaìy 2/9/1952 seî âæåüc viãút nhæ sau : date(2, september, 1952)
Moüi thaình pháön trong haìm tæí date âãöu laì hàòng (hai säú nguyãn vaì mäüt
nguyãn tæí). Tuy nhiãn ta coï thãø thay thãú mäùi thaình pháön bàòng mäüt biãún hay
20 Láûp trçnh logic trong Prolog

mäüt cáúu truïc khaïc. Chàóng haûn ta coï thãø thay thãú thaình pháön thæï nháút bàòng
biãún Day (chuï yï tãn biãún bàõt âáöu båíi chæî hoa) thãø hiãûn báút kyì ngaìy naìo cuía
thaïng 9 :
date(Day, may, 1890)
Chuï yï ràòng Day laì mäüt biãún, coï thãø âæåüc raìng buäüc khi xæí lyï sau âoï.
Trong Prolog, vãö màût cuï phaïp, caïc âäúi tæåüng laì nhæîng haûng. Trong vê duû
trãn, may vaì date(Day, september, 2003) âãöu laì nhæîng haûng.
Moüi âäúi tæåüng coï cáúu truïc âãöu coï thãø âæåüc biãøu diãùn hçnh hoüc dæåïi daûng
cáy (tree), våïi haìm tæí laì gäúc, coìn caïc thaình pháön tham âäúi laì caïc nhaïnh cuía
cáy. Nãúu mäüt trong caïc thaình pháön laì mäüt cáúu truïc, thç thaình pháön âoï taûo
thaình mäüt cáy con cuía cáy ban âáöu. Hai haûng laì coï cuìng cáúu truïc nãúu coï
cuìng cáy biãøu diãùn vaì coï cuìng thaình pháön (pattern of variables). Haìm tæí cuía
gäúc âæåüc goüi laì haìm tæí chênh cuía haûng.
caïc tham âäúi
date
date( Day, september, 2003 )

haìm tæí biãún kyï hiãûu säú


02 september 2003
(a) (b)

Hçnh IV.1. Ngaìy thaïng laì mäüt âäúi tæåüng coï cáúu truïc :
(a) biãøu diãùn daûng cáy cuía cáúu truïc ; (b) giaíi thêch caïch viãút trong Prolog
Vê duû IV.2 :
Cáúu truïc (âån giaín) cuía mäüt cuäún saïch gäöm ba thaình pháön tiãu âãö vaì taïc
giaí cuîng laì caïc cáúu truïc (con), nàm xuáút baín laì mäüt biãún :
book(title(Name), author(Author), Year)
Vê duû IV.3 :
Xáy dæûng caïc âäúi tæåüng hçnh hoüc âån giaín trong khäng gian hai chiãöu.
Mäùi âiãøm âæåüc xaïc âënh båíi hai toaû âäü, hai âiãøm taûo thaình mäüt âæåìng thàóng,
ba âiãøm taûo thaình mäüt tam giaïc. Ta xáy dæûng caïc haìm tæí sau âáy :
point biãøu diãùn âiãøm,
seg biãøu diãùn mäüt âoaûn thàóng (segment),
triangle biãøu diãùn mäüt tam giaïc.
Måí âáöu vãö ngän ngæî Prolog 21

5 ⎯
(6, 4)
4 ⎯
P2 = (2, 3)
3 ⎯

2 ⎯ (4, 2)

1 ⎯ (7, 1)
P1 = (1, 1)
| | | | | | | |
1 2 3 4 5 6 7 8

Hçnh IV.2. Mäüt säú âäúi tæåüng hçnh hoüc âån giaín.

Tæì âoï, caïc âäúi tæåüng trãn Hçnh IV.2 âæåüc biãøu diãùn båíi caïc haûng nhæ sau :
P1 = point(1, 1)
P2 = point(2, 3)
S = seg(P1, P2) = seg(point(1, 1), point(2, 3))
T = triangle(point(4, 2), point(6, 4), point(7, 1))

Nãúu trong cuìng mäüt chæång trçnh, ta coï caïc âiãøm trong mäüt khäng gian
ba chiãöu, ta coï thãø âënh nghéa mäüt haìm tæí måïi laì point3 nhæ sau :
point3(X, Y, Z)
Prolog cho pheïp sæí duûng cuìng tãn hai cáúu truïc khaïc nhau. Vê duû :
point(X1, Y1) vaì point(X, Y, Z)
laì hai cáúu truïc khaïc nhau.
Trong cuìng mäüt chæång trçnh, nãúu mäüt tãn âoïng hai vai troì khaïc nhau,
nhæ træåìng håüp point åí trãn, thç Prolog seî càn cæï vaìo säú læåüng âäúi säú âãø
phán biãût. Cuìng mäüt tãn naìy seî tæång æïng våïi hai haìm tæí, mäüt haìm tæí coï
hai âäúi säú vaì mäüt haìm tæí coï ba âäúi säú. Nhæ váûy, mäüt haìm tæí âæåüc âënh
nghéa båíi hai yãúu täú :
(1) Tãn haìm tæí coï cuï phaïp laì cuï phaïp cuía caïc nguyãn tæí.
(2) Kêch thæåïc cuía haìm tæí laì säú caïc âäúi säú cuía noï.
Biãøu diãùn daûng cáy cuía caïc âäúi tæåüng âiãøm, âoaûn thàóng vaì tam giaïc trãn
âáy âæåüc cho trong Hçnh IV.3. Nhæ âaî trçnh baìy, moüi âäúi tæåüng cáúu truïc cuía
Prolog âãöu âæåüc biãøu diãùn dæåïi daûng cáy, xuáút hiãûn trong mäüt chæång trçnh
dæåïi daûng caïc haûng.
22 Láûp trçnh logic trong Prolog

P1 = point P1 = seg T = triangle

point point point point point


1 1

1 1 2 3
4 2 6 4 7 1

Hçnh IV.3. Biãøu diãùn daûng cáy cuía caïc âäúi tæåüng.

Vê duû biãøu thæïc säú hoüc :


(a + b) * (c − 5)
coï daûng cáy, coï thãø viãút dæåïi daûng biãøu thæïc tiãön täú gäöm caïc haìm tæí *, + vaì − :
*(+(a, b), −(c, 5))
*

+ -

a b c 5

Hçnh IV.4. Cáúu truïc cáy cuía biãøu thæïc (a + b) * (c − 5)

IV.2. So saïnh vaì håüp nháút caïc haûng


Ta væìa xeït caïch biãøu diãùn caïc cáúu truïc dæî liãûu sæí duûng haûng. Báy giåì ta
seî xeït pheïp toaïn quan troüng nháút liãn quan âãún caïc haûng laì pheïp so khåïp
(matching), thæûc cháút laì pheïp so saïnh (comparison operators) trãn caïc haûng
vaì caïc vë tæì.
Trong Prolog, viãûc so khåïp tæång æïng våïi viãûc håüp nháút (unification) âæåüc
nghiãn cæïu trong lyï thuyãút lägich. Cho hai haûng, ngæåìi ta noïi ràòng chuïng laì
håüp nháút âæåüc våïi nhau, nãúu :
(1) chuïng laì giäúng hãût nhau, hoàûc
(2) caïc biãún xuáút hiãûn trong hai haûng coï thãø âæåüc raìng buäüc sao cho caïc
haûng cuía mäùi âäúi tæåüng tråí nãn giäúng hãût nhau.
Thæï tæû chuáøn (standard order) trãn caïc haûng âæåüc âënh nghéa nhæ sau :
1. Biãún < Nguyãn tæí < Chuäùi < Säú < Haûng
2. Biãún cuî < Biãún måïi
3. Nguyãn tæí âæåüc so saïnh theo thæï tæû ABC (alphabetically).
Måí âáöu vãö ngän ngæî Prolog 23

4. Chuäùi âæåüc so saïnh theo thæï tæû ABC.


5. Säú âæåüc so saïnh theo giaï trë (by value). Säú nguyãn vaì säú thæûc âæåüc xæí lyï
nhæ nhau (treated identically).
6. Caïc haûng phæïc håüp (compound terms) âæåüc so saïnh báûc hay säú læåüng
tham âäúi (arity) træåïc, sau âoï so saïnh tãn haìm tæí (functor-name) theo
thæï tæû ABC vaì cuäúi cuìng so saïnh mäüt caïch âãû quy (recursively) láön læåüt
caïc tham âäúi tæì traïi qua phaíi (leftmost argument first).
Vê duû hai haûng date(D, M, 1890) vaì date(D1, May, Y1) laì coï thãø våïi nhau
nhåì raìng buäüc sau :
• D âæåüc raìng buäüc våïi D1
• M âæåüc raìng buäüc våïi May
• Y1âæåüc raìng buäüc våïi 1890
Trong Prolog, ta coï thãø viãút :
D = D1
M = May
Y1 = 1890

Tuy nhiãn, ta khäng thãø raìng buäüc hai haûng date(D, M, 1890) vaì date(D1,
May, 2000), hay date(X, Y, Z) vaì point(X, Y, Z).
Cáúu truïc book(title(Name), author(Author)) âæåüc so khåïp våïi :
book(title(lord_of_the_rings), author(tolkien))
nhåì pheïp thãú :
Name = lord_of_the_rings
Author = tolkien
Thuáût toaïn håüp nháút Herbrand so khåïp hai haûng S vaì T :
(1) Nãúu S vaì T laì caïc hàòng, thç S vaì T chè coï thãø khåïp nhau nãúu vaì chè
nãúu chuïng coï cuìng giaï trë (chè laì mäüt âäúi tæåüng).
(2) Nãúu S laì mäüt biãún, T laì mäüt âäúi tæåüng naìo âoï báút kyì, thç S vaì T khåïp
nhau, våïi S âæåüc raìng buäüc våïi T. Tæång tæû, nãúu T laì mäüt biãún, thç T
âæåüc raìng buäüc våïi S.
(3) Nãúu S vaì T laì caïc cáúu truïc, thç S vaì T khåïp nhau nãúu vaì chè nãúu :
(a) S vaì T coï cuìng mäüt haìm tæí chênh, vaì
24 Láûp trçnh logic trong Prolog

(b) táút caí caïc thaình pháön laì khåïp nhau tæìng âäi mäüt.
Nhæ váûy, sæû raìng buäüc âæåüc xaïc âënh båíi sæû raìng buäüc cuía caïc thaình
pháön.
Ta coï thãø quan saït luáût thæï ba åí caïch biãøu diãùn caïc haûng dæåïi daûng cáy
trong Hçnh IV.5 dæåïi âáy. Quaï trçnh so khåïp âæåüc bàõt âáöu tæì gäúc (haìm tæí
chênh). Nãúu hai haìm tæí laì giäúng nhau, thç quaï trçnh seî âæåüc tiãúp tuûc våïi tæìng
càûp tham âäúi cuía chuïng. Moüi quaï trçnh so khåïp âæåüc xem nhæ mäüt daîy caïc
pheïp tênh âån giaín hån nhæ sau :
triangle = triangle
point(1, 1) = X
A = point(4, Y)
point(2, 3) = point(2, Z)
Moüi quaï trçnh so khåïp laì têch cæûc (positive), nãúu táút caí caïc quaï trçnh so
khåïp bäø tråü laì têch cæûc.
triangle

point A point

1 1 2 3
triangle

X point point

4 Y 2 Z

Hçnh IV.5. Kãút quaí so khåïp :


triangle(point(1, 1), A, point(2, 3)))= triangle(X, point(4, Y), point(2, Z))).

Sæû raìng buäüc nháûn âæåüc nhæ sau :


X = point(1, 1)
A = point(4, Y)
Z=3
Sau âáy laì mäüt vê duû minh hoaû sæí duûng kyî thuáût so khåïp âãø nháûn biãút
mäüt âoaûn thàóng âaî cho laì nàòm ngang hay thàóng âæïng.
Måí âáöu vãö ngän ngæî Prolog 25

Mäüt âoaûn thàóng laì thàóng âæïng nãúu hoaình âäü (abscissa) cuía hai muït laì
bàòng nhau, tæång tæû, laì nàòm ngang nãúu tung âäü (ordinate) cuía hai muït laì
bàòng nhau.
Ta sæí duûng quan hãû âån phán âãø biãøu diãùn caïc tênh cháút naìy nhæ sau :
vertical(seg(point(X, Y), point(X, Y1))).
horizontal(seg(point(X, Y), point(X1, Y))).
Ta coï :
?- vertical(seg(point(1, 1), point(1, 2))).
Yes
?- vertical(seg(point(1, 1), point(2, Y))).
No
?- horizontal(seg(point(1, 1), point(2, Y))).
Y=1
Yes

point(X, Y1)
point(X, Y)
point(X1, Y)

point(X, Y)

Hçnh IV.6. Minh hoaû caïc âoaûn thàóng nàòm ngang vaì thàóng âæïng.

Våïi cáu hoíi thæï nháút, Prolog traí låìi Yes vç caïc sæû kiãûn âæåüc so khåïp âuïng.
Våïi cáu hoíi thæï hai, vç khäng coï sæû kiãûn naìo âæåüc so khåïp nãn Prolog traí låìi
No. Våïi cáu hoíi thæï ba, Prolog cho Y giaï trë 1 âãø âæåüc so khåïp âuïng.
Ta coï thãø âàût mäüt cáu hoíi täøng quaït hån nhæ sau : Cho biãút nhæîng âoaûn
thàóng thàóng âæïng coï mäüt muït cho træåïc laì (2, 3) ?
?- vertical(seg(point(2, 3), P)).
P = point(2, _0104)
Yes
Cáu traí låìi coï nghéa laì moüi âæåìng thàóng coï phæång trçnh X = 2 laì thàóng
âæïng. Chuï yï ràòng åí âáy, ta khäng nháûn âæåüc tãn biãún nhæ mong muäún (laì
Y), maì tuyì theo phiãn baín caìi âàût cuû thãø, Prolog seî taûo ra mäüt tãn biãún khi
thæûc hiãûn chæång trçnh, _0104 trong vê duû trãn, nhàòm traïnh âàût laûi tãn biãún
cuía NSD våïi hai lyï do nhæ sau. Thæï nháút, cuìng mäüt tãn biãún nhæng xuáút
26 Láûp trçnh logic trong Prolog

hiãûn trong caïc mãûnh âãö khaïc nhau thç seî biãøu diãùn nhæîng biãún khaïc nhau.
Thæï hai, do khi aïp duûng liãn tiãúp cuìng mäüt mãûnh âãö, chênh baín «copy» âæåüc
sæí duûng våïi mäüt bäü biãún khaïc.
Báy giåì ta âàût tiãúp mäüt cáu hoíi thuï vë nhæ sau : Coï täön taûi mäüt âoaûn
thàóng væìa thàóng âæïng væìa nàòm ngang hay khäng ?
?- vertical(S), horizontal(S).
S = seg(point(_00E8, _00EC), point(_00E8, _00EC))
Yes
Cáu traí låìi coï nghéa laì moüi âoaûn thàóng khi suy biãún thaình mäüt âiãøm thç
væìa thàóng âæïng, laûi væìa nàòm ngang. Ta tháúy ràòng kãút quaí nháûn âæåüc laì nhåì
so khåïp. ÅÍ âáy, caïc tãn biãún _00E8 vaì _00EC, tæång æïng våïi X vaì Y, âaî âæåüc
taûo ra båíi Prolog.
Sau âáy laì mäüt vê duû khaïc minh hoaû hai cáúu truïc âæåüc säú khåïp våïi nhau.
student

jean X address

maljuin caen

student

jean info Y

Hçnh IV.7. Kãút quaí so khåïp :


student( jean, X, address(maljuin, caen) ) = student( jean,info, Y ).
Måí âáöu vãö ngän ngæî Prolog 27

Toïm tàõt chæång 1


Chæång 1 âaî trçnh baìy nhæîng yãúu täú så cáúp cuía Prolog, ráút gáön guîi våïi
lägich hçnh thæïc. Nhæîng âiãøm quan troüng maì ta coï âæåüc laì :
• Nhæîng âäúi tæåüng så cáúp cuía Prolog laì nguyãn tæí, biãún vaì säú. Caïc âäúi
tæåüng coï cáúu truïc, hay cáúu truïc, duìng âãø biãøu diãùn caïc âäúi tæåüng coï nhiãöu
thaình pháön.
• Caïc haìm tæí duìng âãø xáy dæûng caïc cáúu truïc. Mäùi haìm tæí âæåüc âënh nghéa
båíi tãn vaì thæï nguyãn (dimension).
• Kiãøu cuía mäüt âäúi tæåüng âæåüc âënh nghéa hoaìn toaìn nhåì vaìo sæû xuáút hiãûn
vãö màût cuï phaïp cuía noï.
• Táöm væûc tæì væûng (lexical scope) cuía mäüt biãún laì duy nháút mãûnh âãö maì
biãún xuáút hiãûn. Cuìng mäüt tãn biãún xuáút hiãûn trong hai mãûnh âãö seî tæång
æïng våïi hai biãún khaïc nhau.
• Caïc cáúu truïc âæåüc biãøu diãùn ráút âån giaín båíi caïc cáy. Prolog âæåüc xem
nhæ laì mäüt ngän ngæî xæí lyï cáy.
• Pheïp toaïn so khåïp so saïnh hai pháön tæí (term) vaì tçm caïch âäöng nháút
chuïng båíi caïc raìng buäüc cuía chuïng.
• Nãúu so khåïp thaình cäng, Prolog âæa ra raìng buäüc caïc biãún täøng quaït
nháút.
• Nhæîng khaïi niãûm âaî trçnh baìy laì :
mãûnh âãö, sæû kiãûn, luáût, cáu hoíi,
nguyãn tæí, biãún, biãún raìng buäüc,
pháön âáöu vaì pháön thán cuía cuía mäüt mãûnh âãö,
luáût âãû quy, âënh nghéa âãû quy,
âêch,
âäúi tæåüng : nguyãn tæí, säú, biãún, haûng
cáúu truïc
haìm tæí, thæï nguyãn cuía mäüt haìm tæí
haìm tæí chênh cuía mäüt haûng
so khåïp caïc haûng
raìng buäüc täøng quaït nháút
28 Láûp trçnh logic trong Prolog

Baìi táûp chæång 1


1. Tçm caïc âäúi tæåüng Prolog âuïng âàõn vãö màût cuï phaïp trong säú âäúi tæåüng
âæåüc cho dæåïi âáy. Cho biãút kiãøu cuía chuïng (laì nguyãn tæí, säú, biãún hay
cáúu truïc) ?
a) Diane
b) diane
c) ‘Diane’
d) _diane
e) ‘Diane va en vacances’
f) va( diane, vacances )
g) 45
h) 5(X , Y)
i) +( nord , owest )
j) three( small( cats ) )
2. Haîy tçm mäüt biãøu diãùn daûng âäúi tæåüng cáúu truïc cho caïc hçnh chæî nháût,
hçnh vuäng vaì hçnh troìn. Xem hçnh 2.4 âãø coï caïch giaíi quyãút. Sæí duûng caïc
biãùu diãùn cho caïc hçnh cuû thãø âãø minh hoüa.
3. Chæång trçnh sau noïi ràòng hai ngæåìi laì coï quan hãû doìng hoü våïi nhau nãúu :
a) mäüt laì täø tiãn cuía ngæåìi kia, hoàûc,
b) hai ngæåìi coï chung täø tiãn, hoàûc,
c) hai ngæåìi coï cuìng con chaïu.
kindred( X, Y) :-
ancestor(X , Y).
kindred(X , Y) :-
ancestor(X , Y).
kindred(X , Y) :- % X vaì Y coï cuìng täø tiãn
ancestor( Z, X),
ancestor(Z , Y).
kindred(X , Y) :- % X vaì Y coï cuìng con chaïu
ancestor (X , Z),
ancestor(Y , Z).
Haîy cho biãút coï thãø laìm ngàõn chæång trçnh trãn bàòng caïch sæí duûng
dáúu cháúm pháøy ; âæåüc khäng ?
4. Haîy tçm hiãøu mäüt âënh nghéa måïi vãö quan hãû ancestor :
Måí âáöu vãö ngän ngæî Prolog 29
ancestor(X Z) :-
parent(X Z) .
ancestor(X Z) :-
parent(Y , Z),
ancestor( X, Y).
Âënh nghéa naìy coï âuïng hay khäng ? Coï thãø thay âäøi laûi så âäö âaî cho
trong hçnh 1.7 âãø tæång æïng våïi âënh nghéa måïi naìy ?
5. Ngoaìi caïc âënh nghéa quan hãû gia âçnh âaî coï trong pháön lyï thuyãút vaì baìi
táûp, haîy âënh nghéa caïc quan hãû khaïc theo táûp quaïn Viãût Nam (cä, dç, chuï,
baïc...) ?
6. Haîy âënh nghéa caïc quan hãû trong thãú giåïi sinh váût (âäüng váût, thæûc váût) ?
7. Cho biãút caïc haûng Prolog håüp thæïc sau âáy (valid Prolog terms) :
23 +(fred, jim)
foo(X, bar(+(3, 4))) 1+2.
Foo(x) Alison Cawsey

8. Cho quan hãû parent âæåüc âënh nghéa trong pháön lyï thuyãút cho biãút kãút
quaí cuía caïc cáu hoíi sau :
a) ?- parent(jim , X).
b) ?- parent( X , jim).
c) ?-parent(pam , X) , parent( X , part).
d) ?- parent(pam , X) , parent( X , y ) , parent(y , jim).
9. Viãút caïc mãûnh âãö Prolog diãùn taí caïc cáu hoíi liãn quan âãún quan hãû
parent :
a) Ai laì cha meû cuía Pat ?
b) Liz coï con khäng ?
c) Ai laì äng baì (grandparent) cuía Pat ?
10. Viãút trong Prolog caïc mãûnh âãö sau :
a) Ai coï mäüt âæïa treí ngæåìi âoï laì haûnh phuïc.
Hæåïng dáùn : Xáy dæûng quan hãû mäüt ngäi happy.
b) Våïi moüi X, nãúu X coï mäüt con maì ngæåìi con naìy coï mäüt chë em gaïi, thç X
coï hai con (xáy dæûng quan hãû have_two_children).
11. Âënh nghéa quan hãû grandchild bàòng caïch sæí duûng quan hãû parent.
Hæåïng dáùn : tçm hiãøu quan hãû grandparent.
30 Láûp trçnh logic trong Prolog

12. Âënh nghéa quan hãû aunt( X, Y ) bàòng caïch sæí duûng quan hãû parent.
Âãø thuáûn tiãûn, coï thãø veî så âäö minh hoüa.
13. Caïc pheïp so khåïp dæåïi âáy coï âuïng khäng ? Nãúu âuïng, cho biãút caïc raìng
buäüc biãún tæång æïng ?
a) point( A , B ) = point( 1 , 2 )
b) point( A , B ) = point( X , Y, Z )
c) addition( 2 , 2 ) = 4
d) +( 2 , D ) = +( E , 2 )
e) triangle( point( -1 , 0 ) , P2, P3 ) = triangle( P1, point( 1, 0 ), point( 0,
Y))
Caïc raìng buäüc åí âáy âaî âënh nghéa mäüt låïp caïc tam giaïc. Laìm caïch
naìo âãø mä taí låïp naìy ?
14. Sæí duûng mä taí caïc âæåìng thàóng âaî cho trong baìi hoüc, tçm mäüt haûng biãùu
diãùn moüi âæåìng thàóng âæïng X = 5.
15. Cho hçnh chæî nháût âæåüc biãùu diãùn båíi haûng: rectangle(P1, P2, P3, P4).
Våïi Pi laì caïc âènh cuía hçnh chæî nháût theo chiãöu dæång, haîy âënh nghéa
quan hãû :
regular( R )
laì âuïng nãúu R laì mäüt hçnh chæî nháût coï caïc caûnh thàóng âæïng vaì nàòm
ngang (song song våïi caïc truûc toüa âäü).
CHÆÅNG 2

Ngæî nghéa cuí a chæång trçnh Prolog

I. Quan hãû giæîa Prolog vaì lägich toaïn hoüc


Prolog coï quan hãû chàût cheî våïi lägich toaïn hoüc. Dæûa vaìo lägich toaïn hoüc,
ngæåìi ta coï thãø diãùn taí cuï phaïp vaì nghéa cuía Prolog mäüt caïch ngàõn goün vaì
suïc têch. Tuy nhiãn khäng vç váûy maì nhæîng ngæåìi hoüc láûp trçnh Prolog cáön
phaíi biãút mäüt säú khaïi niãûm vãö lägich toaïn hoüc. Tháût may màõn laì nhæîng khaïi
niãûm vãö lägich toaïn hoüc khäng thæûc sæû cáön thiãút âãø coï thãø hiãøu vaì sæí duûng
Prolog nhæ laì mäüt cäng cuû láûp trçnh. Sau âáy laì mäüt säú quan hãû giæîa Prolog
vaì lägich toaïn hoüc.

Prolog coï cuï phaïp laì nhæîng cäng thæïc lägich vë tæì báûc mäüt (first order
predicate logic), âæåüc viãút dæåïi daûng caïc mãûnh âãö (caïc læåüng tæí ∀ vaì ∃ khäng
xuáút hiãûn mäüt caïch tæåìng minh), nhæng haûn chãú chè âån thuáön åí daûng mãûnh
âãö Horn, laì nhæîng mãûnh âãö chè coï êt nháút mäüt træûc kiãûn dæång (positive
literals). Nàm 1981, Clocksin vaì Mellish âaî âæa ra mäüt chæång trçnh Prolog
chuyãøn caïc cäng thæïc tênh vë tæì báûc mäüt thaình daûng caïc mãûnh âãö.
Caïch Prolog diãùn giaíi chæång trçnh laì theo kiãøu Toaïn hoüc : Prolog xem
caïc sæû kiãûn vaì caïc luáût nhæ laì caïc tiãn âãö, xem cáu hoíi cuía NSD nhæ laì mäüt
âënh lyï cáön phoíng âoaïn. Prolog seî tçm caïch chæïng minh âënh lyï naìy, nghéa laì
chè ra ràòng âënh lyï coï thãø âæåüc suy luáûn mäüt caïch lägich tæì caïc tiãn âãö.

Vãö màût thuí tuûc, Prolog sæí duûng phæång phaïp suy diãùn quay lui (back
chaining) âãø håüp giaíi (resolution) baìi toaïn, âæåüc goüi laì chiãún læåüc håüp giaíi SLD
(Selected, Linear, Definite : Linear resolution with a Selection function for
Definite sentences) do J. Herbrand vaì A. Robinson âãö xuáút nàm 1995.

31
32 Láûp trçnh lägich trong Prolog

Coï thãø toïm tàõt nhæ sau : âãø chæïng minh P(a), ngæåìi ta tçm sæû kiãûn
P(t)
hoàûc mäüt luáût :
P(t) :- L1, L2, …, Ln
sao cho a coï thãø håüp nháút (unifiable) âæåüc våïi t nhåì so khåïp. Nãúu tçm âæåüc
P(t) laì sæû kiãûn nhæ váûy, viãûc chæïng minh kãút thuïc. Coìn nãúu tçm âæåüc P(t) laì
luáût, cáön láön læåüt chæïng minh vãú bãn phaíi L1, L2, ..., Ln cuía noï.

Trong Prolog, cáu hoíi luän luän laì mäüt daîy tæì mäüt âãún nhiãöu âêch. Prolog
traí låìi mäüt cáu hoíi bàòng caïch tçm kiãúm âãø xoaï (erase) táút caí caïc âêch. Xoaï
mäüt âêch nghéa laì chæïng minh ràòng âêch naìy âæåüc thoaí maîn, våïi giaí thiãút
ràòng caïc quan hãû cuía chæång trçnh laì âuïng. Noïi caïch khaïc, xoaï mäüt âêch coï
nghéa laì âêch naìy âæåüc suy ra mäüt caïch lägich båíi caïc sæû kiãûn vaì luáût chæïa
trong chæång trçnh.
Nãúu coï caïc biãún trong cáu hoíi, Prolog tçm caïc âäúi tæåüng âãø thay thãú vaìo
caïc biãún, sao cho âêch âæåüc thoaí maîn. Sæû raìng buäüc giaï trë cuía caïc biãún
tæång æïng våïi viãûc hiãøn thë caïc âäúi tæåüng naìy. Nãúu Prolog khäng thãø tçm
âæåüc raìng buäüc cho caïc biãún sao cho âêch âæåüc suy ra tæì chæång trçnh thç noï
seî traí låìi No.

II. Caïc mæïc nghéa cuía chæång trçnh Prolog


Cho âãún luïc naìy, qua caïc vê duû minh hoaû, ta måïi chè hiãøu âæåüc tênh âuïng
âàõn vãö kãút quaí cuía mäüt chæång trçnh Prolog, maì chæa hiãøu âæåüc laìm caïch naìo
âãø hãû thäúng tçm âæåüc låìi giaíi. Mäüt chæång trçnh Prolog coï thãø âæåüc hiãøu theo
nghéa khai baïo (declarative signification) hoàûc theo nghéa thuí tuûc
(procedural signification). Váún âãö laì cáön phán biãût hai mæïc nghéa cuía mäüt
chæång trçnh Prolog, laì nghéa khai baïo vaì nghéa thuí tuûc. Ngæåìi ta coìn phán
biãût mæïc nghéa thæï ba cuía mäüt chæång trçnh Prolog laì nghéa lägich (logical
semantic).
Træåïc khi âënh nghéa mäüt caïch hçnh thæïc hai mæïc ngæî nghéa khai baïo vaì
thuí tuûc, ta cáön phán biãût sæû khaïc nhau giæîa chuïng. Cho mãûnh âãö :
P :- Q, R.
våïi P, Q, vaì R laì caïc haûng naìo âoï.
Ngæî nghéa cuía chæång trçnh Prolog 33

Theo nghéa khai baïo, ta âoüc chuïng theo hai caïch nhæ sau :
• P laì âuïng nãúu caí Q vaì R âãöu âuïng.
• Q vaì R dáùn ra P.
Theo nghéa thuí tuûc, ta cuîng âoüc chuïng theo hai caïch nhæ sau :
• Âãø giaíi baìi toaïn P, âáöu tiãn, giaíi baìi toaïn con Q, sau âoï giaíi baìi toaïn
con R.
• Âãø xoaï P, âáöu tiãn, xoaï Q, sau âoï xoaï R.
Sæû khaïc nhau giæîa nghéa khai baïo vaì nghéa thuí tuûc laì åí chäù, nghéa thuí
tuûc khäng âënh nghéa caïc quan hãû lägich giæîa pháön âáöu cuía mãûnh âãö vaì caïc
âêch cuía thán, maì chè âënh nghéa thæï tæû xæí lyï caïc âêch.

II.1. Nghéa khai baïo cuía chæång trçnh Prolog


Vãö màût hçnh thæïc, nghéa khai baïo, hay ngæî nghéa chuí yï (intentional
semantic) xaïc âënh caïc mäúi quan hãû âaî âæåüc âënh nghéa trong chæång trçnh.
Nghéa khai baïo xaïc âënh nhæîng gç laì kãút quaí (âêch) maì chæång trçnh phaíi
tênh toaïn, phaíi taûo ra.
Nghéa khai baïo cuía chæång trçnh xaïc âënh nãúu mäüt âêch laì âuïng, vaì trong
træåìng håüp naìy, xaïc âënh giaï trë cuía caïc biãún. Ta âæa vaìo khaïi niãûm thãø
nghiãûm (instance) cuía mäüt mãûnh âãö C laì mãûnh âãö C maì mäùi mäüt biãún cuía noï
âaî âæåüc thay thãú båíi mäüt haûng. Mäüt biãún thãø (variant) cuía mäüt mãûnh âãö C laì
mãûnh âãö C sao cho mäùi mäüt biãún cuía noï âaî âæåüc thay thãú båíi mäüt biãún khaïc.

Vê duû II.1 : Cho mãûnh âãö :


hasachild(X) :-
parent(X, Y).

Hai biãún thãø cuía mãûnh âãö naìy laì :


hasachild(A) :-
parent(A, B).
hasachild(X1) :-
parent(X1, X2).

Caïc thãø nghiãûm cuía mãûnh âãö naìy laì :


hasachild(tom) :-
parent(tom, Z).
34 Láûp trçnh lägich trong Prolog

hasachild(jafa) :-
parent(jafa, small(iago)).

Cho træåïc mäüt chæång trçnh vaì mäüt âêch G, nghéa khai baïo noïi ràòng :
Mäüt âêch G laì âuïng (thoaí maîn, hay suy ra âæåüc tæì chæång trçnh mäüt caïch
logic) nãúu vaì chè nãúu
(1) täön taûi mäüt mãûnh âãö C cuía chæång trçnh sao cho
(2) täön taûi mäüt thãø nghiãûm I cuía mãûnh âãö C sao cho:
(a) pháön âáöu cuía I laì giäúng hãût G, vaì
(b) moüi âêch cuía pháön thán cuía I laì âuïng.
Âënh nghéa trãn âáy aïp duûng âæåüc cho caïc cáu hoíi Prolog. Cáu hoíi laì mäüt
danh saïch caïc âêch ngàn caïch nhau båíi caïc dáúu pháøy. Mäüt danh saïch caïc
âêch laì âuïng nãúu táút caí caïc âêch cuía danh saïch laì âuïng cho cuìng mäüt raìng
buäüc cuía caïc biãún. Caïc giaï trë cuía caïc biãún laì nhæîng giaï trë raìng buäüc täøng
quaït nháút.

II.2. Khaïi niãûm vãö goïi mãûnh âãö


Mäüt goïi hay boï mãûnh âãö (packages of clauses) laì táûp håüp caïc mãûnh âãö coï
cuìng tãn haûng tæí chênh (cuìng tãn, cuìng säú læåüng tham âäúi). Vê duû sau âáy laì
mäüt goïi mãûnh âãö :
a(X) :- b(X, _).
a(X) :- c(X), e(X).
a(X) :- f(X, Y).
Goïi mãûnh âãö trãn coï ba mãûnh âãö coï cuìng haûng laì a(X). Mäùi mãûnh âãö cuía
goïi laì mäüt phæång aïn giaíi quyãút baìi toaïn âaî cho.
Prolog quy æåïc :

• mäùi dáúu pháøy (comma) âàût giæîa caïc mãûnh âãö, hay caïc âêch, âoïng vai troì
pheïp häüi (conjunction). Vãö màût lägich, chuïng phaíi âuïng táút caí.

• mäùi dáúu cháúm pháøy (semicolon) âàût giæîa caïc mãûnh âãö, hay caïc âêch,
âoïng vai troì pheïp tuyãøn (disjunction). Luïc naìy chè cáön mäüt trong caïc
âêch cuía danh saïch laì âuïng.
Ngæî nghéa cuía chæång trçnh Prolog 35

Vê duû II.2 :
P :- Q; R.
âæåüc âoüc laì : P âuïng nãúu Q âuïng hoàûc R âuïng. Ngæåìi ta cuîng coï thãø viãút taïch
ra thaình hai mãûnh âãö :
P :- Q.
P :- R.
Trong Prolog, dáúu pháøy (pheïp häüi) coï mæïc âäü æu tiãn cao hån dáúu cháúm
pháøy (pheïp tuyãøn). Vê duû :
P :- Q, R; S, T, U.
âæåüc hiãøu laì :
P :- (Q, R); (S, T, U).
vaì coï thãø âæåüc viãút thaình hai mãûnh âãö :
P :- (Q, R).
P :- (S, T, U).
Hai mãûnh âãö trãn âæåüc âoüc laì : P âuïng nãúu hoàûc caí Q vaì R âãöu âuïng,
hoàûc caí S, T vaì U âãöu âuïng.
Vãö nguyãn tàõc, thæï tæû thæûc hiãûn caïc mãûnh âãö trong mäüt goïi laì khäng
quan troüng, tuy nhiãn trong thæûc tãú, cáön chuï yï tän troüng thæï tæû cuía caïc
mãûnh âãö. Prolog seî láön læåüt thæûc hiãûn theo thæï tæû xuáút hiãûn caïc mãûnh âãö
trong goïi vaì trong chæång trçnh theo mä hçnh tuáön tæû bàòng caïch thæí quay lui
maì ta seî xeït sau âáy.

II.3. Nghéa lägich cuía caïc mãûnh âãö


Nghéa lägich thãø hiãûn mäúi liãn hãû giæîa âàûc taí lägich (logical specification)
cuía baìi toaïn cáön giaíi våïi baín thán chæång trçnh.
1. Caïc mãûnh âãö khäng chæïa biãún
Mãûnh âãö Nghéa lägich Kyï hiãûu Toaïn hoüc
P(a). P(X) âuïng nãùu X = a P(X) ⇔ X = a
P(a).
P(b).
P(X) âuïng nãùu X = a hoàûc X = b P(X) ⇔ (X = a) ∨ (X = b)

P(a) :- Q(c). P(X) âuïng nãùu X = a vaì Q(c) âuïng P(X) ⇔ X = a ∧ Q(c)

P(a) :- Q(c). P(X) âuïng nãùu hoàûc (X = a vaì Q(c) P(X) ⇔ (X = a ∧ Q(c))
P(b). âuïng) hoàûc X = b ∨ (X = b)
36 Láûp trçnh lägich trong Prolog

Quy æåïc : nãùu = nãúu vaì chè nãúu.

2. Caïc mãûnh âãö coï chæïa biãún


Mãûnh âãö Nghéa lägich Kyï hiãûu Toaïn hoüc
P(X). Våïi moüi giaï trë cuía X, P(X) âuïng ∀X P(X)

P(X) :- Våïi moüi giaï trë cuía X, P(X) âuïng nãùu Q(X)
P(X) ⇔ Q(X)
Q(X). âuïng

Våïi moüi giaï trë cuía X, P(X) âuïng nãùu täön


P(X) :-
taûi Y laì mäüt biãún cuûc bäü sao cho Q(X, Y) P(X) ⇔ ∃Y Q(X, Y)
Q(X, Y).
âuïng

Våïi moüi giaï trë cuía X, P(X) âuïng nãùu täön


P(X) :- taûi mäüt giaï trë naìo âoï cuía Y sao cho Q(X, Y)
P(X) ⇔ ∃Y Q(X, Y)
Q(X, _). âuïng (khäng quan tám âãún giaï trë cuía Y
nhæ thãú naìo)
P(X) :-
Våïi moüi giaï trë cuía X, P(X) âuïng nãùu täön P(X) ⇔ ∃Y Q(X, Y) ∧
Q(X, Y),
taûi Y sao cho Q(X, Y) vaì R(Y) âuïng R(Y)
R(Y).
P(X) :-
Våïi moüi giaï trë cuía X, P(X) âuïng nãùu hoàûc P(X) ⇔ (∃Y Q(X, Y) ∧
Q(X, Y),
R(Y). täön taûi Y sao cho Q(X, Y) vaì R(Y) âuïng, R(Y))
p(a). hoàûc X = a ∨ (X = a)

3. Nghéa lägich cuía caïc âêch


Âêch Nghéa lägich

p(a). Coï phaíi p(a) âuïng (thoaí maîn) ?

p(a), Q(b). Coï phaíi caí p(a) vaì Q(b) âãöu âuïng ?
P(X). Cho biãút giaï trë cuía X âãø P(X) laì âuïng ?

P(X), Q(X, Y). Cho biãút caïc giaï trë cuía X vaì cuía Y âãø P(X) vaì Q(X, Y) âãöu
laì âuïng ?
Ngæî nghéa cuía chæång trçnh Prolog 37

II.4. Nghéa thuí tuûc cuía Prolog


Nghéa thuí tuûc, hay ngæî nghéa thao taïc (operational semantic), laûi xaïc
âënh laìm caïch naìo âãø nháûn âæåüc kãút quaí, nghéa laì laìm caïch naìo âãø caïc quan
hãû âæåüc xæí lyï thæûc sæû båíi hãû thäúng Prolog.
Nghéa thuí tuûc tæång æïng våïi caïch Prolog traí låìi caïc cáu hoíi nhæ thãú naìo
(how) hay láûp luáûn trãn caïc tri thæïc. Traí låìi mäüt cáu hoíi coï nghéa laì tçm caïch
xoïa mäüt danh saïch. Âiãöu naìy chè coï thãø thæûc hiãûn âæåüc nãúu caïc biãún xuáút
hiãûn trong caïc âêch naìy âæåüc raìng buäüc sao cho chuïng âæåüc suy ra mäüt caïch
lägich tæì chæång trçnh (hay tæì caïc tri thæïc âaî ghi nháûn).
Prolog coï nhiãûm vuû thæûc hiãûn láön læåüt tæìng âêch trong mäüt danh saïch caïc
âêch tæì mäüt chæång trçnh âaî cho. «Thæûc hiãûn mäüt âêch» coï nghéa laì tçm caïch
thoaí maîn hay xoaï âêch âoï khoíi danh saïch caïc âêch âoï.

chæång trçnh (sæû kiãûn+luáût)

dáúu hiãûu thaình cäng/tháút baûi


danh saïch caïc âêch execute
raìng buäüc caïc biãún

Hçnh II.1. Mä hçnh vaìo/ra cuía mäüt thuí tuûc thæûc hiãûn mäüt danh saïch caïc âêch.

Goüi thuí tuûc naìy laì execute (thæûc hiãûn), caïi vaìo vaì caïi ra cuía noï nhæ sau :
Caïi vaìo : mäüt chæång trçnh vaì mäüt danh saïch caïc âêch
Caïi ra : mäüt dáúu hiãûu thaình cäng/tháút baûi vaì mäüt raìng buäüc caïc biãún
Nghéa cuía hai caïi ra nhæ sau :
(1) Dáúu hiãûu thaình cäng/tháút baûi laì Yes nãúu caïc âêch âæåüc thoaí maîn (thaình
cäng), laì No nãúu ngæåüc laûi (tháút baûi).
(2) Sæû raìng buäüc caïc biãún chè xaíy ra nãúu chæång trçnh âæåüc thæûc hiãûn.
38 Láûp trçnh lägich trong Prolog

Vê duû II.3 :

Minh hoaû caïch Prolog traí låìi cáu hoíi cho vê duû chæång trçnh gia hãû træåïc
âáy nhæ sau :
Âêch cáön tçm laì :
?- ancestor(tom, pat)
Ta biãút ràòng parent(bob, pat) laì mäüt sæû kiãûn. Âãø sæí duûng sæû kiãûn naìy vaì
luáût 1 (vãö täø tiãn træûc tiãúp), ta coï thãø kãút luáûn ràòng ancestor(bob, pat). Âáy laì
mäüt sæû kiãûn keïo theo : sæû kiãûn naìy khäng coï màût trong chæång trçnh, nhæng
coï thãø âæåüc suy ra tæì caïc luáût vaì sæû kiãûn khaïc. Ta coï thãø viãút goün sæû suy diãùn
naìy nhæ sau :
parent(bob, pat) ⇒ ancestor(bob, pat)
Nghéa laì parent(bob, pat)keïo theo ancestor(bob, pat) båíi luáût 1. Ta laûi biãút
ràòng parent(tom, bob) cuîng laì mäüt sæû kiãûn. Màût khaïc, tæì sæû kiãûn âæåüc suy
diãùn ancestor(bob, pat), luáût 2 (vãö täø tiãn giaïn tiãúp) cho pheïp kãút luáûn ràòng
ancestor(tom, pat). Quaï trçnh suy diãùn hai giai âoaûn naìy âæåüc viãút :
parent(bob, pat) ⇒ ancestor(bob, pat)
parent(tom, bob) vaì ancestor(bob, pat) ⇒ ancestor(tom, pat)
Ta væìa chè ra caïc giai âoaûn âãø xoaï mäüt âêch, goüi laì mäüt chæïng minh. Tuy
nhiãn, ta chæa chè ra laìm caïch naìo Prolog nháûn âæåüc mäüt chæïng minh nhæ
váûy.
Prolog nháûn âæåüc pheïp chæïng minh naìy theo thæï tæû ngæåüc laûi nhæîng gç
âaî trçnh baìy. Thay vç xuáút phaït tæì caïc sæû kiãûn chæïa trong chæång trçnh,
Prolog bàõt âáöu båíi caïc âêch vaì, bàòng caïch sæí duûng caïc luáût, noï thay thãú caïc
âêch naìy båíi caïc âêch måïi, cho âãún khi nháûn âæåüc caïc sæû kiãûn så cáúp.
Âãø xoaï âêch :
?- ancestor(tom, pat).
Prolog tçm kiãúm mäüt mãûnh âãö trong chæång trçnh maì âêch naìy âæåüc suy diãùn
ngay láûp tæïc. Roî raìng chè coï hai mãûnh âãö thoaí maîn yãu cáöu naìy laì luáût 1 vaì
luáût 2, liãn quan âãún quan hãû ancestor. Ta noïi ràòng pháön âáöu cuía caïc luáût
naìy tæång æïng våïi âêch.
Ngæî nghéa cuía chæång trçnh Prolog 39

Hai mãûnh âãö naìy biãøu diãùn hai khaí nàng maì Prolog phaíi khai thaïc xæí lyï.
Prolog bàõt âáöu choün xæí lyï mãûnh âãö thæï nháút xuáút hiãûn trong chæång trçnh :
ancestor(X, Z) :- parent(X, Z).

Do âêch laì ancestor(tom, pat), caïc biãún phaíi âæåüc raìng buäüc nhæ sau :
X = tom, Z = pat

Luïc naìy, âêch ban âáöu tråí thaình :


parent(tom, pat)

Hçnh dæåïi âáy biãøu diãùn giai âoaûn chuyãøn mäüt âêch thaình âêch måïi sæí
duûng mäüt luáût. Tháút baûi xaíy ra khi khäng coï pháön âáöu naìo trong caïc mãûnh
âãö cuía chæång trçnh tæång æïng våïi âêch parent(tom, pat).

ancestor(tom, pat)

Båíi luáût 1

parent(tom, pat)

Hçnh II.2. Xæí lyï bæåïc âáöu tiãn :


Âêch phêa trãn âæåüc thoaí maîn nãúu Prolog coï thãø xoaï âêch åí phêa dæåïi.

Luïc naìy Prolog phaíi tiãún haình quay lui (backtracking) tråí laûi âêch ban
âáöu, âãø tiãúp tuûc xæí lyï mãûnh âãö khaïc laì luáût thæï hai :
ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).
Tæång tæû bæåïc xæí lyï thæï nháút, caïc biãún X vaì Z âæåüc raìng buäüc nhæ sau :
X = tom, Z = pat
Âêch phêa trãn ancestor(tom, pat)âæåüc thay thãú båíi hai âêch laì :
parent(tom, Y), ancestor(Y, pat).

Nhæng luïc naìy, Y chæa coï giaï trë. Luïc naìy cáön xoaï hai âêch. Prolog seî tiãún
haình xoaï theo thæï tæû xuáút hiãûn cuía chuïng trong chæång trçnh. Âäúi våïi âêch
thæï nháút, viãûc xoaï ráút dãù daìng vç âoï laì mäüt trong caïc sæû kiãûn cuía chæång
trçnh. Sæû tæång æïng sæû kiãûn dáùn âãún Y âæåüc raìng buäüc båíi giaï trë bob.
Caïc giai âoaûn thæûc hiãûn âæåüc mä taí båíi cáy håüp giaíi sau âáy :
40 Láûp trçnh lägich trong Prolog

ancestor(tom, pat)

Båíi luáût 1 Båíi luáût 2

Tháút baûi
parent(tom, pat) parent(tom, Y)
ancestor(Y, pat)

Hçnh II.3. Caïc giai âoaûn thæûc hiãûn xæí lyï xoaï âêch.

Sau khi âêch thæï nháút parent(tom, bob) thoaí maîn, coìn laûi âêch thæï hai :
ancestor(bob, pat)
cuîng phaíi âæåüc thoaí maîn Mäüt láön næîa, luáût 1 âæåüc sæí duûng. Chuï yï ràòng viãûc
aïp duûng láön thæï hai cuìng luáût naìy khäng liãn quan gç âãún láön aïp duûng thæï
nháút. Prolog sæí duûng caïc biãún måïi mäùi láön luáût âæåüc goüi âãún. Luáût 1 báy giåì
coï thãø âæåüc âàût tãn laûi nhæ sau :
ancestor(X’, Z’) :- parent(X’, Z’).
Pháön âáöu phaíi tæång æïng våïi âêch thæï nháút, ancestor(bob, pat), tæïc laì :
X’ = bob, Z’ = pat

ancestor(tom, pat)

Båíi luáût 1 Båíi luáût 2

parent(tom, pat) parent(tom, Y)


ancestor(Y, pat)
Tháút baûi Y = bob båíi
parent(tom, bob)
ancestor(bob, pat)

Båíi luáût 1
Thaình cäng
parent(bob, pat)

Hçnh II.4. Quaï trçnh thæûc hiãûn xoaï âêch ancestor(tom, pat).

Tæì âoï âêch (trong pháön thán) phaíi thay thãú båíi :
parent(bob, pat)
Ngæî nghéa cuía chæång trçnh Prolog 41

Âêch naìy âæåüc thoaí maîn ngay láûp tæïc, vç chênh laì mäüt sæû kiãûn trong
chæång trçnh. Quaï trçnh xæí lyï âæåüc minh hoaû laûi âáöy âuí trong Hçnh II.4.
Hçnh 2.4. coï daûng mäüt cáy. Mäùi nuït tæång æïng våïi mäüt âêch, hay mäüt
danh saïch caïc âêch cáön thoaí maîn. Mäùi cung näúi hai nuït tæång æïng våïi viãûc
aïp duûng mäüt luáût trong chæång trçnh. Viãûc aïp duûng mäüt luáût cho pheïp
chuyãøn caïc âêch cuía mäüt nuït thaình caïc âêch måïi cuía mäüt nuït khaïc. Âêch trãn
cuìng (gäúc cuía cáy) âæåüc xoaï khi tçm âæåüc mäüt con âæåìng âi tæì gäúc âãún laï coï
nhaîn laì thaình cäng. Mäüt nuït laï coï nhaîn laì thaình cäng khi trong nuït laì mäüt
sæû kiãûn cuía chæång trçnh. Viãûc thæûc thi mäüt chæång trçnh Prolog laì viãûc tçm
kiãúm nhæîng con âæåìng nhæ váûy.

Nhaïnh bãn phaíi chæïng toí ràòng coï thãø xoaï âêch.
Trong quaï trçnh tçm kiãúm, coï thãø xaíy ra khaí nàng laì Prolog âi trãn mäüt
con âæåìng khäng täút. Khi gàûp nuït chæïa mäüt sæû kiãûn khäng täön taûi trong
chæång trçnh, xem nhæ tháút baûi, nuït âæåüc gàõïn nhaîn tháút baûi, ngay láûp tæïc
Prolog tæû âäüng quay lui lãn nuït phêa trãn, choün aïp duûng mäüt mãûnh âãö tiãúp
theo coï màût trong nuït naìy âãø tiãúp tuûc con âæåìng måïi, chæìng naìo thaình cäng.
Vê duû trãn âáy, ta âaî giaíi thêch mäüt caïch khäng hçnh thæïc caïch Prolog traí
låìi cáu hoíi. Thuí tuûc execute dæåïi âáy mä taí hçnh thæïc vaì coï hãû thäúng hån vãö
quaï trçnh naìy.
Âãø thæûc hiãûn danh saïch caïc âêch :
G1, G2, ..., Gm

thuí tuûc execute tiãún haình nhæ sau :


• Nãúu danh saïch caïc âêch laì räùng, thuí tuûc thaình cäng vaì dæìng.
• Nãúu danh saïch caïc âêch khaïc räùng, thuí tuûc duyãût scrutinize sau âáy
âæåüc thæûc hiãûn
Thuí tuûc scrutinize :
Duyãût caïc mãûnh âãö trong chæång trçnh bàõt âáöu tæì mãûnh âãö âáöu tiãn, cho
âãún khi nháûn âæåüc mãûnh âãö C coï pháön âáöu truìng khåïp våïi pháön âáöu cuía
âêch âáöu tiãn G1.

Nãúu khäng tçm tháúy mäüt mãûnh âãö naìo nhæ váûy, thuí tuûc råi vaìo tçnh traûng
tháút baûi.
42 Láûp trçnh lägich trong Prolog

Nãúu mãûnh âãö C âæåüc tçm tháúy, vaì coï daûng :


H :- D1, ..., Dn

khi âoï, caïc biãún cuía C âæåüc âàût tãn laûi âãø nháûn âæåüc mäüt biãún thãø C’
khäng coï biãún naìo chung våïi danh saïch G1, G2, ..., Gm.
Mãûnh âãö C’ nhæ sau :
H’ :- D’1, ..., D’n

Giaí sæí S laì raìng buäüc cuía caïc biãún tæì viãûc so khåïp giæîa G1 vaì H’, Prolog
thay thãú G1 båíi D’1, ..., D’n trong danh saïch caïc âêch âãø nháûn âæåüc mäüt danh
saïch måïi :
D1’, ..., Dn’, G2, ..., Gm

Chuï yï ràòng nãúu C laì mäüt sæû kiãûn, khi âoï, n=0 vaì danh saïch måïi seî ngàõn
hån danh saïch cuî. Træåìng håüp danh saïch måïi räùng, kãút quaí thaình cäng.
Thay thãú caïc biãún cuía danh saïch måïi naìy båíi caïc giaï trë måïi chè âënh båíi
raìng buäüc S, ta nháûn âæåüc mäüt danh saïch caïc âêch måïi :
D"1, ..., D"n, G"2, ..., G"m

Thæûc hiãûn thuí tuûc mäüt caïch âãû quy cho danh saïch caïc âêch måïi naìy. Nãúu
kãút thuïc thaình cäng, tiãúp tuûc thæûc hiãûn danh saïch ban âáöu. Trong træåìng
håüp ngæåüc laûi, Prolog boí qua danh saïch caïc âêch âãø quay lui laûi thuí tuûc
scrutinize. Quaï trçnh tçm kiãúm caïc mãûnh âãö trong chæång trçnh âæåüc bàõt âáöu
laûi tæì sau mãûnh âãö C, våïi mäüt mãûnh âãö måïi.
Ngæî nghéa cuía chæång trçnh Prolog 43

Quaï trçnh thæûc hiãûn thuí tuûc execute âæåüc mä taí nhæ sau :

Chæång trçnh Prolog G1, G2, ..., Gm


hay cå såí dæî liãûu Khäng coï biãún
truìng nhau :
C' : H’ :- D’1, ..., D’n
Gi, D’j, H'

... S = (G1| H’)


C H :- D1, ..., Dn Nãúu n=0
... D1’, ..., Dn’, G2, ..., Gm mãûnh âãö måïi
seî ngàõn hån
D"1, ..., D"n, G"2, ..., G"m

Hçnh II.5. Quaï trçnh thæûc hiãûn execute.

Sau âáy laì thuí tuûc execute âæåüc viãút bàòng giaí ngæî Pascal.
Procedure execute(program, goallist, success);
{ Tham âäúi vaìo :
program danh saïch caïc mãûnh âãö
goallist danh saïch caïc âêch
Tham âäúi ra :
success kiãøu Boolean, laì true nãúu goallist laì true âäúi våïi tham âäúi
program
Caïc biãún cuûc bäü :
goal âêch
othergoals danh saïch caïc âêch
satisfied kiãøu Boolean
matchOK kiãøu Boolean
process raìng buäüc cuía caïc biãún
H, H’, D1, D1’, ..., Dn, Dn’ caïc âêch
Caïc haìm phuû :
empty(L) coï giaï trë true nãúu L laì danh saïch räùng
head(L) traí vãö pháön tæí âáöu tiãn cuía danh saïch L
tail(L) traí vãö danh saïch L sau khi âaî boí âi pháön tæí âáöu tiãn
add(L1, L2) gheïp danh saïch L2 vaìo sau danh saïch L1
match(T1, T2, matchOK, process)
so khåïp caïc haûng T1 vaì T2, nãúu thaình cäng,
44 Láûp trçnh lägich trong Prolog

biãún matchOK coï giaï trë true, vaì process chæïa caïc raìng
buäüc tæång æïng våïi caïc biãún.
substitute(process, goals)
thay thãú caïc biãún cuía goals båíi giaï trë raìng buäüc tæång æïng
trong process.
}
begin { execute_main }
if empty(goallist) then success:= true
else begin
goal:= head(goallist);
othergoals:= tail(goallist);
satisfied:= false;
while not satisfied and there_are_again_some_terms do begin
Let the following clause of program is:
H :- D1, ..., Dn
constructing a variant of this clause:
H’ :- D1’, ..., Dn’
match(goal, H’, matchOK, process)
if matchOK then begin
newgoals:= add([ D1’, ..., Dn’ ], othergoals);
newgoals:= substitute(process, newgoals);
execute(program, newgoals, satisfied)
end { if }
end; { while }
satisfied:= satisfied
end
end; { execute_main }

Tæì thuí tuûc execute trãn âáy, ta coï mäüt säú nháûn xeït sau. Træåïc hãút, thuí
tuûc khäng mä taí laìm caïch naìo âãø nháûn âæåüc raìng buäüc cuäúi cuìng cho caïc
biãún. Chênh raìng buäüc S âaî dáùn âãún thaình cäng nhåì caïc låìi goüi âãû quy.

Mäùi láön låìi goüi âãû quy execute tháút baûi (tæång æïng våïi mãûnh âãö C),
thuí tuûc scrutinize tçm kiãúm mãûnh âãö tiãúp theo ngay sau mãûnh âãö C. Quaï
trçnh thæûc thi laì hiãûu quaí, vç Prolog boí qua nhæîng pháön vä êch âãø reî sang
nhaïnh khaïc.
Ngæî nghéa cuía chæång trçnh Prolog 45

Luïc naìy, moüi raìng buäüc cho biãún thuäüc nhaïnh vä êch bë loaûi boí hoaìn toaìn.
Prolog seî láön læåüt duyãût hãút táút caí caïc con âæåìng coï thãø âãø âãún thaình cäng.
Ta cuîng âaî tháúy ràòng ngay sau khi coï mäüt kãút quaí têch cæûc, NSD coï thãø
yãu cáöu hãû thäúng quay lui âãø tçm kiãúm mäüt kãút quaí måïi. Chi tiãút naìy âaî
khäng âæåüc xæí lyï trong thuí tuûc execute. Trong caïc caìi âàût Prolog hiãûn nay,
nhiãöu khaí nàng måïi âaî âæåüc thãm vaìo nhàòm âaût hiãûu quaí täúi æu. Khäng
phaíi moüi mãûnh âãö trong chæång trçnh âãöu âæåüc duyãût âãún, maì chè duyãût
nhæîng mãûnh âãö coï liãn quan âãún âêch hiãûn haình.
Vê duû II.4 :
Cho chæång trçnh :
thick(bear). % clause 1
thick(elephant). % clause 2
small(cat). % clause 3
brown(bear). % clause 4
grey(elephant). % clause 5
black(cat). % clause 6
dark(Z) :- black(Z). % clause 7: all this who is black is dark
dark(Z) :- brown(Z). % clause 8: all this who is brown is dark
Cáu hoíi :
?- dark(X), thick(X). % who is thick and dark ?
X = bear
Yes
(1) Danh saïch ban âáöu cuía caïc âêch laì : dark(X), thick(X).
(2) Tçm kiãúm (duyãût) tæì âáöu âãún cuäúi chæång trçnh mäüt mãûnh âãö coï pháön
âáöu tæång æïng våïi âêch âáöu tiãn dark(X). Prolog tçm âæåüc mãûnh âãö 7 :
dark(Z) :- black(Z).
Thay thãú âêch âáöu tiãn båíi pháön thán cuía mãûnh âãö 7 sau khi âaî âæåüc
raìng buäüc (thãú biãún Z båíi X) âãø nháûn âæåüc mäüt danh saïch caïc âêch
måïi :
black(X), thick(X).
(3) Tçm kiãúm trong chæång trçnh mäüt mãûnh âãö sao cho âêch con black(X)
âæåüc so khåïp : tçm âæåüc mãûnh âãö 6 laì sæû kiãûn black(cat). Luïc naìy,
raìng buäüc thaình cäng, danh saïch caïc âêch thu goün thaình :
thick(cat)
46 Láûp trçnh lägich trong Prolog

(4) Tçm kiãúm âêch con thick(cat). Do khäng tçm tháúy mãûnh âãö naìo thoaí
maîn, Prolog quay lui laûi giai âoaûn (3). Raìng buäüc X=cat bë loaûi boí.
Danh saïch caïc âêch tråí thaình :
black(X), thick(X).
Tiãúp tuûc tçm kiãúm trong chæång trçnh bàõt âáöu tæì mãûnh âãö 6. Do
khäng tçm tháúy mãûnh âãö naìo thoaí maîn, Prolog quay lui laûi giai âoaûn
(2) âãø tiãúp tuûc tçm kiãúm bàõt âáöu tæì mãûnh âãö 7. Kãút quaí tçm âæåüc
mãûnh âãö 8 :
dark(Z) :- brown(Z).
Sau khi thay thãú båíi brown(X)trong danh saïch caïc âêch, ta nháûn
âæåüc :
brown(X), thick(X)
(5) Tçm kiãúm cho raìng buäüc brown(X), âæåüc kãút quaí laì brown(bear). Mãûnh
âãö naìy laì mäüt sæû kiãûn, danh saïch caïc âêch thu goün laûi thaình :
thick(bear)
(6) Viãûc tçm kiãúm trong chæång trçnh dáùn âãún kãút quaí thick(bear). Do âáy
laì mäüt sæû kiãûn, danh saïch caïc âêch tråí nãn räùng. Âiãöu naìy chæïng toí
chæång trçnh âaî thæûc hiãûn thaình cäng, sæû raìng buäüc cho biãún laì :
X = bear
Quaï trçnh thæûc hiãûn âæåüc giaíi thêch trong hçnh dæåïi âáy.

dark(X), thick(X)

dark(Z) :- black(Z). Quay lui dark(Z) :- brown(Z).


(Z|X) (Z|X)

black(X), thick(X) brown(X), thick(X)

brown(bear).
black(cat). Quay lui
(X|bear)
(X|cat)
thick(cat) thick(bear)

Tháút baûi Thaìình cäng, X=bear

Hçnh II.6. Quaï trçnh thæûc hiãûn xoaï âêch dark(X), thick(X).
Ngæî nghéa cuía chæång trçnh Prolog 47

II.5. Täø håüp caïc yãúu täú khai baïo vaì thuí tuûc
Ngæåìi ta thæåìng quan tám âãún tênh æu viãût cuía Prolog laì khaí nàng tæû
quaín lyï caïc chi tiãút thuí tuûc. Âiãöu naìy cho pheïp NLT (NLT) dæû kiãún træåïc
âæåüc nghéa khai baïo cuía mäüt chæång trçnh mäüt caïch âäüc láûp våïi nghéa thuí
tuûc cuía noï. Vãö nguyãn tàõc, do kãút quaí thæûc hiãûn cuía mäüt chæång trçnh phuû
thuäüc vaìo pháön khai baïo, nãn phaíi khai baïo âáöy âuí caïc sæû kiãûn, luáût vaì quan
hãû khi láûp trçnh. Âiãöu naìy mang tênh thæûc tiãùn, vç luän luän caïc yãúu täú khai
baïo cuía mäüt chæång trçnh dãù hiãøu hån so våïi caïc chi tiãút thuí tuûc.
Âãø táûn duûng âæåüc khaí nàng tæû quaín lyï caïc chi tiãút thuí tuûc cuía Prolog,
NLT phaíi táûp trung âàûc biãût vaìo yãúu täú khai baïo, traïnh nháöm láùn trong
chæìng mæûc coï thãø båíi caïc chi tiãút thæûc hiãûn chæång trçnh. Cáön âãø cho Prolog
tæû giaíi quyãút caïc chi tiãút mang tênh thuí tuûc naìy.
Nhåì tiãúp cáûn khai baïo, láûp trçnh trãn Prolog luän luän thuáûn tiãûn hån so
våïi caïc ngän ngæî thuí tuûc khaïc nhæ Pascal. Tuy nhiãn, tiãúp cáûn khai baïo
khäng phaíi luän luän âáöy âuí. Nhæ seî tháúy sau naìy, âäúi våïi caïc chæång trçnh
låïn, khäng thãø loaûi boí hoaìn toaìn tênh tiãúp cáûn thuí tuûc, do tênh hiãûu quaí thæûc
tiãùn cuía noï khi thæûc hiãûn chæång trçnh.
Vç váûy, tuyì theo chæång trçnh Prolog maì sæí duûng hoaìn toaìn yãúu täú khai
baïo, loaûi boí yãúu täú thuí tuûc khi raìng buäüc thæûc tiãùn cho pheïp.
Nhæ seî tháúy trong chæång sau ràòng viãûc sàõp âàût thæï tæû caïc mãûnh âãö vaì
caïc âêch cuîng nhæ thæï tæû caïc haûng trong mäùi mãûnh âãö coï vai troì quan troüng
trong viãûc tçm ra kãút quaí. Màût khaïc, mäüt säú chæång trçnh tuy âuïng âàõn vãö
màût khai baïo nhæng laûi khäng chaûy âæåüc trong thæûc tãú. Ranh giåïi giæîa yãúu täú
thuí tuûc vaì yãúu täú khai baïo ráút khoï suy xeït. Mãûnh âãö sau âáy laì mäüt minh
chæïng vãö viãûc khai baïo âuïng, nhæng laûi hoaìn toaìn vä êch vãö màût chaûy chæång
trçnh :
ancestor(X, Z) :- ancestor(X, Z).
Do nhæîng tiãún bäü cuía kyî thuáût láûp trçnh, ngæåìi ta quan tám âãún nghéa
khai baïo âãø boí qua nhæîng chi tiãút thuí tuûc, táûn duûng nhæîng chi tiãút khai baïo
laìm låìi giaíi âån giaín hån vaì dãù hiãøu hån. Khäng phaíi laì NLT, maì chênh hãû
thäúng phaíi quaín lyï nhæîng chi tiãút thuí tuûc. Prolog laì ngän ngæî nhàòm vaìo muûc
âêch naìy. Nhæ ta âaî tháúy, Prolog chè giuïp quaín lyï âuïng âàõn mäüt pháön nhæîng
chi tiãút thuí tuûc, maì khäng thãø quaín lyï âæåüc táút caí.
48 Láûp trçnh lägich trong Prolog

Mäüt yãúu täú thæûc tãú næîa laì ngæåìi ta dãù daìng cháúp nháûn mäüt chæång trçnh
chaûy âæåüc (âuïng nghéa thuí tuûc) hån laì mäüt chæång trçnh chè âuïng âàõn vãö
màût khai baïo maì chæa chaûy âæåüc. Vç váûy, âãø giaíi quyãút mäüt baìi toaïn naìo âoï
mäüt caïch coï låüi, ngæåìi ta táûp trung giaíi quyãút nhæîng yãúu täú khai baïo, tiãún
haình chaûy thæí chæång trçnh trãn maïy, räöi sàõp âàût laûi caïc mãûnh âãö vaì caïc
âêch nãúu noï váùn chæa chaûy âuïng vãö màût thuí tuûc.

III. Vê duû : con khè vaì quaí chuäúi


III.1. Phaït biãøu baìi toaïn
Trong trê tuãû nhán taûo, ngæåìi ta thæåìng láúy âãö taìi con khè vaì quaí chuäúi
(monkey and banana problem) âãø minh hoaû viãûc håüp giaíi baìi toaïn. Sau âáy, ta
seî trçnh baìy laìm caïch naìo âãø váûn duûng so khåïp vaì quay lui cho nhæîng æïng
duûng nhæ váûy. Ta seî triãøn khai mäüt caïch phi thuí tuûc, sau âoï nghiãn cæïu tênh
thuí tuûc mäüt caïch chi tiãút.

Hçnh III.1. Minh hoaû baìi toaïn con khè vaì quaí chuäúi.

Ta sæí duûng mäüt biãún thãø (variant) cuía baìi toaïn nhæ sau : mäüt con khè
âang åí træåïc cæía mäüt càn phoìng. Trong phoìng, åí chênh giæîa tráön coï treo mäüt
quaí chuäúi. Con khè âang âoïi nãn tçm caïch âãø láúy quaí chuäúi, nhæng quaí chuäúi
laûi treo quaï cao âäúi våïi noï. ÅÍ caûnh cæía säø, coï âàût mäüt caïi häüp âãø con khè coï
thãø treìo lãn. Con khè coï thãø thæûc hiãûn caïc âäüng taïc nhæ sau : bæåïc âi trong
phoìng, nhaíy lãn häüp, di chuyãøn caïi häüp (nãúu con khè âæïng caûnh caïi häüp), vaì
Ngæî nghéa cuía chæång trçnh Prolog 49

våïi láúy quaí chuäúi nãúu noï âang âæïng trãn häüp âàût âuïng phêa dæåïi quaí chuäúi.
Cáu hoíi âàût ra laì con khè coï àn âæåüc quaí chuäúi hay khäng ?
Trong láûp trçnh, váún âãö quan troüng laì laìm sao biãøu diãùn âæåüc baìi toaïn
phuì håüp våïi ngän ngæî âang sæí duûng. Træåìng håüp cuía chuïng ta coï thãø nghé
âãún traûng thaïi cuía con khè coï thãø biãún âäøi theo thåìi gian. Traûng thaïi hiãûn
haình âæåüc xaïc âënh båíi vë trê cuía caïc âäúi tæåüng. Chàóng haûn, traûng thaïi ban
âáöu cuía con khè âæåüc xaïc âënh båíi :
(1) Con khè âang åí træåïc cæía (to the door).
(2) Con khè âang åí trãn saìn nhaì (on the floor).
(3) Caïi häüp âang åí caûnh cæía säø (to the window).
(4) Con khè chæa láúy âæåüc quaí chuäúi (not have).
Ta coï thãø nhoïm bäún thäng tin trãn thaình mäüt âäúi tæåüng coï cáúu truïc duy
nháút. Goüi state laì haìm tæí maì ta læûa choün âãø nhoïm caïc thaình pháön cuía âäúi
tæåüng. Hçnh 2.9. trçnh baìy caïch biãøu diãùn traûng thaïi âáöu laì mäüt tæåüng coï cáúu
truïc.

state

tothedoor onthefloor tothewindow nothave

Hçnh III.2. Traûng thaïi âáöu cuía con khè laì mäüt âäúi tæåüng coï cáúu truïc
gäöm bäún thaình pháön : vë trê nàòm ngang, vë trê thàóng âæïng cuía con khè,
vë trê cuía caïi häüp vaì mäüt chè dáùn cho biãút con khè âaî láúy âæåüc quaí chuäúi chæa.

III.2. Giaíi baìi toaïn våïi Prolog


Baìi toaïn con khè vaì quaí chuäúi âæåüc xem nhæ mäüt troì chåi chè coï mäüt ngæåìi
chåi. Ta hçnh thæïc hoaï baìi toaïn nhæ sau : âáöu tiãn, âêch cuía troì chåi laì tçnh
huäúng con khè láúy âæåüc quaí chuäúi, nghéa laì mäüt traûng thaïi state bäún thaình
pháön, thaình pháön thæï tæ laì possessing (chiãúm hæîu) :
state(_, _, _, possessing)
Tiãúp theo, ta tçm caïc âäüng taïc cuía con khè âãø chuyãøn tæì mäüt traûng thaïi
naìy sang mäüt traûng thaïi khaïc. Coï bäún kiãøu âäüng taïc (movement) nhæ sau :
(1) Nàõm láúy quaí chuäúi (grab).
(2) Treìo lãn häüp (climbing).
50 Láûp trçnh lägich trong Prolog

(3) Âáøy caïi häüp (pushing).


(4) Di chuyãøn (walking).
Tuyì theo traûng thaïi hiãûn haình, khäng phaíi táút caí moüi âäüng taïc âãöu coï thãø
sæí duûng. Chàóng haûn, âäüng taïc «nàõm láúy quaí chuäúi chè» coï thãø xaíy ra khi con
khè âaî âæïng trãn caïi häüp, åí âuïng vë trê phêa dæåïi quaí chuäúi (åí chênh giæîa
phoìng), vaì noï chæa nàõm láúy quaí chuäúi. Quy tàõc Prolog displacement dæåïi âáy
coï ba âäúi säú mä taí di chuyãøn cuía con khè nhæ sau :
displacement(state1, Movement, state2).
Vai troì cuía caïc âäúi säú duìng thãø hiãûn di chuyãøn laì :

State1 State2
Movement
Hçnh III.3. Di chuyãøn traûng thaïi.
Quy æåïc state1 laì traûng thaïi træåïc khi di chuyãøn, M laì di chuyãøn âaî thæûc
hiãûn, vaì state2 laì traûng thaïi sau khi di chuyãøn. Âäüng taïc «nàõm láúy quaí
chuäúi» våïi âiãöu kiãûn âáöu cáön thiãút âæåüc âënh nghéa båíi mãûnh âãö coï näüi dung :
«sau khi di chuyãøn, con khè âaî láúy âæåüc quaí chuäúi, vaì noï âang âæïng trãn caïi
häüp, åí giæîa càn phoìng». Mãûnh âãö âæåüc viãút trong Prolog nhæ sau :
displacement(
state(tothecenter, onthebox, tothecenter, nothave), % træåïc khi di
chuyãøn
grab, % di chuyãøn
state(tothecenter, onthebox, tothecenter, possessing). % sau khi di
chuyãøn
Mäüt caïch tæång tæû, ta coï thãø diãùn taí di chuyãøn cuía con khè trãn saìn nhaì
tæì mäüt vë trê nàòm ngang P1 báút kyì naìo âoï âãún mäüt vë trê måïi P2. Viãûc di
chuyãøn cuía con khè laì âäüc láûp våïi vë trê cuía caïi häüp, vaì âäüc láûp våïi sæû kiãûn con
khè âaî láúy âæåüc quaí chuäúi hay laì chæa :
displacement(
state(P1, onthefloor, G, H),
walking(P1, P2), % di chuyãøn tæì P1 âãún P2
state(P2, onthefloor, G, H).
Mãûnh âãö trãn âáy coï ráút nhiãöu nghéa :
• Di chuyãøn âaî thæûc hiãûn laì «âi tæì P1 âãún P2».
Ngæî nghéa cuía chæång trçnh Prolog 51

• Con khè åí trãn saìn nhaì træåïc vaì sau khi di chuyãøn.
• Vë trê häüp laì G khäng thay âäøi sau khi di chuyãøn.
• Quaí chuäúi váùn åí vë trê cuî træåïc vaì sau khi di chuyãøn
(chæa bë con khè láúy âi).
Mãûnh âãö naìy âàûc træng cho mäüt táûp håüp âáöy âuí caïc âäüng taïc vç coï thãø aïp
duûng cho báút kyì mäüt tçnh huäúng naìo tæång æïng våïi traûng thaïi âaî chè ra træåïc
khi di chuyãøn. Ngæåìi ta goüi caïc mãûnh âãö kiãøu naìy laì mäüt så âäö di chuyãøn.
Hai kiãøu haình âäüng khaïc laì «âáøy» vaì «treìo» cuîng âæåüc âàûc træng mäüt
caïch tæång tæû.
displacement
M
S1 S2 S3 … Sn
couldtake couldtake possessing

Hçnh III.4. Daûng âãû quy cuía vë tæì couldtake.

Cáu hoíi âàût ra cho baìi toaïn seî laì «Xuáút phaït tæì vë trê âáöu S, con khè coï
thãø láúy âæåüc quaí chuäúi khäng ?» våïi vë tæì sau âáy :
couldtake(S)
våïi tham âäúi S laì mäüt traûng thaïi chè vë trê cuía con khè. Chæång trçnh xáy
dæûng cho vë tæì naìy dæûa trãn hai quan saït sau âáy :
(1) Våïi mäùi traûng thaïi S maì con khè âaî láúy âæåüc quaí chuäúi, vë tæì
couldtake coï giaï trë true, khäng cáön mäüt di chuyãøn naìo khaïc næîa. Âiãöu
naìy tæång æïng våïi sæû kiãûn :
couldtake(state(_, _, _, possessing)).
(2) Trong caïc træåìng håüp khaïc, cáön thæûc hiãûn mäüt hoàûc nhiãöu di chuyãøn.
Xuáút phaït tæì mäüt traûng thaïi S1, con khè coï thãø láúy âæåüc quaí chuäúi
nãúu täön taûi mäüt säú láön di chuyãøn M naìo âoï tæì S1 âãún mäüt traûng thaïi
S2 sao cho trong traûng thaïi S2, con khè coï thãø láúy âæåüc quaí chuäúi.
Ta coï mãûnh âãö sau :
couldtake(S1) :-
displacement(S1, M, S2),
couldtake(S2).
Vë tæì couldtake coï daûng âãû quy, tæång tæû våïi quan hãû ancestor âaî xeït åí
âáöu chæång.
52 Láûp trçnh lägich trong Prolog

Chæång trçnh Prolog âáöy âuí nhæ sau :

displacement(
state(tothecenter, onthebox, tothecenter, nothave),
grab, % våïi láúy quaí chuäúi
state(tothecenter, onthebox, tothecenter, possessing)).
displacement(
state(P, onthefloor, P, H),
climbing, % treìo lãn häüp
state(P, onthebox, P, H)).
displacement(
state(P1, onthefloor, P1, H),
pushing(P1, P2), % âáøy caïi häüp tæì P1 âãún P2
state(P2, onthefloor, P2, H)).
displacement(
state(P1, onthefloor, G, H),
walking(P1, P2), % di chuyãøn tæì P1 âãún P2
state(P2, onthefloor, G, H)).
pushing(tothewindow, tothecenter).
walking(tothedoor, tothewindow).
% couldtake(state) : con khè coï thãø láúy âæåüc quaí chuäúi trong state
couldtake(state(_, _, _, possessing)). % træåìng håüp 1 : con khè âaî coï quaí chuäúi
couldtake(State1) :- % træåìng håüp 2 : cáön phaíi haình âäüng
displacement(State1, Move, State2), % haình âäüng
couldtake(State2). % láúy quaí chuäúi

Chæång trçnh trãn âáy âaî âæåüc phaït triãøn mäüt caïch phi thuí tuûc. Âãø xeït
tênh thuí tuûc cuía chæång trçnh, ta âàût ra cáu hoíi sau âáy :
?- couldtake(state(tothedoor, onthefloor, tothewindow, nothave)).
Yes

Âãø coï cáu traí låìi, Prolog phaíi thoaí maîn mäüt danh saïch caïc âêch theo ngæî
nghéa thuí tuûc. Âoï laì quaï trçnh tçm kiãúm cho con khè mäüt di chuyãøn håüp lyï
trong moüi di chuyãøn coï thãø. Âäi khi, quaï trçnh naìy seî dáùn âãún mäüt ngoî cuût,
âãø thoaït ra, cáön phaíi quay lui. Cáu hoíi trãn cáön quay lui mäüt láön. Caïc di
chuyãøn håüp lyï tiãúp theo âæåüc tçm tháúy ngay do caïc mãûnh âãö liãn quan âãún
quan hãû displacement coï màût trong chæång trçnh, phuì håüp våïi tçnh huäúng.
Ngæî nghéa cuía chæång trçnh Prolog 53

Tuy nhiãn, váùn coï thãø xaíy ra khaí nàng caïc di chuyãøn khäng håüp lyï. Con
khè âi tåïi âi lui maîi maì khäng chaûm âæåüc caïi häüp, hoàûc khäng coï âêch thæûc
sæû. Trong vê duû trãn, ta âaî æu tiãn quaï trçnh so khåïp caïc mãûnh âãö âãø dáùn
âãún thaình cäng.

state(tothedoor, onthefloor, tothewindow, nothave)


grab climbing pushing walking(tothedoor, P2)

failure failure failure

state(P2, onthefloor, tothewindow, nothave)


grab climbing pushing(P2, P2’)
failure backtrack

state(tothedoor, onthebox, tothewindow, nothave) state(P2’, onthefloor, P2’, nothave)


grab climbing walking pushing grab climbing

failure failure failure failure failure

state(P2’, onthebox, P2’, nothave)


Grab
P2’ = tothecenter
state(tothecenter, onthebox, tothecenter, possessing)

Hçnh III.5. Låìi giaíi cuía baìi toaïn con khè vaì quaí chuäúi.
Quaï trçnh tçm kiãúm bàõt âáöu tæì nuït trãn cuìng vaì tiãúp tuûc xuäúng dæåïi.
Caïc pheïp thæí thæûc hiãûn láön læåüt tæì traïi qua phaíi.
Chè xaíy ra mäüt láön quay lui maì thäi.
54 Láûp trçnh lägich trong Prolog

III.3. Sàõp âàût thæï tæû caïc mãûnh âãö vaì caïc âêch

III.3.1. Nguy cå gàûp caïc voìng làûp vä haûn


Xeït mãûnh âãö sau âáy :
p :- p
Nghéa cuía mãûnh âãö laì « p âuïng nãúu p âuïng». Vãö màût khai baïo, mãûnh âãö
hoaìn toaìn âuïng âàõn. Tuy nhiãn, vãö màût thuí tuûc, mãûnh âãö khäng duìng âãø
laìm gç. Trong Prolog, mãûnh âãö naìy gáy ra ràõc räúi. Ta xeït cáu hoíi :
?- p.
Sæí duûng mãûnh âãö trãn, âêch p âæåüc thay thãú båíi chênh âêch p, räöi laûi âæåüc
thay thãú båíi p, vaì cæï thãú tiãúp tuûc. Prolog bë råi vaìo tçnh traûng quáøn vä haûn.
Vê duû naìy laìm phæång tiãûn thæûc hiãûn caïc voìng làûp cuía Prolog. Tråí laûi vê
duû con khè vaì quaí chuäúi trãn âáy, ta coï thãø thay âäøi thæï tæû caïc âêch bãn
trong cuía caïc mãûnh âãö. Chàóng haûn caïc mãûnh âãö thuäüc vãö quan hãû
displacement âaî âæåüc sàõp xãúp nhæ sau :
grab, climbing, pushing, walking
(ta coï thãø bäø sung thãm mãûnh âãö descending nãúu muäún troün veûn).
Caïc mãûnh âãö naìy noïi ràòng con khè coï thãø nàõm láúy quaí chuäúi (grab), treìo
lãn häüp (climbing), v.v... Vãö màût ngæî nghéa thuí tuûc, thæï tæû caïc mãûnh âãö noïi
ràòng træåïc con khè våïi láúy âæåüc quaí chuäúi, noï phaíi treìo lãn häüp, træåïc khi
treìo lãn häüp, noï phaíi âáøy caïi häüp, v.v... Våïi thæï tæû naìy, con khè láúy âæåüc quaí
chuäúi (giaíi quyãút âæåüc baìi toaïn). Báy giåì nãúu ta thay âäøi thæï tæû thç âiãöu gç seî
xaíy ra ? Giaí thiãút ràòng mãûnh âãö walking xuáút hiãûn âáöu tiãn. Luïc naìy, viãûc
thæûc hiãûn âêch âaî âàût ra trãn âáy :
?- couldtake(state(tothedoor, onthefloor, tothewindow, nothave)).
seî taûo ra mäüt quaï trçnh thæûc thi khaïc.
Bäún danh saïch âêch âáöu tiãn nhæ cuî (caïc tãn biãún âæåüc âàût laûi) :
(1) couldtake(state(tothedoor, onthefloor, tothewindow, nothave))
Sau khi mãûnh âãö thæï hai âæåüc aïp duûng, ta coï :
(2) displacement(state(tothedoor, onthefloor, tothewindow, nothave), M’,
S2’),
couldtake(S2’)
Ngæî nghéa cuía chæång trçnh Prolog 55

Våïi chuyãøn âäüng walking(tothedoor, P2’), ta nháûn âæåüc :


(3) couldtake(state(P2’, onthefloor, tothewindow, nothave))
AÏp duûng láön næîa mãûnh âãö thæï hai cuía couldtake :
(4) displacement(state(P2’, onthefloor, tothewindow, nothave), M’’, S2’’),
couldtake(S2’’)
Tæì thåìi âiãøm naìy, sæû khaïc nhau xuáút hiãûn. Mãûnh âãö âáöu tiãn coï pháön
âáöu coï thãø so khåïp våïi âêch âáöu tiãn trãn âáy báy giåì seî laì walking (maì khäng
phaíi climbing nhæ træåïc).
Raìng buäüc laì S2’’ = state(P2’’, onthefloor, tothewindow, nothave). Danh
saïch caïc âêch tråí thaình :
(5) couldtake(state(P2’’, onthefloor, tothewindow, nothave))
Bàòng caïch aïp duûng mãûnh âãö thæï hai couldtake, ta nháûn âæåüc
(6) displacement(state(P2’’, onthefloor, tothewindow, nothave), M’’’, S2’’’),
couldtake(S2’’’)
Tiãúp tuûc aïp duûng mãûnh âãö walking cho mãûnh âãö thæï nháút vaì ta coï :
(7) couldtake(state(P2’’’, onthefloor, tothewindow, nothave))
Báy giåì ta so saïnh caïc âêch (3), (5) vaì (7). Chuïng gáön nhæ giäúng hãût nhau,
træì caïc biãún P2’, P2’’ vaì P2’’’. Nhæ ta âaî tháúy, sæû thaình cäng cuía mäüt âêch
khäng phuû thuäüc vaìo tãn caïc biãún trong âêch. Âiãöu naìy coï nghéa ràòng kãø tæì
danh saïch caïc âêch (3), quaï trçnh thæûc hiãûn khäng coï sæû tiãún triãøn naìo.
Thæûc tãú, ta nháûn tháúy ràòng mãûnh âãö thæï hai cuía couldtake vaì walking âaî
âæåüc sæí duûng qua laûi. Con khè âi loanh quanh trong phoìng maì khäng bao giåì
coï yï âënh sæí duûng caïi häüp. Do khäng coï sæû tiãún triãøn naìo, nãn vãö màût lyï
thuyãút, quaï trçnh tçm âãún quaí chuäúi seî diãùn ra mäüt caïch vä haûn. Prolog seî
khäng xæí lyï nhæîng tçnh huäúng vä êch nhæ váûy.
Vê duû naìy minh hoaû Prolog âang thæí giaíi mäüt baìi toaïn maì khäng bao giåì
âaût âæåüc låìi giaíi, dáùu ràòng låìi giaíi täön taûi. Nhæîng tçnh huäúng nhæ váûy khäng
phaíi laì hiãúm khi láûp trçnh Prolog. Ngæåìi ta cuîng hay gàûp nhæîng voìng làûp
quáøn vä haûn trong caïc ngän ngæî láûp trçnh khaïc. Tuy nhiãn, âiãöu khäng bçnh
thæåìng so våïi caïc ngän ngæî láûp trçnh khaïc laì chæång trçnh Prolog âuïng âàõn
vãö màût ngæî nghéa khai baïo, nhæng laûi khäng âuïng âàõn vãö màût thuí tuûc, nghéa
laì khäng coï cáu traí låìi âäúi våïi cáu hoíi cho træåïc.
56 Láûp trçnh lägich trong Prolog

Trong nhæîng træåìng håüp nhæ váûy, Prolog khäng thãø xoaï mäüt âêch vç
Prolog cäú gàõng âæa ra mäüt cáu traí låìi trong khi âang âi theo mäüt con âæåìng
xáúu (khäng dáùn âãún thaình cäng).
Cáu hoíi chuïng ta muäún âàût ra laì : liãûu chuïng ta coï thãø thay âäøi chæång
trçnh sao cho coï thãø dæû phoìng træåïc nguy cå bë quáøn ? Coï phaíi chuïng ta luän
luän bë phuû thuäüc vaìo sæû sàõp âàût thæï tæû âuïng âàõn cuía caïc mãûnh âãö vaì caïc
âêch ? Roî raìng ràòng caïc chæång trçnh låïn seî tråí nãn dãù sai soït nãúu phaíi dæûa
trãn mäüt thæï tæû naìo âoï cuía caïc mãûnh âãö vaì caïc âêch. Täön taûi nhiãöu phæång
phaïp khaïc cho pheïp loaûi boí caïc voìng làûp vä haûn, täøng quaït hån vaì âaïng tin
cáûy hån so våïi phæång phaïp sàõp âàût thæï tæû. Sau âáy, chuïng ta seî sæí duûng
thæåìng xuyãn nhæîng phæång phaïp naìy trong viãûc tçm kiãúm caïc con âæåìng,
håüp giaíi caïc baìi toaïn vaì duyãût caïc âäö thë.

III.3.2. Thay âäøi thæï tæû mãûnh âãö vaì âêch trong chæång trçnh
Ngay caïc vê duû åí âáöu chæång, ta âaî tháúy nguy cåí xaíy ra caïc voìng làûp vä
haûn. Chæång trçnh mä taí quan hãû täø tiãn :
ancestor(X, Z) :-
parent(X, Z).
ancestor(X, Z) :-
parent(X, Y),
ancestor(Y, Z).
Ta haîy xeït mäüt säú biãún thãø cuía chæång trçnh naìy. Vãö màût khai baïo, táút caí
caïc chæång trçnh laì tæång âæång, nhæng vãö màût thuí tuûc, chuïng seî khaïc
nhau. Tham khaío ngæî nghéa khai baïo cuía Prolog, khäng aính hæåíng âãún
nghéa khai baïo, ta coï thãø thay âäøi nhæ sau :
(1) Thæï tæû caïc mãûnh âãö trong mäüt chæång trçnh, vaì
(2) Thæï tæû caïc âêch bãn trong thán cuía caïc mãûnh âãö.
Thuí tuûc ancestor trãn âáy gäöm hai mãûnh âãö, âuäi mãûnh âãö thæï nháút coï
mäüt âêch con vaì âuäi mãûnh âãö thæï hai coï hai âêch con. Nhæ váûy chæång trçnh
seî coï bäún biãún thãø (=1×2×2) maì caí bäún âãöu coï cuìng nghéa khai baïo. Ta nháûn
âæåüc nhæ sau :
(1) Âaío thæï tæû caïc mãûnh âãö, vaì
(2) Âaío thæï tæû caïc âêch cho mäùi sàõp âàût thæï tæû caïc mãûnh âãö.
Ngæî nghéa cuía chæång trçnh Prolog 57

Hçnh dæåïi âáy mä taí bäún thuí tuûc anc1, anc2, anc3, anc4 :
% Thuí tuûc gäúc
anc1(X, Z) :-
parent(X, Z).
anc1 (X, Z) :-
parent(X, Y),
anc1 (Y, Z).
% Biãún thãø a : hoaïn âäøi caïc mãûnh âãö
anc2 (X, Z) :-
parent(X, Y),
anc2 (Y, Z).
anc2(X, Z) :-
parent(X, Z).
% Biãún thãø b : hoaïn âäøi caïc âêch cuía mãûnh âãö thæï hai
anc3(X, Z) :-
parent(X, Z).
anc3 (X, Z) :-
anc3 (X, Y),
parent(Y, Z).
% Biãún thãø c : hoaïn âäøi caïc âêch vaì caïc mãûnh âãö
anc4 (X, Z) :-
anc4 (X, Y),
parent(Y, Z).
anc4(X, Z) :-
parent(X, Z).
% Caïc cáu hoíi âæåüc âàût ra láön læåüt nhæ sau :
?- anc1(tom, pat).
-> Yes
?- anc2(tom, pat).
-> Yes
?- anc3(tom, pat).
-> Yes
?- anc4(tom, pat).
ERR 211 Not enough local stack
58 Láûp trçnh lägich trong Prolog

anc2(X, Z) :- anc2(tom, pat)


parent (X, Y),
anc2 (Y, Z), parent (tom, Y’)
anc2(X , Z) :- anc2(Y’, pat)
parent (X, Z). Y’ = bob
anc2(bob, pat)

parent (bob, Y’’) parent (bob, pat)


anc2 (Y’’, pat) thaình cäng
Y” = ann
anc2(ann, pat)

parent(ann, Y’’’) parent (ann, pat) Y’’ = pat


anc2(Y’’’, pat) tháút baûi
tháút baûi anc2(pat, pat)

parent (pat, Y’’’) parent (pat, pat)


anc2(Y’’’, pat) tháút baûi
Y’’’ = jim
anc2 (jim, pat)

parent(jim, Y’’’) parent (jim, pat)


anc2(Y’’’, pat) tháút baûi
tháút baûi

Hçnh III.6. Biãún thãø a cuía quan hãû täø tiãn traí låìi cáu hoíi
“Tom coï phaíi laì mäüt täø tiãn cuía Pat ?”
Trong træåìng håüp cuäúi cuìng, Prolog khäng thãø tçm ra cáu traí låìi. Do bë
quáøn vä haûn nãn Prolog thäng baïo “khäng âuí bäü nhåï”. Hçnh 2.4. mä taí quaï
trçnh thæûc hiãûn cuía anc1 (træåïc âáy laì ancestor) cho cuìng mäüt cáu hoíi.
Hçnh 2.13 (a, b, c) mä taí quaï trçnh thæûc hiãûn cuía anc2, anc3 vaì anc4. Ta
tháúy anc4 khäng coï hy voüng vaì anc2 keïm hiãûu quaí hån so våïi anc1 do thæûc
hiãûn nhiãöu láön tçm kiãúm vaì quay lui hån trong cáy.
Ngæî nghéa cuía chæång trçnh Prolog 59

So saïnh caïc quaï trçnh so khåïp trong caïc hçnh veî, ta tháúy ràòng cáön khai
baïo caïc mãûnh âãö âuí âån giaín khi giaíi caïc baìi toaïn. Âäúi våïi baìi toaïn quan hãû
täø tiãn, caí bäún biãún thãø âãöu dæûa trãn hai yï :
• kiãøm tra nãúu hai tham âäúi cuía quan hãû täø tiãn thoaí maîn quan hãû parent.
• giai âoaûn phæïc taûp nháút laì tçm ai âoï “giæîa” nhæîng ngæåìi laì parent hay
ancestor.

anc3(X, Z) :- anc3(tom, pat)


parent(X, Z).
parent (tom, pat) anc3(tom, Y’)
anc3(X, Z) :-
tháút baûi parent(Y’, pat)
anc3(X, Y),
parent(Y, Z).
parent(tom, Y’)
parent(Y’, pat)
Y’ = bob
paren(bob, pat)
thaình cäng

Hçnh III.7. Biãún thãø b cuía quan hãû täø tiãn traí låìi cáu hoíi
“Tom coï phaíi laì mäüt täø tiãn cuía Pat ?”

anc4(X, Z) :- anc4(tom, pat)


anc4(X, Y),
parent(Y, Z). anc4(tom, Y’)
parent(Y’, pat)
anc4(X, Z) :-
parent(X, Z).
anc4(tom, Y’‘)
parent(Y’‘, Y’)
parent(Y’, pat)

anc4(tom, Y’’’)
parent(Y’’’, Y’‘)
parent(Y’‘, Y’)
parent(Y’, pat)

Hçnh III.8. Biãún thãø c cuía quan hãû täø tiãn traí låìi cáu hoíi
“Tom coï phaíi laì mäüt täø tiãn cuía Pat ?”
60 Láûp trçnh lägich trong Prolog

Trong säú bäún biãún thãø cuía quan hãû ancestor, chè coï anc1 laì thæûc hiãûn quaï
trçnh so khåïp âån giaín nháút. Trong khi âoï, anc4 bàõt âáöu quaï trçnh khoï khàn
nháút. Coìn anc2 vaì anc3 nàòm giæîa hai thaïi cæûc naìy. Duì ta coï xem xeït chi tiãút
caïc quaï trçnh thæûc hiãûn thãú naìo âi chàng næîa, thç anc1 váùn laì luáût âån giaín
nháút. Ngæåìi ta khuyãn nãn sæí duûng caïch naìy khi láûp trçnh.
Ta khäng cáön so saïnh bäún biãún thãø maì xem xeït våïi kiãøu cáu hoíi naìo thç
mäùi biãún thãø dáùn âãún thaình cäng hay tháút baûi. Ta dãù nháûn tháúy ràòng caí hai
thuí tuûc anc1 vaì anc2 âãöu coï khaí nàng âæa ra cáu traí låìi cho moüi kiãøu cáu
hoíi. Coìn anc3 thç khäng chàõc chàõn. Chàóng haûn cáu hoíi sau âáy gáy ra tháút
baûi :
anc3(liz, jim)
ERR 212 Not enough global stack
vç dáùn âãún nhæîng låìi goüi âãû quy vä haûn. Nhæ váûy, ta khäng thãø xem anc3 laì
âuïng âàõn vãö màût thuí tuûc.

Toïm tàõt chæång 2


• Nhæîng khaïi niãûm âaî âæåüc giåïi thiãûu :
âêch thoaí maîn, thaình cäng
âêch khäng thoaí maîn/bë tháút baûi,
âêch bë xoaï,
nghéa khai baïo, nghéa thuí tuûc, nghéa lägich,
quay lui.
thãø nghiãûm cuía mäüt mãûnh âãö, biãún thãø cuía mäüt mãûnh âãö
• Láûp trçnh trãn ngän ngæî Prolog laì âënh nghéa caïc quan hãû vaì âàût cáu hoíi
trãn caïc quan hãû naìy.
• Mäüt chæång trçnh Prolog bao gäöm caïc mãûnh âãö. Coï ba kiãøu mãûnh âãö : sæû
kiãûn, luáût vaì cáu hoíi.
• Mäüt quan hãû coï thãø âæåüc âàûc taí båíi caïc sæû kiãûn, bàòng caïch ghi nháûn bäü−n
âäúi tæåüng thoaí maîn quan hãû, hay thiãút láûp caïc luáût liãn quan âãún quan hãû.
• Mäüt thuí tuûc laì mäüt táûp håüp caïc mãûnh âãö liãn quan âãún cuìng mäüt quan hãû.
Ngæî nghéa cuía chæång trçnh Prolog 61

• Viãûc âàût caïc cáu hoíi trãn caïc quan hãû tæång tæû viãûc váún tin mäüt cå såí dæî
liãûu. Prolog traí låìi cáu hoíi bàòng caïch liãût kã táûp håüp caïc âäúi tæåüng laìm
thoaí maîn cáu hoíi naìy.
• Trong Prolog, khi mäüt âäúi tæåüng laìm thoaí maîn mäüt cáu hoíi thç viãûc traí låìi
cáu hoíi luän luän laì mäüt quaï trçnh phæïc taûp sæí duûng suy diãùn lägich, khai
thaïc caïc khaí nàng khaïc nhau, vaì cå chãú quay lui. Prolog tiãún haình tæû
âäüng quaï trçnh naìy vaì vãö nguyãn tàõc, NSD coï thãø hiãøu âæåüc.
• Ngæåìi ta phán biãût nghéa khai baïo vaì nghéa thuí tuûc khi láûp trçnh. Mäüt
chæång trçnh Prolog thæåìng coï nghéa khai baïo laì chuí yãúu. Tuy nhiãn,
ngæåìi ta váùn tçm tháúy nghéa thuí tuûc trong mäüt säú chæång trçnh Prolog.
• Theo nghéa thuí tuûc, chæång trçnh Prolog thæûc hiãûn quaï trçnh tçm kiãúm, so
khåïp vaì quay lui.
• Ngæî nghéa khai baïo cuía Prolog xaïc âënh nãúu mäüt âêch laì âuïng âäúi våïi mäüt
chæång trçnh âaî cho, tæång æïng våïi raìng buäüc cuía caïc biãún.
• Ngæåìi ta quy æåïc viãút pheïp giao (and) cuía hai âêch bàòng caïch âàût mäüt dáúu
pháøy åí giæîa chuïng, pheïp hoàûc (or) båíi mäüt dáúu cháúm pháøy.
• Ngæî nghéa thuí tuûc cuía Prolog âæåüc thãø hiãûn båíi mäüt thuí tuûc tçm kiãúm laìm
thoaí maîn mäüt danh saïch caïc âêch tæì mäüt chæång trçnh âaî cho. Nãúu tçm
kiãúm thoaí maîn, Prolog traí vãö caïc raìng buäüc caïc biãún tæång æïng. Nãúu taûi
mäüt bæåïc naìo âoï bë tháút baûi, thuí tuûc naìy cho pheïp tæû âäüng quay lui
(backtracking) âãø tçm kiãúm tçm caïc khaí nàng khaïc coï thãø dáùn âãún thaình
cäng.
• Nghéa khai baïo cuía caïc chæång trçnh thuáön Prolog khäng phuû thuäüc sæû
sàõp âàût caïc mãûnh âãö, cuîng nhæ khäng phuû thuäüc sæû sàõp âàût caïc âêch bãn
trong caïc mãûnh âãö.
• Nghéa thuí tuûc phuû thuäüc thæï tæû caïc âêch vaì caïc mãûnh âãö. Thæï tæû sàõp âàût
naìy coï thãø aính hæåíng âãún tênh hiãûu quaí chaûy chæång trçnh, vaì coï thãø dáùn
âãún nhæîng låìi goüi âãû quy vä haûn.
• Cho træåïc mäüt khai baïo âuïng, coï khaí nàng laìm täúi æu hiãûu quaí váûn haình
cuía hãû thäúng bàòng caïch thay âäøi thæï tæû caïc mãûnh âãö, maì váùn âaím baío
tênh âuïng âàõn vãö màût khai baïo. Sæû sàõp âàût laûi thæï tæû caïc âêch vaì caïc
mãûnh âãö laì mäüt trong nhæîng phæång phaïp nhàòm traïnh caïc voìng làûp quáøn
vä haûn.
62 Láûp trçnh lägich trong Prolog

• Coìn coï nhæîng kyî thuáût khaïc täøng quaït hån âãø traïnh caïc voìng làûp quáøn vä
haûn, vaì laìm cho chæång trçnh váûn haình âaïng tin cáûy hån.

Baìi táûp chæång 2


1. Tæì chæång trçnh Prolog dæåïi âáy:
aeroplane(concorde).
aeroplane(jumbo).
on(fred, concorde).
on(jim, No_18_bus).
bird(percy).
animal(leo).
animal(tweety).
animal(peter).
has_feathers(tweety).
has_feathers(peter).
flies(X) :- bird(X).
flies(X) :- aeroplane(X).
flies(X) :- on(X, Y), aeroplane(Y).
bird(X) :- animal(X), has_feathers(X).
Haîy cho biãút caïc kãút quaí nháûn âæåüc tæì cáu hoíi :
?- flies(X).
bàòng caïch liãût kã theo thæï tæû :
X=kq1;
X=kq2; v.v...
2. Sæí duûng så âäö âaî cho trong pháön lyï thuyãút, haîy tçm hiãøu caïch Prolog tçm
ra caïc cáu traí låìi âäúi våïi caïc cáu hoíi dæåïi âáy. Veî så âäö minh hoüa tæång
æïng theo kiãøu så âäö âaî cho. Coï khaí nàng Prolog quay lui khäng ?
a) ?- parent(pam , bob).
b) ?- mother(pam , bob).
c) ?- grand parent(pam, ann).
d) ?- grand parent(bob , jim).
3. Viãút laûi chæång trçnh dæåïi âáy, nhæng khäng sæí duûng dáúu cháúm hoíi :
Ngæî nghéa cuía chæång trçnh Prolog 63

translate (Number, word) :-


Number = 1, Word = one;
Number = 2, Word = two;
Number = 3, Word = three.
4. Tæì chæång trçnh execute trong lê thuyãút, haîy mä phoíng quaï trçnh thæûc
hiãûn cuía Prolog cho cáu hoíi sau :
?- thick( X ) , dack( X ).

Haîy so saïnh caïc quaï trçnh mä phoíng cáu hoíi trãn vaì caïc âêch dæåïi âáy :
?- dack( X ), thick( X ).
5. Âiãöu gç xaíy ra khi yãu cáöu Prolog traí låìi cáu hoíi sau âáy :
?- X = f( X ).

So khåïp coï thaình cäng khäng ?


Giaíi thêch vç sao mäüt säú hãû thäúng Prolog traí låìi :
X = f(f(f(f(f(f(f(f(f(f( ... ))))))))))
Yes
6. Tçm caïc thay thãú håüp thæïc vaì kãút quaí nãúu coï cuía caïc pheïp so khåïp sau
âáy :
a(1, 2) = a(X, X).
a(X, 3) = a(4, Y).
a(a(3, X)) = a(Y).
1+2 = 3.
X = 1+2.
a(X, Y) = a(1, X).
a(X, 2) = a(1, X).
7. Cho træåïc chæång trçnh dæåïi âáy :
f( 1, one ).
f( s(1) , two ).
f( s( s( 1 ) ) , three ).
f( s( s( s( X ) ) ), N ) :-
f(X , N+3).

Haîy cho biãút caïch Prolog traí låìi caïc cáu hoíi sau âáy (khi coï nhiãöu cáu traí låìi
coï thãø, haîy âæa ra êt nháút hai cáu traí låìi) ?
a) ?- f( s( 1 ) , A ).
64 Láûp trçnh lägich trong Prolog

b) ?- f( s( s( 1 ) ) , two ).
c) ?- f( s( s( s( s( s( s( 1 ) ) ) ) ) ), C ).
d) ?- f( D, three ).
8. Cho caïc vë tæì p, a1, a2, a3, a4 âæåüc âënh nghéa båíi caïc mãûnh âãö sau âáy :
p(a, b).
p(b, c b).
a1(X, Y) :- p(X, Y).
a1(X, Y) :- p(X, Z), a1(Z, Y).
a2(X, Y) :- p(X, Y).
a2(X, Y) :- a2(Z, Y), p(X, Z).
a3(X, Y) :- p(X, Z), a3(Z, Y).
a3(X, Y) :- p(X, Y).
a4(X, Y) :- a4(Z, Y), p(X, Z).
a4(X, Y) :- p(X, Y).
a) Veî cáy håüp giaíi SLD coï caïc gäúc laì a1(a, X), a2(a, X), a3(a, X), a4(a, X) ?

b) So saïnh nghéa lägich cuía caïc vë tæì a1, a2, a3, a4 ?


9. Viãút goïi caïc mãûnh âãö âënh nghéa caïc haìm sau :
a) greathan(X, N) traí vãö giaï trë X nãúu X > N, traí vãö N nãúu khäng phaíi.
b) sum_diff(X, Y, X) traí vãö trong Z giaï trë täøng X + Y nãúu X > Y, traí vãö
hiãûu X - Y nãúu khäng phaíi.
CHÆÅNG 3

Caï c pheï p toaï n vaì säú hoü c


Chæång naìy trçnh baìy säú hoüc så cáúp, caïc pheïp toaïn vaì mäüt säú vë tæì chuáøn
âæåüc sæí duûng trong caïc chæång trçnh Prolog.

I. Säú hoüc
I.1. Caïc pheïp toaïn säú hoüc
Nhæ âaî biãút, Prolog laì ngän ngæî chuí yãúu duìng âãø xæí lyï kyï hiãûu, khäng
thêch håüp âãø tênh toaïn säú. Do váûy, caïc phæång tiãûn tênh toaïn trong háöu hãút
caïc hãû thäúng Prolog âãöu ráút haûn chãú. Sau âáy laì baíng caïc pheïp toaïn säú hoüc
chuáøn (standard arithmetic operations) cuía Prolog :

Kyï hiãûu Pheïp toaïn


+ Cäüng (addition)
- Træì (subtraction)
* Nhán (multiplication)
/ Chia säú thæûc (real division)
// Chia säú nguyãn (integer division)
mod Chia láúy pháön dæ (modulus)
** Luyî thæìa (power)

I.2. Biãøu thæïc säú hoüc


Biãøu thæïc säú hoüc (arithmetic expressions) âæåüc xáy dæûng nhåì vë tæì is. Vë
tæì naìy laì mäüt pheïp toaïn tiãön täú (infix operator) coï daûng :
Number is Expr

65
66 Láûp trçnh lägich trong Prolog

Tham âäúi bãn traïi pheïp toaïn is laì mäüt âäúi tæåüng så cáúp. Tham âäúi bãn
phaíi laì mäüt biãøu thæïc säú hoüc âæåüc håüp thaình tæì caïc pheïp toaïn säú hoüc, caïc säú
vaì caïc biãún. Vç pheïp toaïn is seî khåíi âäüng viãûc tênh toaïn, cho nãn khi thæûc
hiãûn âêch naìy, táút caí caïc biãún cáön phaíi âæåüc raìng buäüc våïi caïc giaï trë säú.
Prolog so khåïp thaình cäng nãúu Number khåïp âæåüc våïi Expr. Nãúu Expr laì kiãøu
thæûc (float) thç âæåüc xem nhæ mäüt soï nguyãn.
Vê duû I.1 :
?- X is 3*4.
X = 12
Yes
?- is(X, 40+50).
X = 90
Yes
?- 1.0 is sin(pi/2).
No % sai do sin(pi/2) âæåüc laìm troìn thaình 1
?- 1.0 is float(sin(pi/2)).
Yes
Trong Prolog, caïc pheïp toaïn säú hoüc keïo theo sæû tênh toaïn trãn caïc dæî liãûu.
Âãø thæûc hiãûn caïc pheïp toaïn säú hoüc, cáön biãút caïch goüi duìng theo kiãøu Prolog
maì khäng thãø goüi træûc tiãúp ngay âæåüc nhæ trong caïc ngän ngæî láûp trçnh
mãûnh lãûnh.
Chàóng haûn, nãúu NSD cáön cäüng hai säú 1 vaì 2 maì laûi viãút nhæ sau :
?- X = 1 + 2
thç Prolog seî traí låìi theo kiãøu cuía Prolog :
X=1+2
maì khäng phaíi laì X = 3 nhæ mong muäún. Lyï do ráút âån giaín : biãøu thæïc
X = 1 + 2 chè laì mäüt haûng cuía Prolog maì haìm tæí chênh laì +, coìn 1 vaì 2 laì caïc
tham âäúi cuía noï. Khäng coï gç trong âêch træåïc noï âãø Prolog tiãún haình pheïp
cäüng. Sau âáy laì mäüt säú vê duû :
?- X = 1 + 1 + 1.
X = 1 + 1 + 1 (ou X = +(+(1, 1), 1)).
Âãø Prolog tiãún haình tênh toaïn trãn caïc pheïp toaïn säú hoüc, sæí duûng pheïp
toaïn is nhæ sau :
?- X is 1 + 2.
X=3
Caïc pheïp toaïn vaì säú hoüc 67

Pheïp cäüng thæûc hiãûn âæåüc laì nhåì mäüt thuí tuûc âàûc biãût kãút håüp våïi pheïp
toaïn +. Nhæîng thuí tuûc nhæ váûy âæåüc goüi laì thuí tuûc thæåìng truï (built-in
procedures).
?- X = 1 + 1 + 1, Y is X.
X = 1 + 1 + 1, Y = 3.
?- X is 1 + 1 + a.
ERROR: Arithmetic: `a/0' is not a function (sai do a khäng phaíi laì haìm säú)
?- X is 1 + 1 + Z.
ERROR: Arguments are not sufficiently instantiated (sai do a khäng phaíi laì
säú)
?- Z = 2, X is 1 + 1 + Z.
Z=2
X=4
Âäü æu tiãn cuía caïc pheïp toaïn säú hoüc tiãön âënh cuía Prolog cuîng laì âäü æu
tiãn thoaí maîn tênh cháút kãút håüp trong toaïn hoüc. Caïc càûp dáúu ngoàûc coï thãø
laìm thay âäøi thæï tæû âäü æu tiãn giæîa caïc pheïp toaïn. Chuï yï ràòng +, -, *, / vaì //
âæåüc âënh nghéa nhæ laì yfx, coï nghéa laì viãûc tênh toaïn âæåüc thæûc hiãûn tæì traïi
sang phaíi. Vê duû, biãøu thæïc :
X is 5 -2 – 1
âæåüc giaíi thêch nhæ laì :
X is ( 5 -2 ) - 1
Do âoï :
?- X is 5 -2 - 1.
X=2
Yes
?- X = 5 -2 - 1.
X = 5-2-1
Yes
Caïc pheïp so saïnh giaï trë säú hoüc trong Prolog âæåüc thæûc hiãûn theo nghéa
Toaïn hoüc thäng thæåìng. Chàóng haûn, ta cáön so saïnh nãúu têch cuía 277 våïi 37
laì låïn hån 10000 våïi âêch sau :
?- 277 * 37 > 10000.
Yes
68 Láûp trçnh lägich trong Prolog

Báy giåì giaí sæí ta coï quan hãû birth, cho pheïp liãn hãû mäüt ngæåìi våïi ngaìy
thaïng nàm sinh cuía ngæåìi âoï. Ta coï thãø tçm âæåüc tãn cuía nhæîng ngæåìi sinh
ra giæîa nàm 1950 vaì nàm 1960 (kãø caí hai nàm naìy) bàòng caïch âàût cáu hoíi :
?- birth( Name, Year ), Year >= 1950, Year <= 1960.
% kãút quaí traí vãö laì tãn nhæîng ngæåìi sinh ra trong khoaíng 1950 - 1960
Yes
Prolog coï sàôn caïc haìm säú hoüc nhæ : sin, cos, tan, atan, sqrt, pi, e, exp, log,
...
Vê duû I.2 :
?- X is exp(10).
X = 22026.5
Yes
?- X is sqrt(9).
X=3
Yes
7 ?- X is abs(1.99).
X = 1.99
Yes
?- X is pi.
X = 3.14159
Yes

I.3. Âënh nghéa caïc pheïp toaïn trong Prolog


Biãøu thæïc trong toaïn hoüc thæåìng âæåüc viãút dæåïi daûng trung täú (infix) nhæ
laì :
2*a+b*c
våïi + vaì * laì caïc pheïp toaïn (operator), coìn a, b vaì c laì caïc toaïn haûng
(operand), hay tham âäúi (argument). Biãøu thæïc trãn coìn âæåüc viãút dæåïi daûng
tiãön täú (prefix) nhåì caïc haìm tæí + vaì * nhæ sau :
+( *(2, a), *(b, c) )
hoàûc daûng háûu täú (postfix) nhæ sau :
( (2, a) *, (b, c) * )+
Do thoïi quen, ngæåìi ta thêch viãút caïc biãøu thæïc åí daûng trung täú âãø dãù âoüc
hån. Prolog cho pheïp viãút caïc biãøu thæïc dæåïi daûng trung täú, laì biãøu diãùn bãn
Caïc pheïp toaïn vaì säú hoüc 69

ngoaìi, nhæng thæûc cháút, caïc biãøu thæïc âæåüc biãøu diãùn bãn trong váùn åí daûng
tiãön täú, theo quy æåïc viãút caïc haûng trong mäüt mãûnh âãö.
+

* *

2 a b c

Hçnh I.1. Biãøu diãùn daûng cáy cuía biãøu thæïc 2 ∗ a + b ∗ c


Khi viãút a + b, Prolog hiãøu ràòng âoï laì biãøu thæïc +(a, b). Âãø Prolog coï thãø
hiãøu âæåüc âuïng âàõn caïc biãøu thæïc nhæ laì a + b ∗ c, cáön cho Prolog biãút ràòng
pheïp nhán ∗ coï æu tiãn cao hån pheïp cäüng +. Khi âoï biãøu thæïc naìy phaíi âæåüc
viãút dæåïi daûng :
+( a, ∗(b, c) )
maì khäng phaíi laì :
∗( + (a, b), c)
Prolog quy æåïc pheïp toaïn coï âäü æu tiãn cao nháút laì haìm tæí chênh cuía
haûng. Nãúu caïc biãøu thæïc chæïa + vaì ∗ tuán theo nhæîng quy æåïc thäng thæåìng,
thç caïch viãút a + b ∗ c vaì a + (b ∗ c) chè laì mäüt. Coìn nãúu muäún thay âäøi thæï tæû
æu tiãn, thç cáön viãút roî raìng bàòng caïch sæí duûng caïc càûp dáúu ngoàûc (a + b) ∗ c :
Mäùi NLT coï thãø âënh nghéa caïc pheïp toaïn riãng cuía mçnh, chàóng haûn
âënh nghéa caïc nguyãn tæí is vaì support nhæ laì nhæîng pheïp toaïn trung täú âãø
viãút caïc sæû kiãûn trong mäüt chæång trçnh. Chàóng haûn :
tom bald
wall support ceiling
laì nhæîng sæû kiãûn âæåüc viãút trong Prolog :
is( tom, bald ).
support( wall, ceiling ).
Mäùi pheïp toaïn laì mäüt nguyãn tæí coï âäü æu tiãn laì mäüt giaï trë säú, tuyì thuäüc
phiãn baín Prolog, thäng thæåìng nàòm trong khoaíng giæîa 1 vaì 1200. Caïc pheïp
toaïn âæåüc âàûc taí båíi häùn håüp tãn pheïp toaïn f vaì caïc biãún (tham âäúi) x vaì y.
Mäùi âàûc taí cho biãút caïch kãút håüp (associative) pheïp toaïn âoï vaì âæåüc choün sao
cho phaín aïnh âæåüc cáúu truïc cuía biãøu thæïc. Mäüt pheïp toaïn trung täú âæåüc kyï
hiãûu båíi mäüt f âàût giæîa hai tham âäúi daûng xfy. Coìn caïc pheïp toaïn tiãön täú vaì
70 Láûp trçnh lägich trong Prolog

háûu täú chè coï mäüt tham âäúi âæåüc âàût træåïc (hoàûc âàût sau tæång æïng) dáúu pheïp
toaïn f.
Coï ba nhoïm kiãøu pheïp toaïn trong Prolog nhæ sau :

Caïc pheïp toaïn Khäng kãút håüp Kãút håüp phaíi Kãút håüp traïi
Trung täú xfx xfy yfx

Tiãön täú fx fy

Háûu täú xf yf

Hçnh I.2. Ba nhoïm kiãøu pheïp toaïn trong Prolog.


Coï sæû khaïc nhau giæîa x vaì y. Âãø giaíi thêch, ta âæa vaìo khaïi niãûm âäü æu
tiãn cuía tham âäúi. Nãúu caïc dáúu ngoàûc bao quanh mäüt tham âäúi, hay tham
âäúi naìy laì mäüt âäúi tæåüng khäng coï cáúu truïc, thç âäü æu tiãn cuía noï bàòng 0.
Âäü æu tiãn cuía mäüt cáúu truïc laì âäü æu tiãn cuía haìm tæí chênh. Do x laì mäüt
tham âäúi nãn âäü æu tiãn cuía x phaíi tháúp hån hàón âäü æu tiãn cuía pheïp toaïn f,
coìn tham âäúi y coï âäü æu tiãn tháúp hån hoàûc bàòng âäü æu tiãn cuía pheïp toaïn f.
Khi gàûp mäüt biãøu thæïc chæïa pheïp toaïn op daûng :
a op b op c
Tênh kãút håüp xaïc âënh vë trê dáúu ngoàûc theo thæï tæû æu tiãn nhæ sau :
• Nãúu laì kãút håüp traïi, ta coï : (a op b) op c
• Nãúu laì kãút håüp phaíi, ta coï : a op (b op c)
Caïc quy tàõc trãn cho pheïp loaûi boí tênh nháûp nhàòng cuía caïc biãøu thæïc
chæïa caïc pheïp toaïn coï cuìng âäü æu tiãn. Chàóng haûn :
a-b-c
seî âæåüc hiãøu laì (a - b ) - c, maì khäng phaíi a - (b - c). ÅÍ âáy, pheïp træì «-» coï
kiãøu trung täú yfx. Xem Hçnh I.3 dæåïi âáy.
Báy giåì ta láúy mäüt vê duû khaïc vãö pheïp toaïn tiãön täú mäüt ngäi not. Nãúu not
âæåüc xãúp kiãøu fy, thç biãøu thæïc sau âáy viãút âuïng :
not not p
Caïc pheïp toaïn vaì säú hoüc 71

- -

- c a -

âäü æu tiãn 0 âäü æu tiãn 0


a b b c

Caïch giaíi thêch 1 : (a - b ) – c Caïch giaíi thêch 2 : a - (b - c)


Hçnh I.3. Hai caïch giaíi thêch cho biãøu thæïc a - b - c våïi giaí thiãút ràòng pheïp træì «-» coï
âäü æu tiãn laì 500. Nãúu «-» laì yfx, thç caïch giaíi thêch 2 laì sai
vç âäü æu tiãn cuía b - c khäng tháúp hån âäü æu tiãn cuía «-».
Traïi laûi, nãúu pheïp toaïn not âæåüc âënh nghéa nhæ laì fx, thç biãøu thæïc trãn
seî khäng coìn âuïng næîa, vç ràòng tham âäúi cuía not âáöu tiãn laì not p, seî coï cuìng
âäü æu tiãn våïi noï. Trong træåìng håüp naìy, biãøu thæïc phaíi âæåüc viãút kãút håüp våïi
caïc càûp dáúu ngoàûc :
not ( not p )

Tênh dãù âoüc cuía mäüt chæång trçnh tuyì thuäüc vaìo caïch sæí duûng caïc pheïp
toaïn. Trong caïc chæång trçnh Prolog, nhæîng mãûnh âãö sæí duûng pheïp toaïn måïi
do ngæåìi duìng âënh nghéa thæåìng âæåüc goüi laì caïc chè dáùn hay âënh hæåïng
(directive). Caïc chè dáùn phaíi xuáút hiãûn træåïc khi mäüt pheïp toaïn måïi âæåüc sæí
duûng âãún trong mäüt mãûnh âãö, coï daûng nhæ sau :
:- op(Âäü æu tiãn, Caïch kãút håüp, Tãn pheïp toaïn).
Chàóng haûn ngæåìi ta âënh nghéa pheïp toaïn is nhåì chè dáùn :
:- op( 600, xfx, is ).
Chè dáùn naìy baïo cho Prolog biãút ràòng is seî âæåüc sæí duûng nhæ laì mäüt pheïp
toaïn coï âäü æu tiãn laì 600, coìn kyï hiãûu âàûc taí xfx chè âënh âáy laì mäüt pheïp
toaïn trung täú. YÏ nghéa cuía xfx nhæ sau : f laì dáúu pheïp toaïn âæåüc âàût åí giæîa,
coìn x laì tham âäúi âæåüc âàût hai bãn dáúu pheïp toaïn.
Viãûc âënh nghéa mäüt pheïp toaïn khäng keïo theo mäüt haình âäüng (action)
hoàûc mäüt thao taïc (opration) naìo. Vãö nguyãn lyï, khäng mäüt thao taïc naìo trãn
dæî liãûu âæåüc kãút håüp våïi mäüt pheïp toaïn (træì mäüt vaìi træåìng håüp hiãúm gàûp âàûc
biãût, nhæ caïc pheïp toaïn säú hoüc). Tæång tæû nhæ moüi haìm tæí, caïc pheïp toaïn chè
âæåüc duìng âãø cáúu truïc caïc haìm tæí, maì khäng keïo theo mäüt thao taïc naìo trãn
caïc dæî liãûu, dáùu ràòng tãn goüi «pheïp toaïn» coï thãø gåüi lãn vai troì hoaût âäüng.
72 Láûp trçnh lägich trong Prolog

Prolog cung cáúp sàôn mäüt säú pheïp toaïn chuáøn. Nhæîng pheïp toaïn tiãön âënh
nghéa naìy thay âäøi tuìy theo phiãn baín Prolog. Hçnh 3.5 dæåïi âáy trçnh baìy
mäüt säú pheïp toaïn chuáøn tiãön âënh nghéa cuía Prolog. Chuï yï ràòng cuìng mäüt
mãûnh âãö coï thãø âënh nghéa nhiãöu pheïp toaïn, miãùn laì chuïng cuìng kiãøu vaì
cuìng âäü æu tiãn. Caïc tãn pheïp toaïn âæåüc viãút trong mäüt danh saïch.
Caïc pheïp toaïn tiãön âënh nghéa trong Prolog nhæ sau :

Âäü æu tiãn Caïch kãút håüp Caïc pheïp toaïn


1200 xfx -->, :-
1200 fx :-, ?-
1100 xfy ;, |
1000 xfy ,
900 fy \+
900 fx ~
<, =, =.., =@=, =:=, =<, ==, =\=, >, >=, @<, @=<, @>,
700 xfx
@>=, \=, \==, is
600 xfy :
500 yfx +, -, /\, \/, xor
500 fx +, -, ?, \
400 yfx *, /, //, <<, >>, mod, rem
200 xfx **
200 xfy ^

Hçnh 3.5. Caïc pheïp toaïn tiãön âënh nghéa trong Prolog.

Âãø minh hoaû, ta xeït vê duû viãút mäüt chæång trçnh xæí lyï caïc biãøu thæïc lägich
(boolean). Giaí sæí ta cáön biãøu diãùn mäüt trong caïc âënh lyï tæång âæång cuía
Morgan, âæåüc viãút dæåïi daûng toaïn hoüc nhæ sau :
∼ ( A & G ) <===> ~ A ∨ ∼ B
Trong Prolog, mãûnh âãö trãn phaíi âæåüc viãút nhæ sau :
equivalent( not ( and( A, B ) ), or(not ( A ), not ( B ) ) ).
Tuy nhiãn, caïch láûp trçnh täút nháút laì thæí tçm caïch baío læu täúi âa sæû giäúng
nhau giæîa caïc kyï hiãûu trong baìi toaïn âaî cho våïi caïc kyï hiãûu âæåüc sæí duûng
trong chæång trçnh..
Caïc pheïp toaïn vaì säú hoüc 73

<===>
~ v

& ~ ~

A B A B

Hçnh I.4. Biãøu diãùn cáy cuía haûng ~ ( A & B ) <===> ~ A ∨ ~ B


Trong vê duû trãn, ta dãù daìng âënh nghéa laûi caïc pheïp toaïn lägich nhæ sau :
:- op( 800, xfx, <===> ).
:- op( 700, xfy, v ).
:- op( 600, xfy, & ).
:- op( 500, fy, ~ ).
Tæì âáy, âënh lyï Morgan âæåüc viãút laûi thaình haûng sau (xem hçnh trãn) :
~ ( A & B ) <===> ~ A ∨ ~ B

II. Caïc pheïp so saïnh cuía Prolog


II.1. Caïc pheïp so saïnh säú hoüc
Prolog coï caïc pheïp so saïnh vaì haìm säú hoüc nhæ sau :

Kyï hiãûu Giaíi thêch pheïp toaïn


Expr1 > Expr2 Thaình cäng nãúu Expr1 coï giaï trë säú låïn hån Expr2
Expr1 < Expr2 Thaình cäng nãúu Expr1 coï giaï trë säú nhoí hån Expr2
Expr1 =< Expr2 Thaình cäng nãúu Expr1 coï giaï trë säú nhoí hån hoàûc
bàòng Expr2
Expr1 >= Expr2 Thaình cäng nãúu Expr1 coï giaï trë säú låïn hån hoàûc
bàòng Expr2
Expr1 =\= Expr2 Thaình cäng nãúu Expr1 coï giaï trë säú khaïc Expr2
Expr1 =:= Expr2 Thaình cäng nãúu Expr1 coï giaï trë säú bàòng Expr2
between(Low, High, Value) Low vaì High laì caïc säú nguyãn, Low=< Value=< High.
Value laì biãún seî âæåüc nháûn giaï trë giæîa Low vaì High
succ(Int1, Int2) Thaình cäng nãúu Int2= Int1+ 1 vaì Int1>= 0
plus(Int1, Int2, Int3) Thaình cäng nãúu Int3= Int1+Int2
74 Láûp trçnh lägich trong Prolog

Chuï yï ràòng caïc pheïp toaïn = vaì =:= laì hoaìn toaìn khaïc nhau, chàóng haûn
trong caïc âêch X = Y vaì X =:= Y :
• Âêch X = Y keïo theo viãûc âäöng nháút caïc âäúi tæåüng X vaì Y, nãúu chuïng
âäöng nháút våïi nhau thç coï thãø raìng buäüc mäüt säú biãún naìo âoï trong X vaì
Y.
• Âêch X =:= Y chè gáy ra mäüt pheïp tênh säú hoüc âãø so saïnh maì khäng xaíy
pheïpû raìng buäüc naìo trãn caïc biãún.
Vê duû II.1 :
?- X = Y.
X = _G997
Y = _G997
Yes
?- 1 + 2 =:= 2 + 1.
Yes.
?- 1 + 2 = 2 + 1.
No.
?- 1 + 2 = 1 + 2.
Yes.
?- 1 + X = 1 + 2.
X=2
?- 1 + A = B + 2.
A=2
B=1
?- 1 + 2 =:= 2 + 1.
Yes.
?- 1 + X =:= 1 + 2.
ERROR: Arguments are not sufficiently instantiated (sai do a khäng phaíi laì
säú)
?- 1 + 2 == 1 + 2.
Yes.
?- 1 + 2 == 2 + 1.
No.
?- 1 + X == 1 + 2.
No.
?- 1 + a == 1 + a.
Yes.
Caïc pheïp toaïn vaì säú hoüc 75
1 is sin(pi/2).
Yes
?- 1.0 is sin(pi/2).
No
?- 1.0 is float(sin(pi/2)).
Yes
?- 1.0 =:= sin(pi/2).
Yes

II.2. Caïc pheïp so saïnh haûng


Caïc pheïp so saïnh haûng cuía Prolog nhæ sau :

Kyï hiãûu Giaíi thêch pheïp toaïn

Term1 == Term2 Thaình cäng nãúu Term1 tæång âæång våïi Term2. Mäüt biãún
chè âäöng nháút våïi mäüt biãún cuìng chia seí trong haûng
(sharing variable)

Term1 \== Term2 Tæång âæång våïi \Term1 == Term2.

Term1 = Term2 Thaình cäng nãúu Term1 khåïp âæåüc våïi Term2

Term1 \= Term2 Tæång âæång våïi \Term1 = Term2

Term1 =@= Term2 Thaình cäng nãúu Term1 coï cuìng cáúu truïc (structurally
equal) våïi Term2. Tênh coï cuìng cáúu truïc yãúu hån tênh
tæång âæång (equivalence), nhæng laûi maûnh hån pheïp
håüp nháút

Term1 \=@= Term2 Tæång âæång våïi `\Term1 =@= Term2'

Term1 @< Term2 Thaình cäng nãúu Term1 vaì Term2 theo thæï tæû chuáøn cuía
caïc haûng

Term1 @=< Term2 Thaình cäng nãúu hoàûc hai haûng bàòng nhau hoàûc Term1
âæïng træåïc Term2 theo thæï tæû chuáøn cuía caïc haûng

Term1 @> Term2 Thaình cäng nãúu Term1 âæïng sau Term2 theo thæï tæû
chuáøn cuía caïc haûng

Term1 @>= Term2 Thaình cäng nãúu hoàûc hai haûng bàòng nhau both hoàûc
Term1 âæïng sau Term2 theo thæï tæû chuáøn cuía caïc haûng

compare(?Order, Haûng1, Haûng2) Kiãøm tra thæï tæû <, > hoàûc = giæîa hai haûng
76 Láûp trçnh lägich trong Prolog

Vê duû II.2 :
?- free_variables(a(X, b(Y, X), Z), L).
L = [G367, G366, G371]
X = G367
Y = G366
Z = G371
?- a =@= A.
No
?- a =@= B.
No
?- x(A, A) =@= x(B, C).
No
?- x(A, A) =@= x(B, B).
A = _G267
B = _G270
Yes
5 ?- x(A, B) =@= x(C, D).
A = _G267
B = _G268
C = _G270
D = _G271
Yes
?- 3 @< 4.
Yes
?- 3 @< a.
Yes
?- a @< abc6.
Yes
?- abc6 @< t(c, d).
Yes
?- t(c, d) @< t(c, d, X).
X = _G284
Yes
Caïc pheïp toaïn vaì säú hoüc 77

II.3. Vë tæì xaïc âënh kiãøu


Do Prolog laì mäüt ngän ngæî âënh kiãøu yãúu nãn NLT thæåìng xuyãn phaíi
xaïc âënh kiãøu cuía caïc tham âäúi. Sau âáy laì mäüt säú vë tæì xaïc âënh kiãøu (type
predicates) cuía Prolog..
Vë tæì Kiãøm tra
var(V) V laì mäüt biãún ?
nonvar(X) X khäng phaíi laì mäüt biãún ?
atom(A) A laì mäüt nguyãn tæí ?
integer(I) I laì mäüt säú nguyãn ?
float(R) R laì mäüt säú thæûc (dáúu cháúm âäüng) ?
number(N) N laì mäüt säú (nguyãn hoàûc thæûc) ?
atomic(A) A laì mäüt nguyãn tæí hoàûc mäüt säú ?
compound(X) X laì mäüt haûng coï cáúu truïc ?
ground(X) X laì mäüt haûng âaî hoaìn toaìn raìng buäüc ?
Vê duû II.3 :
?- var(X).
X = _G201
Yes
?- integer(34).
Yes
?- ground(f(a, b)).
Yes
?- ground(f(a, Y)).
No

II.4. Mäüt säú vë tæì xæí lyï haûng


Vë tæì Kiãøm tra
functor(T, F, N) T laì mäüt haûng våïi F laì haûng tæí vaì coï N âäúi (arity)

T =..L Chuyãøn âäúi haûng T thaình danh saïch L


clause(Head, Term) Head :- Term laì mäüt luáût trong chæång trçnh ?

arg(N, Term, X) Thãú biãún X cho tham âäúi thæï N cuía haûng Term
78 Láûp trçnh lägich trong Prolog

name(A, L) Chuyãøn nguyãn tæí A thaình danh saïch L gäöm caïc


maî ASCII (danh saïch seî âæåüc trçnh baìy trong
chæång sau).
Vê duû II.4 :
?- functor(t(a, b, c), F, N).
F=t
N=3
Yes
?- functor(father(jean, isa), F, N).
F = father, N = 2.
Yes
?- functor(T, father, 2).
T = father(_G346, _G347). % _G346 vaì _G347 laì hai biãún cuía Prolog
?- t(a, b, c) =..L.
L = [t, a, b, c]
Yes
?- T =..[t, a, b, c, d, e].
T = t(a, b, c, d, e)
Yes
?- arg(1, father(jean, isa), X).
X = jean
?- name(toto, L).
L = [116, 111, 116, 111].
Yes
?- name(A, [116, 111, 116, 111]).
A = toto.
Yes
Vê duû II.5 : Cho cå såí dæî liãûu :
personal(tom).
personal(ann).
father(X, Y) :- son(Y, X), male(X).
?- clause(father(X, Y), C).
C = (son(Y, X), male(X)).
?- clause(personal(X), C).
X = tom, C = true;
X = ann, C = true
Yes
Caïc pheïp toaïn vaì säú hoüc 79

III. Âënh nghéa haìm


Prolog khäng coï kiãøu haìm, haìm phaíi âæåüc âënh nghéa nhæ mäüt quan hãû
trãn caïc âäúi tæåüng. Caïc tham âäúi cuía haìm vaì giaï trë traí vãö cuía haìm phaíi laì
caïc âäúi tæåüng cuía quan hãû âoï. Âiãöu naìy coï nghéa laì khäng thãø xáy dæûng âæåüc
caïc haìm täø håüp tæì caïc haìm khaïc.
Vê duû III.1 : Âënh nghéa haìm säú hoüc cäüng hai säú báút kyì

plus(X, Y, Z) :- % træåìng håüp tênh Z = X + Y


nonvar(X), nonvar(Y),
Z is X + Y.
plus(X, Y, Z) :- % træåìng håüp tênh X = Z - Y
nonvar(Y), nonvar(Z),
X is Z - Y.
plus(X, Y, Z) :- % træåìng håüp tênh Y - Z - X
nonvar(X), nonvar(Z),
Y is Z - X.
?- add1(2, 3, X).
X=5
Yes
add1(7, X, 3).
X = -4
Yes
add1(X, 2, 6).
X=4
Yes

III.1. Âënh nghéa haìm sæí duûng âãû quy


Trong chæång 1, ta âaî trçnh baìy caïch âënh nghéa caïc luáût (mãûnh âãö) âãû
quy. Sau âáy, ta tiãúp tuûc æïng duûng pheïp âãû quy âãø xáy dæûng caïc haìm. Tæång
tæû caïc ngän ngæî láûp trçnh mãûnh lãûnh, mäüt thuí tuûc âãû quy cuía Prolog phaíi
chæïa caïc mãûnh âãö thoaí maîn 3 âiãöu kiãûn :

• Mäüt khåíi âäüng quaï trçnh làûp.


• Mäüt så âäö làûp laûi chênh noï.
• Mäüt âiãöu kiãûn dæìng.
80 Láûp trçnh lägich trong Prolog

Vê duû thuí tuûc âãû quy taûo daîy 10 säú tæû nhiãn chàôn âáöu tiãn nhæ sau : âáöu
tiãn láúy giaï trë 0 âãø khåíi âäüng quaï trçnh. Sau âoï láúy 0 laì giaï trë hiãûn haình âãø
taûo säú tiãúp theo nhåì så âäö làûp : even_succ_nat = even_succ_nat + 2. Quaï
trçnh cæï tiãúp tuûc nhæ váûy cho âãún khi âaî coï âuí 10 säú 0 2 4 6 8 10 12 14 16 18
thç dæìng laûi.
Trong Prolog, mäüt mãûnh âãö âãû quy (âãø taûo så âäö làûp ) laì mãûnh âãö coï chæïa
trong thán (vãú phaíi) êt nháút mäüt láön låìi goüi laûi chênh mãûnh âãö âoï (vãú traïi) :
a(X) :- b(X, Y), a(Y).
Mãûnh âãö a goüi laûi chênh noï ngay trong vãú phaíi. Daûng så âäö làûp nhæ váûy
âæåüc goüi laì âãû quy træûc tiãúp. Âãø khäng xaíy ra låìi goüi vä haûn, cáön coï mäüt mãûnh
âãö laìm âiãöu kiãûn dæìng âàût træåïc mãûnh âãö. Mäùi láön vaìo làûp måïi, âiãöu kiãûn
dæìng seî âæåüc kiãøm tra âãø quyãút âënh xem coï thãø tiãúp tuûc goüi a hay khäng ?

Ta xáy dæûng thuí tuûc even_succ_nat(Num, Count) taûo láön læåüt caïc säú tæû
nhiãn chàôn Num, biãún Count âãø âãúm säú bæåïc làûp. Âiãöu kiãûn dæìng laì
Count=10, ta coï :
even_succ_nat(Num, 10).
Mãûnh âãö làûp âæåüc xáy dæûng nhæ sau :
even_succ_nat(Num, Count) :-
write(Num), write(' '),
Count1 is Count + 1,
Num1 is Num + 2,
even_succ_nat(Num1, Count1).
Nhæ váûy, låìi goüi taûo 10 säú tæû nhiãn chàôn âáöu tiãn seî laì :
?- even_succ_nat(0, 0).
0 2 4 6 8 10 12 14 16 18
Yes
Mäüt caïch khaïc âãø xáy dæûng så âäö làûp âæåüc goüi laì âãû quy khäng træûc tiãúp coï
daûng nhæ sau :
a(X) :- b(X).
b(X) :- c(Y...), a(Z).
Trong så âäö làûp naìy, mãûnh âãö âãû quy a khäng goüi goüi træûc tiãúp âãún a, maì
goüi âãún mäüt mãûnh âãö b khaïc, maì trong b naìy laûi coï låìi goüi âãún a. Âãø khäng
xaíy ra låìi goüi luáøn quáøn vä haûn, trong b cáön thæûc hiãûn caïc tênh toaïn laìm
Caïc pheïp toaïn vaì säú hoüc 81

giaím dáön quaï trçnh làûp træåïc khi goüi laûi mãûnh âãö a (vê duû mãûnh âãö c). Vê duû
så âäö dæåïi âáy seî gáy ra voìng luáøn quáøn vä haûn :
a(X) :- b(X, Y).
b(X, Y) :- a(Z).
Baìi toaïn taûo 10 säú tæû nhiãn chàôn âáöu tiãn âæåüc viãút laûi theo så âäö âãû quy
khäng træûc tiãúp nhæ sau :
a(0).
a(X) :- b(X).
b(X) :- X1 is X - 2, write(X), write(' '), a(X1).
Chæång trçnh naìy khäng goüi « âãû quy » nhæ even_succ_nat. Kãút quaí sau
låìi goüi a(20) laì daîy säú giaím dáön 20 18 16 14 12 10 8 6 4 2.
Vê duû III.2 : Xáy dæûng säú tæû nhiãn (Peano) vaì pheïp cäüng trãn caïc säú tæû nhiãn
/* Âënh nghéa säú tæû nhiãn */
nat(0). % 0 laì mäüt säú tæû nhiãn
nat(s(N)) :- % s(X) cuîng laì mäüt säú tæû nhiãn
nat(N). % nãúu N laì mäüt säú tæû nhiãn
Chàóng haûn säú 5 âæåüc viãút : s(s(s(s(s(zero)))))
/* Âënh nghéa pheïp cäüng */
addi(0, X, X). % luáût 1 : 0 + X = X
addi(X, 0, X). % luáût 2 : X + 0 = X
addi(s(X), Y, s(Z)) :- % luáût 3 : nãúu X + Y = Z thç (X+1) + Y =
(Z+1)
addi(X, Y, Z).
Hoàûc âënh nghéa theo nat(X) nhæ sau :
addi(0, X, X) :- nat(X).
?- addi(X, Y, s(s(s(s(0))))).
X=0
Y = s(s(s(s(0))))
Yes
?- addi(X, s(s(0)), s(s(s(s(s(0)))))).
X = s(s(s(0)))
Yes
?- THREE = s(s(s(0))), FIVE = s(s(s(s(s(0))))), addi(THREE, FIVE, EIGHT).
THREE = s(s(s(0)))
FIVE = s(s(s(s(s(0)))))
82 Láûp trçnh lägich trong Prolog

EIGHT = s(s(s(s(s(s(s(s(0))))))))
Yes
Vê duû III.3 : Tçm æåïc säú chung låïn nháút (GCD: Greatest Common Divisor)
Cho træåïc hai säú nguyãn X vaì Y, ta cáön tênh æåïc säú D vaì USCLN dæûa trãn
ba quy tàõc nhæ sau :
1. Nãúu X = Y, thç D bàòng X.
2. Nãúu X < Y, thç D bàòng USCLN cuía X vaì cuía Y - X.
3. Nãúu X > Y, thç thæûc hiãûn tæång tæû bæåïc 2, bàòng caïch hoaïn vë vai troì X
vaì Y.
Coï thãø dãù daìng tçm âæåüc caïc vê duû minh hoaû sæû hoaût âäüng cuía ba quy tàõc
træåïc âáy. Våïi X =20 vaì Y =25, thç ta nháûn âæåüc D =5 sau mäüt daîy caïc pheïp
træì.
Chæång trçnh Prolog âæåüc xáy dæûng nhæ sau :
gcd( X, X, X ).
gcd( X, Y, D ) :-
X < Y,
Y1 is Y – X,
gcd( X, Y1, D ).
gcd( X, Y, D ) :-
X > Y,
gcd( Y, X, D ).
Âêch cuäúi cuìng trong mãûnh âãö thæï ba trãn âáy coï thãø âæåüc thay thãú båíi :
X1 is X – Y,
gcd( X1, Y, D ).
Kãút quaí chaûy Prolog nhæ sau :
?- gcd( 20, 55, D ).
D=5
Vê duû III.4 : Tênh giai thæìa
fac(0, 1).
fac(N, F) :-
N > 0,
M is N - 1,
fac(M, Fm),
F is N * Fm.

Mãûnh âãö thæï hai coï nghéa ràòng nãúu láön læåüt :
Caïc pheïp toaïn vaì säú hoüc 83

N > 0, M = N - 1, Fm is (N-1)!, vaì F = N * Fm,


thç F laì N!. Pheïp toaïn is giäúng pheïp gaïn trong caïc ngän ngæî láûp trçnh mãûnh
lãûnh nhæng trong Prolog, is khäng gaïn giaï trë måïi cho biãún. Vãö màût lägich,
thæï tæû caïc mãûnh âãö trong vãú phaíi cuía mäüt luáût khäng coï vai troì gç, nhæng laûi
coï yï nghéa thæûc hiãûn chæång trçnh. M khäng phaíi laì biãún trong låìi goüi thuí tuûc
âãû quy vç seî gáy ra mäüt voìng làûp vä haûn.
Caïc âënh nghéa haìm trong Prolog thæåìng ràõc räúi do haìm laì quan hãû maì
khäng phaíi laì biãøu thæïc. Caïc quan hãû âæåüc âënh nghéa sæí duûng nhiãöu luáût vaì
thæï tæû caïc luáût xaïc âënh kãút quaí traí vãö cuía haìm...
Vê duû III.5 : Tênh säú Fibonacci
/* Fibonacci function */
fib(0, 1). %01
fib(1, 1).
fib(N, F) :- % fibn+2 = fibn+1 + fibn
N > 1,
N1 is N - 1, fib(N1, F1),
N2 is N - 2, fib(N2, F2),
F is F1 + F2.
?- fib(20, F).
F = 10946
Yes
?- fib(21, F).
ERROR: Out of local stack

Ta nháûn tháúy thuáût toaïn tênh säú Fibonacci trãn âáy sæí duûng hai láön goüi
âãû quy âaî nhanh choïng laìm âáöy bäü nhåï vaì chè våïi N=21, SWI-prolog phaíi
dæìng laûi âãø thäng baïo läùi.
Vê duû III.6 : Tênh haìm Ackerman
/* Ackerman's function */
ack(0, N, A) :- % Ack(0, n) = n + 1
A is N + 1.
ack(M1, 0, A) :- % Ack(m, n) = Ack(m−1, 1)
M > 0,
M is M - 1,
ack(M, 1, A).
ack(M1, N1, A) :- % Ack(m, n) = Ack(m−1, Ack(m, n−1))
M1 > 0, N1 > 0,
84 Láûp trçnh lägich trong Prolog

M is M - 1, N is N - 1,
ack(M1, N, A1),
ack(M, A1, A).
Vê duû III.7 : Haìm tênh täøng
plus(X, Y, Z) :-
nonvar(X), nonvar(Y),
Z is X + Y.
plus(X, Y, Z) :-
nonvar(Y), nonvar(Z),
X is Z - Y.
plus(X, Y, Z) :-
nonvar(X), nonvar(Z),
Y is Z - X.
Vê duû III.8 : Thuáût toaïn håüp nháút
Sau âáy laì mäüt thuáût toaïn håüp nháút âån giaín cho pheïp xæí lyï træåìng håüp
mäüt biãún naìo âoï âæåüc thay thãú (håüp nháút) båíi mäüt haûng maì haûng naìy laûi coï
chæïa âuïng tãn biãún âoï. Chàóng haûn pheïp håüp nháút X = f(X) laì khäng håüp lãû.
% unify(T1, T2).
unify(X, Y) :- % træåìng håüp 2 biãún
var(X), var(Y), X = Y.
unify(X, Y) :- % træåìng håüp biãún = khäng phaíi biãún
var(X), nonvar(Y), X = Y.
unify(X, Y) :- % træåìng håüp khäng phaíi biãún = biãún
nonvar(X), var(Y), Y = X.
unify(X, Y) :- % nguyãn tæí hay säú = nguyãn tæí hay säú
nonvar(X), nonvar(Y),
atomic(X), atomic(Y),
X = Y.
unify(X, Y) :- % træåìng håüp cáúu truïc = cáúu truïc
nonvar(X), nonvar(Y),
compound(X), compound(Y),
termUnify(X, Y).
termUnify(X, Y) :- % håüp nháút haûng våïi haûng chæïa cáúu truïc
functor(X, F, N),
functor(Y, F, N),
argUnify(N, X, Y).
argUnify(N, X, Y) :- % håüp nháút N tham âäúi cuía X vaì Y
N>0,
Caïc pheïp toaïn vaì säú hoüc 85
argUnify1(N, X, Y),
Ns is N - 1,
argUnify(Ns, X, Y).
argUnify(0, X, Y).
argUnify1(N, X, Y) :- % håüp nháút caïc tham âäúi coï báûc N
arg(N, X, ArgX),
arg(N, Y, ArgY),
unify(ArgX, ArgY).
Vê duû III.9 : Lyï thuyãút säú
Ta tiãúp tuûc xáy dæûng haìm måïi trãn caïc säú tæû nhiãn âaî âæåüc âënh nghéa
trong vê duû 1. Ta xáy dæûng pheïp so saïnh hai säú tæû nhiãn dæûa trãn pheïp cäüng
nhæ sau :
egal(+(X, 0), X). % pheïp cäüng coï tênh giao hoaïn
egal(+(0, X), X).
egal(+(X, s(Y)), s(Z)) :- % X YZ.egal(X+Y, Z) → egal(X+s(Y), s(Z))
egal(+(X, Y), Z).

Sau âáy laì mäüt säú kãút quaí :


?- egal(s(s(0))+s(s(s(0))), s(s(s(s(s(0)))))).
Yes
?- egal(+(s(s(0)), s(s(0))), X).
X = s(s(s(s(0))))
?- egal(+(X, s(s(0))), s(s(s(s(s(0)))))).
X = s(s(s(0)))
Yes
?- egal(+(X, s(s(0))), s(s(s(s(s(0)))))).
X = s(s(s(0)))
Yes
?- egal(X, s(s(s(s(0))))).
X = s(s(s(s(0))))+0 ;
X = 0+s(s(s(s(0)))) ;
X = s(s(s(0)))+s(0) ;
X = 0+s(s(s(s(0)))) ;
X = s(s(0))+s(s(0)) ;
X = 0+s(s(s(s(0)))) ;
X = s(0)+s(s(s(0))) ;
X = 0+s(s(s(s(0)))) ;
86 Láûp trçnh lägich trong Prolog

X = 0+s(s(s(s(0)))) ;
X = 0+s(s(s(s(0)))) ;
No

Våïi âêch egal(X, Y) sau âáy, cáu traí låìi laì vä haûn :
?- egal(X, Y).
X = _G235+0
Y = _G235 ;
X = 0+_G235
Y = _G235 ;
X = _G299+s(0)
Y = s(_G299) ;
X = 0+s(_G302)
Y = s(_G302) ;
X = _G299+s(s(0))
Y = s(s(_G299)) ;
X = 0+s(s(_G309))
Y = s(s(_G309)) ;
X = _G299+s(s(s(0)))
Y = s(s(s(_G299))) ;
X = 0+s(s(s(_G316)))
Y = s(s(s(_G316))) ;
X = _G299+s(s(s(s(0))))
Y = s(s(s(s(_G299)))) ;
X = 0+s(s(s(s(_G323))))
Y = s(s(s(s(_G323)))) ;
X = _G299+s(s(s(s(s(0)))))
Y = s(s(s(s(s(_G299))))) ;
...
X = 0+s(s(s(s(s(s(_G337))))))
Y = s(s(s(s(s(s(_G337)))))) ;
X = _G299+s(s(s(s(s(s(s(0)))))))
Y = s(s(s(s(s(s(s(_G299)))))))
v.v...
Caïc pheïp toaïn vaì säú hoüc 87

III.2. Täúi æu pheïp âãû quy


Låìi giaíi caïc baìi toaïn sæí duûng âãû quy trong caïc ngän ngæî láûp trçnh noïi
chung thæåìng ngàõn goün, dãù hiãøu vaì dãù quaín lyï âæåüc chæång trçnh. Tuy
nhiãn, trong mäüt säú træåìng håüp, sæí duûng âãû quy laûi xaíy ra váún âãö vãö âäü phæïc
taûp tênh toaïn, khäng nhæîng täún keïm bäü nhåï maì coìn täún keïm thåìi gian.
Trong caïc ngän ngæî mãûnh lãûnh, pheïp tênh n! sæí duûng âãû quy cáön sæí duûng
bäü nhåï coï cåî 0(n) vaì thåìi gian tênh toaïn cuîng coï cåî 0(n), thay vç goüi âãû quy,
ngæåìi ta thæåìng sæí duûng pheïp làûp fac=fac*i, i=1..n.
Ta xeït laûi vê duû 4 tênh säú Fibonacci trãn âáy våïi låìi goüi âãû quy :
fib(N, F) :-
N > 1, N1 is N - 1, fib(N1, F1), N2 is N - 2, fib(N2, F2), F is F1 + F2.
Âãø yï ràòng mäùi láön goüi haìm fib(n) våïi n>1 seî dáùn tåïi hai láön goüi khaïc, nghéa
laì säú láön goüi seî tàng theo luyî thæìa 2. Våïi n låïn, chæång trçnh goüi âãû quy nhæ
váûy dãù gáy traìn bäü nhåï. Vê duû sau âáy laì táút caí caïc låìi goüi coï thãø cho træåìng
håüp n=5.

fib5
4 3
3 2 2 1
2 1 1 0 1 0
1 0

Hçnh III.1. Biãøu diãùn cáy caïc låìi goüi âãû quy tçm säú Fibonacci

Mäüt säú ngän ngæî mãûnh lãûnh tênh säú Fibonacci sæí duûng cáúu truïc làûp âãø
traïnh tênh âi tênh laûi cuìng mäüt giaï trë. Chæång trçnh Pascal dæåïi âáy duìng
hai biãún phuû x=fib(i) vaì y=fib(i+1) :
{ tênh fib(n) våïi n > 0 }
i:= 1; x:= 1; y:= 0;
while i < n do
begin x:= x + y; y:= x – y end;
Ta viãút laûi chæång trçnh Prolog nhæ sau :
fibo(0, 0).
fibo(N, F) :-
88 Láûp trçnh lägich trong Prolog

N >= 1,
fib1(N, 1, 0, F).
fib1(1, F, _, F).
fib1(N, F2, F1, FN) :-
N > 1,
N1 is N - 1,
F3 is F1 + F2,
fib1(N1, F3, F2, FN).
?- fibo(21, F).
F = 10946
Yes
?- fibo(200, F).
F = 2.80571e+041
Yes

III.3. Mäüt säú vê duû khaïc vãö âãû quy


III.3.1. Tçm âæåìng âi trong mäüt âäö thë coï âënh hæåïng
Cho mäüt âäö thë coï âënh hæåïng nhæ sau :

A B

C D

E
Hçnh III.2. Tçm âæåìng âi trong mäüt âäö thë coï âënh hæåïng.

Ta xeït baìi toaïn tçm âæåìng âi giæîa hai âènh cuía âäö thë. Mäùi cung näúi hai
âènh cuía âäö thë biãøu diãùn mäüt quan hãû giæîa hai âènh naìy. Tæì âäö thë trãn, ta
coï thãø viãút caïc mãûnh âãö Prolog biãøu diãùn caïc sæû kiãûn :
arc(a, b).
arc(b, c).
arc(c, e).
arc(c, d).
arc(a, e).

Giaí sæí cáön kiãøm tra coï täön taûi mäüt âæåìng âi giæîa hai nuït a vaì d (khäng
täön taûi âæåìng âi giæîa hai nuït naìy nhæ âaî mä taí), ta viãút mãûnh âãö :
path(a, d).
Caïc pheïp toaïn vaì säú hoüc 89

Âãø âënh nghéa naìy, ta nháûn xeït nhæ sau :


• Täön taûi mäüt âæåìng âi giæîa hai nuït coï cung näúi chuïng.
• Täön taûi mäüt âæåìng âi giæîa hai nuït X vaì Y nãúu täön taûi mäüt nuït thæï ba Z
sao cho täön taûi mäüt âæåìng âi giæîa X vaì Z vaì mäüt âæåìng âi giæîa Z vaì Y.
Ta viãút chæång trçnh nhæ sau :
path(X, Y) :- arc(X, Y).
path(X, Y) :-
arc(X, Z),
path(Z, Y).

Ta tháúy âënh nghéa thuí tuûc path(X, Y) tæång tæû thuí tuûc tçm täø tiãn giaïn
tiãúp giæîa hai ngæåìi trong cuìng doìng hoü ancestor(X, Y) âaî xeït træåïc âáy.
?- path(X, Y).
X=a
Y=b;
X=b
Y=c;
...

III.3.2. Tênh âäüü daìi âæåìng âi trong mäüt âäö thë


Ta xeït baìi toaïn tênh âäü daìi âæåìng âi giæîa hai nuït, tæì nuït âáöu âãún nuït
cuäúi trong mäüt âäö thë laì säú cung giæîa chuïng. Chàóng haûn âäü daìi âæåìng âi giæîa
hai nuït a vaì d laì 3 trong vê duû trãn. Ta láûp luáûn nhæ sau :

• Nãúu giæîa hai nuït coï cung näúi chuïng thç âäü daìi âæåìng âi laì 1.
• Goüi L laì âäü daìi âæåìng âi giæîa hai nuït X vaì Y, L1 laì âäü daìi âæåìng âi giæîa
mäüt nuït thæï ba Z vaì Y nãúu täön taûi vaì giaí sæí coï cung näúi X vaì Z, khi âoï
L = L1 + 1.

Chæång trçnh âæåüc viãút nhæ sau :


trajectory(X, Y, 1) :- arc(X, Y).
trajectory(X, Y, L) :-
arc(X, Z),
trajectory(Z, Y, L1),
L is L1 + 1.
trajectory(a, d, L).
L=3
Yes
90 Láûp trçnh lägich trong Prolog

III.3.3. Tênh gáön âuïng caïc chuäùi


Trong Toaïn hoüc thæåìng gàûp baìi toaïn tênh gáön âuïng giaï trë cuía mäüt haìm
säú våïi âäü chênh xaïc nhoí tuyì yï (ε) theo phæång phaïp khai triãøn thaình chuäùi
Max Loren :
Vê duû tênh haìm muî ex våïi âäü chênh xaïc 10-6 nhåì khai triãøn chuäùi Max
Loren :
x 2 x3
ex = 1 + x + + + ...
2! 3!

Goüi expower(X, S) laì haìm tênh giaï trë haìm muî theo X, biãún S laì kãút quaí
gáön âuïng våïi âäü chênh xaïc ε=10-6. Tæì cäng thæïc khai triãøn Max Loren trãn
âáy, ta nháûn tháúy giaï trë cuía haìm muî ex laì täøng vä haûn coï daûng :

sum(0) = 1, t0 = 1 tæång æïng våïi x = 0 vaì ex = 1


sum(i+1) = sum(i) + ti+1, våïi ti+1 = ti ∗ x /( i+1), i = 0, 1, 2 ...
Âãø thæûc hiãûn pheïp làûp, ta cáön xáy dæûng haìm âãû quy tênh täøng sum(X, S, I,
T) trong âoï sæí duûng caïc biãún trung gian I laì bæåïc làûp thæï i vaì T laì säú haûng ti.
Theo caïch xáy dæûng naìy, haìm tênh täøng sum(X, S, I, T) laì täøng cuía caïc säú
haûng thæï I tråí âi cuía chuäùi. Quaï trçnh tênh caïc täøng dæìng laûi khi ti< ε, nghéa
laì âaî âaût âæåüc âäü chênh xaïc ε. Taûi thåìi âiãøm naìy, giaï trë cuía täøng cuîng chênh
laì säú haûng ti. Âiãöu kiãûn khåíi âäüng quaï trçnh làûp laì chuyãøn vë tæì expower(X,
S) thaình vë tæì tênh täøng sum(X, S, I, T) våïi giaï trë âáöu I=0 vaì T=1.

Ta coï chæång trçnh âãû quy nhæ sau :


expower(X, S) :-
sum(X, S, 0, 1).
sum(_, T, _, T) :-
abs(T) < 0.000001.
sum(X, S, I, T) :-
abs(T) > 0.000001,
I1 is I + 1,
T1 is T*X/I1,
sum(X, S1, I1, T1),
S is S1 + T.
?- expower(1, S).
S = 2.71828
Yes
Caïc pheïp toaïn vaì säú hoüc 91
?- expower(10, S)
S = 22026.5
Yes

Toïm tàõt chæång 3


• Caïc pheïp toaïn säú hoüc âæåüc thæûc hiãûn nhåì caïc thuí tuûc thæåìng truï trong
Prolog.
• Vai troì cuía caïc pheïp toaïn tæång tæû vai troì cuía caïc haìm tæí, chè âãø nhoïm
caïc thaình pháön cuía caïc cáúu truïc maì thäi.
• Mäùi NLT coï thãø tæû âënh nghéa nhæîng pheïp toaïn riãng cuía mçnh. Mäùi
pheïp toaïn âæåüc âënh nghéa båíi tãn, âäü æu tiãn vaì kiãøu goüi tham âäúi.
• Caïc pheïp toaïn cho pheïp NLT váûn duûng cuï phaïp linh hoaût cho caïc nhu
cáöu riãng cuía hoü. Sæí duûng caïc pheïp toaïn laìm cho chæång trçnh tråí nãn dãù
âoüc (readability).
• Âãø tênh mäüt biãøu thæïc säú hoüc, moüi tham âäúi coï màût trong biãøu thæïc âoï
phaíi âæåüc raìng buäüc båíi caïc giaï trë säú.
• Chè dáùn op duìng âãø âënh nghéa mäüt pheïp toaïn måïi, gäöm caïc yãúu täú : tãn,
kiãøu vaì âäü æu tiãn cuía pheïp toaïn måïi.
• Sæí duûng caïc pheïp toaïn trung täú, tiãön täú, hoàûc háûu täú laìm tàng cæåìng tênh
dãù âoüc cuía mäüt chæång trçnh Prolog.
• Âäü æu tiãn laì mäüt säú nguyãn nàòm trong mäüt khoaíng giaï trë cho træåïc,
thäng thæåìng nàòm giæîa 1 vaì 1200. Haìm tæí chênh cuía mäüt biãøu thæïc laì
pheïp toaïn coï âäü æu tiãn cao nháút. Caïc pheïp toaïn coï âäü æu tiãn tháúp nháút
âæåüc æu tiãn nháút.
• Kiãøu cuía mäüt pheïp toaïn phuû thuäüc vaìo hai yãúu täú :
1. vë trê cuía pheïp toaïn so våïi caïc tham âäúi,
2. âäü æu tiãn cuía caïc tham âäúi âæåüc so saïnh våïi âäü æu tiãn cuía pheïp toaïn.
Âäúi våïi caïc kyï hiãûu âàûc taí xfy, tham âäúi x coï âäü æu tiãn beï hån hàón âäü æu
tiãn cuía pheïp toaïn, coìn tham âäúi y coï âäü æu tiãn beï hån hoàûc bàòng âäü æu
tiãn cuía pheïp toaïn.
92 Láûp trçnh lägich trong Prolog

Baìi táûp chæång 3


1. Cho biãút kãút quaí cuía caïc cáu hoíi sau âáy :
?- X=Y.
?- X is Y
?- X=Y, Y=Z, Z=1.
?- X=1, Z=Y, X=Y.
?- X is 1+1, Y is X.
?- Y is X, X is 1+1.
?- 1+2 == 1+2.
?- X == Y.
?- X == X.
?- 1 =:= 2-1
?- X =:= Y.
2. Cho biãút kãút quaí cuía caïc cáu hoíi sau âáy :
?- op(X) is op(1).
?- op(X) = op(1).
?- op(op(Z), Y) = op(X, op(1)).
?- op(X, Y) = op(op(Y), op(X)).
3. Tæì caïc âënh nghéa säú tæû nhiãn (nat) vaì pheïp cäüng (addi) cho trong vê duû 1
åí muûc âënh nghéa haìm, haîy viãút tiãúp caïc haìm træì (subt), nhán (multi), chia
(divi), luyî thæìa (power), giai thæìa (fact), so saïnh nhoí hån (less) vaì tçm æåïc
säú chung låïn nháút (pdg) sæí duûng caïc haìm âaî coï (chàóng haûn less, subt...).
4. Viãút haìm Prolog âãø kiãøm tra mäüt säú nguyãn tuyì yï N :
a. N laì säú chàôn (even number) sæí duûng âãû quy træûc tiãúp
Hæåïng dáùn : N chàôn thç N±2 cuîng laì säú chàôn
b. N laì säú leí (odd number) sæí duûng âãû quy træûc tiãúp
Hæåïng dáùn : N leí thç N±2 cuîng laì säú leí
c. N chàôn sæí duûng haìm kiãøm tra säú leí cáu d (N chàôn thç N±1 laì säú leí)
d. N laì säú leí sæí duûng haìm kiãøm tra säú chàôn cáu c (N leí thç N±1 chàôn).
Caïc pheïp toaïn vaì säú hoüc 93

5. Viãút haìm Prolog âãø laìm duyãût (tracking/traverse) trãn cáy nhë phán theo
caïc thæï tæû træåïc (reorder), sau (post-order) vaì giæîa (in-order).
Giaí sæí cáy nhë phán tæång æïng våïi biãøu thæïc säú hoüc (5+6)*(3-(2/2)) laì caïc
mãûnh âãö Prolog nhæ sau :
tree(’*’, tree(’+’, leaf(5), leaf(6)), tree(’-’, leaf(3), tree(’/’, leaf(2), leaf(2)))
Kãút quaí duyãût cáy nhæ sau : theo thæï tæû træåïc :
[*, +, 5, 6, -, 3, /, 2, 2]
thæï tæû giæîa :
[5, +, 6, *, 3, -, 2, /, 2]
thæï tæû sau :
[5, 6, +, 3, 2, 2, /, -, *]
6. Viãút laûi haìm taûo 10 säú tæû nhiãn chàôn âáöu tiãn (âaî cho trong pháön âãû quy)
sao cho kãút quaí traí vãö laì daîy säú tàng dáön.
7. Láûp baíng nhán table(R, N) coï säú bë nhán (multiplicator) tæì 1 tråí âi våïi säú
nhán N (multiplier) vaì dæìng laûi khi gàûp säú bë nhán R (kãút quaí R * N).
8. Viãút caïc haìm tênh gáön âuïng giaï trë caïc haìm sau våïi âäü chênh xaïc ε = 10-5 :
π 1 1 1 1
= 1 − + − +... cho âãún khi <ε
4 3 5 7 2n - 1
x2 2 x4 2 4 x6
1+ + × + × × + ... cho âãún khi pháön tæí thæï n
2 3 4 3 5 6

x2 x3 n x
n
xn
S = 1 - x + - + ... + (-1) + ... cho âãún khi <ε
2! 3! n! n!

x2 x4 x6 x 2n x 2n
S = 1+ + + +...+ +... cho âãún khi < 10−5
2! 4! 6! (2 n)! (2 n)!

y= x + x + ... + x coï n > 1 dáúu càn

9. Trçnh Prolog dæåïi âáy laì mäüt trçnh diãùn dëch (interpreter) cho mäüt ngän
ngæî láûp trçnh âån giaín chè gäöm caïc säú nguyãn int(N), caïc biãún id(X), caïc
haìm fn(X,E), vaì goüi haìm app(E1,E2) :
%% subst(E1, E2, X, V)
94 Láûp trçnh lägich trong Prolog

%% thæûc hiãûn pheïp thãú biãún X båíi biãún V trong E1 âãø traí vãö E2.
subst(int(N), int(N), _, _).
subst(id(X), V, X, V).
subst(id(Y), id(Y), X, _) :-
X \= Y.
subst(fn(X, E), fn(X, E), X, _).
subst(fn(Y, Ea), fn(Y, Eb), X, V) :-
X \= Y,
subst(Ea, Eb, X, V).
subst(app(E1a, E2a), app(E1b, E2b), X, V) :-
subst(E1a, E1b, X, V),
subst(E2a, E2b, X, V).
%% reduce(E, V)
%% thæûc hiãûn pheïp tênh giaï trë cuía E âãø traí vãö V.
reduce(int(N), int(N)).
reduce(fn(X, B), fn(X, B))
reduce(app(E1, E2), V) :-
reduce(E1, fn(X, B)),
reduce(E2, V2),
subst(B, E, X, V2),
reduce(E, V).
Cáu hoíi :
a. Cho biãút caïch trao âäøi tham biãún håüp lãû trong ngän ngæî mä taí trãn
âáy ? Caïch trao âäøi tham biãún naìo thç khäng thãø thæûc hiãûn âæåüc ?
b. Tçm caïch thay âäøi trçnh Prolog trãn âáy âãø coï thãø thæûc hiãûn âæåüc caïc
phæång phaïp trao âäøi tham biãún khaïc nhau.
c. Cho biãút táöm væûc (scope) cuía caïc biãún laì ténh hay âäüng ?
10. Cho vê duû mäüt âäö thë khäng âënh hæåïng dæåïi âáy :
arc(a,b). arc(d,f).
arc(b,c). arc(f,a).
arc(c,d). arc(a,b).
arc(c,e). arc(h,i).
arc(c,g). arc(i,j).
arc(g,f).
Haîy viãút haìm tçm âæåìng âi giæîa hai âènh cuía âäö thë.
CHÆÅNG 4

Cáú u truï c danh saï c h


Chæång naìy trçnh baìy khaïi niãûm vãö danh saïch, mäüt trong nhæîng cáúu truïc
âån giaín nháút vaì thäng duûng nháút, cuìng våïi nhæîng chæång trçnh tiãu biãøu
minh hoaû caïch váûn duûng danh saïch trong Prolog. Cáúu truïc danh saïch taûo
nãn mäüt mäi træåìng láûp trçnh thuáûn tiãûn cuía ngän ngæî Prolog.

I. Biãøu diãùn cáúu truïc danh saïch


Danh saïch laì kiãøu cáúu truïc dæî liãûu âæåüc sæí duûng räüng raîi trong caïc ngän
ngæî láûp trçnh phi säú. Mäüt danh saïch laì mäüt daîy báút kyì caïc âäúi tæåüng. Khaïc våïi
kiãøu dæî liãûu táûp håüp, caïc âäúi tæåüng cuía danh saïch coï thãø truìng nhau (xuáút
hiãûn nhiãöu láön) vaì mäùi vë trê xuáút hiãûn cuía âäúi tæåüng âãöu coï yï nghéa.
Danh saïch laì caïch diãùn âaût ngàõn goün cuía kiãøu dæî liãûu haûng phæïc håüp
trong Prolog. Haìm tæí cuía danh saïch laì dáúu cháúm “.”. Do viãûc biãøu diãùn danh
saïch båíi haìm tæí naìy coï thãø taûo ra nhæîng biãøu thæïc máûp måì, nháút laì khi xæí lyï
caïc danh saïch gäöm nhiãöu pháön tæí läöng nhau, cho nãn Prolog quy æåïc âàût daîy
caïc pháön tæí cuía danh saïch giæîa caïc càûp moïc vuäng.
Chàóng haûn .(a,.(b,[ ])). Laì danh saïch [ a, b ].
Danh saïch caïc pháön tæí anne, tennis, tom, skier (tãn ngæåìi) âæåüc viãút :
[ anne, tennis, tom, skier ]
chênh laì haìm tæí :
. ( anne, .( tennis, .( tom, .( skier, [ ] ) ) ) )
Caïch viãút daûng càûp moïc vuäng chè laì xuáút hiãûn bãn ngoaìi cuía mäüt danh
saïch. Nhæ âaî tháúy åí muûc træåïc, moüi âäúi tæåüng cáúu truïc cuía Prolog âãöu coï
biãøu diãùn cáy. Danh saïch cuîng khäng nàòm ngoaûi lãû, cuîng coï cáúu truïc cáy.

95
96 Láûp trçnh lägich trong Prolog

Laìm caïch naìo âãø biãøu diãùn danh saïch båíi mäüt âäúi tæåüng Prolog chuáøn ?
Coï hai khaí nàng xaíy ra laì danh saïch coï thãø räùng hoàûc khäng. Nãúu danh saïch
räùng, noï âæåüc viãút dæåïi daûng mäüt nguyãn tæí :
[]
Nãúu danh saïch khaïc räùng, coï thãø xem noï âæåüc cáúu truïc tæì hai thaình pháön
(pair syntax) :
1. Thaình pháön thæï nháút, âæåüc goüi laì âáöu (head) cuía danh saïch.
2. Thaình pháön thæï hai, pháön coìn laûi cuía danh saïch (træì ra pháön âáöu),
âæåüc goüi laì âuäi (tail) cuía danh saïch, cuîng laì mäüt danh saïch.
Trong vê duû trãn thç âáöu laì anne, coìn âuäi laì danh saïch :
[ tennis, tom, skier ]
Noïi chung, âáöu cuía danh saïch coï thãø laì mäüt âäúi tæåüng báút kyì cuía Prolog,
coï thãø laì cáy hoàûc biãún, nhæng âuäi phaíi laì mäüt danh saïch. Hçnh I.1. Biãøu diãùn
daûng cáy cuía danh saïch mä taí cáúu truïc cáy cuía danh saïch âaî cho :
.

anne . âuäi cuîng laì danh saïch

âáöu tennis .
tom .

skier []

Hçnh I.1. Biãøu diãùn daûng cáy cuía danh saïch


Vç âuäi tail laì mäüt danh saïch, nãn tail coï thãø räùng, hoàûc laûi coï thãø âæåüc taûo
thaình tæì mäüt âáöu head vaì mäüt âuäi tail khaïc.
Chuï yï ràòng danh saïch räùng xuáút hiãûn trong säú caïc haûng, vç ràòng pháön tæí
cuäúi cuìng coï thãø xem laì danh saïch chè gäöm mäüt pháön tæí duy nháút coï pháön
âuäi laì mäüt danh saïch räùng:
[ skier ]
Vê duû trãn âáy minh hoaû nguyãn lyï cáúu truïc dæî liãûu täøng quaït trong
Prolog aïp duûng cho caïc danh saïch coï âäü daìi tuyì yï.
?- L1 = [ a, b, c ].
?- L2 = [ a, a, a ].
Cáúu truïc danh saïch 97

L1 = [ a, b, c ]
L2 = [ a, a, a ]
?- Leisure1 = [ tennis, music, [ ] ].
?- Leisure2 = [ sky, eating ],
?- L = [ anne, Leisure1, tom, Leisure2 ].
Leisure1 = [ tennis, music ]
Leisure2 = [ sky, eating ]
L = [ anne, [ tennis, music ], tom, [ sky, eating ] ]
Nhæ váûy, caïc pháön tæí cuía mäüt danh saïch coï thãø laì caïc âäúi tæåüng coï kiãøu
báút kyì, kãø caí kiãøu danh saïch. Thäng thæåìng, ngæåìi ta xæí lyï âuäi cuía danh
saïch nhæ laì mäüt danh saïch. Chàóng haûn, danh saïch :
L = [ a, b, c ]
coï thãø viãút :
tail = [ b, c ] vaì L = .(a, tail)
Âãø biãøu diãùn mäüt danh saïch âæåüc taûo thaình tæì âáöu (Head) vaì âuäi (Tail),
Prolog sæí duûng kyï hiãûu | (split) âãø phán caïch pháön âáöu vaì pháön âuäi nhæ
sau :
L = [ a | Tail ]
Kyï hiãûu | âæåüc duìng mäüt caïch ráút täøng quaït bàòng caïch viãút mäüt säú pháön
tæí tuyì yï cuía danh saïch træåïc | räöi danh saïch caïc pháön tæí coìn laûi. Danh saïch
báy giåì âæåüc viãút laûi nhæ sau :
[ a, b, c ] = [ a | [ b, c ] ] = [ a, b | [ c ] ] = [ a, b, c | [ ] ]
Sau âáy laì mäüt säú caïch viãút danh saïch :
Kiãøu hai thaình pháön Kiãøu liãût kã pháön tæí
[] []
[a|[]] [a]
[a|b|[]] [ a, b ]
[a|X] [a|X]
[a|b|X] [ a, b | X ]
[ X1 | [ ... [ Xn | [ ] ]... ] ] [ X1, ... , Xn ]
Ta coï thãø âënh nghéa danh saïchtheo kiãøu âãû quy nhæ sau :
List Æ [ ]
List Æ [ Element | List ]
98 Láûp trçnh lägich trong Prolog

II. Mäüt säú vë tæì xæí lyï danh saïch cuía Prolog
SWI-Prolog coï sàôn mäüt säú vë tæì xæí lyï danh saïch nhæ sau :
Vë tæì YÏ nghéa
append(List1, List2, List3) Gheïp hai danh saïch List1 vaì List2 thaình List3.
Kiãøm tra Elem coï laì pháön tæí cuía danh saïch List hay
member(Elem, List) khäng, nghéa laì Elem håüp nháút âæåüc våïi mäüt trong
caïc pháön tæí cuía List.
Kiãøm tra nãúu pháön tæí Y coï âæïng ngay sau pháön tæí X
nextto(X, Y, List)
trong danh saïch List hay khäng.
Xoaï khoíi danh saïch List1 nhæîng pháön tæí håüp nháút
delete(List1, Elem, List2)
âæåüc våïi Elem âãø traí vãö kãút quaí List2.
Láúy pháön tæí Elem ra khoíi danh saïch List âãø traí vãö
select(Elem, List, Rest) nhæîng pháön tæí coìn laûi trong Rest, coï thãø duìng âãø
cheìn mäüt pháön tæí vaìo danh saïch.
Kiãøm tra pháön tæí thæï Index (tênh tæì 0) cuía danh
nth0(Index, List, Elem)
saïch List coï phaíi laì Elem hay khäng.
Kiãøm tra pháön tæí thæï Index (tênh tæì 1) cuía danh saïch
nth1(Index, List, Elem)
List coï phaíi laì Elem hay khäng.
Kiãøm tra pháön tæí âæïng cuäúi cuìng trong danh saïch
last(List, Elem)
List coï phaíi laì Elem hay khäng.
Nghëch âaío thæï tæû caïc pháön tæí cuía danh saïch List1
reverse(List1, List2)
âãø traí vãö kãút quaí List2.
permutation(List1, List2) Hoaïn vë danh saïch List1 thaình danh saïch List2.
Chuyãøn danh saïch List1 chæïa caïc pháön tæí báút kyì
thaình danh saïch phàóng List2.
flatten(List1, List2)
Vê duû : flatten([a, [b, [c, d], e]], X).
cho kãút quaí X = [a, b, c, d, e].
sumlist(List, Sum) Tênh täøng caïc pháön tæí cuía danh saïch List chæïa toaìn
säú âãø traí vãö kãút quaí Sum.
Nãúu Low vaì High laì caïc säú sao cho Low =< High, thç
numlist(Low, High, List)
traí vãö danh saïch List = [Low, Low+1, ..., High].

Chuï yï mäüt säú vë tæì xæí lyï danh saïch coï thãø sæí duûng cho moüi raìng buäüc, kãø
caí khi caïc tham âäúi âãöu laì biãún.
Trong Prolog, táûp håüp âæåüc biãøu diãùn båíi danh saïch, tuy nhiãn, thæï tæû caïc
pháön tæí trong mäüt táûp håüp laì khäng quan troüng, caïc âäúi tæåüng duì xuáút hiãûn
Cáúu truïc danh saïch 99

nhiãöu láön chè âæåüc xem laì mäüt pháön tæí cuía táûp håüp. Caïc pheïp toaïn vãö danh
saïch coï thãø aïp duûng cho caïc táûp håüp. Âoï laì :
• Kiãøm tra mäüt pháön tæí coï màût trong mäüt danh saïch tæång tæû viãûc kiãøm tra
mäüt pháön tæí coï thuäüc vãö mäüt táûp håüp khäng ?
• Gheïp hai danh saïch âãø nháûn âæåüc mäüt danh saïch thæï ba tæång æïng våïi
pheïp håüp cuía hai táûp håüp.
• Thãm mäüt pháön tæí måïi, hay loaûi boí mäüt pháön tæí.
Prolog coï sàôn mäüt säú vë tæì xæí lyï táûp håüp nhæ sau :
Vë tæì YÏ nghéa
is_set(Set) Kiãøm tra Set coï phaíi laì mäüt táûp håüp hay khäng
Chuyãøn danh saïch List thaình táûp håüp Set giæî
nguyãn thæï tæû caïc pháön tæí cuía List (nãúu List coï caïc
list_to_set(List, Set) pháön tæí truìng nhau thç chè láúy pháön tæí gàûp âáöu
tiãn). Vê duû : list_to_set([a,b,a], X) cho kãút quaí
X = [a,b].
intersection(Set1, Set2, Set3) Pheïp giao cuía hai táûp håüp Set1 vaì Set2 laì Set3.
Traí vãö kãút quaí pheïp hiãûu cuía hai táûp håüp Set vaì
subtract(Set, Delete, Result) Delete laì Result (laì táûp Set sau khi âaî xoaï hãút caïc
pháön tæí cuía Delete coï màût trong âoï).
Traí vãö kãút quaí pheïp håüp cuía hai táûp håüp Set1 vaì
union(Set1, Set2, Set3)
Set2 laì Set3.
Kiãøm tra táûp håüp Subset coï laì táûp håüp con cuía Set
subset(Subset, Set)
hay khäng.

III. Caïc thao taïc cå baín trãn danh saïch


III.1. Xáy dæûng laûi mäüt säú vë tæì coï sàôn
Sau âáy ta seî trçnh baìy mäüt säú thao taïc cå baín trãn danh saïch bàòng caïch
xáy dæûng laûi mäüt säú vë tæì coï sàôn cuía Prolog.

III.1.1. Kiãøm tra mäüt pháön tæí coï màût trong danh saïch
Prolog kiãøm tra mäüt pháön tæí coï màût trong mäüt danh saïch nhæ sau :
member(X, L)
100 Láûp trçnh lägich trong Prolog

trong âoï, X laì mäüt pháön tæí vaì L laì mäüt danh saïch. Âêch member(X, L) âæåüc
thoaí maîn nãúu X xuáút hiãûn trong L. Vê duû :
?- member( b, [ a, b, c ] )
Yes
?- member( b, [ a, [ b, c ] ] )
No
?- member( [ b, c], [ a, [ b, c ] ] )
Yes
Tæì caïc kãút quaí trãn, ta coï thãø giaíi thêch quan hãû member(X, L) nhæ sau :
Pháön tæí X thuäüc danh saïch L nãúu :
1. X laì âáöu cuía L, hoàûc nãúu
2. X laì mäüt pháön tæí cuía âuäi cuía L.
Ta coï thãø viãút hai âiãöu kiãûn trãn thaình hai mãûnh âãö, mãûnh âãö thæï nháút laì
mäüt sæû kiãûn âån giaín, mãûnh âãö thæï hai laì mäüt luáût :
member( X, [ X | Tail ] ).
member( X, [ Head | Tail ] ) :- member( X, Tail ).
hoàûc :
member(X, [X|T]).
member(X, [_|T]) :- member(X, T).

III.1.2. Gheïp hai danh saïch


Âãø gheïp hai danh saïch, Prolog coï haìm :
append( L1, L2, L3).
trong âoï, L1 vaì L2 laì hai danh saïch, L3 laì kãút quaí cuía pheïp gheïp L1 vaì L2. Vê
duû :
?- append( [ a, b ], [ c, d ], [ a, b, c, d ] ).
Yes
?- append( [ a, b ], [ c, d ], [ a, b, a, c ] ).
No
Haìm append hoaût âäüng phuû thuäüc tham âäúi âáöu tiãn L1 theo caïch nhæ
sau :
1. Nãúu tham âäúi âáöu tiãn laì danh saïch räùng, thç tham âäúi thæï hai vaì thæï
ba phaíi laì mäüt danh saïch duy nháút, goüi laì L. Ta viãút trong Prolog nhæ
sau :
append( [ ], L, L).
Cáúu truïc danh saïch 101

2. Nãúu tham âäúi âáöu tiãn cuía append laì danh saïch khaïc räùng, thç noï gäöm
mäüt âáöu vaì mäüt âuäi nhæ sau
[ X | L1 ]
Kãút quaí pheïp gheïp danh saïch laì danh saïch [ X | L3 ], våïi L3 laì pheïp
gheïp cuía L1 vaì L2. Ta viãút trong Prolog nhæ sau :
append( [ X | L1 ], L2, [ X | L3 ] ) :- append( L1, L2, L3 ).
Hçnh 4.2 dæåïi âáy minh hoaû pheïp gheïp hai danh saïch [ X | L1 ] vaì L2.

[ X | L1 ]

X L1 L2

L3
X L3

[ X | L3 ]

Hçnh III.1. Gheïp hai danh saïch [ X | L1 ] vaì L2 thaình [ X | L3 ].

Ta coï caïc vê duû sau :


?- append( [ a, b, c ], [ 1, 2, 3 ], L ).
L = [ a, b, c, 1, 2, 3 ]
?- append( [ a, [ b, c ], d ], [ a, [ ], b ], L ] ).
L = [ a, [ b, c ], d, a, [ ], b ]
Thuí tuûc append âæåüc sæí duûng ráút mãöm deío theo nhiãöu caïch khaïc nhau.
Chàóng haûn Prolog âæa ra bäún phæång aïn âãø phán taïch mäüt danh saïch âaî
cho thaình hai danh saïch måïi nhæ sau :
?- append( L1, L2, [ a, b, c ] ).
L1 = [ ]
L2 = [ a, b, c ];
L1 = [ a ]
L2 = [ b, c ];
L1 = [ a, b ]
L2 = [ c ];
L1 = [ a, b, c ]
L2 = [ ];
Yes
102 Láûp trçnh lägich trong Prolog

Sæí duûng append, ta cuîng coï thãø tçm kiãúm mäüt säú pháön tæí trong mäüt danh
saïch. Chàóng haûn, tæì danh saïch caïc thaïng trong nàm, ta coï thãø tçm nhæîng
thaïng âæïng træåïc mäüt thaïng âaî cho, giaí sæí thaïng nàm (May) :
?- append( Before, [ May | After ] ,
[ jan, fev, mar, avr, may, jun, jul, aut, sep, oct, nov, dec ] ).
Before = [ jan, fev, mar, avr ]
After = [ jun, jul, aut, sep, oct, nov, dec ]
Yes
Thaïng âæïng ngay træåïc vaì thaïng âæïng ngay sau thaïng nàm nháûn âæåüc nhæ
sau :
?- append( _, [ Month1, may, Month2 | _ ] ,
[ jan, fev, mar, avr, may, jun, jul, aut, sep, oct, nov, dec ] ).
Month1 = avr
Month2 = jun
Yes
Báy giåì cho træåïc danh saïch :
L1 = [ a, b, z, z, c, z, z, z, d, e ]
Ta cáön xoïa caïc pháön tæí âæïng sau ba chæî z liãn tiãúp, kãø caí ba chæî z :
?- L1 = [ a, b, z, z, c, z, z, z, d, e ],
append( L2, [ z, z, z | _ ], L1 ).
L1 = [ a, b, z, z, c, z, z, z, d, e ]
L2 = [ a, b, z, z, c ]
Træåïc âáy ta âaî âënh nghéa quan hãû member( X, L ) âãø kiãøm tra mäüt pháön
tæí X coï màût trong mäüt danh saïch L khäng. Báy giåì bàòng caïch sæí duûng
append, ta coï thãø âënh nghéa laûi member nhæ sau :
member1( X, L ) :- append( L1, [ X | L2], L).
Mãûnh âãö naìy coï nghéa : nãúu X coï màût trong danh saïch L thç L coï thãø âæåüc
phán taïch thaình hai danh saïch, våïi X laì âáöu cuía danh saïch thæï hai. Âënh
nghéa member1 hoaìn toaìn tæång âæång våïi âënh nghéa member.
ÅÍ âáy ta sæí duûng hai tãn khaïc nhau âãø phán biãût hai caïch caìi âàût Prolog.
Ta cuîng coï thãø âënh nghéa laûi member1 bàòng caïch sæí duûng biãún nàûc danh
(anonymous variable) :
member1( X, L ) :- append( _ , [ X | _ ], L).
Cáúu truïc danh saïch 103

member1( b, [ a, b, c ] )

append( L1, [ b | L2 ], [ a, b, c ] )
Mãûnh âãö 1 cuía append Mãûnh âãö 2 cuía append

So khåïp : So khåïp :
L1 = [ ] L1 = [ X | L1’ ]
[ b | L2 ] = [ a, b, c ] [ b | L2 ] = L2’
[ a, b, c ] = [ X | L3’ ]
Tháút baûi vç b ≠ a
Tæì âoï keïo theo :
X = a, L3’ = [ b, c ]

append( L1’, [ b | L2 ], [ b, c ] )

Mãûnh âãö 1 cuía append


So khåïp :
L1’ = [ ]
[ b | L2 ] = [ b, c ]
Tæì âoï keïo theo :
L2 = [ c ]

thaình cäng

Hçnh III.2. Thuí tuûc member1 tçm tuáön tæû mäüt âäúi tæåüng trong danh saïch âaî cho.
So saïnh hai caïch caìi âàût khaïc nhau vãö quan hãû thaình viãn, ta nháûn tháúy
nghéa thuí tuûc trong âënh nghéa member âæåüc thãø hiãûn ráút roî :
Trong member, âãø kiãøm tra pháön tæí X coï màût trong mäüt danh saïch L
khäng,
1. Træåïc tiãn kiãøm tra pháön tæí âáöu cuía L laì âäöng nháút våïi X, nãúu khäng,
2. Kiãøm tra ràòng X coï màût trong pháön âuäi cuía L.
Nhæng trong træåìng håüp âënh nghéa member1, ta tháúy hoaìn toaìn nghéa
khai baïo maì khäng coï nghéa thuí tuûc.
Âãø hiãøu âæåüc caïch member1hoaût âäüng nhæ thãú naìo, ta haîy xem xeït quaï
trçnh Prolog thæûc hiãûn cáu hoíi :
?- member1( b, [ a, b, c ] ).
104 Láûp trçnh lägich trong Prolog

Caïch tçm cuía thuí tuûc member1 trãn âáy tæång tæû member, bàòng caïch
duyãût tæìng pháön tæí, cho âãún khi tçm tháúy âäúi tæåüng cáön tçm, hoàûc danh saïch
âaî caûn.

III.1.3. Bäø sung mäüt pháön tæí vaìo danh saïch


Phæång phaïp âån giaín nháút âãø bäø sung mäüt pháön tæí vaìo danh saïch laì âàût
noï åí vë trê âáöu tiãn, âãø noï tråí thaình âáöu. Nãúu X laì mäüt âäúi tæåüng måïi, coìn L
laì danh saïch cáön bäø sung thãm, thç danh saïch kãút quaí seî laì :
[X|L]
Ngæåìi ta khäng cáön viãút thuí tuûc âãø bäø sung mäüt pháön tæí vaìo danh saïch.
Båíi vç viãûc bäø sung coï thãø âæåüc biãøu diãùn dæåïi daûng mäüt sæû kiãûn nãúu cáön :
insert( X, L, [ X | L ] ).

III.1.4. Loaûi boí mäüt pháön tæí khoíi danh saïch


Âãø loaûi boí mäüt pháön tæí X khoíi danh saïch L, ngæåìi ta xáy dæûng quan hãû :
remove( X, L, L1 )
trong âoï, L1 âäöng nháút våïi L, sau khi X bë loaûi boí khoíi L. Thuí tuûc remove coï
cáúu truïc tæång tæû member. Ta coï thãø láûp luáûn nhæ sau
1. Nãúu pháön tæí X laì âáöu cuía danh saïch, thç kãút quaí laì âuäi cuía danh
saïch.
2. Nãúu khäng, tçm caïch loaûi boí X khoíi pháön âuäi cuía danh saïch.
remove( X, [ X | Tail ], Tail ).
remove( X, [ Y | Tail ], [ Y | Tail1 ] ) :-
remove( X, Tail, Tail1 ).
Tæång tæû thuí tuûc member, thuí tuûc remove mang tênh khäng xaïc âënh.
Nãúu coï nhiãöu pháön tæí laì X coï màût trong danh saïch, thç remove coï thãø xoaï báút
kyì pháön tæí naìo, do quaï trçnh quay lui. Tuy nhiãn, mäùi láön thæûc hiãûn, remove
chè xoaï mäüt pháön tæí laì X maì khäng âuûng âãún nhæîng pháön tæí khaïc. Vê duû :
?- remove( a, [ a, b, a, a ], L ).
L = [ b, a, a ];
L = [ a, b, a ];
L = [ a, b, a ]
No
Cáúu truïc danh saïch 105

Thuí tuûc remove tháút baûi nãúu danh saïch khäng chæïa pháön tæí cáön xoaï.
Ngæåìi ta coï thãø sæí duûng remove trong mäüt khêa caûnh khaïc, muûc âêch âãø bäø
sung mäüt pháön tæí måïi vaìo báút cæï âáu trong danh saïch.
Vê duû, nãúu ta muäún âàût pháön tæí a vaìo taûi moüi vë trê báút kyì trong danh
saïch [ 1, 2, 3 ], chè cáön âàût cáu hoíi : Cho biãút danh saïch L nãúu sau khi xoaï a,
ta nháûn âæåüc danh saïch [ 1, 2, 3 ] ?
?- remove( a, L, [ 1, 2, 3 ] ).
L = [ a, 1, 2, 3 ];
L = [ 1, a, 2, 3 ];
L = [ 1, 2, a, 3 ];
L = [ 1, 2, 3, a ]
No
Mäüt caïch täøng quaït, pheïp toaïn cheìn insert mäüt pháön tæí X vaìo mäüt danh
saïch List âæåüc âënh nghéa båíi thuí tuûc remove bàòng caïch sæí duûng mäüt danh
saïch låïn hån LargerList laìm tham âäúi thæï hai :
insert( X, List, LargerList ) :-
remove( X, LargerList, List ).
Ta âaî âënh nghéa quan hãû thuäüc vãö trong thuí tuûc member1 bàòng caïch sæí
duûng thuí tuûc append. Tuy nhiãn, ta cuîng coï thãø âënh nghéa laûi quan hãû
thuäüc vãö trong thuí tuûc måïi member2 båíi thuí tuûc remove bàòng caïch xem mäüt
pháön tæí X thuäüc vãö mäüt danh saïch List nãúu X bë xoaï khoíi List :
member2( X, List ) :-
remove( X, List, _ ).

III.1.5. Nghëch âaío danh saïch


Sæí duûng append, ta coï thãø viãút thuí tuûc nghëch âaío mäüt danh saïch nhæ
sau :
reverse ( [ ], [ ] ).
reverse ( [ X | Tail ], R ) :-
reverse (Tail, R1 ),
append(R1, [X], R).
?- reverse( [ a, b, c , d, e, f ] , L).
L = [f, e, d, c, b, a]
Yes
106 Láûp trçnh lägich trong Prolog

Sau âáy laì mäüt thuí tuûc khaïc âãø nghëch âaío mäüt danh saïch nhæng coï sæí
duûng haìm bäø tråü trong thán thuí tuûc :
revert(List, RevList) :-
rev(List, [ ], RevList).
rev([ ], R, R).
rev([H|T], S, R) :-
rev(T, [H|S], R).
?- revert( [ a, b, c , d, e, f ] , R).
R = [f, e, d, c, b, a]
Yes

Sæí duûng reverse, ta coï thãø kiãøm tra mäüt danh saïch coï laì âäúi xæïng
(palindrome) kay khäng :
palindrome(L) :-
reverse( L, L ).
?- palindrome([ a, b, c , d, c, b, a ]).
Yes

III.1.6. Danh saïch con


Ta xáy dæûng thuí tuûc sublist nháûn hai tham âäúi laì hai danh saïch L vaì S
sao cho S laì danh saïch con cuía L nhæ sau :
?- sublist( [ c, d, e ], [ a, b, c , d, e, f ] )
Yes
?- sublist( [ c, e ], [ a, b, c , d, e, f ] )
No
Nguyãn lyï âãø xáy dæûng thuí tuûc sublist tæång tæû thuí tuûc member1, màûc duì
åí âáy quan hãû danh saïch con täøng quaït hån.
L

L1 X L2 member( X, L )

L [ X | L2 ]

L1 S L3 sublist( S, L )

L2

Hçnh III.3. Caïc quan hãû member vaì sublist.


Cáúu truïc danh saïch 107

Quan hãû danh saïch con âæåüc mä taí nhæ sau :


S laì mäüt danh saïch con cuía L nãúu :
1. Danh saïch L coï thãø âæåüc phán taïch thaình hai danh saïch L1 vaì L2, vaì
nãúu
2. Danh saïch L2 coï thãø âæåüc phán taïch thaình hai danh saïch S vaì L3.
Nhæ âaî tháúy, viãûc phán taïch caïc danh saïch coï thãø âæåüc mä taí båíi quan hãû
gheïp append.
Do âoï ta viãút laûi trong Prolog nhæ sau :
sublist( S, L ) :-
append( L1, L2, L ), append( S, L3, L2 ).
Ta tháúy thuí tuûc sublist ráút mãöm deío vaì do váûy coï thãø sæí duûng theo nhiãöu
caïch khaïc nhau. Chàóng haûn ta coï thãø liãût kã moüi danh saïch con cuía mäüt
danh saïch âaî cho nhæ sau :
?- sublist( S, [ a, b, c ] ).
S = [ ];
S = [ a ];
S = [ a, b ];
S = [ a, b, c ];
S = [ b ];
...

III.2. Hoaïn vë
Âäi khi, ta cáön taûo ra caïc hoaïn vë cuía mäüt danh saïch. Ta xáy dæûng quan
hãû permutation coï hai tham biãún laì hai danh saïch, maì mäüt danh saïch laì hoaïn
vë cuía danh saïch kia. Ta seî táûn duûng pheïp quay lui nhæ sau :
?- permutation( [ a, b, c ], P ).
P = [ a, b, c ];
P = [ a, c, b ];
P = [ b, a, c ];
...
Nguyãn lyï hoaût âäüng cuía thuí tuûc swap dæûa trãn hai træåìng håüp phán
biãût, tuyì theo danh saïch thæï nháút :
1. Nãúu danh saïch thæï nháút räùng, thç danh saïch thæï hai cuîng phaíi räùng.
108 Láûp trçnh lägich trong Prolog

2. Nãúu danh saïch thæï nháút khaïc räùng, thç noï seî coï daûng [ X | L ] vaì âæåüc
tiãún haình hoaïn vë nhæ sau : træåïc tiãn hoaïn vë L âãø nháûn âæåüc L1, sau
âoï cheìn X vaìo táút caí caïc vë trê trong L1.

X L

hoaïn vë L

L1 L1 laì mäüt hoaïn vë cuía L

Cheìn X taûi mäüt vë trê âãø nháûn âæåüc mäüt hoaïn vë cuía [ X | L ]

Hçnh III.4. Mäüt caïch xáy dæûng hoaïn vë permutation cuía danh saïch [ X | L ].

Ta nháûn âæåüc hai mãûnh âãö tæång æïng våïi thuí tuûc nhæ sau :
permutation( [ ], [ ] ).
permutation( [ X | L ], P ) :-
permutation( L, L1 ), insert( X, L1, P ).
Mäüt phæång phaïp khaïc laì loaûi boí pháön tæí X khoíi danh saïch âáöu tiãn,
hoaïn vë pháön coìn laûi cuía danh saïch naìy âãø nháûn âæåüc danh saïch P, sau âoï
thãm X vaìo pháön âáöu cuía P. Ta coï chæång trçnh khaïc permutation2 nhæ sau :
permutation2( [ ], [ ] ).
permutation2( L, [ X | P ] ) :-
remove( X, L, L1 ), permutation2( L1, P ).

Tæì âáy, ta coï thãø khai thaïc thuí tuûc hoaïn vë, chàóng haûn (chuï yï khi chaûy
Arity Prolog cáön goî vaìo mäüt dáúu cháúm pháøy ; sau ->) :
?- permutation( [ red, blue, green ], P ).
P = [ red, blue, green ];
P = [ red, green, blue ];
P = [ blue, red, green ];
P = [ blue, green, red ];
P = [ green, red, blue ];
P = [ green, blue, red ];
Yes
Hoàûc nãúu sæí duûng permutation theo caïch khaïc nhæ sau :
?- permutation( L, [ a, b, c ] ).
Prolog seî raìng buäüc liãn tiãúp cho L âãø âæa ra 6 hoaïn vë khaïc nhau coï thãø.
Tuy nhiãn, nãúu NSD yãu cáöu mäüt giaíi phaïp khaïc, Prolog seî khäng bao giåì
Cáúu truïc danh saïch 109

traí låìi “No”, maì råi vaìo mäüt voìng làûp vä haûn do phaíi tçm kiãúm mäüt hoaïn vë
måïi maì thæûc ra khäng täön taûi. Trong træåìng håüp naìy, thuí tuûc permutation2
chè tçm tháúy mäüt hoaïn vë thæï nháút, sau âoï ngay láûp tæïc råi vaìo mäüt voìng làûp
vä haûn. Vç váûy, cáön chuï yï khi sæí duûng caïc quan hãû hoaïn vë naìy.

III.3. Mäüt säú vê duû vãö danh saïch


III.3.1. Sàõp xãúp caïc pháön tæí cuía danh saïch
Xáy dæûng thuí tuûc sàõp xãúp caïc pháön tæí coï cuía mäüt danh saïch bàòng phæång
phaïp cheìn nhæ sau :
ins(X, [ ], [ X ]).
ins(X, [H|T], [ X,H|T ]) :-
X @=< H.
ins(X, [ H|T ], [ H|L ]) :-
X @> H, ins( X, T, L ).
?- ins(8, [ 1, 2, 3, 4, 5 ], L).
L = [1, 2, 3, 4, 5, 8]
Yes
?- ins(1, L, [ 1, 2, 3, 4, 5 ]).
L = [2, 3, 4, 5]
Yes
ins_sort([ ], [ ]).
ins_sort([H|T], L) :-
ins_sort(T, L1),
ins(H, L1, L).
?- ins_sort([3, 2, 6, 4, 7, 1], L).
L = [1, 2, 3, 4, 6, 7]
Yes

III.3.2. Tênh âäü daìi cuía mäüt danh saïch


Xáy dæûng thuí tuûc tênh âäü daìi hay âãúm säú læåüng caïc pháön tæí coï màût trong
mäüt danh saïch âaî cho nhæ sau :
length( L, N ).
Xaíy ra hai træåìng håüp :
1. Nãúu danh saïch räùng, thç âäü daìi N = 0.
110 Láûp trçnh lägich trong Prolog

2. Nãúu danh saïch khaïc räùng, thç noï âæåüc taûo thaình tæì danh saïch coï
daûng :
[ head | queue ]
vaì coï âäü daìi bàòng 1 cäüng våïi âäü daìi cuía queue.
Ta coï chæång trçnh Prolog nhæ sau :
length( [ ], 0 ).
length( [ _ | Queue ], N ) :-
length(Queue, N1 ),
N is 1 + N1.
Kãút quaí chaûy Prolog nhæ sau :
?- length( [ a, b, c, d, e ], N ).
N=5
Yes
?- length( [ a, [ b, c ], d, e ], N ).
N=4
Yes
Ta tháúy ràòng trong mãûnh âãö thæï hai, hai âêch cuía pháön thán laì khäng
thãø hoaïn âäøi cho nhau, vç ràòng N1 phaíi âæåüc raìng buäüc træåïc khi thæûc hiãûn
âêch :
N is 1 + N1
Chàóng haûn, nãúu goüi trace, quaï trçnh thæûc hiãûn length( [ 1, 2, 3 ], N ) nhæ
sau :
(0) goüi length([1, 2, 3], N) ->
(1) goüi length([2, 3], N’) ->
(2) goüi length([3], N’’) ->
(3) goüi length([ ], N’’’) -> N’’’ = 0
(4) goüi N’’ is 1 + 0 -> N’’ = 1
(5) goüi N’ is 1 + 1 -> N’ = 2
(6) goüi N is 1 + 2 -> N=3

Våïi is, ta âaî âæa vaìo mäüt quan hãû nhaûy caím våïi thæï tæû thæûc hiãûn caïc âêch,
vaì do váûy khäng thãø boí qua yãúu täú thuí tuûc trong chæång trçnh.
Âiãöu gç seî xaíy ra nãúu ta khäng sæí duûng is trong chæång trçnh. Chàóng
haûn :
length1( [ ], 0 ).
Cáúu truïc danh saïch 111

length1( [ _ | Queue ], N ) :-
length1( Queue, N1 ),
N = 1 + N1.
Luïc naìy, nãúu goüi :
?- length1( [ a, [ b, c ], d, e ], N ).
Prolog traí låìi :
N = 1 + (1 + (1 + (1 + 0)))
Yes
Pheïp cäüng do khäng âæåüc khåíi âäüng mäüt caïch tæåìng minh nãn seî khäng
bao giåì âæåüc thæûc hiãûn. Tuy nhiãn, ta coï thãø hoaïn âäøi hai âêch cuía mãûnh âãö
thæï hai trong length1 :
length1( [ ], 0 ).
length1( [ _ | Queue ], N ) :-
N = 1 + N1,
length1( Queue, N1 ).
Kãút quaí chaûy chæång trçnh sau khi hoaïn âäøi váùn y hãût nhæ cuî. Báy giåì, ta
laûi coï thãø ruït goün mãûnh âãö vãö chè coìn mäüt âêch :
length1( [ ], 0 ).
length2( [ _ | Queue ], 1 + N ) :-
length2( Queue, N ).
Kãút quaí chaûy chæång trçnh láön naìy váùn y hãût nhæ cuî. Prolog khäng âæa
ra traí låìi nhæ mong muäún, maì laì :
?- length1([ a, b, c, d], N).
N = 1+ (1+ (1+ (1+0)))
Yes

III.3.3. Taûo sinh caïc säú tæû nhiãn


Chæång trçnh sau âáy taûo sinh vaì liãût kã caïc säú tæû nhiãn :
% Natural Numbers
nat(0).
nat(N) :- nat(M), N is M + 1.
Khi thæûc hiãûn caïc âêch con trong cáu hoíi :
?- nat(N), write(N), nl, fail.
112 Láûp trçnh lägich trong Prolog

caïc säú tæû nhiãn âæåüc taûo sinh liãn tiãúp nhåì kyî thuáût quay lui. Sau khi säú tæû
nhiãn âáöu tiãn nat(N) âæåüc in ra nhåì write(N), hàòng fail bàõt buäüc thæûc hiãûn
quay lui. Khi âoï, luáût thæï hai âæåüc váûn duûng âãø taûo sinh säú tæû nhiãn tiãúp
theo vaì cæï thãú tiãúp tuûc cho âãún khi NSD quyãút âënh dæìng chæång trçnh (^C).

Toïm tàõt chæång 4


• Danh saïch laì mäüt cáúu truïc hoàûc räùng, hoàûc gäöm hai pháön : pháön âáöu laì
mäüt pháön tæí vaì pháön coìn laûi laì mäüt danh saïch.
• Prolog quaín lyï caïc danh saïch theo cáúu truïc cáy nhë phán. Prolog cho
pheïp sæí duûng nhiãöu caïch khaïc nhau âãø biãøu diãùn danh saïch.
[ Object1, Object2, ... ]
hoàûc [ Head | Tail ]
hoàûc [ Object1, Object2, ... | Others ]
Våïi Tail vaì Others laì caïc danh saïch.
• Caïc thao taïc cäø âiãøn trãn danh saïch coï thãø láûp trçnh âæåüc laì : kiãøm tra
mäüt pháön tæí coï thuäüc vãö mäüt danh saïch cho træåïc khäng, pheïp gheïp
hai danh saïch, bäø sung hoàûc loaûi boí mäüt pháön tæí åí âáöu hoàûc cuäúi danh
saïch, trêch ra mäüt danh saïch con...

Baìi táûp chæång 4


1. Viãút mäüt thuí tuûc sæí duûng append âãø xoïa ba pháön tæí cuäúi cuìng cuía danh
saïch L, taûo ra danh saïch L1. Hæåïng dáùn : L laì pheïp gheïp cuía L1 våïi mäüt
danh saïch cuía ba pháön tæí (âaî bë xoïa khoíi L).
2. Viãút mäüt daîy caïc âêch âãø xoïa ba pháön tæí âáöu tiãn vaì ba pháön tæí cuäúi cuìng
cuía mäüt danh saïch L, âãø traí vãö danh saïch L2.

3. Âënh nghéa quan hãû :


last_element( Object, List )

sao cho Object phaíi laì pháön tæí cuäúi cuìng cuía danh saïch List. Haîy viãút
thaình hai mãûnh âãö, trong âoï coï mäüt mãûnh âãö sæí duûng append, mãûnh âãö
kia khäng sæí duûng append.
4. Âënh nghéa hai vë tæì :
Cáúu truïc danh saïch 113

even_length( List ) vaì odd_length( List )


âæåüc thoîa maîn khi säú caïc phán tæí cuía danh saïch List laì chàôn hay leí tæång
æïng. Vê duû danh saïch :
[ a, b, c, d ] coï âäü daìi chàôn,
[ a, b, c ] coï âäü daìi leî.

5. Cho biãút kãút quaí Prolog traí låìi caïc cáu hoíi sau :
?- [1,2,3] = [1|X].
?- [1,2,3] = [1,2|X].
?- [1 | [2,3]] = [1,2,X].
?- [1 | [2,3,4]] = [1,2,X].
?- [1 | [2,3,4]] = [1,2|X].
?- b(o,n,j,o,u,r) =.. L.
?- bon(Y) =.. [X,jour].
?- X(Y) =.. [bon,jour].

6. Viãút chæång trçnh Prolog kiãøm tra mäüt danh saïch coï phaíi laì mäüt táûp håüp
con cuía mäüt danh saïch khaïc khäng ? Chæång trçnh hoaût âäüng nhæ sau :
?- subset2([4,3],[2,3,5,4]).
Yes

7. Viãút chæång trçnh Prolog âãø láúy ra caïc pháön tæí tæì mäüt danh saïch. Chæång
trçnh cuîng coï thãø cheìn caïc pháön tæí vaìo mäüt danh saïch hoaût âäüng nhæ
sau :
?- takeout(3,[1,2,3],[1,2]).
Yes
?- takeout(X,[1,2,3],L).
X=1
L = [2, 3] ;
X=2
L = [1, 3] ;
X=3
L = [1, 2] ;
No
?- takeout(4,L,[1,2,3]).
4
L = [4, 1, 2, 3] ;
L = [1, 4, 2, 3] ;
L = [1, 2, 4, 3] ;
114 Láûp trçnh lägich trong Prolog

L = [1, 2, 3, 4] ;
No

8. Viãút vë tæì Prolog getEltFromList(L,N,E) cho pheïp láúy ra pháön tæí thæï N
trong mäüt danh saïch. Tháút baûi nãúu danh saïch khäng coï âuí N pháön tæí.
Chæång trçnh hoaût âäüng nhæ sau :
?- getEltFromList([a,b,c],0,X).
No
?- getEltFromList([a,b,c],2,X).
X=b
?- getEltFromList([a,b,c],4,X).
No

9. Viãút chæång trçnh Prolog tçm pháön tæí låïn nháút vaì pháön tæí nhoí nháút trong
mäüt danh saïch caïc säú. Chæång trçnh hoaût âäüng nhæ sau :
?- maxmin([3,1,5,2,7,3],Max,Min).
Max = 7
Min = 1
Yes
?- maxmin([2],Max,Min).
Max = 2
Min = 2
Yes
10. Viãút chæång trçnh Prolog chuyãøn mäüt danh saïch phæïc håüp, laì danh saïch
maì mäùi pháön tæí coï thãø laì mäüt danh saïch con chæïa caïc danh saïch con
phæïc håüp khaïc, thaình mäüt danh saïch phàóng laì danh saïch chè chæïa caïc
pháön tæí trong táút caí caïc danh saïch con coï thãø, giæî nguyãn thæï tæû luïc
âáöu. Chæång trçnh hoaût âäüng nhæ sau :
flatten([[1,2,3],[4,5,6]], Flatlist).
Flatlist = [1,2,3,4,5,6]
Yes
flatten([[1,[hallo,[[aloha]]],2,[],3],[4,[],5,6]], Flatlist)
Flatlist = [1, hallo, aloha, 2, 3, 4, 5, 6]
Yes
11. Viãút caïc chæång trçnh Prolog thæûc hiãûn caïc vë tæì xæí lyï táûp håüp cho åí pháön
lyï thuyãút (muûc II).
Cáúu truïc danh saïch 115

12. Sæí duûng vë tæì forall âãø viãút chæång trçnh Prolog kiãøm tra hai danh saïch
coï råìi nhau (disjoint) khäng ? Chæång trçnh hoaût âäüng nhæ sau :
?- disjoint([a,b,c],[d,g,f,h]).
Yes
?- disjoint([a,b,c],[f,a]).
No
13. Vë tæì forall(Cond, Action) thæûc hiãûn kiãøm tra sæû so khåïp tæång æïng giæîa
Cond, thæåìng kãút håüp våïi vë tæì member, vaì Action. Vê duû dæåïi âáy kiãøm
tra viãûc thæûc hiãûn caïc pheïp toaïn säú hoüc trong danh saïch L laì âuïng âàõn.
?- forall(member(Result = Formula, [2 = 1 + 1, 4 = 2 * 2]), Result =:=
Formula).
Result = _G615
Formula = _G616
Yes
14. Sæí duûng vë tæì forall âãø viãút chæång trçnh Prolog kiãøm tra mäüt danh saïch
coï laì mäüt táûp håüp con cuía mäüt danh saïch khaïc hay khäng ? Chæång trçnh
hoaût âäüng nhæ sau :
?- subset3([a,b,c],[c,d,a,b,f]).
Yes
?- subset3([a,b,q,c],[d,a,c,b,f])
No

15. Sæí duûng vë tæì append gheïp hai danh saïch âãø viãút caïc chæång trçnh
Prolog thæûc hiãûn caïc viãûc sau :
prefixe(L1, L2) danh saïch L1 âæïng træåïc (prefixe list) danh saïch L2.
suffixe(L1, L2) danh saïch L1 âæïng sau (suffixe list) danh saïch L2.
isin(L1, L2) caïc pháön tæí cuía danh saïch L1 coï màût trong danh saïch
L2.

16. Sæí duûng phæång phaïp Quicksort viãút chæång trçnh Prolog sàõp xãúp nhanh
mäüt danh saïch caïc säú âaî cho theo thæï tæû tàng dáön.
17. Âoüc hiãøu chæång trçnh sau âáy räöi dæûng laûi thuáût toaïn :
/* Missionarys & Cannibals */
/* Traïnh voìng làûp */
lNotExist(_,[]).
lNotExist(X,[T|Q]) :-
X\==T, lNotExist(X,Q).
116 Láûp trçnh lägich trong Prolog

/* Kiãøm tra tênh håüp lyï cuía traûng thaïi */


valid(MG,CG,MD,CD) :-
MG>=0, CG>=0, MD>=0, CD>=0, MG=0, MD>=CD.
valid(MG,CG,MD,CD) :-
MG>=0, CG>=0, MD>=0, CD>=0, MG>=CG, MD=0.
valid(MG,CG,MD,CD) :-
MG>=0, CG>=0, MD>=0, CD>=0, MG>=CG, MD>=CD.
/* Xáy dæûng cung vaì kiãøm tra */
sail(1,0). sail(0,1). sail(1,1). sail(2,0). sail(0,2).
arc([left,MGi,CGi,MDi,CDi],[droite,MGf,CGf,MDf,CDf]) :-
sail(Mis,Can),
MGf is MGi-Mis, MDf is MDi+Mis,
CGf is CGi-Can, CDf is CDi+Can,
valid(MGf,CGf,MDf,CDf).
arc([right,MGi,CGi,MDi,CDi],[left,MGf,CGf,MDf,CDf]) :-
sail(Mis,Can),
MGf is MGi+Mis, MDf is MDi-Mis,
CGf is CGi+Can, CDf is CDi-Can,
valid(MGf,CGf,MDf,CDf).
/* Pheïp âãû quy */
cross(A,A,[A],Non).
cross(X,Y,Ch,Non) :-
arc(X,A), lNotExist(A,Non),
cross(A,Y,ChAY,[A|Non]), Ch=[X|ChAY].
/* Âi qua */
traverse(X,Y,Ch) :-
cross(X,Y,Ch,[X]).
CHÆÅNG 5

Kyî thuáû t láû p trçnh Prolog

I. Nhaït càõt
I.1. Khaïi niãûm nhaït càõt
Nhæ âaî tháúy, mäüt trçnh Prolog âæåüc thæûc hiãûn nhåì caïc mãûnh âãö vaì caïc
âêch. Sau âáy ta seî xeït mäüt kyî thuáût khaïc cuía Prolog cho pheïp ngàn chàûn sæû
quay lui laì nhaït càõt (cut).
Prolog tæû âäüng quay lui khi cáön tçm mäüt tçm kiãúm mäüt mãûnh âãö khaïc âãø
thoaí maîn âêch. Âiãöu naìy ráút coï êch âäúi våïi ngæåìi láûp trçnh khi cáön sæí duûng
nhiãöu phæång aïn giaíi quyãút váún âãö . Tuy nhiãn, nãúu khäng kiãøm soaït täút quaï
trçnh naìy, viãûc quay lui seî tråí nãn keïm hiãûu quaí. Vç váûy, Prolog sæí duûng kyî
thuáût nhaït càõt kiãøm soaït quay lui, hay cáúm quay lui, âãø khàõc phuûc khiãúm
khuyãút naìy.
Trong vê duû sau âáy, mäüt chæång trçnh Prolog sæí duûng kyî thuáût quay lui
keïm hiãûu quaí. Ta cáön xaïc âënh caïc vë trê maì tæì âoï chæång trçnh bàõt âáöu quaï
trçnh quay lui. Ta xeït haìm báûc thang
Ta coï ba quy tàõc xaïc âënh quan hãû giæîa hai truûc X vaì Y nhæ sau :
1. Nãúu X < 3 thç Y = 0
2. Nãúu X ≤ 3 vaì X < 6 thç Y = 2
3. Nãúu X ≤ 6 thç Y = 4
Ta viãút thaình quan hãû nhë phán f( X, Y ) trong Prolog nhæ sau :
f( X, 0) :- X < 3. % luáût 1
f( X, 2) :- 3 =< X, X < 6. % luáût 2
f( X, 4) :- 6 =< X. % luáût 3

117
118 Láûp trçnh lägich trong Prolog

Y
-
-
4 -
-
2 -
-
+ + + + + + + + +
3 6 X
Hçnh I.1.Haìm báûc thang coï hai báûc.
Khi chaûy chæång trçnh, giaí sæí ràòng biãún X cuía haìm f( X, Y ) âaî âæåüc nháûn
mäüt giaï trë säú âãø coï thãø thæûc hiãûn pheïp so saïnh trong thán haìm. Tæì âáy, xaíy
ra hai khaí nàng sæí duûng kyî thuáût nhaït càõt nhæ sau :

I.2. Kyî thuáût sæí duûng nhaït càõt


I.2.1. Kyî thuáût nhaït càõt thæï nháút
Giaí sæí ta âàût ra cáu hoíi :
?- f( 1, Y ), 2 < Y.
Luïc naìy, Y nháûn giaï trë 0, âêch thæï hai tråí thaình :
2<0
vaì gáy ra kãút quaí No (tháút baûi) cho caí danh saïch caïc âêch coìn laûi, vç Prolog
coìn tiãúp tuûc tiãún haình thãm hai quaï trçnh quay lui vä êch khaïc :

f( 1, Y), 2 < Y.

Luáût 1 Luáût 2 Luáût 3


Y=0 Y=2 Y=4
1 < 3, 2 < 0 3 ≤ 1, 1 < 6, 2 < 2 6 ≤ 1, 2 < 4

Nhaït càõt Tháút baûi Tháút baûi

2<0
Tháút baûi
Hçnh I.2. Taûi vë trê «Nhaït càõt», caïc luáût 2 vaì 3 âaî biãút træåïc tháút baûi.
Kyî thuáût láûp trçnh Prolog 119

Caí ba luáût âënh nghéa quan hãû f coï tênh cháút loaûi træì láùn nhau, chè coï duy
nháút mäüt trong chuïng laì coï thãø thaình cäng. Ngæåìi láûp trçnh biãút âiãöu naìy
nhæng Prolog laûi khäng biãút, cho nãn cæï tiãúp tuûc aïp duûng táút caí caïc luáût màûc
duì âi âãún tháút baûi. Trong vê duû trãn, luáût 1 âæåüc aïp duûng taûi vë trê «Nhaït
càõt» vaì gáy ra tháút baûi. Âãø traïnh sæû quay lui khäng cáön thiãút bàõt âáöu tæì vë
trê naìy, chuïng ta cáön baïo cho Prolog biãút mäüt caïch tæåìng minh, bàòng caïch sæí
duûng mäüt nhaït càõt, kyï hiãûu båíi mäüt dáúu cháúm than «!» thæûc cháút laì mäüt âêch
giaí (pseudo goal) âæåüc cheìn vaìo giæîa caïc âêch tháût khaïc. Chæång trçnh haìm
báûc thang âæåüc viãút laûi nhæ sau :
f( X, 0) :- X < 3, !. % luáût 1
f( X, 2) :-
3 =< X, X < 6, !. % luáût 2
f( X, 4) :-
6 =< X. % luáût 3
Nhaït càõt ! seî cáúm moüi quaï trçnh quay lui tæì vë trê xuáút hiãûn cuía noï trong
chæång trçnh. Nãúu báy giåì ta yãu cáöu thæûc hiãûn âêch :
?- f( 1, Y ), 2 < Y.
Prolog chè thæûc hiãûn nhaïnh traïi nháút æïng våïi luáût 1 trong hçnh trãn, traí vãö
kãút quaí tháút baûi vç xaíy ra 2 < 0 maì khäng tiãúp tuûc quay lui thæûc hiãûn caïc
nhaïnh tæång æïng våïi luáût 2 vaì 3, do âaî gàûp nhaït càõt !. Chæång trçnh måïi sæí
duûng nhaït càõt chaûy hiãûu quaí hån chæång trçnh cuî. Khi xaíy ra tháút baûi,
Prolog seî nhanh choïng dæìng, maì khäng máút thåìi gian âãø thæûc hiãûn nhæîng
viãûc vä êch khaïc. Sæí duûng nhaït càõt trong mäüt chæång trçnh laìm thay âäøi
nghéa thuí tuûc nhæng khäng laìm thay âäøi nghéa khai baïo. Tuy nhiãn sau âáy
ta seî tháúy ràòng nhaït càõt coï thãø laìm máút âi nghéa khai baïo.

I.2.2. Kyî thuáût nhaït càõt thæï hai


Giaí sæí báy giåì ta goüi thæûc hiãûn âêch :
?- f( 7, Y ).
Y=4
Yes
Quaï trçnh thæûc hiãûn âæåüc mä taí nhæ sau : træåïc khi nháûn âæåüc kãút quaí,
vãö nguyãn tàõc, Prolog phaíi sæí duûng caí ba luáût âãø coï quaï trçnh xoaï âêch.
120 Láûp trçnh lägich trong Prolog

Thæí luáût 1 7 < 3 tháút baûi, quay lui, thæí luáût 2 (nhaït càõt chæa âæåüc sæí
duûng).
Thæí luáût 2 3 ≤ 7 thoaí maîn, nhæng 7 < 6 tháút baûi, quay lui, thæí luáût 3
(nhaït càõt chæa âæåüc sæí duûng).
Thæí luáût 3 6 <= 7 thoaí maîn.
Âãún âáy, ta laûi tháúy xuáút hiãûn chæång trçnh thæûc hiãûn keïm hiãûu quaí. Khi
xaíy ra âêch X < 3 (nghéa laì 7 < 3) tháút baûi, âêch tiãúp theo 3 ≤ X (3 ≤ 7) thoaí
maîn, Prolog tiãúp tuûc kiãøm tra âêch trong luáût 3. Nhæng ta biãút ràòng nãúu mäüt
âêch thæï nháút tháút baûi, thç âêch thæï hai bàõt buäüc phaíi âæåüc thoaí maîn vç noï laì
phuí âënh cuía âêch thæï nháút. Viãûc kiãøm tra láön næîa seî tråí nãn dæ thæìa vç âêch
tæång æïng våïi noï coï thãø bë xoaï. Nhæ váûy viãûc kiãøm tra âêch 6 <= X cuía luáût 3
laì khäng cáön thiãút. Våïi nháûn xeït naìy, ta coï thãø viãút laûi chæång trçnh haìm báûc
thang tiãút kiãûm hån nhæ sau :
Nãúu X < 3 thç Y = 0,
Nãúu khäng, nãúu X < 6 thç Y = 2,
Nãúu khäng Y = 4.
Bàòng caïch loaûi khoíi chæång trçnh nhæîng âiãöu kiãûn maì biãút chàõc chàõn seî
âuïng, ta nháûn âæåüc chæång trçnh måïi nhæ sau :
f( X, 0) :- X < 3, !.
f( X, 2) :- X < 6, !.
f( X, 4).
Chæång trçnh naìy cho kãút quaí tæång tæû hai chæång trçnh træåïc âáy
nhæng thæûc hiãûn nhanh hån do âaî loaûi boí hoaìn toaìn nhæîng quay lui khäng
cáön thiãút.
?- f(1, Y ).
Y=0
Yes
?- f(5, Y ).
Y=2
Yes
?- f(7, Y ).
Y=4
Yes
Nhæng váún âãö gç seî xaíy ra nãúu báy giåì ta laûi loaûi boí hãút caïc nhaït càõt ra
khoíi chæång trçnh ? Chàóng haûn :
Kyî thuáût láûp trçnh Prolog 121

f( X, 0) :- X < 3.
f( X, 2) :- X < 6.
f( X, 4).
Våïi låìi goüi :
?- f( 1, Y ).
Y = 0;
Y = 2;
Y = 4;
No
Prolog âæa ra nhiãöu cáu traí låìi nhæng khäng âuïng. Nhæ váûy, viãûc sæí
duûng nhaït càõt âaî laìm thay âäøi âäöng thåìi nghéa thuí tuûc vaì nghéa khai baïo.
Kyî thuáût nhaït càõt coï thãø âæåüc mä taí nhæ sau :
Ta goüi «âêch cha» laì âêch tæång æïng våïi pháön âáöu cuía mãûnh âãö chæïa nhaït
càõt. Ngay khi gàûp nhaït càõt, Prolog xem ràòng mäüt âêch âaî âæåüc thoaí maîn mäüt
caïch tæû âäüng, vaì gêåïi haûn sæû læûa choün caïc mãûnh âãö trong phaûm vi giæîa låìi goüi
âêch cha vaì thåìi âiãøm thæûc hiãûn nhaït càõt. Táút caí caïc mãûnh âãö tæång æïng våïi
caïc âêch con chæa âæåüc kiãøm tra so khåïp giæîa âêch cha vaì nhaït càõt âãöu âæåüc boí
qua.
Âãø minh hoaû, ta xeït mãûnh âãö coï daûng :
H :- G1, G2, ... Gm, ! , ... , Bn.
Giaí sæí ràòng mãûnh âãö naìy âæåüc khåíi âäüng båíi mäüt âêch G håüp nháút âæåüc
våïi H, khi âoï, G laì âêch cha. Cho âãún khi gàûp nhaït càõt, Prolog âaî tçm âæåüc
caïc låìi giaíi cho caïc âêch con G1, G2, ... Gm.
Ngay sau khi thæûc hiãûn nhaït càõt, caïc âêch con G1, G2, ... Gm bë «vä hiãûu
hoaï», kãø caí caïc mãûnh âãö tæång æïng våïi caïc âêch con naìy cuîng bë boí qua. Hån
næîa, do G håüp nháút våïi H nãn Prolog khäng tiãúp tuûc tçm kiãúm âãø so khåïp H
våïi âáöu (head) cuía caïc mãûnh âãö khaïc.
Chàóng haûn, aïp duûng nguyãn lyï trãn cho vê duû sau :
C :- P, Q, R, ! S, T, U.
C :- V.
A :- B, C, D.
?- A.
Giaí sæí A, B, C, D, P, ... âãöu laì caïc haûng. Taïc âäüng cuía nhaït càõt khi thæûc
hiãûn âêch C nhæ sau : quaï trçnh quay lui xaíy ra bãn trong danh saïch caïc âêch
122 Láûp trçnh lägich trong Prolog

P, Q, R, nhæng ngay khi thæûc hiãûn nhaït càõt, moüi con âæåìng dáùn âãún caïc
mãûnh âãö trong danh saïch P, Q, R âãöu bë boí qua. Mãûnh âãö C thæï hai :
C :- V.
cuîng bë boí qua. Tuy nhiãn, viãûc quay lui váùn coï thãø xaíy ra bãn trong danh
saïch caïc âêch S, T, U. Âêch cha cuía mãûnh âãö chæïa nhaït càõt laì C åí trong mãûnh
âãö :
A :- B, C, D.
Nhæ váûy, nhaït càõt chè taïc âäüng âäúi våïi mãûnh âãö C, maì khäng taïc âäüng âäúi
våïi A. Viãûc quay lui tæû âäüng trong danh saïch caïc âêch B, C, D váùn âæåüc thæûc
hiãûn, âäüc láûp våïi nhaït càõt hiãûn diãûn trong C.

I.2.3. Vê duû sæí duûng kyî thuáût nhaït càõt


1. Tçm säú max
Xáy dæûng chæång trçnh tçm säú låïn nháút trong hai säú coï daûng :
max( X, Y, MaX )
trong âoï, Max = X nãúu X låïn hån hoàûc bàòng Y, vaì Max = Y nãúu X nhoí hån
hoàûc bàòng Y. Ta xáy dæûng hai quan hãû nhæ sau :
max( X, Y, X ) :- X >= Y.
max( X, Y, Y ) :- X < Y.
Hai quan hãû trãn loaûi træì láùn nhau. Nãúu quan hãû thæï nháút thoaí maîn, thç
quan hãû thæï 2 chè coï thãø tháút baûi vaì ngæåüc laûi. AÏp duûng daûng âiãöu kiãûn quen
thuäüc «nãúu-thç-nãúu khäng thç» âãø laìm goün chæång trçnh laûi nhæ sau :

Nãúu X ≥ Y thç Max = X,


Nãúu khäng thç Max = Y.
Sæí duûng kyî thuáût nhaït càõt, chæång trçnh âæåüc viãút laûi nhæ sau :
max( X, Y, X ) :- X >= Y, !.
max( X, Y, Y ).
Kyî thuáût láûp trçnh Prolog 123

2. Kiãøm tra mäüt pháön tæí coï thuäüc danh saïch âaî cho khäng
Ta âaî xáy dæûng quan hãû :
membre( X, L).
âãø kiãøm tra pháön tæí X coï nàòm trong danh saïch L hay khäng. Chæång trçnh
nhæ sau :
membre( X, [X | L]).
membre( X, [X | L]) :- membre( X, L).
Tuy nhiãn, chæång trçnh naìy hoaût âäüng mäüt caïch «khäng âån âënh». Nãúu
X xuáút hiãûn nhiãöu láön trong danh saïch, thç báút kyì pháön tæí naìo bàòng X cuîng
âæåüc tçm tháúy. Báy giåì ta chuyãøn membre thaình mäüt quan hãû âån âënh chè
taïc âäüng âäúi våïi pháön tæí X âáöu tiãn. Viãûc thay âäøi ráút âån giaín nhæ sau : chè viãûc
cáúm quay lui ngay khi X âæåüc tçm tháúy, nghéa laì khi mãûnh âãö âáöu tiãn âæåüc
thoaí maîn :
membre( X, [ X | L ]) :- !.
membre( X, [ X | L ]) :- membre( X, L).
Khi âoï, trong vê duû sau, Prolog chè âæa ra mäüt låìi giaíi :
?- membre( X, [a, a, b, c]).
X=a;
No

3. Thãm mäüt pháön tæí vaìo danh saïch maì khäng bë truìng làõp
Thäng thæåìng, khi muäún thãm mäüt pháön tæí måïi, chàóng haûn X, vaìo danh
saïch L, ngæåìi ta muäún træåïc âoï, L khäng chæïa pháön tæí naìy. Giaí sæí quan hãû
cáön xáy dæûng :
ajoute( X, L, L1)
coï X laì pháön tæí måïi cáön thãm vaìo danh saïch L, L1 laì kãút quaí coï chæïa âuïng
mäüt X. Ta láûp luáûn nhæ sau :

Nãúu X thuäüc danh saïch L, thç L1 = L,


Nãúu khäng, L1 laì L âaî âæåüc thãm X vaìo.
Caïch âån giaín nháút laì cheìn pháön tæí X vaìo ngay âáöu danh saïch sao cho
noï laì pháön tæí âáöu (head) cuía L1. Ta coï chæång trçnh nhæ sau :
ajoute( X, L, L) :- membre( X, L), !.
124 Láûp trçnh lägich trong Prolog

ajoute( X, L, [ X | L ] ).
Sau âáy laì caïc váûn duûng chæång trçnh :
?- ajoute( a, [ b, c ], L).
L = [ a, b, c ]
?- ajoute( X, [ b, c ], L).
L = [ b, c ]
X=b
?- ajoute( a, [ b, c, X ], L).
X = _G333
L = [a, b, c, _G333]
?- ajoute( a, [ a, b, c ], L).
L = [a, b, c];
Trong vê duû naìy, nhåì sæí duûng kyî thuáût nhaït càõt, ngæåìi láûp trçnh dãù daìng
thãm mäüt pháön tæí måïi vaìo danh saïch maì khäng laìm truìng làûp pháön tæí âoï.
Nãúu khäng sæí duûng kyî thuáût nhaït càõt, viãûc thãm mäüt pháön tæí måïi vaìo mäüt
danh saïch coï thãø laìm truìng làûp pháön tæí.
Nhæ váûy, kyî thuáût nhaït càõt khäng nhæîng laìm täúi æu hiãûu quaí láûp trçnh,
maì coìn ráút cáön thiãút âãø âàûc taí âuïng âàõn mäúi quan hãû giæîa caïc âäúi tæåüng.

4. Sæí duûng nhaït càõt âãø phán loaûi dæî liãûu


Giaí sæí ta cáön quaín lyï mäüt CSDL chæïa kãút quaí caïc tráûn âáúu cuía caïc häüi
viãn mäüt cáu laûc bäü quáön våüt. Caïc tráûn âáúu khäng âæåüc sàõp xãúp mäüt caïch coï
hãû thäúng, maì mäùi häüi viãn coï thãø âáúu våïi báút cæï ai. Kãút quaí caïc tráûn âáúu
âæåüc biãøu diãùn båíi caïc sæû kiãûn nhæ sau :
bat( tom, jim).
bat( ann, tom).
bat( pat, jim).
Ta cáön âënh nghéa quan hãû :
classe(Player, CategorY ).
âãø phán thæï haûng cho mäùi ngæåìi chåi quáön våüt trong ba haûng nhæ sau :
champion ngæåìi luän thàõng trong táút caí caïc tráûn âáúu
combative ngæåìi coï caí baìn thàõng vaì coï caí baìn thua
dilettante ngæåìi luän thua trong táút caí caïc tráûn âáúu
Kyî thuáût láûp trçnh Prolog 125

Tæì kãút quaí nhæîng tráûn âáúu âaî coï âæåüc cho trong caïc sæû kiãûn, ta tháúy Ann
vaì Pat âæåüc xãúp haûng quaïn quán (champion), Tom âæåüc xãúp haûng trung bçnh
(combative), coìn Jim thç âæåüc xãúp haûng yãúu keïm (dilettante). Ta coï thãø dãù
daìng xáy dæûng caïc luáût xãúp haûng nhæ sau :
X âæåüc xãúp haûng trung bçnh nãúu
täön taûi Y sao cho X thàõng Y, vaì
täön taûi Z sao cho Z thàõng X.
X âæåüc xãúp haûng quaïn quán nãúu
X thàõng Y, vaì
X khäng bë thua báút kyì âäúi thuí naìo.
Luáût xãúp haûng quaïn quán coï chæïa pheïp phuí âënh (not) maì cho âãún luïc
naìy, ta chæa tçm hiãøu caïch biãøu diãùn nhæ thãú naìo trong Prolog. Luáût xãúp
haûng yãúu keïm cuîng xáy dæûng tæång tæû luáût xãúp haûng quaïn quán. Ta coï thãø
sæí duûng så âäö if-then-else âãø xæí lyï âäöng thåìi hai tçnh huäúng nhæ sau :
Nãúu X thàõng vaì X bë thua khi âáúu våïi báút kyì ai
thç X âæåüc xãúp haûng trung bçnh
nãúu khäng, nãúu X thàõng báút kyì ai
thç X âæåüc xãúp haûng quaïn quán
nãúu khäng, nãúu X luän bë thua
thç X âæåüc xãúp haûng yãúu keïm.
Tæì så âäö trãn ta coï thãø chuyãøn sang Prolog sæí duûng kyî thuáût nhaït càõt âãø
xæí lyï khaí nàng loaûi træì nhau giæîa ba thæï haûng.
classe( X, combative) :-
bat( X, _ ),
bat( _, X ), !.
classe( X, champion) :-
bat( X, _ ), !.
classe( X, dilettante) :-
bat( _, X ).
Chuï yï ràòng khäng nháút thiãút phaíi sæí duûng nhaït càõt trong mãûnh âãö
champion vç baín cháút cuía ba thæï haûng.
126 Láûp trçnh lägich trong Prolog

I.3. Pheïp phuí âënh


I.3.1. Phuí âënh båíi tháút baûi
Trong Prolog, ta coï thãø noïi âæåüc cáu : «Marie thêch táút caí loaìi âäüng váût
træì loaìi ràõn» hay khäng ?
Âäúi våïi vãú thæï nháút, ta coï thãø dãù daìng dëch ra thaình : Duì X laì gç, Marie
thêch X nãúu X laì loaìi âäüng váût :
enjoy( marie, X ) :-
animal( X ).
Tuy nhiãn cáön loaûi træì loaìi ràõn. Luïc naìy ta cáön dëch ra nhæ sau :
Nãúu X laì loaìi ràõn, thç «Marie thêch X» laì sai,
Nãúu khäng, nãúu X laì loaìi âäüng váût thç Marie thêch X.
Nhæîng gç khäng âuïng thç coï thãø sæí duûng âêch âàûc biãût fail (tháút baûi) âãø
luän luän sai, vaì cuîng laìm cho âêch cha tháút baûi. Chæång trçnh âæåüc viãút laûi
nhæ sau :
enjoy( marie, X ) :-
serpent( X ), !, fail.
enjoy( marie, X ) :-
animal( X ).
Luáût thæï nháút xæí lyï tçnh huäúng Marie khäng thêch loaìi ràõn : nãúu X laì loaìi
ràõn, thç nhaït càõt seî ngàn sæû quay lui (vaì do âoï, luáût thæï hai khäng âæåüc thæûc
hiãûn), vaì âêch fail seî gáy ra tháút baûi. Ta coï thãø sæí duûng dáúu ; âãø viãút cä âoüng
hai luáût thaình mäüt luáût nhæ sau :
enjoy( marie, X ) :-
serpent( X ), !, fail;
animal( X ).
Mäüt caïch tæång tæû, ta âënh nghéa quan hãû khaïc nhau :
différent( X, Y )
thoaí maîn nãúu X vaì Y laì khaïc nhau. Do sæû khaïc nhau coï thãø âæåüc diãùn giaíi
theo nhiãöu caïch nãn ta cáön chè roî nhæ sau :
• X vaì Y khäng phaíi laì caïc træûc hàòng (literal) âäöng nháút,
• X vaì Y khäng thãø khåïp våïi nhau,
• Caïc giaï trë cuía caïc biãøu thæïc säú hoüc X vaì Y khäng thãø bàòng nhau.
Kyî thuáût láûp trçnh Prolog 127

Ta noïi ràòng X vaì Y khaïc nhau do chuïng khäng thãø khåïp âæåüc våïi nhau :
Nãúu X vaì Y laì âäöng nháút, thç différent( X, Y ) tháút baûi,
Nãúu khäng, différent( X, Y ) thaình cäng.
Ta sæí duûng nhaït càõt vaì âêch fail âãø viãút quan hãû naìy thaình hai luáût :
différent( X, X ) :- !, fail.
différent( X, Y ).
Hoàûc viãút laûi thaình mäüt luáût nhæ sau :
différent( X, Y ) :-
X = Y, !, fail;
true.
Chuï yï ràòng âêch true (âuïng) luän luän thaình cäng.
Tæì âáy, ta coï thãø âënh nghéa vë tæì not(Goal) cho pheïp kiãøm tra âêch khäng
thoaí maîn nhæ sau :
Nãúu Goal thoaí maîn, thç not(Goal) tháút baûi,
Nãúu khäng, not(Goal) thaình cäng.
Chæång trçnh Prolog :
not( P ) :-
P, !, fail;
true.
Háöu hãút caïc phiãn baín Prolog hiãûn nay âãöu coï vë tæì not
not(2 = 3).
Yes
?- not(2 = 2).
No
Sæí duûng vë tæì not, ta coï thãø âënh nghéa laûi caïc quan hãû enjoy, différent vaì
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 ).
128 Láûp trçnh lägich trong Prolog

classe( X, champion) :-
bat( X _ ),
not bat( _ , X ).
classe( X, dilettante) :-
bat( _ , X ),
not bat( X, _ ).

I.3.2. Sæí duûng kyî thuáût nhaït càõt vaì phuí âënh

Æu âiãøm cuía kyî thuáût nhaït càõt coï thãø toïm tàõt nhæ sau :
1. Náng cao tênh hiãûu quaí cuía mäüt chæång trçnh nhåì nguyãn tàõc thäng
baïo mäüt caïch tæåìng minh cho Prolog traïnh khäng âi theo nhæîng con
âæåìng dáùn âãún tháút baûi.
2. Kyî thuáût nhaït càõt cho pheïp xáy dæûng nhæîng luáût coï tênh cháút loaûi træì
nhau coï daûng :

Nãúu âiãöu kiãûn P xaíy ra thç kãút luáûn laì Q,


Nãúu khäng, thç kãút luáûn laì R.
Tuy nhiãn sæí duûng nhaït càõt coï thãø laìm máút sæû tæång æïng giæîa nghéa khai
baïo vaì nghéa thuí tuûc cuía mäüt chæång trçnh. Nãúu trong chæång trçnh khäng
xuáút hiãûn nhaït càõt, thç viãûc thay âäøi thæï tæû caïc mãûnh âãö vaì caïc âêch chè laìm
aính hæåíng âãún hiãûu quaí chaûy chæång trçnh maì khäng laìm thay âäøi nghéa
khai baïo. Coìn khi coï màût nhaït càõt trong mäüt chæång trçnh, thç laûi xaíy ra váún
âãö, luïc naìy coï thãø coï thãø nhiãöu kãút quaí khaïc nhau. Vê duû :
p :- a, b.
p :- c.
Xeït vãö màût nghéa khai baïo, chæång trçnh trãn coï nghéa : p âuïng nãúu vaì
chè nãúu caí a vaì b âãöu âuïng, hoàûc c âuïng. Tæì âoï ta xáy dæûng biãøu thæïc lägich
nhæ sau :
p ⇔ (a ∧ b) ∨ c
Nghéa khai baïo khäng coìn âuïng næîa nãúu ta thay âäøi mãûnh âãö thæï nháút
bàòng caïch thãm vaìo mäüt nhaït càõt :
p :- a, !, b.
p :- c.
Biãøu thæïc lägich tæång æïng nhæ sau :
Kyî thuáût láûp trçnh Prolog 129

p ⇔ (a ∧ b) ∨ (~a ∧ c)
Nãúu ta âaío thæï tæû hai mãûnh âãö :
p :- c.
p :- a, !, b.
thç ta laûi coï cuìng nghéa nhæ ban âáöu :
p ⇔ c ∨ (a ∧ b)
Ngæåìi ta phaíi tháûn troüng khi sæí duûng kyî thuáût nhaït càõt do nhaït càõt laìm
thay âäøi nghéa thuí tuûc vaì laìm tàng nguy cå xaíy ra sai soït trong chæång
trçnh. Nhæ âaî xeït trong caïc vê duû træåïc âáy, viãûc loaûi boí nhaït càõt coï thãø laìm
thay âäøi nghéa khai baïo cuía mäüt chæång trçnh. Tuy nhiãn trong mäüt säú
træåìng håüp, nhaït càõt khäng aính hæåíng âãún nghéa khai baïo. Ngæåìi ta goüi
nhæîng nhaït càõt khäng laìm thay âäøi ngæî nghéa cuía chæång trçnh laì nhaït càõt
xanh (green cuts). Âæïng trãn quan âiãøm láûp trçnh dãù âoüc vaì dãù hiãøu
(readability), caïc nhaït càõt xanh laì an toaìn vaì ngæåìi ta thæåìng hay sæí duûng
chuïng. Tháûm chê, ngæåìi ta coï thãø boí qua sæû coï màût cuía chuïng khi âoüc chæång
trçnh. Ngæåìi ta noïi nhaït càõt xanh laìm roî raìng (explicit) tênh tiãön âënh
(determinism) väún khäng roî raìng (implicit). Thäng thæåìng nhaït càõt xanh
âæåüc âàût ngay sau pheïp kiãøm tra tiãön âënh.
Vê duû sæí duûng nhaït càõt xanh tçm säú min :
minimum(X, Y, X) :-
X =< Y, !.
minimum(X, Y, Y) :-
X > Y, !.
Vê duû sæí duûng nhaït càõt xanh kiãøm tra kiãøu cuía cáy nhë phán caïc säú
nguyãn :
int_bin_tree(ab(X,G,D)) :-
integer(X),
int_bin_tree(G),
int_bin_tree(D).
int_bin_tree(X) :-
integer(X).
Trong caïc træåìng håüp khaïc, caïc nhaït càõt aính hæåíng âãún nghéa khai baïo
âæåüc goüi laì nhaït càõt âoí (red cuts). Sæû coï màût cuía caïc nhaït càõt âoí thæåìng laìm
cho chæång trçnh tråí nãn khoï âoüc, khoï hiãøu. Âãø sæí duûng âæåüc chuïng, NSD
130 Láûp trçnh lägich trong Prolog

phaíi hãút sæïc chuï yï. Vê duû sæí duûng nhaït càõt âoí tçm säú min thay âäøi ngæî
nghéa :
minimum_cut( X, Y, X ) :-
X =< Y, !.
minimum_cut( X, Y, Y ).
Trong mäüt säú træåìng håüp, mäüt cáu hoíi coï thãø khäng liãn quan âãún ngæî
nghéa cuía chæång trçnh. Vê duû vë tæì kiãøm tra mäüt pháön tæí coï thuäüc danh
saïch khäng :
member_cut(X, [ X | _ ] ) :- !.
member_cut(X, [ _ | L ] ) :- member_cut(X, L ).
Våïi cáu hoíi member_cut(X, [ 1, 2, 3 ] ) seî khäng cho kãút quaí X = 2.
?- member_cut(X, [ 1, 2, 3 ] ).
X=1;
No
Thäng thæåìng, âêch fail âæåüc duìng càûp âäi våïi nhaït càõt (cut-fail). Ngæåìi ta
thæåìng âënh nghéa pheïp phuí âënh mäüt âêch (not) bàòng caïch gáy ra sæû tháút
baûi cuía âêch naìy, thæûc cháút laì caïch sæí duûng nhaït càõt coï haûn chãú. Âãø chæång
trçnh dãù hiãùu hån, thay vç sæí duûng càûp âäi cut-fail, ngæåìi ta sæí duûng not. Tuy
nhiãn, pheïp phuí âënh not cuîng khäng phaíi khäng gáy ra nhæîng phiãön phæïc
cho ngæåìi duìng. Nhiãöu khi sæí duûng not khäng hoaìn toaìn chênh xaïc våïi pheïp
phuí âënh trong Toaïn hoüc. Chàóng haûn nãúu trong chæång trçnh coï âënh nghéa
quan hãû man, maì ta âæa ra mäüt cáu hoíi âaûi loaûi nhæ :
?- not( man( marie)).
Khi âoï, Prolog seî traí låìi No nãúu âaî coï âënh nghéa man( marie), traí låìi Yes
nãúu chæa coï âënh nghéa nhæ váûy. Tuy nhiãn, khi traí låìi No, khäng phaíi
Prolog noïi ràòng «Marie khäng phaíi laì mäüt ngæåìi», maì noïi ràòng «Khäng tçm
tháúy trong chæång trçnh thäng tin âãø chæïng minh Marie laì mäüt ngæåìi». Khi
thæûc hiãûn pheïp not, Prolog khäng chæïng minh træûc tiãúp maì tçm caïch chæïng
minh âiãöu ngæåüc laûi. Nãúu chæïng minh âæåüc, Prolog suy ra ràòng âêch not
thaình cäng. Caïch láûp luáûn nhæ váûy âæåüc goüi laì giaí thuyãút vãö thãú giåïi kheïp kên
(hypothesis of the enclosed world). Theo giaí thuyãút naìy, thãú giåïi kheïp kên coï
nghéa laì nhæîng gi täön taûi (âuïng) âãöu nàòm trong chæång trçnh hoàûc âæåüc suy
ra tæì chæång trçnh. Nhæîng gç khäng nàòm trong chæång trçnh, hoàûc khäng
thãø suy ra tæì chæång trçnh, thç seî laì khäng âuïng (sai), hay âiãöu phuí âënh laì
Kyî thuáût láûp trçnh Prolog 131

âuïng. Vç váûy, cáön chuï yï khi sæí duûng phuí âënh do thäng thæåìng, ngæåìi ta âaî
khäng giaí thiãút ràòng thãú giåïi laì kheïp kên. Trong chæång trçnh, do thiãúu khai
baïo mãûnh âãö :
man( marie).
nãn Prolog khäng chæïng minh âæåüc ràòng Marie laì mäüt ngæåìi.
Sau âáy laì mäüt vê duû khaïc sæí duûng pheïp phuí âënh not :
r( a).
q( b).
p( X ) :- not( r( X )).
Nãúu âàût cáu hoíi :
?- q( X ), p( X ).
thç Prolog seî traí låìi :
X=b
Yes
Nhæng nãúu âàût cáu hoíi :
?- p( X ), q( X ).
thç Prolog seî traí låìi :
No
Âãø hiãøu âæåüc vç sao cuìng mäüt chæång trçnh nhæng våïi hai caïch âàût cáu
hoíi khaïc nhau laûi coï hai caïch traí låìi khaïc nhau, ta cáön tçm hiãøu caïch Prolog
láûp luáûn. Trong træåìng håüp thæï nháút, biãún X âæåüc raìng buäüc giaï trë laì b khi
thæûc hiãûn âêch q( X ). Tiãúp tuûc thæûc hiãûn âêch con p( X ), nhåì raìng buäüc X=b,
âêch not( r( X )) thoaí maîn vç âêch r( b ) khäng thoaí maîn, Prolog traí låìi Yes.
Traïi laûi trong træåìng håüp thæï hai, do Prolog thæûc hiãûn âêch con p( X )
træåïc nãn sæû tháút baûi cuía not( r( X )), tæïc r( X ) thaình cäng våïi raìng buäüc X=a,
dáùn âãún cáu traí låìi No.

II. Sæí duûng caïc cáúu truïc


Kiãøu dæî liãûu cáúu truïc, danh saïch, kyî thuáût so khåïp, quay lui vaì nhaït càõt
laì nhæîng âiãøm maûnh trong láûp trçnh Prolog. Chæång naìy seî tiãúp tuûc trçnh
baìy mäüt säú vê duû tiãu biãøu vãö :
ƒ Truy cáûp thäng tin cáúu truïc tæì mäüt cå såí dæî liãûu.
132 Láûp trçnh lägich trong Prolog

ƒ Mä phoíng mäüt ätämat hæîu haûn khäng âån âënh vaì maïy Turing.
ƒ Láûp kãú hoaûch âi du lëch
ƒ Baìi toaïn taïm quán háûu

Âäöng thåìi, ta cuîng trçnh baìy caïch Prolog træìu tæåüng hoaï dæî liãûu.

II.1. Truy cáûp thäng tin cáúu truïc tæì mäüt cå såí dæî liãûu
Sau âáy laì mäüt vê duû cho pheïp biãøu diãùn vaì thao taïc caïc dæî liãûu cáúu truïc.
Tæì âoï, ta cuîng hiãøu caïch sæí duûng Prolog nhæ mäüt ngän ngæî truy váún cå såí dæî
liãûu.
Trong Prolog, mäüt cå såí âæåüc biãøu diãùn dæåïi daûng mäüt táûp håüp caïc sæû
kiãûn. Chàóng haûn, mäüt cå såí dæî liãûu vãö caïc gia âçnh seî mä taí mäùi gia âçnh
(family) nhæ mäüt mãûnh âãö. Mäùi gia âçnh seî gäöm ba pháön tæí láön læåüt : chäöng,
våü (individual) vaì caïc con (children). Do caïc pháön tæí naìy thay âäøi tuy theo
tæìng gia âçnh, nãn caïc con seî âæåüc biãøu diãùn båíi mäüt danh saïch âãø coï thãø
nháûn âæåüc mäüt säú læåüng tuyì yï säú con. Mäùi ngæåìi trong gia âçnh âæåüc biãøu
diãùn båíi bäún thaình pháön : tãn, hoü, ngaìy thaïng nàm sinh vaì viãûc laìm. Thaình
pháön viãûc laìm coï thãø coï giaï trë “tháút nghiãûp” (inactive), hoàûc chè roî tãn cå
quan cäng taïc vaì thu nháûp theo nàm.
Giaí sæí cå såí dæî liãûu chæïa mãûnh âãö âáöu tiãn nhæ sau :
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) ] ).
Dæî liãûu vãö nhæîng gia âçnh khaïc tiãúp tuûc âæåüc bäø sung dæåïi daûng caïc
mãûnh âãö tæång tæû. Hçnh 5.1 dæåïi âáy minh hoaû caïch täø chæïc cå såí dæî liãûu.
Prolog laì mäüt ngän ngæî ráút thêch håüp cho viãûc khäi phuûc thäng tin : ngæåìi
sæí duûng coï thãø goüi caïc âäúi tæåüng maì khäng nháút thiãút chè roî táút caí caïc thaình
pháön. Ngæåìi sæí duûng chè cáön chè ra cáúu truïc cuía caïc âäúi tæåüng maì hoü quan
tám mäüt caïch tæûång træng, khäng cáön phaíi chè ra hãút. Hçnh 1.2 minh hoaû
nhæîng cáúu truïc nhæ váûy. Vê duû, âãø biãøu diãùn nhæîng gia âçnh doìng hoü Smith,
trong Prolog viãút :
family( individual( _ , smith, _ , _ ), _ , _ )
Kyî thuáût láûp trçnh Prolog 133

family

individual individual .

tom smith date work ann smith date inactive children .

7 may 1960 microsoft 30000 9 avril 1962 roze smith date inactive children []

16 june 1991 eric smith date inactive

23 march 1993

Hçnh II.1. Cáúu truïc cáy biãøu diãùn thäng tin vãö mäüt gia âçnh
(a) family (b) family

_ _ .
individual _ _

_ .
_ bob _ _

(c) family _ .

_ []
_ individual .

Firstname Lastname _ _ _ .

_ .

_ _

Hçnh II.2. tênh cháút cáúu truïc cuía caïc âäúi tæåüng Prolog cho pheïp biãøu diãùn :
(a) mäüt gia âçnh Smith naìo âoï ; (b) nhæîng gia âçnh coï âuïng ba con ; (c) nhæîng gia
âçnh coï êt nháút ba con. Riãng træåìng håüp (c) coìn cho pheïp biãøu diãùn tãn cuía ngæåìi våü
nhåì sæû raìng buäüc caïc biãún Firstname vaì Lastname.
Nhæîng dáúu gaûch dæåïi doìng nhæ âaî biãút laì caïc biãún nàûc danh, ngæåìi sæí
duûng khäng cáön quan tám âãún giaï trë cuía chuïng. Mäüt caïch tæång tæû, nhæîng
gia âçnh coï ba con âæåüc biãøu diãùn båíi :
family( _ , _ , [ _ , _ , _ ] )
134 Láûp trçnh lägich trong Prolog

Ta cuîng coï thãø âàût cáu hoíi tçm nhæîng ngæåìi våü trong nhæîng gia âçnh coï êt
nháút ba con :
?- family( _ , individual( Firstname, Lastname, _ , _ ), [ _ , _ , _ | _ ] ).
Nhæîng vê duû trãn âáy chè ra ràòng ta coï thãø biãøu diãùn caïc âäúi tæåüng båíi cáúu
truïc cuía chuïng maì khäng cáön quan tám âãún näüi dung, bàòng caïch boí qua
nhæîng tham âäúi vä âënh.
Sau âáy laì mäüt säú mãûnh âãö âæåüc âæa thãm vaìo cå såí dæî liãûu caïc gia âçnh
âãø coï thãø âàût caïc cáu hoíi váún tin khaïc nhau (coï thãø bäø sung thãm caïc gia âçnh
måïi båíi mãûnh âãö family) :
husban( X ) :- % X laì mäüt ngæåìi chäöng
family( X , _ , _ ).
wife( X ) :- % X laì mäüt ngæåìi våü
family( _, X , _ ).
chidren( X ) :- % X laì mäüt ngæåìi con, chuï yï caïc tãn biãún chæî hoa
family( _, _ , Chidren ),
ismember( X, Chidren ).
ismember( X, [ X | L ] ). % coï thãø sæí duûng mãûnh âãö member cuía Prolog
ismember( X, [ Y | L ] ) :-
ismember( X, L ).
exist( Individual ) :- % moüi thaình viãn cuía gia âçnh
husban( Individual ) ;
wife( Individual ) ;
chidren( Individual ).
dateofbirth( individual( _ , _, Date , _ ), Date ).
salary( individual( _ , _, _ , work( _ , S ) ), S ). % thu nháûp cuía ngæåìi lao
âäüng
salary( individual( _ , _, _ , inactive ), 0 ). % ngæåìi khäng coï nguäön thu
nháûp
Báy giåì ta coï thãø âàût caïc cáu hoíi nhæ sau :
1. Tçm tãn hoü cuía nhæîng ngæåìi coï màût trong cå såí dæî liãûu :
?- exist( individual( Firstname, Lastname, _ , _ ) ).
2. Tçm nhæîng ngæåìi con sinh nàm 1991 :
?- chidren( X ), dateofbirth( X, date( _ , _ , 1991 ) ).
3. Tçm nhæîng ngæåìi våü coï viãûc laìm :
Kyî thuáût láûp trçnh Prolog 135

?- wife( individual( Firstname, Lastname, _ , work( _ , _ ) ) ).


4. Tçm nhæîng ngæåìi khäng coï viãûc laìm sinh træåïc nàm 1975 :
?- exist( individual( Firstname, Lastname, date( _ , _ , Year ), inactive ) ),
Year < 1975.
5. Tçm nhæîng ngæåìi sinh træåïc nàm 1975 coï thu nháûp dæåïi 10000 :
?- exist( Individual ),
dateofbirth( Individual, date( _ , _ , Year ) ),
Year < 1975,
salary( Individual, Salary ),
Salary < 10000.
6. Tçm nhæîng gia âçnh coï êt nháút ba con :
?- family( individual( _, Name, _ , _ ), _, [ _, _, _ | _ ] ).
Âãø tênh täøng thu nháûp cuía mäüt gia âçnh, ta coï thãø âënh nghéa mäüt quan
hãû nhë phán cho pheïp tênh täøng caïc thu nháûp cuía mäüt danh saïch nhæîng
ngæåìi âang coï viãûc laìm daûng :
total( List_of_ individual, Sum_of_ salary )
Ta viãút trong Prolog nhæ sau :
total( [ ], 0 ) % danh saïch räùng
total( [ Individual | List ], Sum ) :-
salary( Individual, S ), % S laì thu nháûp cuía ngæåìi âáöu tiãn
total( List, Remain ), % Remain laì thu nháûp cuía táút caí nhæîng ngæåìi
coìn laûi
Sum is S + Remain.
Nhæ váûy, täøng thu nháûp cuía mäüt gia âçnh âæåüc tênh båíi cáu hoíi :
?- family( Husban, Wife, Chidren ),
total( [ Husban, Wife | Chidren ], Income ).

Caïc phiãn baín Prolog âãöu coï thãø tênh âäü daìi (length) cuía mäüt danh saïch
(xem muûc III chæång 1 træåïc âáy, ta cuîng âaî tçm caïch xáy dæûng quan hãû
naìy). Báy giåì ta coï thãø aïp duûng âãø tçm nhæîng gia âçnh coï nguäön thu nháûp
nhoí hån 5000 tênh theo âáöu ngæåìi :
?- family( Husban, Wife, Chidren ),
total( [ Husban, Wife | Chidren ], Income )
length( [ Husban, Wife | Chidren ], N ),
Income / N < 5000. % N laì säú ngæåìi trong mäüt gia âçnh
136 Láûp trçnh lägich trong Prolog

II.2. Træìu tæåüng hoaï dæî liãûu


Træìu tæåüng hoaï dæî liãûu (data abstraction) âæåüc xem laì caïch täø chæïc tæû
nhiãn (mäüt caïch coï thæï cáúp) nhæîng thaình pháön khaïc nhau trong cuìng nhæîng
âån vë thäng tin, sao cho vãö màût yï niãûm, ngæåìi sæí duûng coï thãø hiãøu âæåüc cáúu
truïc bãn trong. Chæång trçnh phaíi dãù daìng truy cáûp âæåüc vaìo tæìng thaình
pháön dæî liãûu. Mäüt caïch lyï tæåíng thç ngæåìi sæí duûng khäng nhçn tháúy âæåüc
nhæîng chi tiãút caìi âàût caïc cáúu truïc naìy, ngæåìi sæí duûng chè quan tám âãún
nhæîng âäúi tæåüng vaì quan hãû giæîa chuïng. Våïi muûc âêch âoï, Prolog phaíi coï
caïch biãøu diãùn thäng tin phuì håüp.
Âãø tçm hiãøu caïch Prolog giaíi quyãút, ta quay laûi vê duû cå såí dæî liãûu gia
âçnh trong muûc træåïc âáy. Mäùi gia âçnh laì mäüt nhoïm caïc thäng tin khaïc
nhau vãö baín cháút, mäùi ngæåìi hay mäùi gia âçnh âæåüc xæí lyï nhæ mäüt âäúi tæåüng
âäüc láûp.
Giaí thiãút ràòng mäùi gia âçnh âæåüc biãøu diãùn nhæ Hçnh II.1. Báy giåì ta tiãúp
tuûc âënh nghéa caïc quan hãû âãø coï thãø tiãúp cáûn âãún caïc thaình pháön cuía gia
âçnh maì khäng cáön biãút chi tiãút. Nhæîng quan hãû naìy âæåüc goüi laì caïc bäü choün
(selector), vç chuïng choün nhæîng thaình pháön naìo âoï. Mäùi bäü choün seî coï tãn laì
tãn thaình pháön maì noï choün ra, vaì coï hai tham âäúi : âäúi tæåüng chæïa thaình
pháön âæåüc choün vaì baín thán thaình pháön âoï :
selector_relation( Object, Selected_component )
Sau âáy laì mäüt säú vê duû vãö caïc bäü choün :
husban( family( Husban, _ , _ ), Husban ).
wife( family( _ , Wife, _ ), Wife ).
chidren( family( _ , _ , ChidrenList ), ChidrenList ).
Ta cuîng coï thãø âënh nghéa nhæîng bäü choün choün ra nhæîng ngæåìi con âàûc
biãût nhæ con træåíng, con uït vaì con thæï N trong gia âçnh :
eldest( Family, Eldest ) :- % ngæåìi con træåíng
chidren(Family, [ Eldest | _ ] ).
cadet( Family, Eldest ) :- % ngæåìi con uït
chidren( Family, [ Eldest | _ ] ).
Choün ra mäüt ngæåìi con báút kyì naìo âoï :
nth_child( N, Family, Chidren ) :- % ngæåìi con thæï N trong gia âçnh
chidren( Family, ChidrenList ),
Kyî thuáût láûp trçnh Prolog 137

% pháön tæí thæï N cuía mäüt danh saïch


nth_member( N, ChidrenList, Chidren ).
Tæì biãøu diãùn cáúu truïc minh hoaû trong Hçnh II.1, sau âáy laì mäüt säú bäü
choün nháûn tham âäúi laì mäüt thaình viãn trong gia âçnh (individual) :
lastname( individual( _ , Lastname, _ , _ ), Lastname ). % tãn gia âçnh (hoü)
firstname( individual( Firstname, _ , Wife, _ ), Firstname ). % tãn riãng
born( individual( _ , _ , Date, _ ), Date ). % ngaìy sinh
Laìm caïch naìo âãø coï thãø aïp duûng caïc bäü choün ? Mäùi khi caïc bäü choün âaî
âæåüc âënh nghéa, ta khäng cáön quan tám âãún caïch biãøu diãùn nhæîng thäng tin
coï cáúu truïc. Âãø taûo ra vaì âãø thao taïc trãn nhæîng thäng tin cáúu truïc, chè cáön
biãút tãn caïc bäü choün vaì sæí duûng chuïng trong chæång trçnh. Våïi phæång phaïp
naìy, caïc biãøu diãùn phæïc taûp cáúu truïc dæî liãûu seî dãù daìng hån so våïi phæång
phaïp mä taí âaî xeït.
Vê duû, ngæåìi sæí duûng khäng cáön biãút nhæîng ngæåìi con trong gia âçnh âæåüc
læu giæî trong mäüt danh saïch. Giaí sæí ràòng ta muäún hai ngæåìi con Johan
Smith vaì Eric Smith cuìng thuäüc mäüt gia âçnh, vaì Eric laì em thæï hai cuía
Johan. Ta coï thãø sæí duûng bäü choün âãø âënh nghéa hai caï thãø, âæåüc goüi laì
Individual1 vaì Individual2, vaì âënh nghéa gia âçnh nhæ sau :
% Johan Smith
lastname( Individual1, smith ), firstname( Individual1, johan ).
% Eric Smith
lastname( Individual2, smith ), firstname( Individual1, eric ),
husban( Family, Individual1 ).
nth_child( 2, Family, Individual2 ).

Viãûc sæí duûng caïc bäü choün laìm thay âäøi dãù daìng mäüt chæång trçnh Prolog.
Giaí sæí ta muäún thay âäøi dæî liãûu cuía mäüt chæång trçnh, ta chè cáön âënh nghéa
laûi caïc bäü choün, pháön coìn laûi cuía chæång trçnh váùn hoaût âäüng nhæ cuî.
138 Láûp trçnh lägich trong Prolog

II.3. Mä phoíng ätämat hæîu haûn


Vê duû sau âáy minh hoaû caïch Prolog biãøu diãùn caïc mä hçnh toaïn hoüc
træìu tæåüng.
II.3.1. Mä phoíng ätämat hæîu haûn khäng âån âënh
Mäüt oâtämat hæîu haûn khäng âån âënh (Non-deterministic Finite
Automaton, viãút tàõt NFA) laì mäüt maïy træìu tæåüng coï thãø âoüc mäüt cáu vaìo
(input string) laì mäüt xáu (hay chuäùi) kyï tæû naìo âoï vaì coï thãø quyãút âënh coï
thæìa nháûn (accept) hay khäng thæìa nháûn (rejecting). Ätämat coï mäüt säú hæîu
haûn traûng thaïi (state) vaì luän åí mäüt traûng thaïi naìo âoï âãø coï thãø chuyãøn tiãúp
(transition) qua mäüt traûng thaïi khaïc sau khi âoüc (thæìa nháûn) mäüt kyï hiãûu
(symbol) hay kyï tæû thuäüc mäüt baíng kyï tæû (alphabet hay set of characters)
hæîu haûn naìo âoï. Mäüt xáu âaî cho âæåüc goüi laì âæåüc thæìa nháûn båíi ätämat, nãúu
sau khi âoüc hãút cáu vaìo, ätämat råi vaìo mäüt trong caïc traûng thaïi thæìa nháûn.
Ngæåìi ta thæåìng biãøu diãùn oâtämat hæîu haûn båíi mäüt âäö thë âënh hæåïng mä
taí caïc chuyãøn tiãúp traûng thaïi coï thãø. Mäùi cung âënh hæåïng cuía âäö thë âæåüc
gàõn nhaîn laì kyï tæû seî âoüc. Mäùi nuït cuía âäö thë laì mäüt traûng thaïi, trong âoï,
traûng thaïi âáöu (initial state) âæåüc âaïnh dáúu båíi >, vaì caïc traûng thaïi thæìa
nháûn (accepted state) âæåüc âaïnh dáúu båíi âæåìng keïp.
Hçnh 5.3 dæåïi âáy minh hoaû mäüt ätämat hæîu haûn khäng âån âënh coï bäún
traûng thaïi s1, s2, s3 vaì s4, trong âoï, s1 laì traûng thaïi âáöu vaì ätämat chè coï
mäüt traûng thaïi thæìa nháûn duy nháút laì s3. Chuï yï ätämat coï hai chuyãøn tiãúp
näúi voìng (chu kyì) taûi traûng thaïi s1 (nghéa laì ätämat khäng thay âäøi traûng
thaïi sau khi âoüc xong hoàûc kyï tæû a, hoàûc kyï tæû b).
Mäùi chuyãøn tiãúp cuía ätämat âæåüc xaïc âënh båíi mäüt quan hãû giæîa traûng
thaïi hiãûn haình, kyï tæû seî âoüc vaì traûng thaïi seî âaût tåïi. Chuï yï ràòng mäùi chuyãøn
tiãúp coï thãø khäng âån âënh. Trong Hçnh II.3, tæì traûng thaïi s1, sau khi âoüc kyï
tæû a, ätämat coï thãø råi vaìo hoàûc traûng thaïi s1, hoàûc traûng thaïi s2. Ta cuîng
tháúy mäüt säú cung coï nhaîn ε (cáu räùng), tæång æïng våïi “chuyãøn tiãúp epsilon”,
kyï hiãûu ε-chuyãøn tiãúp. Nhæîng cung naìy mä taí sæû chuyãøn tiãúp “khäng nhçn
tháúy âæåüc” cuía ätämat : ätämat chuyãøn qua mäüt traûng thaïi måïi khaïc maì
Kyî thuáût láûp trçnh Prolog 139

khäng hãö âoüc mäüt kyï tæû naìo. Nghéa laì pháön cáu vaìo váùn khäng thay âäøi,
nhæng ätämat âaî thay âäøi traûng thaïi.
a
a
s1 s2

b ε b
ε

s4 a s3

Hçnh II.3. Mäüt oâtämat hæîu haûn khäng âån âënh bäún traûng thaïi.
Ngæåìi ta noïi ätämat thæìa nháûn cáu vaìo nãúu täön taûi mäüt daîy caïc chuyãøn
tiãúp trong âäö thë sao cho :
1. Luïc âáöu, ätämat åí traûng thaïi âáöu (vê duû s1).

2. Ätämat kãút thuïc viãûc âoaïn nháûn cáu vaìo vaì åí traûng thaïi thæìa nháûn
(s3).

3. Caïc nhaîn trãn caïc cung cuía con âæåìng chuyãøn tiãúp tæì traûng thaïi âáöu
âãún traûng thaïi thæìa nháûn tæång æïng våïi cáu vaìo laì xáu âaî âoüc.
Trong quaï trçnh âoaïn nháûn cáu vaìo, ätämat quyãút âënh læûa choün mäüt
trong säú caïc chuyãøn tiãúp coï thãø âãø tiãúp tuûc. Âàûc biãût, ätämat coï thãø thæûc hiãûn
hay khäng thæûc hiãûn mäüt ε−chuyãøn tiãúp, nãúu traûng thaïi hiãûn haình cho pheïp.
Ätämat khäng thæìa nháûn cáu vaìo nãúu noï khäng råi vaìo traûng thaïi thæìa
nháûn duì âaî âoüc hãút cáu vaìo, hoàûc khäng coìn khaí nàng tiãúp tuûc chuyãøn tiãúp
maì cáu vaìo chæa kãút thuïc, hoàûc coï thãø bë quáøn vä haûn.
Nhæ âaî biãút, caïc ätämat hæîu haûn khäng âån âënh træìu tæåüng coï mäüt tênh
cháút thuï vëû : taûi mäùi thåìi âiãøm, ätämat coï khaí nàng læûa choün, trong säú caïc
chuyãøn tiãúp coï thãø, mäüt chuyãøn tiãúp “täút nháút” âãø thæìa nháûn cáu vaìo.
Chàóng haûn, ätämat cho åí Hçnh II.3 seî thæìa nháûn caïc xáu ab vaì aabaab,
nhæng khäng thæìa nháûn caïc xáu abb vaì abba. Mäüt caïct täøng quaït, ätämat
thæìa nháûn moüi xáu kãút thuïc båíi ab, nhæng khäng thæìa nháûn caïc xáu khaïc.
Trong Prolog, mäüt ätämat âæåüc âënh nghéa båíi ba quan hãû :
140 Láûp trçnh lägich trong Prolog

1. Mäüt quan hãû mäüt ngäi satisfaction cho pheïp xaïc âënh caïc traûng thaïi
thæìa nháûn cuía ätämat.
2. Mäüt quan hãû ba ngäi trans cho pheïp xaïc âënh caïc traûng thaïi chuyãøn
tiãúp, chàóng haûn :
trans( S1, X, S2 ).
coï nghéa laì ätämat chuyãøn tiãúp tæì traûng thaïi S1 qua traûng thaïi S2 sau
khi âoüc kyï tæû X.
3. Mäüt quan hãû hai ngäi epsilon chè ra pheïp chuyãøn tiãúp räùng tæì traûng
thaïi S1 qua traûng thaïi S2 :
epsilon( S1, S2 ).
Ätämat âaî cho åí Hçnh II.3 âæåüc mä taí båíi caïc mãûnh âãö Prolog nhæ sau :
satisfaction( s3 ).
trans( s1, a, s1 ).
trans( s1, a, s2 ).
trans( s1, b, s1 ).
trans( s2, b, s3 ).
trans( s3, b, s4 ).
epsilon( s2, s4 ).
epsilon( s3, s1 ).

Âãø biãøu diãùn caïc xáu kyï tæû trong Prolog, ta seî sæí duûng kiãøu danh saïch.
Chàóng haûn xáu aab âæåüc biãøu diãùn båíi [ a, b, a ]. Xuáút phaït tæì mäüt cáu vaìo,
ätämat væìa mä taí trãn âáy seî mä phoíng quaï trçnh âoaïn nháûn, bàòng caïch âoüc
láön læåüt caïc pháön tæí cuía danh saïch, âãø thæìa nháûn hay khäng thæìa nháûn.
Theo âënh nghéa, ätämat hæîu haûn khäng âån âënh seî thæìa nháûn cáu vaìo
nãúu, xuáút phaït tæì traûng thaïi âáöu, sau khi âoüc hãút cáu (xæí lyï hãút moüi pháön tæí
cuía danh saïch), ätämat råi vaìo traûng thaïi thæìa nháûn. Quan hãû hai ngäi
accept sau âáy cho pheïp mä phoíng quaï trçnh âoaïn nháûn mäüt cáu vaìo tæì mäüt
traûng thaïi âaî cho :
accept( State, InputString )
Quan hãû accept laì âuïng nãúu State laì traûng thaïi âáöu vaì InputString laì mäüt
cáu vaìo.
Kyî thuáût láûp trçnh Prolog 141

kyï tæû âáöu tiãn pháön coìn laûi cuía cáu vaìo

X
S S1
(a)
cáu vaìo

ε
S S1

(b)

Hçnh II.4. Oâtämat thæìa nháûn cáu vaìo :


(a) âoüc kyï tæû âáöu tiãn X ; (b) thæûc hiãûn mäüt ε-chuyãøn tiãúp.

Ba mãûnh âãö cho pheïp âënh nghéa quan hãû naìy, tæång æïng våïi ba træåìng
håüp nhæ sau :
1. Xáu räùng [ ] âæåüc thæìa nháûn taûi traûng thaïi S nãúu ätämat âang åí taûi traûng
thaïi S vaì S laì mäüt traûng thaïi thæìa nháûn.
2. Mäüt xáu khaïc räùng âæåüc thæìa nháûn taûi traûng thaïi S nãúu âáöu âoüc âang
åí taûi vë trê âoüc kyï tæû âáöu tiãn cuía xáu âãø sau khi âoüc, ätämat chuyãøn
qua traûng thaïi S1 vaì xuáút phaït tæì traûng thaïi S1 naìy, ätämat thæìa
nháûn toaìn bäü pháön coìn laûi cuía cáu vaìo (xem minh hoaû åí Hçnh II.4 (a) ).
3. Mäüt xáu khaïc räùng âæåüc thæìa nháûn taûi traûng thaïi S nãúu ätämat coï thãø
thæûc hiãûn mäüt ε-chuyãøn tiãúp tæì traûng thaïi S qua traûng thaïi S1 vaì xuáút
phaït tæì traûng thaïi S1 naìy, ätämat thæìa nháûn toaìn bäü pháön coìn laûi cuía
cáu vaìo (xem minh hoaû åí Hçnh II.4 (b) ).

Ta coï thãø viãút trong Prolog nhæ sau :


accept( S, [ ] ) :- % thæìa nháûn xáu räùng
satisfaction( S ).
accept( S, [ X | Remainder ] ) :- % thæìa nháûn sau khi âoüc kyï tæû âáöu tiãn
trans( S, X, S1 ),
accept( S1, Remainder).
accept( S, InputString ) :- % thæìa nháûn båíi ε-chuyãøn tiãúp
epsilon( S, S1 ),
accept( S1, Remainder).
142 Láûp trçnh lägich trong Prolog

Báy giåì, ta coï thãø yãu cáöu ätämat nháûn biãút xáu aaab båíi cáu hoíi sau :
?- accept( s1, [ a, a, a, b ] ).
Yes

Tuy nhiãn, ätämat khäng thæìa nháûn xáu abbb :


?- accept( s1, [ a, b, b, b ] ).
ERROR: Out of local stack
Ta cuîng tháúy ràòng caïc chæång trçnh Prolog thæåìng giaíi quyãút caïc baìi toaïn
täøng quaït hån nhæîng gç maì NLT taûo ra chuïng. Vê duû, âãø yãu cáöu Prolog cho
biãút traûng thaïi âáöu naìo thç xáu ab âæåüc thæìa nháûn :
?- accept( S, [ a, b ] ).
S = s1
Yes
Thuï vë hån næîa, ta coï thãø yãu cáöu Prolog cho biãút nhæîng xáu ba kyï tæû naìo
thç âæåüc thæìa nháûn båíi ätämat :
?- accept( s1, [ X1, X2, X3 ] ).
X1 = a
X2 = a
X3 = b
Yes
Nãúu ta muäún kãút quaí traí vãö laì mäüt xáu, ta chè cáön âàût cáu hoíi :
?- InputString = [ _ , _ , _ ], accept( s1, InputString ).
InputString = [a, a, b]
Yes
Âi xa hån, taûi sao ta khäng thãø yãu cáöu Prolog cho biãút nhæîng traûng thaïi
âáöu naìo cuía ätämat cho pheïp nháûn biãút nhæîng xáu coï baíy kyï tæû, v.v... ?
Cáön phaíi coï nhæîng thay âäøi trãn caïc quan hãû satisfaction, trans vaì epsilon
nãúu ta muäún ätämat thæûc hiãûn nhæîng xæí lyï täøng quaït hån. Ätämat âaî cho åí
Hçnh II.4 häng chæïa caïc näúi voìng ε−chuyãøn tiãúp. Báy giåì nãúu ta thãm mäüt
chuyãøn tiãúp :
epsilon( s1, s3 ).
thç ta âaî taûo ra mäüt näúi voìng trãn xáu räùng ε laìm räúi loaûn chæïc nàng âoaïn
nháûn cuía ätämat. Luïc naìy våïi cáu hoíi :
?- accept( s1, [ a ] ).
Kyî thuáût láûp trçnh Prolog 143

seî gáy ra mäüt voìng làûp quáøn vä haûn taûi traûng thaïi s1, trong khi ätämat cäú
gàõng tçm mäüt con âæåìng âãún traûng thaïi thæìa nháûn s3.

II.3.2. Mä phoíng ätämat hæîu haûn âån âënh


Mäüt äâtämat hæîu haûn laì âån âënh (Deterministic Finite Automaton, viãút
tàõt DFA) nãúu chuyãøn tiãúp cuía ätämat âæåüc xaïc âënh âån âënh : ätämat chè coï
thãø chuyãøn qua mäüt vaì chè mäüt traûng thaïi tiãúp theo sau khi âoüc mäüt kyï tæû vaì
khäng coï caïc « chuyãøn tiãúp epsilon». Thay vç sæí duûng thuáût ngæî quan hãû ba
ngäi, ngæåìi ta thæåìng sæí duûng thuáût ngæî haìm chuyãøn tiãúp delta δ(s, a) = s’ âãø
mä taí caïc hoaût âäüng âoaïn nháûn cáu cuía ätämat âån âënh.

DFA âæåüc viãút trong Prolog nhæ sau :


parse(L) :-
start(S),
trans(S,L).
trans(X,[A|B]) :-
delta(X,A,Y), % X ---A---> Y
write(X),
write(' '),
write([A|B]),
nl,
trans(Y,B).
trans(X,[]) :-
final(X),
write(X),
write(' '),
write([]), nl.

DFA sau âáy thæìa nháûn ngän ngæî (a,b)*ab(a,b)* :


start(0).
final(2).
delta(0,a,1).
delta(0,b,0).
delta(1,a,1).
delta(1,b,2).
delta(2,a,2).
delta(2,b,2).
144 Láûp trçnh lägich trong Prolog

Så âäö biãøu diãùn ätämat nhæ sau :

b A a, b
a b
0 1 2

Hçnh II.5. Ätämat hæîu haûn âån âënh coï ba traûng thaïi.

Sau âáy laì mäüt säú hoaût âäüng âoaïn nháûn cuía ätämat :
?- parse([b,b,a,a,b,a,b]).
0 [b, b, a, a, b, a, b]
0 [b, a, a, b, a, b]
0 [a, a, b, a, b]
1 [a, b, a, b]
1 [b, a, b]
2 [a, b]
2 [b]
2 []
Yes
?- parse([b,b,a]).
0 [b, b, a]
0 [b, a]
0 [a]
No

II.4. Vê duû : láûp kãú hoaûch âi du lëch bàòng maïy bay


Trong muûc naìy, ta seî xáy dæûng mäüt chæång trçnh Prolog cho pheïp láûp kãú
hoaûch âãø âi du lëch bàòng maïy bay. Dáùu ràòng âån giaín, nhæîng vê duû naìy traí
låìi âæåüc nhæîng cáu hoíi mang tênh thæûc tiãùn sau âáy :
• Nhæîng ngaìy naìo trong tuáön coï chuyãún bay træûc tiãúp tæì Paris âi
Ljubljana ?
• Laìm caïch naìo âãø âi tæì Ljubljana âãún Grenoble ngaìy thæï Nàm ?
Kyî thuáût láûp trçnh Prolog 145

• Täi phaíi âi du lëch Milan, Ljubljana vaì Zurich xuáút phaït tæì Paris ngaìy
thæï Ba vaì phaíi quay vãö trong ngaìy thæï Saïu. Laìm sao âãø coï thãø sàõp xãúp
caïc chuyãøn âi cuía täi sao cho mäùi ngaìy khäng âi maïy bay quaï mäüt láön ?
Chæång trçnh Prolog âæåüc dæûa trãn mäüt cå såí dæî liãûu chæïa nhæîng thäng
tin vãö caïc chuyãún bay. Mäùi chuyãún bay laì mäüt quan hãû ba ngäi cho biãút lëch
trçnh bay timetable nhæ sau :
timetable( Place1, Place2, Fly_List).

Danh saïch caïc chuyãún bay coï daûng nhæ sau :


Departure_hour / Arrival_hour / Fly_Number / Day_List

Danh saïch caïc ngaìy coï chuyãún bay hoàûc laì mäüt danh saïch caïc ngaìy thæï
trong tuáön, hoàûc laì mäüt nguyãn tæí all (cho táút caí caïc ngaìy). Chàóng haûn, sau
âáy laì mäüt quan hãû timetable :
timetable( paris , grenoble ,
[ 9:40 / 10:50 / ba4732 / all ,
11:40 / 12:50 / ba4752 / all ,
18:40 / 19:50 / ba4822 / [ mo , tu , we , th , fr ] ] ).

Lëch trçnh bay âæåüc biãøu diãùn båíi caïc cáúu truïc hai thaình pháön laì giåì vaì
phuït phán caïch nhau båíi pheïp toaïn : (dáúu hai cháúm).
Baìi toaïn chênh âàût ra laì tçm nhæîng läü trçnh chênh xaïc giæîa hai thaình phäú
(nåi âi vaì nåi âãún) vaì mäüt ngaìy naìo âoï âaî cho. Âãø láûp trçnh, ta sæí duûng mäüt
quan hãû coï bäún tham âäúi nhæ sau :
path( Place1 , Place2 , Day, Path )
trong âoï, laì mäüt daîy caïc chuyãún bay thoaí maîn caïc tiãu chuáøn sau :
(1) Nåi âi laì Place1.
(2) Nåi âãún laì Place2.
(3) Táút caí nhæîng chuyãún bay cuìng ngaìy Day trong tuáön.
(4) Táút caí nhæîng chuyãún bay cuía läü trçnh Path thuäüc vãö quan hãû
timetable.
(5) Coï âuí thåïi gian âãø di chuyãøn giæîa caïc chuyãún bay.
Läü trçnh âæåüc biãøu diãùn båíi mäüt danh saïch caïc âäúi tæåüng nhæ sau :
Departure - Arrival : Fly_number : Departure_hour
146 Láûp trçnh lägich trong Prolog

Ta cuîng sæí duûng caïc vë tæì bäø tråü sau âáy :


(1) fly( Place1, Place2 , Day , Fly_number , Departure_hour, Arrival_hour )
Coï nghéa laì täön taûi mäüt chuyãún bay säú hiãûu Fly_number giæîa Place1
vaì Place2 trong ngaìy Day, tæång æïng våïi ngaìy âi vaì ngaìy âãún âaî cho.
(2) dephour( Path , Hour )

Giåì xuáút phaït cuía läü trçnh Path laì Hour.


(3) connecting( Hour1, Hour2 )
Coï êt nháút 40 phuït giæîa Hour1vaì Hour2, cho pheïp thæûc hiãûn viãûc di
chuyãøn (näúi tiãúp giæîa hai chuyãún bay.
Váún âãö tçm mäüt läü trçnh giæîa hai thaình phäú tæång tæû baìi toaïn âoaïn nháûn
xáu cuía mäüt ätämat hæîu haûn khäng âån âënh âaî xeït trong muûc træåïc. Nhæîng
âiãøm chung laì :
• Caïc traûng thaïi cuía ätämat tæång æïng våïi caïc thaình phäú.
• Mäüt chuyãøn tiãúp giæîa hai traûng thaïi tæång æïng våïi caïc chuyãún bay
giæîa hai thaình phäú.
• Quan hãû trans cuía ätämat tæång æïng våïi quan hãû timetable.

• Âãø mä phoíng quaï trçnh âoaïn nháûn cáu, ätämat tçm âæåüc mäüt läü trçnh
giæîa traûng thaïi âáöu vaì mäüt traûng thaïi thæìa nháûn. Coìn âãø mä phoíng
viãûc láûp kãú hoaûch âi du lëch, chæång trçnh tçm âæåüc mäüt lëch trçnh bay
giæîa thaình phäú xuáút phaït vaì thaình phäú âãún.
Chênh vç váûy, ta coï thãø âënh nghéa mäüt quan hãû vãö läü trçnh path tæång tæû
våïi quan hãû accept, chè coï khaïc laì quan hãû path khäng chæïa chuyãøn tiãúp
räùng.
Xaíy ra hai træåìng håüp nhæ sau :
(1) Nãúu coï mäüt chuyãún bay træûc tiãúp giæîa P1 vaì P2 thç läü trçnh âæåüc ruït
goün thaình :
path( P1 , P2 , Day, [ P1 - P2 : FlyNum : DepH ] ) :-
fly( P1 , P2 , Day , FlyNum , Dep , Arr ).

(2) Nãúu khäng coï mäüt chuyãún bay træûc tiãúp giæîa P1 vaì P2 thç läü trçnh seî
phaíi bao gäöm mäüt chuyãún bay giæîa P1 vaì mäüt thaình phäú trung gian
Kyî thuáût láûp trçnh Prolog 147

P3, räöi mäüt chuyãún bay giæîa P3 vaì P2. Luïc naìy cáön coï âuí thåìi gian âãø
di chuyãøn giæîa hai chuyãún bay, tæì nåi âãún cuía chuyãún bay thæï nháút
âãún nåi xuáút phaït cuía chuyãún bay thæï hai :
path( P1 , P2 , Day , [ P1 - P3 : FlyNum : Dep1 | Path ] ) :-
path( P3 , P2 , Day , Path ),
fly( P1 , P3 , Day , FlyNum1 , Dep1 , Arr1 ),
dephour( Path , Dep2 ) ,
connecting( Arr1 , Dep2 ).

Caïc quan hãû fly, connecting vaì dephour âæåüc xáy dæûng tæång âäúi dãù daìng.
Dæåïi âáy laì chæång trçnh âáöy âuí bao gäöm cå såí dæî liãûu vãö lëch trçnh bay.
Vê duû naìy âån giaín, khäng xaíy ra træåìng håüp coï läü trçnh vä êch, nghéa laì
mäüt läü trçnh khäng dáùn âãún âáu. Ta cuîng tháúy ràòng cå såí dæî liãûu vãö lëch
trçnh bay coìn nhoí. Âãø coï thãø quaín lyï mäüt cå såí dæî liãûu låïn hån, nháút thiãút
phaíi sæí duûng mäüt chæång trçnh láûp kãú hoaûch thäng minh hån.

% Chæång trçnh láûp kãú hoaûch âi du lëch


:- op( 50 , xfy , : ).
fly( Place1, Place2 , Day , FlyNum , DepH , ArrH ) :-
timetable( Place1 , Place2 , FlyList ) ,
ismember( DepH / ArrH / FlyNum / DayList , FlyList ) ,
flyday( Day , DayList ).
ismember( X , [ X | L ] ).
ismember( X , [ Y | L ] ) :-
ismember( X , L ).
flyday( Day , DayList ) :-
ismember( Day , DayList ).
flyday( Day , all ) :-
ismember( Day , [ mo , tu , we , th , fr , sa , su ] ).
% Chuyãún bay træûc tiãúp
path( P1 , P2 , Day, [ P1 - P2 : FlyNum : DepH ] ) :-
fly( P1 , P2 , Day , FlyNum , DepH , _ ).
% Chuyãún bay khäng træûc tiãúp
path( P1 , P2 , Day , [ P1 - P3 : FlyNum : Dep1 | Path ] ) :-
path( P3 , P2 , Day , Path ),
fly( P1 , P3 , Day , FlyNum1 , Dep1 , Arr1 ),
dephour( Path , Dep2 ) ,
connecting( Arr1 , Dep2 ).
dephour( [ P1 - P2 : FlyNum : Dep | _ ] , Dep ).
148 Láûp trçnh lägich trong Prolog

connecting( Hour1 : Mins1 , Hour2 : Mins2 ) :-


60 *( Hour2 - Hour1 ) + Mins2 - Mins1 >= 40.
% Mäüt cå såí dæî liãûu vãö lëch trçnh caïc chuyãún bay
timetable( grenoble , paris ,
[ 9 :40 / 10:50 / ba4733 / all ,
13 :40 / 14:50 / ba4773 / all ,
19:40 / 20:50 / ba4833 / [ mo , tu , we , th , fr , su ] ] ).
timetable( paris , grenoble ,
[ 9:40 / 10:50 / ba4732 / all ,
11:40 / 12:50 / ba4752 / all ,
18:40 / 19:50 / ba4822 / [ mo , tu , we , th , fr ] ] ).
timetable( paris , ljubljana ,
[ 13:20 / 16:20 / ju201 / [ fr ] ,
13:20 / 16:20 / ju213 / [ su ] ] ).
timetable( paris , zurich ,
[ 9:10 / 11:45 / ba614 / all ,
14:45 / 17:20 / sr805 / all ] ).
timetable( paris , milan ,
[ 8:30 / 11:20 / ba510 / all ,
11:00 / 13:50 / az459 / all ] ).
timetable( ljubljana , zurich ,
[ 11:30 / 12:40 / ju322 / [ tu , fr ] ] ).
timetable( ljubljana , paris ,
[ 11:10 / 12:20 / yu200 / [ fr ] ,
11:25 / 12:20 / yu212 / [ su ] ] ).
timetable( milan , paris ,
[ 9:10 / 10 :00 / az458 / all ,
12:20 / 13:10 / ba511 / all ] ).
timetable( milan , zurich ,
[ 9:25 / 10:15 / sr621 / all ,
12:45 / 13:35 / sr623 / all ] ).
timetable( zurich , ljubljana ,
[ 13:30 / 14:40 / yu323 / [ tu , th ] ] ).
timetable( zurich , paris ,
[ 9:00 / 9:40 / ba613 / [ mo , tu , we, th, fr, sa ],
16:10 /16:55 / sr806 / [ mo , tu , we, th, fr, su ] ] ).
timetable( zurich , milan ,
[ 7:55 / 8:45 / sr620 / all ] ).
Kyî thuáût láûp trçnh Prolog 149

Sau âáy laì mäüt säú cáu hoíi trãn cå såí dæî liãûu vãö lëch trçnh haìng khäng :
• Nhæîng ngaìy naìo trong tuáön coï mäüt chuyãún bay træûc tiãúp giæîa Paris vaì
Ljubljana ?
?- fly( paris , ljubljana , Day , _ , _ , _ ).
Day = fr;
Day = su;
No
• Laìm caïch naìo âãø coï thãø âi tæì Ljubljana âãún Grenoble ngaìy thæï nàm ?
?- path( ljubljana , grenoble , th, C ).
C = [ ljubljana-paris:yu200:11:10, paris-grenoble:ba4822:18:40 ] ;
C = [ ljubljana-paris:yu212:11:25, paris-grenoble:ba4822:18:40 ] ;
C = [ ljubljana-zurich:ju322:11:30, zurich-paris:sr806:16:10,
paris-grenoble:ba4822:18:40 ]
• Laìm caïch naìo âãø xuáút phaït tæì Paris, coï thãø du lëch Milan, Ljubljana vaì
Zurich trong ngaìy thæï Ba, âãø tråí vãö trong ngaìy thæï Saïu, sao cho mäùi
ngaìy chè thæûc hiãûn khäng quaï mäüt chuyãún bay ?
Âáy laì mäüt cáu hoíi tæång âäúi luíng cuíng. Âãø traí låìi, ta cáön sæí duûng
quan hãû permutation âaî trçnh baìy trong chæång 1, muûc 3. Quan hãû naìy
cho pheïp hoaïn vë táút caí caïc thaình phäú Milan, Ljubljana vaì Zurich sao
cho täön taûi nhæîng chuyãún bay thêch håüp mäùi ngaìy :
?- permutation( [ milan , ljubljana , zurich ] , [ V1, V2, V3 ] ),
fly( paris, V1, tu, FN1, Dep1, Arr1 ),
fly( V1, V2, tu, FN2, Dep2, Arr2 ),
fly( V2, V3, tu, FN3, Dep3, Arr3 ),
fly( V3, paris, fr, FN4, Dep4, Arr4 ).
Kãút quaí -> V1 = ljubljana -> V1 = milan
V2 = zurich V2 = zurich
V3 = milan V3 = ljubljana
FN1 = ju213 FN1 = ba510
Dep1 = 13:20 Dep1 = 8:30
Arr1 = 16:20 Arr1 = 11:20
FN2 = ju322 FN2 = sr621
Dep2 = 11:30 Dep2 = 9:25
Arr2 = 12:40 Arr2 = 10:15
FN3 = sr620 FN3 = yu323
Dep3 = 7:55 Dep3 = 13:30
Arr3 = 8:45 Arr3 = 14:40
FN4 = az458 FN4 = yu200
Dep4 = 9:10 Dep4 = 11:10
Arr4 = 10:0 ; Arr4 = 12:20
150 Láûp trçnh lägich trong Prolog

II.5. Baìi toaïn taïm quán háûu


Baìi toaïn taïm quán háûu do Call Friedrich Gauss âæa ra vaìo nàm 1850
nhæng khäng coï låìi giaíi hoaìn toaìn theo phæång phaïp giaíi têch. Sau âoï baìi
toaïn naìy âæåüc nhiãöu ngæåìi giaíi troün veûn trãn MTÂT, theo nhiãöu caïch khaïc
nhau. Baìi toaïn phaït biãøu nhæ sau :
Haîy tçm caïch âàût taïm quán háûu lãn mäüt baìn cåì vua (coï 8 x 8 ä, luïc âáöu
khäng chæïa quán naìo) sao cho khäng coï quán naìo àn âæåüc quán naìo ? Mäüt
quán háûu coï thãø àn âæåüc bàõt cæï quán naìo nàòm trãn cuìng cäüt, hay cuìng haìng,
hay cuìng âæåìng cheïo thuáûn, hay cuìng âæåìng cheïo nghëch våïi noï.

Hçnh II.6. Mäüt låìi giaíi cuía baìi toaïn taïm quán háûu
Niclaus Wirth trçnh baìy phæång phaïp thæí-sai (trial-and-error) nhæ sau :
− Âàût mäüt quán háûu vaìo cäüt 1 (trãn mäüt haìng tuyì yï);
− Âàût tiãúp mäüt quán háûu thæï hai sao cho 2 quán khäng àn nhau;
− Tiãúp tuûc âàût quán thæï 3, v.v...
Låìi giaíi coï daûng mäüt voìng làûp theo giaí ngæî Pascal nhæ sau :
Xeït-cäüt-âáöu ;
repeat
Thæí_cäüt ;
if An_toaìn then begin
Âàût_quán_háûu_vaìo ;
Xeït_cäüt_kãú_tiãúp;
end else Quay_laûi ;
until Âaî_xong_våïi_cäüt_cuäúi or Âaî_quay_laûi_quaï_cäüt_âáöu ;
Kyî thuáût láûp trçnh Prolog 151

Våïi Prolog, chæång trçnh seî coï daûng mäüt vë tæì :


solution( Pos )
Vë tæì naìy chè thoaí maîn khi vaì chè khi Pos biãøu diãùn mäüt caïch bäú trê taïm
quán háûu sao cho khäng coï quán naìo àn âæåüc quán naìo. Sau âáy ta seî trçnh
baìy ba caïch tiãúp cáûn âãø láûp trçnh Prolog dæûa trãn caïc caïch biãøu diãùn khaïc
nhau.

II.5.1. Sæí duûng danh saïch toaû âäü theo haìng vaì cäüt
Ta cáön tçm caïch biãøu diãùn caïc vë trê trãn baìn cåì. Giaíi phaïp træûc tiãúp nháút
laì sæí duûng mäüt danh saïch taïm pháön tæí maì mäùi pháön tæí tæång æïng våïi ä âàût
quán háûu. Mäùi pháön tæí laì mäüt càûp säú nguyãn giæîa 1 vaì 8 chè toaû âäü cuía quán
háûu :
X/Y
8 •
7 •
6 •
5 •
4 •
3 •
2 •
1 •
1 2 3 4 5 6 7 8

Hçnh II.7. Mäüt låìi giaíi cuía baìi toaïn taïm quán háûu,
biãøu diãùn båíi danh saïch [ 1/4, 2/2, 3/7, 4/3, 5/6, 6/8, 7/5, 8/1 ] .
ÅÍ âáy, pheïp toaïn / khäng phaíi laì pheïp chia, maì chè laì caïch täø håüp hai toaû
âäü cuía mäüt ä baìn cåì. Hçnh 5.6 trãn âáy laì mäüt låìi giaíi khaïc cuía baìi toaïn taïm
quán háûu âæåüc biãøu diãùn dæåïi daûng mäüt danh saïch nhæ sau :
[ 1/4, 2/2, 3/7, 4/3, 5/6, 6/8, 7/5, 8/1 ]

Tæì caïch biãøu diãùn danh saïch, ta cáön tçm låìi giaíi coï daûng :
[ X1/Y1, X2/Y2, X3/Y3, ... , X8/Y8 ]
152 Láûp trçnh lägich trong Prolog

Ta cáön tçm caïc giaï trë cuía caïc biãún X1, Y1, X2, Y2, X3, Y3, ... , X8, Y8. Do
caïc quán háûu phaíi nàòm trãn caïc cäüt khaïc nhau âãø khäng thãø àn láùn nhau,
nãn ta coï ngay giaï trë cuía caïc toaû âäü X, vaì låìi giaíi luïc naìy coï daûng :
[ 1/Y1, 2/Y2, 3/Y3, ... , 8/Y8 ]
Cho âãún luïc naìy, baìi toaïn taïm quán háûu chè âàût ra âäúi våïi baìn cåì 8 × 8.
Tuy nhiãn, låìi giaíi phaíi dæû kiãún âæåüc cho træåìng håüp täøng quaït khi láûp trçnh.
ÅÍ âáy, ta seî tháúy ràòng chênh træåìng håüp täøng quaït laûi âån giaín hån baìi toaïn
ban âáöu. Baìn cåì 8 × 8 chè laì mäüt træåìng håüp riãng.
Âãø giaíi quyãút cho træåìng håüp täøng quaït, ta chuyãøn kêch thæåïc 8 quán háûu
thaình mäüt säú quán háûu báút kyì naìo âoï (mäùi cäüt mäüt quán háûu), kãø caí säú cäüt
bàòng khäng. Ta xáy dæûng quan hãû solution tæì hai tçnh huäúng sau :
1. Danh saïch caïc quán háûu laì räùng : danh saïch räùng cuîng laì mäüt låìi giaíi
vç khäng xaíy ra sæû táún cäng naìo.
solution( [ ] ).
2. Danh saïch caïc quán háûu khaïc räùng vaì coï daûng nhæ sau :
[ X/Y | Others ]
Trong træåìng håüp thæï hai, quán háûu thæï nháút nàòm trãn ä X/Y, coìn nhæîng
quán háûu khaïc nàòm trong danh saïch Others. Nãúu danh saïch naìy laì mäüt låìi
giaíi, thç nhæîng âiãöu kiãûn sau âáy phaíi âæåüc thoaí maîn :
1. Nhæîng quán háûu trong danh saïch Others khäng thãø táún cäng láùn
nhau, âiãöu naìy noïi lãn ràòng Others cuîng laì mäüt låìi giaíi.
2. Vë trê X vaì Y cuía nhæîng quán háûu phaíi nàòm giæîa 1 vaì 8.
3. Mäüt quán háûu taûi vë trê X/Y khäng thãø táún cäng mäüt quán háûu naìo
khaïc trong danh saïch Others.
Âäúi våïi âiãöu kiãûn thæï nháút, quan hãû solution phaíi âæåüc goüi mäüt caïch âãû
quy.
Âiãöu kiãûn thæï hai noïi lãn ràòng Y phaíi thuäüc vãö danh saïch [ 1, 2, 3, 4, 5, 6,
7, 8 ]. ÅÍ âáy, ta khäng cáön quan tám âãún vë trê X, vç noï phaíi tæång håüp våïi
danh saïch kãút quaí traí vãö nhæ ta âaî xaïc âënh ngay tæì âáöu. Nghéa laì X phaíi
thuäüc vãö nhæîng giaï trë âaî âæåüc áún âënh tæång æïng.
Kyî thuáût láûp trçnh Prolog 153

Giaí sæí âiãöu kiãûn thæï ba âæåüc giaíi quyãút nhåì quan hãû noattack, chæång
trçnh Prolog cho quan hãû solution nhæ sau :
solution( [ X/Y | Others ] ) :-
solution( Others ),
member( Y, [ 1, 2, 3, 4, 5, 6, 7, 8 ] ),
noattack( X/Y, Others ).

Báy giåì ta cáön tçm quan hãû noattack. Ta tháúy :


1. Nãúu danh saïch Rlist räùng, khi âoï noattack laì âuïng, vç khäng coï quán
háûu naìo táún cäng quán háûu taûi X/Y naìo âoï.
noattack( _, [ ] ).
2. Nãúu danh saïch Rlist khaïc räùng, khi âoï coï daûng [ R1 | Rlist1 ] vaì hai
âiãöu kiãûn sau âáy phaíi âæåüc thoaí maîn :
(a) Quán háûu taûi ä R khäng thãø táún cäng quán háûu taûi ä R1, vaì
(b) Quán háûu taûi ä R khäng thãø táún cäng quán háûu naìo trong Rlist1.
Âãø mäüt quán háûu khäng thãø táún cäng quán háûu khaïc, thç chuïng khäng
thãø nàòm trãn cuìng haìng, cuìng cäüt vaì cuìng âæåìng cheïo chênh hoàûc phuû. Ta
biãút chàõc chàõn ràòng caïc quán háûu âaî nàòm trãn caïc cäüt phán biãût nhau do mä
hçnh låìi giaíi âaî áún âënh. Báy giåì ta cáön chè ra ràòng :
• Caïc toaû âäü Y cuía caïc quán háûu phaíi phán biãût nhau, vaì

• Caïc quán háûu khäng thãø nàòm trãn cuìng âæåìng cheïo chênh hoàûc phuû.
nghéa laì khoaíng caïch giæîa caïc ä trãn truûc X phaíi khaïc våïi caïc ä trãn
truûc Y.
noattack( X/Y, [ X1/Y2 | Others ] ) :-
Y =\= Y1,
Y1 - Y =\= X1 - X,
Y1 - Y =\= X - X1,
noattack( X/Y, Others ).
Dæåïi âáy laì chæång trçnh Prolog âáöy âuí thæï nháút coï chæïa danh saïch låìi
giaíi laì quan hãû model. Mä hçnh laìm cho viãûc tçm låìi giaíi cho baìi toaïn taïm
quán háûu tråí nãn âån giaín hån.

% chæång trçnh thæï nháút giaíi baìi toaïn taïm quán háûu
% The problem of the eight queens - Program 1
% −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
154 Láûp trçnh lägich trong Prolog

solution( [ ] ).
solution( [ X/Y | Others ] ) :-
solution( Others ),
ismember( Y, [ 1, 2, 3, 4, 5, 6, 7, 8 ] ),
noattack( X/Y, Others ).
noattack( _ , [ ] ).
noattack( X/Y, [ X1/Y1 | Others ] ) :-
Y =\= Y1,
Y1 – Y =\= X1 - X,
Y1 – Y =\= X - X1,
noattack( X/Y, Others ).
ismember( X , [ X | L ] ).
ismember( X, [ Y | L ] ) :-
ismember( X, L ).
model( [ 1/Y1, 2/Y2, 3/Y3, 4/Y4, 5/Y5, 6/Y6, 7/Y7, 8/Y8 ] ).

?- model( S ), solution( S ).
S = [1/4, 2/2, 3/7, 4/3, 5/6, 6/8, 7/5, 8/1] ;
S = [1/5, 2/2, 3/4, 4/7, 5/3, 6/8, 7/6, 8/1] ;
S = [1/3, 2/5, 3/2, 4/8, 5/6, 6/4, 7/7, 8/1] ;
S = [1/3, 2/6, 3/4, 4/2, 5/8, 6/5, 7/7, 8/1] ;
S = [1/5, 2/7, 3/1, 4/3, 5/8, 6/6, 7/4, 8/2] ;
S = [1/4, 2/6, 3/8, 4/3, 5/1, 6/7, 7/5, 8/2]
Yes

Sæí duûng vë tæì not, ta viãút laûi chæång trçnh nhæ sau :
solution( [ ] ).
solution( [ X/Y | Others ] ) :-
solution( Others ),
member( Y, [ 1, 2, 3, 4, 5, 6, 7, 8 ] ),
not( attack( X/Y, Others )).

attack( X/Y, Others ) :-


member( X1/Y1, Others ),
( Y1 = Y,
Y1 is Y + X1 - X;
Y1 is Y - X1 + X ).

member( A, [ A | L ] ).
member( A, [ B | L ] ) :-
member( A, L).
% Mä hçnh låìi giaíi
Kyî thuáût láûp trçnh Prolog 155

model( [ 1/Y1, 2/Y2, 3/Y3, 4/Y4, 5/Y5, 6/Y6, 7/Y7, 8/Y8 ] ).


?- model( S ), solution( S ).
S = [1/1, 2/1, 3/1, 4/1, 5/1, 6/1, 7/1, 8/1] ;
S = [1/1, 2/8, 3/1, 4/1, 5/1, 6/1, 7/1, 8/1] ;
S = [1/2, 2/8, 3/1, 4/1, 5/1, 6/1, 7/1, 8/1] ;
S = [1/1, 2/1, 3/7, 4/1, 5/1, 6/1, 7/1, 8/1] ;
S = [1/3, 2/1, 3/7, 4/1, 5/1, 6/1, 7/1, 8/1] ;
S = [1/1, 2/2, 3/7, 4/1, 5/1, 6/1, 7/1, 8/1]
Yes

II.5.2. Sæí duûng danh saïch toaû âäü theo cäüt


Trong chæång trçnh thæï nháút, ta âaî âæa ra låìi giaíi biãøu diãùn baìn cåì coï
daûng :
[ 1/Y1, 2/Y2, 3/Y3, ... , 8/Y8 ]

do mäùi cäüt chè âàût âuïng mäüt quán háûu. Thæûc ra, ta khäng máút thäng tin nãúu
boí âi caïc toaû âäü X. Ta coï thãø biãøu diãùn baìn cåì chè våïi caïc toaû âäü Y cuía caïc
quán háûu :
[ Y1, Y2, Y3, ... , Y8 ]
Âãø khäng xaíy ra caïc quán háûu nàòm trãn cuìng cäüt, cáön phaíi bäú trê mäùi
quán háûu mäüt haìng. Tæì âáy ta âàût ra raìng buäüc cho caïc toaû âäü Y : mäùi haìng
1, 2, 3, ..., 8 cuía baìn cåì chè âæåüc pheïp âàût duy nháút mäüt quán háûu. Ta nháûn
tháúy ràòng mäùi låìi giaíi laì mäüt hoaïn vë cuía danh saïch caïc säú 1 .. 8 sao cho thæï
tæû cuía mäùi con säú laì khaïc nhau :
[ 1, 2, 3, 5, 6, 7, 8 ]
Mäùi hoaïn vë cuía danh saïch laì mäüt låìi giaíi S sao cho caïc quán háûu åí traûng
thaïi an toaìn (khäng àn âæåüc láùn nhau). Ta coï :
solution( S ) :-
permutation( [ 1, 2, 3, 5, 6, 7, 8 ], S ),
insafety( S ).
Trong chæång 1 træåïc âáy, ta âaî xáy dæûng quan hãû permutation, báy giåì ta
cáön âënh nghéa quan hãû safety. Xaíy ra hai træåìng håüp nhæ sau :
1. Nãúu danh saïch S räùng, khi âoï S cuîng laì låìi giaíi, vç khäng coï quán háûu
naìo táún cäng quán háûu naìo.
insafety( [ ] ).
156 Láûp trçnh lägich trong Prolog

2. Nãúu danh saïch S khaïc räùng, khi âoï S coï daûng [ Queen | Others ]. Ta
tháúy S laì låìi giaíi nãúu caïc quán háûu trong Others laì åí traûng thaïi an
toaìn vaì quán háûu Queen khäng thãø táún cäng quán háûu naìo trong
Others.

Tæì âoï ta coï :


insafety( [ ] ).
insafety( [ Queen | Others ] ) :-
insafety( Others ),
noattack( Queen, Others ).
Trong âënh nghéa insafety, quan hãû noattack toí ra tinh tãú hån so våïi cuîng
cuìng quan hãû naìy trong chæång trçnh 1 trãn âáy. Khoï khàn nàòm åí chäù vë trê
cuía mäüt quán háûu chè âæåüc xaïc âënh båíi caïc toaû âäü Y, maì vàõng màût toaû âäü X.
Âãø âënh nghéa quan hãû noattack, ta tçm caïch khaïi quaït váún âãö nhæ nhæ minh
hoaû åí hçnh dæåïi âáy.

(a) (b)
• •

• Others •
• •

Queen
• •

khoaíng caïch toaû âäü X = 1 khoaíng caïch toaû âäü X = 3


Hçnh II.8. Khoaíng caïch giæîa toaû âäü X cuía Queen vaì toaû âäü X cuía Others laì 1.
(b) Khoaíng caïch giæîa toaû âäü X cuía Queen vaì toaû âäü X cuía Others laì 3.

Ta tháúy ràòng sæí duûng âêch :


noattack( Queen, Others )
laì âãø minh chæïng ràòng quán háûu Queen chè coï thãø táún cäng caïc quán háûu
trong danh saïch Others khi toaû âäü X cuía Queen caïch toaû âäü X cuía Others êt
nháút laì 1.
Âãø thæûc hiãûn âiãöu naìy, ta thãm mäüt âäúi thæï ba laì XDist (khoaíng caïch theo
toaû âäü X giæîa Queen vaì Others) vaìo noattack :
Kyî thuáût láûp trçnh Prolog 157

noattack( Queen, Others, XDist )


Vç váûy, ta phaíi thay âäøi laûi âêch noattack trong insafety nhæ sau :
insafety( [ Queen | Others ] ) :-
insafety( Others ),
noattack( Queen, Others, XDist ).
Âãø âënh nghéa noattack, cáön phán biãût hai træåìng håüp cuía danh saïch
Others :
1. Nãúu Others räùng, khi âoï khäng coï quán háûu naìo táún cäng quán háûu
naìo.
noattack( _ , [ ], _ ).
2. Nãúu danh saïch Others khaïc räùng, khi âoï Queen khäng thãø táún cäng
quán háûu laì pháön tæí âáöu cuía danh saïch Others (khoaíng caïch giæîa toaû
âäü X cuía Queen vaì toaû âäü X cuía pháön tæí âáöu naìy laì 1), cuîng nhæ
khäng thãø táún cäng mäüt quán háûu naìo trong pháön danh saïch coìn laûi
cuía Others, våïi mäüt khoaíng caïch laì XDist + 1.
Tæì âoï ta coï :
noattack( Y, [ Y1 | YList ], XDist ) :-
Y1 - Y =\= XDist,
Y - Y1 =\= XDist,
Dist1 is XDist + 1,
noattack( Y, YList, Dist1 ).
Táút caí nhæîng láûp luáûn vaì quan hãû væìa âënh nghéa trãn âáy cho ta chæång
trçnh låìi giaíi thæï hai cho baìi toaïn taïm quán háûu nhæ sau :

% chæång trçnh thæï hai giaíi baìi toaïn taïm quán háûu
% The problem of the eight queens - Program 2
% −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
solution( Queens ) :-
permutation( [ 1, 2, 3, 4, 5, 6, 7, 8 ], Queens ),
insafety( Queens ).
permutation( [ ], [ ] ).
permutation( [ Head | Tail ], PermList ) :-
permutation( Tail, PermTail ),
remove( Head, PermList, PermTail ).
remove( X, [ X | L ], L ).
remove( X, [ Y | L ], [ Y | L1 ] ) :-
remove( X, L, L1 ).
insafety( [ ] ).
158 Láûp trçnh lägich trong Prolog

insafety( [ Queen | Others ] ) :-


insafety( Others ),
noattack( Queen, Others, 1 ).
noattack( _ , [ ], _ ).
noattack( Y, [ Y1 | YList ], XDist ) :-
Y1 - Y =\= XDist,
Y - Y1 =\= XDist,
Dist1 is XDist + 1,
noattack( Y, YList, Dist1 ).

Sau khi yãu cáöu, Prolog âæa ra caïc låìi giaíi nhæ sau :
?- solution( S ).
S = [5, 2, 6, 1, 7, 4, 8, 3] ;
S = [6, 3, 5, 7, 1, 4, 2, 8] ;
S = [6, 4, 7, 1, 3, 5, 2, 8] ;
S = [3, 6, 2, 7, 5, 1, 8, 4] ;
S = [6, 3, 1, 7, 5, 8, 2, 4] ;
S = [6, 2, 7, 1, 3, 5, 8, 4] ;
S = [6, 4, 7, 1, 8, 2, 5, 3] ;

Yes

II.5.3. Sæí duûng toaû âäü theo haìng, cäüt vaì caïc âæåìng cheïo
Trong chæång trçnh thæï ba, ta âæa ra láûp luáûn nhæ sau :
Cáön phaíi âàût mäùi quán háûu lãn mäüt ä, nghéa laì trãn mäüt haìng, mäüt cäüt,
mäüt âæåìng cheïo nghëch (tæì dæåïi lãn) vaì mäüt âæåìng cheïo thuáûn (tæì trãn
xuäúng). Âãø moüi quán háûu khäng thãø àn âæåüc láùn nhau, chuïng phaíi âæåüc âàût
mäùi quán trãn mäüt haìng, mäüt cäüt, mäüt âæåìng cheïo nghëch vaì mäüt âæåìng cheïo
thuáûn phán biãût. Nhæ váûy, ta dæû kiãún mäüt hãû thäúng toaû âäü biãøu diãùn caïc
quán háûu nhæ sau :
x cäüt
y haìng
u âæåìng cheïo nghëch
v âæåìng cheïo thuáûn
Caïc toaû âäü khäng hoaìn toaìn âäüc láûp våïi nhau : våïi x vaì y âaî cho, ta coï thãø
tênh âæåüc u vaì v :
u=x-y
v=x+y
Kyî thuáût láûp trçnh Prolog 159

Sau âáy laì bäún miãön giaï trë tæång æïng våïi bäún toaû âäü X, Y, U, V :
Dx = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
Dy = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
Du = [ -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 ]
Dy = [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ]
Baìi toaïn taïm quán háûu báy giåì âæåüc phaït biãøu laûi nhæ sau : haîy choün ra
taïm bäü bäún (X, Y, U, V), sao cho X ∈ Dx, Y ∈ Dy, U ∈ Du, V ∈ Dv vaì khäng
bao giåì sæí duûng hai láön cuìng mäüt pháön tæí trong mäùi miãön giaï trë Dx, Dy, Du
vaì Dv.
Nhæ váûy, U vaì V âæåüc sinh ra tæì viãûc læûa choün X vaì Y.

-7 -2 u=x–y +7
| | | | | | | | | | | | | | |

8
7
6
5
4 •
3
2
1
1 2 3 4 5 6 7 8 x

2 6 u=x+y 16
| | | | | | | | | | | | | | |

Hçnh II.9. Quan hãû giæîa cäüt, haìng, âæåìng cheïo nghëch vaì âæåìng cheïo thuáûn
Ä coï âaïnh dáúu () trong hçnh coï toaû âäü x = 2, y = 4, u = 2 – 4 = -2, v = 2 + 4 = 6.
Låìi giaíi âaûi khaïi coï daûng nhæ sau : cho træåïc bäún miãön giaï trë, haîy choün
mäüt vë trê cho quán háûu âáöu tiãn, räöi xoaï caïc toaû âäü cuía chuïng trong miãön
giaï trë, sau âoï sæí duûng caïc miãön giaï trë måïi naìy âãø âàût caïc quán háûu khaïc
tiãúp theo. Caïc vë trê trãn baìn cåì cuîng âæåüc biãøu diãùn båíi mäüt danh saïch caïc
160 Láûp trçnh lägich trong Prolog

toaû âäü trãn truûc Y. Chæång trçnh Prolog giaíi baìi toaïn taïm quán háûu seî sæí
duûng quan hãû :
sol ( ListY, Dx, Dy, Du, Dv )
cho pheïp raìng buäüc caïc toaû âäü cuía caïc quán háûu (trong ListY), xuáút phaït tæì
nguyãn lyï laì caïc quán háûu nàòm trãn caïc cäüt liãn tiãúp nhau láúy tæì Dx. Caïc toaû
âäü Y, U vaì V âæåüc láúy tæì Dy, Du vaì Dv tæång æïng.
Låìi giaíi cuäúi cuìng cuía baìi toaïn taïm quán háûu laì mãûnh âãö :
?- solution( S )
cho pheïp goüi sol våïi danh saïch caïc tham âäúi âáöy âuí. Chæång trçnh nhæ sau :

% chæång trçnh thæï ba giaíi baìi toaïn taïm quán háûu


% The problem of the eight queens - Program 3
% −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
solution( ListY) :-
sol( ListY ),
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 ],
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ] ) .
sol( [ ], [ ], Dy, Du, Dv ).
sol( [ Y | ListY ], [ X | Dx1 ], Dy, Du, Dv ) :-
del( Y, Dy, Dy1 ),
U is X – Y,
del( U, Du, Du1 ),
V is X + Y,
del( V, Dv, Dv1 ),
sol ( ListY, Dx1, Dy1, Du1, Dv1 ).
del( A, [ A | List ], List ) .
del( A, [ B | List ], [ B | List1 ] ) :-
del( A, List , List1 ).
Sau khi yãu cáöu, Prolog âæa ra caïc låìi giaíi nhæ sau :
?- solution( S ).
S = [ 1, 5, 8, 6, 3, 7, 2, 4 ] ;
S = [ 1, 6, 8, 3, 7, 4, 2, 5 ] ;
S = [ 1, 7, 4, 6, 8, 2, 5, 3 ] ;
S = [ 1, 7, 5, 8, 2, 4, 6, 3 ]

Yes
Kyî thuáût láûp trçnh Prolog 161

Thuí tuûc sol væìa xáy dæûng trãn âáy coï tênh täøng quaït vç coï thãø duìng âãø
giaíi quyãút baìi toaïn cho N quán háûu báút kyì (trãn baìn cåì N × N). Sæû khaïc nhau
laì åí chäù miãön giaï trë Dx, Dy, … thay âäøi tuyì theo N.
Âãø taûo sinh caïc miãön giaï trë naìy mäüt caïch tæû âäüng, ta âënh nghéa thuí tuûc :
gen( N1, N2, List ).
âãø taûo ra mäüt danh saïch caïc säú nguyãn giæîa N1 vaì N2 :
List = [ N1, N1 + 1, N1 + 2, …, N2 – 1, N2 ]
Thán thuí tuûc nhæ sau :
gen( N, N, [ N ] ).
gen( N1, N2, [ N1 | List ] ) :-
N1 < N2,
M is N1 + 1,
gen( M, N2, List ).
Báy giåì ta thay âäøi quan hãû solution nhæ sau :
solution( N, S ) :-
gen( 1, N, Dxy),
Nu1 is 1 – N,
Nu2 is N - 1,
gen( Nu1, Nu2, Du ),
Nv2 is N + N,
gen( 2, Nv2, Dv ),
sol( S, Dxy, Dxy, Du, Dv).
Giaí sæí cáön giaíi baìi toaïn våïi 12 quán háûu, ta coï låìi goüi nhæ sau :
?- solution( 12, S ).
S = [ 1, 3, 5, 8, 10, 12, 6, 11, 2, 7, 9, 4]

Yes

II.5.4. Kãút luáûn


Vê duû baìi toaïn taïm quán háûu trãn âáy minh hoaû caïch giaíi quyãút mäüt baìi
toaïn trong Prolog theo nhiãöu låìi giaíi khaïc nhau, mäùi låìi giaíi sæí duûng mäüt
phæång phaïp biãøu diãùn cáúu truïc dæî liãûu. Mäùi caïch biãøu diãùn dæî liãûu âãöu coï
nhæîng âàûc træng riãng, nhæ tiãút kiãûm bäü nhåï, hay biãøu diãùn tæåìng minh, hay
biãøu diãùn phæïc håüp caïc thaình pháön cuía âäúi tæåüng cáön xæí lyï. Caïch biãøu diãùn
162 Láûp trçnh lägich trong Prolog

dæî liãûu nhàòm tiãút kiãûm bäü nhåï coï báút låüi åí chäù laì thæåìng xuyãn phaíi tênh âi
tênh laûi mäüt säú giaï trë dæî liãûu træåïc khi coï thãø sæí duûng chuïng.
Trong ba låìi giaíi trãn âáy, låìi giaíi thæï ba minh hoaû roî neït hån caí vãö caïch
xáy dæûng caïc cáúu truïc dæî liãûu xuáút phaït tæì mäüt táûp håüp caïc pháön tæí âaî cho
coï nhiãöu raìng buäüc. Hai chæång trçnh âáöu xáy dæûng táút caí caïc hoaïn vë coï thãø
räöi láön læåüt kiãøm tra coï phaíi hoaïn vë âang xeït laì mäüt låìi giaíi khäng âãø loaûi boí
nhæîng hoaïn vë khäng täút træåïc khi xáy dæûng chuïng mäüt caïch âáöy âuí. Viãûc
xaïc âënh caïc hoaïn vë gáy ra täún thåìi gian do phaíi thæûc hiãûn nhiãöu láön caïc
pheïp tênh säú hoüc. Chæång trçnh thæï ba traïnh âæåüc âiãöu naìy nhåì caïch biãøu
diãùn baìn cåì håüp lyï.

II.5.5. Bäü diãùn dëch Prolog


Xáy dæûng bäü diãùn dëch Prolog bàòng chênh ngän ngæî Prolog, âæåüc goüi laì bäü
siãu diãùn dëch vani (vanilla meta-interpreter).
solve(true).
solve((A, B)) :-
solve(A),
solve(B).
solve(A) :-
clause(A, B),
solve(B).
Mãûnh âãö clause(A, B) Prolog cho pheïp kiãøm tra nãúu A laì mäüt sæû kiãûn hay
vãú traïi (LHS) cuía mäüt luáût naìo âoï trong cå såí dæî liãûu (chæång trçnh Prolog),
B laì thán hay vãú phaíi cuía luáût âoï (nãúu A laì mäüt sæû kiãûn thç B = true). Vê duû :
?- clause(ins(X, [H|T], [ X,H|T ]), X @=< H).
X = _G420
H = _G417
T = _G418
Yes
Caïch goüi bäü siãu diãùn dëch vani :
?- solve(PrologGoal).
Kyî thuáût láûp trçnh Prolog 163

III. Quaï trçnh vaìo-ra vaì laìm viãûc våïi tãûp


III.1. Khaïi niãûm
Cho âãún luïc naìy, ta måïi laìm viãûc våïi Prolog qua chãú âäü tæång taïc : NSD
âàût cáu hoíi laì daîy caïc âêch dæûa trãn chæång trçnh âaî biãn dëch (laì mäüt
CSDL chæïa luáût vaì sæû kiãûn), Prolog traí låìi cho biãút caïc âêch âæåüc thoaí maîn
(Yes) hay khäng thoaí maîn (No), âäöng thåìi tuyì theo yãu cáöu maì âæa ra kãút
quaí dæåïi daûng raìng buäüc giaï trë cho caïc biãún (X = ...). Phæång phaïp naìy âån
giaín, âuí âãø trao âäøi thäng tin, tuy nhiãn ngæåìi ta váùn luän luän tçm caïch måí
räüng khaí nàng trao âäøi naìy. Ngæåìi ta cáön giaíi quyãút nhæîng váún âãö sau :
• Vaìo dæî liãûu cho chæång trçnh dæåïi caïc daûng khaïc cáu hoíi, chàóng haûn
caïc cáu trong ngän ngæî tæû nhiãn (tiãúng Anh, tiãúng Phaïp...).
• Âæa ra thäng tin dæåïi báút kyì daûng thæïc naìo mong muäún.
• Laìm viãûc âæåüc våïi caïc tãûp (file) khäng chè thuáön tuyï maìn hçnh, baìn
phêm.
Háöu hãút caïc phiãn baín Prolog âãöu coï nhæîng vë tæì thêch håüp giaíi quyãút
âæåüc nhæîng váún âãö nãu trãn. Giäúng nhæ caïc ngän ngæî láûp trçnh khaïc, Prolog
xem caïc thiãút bë vaìo-ra chuáøn (baìn phêm, maìn hçnh) laì caïc tãûp âàûc biãût. Quaï
trçnh vaìo-ra trãn caïc thiãút bë naìy vaì trãn caïc thiãút bë læu træî ngoaìi âæåüc xem
laì quaï trçnh laìm viãûc våïi caïc tãûp. Hçnh dæåïi âáy mä taí caïch Prolog laìm viãûc
våïi caïc tãûp.

Giao diãûn NSD

Vaìo tæì Ra
baìn phêm maìn hçnh,
maïy in
Doìng Doìng
Tãûp 1 Trçnh Tãûp 3
dæî liãûu dæî liãûu
Tãûp 2 Prolog Tãûp 4
vaìo ra
... ...

Hçnh III.1. Liãn laûc giæîa mäüt trçnh Prolog vaì nhiãöu tãûp .
Trçnh Prolog coï thãø âoüc dæî liãûu vaìo tæì nhiãöu tãûp, âæåüc goüi laì doìng dæî liãûu
vaìo (input streams), sau khi tênh toaïn, coï thãø ghi lãn nhiãöu tãûp, âæåüc goüi laì
164 Láûp trçnh lägich trong Prolog

doìng dæî liãûu ra (output streams). Dæî liãûu âãún tæì giao diãûn NSD (baìn phêm),
räöi kãút quaí gæíi ra maìn hçnh, cuîng âæåüc xæí lyï nhæ laì nhæîng doìng dæî liãûu vaìo
ra khaïc. Âáy laì nhæîng tãûp giaí (pseudo-file) âæåüc âàût tãn laì user (ngæåìi sæí
duûng). Caïc tãûp chæïa chæång trçnh, hay dæî liãûu Prolog âæåüc NSD læûa choün âàût
tãn tæû do (miãùn laì khaïc user) trong khuän khäø cuía hãû âiãöu haình.
Khi thæûc hiãûn mäüt trçnh Prolog, taûi mäùi thåìi âiãøm, chè coï hai tãûp hoaût
âäüng laì tãûp âang âæåüc âoüc, âæåüc goüi laì doìng vaìo hiãûn haình (active input
streams), vaì tãûp âang âæåüc ghi, âæåüc goüi laì doìng ra hiãûn haình (active output
streams).
Luïc måïi chaûy chæång trçnh, doìng vaìo hiãûn haình laì baìn phêm vaì doìng ra
hiãûn haình laì maìn hçnh (hoàûc maïy in) tæång æïng våïi chãú âäü vaìo ra chuáøn
user.

III.2. Laìm viãûc våïi caïc tãûp


III.2.1. Âoüc vaì ghi lãn tãûp
Mäüt säú vë tæì xæí lyï âoüc vaì ghi lãn tãûp cuía Prolog nhæ sau :
Tãn vë tæì YÏ nghéa
Måí tãûp File âãø âoüc dæî liãûu vaì xaïc âënh File laì doìng vaìo hiãûn
see(File) haình. Tãûp File phaíi coï tæì træåïc, nãúu khäng, Prolog baïo läùi
tãûp File khäng täön taûi.
see(user) Doìng vaìo hiãûn haình laì baìn phêm (chãú âäü chuáøn).
seeing(File) Håüp nháút tãûp File våïi tãûp vaìo hiãûn haình.
tell(File) Måí tãûp File âãø ghi dæî liãûu lãn vaì xaïc âënh File laì doìng ra
hiãûn haình. Nãúu tãûp File chæa âæåüc taûo ra træåïc âoï, thç tãûp
File seî âæåüc taûo ra. Nãúu tãûp File âaî täön taûi, näüi dung tãûp File
seî bë xoaï âãø ghi laûi tæì âáöu.
tell(user) Doìng ra hiãûn haình laì maìn hçnh (chãú âäü chuáøn).
telling(File) Håüp nháút tãûp File våïi tãûp ra hiãûn haình.
Âoïng tãûp âang ghi lãn hiãûn haình. Doìng vaìo tråí laûi chãú âäü
told
vaìo chuáøn user.
Âoïng tãûp âang âoüc hiãûn haình. Doìng ra tråí laûi chãú âäü ra
seen
chuáøn user.
Kyî thuáût láûp trçnh Prolog 165

Âoüc tæì doìng vaìo hiãûn haình mäüt giaï trë âãø khåïp våïi haûng
Term. Nãúu Term laì biãún thç âæåüc láúy giaï trë naìy vaì vë tæì thoaí
maîn. Nãúu khäng thãø säú khåïp, vë tæì traí vãö tháút baûi maì khäng
read(Term) tiãún haình quay lui. Mäùi haûng trong tãûp phaíi kãút thuïc båíi
mäüt dáúu cháúm vaì mäüt dáúu caïch (space) hoàûc dáúu Enter. Khi
thæûc hiãûn read maì âang åí vë trê cuäúi tãûp, Term seî nháûn giaï
trë end_of_file.
Ghi lãn tãûp hiãûn haình giaï trë cuía haûng Term. Nãúu Term laì
write(Term) biãún thç giaï trë naìy âæåüc âæa ra theo kiãøu cuía Prolog. Caïc
kiãøu giaï trë khaïc nhau âãöu coï thãø âæa ra båíi write.

Vê duû III.1 :
NSD âënh hæåïng doìng vaìo laì tãûp myexp1.pl :
?- see(‘myexp1.pl'). % Bàõt âáöu âoüc tãûp myexp1.pl.
Yes
Hoàûc :
?- see('C:/My Documents/Gt-Prolog/Example/myexp1.pl').
Yes
Âêch see(F) luän luän âæåüc thoaí maîn, træì træåìng håüp xaíy ra sai soït âäúi
våïi caïc tãûp dæî liãûu. Chuï yï tãn thæ muûc vaì âæåìng dáùn âæåüc viãút theo kiãøu
Unix vaì âæåüc âàût trong càûp dáúu nhaïy âån. Sau khi laìm viãûc trãn tãûp
myexp1.pl, lãûnh seen cho pheïp tråí vãö chãú âäü chuáøn.
?- seen.
Yes
Vê duû III.2 :
Duìng read âãø âoüc dæî liãûu vaìo báút kyì tæì baìn phêm :
?- read(N).
| 100.
N = 100
Yes
?- read('Your name ?').
| asimo.
No
?- read('Your name ?').
166 Láûp trçnh lägich trong Prolog

| 'Your name ?'.


Yes
?- read(asimo).
| Your_name.
Yes
% Âoüc vaì ghi caïc haûng
?- read(X).
| father(tom, mary).
X = father(tom, mary)
Yes
T = father(tom, mary), write(T).
father(tom, mary)
T = father(tom, mary)
Yes
Vê duû III.3
Âoüc näüi dung trong tãûp 'myex1.pl', sau âoï quay laûi chãú âäü vaìo ra chuáøn.
?- see('myex1.pl'), read(T),see(user).
T = del(_G467, [_G467|_G468], _G468)
Yes
Trong daîy âêch trãn, âêch read(T) âoüc âæåüc sæû kiãûn (X, [ X | L ], L ). laì näüi
dung doìng âáöu tiãn cuía tãûp coï nghéa, sau khi boí qua caïc doìng chuï thêch (nãúu
coï).
Ta cuîng coï thãø hæåïng doìng ra lãn tãûp bàòng caïch sæí duûng âêch :
?- tell(‘myex2.pl’).
Daîy âêch sau âáy gæíi thäng tin laì sæû kiãûn parent(tom, bob). lãn tãûp
myex2.pl, sau âoï quay laûi chãú âäü vaìo ra chuáøn :
tell(myex2.txt'), write('parent(tom, bob).'), tell(user).
Caïc tãûp chè coï thãø truy cáûp tuáön tæû. Prolog ghi nhåï vë trê hiãûn haình cuía
doìng vaìo âãø âoüc dæî liãûu. Mäùi láön âoüc hãút mäüt âäúi tæåüng (luáût, hay sæû kiãûn),
Prolog dåìi âáöu âoüc âãún vë trê âáöu âäúi tæåüng tiãúp theo. Khi âoüc âãún hãút tãûp,
Prolog âæa ra thäng baïo hãút tãûp :
?- see('exp.txt'), read(T),see(user).
T = end_of_file
Yes
Kyî thuáût láûp trçnh Prolog 167

Vê duû III.4 :
Duìng write âãø âæa dæî liãûu báút kyì ra maìn hçnh :
?- write(asimo).
asimo
Yes
Caïch ghi lãn tãûp cuîng theo cå chãú tæång tæû, dæî liãûu âæåüc ghi liãn tiãúp bàõt
âáöu tæì vë trê cuäúi cuìng cuía âäúi tæåüng. Prolog khäng thãø quay lui hay ghi âeì
lãn pháön âaî ghi træåïc âoï.
Prolog chè laìm viãûc våïi caïc tãûp daûng vàn baín (text files), nghéa laì chè vaìo
ra våïi caïc chæî caïi chæî säú vaì kyï tæû âiãöu khiãøn ASCII.

III.2.2. Mäüt säú vê duû âoüc vaì ghi lãn tãûp


Mäüt säú vë tæì âoüc vaì ghi khaïc cuía Prolog nhæ sau :
Tãn vë tæì YÏ nghéa
write(File, Term) Ghi lãn tãûp File giaï trë haûng Term.
Ghi lãn doìng ra hiãûn haình giaï trë haûng Term
writeq(Term)
keìm dáúu nhaïy âån (quotes).
Ghi lãn tãûp File giaï trë haûng Term keìm dáúu nhaïy
writeq(File, Term)
âån (quotes).
print(Term) In ra doìng ra hiãûn haình giaï trë haûng Term.
print(File, Term) In ra tãûp File giaï trë haûng Term.
read(File, Term) Âoüc tæì tãûp File hiãûn haình cho Term.
Tæång tæû to read/1. Âoüc mäüt mãûnh âãö tæì doìng
read_clause(Term)
vaìo hiãûn haình.
read_clause(File, Term) Âoüc mäüt mãûnh âãö tæì tãûp File.
nl Nhaíy qua doìng måïi (neuwline).
tab(N) In ra N dáúu khoaíng träúng (space)
tab(File, N) In ra N dáúu khoaíng träúng trãn tãûp File
Vê duû III.5 :
?- nl. % Qua doìng måïi
Yes
?- tab(5), write(*), nl.
*
Yes
168 Láûp trçnh lägich trong Prolog

âæa ra maìn hçnh 5 dáúu caïch räöi âãún mäüt dáúu * vaì qua doìng.
Vê duû III.6 :
Viãút thuí tuûc tênh luyî thæìa 3 cuía mäüt säú :
cube( N, C) :-
C is N * N* N.
Giaí sæí ta muäún tênh nhiãöu láön cube, khi âoï ta phaíi viãút nhiãöu láön âêch :
?- cube( 2, X ).
X=8
Yes
?- cube( 5, Y ).
V 125
?- cube( 12, Z).
Z = 1728
Yes
Âãø chè cáön sæí duûng mäüt âêch maì coï thãø tênh nhiãöu láön cube, ta cáön sæía laûi
chæång trçnh nhæ sau :
cube :-
read( X ),
compute( X ).
compute( stop ) :- !.
compute( N) :-
C is N *N* N,
write( C),
cube.
Nghéa thuí tuûc cuía chæång trçnh cube nhæ sau : âãø tçm luyî thæìa 3, træåïc
tiãn âoüc X, sau âoï thæûc hiãûn tênh toaïn våïi X vaì in ra kãút quaí. Nãúu X coï giaï trë
laì stop, ngæìng ngay, nãúu khäng, thæûc hiãûn tênh toaïn mäüt caïch âãû quy. Chuï yï
khi nháûp dæî liãûu cho vë tæì read, cáön kãút thuïc båíi mäüt dáúu cháúm :
?- cube.
|: 3.
27
|: 10.
1000
|: 18.
5832
|: stop.
Yes
Kyî thuáût láûp trçnh Prolog 169

Ta coï thãø tiãúp tuûc thay âäøi chæång trçnh. Mäüt caïch træûc giaïc, nãúu viãút laûi
cube maì khäng sæí duûng compute nhæ sau laì sai :
cube :-
read( stop), !.
cube :-
read( N),
C is N *N * N,
write( C),
cube.
båíi vç, giaí sæí NSD goî vaìo 3, âêch read( stop) tháút baûi, nhaït càõt boí qua dæî liãûu
naìy vaì do váûy, cube(3) khäng âæåüc tênh. Lãûnh read( N) tiãúp theo seî yãu cáöu
NSD vaìo tiãúp dæî liãûu cho N. Nãúu N laì säú, viãûc tênh toaïn thaình cäng, ngæåüc
laûi, nãúu N laì stop, Prolog seî thæûc hiãûn tênh toaïn trãn caïc dæî liãûu phi säú stop :
?- cube1.
|: 3. % Prolog boí qua, khäng tênh
|: 9.
729 % Prolog tênh ra kãút quaí cho N = 9
|: 4. % Prolog boí qua, khäng tênh
|: stop. % Prolog baïo läùi
ERROR: Arithmetic: `stop/0' is not a function
^ Exception: (9) _L143 is stop*stop*stop ? creep
Thäng thæåìng caïc chæång trçnh khi thæûc hiãûn cáön sæû tæång taïc giæîa NSD
vaì hãû thäúng. NSD cáön âæåüc biãút kiãøu vaì giaï trë dæî liãûu chæång trçnh yãu cáöu
nháûp vaìo. Muäún váûy, chæång trçnh cáön âæa ra doìng yãu cáöu hay låìi nhàõc
(prompt). Haìm cube âæåüc viãút laûi nhæ sau :
cube :-
write('Please enter a number: '),
read( X ),
compute( X ).
compute( stop ) :- !.
compute( N) :-
C is N *N* N,
write('The cube of '), write(N),
write(' is '), write( C), nl,
cube.
cube.
Please enter a number: 3.
The cube of 3 is 27
Please enter a number: stop.
170 Láûp trçnh lägich trong Prolog

Yes
Vê duû III.7
Ta xáy dæûng thuí tuûc displaylist sau âáy âãø in ra caïc pháön tæí cuía danh
saïch :
displaylist( [ ]).
displaylist( [X | L ] ) :-
write( X ), nl,
displaylist( L).
?- displaylist( [[a, b, c], [d, e, f], [g, h, i]]).
[a, b, c]
[d, e, f]
[g, h, i]
Yes
Ta tháúy trong træåìng håüp caïc pháön tæí cuía mäüt danh saïch laûi laì nhæîng
danh saïch nhæ trãn thç täút hån caí laì in chuïng ra trãn cuìng haìng :
displaylist( [ ]).
displaylist( [X | L ] ) :-
write( X ), tab( 1),
displaylist( L), nl.
displaylist( [[a, b, c], [d, e, f], [g, h, i]]).
[a, b, c] [d, e, f] [g, h, i]
Yes
Thuí tuûc dæåïi âáy in ra caïc pháön tæí kiãøu danh saïch phàóng trãn cuìng
haìng :
displaylist2( [ ] ).
displaylist2( [ L | L1 ] ) :-
inline( u),
displaylist2( L1 ), nl.
inline( [ ] ).
inline( [ X I L ] ) :-
write( X ), tab( 1),
inline( L).
?- displaylist2( [[a, b, c], [d, e, f], [g, h, i]]).
abcdefghi
Yes
Vê duû dæåïi âáy in ra danh saïch caïc säú nguyãn dæåïi daûng mäüt âäö thë gäöm
caïc doìng keí laì caïc dáúu sao (hoa thë) * :
Kyî thuáût láûp trçnh Prolog 171

barres( [ N | L]) :-
asterisk(N), nl,
barres(L).
asterisk( N) :-
N > 0,
write( *),
N1 is N - 1,
asterisk( N1).
asterisk( N) :-
N =< 0.
?- barres([3, 4, 6, 5, 9]).
***
****
******
*****
*********
No
Vê duû III.8 :
Âoüc näüi dung mäüt tãûp vaìo danh saïch caïc säú nguyãn :
readmyfile( File, List) :-
see( File),
readlist( List),
seen,
!.
readlist( [X | L ]) :-
get0(X),
X =\= -1,
!,
read_list( L).
readlist( [ ] ).

III.2.3. Naûp chæång trçnh Prolog vaìo bäü nhåï


Caïc chæång trçnh Prolog thæåìng âæåüc læu cáút trong caïc tãûp coï tãn háûu täú
(hay pháön måí räüng cuía tãn) laì « .pl » . Âãø naûp chæång trçnh (load) vaìo bäü nhåï
vaì biãn dëch (compile, Prolog sæí duûng vë tæì :
?- consult(file_name).
trong âoï, file_name laì mäüt nguyãn tæí.
Vê duû III.9 :
Âêch sau âáy naûp vaì biãn dëch chæång trçnh nàòm trong tãûp myexp.pl :
?- consult(‘myexp.pl').
172 Láûp trçnh lägich trong Prolog

Yes
Prolog cho pheïp viãút goün trong mäüt danh saïch nhæ sau :
?- [‘myexp.pl' ].
Âãø naûp vaì biãn dëch âäöng thåìi nhiãöu tãûp chæång trçnh khaïc nhau, coï thãø
liãût kã trong mäüt danh saïch nhæ sau :
?- ['file1.pl', 'file2.pl'].
Sau khi caïc chæång trçnh âaî âæåüc naûp vaìo bäü nhåï, NSD bàõt âáöu thæûc hiãûn
chæång trçnh. NSD coï thãø xem näüi dung toaìn bäü chæång trçnh nhåì vë tæì :
?- listing.
hoàûc xem mäüt mãûnh âãö naìo âoï :
?- listing(displaylist).
displaylist( [ ]).
displaylist( [X | L ] ) :-
write( X ),
tab( 1),
displaylist( L), nl.
Yes

III.3. ÆÏng duûng chãú âäü laìm viãûc våïi caïc tãûp
III.3.1. Âënh daûng caïc haûng
Giaí sæí mäüt baín ghi cå såí dæî liãûu, laì mäüt sæû kiãûn coï daûng cáúu truïc haìm tæí
cuía Prolog, coï näüi dung nhæ sau :
family( individual(tom, smith, date(7, may, 1960), work(microsoft, 30000)),
individual( ann, smith, date(9, avril, 1962), inactive),
[ individual( roza, smith, date(16, june, 1991), inactive),
individual( eric, smith, date(23, march, 1993), inactive) ] ).
Ta cáön in ra näüi dung baín ghi sæí duûng vë tæì write(F) theo quy caïch nhæ
sau :
parents
tom smith, birth day may 7,1960, work microsoft, salary 30000
ann smith, birth day avril 9, 1962, out of work
children
roza smith, birth day june 16, 1991, out of work
eric smith, birth day march 23, 1993, out of work
Ta xáy dæûng thuí tuûc writefamily( F) nhæ sau :
Kyî thuáût láûp trçnh Prolog 173

writefamily(family(Husband, Wife, Children)) :-


nl, write(parents),nl, nl,
writeindividual(Husband) ,nl,
writeindividual(Wife), nl, nl,
write(children), nl, nl,
writeindividual(Children).
writeindividual(individual(Firstname, Name, date(D, M, Y), Work)) :-
tab(4), write(Firstname),
tab(1), write(Name),
write(', birth day '), write(M), tab(1),
write(D), tab(1), write(', '), write(Y), write(', '),
writework(Work).
writeindividual([ ]).
writeindividual([ P | L] ):-
writeindividual( P), nl,
writeindividual( L).
writework(inactive):-
write('out of work').
writework(work(Soc, Sal)):-
write(' work '), write(Soc),
write(', salaire '), write(Sal).
Thæûc hiãûn âêchX = ..., writefamily(X), ta nháûn âæåüc kãút quaí nhæ sau
?- X = family(individual( tom, smith, date(7, may, 1960), work(microsoft,
30000) ),individual( ann, smith, date(9, avril, 1962), inactive),[individual(
roza, smith, date(16, june, 1991), inactive),individual( eric, smith, date(23,
march, 1993), inactive) ] ), writefamily(X).
parents
tom smith, birth day may 7 , 1960, work microsoft, salaire 30000
ann smith, birth day avril 9 , 1962, out of work
children
roza smith, birth day june 16 , 1991, out of work
eric smith, birth day march 23 , 1993, out of work
X = family(individual(tom, smith, date(7, may, 1960), work(microsoft,
30000)), individual(ann, smith, date(9, avril, 1962), inactive), [individual(roza,
smith, date(16, june, 1991), inactive), individual(eric, smith, date(23, march,
1993), inactive)])
Yes

III.3.2. Sæí duûng tãûp xæí lyï caïc haûng


Âãø âoüc dæî liãûu trãn tãûp, ngæåìi ta sæí duûng daîy âêch sau :
..., see( F), fileprocess, see( user), ...
174 Láûp trçnh lägich trong Prolog

Thuí tuûc fileprocess âoüc vaì xæí lyï láön læåüt tæìng haûng cuía F cho âãún khi âoüc
hãút tãûp. Mä hçnh thuí tuûc nhæ sau :
filetreat :-
read( Term),
treat( Term).
treat( end_of_file) :- !. % Kãút thuïc tãûp
treat( Term) :-
treatment( Term), % Xæí lyï haûng hiãûn haình
filetreat. % Xæí lyï pháön coìn laûi cuía tãûp
Trong thuí tuûc trãn, treatment( Terme) thãø hiãûn moüi thao taïc coï thãø taïc
âäüng lãn haûng. Chàóng haûn thuí tuûc dæåïi âáy liãût kã tæìng haûng cuía tãûp kãø tæì
doìng thæï N tråí âi cho âãún hãút tãûp, keìm theo thæï tæû coï màût cuía haûng âoï trong
tãûp :
viewfile( N) :-
read( Term),
viewterm( Term, N).
viewterm( end_of_file, _ ) :- !.
viewterm( Term, N) :-
write( N), tab( 2),
write( Term), nl,
N1 is N + 1,
viewfile( N1).
?- see('exp.txt'), viewfile(1), see( user), seen.
1 parent(pam, bob)
2 parent(tom, bob)
3 parent(tom, liz)
4 parent(bob, ann)
5 parent(bob, pat)

Yes
Sau âáy laì mäüt mä hçnh khaïc âãø xæí lyï tãûp. Giaí sæí file1 laì tãûp dæî liãûu
nguäön chæïa caïc haûng coï daûng :
object( NoObject, Description, Price, FurnisherName).
Mäùi haûng mä taí mäüt pháön tæí cuía danh saïch caïc âäúi tæåüng. Giaí sæí ràòng
tãûp cáön xáy dæûng file2 chæïa caïc âäúi tæåüng do cuìng mäüt nhaì cung cáúp cáúp
haìng. Trong tãûp naìy, tãn nhaì cung cáúp âæåüc viãút mäüt láön åí âáöu tãûp, maì
Kyî thuáût láûp trçnh Prolog 175

khäng xuáút hiãûn trong caïc âäúi tæåüng, coï daûng object( No, Desc, Price). Thuí
tuûc taûo tãûp nhæ sau :
createfile(Furnisher) :-
write(Furnisher), write( ‘.‘), nl,
creatremaining(Furnisher).
creatremaining( Fournisseur) :-
read( Objet),
treat( Objet, Furnisher).
treat( end_of_file) :- !.
treat(object( No, Desc, Price, Furn), Furn) :-
write( object( No, Desc, Price) ),
write( ‘.‘), nl,
creatremaining(Furn).
treat( _ , Furnisher) :-
creatremaining(Furnisher).
Giaí sæí file1 laì tãûp
see(' file1.txt'),tell(' file2.txt'), createfile(suzuki), seen, see(user), told,
tell(user).
Vê duû III.10 :
Sao cheïp näüi dung mäüt tãûp lãn mäüt tãûp khaïc :
copie :-
repeat,
read(X),
mywrite(X),
X == end_of_file, !.
mywrite( end_of_file).
mywrite( X) :-
write( X), write( '.'), nl.
Âêch sau cho pheïp cäpy tæì tãûp nguäön f1.txt vaìo tãûp âêch f2.txt :
?- tell('f2.txt'), see('f1.txt'), copie, seen, told.
Yes
Trong thuí tuûc copie coï sæí duûng vë tæì repeat. Vë tæì repeat luän luän thaình
cäng, taûo ra mäüt voìng làûp vä haûn. Vë tæì repeat âæåüc âënh nghéa nhæ sau :
repeat.
repeat :- repeat.

III.3.3. Thao taïc trãn caïc kyï tæû


Mäüt säú vë tæì xæí lyï kyï tæû cuía Prolog nhæ sau :
176 Láûp trçnh lägich trong Prolog

Tãn vë tæì YÏ nghéa


Âæa Char ra doìng ra hiãûn haình, Char hoàûc laì mäüt giaï
put(Char)
trë nguyãn trong khoaíng 0..255, hoàûc mäüt kyï tæû
put(File, Char) Âæa Char ra tãûp File
get_char(Char) Âoüc tæì tãûp File vaì håüp nháút Char våïi kyï tæû tiãúp theo.
get_char(File, Char) Håüp nháút Char våïi kyï tæû tiãúp theo trong tãûp File.
get0(Char) Âoüc kyï tæû tiãúp theo
get0(File, Char) Âoüc kyï tæû tiãúp theo trong tãûp File.
Âoüc kyï tæû khaïc khoaíng träúng tæì doìng vaìo vaì håüp
get(-Char)
nháút våïi Char.
get(File, Char) Âoüc kyï tæû khaïc khoaíng träúng tiãúp theo trong tãûp File.
Âoüc vaìo vaì boí qua caïc kyï tæû âoüc âæåüc cho âãún khi gàûp
skip(Char)
âuïng kyï tæû khåïp âæåüc våïi Char.
Âoüc vaìo tæì tãûp File vaì boí qua caïc kyï tæû âoüc âæåüc cho
skip(File, Char)
âãún khi gàûp âuïng kyï tæû khåïp âæåüc våïi Char.
Vê duû III.11 :
% Âæa ra liãn tiãúp caïc kyï tæû A, B vaì C coï maî ASCII láön læåüt laì 65, 66, 67
?- put( 65), put( 66), put( 67).
ABC
yes
% Âoüc vaì ghi caïc kyï tæû
?- get0(X).
|: a % Goî vaìo mäüt kyï tæû räöi Enter (↵), khäng goî dáúu cháúm
X = 97
Yes.
?- get0(X).
^D
X = -1.
Yes.
Vê duû III.12 :
Sau âáy ta xáy dæûng thuí tuûc del_space âoüc vaìo mäüt cáu gäöm nhiãöu tæì
caïch nhau båíi caïc khoaíng träúng vaì traí vãö âuïng cáu âoï sau khi âaî loaûi boí caïc
khoaíng träúng thæìa, chè giæî laûi mäüt khoaíng träúng giæîa caïc tæì maì thäi.
Thuí tuûc hoaût âäüng tæång tæû caïc thuí tuûc xæí lyï tãûp, bàòng caïch âoüc láön læåüt
tæìng kyï tæû räöi âæa ra maìn hçnh. Thuí tuûc sæí duûng kyî thuáût nhaït càõt âãø xæí lyï
Kyî thuáût láûp trçnh Prolog 177

tçnh huäúng kyï tæû âoüc vaìo hoàûc laì mäüt khoaíng träúng, hoàûc laì mäüt chæî caïi,
hoàûc laì mäüt dáúu cháúm kãút thuïc. Sau âáy laì thuí tuûc del_space :
del_space :-
get0( C),
put( C),
follow( C).
follow( 46) :- !. % 46 laì maî ASCII cuía dáúu cháúm
follow( 32) :- !, % 32 laì maî ASCII cuía dáúu khoaíng träúng
get( C), % Boí qua caïc dáúu khoaíng träúng tiãúp theo
put( C),
follow( C).
follow( Letter) :-
del_space.
Chaûy thæí nhæ sau :
?- del_space.
|: The robot try to cast the balls to the basket.
The robot try to cast the balls to the basket.
Yes

III.3.4. Thao taïc trãn caïc nguyãn tæí


Prolog coï vë tæì name/2 cho pheïp âàût tæång æïng caïc nguyãn tæí våïi caïc maî
ASCII :
name( A, L)
Vë tæì thoaí maîn khi L laì danh saïch caïc cuía caïc kyï tæû cuía A. Vê duû :
?- name(mic29, [109, 105, 99, 50, 57 ]).
Yes
?- name( aikieutuido, L).
L = [ 97, 105, 107, 105, 101, 117, 116, 117, 105 |... ]
Yes
?- name(X, [ 97, 105, 107, 105, 101, 117, 116, 117, 105, 100, 111 ]).
X = aikieutuido
Yes
Hai chæïc nàng chênh cuía vë tæì name nhæ sau :
1. Chuyãøn mäüt nguyãn tæí thaình mäüt danh saïch caïc kyï tæû (maî ASCII).
2. Taûo mäüt nguyãn tæí tæì mäüt danh saïch caïc kyï tæû.
178 Láûp trçnh lägich trong Prolog

Vê duû III.13 :
Xáy dæûng thuí tuûc quaín lyï caïc cuäüc goüi dëch vuû xe taxi chåí haình khaïch
nhåì caïc nguyãn tæí sau :
Tãn caïc cuäüc goüi call1, call2, ...
Tãn caïc laïi xe chauffeur1, chauffeur2, ...
Tãn caïc xe taxi taxi1, taxi2, ...
Vë tæì taxi( X ) kiãøm tra mäüt nguyãn tæí coï biãøu diãùn âuïng mäüt taxi theo
caïch biãøu diãùn nhæ trãn khäng :
taxi( T ) :-
name( T, Tlist),
name( taxi, L),
append( L, _ , Tlist).
Mäüt caïch tæång tæû, ta coï thãø xáy dæûng caïc vë tæì chauffer vaì taxi.
Vê duû III.14 :
Sau âáy ta xáy dæûng thuí tuûc cho pheïp taûo ra mäüt nguyãn tæí bàòng caïch täø
håüp caïc kyï tæû. Thuí tuûc readsentence( Wordlist) seî âoüc mäüt cáu thuäüc ngän
ngæî tæû nhiãn räöi gaïn cho Wordlist danh saïch caïc giaï trë maî biãøu diãùn trong
cuía caïc kyï tæû trong cáu. Tiãúp theo, mäùi cáu âæåüc xem laì mäüt danh saïch caïc
tæì, mäùi tæì âæåüc chuyãøn thaình mäüt nguyãn tæí.
readsentence( WordList) :-
get0( Char),
readchain( Char, WordList).
readchain( 46,[ ] ) :- !. % dáúu cháúm kãút thuïc cáu
readchain( 32, WordList) :-
readsentence(WordList). % Boí qua caïc dáúu khoaíng träúng
readchain( L, [ W | WordList ] ) :-
readletter( L, Letters, Nextchar ), % Âoüc caïc kyï tæû cuía tæì tiãúp theo
name( W, Letters),
readchain( Nextchar, WordList).
readletter( 46, [ ], 46) :- !. % kãút thuïc tæì laì mäüt dáúu cháúm
readletter( 32, [ ], 32) :- !. % kãút thuïc tæì laì mäüt dáúu khoaíng
träúng
readletter( C, [ C | Letters] , Nextchar) :-
get0( Char),
readletter( Char, Letters, Nextchar).
Kyî thuáût láûp trçnh Prolog 179

Chaûy chæång trçnh, ta coï caïc kãút quaí nhæ sau :


?- readsentence( WordList).
|: The robot ASIMO try to cast the balls to the basket.
WordList = ['The', robot, 'ASIMO', try, to, cast, the, balls, to|...]
Yes
?- readsentence( WordList).
|: " Ai âi tràm suäúi ngaìn ræìng " % dáúu Enter ↵ sau dáúu nhaïy keïp
|: . % dáúu cháúm kãút thuïc cáu
WordList = [ '" Ai', âi, tràm, suäúi, ngaìn, 'ræìng "\n' ]
Yes
Trong thuí tuûc, ta âaî giaí thiãút ràòng kãút thuïc cáu vaìo laì mäüt dáúu cháúm vaì
nãúu coï dáúu cháúm cáu trong cáu, thç tuyì theo caïch xuáút hiãûn maì noï âæåüc xem
nhæ laì mäüt tæì hoàûc dênh vaìo våïi tæì.
Thuí tuûc âoüc kyï tæû âáöu tiãn laì Char, räöi chuyãøn cho thuí tuûc readchain.
Thuí tuûc readchain xæí lyï 3 træåìng håüp nhæ sau :
(1) Nãúu Char laì mäüt dáúu cháúm, thç quaï trçnh âoüc cáu vaìo kãút thuïc.
(2) Nãúu Char laì mäüt khoaíng träúng, aïp duûng thuí tuûc readsentence cho
pháön coìn laûi cuía cáu.
(3) Nãúu Char laì mäüt kyï tæû : træåïc tiãn âoüc tæì W âæåüc bàõt âáöu båíi kyï tæû
Char, sau âoï sæí duûng readsentence âãø âoüc pháön coìn laûi cuía cáu vaì taûo
ra danh saïch WordList. Kãút quaí âæåüc têch luyî trong [ W | WordList ].
Thuí tuûc readletter( L, Letters, Nextchar ) âoüc caïc kyï tæû cuía mäüt tæì, trong
âoï :
(1) L laì chæî caïi hiãûn haình (âaî âæåüc âoüc) cuía tæì âang âoüc.
(2) Letters laì danh saïch caïc chæî caïi, bàõt âáöu båíi L cho âãún hãút tæì.
(3) Nextchar laì kyï tæû theo sau tæì âang âoüc, coï thãø khäng phaíi laì mäüt chæî
caïi.
Nhåì caïch biãøu diãùn caïc tæì cuía cáu trong mäüt danh saïch, ngæåìi ta coï thãø
sæí duûng Prolog âãø xæí lyï ngän ngæî tæû nhiãn, nhæ tçm hiãøu nghéa cuía cáu theo
mäüt quy æåïc naìo âoï, v.v.. thuäüc lénh væûc trê tuãû nhán taûo.
180 Láûp trçnh lägich trong Prolog

III.3.5. Mäüt säú vë tæì xæí lyï cå såí dæî liãûu


Sau âáy laì mäüt säú vë tæì chuáøn cho pheïp xæí lyï trãn caïc luáût vaì sæû kiãûn cuía
mäüt cå såí dæî liãûu Prolog.
assert(P)
Thãm P vaìo cå såí dæî liãûu. Vê duû cho cå såí dæî liãûu luïc ban âáöu :
personal(tom).
personal(ann).
Sau khi thæûc hiãûn âêch :
?- assert(personal(bob)).
cå såí dæî liãûu luïc naìy tråí thaình :
personal(tom).
personal(ann).
personal(bob).
Do NSD khäng biãút assert âaî thãm P vaìo âáöu hay cuäúi cuía cå såí dæî liãûu,
Prolog cho pheïp sæí duûng hai daûng khaïc laì :
asserta(P) Thãm P vaìo âáöu cå såí dæî liãûu.
assertz(P) Thãm P vaìo cuäúi cå såí dæî liãûu.
Sæí duûng vë tæì :

assert((P :- B, C, D)).
coï thãø laìm thay âäøi näüi dung mäüt mãûnh âãö trong chæång trçnh. Tuy nhiãn,
ngæåìi ta khuyãn khäng nãn sæí duûng lãûnh naìy.
retract(P)
Loaûi boí P khoíi cå såí dæî liãûu. Vê duû cho cå såí dæî liãûu luïc ban âáöu :
personal(tom).
personal(ann).
personal(bob).
Sau khi thæûc hiãûn âêch :
?- retract(personal(ann)).
cå såí dæî liãûu luïc naìy chè coìn :
personal(tom).
personal(bob).
Coï thãø sæí duûng biãún trong retract nhæ sau :
Kyî thuáût láûp trçnh Prolog 181

?- retract(personal(X)).
X = tom ;
X = bob ;
No
Luïc naìy cå såí dæî liãûu âaî räùng.
abolish(Term, Arity)
Loaûi boí táút caí caïc haûng Term coï cáúp Arity khoíi cå såí dæî liãûu. Vê duû :
?- abolish(personal, 2).
Loaûi boí táút caí caïc haûng Term coï cáúp Arity=2.
Vê duû III.15
Xáy dæûng bäü siãu diãùn dëch Prolog trong Prolog, viãûc xoaï mäüt âêch âæåüc
viãút laûi nhæ sau :
prove(Goal) :- call(Goal).
hoàûc :
prove(Goal) :- Goal.
hoàûc viãút caïc mãûnh âãö :
prove(true).
prove((Goal1, Goal2)) :-
prove(Goal1),
prove(Goal2).
prove(Goal) :-
clause(Goal, Body),
prove(Body).
182 Láûp trçnh lägich trong Prolog

Toïm tàõt chæång 5 :


Kyî thuáût nhaït càõt vaì phuí âënh
• Nhaït càõt ngàn caín sæû quay lui, khäng nhæîng laìm tàûng hiãûu quaí chaûy
chæång trçnh maì coìn laìm täúi æu tênh biãøu hiãûn cuía ngän ngæî.
• Âãø tàûng hiãûu quaí chaûy chæång trçnh, ngæåìi láûp trçnh sæí duûng nhaït càõt
âãø chè ra cho Prolog biãút nhæîng con âæåìng dáùn âãún tháút baûi.
• Nhaït càõt cho pheïp taûo ra caïc kãút luáûn loaûi træì nhau daûng :
If Condition Thç Conclusion_1 nãúu Conclusion_2
• Nhaït càõt cho pheïp âënh nghéa pheïp phuí âënh : not Goal thoaí maîn nãúu
Goal tháút baûi.
• Prolog coï hai âêch âàûc biãût : true luän luän âuïng vaì fail luän luän sai.
• Cáön tháûn troüng khi sæí duûng kyî thuáût nhaït càõt, nhaït càõt coï thãø laìm sai
lãûch sæû tæång æïng giæîa nghéa khai baïo vaì nghéa thuí tuûc cuía mäüt
chæång trçnh.
• Pheïp phuí âënh not trong Prolog khäng hoaìn toaìn mang yï nghéa lägich,
cáön chuï yï khi sæí duûng not.
Sæí duûng caïc cáúu truïc
Caïc vê duû âaî trçnh baìy trong chæång naìy minh hoaû nhæîng âàûc træng ráút
tiãu biãøu cuía kyî thuáût láûp trçnh Prolog :
• Trong Prolog, táûp håüp caïc sæû kiãûn âuí âãø biãøu diãùn mäüt cå såí dæî liãûu.
• Kyî thuáût âàût cáu hoíi vaì so khåïp cuía Prolog laì nhæîng phæång tiãûn mãöm
deío cho pheïp truy cáûp tuì cå såí dæî liãûu nhæîng thäng tin coï cáúu truïc.
• Cáön sæí duûng phæång phaïp træìu tæåüng hoaï dæî liãûu nhæ laì mäüt kyî thuáût
láûp trçnh cho pheïp sæí duûng caïc cáúu truïc dæî liãûu phæïc taûp mäüt caïch âån
giaín, laìm chæång trçnh tråí nãn dãù hiãøu. Trong Prolog, phæång phaïp
træìu tæåüng hoaï dæî liãûu ráút dãù triãøn khai.
• Nhæîng cáúu truïc toaïn hoüc træìu tæåüng nhæ ätämat cuîng ráút dãù caìi âàût
trong Prolog.
• Ngæåìi ta coï thãø tiãúp cáûn âãún nhiãöu låìi giaíi khaïc nhau cho mäüt baìi toaïn
nhåì sæí duûng nhiãöu caïch biãøu diãùn dæî liãûu khaïc nhau, nhæ træåìng håüp
Kyî thuáût láûp trçnh Prolog 183

baìi toaïn taïm quán háûu. Caïch biãøu diãùn dæî liãûu sæí duûng nhiãöu thäng
tin tiãút kiãûm âæåüc tênh toaïn, màûc duì laìm cho chæång trçnh tråí nãn
ræåìm raì, khoï cä âoüng.
• Kyî thuáût täøng quaït hoaï mäüt baìi toaïn, tuy træìu tæåüng, nhæng laûi laìm
tàng khaí nàng hæåïng âãún låìi giaíi, laìm âån giaín hoaï phaït biãøu baìi toaïn.
Laìm viãûc våïi tãûp

Cuìng våïi chãú âäü tæång taïc cáu hoíi-traí låìi, quaï trçnh vaìo ra vaì chãú âäü laìm
viãûc våïi tãûp âaî laìm phong phuï mäi træåìng laìm viãûc cuía Prolog.
• Caïc tãûp trong Prolog âãöu hoaût âäüng theo kiãøu tuáön tæû. Prolog phán biãût
doìng vaìo hiãûn haình vaì doìng ra hiãûn haình.
• Thiãút bë cuäúi (terminal) cuía NSD gäöm maìn hçnh vaì baìn phêm âæåüc xem
nhæ mäüt tãûp giaí coï tãn laì user.
• Prolog coï nhiãöu vë tæì coï sàôn âãø xæí lyï caïc doìng vaìo-ra.
• Khi laìm viãûc våïi tãûp, chãú âäü âoüc ghi laì xæí lyï tæìng kyï tæû hoàûc tæìng haûng.
184 Láûp trçnh lägich trong Prolog

Baìi táûp chæång 5


1. Cho chæång trçnh :
p( 1 ).
p( 2 ) :- !.
p( 3 ).
Cho biãút caïc cáu traí låìi cuía Prolog tuì caïc cáu hoíi sau :
(a) ?- p( X ).
(b) ?- p( X ), p( Y ).
(c) ?- p( X ), !, p( Y ).
2. Quan hãû sau âáy cho biãút mäüt säú coï thãø laì dæång, bàòng khäng, hoàûc ám :
sign( Number, positive) :-
Number > 0.
sign( 0, null).
sign( Number, negative) :-
Number < 0.
Haîy sæí duûng kyî thuáût nhaït càõt âãø viãút laûi chæång trçnh trãn hiãûu quaí
hån.
3. Thuí tuûc separate(Number, Positive, Negative) xãúp caïc pháön tæí trong danh
saïch Number láön læåüt thaình hai danh saïch, danh saïch Positive chè chæïa
caïc säú dæång, hoàûc bàòng khäng, danh saïch Negative chè chæïa caïc säú ám.
Vê duû :
separate( [ 3, -1, 0, 5, -2 ], [ 3, 0, 5 ], [ -1, -2 ] )
Haîy âënh nghéa thuí tuûc trãn theo hai caïch, mäüt caïch khäng sæí duûng kyî
thuáût nhaït càõt, mäüt caïch coï sæí duûng kyî thuáût nhaït càõt.
4. Cho hai danh saïch, Accept vaì Reject, haîy viãút danh saïch caïc âêch sæí duûng
kyî thuáût quay lui vaì caïc quan hãû member vaì not âãø tçm caïc pháön tæí coï
màût trong Accept nhæng khäng coï màût trong Reject.
5. Âënh nghéa thuí tuûc difference( Set1, Set2, SetDiff) tçm hiãûu hai táûp håüp
Set1 vaì Set2 våïi quy æåïc caïc táûp håüp âæåüc biãøu diãùn båíi caïc danh saïch.
Kyî thuáût láûp trçnh Prolog 185

6. Chàóng haûn :
difference( [ a, b, c, d ], [ b, d, e, f ], [ a, c ] )
7. Haîy âënh nghéa vë tæì unifiable( List1, Term, List2) âãø kiãøm tra so khåïp,
trong âoï List2 laì danh saïch táút caí caïc pháön tæí cuía List1 coï thãø so khåïp våïi
Term nhæng khäng thæûc hiãûn pheïp thãú trãn caïc biãún âaî âæåüc so khåïp. Vê
duû :
?- unifiable( [ X, bibo, t( Y ) ], t(a), List ).
List = [X, t( Y )]
Chuï yï ràòng X vaì Y váùn laì caïc biãún tæû do khäng thæûc hiãûn pheïp thãú t(a) cho
X, hay pheïp thãú a cho Y. Muäún váûy, thæûc hiãûn hæåïng dáùn sau :
Sæí duûng pheïp phuí âënh not( Term1 = Term2). Nãúu quan hãû Term1 =
Term2 âæåüc thoaí maîn, khi âoï, not( Term1 = Term2) seî tháút baûi, vaì pheïp
thãú biãún khäng xaíy ra.
8. Baìi toaïn maî âi tuáön. Giaí sæí caïc ä cuía baìn cåì vua 8×8 âæåüc biãøu diãùn båíi
caïc càûp toaû âäü coï daûng X/Y, våïi X vaì Y nàòm trong khoaíng 1 vaì 8.
(a) Âënh nghéa quan hãû jump( case1, case2 ), bàòng caïch sæí duûng luáût âi
cuía quán maî, vaì giaí sæí ràòng case1 luän luän bë raìng buäüc. Vê duû :
?- jump( 1/1, C ).
C = 3/2;
C = 2/3;
No
(b) Âënh nghéa quan hãû mvt_ knight( path ), våïi path laì mäüt danh saïch gäöm
caïc ä biãøu diãùn läü trçnh caïc bæåïc nhaíy håüp lyï cuía quán maî trãn baìn cåì
räùng.
(c) Sæí duûng quan hãû mvt_ knight, viãút mäüt cáu hoíi âãø tçm táút caí caïc läü
trçnh bäún bæåïc nhaíy håüp lyï cuía quán maî, xuáút phaït tæì ä coï toaû âäü 2/1,
âãø âãún biãn bãn phaíi cuía baìn cåì (Y = 8) vaì âãø âãún ä 5/4 sau hai bæåïc
nhaíy.
9. Cho f mäüt tãûp chæïa caïc haûng, haîy âënh nghéa thuí tuûc findterm(Term) âãø
âæa ra maìn hçnh haûng âáöu tiãn cuía f khåïp âæåüc våïi Term ?
10. Cho f mäüt tãûp chæïa caïc haûng, haîy âënh nghéa thuí tuûc findallterm(Term) âãø
âæa ra maìn hçnh táút caí caïc haûng cuía f khåïp âæåüc våïi Term ? Kiãøm tra
tênh cháút biãún Term khäng thãø âæåüc gaïn giaï trë khi thæûc hiãûn tçm kiãúm.
186 Láûp trçnh lägich trong Prolog

11. Haîy måí räüng thuí tuûc del_space âaî âæåüc trçnh baìy trong pháön lyï thuyãút
âãø coï thãø xæí lyï loaûi boí caïc dáúu caïch thæìa nàòm træåïc dáúu pháøy (comma) vaì
chè giæî laûi mäüt dáúu caïch nàòm ngay sau dáúu pháøy.
12. Tæång tæû baìi 3 cho caïc dáúu cháúm cáu khaïc nhæ dáúu cháúm (period), dáúu
cháúm pháøy (semicolon), dáúu cháúm hoíi (question mark), v.v...
13. Âënh nghéa quan hãû firstchar( Atom, Char) cho pheïp kiãøm tra Char coï phaíi
laì kyï tæû âáöu tiãn cuía Atom khäng (Atom bàõt âáöu båíi Char) ?
14. Âënh nghéa thuí tuûc cho pheïp âäøi mäüt danh tæì tiãúng Anh tæì säú êt
(singular) sang säú nhiãöu (plural) âæåüc thæûc hiãûn nhæ sau :
?- plural ( table, X ).
X = tables
Yes
15. AÏp duûng thuí tuûc readsentence âaî âæåüc trçnh baìy trong pháön lyï thuyãút âãø
xáy dæûng thuí tuûc :
?- find( Keyword, Sentence ).
cho pheïp tçm trong tãûp âang âoüc mäüt cáu coï chæïa tæì khoaï Keyword. Cáu
Sentence phaíi åí daûng måïi âæåüc âoüc vaìo chæa xæí lyï, nghéa laì âæåüc biãøu
diãùn båíi mäüt chuäùi kyï tæû, hoàûc båíi mäüt nguyãn tæí.
PHUÛ LUÛC A

Mäü t säú chæång trçnh Prolog


• Yãu cáöu âoüc hiãøu, dæûng laûi thuáût toaïn vaì âaïnh giaï âäü phæïc taûp caïc chæång
trçnh Prolog dæåïi âáy.
• Chaûy chæång trçnh SWI-Prolog ra kãút quaí.

% Thao taïc trãn cáy


tree(X) :-
b_tree(5, b_tree(2, b_tree(8, et, et), b_tree(2, et, et)), b_tree(3, et,
b_tree(9, b_tree(2, et, et), et))).
is_tree(et).
is_tree(X) :-
X=tree(_, Y, Z), is_tree(Z), is_tree(Z).
in_ordre(et).
in_ordre(tree(R, G, D)) :-
in_ordre(G), write(-), write(R), write(-), in_ordre(D).
pre_ordre(et).
pre_ordre(tree(R, G, D)) :-
write(-), write(R), write(-), pre_ordre(G), pre_ordre(D).
post_ordre(et).
post_ordre(tree(R, G, D)) :-
post_ordre(G), post_ordre(D), write(-), write(R), write(-).
root(et).
root(tree(R, G, D), X) :-
X is R.
sort(et).
sort(tree(R, G, D)) :-
RG is root(G, X), RD is root(D, X), R>RG, R<RD, sort(G), sort(D).

is_tree(emptytree).
is_tree(X) :-
X=tree(A, B, C), number(A), is_tree(B), is_tree(C).
187
188 Láûp trçnh lägich trong Prolog

treetest(X) :-
X=(tree(5, tree(2, tree(8, emptytree, emptytree), tree(2, emptytree,
emptytree)), tree(3, emptytree, tree(9, tree(2, emptytree, emptytree),
emptytree)))).
treesort(X) :-
X=(tree(5, tree(3, tree(2, emptytree, emptytree), tree(25, emptytree,
emptytree)), tree(11, tree(8, emptytree, tree(9, emptytree, emptytree)),
tree(13, emptytree, emptytree)))).
affpre(X) :-
X=emptytree.
affpre(X) :-
X=tree(A, B, C), write(A), affpre(B), affpre(C).
affin(X) :-
X=emptytree.
affin(X) :-
X=tree(A, B, C), affin(B), write(A), affin(C).
affpost(X) :-
X=emptytree.
affpost(X) :-
X=tree(A, B, C), affpost(B), affpost(C), write(A).
tree_sort(X) :-
X=emptytree.
tree_sort(X) :-
X=tree(A, B, C), B=emptytree, C=emptytree.
tree_sort(X) :-
X=tree(A, B, C), B=tree(Y, _, _), A>Y, tree_sort(B), C=emptytree.
tree_sort(X) :-
X=tree(A, B, C), B=emptytree, C=tree(Y, _, _), Y>A, tree_sort(C).
tree_sort(X) :-
X=tree(A, B, C), B=tree(Y, _, _), A>Y, tree_sort(B), C=tree(Z, _, _), Z>A,
tree_sort(C).

% Baìi toaïn Thaïp Haì Näüi (Hanoi towers).


towers :-
repeat,
write('Number of rings (or ctl-c to end): '),
read(X),
hanoi(X),
fail.
hanoi(N) :- move(N,left,center,right), !.
move(0,_,_,_) :- !.
Phuû luûc A Mäüt säú chæång trçnh Prolog 189

move(N,A,B,C) :-
M is N-1,
move(M,A,C,B),
inform(A,B),
move(M,C,B,A).

inform(A,B) :-
write([move,disk,from,A,to,B]), nl.

% Taûo baíng (Table).


table :-
create_popup( _,_,_,_ ),
for(0,15,Row),
for(0,15,Colidx),
Attr is Row*16+Colidx,
Col is 5*Colidx,
tmove(Row,Col),
write(Attr),
tmove(Row,Col),
wa(5, Attr),
fail.
table :-
nl,nl,write( $Press any key to continue$ ),
get0_noecho(_),
exit_popup.

for(X, X, X) :- !.
for(Y, X, Y) :- true.
for(X, Y, Z) :- inc(X, X1), for(X1, Y, Z).

:- public misscann/0.
misscann :- solve(start-state(3,3,left), X), pathwrite(X).

solve(Init-state(0,0,right), Init-state(0,0,right)-finish) :- !.
solve(Init-S1, Final) :-
new_state(S1, S2),
not member(S2, Init),
solve(Init-S1-S2, Final).

new_state(state(M1,C1,left), state(M2,C2,right)) :-
move(M, C),
M =< M1,
C =< C1,
M2 is M1-M,
C2 is C1-C,
balanced(M2, C2).

new_state(state(M1,C1,right), state(M2,C2,left)) :-
190 Láûp trçnh lägich trong Prolog

move(M, C),
M2 is M1+M,
C2 is C1+C,
M2 =< 3,
C2 =< 3,
balanced(M2, C2).

balanced(X, X) :- !.
balanced(3, X) :- !.
balanced(0, X).
move(2,0).
move(1,0).
move(1,1).
move(0,1).
move(0,2).
member(X, Y - X) :- !.
member(X, Y - Z) :- member(X,Y).
pathwrite(A-B) :- !,
pathwrite(A),
nl,
!,
pathwrite(B).
pathwrite(X) :- write(X).

% solve/1
% PROLOG interpreter written in PROLOG (so-called vanilla meta-interpreter)
% usage: ?-solve(PrologGoal).
solve(true).
solve((A, B)) :-
solve(A),
solve(B).
solve(A) :-
clause(A,B),
solve(B).

% Vê duû mäüt hãû chuyãn gia


animal(su_tu_bien, [1, 2, 8, 18]).
animal(ca_voi, [1, 2, 4, 9]).
animal(su_tu, [1, 2, 5, 11]).
animal(báo, [1, 2, 5, 10, 17]).
animal(gau, [1, 2, 6, 8, 15, 16, 17]).
animal(huou_cao_co, [1, 5, 7, 10]).
animal(voi, [1, 5, 6, 12, 13, 18]).
animal(con_diec, [3, 7, 8, 15, 18]).
animal(chim_mòng_bien, [3, 8, 14, 15, 18]).
animal(dà_dieu_châu_phi, [7]).
animal(chim_canh_cut, [4, 8, 19]).
Phuû luûc A Mäüt säú chæång trçnh Prolog 191

question(1) :-
write('Con vật này có lông không không ?’),
nl, !, answer(1).
question(2) :-
write(‘Con vâ.t này ăn thịt không ?’),
nl, !, answer(2).
question(3) :-
write(‘Con vâ.t này biết bay không ?’),
nl, !, answer(3).
question(4) :-
write(‘Con vâ.t này có sống trong nước không ?’),
nl, !, answer(4).
question(5) :-
write(‘Con vâ.t này có sống ở Châu Phi không ?’),
nl, !, answer(5).
question(6) :-
write(‘Con vâ.t này có sống ở trong rừng không ?’),
nl, !, answer(6).
question(7) :-
write(‘Con vâ.t này có chân dài không ?’),
nl, !, answer(7).
question(8):-
write(‘Con vâ.t này có ăn cá không ?’),
nl, !, answer(8).
question(9):-
write(‘Con vâ.t này có ăn phù du sinh vật nổi không ?’),
nl, !, answer(9).
question(10):-
write(‘Con vâ.t này có da lông lốm đốm không ?’),
nl, !, answer(10).
question(11):-
write(‘Con vâ.t này có bờm không ?’),
nl, !, answer(11).
question(12):-
write(‘Con vâ.t này có răng nanh hay ngà không ?’),
nl, !, answer(12).
question(13):-
write(‘Con vâ.t này có sừng không ?’),
nl, !, answer(13).
question(14):-
write(‘Con vâ.t này có làm tổ trong núi đá không ?’),
nl, !, answer(14).
question(15):-
write(‘Con vâ.t này có một phần da (lông) màu trắng không ?’),
nl, !, answer(15).
question(16):-
write(‘Con vâ.t này có một phần da (lông) màu nâu không ?’),
nl, !, answer(16).
question(17):-
192 Láûp trçnh lägich trong Prolog

write(‘Con vâ.t này có leo trèo trên cây không ?’),


nl, !, answer(17).
question(18):-
write(‘Con vâ.t này có da (lông) màu xám không ?’),
nl, !, answer(18).
question(19):-
write(‘Con vâ.t này có da (lông) màu trắng và đen không ?’),
nl, !, answer(19).

% Nhận diện con vật


identifier :-
animal(X, Y),
put_questions(Y),
explaining(X, Y),
abolish(discovery, 2).
identifier(X) :-
write(‘Con vật chưa biết.'), nl.

% Hệ chuyên gia đặt câu hỏi hỏi ngược lại người sử dụng
put_questions([]).
put_questions([ X|Y ]) :-
questioner(X),
put_questions(Y).
questioner(X) :-
discovery(X, yes), !.
questioner(X) :-
discovery(X, no), !, fail.
questioner(X) :-
question(X).

% Phân tích câu trả lời


answer(X) :-
read(R),
assert(discovery(X, R)),
R = yes.

explaining(X, Y) :-
write(‘Đây là con :'),
write(X), nl,
write('Bởi vì :'),
nl, explications(Y).

explications([ ]).
explications([ X1|X2 ]) :-
expl(X1), nl,
explications(X2).

expl(1) :-
write(‘Con vâ.t này là loài động vật có vú.').
Phuû luûc A Mäüt säú chæång trçnh Prolog 193

expl(2) :-
write(‘Con vâ.t này là loài động vật ăn thịt.').
expl(3) :-
write(‘Con vâ.t này biết bay.').
expl(4) :-
write('Con vật này sống trong nước.').
expl(5) :-
write(‘Con vâ.t này sống ở Châu Phi.').
expl(6) :-
write(‘Con vâ.t này sống trong rừng.').
expl(7) :-
write(‘Con vâ.t này có chân dài.').
expl(8) :-
write(‘Con vâ.t này ăn cá.').
expl(9) :-
write(‘Con vâ.t này ăn ăn phù du sinh vật nổi.').
expl(10) :-
write(‘Con vâ.t này có da lông lốm đốm.').
expl(11) :-
write(‘Con vâ.t này có bờm.').
PHUÛ LUÛC B

Hæåï n g dáù n sæí duû n g SWI-Prolog


I. Giåïi thiãûu SWI-Prolog
SWI-Prolog thuäüc hoü Prolog Edinburgh do Giaïo sæ Jan Wielemaker xáy
dæûng tæì nàm 1983 taûi Khoa Khoa hoüc Thäng tin Xaî häüi, træåìng Âaûi hoüc
Amsterdam, Haì Lan (Dept. of Social Science Informatics, SWI, University of
Amsterdam, Netherlands). Hiãûn nay, coï thãø taíi miãùn phê pháön mãöm SWI-
Prolog phiãn baín 5.2.11 for Windows tæì âëa chè Web :
http://www.swi-prolog.org/.
SWI-Prolog coï mäüt thæ viãûn vë tæ, vaì taìi liãûu hæåïng dáùn phong phuï. SWI-
Prolog hoaût âäüng theo hãû thäúng âån thãø, coï giao diãûn trao âäøi hai chiãöu linh
hoaût våïi ngän ngæî C. SWI-Prolog laì mäüt ngän ngæî sæ phaûm, do váûy bë haûn
chãú êt nhiãöu vãö täúc âäü biãn dëch chæång trçnh.
SWI-Prolog hoaût âäüng trong mäi træåìng âäö hoaû XPCE âënh hæåïng âäúi
tæåüng (GUI) X-window. SWI-Prolog tæång âäúi dãù sæí duûng nhåì khai thaïc caïc
âàûc træng tæång taïc âäö hoaû. SWI-Prolog coï caïc phiãn baín cho caïc maïy chaûy
Linux/Unix, Macintosh. Khi taíi SWI-Prolog, NSD coï thãø taíi thãm taìi liãûu
hæåïng dáùn sæí duûng.
Sau khi caìi âàût phiãn baín SWI-Prolog 5.2.11 for Windows, räöi khåíi âäüng
trçnh plwin.exe, cæía säø laìm viãûc SWI-Prolog hiãûn ra nhæ hình dæåïi âáy.

SWI-Prolog laìm viãûc theo chãú âäü tæång taïc (interpreter mode) (xem hçnh).
Dáúu nhàõc lãûnh SWI-Prolog laì mäüt càûp dáúu cháúm hoíi vaì dáúu gaûch ngang (dáúu
træì), âæåüc liãût kã thæï tæû 1, 2, 3... âãø theo doîi quaï trçnh laìm viãûc cuía NSD,
theo sau laì con troí maìn hçnh (dáúu cheìn) nháúp nhaïy :

1 ?- „
Âãø ra khoíi SWI-Prolog, duìng lãûnh File/ Exit, hoàûc duìng vë tæì halt :
?- halt.

194
Phuû luûc B Hæåïng dáùn sæí duûng SWI-Prolog 195

Hçnh I.1. Cæía säø laìm viãûc cuía SWI-Prolog.

II. Laìm viãûc våïi SWI-Prolog


II.1. Âàût cáu hoíi
Sau khi mäüt chæång trçnh Prolog âæåüc biãn dëch hoàûc âæåüc taíi vaìo bäü nhåï,
NSD coï thãø âàût cáu hoíi truy váún (kãút thuïc båíi mäüt dáúu cháúm). Tuyì theo cáu
hoíi (âêch phaíi xoaï), Prolog traí låìi âuïng (Yes) hoàûc sai (No) vaì keìm theo kãút
quaí X = <value> nãúu trong âêch coï chæïa biãún X naìo âoï. Trong træåìng håüp coï
nhiãöu cáu traí låìi, ngay sau kãút quaí traí låìi âáöu tiãn, NSD coï thãø âàût mäüt dáúu
cháúm pháøy ; (semi-colon) nãúu muäún tiãúp tuûc yãu cáöu Prolog âæa ra caïc cáu
traí låìi khaïc. Tiãúp tuûc quaï trçnh naìy, Prolog láön læåüt âæa ra caïc kãút quaí khaïc
nhau cho âãún khi, hoàûc Prolog traí låìi No, thç coï nghéa laì khäng coìn cáu traí
låìi naìo næîa, hoàûc Yes, nãúu NSD muäún dæìng laûi bàòng caïch goî Enter (↵). NSD
coï thãø nháûn âæåüc thäng baïo läùi nãúu cáu hoíi coï váún âãö :
196 Láûp trçnh lägich trong Prolog

ERROR: Undefined procedure <... /...> % NSD âaî goî sai tãn thuí tuûc
hoàûc :
ERROR: Syntax error: Operator expected % NSD âaî goî sai biãøu thæïc, v.v...
II.2. Chaûy trçnh demo
Sau âáy laì vê duû chaûy chæång trçnh demo likes.pl cuía SWI-Prolog. Näüi
dung tãûp likes.pl nhæ sau :
likes(sam, A) :-
indian(A),
mild(A).
likes(sam, A) :-
chinese(A).
likes(sam, A) :-
italian(A).
likes(sam, chips).
italian(pizza).
italian(spaghetti).
chinese(chow_mein).
chinese(chop_suey).
chinese(sweet_and_sour).
mild(dahl).
mild(tandoori).
mild(kurma).
indian(curry).
indian(dahl).
indian(tandoori).
indian(kurma).
NSD naûp chæång trçnh vaìo bäü nhåï båíi lãûnh sau :
?- [swi('demo/likes')].
% swi('demo/likes') compiled 0.00 sec, 2, 340 bytes
Yes
Sau khi tãûp likes.pl âæåüc taíi vaìo bäü nhåï, NSD âàût caïc cáu hoíi vaì nháûn
âæåüc kãút quaí nhæ sau :
?- like(X, Y).
Correct to: likes(X, Y)? Yes
X = sam
Y = dahl ;
X = sam
Y = tandoori ;
Phuû luûc B Hæåïng dáùn sæí duûng SWI-Prolog 197

...
Yes % NSD âaî goî Enter vaì váùn coìn cáu traí låìi.
?-
II.3. Chaûy trçnh demo XPCE
SWI-Prolog âæåüc trang bë chæïc nàng láûp trçnh hæåïng âäúi tæåüng taûo giao
diãûn âäö hoaû, âæåüc goüi laì XPCE, coï maî nguäön tæång thêch våïi Unix/X11 vaì
Wçndows.
NSD coï thãø thæûc hiãûn caïc chæång trçnh demo XPCE bàòng caïch goî :
?- [swi( 'xpce/prolog/demo/pce_demo')].
% contrib(contrib) compiled into pce_contrib 0.02 sec, 1,260 bytes
% swi('xpce/prolog/demo/pce_demo') compiled into pce_demo 0.02 sec,
11,408 bytes
Yes
?- pcedemo.
Yes
Mäüt cæía säø hiãûn ra nhæ sau :

Hçnh II.1. Caïc chæång trçnh demo XPCE cuía SWI-Prolog.

NSD choün xem mäüt troì chåi bàòng caïch læûa tãn troì chåi räöi Open. Sau âoï,
nhàõp chuäüt taûi nuït Quit âãø kãút thuïc chæång trçnh. Vê duû troì chåi Rubiks Cube
nhæ hçnh dæåïi âáy :
198 Láûp trçnh lägich trong Prolog

Hçnh II.2. Trçnh demo XPCE Rubiks Cube cuía SWI-Prolog.

II.4. Caïc lãûnh âån (Menu commands)


Cæía säø laìm viãûc SWI-Prolog gäöm mäüt säú lãûnh âån chuí yãúu nhæ sau :
File/consult...
Tæång tæû lãûnh consult(File) duìng âãø naûp tãûp chæång trçnh File vaìo bäü nhåï.
File/Reload modified files
Duìng âãø naûp laûi (reloads) mäüt tãûp chæång trçnh âaî bë thay âäøi vaìo bäü nhåï.
Thæåìng âæåüc sæí duûng sau khi âaî soaûn thaío trãn chæång trçnh. coï thãø sæí
duûng lãûnh make.
File/Navigator ...
Måí cæía säø tæång tæû explorer cuía Windows âãø tçm kiãúm tãûp hoàûc vë tæì
Prolog trong caïc thæ muûc, äø âéa. ..
Phuû luûc B Hæåïng dáùn sæí duûng SWI-Prolog 199

Hçnh II.Cæía säø Navigator.

Settings/Font ... Duìng âãø thay âäøi phäng chæî trong giao diãûn SWI-Prolog.
Settings/User init file ...
Soaûn thaío tãûp cáúu hçnh pl.ini chæïa caïc thäng tin caìi âàût hãû thäúng vaì chuï
thêch.
Settings/Stack sizes ...
Cho pheïp âënh nghéa laûi kêch thæåïc khäng gian laìm viãûc cuía caïc danh
saïch âáøy xuäúng (stack sizes).

Hçnh II.3 Âënh nghéa kêch thæåïc danh saïch âáøy xuäúng
Run/Interrupt
Ngàõt mäüt tiãún trçnh Prolog (Prolog process) coï thãø sæí duûng täø håüp phêm
Control-C coï cuìng hiãûu quaí tæång tæû. Luïc naìy, xuáút hiãûn âäúi thoaûi :
Action (h for help) ? Options:
a: abort b: break
c: continue e: exit
200 Láûp trçnh lägich trong Prolog

g: goals t: trace
h (?): help
Action (h for help) ? abort
ERROR: Execution Aborted
% Execution Aborted
?-
Run/New thread
Taûo mäüt cæía säø laìm viãûc måïi âãø thæûc hiãûn chæång trçnh. Trong cæía säø måïi
naìy coï thãø duìng chung chæång trçnh vaì dæî liãûu âaî coï màût trong cæía säø laìm
viãûc chênh.
Debug/Edit spy points ...
Soaûn thaío caïc âiãøm ngàõt trong caïc vë tæì.
Help Tçm âoüc caïc näüi dung hæåïng dáùn sæí duûng SWI-Prolog khaïc nhau.

II.5. Soaûn thaío chæång trçnh


NSD coï thãø sæí duûng mäüt hãû soaûn thaío vàn baín báút kyì cuía Windows nhæ
NotePad, NCeditor... âãø soaûn thaío chæång trçnh Prolog, læu cáút lãn âéa, sau
âoï taíi vaìo mäi træåìng SWI-Prolog âãø chaûy nhåì lãûnh :
?- consult( <file_name>).
hoàûc :
?- [ <file_name> ].
Våïi <file_name> laì tãn tãûp chæång trçnh (khäng cáön ghi pháön måí räüng .pl.
Coï thãø chè âënh âæåìng dáùn thæ muûc âãún tãn tãn tãûp. Chuï yï dáúu cháúm hoíi ?-
âàût træåïc mäùi cáu lãûnh laì dáúu nhàõc cuía SWI-Prolog.
Vê duû naûp chæång trçnh baìi toaïn 8 Quán Háûu (xem pháön trçnh baìy lyï
thuyãút) :
?- [myex5].
% myex5 compiled 0.00 sec, 2,020 bytes
Yes
?- solution( 8, S ). % Tçm mäüt låìi giaíi cho baìi toaïn 8 Quán Háûu
S = [1, 7, 4, 6, 8, 2, 5, 3] % Vë trê Quán Háûu trãn caïc cäüt.
Yes
Khi âaî naûp chæång trçnh Prolog vaìo bäü nhåï, duìng lãûnh :
?- Listing.
Phuû luûc B Hæåïng dáùn sæí duûng SWI-Prolog 201

âãø liãût kã caïc doìng lãûnh trong cæía säø laìm viãûc chênh cuía Prolog.

Hçnh II.4. Cæía säø soaûn thaío vàn baín PceEmacs cuía SWI-Prolog.
SWI-Prolog coï sàôn mäüt hãû soaûn thaío PceEmacs ráút thuáûn tiãûn âãø soaûn
thaío vaì thæûc hiãûn chæång trçnh. Goî vaìo doìng lãûnh :
?- emacs.
âãø måí cæía säø soaûn thaío vàn baín nhiãöu chæïc nàng (scratch).

III. Mäüt säú lãûnh SWI-Prolog thäng duûng


Sau âáy laì mäüt säú vë tæì âiãöu khiãøn mäi træåìng thäng duûng cuía SWI-
Prolog.
consult(+File)
Naûp tãûp chæång trçnh vaìo bäü nhåï. Chuï yï sæí duûng dáúu phán caïch thæ muûc
laì /. Vê duû :
% Naûp tãûp likes.pl tæì thæ muûc laìm viãûc (xem pwd) vaìo bäü nhåï.
?- consult(likes).
% Naûp tãûp likes.pl sæí duûng âæåìng dáùn âáöy âuí - tuyãût âäúi (absolute path).
?- ['C:/Program Files/pl/demo/likes'] .
% Sæí duûng âæåìng dáùn kiãøu Windows (Windows-style path-name).
?- ['C:\\Program Files\\pl\\demo\\likes'].
202 Láûp trçnh lägich trong Prolog

pwd
Âæa ra thæ muûc laìm viãûc (working directory hay folder) cuía SWI-Prolog.
ls
Liãût kã danh saïch caïc tãûp trong thæ muûc hiãûn haình.
edit
Nãúu Prolog âæåüc khåíi âäüng båíi mäüt tãûp .pl tæì trong Windows Explorer,
thç chaûy trçnh soaûn thaío màûc nhiãn, chàóng haûn Windows Notepad, âãø soaûn
thaío tãûp naìy. Coï thãø sæí duûng lãûnh âån File/Edit...
?- edit.
% Waiting for editor ...
...
Yes % Sau khi NSD kãút thuïc soaûn thaío
edit(+File)
Saûn thaío tãûp hay âån thãø chæång trçnh âaî coï màût trãn âéa.
?- edit(myex). % Måí Notepad âãø soaûn thaío tãûp myex.pl
% Waiting for editor ... % hiãûn coï åí thæ muûc hiãûn haình
...
Yes % Sau khi NSD kãút thuïc soaûn thaío
make
Naûp tãûp chæång trçnh vaìo bäü nhåï sau khi âaî thæûc hiãûn mäüt säú thay âäøi.
trace
Chaûy trçnh duyãût tçm sæía läùi debugger.
apropos(+Keyword)
Tçm vë tæì coï chæïa tæì khoaï Keyword.
help(+Spec)
Måí cæía säø hæåïng dáùn vãö Spec, laì tãn mäüt vë tæì hoàûc tãn mäüt haìm C.
Taì i liãû u tham khaí o
1. I. Bratko (L. Ricard dịch), Programmation en Prolog pour l’ intelligence artificielle,
InterÉditions, Paris, 1988.
2. I. Bratko, Programming for Artificial Intelligence, AddisonWesley, 1987.
3. K.L. Clavle, S.A. Tarnlound. Logic Programming. Accademic Press 1983.
4. G. Falquet. Prolog et programmation logique. Notes de cours, Université de Genève, 2002.
5. H. Farrenry, M. Ghallab. Éléments d’intelligence artificielle, Hermes, Paris-Londre-
Lausanne 1990.
6. Bạch Hưng Khang, Hoàng Kiếm. Trí tuệ nhân tạo : các phương pháp và ứng dụng. Nhà
Xuất bản Khoa học Kỹ thuật, 1989.
7. J.W. Leoyd. Foundations of Logic Programming, Springer-Verlag, 1984.
8. P. Nugues. La Programmation logique et le langage Prolog. Notes de cours, ISMRA, 2002.
9. D.Teller. Partiel de Prolog. Notes de cours, École Centrale de Lyons, 2001.
10. Nguyễn Thanh Thuỷ. Trí tuệ nhân tạo : các phương pháp giải quyết vấn đề và
kỹ thuật xử lý tri thức. Nhà Xuất bản Giáo dục, 1986.
11. A.Voronkov, Logic Programming and automated reasoning, Springer-Verlag, 1993.
12. Các tài liệu về Prolog và bài tập Prolog trên Internet :
ftp://ftp.umh.ac.be/pub/ftp_sgl/LangagesProgrammation/LP-exercProlog.pdf
http://www.etse.urv.es/EngInf/assig/iai/Laboratoris/Prolog/
http://membres.lycos.fr/epl2000/2eme/POO/
SPV_Prolog/1_Prolog_leLangage/

203

You might also like