Professional Documents
Culture Documents
LyThuyetTinhToan - Phan Huy Khanh
LyThuyetTinhToan - Phan Huy Khanh
GIÁO TRÌNH
LÝ THUYẾT
TÍNH TOÁN
−
VI. TỒN TẠI CÁC HÀM KHÔNG LÀ T TÍNH ĐƯỢC ............................................................ 55
người ta sắp xếp các câu theo một thứ tự phân cấp (hierechical order), đầu tiên là
theo độ dài câu, sau đó theo thứ tự từ vựng (lexicography), hay thứ tự ABC.
Ví dụ :
Cho S = {a, b, c}, với giả thiết thứ tự phân cấp của các ký tự là a < b < c, ta
có thể đánh số các câu của S* (kể cả câu rỗng e) bắt đầu từ 1 trở đi như sau :
e1
a2 b3 c4
aa 5 ab 6 ac 7 ba 8 bb 9 bc 10 ca 11 cb 12 cc 13
Các tập hợp này tạo thành các ngôn ngữ (language). Hai tập hợp đầu là bù
nhau nếu với mọi dữ liệu vào, máy đều cho một kết quả. Người ta gọi đó là
máy đoán nhận (recognition machine) câu.
2. Nếu kết quả là một dãy hữu hạn các ký tự, ta nhận được một câu trên một
bảng chữ G nào đó.
Cho S là bảng chữ vào, máy xác định một hàm f từ S* vào G*, ta viết :
f : S* → G *
nghĩa là với một câu vào w ∈ S*, f(w) ∈ G*. Người ta nói máy thực hiện
hàm f. Nếu với mọi câu vào w ∈ S*, máy đều cho một kết quả f(w) ∈ G*,
thì f được gọi là hàm toàn phần (partial function). Người ta gọi đó là máy
tính toán (computation machine) hay máy tính.
Chú ý rằng kiểu máy thứ nhất (máy đoán nhận) mà chúng ta vừa phân biệt
thực ra chỉ là một trường hợp đặc biệt của kiểu máy thứ hai (máy tính).
3. Nếu kết quả là một dãy vô hạn các ký tự và bảng chữ đang sử dụng chỉ có
tối thiểu hai ký tự, trong đó có một dấu phân cách (separator) #, thì người ta
nhận được kết quả là một dãy liên tiếp các câu phân cách nhau bởi dấu #,
tạo thành một ngôn ngữ. Người ta gọi ngôn ngữ này là liệt kê được
(enumerated) bởi máy.
Việc biểu diễn tường minh các dữ liệu là một thành phần của bài toán. Điều
này đóng vai trò đặc biệt quan trọng khi người ta quan tâm đến độ phức tạp
(complexity) của một bài toán. Mỗi dữ liệu sẽ tạo thành một trường hợp cá biệt
của bài toán, được biểu diễn bởi một câu trên một bảng chữ hữu hạn đã cho.
Với mỗi bài toán P được hợp thành từ một biểu diễn các phần tử của một tập
hợp và từ một phát biểu liên quan đến các phần tử này, người ta thường kết hợp
bài toán P với một ngôn ngữ, gọi là ngôn ngữ đặc trưng (characteristic language)
của bài toán, được hợp thành từ tập hợp các câu biểu diễn một phần tử của tập
hợp để từ đó, kết quả của bài toán là câu trả lời đúng. Người ta ký hiệu LP là
ngôn ngữ đặc trưng của bài toán P.
Cho trước một bài toán P, bài toán ngược lại CP là bài toán nhận được từ P
bằng cách giữ nguyên cách biểu diễn các dữ liệu nhưng riêng câu hỏi thì đặt
ngược lại. Ví dụ, bài toán ngược với bài toán 1 sẽ là :
Bài toán 1’ :
Dữ liệu : Cho một số nguyên viết trong hệ 10.
Câu hỏi : Số nguyên này không phải là một số nguyên tố ?
Từ đó, lời giải một bài toán đưa đến sự nhận biết của một ngôn ngữ : ngôn
ngữ kết hợp với bài toán này. Người ta đưa ra định nghĩa hình thức sau đây :
Định nghĩa 1.2 :
Một máy giải (solve) một bài toán P nếu và chỉ nếu với mọi câu f biểu diễn
một phần tử của tập hợp liên quan đến bài toán này, máy cho phép xác định,
trong một khoảng thời gian hữu hạn, nếu câu này thuộc về LP hay LCP.
Người ta phân lớp các bài toán tùy theo độ khó (difficulty) để đưa ra câu trả
lời từ dữ liệu vào đã cho.
Một bài toán là tầm thường (trivial) nếu LP = ∅ hoặc nếu LCP = ∅.
Thật vậy, trong trường hợp này, không cần thiết biết dữ liệu đưa vào để đưa ra
câu trả lời. Chú ý rằng, những gì là tầm thường, đó là việc đưa ra câu trả lời,
nhưng có thể rất khó để chứng minh rằng bài toán là tầm thường theo nghĩa này.
Ví dụ, bài toán 2 là tầm thường.
Các bài toán 1 và 3 có cùng câu hỏi, nhưng bài toán 3 giải quyết rất dễ dàng :
chỉ cần đọc qua dữ liệu vào, người ta có thể đưa ra kết quả, tuy nhiên trong bài
toán 1 thì cần phải xử lý dữ liệu vào. Bài toán 4 phức tạp hơn : người ta chưa biết
phương pháp nào hoạt động một cách đơn định (deterministic) tiêu tốn một lượng
thời gian đa thức (polynomial times) để giải quyết vấn đề đặt ra.
Đối với bài toán 5 thì tính phức tạp còn lớn hơn nữa : người ta biết rằng mọi
phương pháp đều hoạt động theo thời gian tối thiểu là lũy thừa. Cuối cùng bài
toán 6 không thể giải được theo nghĩa đã đưa ra. Bài toán này được gọi là bài
toán tương ứng Post (Post’s correspondence problem).
Nhập môn lý thuyết tính toán 7
Bài tập
1) Chứng minh rằng một tập hợp E là hữu hạn hay vô hạn đếm được nếu tồn tại
một đơn ánh từ E vào N. Tương tự, nếu tồn tại một toàn ánh (surjection) từ Ν
vào E.
2) Chứng minh rằng tích Đê-cac của hai tập hợp vô hạn đếm được cũng là một
tập hợp vô hạn đếm được.
3) Chứng minh các tập hợp sau đây là vô hạn đếm được : N×N, Q, tập hợp Ν*
gồm các dãy số nguyên, S*, S*×G*, S*×N, tập hợp (S*)* gồm các dãy các
câu. Thể hiện các song ánh (bijection) giữa N và mỗi một tập hợp vừa nêu.
4) Cho S là một bảng chữ kích thước (bản số) n. Với mọi câu w∈S*, ký hiệu |w|
là độ dài của w và m(w) là số thứ tự của w trong thứ tự phân cấp đã cho. Hãy
tìm cách tính m(w) khi biết w.
5) Chứng minh rằng NN không phải là vô hạn đếm được. Tập hợp các chương
trình Pascal có phải là vô hạn đếm được hay không ? Tập hợp các hàm f: N →
N tính được nhờ một chương trình Psacal có là vô hạn đếm được hay không ?
Từ đó suy ra rằng tồn tại các hàm từ N vào N không là vô hạn đếm được nhờ
một chương trình Pascal.
6) Viết một chương trình để liệt kê :
− các cặp số nguyên
− các dãy hữu hạn các số nguyên
− các câu trên một bảng chữ hữu hạn (chẳng hạn S={a, b, c})
− các cặp câu
− các dãy hữu hạn các câu.
CHƯƠNG 2
1 R0 Thanh tổng
Chương trình
2 R1
... ... ... ... Các thanh ghi
j Ri
... ... ... ...
p Rn
i
Thanh
đếm lệnh
y1 y2 y3 ... Băng ra
Theo nguyên tắc địa chỉ, phần toán hạng là địa chỉ (address) của toán hạng
tham gia phép toán chỉ định bởi phần mã lệnh. Toán hạng có thể là một trong ba
kiểu sau :
Kiểu địa chỉ Ý nghĩa
Số nguyên n Chỉ nội dung của thanh ghi thứ n (Rn).
A: n (A = Absolute) toán hạng chính là số nguyên n đó.
I: n (I = Indirection) toán hạng là nội dung của thanh ghi có số thứ
tự là nội dung của thanh ghi Rn. Đây là kiểu lệnh gián tiếp.
Nếu lệnh là một lệnh nhảy thì địa chỉ chính là số thứ tự của lệnh trong chương
trình. Các lệnh trên đây của máy RAM điển hình cho các lệnh của ngôn ngữ
assembler. Tuy nhiên ở đây vắng mặt các lệnh xử lý ký tự và các lệnh logic nhằm
đơn giản cách trình bày.
Thứ tự thực hiện các lệnh của chương trình là tuần tự (on sequence), bắt đầu
từ lệnh đầu tiên (có nhãn 1). Ngoại lệ duy nhất là khi gặp lệnh nhảy (hay chuyển
điều khiển) thì lệnh tiếp theo được thực hiện có nhãn chỉ định bởi lệnh nhảy này.
Nguyên tắc thực hiện như sau : OC luôn luôn chứa nhãn của lệnh sẽ được
thực hiện, lúc đầu nội dung OC là 1. Sau khi thực hiện lệnh, nội dung OC được
tự động tăng thêm 1 (increment) nếu như lệnh vừa thực hiện không là lệnh nhảy.
Nếu như lệnh vừa thực hiện là lệnh nhảy thì nội dung của OC lấy nhãn là phần
địa chỉ của lệnh nhảy này.
Sau đây sử dụng một số quy ước để giải thích cách thực hiện lệnh.
← dấu gán ; quy ước số nguyên i nằm bên trái dấu gán chỉ thanh ghi
thứ i là Ri, số nguyên i nằm bên phải dấu gán chỉ giá trị chính là số
nguyên i đó.
<i> Chỉ nội dung của thanh ghi Ri.
<<i>> Chỉ nội dung của thanh ghi có số thứ tự được chứa trong thanh ghi
Ri đối với kiểu lệnh gián tiếp.
ACC Chỉ thanh ghi R0.
CO Chỉ thanh đếm lệnh.
<CO> Nội dung của CO.
Sau đây là bảng các lệnh RAM và ý nghĩa sử dụng của chúng.
12 Lý thuyết tính toán
Lệnh Ý nghĩa
LOAD
n ACC ← <n>
LOAD
A: n ACC ← giá trị n
LOAD
I: n ACC ← <<n>>
STORE
n n ← <ACC>
STORE
I: n <n> ← <ACC>
INCR
n n ← <n> + 1
DECR
n n ← <n> - 1
ADD
n ACC ← <ACC> + <n>
SUB
n ACC ← <ACC> − <n>
MULT
n ACC ← <ACC> × <n>
DIV
n ACC ← <ACC> / <n>
JUMP
n CO ← n
JGTZ
n CO ← n nếu <ACC> ≥ 0
JZERO
n CO ← n nếu <ACC> = 0
Cả hai trường hợp trên, nếu không thỏa mãn, CO ← <CO> + 1
HALT
Dừng máy
READ n
n ← số nguyên trong ô dưới đầu đọc của băng,
đầu đọc dịch một ô qua phải
WRITE n
Nội dung <n> được ghi vào ô dưới đầu ghi,
đầu ghi dịch qua phải một ô.
Ví dụ 2.1 : Chương trình RAM sau đây đánh giá trị n!
READ 0 đọc một giá nguyên n vào ACC
JZERO 10 nếu n = 0, nhảy đến nhãn 10,
nếu không, thực hiện lệnh tiếp theo
STORE 1 R1 ← <ACC>
4: STORE 2 R2 ← <ACC>
DECR 1 R1 ← < R1> − 1
LOAD 1 ACC ← <R1>
JZERO 12 nếu <ACC> = 0 nhảy đến 12
MULT 2 ACC ← <ACC> * <R2>
JUMP 4 CO ← 4
10: LOAD A: 1 ACC ← 1
STORE 2 R2 ← <ACC>
12 : WRITE 2 ghi ra <R2>
HALT Dừng máy
Mô hình các máy RAM 13
Dạng hàm f : S* → S*
Giả sử chương trình P luôn đọc được từ băng vào n số nguyên x1, x2, ..., xn và
ghi lên băng ra không quá một số nguyên y ở ô đầu tiên, khi đó ta nói P tính hàm
f (x1, x2, ..., xn) = y.
Dạng ngôn ngữ L ⊆ S*
Giả sử trên băng vào có câu w = a1a2 ... an với ai ở ô thứ i, i = 1.. n, còn ô thứ
n+1 chứa # là ký tự kết thúc dãy. Ta nói w được thừa nhận bởi chương trình
RAM nếu nó đọc được hết w, kể cả ký tự #, sau đó viết lên ô đầu tiên của băng ra
một ký tự kết quả và dừng.
Ta nói máy RAM thừa nhận một ngôn ngữ L đã cho nếu thừa nhận mọi câu
w∈L. Nếu w∉L thì máy RAM có thể không đọc hết w, ghi ký tự kết thúc lên
băng ra, hoặc bị hóc (crash), hoặc không bao giờ dừng.
Sự khác nhau cơ bản giữa mô hình máy RAM vừa mô tả ở trên và các máy
tinh điện tử hiện nay là ở chỗ :
1) Ta đã giả thiết có thể sử dụng một số lớn tùy ý các thanh ghi, tuy nhiên
trong thực tế điều này rất khó thực hiện. Tương tự, ta đã giả thiết có thể đặt
một số nguyên lớn tùy ý vào một thanh ghi nào đó, hoặc vào một ô nào đó
trên băng vào, hoặc trên băng ra. Nhưng điều này cũng rất khó thực hiện
trong thực tiễn.
2) Ta đã giả thiết rằng chương trình có sẵn trong bộ nhớ RAM chỉ có thể đọc
(không thể bị thay đổi khi chạy chương trình), khác với các bộ nhớ kiểu
thanh ghi. Điều này cũng không xảy ra với các máy tính thông dụng.
Sự khác nhau chi tiết như sau :
3) Các lệnh sơ cấp được chọn hạn chế hơn so với các ngôn ngữ assembler
Tuy nhiên, người ta có thể nói rằng vẫn không làm mất tính tổng quát nếu
giảm đáng kể tập hợp các lệnh sơ cấp.
4) Các dữ liệu đưa vào không phải dưới dạng các số nguyên được đọc toàn bộ
một lần trong một ô, mà dưới dạng một dãy ký tự (một dãy các chữ số),
tương tự như vậy đối với các kết quả ra.
Ta hãy xem làm cách nào để giải quyết vấn đề do 4) đặt ra : Trong các máy
tính, các số nguyên thường được biểu diễn theo hai cách phân biệt là biểu diễn
thập phân, hoặc biểu diễn nhị phân. Cách biểu diễn nhị phân có lợi thế hơn vì chỉ
sử dụng hai chữ số. Máy tính sẽ chuyển đổi chuỗi ký tự biểu diễn số nguyên
thành biểu diễn nhị phân để đặt trong các thanh ghi, sau đó chuyển đổi kết quả
đang ở dạng biểu diễn nhị phân của số nguyên thành chuỗi ký tự trên băng ra.
Điểm 1) trên đây có nghĩa : trong mọi trường hợp, kích thước của bài toán cần
giải là đủ bé để bộ nhớ máy tính có thể chứa hết ở dạng nhị phân trong các đơn vị
nhớ, hay từ nhớ (memory word). Chú ý rằng nếu chỉ làm việc với cách biểu diễn
số nguyên bởi chuỗi các chữ số thì không còn giả thiết số lớn tùy ý nữa.
Mô hình các máy RAM 15
Cuối cùng, sự khác nhau ở điếm (2) đưa đến việc xây dựng một mô hình
tương tự mô hình RAM, nhưng chương trình được đặt trong các thanh ghi (và do
vậy có thể bị thay đổi), được gọi là mô hình các máy RASP (Random Access
with Stored Program). Sự khác nhau cơ bản với các máy RAM là vùng nhớ lưu
giữ chương trình của RASP hoàn toàn không khác gì so với các vùng nhớ khác.
Máy RASP
Để thuận tiện cách trình bày, ta quy ước rằng mỗi lệnh RASP chiếm chỗ hai
thanh ghi liên tiếp nhau : thanh ghi đầu chứa trường toán hạng, thanh ghi thứ hai
chứa trường địa chỉ của lệnh.
R0 Thanh tổng
R1
R2
Chương trình
Rp
i
Thanh đếm lệnh
... Các thanh ghi khác
y1 y2 y3 ... Băng ra
Ví dụ 2.4 : Dịch chuyển một trình RASP có một lệnh dạng gián tiếp :
⎧⎪1 + a nãúu a ≤ b
Tính in ⎨
⎪⎩1 + b nãúu a > b
Chương trình RASP xuất phát P : sau khi dịch chuyển thành P’ :
2 READ R27 ← a READ
3 27 37
4 READ R27 ← b READ
5 28 38
6 LOAD A: ACC ← <R27> LOAD A:
7 27 37
8 STORE R26 ← <ACC> STORE
9 26 36 Phần này là
10 LOAD ACC ← <R28> LOAD dịch chuyển của P
11 28 38 với ánh xạ :
12 SUB I(r) = r+p’-p = r+10
ACC ← <ACC> - <R27> SUB
13 27 37
14 JGTZ JGTZ
OC ← 18, if <ACC> > 0
15 18 18
16 INCR R26 ← < R26> + 1 INCR
17 26 36
18 LOAD A: LOAD A:
ACC ← 1
19 1 1
20 ADD I: ACC ← <ACC> + <<R26>> STORE R1 ← <ACC>
21 26 1
22 WRITE LOAD ACC ← <R36>
In ra <ACC>
23 0 36
24 HALT ADD A: ACC ← <ACC> +
Dừng
p 25 0 10 10
P+1 26 27 / 28 Nội dung 27, hoặc 28 STORE R31 ← <ACC> : số
27 a Chứa giá trị a 31 x
q 28 b Chứa giá trị b LOAD ACC ← <R1>
29 1
30 ADD ACC←<ACC> +
Nội dung thay đổi : số x <Rx>
31 0
→
32 WRITE
33 0
34 HALT
P’ 35 0
P’+1 36 37 / 38 Nội dung 37, hoặc 38
37 a Chứa giá trị a
q +P’-p 38 b Chứa giá trị b
Hình 2.3. Trình P’ bị thay đổi khi thực hiện
Mô hình các máy RAM 19
198 7 ~ 198 × 28 + 7
Từ đó, người ta có thể thu hẹp về một mô hình tính toán, gọi là mô hình RAM
thô sơ, chỉ có tập hợp các lệnh tối thiểu sau :
Lệnh Ý nghĩa
I <n> Tăng thêm 1 nội dung của thanh ghi n
D <n> Giảm bớt 1 nội dung của thanh ghi n
Z <n> Đặt nội dung của thanh ghi n về 0
S <n, m> Hoán đổi nội dung các thanh ghi n và m
J <n> (i, j) Nếu nội dung của thanh ghi n là 0, nhảy đến lệnh có nhãn i,
nếu không nhảy đến lệnh có nhãn j
HALT Dừng máy
Với tập hợp các lệnh trên, chương trình cũng là một dãy lệnh có mang nhãn.
Nếu <n> chỉ định nội dung của thanh ghi n, thì <<n>> chỉ định nội dung của
thanh ghi có số thứ tự là <n>.
Ví dụ 2.5 :
1: J <2> (5, 2)
2: I <1>
3: D <2>
4: J <3> (1, 1)
5: HALT
Nếu các thanh ghi 1 và 2 chứa lần lượt các số nguyên n và p, thì máy dừng lại
khi hai thanh ghi này chứa lần lượt n + p và 0.
22 Lý thuyết tính toán
− Tăng nội dung thanh ghi R2 lên 1 để R2 chứa địa chỉ của thanh ghi đầu tiên
trong hai thanh ghi chứa lệnh tiếp theo cần mô phỏng :
INCR 2
− Quay lại từ đầu vòng lặp bởi lệnh nhảy :
JUMP loop
Tương tự, từ nhãn t, thực hiện mô phỏng phép toán nhảy dương JGTZ :
− Kiểm tra nội dung thanh tổng của RASP, nếu dương thì nhảy :
LOAD 3
JGTZ lab
− Nếu kết quả âm, tăng nội dung của R2 lên 2 để R2 chứa địa chỉ của thanh
ghi đầu tiên trong hai thanh ghi chứa lệnh tiếp theo cần mô phỏng và quay
lại đầu vòng lặp :
INCR 2
INCR 2
JUMPloop
− Nếu kết quả dương, từ nhãn lab, tăng nội dung thanh ghi R2 lên 1 để R2
chứa địa chỉ của thanh ghi chứa toán hạng :
lab: INCR 2
− Gán địa chỉ này cho thanh ghi R1 :
LOAD I: 2
STORE 1
− Lấy địa chỉ của lệnh nhảy điều kiện :
LOAD I: 1
− Thay đổi sao cho thanh ghi R2 mô phỏng thanh đếm lệnh OC của RASP,
và quay lại đầu vòng lặp :
STORE 2
JUMPloop
Như vậy mỗi phép toán sơ cấp của RASP được mô phỏng bởi một dãy các lệnh
lặp của máy RAM. Máy RAM vừa mô phỏng có dữ liệu là chương trình P của một
máy RASP bất kỳ, theo sau là một dữ liệu D cho chương trình P. Máy RAM có kết
quả là kết quả của P trên dữ liệu D. Máy RAM mô phỏng hoạt động của mọi máy
RASP.
Một cách tương tự, người ta có thể xây dựng một máy RAM mô phỏng hoạt
động của tất cả máy RAM. Một máy RAM dựa trên mô hình tính toán mô phỏng
hoạt động của tất cả các phần tử của mô hình như vừa xét được gọi là một máy
RAM vạn năng (universal).
24 Lý thuyết tính toán
Bài tập
1. Viết chương trình của một máy RAM tính nn với số nguyên n cho trước.
2. Viết chương trình của một máy RASP tính giá trị bình quân nguyên của dãy n
số nguyên cho trước, với n lẻ.
3. Viết chương trình của một máy RASP không sử dụng kiểu gián tiếp để tính
giống bài 2.
4. Viết chương trình của một máy RAM thô sơ tính :
a. Phần dư của phép chia m cho n, với m và n cho trước.
b. Số nguyên tố thứ n, với n cho trước
5. Chứng tỏ rằng có thể rút lệnh hoán đổi : S <n, m> trong máy RAM thô sơ.
6. Hãy tìm cách mô phỏng các phép toán logic sơ cấp trong một máy RAM,
trong một máy RASP và trong một máy RAM thô sơ.
7. Hãy cho biết tập hợp các phép toán sơ cấp để xử lý ký tự. Hãy tìm cách mô
phỏng chúng trong một máy RAM, trong một máy RASP và trong một máy
RAM thô sơ.
8. Viết chương trình của một máy RAM vạn năng.
CHƯƠNG 3
Mô hình các máy Turing (Turing machines model) là một trong trong những
mô hình được sử dụng rất rộng rãi trong lý thuyết tính toán. Trong chương này,
chúng ta sẽ tập trung mô tả hình thức các máy Turing, chức năng đoán nhận ngôn
ngữ và tính hàm của chúng. Từ đó chúng ta sẽ nghiên cứu các tính chất của lớp
các hàm T−tính được. Phần cuối chương trình bày các biến thể khác của mô hình
các máy Turing và các máy Turing không đơn định.
Một bảng chữ S có tối thiểu hai ký tự, một trong chúng là một ký tự trắng,
ký hiệu # (hoặc B). Trên băng của máy Turing, mỗi ô chứa một ký tự của
bảng chữ này.
Một tập hợp hữu hạn các trạng thái Q. Mỗi trạng thái là một tên chỉ định
thông tin của bộ nhớ phụ hữu hạn.
Một chương trình P là một tập hợp con của Q×S´S´M´Q, trong đó,
M = {L, R} là tập hợp các chuyển động có thể của đầu đọc−ghi, tương ứng
với việc chuyển đầu đọc qua trái (Left) một ô, hoặc qua phải (Right) một ô.
Mỗi phần tử (q, x, y, m, p) của P là một quy tắc, được viết như sau :
q, x → y, m, p
với x và y ∈ S, q và p ∈ Q, m ∈ M, trong đó :
Cặp (q, x) là vế trái của quy tắc, cho biết điều kiện để áp dụng quy tắc.
Bộ ba (y, m, p) là vế phải của quy tắc, cho biết các thay đổi khác nhau khi
áp dụng quy tắc, theo một thể thức sẽ trình bày dưới đây.
Người ta thường biểu diễn một quy tắc của P dưới dạng sơ đồ như sau :
x | y, m
q p
Hình 3.1. Biểu diễn dạng sơ đồ một quy tắc của máy Turing
Như vậy, một máy Turing là một bộ ba T = <S, Q, P> được đặc tả một cách
hữu hạn. Trước khi giải thích họat động của một máy Turing, ta có nhận xét rằng
tồn tại nhiều cách định nghĩa máy Turing. Mặc dù những định nghĩa này không
làm ảnh hưởng đến hiệu lực của mô hình, nhưng đều có các nhược điểm.
Mô hình được chọn định nghĩa ở đây cũng có những điều bất tiện. Đó là cách
mô tả các ô của băng vô hạn. Ở đây ta đã quy ước rằng các máy Turing luôn luôn
có vô hạn các ô chứa ký tự trắng # về phía bên trái và về phía bên phải, chỉ có
một phần của băng gồm một số hữu hạn ô (nhưng không bị giới hạn) là hữu ích,
gọi là phần hữu ích (usable part).
Dãy ký tự chứa trong phần hữu ích này là một câu f trên bảng chữ S, nằm giữa
hai ký tự #. Người ta viết f#f.
Chú ý rằng một số tài liệu xem ký tự trắng không thuộc bảng chữ S, # ∉ S.
Một máy Turing và một cấu hình của máy cho phép mô tả đầy đủ hệ thống.
Cho máy Turing T = <S, Q, P>, và c = (f, q, xg) là một cấu hình nào đó, ta nói
rằng tồn tại một chuyển tiếp (transition) hay dịch chuyển từ cấu hình c thành cấu
hình c’ = (f’, q’, g’), ký hiệu :
c Ã− c’
nếu và chỉ nếu :
− (q, x) là vế trái của quy tắc (q, x → y, m, q’) của P và :
− nếu m = R thì f’ = fy và g’ = g
− nếu m = L thì f = f’z và g’ = zyg, với z là ký tự trên băng.
Trong cả hai trường hợp, chuyển tiếp làm thay đổi nội dung của ô nằm dưới
đầu đọc−ghi, và dịch đầu đọc−ghi qua trái hoặc qua phải tuỳ theo giá trị chỉ
hướng của m (L hoặc R). Cuối cùng chuyển tiếp làm thay đổi nội dung của bộ
nhớ phụ, chuyển từ trạng thái q thành trạng thái q’.
...### f x g ###...
q3, 1 → 1, L, q3,
q3, 1 → 1, R, q3,
q3, 1 → #, R, q1 }
Xét cấu hình c = (e, q1, 111), ta có thể có các chuyển tiếp sau :
c = (e, q1, 111) Ã− (11, q1, 1) Ã- (111, q2, #)
Từ cấu hình cuối cùng, không tồn tại quy tắc nào trong P có vế trái là (q2, #)
nên không thể tiếp tục được nữa.
Bây giờ xét cấu hình c’ = (e, q1, 1111), ta có các chuyển tiếp sau :
c’ = (e, q1, 1111) Ã− (e, q1, 111)
Ã− (11, q1, 11)
Ã− (111, q2, 1)
Ã− (1111, q1, #)
Ã− (111, q3, 1)
Ã− (11, q3, 1)
Ã− (11, q3, 11)
Ã− (1, q3, 111)
Ã− (e, q3, 1111) = (#, q3, 1111)
Ã− (e, q3, # 1111)
Ã− (#, q1, 1111) = (e, q1, 1111)
Cấu hình cuối cùng nhận được chính là cấu hình xuất phát c’. Như vậy quá
trình tính toán có thể lặp lại vô hạn.
Chú ý rằng phép tính trên không là phép tính duy nhất có thể, từ cấu hình
(111, q3, 1) chẳng hạn, người ta có thể thực hiện chuyển tiếp :
(111, q3, 1) Ã− (1111, q3, #)
Chúng ta sẽ quay lại xét hiện tượng này.
Như vậy, trong một số cấu hình, khi không còn tồn tại một chuyển tiếp nào có
thể, người ta nói rằng máy Turing dừng (halt) tại những cấu hình đó.
Một phép tính hợp lệ dẫn đến một cấu hình như vậy sẽ không thể kéo dài.
Người ta có thể nói về phép tính hợp lệ tối đa trong trường hợp này. Ký hiệu :
c Ã− c’
T
là sự kiện tồn tại một phép tính hợp lệ giữa các cấu hình c và c’ và không một
chuyển tiếp nào có thể kể từ cấu hình c’.
Ngược lại, xuất phát từ một số cấu hình, tồn tại các phép tính hợp lệ không
bao giờ dừng. Từ đó người ta có thể chia tập hợp các câu f ∈ S* thành hai phần :
Mô hình các máy RAM 29
Tập hợp các câu f sao cho xuất phát từ cấu hình (e, q1, f), máy Turing có ít
nhất một phép tính hợp lệ dừng, gọi là L(T).
Tập hợp các câu f sao cho từ cấu hình (e, q1, f), máy Turing không có một
phép tính hợp lệ nào dừng.
Bây giờ xét các cấu hình c1 = (e, q1, 10100) và c2 = (e, q1, 100111). Tồn tại
phép tính tối đa dẫn c1 và c2 đến các cấu hình (1010, q3, 1) và (10, q3, 1000)
tương ứng như sau :
c1 = { e, q1, 10100} Ã− (1010, q3, 1)
T
c2 = { e, q1, 100111} Ã− (10, q3, 1000)
T
Dễ dàng nhận thấy rằng, xuất phát từ một cấu hình c = (e, q1, f), tồn tại một
phép tính tối đa dẫn c đến cấu hình (g, q3, h) sao cho, nếu f là biểu diễn nhị phân
của số nguyên n, thì câu gh là biểu diễn nhị phân của số nguyên n + 1.
Người ta nói máy Turing T1 đã thực hiện hàm tính số nguyên kế tiếp
(successor) trên một biểu diễn nhị phân của số nguyên.
Ví dụ 3.3 :
Cho T2 = < S, Q, P> với S = {1, #}, Q = {q1, q2, q3, q4} và
P = { q1, 1 → #, R, q2,
q2, 1 → # R, q3,
q3, 1 → 1, R, q3,
q3, # → 1, L, q4 }
Nếu qui ước biểu diễn đơn nguyên (unary) của một số nguyên bởi viết liên
tiếp n+1 chữ số 1 (số nguyên 0 được biểu diễn bởi một chữ số 1) và các cặp số
nguyên biểu diễn theo quy ước này được đặt cách nhau một ký tự trắng #, khi đó,
dễ dàng nhận thấy rằng máy Turing T2 thực hiện hàm tính tổng hai số nguyên
cho kết quả là một biểu diễn đơn nguyên. Chẳng hạn :
(ε, q1, 11 # 111) Ã− (##1111, q4, 111)
T
Định nghĩa 3.1 :
Một hàm bộ phận φ từ S* → S* được gọi là tính được bởi máy Turing (Turing
−computable), viết tắt T−tính được, nếu tồn tại một máy Turing đơn định tính
được hàm này.
Rõ ràng, với mỗi hàm T−tính được, sẽ có vô số các máy Turing tính nó.
Chú ý rằng quan điểm tính được trong lý thuyết tính toán được nêu ra ở đây
liên quan chặt chẽ đến sự nhận biết (cognition) :
Một mặt, với mọi ngôn ngữ L ⊂ S*, sẽ có một hàm đặc trưng
(characteristic function) δL tương ứng được định nghĩa bởi :
δL(f) = 1 nếu f ∈ L
δL (f) = 0 nếu không (f ∉ L)
32 Lý thuyết tính toán
Người ta cũng kết hợp L với một hàm đặc trưng cục bộ (partial characteristic
function) δ‘L được định nghĩa bởi :
δ‘L(f) = 1 nếu f ∈ L
δ‘L(f) không xác định nếu không (f ∉ L)
Mặt khác, với mọi hàm φ : S* → S*, φ được kết hợp với một ngôn ngữ Gφ ,
trên S ∪ {#} chẳng hạn, gọi là đồ thị của hàm, được xác định bởi :
Gφ = { f # φ(f) | f ∈ Dom(φ) }
Sau đây ta sẽ chỉ ra rằng, lớp các hàm T−tính được là rất lớn, trước khi chỉ ra
rằng tồn tại các hàm không là T−tính được.
q2, 0 → #, R, q2,
q2, 1 → #, R, q2,
q2, # → 1, L, q3,
q3, # → 0, L, q4,
q4, # → 1, L, q5 }
Ta có : c = (e, q1, #01 #10) Ã−* ( #, q5, # 101 #).
T
Hàm hằng rất dễ triển khai và có thể xây dựng bất kỳ hàm hằng nào.
SuccG : G* → G*
sao cho với mọi câu f∈G*, hàm SuccG trả về câu kế tiếp của f theo thứ tự đã cho.
Ví dụ 3.6 :
Giả sử G = {0, 1, 2} với thứ tự 0<1<2, xây dựng máy Turing thực hàm kế tiếp
như sau :
T =< S, Q, P > với S = G ∪ {#}, Q = { q1, q2, q3} và
P = { q1, 0 → 0, R, q1,
q1, 1 → 1, R, q1,
q1, 2 → 2, R, q1
q1, # → #, L, q2,
q2, 0 → 1, R, q3,
q2, 1 → 2, R, q3,
q2, 2 → 0, L, q2,
q2, # → 1, R, q3 }
Ta có c = (e, q1, # 22 #)Ã−* (#1, q3, 00#)
T
Ta nhận thấy rằng có thể dễ dàng xây dựng các kiểu hàm kế tiếp cho mọi bảng
chữ và cho mọi kiểu thứ tự của các ký tự trong bảng chữ.
...### a ###...
Mệnh đề 3.2 :
Có thể luôn luôn giả thiết được rằng trạng thái đầu (trạng thái xuất phát)
không nằm trong bất kỳ một vế phải nào của quy tắc.
Chứng minh :
Thật vậy, nếu q1 là trạng thái đầu, ta thêm vào Q một trạng thái mới q’1 và
thêm vào P mọi quy tắc dạng :
q’1, x → y, m, qi
sao cho quy tắc :
q1, x → y, m, qi
là một quy tắc của máy Turing đang xét. Vậy người ta chọn lại q’1 là trạng thái
đầu. Như vậy, máy Turing vừa thêm q’1 thực hiện cùng một chức năng với máy
Turing cũ và thỏa mãn điều kiện của giả thiết.
Lúc này, người ta có thể biểu diễn máy Turing có trạng thái đầu thỏa mãn
mệnh đề 3.2 bởi sơ đồ sau đây :
q1 T
Mệnh đề 3.3 :
Nếu T là một máy Turing, có thể xây dựng từ T một máy Turing T’ chuẩn hóa
thực hiện cùng chức năng với T.
(Tự chứng minh)
Chú ý rằng người ta có thể xem rằng máy Turing chỉ có một trạng thái dừng,
lúc đó, máy Turing có thể được biểu diễn bởi sơ đồ :
q1 T qh
III.5. Lập trình trên ngôn ngữ bậc cao máy Turing
Để mở rộng phạm vi các lệnh thông dụng và sử dụng chúng như là các lệnh vĩ
mô (macro instruction), người ta định nghĩa các máy Turing tiện ích như sau :
Ví dụ 3.7 :
Xây dựng máy Turing T =< S, P, Q > cho phép dời đầu đọc−ghi qua phải đến
vị trí ký tự thứ n trong tập ký tự G là một tập hợp con của S. Giả sử lấy n = 2, ta
có tập hợp P gồm các lệnh như sau :
P = { q1, x → x, R, q1, với ∀x ∉ G
q1, y → y, R, q2, với ∀y ∈ G
q2, x → x, R, q2, với ∀x ∉ G
q2, y → y, R, q3, với ∀y ∈ G
q3, x → x, L, q4 } với ∀x ∈ S
Một cách tương tự, ta có thể xây dựng máy Turing cho phép dời đầu đọc−ghi
qua phải (hay qua trái) đến vị trí (ngay trước, hoặc ngay sau) ký tự thứ n trong G
là một tập hợp con của S.
Ta cũng có thể xây dựng một số máy Turing tiện ích khác để thực hiện các
chức năng như : chuyển thành hằng, phép chiếu, kế tiếp, kế trước, và các hàm
mới như sao chép, hoán vị.
Sau đây, ta sẽ mở rộng phương tiện thể hiện các máy Turing bằng cách đưa
vào các cấu trúc điều khiển và chỉ ra cách hoạt động của chúng.
Chẳng hạn với k = 2, máy Turing T thực hiện lệnh if then else :
qh T1
1
q1 T
qh T2
2
qh
1
q1 T
qh T’
2
là bản sao tương ứng với trạng thái qi, còn pi là trạng thái đầu và pi là trạng thái
1 h
cuối của T2i.
Xây dựng từ máy T một máy mới T3 có tất cả các quy tắc của T và các quy tắc
của tất cả các máy T2 , ngoài ra, P3 còn có thêm các quy tắc sau :
i
P3 = { qi, h → h, R, pi
1
pi , x → x, L, qi } với x ∈ S là ký tự bất kỳ.
h
Với các điều kiện trên, T1 next T3 là máy thỏa mãn yêu cầu đặt ra.
q5, 1 → 1, L, q5,
q3, b, → b, L, q3,
q5, b → b, L, q5,
q3, a → 1, R, q6,
q5, a, → 0, R, q6 }
Xây dựng T2 là máy Turing :
while < tại trạng thái q1 không đọc ký tự b > : T1
Xuất phát từ câu vào fb#, T2 cho kết quả là fbf#. Vậy T2 là máy sao chép cần
xây dựng.
III.7.3. Liệt kê các câu, các cặp câu và dãy các câu
Việc liệt kê các câu của S* rất đơn giản : người ta liệt kê câu đầu tiên của S*
(là một hằng), sau đó lần lượt liệt kê câu kế tiếp của câu trước đó đã liệt kê.
Việc liệt kê các cặp câu được tiến hành như sau : giả sử máy Turing T1 đã có
trên băng vào một cặp câu, giả sử f#g, T1 thực hiện việc chép kế tiếp một cặp câu,
gồm câu đầu tiên của S*, là f, và câu kế tiếp của câu kia, là succ(g). Sau đó T1 lặp
đi lặp lại việc chép cặp câu tiếp theo bằng cách lấy câu kế tiếp của thành phần thứ
nhất, là succ(f), và câu kế trước của thành phần thứ hai, là pred(succ(g)), khi mà
thành phần này không phải là câu đầu tiên của S*.
Giả sử máy Turing T2 có cặp câu vào x#y trên băng, T2 thực hiện chép một
cặp câu, gồm câu kế tiếp của câu đầu tiên, là succ(x), và câu còn lại, là y. Sau đó,
T2 thực hiện lặp đi lặp lại việc chép cặp câu tiếp theo bằng cách lấy câu kế trước
42 Lý thuyết tính toán
của thành phần thứ nhất, là pred(succ(x)), khi mà thành phần này không phải là
câu đầu tiên của S*, và lấy câu kế tiếp của thành phần thứ hai, là succ(y).
Máy Turing cần tìm thực hiện chép một cặp câu gồm hai câu đầu tiên của S*,
sau đó lặp đi lặp lại thực hiện T1 next T2.
Bài tập : Mô tả máy Turing liệt kê dãy các câu trên S*.
Đặt đầu đọc−ghi tại ký tự cuối cùng của v, tiếp theo, trong khi ký tự đọc được
(dưới đầu đọc−ghi) chưa là b thì ghi nhớ bằng cách xóa ký tự đọc được (0 hay 1)
và đi đến ngay trước ký tự a. Ở đây, tùy theo ký tự đã đọc (0 hay 1 hoặc ký tự
trắng # được xử lý hoàn toàn tương tự 0), tùy theo ký tự đã ghi nhớ, và theo một
số nguyên 0 hay 1 cũng đã ghi nhớ (phần nhớ do 1 + 1), lúc đó đã được khởi
động giá trị 0, viết ký tự a theo sau 0 hoặc 1 tùy theo kết quả (nghĩa là sự đối
chiếu của tổng 3 chữ số này), và ghi nhớ phần nhớ 0 hoặc 1 (tùy theo có hay
không ít ra là hai chữ số 1 trong 3 chữ số này). Tiếp tục quay lại ngay trước ký tự
trắng # đầu tiên bên phải, rồi lại quay đến ngay trước chữ a và trong khi phần
nhớ là 1, thay đổi ký tự đọc được và dời một ô qua bên trái : 1 được thay thế bởi
0, với phần nhớ vẫn giữ, và 0 được thay thế bởi 1, với phần nhớ thay đổi thành 0.
Từ đó nhận được câu fagb với fg là biểu diễn nhị phân của m + n.
Máy Turing xây dựng theo cách trên có thể thực hiện được phép cộng các số
nguyên biểu diễn trong một hệ đếm bất kỳ.
Bài tập : Xây dựng máy Turing thực hiện phép trừ, phép nhân và phép chia của
hai số nguyên biểu diễn trong hệ 2, hệ 10 hoặc trong một hệ đếm bất kỳ.
Chính vì vậy mà người ta thường nói theo cách lạm dụng (excessively) về hàm
mà không chỉ rõ cách biểu diễn lựa chọn.
Chẳng hạn, tồn tại T−tính được phép cộng các số nguyên biểu diễn trong một
hệ đếm nào đó thì người ta nói rằng phép cộng các số nguyên là T−tính được.
Mối quan hệ hẹp giữa các ngôn ngữ và các hàm được chỉ rõ qua các mệnh đề sau.
Mệnh đề 3.4 :
Ngôn ngữ L là được nhận biết bởi một máy Turing khi hàm cục bộ đặc trưng
của L, viết d’L, là T−tính được.
Chứng minh :
Nếu ngôn ngữ L nhận biết bởi một máy Turing T, ta có thể giả thiết T được
chuẩn hóa và tiêu chuẩn hóa. Nếu T là một máy Turing viết ra hằng 1, thì máy
T next T1 là một máy Turing thực hiện hàm d’L. Nếu T’ là một máy Turing thực
hiện d’L, T’ nhận biết L.
Mệnh đề 3.5 :
Hàm f là T−tính được khi và chỉ khi đồ thị Gf của nó là được nhận biết bởi
một máy Turing.
Chứng minh :
«Chỉ khi» : Cho T là máy Turing thực hiện hàm f, ta cần chứng minh rằng đồ
thị Gf của nó được nhận biết bởi một máy Turing nào đó.
Nếu T là máy Turing thực hiện hàm f : f → f( f) = g, có thể giả thiết rằng T
được chuẩn hóa và tiêu chuẩn hóa, đầu đọc−ghi của T sẽ không bao giờ vượt qua
bên trái vị trí xuất phát.
Để xây dựng máy Turing nhận biết Gf, ta xây dựng hai máy Turing bổ trợ :
− T1 hoán vị hai câu vào (f#g trở thành g#f) và dời đầu đọc-ghi về vị trí
bắt đầu của câu thứ hai (câu mới),
− T2 so sánh hai câu vào g#g và sẽ không bao giờ dừng trong trường hợp
không bằng nhau.
Từ đây, máy Turing : T1 next T next T2 có thể nhận biết Gf.
«Khi» : Cho T là một máy Turing nhận biết ngôn ngữ Gf,, ta cần chứng minh
rằng có thể xây dựng được một máy Turing thực hiện hàmf.
Giả sử T là máy Turing nhận biết ngôn ngữ (hay đồ thị của φ) Gf ⊂ S*,
Gφ = { f # g | f ∈ Dom(φ) và g = φ(f) }
Ta xây dựng một máy Turing T’ thực hiện hàm f theo cách sau : nếu f là một
dữ liệu vào của T’, máy T’ sẽ liệt kê tất cả các cặp (g, n_ ) có thể, với g là một câu,
g∈S* và n là độ dài của phép tính (hay quá trình đoán nhận) đối với dữ liệu f #g
của máy T đã cho. Nếu T dừng trên f #g, thì T’ cũng dừng sau mỗi cặp liệt kê.
Mô hình các máy RAM 45
Ở đây, n_ là một biểu diễn nào đó của số nguyên n. Từ nay về sau, ta quy ước
rằng mọi số nguyên có gạch dưới chỉ định biểu diễn nhị phân của số nguyên đó.
Cụ thể, xuất phát từ máy T, đầu tiên ta xây dựng một máy TU sao cho với mọi
dữ liệu f#g và mọi số nguyên n, máy TU thực hiện đối với dữ liệu f#g#n_. và dừng
khi gặp trạng thái qYes nếu T thực hiện phép tính đối với dữ liệu f#g dừng ở độ
dài n, và dừng ở trạng thái qNo nếu T không dừng. Ta cũng giả thiết rằng, đầu đọc
của TU không bao giờ qua trái kể từ vị trí xuất phát, và, trong trường hợp thất bại
(dừng ở trạng thái qNo), TU xóa hết nội dung trên băng vào của nó.
Tiếp theo, ta xây dựng máy các máy Turing :
− T1 nhận dữ liệu vào f#g#n_ để trả về kết quả là f#g’#n_’, với (g’, n’) là cặp
câu theo sau cặp (g, n).
− T2 thực hiện sao chép f#g#n_ thành f#g#n_#f#g#n_ và đặt đầu đọc−ghi vị trí
bắt đầu câu f thứ hai.
− T0 chép qua bên phải f cặp (g, n) đầu tiên để nhận được f#g#n_. .
Từ đó, máy Turing T’ được xây dựng như sau :
T0 next T2 next TU next while T give qNo : T1 next T2 next T_
cho phép thực hiện f.
46 Lý thuyết tính toán
...### f x g ###...
Băng làm việc
q
w # # # # ... Băng ra
trên băng thứ ba, ta liệt kê tất cả các dãy số thứ tự của các quy tắc đã dùng đến để
tính toán của máy Turing T (trong các dãy số này có các dãy số thứ tự của các
quy tắc được dùng cho các tính toán hợp thức).
Phép tính thực hiện trên băng thứ hai như sau : áp dụng các quy tắc của T cho
dữ liệu vào đã được chép từ băng một, nếu được, thì dãy quy tắc này được liệt kê
trên băng thứ ba. Nếu phép tính này là hợp thức và dẫn đến các cấu hình dừng
của T, thì người ta dừng tính toán. Nếu không, thay thế nội dung của băng hai bởi
dữ liệu vào (đang được lưu giữ trên băng một) và tiến hành lại phép tính.
Rõ ràng, nếu một câu được nhận biết bởi T, một tính toán dẫn đến dừng máy
và liệt kê được các quy tắc đã dùng đến trên băng ba, thì phép tính của T’ cũng sẽ
dừng. Nếu một câu không được nhận biết bởi T, thì các dãy quy tắc của T sẽ liên
tục được liệt kê, không bao giờ dừng. Vậy T’ nhận biết cùng một ngôn ngữ với T.
Có thể xây dựng được một máy Turing TU, gọi là máy Turing vạn năng, cho
phép thực hiện một hàm fu có hai đối số i và f sao cho, với mọi số nguyên i và
với mọi dữ liệu vào f của máy Turing thứ i (thực hiện hàm gi), fu thỏa mãn :
fu(i_ #f) = gi (f)
Chứng minh :
Vì tồn tại máy Turing TD nhận dữ liệu vào _i và cho kết quả là câu mã hóa máy
Turing thứ i, nên chỉ cần chứng minh rằng tồn tại một máy Turing T’U thực hiện
hàm f’u sao cho với mọi wi là mã của máy Turing thứ i, và với mọi f là dữ liệu
vào, sẽ có f’u(wi#f) =gi(f).
Ta sẽ chỉ ra cách xây dựng máy T’U nhờ hai máy Turing ba băng là TC và T”U
:
Máy thứ nhất TC thực hiện việc khởi động : dữ liệu vào wi#f được đọc và câu
wi bị xóa khỏi băng thứ nhất để chép lại lên băng thứ hai. Băng thứ ba được ghi
hằng q1_ . Khi kết thúc, máy TC ở cấu hình như sau :
− Băng thứ nhất chứa câu f với đầu đọc-ghi nằm phía trái của f.
− Băng thứ hai chứa câu wi với đầu đọc-ghi nằm phía trái của wi.
− Băng thứ ba chứa câu q1_ với đầu đọc-ghi nằm phía trái của q1_. .
Máy thứ hai T”U mô phỏng hoạt động của máy Ti, với chương trình wi của Ti
được ghi trên băng thứ hai của T”U theo cách sau:
Cấu hình uqnv của Ti được mã hóa bởi :
− Câu uv trên băng thứ nhất với đầu đọc−ghi đặt tại ký tự đầu tiên của v.
− Câu qn_ trên băng thứ ba.
Giả sử rằng lúc đầu, người ta đã có cấu hình xuất phát của Ti đã được mã hóa.
Một cách lặp đi lặp lại, ta thực hiện phép toán như sau :
Đầu đọc của băng thứ hai đặt ở bên trái, lần lượt di chuyển qua bên phải của
băng cho đến khi tìm thấy dãy #q. Lúc này máy so sánh số nguyên tiếp theo (số
của trạng thái của vế trái của một quy tắc) với số nguyên của trên băng thứ ba (ở
đó có mặt trạng thái hiện hành của máy được mô phỏng Ti), sau đó, so sánh ký tự
nằm dưới đầu đọc ở băng thứ nhất với ký tự được mã hóa nằm trên băng thứ hai
ở ngay sau dấu phẩy chỉ sự kết thúc của số thứ tự của trạng thái vừa được kiểm
tra.
Xảy ra hai trường hợp như sau :
− Chúng không đồng thời bằng nhau, có nghĩa vế trái của một quy tắc không
áp dụng được trong cấu hình được mã hóa lúc này. Ta tiếp tục di chuyển
Mô hình các máy RAM 55
đầu đọc của băng thứ hai qua trái. Nếu đã qua tất cả chương trình mà
không tìm thấy quy tắc áp dụng được, máy T”U dừng lại.
− Chúng bằng nhau, có nghĩa đã tìm thấy vế trái của một quy tắc của Ti áp
dụng được cho cấu hình được mã hóa lúc này. Chỉ còn việc thay đổi trên
các băng thứ nhất và thứ ba tương ứng với việc áp dụng quy tắc này.
Trên băng thứ hai, người ta đọc ký tự nào nằm ngay sau dấu mũi tên → dùng
để thay thế cho ký tự nằm trên băng thứ nhất ở dưới đầu đọc-ghi , và người ta
tiến hành thay thế. Tiếp theo, đọc sau dấu phẩy một ký tự L hoặc R chỉ chiều di
chuyển nào của đầu đọc-ghi của băng thứ nhất sẽ được thực hiện, và tiến hành
việc di chuyển này. Sau đó, đọc sau dấu phẩy tiếp theo trạng thái hiện hành mới
nào của máy Turing được chọn để chép lại trên băng thứ ba tại vị trí cũ.
Rõ ràng, máy T’u vừa mô tả đã mô phỏng được hoạt động của máy Turing có
chương trình nằm trên băng thứ hai. Máy này dừng lại trên một dữ liệu vào f ở
băng thứ nhất nếu và chỉ nếu máy mô phỏng T’U dừng trên f. Trong trưòng hợp
này, những gì mà máy này có trên băng thứ nhất thì máy mô phỏng cũng có đúng
như vậy. Từ đó, máy :
T’U = TC next T”U
là máy cần tìm kiếm.
Chú ý rằng ta có thể dễ dàng tổ hợp máy TD đã đưa ra ở đầu chứng minh này
với máy TC. Nếu ký hiệu T’C là máy tổ hợp nhận được , thì ta có :
TU = T’C next T”U.
Cũng chú ý thêm rằng máy Turing vạn năng TU mô phỏng họat động của mọi
máy Turing trên một bảng chữ gồm có 9 ký tự. Đồng thời TU cũng là máy trên
một bảng chữ có 9 ký tự. Rõ ràng, ta có thể nhận được cùng một lúc kết quả với
bất kỳ kích thước nào (k ≥ 2) của bảng chữ.
Bằng phản chứng, ta giả thiết rằng tồn tại một máy Turing T như vậy. Xuất
phát từ T, ta có thể xây dựng một máy Turing T’ khác T thực hiện hàm g như sau
: với mọi số nguyên i :
g(i) = 1 nếu th(i, i) = 0,
g(i) = không xác định nếu th(i, i) = 1
Máy Turing T’ được xây dựng như sau :
TC(i) = (i, i) ∀i∈Ν
T’ = TC next T next TD TD(0) = 1,
TD(i) không dừng ∀ i > 0
Ở đây, máy Turing TC nhận dữ liệu vào là một số nguyên i để trả về kết quả là
cặp (i, i) và máy Turing TD cho kết quả là 1 với từ dữ liệu vào là 0 và không bao
giờ dừng trên một dữ liệu vào nào khác 0.
Máy Turing T’ vừa xây dựng trên đây quả thực đã thực hiện hàm g và giả sử
T’ có số thứ tự là k, T’ = Tk. Xảy ra hai trường hợp như sau :
Giả sử hàm g(k) không xác định, điều này có nghĩa T’ không dừng trên
dữ liệu k, điều này cũng có nghĩa máy T, đến lượt nó, có kết quả là 1 trên
dữ liệu vào của cặp (k, k), tức là th(k, k) = 1. Vả lại th(k, k) = 1 nếu và chỉ
nếu máy Turing có số hiệu k dừng trên dữ liệu vào k. Nhưng máy Turing có
số hiệu k, chính là T’, không dừng trên dữ liệu vào k.
Giả sử hàm g(k) xác định và có giá trị 1, điều này có nghĩa rằng máy T
dừng trên dữ liệu vào k và có kết quả 0 trên dữ liệu vào của cặp (k,k). Nghĩa
là th(k, k) = 0. Vả lại th(k, k) = 0 nếu và chỉ nếu máy Turing có số hiệu k
không dừng trên dữ liệu vào k. Tuy nhiên, máy Turing có số hiệu k chính là
T’ lại dừng trên dữ liệu vào k.
Trong cả hai trường hợp trên, ta đều đi đến mâu thuẫn, vậy không tồn tai máy
Turing như đã giả thiết. QED
Kết quả chứng minh rất quan trọng vì đã chỉ ra rằng không tồn tại cách nào
để tính toán nhờ một máy Turing nếu một máy Turing T sẽ dừng hoặc không
dừng trên một dữ liệu vào f. Từ đây, ta cũng có thể chứng minh được :
Mệnh đề 3.8 :
Tồn tại các hàm T−tính được bộ phận (partial) không thể mở rộng thành một
hàm T−tính được nào khác.
Chứng minh
Định nghĩa hàm bộ phận g : Ν →/ Ν như sau:
g(i) = TU(i, i) + 1 nếu TU(i, i) xác định
g(i) không xác định nếu TU(i, i) không xác định
Mô hình các máy RAM 57
Hàm g là T−tính được. Thật vậy, xuất phát từ máy Turing vạn năng TU, ta có
thể dễ dàng xây dựng được một máy Turing thực thi hàm g này (chỉ việc thêm 1
vào kết quả).
Hàm g này không thể được mở rộng thành một hàm toàn phần từ Ν vào Ν dẫu
rằng T−tính được.
Ta sẽ chỉ ra bằng cách dùng phản chứng. Giả sử rằng g’ là một hàm như vậy.
Hàm g’ được thực hiện bởi một máy Turing T có số hiệu k, giả sử Tk.
Vì rằng g’ là một hàm toàn phần, nên T có một tính toán dừng cho mọi dữ liệu
vào. Chẳng hạn, với dữ liệu vào k, Tk dừng với một kết quả g’(k). Vả lại, vì Tk là
máy số hiệu k dừng trên dữ liệu vào k, TU(k, k) là xác định, khi đó g(k) được xác
định và có giá trị là TU(k, k)+1.
Tuy nhiên, TU là một máy Turing vạn năng, và do đó TU(k, k) là kết quả của
máy Turing số hiệu k trên dữ liệu vào k, giả sử là g’(k).
Vậy ta có : g(k) = g’(k) + 1
Nhưng g’ là một mở rộng của g, do đó g’(k) + 1 = g’(k).
Điều này mâu thuẫn.QED
58 Lý thuyết tính toán
Bài tập
1. Cho bảng chữ S = {a, b, c}, f và g ∈ S*. Hãy viết chương trình của một máy
Turing thực hiện các hàm sau :
− Hàm gương (miror function) hay hàm đảo ngược f → f R : φ(x1...xn ) =
xn...x1.
− Hàm chép f#g → f#g#g.
− Hàm f#g → fg.
− Hàm f → ff.
− Hàm f → ffR.
2. Cho S = {a, b, c} với thứ tự phân cấp là a<b<c. Viết chương trình máy Turing
để liệt kê các bộ ba câu và liệt kê các dãy các câu trên S.
3. Cho S = {0, 1, 2, 3} có thứ tự phân cấp là 0<1<2<3. Hãy viết chương trình
máy Turing thực hiện hàm kế tiếp Succ và hàm kế trước Pred.
4. Các số nguyên được biểu diễn lần lượt trong các hệ đếm cơ số 1, 2, 10. Hãy
viết chương trình của một máy Turing thực hiện các hàm tính tổng, tính nhân,
tính nhân với 7, tính chia, lấy phần dư (modulo), tính phần nguyên của căn
bậc hai và chuyển đổi giữa các hệ đếm này.
5. Các số nguyên được biểu diễn trong hệ cơ số 10, hãy viết chương trình của
một máy Turing thực hiện hàm :
− f(n) = 3n + 5
− g(n) = 2n
− h(n, m) = 2n + m
p
− l (n, m, p) = (nm)
6. Viết chương trình của một máy Turing không đơn định có một băng để nhận
biết ngôn ngữ L = {abi1abi2 ... abin | ∃ j, k : j ≠ k, và ij = ik }.
7. Hãy viết chương trình của một máy Turing đơn định có hai băng để nhận biết
ngôn ngữ L = {anbncn | n ≥ 1}. Tương tự đối với các ngôn ngữ :
L1 = {a2n | n ≥ 0}
L2 = {anb2n | n ≥ 0}
L3 = {anbpcq | q ≥ n ≥ 0 và p > 0}
Hãy chỉ ra rằng luôn luôn có thể giả thiết các phép tính dừng lại đều có độ dài
chẵn (một cách tương ứng : có độ dài lẻ).
CHƯƠNG 4
Luận đề Church
«The greatest ocean of truth lay all undiscovered before me»
Sir Isaac Newton
Ti duyệt băng từ trái qua phải và so sánh số đứng ngay sau mỗi ký tự với n. Nếu là bằng
nhau, Ti so sánh số nguyên tiếp theo với hằng 0 và dừng ở trạng thái qj nếu là bằng nhau dừng
ở qk nếu không bằng nhau.
hi : (S*)2 → S*
Nghĩa là mỗi hàm hi nhận giá trị từ fi và gi bởi sơ đồ đệ quy đồng thời :
hi(1, m) = fi(m)
hi(wx, m) = gi(w, x, h1(w, m), ..., hk(w, m), m)
Ta định nghĩa lớp P các hàm đệ quy nguyên thủy S* → S* là các lớp bé nhất các hàm chứa
các hàm sơ cấp sau :
identity (hàm hằng, trả về một câu cố định),
ls, ppx, first, last, prefix, suffix,
equal,
copy, identity, proiection, antiprojection.
Lớp các hàm này là đóng đối với các sơ đồ hợp thành và đệ quy đơn.
Ví dụ 4.1 :
Cho bảng chữ S, ta xây dựng các hàm đệ quy nguyên thuỷ sau đây :
64 Lý thuyết tính toán
1. Ghép hai câu
Hàm concat ghép hai câu u và w thành uw như sau :
concat (u, w) =u nếu w = 1
concat (u, wx) = ppx(concat(u, w))
Người ta cũng có thể viết :
concat = rec(f, g)
với f là hàm identity và g được hợp thành từ các hàm ppx và phép chiếu thứ ba :
P3 : g = ppx ° P3
2. Nghịch đảo câu
Hàm mirror trả về câu nghịch đảo (reverse) của câu w là wR, nghĩa là nếu
w = x1x2 ... xn thì mirror(w) = xnxn-1 ... x2x1, như sau :
mirror(1) =1
mirror(wx) = concat (x, mirror(w))
3. Nuốt (hấp thu) câu
Hàm đệ quy nguyên thuỷ absorb như sau :
absorb (1, f) = 1
absorb (w, f) = f nếu w ≠ e
4. Kiểm tra không bằng nhau
Xây dựng hàm nonequal :
nonequal(x, y) = x0 nếu x = y với x0 ∈ S là ký tự cố định
=1 nếu x ≠ y
5. Các hàm case
Giả sử S = { x1, x2, ..., xk }, x1 là ký tự đầu tiên, xk là ký tự cuối cùng trong S.
Xây dựng hàm case1 trả về câu kế tiếp của câu w trong thứ tự phân cấp khi ký tự cuối cùng
của w không là ký tự cuối cùng của bảng chữ S như sau :
case1(1) =1
case1(wx) = absorb(equal(x, xk), ppx (w))
1
Xây dựng hàm case2 như sau :
case2(1, u) =1
case2(wx, u) = absorb(nonequal(x, xk), ppx(u)) nếu x = last(w)
Từ cách xây dựng các hàm đệ quy nguyên thuỷ trên đây, ta định nghĩa lại hàm kế tiếp
successor :
successor(1) = x1
successor(wx) = concat(case1(wx), case2(wx, successor(w)))
Cũng như trước đây, ta đã chuyển từ một ngôn ngữ sang một hàm bằng cách sử dụng hàm
đặc trưng và ta có định nghĩa sau :
Định nghĩa 4.1 :
Một phần L ⊂ S* được gọi là đệ quy nguyên thủy nếu hàm đặc trưng của nó là một hàm đệ
quy nguyên thuỷ.
Mô hình các máy RAM 65
trong đó C là một hàm mã hóa từ S* × S*→ S* thỏa mãn C(1,1) = 1 và sao cho các hàm h1 và
h2 nhận được từ h bởi phép giải mã nhờ các hàm đệ quy nguyên thuỷ P1 và P2 :
hi(w, m) = Pi(h(w, m))
Vấn đề còn lại là chứng minh rằng h cũng là một hàm đệ quy nguyên thuỷ.
4
Hàm h nhận được bỡi sơ đồ đệ quy đơn nhờ hai hàm f và g, hàm f từ S* → S* và g từ (S*)
→ S*, như sau :
f(m) =C(f1(m), f2(m)) và
g(w, x, C(u1, u2), m) = C(g1(w, x, u1, u2, m), g2(w, x, u1, u2, m))
Bây giờ kí hiệu f = rec(f, g), theo định nghĩa, ta có :
f(1, m) = f(m),
f(mx, m) = g(w, x, f(w, m), m)
Với câu rỗng, rõ ràng ta có f(1, m) = h(1, m), còn đối với các câu khác, ta có :
f(wx, m) = C( g1(w, x, P1 ° f(w, m), P2 ° f(w, m), m),
g2 (w, x, P1 ° f(w, m), P2 ° f(w, m), m))
Như vậy, ta có f = h cho mọi câu w và mọi câu m.
Do f và g đều là đệ quy nguyên thuỷ bởi các hàm f1, f2 và g1, g2 cũng là đệ quy nguyên
thuỷ, nên h cũng là đệ quy nguyên thuỷ. Vậy h1 và h2 cũng là các hàm đệ quy nguyên thuỷ.
Cần phải chú ý rằng tất cả các hàm đệ quy nguyên thuỷ đều là các hàm toàn phần. Người ta
có thể mở rộng khái niệm đệ quy nguyên thuỷ cho các hàm bộ phận nhờ đưa vào định nghĩa
sau đây :
Định nghĩa 4.2 :
Một hàm được gọi là đệ quy nguyên thuỷ bộ phận (partial primitive recursive function) nếu
hàm đó được định nghĩa trên một miền xác định đệ quy nguyên thuỷ (partial primitive
recursive domain) nhờ một hàm đệ quy nguyên thuỷ.
Rõ ràng, một hàm đệ quy nguyên thuỷ bộ phận là một hàm có thể được mở rộng thành một
hàm đệ quy nguyên thuỷ.
Mô hình các máy RAM 67
Chú ý rằng kỹ thuật đường chéo đều được áp dụng cho tất cả lớp p’ các hàm được xây
dựng tương tự như đã xây dựng trong p, nghĩa là từ các hàm cơ sở và từ một số hữu hạn sơ đồ
xây dựng hàm. Như vậy không tồn tại một cách xây dựng hàm như vậy cho p.
Định nghĩa 4.3 :
Một phân hoạch L ⊂ S* được gọi là đệ quy (hiểu là toàn phần) nếu hàm đặc trưng của L là
một hàm đệ quy toàn phần.
68 Lý thuyết tính toán
Trong số các hàm đệ quy bộ phận có thể phân biệt được những hàm mở rộng được thành
một hàm đệ quy toàn phần và những hàm không thể kéo mở rộng. Loại hàm mở rộng được có
miền xác định là đệ quy.
II.2.3. Một số ví dụ
1. Tính tổng và tích hai số nguyên
Các hàm tính tổng sum và tích product của hai số nguyên sau đây đều là đệ quy nguyên
thuỷ :
sum(n, m) = P1 (m) nếu n = 0,
= succ ° P2 (n', sum (n', m), m) nếu n = n' + 1
Hàm chiếu thứ nhất P1 (là hàm đồng nhất) là đệ quy nguyên thuỷ. Hàm tổ hợp succ°P2
cũng là đệ quy nguyên thuỷ vì cả hai hàm, hàm kế tiếp succ và hàm chiếu thứ hai P2, đều là đệ
quy nguyên thuỷ. Từ đó, hàm sum viết dưới dạng
sum = rec(P1, succ°P2) là đệ quy nguyên thuỷ. Có thể viết lại đơn giản hơn :
Mô hình các máy RAM 69
sum (n, m) = m nếu n = 0
= succ(sum (n', m)) nếu n = n' + 1
Tương tự :
product (0, m) =0
product (n + 1, m) = sum (product (n, m), m)
Người ta thường viết n+m và n*m thay vì viết sum (n, m) và product (n, m).
2. Kiểm tra bằng 0
Hàm zt (zerotest) kiểm tra số nguyên n có bằng 0 không được định nghĩa :
zt (n) = 1 nếu n = 0
=0 nếu n ≠ 0
là một hàm đệ quy nguyên thuỷ, vì rằng zt = rec(1, 0) với 0 và 1 là hai hàm hằng.
LUẬN ĐỀ CHURCH
Mọi hàm tính được một cách máy móc là Turing-tính được.
Để chứng minh luận đề Church, ta cần so sánh các thủ tục hiệu quảf (effective procedure)
là một khái niệm trực giác với các máy Turing là một khái niệm hình thức. Do đó, ta cần hình
thức hoá khái niệm về thủ tục hiệu quả. Nhưng khi đó, ta lại phải giải quyết vấn đề là có sự
tương đương giữa phương pháp hình thức hoá đưa ra và khái niệm trực giác hay không ? Lời
giải của vấn đề này lại nảy sinh ra một luận đề Church khác và như vậy, ta sẽ đi đến một sự
truy lùi vô hạn.
Nhưng một khi đã chấp nhận luận đề Church, thì tồn tại các hàm không là T-tính được do
tồn tại các hàm không tính được một cách máy móc.
Cũng có thể giả thiết rằng người ta sử dụng một cơ chế mới cho phép nhận được một lớp
hàm lớn hơn, khi đó tính có hạn của việc mô tả các phần tử tuân theo cơ chế này sẽ dẫn đến
một tập hợp đếm được các hàm tính được bởi cơ chế này, và bởi kỹ thuật đường chéo, người ta
cũng có thể chỉ ra rằng, các hàm rơi ra ngoài tập hợp này.
Như vậy, ta đã khẳng định rằng, không thể tính toán được hết (giải hết các bài toán) nhờ
máy tính. Chương sau đây sẽ chỉ ra một số bài toán không thể giải được bằng máy tính.
Bài tập
1. Chứng minh rằng các hàm sau đây là đệ quy nguyên thuỷ :
a) remainder (n, m) = phần dư của phép chia n cho m
b) power (n, m) = nm
c) factorial (n) = n!
d) divesiontest (n,m) = 1 nếu n chia hết m
= 0 nếu n không chia hết m
e) primetest (n) = 1 nếu n là số nguyên tố
= 0 nếu n không phải là số nguyên tố
f) prime (n) = số nguyên tố thứ n
g) exponent (n, m) = max { k ∈ Ν | mk chia hết cho n }
2. Ta định nghĩa sơ đồ tối thiểu bị chặn mink bởi : xuất phát từ một hàm f,
mink (f) là một hàm h được xác định bởi :
h(m) = số bé nhất y ≤ k sao cho f (y, m ) = 0 nếu một số y như vậy tồn tại
= 0 nếu không.
Chứng minh rằng nếu f là một hàm đệ quy nguyên thuỷ, thì mink (f) cũng là hàm đệ quy
nguyên thuỷ.
f
Ta có thể đồng nhất thuật ngữ này với thuật toán.
Mô hình các máy RAM 75
3. a) Cho hàm c được định nghĩa bởi :
c(n, m) = 2n + 2n + m + 1
Chứng minh răng c là một đơn ánh đệ quy nguyên thuỷ từ Ν × Ν → Ν.
Cho d là hàm "ngược lại" từ Ν → Ν × Ν được định nghĩa bởi :
d(p) = (n, m) ⇔ c (n, m) = p
Gọi d1 và d2 là các hàm Ν → Ν được định nghĩa bởi :
d1(p) = n và d2(p) = m ⇔ c (n, m) = p.
Hãy chứng minh rằng d, d1 và d2 đều là các hàm đệ quy nguyên thuỷ.
b) Phép mã hoá các dãy số nguyên dưới đây được gọi là phép đánh số Gdel :
g : N* → N được định nghĩa bởi : g (i1, i2, ..., ir) = 2 i 1 3 i 2....p i i r
với pi là số nguyên tố thứ i
Hãy chứng minh rằng g và g-1 là các hàm đệ quy nguyên thuỷ.
4. Cho S là bảng chữ có thứ tự kích thước k. Giả sử n là ánh xạ từ S* → Ν để đánh số các câu
theo thứ tự phân cấp. Chứng minh rằng các hàm sau đây đều là đệ quy nguyên thuỷ :
- letter (i, n) = 0 nếu i > | n-1 (n) |
letter (i, n) = số thứ tự của ký tự thứ i của câu n-1(n) nếu i ≤ | n-1 (n) |
- factor (i, j, n) = số thứ tự của thừa số của câu n-1(n) bắt đầu từ ký tự thứ i và kết thúc ở
ký tự thứ j nếu i ≤ j ≤ | n-1 (n) |
- factortest (m,n) = 1 nếu n-1(m) là một thừa
số của n-1(n)
= 0 nếu không phải.
5. Cho ri là hàm đệ quy toàn phần thứ i trong phép đánh số hàm đã cho. Người ta cũng đánh
số các câu theo thứ tự phân cấp và ký hiệu wj là câu thứ j theo thứ tự này. Chứng minh hàm
toàn phần f được định nghĩa bởi :
f (wi) = successor (ri (wi))
là một hàm đệ quy, đối với các hàm ri thì f không phải đệ quy.
6. Cho h là một hàm, xây dựng từ h hàm h~ như sau:
h~ (0, m) = 1
h~ (n + 1, m) = ∏ p h (i , m ) + 1
i trong đó pi là số nguyên tố thứ i
0≤ ≤
i n
Tiếp tục định nghĩa sơ đồ đệ quy tổng quát renrec(f, g) như sau : xuất phát từ hai hàm f và
g, định nghĩa hàm h = renrec(f, g) :
h(n, m) = f (m ) nếu n = 0
= g (n', h~(n', m), m) nếu n = n' + 1
Chứng minh rằng f là một hàm đệ quy nguyên thuỷ, thì renrec(f, g) cũng là hàm đệ quy
nguyên thuỷ.
7. Cho hàm Ackermann từ Ν × Ν → Ν:
A (0, m) = m + 1
A (n + 1, 0) = A (n + 1)
A (n + 1, m + 1) = A (n, A (n + 1, m))
76 Lý thuyết tính toán
Gọi Ai là các hàm từ Ν → Ν được định nghĩa bởi : Ai (m) = A (i, m).
a) Tính giá trị hàm Ai với i = 0, 1, 2, 3 và 4.
Người ta nói rằng hàm g : Ν → Ν làm tăng (increase) hàm f : Νk → Ν nếu:
∀x1, x2, ..., xk : f (x1, x2, ..., xk) < g (max { x1, x2, ..., xk }).
b) Chứng minh rằng nếu f là một hàm đệ quy nguyên thuỷ, thì tồn tại một số nguyên i sao
cho Ai làm tăng f.
c) Chứng minh rằng A không làm tăng một hàm Ai nào khác.
8. Tập hợp k các hàm đệ quy bộ phận đã cho là đếm được. Ký hiệu gi là hàm thứ i của k. Hãy
chứng minh định lý Kleene về sự tham số hoá (parameterrization) như sau :
∀ n, p, tồn tại hàm đệ quy snp : Νn + 1 → Ν sao cho : ∀x1, x2, ..., xn+p và ∀ i :
gi (x1, x2, ..., xn+p) = gj (xn+1, xn+2, xn+p)
với j = snp (i, x1, x2, ..., xn).
Định lý đệ quy của Kleene : Xét hàm h được định nghĩa như sau :
h (j, x) = gr (x) nếu gj (j) = r xác định
= không xác định nếu không phải.
Cho i là số thứ tự của h, và k là số thứ tự của s11. Hãy kiểm tra rằng :
gi (i, x) = ggk (i, j) (x)
1
gk (i, j) = gs (j) với s = s1 (k, i)
Với mọi hàm đệ qui f, người ta kết hợp f với số nguyên p là số thứ tự của phép hợp thành
của f và gs, gia sử n = gs (p).
Chứng minh rằng ∀x : gn (x) = gf (n) (x).
CHƯƠNG 5
Có vẻ khác thường khi ta đưa vào kiểu nhận biết mới tương đương với kiểu nhận
biết trước đây. Tuy nhiên, việc đưa kiểu nhận biết mới này đã được chứng minh vì
rằng ta sẽ nghiên cứu tiếp theo đây về các máy Turing luôn luôn dừng.
Định nghĩa 5.3 :
Một ngôn ngữ là liệt kê đệ quy nếu tồn tại một máy Turing với các trạng thái dừng
nhận biết nó.
Một ngôn ngữ là đệ quy nếu tồn tại một máy Turing với các trạng thái dừng có
một tính toán dừng cho mọi dữ liệu vào và nhận biết ngôn ngữ đó.
Rõ ràng, nếu T = <S, Q, P, A> là một máy Turing (đơn định) với trạng thái dừng
có một tính toán dừng cho mọi dữ liệu vào, thì với một dữ liệu f, sẽ chỉ có hai trường
hợp sau đây xảy ra :
− Tính toán hợp thức dừng và dẫn đến một trạng thái không thuộc A.
− Tính toán hợp thức dừng và dẫn đến một trạng thái thuộc A.
Cần phải chú ý rằng, sự kiện một máy Turing thỏa mãn hay không thỏa mãn điều
kiện có một tính toán dừng cho mọi dữ liệu vào không có mặt trong định nghĩa của
máy Turing này. Và, không tồn tại một phương pháp có tính hệ thống nào (nghĩa là
có hiệu lực cho tất cả các máy Turing) cho phép biết được là điều kiện này có thỏa
mãn hay không.
Ta sẽ ký hiệu RE là họ tất cả các ngôn ngữ liệt kê đệ quy, và R là họ tất cả các
ngôn ngữ đệ quy.
Mệnh đề 5.3 :
Họ R là đóng đối với phép bù (complement).
Chứng minh :
Dễ thấy rằng nếu T = <S, Q, P, A> là một máy Turing đơn định với các trạng thái
dừng nhận biết ngôn ngữ L, thì T’ = <S, Q, P, Q\A> là một máy Turing (đơn định)
với trạng thái dừng nhận biết phần bù của L.
Mệnh đề 5.4 :
Nếu một ngôn ngữ L và phần bù S*\L của nó đều là liệt kê đệ quy, thì chúng cũng
là các ngôn ngữ đệ quy.
Chứng minh :
Cho T là một máy Turing nhận biết L và giả sử T’ là một máy Turing nhận biết
*
S \L. Xuất phát từ T và T’, xây dựng một máy Turing thứ ba T” theo cách sau đây :
Máy Turing T” có hai băng và được khởi động bằng cách chép lại dữ liệu vào f từ
băng thứ nhất lên băng thứ hai. Sau đó, T” mô phỏng cách tính toán của T trên băng
thứ nhất và cách tính toán của T’ trên băng thứ hai bằng cách thực hiện lần lượt một
bước tính toán trên băng thứ nhất rồi lại một bước tính toán trên băng thứ hai. T”
dừng ngay khi sự mô phỏng một trong hai máy dẫn đến một cấu hình dừng.
Nếu đó là T, thì T” dừng trong một trạng thái qh . Nếu đó là T’, thì dừng trong
1
một trạng thái qh .
2
80 Lý thuyết tính toán
Một câu f là dữ liệu đã cho hoặc thuộc L, hoặc thuộc S*\L, hoặc T, hoặc T’ dừng
trên dữ liệu f, do vậy T” dừng trên mọi dữ liệu vào.
Bằng cách lấy qh1 như là một trạng thái dừng duy nhất, T” nhận biết L là một
ngôn ngữ đệ quy. Tương tự S*\L cũng là đệ quy : ngôn ngữ bù này được nhận biết
bởi T” với một trạng thái dừng duy nhất qh .
2
phân cấp, sau câu đã liệt kê và T’ dừng nếu f không có mặt trong một trạng thái loại
bỏ (T’ dừng trong một trạng thái dừng khi xảy ra sự bằng nhau).
Rõ ràng, máy T’ dừng cho mọi dữ liệu và nhận biết L.
“⇒” (L ∈ R ⇒ tồn tại một máy Turing liệt kê L trong thứ tự phân cấp)
Cho T là một máy Turing dừng cho mọi dữ liệu và nhận biết L. Từ T, xây dựng
một máy Turing T’ liệt kê L theo cách như sau :
T’ có nhiều hơn T hai băng. Trên một băng này, tất cả câu của S* được liệt kê
(trong thứ tự phân cấp). Còn trên băng kia dùng làm băng ra, tất cả các câu của L
được liệt kê. Với mỗi câu được liệt kê f ∈ S*, T’ sao chép lại câu này trên băng mà
trong T, đó là băng chứa dữ liệu.
Máy T’ sẽ mô phỏng hoạt động của T trên dữ liệu nà. Nếu T dừng cho dữ liệu f
trong một trạng thái thừa nhận, thì T’ ghi câu f lên băng ra theo sau ký tự đánh dấu.
Trong mọi trường hợp, T’ bắt đầu trở lại việc đánh số các câu của S*.
Vậy, rõ ràng máy T’ mô phỏng L trong thứ tự phân cấp.
“⇒” (L ∈ RE ⇒ tồn tại một máy Turing liệt kê L)
Nếu ta sử dụng cách chứng minh vừa mới trình bày trên đây thì sẽ không nhận
được kết quả, vì rằng máy Turing nhận biết L khi không dừng cho một câu bị loại bỏ
sẽ không cho phép chuyển qua câu tiếp theo, mà câu này có thể ∈ L.
Như thế, ta phải sử dụng cách chứng minh phức tạp hơn như sau :
Cho T là một máy Turing nhận biết L. Từ T, xây dựng một máy Turing T’ liệt kê L
theo cách như sau :
T’ có nhiều hơn T hai băng. Trên một băng này, liệt kê tất cả các cặp (f, n) trong
đó f là một câu ∈ S* và n là một số nguyên. Còn trên băng kia dùng làm băng ra, liệt
kê tất cả các câu của L. Với mỗi câu f đã liệt kê ∈ S*, T’ sao chép câu này lên băng
mà trong T, đó là băng chứa dữ liệu. T’ mô phỏng n bước tính toán của T trên dữ liệu
này. Nếu T dừng với dữ liệu f sau n bước tính toán, T’ ghi câu f lên băng ra phía sau
ký tự đánh dấu, và trong mọi trường hợp, T’ lại tiếp tục đánh số các cặp.
Dễ dàng kiểm chứng rằng máy T vừa mô tả liệt kê L trong thứ tự phân cấp.
Mệnh đề 5.5 :
Ngôn ngữ Lu sau đây không là đệ quy :
Tu" (<w, f>) = gi (f) với gi là hàm được tính bởi máy Turing thứ i.
Mặt khác, ta cũng nhớ lại rằng hàm th, xác định trên mọi cặp số nguyên i, j, cho
bởi định nghĩa sau đây không là T-tính được :
th (i, j) = 1 nếu máy Turing thứ i dừng trên dữ liệu j.
th (i, j) = 0 nếu không phải.
Do miền xác định của hàm được tính bởi máy Turing vạn năng Tu" là Lu, nên Tu"
sẽ nhận biết L. Vậy, Lu ∈ RE.
Mặt khác, ta có thể dễ dàng suy ra rằng hàm th không là T−tính được và
Lu ∉ R. Thật vậy, nếu không phải như thế, bằng phản chứng, xuất phát từ một máy
Turing T có trạng thái dừng dừng cho mọi dữ liệu vào và nhận biết Lu, ta xây dựng
một máy Turing T’ thực hiện hàm th. Chỉ cần mở rộng các tính toán của T thành hàm
với trạng thái dừng : nếu trạng thái này thuộc về tập hợp các trạng thái thừa nhận của
T, phép tính toán được mở rộng bằng cách xóa kết quả của T rồi ghi thành hằng 1.
Nếu không phải như vậy thì xóa kết quả của T rồi ghi thành hằng 0.QED
Bổ đề 5.1 :
Tồn tại các ngôn ngữ không là liệt kê đệ quy.
Thật vậy, nếu không phải như vậy thì ngôn ngữ Lu sẽ là liệt kê đệ quy, và phần bù
của Lu là S*\Lu sẽ là đệ quy, nhưng điều này là không đúng QED.
Nếu ta thừa nhận luận đề Church, thì việc giải một bài toán chính là việc đưa ra
một máy Turing cho phép xác định, trong một khoảng thời gian hữu hạn, nếu quả thật
câu w ∈ LP hay w ∈ LCP. Như vậy, tồn tại một máy Turing dừng cho mọi dữ liệu và
nhận biết LP. Từ đó ta có định nghĩa sau đây.
Định nghĩa 5.5 :
Một bài toán P được gọi là quyết định được (decidable) nếu ngôn ngữ đặc trưng
LP là đệ quy.
Bài toán P được gọi là không quyết định được (undecidable) nếu LP không phải là
đệ quy.
Người ta còn gọi một bài toán P là nửa quyết định (semi−decidable) nếu ngôn ngữ
đặc trưng LP là liệt kê đệ quy (không là đệ quy).
Một trong những kết quả quan trọng nhất của Tin học cơ bản là tồn tại những bài
toán không quyết định được.
Chẳng hạn, bài toán say đây là không quyết định được :
Dữ liệu : Một cặp (w, f), w là mã của một máy Turing và f là một câu.
Câu hỏi : Máy Turing có mã w có dừng trên dữ liệu f hay không ?
Thật vậy, ngôn ngữ đặc trưng LP của bài toán này là Lu mà ta đã chỉ ra rằng, Lu
không phải là ngôn ngữ đệ quy.
Bài toán này được gọi là bài toán dừng (halting problem) của các máy Turing.
Dưới đây, ta sẽ chỉ ra đặc trưng không quyết định được của nhiều bài toán khác
nhưng có thể đưa về bài toán này một cách trực tiếp hoặc gián tiếp.
III. Thuật toán rút gọn một bài toán về bài toán
khác
Định nghĩa 5.6
Ta nói rằng bài toán A được rút gọn theo một thuật toán nào đó (gọi tắt là rút gọn)
về bài toán B nếu tồn tại một máy Turing dừng cho mọi dữ liệu và thực hiện tính hàm
f, là ánh xạ từ tập hợp các biểu diễn của các dữ liệu của bài toán A vào tập hợp các
biểu diễn của các dữ liệu của bài toán B, thỏa mãn :
w ∈ LA ⇔ f (w) ∈ LB
Trong định nghĩa này, câu theo một thuật toán nào đó (algorithmically) có nghĩa
nhờ một thuật toán, theo luận đề Church, tức là nhờ một máy Turing.
Người ta nói rằng máy Turing như vậy rút gọn bài toán A về bài toán B.
84 Lý thuyết tính toán
Ta có mệnh đề sau :
Mệnh đề 5.7 :
Nếu một bài toán A được rút gọn thành bài toán B, thì nếu B là bài toán quyết định
được, thì A cũng là bài toán quyết định được.
Chứng minh :
Thật vậy, giả sử T là một máy Turing luôn luôn dừng và nhận biết LB, T’ là một
máy Turing thực hiện việc rút gọn từ bài toán A về bài toán B. Rõ ràng, máy Turing
T’ next T là một máy Turing luôn luôn dừng và nhận biết LA.
Thực tế, người ta sử dụng mệnh đề trái lại như sau :
Mệnh đề 5.8 :
Nếu bài toán A được rút gọn thành bài toán B, thì nếu A là một bài toán không
quyết định được, thì B cũng là một bài toán không quyết định được.
Ví dụ 5.1 : Bài toán dừng đều (uniform halting problem) của các máy Turing.
Người ta gọi bài toán dừng đều của các máy Turing là bài toán như sau :
Dữ liệu : Một máy Turing M.
Câu hỏi : M có dừng cho mọi dữ liệu vào ?
Bây giờ ta rút gọn bài toán dừng của các máy Turing về bài toán mới này.
Giả sử T là một máy Turing và f là một câu, hợp thành một trường hợp cá biệt
(instance) của bài toán dừng của các máy Turing. Xuất phát từ (T, f), xây dựng một
máy Turing M đọc dữ liệu của T và dừng trong một trạng thái loại bỏ nếu dữ liệu này
không phải là câu f. Sau đó, nếu dữ liệu đúng là f, thì M bắt chước cách tính toán của
T trên dữ liệu f. Rõ ràng, T dừng trên dữ liệu f nếu và chỉ nếu M dừng trên mọi dữ
liệu.
Sau khi rút gọn một bài toán không quyết định được về bài toán dừng đều của các
máy Turing, người ta suy ra rằng bài toán dừng đều của các máy Turing là không
quyết định được.
Các bài toán không quyết định được 85
Chú ý :
Cho A là một bài toán, nếu thay đổi cách biểu diễn dữ liệu nhưng vẫn giữ nguyên
câu hỏi, thì ta nhận được bài toán A’.
Nếu cách biểu diễn dữ liệu được thay đổi như sau :
- Tồn tại một máy Turing T, xuất phát từ cách biểu diễn của cùng phần tử của bài
toán A, trả về một biểu diễn của cùng phần tử đó của bài toán A’.
- Tồn tại một máy Turing T’, xuất phát từ cách biểu diễn một phần tử của bài
toán A’, trả về một biểu diễn của cùng phần tử đó của bài toán A.
Thì khi đó, A và A’ đồng thời là quyết định được hoặc không quyết định được.
Thật vậy, bài toán A được rút gọn theo một thuật toán nào đó về bài toán A’ tương
ứng với máy Turing A, và ngược lại A’ được rút gọn về A tương ứng với Turing T’.
Đặc trưng quyết định được hay không quyết định được của một bài toán vẫn là
không thay đổi khi thay đổi, trong phạm vi hợp lý, sự biểu diễn của các dữ liệu.
Người ta thường sai lầm khi chỉ định một bài toán chỉ bởi câu hỏi mà thôi. Do vậy
cần phải tránh sai lầm này.
Khi người ta xét đến độ phức tạp (complexity) của một bài toán, sự biểu diễn các
dữ liệu là tuyệt đối cần thiết để đánh giá độ phức tạp.
Bây giờ ta tiếp tục xét các bài toán không quyết định được. Chúng rất nhiều như
định lý Rice sau đây khẳng định.
Định lý Rice :
Mọi tính chất không tầm thường của các ngôn ngữ liệt kê đệ quy là không quyết
định được.
Ta nhớ lại rằng một tính chất được nói là tầm thường (trivial) nếu tất cả các phần
tử của tập hợp đang xét đều cùng có tính chất này, hoặc không một phần tử nào trong
chúng có tính chất này cả.
Định lý Rice có nghĩa là nếu P là một tính chất không tầm thường, thì bài toán sau
đây là bài toán không quyết định được :
Dữ liệu : Một máy Turing (nhận biết một ngôn ngữ liệt kê đệ quy).
Câu hỏi : Ngôn ngữ này có tính chất P không ?
Chứng minh
Cho P là một tính chất không tầm thường và J là họ các ngôn ngữ liệt kê đệ quy
có tính chất P. Ta có thể luôn luôn giả thiết rằng ngôn ngữ trống (∅) không thuộc J.
Khi đó, tồn tại ít nhất một ngôn ngữ L ≠ f và L ∈ J, L được nhận biết bởi một máy
Turing TL.
Xuất phát từ một dữ liệu <w, f>, trong đó w là mã của một máy Turing T và f là
một dữ liệu cho máy này, và xuất phát từ TL, xây dựng một máy Turing T’ thực hiện
các phép toán sau đây : trên mọi dữ liệu g, T’ mô phỏng tính toán của T trên f, độc lập
với dữ liệu g, rồi khi thành công, T’ thực hiện tính toán của TL trên dữ liệu g.
86 Lý thuyết tính toán
Rõ ràng T’ nhận biết được hoặc ngôn ngữ trống, nếu T không dừng trên f, hoặc
ngôn ngữ L, nếu T dừng trên f. Do đó, ngôn ngữ nhận biết bởi T’ là trong J nếu và chỉ
nếu T có một tính toán và dừng trên dữ liệu f.
Nếu ta giả thiết rằng tính chất đang xét là quyết định được, ta có một máy Turing
luôn luôn dừng và xác định nếu ngôn ngữ nhận biết bởi T’ là thuộc J. Từ đó suy ra
tồn tại một máy Turing luôn luôn dừng và, xuất phát từ một dữ liệu <w, f>, trong đó
w là mã của một máy Turing T, máy này xác định nếu T dừng hoặc không dừng trên
dữ liệu vào f.
Tuy nhiên, ta biết rằng một máy Turing như vậy (dừng trên mọi dữ liệu và nhận
biết Lu) là không tồn tại QED.
Ngoài các bài toán không quyết định được này, theo định lý Rice, còn rất nhiều
bài toán khác đến từ các miền xác định khác nhau, đều không quyết định được. Chính
vì vậy mà khái niệm về bài toán không quyết định được đóng vai trò quan trọng trong
tin học lý thuyết.
Bây giờ ta đưa ra bốn ví dụ cổ điển. Mỗi lần đưa ra một bài toán không quyết định
được, ta tìm cách rút gọn về bài toán đã xét.
Ví dụ 5.2 :
1. Bài toán tương ứng Post (Post’s correspondence problem)
Dữ liệu : Một dãy các cặp câu (u1, v1), ..., (uk, vk) trên một bảng chữ S
(S có ít nhất 2 ký tự).
Câu hỏi : Tồn tại hay không một câu w∈ S* thừa nhận hai phân tách
tương ứng với : w = ui ui ...ui = vi v i ... v i ?
1 2 r 1 2 r
Trong đó i1 , i2 , ..., ir ∈ { 1, 2, ..., k }
1bis. Bài toán tương ứng Post cải biên (Post’s correspondence problem)
Dữ liệu : Một dãy các cặp câu (u1, v1), ..., (uk, vk) trên một bảng chữ S
(S có ít nhất 2 ký tự).
Câu hỏi : Tồn tại hay không một câu w∈ S* thừa nhận hai phân tách
tương ứng với phần tử đầu tiên là cặp đầu tiên :
w = u1ui ...ui = v1vi ... vi ?
2 r 2 r
Giả sử cho S = {a, b, c} và cho dãy các cặp câu trên S :
((ab, aba), (ab, ba), (bab, ba), (ab, bab)).
Dễ dàng thấy rằng câu babababab được phân tách thành hai cách :
bab.ab.ab.ab = ba.ba.ba.bab
là tương ứng với nhau. Tuy nhiên, không có câu được phân tách thành hai cách tương
ứng với phần tử đầu tiên là cặp đầu tiên.
Như vậy, với dữ liệu này (là dãy các cặp câu đã cho), bài toán tương ứng Post
thừa nhận (ít nhất) một lời giải. Thế nhưng, cũng với dữ liệu này, thì bài toán Post cải
biên lại không có lời giải.
Các bài toán không quyết định được 87
Bây giờ ta sẽ chứng minh rằng cả hai bài toán này đều không quyết định được
bằng cách bắt đầu từ bài toán thứ hai.
Giả sử T = < S, Q, P> là một máy Turing tiêu chuẩn hóa (rormalized) có một
trạng thái dừng qh duy nhất. Xuất phát từ T, ta định nghĩa một tập hợp F1 các cặp câu
trên y = S ∪ Q ∪ { }, với là một ký tự mới, được cấu thành như sau :
FT = { (qxz, yq’z) | z ∈ S và q, x → y, R, q’ }
1
∪ { (qx , yq’# ) | q, x → y, R, q’ },
FT = { (zqx, q’zy) | z ∈ S và q, x → y, L, q’ }
2
∪ { qx, q’#y) | q, x → y, L, q’ },
FT = { (z, z) | z∈S} ,
3
FT = { (zqh, qh), (qh, qhz) | z ∈ S } ∪ { ( qh , ) }
4
Ứng với mỗi trường hợp cá biệt của bài toán dừng của các máy Turing, nghĩa là
với mọi dữ liệu của bài toán này, được cấu thành từ T là máy Turing tiêu chuẩn hóa
theo giả thiết và f là câu xuất phát trên băng vào của T, ta có thể kết hợp một dữ liệu
FT, f cho bài toán tương ứng Post cải biên được cấu thành từ cặp đầu tiên ( , q1f )
và các cặp của FT.
Ta sẽ chỉ ra rằng trường hợp cá biệt này của bài toán tương ứng Post cải biên có
một lời giải nếu và chỉ nếu T có một tính toán dừng trên dữ liệu f.
Nếu T có một tính toán dừng trên dữ liệu f, tính toán được viết như sau :
co = q1f, c1, ..., cn = g1qhg2
Ta xét câu sau :
w = q1f c1 ... cn-1 g1qhg2 g’1qhg2 ... qhg2 qhg’2 ... qh
trong đó câu g1 bị cắt cụt một ký tự cuối cùng, sau mỗi ký tự ; tiếp đến g2 bị cắt cụt
một ký tự phía đầu, sau mỗi .
Dễ dàng thấy rằng câu w này có hai cách phân tách tương ứng với nhau.
Ngược lại, nếu ta có hai cách phân tách một câu sao cho tương ứng với nhau với
đầu câu là cặp đầu tiên, dễ dàng thấy rằng nếu ci là một cấu hình, và nếu trong cả hai
cách phân tách mà cấu hình theo các u có độ dài hơn cấu hình theo các v của các
thành phần ci , thì khi phân tách theo các u cho đến khi gặp tiếp theo, cấu hình này
có độ dài lớn hơn cấu hình theo các v của thành phần ci+1 .
Hơn nữa, tham đối sơ cấp về số các ký tự chỉ ra rằng cặp cuối cùng đã sử dụng
là ( qh , ). Dễ dàng thấy rằng khi qh xuất hiện lần đầu tiên trong câu thuộc về hai
cách phân tách, qh được bao bởi các câu g1 và g2 sao cho nếu tồn tại một tính toán
hợp thức trong T :
q1f Ã−* g1qhg2
88 Lý thuyết tính toán
Do tính toán hợp thức dẫn đến trạng thái qh, cho nên T sẽ dừng.
Như vậy, ta đã rút gọn bài toán dừng của các máy Turing về bài toán tương ứng
Post cải biên.
Bây giờ giả sử (u1, v1), ..., (uk, vk) là dãy các cặp câu trên một bảng chữ S, tạo
thành một dữ liệu cho bài toán tương ứng Post cải biên. Giả sử a là một ký tự mới.
Với mọi câu f ∈ S*, ta kết hợp các câu p(f) và d(f) được định nghĩa bởi :
nếu f = x1, x2 ... xr, thì p(f) = ax1ax2 ..., axr và
d(f) = x1ax2a ..., xra.
Với mọi dữ liệu cho bài toán tương ứng Post cải biên, ta kết hợp tập hợp U gồm
các cặp như sau :
U = { (p(u1), d(v1)), ..., (p(uk), d(vk)), (p(u1)a, d(v1)), ...,
(p(uk)a, d(vk)), (p(u1), ad(v1)) }
tạo thành một dữ liệu cho bài toán tương ứng Post.
Nếu w = u1ui ...ui = v1vi ... vi là một lời giải của bài toán tương ứng Post cải
2 r 2 r
biên xuất phát, thì rõ ràng, câu p(w)a = ad(w) có hai cách phân tách tương ứng với
nhau theo U :
p(w)a = p(u1)p(ui ) ... p(uir)a = ad(v1) d (vi ) ... d (vi ).
2 2 r
Ngược lại một cách tương ứng, nếu một câu m có hai cách phân tách tương ứng
với nhau theo U, thì cặp đầu tiên sử dụng đến sẽ chỉ có thể là cặp :
(P (u1), ad (v1)).
Bằng cách xóa tất cả chữ a trong m và hai phân tách của m, ta nhận được câu w và
hai phân tách của w tương ứng với nhau dựa theo dãy xuất phát của bài toán tương
ứng Post cải biên, với thành phần đầu tiên là cặp đầu tiên. Như vậy, bài toán tương
ứng Post cải biên đã được rút gọn về bài toán tương ứng Post.
2. Bài toán zero trong các ma trận 3 x 3 hệ số trong Z
Dữ liệu : Một tập hợp hữu hạn M các ma trận hệ số 3´3 trong Z.
Câu hỏi : Tồn tại hay không một tích hữu hạn M = Mi M i ... Mi các ma trận của
1 2 r
M sao cho phần tử (3, 2) của M là bằng 0 ?
Cho bảng chữ có thứ tự S với |S| = n, với mọi câu f ∈ S*, ta ký hiệu như sau :
el (f) = n|f| (|f| là độ dài của câu f)
nu (f) = số thứ tự của f trong thứ tự phân cấp.
Rõ ràng, với mọi câu f, g ∈ S*, ta đều có :
el (fg) = el (f) × el (g)
nu (fg) = nu (f) × el (g) + nu (g)
Bây giờ xét ánh xạ j từ S* × S* vào tập hợp các ma trận hệ số 3´3 trong Z được
xác định như sau :
Các bài toán không quyết định được 89
4. Bài toán về tính kết hợp của một luật cấu thành
Dữ liệu : Một luật cấu thành bên trong của một tập hợp, đệ quy hoàn toàn.
Câu hỏi : Có phải luật này là kết hợp ?
Giả sử T = <S, Q, P> là một máy Turing và f là một dữ liệu của T.
90 Lý thuyết tính toán
Tương tự bài toán 3 đã xét, ta đánh số trên Z các ô của băng làm việc của T kể từ
0 là ô nằm dưới đầu đọc tại vị trí xuất phát của T. Xuất phát từ T và f, xây dựng các
hàm ϕ và s như sau :
ϕ:Ν→Z
s:Z→N
Với ϕ(n) là số thứ tự của ô nằm dưới đầu đọc sau n bước tính toán của T trên dữ
liệu vào f.
Theo quy ước, nếu việc tính toán này là dừng sau p bước trên ô có đánh số thứ tự
1, thì tất cả các hạng của dãy có số thứ tự lớn hơn p sẽ có giá trị 1.
s(z) = µn [ϕ(n) = z]
nghĩa là s(z) là số bước tính toán cần thiết nhỏ nhất để thăm ô có số thứ tự là z. Hàm s
là hàm bộ phận : một số ô trên băng có thể không bao giờ được đầu đọc đến thăm.
Cuối cùng, ta định nghĩa ánh xạ ⊕ từ N × N → N như sau :
⊕ (n, m) = s (j (n) + j (m)) nếu số này xác định
=0 nếu số này không xác định
Ánh xạ ⊕ là một luật cấu thành bên trong của N và là đệ quy hoàn toàn.
Như vậy, ta có thể dễ dàng chứng minh được rằng, nếu :
Imϕ = [-k, +k] với k ≥ 1,
thì ⊕ không có tính kết hợp, và cũng chứng minh được rằng, nếu :
Imϕ = [-∞, +∞],
thì ⊕ là có tính kết hợp.
Bây giờ ta xem xét một dữ liệu cho bài toán dừng của các máy Turing, nghĩa là
một máy T và một câu f. Xuất phát từ T, ta xây dựng một máy T’ thực hiện các phép
tính sau đây : một cách tương hỗ, T’ mô phỏng một bước tính toán của máy T, rồi thì,
trong khi không làm thay đổi nội dung của băng, T’ đi từ trái qua phải đến một ô khác
mà T’ chưa xử lý ở bước trước đó.
Như vậy, trên f, nếu việc tính toán của T, và cũng là của T’, mà dừng, thì các ô đã
được thăm bởi T’ khi tính toán sẽ có các số thứ tự [-k, +k]. Còn nếu như việc tính toán
vừa xét không dừng, thì số thứ tự sẽ là [-∞, +∞].
Bằng cách áp dụng vào T’ và f để xây dựng một luật ⊕ như vừa mô tả trên đây, ta
nhận được kết quả là luật ⊕ có tính kết hợp nếu và chỉ nếu T có một tính toán dừng
trên dữ liệu f. Như vậy, ta đã rút gọn bài toán dừng của các máy Turing về bài toán
tìm tính kết hợp của một luật cấu thành.
Ngoài các bài toán trên, các bài toán sau đây cũng là không quyết định được :
- Bài toán thứ 10 của Hilbert
(một đa thức nhiều biến có nghiệm nguyên không ?)
- Tính đúng đắn (truthfulness) của các công thức số học bậc một.
- Bài toán Thue và nửa−Thue về các câu có cấu trúc đại số bất kỳ.
Các bài toán không quyết định được 91
- Bài toán về tính bằng nhau (equality) của các ngôn ngữ được sinh ra bởi hai
văn phạm đại số (algebra grammars), hay bài toán về tính nhập nhằng
(ambiguity) của một văn phạm đại số.
− v, v...
92 Lý thuyết tính toán
Bài tập
1. Chứng minh rằng ngôn ngữ L là RE nếu và chỉ nếu L là ảnh của N bởi một hàm
đệ quy bộ phận.
2. Xuất phát từ một máy Turing T nhận biết một ngôn ngữ L đã cho và từ một máy
Turing T’ nhận biết phần bù S*\L, xây dựng một máy Turing không đơn định đơn
giản cho phép nhận biết L hoặc S*\L tùy theo một trạng thái thừa nhận đã chọn.
Từ đó suy ra một cách chứng minh mới rằng nếu L và S*\L là các ngôn ngữ liệt kê
đệ quy, thì chúng cũng là các ngôn ngữ đệ quy.
3. Phát biểu bài toán dừng của một máy RAM.
Chứng minh bài toán này là không quyết định được.
4. Chứng minh rằng bài toán sau đây là không quyết định được :
Dữ liệu : Một máy RAM M được xác định bởi chương trình của nó, một dữ liệu
vào f cho máy RAM này và một số nguyên j.
Câu hỏi : Việc tính toán của M trên f có sử dụng đến lệnh thứ j không ?
5. Chứng minh rằng bài toán sau đây là không quyết định được :
Dữ liệu : Một máy RAM M được xác định bởi chương trình của nó và một số
nguyên j.
Câu hỏi : Tồn tại hay không một dữ liệu f để việc tính toán của M trên f sử dụng
đến lệnh thứ j ?
6. Gọi gi là hàm được tính bởi máy Turing thứ i. Các bài toán sau đây có là quyết
định được hay không ?
a) Dữ liệu : Cho trước một số nguyên i.
Câu hỏi : gi có phải là một hàm không ?
b) Dữ liệu : Cho trước ba số nguyên i, j, k.
Câu hỏi : gi (j) = k ?
c) Dữ liệu : Cho trước hai số nguyên i, k.
Câu hỏi : Có tồn tại hay không một số nguyên j sao cho gi (j) = k ?
d) Dữ liệu : Cho trước hai số nguyên i, j.
Câu hỏi : Có phải gi = gj ?
e) Dữ liệu : Cho trước một số nguyên i.
Câu hỏi : Có phải hàm gi có một ảnh hữu hạn.
CHƯƠNG 6
Trong chương trình này, ta tập trung xem xét những vấn đề liên quan đến các bài
toán quyết định được. Nếu tồn tại một thuật toán giải một bài toán đã cho, thì có thể
xảy ra rằng chưa chắc đã triển khai được thuật toán đó trên một máy tính, vì lý do độ
phức tạp tính toán.
Trong thực tế, độ phức tạp của một thuật toán bắt nguồn từ thời gian tính toán và
bộ nhớ cần sử dụng đến có thể rất lớn. Nhờ những lập luận đơn giản, ta sẽ chỉ ra làm
cách nào để có thể phân lớp các bài toán quyết định được thành những bài toán ít
nhiều phức tạp hơn, không phụ thuộc vào hiện trạng của công nghệ Tin học.
Có nhiều cách đo độ phức tạp tính toán đã được nghiên cứu, đó là độ phức tạp
trung bình, độ phức tạp trong trường hợp xấu nhất, v. v... Dưới đây, ta sẽ chỉ xét độ
phức tạp tính toán trong trường hợp xấu nhất.
Tương tự, ta xét một máy Turing off-line đơn định có k băng và dừng với mọi dữ
liệu. Từ một cấu hình xuất phát (1, q1, f), máy này có một tính toán trên f và dừng.
Trong quá trình tính toán, máy Turing di chuyển các đầu đọc-ghi của nó, mỗi một đầu
đọc-ghi đến thăm một số ô phân biệt.
Bây giờ ta xét tập hợp Ln của tất cả các câu f có cùng một độ dài n. Với mỗi số
nguyên n, ta cho kết hợp với số nguyên :
S (n) = Maxf∈L
n
là số các ô đã được thăm trên các băng làm việc khi tính toán để nhận biết f .
Nếu Ln = ∅, ta đặt S (n) = 0
Hàm S : N → N vừa định nghĩa xác định độ phức tạp về bộ nhớ (space
complexity) S(n) của máy Turing 0ff-line k băng. Người ta nói rằng ngôn ngữ được
nhận biết bởi máy Turing có một độ phức tạp về bộ nhớ nhiều nhất là S(n).
Chú ý rằng khi xét độ phức tạp về bộ nhớ, người ta không xét không gian nhớ sử
dụng trên băng đọc : không gian nhớ này đúng bằng độ dài n của câu cần nhận biết.
Vì nếu không, người ta sẽ không thể nhận được hàm S(n).
Sau đây, ký hiệu I (x) là phần nguyên của x, ta viết :
T (n) = f (n) hàm T (n) được tăng lên max { n+1, I (f (n)) + 1 }
S (n) = f (n) hàm S (n) được tăng lên max { 1, I (f (n) + 1 }
Ví dụ 6.1 :
Cho L = { w wR | w∈ {0, 1}* và wR là câu đảo của w }
Tồn tại một máy Turing T1 có hai băng nhận biết ngôn ngữ L với chi phí về thời
gian là T(n) = n + 1. Máy này sao chép lên băng thứ hai các ký tự đã đọc trên băng
thứ nhất cho đến khi gặp ký tự rồi kiểm tra sự bằng nhau tương ứng của các ký tự
tiếp theo trên băng thứ nhất với các ký tự đã ghi trên băng thứ hai nhưng theo chiều
ngược lại.
Rõ ràng, thời gian tính toán đúng bằng độ dài của câu cộng thêm một thời gian
đọc ký tự # để kết thúc.
Tồn tại một máy Turing T2 có hai băng nhận biết ngôn ngữ L có chi phí về
bộ nhớ là S (n) = log2 (n). Máy này tính ghi theo hệ nhị phân trên băng thứ hai số các
ký tự đã đọc trên băng thứ nhất cho đến khi gặp ký tự C, sau đó kiểm tra số ký tự kế
tiếp ký tự này trên băng thứ nhất đúng bằng số ký tự vừa ghi trên băng thứ hai bằng
cách giảm dần từng ký tự.
Trường hợp thành công, máy kiểm tra từng đôi ký tự giống nhau cho tới một
khoảng cách i của ký tự # ở mỗi phía, và kiểm tra tất cả các giá trị i cần thiết. Các giá
trị này liên tiếp được ghi dưới dạng nhị phân trên băng thứ hai.
Rõ ràng, không gian nhớ sử dụng trên băng thứ hai được tăng thêm một lượng là
độ dài của câu dạng nhị phân, hay là logarit cơ số 2 của số nguyên này.
Độ phức tạp tính toán 95
Như vậy, đối với các máy Turing không đơn định, có thể định nghĩa theo cách
tương tự độ phức tạp tính toán không đơn định về thời gian và độ phức tạp tính toán
không đơn định về bộ nhớ. Chỉ cần định nghĩa các hàm T (n) và S (n), cho trường hợp
Ln ≠ ∅, như sau:
T (n) = Maxf∈L { độ dài của tính toán ngắn nhất để nhận biết f }
n
S (n) = Maxf∈L { số các ô đã được thăm trên băng khi tính toán
n
một cách tiết kiệm nhất để nhận biết f }
Rõ ràng, các định nghĩa đã đưa ra trong trường hợp các máy Turing đơn định chỉ
là trường hợp đặc biệt của các định nghĩa về tính chất không đơn định này.
Giữa các phép đo độ phức tạp tính toán khác nhau này, ta có thể thiết lập các mối
quan hệ. Một số quan hệ dễ dàng nhận được như sau :
L ∈ DTIME (f (n)) ⇒ L ∈ DSPACE (f (n))
Thật vậy, máy Turing thăm một ô tại mỗi bước tính toán. Trường hợp xấu nhất
xảy ra khi tất cả các ô đều khác nhau.
L ∈ DSPACE (f (n)) và f (n) = log2 (n) ⇒ L ∈ DTIME (cf (n))
Thật vậy, nếu f (n) = log2 (n), tồn tại một hằng c sao cho cf(n) là lớn hơn số các
cấu hình phân biệt có độ dài tối đa là f (n) của một máy Turing đã cho.
L ∈ NTIME (f (n)) ⇒ L ∈ DTIME (cf (n)).
Thật vậy, quan hệ này đến từ việc tăng thêm số cấu hình phân biệt đối với một dữ
liệu có độ dài n. Thời gian tăng thêm là cf (n).
Sau đây là một quan hệ được cho bởi định lý Savitch.
Định lý Savitch WJ :
L ∈ NSPACE (f (n)) và f (n) = log2 (n) ⇒ L ∈ DSPACE (f2 (n)).
Chứng minh :
Thật vậy, giả sử T là một máy Turing luôn luôn dừng và nhận biết ngôn ngữ LB
một lượng thời gian đa thức. Giả sử T’ là một máy Turing thực hiện việc rút gọn hết
một lượng thời gian đa thức từ bài toán A về bài toán B. Rõ ràng, máy Turing T’ next
T luôn luôn dừng và nhận biết ngôn ngữ LA một lượng thời gian đa thức.
Một cách tương tự, ta định nghĩa khái niệm rút gọn sử dụng bộ nhớ logarit.
Định nghĩa 6.2 :
Người ta nói bài toán A được rút gọn về bài toán B cần một lượng bộ nhớ logarit
nếu tồn tại một máy Turing luôn luôn dừng cho mọi dữ liệu và thực hiện tính hàm f
sử dụng một lượng bộ nhớ theo logarit. Hàm f được xác định từ tập hợp các biểu
diễn dữ liệu của bài toán A vào tập hợp các biểu diễn dữ liệu của bài toán B, thỏa
mãn :
w ∈ LA ⇔ f (w) ∈ LB
Ta có mệnh đề sau :
Mệnh đề 6.3 :
Lớp P đóng đối với phép rút gọn sử dụng bộ nhớ logarit.
Việc chuyển một chương trình RAM thành một chương trình của một máy Turing
được thực hiện sao cho thời gian chạy của máy Turing được tính theo số bước tính
toán, là một đa thức theo thời gian chạy chương trình của máy RAM được tính theo
số các lệnh (instructions) đã thực hiện.
Tương tự, việc chuyển một công thức trong một ngôn ngữ bậc cao thành một công
thức của một máy RAM được thực hiện sao cho thời gian chạy công thức của máy
RAM được tính theo số các lệnh của RAM đã thực hiện, là một đa thức về thời gian
chạy công thức trên ngôn ngữ bậc cao, được tính theo số các lệnh đã thực hiện.
Từ đó, việc định nghĩa các lớp P và NP được dựa trên mô hình các máy Turing
nhưng không phụ thuộc chính xác vào mô hình này, và để đảm bảo rằng một ngôn
ngữ là thuộc một trong hai lớp này, chỉ cần đếm số lượng các phép toán một cách đơn
giản.
Câu hỏi : Có thể sắp xếp các việc sao cho tổng số các hình phạt là nhỏ hơn hoặc
bằng k ? Nói cách khác, với mọi hoán vị P của n số nguyên đầu tiên, ta
kết hợp một số nguyên :
⎧= ∑ ⎡ P ⎤ nãu
ú ∑ t p(r) > d p(j)
⎪ ⎣ p (j) ⎦
Pp = ⎨ j = 1, n r = 1, j
⎪= 0
⎩ nãú
u khäng
và người ta tìm một hoán vị P nếu hoán vị P tồn tại sao cho Pp = k.
3. Bài toán sắp xếp trong các thùng chứa
Dữ liệu : Cho số nguyên c (dung lượng của các thùng), n vật đặc trưng bởi các
kích thước s1, s2, ..., sn với 0 < si ≤ c và một số nguyên k.
Câu hỏi : Có thể đặt n vật vào nhiều nhất là k thùng chứa được không ?
4. Bài toán ba-lô (rucksack)
Dữ liệu : Cho một số nguyên c (kích thước ba-lô) và n vật có các kích thước lần
lượt s1, s2, ..., sn.
Câu hỏi : Có thể bỏ đầy hoàn toàn ba-lô bởi một số vật lấy từ n vật đã cho ?
5. Bài toán thỏa mãn các biểu thức boolean ở dạng chuẩn hội
Dữ liệu: Một biểu thức boolean ở dạng chuẩn hội.
Câu hỏi : Có thể gán giá trị nào đó cho các biến làm biểu thức thỏa mãn ?
6. Bài toán đường đi Hamilton
Dữ liệu: Một đồ thị G = < S, V>.
Câu hỏi : Tồn tại hay không một đường đi Hamilton (đi qua tất cả các đỉnh) trong
đồ thị đã cho ?
Nếu bài toán ba-lô có một lời giải, khi đó tồn tại một tập hợp con J thuộc khoảng
{ 1, ..., n } sao cho ∑j∈J sj = c. Ta chọn một hoán vị P sao cho tất cả các việc có chỉ
số trong J được chọn trước các việc khác.
Cả || J || việc này đều được làm xong trước ngày kết thúc của chúng, trong khi đó,
các việc khác được làm xong sau ngày kết thúc, từ đó sinh ra một hình phạt:
∑J = || J|| + 1, npP (J) = ∑J = || J|| + 1, n sP (J)
= ∑J = 1, n J ∈J
= ∑J = 1, n sJ - c = k
Như vậy, các việc được làm xong với một hình phạt nhỏ hơn hoặcbằng k, giả sử m
là số nguyên lớn nhất sao cho m việc đầu tiên được làm xong trước ngày kết thúc
chung của chúng là c. Như vậy, ta có: ∑J -- 1, m tP(J) ≤ c và hình phạt là : ∑J = m + 1, n
PP(J) ≤ k
Do ti = Pi = si, ta có
∑J - 1, m tP(J)z + ∑J - m + 1, n PP(J) = ∑J - 1,n sJ = c + k
Do đó, cả hai bất đẳng thức đều bằng nhau và các vật có chỉ số P(j) với
j = 1..m sẽ làm đầy ba-lô. Ta cần kiểm chứng rằng việc rút gọn là theo thời gian đa
thức, nghĩa là chỉ có một phép tính duy nhất là tính giá trị ∑J - 1, n sJ - c.
Rõ ràng phép tính này đòi hỏi một thời gian đa thức. Việc xây dựng bài toán sắp
đặt các việc có hình phạt sẽ là có thời gian hằng nếu số nguyên này âm, có thời gian
tuyến tính nếu số nguyên này dương.
Cho đến lúc này, ta chưa biết có bài toán nào trong sáu bài toán trên thuộc vào lớp
không P. Tuy nhiên, người ta dễ dàng chứng minh được rằng chúng đều thuộc lớp
NP.
Ví dụ 6. 2
Bài toán tô màu các đỉnh của một đồ thị là thuộc lớp NP.
Thật vậy, máy Turing không đơn định sau đây nhận biết ngôn ngữ kết hợp với bài
toán này về thời gian tuyến tính (và do vậy, là đa thức) : trong thời gian đầu, máy
Turing thực hiện tô cho mỗi đỉnh, một cách không đơn định, một màu nào đó trong số
k màu.
Sau đó, máy Turing kiểm tra việc tô màu này đã thỏa mãn chưa, nghĩa là kiểm tra
tại các mút của các cung xem các đỉnh có cùng một tô một màu không ?.
Bây giờ ta chứng minh rằng thực tế tất cả sáu bài toán trên đều có thể rút gọn kiểu
đa thức từ bài toán kia. Từ đó, cả sáu bài toán đều thuộc lớp P nếu và chỉ nếu một
trong chúng thuộc P. Ta có định nghĩa sau đây :
Định nghĩa 6.3
Một bài toán là NP-cứng (NP - Comlete) nếu nó ở trong lớp NP.
Rõ ràng, định nghĩa trên có ích vì tồn tại những bài toán NP-đầy đủ như vậy.
102 Lý thuyết tính toán
Bài tập
1. Xét ngôn ngữ L = { wcw’ | w ∈ { a, b }* và w ≠ w’ }
Chứng minh rằng L ∈ NTIME (n) ∩ DSPACE (log2 (n)).
2. Chứng minh rằng cả sáu bài toán đã nêu đều có thể rút gọn kiểu đa thức từ bài
toán này về bài toán kia.
3. Một đồ thị được gọi là đầy đủ nếu có hai đỉnh bất kỳ được nối với nhau bới một
cạnh. Đồ thị được gọi là k-đầy đủ nếu tồn tại một đồ thị con có k đỉnh là đầy đủ.
Bài toán đầy đủ k-đầy đủ như sau:
Dữ liệu : Một đồ thị G và một số nguyên k
Câu hỏi : G có phải là k-đầy đủ?
Chứng minh rằng bài toán đồ thị k-đầy đủ là bài toán NP đầy đủ.
4. Những bài toán sau đây thuộc lớp NP, thuộc lớp P, thuộc lớp NP-bộ nhớ ?
Bài toán nào là NP-đầy đủ ?
a) Dữ liệu : Một câu w biểu diễn một biểu thức Boolean.
Câu hỏi : Câu w có phải là một hằng đúng (tautology) không ?
b) Dữ liệu : Một máy Turing T trên bảng chữ { a, b }.
Câu hỏi : Có tồn tại không một câu w ∈ S* có độ dài n sao cho máy Turing
T nhận biết w hết một lượng thời gian nhỏ hơn boặc bằng n ?
c) Dữ liệu : Một máy Turing trên bảng chữ { a, b }.
Câu hỏi : Tồn tại hay không một câu có độ dài n sao cho T nhận biết
câu này về bộ nhớ nhỏ hơn hoặc bằng n ?
d) Dữ liệu : Một cặp đồ thị (G, G’).
Câu hỏi : Đồ thị G’ có đẳng cấu (isomorphic) với một đồ thị con của G hay
không ?