Tải bản đầy đủ (.doc) (29 trang)

Máy turing và tính khả quyết của thuật toán

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (516.96 KB, 29 trang )

MỤC LỤC
CHƯƠNG 1. MÁY TURING VÀ THUẬT TOÁN................................................1
1. Mô tả và định nghĩa về máy Turing..............................................................1
1.1. Mô tả phi hình thức về máy turing .....................................................................1
1.2. Định nghĩa hình thức của máy Turing (máy Turing đơn băng – Single tape
Turing machine) ........................................................................................................3
1.4. Ví dụ về máy Turing...........................................................................................4
1.5. Sơ đồ chuyển vị cho máy Turing .......................................................................5

2. Giới thiệu về máy Turing phổ dụng .............................................................6
3. Máy turing với biểu diễn thuật toán.............................................................9
3.1. Khái niệm thuật toán .......................................................................................10
3.2. Biểu diễn thuật toán một cách hình thức bằng máy Turing..............................11

CHƯƠNG 2. TÍNH KHẢ QUYẾT CỦA THUẬT TOÁN............................16
1. Tổng quan về tính khả quyết của thuật toán..............................................16
2. Luận đề Church-Turing..............................................................................17
3. Các chương trình như các bộ nhận dạng ngôn ngữ...................................18
3.1. Các chương trình và máy Turing.....................................................................20
3.2. Các hàm tính toán..............................................................................................20

4. Máy Turing và vấn đề khả quyết................................................................22
4.1. Các tập đệ quy kể được và khả quyết................................................................22
4.1.1. Một số định nghĩa...........................................................................................22
4.1.2. So sánh RE và tính khả quyết.........................................................................22
4.1.3. Tính kể được...................................................................................................22
4.2. Các ngôn ngữ đệ quy liệt kê .............................................................................24
4.2.1. Ngôn ngữ đệ quy............................................................................................24
4.2.2. Ngôn ngữ đệ quy liệt kê ................................................................................24
4.3. Các bài toán khả quyết .....................................................................................24


5. Một số vấn đề máy Turing không giải được...............................................25
5.1. Bài toán in (printing problem) và bài toán dừng(halting problem)...................25
5.2. Hàm dừng..........................................................................................................26
5.3. Entscheidungsproblem......................................................................................26

TÀI LIỆU THAM KHẢO...............................................................................28
...........................................................................................................................28


Máy Turing và tính khả quyết của thuật toán 1

CHƯƠNG 1. MÁY TURING VÀ THUẬT TOÁN
1. Mô tả và định nghĩa về máy Turing
1.1. Mô tả phi hình thức về máy turing
Khái niệm của máy Turing dựa trên ý tưởng của một người đã thực hiện một
thủ tục rất rõ ràng bằng cách thay đổi những nội dụng của một băng giấy vô hạn,
mà nó được phân thành các ô vuông có thể chứa một trong các tập hữu hạn các ký
hiệu. Người này cần nhớ một trong các tập trạng thái hữu hạn và một thủ tục được
trình bày trong nhiều bước cơ bản dưới dạng “Nếu trạng thái của bạn là 42 và ký
hiệu mà bạn thấy là ‘0’ thì thay thế nó bằng ‘1’, di chuyển một ký hiệu sang phải,
và thừa nhận rằng trạng thái 17 như một trạng thái mới của bạn”.

Trong một số mô hình, đầu đọc (head) di chuyển dọc theo băng tĩnh
(Stationary tape). Chỉ thị để được thực hiện (q1) được chỉ ra bên trong đầu đọc.
Trong mô hình này, băng trống là tất cả các ô bằng 0. Các ô vuông được tô đậm,
gồm ô đã được quét qua bởi đầu đọc, và các ô vuông được đánh dấu 1, 1, B và biểu
tượng đầu đọc, tạo thành trạng thái của hệ thống.
Một cách rõ ràng hơn, có thể hình dung một máy Turing sẽ bao gồm các
thành phần sau:
• Một băng (TAPE), hay còn gọi là một bộ nhớ vô hạn, dưới dạng một

băng gồm nhiều ô, có thể kéo dài vô hạn về phía phải. Mỗi ô trên băng có
thể chứa một ký hiệu thuộc một bộ chữ, gọi là bộ chữ trên băng (mà một
phần trong đó là bộ chữ vào, dùng cho xâu vào);
• Một đầu đọc (HEAD) di chuyển ở trên băng, ở mỗi thời điểm nhìn vào
một ô trên băng;
• Một tập hữu hạn các trạng thái, trong đó có phân biệt một trạng thái đầu
và một tập hợp các trạng thái đã được thừa nhận;
• Một hàm dịch chuyển chứa một tập hữu hạn chỉ thị cho phép cứ với mỗi
trạng thái của máy và một ký hiệu đọc được trong ô đối diện với đầu đọc,
máy sẽ thực hiện các bước như sau:
o Chuyển trạng thái
o In một ký hiệu trên băng tại ô đang duyệt (nghĩa là thay ký hiệu đọc
được trên băng bằng ký hiệu nào đó)


Máy Turing và tính khả quyết của thuật toán 2

o Dịch chuyển đầu đọc - viết (sang trái (L), sang phải (R) hoặc đứng
yên(∅))

a1

a1





a1


B

B

Băng

Đầu đọc

q

Trạng thái

Hình 1. Các bộ phận của máy Turing
• Các thao tác có thể của một máy Turing (thường gọi là các thao tác
nguyên tử - Atomic operations)
• Đọc (xác định) ký hiệu hiện tại mà đầu đọc đang trỏ tới
• Viết một ký hiệu lên ô vuông hiện tại mà đầu đọc đang trỏ tới (sau khi
xóa lần đầu tiên ký hiệu vừa được ghi ở đó)
• Di chuyển băng sang trái một ô
• Di chuyển băng sang phải một ô
• Thay đổi trạng thái
• Ngắt


Máy Turing và tính khả quyết của thuật toán 3

• Quá trình thực hiện của máy Turing có thể được mô tả như sau:
• Lúc khởi đầu, xâu vào được đặt trên băng (tận cùng bên trái). Mọi ô khác
trên băng đều chứa một ký hiệu đặc biệt, B (blank), được gọi là ký hiệu
trống. Đầu đọc trỏ vào ô thứ nhất trên băng và máy ở trạng thái đầu.

• Cứ mỗi bước trong quá trình thực hiện (xem hình 2), máy sẽ thực hiện:
o Đọc ký hiệu đối diện đầu đọc,
o Thay ký hiệu đó bằng ký hiệu tính được từ hàm dịch chuyển,
o Dời đầu đọc một ô sang trái hay sang phải theo hướng chỉ định bởi
hàm dịch chuyển,
o Đổi trạng thái hiện tại thành trạng thái tiếp theo, cho bởi hàm dịch
chuyển.
• Xâu vào là được thừa nhận khi quá trình thực hiện đối với xâu đó đạt đến
một trạng thái thừa nhận.

0

1

0

1

1

B

B

0

1

1


1

1

B

B

q

q

Hình 2. Một bước dịch chuyển

1.2. Định nghĩa hình thức của máy Turing (máy Turing đơn băng –
Single tape Turing machine)
Sự mô tả máy Turing một cách trực quan như ở phần 1 đã giúp chúng ta
bước đầu dễ dàng hình dung ra sự hoạt động của nó. Tuy nhiên, một sự mô tả phi
hình thức như thế là chưa đủ chặt chẽ để có thể tiến hành sự suy diễn toán học,
nhằm đi sâu nghiên cứu về máy Turing được. Bởi vậy, ta cần có một định nghĩa
hình thức về máy Turing.
Theo Hopcroft và Ullman (1979) đã định nghĩa một cách hình thức một máy
Turing như là một bộ 7- M = < Q, Γ , b, ∑ , δ , q0, F> trong đó:
• Q là một tập hữu hạn các trạng thái,


Máy Turing và tính khả quyết của thuật toán 4




Γ là bộ chữ trên băng (bộ chữ dùng trên băng),



b ∈ Γ là ký hiệu trống (ký hiệu duy nhất cho phép xuất hiện một cách vô
hạn trên băng ở bất kỳ bước nào trong quá trình tính toán),



∑ ⊆ Γ là bộ chữ vào (bộ chữ dùng cho xâu vào),



δ : Q x Γ → Q x Γ x {L, R} là một hàm bộ phận, hay còn gọi là hàm

dịch chuyển (là hàm định nghĩa các việc dịch chuyển trạng thái của máy
Turing hoặc máy trạng thái), trong đó L và R được hiểu là trái (Left) và
phải (Right)).



q0 ∈ Q là trạng thái đầu (trạng thái khởi tạo),



F ⊆ Q là tập các trạng thái thừa nhận – accepting state (hoặc trạng thái
cuối).

1.4. Ví dụ về máy Turing
Dưới đây là ví dụ về máy Turing ứng đụng trong việc chấp nhận các tập.

Ví dụ 1. Thiết kế máy Turing chấp nhận ngôn ngữ L = { 0n1n | n ≥ 1}
Khởi đầu, máy Turing chứa 0n1n bên trái nhất trên băng sau đó là vô hạn
khoảng trống Blank. Máy Turing lặp lại quá trình sau:
 M thay 0 bên trái nhất bằng X rồi chuyển sang phải tới 1 trái nhất, máy
Turing thay 1 này bằng Y rồi dịch chuyển về bên trái cho tới khi gặp X
phải nhất nó chuyển sang phải một ô (tới 0 trái nhất) rồi tiếp tục lặp một
chu trình mới.
 Nếu trong khi dịch chuyển sang phải để tìm 1 mà máy Turing gặp Blank
thì máy Turing dừng và không chấp nhận input. Tương tự, khi máy
Turing đã thay hết 0 bằng X và kiểm tra còn 1 trên băng thì máy Turing
cũng dừng và không chấp nhận input.
 Máy Turing chấp nhận input nếu như cũng không còn ký hiệu 1 nào nữa
trên băng.
Đặt máy Turing M = < Q, Γ , b, ∑ , δ , q0, F> với các thành phần :
Q = {q0, q1, q2, q3, q4}; ∑= {0, 1}; Γ = {0, 1, X, Y, B} và F = {q4}.
Ta có thể hình dung mỗi trạng thái là một câu lệnh hoặc một nhóm các câu
lệnh trong chương trình. Trạng thái q0 là trạng thái khởi đầu và nó làm cho ký hiệu
0 bên trái nhất thay bằng X. Trạng thái q 1 được dùng để tiến sang phải bỏ qua các số
0 và Y để tìm 1 bên trái nhất. Nếu M tìm thấy 1 nó thay 1 bằng Y rồi đi vào trạng
thái q2. Trạng thái q2 đưa M tiến sang trái cho tới X đầu tiên và đi vào trạng thái q 0,
dịch chuyển sang phải để tới 0 bên trái nhất và tiếp tục một chu trình mới. Khi M
tiến sang phải trong trạng thái q1, nếu B hoặc X được tìm thấy trước 1 thì input bị
loại bỏ (không chấp nhận) vì có chứa nhiều ký hiệu 0 hơn 1 hoặc input không có
dạng 0*1* .
Trạng thái q0 còn có vai trò khác. Nếu trạng thái q 2 tìm thấy X bên phải nhất
và ngay sau đó là Y thì các số 0 đã được xét hết, do đó ở trạng thái bắt đầu một chu
trình mới q0 không tìm thấy ký hiệu 0 nào để thay thành X mà chỉ gặp Y thì máy
Turing đi vào trạng thái q3 duyệt qua các Y để kiểm tra có hay không có ký hiệu 1



Máy Turing và tính khả quyết của thuật toán 5

còn lại. Nếu theo ngay sau các Y là B, nghĩa là trên băng nhập không còn ký hiệu 1
nào nữa thì máy Turing sẽ đi vào q4 (trạng thái kết thúc) để chấp nhận input. Ngược
lại input bị loại bỏ.
Ta có hàm chuyển δ được cho trong bảng sau :

Hình 4. Một máy Turing kiểm nhận {0n1n | n>=1}
Các phép chuyển hình thái của máy Turing M trên input 0011 :
q00011 ⊢ Xq1011 ⊢ X0q111 ⊢ X q20Y1 ⊢ q2X0Y1 ⊢ X q00Y1 ⊢ XXq1Y1
⊢ XXY q11 ⊢ XX q2YY ⊢ X q2XYY ⊢ XX q0YY ⊢ XXYq3Y ⊢
XXYYq3 ⊢ XXYYq4

1.5. Sơ đồ chuyển vị cho máy Turing
Chúng ta có thể biểu diễn các chuyển vị của một máy Turing một cách hình
ảnh. Một sơ đồ chuyển vị (transition diagram) bao gồm một tập các nút tương ứng
với các trạng thái của máy Turing. Một cung từ trạng thái q đến trạng thái p với
nhãn là một hoặc nhiều mục có dạng X/YD, trong đó X và Y là các ký hiệu băng, D
là một hướng (L hoặc R). Điều này có nghĩa là mỗi khi δ (q, Xi) = (p, Y, D), chúng
ta thấy nhãn X/YD trên cung từ q đến p. Tuy nhiên, trong sơ đồ của chúng ta,
hướng D được biểu diễn bằng các mũi tên chỉ sang trái ( ← ) hoặc chỉ sang phải ( →
).
Giống như các loại sơ đồ chuyển vị khác, chúng ta biểu diễn khởi trạng bằng
từ “start” và một mũi tên đi vào trạng thái đó. Kiểm trạng được chi ra bằng vòng
kép. Vì thế thông tin duy nhất của máy Turing không đọc trực tiếp được từ sơ đồ là
ký hiệu được dùng cho ô trống. Chúng ta sẽ xem như đó là B trừ khi được nói rõ.
Ví dụ 1: Hình 5 trình bày sơ đồ chuyển vị cho máy Turing ở ví dụ 1 vừa trình bày ở
trên, với hàm chuyển vị được cho trong hình 4.



Máy Turing và tính khả quyết của thuật toán 6

Hình 5. Sơ đồ chuyển vị cho một máy Turing kiểm nhận các chuỗi có dạng 0n1n

2. Giới thiệu về máy Turing phổ dụng
Máy Turing phổ dụng là một máy Turing có thể bắt chước sự hoạt động
của bất kỳ máy Turing nào. Máy Turing phổ dụng U có thể được hiểu như sau:
Với một cách mã hóa thích hợp, ánh xạ chuyển trạng thái của máy
Turing bất kỳ M và từ ω trên bảng chữ vào. Với từ đã mã hóa này máy
Turing phổ dụng U dừng khi và chỉ khi máy Turing M dừng với từ ω .

Hình 6. Máy Turing phổ dụng
Chúng ta có thể xem máy Turing phổ dụng như là mô hình toán học của máy
tính điện tử ngày hôm nay. Các máy này thực hiện công việc bằng cách mã hóa
chương trình theo ngôn ngữ bên trong được gọi là ngôn ngữ máy.
Tập các kí hiệu có thể ghi lên băng là hữu hạn nên ta có thể ký hiệu chúng
như sau: S0 = B, S1, S2, ..., Sm và có thể mã hóa bằng bộ các chữ số 1. Chẳng hạn:
B – 1, S1 – 11, S2 – 111, ..., Sm – 1m+1.
Tương tự như vậy, tập các trạng thái là hữu hạn và ta cũng có thể mã hóa
chúng như sau:
q0 – 1, q1 – 11, q2 – 111, ..., qn – 1n+1.


Máy Turing và tính khả quyết của thuật toán 7

Cuối cùng hai ký hiệu L và R cũng có thể được mã hóa L – 1 và R – 11.
Bây giờ, để mã hóa ánh xạ chuyển trạng thái của máy Turing, ta sử dụng
bảng biểu diễn ánh xạ này. Trong bảng các cột được ký hiệu bởi các ký hiệu có thể
ghi lên băng vào, các dòng được ký hiệu bởi các trạng thái. Tiếp theo, liệt kê các
phần tử của bảng theo dòng cùng với các chỉ số dòng và cột tương ứng của chúng:

Các phần tử của dòng 1, tiếp đến các phần tử của dòng 2, ... Chẳng hạn, trên một
dòng xuất hiện bộ <qi, Sj, Sk, D, qh> có nghĩa là δ (qi, Sj) = <qh, Sk, D>. Giữa các
dãy mã của các bộ 5 <qi, Sj, Sk, D, qh> có chèn hai ký hiệu 0 và giữa mã các ký hiệu
trong bộ 5 được chèn bởi một ký hiệu 0. Máy Turing M được mã hóa như vậy có ký
hiệu là [M].
Ở đây, chúng ta thừa nhận mà không chứng minh rằng: Với một máy Turing
M bất kỳ tồn tại một máy Turing tương đương chỉ có một trạng thái kết thúc. Vì
vậy, chúng ta có quyền giải thiết q0 là trạng thái đầu và q1 là trạng thái kết thúc duy
nhất của máy Turing M.
Ví dụ 2. Cho máy Turing M với ánh xạ chuyển trạng thái được cho bởi bảng sau:

q0

B

S1

<S1, R, q1>

<S1, R, q0>

q1

<S1, R, q2>

q2

<S1, R, q2>

Các phần tử của mảng được sắp xếp thành dãy dưới đây :

<q0, B, S1, R, q1> <q0, S1, S1, R, q0>
<q1, S1, S1, R, q2> <q2, S1, S1, R, q2>
Dãy này sẽ được mã hóa dưới dạng dãy số 0, 1.
[M] = 01010110110010110110110100110110110101
1100111011011010111
<q0, B, S1, R, q1> <q0, S1, S1, R, q0> <q1, S1, S1, R, q2> <q2, S1, S1, R, q2>
Nếu trên băng vào có ω = S1S1BS1, thì mã tương ứng của nó sẽ là:
[ ω ] = 1101101011
Với [M] và [ ω ] đã cho ta có thể dịch ra M và từ ω như sau:
M = < {q0, q1, q2}, {S1}, B, {S1, B}, q0, {q1}>
Trong đó:
δ (q0, B) = <S1, R, q1>,

δ (q0, S1) = <S1, R, q0>
δ (q0, S1) = <S1, R, q2>

δ (q0, S1) = <S1, R, q2>


Máy Turing và tính khả quyết của thuật toán 8

và ω =S1S1BS1
Bây giờ giả sử máy Turing M có n trạng thái trong và bảng chữ ghi lên băng
có m ký hiệu, thêm vào đó các ký hiệu, các trạng thái, và ánh xạ chuyển trạng thái
của M được mã hóa như đã nói ở trên. Mô hình hóa hoạt động của máy Turing M
bằng một máy Turing phổ dụng U có thể mô tả khái quát như sau:
Trước hết [M] và [ ω ] cần phải được ghi lên băng của máy Turing phổ
dụng U theo quy cách sau đây: Ký hiệu X được ghi lên băng, chia băng
thành 2 nửa vô hạn. Nửa băng bên phải được dành ra 3 đoạn kề nhau kể
từ vị trí ký hiệu ngay sau X: Đoạn đầu tiên được gọi là Buffer gồm n + m

+ 2 vị trí ký hiệu và tất cả đều được nhận ký hiệu 0; đoạn tiếp theo được
gọi là vùng mã hóa của M, bắt đầu bởi ký hiệu Y, tiếp sau Y là [M] và
được kết thúc bởi 3 chữ số 0 ; đoạn sau cùng được gọi là đoạn mã hóa
của ω , bắt đầu bởi ký hiêu Z và tiếp theo là [ ω ]. Hình ảnh của băng lúc
đầu như sau:

B X

0

. . .

Buffer

Y

. . .

0

0

0

Z

Mã hóa M

. . .


B B

Mã hóa

Hình 7. Hình ảnh của Băng lúc đầu
Buffer phục vụ cho việc ghi nhận nhận cấu hình của M trong từng bước.
Chúng ta có thể sao chép vào vùng này trạng thái bên trong và mã hóa
của ký hiệu đang đọc. Ký hiệu Y thường đứng trước bộ 5 xác định trạng
thái hiện hành của M, ký hiệu hiện hành hành trên băng, hướng chuyển
động của đầu đọc trên băng. Z đánh dấu ký hiệu đang đọc trên băng của
M.
Quá trình tính toán trong U mô phỏng hoạt động của máy Turing M với
xâu vào ω được chia ra các pha thích hợp với việc dịch chuyển các cấu
hình của M.
Một giai đoạn (pha) hoạt động của máy Turing phổ dụng U có thể được tóm
tắt như sau:
Đầu tiên sao chép vào buffer một khối các ký hiệu 1 nằm ngay sau Y (gọi
là khối Y), sau đó ghi vào cuối khối vừa được chép một ký hiệu X, tiếp
theo xóa ký hiệu Y, chạy sang phải tìm ký hiệu Z và sao chép khối ký
hiệu 1 ngay sau Z (gọi là khối Z) vào buffer ngay sau ký hiệu X rồi ghi
lại ký hiệu Y trước [M]. Như vậy, sau giải đoạn này, trong Buffer chứa
mã của trạng thái và ký hiệu hiện hành của máy Turing M. Bước tiếp
theo, máy Turing phổ dụng U so sánh 2 khối ký hiệu 1 liên tiếp nhau sau
Y với nội dung buffer. Nếu trùng nhau thì tìm được bộ 5 cần tìm. Nếu
ngược lại, thì tìm đến mã hóa của bộ 5 tiếp theo sau Y và lại tiếp tục so
sánh. Trong trường hợp giữa các bộ 5 mô tả M không tìm thấy bộ nào
thích hợp thì U dừng. Ngược lại, nếu tìm được bộ 5 cần tìm thì xóa nội
dung buffer rồi chuyển Y đến trước phần tử thứ 3 trong bộ 5 đó. Đổi nội



Máy Turing và tính khả quyết của thuật toán 9

dung của khối sau Z bởi nội dung của khối sau Y và chuyển Y đến trước
phần tử thứ tư của bộ 5. Sau khi đã đọc xong phần tử thứ tư mà nó xác
định hướng chuyển động của đầu đọc/ghi của M và U chuyển ký hiệu Y
đến sau phần tử trước phẩn tử thứ 5. Tùy thuộc vào nội dung của khối thứ
4 (một ký hiệu 1 hay hai ký hiệu 1) mà U sẽ chuyển Z qua phải hay qua
trái một khối. Nếu Z lúc đầu nằm ở tận cùng bên trái của băng ghi và M
cần dịch chuyển sang phải thì U đẩy mã của từ sang phải và ghi mã hóa
của ký hiệu trắng vào sau Z. Nếu Z nằm tận cùng bên phải và cần chuyển
sang phải thì khi đó U ghi mã của ký hiệu trắng vào cuối từ. Khi hoàn
thành các công việc trên khối ký hiệu 1 đứng sau Y ký hiệu trạng thái
hiện hành của M, còn khối sau Z xác định ký hiệu M cần đọc tiếp theo.
Như vậy, giai đoạn tiếp theo của việc mô phỏng bước tiếp theo của M có
thể bắt đầu.
Các giai đoạn hoạt động của máy Turing phổ dụng U mô hình hóa hoạt động
từng bước của máy Turing M như đã chỉ ra ở trên. Ngoài ra, U còn thực hiện công
việc sau đây:
Đầu tiên U thay tất cả các ký hiệu 0 trên 3 đoạn của băng vào bằng các
khoảng trắng, cuối công việc, khi M dừng máy U còn kiểm tra liệu trạng
thái cuối của M có phải là trạng thái kết thúc hay không.
Các pha của một máy Turing phổ dụng U được chia thành 9 phần như sau:
• Phần 1. Thay các ký hiệu 0 bởi ký hiệu B và đầu đọc/ghi chuyển đến
trước Y.
• Phần 2. Sao chép mã của trạng thái hiện hành vào buffer.
• Phần 3. Sao chép mã của ký hiệu cần đọc trên băng của M vào buffer.
• Phần 4. Đặt X và Y vào trước buffer và trước vị trí của [M].
• Phần 5. Tìm bộ 5 có mã của trạng thái và ký hiệu trên băng trùng với
buffer.
• Phần 6. Xóa buffer

• Phần 7. Thay mã ký hiệu đã đọc bằng mã ký hiệu mới của M.
• Phần 8. Đẩy Z sang phải hay sang trái một khối mà mã ký hiệu của khối
đó sẽ được đọc trong pha tiếp theo. Nếu cần thì ghi mã một khoảng trắng
vào phải hoặc trái từ trên băng M.
• Phần 9. Máy Turing phổ dụng U dừng ở trạng thái kết thúc khi và chỉ khi
M dừng ở trạng thái kết thúc. Đồng thời trong vùng mã hóa của từ trên
băng sẽ chứa mã của từ đáng ra còn lại trên băng của M, còn mã của
trạng thái cuối của M có thể thấy trên buffer.
Chúng ta ký hiệu <M ω > là [M] và [ ω ] được ghi trên băng của U và gọi T(U)
là ngôn ngữ được chấp nhận bởi máy Turing phổ dụng U. Chúng ta có thể nhận
thấy rằng <M ω > thuộc T(U) khi và chỉ khi ω được chấp nhận bởi M, có nghĩa là:
T(U) = {<M ω > : ω ∈ T(M)}

3. Máy turing với biểu diễn thuật toán


Máy Turing và tính khả quyết của thuật toán 10

3.1. Khái niệm thuật toán
Trong vòng 200 năm qua, vẫn chưa một một định nghĩa về thuật toán được
chấp nhận một cách rộng rãi. Tuy nhiên, phần lớn các nhà nghiên cứu trong các lĩnh
vực toán học, tính toán, và các chuyên ngành liên quan đều thống nhất rằng thuật
toán là một quá trình (một tập hữu hạn các lệnh hay phương cách được định nghĩa
rõ ràng) để hoàn thành một số tác vụ nào đó, với một trạng thái ban đầu cho trước,
khi các lệnh này được áp dụng triệt để thì sẽ kết thúc tại một trạng thái kết thúc
được đã được định nghĩa. Nói cách khác, thuật toán là một bộ các qui tắc hay qui
trình cụ thể nhằm giải quyết một vấn đề trong một số bước hữu hạn, hoặc nhằm
cung cấp một kết quả từ một tập hợp của các dữ kiện đưa vào.
Việc nghiên cứu thuật toán là một trong những lĩnh vực nền tảng của khoa
học máy tính. Thông qua việc xây dựng một chương trình máy tính nhằm giải quyết

một bài toán cụ thể, người lập trình đã biểu diễn bằng ngôn ngữ máy tính một thuật
toán giải bài toán, qua đó điều chỉnh thuật toán thành một chương trình máy tính.
Nhiều thuật toán rất hữu dụng trong nhiều ứng dụng máy tính đa dạng.
Những thuật toán cơ sở này được nghiên cứu rộng rãi và được xem là một thành
phần thiết yếu của khoa học máy tính, bao gồm các thuật toán sắp xếp, tìm kiếm, xử
lý chuỗi, đồ thị, thực hiện các phép tính toán toán học phổ biến, …
Ví dụ 3. Thuật toán để giải phương trình bậc nhất P(x): ax + b = c, (a, b, c là các
số thực), trong tập hợp các số thực có thể là một bộ các bước sau đây:
1. Nếu a = 0
o b = c thì P(x) có nghiệm bất kì
o b ≠ c thì P(c) vô nghiệm
2. Nếu a ≠ 0
o P(x) có duy nhất một nghiệm x = (c - b)/a
Knuth (1968, 1973) đã đưa ra một danh sách 5 thuộc tính được thừa nhận
rộng rãi như là các yêu cầu của một thuật toán:
o Tính hữu hạn: “Một thuật toán luôn phải dừng sau một số hữu hạn
bước … một số hữu hạn có thể chấp nhận được”. Các thuật toán cần
được tạo thành từ một tập hữu hạn các thao tác và phải hoàn thành
việc thực hiện trong một thời gian hữu hạn.
o Tính tường minh: “Từng bước của thuật toán phải được định nghĩa
chính xác, các hành động được thực hiện phải chặt chẽ và được xác
định không nhập nhằng cho từng trường hợp”. Cụ thể là bất kỳ những
bước điều kiện nào cũng phải được xử lý một cách có hệ thống theo
từng trường hợp với tiêu chí là từng trường hợp phải rõ ràng (và có
thể tính được). Ngoài ra, vì một thuật toán là một tập các thao
tác/lệnh, chúng ta phải biết trật tự đúng để thực hiện các thao tác.
Nếu trật tự không rõ ràng, chúng ta có thể thực hiện các thao tác sai
hay không chắc chắn thao tác nào sẽ được thực hiện tiếp theo.



Máy Turing và tính khả quyết của thuật toán 11

o Đầu vào: “… định lượng cần được gán lúc ban đầu trước khi thuật
toán bắt đầu. Những đầu vào này được lấy ra từ một tập các đối tượng
xác định”
o Đầu ra: “… định lượng có một quan hệ xác định với đầu ra”. Và các
thuật toán phải đưa ra các kết quả cụ thể, qua đó có thể xác định các
kết quả đó là đúng hay sai.
o Tính hiệu quả: “… tất cả các thao tác cần thực hiện trong thuật toán
phải được đảm bảo về nguyên tắc có thể được thực hiện một cách
chính xác và trong một khoảng thời gian hữu hạn”. Những thao tác
toán học như tìm căn bậc hai của một số âm sẽ là thao tác không hiệu
quả, do đó không thể được sử dụng trong các thuật toán
Thuật toán có thể được biểu diễn bằng nhiều cách, bao gồm ngôn ngữ tự
nhiên, giả mã, ngôn ngữ lưu đồ (sơ đồ khối), ngôn ngữ lập trình. Tuy nhiên, một khi
dùng ngôn ngữ lập trình thì chỉ những lệnh được phép trong ngôn ngữ đó mới có
thể dùng được và điều này thường làm cho sự mô tả các thuật toán trở nên rối rắm
và khó hiểu. Hơn nữa, vì nhiều ngôn ngữ lập trình đều được dùng rộng rãi, nên
chọn một ngôn ngữ đặc biệt nào đó là điều người ta không muốn. Vì vậy ở đây các
thuật toán ngoài việc được trình bày bằng ngôn ngữ tự nhiên cùng với những ký
hiệu toán học quen thuộc còn dùng một dạng giả mã để mô tả thuật toán. Giả mã tạo
ra bước trung gian giữa sự mô tả một thuật toán bằng ngôn ngữ thông thường và sự
thực hiện thuật toán đó trong ngôn ngữ lập trình. Các bước của thuật toán được chỉ
rõ bằng cách dùng các lệnh giống như trong các ngôn ngữ lập trình.

3.2. Biểu diễn thuật toán một cách hình thức bằng máy Turing
Máy Turing là một thành phần rất quan trọng trong nền khoa học của thế kỷ
XX, một phần vì máy Turing đóng vai trò trung tâm trong lý thuyết về tính toán và
khả năng tính toán. Đặc biệt, máy Turing không chỉ được quan tâm như là một bộ
chấp nhận ngôn ngữ mà còn cung cấp một định nghĩa nghiêm ngặt về thuộc tính

hay phương pháp.
Có thể nói các thuật toán rất cần thiết cho máy tính xử lý thông tin, vì một
chương trình máy tính cần là một thuật toán chỉ ra cho máy tính các bước cụ thể nào
cần thực hiện (theo trật tự nào) nhằm thực hiện một tác vụ cụ thể với mục đích
chính của một máy tính là biến đổi input thành output.
Thông thường, khi một thuật toán được kết hợp với thông tin xử lý, dữ liệu
được đọc từ một nguồn hay thiết bị đầu vào, được viết trên một thiết bị đầu ra,
và/hoặc được lưu trữ cho các xử lý tiếp sau. Dữ liệu được lưu trữ được xem là một
phần của trạng thái bên trong của thực thể thực hiện thuật toán. Trên thực tế, trạng
thái được lưu trong một cấu trúc dữ liệu, nhưng một thuật toán chỉ yêu cầu dữ liệu
bên trong cho các tập thao tác xác định gọi là các kiểu dữ liệu trừu tượng. Trong đó,
một kiểu dữ liệu trừu tượng được định nghĩa là đặc tả của một tập dữ liệu và tập
thao tác có thể thực hiện trên dữ liệu. Kiểu dữ liệu này trừu tượng trên khía cạnh
độc lập với các thực thi cụ thể khác nhau.
Trong khi đó, một máy Turing có thể được biểu diễn như một hệ thống thực
hiện chức năng tự động có khả năng ở một số hữu hạn các trạng thái bên trong và
được hỗ trợ bởi một bộ nhớ bên ngoài vô hạn, gọi là băng (nhập/xuất). Trong đó,
băng đóng vai trò là phương tiện lưu trữ có mục đích tổng quát của máy Turing:


Máy Turing và tính khả quyết của thuật toán 12

máy được thiết lập ở trạng thái chuyển động với các đầu vào là nội dung cụ thể thời
điểm khởi đầu băng chứa, đầu ra là nội dung cụ thể thời điểm kết thúc băng chứa,
và băng sẽ là bộ nhớ hoạt động tạm thời để lưu các kết quả của các bước trung gian
trong quá trình tính toán. Chương trình (bảng trạng thái) chỉ đạo quá trình tính cụ
thể mà máy sẽ thực hiện cũng được lưu trữ trên băng. Một chương trình nhỏ, cố
định được tích hợp sẵn trong đầu đọc sẽ hỗ trợ đầu đọc đọc và thực hiện các chỉ dẫn
của chương trình bất kỳ đang ở trên băng.
Trong bối cảnh đó, khái niệm máy Turing có thể được sử dụng để đảm bảo

mô hình hóa ý tưởng tổng quát của một thuật toán được chính xác với một bảng chữ
cái đã cho như sau:
• Input của một sự tính toán là tất cả các kí hiệu không trắng trên băng tại
thời điểm khởi đầu.
• Tại thời điểm kết thúc của sự tính toán, output sẽ là bất kì cái gì có trên
băng.

• Vậy có thể xem một máy Turing M như là một sự hiện thực của một hàm
f được định nghĩa bởi

= f(w) trong đó q0w

M

qf với qf là một trạng thái

kết thúc nào đó.
• Lúc đó, một hàm f với miền xác định D được gọi là khả tính toán-Turing
hay đơn giản là khả tính toán nếu tồn tại một máy Turing nào đó M = <
Q, Γ , b, ∑ , δ , q0, F> sao cho q0w M qf f(w), qf ∈F, ∀w ∈ D.
Ví dụ 4. Xét bài toán cộng hai số nguyên viết ở dạng nhị phân f(x, y) = x + y . Thủ
tục thực hiện phép cộng có thể dựa trên phương pháp thông thường là cộng cặp chữ
số nhị phân với nhau (có nhớ) để tính tổng của hai số nguyên.
Để cộng a và b, trước hết cộng hai bit ở phải cùng của chúng, tức là:
a0 + b0 = c0.2 + s0.
Ở đây s0 là bit phải cùng trong khai triển nhị phân của a+b, c 0 là số nhớ, nó
có thể bằng 0 hoặc 1. Sau đó ta cộng hai bit tiếp theo và số nhớ
a1 + b1 + c0 = c1.2 + s1.
Ở đây s1 là bit tiếp theo (tính từ bên phải) trong khai triển nhị phân của a+b
và c1 là số nhớ. Tiếp tục quá trình này bằng cách cộng các bit tương ứng trong hai

khai triển nhị phân và số nhớ để xác định bit tiếp sau tính từ bên phải trong khai
triển nhị phân của tổng a+b. Ở giai đoạn cuối cùng, cộng a n-1, bn-1 và cn-2 để nhận
được cn-1.2+sn-1. Bit đứng đầu của tổng là s n=cn-1. Kết quả, thủ tục này tạo ra được
khai triển nhị phân của tổng, cụ thể là a+b = (sn sn-1 sn-2 ... s1 s0)2.


Máy Turing và tính khả quyết của thuật toán 13

Triển khai thuật toán này với máy Turing, chúng ta phải quyết định các số x
và y vào lúc ban đầu được đặt như thế nào trên băng và tổng của chúng xuất hiện
như thế nào lúc kết thúc sự tính toán.
• Chúng ta giả thiết rằng w(x) và w(y) được phân cách bằng một kí hiệu ,
với đầu đọc ở trên kí tự phải cùng của w(y).

• Chúng ta vì vậy muốn thiết kế một máy Turing để thực hiện sự tính toán
(trong đó qf là một trạng thái kết thúc)
q0w(x) w(y)

M

qf w(x + y) ,

Q = {q0, q1, q2, q3,…., q9, qf}, F = {qf}

Với bảng trạng thái được cho bởi đồ thị trạng thái như sau:

• Sau khi tính toán, w(x + y) sẽ ở trên băng và được theo sau bởi một kí tự
, và đầu đọc sẽ được đặt trên kí tự phải cùng của kết quả.

Như trên, chúng ta đã thấy máy Turing có thể thực hiện được các phép toán

cơ bản và quan trọng những cái mà có trong tất cả các máy tính. Vì trong các máy
tính số, các phép toán cơ bản như vậy là các thành phần cơ bản cho các lệnh phức
tạp hơn, sau đây là một ví dụ trình bày khả năng máy Turing kết hợp các phép toán
này lại với nhau.
Giả sử chúng ta thiết kế máy Turing tính toán hàm sau:


Máy Turing và tính khả quyết của thuật toán 14

Ta xây dựng mô hình tính toán như sau:

Vấn đề xây dựng được hàm tính toán được yêu cầu của chúng ta bây giờ sẽ
được chuyển thành xây dựng các bộ so sánh, bộ cộng và bộ xóa. Điều này cũng có
nghĩa rằng bài toán phức tạp của chúng ta đã được chuyển thành kết hợp các phép
toán cơ bản.
Với khá nhiều bằng chứng mạnh mẽ tuy chưa đủ là một chứng minh chặt
chẽ, nhưng chúng ta chấp nhận miêu tả chính xác của ý tưởng tổng quát về thuật
toán trong một bộ chữ cái được thực hiện bởi máy Turing là hoàn toàn đầy đủ. Có
nghĩa rằng, đối với mọi thuật toán trong bảng chữ cái cụ thể, có thể xây dựng một
thuật toán Turing cho cùng các kết quả với cùng dữ liệu ban đầu như thuật toán .
Sự chấp nhận này được gọi là luận đề Turing trong lý thuyết thuật toán, như một
định nghĩa của một “sự tính toán cơ học”. Cụ thể,
• Bất kỳ cái gì có thể được thực hiện trên bất kỳ máy tính số đang tồn tại
nào đều có thể được thực hiện bởi một máy Turing.
• Không ai có thể đưa ra một bài toán, có thể giải quyết được bằng những
gì mà một cách trực quan chúng ta xem là một thuật toán, mà đối với nó
không tồn tại máy Turing nào giải quyết được.
• Các mô hình thay thế khác có thể được đưa ra cho sự tính toán cơ học
nhưng không có cái nào trong số chúng là mạnh hơn mô hình máy
Turing.

Bằng việc chấp nhận luận đề Turing, chúng ta sẵn sàng để định nghĩa chính
xác khái niệm thuật toán, một khái niệm cơ bản trong khoa học máy tính.
Một thuật toán cho một hàm f: D → R là một máy Turing M sao cho cho một
chuỗi nhập w∈D trên băng nhập, cuối cùng M dừng với kết quả f(w) ∈R trên băng.
Một cách cụ thể là:
q0w

M

qf f(w), qf ∈F, ∀w ∈ D.

Luận đề Turing ngay lập tức được chấp nhận rộng rãi. Thông qua việc thực
hiện các phép tính dựa trên một kế hoạch được chọn trước, các nhà khoa học đã tiến
hành theo một cách tương đương với máy Turing: xem xét một số vị trí trong bài
viết của mình và ở trong một “trạng thái trí tuệ”nhất định, họ tiến hành sửa đổi
trong bài viết của mình và được thúc đẩy bởi một “trạng thái trí tuệ” mới, sẽ
chuyển sang suy ngẫm về các phần viết sau.


Máy Turing và tính khả quyết của thuật toán 15

Tóm lại, một thuật toán có thể được xem là một chuỗi các thao tác có thể
được thực hiện bởi một hệ thống Turing-đầy đủ (Turing complete) (còn được gọi
là Turing-tương đương (Turing equivalent) hay phổ dụng ((computationally)
universal). Trong đó, một máy trừu tượng hay ngôn ngữ lập trình được gọi là
Turing-đầy đủ nếu có khả năng tính toán tương đương một mô hình được đơn giản
hóa của máy tính có khả năng lập trình, đó chính là máy Turing phổ dụng.
“Lý luận không hình thức của Turing trong luận đề của ông đã giải thích cho một
luận đề mạnh hơn: Mọi thuật toán có thể được mô phỏng bởi một máy Turing”
Gurevich (2000)

Còn theo Savage [1987], “Một thuật toán là một quá trình tính được định nghĩa
bởi một máy Turing”


Máy Turing và tính khả quyết của thuật toán 16

CHƯƠNG 2. TÍNH KHẢ QUYẾT CỦA THUẬT TOÁN
1. Tổng quan về tính khả quyết của thuật toán
Trong phần này, chúng ta sẽ tìm hiểu về một trong nền tảng khoa học cơ bản
nhất của khoa học máy tính, đó là tính khả quyết của bài toán. Đó là “Những vấn
đề nào có thể và không thể thực hiện được bởi thuật toán hay máy tính?”
Trong lý thuyết tính toán, một bài toán quyết định là một câu hỏi trong một
số hệ thống hình thức với các câu trả lời có/không. Ví dụ, bài toán “cho 2 số x và y,
x có chia hết y không?”. Câu trả lời sẽ là “có” hay “không”, phụ thuộc vào giá trị
của x và y.
Bên cạnh đó, các bài toán quyết định còn liên hệ mật thiết với các bài toán
hàm (function problem) có thể có các câu trả lời phức tạp hơn so với có/không. Một
bài toán hàm có thể là “cho 2 số x, y, tìm x có thể chia hết bởi y?”. Các bài toán
quyết định còn có thể quan hệ với các bài toán tối ưu, được xét đến với việc tìm lời
giải tối ưu cho một vấn đề cụ thể.
Trong một hướng tiếp cận mới trong vấn đề về tính khả quyết của bài toán,
những nhà khoa học quan tâm đến một họ các bài toán và tìm một thuật toán để
quyết định từng họ bài toán đó. Theo đó, vì các thuật toán là lời giải cho các bài
toán nên các phương pháp được sử dụng để giải các bài toán quyết định được gọi là
thủ tục quyết định hay thuật toán. Từ đó, một bài toán tổng quát khả quyết nếu lời
giải của nó sẽ dừng trong một khoảng thời gian hữu hạn, còn không bài toán bất khả
quyết. Chúng ta cần chú ý rằng vấn đề về tính khả quyết chỉ là một phần của lý
thuyết tính toán không quan tâm đến lượng thời gian mà một lời giải cần mà chỉ cần
khoảng thời gian đó là hữu hạn. Ví dụ, một thuật toán cho bài toán quyết định sẽ
giải thích làm cách nào để xác định x có chia hết cho y không, với x và y cho trước.

Một bài toán quyết định có thể được giải bởi một số thuật toán được gọi là khả
quyết.
Năm 1936, Church đã hình thức hóa một họ các bài toán mà ông có thể
chứng minh rằng không thể quyết định được bởi bất kỳ thuật toán nào. Để phát biểu
này có nghĩa, khái niệm toán học mới của một thuật toán phải được đưa ra. Và
Church đã sử dụng các công cụ từ logic, khái niệm các hàm đệ quy, để hình thức
hóa khái niệm về khả năng giải được về mặt thuật toán.
Trong cùng một năm khi Church công bố công trình của mình, Turing cũng
đã đưa ra khái niệm về máy Turing. Và ngày nay, chúng ta gọi những bài toán có
khả năng tính được về mặt thuật toán (algorithmic solvability) nếu chúng có thể
được tính bởi máy Turing. Tuy nhiên, các nhà khoa học đã thống nhất rằng lớp các
hàm có thể tính được bằng thuật toán trùng với lớp các hàm có thể tính được bằng
máy Turing. Nhiều mô hình tính toán khác đã được đề xuất (một số mô hình tương
đối khác với máy Turing) nhưng chúng ta vẫn chưa tìm được một mô hình máy có
thể giải quyết được nhiều vấn đề tính toán hơn máy Turing. Trong phần sau đây,
chúng ta sẽ khảo sát về luận đề Church-Turing, một luận đề nền tảng trong lý thuyết
về tính khả quyết của bài toán


Máy Turing và tính khả quyết của thuật toán 17

2. Luận đề Church-Turing
Luận đề Church-Turing đề cập đến khái niệm của một thuật toán hiệu quả
trong logic và toán học. Một thuật toán, hay thủ tục, M, cho việc thu được các kết
quả mong muốn được gọi là “hiệu quả” trong trường hợp:
• M được thiết lập với hình thức một số hữu hạn các lệnh chính xác (từng
lệnh được biểu diễn dưới dạng một số hữu hạn các ký hiệu)
• Nếu được thực hiện không lỗi, M sẽ đưa ra các kết quả mong muốn trong
một số hữu hạn bước.
Khái niệm về một thuật toán hiệu quả là một khái niệm không hình thức, và

các nỗ lực để xác định tính hiệu quả cho yêu cầu quan trọng mà thuật toán đòi hỏi
vẫn được được phát triển. Một trong những thành tựu hàng đầu của Turing – và là
bước phát triển lớn đầu tiên trong quá trình phát triển của lý thuyết tính toán – là đề
xuất một biểu thức được định nghĩa một cách nghiêm ngặt, qua đó phát biểu không
chính quy “bằng một thuật toán hiệu quả” có thể được thay “bằng một máy
Turing”. Tầm quan trọng của đề xuất Turing là ở chỗ: nếu đề xuất là chính xác, thì
việc nói về sự tồn tại và không tồn tại các thuật toán hiệu quả có thể được thay thế,
cả trong toán học và logic, bằng cách nói về sự tồn tại hay không tồn tại của các
chương trình máy Turing. Ví dụ, một người có thể thiết lập rằng không có thuật
toán hiệu quả để thực hiện một vấn đề nào đó bằng cách chứng minh rằng không có
máy Turing nào có thể thực hiện được cùng vấn đề đó.
Khái niệm hình thức được đề xuất bởi Turing là khái niệm về tính khả quyết
của máy Turing. Ông cho rằng mỗi khi có một thuật toán hiệu quả có thể thu được
các giá trị của một hàm toán học, hàm đó cũng có thể được tính bởi máy Turing.
Chúng ta cần chú ý rằng phần đảo của luận đề - bất kỳ thuật toán giải quyết vấn đề
nào có thể thực hiện bởi máy Turing đều hiệu quả - là đúng. Đó là do chương trình
máy Turing tự mình là một đặc tả của thuật toán hiệu quả, nên một người có thể, về
mặt lý thuyết, làm việc với bất kỳ một chương trình máy Turing nào, theo các lệnh
đã được định nghĩa trước và thực hiện các thao tác được yêu cầu.
Trước đó, Church cũng đã độc lập đề xuất một cách khác để thay thế cách
nói về các thuật toán hiệu quả với ngôn ngữ chính xác một cách chính quy, sử dụng
khái niệm khả năng định nghĩa-lambda (lambda-definability) thay vì “khả năng
tính được của máy Turing”. Trong đó, một hàm các số nguyên dương được gọi là
có khả năng định nghĩa-lambda nếu giá trị của hàm có thể được tính bằng một quá
trình các phép thế được lặp lại. Và ông đã sử dụng biểu diễn (phi hình thức) “có thể
tính được hiệu quả” để chỉ ra rằng có một thuật toán hiệu quả để tính các giá trị
của hàm qua đề xuất:
“Xác định khái niệm của một hàm có thể tính được hiệu quả các số nguyên
dương bằng cách xác định khái niệm đó bằng khái niệm của hàm đệ quy của các số
nguyên dương (hay với khái niệm hàm có khả năng định nghĩa-lambda các số

nguyên dương”.
Trong thực tế, Church đã đề xuất “Một hàm các số nguyên dương có khả
năng tính được hiệu quả chỉ khi là hàm đệ quy”
Sự đảo lại, rằng mọi hàm đệ quy của các số nguyên dương là có khả năng
tính được hiệu quả, thường được xem là định lý đảo của luận đề Church.


Máy Turing và tính khả quyết của thuật toán 18

Sau khi tìm hiểu đề xuất của Church, Turing nhanh chóng chứng minh được
rằng cấu trúc của khái niệm khả năng định nghĩa-lambda của Church và cấu trúc
khái niệm về khả năng tính được của ông là tương đương. Do đó, trong đề xuất của
Church, các từ “hàm đệ quy của các số nguyên dương” có thể được thay thế bởi các
từ “hàm các số nguyên dương có thể tính được bởi máy Turing”.
Và với quan điểm của các kết quả được tìm hiểu trên đây, nếu chỉ giới hạn
trong các hàm các số nguyên dương, thì luận đề của Church và của Turing đề xuất,
tuy có vẻ rất khác nhau, nhưng lại trở thành tương đương nhau, theo nghĩa là mỗi
hướng đề đưa ra chung một tập các hàm toán học. Luận đề Church-Turing là sự
khẳng định rằng tập này bao gồm mọi hàm có giá trị có thể thu được bằng một thuật
toán thỏa mãn các điều kiện trên đây cho tính hiệu quả. Tuy nhiên, cả Turing và
Church đề nhận ra rằng cách triển khai của Turing là “có sức thuyết phục hơn”
[turing] và “có ưu điểm trong việc đưa ra khả năng nhận dạng với tính hiệu quả…
hiển nhiên ngay lập tức” [Church].
Tóm lại, luận đề Church-Turing, mà nay đã trở thành chuẩn, được đề xuất
bởi Kleene như sau:
“Các luận đề của Turing và Church là tương đương nhau. Chúng ta có thể
xem các luận đề này vừa là luận đề Church, hay liên hệ với một trong các phiên bản
… của nó có quan hệ với máy Turing như Luận đề Church-Turing”.

3. Các chương trình như các bộ nhận dạng ngôn ngữ

Như trên tiểu luận đã trình bày, ưu điểm nổi bật của máy Turing là tính đơn
giản, và cần chú ý rằng chỉ một sự thay đổi đơn giản máy automat hữu hạn (thêm bộ
nhớ đọc/viết) đã mang lại cho chúng ta khả năng tính toán phổ dụng. Tuy nhiên,
việc máy Turing thuộc loại “bậc thấp” đã dẫn đến các hạn chế trong một số tình
huống như sau: Xây dựng một máy Turing chỉ để thực hiện một công việc đơn giản
như kiểm tra một số nguyên có phải là một số nguyên tố hay không cũng đã là một
công việc rắc rối và mất thời gian.
Chính vì lý do đó, trong tiểu luận này, chúng ta sẽ tiến hành theo một cách
tương đối phi truyền thống. Chúng ta sẽ sử dụng chính các chương trình để
nghiên cứu khả năng tính toán thuần túy như một khái niệm, định lý … trong phần
dưới đây sẽ đảm bảo cho chúng ta rằng việc chúng ta có sử dụng các máy Turing
hay các chương trình như cách hình thức hóa “chính thức” không phải là vấn đề
quan trọng.
Đầu tiên, chúng ta cần xác định một chương trình chấp nhận một ngôn ngữ
có ý nghĩa như thế nào. Để cụ thể, chúng ta xét lại một số quy ước về chương trình
(mà ở đây là chương trình C):
• Một file văn bản được mô hình hóa như một chuỗi các ký tự (được kết
thúc bằng một dấu hiệu đánh dấu). Trong thuật ngữ ngôn ngữ hình thức
chuẩn, một file văn bản đơn giản là một từ trên bảng ký tự ASCII.
• Một chương trình p có thể lấy đầu vào từ file đầu vào chuẩn, và có thể
xuất các kết quả đầu ra vào một file đầu ra chuẩn
• Khi một chương tình dừng, nó sẽ trả về một điều kiện thoát cho hệ điều
hành bằng cách gọi hàm exit(status). Trạng thái 0 được sử dụng để thông
báo sự thực hiện thành công mà ở đây chúng ta ký hiệu là exit(0). Chúng


Máy Turing và tính khả quyết của thuật toán 19

ta cũng ký hiệu một trạng thái thoát khác của 1 là exit(1) minh họa các
điều kiện khác được sử dụng để báo hiệu sự không thành công.

• Và chương trình tự bản thân cũng chỉ là một file văn bản
Vì vậy, cho p là chương trình, x là file văn bản, và giả sử rằng p được thực
hiện với x là đầu vào. Hãy tạm bỏ qua đầu ra và chỉ chú trọng vào cách kết thúc của
p. Có 3 khả năng sau đây:
• p dừng với exit(0), hay
• p dừng với điều kiện dừng khác, hay
• p không thể dừng lại, có nghĩa là quá trình tính toán sẽ được thực hiện
mãi mãi (chú ý rằng trong mô hình tính toán của chúng ta, chúng ta
không cho phép hệ điều hành có thể dừng chương trình vì tràn stack hay
các ràng buộc khác)
Theo cách này, chúng ta có thể xét một chương trình p để định nghĩa một tập
các từ trên bảng chữ cái ASCII: những từ này sẽ làm cho chương trình thực hiện
lệnh exit(0). Nghĩa là, bất kỳ chương trình nào cũng định nghĩa (đoán nhận) một
ngôn ngữ trên ASCII. Qua đây, chúng ta có thể thấy được mối liên quan khăng
khít và tự nhiên giữa lý thuyết tính toán và lý thuyết ngôn ngữ. Tóm lại:
Định nghĩa 1. Cho bảng ký tự ASCII được ký hiệu bằng ΣA. Giả sử p là chương
trình, và x là từ trên ΣA. Xét kết quả của việc thực hiện chương trình p khi đầu vào
chuẩn là một file với nội dung x. Nếu p dừng với exit(0) (tức thành công), chúng ta
sẽ phát biểu P chấp nhận x.
Tập ngôn ngữ được chấp nhận bởi p là tập tất cả các từ được chấp nhận bởi p
và được ký hiệu là L(p):
L(p)
Với

{x∈

| p dừng với điều kiện thoát exit(0) trên đầu vào x}

là tập tất cả các từ có thể được thành lập từ Σ A.


Ví dụ 5. Cho p là chương trình có giả mã như sau:
//Chấp nhận anbncn
Đọc đầu vào vào một mảng;
oksofar = true;
duyệt mảng, đếm số a, lưu kết quả đếm vào n1;
duyệt mảng, đếm số b, lưu kết quả đếm vào n2;
nếu thấy một a, exit(1);
duyệt mảng, đếm số c, lưu kết quả đếm vào n3;
nếu thấy a hay b, exit(1);
nếu không eof, exit(1);
nếu n1 == n2 == n3 exit(0) còn không thì exit(1)

Lúc này L(p) là {anbncn | n ≥ 0}


Máy Turing và tính khả quyết của thuật toán 20

Thực tế, có thể rút ra được nhiều điều từ việc chương trình p chấp nhận ngôn
ngữ {a b c | n ≥ 0}. Vì p luôn dừng, chúng ta có thể xét exit(0) như “đúng vậy, từ
đầu vào có vẻ như là a nbncn với một số n”, và chúng ta có thể xét exit(1) như
“không, từ đầu vào không có vẻ là a nbncn với bất kỳ n nào”. Có nghĩa là, chúng ta có
thể xét một cách tự nhiên rằng p như một thủ tục quyết định để kiểm tra các phần tử
của ngôn ngữ {anbncn | n ≥ 0}.
n n n

Định nghĩa 2. Cho p là một chương trình. Ta nói p là một bộ quyết định nếu với
mọi đầu vào x, hoặc p sẽ dừng với exit(0), hoặc p sẽ dừng với exit(1). Đôi khi một
bộ quyết định còn được gọi là một chương trình toàn thể (total program)
Điểm cần chú ý ở đây là p sẽ không bao giờ thực hiện mãi mãi trên bất kỳ
một đầu vào nào, cũng như không dừng với trạng thái thoát nào ngoài exit(0) hay

exit(1). Chúng ta có thể thấy p là một bộ quyết định.
Sự phân biệt trên đây là rất quan trọng [], và là nguyên tắc trung tâm mà lý
thuyết về tính khả quyết sử dụng làm nền tảng. Chúng ta sẽ xét điểm này chi tiết
trong những phần sau.

3.1. Các chương trình và máy Turing
Với nền tảng lý thuyết ở phần trên (khả năng biểu diễn thuật toán một cách
hình thức của máy Turing + khả năng nhận dạng ngôn ngữ của máy Turing), chúng
ta có thể suy ra những kết quả cơ bản sau:
Định lý 1. Cho một chương trình p, có một máy Turing M mô phỏng p cho mọi từ x
với nghĩa sau:
• Nếu p dừng với exit(0) trên đầu vào x thì M chấp nhận x và dừng,
• Nếu p dừng với một số điều kiện thoát khác trên đầu vào x thì M dừng
trên x mà không chấp nhận x, và
• Nếu p không dừng trên đầu vào x thì M không thể dừng trên đầu vào x.
Hơn nữa, cho một máy Turing M, có một chương trình p mô phỏng M theo
cùng một cách như trên.
Chú ý rằng, những quan sát trên đây mang lại cho chúng ta những khái niệm
đáng chú ý về quá trình tính toán bằng các chương trình. Đó chính là khái niệm
mạnh (robust) không phân biêt theo những ngôn ngữ lập trình khác nhau. Và một
lần nữa chúng ta có thể thấy rằng khái niệm máy Turing, dù đơn giản hơn rất nhiều
so với các ngôn ngữ lập trình hiện đại, vẫn sẵn sàng thực hiện tất cả các thao tác
phức tạp có thể có trong quá trình tính toán.

3.2. Các hàm tính toán
Trên đây chúng ta đã xét các chương trình đơn giản như là các bộ chấp nhận
từ, nghĩa là định nghĩa ngôn ngữ. Dĩ nhiên, các chương trình thường cũng cho ra
các đầu ra cũng như các đầu vào, và do đó các chương trình tính các hàm.
Trong phần trên, chúng ta đã xét một định nghĩa hình thức của một thuật
toán tổng quát với máy Turing. Phần này, chúng ta sẽ xét một số định nghĩa thuật

ngữ về các hàm trên khía cạnh nhận dạng ngôn ngữ.
Định nghĩa 3. Một hàm một phần từ Σ* vào Σ* là một hàm f từ D và Σ*, trong đó D
là tập con của Σ*.


Máy Turing và tính khả quyết của thuật toán 21

Chú ý rằng, nếu f là hàm một phần trên các từ vựng, hoàn toàn có thể xảy ra
trường hợp miền D của f là tất cả Σ*, lúc này ta gọi f là hàm toàn phần từ Σ* vào Σ*.
Định nghĩa 4. Cho p là chương trình, và w là từ. Xét kết quả của chương trình thực
thi p khi đầu vào chuẩn là một file với nội dung là w. Nếu p dừng với exit(0), và nội
dung của file đầu ra chuẩn là từ x, chúng ta sẽ nói rằng quá trình tính toán của p trên
w sẽ trả về x.
Hàm một phần được tính bởi p là hàm một phần từ các từ vựng vào các từ
vựng được miêu tả ở phần trên. Và chúng ta cũng cần chú ý rằng miền của hàm
được tính bởi p chính xác là L(p).
Dĩ nhiên, chúng ta cũng có những mối quan hệ chung giữa các máy Turing và
các chương trình trong bối cảnh các hàm chúng ta cho nhận dạng ngôn ngữ như sau:
Định lý 2. Cho một chương trình p, có một máy Turing M sao cho M tính cùng một
hàm một phần trên các từ vựng mà p đã thực hiện.
Cho máy Turing M có một chương trình p sao cho p tính cùng một hàm một
phần trên các từ vựng mà M đã thực hiện.
Lúc này,
• Một hàm một phần f từ Σ* vào Σ* được gọi là hàm một phần T-tính được
nếu tồn tại một máy Turing sao cho:
o Với một xâu đầu vào w thuộc miền xác định của f, thì máy Turing sẽ
dừng ở một hình trạng mà f(w) đang ở trên băng,
o Với xâu đầu vào w không thuộc miền xác định của f, thì máy Turing
sẽ chạy không dừng hoặc sẽ dừng và thông báo, nhờ một giá trị quy
ước trên băng rằng hàm là không xác định

• Một hàm toàn phần f từ Σ* vào Σ* được gọi là hàm T-tính được nếu tồn
tại một máy Turing sao cho với mọi đầu vào w, máy sẽ dừng ở một hình
trạng mà f(w) đang ở trên băng.
Trong tiểu luận này, chúng ta xét một bài toán quyết định là mọi câu hỏi
có/không bất kỳ trên một tập các đầu vào vô hạn. Do đó, chúng ta có thể định nghĩa
bài toán quyết định dưới hình thức tập các đầu vào mà bài toán sẽ trả về kết quả có.
Với nghĩa này, một bài toán quyết định tương đương với bài toán quyết định một
chuỗi đã cho có thuộc về tập các chuỗi hay không, với tập các chuỗi này được gọi là
một ngôn ngữ hình thức, trong đó một chuỗi đầu vào thuộc tập này sẽ trả về CÓ.
Hay phát biểu một cách hình thức hơn, một thuật toán khả quyết sẽ dừng với
một câu trả lời CÓ hay KHÔNG trên mỗi chuỗi đầu vào đối với một ngôn ngữ L đã
cho. Đối với một vấn đề cụ thể, nếu một thuật toán có thể quyết định chính xác một
chuỗi có thuộc một ngôn ngữ không thì bài toán sẽ khả quyết. Do đó, tính khả quyết
của nhiều ngôn ngữ có thể được xác định theo thuật toán. Và cũng theo đó, việc chỉ
ra rằng một ngôn ngữ là khả quyết cũng sẽ tương đương với việc chỉ ra rằng một bài
toán là khả quyết.
Trong đó, một bài toán khả quyết là T-quyết định được nếu tồn tại một máy
Turing quyết định ngôn ngữ liên kết với bài toán đó (có nghĩa ngôn ngữ liên kết
với nó là đệ quy). Còn một bài toán khả quyết là T-nửa quyết định được nếu tồn
tại một máy Turing thừa nhận ngôn ngữ liên kết với bài toán đó (có nghĩa ngôn


Máy Turing và tính khả quyết của thuật toán 22

ngữ liên kết với nó là đệ quy kể được). Trong những phần sau, chúng ta sẽ xét các
khái niệm đệ quy và đệ quy kể được một cách cụ thể hơn.

4. Máy Turing và vấn đề khả quyết
4.1. Các tập đệ quy kể được và khả quyết
4.1.1. Một số định nghĩa

Định nghĩa 5. Cho p là một chương trình. Người ta nói rằng p là một bộ quyết định
(decider) nếu với mỗi đầu vào x, hoặc p ngắt với EXIT_SUCCESS hoặc p ngắt với
EXIT_FAILURE.
Điểm mấu chốt ở đây là p sẽ không bao giờ chạy mãi trên bất kỳ đầu vào
nào, cũng không ngắt với một trạng thái kết thúc nào ngoài EXIT_SUCCESS hoặc
EXIT_FAILURE.
Định nghĩa 6. Cho A là một tập con của ∑ *.
• A là nửa khả quyết (semi-decidability), hoặc là đệ quy kể được (RE) nếu nó
là ngôn ngữ L(p) cho một chương trình p nào đó.
• A là khả quyết nếu nó là ngôn ngữ L(p) cho một bộ quyết định p nào đó.
Định đề 1. Cho A là một tập con của ∑ *. Thì :
• A là RE nếu và chỉ nếu có một máy Turing M sao cho A = L(M)
• A là khả quyết nếu và chỉ nếu có một máy Turing M mà nó ngắt trên mỗi
đầu vào sao cho A = L(M).
4.1.2. So sánh RE và tính khả quyết
Điểm khác nhau giữa RE và khả quyết là gì? Một điều chắc chắn rằng, nếu
một tập A là khả quyết thì A là RE.
Điều này được suy ra trực tiếp từ các định nghĩa: Nếu A là khả quyết thì
nó là L(p) cho một bộ quyết định p nào đó, và do đó nó cũng là L(p) cho
một chương trình p nào đó, suy ra nó là RE.
Vậy, điều ngược lại sẽ như thế nào? Đó là, nếu A là RE, thì liệu rằng A có
khả quyết không? Trong một số tài liệu đã chỉ ra rằng điều ngược lại này là không
đúng vì có các tập RE nhưng chúng lại không khả quyết.
Tóm lại: Nếu chúng ta nói rằng “A là RE” thì điều này có nghĩa là “A là nửa
khả quyết, nó cũng có thể hoặc không thể là khả quyết”.
4.1.3. Tính kể được
Thuật ngữ “đệ quy kể được” được nêu ra trong các định nghĩa ở trên dường
như là một nghịch lý, bởi có thể thấy rằng hầu như không có cái gì liên quan đến
“đếm được” cả.
Chúng ta cùng nhau xem định nghĩa dưới đây:

Định nghĩa 7. Một chương trình E kể được một tập A nếu, khi được xử lý với một
file đầu vào rỗng, nó tạo ra một chuỗi các từ bao gồm các thành phần của A.


Máy Turing và tính khả quyết của thuật toán 23

Nó không được yêu cầu rằng một bộ kể được (enumerator) tạo ra các từ của
A trong bất kỳ thứ tự cụ thể nào. Nó cũng không được yêu cầu rằng một bộ kể được
tạo ra các từ chỉ một lần. Nghĩa là một bộ kể được E cho một tập A sẽ tạo ra cùng
một x từ A sau nhiều lần thực hiện. Nó chỉ được yêu cầu rằng mỗi thành phần của A
xuất hiện ít nhất một lần trong đầu ra của E.
Nói cách khác, bạn có thể chỉ ra rằng nếu A là RE thì có một bộ kể được nào
đó cho A mà nó có thể in mỗi thành phần của A đúng một lần.
Chú ý rằng một bộ kể được sẽ không bao giờ ngắt. Nếu nó ngắt nghĩa là nó
sẽ đếm một tập hữu hạn. Ngay cả khi nó không ngắt nó cũng có thể chỉ đếm một tập
hữu hạn. Tuy nhiên, nó cũng hoàn toàn có thể đếm một tập vô hạn, bởi vì một bộ kể
được không được yêu cầu ngắt.
Định lý chính của phần này đó là: Một tập là đệ quy kể được nếu và chỉ nếu
nó có thể kể được bởi một chương trình nào đó. Đến đây, có thể thấy rằng cái tên
“đệ quy kể được” không còn ẩn đi như lúc trước nữa.
Chiều “nếu” của chứng minh có thể được kiểm chứng một cách dễ dàng.
Chiều còn lại thì có vẻ hơi phức tạp. Giả sử A là RE, một chương trình p với L(p) =
A. Ở đây, chúng ta phải đi tìm một chương trình E để tạo ra một danh sách của
thành phần của A. Ý tưởng dưới đây hoàn toàn có thể thực hiện được: bằng việc
đếm tất cả các từ x0, x1, x2, … xem mỗi xi lần lượt là đầu vào của p. Bất kể khi nào p
chấp nhận xi, thì thêm xi vào đầu ra của E.
Một rắc rối xảy ra với ý tưởng này đó là nếu chúng ta không cẩn thận, chúng
ta sẽ rơi vào một vòng lặp vô hạn để cố gắng quyết định phải chăng p chấp nhận
một xi cụ thể nào đó và chưa bao giờ có cơ hội để xem xét x i+1, xi+2, … Một thủ thuật
ở đây là chạy một cách có hiệu quả tất cả các kiểm tra trên tất cả các giá trị x i một

cách đồng thời. Đoạn mã được cho bên dưới (trong chứng minh của nửa thứ hai của
mệnh đề nếu và chỉ nếu) đưa ra một kỹ thuật thực sự.
Định lý 3. Một tập A ⊆ ∑ * là RE nếu và chỉ nếu có một chương trình máy tính mà
nó đếm được A.
Chứng minh.
Giả sử có một chương trình E. Ở đây, ta có một chương trình p sao cho L(p)
= E.
Trên đầu vào x;
Bắt đầu chương trình E và xem đầu ra;
Nếu và khi x xuất hiện trên đầu ra của E, thì exit(0).

Ngược lại, giả sử rằng A là RE. Ở đây, ta có một chương trình E mà nó kể
được A.
int k = 0;
while true do
For each xi with 0 ≤ i ≤ k
Chạy p trên xi trong k bước;
Bất kể khi nào xi được chấp nhận bởi p thì print(xi);
k = k+1;


Máy Turing và tính khả quyết của thuật toán 24

Chú ý rằng, với việc kể được của chương trình E mà chúng ta đã xây dựng
trong phần 2, mỗi x trong A hoàn toàn được in bởi E nhiều lần một cách vô hạn.

4.2. Các ngôn ngữ đệ quy liệt kê
4.2.1. Ngôn ngữ đệ quy
Ngôn ngữ đệ quy là tập tất cả các ngôn ngữ mà chúng được quyết định bởi
một máy Turing nào đó.

LREC = {L : Tồn tại một máy Turing M, sao cho M quyết định L}
4.2.2. Ngôn ngữ đệ quy liệt kê
Ngôn ngữ đệ quy liệt kê là tập tất cả các ngôn ngữ mà chúng được quyết
định một nửa (semi-decided) bởi một máy Turing nào đó
LR.E = {L : Tồn tại một máy Turing, sao cho M quyết định một nửa L }

4.3. Các bài toán khả quyết
Có một quan hệ gần gũi giữa các câu hỏi về mối quan hệ giữa các ngôn ngữ
và loại câu hỏi “yes/no” mà chúng ta thường muốn giải quyết trong thế giới thực,
chẳng hạn như kiểm tra tính nguyên thủy (primality) của các số nguyên, kiểm tra
các đồ thị có là đồ thị phẳng hay không, hay kiểm tra tính đúng đắn của các chương
trình.
Mối quan hệ này chỉ đơn giản như sau: mỗi khi chúng ta đặt một ký tự ∑ lên
những gì mà chúng ta sẽ biểu diễn các trường hợp của một bài toán, các trường hợp
mà nó cho ra câu trả lời ứng với câu hỏi của chúng ta là “đúng” thì nó sẽ định nghĩa
một ngôn ngữ trên ∑ , đó là tập con của ∑ *. Với cách này, có thể hiểu rằng bài toán
của chúng ta là khả quyết hoặc RE. Sự liên hệ này rất đáng để chú ý:
Chúng ta xác định một vấn đề đã cho với một ngôn ngữ chứa tất cả các đầu
vào lấy từ một câu trả lời “đúng” cho vấn đề đó.
Chẳng hạn, như đã định nghĩa ở trên, ngôn ngữ sau đây:
{w ∈ [0, 1] * | w mã hóa một số nguyên tố}
có thể được xác định với bài toán:
Đầu vào: Một số nguyên n ở dạng nhị phân
Câu hỏi: n có phải là số nguyên tố hay không?
Như vậy, chúng ta nói rằng một bài toán là RE hoặc khả quyết khi ngôn ngữ
kết hợp là RE hoặc khả quyết, nghĩa là khi ngôn ngữ kết hợp có một chương trình
nhận ra nó hoặc thậm chí là quyết định nó.
Ví dụ 7. Bài toán dưới đây là khả quyết
Đầu vào: Một số nguyên n ở dạng nhị phân
Câu hỏi: Có phải n là số nguyên tố không?

Những gì mà chúng tôi muốn nói ở đây, đó là: các số nguyên được mã hóa
dưới dạng các từ trên tập {0, 1} sử dụng cơ số 2. Tập các từ để mã hóa một số
nguyên tố là một ngôn ngữ. Và chúng ta khai báo rằng ngôn ngữ này là ngôn ngữ
khả quyết. Để định nghĩa khai báo này, chúng ta sẽ trình bày một chương trình mà


×