LyThuyetTinhToan - Phan Huy Khanh

108
ĐẠI HC ĐÀ NNG TR ƯỜ NG ĐẠ I H C BÁCH KHOA KHOA CÔNG NGHTHÔNG TIN GIÁO TRÌNH LÝ THUYT TÍNH TOÁN PGS.TS. PHAN HUY KHÁNH ĐÀ NNG 1999

Transcript of LyThuyetTinhToan - Phan Huy Khanh

Page 1: LyThuyetTinhToan - Phan Huy Khanh

ĐẠI HỌC ĐÀ NẴNG TRƯỜNG ĐẠI HỌC BÁCH KHOA

KHOA CÔNG NGHỆ THÔNG TIN

GIÁO TRÌNH

LÝ THUYẾT TÍNH TOÁN

PGS.TS. PHAN HUY KHÁNH ĐÀ NẴNG 1999

Page 2: LyThuyetTinhToan - Phan Huy Khanh
Page 3: LyThuyetTinhToan - Phan Huy Khanh

PGS.TS. PHAN HUY KHÁNH biên soạn 1

MỤC LỤC

CHƯƠNG 1 NHẬP MÔN LÝ THUYẾT TÍNH TOÁN ........................................... 1 I. CÁC ĐỐI TƯỢNG ĐƯỢC XỬ LÝ TRONG TIN HỌC.............................................................1 II. CÁC MÁY (MACHINES).......................................................................................................................2

II.1. Khía cạnh chức năng (functional look)........................................................ 2 II.2. Khía cạnh cấu trúc (structural look)............................................................ 3

III. MÔ HÌNH TÍNH TOÁN .........................................................................................................................4 IV. ĐỊNH NGHĨA BÀI TOÁN.....................................................................................................................5

CHƯƠNG 2 MÔ HÌNH CÁC MÁY RAM ............................................................... 9 I. CÁC MÁY RAM .....................................................................................................................................9 II. MÔ PHỎNG MỘT MÁY BỞI MỘT MÁY KHÁC .........................................................16 III. MỘT MÔ HÌNH THÔ SƠ KIỂU RAM..................................................................................19

III.1. Mô phỏng các phép toán trên chuỗi ký tự bởi các phép toán trên các số nguyên........................................................ 19 III.2. Thu gọn tập hợp các lệnh ngắt................................................................... 20 III.3. Thu gọn tập hợp các lệnh số học................................................................ 20

IV. MÁY RAM VẠN NĂNG....................................................................................................................22

CHƯƠNG 3 MÔ HÌNH CÁC MÁY TURING ....................................................... 25 I. MÔ TẢ VÀ HOẠT ĐỘNG CỦA MÁY TURING.......................................................................25

I.1. Mô tả máy Turing....................................................................................... 25 I.2. Hoạt động của máy Turing ........................................................................ 26 I.3. Cấu hình xuất phát của máy Turing........................................................... 29 I.4. Máy Turing đơn định.................................................................................. 29

II. CAC HÀM T-TÍNH ĐƯỢC...............................................................................................................30 III. LỚP CÁC HÀM T-TÍNH ĐƯỢC .....................................................................................................32

III.1. Một số hàm sơ cấp ..................................................................................... 32 III.1.1. Các hàm hằng (constant functions)............................................................ 32 III.1.2. Các hàm chiếu (projection functions) ........................................................ 33

III.2. Các hàm kế tiếp (successor functions) ....................................................... 33 III.3. Các hàm kế trước (predecessor functions).......................................................... 34 III.4. Sự hợp thành (composition) ....................................................................... 34

III.3.1. Các máy được tiêu chuẩn hóa .................................................................... 35 III.3.2. Các máy Turing được chuẩn hóa ............................................................... 36 III.3.3. Tổ hợp các máy Turing.............................................................................. 36

III.5. Lập trình trên ngôn ngữ bậc cao máy Turing ............................................ 37 III.4.1. Cấu trúc if then else và cấu trúc rẽ nhiều nhánh ........................................ 37 III.4.2. Cấu trúc while ............................................................................................ 38

III.6. Quản lý bộ nhớ ........................................................................................... 39 III.5.1. Máy Turing chuyển một ô qua phải ........................................................... 39

Page 4: LyThuyetTinhToan - Phan Huy Khanh

2 Lý thuyết tính toán

III.5.2. Máy Turing chỉ sử dụng phần băng bên phải kể từ vị trí đầu tiên của đầu đọc-ghi ...........................................................39

III.7. Một số máy Turing thông dụng ..................................................................40 III.6.1. Sao chép .....................................................................................................40 III.6.2. Kiểm tra bằng nhau ....................................................................................41 III.6.3. Liệt kê các câu, các cặp câu và dãy các câu ...............................................41 III.6.4. Các hàm chiếu ngược (antiprojection function) .........................................42 III.6.5. Các hàm giao hoán .....................................................................................42

III.7. Các hàm T-tính được phức tạp hơn............................................................42 III.8. Nhận xét......................................................................................................43

IV. CÁC BIẾN THẾ KHÁC CỦA MÔ HÌNH MÁY TURING........................................................46 IV.1. Mô phỏng một máy Turing bởi một máy khác............................................46 IV.2. Các biến thể của máy Turing .....................................................................48

IV.2.1. Máy Turing có k băng ................................................................................48 IV.2.2. Các máy off−line và các máy có băng ra ...................................................49 IV.2.3. Các máy Turing không đơn định................................................................49 IV.2.4. Thu gọn một bảng chữ còn ba ký tự...........................................................50 IV.2.5. Rút gọn một bảng chữ còn hai ký tự ..........................................................52

IV.3. Các máy Turing có băng vô hạn một phía .................................................52 V. MÁY TURING VẠN NĂNG ..............................................................................................................53

VI. TỒN TẠI CÁC HÀM KHÔNG LÀ T−TÍNH ĐƯỢC............................................................55

CHƯƠNG 4 LUẬN ĐỀ CHURCH ........................................................................59 I. TƯƠNG ĐƯƠNG GIỮA CÁC MÔ HÌNH MÁY TURING VÀ MÁY RAM .........................59

I.1. Mọi hàm T-tính được cũng là R−tính được................................................59 I.2. Mọi hàm R−tính được cũng là T−tính được ...............................................60

I.2.1. Tăng nội dung thanh ghi n lên 1.................................................................60 I.2.2. Giảm 1 nội dung thanh ghi n ......................................................................60 I.2.3. Đưa nội dung thanh ghi n về 0 ...................................................................60 I.2.4. Nhảy theo nội dung thanh ghi n .................................................................61 I.2.5. Hoán vị nội dung hai thanh ghi n và m ......................................................61

I.3. Sự khác nhau giữa máy Turing và máy RAM.............................................61 II. MÔ HÌNH CÁC HÀM ĐỆ QUY.......................................................................................................62

II.1. Các hàm đệ quy nguyên thủy (primitive recursive functions)....................62 II.1.1. Xây dựng các hàm sơ cấp...........................................................................62 II.1.2. Sơ đồ hợp thành tổng quát..........................................................................62 II.1.3. Sơ đồ đệ quy đơn (simple recurrence) .......................................................63 II.1.4. Sơ đồ đệ quy đồng thời ..............................................................................63 II.1.5. Các hàm được định nghĩa bởi case.............................................................65

II.2. Các hàm đệ quy ..........................................................................................67 II.2.1. Sơ đồ tối thiểu ............................................................................................67 II.2.2. Các hàm đệ quy trừu tượng (abstract recursive functions) ........................68 II.2.3. Một số ví dụ................................................................................................68

II.3. Các hàm đệ quy đều T−tính được...............................................................70 II.3.1. Sơ đồ hợp thành tổng quát..........................................................................70 II.3.2. Sơ đồ đệ quy đơn........................................................................................70 II.3.3. Sơ đồ tối thiểu ............................................................................................71

Page 5: LyThuyetTinhToan - Phan Huy Khanh

Nhập môn lý thuyết tính toán 3

II.4. Mọi hàm T−tính được là đệ quy bộ phận ................................................... 71 III. LUẬN ĐỀ CHURCH............................................................................................................................73

CHƯƠNG 5 CÁC BÀI TOÁN KHÔNG QUYẾT ĐỊNH ĐƯỢC .......................... 77 I. CÁC NGÔN NGỮ LIỆT KÊ ĐỆ QUY VÀ CÁC NGÔN NGỮ ĐỆ QUY.......................................77

II. CÁC BÀI TOÁN KHÔNG QUYẾT ĐịNH ĐƯỢC................................................................................82

III. THUẬT TOÁN RÚT GỌN MỘT BÀI TOÁN VỀ BÀI TOÁN KHÁC .............................................83

CHƯƠNG 6 ĐỘ PHỨC TẠP TÍNH TOÁN......................................................... 93 I. ĐỘ PHỨC TẠP VỀ THỜI GIAN VÀ VỀ BỘ NHỚ ...............................................................84 II. CÁC LỚP CỦA ĐỘ PHỨC TẠP ....................................................................................................84

II.1. Hiện tượng nén........................................................................................... 84 II.2. Các họ P, NP và P−bộ nhớ (P−space)..................................................... 84

III. RÚT GỌN ĐA THỨC VÀ CÁC BÀI TOÁN NP−ĐẦY ĐỦ.........................................................84 III.1. Khái niệm ................................................................................................... 84 III.2. Các bài toán cổ điển .................................................................................. 84 III.3. Ví dụ về rút gọn kiểu đa thức ..................................................................... 84

Page 6: LyThuyetTinhToan - Phan Huy Khanh
Page 7: LyThuyetTinhToan - Phan Huy Khanh

PGS.TS. PHAN HUY KHÁNH biên soạn 1

CHƯƠNG 1

Nhập môn lý thuyết tính toán (Introduction to the theory of computation)

It’s not bad being the small fish.

I. Các đối tượng được xử lý trong Tin học Trong Tin học, các đối tượng (objects) được xử lý thông thường là những

phần tử thuộc vào những tập hợp vô hạn đếm được. Những phần tử này luôn luôn được biểu diễn (represented) dưới một dạng nào đó.

Chẳng hạn trong ngôn ngữ tự nhiên, số nguyên 1999 được biểu diễn trong hệ đếm cơ số 10 (hệ thập phân) gồm một dãy bốn chữ số thập phân thuộc bảng chữ số {0, 1, ..., 9}. Việc xử lý (thực hiện các phép toán số học thông thường) đối với các số nguyên được tiến hành trên cách biểu diễn cơ số 10 này.

Ví dụ : Phép cộng hai số 1999 + 1 = 2000. Người ta giả thiết rằng các đối tượng được xử lý là những câu (word, hay

sentence) được xây dựng trên một bảng chữ (alphabet) hữu hạn, được xem như là sự biểu diễn của đối tượng trong một bản chất khác. Định nghĩa 1.1 :

Một bảng chữ S là một tập hợp hữu hạn các chữ (letters), hay là các ký tự (symbols, hay characters).

Số lượng các ký tự, còn gọi là bản số (cardinality) hay lực lượng của S, được ký hiệu ||S||, hay |S|, nếu không sợ nhầm lẫn.

Một câu, hay một từ, trên bảng chữ S đã cho là một dãy hữu hạn các ký tự của bảng chữ S được viết liên tiếp nhau. Độ dài (length) của một câu (trên bảng chữ S đã cho) là số lượng các ký tự có

mặt trong câu. Câu rỗng (empty word), được ký hiệu là e (ω hoặc e, hoặc l), là câu có độ dài không, tức không chứa ký tự nào.

Ghép (concatenation) của hai câu là đặt kế tiếp hai câu đã cho (trên cùng dòng) để nhận được một câu mới. Bằng cách ghép liên tục như vậy cho mọi ký tự, mọi câu của S, ta nhận được một tập hợp chứa mọi câu có thể trên S, ký hiệu S*. Người ta nói S*là một cấu trúc đồng đẳng (nonoide), mà phần tử trung hòa (neutral element) chính là câu rỗng.

Cho trước một bảng chữ S, người ta định nghĩa một quan hệ có thứ tự toàn phần (total order) trên S* như sau : cho một thứ tự tùy ý trên các ký tự của S,

Page 8: LyThuyetTinhToan - Phan Huy Khanh

2 Lý thuyết tính toán

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 :

Hình 1.1. Thứ tự phân cấp trong S*

II. Các máy (machines)

II.1. Khía cạnh chức năng (functional look) Một máy (machine) được biểu diễn một cách hệ thống như sau :

Hình 1.2. Khía cạnh chức năng của một máy

Ở lối vào, người ta cung cấp một hoặc nhiều dữ liệu (data) cho máy, thì lối ra, người ta nhận được kết quả (result).

Giả thiết rằng các dữ liệu vào có dạng là dãy các ký tự, là một câu trên một bảng chữ nào đó đã cho (vào từ bàn phím chẳng hạn). Kết quả là một phần tử của một tập hợp xác định trước (predefini). Người ta phân biệt các kiểu máy (machine type) tùy theo bản chất của tập hợp kết quả này như sau :

1. Nếu tập hợp chỉ có hai phần tử { không, có } hay {0, 1}, máy sẽ chia dữ liệu vào thành ba phần tùy theo kết quả : � Tập hợp các câu trên bảng chữ vào sau khi được xử lý sẽ cho ra một kết

quả là có (đúng, true), hoặc không (sai, false). � Tập hợp các câu mà máy đưa ra một kết quả khác. � Tập hợp các câu trên bảng chữ vào mà máy không cho kết quả nào.

e 1

a 2 b 3 c 4

aa 5 ab 6 ac 7 ba 8 bb 9 bc 10 ca 11 cb 12 cc 13

aaa 14 aab 15 aac 16 . . .

Dữ liệu vào Máy

Dữ liệu ra

Page 9: LyThuyetTinhToan - Phan Huy Khanh

Nhập môn lý thuyết tính toán 3

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.

II.2. Khía cạnh cấu trúc (structural look) Ở đây, ta chỉ quan tâm đến các máy được mô tả đầy đủ về chức năng hoạt

động của chúng. Những máy này có thê : � Thực hiện các phép toán sơ cấp (elementary operation) trong một khoảng

thời gian hữu hạn. Mỗi phép toán, giả thiết không chia cắt nhỏ hơn được, được chọn trong một tập hợp hữu hạn các phép toán là một phần mô tả cấu trúc máy.

� Lần lượt thực hiện các phép toán sơ cấp theo một thứ tự xác định trước, tạo thành một chương trình (program), là một phần mô tả cấu trúc máy.

Một dãy các phép toán sơ cấp được máy thực hiện liên tiếp được gọi là một tính toán (computation) của máy.

Page 10: LyThuyetTinhToan - Phan Huy Khanh

4 Lý thuyết tính toán

III. Mô hình tính toán Thay vì phải thay đổi lại máy tính mỗi lần thay đổi bài toán cần giải, người ta

định nghĩa các lớp máy có cùng nguyên lý hoạt động và chúng chỉ khác nhau ở chương trình.

Người ta gọi mô hình tính toán (model), ký hiệu T, là sự mô tả tất cả các phép toán sơ cấp có thể được thực hiện trên những đối tượng nào, cách tác động lên mỗi một trong chúng như thế nào, và mô tả cách thức chương trình được thực hiện (execution) trên máy.

Một trường hợp riêng (instance) của mô hình là một máy biệt lập nào đó, gọi tắt là máy, hoạt động theo cách mô hình tính toán đã chỉ ra. Máy này được định nghĩa bởi dữ liệu vào của chương trình :

Mô hình + Chương trình = Máy Một khi một mô hình tính toán T được định nghĩa, được gọi là một T−máy,

vấn đề đặt ra là làm sao để có thể biết : − lớp ngôn ngữ đoán nhận được (recognized), được gọi là T−nhận biết được,

hoặc − lớp các hàm tính được (computable), được gọi là T−tính được, hoặc − lớp các ngôn ngữ liệt kê được (enumerable) được gọi là T −liệt kê được,

bởi một máy nào đó của mô hình này ? Hai mô hình tính toán được đưa ra so sánh với nhau : một mô hình T1 được

nói là mạnh hơn so với một mô hình T2 nếu :

− mọi ngôn ngữ T2−nhận biết được cũng là T1−nhận biết được, hoặc

− mọi hàm T2-tính được cũng là T1−tính được, hoặc

− mọi ngôn ngữ T2-liệt kê được cũng là T1-liệt kê được.

Hai mô hình được gọi là tương đương (equivalent) nếu mỗi mô hình mạnh hơn mô hình kia và ngược lại.

Hai mô hình là không thể so sánh với nhau được nếu không tồn tại mô hình nào ít ra đủ mạnh hơn mô hình kia.

Page 11: LyThuyetTinhToan - Phan Huy Khanh

Nhập môn lý thuyết tính toán 5

IV. Định nghĩa bài toán Trong Tin học lý thuyết, định nghĩa về bài toán (problem) có vai trò đặc biệt

quan trọng, khác với khái niệm thông thường về bài toán được dùng trong lĩnh vực Toán học hoặc hiểu theo nghĩa thông dụng. Định nghĩa 1.2 :

Một bài toán là : − Sự mô tả cách biểu diễn (hữu hạn) các phần tử của một tập hợp hữu hạn

hay vô hạn đếm được. − Một phát biểu liên quan đến các phần tử của tập hợp này, có thể là đúng,

hoặc có thể là sai tùy theo phần tử được chọn. Sau đây là một số ví dụ :

Bài toán 1 : Dữ liệu: Một số nguyên viết trong hệ 10. Câu hỏi : Số nguyên đã cho có là số nguyên tố hay không ?

Bài toán 2 : Dữ liệu : Một số nguyên viết trong hệ 10. Câu hỏi : Có phải số nguyên này được viết dưới dạng tổng của 4 số bình phương

? Bài toán 3 :

Dữ liệu : Một số nguyên viết dưới dạng tích của các số hạng trong hệ 10. Câu hỏi : Số nguyên đã cho có là số nguyên tố hay không ?

Bài toán 4 : Dữ liệu : Một đồ thị hữu hạn được biểu diễn bởi một danh sách gồm các đỉnh

và các cung, trong đó mỗi đỉnh được biểu diễn bởi một số nguyên trong hệ 10.

Câu hỏi : Có tồn tại một đường đi Hamilton (đi qua hết tất cả các đỉnh của đồ thị, mỗi đỉnh đi qua đúng một lần) trong đồ thị đã cho không ?

Bài toán 5 : Dữ liệu : Một biểu thức chính quy (regular expression) được xây dựng trên

một bảng chữ S (là một biểu thức nhận được từ các câu w∈S* bởi các phép hoặc, phép ghép tiếp, phép * và lấy bù).

Câu hỏi : Có phải biểu thức đã cho biểu diễn (hay chỉ định) một ngôn ngữ trống (empty language) hay không ?

Bài toán 6 : Dữ liệu : Một dãy hữu hạn các cặp câu (u1, v1), (u2, v2)..., (uk, vk). Câu hỏi : Tồn tại hay không một dãy chỉ số i1 , i2 ,...in sao cho thoả mãn

ui1 ui2... uin = vi1 vi2... vin ?

Page 12: LyThuyetTinhToan - Phan Huy Khanh

6 Lý thuyết tính toán

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).

Page 13: LyThuyetTinhToan - Phan Huy Khanh

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.

Page 14: LyThuyetTinhToan - Phan Huy Khanh
Page 15: LyThuyetTinhToan - Phan Huy Khanh

PGS.TS. PHAN HUY KHÁNH biên soạn 9

CHƯƠNG 2

Mô hình các máy RAM « I like the dreams of the future better than

the history of the past » Jefferson

I. Các máy RAM Máy RAM là một mô hình tính toán rất gần với máy tính điện tử và ngôn ngữ

assembler. Máy RAM có các thành phần đặc trưng chung như sau : � Một băng vào, hay dải vào (input tape) được chia thành nhiều ô (square hay

pigeonhole) liên tiếp nhau, mỗi ô chứa một số nguyên hoặc một ký tự. Một đầu đọc (read head) đọc lần lượt nội dung từng ô trên băng vào, đọc từ trái qua phải.

� Một băng ra (output tape) cũng chia ra thành nhiều ô liên tiếp nhau và một đầu ghi (write head) có thể ghi mỗi lần lên một ô và tiến từ trái qua phải.

Người ta nói rằng đầu đọc (hoặc ghi) được đặt trên (tại) một ô và di chuyển qua phải mỗi lần một ô. Trước tiên, ta xem rằng mỗi ô chứa một số nguyên có thể lớn tuỳ ý. Băng vào và băng ra của máy RAM được gọi là các cơ quan vào/ra. Máy RAM còn có các thành phần bên trong như sau :

� Các thanh ghi (registers) là các phần tử nhớ được đánh số thứ tự, số lượng các thanh ghi có thể lớn tuỳ ý. Mỗi thanh ghi có thể lưu giữ một số nguyên. Các thanh ghi lần lượt được đặt tên là R0, R1, R2, ... , Rn...

Chỉ số i, i = 0, 1, 2, ..., được gọi là địa chỉ (address) của mỗi thanh ghi (hay của bộ nhớ). Riêng R0 là một thanh ghi đặc biệt, được gọi là thanh tổng (ACC − accumulator) hay thanh tích luỹ.

� Một tập hợp các đơn vị nhớ được đánh số chứa chương trình của máy RAM dưới dạng một dãy các lệnh sơ cấp (primary instructions) không bị thay đổi trong quá trình chạy (thực hiện). Mỗi lệnh được lưu trữ trong một đơn vị nhớ, được đánh số tương ứng với số thứ tự hay nhãn của lệnh (label).

� Một đơn vị nhớ chứa số thứ tự của lệnh đang được thực hiện, được gọi là thanh đếm lệnh (OC − Ordinal Counter). Lúc đầu nội dung là của OC là 1.

Trong kiểu máy này, người ta truy cập trực tiếp đến mỗi thanh ghi bởi địa chỉ của thanh ghi đó. Chính lý do này mà kiểu máy này được đặt tên là Random Access Memory (viết tắt RAM).

Page 16: LyThuyetTinhToan - Phan Huy Khanh

10 Lý thuyết tính toán

Hình 2.1 Sơ đồ một máy RAM

Mỗi chương trình của máy RAM gồm một dãy lệnh sơ cấp, mỗi lệnh được tạo thành từ 2 thành phần : mã lệnh (operation code) và toán hạng (operand) :

Mã lệnh Toán hạng

Các lệnh được phân thành nhóm theo chức năng của phần mã lệnh như sau : Nhóm lệnh gán :

LOAD Operand STORE Operand

Nhóm lệnh số học : INCR Operand DECR Operand AD Operand SUB Operand MULT Operand DIV Operand

Nhóm lệnh nhảy (hay lệnh ngắt, cũng còn gọi là lệnh chuyển điều khiển) : JUMP Label JGTZ Label JZERO Label HALT

Nhóm lệnh vào − ra : READ Operand WRITE Operand

1 R0 Thanh tổng

2 R1 . . . . . . . . . . . . Các thanh ghi j Ri . . . . . . . . . . . . p Rn

i Thanh

đếm lệnh

y1 y2 y3 . . . Băng ra

Chương trình

x1 x2 . . . xn Băng vào

Page 17: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 11

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.

Page 18: LyThuyetTinhToan - Phan Huy Khanh

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

Page 19: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 13

Ví dụ 2.2 : Chương trình RAM tính nn READ 1 R1 ← số nguyên trên ô của băng vào LOAD 1 ACC ← <R1> JGTZ 6 nếu <ACC> ≥ 0, nhảy đều 6 WRITE A:0 in ra 0 JUMP 22 về lệnh dừng

6 : LOAD 1 ACC ← <R1> STORE 2 R2 ← <ACC> LOAD 1 ACC ← <R1> DECR 0 ACC ← <ACC> − 1 STORE 3 R3 ← <ACC>

11 : LOAD 3 ACC ← <R3> JGTZ 14 nếu <ACC> ≥ 0, nhảy đến 14 JUMP 21 nhảy đến 21 nếu <ACC> < 0

14: LOAD 2 ACC ← <R2> MULT 1 ACC ← <ACC> * <R1> STORE 2 R2 ← <ACC> LOAD 3 ACC ← <> DECR 0 ACC ← <ACC> − 1 STORE 3 R3 ← <ACC> JUMP 11 nhảy đến 11

21: WRITE 2 in ra nội dung <R2> 22: HALT dừng Ta có thể viết đoạn trình Pascal minh họa trình RAM như sau : begin

read (R1) if R1 < 0 then write (R0) else begin

R2:= R1 ; R3:= R1 − 1 ; while R3 > 0 do begin R2:= R2*R1 ; R3:= R3–1 end ; write (R2)

end end ; Ta thấy một trình RAM xác định một ánh xạ từ tập các băng vào lên tập các

băng ra. Đây là ánh xạ bộ phận (partial map) vì một số ánh xạ có thể không xác định trên một số băng vào, nghĩa là chương trình ứng với băng vào đó không dừng.

Ta có thể giải thích ánh xạ này ở dưới hai dạng : dạng hàm và dạng ngôn ngữ.

Page 20: LyThuyetTinhToan - Phan Huy Khanh

14 Lý thuyết tính toán

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.

Page 21: LyThuyetTinhToan - Phan Huy Khanh

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.

Hình 2.2 Sơ đồ một máy RASP Trong máy RASP, thanh tổng luôn luôn là R0, thanh ghi R1 dùng để lưu giữ

trung gian nội dung của thanh tổng. Các thanh ghi từ 2..p (với p là một số nguyên lẻ) chứa chương trình của máy

RASP, và các thanh ghi tiếp theo, từ p + 1 trở đi, là các thanh ghi còn trống. Sự khác nhau cớ bản với mô hình máy RAM là có thể thay đổi một thanh ghi

chứa chương trình, và do vậy, có thể thay đổi chương trình.

R0 Thanh tổng

R1 R2 Chương trình Rp

. . . Các thanh ghi khác Thanh đếm lệnh

i

y1 y2 y3 . . . Băng ra

x1 x2 . . . xn Băng vào

Page 22: LyThuyetTinhToan - Phan Huy Khanh

16 Lý thuyết tính toán

II. Mô phỏng một máy bởi một máy khác Từ đây trở đi, người ta thường phải mô phỏng một máy bởi một máy khác :

máy mô phỏng sẽ bắt chước hay nhại lại (mime) mỗi một lệnh của máy được mô phỏng, bằng cách thực hiện nhiều lệnh (nói chung) để đi đến cùng một kết quả.

Khi có một máy RAM M có chương trình P chạy và sử dụng đến thanh ghi 0 và các thanh ghi từ 1 đến p (giá trị của p thay đổi tùy theo dữ liệu), người ta nói rằng một máy RAM M’ có chương trình P’ mô phỏng chức năng của máy RAM M nếu :

� Tồn tại một ánh xạ I từ N vào N mà biến 0 thành 0. � Mỗi lệnh của P được thay thế bởi một lệnh của P’ sao cho, mỗi lần thực

hiện chương trình P (nghĩa là với mọi dữ liệu), nội dung mỗi thanh ghi I (r) của M’ sau khi thực hiện dãy các lệnh của P’ là giống như nội dung của thanh ghi R của M sau khi thực hiện các lệnh tương ứng của P.

Ví dụ 2.3 : Dịch chuyển các địa chỉ thanh ghi. Xuất phát từ một máy RAM có chương trình P khi chạy sử dụng thanh ghi 0

và các thanh ghi từ 1 đến p, ta có thể xây dựng một máy RAM khác có chương trình Pk mô phỏng trình P với ánh xạ I xác định bởi :

I (0) = 0 I (r) = k + r với r > 0. Việc mô phỏng máy RAM sẽ trở nên tầm thường nếu không xử lý các lệnh

gián tiếp. Đối với kiểu lệnh này, vấn đề là thay đổi địa chỉ các thanh ghi sử dụng đến, bằng cách thêm giá trị k (nhờ lệnh ADD A:k) vào nội dung của thanh ghi liên quan (đặt sau I) để thực hiện kiểu gián tiếp.

Các máy RASP cũng có thể được mô phỏng và có thể xử lý kiểu lệnh gián tiếp. Dịch chuyển các địa chỉ thanh ghi của RASP

Những gì mà một máy RAM làm được thì một máy RASP cũng có thể được làm được. Thật vậy, nếu chương trình của RASP được lưu giữ trong các thanh ghi từ 2 đến p, chỉ cần thực hiện một sự biến đổi của p lên tất cả các số của thanh ghi sử dụng bởi máy RAM tương ứng.

Tuy nhiên trong mô hình của RASP, kiểu lệnh gián tiếp được xử lý như sau : Giả sử một chương trình P của máy RASP được lưu giữ từ thanh ghi số 2 đến

p và khi chạy sử dụng đến các thanh ghi từ p + 1 đến q. Ta sẽ xây dựng một chương trình mới mô phỏng P được lưu giữ trong các thanh ghi từ 2 đến p’.

Khi chạy, chương trình sử dụng đến các thanh ghi từ p’ + 1 đến q + p’ − p, bằng cách thay thế mỗi lệnh kiểu gián tiếp bởi 6 lệnh không là kiểu gián tiếp, sao cho kết quả của 6 lệnh này là tương tự trên mỗi thanh ghi số p’ + i với kết quả của lệnh được mô phỏng trên mỗi thanh ghi số p + i.

Page 23: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 17

Một cách cụ thể hơn, p’ − p có giá trị 2 × (6 − 1) × s = 10s với s là tổng số lệnh kiểu gián tiếp của chương trình.

Giả sử ta cần mô phỏng một trong các lệnh MULT I: n của chương trình RASP cần mô phỏng, được lưu giữ trên các thanh ghi 30 và 31 của máy xuất phát. Để mô phỏng, ta cần tạo ra nhóm 6 lệnh chiếm 12 liên tiếp, giả sử từ thanh ghi số 50 đến 61, với giả thiết chương trình có trên hai lệnh kiểu gián tiếp. Lệnh đầu tiên của nhóm 6 lệnh này là lưu giữ nội dung của thanh tổng vào thanh ghi R1 :

50 STORE 51 1 R1 ← <ACC>

Lệnh thứ hai nạp vào thanh tổng nội dung của thanh ghi n + p’ − p (tương ứng với thanh ghi n trong chương trình xuất phát) :

52 LOAD 53 n + p’- p ACC ← <Rn> + (p’ − p)

Lệnh thứ ba tăng nội dung của thanh tổng lên p’ − p để lúc này thanh tổng chứa địa chỉ của thanh ghi chứa giá trị cần nhân :

54 ADD A: 55 p’- p ACC ← <ACC> + (p’ − p) Lệnh thứ tư gán trực tiếp lệnh thứ sáu bằng cách thay đổi trường địa chỉ của

lệnh này (việc thực hiện chương trình làm thay đổi bản thân chương trình đó) : 56 STORE 57 61 R61 ← <ACC>

Lệnh thứ năm khôi phục nội dung lúc đầu của thanh tổng : 58 LOAD 59 1 ACC ← <R1>

Cuối cùng, thực hiện phép nhân : 60 MULT 61 x ACC ← <ACC> * <Rx>

Ở đây, lúc bắt đầu thực hiện chương trình, x là một giá trị nào đó, và mỗi lần thực hiện, nếu thanh ghi n của máy xuất phát chứa số nguyên a, thì x sẽ có giá trị là a + p’ - p tại thời điểm thực hiện lệnh đặt trong các thanh ghi 60 và 61. Như vậy, khi mô phỏng trình P thành P’ đặt trong các thanh ghi RASP, P’ đã bị thay đổi khi thực hiện nó.

Page 24: LyThuyetTinhToan - Phan Huy Khanh

18 Lý thuyết tính toán

Ví dụ 2.4 : Dịch chuyển một trình RASP có một lệnh dạng gián tiếp :

Tính in ⎪⎩

⎪⎨⎧

>+

≤+

b abb aa

nãúunãúu

1

1

Chương trình RASP xuất phát P : sau khi dịch chuyển thành P’ : 2 READ READ 3 27

R27 ← a 37

4 READ READ 5 28

R27 ← b 38

6 LOAD A: LOAD A: 7 27

ACC ← <R27> 37

8 STORE STORE 9 26

R26 ← <ACC> 36

10 LOAD LOAD 11 28

ACC ← <R28> 38

12 SUB SUB 13 27

ACC ← <ACC> - <R27> 37

14 JGTZ JGTZ 15 18 OC ← 18, if <ACC> > 0 18 16 INCR INCR 17 26

R26 ← < R26> + 1 36

18 LOAD A: LOAD A: 19 1 ACC ← 1 1

Phần này là dịch chuyển của P

với ánh xạ : I(r) = r+p’-p = r+10

20 ADD I: STORE 21 26

ACC ← <ACC> + <<R26>>1

R1 ← <ACC>

22 WRITE LOAD 23 0 In ra <ACC> 36

ACC ← <R36>

24 HALT ADD A: p 25 0 Dừng 10

ACC ← <ACC> + 10

P+1 26 27 / 28 Nội dung 27, hoặc 28 STORE 27 a Chứa giá trị a 31

R31 ← <ACC> : số x

q 28 b Chứa giá trị b LOAD 29 1

ACC ← <R1>

30 ADD

31 Nội dung thay đổi : số x → 0

ACC←<ACC> + <Rx>

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

Page 25: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 19

III. Một mô hình thô sơ kiểu RAM Trong phần này, ta sẽ chỉ ra rằng có thể thu gọn về một tập hợp lệnh sơ cấp rất

nhỏ. Đặc biệt, ta sẽ chỉ ra rằng có thể xử lý ký tự và xử lý các số nguyên. Trước hết, ta quay lại cách biểu diễn các số nguyên. Trong máy tính, có hai

cách biểu diễn : biểu diễn nhị phân cho phép lưu trữ một số nguyên trong một thanh ghi làm tiết kiệm chỗ và tính toán nhanh chóng nhưng có nhược điểm là độ lớn của số nguyên phụ thuộc vào kích thước thực tế của thanh ghi (hữu hạn).

Cách biểu diễn thứ hai là sử dụng một dãy chữ số trên bảng chữ {0.. 9}. Thực tế, ngay cả khi người ta có thể biểu diễn trong một thanh ghi nhiều ký tự (thường không quá 4), thì để biểu diễn một số nguyên cũng đòi hỏi có nhiều thanh ghi. Mặc dù dải số nguyên có thể biểu diễn được là khá lớn, nhưng do số lượng các thanh ghi trong máy tính hiện nay bị hạn chế nên cách biểu diễn này cũng chưa phải tối ưu.

III.1. Mô phỏng các phép toán trên chuỗi ký tự bởi các phép toán trên các số nguyên

Mỗi ký tự được mã hóa bởi một dãy các chữ số nhị phân {0, 1} (chẳng hạn 8 chữ số cho một ký tự). Một chuỗi bit như vậy có thể dùng để biểu diễn các số nguyên nhờ thực hiện các phép toán trên các số nguyên.

Chẳng hạn, ghép 198 và 7, dẫn đến phép nhân số nguyên biểu diễn chuỗi 198 với 28 rồi cộng thêm số nguyên biểu diễn chuỗi 7 vào tích số nhận được :

Hình 2.4 Ghép hai số nguyên Ngược lại, các phép toán số học có thể được thực hiện trên biểu diễn các số

nguyên bởi các chuỗi ký tự, đó là các phép tính sơ cấp. Chú ý rằng khi người ta tiến hành các phép toán trên các số nguyên theo cách

biểu diễn nhị phân, người ta đã xử lý trên các câu của bảng chữ {0, 1}, và phép toán được thực thi trên các ký tự.

198 7 198 28 7 ~ × +

Page 26: LyThuyetTinhToan - Phan Huy Khanh

20 Lý thuyết tính toán

III.2. Thu gọn tập hợp các lệnh ngắt Ta có thể chuyển đổi các lệnh ngắt JUMP n về hai kiểu lệnh là nhảy nếu gặp 0

(zero) JZERO và lệnh dừng máy HALP. Lệnh JUMP n sẽ sử dụng thanh ghi R1 làm trung gian để lưu giữ nội dung của

thanh tổng, bằng cách thêm vào trước mỗi lệnh đã gắn nhãn các lệnh sau :

STORE 1 R1 ← <ACC> LOAD 1 <ACC> ← R1

sau đó thay thế lệnh nhảy bởi : STORE 1 R1 ← <ACC> LOAD A: 0 <ACC> ← 0 JZERO n’ goto n’, if <ACC> = 0 Trong đó n’ là nhãn của lệnh STORE 1 đặt trước ngay lệnh có nhãn n trong

máy xuất phát. Bài tập : Một cách tương tự, xây dựng lại lệnh JGTZ (nhảy nếu kết quả dương).

III.3. Thu gọn tập hợp các lệnh số học Có thể chuyển đổi các lệnh số học (cộng, trừ, nhân, chia) về hai kiểu lệnh là

INCR (tăng 1) và DECR (giảm 1). Chẳng hạn, lệnh nhân MULT n sẽ được chuyển đổi bằng cách thêm <n> lần

nội dung của thanh tổng. Sử dụng các thanh ghi từ 1 đến 3 làm trung gian, ta có thể thay lệnh nhân bởi các lệnh sau :

STORE 1 LOAD n STORE 2 LOAD A: 0 STORE 3

return: LOAD 2 JZERO lab DECR 2 LOAD 1 ADD 1 STORE 3 JUMP return

lab: LOAD 3 Một cách tương tự, lệnh ADD n tăng thêm 1 (INCR) đúng <n> lần nội dung

của thanh tổng nhờ các lệnh STORE, LOAD, JGTZ, DECR ...

Page 27: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 21

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.

Page 28: LyThuyetTinhToan - Phan Huy Khanh

22 Lý thuyết tính toán

IV. Máy RAM vạn năng Trong phần này, chúng ta sẽ chỉ ra cách xây dựng một máy kiểu RAM có thể

mô phỏng bất kỳ máy RASP nào không sử dụng kiểu gián tiếp. Nguyên lý mô phỏng như sau : lúc đầu, người ta đọc chương trình của máy RASP, chương trình này được lưu giữ trong các thanh ghi từ 4 đến p của máy RAM. Thanh ghi R1 dùng làm địa chỉ gián tiếp ; thanh ghi R2 dùng để mô phỏng thanh đếm lệnh của RASP. Thanh ghi R3 dùng để mô phỏng thanh tổng của RASP. Sau đó, thực hiện một vòng lặp trên các phép toán được mô tả dưới đây, mỗi lần lặp là một lần mô phỏng một lệnh của RASP.

Giả thiết rằng thanh ghi R2 chứa địa chỉ của thanh ghi đầu tiên trong hai thanh ghi chứa lệnh cần mô phỏng (bắt đầu từ 4). Vòng lặp như sau :

Loop: − Nội dung của thanh ghi của R2 được gán cho thanh tổng :

LOAD I: 2 − Phân tích mã phép toán của lệnh này và tùy theo mã đã phân tích mà nhảy

đến dãy lệnh tương ứng với nó. Ví dụ, nếu x là mã của phép chia DIV và y là nhãn của dãy phép toán mô phỏng DIV, nếu z là mã của phép nhảy dương JGTZ và t là nhãn của dãy phép toán mô phỏng JGTZ : . . . SUB A: x JZERO y ADD A: x SUB A: z JZERO t ADD A: z . . .

Sau đó, từ nhãn y, thực hiện mô phỏng phép toán chia DIV : − Tăng nội dung R2 lên 1 để R2 chứa địa chỉ của thanh ghi chứa toán hạng :

INCR 2 − Gán địa chỉ này cho thanh ghi R1 :

LOAD I: 2 STORE 1

− Mô phỏng phép toán giữa nội dung thanh tổng của RASP và toán hạng này bởi : LOAD 3 DIV I: 1 STORE 3

Page 29: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 23

− 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 JUMP loop

− 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 JUMP loop

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).

Page 30: LyThuyetTinhToan - Phan Huy Khanh

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.

Page 31: LyThuyetTinhToan - Phan Huy Khanh

PGS. TS. PHAN HUY KHÁNH biên soạn 25

CHƯƠNG 3

Mô hình các máy Turing « If the human brain was so simple

that we could understand it, then we would be so simple that we could not »

(L. Watson)

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.

I. Mô tả và hoạt động của máy Turing

I.1. Mô tả máy Turing Một máy Turing gồm : � Một băng vô hạn cả hai phía trái và phải được chia thành các ô liên tiếp

nhau. Mỗi ô chứa một thông tin hữu hạn (finite information) nào đó được biểu diễn bởi một chữ cái (letter) hay ký tự. Tập hợp các chữ cái (hay ký tự) này tạo ra bảng chữ của máy Turing, đưọc định nghĩa đồng thời với máy Turing.

� Một đầu đọc−ghi để đọc hay ghi (làm thay đổi) nội dung từng ô của băng, và mỗi lần chỉ di chuyển, qua phải hoặc qua trái, một vị trí tương ứng với một ô. Như vậy, tại mỗi thời điểm, chỉ duy nhất một ô được đọc, hoặc được ghi mà thôi.

� Một bộ nhớ phụ hữu hạn có thể tiếp cận tại mọi thời điểm, có thể biết được nội dung và thay đổi được. Tất cả các nội dung có thể của bộ nhớ phụ này được liệt kê hết lúc định nghĩa máy Turing, được chỉ định bởi một số thứ tự, gọi là trạng thái của máy Turing.

� Một chương trình là một tập hợp hữu hạn các quy tắc chỉ ra sự thay đổi các thông tin trên băng và nội dung của bộ nhớ phụ.

Một cách hình thức, máy Turing được định nghĩa từ các thành phần sau đây :

Page 32: LyThuyetTinhToan - Phan Huy Khanh

26 Lý thuyết tính toán

� 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 :

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.

I.2. Hoạt động của máy Turing Người ta gọi c là cấu hình (configuration) của một máy Turing T =<S, Q, P>

là một bộ ba : c = (f, q, xg) ∈ S* ´ Q ´ SS*

sao cho câu fxg tạo thành phần hữu ích của băng vô hạn. Trạng thái q chỉ định nội dung của bộ nhớ phụ. Đầu đọc−ghi được đặt trên ô chứa ký tự x.

x | y, mq p

Page 33: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 27

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’.

Hình 3.2. Máy Turing trong cấu hình c = (f, q, xg)

Cho máy Turing T = <S, Q, P>, và c là một cấu hình, ta nói rằng tồn tại một phép tính hợp lệ (valid computation) có độ dài n ≥ 0 dẫn từ cấu hình c đến cấu hình c’, ký hiệu c Ã−n c’, nếu và chỉ nếu :

− tồn tại một dãy các cấu hình c0, c1, ..., cn sao cho c = c0, c’ = cn

− với mỗi i ∈ {0 .. n-1}, tồn tại một chuyển tiếp giữa ci và ci+1 : ci Ã− ci+1

Ta ký hiệu cÃ−* c’ là phép tính hợp lệ dẫn từ cấu hình c đến cấu hình c’ có độ dài không biết chắc chắn (quan hệ Ã−* là đóng đối với các phép phản xạ và bắc cầu của quan hệ Ã−).

Chú ý rằng người ta không xét các phép tính không hợp lệ. Ví dụ 3.1 :

Cho máy Turing T =<S, Q, P> với S = {1, #}, Q = {q1, q2, q3, q4} và

P = { q1, 1 → 1, R, q2, q2, 1 → 1, R, q1, q1, # → #, L, q3,

←−− Phần hữu ích −−→

. . . # # # f x g # # # . . .

q

Page 34: LyThuyetTinhToan - Phan Huy Khanh

28 Lý thuyết tính toán

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 Ã−

T c’

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 :

Page 35: LyThuyetTinhToan - Phan Huy Khanh

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.

I.3. Cấu hình xuất phát của máy Turing Bây giờ, ta cần xem xét những yếu tố bất tiện của mô hình máy Turing. Ta dễ

nhận thấy rằng không thể biết đâu là điểm bắt đầu và đâu là điểm kết thúc của dữ liệu trên băng. Bởi vì phần hữu ích không phân biệt được với phần còn lại trên băng. Để khắc phục điều bất tiện này, người ta đưa vào các quy ước đối với các cấu hình xuất phát như sau :

� Lúc đầu, phần hữu ích phải khác rỗng để loại trừ các khả năng liệt của các máy Turing.

� Lúc đầu, phần hữu ích không chứa hai ký tự # liên tiếp nhau và dễ dàng xác định được vị trí bắt đầu và vị trí kết thúc để phân biệt với phần còn lại trên băng.

� Lúc đầu, đầu đọc−ghi được đặt trong phần hữu ích để chỉ định phần này. Mặt khác, người ta cũng quy ước thêm như sau : � Trạng thái xuất phát phải luôn luôn là q1, gọi là trạng thái đầu (initial).

� Đầu đọc−ghi đặt tại ký tự khác # và sát bên trái nhất của phần hữu ích.

Một câu f ∈ S* được gọi là được thừa nhận (accepted) bởi máy Turing nếu, xuất phát từ cấu hình ban đầu (e, q1, f), máy Turing đã thực hiện một phép tính hợp lệ và dừng. Ngôn ngữ L(T) gồm tập hợp các câu được thừa nhận, được gọi là ngôn ngữ được thừa nhận (accepted language) bởi máy Turing.

Trong ví dụ trên, ngôn ngữ được thừa nhận là các câu chứa một số lẻ số 1 :

L(T) = { f ∈ S * | f gồm một số lẻ chữ số 1 }.

I.4. Máy Turing đơn định Điểm bất tiện thứ hai trong mô hình máy Turing là có thể thực hiện nhiều

phép tính khác nhau tại mỗi thời điểm. Nếu với mọi cặp (q, x) ∈ Q ´ S, tồn tại nhiều nhất một quy tắc của máy Turing có (q, x) là phần bên trái, khi đó từ một cấu hình đã cho c, tồn tại duy nhất một phép tính hợp lệ có thể. Người ta gọi máy Turing như vậy là đơn định (deterministic).

Ta dễ nhận thấy tính đơn giản của các máy Turing đơn định với quan niệm như sau : một câu f ∈ S* không được thừa nhận ngay khi phép tính hợp lệ xuất phát từ (e, q1, f) không dừng. Trong trường hợp này, chương trình P của máy Turing :

P ⊆ Q ´ S ´ S ´ M ´ Q

Page 36: LyThuyetTinhToan - Phan Huy Khanh

30 Lý thuyết tính toán

là một hàm bộ phận (partial function) của Q ´ S vào S ´ M ´ Q, dễ dàng được phân tách thành ba hàm bộ phận khác nhau có cùng miền xác định (domain) trong Q ´ S :

� hàm ký tự mới nc : Q ´ S → S � hàm dịch chuyển đầu đọc−ghi mh : Q ´ S → M � hàm trạng thái mới ns : Q ´ S → Q Ba hàm này được định nghĩa như sau : nc (q, x) = y mh (q, x) = m ns (q, x) = q’

nếu và chỉ nếu (q, x, y, m, q’) là một quy tắc của P. Các máy Turing được sử dụng theo nhiều cách khác nhau. Ví dụ vừa được

trình bày trên đây mô tả cách thức máy Turing nhận biết các ngôn ngữ. Dưới đây, ta sẽ tiếp tục trình bày cách máy Turing tính toán các hàm.

II. Các hàm T−tính được Giả sử ta chỉ xét các máy Turing đơn định. Cho T =<S, Q, P> là một máy Turing. Ta nói T xác định một hàm bộ phận fT

từ S* → S* như sau : miền xác định của hàm fT là ngôn ngữ được thừa nhận bởi T, và với mỗi câu f ∈ S*, ta có một phép tính hợp lệ tối đa :

(e, q1, f) Ã−T c’ = (g, q, h)

với fT được xác định bởi :

fT(f) = gh

gh được gọi là kết quả của phép tính của T đối với câu vào f. Người ta cũng nói náy Turing T thực hiện (tính) hàm fT.

Ví dụ 3.2 : Cho T1 = <S, Q, P> với S = {0, 1, #}, Q = {q1, q2, q3} và

P = { q1, 1 → 1, R, q1, q2, 0 → 1, L, q3, q1, 0 → 0, R, q1, q2, 1 → 0 L, q2, q1, # → #, L, q2, q2, # → 1, L, q3 }

Page 37: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 31

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} Ã−T (1010, q3, 1)

c2 = { e, q1, 100111} Ã−T (10, q3, 1000)

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) Ã−T (##1111, q4, 111)

Đị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)

Page 38: LyThuyetTinhToan - Phan Huy Khanh

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.

III. Lớp các hàm T−tính được Trong mục này, ta sẽ xét một số hàm T-tính được rất sơ cấp (elementary

functions), để từ đó, ta xây dựng các hàm phức tạp hơn nhờ phép hợp thành. Ta cũng tìm cách mở rộng khả năng hoạt động của các máy Turing.

III.1. Một số hàm sơ cấp Ta xây dựng máy Turing để tính toán một số hàm rất sơ cấp từ G* vào G*,

hay (G*)n vào G*, trong đó, G là một bảng chữ không chứa ký tự trắng #, và các bộ−n (n−tuple) gồm các phần tử được ngăn cách nhau bởi một ký tự trắng #. Đó là các hàm hằng, hàm chiếu, hàm kế tiếp và hàm kế trước.

III.1.1. Các hàm hằng (constant functions) Xét hàm hằng : Bin_FivnG : (G*)n → G*

sao cho mọi dữ liệu vào là một bộ−n câu của G*, dạng f1#f2# ... #fn, hàm hằng luôn trả về một câu nào đó của G*. Ví dụ 3.4 :

Giả sử G = {0, 1} và n = 2, với mọi dữ liệu vào là một cặp câu dạng f#g, Bin_Fiv2G luôn trả về một câu, chẳng hạn 101∈G* (101 là biểu diễn nhị phân của số 5).

Xây dựng máy Turing thực hiện hàm hằng Bin_Fiv2G như sau : T =<S, Q, P> với S = G ∪ {#}, Q = {q1, q2, q3, q4, q5} và

P = { q1, 1 → $, R, q1, q1, # → #, R, q2, q1, 0 → #, R, q1,

Page 39: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 33

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) Ã−*T ( #, q5, # 101 #).

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.

III.1.2. Các hàm chiếu (projection functions) Xét hàm chiếu :

Projn, iG : (G*)n → G* sao cho với mọi bộ−n các câu của G*, hàm chiếu trả về câu thứ i của dãy này. Ví dụ 3.5 :

Giả sử G = {0, 1}, n = 4 và i = 2, xây dựng máy Turing thực hiện hàm chiếu Proj4, 2G để trả về kết quả là câu thứ hai trong dữ liệu vào là dãy bốn câu như sau :

T =< S, Q, P> với S = G ∪ {#}, Q = q1, q2, q3, q4, q5} và

P = { q1, 1 → #, R, q1, q1, 0 → # R, q1, q1, # → #, R, q2, q2, 1 → 1, R, q2, q2, 0 → 0, R, q2, q2, # → #, R, q3, q3, 1 → #, R, q3, q3, 0 → #, R, q3, q3, # → #, R, q4, q4, 1 → #, R, q4, q4, 0 → #, R, q4 q4, # → #, L, q5 }

Ta có c = (e, q1, 10#01#100#101#) Ã−*T (#, q5, #10#)

Ta nhận thấy rằng hàm chiếu cũng rất dễ triển khai như hàm hằng và có thể xây dựng bất kỳ kiểu hàm chiếu nào.

III.2. Các hàm kế tiếp (successor functions) Xét hàm kế tiếp :

Page 40: LyThuyetTinhToan - Phan Huy Khanh

34 Lý thuyết tính toán

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 #)Ã−*T (#1, q3, 00#)

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ữ.

III.3. Các hàm kế trước (predecessor functions) Tương tự hàm kế tiếp, ta có thể dễ dàng xây dựng hàm kế trước :

PredG : G* → G*

sao cho với mọi câu f∈G*, hàm PredG trả về câu kế trước của f trong thứ tự đã cho của bảng chữ S. Để hàm PredG là toàn phần, ta cần quy ước rằng câu đứng trước câu rỗng cũng chính là câu rỗng.

Bài tập : Xây dựng một máy Turing thực hiện hàm kế trước.

III.4. Sự hợp thành (composition) Nhiều hàm được định nghĩa từ nhiều hàm khác hợp thành. Ta sẽ nghiên cứu

các kỹ thuật cho phép xây dựng lớp các hàm T−tính được nhờ phép hợp thành.

Page 41: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 35

III.4.1. Các máy được tiêu chuẩn hóa Một máy Turing được gọi là đã tiêu chuẩn hóa (standadized) nếu, khi tính

toán xong, đầu đọc-ghi được đặt tại vị trí khác ký tự trắng # cận trái nhất của phần hữu ích trên băng.

Hình 3.3 Máy Turing được tiêu chuẩn hóa

Mệnh đề 3.1 : Nếu T là một máy Turing, thì có thể xây dựng từ T một máy turing T’ khác

được tiêu chuẩn hóa cùng thực hiện một chức năng (tính hàm) như T.

Bài tập : Chứng minh mệnh đề 3.1

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 :

Hình 3.4. Máy Turing T có trạng thái đầu

←−− Phần hữu ích −−→

. . . # # # a # # # . . .

q

q1 T

Page 42: LyThuyetTinhToan - Phan Huy Khanh

36 Lý thuyết tính toán

III.4.2. Các máy Turing được chuẩn hóa Cho máy Turing T =<S, Q, P> có một tập hợp con A các trạng thái thõa mãn : 1. Không một trạng thái nào của A nằm trong vế trái của quy tắc

2. Với mọi trạng thái q∈Q\A và mọi ký tự x∈S, tồn tại một quy tắc của P có (q, x) là vế trái.

Một máy Turing như vậy được gọi là đã được chuẩn hóa (normalized). Nói cách khác, máy Turing là được chuẩn hóa nếu với một tập hợp trạng thái

A, một phép tính dừng nếu và chỉ nếu máy Turing rơi vào một trạng thái của A. Một trạng thái của A được gọi là một trạng thái dừng (halt state)

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ơ đồ :

Hình 3.5. Máy Turing T được chuẩn hóa Nếu tiến hành đồng thời cả hai cách xây dựng vừa nêu, chúng ta sẽ nhận được

một máy Turing vừa được tiêu chuẩn hóa, vừa được chuẩn hóa.

III.4.3. Tổ hợp các máy Turing Cho T là một máy Turing chuẩn hóa có một trạng thái dừng duy nhất qh, và T’

là một máy Turing bất kỳ nào đó. Ta định nghĩa máy Turing tổ hợp từ T và T’, ký hiệu T next T’, bằng cách đánh số lại các trạng thái của T’ để nhận được các trạng thái tách rời (disjoint) với các trạng thái của T và lấy trạng thái dừng của T làm trạng thái đầu của T’ :

Hình 3.6. Máy Turing T next T’ Chú ý rằng nếu T’ được tiêu chuẩn hóa (một cách tương ứng, được chuẩn hóa)

thì máy Turing T next T’ cũng được tiêu chuẩn hóa (được chuẩn hóa). Rõ ràng rằng, nếu T được tiêu chuẩn hóa và thực hiện hàm f và nếu T’ thực

hiện hàm f’, thì máy Turing T next T’ thực hiện hàm ghép f’°f.

q1 T qh

q1 T T’ qh

= q’1

Page 43: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 37

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.

III.5.1. Cấu trúc if then else và cấu trúc rẽ nhiều nhánh Cho T là một máy Turing chuẩn hóa dừng ở các trạng thái qh1

, qh2, ..., qhk

T1, T2, ..., Tk là những máy Turing bất kỳ, người ta định nghĩa phép tổ hợp tổng quát (generalized combinator) từ phép tổ hợp next bởi :

T next if h1 : T1, if h2 : T2, ..., if hk : Tk

là máy Turing nhận được bằng cách đánh số lại các trạng thái của Ti để nhận được các trạng thái tách rời nhau giữa chúng và tách rời các trạng thái của T, bằng cách lấy trạng thái dừng qh1

của T làm trạng thái đầu của T1, lấy trạng thái

dừng qh2 của T làm trạng thái đầu của T2, ..., lấy trạng thái dừng qhk

của T làm

trạng thái đầu của Tk.

Nếu máy Turing T dừng với mọi dữ liệu vào, T sẽ thực hiện phép rẽ nhánh theo các trường hợp khác nhau (với if then else là một trường hợp đặc biệt).

Page 44: LyThuyetTinhToan - Phan Huy Khanh

38 Lý thuyết tính toán

Chẳng hạn với k = 2, máy Turing T thực hiện lệnh if then else :

Hình 3.7. Máy Turing T next if h1 : T1, if h2 : T2

III.5.2. Cấu trúc while Cho T là máy Turing chuẩn hóa có hai trạng thái dừng qh1

và qh2, và T’ là

một máy Turing chuẩn hóa có duy nhất một trạng thái dừng q’h. Giả thiết rằng T và T’ có các trạng thái rời nhau. Người ta định nghĩa while T do qh : T’ là máy Turing nhận được từ T và T’ bằng cách lấy trạng thái dừng qh2

của T làm trạng

thái đầu của T’ và lấy trạng thái dừng của T’ làm trạng thái đầu q1 của T.

Máy Turing while T do qh : T’ được vẽ như sau :

Hình 3.8. Máy Turing while T do h2 : T’

Người ta nhận thấy rằng, các trạng thái của một máy Turing có thể được xem như là các nhãn (label) của chương trình của chính máy này. Do vậy, các quy tắc trong P dạng q, x → y, m, p có thể được viết dưới dạng :

q : if x then y, m next goto p và bằng cách nhóm tất cả các quy tắc có cùng trạng thái q là vế trái, lúc này chỉ cần viết q ở quy tắc đầu tiên liên quan.

Chương trình tìm phần tử kế tiếp ở ví dụ 3.7 bây giờ được viết lại như sau : q1 : if 0 then 0, R next goto q1

if 1 then 1, R next goto q1 if 2 then 2, R next goto q1 if # then #, L next goto q2

q2 : if 0 then 1, R next goto q3

q1 T

T1 qh1

T2qh2

q1 T

qh1

T’qh2

Page 45: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 39

if 1 then 2, R next goto q3 if 2 then 0, L next goto q2 if # then #, R next goto q3

q3 : halt

III.6. Quản lý bộ nhớ Khi xây dựng các máy Turing thực hiện các hàm phức tạp, người ta gặp phải

vấn đề quản lý bộ nhớ, nghĩa là khả năng tổ chức lại nội dung các ô ở trên băng. Ta đưa vào các khả năng quản lý bộ nhớ cho máy Turing như sau :

III.6.1. Máy Turing chuyển một ô qua phải Việc chuyển một ký tự sang bên phải được thực hiện đối với một bảng chữ có

ba ký tự là S = {#, 0, 1} nhờ máy Turing có tập hợp P gồm các quy tắc như sau : P = { q1, 0 → #, R, q(0),

q1, 1 → #, R, q(1), q(0), 0 → 0, R, q(0), q(0), 1 → 0, R, q(1), q(1), 0 → 1, R, q(0), q(1), 1 → 1, R, q(1), q(0), # → 0, R, q(#), q(1), # → 1, R, q(#), q(#), 0 → #, R, q(0), q(#), 1 → #, R, q(1) }

Máy Turing này dừng lại khi gặp hai ký tự # liên tiếp. Từ cách xây dựng này, dễ dàng xây dựng được các máy Turing chuyển k ô qua phải (hoặc qua trái).

III.6.2. Máy Turing chỉ sử dụng phần băng bên phải kể từ vị trí đầu tiên của đầu đọc-ghi

Nếu T =< S, Q, P > là một máy Turing thực hiện hàm f, có thể xây dựng một máy Turing khác mô phỏng T sao cho đầu đọc−ghi không bao giờ vượt qua bên trái vị trí ban đầu.

Giả sử T1 là máy Turing đặt một dấu h ở vị trí đầu tiên của đầu đọc−ghi và di chuyển nội dung câu vào một ô qua bên phải. Giả sử T2 là máy Turing cho phép di chuyển nội dung một ô qua bên phải xuất phát từ vị trí đầu tiên của đầu đọc−ghi (và đặt một ô ký tự trắng # tại vị trí ô đầu tiên đã di chuyển).

Như vậy, có bao nhiêu trạng thái trong máy T thì có bấy nhiêu máy sao chép của T2 và giả thiết chúng đều đã được tiêu chuẩn hóa và chuẩn hóa. Ký hiệu T2i

Page 46: LyThuyetTinhToan - Phan Huy Khanh

40 Lý thuyết tính toán

là bản sao tương ứng với trạng thái qi, còn pi1 là trạng thái đầu và pih

là trạng thái

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 T2i

, ngoài ra, P3 còn có thêm các quy tắc sau :

P3 = { qi, h → h, R, pi1

pih, x → x, L, qi } với x ∈ S là ký tự bất kỳ.

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.

III.7. Một số máy Turing thông dụng Sau đây ta sẽ xét một số máy Turing thực hiện các chức năng phức tạp hơn.

III.7.1. Sao chép Xây dựng hàm :

CopyG : G* → (G*)2

sao cho ∀ câu f ∈ G*, với G = {0, 1}, hàm CopyG trả về câu f #f ∈ (G*)2.

Giả sử T1 là máy Turing đọc một ký tự và thay thế ký tự đó bởi ký tự đánh dấu a, sau đó di chuyển qua phải để viết lại ký tự này tại vị trí của ký tự trắng # đầu tiên gặp phải, sau đó quay trở lại ký tự đánh dấu a để thay thế nó bởi ký tự ban đầu. Máy T1 dừng ngay lập tức ở bên phải vị trí này.

Cho T1 = < S, Q, P> với S = G ∪ {a, b, #}, Q = {q1, q2, q3, q4, q5, q6} và

P = { q1, 1 → a, R, q2, q1, 0 → a, R, q4, q2, 0 → 0, R, q2, q2, 1 → 1, R, q2, q4, 0 → 0, R, q4, q4, 1 → 1, R, q4, q2, b → b, R, q2, q4, b → b, R, q4, q2, # → 1, L, q3, q4, # → 0, L, q5 q3, 0 → 0, L, q3, q3, 1 → 1, L, q3, q5, 0 → 0, L, q5,

Page 47: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 41

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.2. Kiểm tra bằng nhau Cần xây dựng máy Turing so sánh hai câu cho trước có bằng nhau không. Muốn vậy, ta xây dựng máy Turing có hai trạng thái dừng qYes và qNo sao cho

khi cho câu vào f#g, máy dừng ở trạng thái qYes nếu f = g và máy dừng ở trạng thái qNo nếu f ≠ g.

Máy hoạt động như sau : thay đổi câu vào f#g thành fagb với a và b là hai ký tự đánh dấu. Sau đó, trong khi f và g còn khác rỗng, thay thế các ký tự cuối của f và g bởi a và b tương ứng rồi ghi nhớ chúng. Nếu sau khi thay thế, chúng khác nhau, máy dừng ở trạng thái qNo. Nếu không, tiếp tục quá trình. Cho tới khi đồng thời cả f và g đều rỗng thì máy dừng ở trạng thái thái qYes, nếu không phải, máy dừng ở trạng thái qNo.

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

Page 48: LyThuyetTinhToan - Phan Huy Khanh

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*.

III.7.4. Các hàm chiếu ngược (antiprojection function) Xét hàm chiếu ngược :

Antiprojn, iG : (G*)n → (G*)n-1

sao cho biến mỗi bộ−n là dãy n câu của G* thành bộ−(n−1) câu, bằng cách lấy đi câu thứ i của dãy n câu.

Máy Turing thực hiện hàm chiếu ngược được mô tả như sau : sau khi đặt đầu đọc−ghi ngay trước câu thứ i (tại ký tự # thứ i của dữ liệu vào), máy Turing đánh dấu a tại vị trí này và xóa (thay thế bởi #) câu thứ i cho đến khi gặp ký tự # đặt trước câu thứ i+1. Sau đó, máy thực hiện lặp đi lặp lại phép dời qua trái một ô cho phần các câu còn lại (từ i + 1 đến n) cho đến khi gặp ký tự đánh dấu a. Máy dừng lại sau khi đã xóa ký tự đánh dấu a.

III.7.5. Các hàm giao hoán Hàm giao hoán (permutation function) :

Permi, j : (G*)n → (G*)n cho phép giao hoán câu thứ i và câu thứ j của dãy n câu :

(w1, ..., wi, ...,wj, ..., wn) ∈ (G*)n

thành : (w1, ...,wi-1, wj , wi+1 , ..., wj-1 , wi , wj+1 , ..., wn)

nghĩa là câu thứ i đổi chỗ cho câu thứ j và ngược lại. Máy Turing thực hiện hàm giao hoán được xây dựng bằng cách tổ hợp cách

máy sao chép và máy chiếu ngược.

III.8. Các hàm T-tính được phức tạp hơn Bây giờ ta sẽ xây dựng các máy Turing thực hiện các phép tính số học dựa

trên các công cụ đã có. Phép cộng : Ta cần thực hiện phép cộng hai số nguyên hệ 2 : Giả sử m và n là

hai số nguyên được biểu diễn bởi hai câu u và v trên bảng chữ {0, 1}. Gọi dữ liệu là u#v và ta cần chuyển nó thành uabv, với a và b là hai ký tự đánh dấu.

Page 49: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 43

Đặ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ỳ.

III.9. Nhận xét Như đã trình bày, nhờ các máy Turing, ta có thể thực hiện được một lớp rộng

các hàm xử lý các phép tính số học. Tuy nhiên, như ta sẽ thấy về sau, lớp các hàm T−tính được không chứa tất cả mọi hàm. Như vậy, ta không thể xây dựng bất cứ mọi hàm nhờ các máy Turing. Vì vậy, trong những phần sau, ta cần khoanh vùng chính xác các hàm T−tính được.

Bây giờ ta xét một hàm f từ Ν → Ν và bốn cách biểu diễn các số nguyên r1, r2, r3 và r4 (chẳng hạn đơn phân, nhị phân, thập phân và thập lục phân). Giả sử f1 là hàm nhận đối số là một số nguyên n có dạng biểu diễn r1 để cho kết quả f (n) có dạng biểu diễn r2. Giả sử f2 là hàm nhận đối số là một số nguyên n có dạng biểu diễn r3 để cho kết quả f (n) có dạng biểu diễn r4. Khi đó, f1 là T−tính được khi và chỉ khi f2 là T−tính được.

Theo cách xây dựng hàm f, ta thấy rằng có thể xây dựng được máy Turing TC có dữ liệu vào là một số nguyên n dưới dạng biểu diễn r1 để có kết quả dưới dạng biểu diễn r3. Tương tự, ta có thể xây dựng máy TD có dữ liệu vào là một số nguyên m dưới dạng biểu diễn r4 để cho kết quả dưới dạng biểu diễn r2.

Nếu T’ là máy Turing thực hiện hàm f2, thì T =TC next T’ next TD là một máy Turing thực hiện hàm f1.

Như vậy một hàm T−tính được phải không phụ thuộc vào cách biểu diễn lựa chọn, miễn rằng cách biểu diễn này vẫn còn hợp lý. Nghĩa là người ta có thể chuyển từ cách biểu diễn này qua cách biểu diễn khác nhờ một máy Turing.

Page 50: LyThuyetTinhToan - Phan Huy Khanh

44 Lý thuyết tính toán

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ê.

Page 51: LyThuyetTinhToan - Phan Huy Khanh

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.

Page 52: LyThuyetTinhToan - Phan Huy Khanh

46 Lý thuyết tính toán

IV. Các biến thế khác của mô hình máy Turing Theo quan niệm của lý thuyết tính toán, hai mô hình được gọi là tương đương

nếu những gì tính được (một cách tương ứng : nhận biết được, liệt kê được) trong một mô hình này thì cũng có thể tính được (một cách tương ứng : nhận biết được, liệt kê được) trong mô hình kia. Trong mục này, ta sẽ chỉ ra rằng các mô hình biến thể (variant model) của mô hình các máy Turing tiêu chuẩn hoá đã xét trước đây cũng chỉ là những mô hình tương đương với chúng.

Nhờ khái niệm về phép mô phỏng (simulation), trước hết ta cần chỉ ra rằng các máy Turing nhiều băng và các máy Turing không đơn định có thể được mô phỏng bởi các máy Turing tiêu chuẩn hoá. Sau đó, ta sẽ xem xét vấn đề về bản số giới hạn (số lượng ký tự) của một bảng chữ.

IV.1. Mô phỏng một máy Turing bởi một máy khác Định nghĩa 3.3 :

Một máy Turing T được mô phỏng bởi một máy T’ nếu xây dựng được một phép đơn ánh i từ các cấu hình của T vào các cấu hình của T’, sao cho, nếu cÃ− c’ trong T, thì i(c) Ã−* i(c’) trong T’. Máy T’ dừng kể từ một cấu hình xuất phát i(c) nếu và chỉ nếu T dừng kể từ một cấu hình xuất phát c.

Nếu T’ mô phỏng T, thì hàm do T’ thực hiện sẽ cho phép tìm lại hàm do T thực hiện modulo phép biểu diễn các đối tượng ( dữ liệu và kết quả).

Một cách cụ thể hơn, giả sử TC là một máy Turing thực hiện phép đơn ánh, nghĩa là, xuất phát từ một dữ liệu của máy T, trả về một dữ liệu tương ứng cho T’ (người ta nói rằng dữ liệu đã được mã hóa). Giả sử TD thực hiện phép đơn ánh ngược lại, nghĩa là xuất phát từ một kết quả của máy T’ trả về một kết quả cho T (người ta nói rằng dữ liệu đã được giải mã). Khi đó máy :

TC next T’ next TD

quả thực đã thực hiện cùng một hàm với máy T. Ví dụ 3.8 : Phép tính giữa hai ký tự đánh dấu

Cho T =<S, Q, P> là máy Turing thực hiện hàm f, xây dựng máy T’ trên bảng chữ S ∪ {a, b}, với a và b là hai ký tự mới. Máy T’ sẽ mô phỏng máy T sao cho một cấu hình (f, q, g) của T sẽ được mã hóa bởi một cấu hình (af, q, gb) của T’.

Cho Q’ và Q’’ là hai tập hợp các trang thái có song ánh (bijection) với Q. Đặt q’i và q’’i lần lượt là các trạng thái của Q’ và Q’’ có song ánh với trạng thái qi của Q. Xây dựng các tập hợp quy tắc P và P” như sau :

P’ = { qi, b → #, R, qi’, q’i, # → b, L, qi } với ∀qi ∈ Q

Page 53: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 47

P’’ = { qi, a → #, L, q’’i, q’’i, # → a, R, qi } với ∀qi ∈ Q

Khi đó, máy T’ = <S ∪ {a, b}, Q ∪ Q’ ∪ Q”, P ∪ P”> cũng là một máy Turing.

Bây giờ xây dựng máy Turing TC (với chương trình PC) có dữ liệu vào là câu f và kết quả là câu afb :

PC = { q1, x → x, L, q2, q2, # → a, R, q3, q3, x → x, R, q3, q3, # → #, R, q4, q4, x → x, R, q3 q4, # → #, L, q5, q5, # → b, L, q6, q6, y → y, L, q6 q6, a → a, R, q7 }

Ở đây, x ≠ # và x ∈ S là ký tự bất kỳ, y ∈ S cũng là ký tự bất kỳ. Xây dựng máy Turing TD (với chương trình PD) có dữ liệu vào là câu afb và

kết quả là câu f : PD = { q1, y → y, R, q1,

q1, b → #, L, q2, q2, y → y, L, q2, q2, a → #, R, q3 }

Ở đây y là ký tự bất kỳ y ≠ a và y ≠ b. Như vậy máy Turing : TC next T’ next TD

thực hiện hàm f.

Page 54: LyThuyetTinhToan - Phan Huy Khanh

48 Lý thuyết tính toán

IV.2. Các biến thể của máy Turing Biến thể quan trọng nhất và thông dụng nhất là máy Turing không đơn định

(non-deterministic). Tuy nhiên vẫn còn các biến thể khác với những thay đổi không lớn. Ta sẽ nghiên cứu các máy Turing không đơn định ở chương cuối khi nghiên cứu các lớp độ phức tạp.

IV.2.1. Máy Turing có k băng Máy Turing loại này có k băng vô hạn về cả hai phía, mỗi băng có đầu

đọc−ghi riêng. Mỗi quy tắc lúc này có dạng : q, x1, x2, ..., xk → y1, m1, y2, m2, ..., yk, mk, q’

với xi là ký tự nằm dưới đầu đọc-ghi, yi là ký tự thay thế cho xi, và mi∈{L, R} chỉ hướng (qua trái hoặc qua phải) của đầu đọc-ghi tương ứng tại băng thứ i, i=1..k.

Giả sử T =<S, Q, P> là máy Turing có k băng như đã mô tả, ta mô phỏng T bởi một máy Turing T’ hoạt động trên bảng chữ :

G = {a, b} ∪ Z, với Z = { <z1, z2, ..., zk> | zi ∈ S ∪ {#} },

với a, b và # là những ký tự mới thêm. Ta ký hiệu pi là phép đơn ánh :

pi(<z1, z2, ..., zk>) = zi.

Một cấu hình (q, f1g1, f2g2, ..., fkgk) của T (đầu đọc−ghi của băng thứ i đặt tại ký tự đầu tiên của câu gi, được mã hóa bởi câu awb, với w ∈ Z*, sao cho với ∀i :

pi(w) = fi#gi (phần không sử dụng của mỗi băng là các ký tự #).

Lúc này, mỗi quy tắc của T dạng : q, x1, x2, ..., xk → y1, m1, y2, m2, ..., yk, mk, q’

sẽ được mô phỏng bởi một dãy các quy tắc của T’ thực hiện các phép tính sau : Xuất phát từ ký tự đánh dấu a, đầu đọc−ghi của T’ đọc các ký tự của w. Với

mỗi thành phần fi#gi, máy ghi nhớ trong các trạng thái của nó, trạng thái q hiện hành của T và ký tự theo sau # là xi (ký tự đầu tiên của gi). Sau khi đã ghi nhớ hết các thành phần bên trái của quy tắc, T’ thực hiện các thay đổi tương ứng với thành phần bên phải của quy tắc này. T’ xem xét câu vào w để trên mỗi băng i :

Nếu mi = R, thay đổi # và xi tương ứng bởi yi và #, nghĩa là #xi → yi#.

Nếu mi = L và giả sử zi đứng trước # (ký tự cuối của fi), thay đổi zi, # và xi tương ứng bởi #, zi và yi, nghĩa là zi#xi → #ziyi.

Cuối cùng, đầu đọc-ghi đặt tại ký tự đánh dấu a. Như đã chỉ ra ở trên, trong phép tính giữa các ký tự đánh dấu, các ký tự a và b có thể bị xê xịch trong quá trình tính toán do ký tự <#, #, ..., #> gây ra. Rõ ràng, máy Turing T’ một băng đã mô phỏng máy Turing T có k băng.

Page 55: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 49

IV.2.2. Các máy off−line và các máy có băng ra Máy Turing có nhiều băng có đặc tính sau : trên một băng nào đó, đầu

đọc−ghi không làm thay đổi ký tự đã đọc. Nói cách khác, đầu đọc-ghi chỉ làm nhiệm vụ đọc không bao giờ ghi, gọi tắt là đầu đọc, không làm thay đổi nội dung câu vào trên băng. Do băng này chỉ dùng để lưu giữ và nhận biết dữ liệu vào, nên được gọi là băng vào của máy Turing.

Một máy Turing k + 1 băng có một băng vào với đầu đọc chỉ di chuyển theo một chiều duy nhất (giả sử quy ước từ trái qua phải) như vừa mô tả được gọi là máy off−line. Rõ ràng, một máy Turing k băng có thể được mô phỏng bởi một máy off−line có k + 1 băng (chỉ cần sao chép dữ liệu trên băng vào lên một băng nào đó và sau đó chỉ làm việc với k băng còn lại).

Tương tự, ta có thể xây dựng máy Turing nhiều băng có một băng ra có đặc tính như sau : trên một băng nào đó chọn làm băng ra, lúc đầu chỉ chứa toàn ký tự trắng #, đầu đọc−ghi trên băng này chỉ di chuyển theo một chiều duy nhất (từ trái qua phải). Nói cách khác, đầu đọc−ghi chỉ làm nhiệm vụ ghi, gọi tắt là đầu ghi, để ghi các ký tự kết quả lên các ô, sau khi ghi xong, đầu ghi không bao giờ quay lui trở lại để thay đổi nội dung đã ghi. Do đầu ghi chỉ di chuyển theo một chiều nên thực tế, băng ra chỉ vô hạn về một phía mà thôi.

Máy Turing vừa có một băng vào và vừa có băng ra được biểu diễn như sau:

Hình 3.9. Máy Turing có một băng vào và một băng ra Kiểu máy Turing có băng vào và băng ra được xem là kiểu cơ sở của các máy

Turing. Ưu điểm của kiểu máy này là tính đồng dạng (similitude) với mô hình các máy RAM đã xét trước đây.

IV.2.3. Các máy Turing không đơn định Chúng ta sẽ chỉ ra rằng nếu L là ngôn ngữ được nhận biết bởi một máy Turing

không đơn định, thì L cũng được nhận biết bởi một máy Turing đơn định. Cho T là một máy Turing không đơn định. Từ T, người ta xây dựng một máy

Turing T’ đơn định có ba băng : băng thứ nhất chứa dữ liệu vào, trên băng thứ hai, ta chép lại dữ liệu vào và tiến hành phép tính một cách lặp đi lặp lại. Còn

. . . # # # f x g # # # . . .

Băng làm việc q

w # # # # . . .

u y v # # # . . . Băng vào

Băng ra

Page 56: LyThuyetTinhToan - Phan Huy Khanh

50 Lý thuyết tính toán

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.

IV.2.4. Thu gọn một bảng chữ còn ba ký tự Cho máy Turing T =<S, Q, P> với || S|| = n. Nếu n ≤ 1 + 2k người ta có thể sử

dụng mã sau đây : c(#) = #

và với ∀xi ∈ S, thì c(xi) là câu thứ i trên {0, 1} có độ dài k.

Mô phỏng máy T bởi máy T’ = <S’, Q’, P’>, trong đó : S’ = {#, 0, 1} Q’ là tập hợp các trạng thái <q, w, w’, i, m> (có 5 thành phần) với :

− q ∈ Q,

− w và w’ là các câu ∈ S’* có độ dài nhỏ hơn hoặc bằng k, − i ≤ k, i là một số nguyên, − m ∈ {L, R, ε}

Một cấu hình (f, q, g) của máy T được mã hóa bởi cấu hình của máy T’ : (c (f), < q, w, ε, 0, ε>, c (g)) Còn P’ gồm ba loại quy tắc được định nghĩa như sau :

Page 57: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 51

z Các quy tắc nhận biết mã ký tự : <q, w, ε, 0, ε>, x → x, R, <q, wx, e, 0, e> nếu |wx| < k Ở đây, T’ sử dụng các trạng thái có 5 thành phần để ghi nhớ trạng thái hiện

hành q của T (thành phần thứ nhất) và ghi nhớ quá trình đọc lần lượt k−1 ký tự đầu tiên của mã của một ký tự (thành phần thứ hai). Nội dung ghi nhớ này sẽ dùng để xây dựng các quy tắc mô phỏng P.

z Các quy tắc thay đổi ký tự mới : Nếu q, xi → xj, m, p là quy tắc của P, và nếu wx có giá trị c(xi) và w’y có giá

trị c(xj) thì P’ có quy tắc :

<q, w, e, 0, e>, x → y, L, <q, wx, w’, k − 1, m> Khi nhận biết được mã wx của ký tự, mã này sẽ được thay thế bởi mã w’y của

ký tự có mặt trong vế phải. Để bắt đầu thay thế, ta viết y, ký tự cuối của mã. Phần còn lại của mã này là w’ sẽ được ghi nhớ trong trạng thái (thành phần thứ ba). Cuối cùng, thành phần thứ tư là một bộ đếm được khởi động đến k − 1.

z Các quy tắc di chuyển đầu đọc−ghi : Ta phải di chuyển đầu đọc-ghi theo chiều chỉ ra bởi m, được ghi nhớ trong

thành phần thứ năm của trạng thái. Luôn luôn nếu quy tắc q, xi → xj, m, p ∈ P, và nếu wx có giá trị c(xi), thì sau

khi tiến hành mọi sự thay thế cần thiết, T’ sẽ rơi vào trạng thái <q, wx, e, 1, m>. z Các quy tắc di chuyển trạng thái mới : <q, wx, e, 1, m>, z → z, m, <p, e, e, 0, e> Những sự thay đổi cần thiết được thực hiện nhờ các quy tắc : <q, w, w’x, k − 1, m>, y → x, L, <q, w, w’, k − 1, m> và <q, w, e, i, m>, x → x, m, <q, w, e, i − 1, m> với i > 0. Trạng thái đầu của T’ là <q, e, e, 0, e> ∈ Q’.

Ví dụ 3.9 : Với bảng chữ gồm 9 ký tự {x1, x2, ..., x8, #}, ta sử dụng mã 3 ký tự sau :

c(#) = #, c(x3) =010, c(x6) = 101,

c(x1) = 000, c(x4) = 011, c(x7) = 110,

c(x2) = 001, c(x5) = 100, c(x8) = 111

Chẳng hạn ta mô phỏng quy tắc (q, x4) → (x7, R, p) thành dãy các quy tắc :

Page 58: LyThuyetTinhToan - Phan Huy Khanh

52 Lý thuyết tính toán

<q, ε, ε, 0, ε>, 0 → 0, R, <q, 0, ε, 0, ε> <q, 0, ε, 0, ε>, 1 → 1, R, <q, 01, ε, 0, ε> <q, 01, ε, 0, ε>, 1 → 0, L, <q, 011, 11, 2, R>, <q, 011, 11, 2, R>, 1 → 1, L, <q, 011, 1, 2, R>, <q, 011, 1, 2, R>, 0 → 1, R, <q, 011, ε, 2, R>, <q, 011, ε, 2, R>, 1 → 1, R, <q, 011,ε 1, R>, <q, 011, ε, 1, R>, 0 → 0, R, <p, ε, ε, 0, ε>

IV.2.5. Rút gọn một bảng chữ còn hai ký tự Cho T = <S, Q, P> với S = {#, 0, 1} Ta có thể sử dụng mã có cùng độ dài 5 như sau : c(#) = |#|||, c(0) = ||#||, c(1) = ||| # | Ta mô phỏng T bởi máy Turing T’ = <{#, 1}, Q’, P’> trong đó : Q’ là tập hợp

các trạng thái có dạng : <q, w, w’, i, m> như ở trên đã trình bày với một cấu hình :

(f, q, g) được mã hóa bởi cấu hình :

(c(f), <q, ε, ε, 0, ε>, c(g)). P’ là tập hợp các quy tắc cho phép nhận biết mã của một ký tự (được đặt trong

thành phần thứ hai của trạng thái), và thực hiện ba thay đổi (ký tự mới, di chuyển đầu đọc-ghi và trạng thái mới) tuân theo vế phải của quy tắc sao cho hai thành phần đầu tiên của trạng thái được dùng cho vế trái.

Nếu tại một thời điểm tính toán, máy nhảy ra ngoài phần được mã hóa, thì khi đó sẽ gặp hai ký tự trắng # liên tiếp. Người ta sẽ thay thế năm ký tự # (5 là độ dài của mã) bởi mã của ký tự # trước khi tính toán trở lại.

IV.3. Các máy Turing có băng vô hạn một phía Như đã biết, nhiều tác giả chỉ nghiên cứu các máy Turing có băng vô hạn về

một phía. Thực ra, mô hình này tương đương với mô hình ta đã định nghĩa trong phần quản lý bộ nhớ (mục III.6).

Page 59: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 53

V. Máy Turing vạn năng Trong mục này, ta sẽ giải thích vì sao có thể mã hóa các máy Turing bởi một

câu trên một bảng chữ đã cho, từ đó có thể đánh số các máy. Tiếp theo, ta sẽ chỉ ra sự tồn tại của một máy Turing, gọi là máy Turing vạn năng (universal Turing machine), có dữ liệu vào là số thứ tự (number) của một máy Turing T và một dữ liệu vào khác f cùng đạt một kết quả như T đối với f, dù T và f như thế nào.

Không làm mất tính chất tổng quát, ta xét các máy Turing có Q = {q1, q2, ..., qn} và S có 9 ký tự kể cả ký tự trắng # được ký hiệu tổng quát S = {x1, x2, ..., x9}. Chẳng hạn bảng chữ Z = { #, 0, 1, q, x, L, R, ,, → }. Một quy tắc r ∈ P :

qi, xj → xk, m, ql

có thể được mã hóa bởi một câu trên Z như sau : c(r) = qi, xj, xk, m, ql

trong đó, mỗi số nguyên i được biểu diễn dưới một dạng nhị phân i_ . Từ nay về sau, ta sẽ quy ước rằng mọi số nguyên đều ở dạng biểu diễn nhị phân, chú ý rằng một số nguyên có gạch dưới (i_ , j_ , k_ , l_ ) chỉ định biểu diễn nhị phân của số nguyên đó.

Mã của một quy tắc sẽ là một câu của : R = q{0, 1}*, x{0,1}* → x{0, 1}*, M, q{0, 1}* với M = { L, R} Chú ý rằng ở đây R không sử dụng ký tự #. Chương trình của một máy Turing

gồm các quy tắc r1, r2, ..., rs có thể được mã hóa bởi câu : c(r1) # c(r2) # ... # c(rs).

Ta nhận thấy rằng mọi máy Turing có thể được mã hóa bởi một câu trên Z. Do đó các máy Turing là có thể đếm được. Từ đó, có thể gán cho mỗi máy Turing một con số, chẳng hạn hạng của nó trong một thứ tự phân cấp quy ước nào đó.

Giả sử Ti là máy Turing thứ i và gi là hàm được tính bởi máy Turing thứ i này. Dễ dàng xây dựng được máy Turing TD sao cho với dữ liệu vào i_ , cho ra kết quả là câu dùng để mã hóa máy Turing thứ i như sau :

Ta xây dựng một máy Turing hai băng. Băng thứ nhất chứa dữ liệu vào i_. . Trên băng thứ hai, ta liệt kê các câu của Z*, và với mỗi câu f đã liệt kê, ta kiểm tra nếu đó là mã của một máy Turing, nghĩa là nếu f thuộc về (R#)*R ? Nếu đúng như vậy, thì người ta giảm đi 1 số nguyên đang ở trên băng thứ nhất ( i_ ← i_ −1) và dừng lại nếu số nguyên nhận được là số không. Nếu không phải, tức là số nguyên chưa là số không, hoặc nếu câu vừa liệt kê không là mã của một máy Turing, thì người ta tiếp tục liệt kê các câu của Z*. Mệnh đề 3.6 :

Page 60: LyThuyetTinhToan - Phan Huy Khanh

54 Lý thuyết tính toán

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

Page 61: LyThuyetTinhToan - Phan Huy Khanh

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ữ.

VI. Tồn tại các hàm không là T−tính được Trong mục này, nhờ kỹ thuật chéo (diagonization argument), ta sẽ chứng

minh rằng tồn tại các hàm không là T−tính được. Mệnh đề 3.7 :

Không tồn tại máy Turing tính được hàm th được định nghĩa như sau : với mọi cặp số nguyên i và j :

th(i, j) = 1 nếu máy Turing số hiệu i dừng trên dữ liệu vào j, th(i, j) = 0 nếu không dừng. Ta nhận thấy phát biểu này thoả mãn cho mọi biểu diễn của các số nguyên

trong một hệ đếm bất kỳ. Chứng minh :

Page 62: LyThuyetTinhToan - Phan Huy Khanh

56 Lý thuyết tính toán

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 :

T’ = TC next T next TD

TC(i) = (i, i) ∀ i ∈ Ν 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

Page 63: LyThuyetTinhToan - Phan Huy Khanh

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

Page 64: LyThuyetTinhToan - Phan Huy Khanh

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 − l (n, m, p) = (nm)p

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ẻ).

Page 65: LyThuyetTinhToan - Phan Huy Khanh

PGS. TS. PHAN HUY KHÁNH biên soạn 59

CHƯƠNG 4

Luận đề Church «The greatest ocean of truth lay all undiscovered before me»

Sir Isaac Newton

I. Sự tương đương giữa các mô hình máy Turing và máy RAM

Trong mục này, ta sẽ chỉ ra rằng một hàm là T-tính được nếu và chỉ nếu hàm đó là tính được nhờ một máy RAM (hàm tính được nhờ một máy RAM được gọi là R−tính được).

I.1. Mọi hàm T-tính được cũng là R−tính được Ở đây, vấn đề là cần chỉ ra làm sao từ một chương trình P của một máy Turing giả thiết chỉ

có một băng vô hạn về một chiều, có thể suy ra được chương trình của một máy RAM thỏa mãn cho mỗi bước tính toán của máy Turing. Cách xây dựng như sau :

Nội dung các ô trên băng của máy Turing, được đánh số 0, 1, ... là nội dung tương ứng trong các thanh ghi R2, R3, ... của máy RAM. Số của thanh ghi tương ứng với ô nằm dưới đầu đọc ghi của máy Turing sẽ nằm trong thanh ghi R1 (lúc đầu nội dung của R1 là 2 do đầu đọc của máy Turing xuất phát từ ô đánh số 0).

Với mỗi trạng thái qi của máy Turing, người ta đưa vào một phần của chương trình của máy RAM để mô phỏng các thao tác tính toán của máy Turing tại trạng thái này, tùy theo ký tự được đọc trên băng.

Ví dụ, cho máy Turing trên bảng chữ kích thước 2 là S = {0, 1}. Giả sử nếu có hai quy tắc của P tương ứng với trạng thái qi ∈ Q là :

qi, 1 → x, m, qr qi, 0 → y, m’, qs

(trong đó, các di chuyển m và m’ có thể là L, R và qr, qs ∈ Q), thì một đoạn chương trình của máy RAM tương ứng sẽ là :

ki : LOAD I: R1 JZERO k’i LOAD A:x STORE I:R1 INCR R1 (hoặc, tùy theo m :DECR R1) JUMP Kr

k’i: LOAD A:y STORE I:R1 INCR R1 (hoặc tùy theo m’ : DECR R1) JUMP ks

Page 66: LyThuyetTinhToan - Phan Huy Khanh

60 Lý thuyết tính toán

Nếu một quy tắc tương ứng với một trạng thái qi không tồn tại, nghĩa là nếu một cặp (qi, x) không là vế trái của một quy tắc nào, thì máy Turing dừng. Lúc đó, nhom lệnh tương ứng cuả máy RAM sẽ là lệnh dừng Halt.

Rõ ràng, việc thực hiện của nhóm lệnh này mô phỏng một bước tính toán của máy Turing. Các trạng thái của máy Turing tương ứng hoàn toàn với các nhãn ki của chương trình RAM.

Khi viết hết các đoạn chương trình (tương ứng với các trạng thái khác nhau của máy Turing), người ta đã đặt chúng kề sát nhau, và có thể thay thế các nhãn ki bởi các con số. Như vậy, việc thực hiện toàn bộ chương trình đã mô phỏng việc tính toán đầy đủ của máy Turing.

I.2. Mọi hàm R−tính được cũng là T−tính được Ở đây, ta cần chỉ ra rằng, cho trước chương trình của một máy RAM, với giả thiết máy

RAM này rất thô sơ mà không làm mất tính tổng quát, ta có thể xây dựng được một máy Turing cho phép kiểm chứng từng bước tính toán của máy RAM. Cách xây dựng như sau :

Nếu x0, x1, ... là nội dung tương ứng của các thanh ghi R0, R1, ..., thì băng của máy Turing chứa :

0 : x 0 1 : x 1 . . . j : x j . . . Ở đây, và : là hai ký tự mới được thêm vào.

I.2.1. Tăng nội dung thanh ghi n lên 1 Với mọi lệnh của chương trình của máy RAM có dạng :

i: I<n> xây dựng một máy Turing Ti tiêu chuẩn hóa (normalized), có qi là trạng thái xuất phát và qi + 1 là trạng thái dừng.

Máy Ti hoạt động như sau : Ti di chuyển đầu đọc−ghi trên băng từ trái qua phải và so sánh số đứng sau mỗi ký tự với n.

Nếu là bằng nhau thì Ti tăng số nguyên tiếp theo sau ký tự : lên 1 (increment) bằng cách dời theo nhu cầu những gì theo sau qua bên phải, rồi dừng.

I.2.2. Giảm 1 nội dung thanh ghi n Tương tự như vậy, với mỗi lệnh của chương trình của máy RAM có dạng :

i: D<n> xây dựng một máy Turing Ti tiêu chuẩn hóa có qi là trạng thái xuất phát và qi + 1 là trạng thái dừng. Máy Ti hoạt động như sau :

Ti di chuyển đầu đọc−ghi trên băng từ trái qua phải và so sánh số đứng sau mỗi ký tự với n. Nếu là bằng nhau, thì Ti giảm một (decrement) số nguyên tiếp theo và dừng.

I.2.3. Đưa nội dung thanh ghi n về 0 Với mỗi lệnh của chương trình của máy RAM có dạng :

i: Z<n>

Page 67: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 61

xây dựng một máy Turing tiêu chuẩn hóa có qi là trạng thái xuất phát và qi + 1 là trạng thái dừng. Máy Ti hoạt động như sau :

Ti di chuyển đầu đọc−ghi trên 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 thay thế số nguyên tiếp theo bởi hằng 0 và dừng.

I.2.4. Nhảy theo nội dung thanh ghi n Với mỗi lệnh của chương trình của máy RAM có dạng :

i: J<n> (j, k) xây dựng một máy Turing tiêu chuẩn hóa có qi là trạng thái xuất phát và hai trạng thái dừng qj và qk. Máy Ti hoạt động như sau :

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.

I.2.5. Hoán vị nội dung hai thanh ghi n và m Bài tập : Xây dựng một máy Turing tiêu chuẩn hóa thực hiện lệnh của chương trình của

máy RAM có dạng :

I: S<n,m> Rõ ràng, mỗi bước tính toán của máy RAM, hay mỗi lần thực hiện một lệnh thứ i, đã được

mô phỏng bởi một máy Turing tương ứng. Nếu tập hợp tất cả các máy Turing này thành một máy duy nhất, thì máy này sẽ mô phỏng máy RAM.

I.3. Sự khác nhau giữa máy Turing và máy RAM Trước đây, ta đã giới thiệu máy Turing có băng vào và băng ra. Tuy vậy mô hình máy

Turing vẫn còn khác xa mô hình của máy RAM, do các chức năng của máy Turing rất hạn chế. Tuy nhiên, nếu ta nhớ lại rằng tập hợp các lệnh của các máy RAM có thể thu gọn đáng kể, bằng cách chuyển qua mô hình của máy RAM thô sơ, khi đó sự khác nhau giữa hai mô hình sẽ trở nên không đáng kể.

Vấn đề là cách biểu diễn dữ liệu khác nhau giữa hai mô hình. Với các máy Turing, dữ liệu vào là xâu ký tự trên băng, mỗi ô của băng chỉ chứa một ký tự. Còn với máy RAM, mỗi ô của băng chứa đúng một số nguyên.

Khi nghiên cứu về máy RAM, ta thấy rằng, nếu, một mặt, cách biểu diễn một số nguyên trong RAM gần giống với việc lưu giữ một “số nguyên” trong một đơn vị nhớ (memory word), mặt khác, lại không phải như vậy vì rằng kích thước của các số nguyên luôn luôn bị hạn chế trong thực tế.

Tuy nhiên, sự khác nhau chủ yếu giữa hai mô hình máy RAM và máy Turing là cách truy cập thông tin : trong mô hình máy RAM, nội dung một ô được đọc trực tiếp nhờ địa chỉ của ô đó, còn trong mô hình của máy Turing, để đi từ một ô này đến một ô khác, cần phải duyệt thăm tất cả các ô trung gian (cơ chế tuần tự).

Page 68: LyThuyetTinhToan - Phan Huy Khanh

62 Lý thuyết tính toán

II. Mô hình các hàm đệ quy

II.1. Các hàm đệ quy nguyên thủy (primitive recursive functions)

Có rất nhiều hàm được định nghĩa không theo cách trực tiếp, mà cần đến các hàm đã được định nghĩa trước đó, bằng cách sử dụng các sơ đồ định nghĩa. Đó là việc hợp thành (composition) một lớp các hàm xuất phát từ một số hàm sơ cấp (elementary function) dùng làm cơ sở.

II.1.1. Xây dựng các hàm sơ cấp Cho S là một bảng chữ có thứ tự (có ít nhất là hai ký tự) và một ký tự x ∈ S, ta ký hiệu ls(x)

là ký tự tiếp theo ký tự x theo thứ tự này, ls(x) ∈ S. Nếu x đứng cuối cùng của bảng chữ, thì ls(x) được quy ước là ký tự đầu tiên của bảng chữ S.

Với mỗi ký tự x ∈ S, ký hiệu ppx là hàm mà với mọi câu w ∈ S*, ppx (w) trả về câu wx.

Nghĩa là ppx(w) ∈ S*.

Tiếp tục định nghĩa các hàm first và last như sau : first (w) = 1 nếu w = e (câu rỗng)

= x nếu w = xw’ (x ∈ S) last (w) = 1 nếu w = e

= x nếu w = w’x (x ∈ S) Tiếp tục định nghĩa các hàm prefix và suffix như sau : prefix (w) = 1 nếu w = e

= w’ nếu w = w’x (x ∈ S) w’ là tiền tố dài nhất của w và khác với w khi w ≠ e suffix (w) = 1 nếu w = e

= w’ nếu w = xw’ (x ∈ S) Cuối cùng ta định nghĩa hàm equal trên S × S như sau : equal (x, y) = 1 nếu x = y

= x0 nếu x ≠ y, trong đó x0 là một ký tự cố định của bảng chữ S.

Chú ý : Đối với bảng chữ chỉ có một ký tự x duy nhất, các hàm prefix và suffix là đồng nhất với nhau và chính là hàm kế trước (predecessor), còn hàm kế tiếp (successor) lúc này chính là hàm ppx. Các hàm khác vừa được định nghĩa trên đây đều không có nghĩa.

Sau đây, ta đưa vào một số sơ đồ định nghĩa như sau :

II.1.2. Sơ đồ hợp thành tổng quát Cho S là một bảng chữ có thứ tự. Ta định nghĩa các hàm fi, i = 1.. k, k>0, và một hàm g như

sau : fi : S

* → S*, i = 1.. k

g : (S*)k → S*

Page 69: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 63

Từ fi và g, ta định nghĩa hàm h bởi sơ đồ hợp thành tổng quát như sau :

h = compk (f1, f2, ..., fk, g) : S* → S*

Nghĩa là với câu vào w ∈ S*, ta nhận được : h(w) = g(f1(w), f2(w), ..., fk(w)).

II.1.3. Sơ đồ đệ quy đơn (simple recurrence) Cho S là bảng chữ có thứ tự. Ta định nghĩa các hàm f và g như sau :

f : S* → S*

g : (S*)4 → S* Từ f và g, ta định nghĩa hàm h :

h = rec(f, g) : (S*)2 → S* Nghĩa là h nhận giá trị từ f và g bởi sơ đồ đệ quy đơn : h(1, m) = f(m) h(wx, m) = g(w, x, h(w, m), m) Nói cách khác, phép đệ quy tác động lên đối của hàm là câu w. Khi w = e, hàm h được khởi

động bởi hàm f. Nếu w ≠ e, hàm h được định nghĩa bởi một hàm f phụ thuộc vào giá trị trả về h(w, m) của

hàm h từ câu bị cắt bỏ ký tự cuối cùng, bản thân câu bị cắt bỏ ký tự cuối cùng này (w), ký tự bị cắt bỏ (x) và các đối khác.

II.1.4. Sơ đồ đệ quy đồng thời Cho bảng chữ S có thứ tự. Ta định nghĩa các hàm fi và gi, i = 1.. k, k>0, như sau :

fi : S* → S*,

gi : (S*)k + 3 → S*, i = 1.. k.

Từ fi và gi, định nghĩa các hàm hi, i=1.. k, bởi sơ đồ đệ quy đồng thời như sau :

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 :

Page 70: LyThuyetTinhToan - Phan Huy Khanh

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), ppx1

(w))

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ỷ.

Page 71: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 65

II.1.5. Các hàm được định nghĩa bởi case Hàm được định nghĩa bởi case là một hàm có miền xác định được phân hoạch (thành các

trường hợp khác nhau), trong đó, mỗi phân hoạch xác định một hàm. Nhiều hàm được định nghĩa bởi case. Ví dụ hàm xác định từ các dữ liệu được tạo thành bởi một số chẵn ký tự (hoặc từ một số chẵn thành phần dữ liệu).

Ta có mệnh đề sau :

Mệnh đề 4.1 : Cho f1, f2, ..., fk là các hàm đệ quy nguyên thuỷ từ S* → S* và giả sử S được phân hoạch

thành k lớp L1, L2, ..., Lk, khi đó hàm f định nghĩa bởi case như sau :

f(w) = fi(w) nếu w ∈ Li, i ∈ 1..k, thì f cũng là một hàm đệ quy nguyên thuỷ.

Chứng minh : Thật vậy, giả sử d1, d2, ..., dk lần lượt là các hàm đặc trưng của các ngôn ngữ L1, L2, ..., Lk,

được định nghĩa như sau : di(w) = 1 nếu w ∉ Li di(w) = x0 nếu w ∈ Li (x0 ∈ S là một ký tự cố định)

Khi đó hàm f được xây dựng : f(w) = concat(absort(di(w), fi(w)))

Do các hàm xuất hiện trong định nghĩa của f đều đệ quy nguyên thuỷ, do đó f cũng đệ quy nguyên thuỷ.QED

Mệnh đề 4.2 : Lớp P các hàm đệ quy nguyên thuỷ là đóng đối với sơ đồ đệ quy đồng thời.

Chứng minh : Ta cần chỉ ra rằng, với S là một bảng chữ có thứ tự, nếu cho :

fi : S*→S*,

gi : (S*)k+3 → S*, i = 1 .. k,

là các hàm đệ quy nguyên thuỷ, thì các hàm :

hi : (S*)2 → S*

được xây dựng từ các hàm fi và gi bởi sơ đồ đệ quy đồng thời, cũng là đệ quy nguyên thuỷ. Lấy k = 2 để chứng minh, với k bất kỳ được chứng minh tương tự.

Giả sử S là bảng chữ có thứ tự, cho trước các hàm :

f1, f2 : S* → S* và

g1, g2 : (S*)5 → S* là đệ quy nguyên thuỷ. Xây dựng các hàm :

h1, h2 : (S*)2 → S*

từ các hàm f1, f2 và g1, g2 theo sơ đồ đệ quy đồng thời như sau :

hi(1, m) = fi(m)

Page 72: LyThuyetTinhToan - Phan Huy Khanh

66 Lý thuyết tính toán

hi(wx, m) = gi(w, x, h1(w, m) = gi(w, x, h1(w, m), h2(w, m), m)

Tiếp tục xây dựng hàm h từ (S*)2 → S* như sau : h(w, m) = C(h1 (w, m), h2(w, m))

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ỷ.

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*)4 → 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ỷ.

Page 73: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 67

II.2. Các hàm đệ quy Sau đây ta tiếp tục đưa vào một số sơ đồ định nghĩa như sau :

II.2.1. Sơ đồ tối thiểu

Cho g là một hàm từ (S*)2 → S*, với S là một bảng chữ có thứ tự.

Xuất phát từ g, định nghĩa hàm h = Min(g) từ S* → S* theo sơ đồ tối thiểu như sau : h(w) là câu nhỏ nhất f (trong thứ tự phân cấp) sao cho g(f, w) hoặc là câu rỗng, nếu một câu f như vậy tồn tại, và nếu g(u, v) được xác định bởi u trước khi xác định f, còn h(w) sẽ không xác định nếu trái lại.

Bây giờ ta định nghĩa lớp k các hàm đệ quy bộ phận từ S* → S* là lớp nhỏ nhất các hàm chứa các hàm sơ cấp sau đây :

− hằng (trả về một câu cố định) − ls, ppx, first, last, prefix, suffix

− equal − copy, identity, projection, antiprojection

Lớp k là đóng đối với các sơ đồ hợp thành, đệ quy đơn và tối thiểu. Rõ ràng, sơ đồ tối thiểu có thể đưa vào trong các hàm bộ phận. Tuy nhiên, một hàm được

định nghĩa nhờ sơ đồ tối thiểu có thể toàn phần. Người ta gọi một hàm đệ quy bộ phận nhưng toàn phần là một hàm đệ quy toàn phần (total recursive function) hay còn gọi là hàm đệ quy.

Vấn đề đầu tiên đặt ra là : lớp r các hàm đệ quy toàn phần có chứa ngặt (trictly) lớp p các hàm đệ quy nguyên thuỷ ?

Câu trả lời là có. Để chứng minh, người ta sử dụng kỹ thuật đường chéo.

Mệnh đề 4.3 :

Phép bao hàm p ⊂ r là ngặt.

Chứng minh : Theo định nghĩa, vì các hàm đệ quy nguyên thuỷ được xây dựng từ tập hợp hữu hạn các

hàm nhờ một số hữu hạn các sơ đồ nên chúng tạo thành một tập hợp đếm được, và liệt kê được. Giả sử pi là hàm thứ i trong phép liệt kê đã cho. Người ta cũng liệt kê các câu theo thứ tự phân cấp và wj là câu thứ j trong thứ tự này. Xét hàm f được định nghĩa như sau :

f(wi) = successor(pi(wi))

Người ta chứng minh rằng hàm toàn phần này là một hàm đệ quy và không phải là một hàm pi nào đó.

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.

Page 74: LyThuyetTinhToan - Phan Huy Khanh

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.2. Các hàm đệ quy trừu tượng (abstract recursive functions) Phép chuyển đổi cách biểu diễn một số nguyên từ một hệ đếm này sang một hệ đếm khác

được tiến hành nhờ các hàm đệ quy nguyên thuỷ. Do đó cần định nghĩa các hàm đệ quy không được biểu diễn (gọi là trừu tượng). Vấn đề là các hàm xác định từ Νp → Νk làm việc với các số nguyên trừu tượng (không quan tâm đến cách biểu diễn chúng như thế nào). Thực tế vấn đề này rất gần với trường hợp biểu diễn các số nguyên trên một bảng chữ chỉ chứa một ký tự.

Người ta định nghĩa lớp hàm đệ quy nguyên thủy (một cách tương ứng : lớp hàm đệ quy bộ phận) từ Νp → Νk là lớp hàm bé nhất chứa các hàm sơ cấp sau đây :

− hằng (chỉ trả về một số nguyên cố định) − kế tiếp, kế trước (theo nghĩa số nguyên) − gấp đôi (duplication), chiếu, phản chiếu Lớp này là đóng đối với các sơ đồ hợp thành và đệ quy đơn (một cách tương ứng: tối

thiểu). Ở đây, sơ đồ đệ quy đơn được xác định một cách đơn giản hơn như sau :

Nếu f là một hàm từ Νp → Νk, g là một hàm từ Νp+k+1 → Νk, xây dựng hàm h = rec(f, g) từ Νp+1 → Νk nhờ các hàm f và g như sau :

h(0, m) = f(m) h(n + 1, m) = g(n’, h(n’, m), m) ở đây, m là một bộ−p các số nguyên. Tương tự, sơ đồ tối thiểu được định nghĩa một cách đơn giản như sau :

Cho hàm g : Νp+1 → Νk, xuất phát từ g, xây dựng hàm h = Min(g) : Νp → Νk như sau : h(m) là số nguyên n bé nhất sao cho g(n, m) = 0, nếu n như vậy tồn tại và nếu g(i, m) xác

định với i < n. h(m) không xác định nếu trái lại. Người ta dùng cách viết tắt như sau : m(m) [g(n, m) = 0]

để chỉ rằng số nguyên bé nhất n sao cho g(n, m) = 0

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 :

Page 75: LyThuyetTinhToan - Phan Huy Khanh

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.

3. Kiểm tra chẵn lẻ Các hàm kiểm tra số nguyên n có là chẵn et (even test) hoặc có là lẻ ot (odd test) được định

nghĩa như sau : et (n) = 1 nếu n = 2p

= 0 nếu n = 2p + 1 ot (n) = 0 nếu n = 2p

= 1 nếu n = 2p + 1 là các hàm đệ quy nguyên thuỷ, vì chúng được viết :

et (0) = 1 và et (n + 1) = zt (et (n)) ot (n) = zt (et (n))

4. Chia đôi lấy phần nguyên Hàm half chia đôi lấy phần nguyên một số n được định nghĩa như sau : half (n) = phần nguyên của n/2

là đệ quy nguyên thuỷ, vì có thể được viết : half (0) = 0 half (n + 1) = et (n) + half (n)

5. Tính hiệu hai số nguyên Hàm tính hiệu hai số nguyên n và m, ký hiệu n ⎯ m, định nghĩa như sau : n ⎯ m = 0 nếu n ≤ m n ⎯ m = n − m nếu n > m

là đệ quy nguyên thuỷ, vì được viết như sau (với pred là hàm kế trước) : n ⎯ 0 = n n ⎯ m + 1 = pred (n m) Ở đây, phép đệ quy nguyên thủy tác động lên đối thứ hai.

6. Phép chia nguyên Hàm chia nguyên n div m, là đệ quy nguyên thuỷ, vì được viết : 0 div m = 0 n + 1 div m = n div m + zt (m + m * (n div m) ⎯ (n + 1))

7. Phép chia lấy phần dư

Page 76: LyThuyetTinhToan - Phan Huy Khanh

70 Lý thuyết tính toán

Hàm lấy phần dư, ký hiệu n mod k, là đệ quy nguyên thuỷ vì được viết : n mod k = n ⎯ (n div m) * m Từ đây ta dễ dàng nhận thấy rằng, tất cả các hàm số học thông dụng đều được cấu thành từ

các hàm đệ quy nguyên thuỷ.

II.3. Các hàm đệ quy đều T−tính được Ta có mệnh đề sau :

Mệnh đề 4.4 : Mọi hàm đệ quy bộ phận là T−tính được.

Chứng minh :

Thật vậy, chỉ cần chỉ ra rằng tất cả các hàm cơ sở đều là T−tính được, và chỉ ra rằng cả ba sơ đồ (hợp thành, đệ quy đơn và tối thiểu) đều bảo tồn đặc trưng T−tính được. Vả lại, nhớ lại rằng các hàm cơ sở quả thực là những hàm đầu tiên ta đã xây dựng trong chương trước đây nhờ các máy Turing. Như vậy chỉ cần chứng minh rằng có thể thực hiện mỗi một trong ba sơ đồ nhờ các máy Turing.

II.3.1. Sơ đồ hợp thành tổng quát Cho f1, f2, ..., fk và g đều là các hàm T−tính được, khi đó hàm :

compk (f1, f2, ..., fk, g)

cũng là T−tính được. Thật vậy, giả sử T1, T2, ..., Tk và T là các máy Turing thực hiện một cách tương ứng các

hàm f1, f2, ..., fk và g. Có thể giả thiết thêm rằng chúng có đầu đọc−ghi không bao giờ vượt qua bên trái vị trí xuất phát.

Xây dựng máy T' như sau : T' bắt đầu bởi thực hiện k phép sao chép dữ liệu w, rồi thì với i chạy lùi từ k về 1, và, nhờ các Ti, T' thực hiện phép tính trên câu w về bên phải, được kết quả là fi (w) và hoán vị kết quả này với các câu khác. Khi T' kết thúc, trên băng có kết quả :

f1(w)# ... #fk(w)

Sau đó, nhờ máy T, T' thực hiện phép tính trên câu : g (f1(w) , f2(w), ..., fk(w))

Rõ ràng, T' đã thực hiện hàm compk (f1, f2, ..., fk, g)

II.3.2. Sơ đồ đệ quy đơn Cho f và g là các hàm T−tính được, khi đó hàm rec(f, g) cũng là T−tính được. Thật vậy : Cho T và T' là các máy Turing thực hiện một cách tương ứng các hàm f và g. Có

thể giả thiết rằng chúng có đầu đọc-ghi không bao giờ vượt qua bên trái vị trí xuất phát. Xây dựng máy Turing T’’ như sau:

Nếu w là câu rỗng, T’’ lấy lại tính toán của T trên m. Nếu w ≠ e (khác rỗng), T" ghi trên băng của nó dãy các phép tính thực hiện được là :

G(wk, H(wk), m)#...#G(wi, H(wi), m)#...#G(w1, H(w1), m)#F(m)

Page 77: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 71

Trong đó các wi là các câu theo thứ tự phân cấp tăng dần kể từ wk = w', kế trước của w. Còn các ký tự mới thêm vào G, H, F dùng để đánh dấu.

Rõ ràng, điều này có thể được thực hiện bởi một máy Turing : chỉ cần sao chép các dữ liệu đã được thêm vào các ký tự đánh dấu bằng cách giảm 1 (decrement) liên tiếp, chừng nào dãy này còn khác rỗng. Sau đó T" tiếp tục thực hiện tất cả các phép tính trong thứ tự ngược lại, từ phải qua trái. Đầu tiên T" sử dụng T để tính hàm f(m), rồi với i chạy từ 1 đến k, T" sao chép kết quả vừa tìm thấy tại vị trí H(wi) và tính hàm g(wi, h(wi, m), m).

Rõ ràng, T' thực hiện hàm rec(f, g).

II.3.3. Sơ đồ tối thiểu Cho g là một hàm T-tính được, khi đó Min(g) cũng là T-tính được. Thật vậy : Cho T là một máy Turing thực hiện g. Xây dựng máy Turing T' có hai băng để liệt kê tất cả

các câu trên băng thứ nhất, và với mỗi câu đã liệt kê, tiến hành sao chép trên băng thứ hai. Sau đó T' thực hiện phép tính toán của T trên câu đã sao chép này. Khi tính xong, thì T' dừng, nếu chưa rỗng, thì T' tiếp tục liệt kê và cứ thế tiếp tục.

Một cách rõ hơn, ta xem rằng các máy Turing có hai băng như sau: T0 viết lên băng thứ nhất câu đầu tiên, T1 tính câu kế tiếp của câu được viết trên băng thứ nhất, T2 sao chép lại câu đã được viết trên băng thứ nhất lên băng thứ hai và bao bọc phần câu sao chép này bởi ký tự đánh dấu. T3 kiểm tra nếu câu được viết giữa hai ký tự đánh dấu trên băng thứ hai có phải là câu rỗng hay không.

Nếu là câu rỗng, T3 rơi vào trạng thái qyes và T3 dừng. Nếu không phải là câu rỗng, T3 rơi vào trạng thái qno.

Cuối cùng, T’ thực hiện trên băng thứ hai phép tính giữa các ký tự đánh dấu mà T đã thực hiện trên băng của nó.

Khi đó, giả sử ta có: T' = T0 next T2 next T next T3

next while T3 give qyes : T1 next T2 next T next T3

Rõ ràng, T' thực hiện hàm Min(g).

II.4. Mọi hàm T−tính được là đệ quy bộ phận Trong mục này, ta chứng minh mệnh đề ngược lại như sau :

Mệnh đề 4.5 : Mọi hàm T−tính được là đệ quy bộ phận.

Chứng minh : Cho F là một hàm T-tính được nhờ máy Turing T = < S, Q, P> tiêu chuẩn hoá và chuẩn

hoá có một trạng thái dừng duy nhất qN. Giả thiết rằng, S là bảng chữ có kích thước n. Chương trình của máy T có ba hàm nc, mh và ns được định nghĩa như sau:

nc (q, x) = y mh (q,x) = m ns (q,x) = q'

nếu và chỉ nếu (q, x, y, m, q') là một quy tắc của P.

Page 78: LyThuyetTinhToan - Phan Huy Khanh

72 Lý thuyết tính toán

Cả ba hàm này đều được định nghĩa bởi case, rõ ràng chúng đều là đệ quy bộ phận (và cũng là đệ quy nguyên thuỷ nếu mở rộng chúng cho đến khi chúng không còn được xác định, nghĩa là đến khi đối thứ nhất là qN).

Bây giờ nhờ phép đệ quy đồng thời, ta sẽ xây dựng một số hàm mô tả các phần tử khác nhau của một cấu hình của máy T sau k bước tính toán trên dữ liệu f :

1. Hàm "trạng thái " Giả sử S là một hàm "trạng thái " được định nghĩa bởi : S(f, k) = q nếu q là trạng thái của T sau khi bước tính toán trên dữ liệu f

2. Hàm " vế bên trái" Giả sử L là hàm " vế bên trái" được định nghĩa bởi : L(f, k) = w nếu w là phần hữu ích phía bên trái đầu đọc ghi của T sau k bước tính toán trên

dữ liệu f. Ta sẽ xem n ký tự của S như là các con số (ký tự # được xem là 0). Như vậy, câu w sẽ là

một số nguyên viết trong hệ cơ số n. Do giá trị số nguyên không thay đổi khi thêm một số 0 về phía trái (trước) của câu (dãy số)

biểu diễn số nguyên đó, nên không đặt ra vấn đề xác định phần hữu ích. Hơn nữa, các phép toán tác động lên các câu như ghép một ký tự, hay loại bỏ một ký tự đứng cuối cùng của câu, hay chỉ giữ lại ký tự đứng cuối cùng của câu, được thể hiện một cách trực tiếp theo cách viết số học thông thường.

3. Hàm " vế bên phải"

Giả sử R là "vế bên phải" được định nghĩa bởi :

R(f, k) = wx nếu x là ký tự nằm dưới đầu đọc-ghi và nếu w là ảnh gương (nghịch đảo) của phần hữu ích phía bên phải của đầu đọc-ghi của T sau k bước tính toán trên dữ liệu vào f. Ở đây, ta sử dụng câu nghịch đảo để sao cho việc thêm một số 0 về phía bên phải của câu biểu diễn không làm thay đổi giá trị của số nguyên đó.

Rõ ràng, cả ba hàm này xác định hoàn toàn cấu hình của máy T sau k bước tính toán trên dữ liệu vào f.

Để cho tiện, ta đưa thêm hàm thứ tư như sau:

4. Hàm " ký tự"

Giả sử C là hàm "ký tự" được định nghĩa :

C(f, k) = x nếu x là ký tự nằm dưới đầu đọc-ghị của T sau k bước tính toán trên dữ liệu vào f.

Rõ ràng ta có C(f, k) = [R(f, k)] mod n

Với k = 0, phép tính chưa đựơc bắt đầu. Lúc này ta đang ở cấu hình xuất phát. Ta có các giá trị khởi động của các hàm như sau:

S(f, 0) = q1 q1 là trạng thái đầu,

L(f, 0) = 0 trong cấu hình xuất phát, phía trái đầu đọc-ghi không có gì,

R(f, 0) = mir(f) là câu đảo ngược của f, trong cấu hình xuất phát, trên băng có dữ liệu f, đầu đọc-ghi đặt tại ký tự đầu tiên của f.

Từ các giá trị khởi động này, ta có phép đệ quy đồng thời :

Page 79: LyThuyetTinhToan - Phan Huy Khanh

Mô hình các máy RAM 73

S(f, k + 1) = ns (S(f, k), C(f, k))

L(f, k+1) = [ L(f, k) ] div n nếu mh(S(f, k), C(f, k)) = L =n × L(f, k) + nc(S(f, k), C(f, k)) nếu mh (S(f, k), C(f, k)) = R

R(f, k + 1) = n × R(f, k) + nc (S(f, k), C(f, k)) nếu mh (S(f, k), C(f, k)) = L =[ R(f, k) ] div n nếu mh (S(f, k), C(f, k)) = R

Ở đây, ta đã viết theo cách viết số học. Tuy nhiên có thể dịch các định nghĩa này theo cách viết các câu.

Các hàm S, L và R do được định nghĩa bởi phép đệ quy đồng thời nhờ các hàm đệ quy nguyên thuỷ, nên chúng là đệ quy nguyên thuỷ.

Rõ ràng, quá trình tính toán của máy T trên dữ liệu vào f là dừng nếu và chỉ nếu tồn tại một số nguyên k sao cho S(f, k) = qN. Khi đó ta có kết quả của phép tính trên băng, nghĩa là kết quả này là câu nghịch đảo của R(f, k).

Từ đó, ta có:

F(f) = mir (R(f, mk[ S(f, k) = qN ]))

Vậy quả thật F là một hàm đệ quy bộ phận. QED

Chú ý:

Trong cách xây dựng trên đây, ta đã thấy rằng nếu máy Turing T luôn luôn dừng, giá trị mk[ S(f, k) = qN ] luôn luôn xác định, và do vậy F là toàn phần.

Cách xây dựng trên đây chỉ ra rằng tất cả các hàm đệ quy bộ phận có thể được viết bằng cách sử dụng một lần duy nhất sơ đồ tối thiểu.

III. Luận đề Church Cho đến lúc này, ta đã nghiên cứu một số mô hình tính toán : − Mô hình các máy RAM (và các máy RASP), rất gần với chức năng của một máy tính

chạy trên ngôn ngữ assembler − Mô hình các máy Turing, xa hơn mô hình RAM, nhưng trong đó, ta tìm thấy một số vấn đề của các máy thực như các máy xử lý dữ liệu, quản lý bộ nhớ, v.v...

− Mô hình các hàm đệ quy, từ S* → S*, trong đó những vấn đề vừa xét không đặt ra, nhưng lại giữ nguyên những vấn đề về biểu diễn dữ liệu

− Cuối cùng ta cũng đã xét mô hình các hàm đệ quy trừu tượng thao tác trên các đối tượng (các bộ−n của các số nguyên) không được biểu diễn.

Ta thấy rằng các lớp hàm tính được nhờ các phần tử của mỗi một trong các mô hình trên đây luôn luôn là như nhau. Hơn nữa, những mô hình khác đã được nghiên cứu cho đến nay như :

− các văn phạm (grammar), − hệ viết lại (rewriting system), − thuật toán Markov (Markov algorithm), − phép tính l (l-calculus), − các hệ Post (Post systems), − hệ L, v.v...,

Page 80: LyThuyetTinhToan - Phan Huy Khanh

74 Lý thuyết tính toán

đều chưa cho phép định nghĩa một lớp hàm tính được rộng hơn. Với một số nhà nghiên cứu, thì lớp các hàm này là lớp lớn nhất mà người ta có thể định nghĩa như một mô hình tính toán.

Niềm tin này đối với lớp các hàm tính được một cách máy móc (mechanically) được thể hiện qua luận đề Church (Church's thesis, hay Church-Turing thesis) phát biểu như sau :

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ả (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ỷ.

Ta có thể đồng nhất thuật ngữ này với thuật toán.

Page 81: LyThuyetTinhToan - Phan Huy Khanh

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 i2. . . .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) = ∏

≤≤

+

ni 0

1 ) ,( mihip trong đó pi là số nguyên tố thứ i

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))

Page 82: LyThuyetTinhToan - Phan Huy Khanh

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 spn : Ν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 = spn (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)

gk (i, j) = gs (j) với s = s11 (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).

Page 83: LyThuyetTinhToan - Phan Huy Khanh

PGS. TS. PHAN HUY KHÂNH biên soạn 77

CHƯƠNG 5

Các bài toán không quyết định được (Undecidable Problems)

« Very unlike a divine man would he be who is unable to count one, two, three »

Plato

I. Các ngôn ngữ liệt kê đệ quy và các ngôn ngữ đệ quy

Trong mục này, ta sẽ định nghĩa các ngôn ngữ liệt kê đệ quy (recursively enumerable languages) và các ngôn ngữ đệ quy (recursive languages) nhờ các máy Turing có trạng thái thừa nhận (accepted states). Ta cũng chỉ ra các đặc điểm của chúng dựa theo các máy liệt kê (enumerator machines). Định nghĩa 5.1 :

Một máy Turing có một tập hợp A các trạng thái là các trạng thái thừa nhận thì được gọi là một máy Turing có trạng thái thừa nhận.

Lúc này máy Turing là một bộ bốn : T = <S, Q, P, A>

trong đó S, Q, P cùng nghĩa với các máy Turing thông thường, còn A ⊆ Q là tập hợp các trạng thái thừa nhận.

Một trạng thái được gọi là loại bỏ (reject states) nếu không phải là trạng thái thừa nhận. Định nghĩa 5.2 :

Một câu f là được nhận biết (recognized, accepted) bởi một máy Turing có trạng thái thừa nhận T = <S, Q, P, A> nếu tồn tại một tính toán hợp thức dừng để chuyển một cấu hình xuất phát có câu vào f ở trên băng về một cấu hình mà trạng thái của cấu hình này thuộc A.

Cho trước một câu vào f, xảy ra ba trường hợp như sau : � Không có một tính toán hợp thức nào dừng. � Tồn tại một tính toán hợp thức dừng và tất cả các tính toán hợp thức dừng đều

dẫn đến các trạng thái không thuộc A. � Tồn tại một tính toán hợp thức dừng và dẫn đến một trạng thái thuộc A. Như vậy, ngôn ngữ được nhận biết bởi một máy Turing có trạng thái thừa nhận là

tập hợp các câu được nhận biết bởi máy này. Trong trường hợp đơn định, ba trường hợp trên đây được phát biểu lại đơn giản

hơn như sau :

Page 84: LyThuyetTinhToan - Phan Huy Khanh

78 Lý thuyết tính toán

� Tính toán hợp thức không dừng. � 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.

Mệnh đề 5.1 : Một ngôn ngữ L được nhận biết bởi một máy Turing (không đơn định) có các

trạng thái thừa nhận (một cách tương ứng : có một tính toán dừng cho mọi dữ liệu vào) nếu và chỉ nếu tồn tại một máy Turing đơn định có trạng thái dừng (một cách tương ứng : có một tính toán hợp thức dừng và dẫn đến một trạng thái thuộc A) thừa nhận ngôn ngữ này. Chứng minh :

Ta chỉ cần chứng minh đặc trưng cần thiết của mệnh đề này. Muốn vậy, chỉ cần kiểm tra nếu T là một máy Turing có trạng thái dừng không đơn định nhận biết ngôn ngữ L, thì việc xây dựng một máy Turing đơn định T’ mô phỏng máy T có các trạng thái thừa nhận nhận biết L.

Ta cũng chỉ ra rằng nếu T có một tính toán dừng cho mọi câu vào, thì T’ cũng có tính toán dừng cho mọi câu vào.

Căn cứ vào mệnh đề này, từ nay, ta chỉ cần xem xét các máy Turing đơn định mà thôi.

Mệnh đề sau đây có nghĩa rằng sự nhận biết (recognition) theo kiểu mới (không dừng trong một trạng thái thừa nhận) là tương đương với kiểu không dừng đã trình bày trong chương trước. Mệnh đề 5.2 :

Một ngôn ngữ là được nhận biết bởi một máy Turing có các trạng thái thừa nhận nếu và chỉ nếu ngôn ngữ này được thừa nhận (không dừng) bởi một máy Turing. Chứng minh :

“⇒” Cho L là ngôn ngữ được nhận biết bởi một máy Turing có các trạng thái dừng T = <S, Q, P, A>.

Xây dựng từ T một máy Turing T’ = <S, Q’, P∪P’> bằng cách thêm vào Q một trạng thái mới qv : Q’ = Q ∪ {qv}, và thêm vào P tập hợp P’ các quy tắc như sau :

P’ = { qv, x → x, R, qv } ∀x ∈ S ∪ { q, x → x, R, qv } ∀q, x sao cho (q, x) không là vế trái của một quy tắc nào trong P và q ∉ A

Như thế, mọi tính toán dừng trong một trạng thái không thuộc A đều có thể kéo dài vô hạn. Các câu rơi vào trường hợp thứ hai thì cũng sẽ rơi vào trong trường hợp thứ nhất. Vậy L là được nhận biết bởi T’ (không dừng).

“⇐” Ngược lại, nếu L được nhận biết (không dừng) bởi T = <S, Q, P>, L sẽ được nhận biết bởi các trạng thái thừa nhận của T’ = <S, Q, P, Q>.

Page 85: LyThuyetTinhToan - Phan Huy Khanh

Các bài toán không quyết định được 79

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 qh1. Nếu đó là T’, thì dừng trong

một trạng thái qh2.

Page 86: LyThuyetTinhToan - Phan Huy Khanh

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 qh2

.

Máy Turing liệt kê các câu Khi ta có một máy Turing một băng ra (xem chương 3 về các máy Turing có băng

ra), máy này ghi các ký tự của bảng chữ S lên băng. Điều này chỉ có thể có ích nếu S chứa ít nhất hai ký tự.

Trong trường hợp này, nếu ta phân biệt một ký tự # của S, gọi là dấu phân cách, thì những gì đã được ghi trên băng ra là dãy các câu trên bảng chữ S\{#} được đặt cách nhau bởi các dấu #. Định nghĩa 5.4 :

Nếu T là một máy Turing với một băng ra, T ghi lên băng ra các ký tự của một bảng chữ S có chứa một ký tự đánh dấu #, thì người ta gọi ngôn ngữ được liệt kê bởi T là tập hợp các câu được ghi trên băng cách nhau bởi các ký tự # này. Mệnh đề 5.5 :

Ngôn ngữ L ∈ RE nếu và chỉ nếu tồn tại một máy Turing liệt kê L. Ngôn ngữ L ∈ R nếu và chỉ nếu tồn tại một máy Turing liệt kê L trong thứ tự

phân cấp. Chứng minh :

“⇐” (L ∈ RE ⇐ tồn tại một máy Turing liệt kê L) Giả sử T là một máy Turing liệt kê ngôn ngữ L. Xuất phát từ T, xây dựng một máy

Turing T’ nhận biết L theo cách như sau : T’ có nhiều hơn T một băng, trên đó ghi dữ liệu vào f. Còn các băng khác, T’ sử

dụng như T sử dụng để mô phỏng chức năng của T, nhưng xem băng ra của T như là một băng làm việc bình thường. T’ liệt kê các câu của L, nhưng với mỗi câu đã liệt kê (nghĩa là mỗi lần T’ viết ký tự đánh dấu lên băng vừa thêm), T’ kiểm tra câu vừa đánh dấu là khác với câu f. Nếu khác, T’ tiếp tục việc đánh dấu, còn nếu giống nhau (nghĩa là câu vừa đánh dấu chính là f), thì T’ dừng.

Rõ ràng máy T’ vừa mô tả 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) Xảy ra hai trường hợp : - L hữu hạn, rõ ràng L là ngôn ngữ đệ quy - L là vô hạn, việc chứng minh hoàn toàn tương tự trên đây. Người ta đòi hỏi thêm rằng, khi T kiểm tra nếu câu đã liệt kê là khác với câu f

đang xét, nếu câu trả lời là đúng, T’ sẽ chỉ tiếp tục đánh số nếu f có mặt, trong thứ tự

Page 87: LyThuyetTinhToan - Phan Huy Khanh

Các bài toán không quyết định được 81

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 :

Lu = { <w, f>| máy Turing có mã w dừng trên dữ liệu vào f } ∈ RE\R.

Chứng minh : Kết quả này đã được chỉ ra dưới một dạng khác ở chương 3. Ta nhớ lại rằng máy Turing vạn năng Tu thỏa mãn cho ∀i và ∀f :

Tu (i#f) = gi (f) với gi là hàm được tính bởi máy Turing thứ i.

Một dạng khác của máy Turing vạn năng là Tu" thỏa mãn mọi mã w của máy Turing thứ i, và với mọi câu f :

Page 88: LyThuyetTinhToan - Phan Huy Khanh

82 Lý thuyết tính toán

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.

II. Các bài toán không quyết định được (Undecidable problems)

Ta nhớ lại rằng một bài toán được cấu thành bởi hai yếu tố : 1. Mô tả cách biểu diễn (hữu hạn) các phần tử của một tập hợp D hữu hạn hoặc

vô hạn đếm được. Mỗi phần tử của D được gọi là một câu. 2. Một phát biểu dựa vào tập hợp D này, có thể đúng, hoặc có thể sai tùy theo

phần tử (câu) được lựa chọn từ D.

Với mỗi bài toán♣ P, được hợp thành từ các câu của tập hợp D đang xét và từ một phát biểu dựa theo D, ta xét một ngôn ngữ đặc trưng LP của P. Ngôn ngữ LP được cấu thành từ tập hợp câu của D có lời giải là đúng. Tương tự như vậy, người ta xét ngôn ngữ đặc trưng LCP của bài toán ngược CP 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 phát biểu theo nghĩa trái ngược (lời giải có giá trị sai - contrary).

Như vậy, lời giải của một bài toán dẫn đến sự nhận biết của một ngôn ngữ : một máy giải một bài toán P nếu và chỉ nếu với mọi câu w ∈ D (là biểu diễn một phần tử của D cho 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 w ∈ LP hay w ∈ LCP.

♣ Ta đồng nhất hai thuật ngữ vấn đề và bài toán (problem).

Page 89: LyThuyetTinhToan - Phan Huy Khanh

Các bài toán không quyết định được 83

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.

Page 90: LyThuyetTinhToan - Phan Huy Khanh

84 Lý thuyết tính toán

Hình 5.1 Rút gọn bài toán A về bài toán B

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.

LPA

S*\LPA

LPB

S*\LPB

Anh của f từ các biểu diễn dữ liệu của bài toán A

Biểu diễn dữ liệu của bài toán B

Biểu diễn dữ liệu của bài toán A

f

f

Page 91: LyThuyetTinhToan - Phan Huy Khanh

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.

Page 92: LyThuyetTinhToan - Phan Huy Khanh

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 = ui1

ui2...uir

= vi1v i2

... v ir ?

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 = u1ui2

...uir = v1vi2

... vir?

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.

Page 93: LyThuyetTinhToan - Phan Huy Khanh

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 :

FT1 = { (qxz, yq’z) | z ∈ S và q, x → y, R, q’ }

∪ { (qx , yq’# ) | q, x → y, R, q’ }, FT2

= { (zqx, q’zy) | z ∈ S và q, x → y, L, q’ }

∪ { qx, q’#y) | q, x → y, L, q’ }, FT3

= { (z, z) | z ∈ S } ,

FT4 = { (zqh, qh), (qh, qhz) | z ∈ S } ∪ { ( qh , ) }

Ứ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

Page 94: LyThuyetTinhToan - Phan Huy Khanh

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 = u1ui2

...uir = v1vi2

... vir là một lời giải của bài toán tương ứng Post cải

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(ui2) ... p(uir)a = ad(v1) d (vi2

) ... d (vir).

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 = Mi1

M i2 ... Mir các ma trận của

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 :

Page 95: LyThuyetTinhToan - Phan Huy Khanh

Các bài toán không quyết định được 89

j (u, v) = ⎥⎥⎥

⎢⎢⎢

1(u) nu - (v) nu(u) nu0el(v)00(u) el- (v) el(u) el

Ta có thể dễ dàng chứng minh rằng j là một đơn ánh đồng cấu, và phần tử (3, 2) của j (u, v) là bằng 0 nếu và chỉ nếu u = v.

Bây giờ giả sử (u1, v1), ..., (uk, vk) là một dãy các cặp câu trên bảng chữ S tạo thành một dữ liệu vào cho bài toán tương ứng Post. Tương ứng với trường hợp cá biệt này, ta đưa vào một tập hợp hữu hạn M các ma trận hệ số 3×3 trong Z :

M = {j (u1, v1), ..., j (uk, vk)}.

Rõ ràng bài toán Post này có lời giải nếu và chỉ nếu tồn tại một tích hữu hạn các ma trận của M sao cho phần tử (3, 2) của M là bằng 0. Như vậy ta đã rút gọn bài toán tương ứng Post về bài toán zero trong các ma trận hệ số 3´3 trong Z. 3. Bài toán về sự hội tụ của một dãy phần tử của Z

Người ta nói một dãy đã cho là xác định đệ quy (recursively defined sequence) nếu với mọi số nguyên n, có thể tìm được một cách hiệu quả, phần tử thứ n của dãy này.

Bài toán về sự hội tụ của một dãy phần tử của Z được phát biểu như sau : Dữ liệu : Một dãy phần tử của Z là xác định đệ quy. Câu hỏi : Hỏi rằng dãy này là một máy Turing và f là một dữ liệu vào của T. Giả sử T = <S, Q, P> là một máy Turing và f là một dữ liệu vào của T. Ta đánh số

trên Z các ô của băng làm việc của T bắt đầu 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ác định dãy (un) với un là số thứ tự của ô dưới đầu đọc sau n bước tính toán của T trên dữ liệu f. Theo quy ước, nếu việc tính toán này là dừng sau p trước trên ô có số thứ tự 1, thì tất cả các hạng của dãy có vị trí lớn hơn p sẽ có giá trị 1.

Như vậy, u0 = 0, khoảng cách (độ lệch) giữa un và un+1 bị chặn bởi 1 theo trị tuyệt đối và chỉ có thể bằng 0 nếu máy T dừng sau tối đa n trước tính toán. Mặt khác, dãy này là xác định đệ quy.

Vả lại, dãy này là hội tụ nếu và chỉ nếu dãy này không đổi (stationary). Như vậy, dãy này là hội tụ nếu và chỉ nếu việc tính toán của máy Turing T 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 hội tụ của một dãy.

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.

Page 96: LyThuyetTinhToan - Phan Huy Khanh

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ỳ.

Page 97: LyThuyetTinhToan - Phan Huy Khanh

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...

Page 98: LyThuyetTinhToan - Phan Huy Khanh

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.

Page 99: LyThuyetTinhToan - Phan Huy Khanh

PGS. TS. PHAN HUY KHÂNH biên soạn 93

CHƯƠNG 6

Độ phức tạp tính toán (Computational Complexity)

« Better one safe way than a hundred on which you cannot reckon »

Aesop

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.

I. Độ phức tạp về thời gian và về bộ nhớ Người ta thường đưa vào khái niệm độ phức tạp cho các ngôn ngữ . Độ phức tạp

của một bài toán là độ phức tạp của ngôn ngữ đặc trưng cho bài toán này. Ta xét một máy Turing đơn định có k băng và dừng trên mọi dữ liệu. Xuất phát từ

một cấu hình ban đầu (1, q1, f), máy Turing có một tính toán dừng ở độ dài m. Ta xem rằng tập hợp Ln của tất cả các câu f cùng có một độ dài như nhau là n. Nếu Ln khác rỗng, với mỗi số nguyên n, ta cho kết hợp với số nguyên :

T(n) = Maxf∈Ln { độ dài tính toán nhận biết f }

Nếu Ln = ∅ (tập hợp trống), ta đặt T (n) = 0.

Hàm T : N → N vừa định nghĩa xác định độ phức tạp về thời gian (time complexity) T(n) của máy Turing k băng (ta quy ước mỗi bước tính toán kéo dài trong một khoảng thời gian bằng đơn vị).

Người ta cũng 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ề thời gian nhiều nhất là T (n).

Page 100: LyThuyetTinhToan - Phan Huy Khanh

94 Lý thuyết tính toán

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∈Ln

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.

Page 101: LyThuyetTinhToan - Phan Huy Khanh

Độ 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∈Ln { độ dài của tính toán ngắn nhất để nhận biết f }

S (n) = Maxf∈Ln { số các ô đã được thăm trên băng khi tính toá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.

II. Các lớp của độ phức tạp (Complexity classes) Trong mục trước, ta đã định nghĩa độ phức tạp của một ngôn ngữ cho trước.

Ngược lại, bây giờ ta có thể xem xét họ các ngôn ngữ có một độ phức tạp đã cho. Giả sử f là một hàm tăng, ta có các định nghĩa sau : Ký hiệu Ý nghĩa

DSPACE (f (n)) Họ các ngôn ngữ có độ phức tạp về bộ nhớ S (n) = f (n) NSPACE (f (n)) Họ các ngôn ngữ có độ phức tạp không đơn định

về bộ nhớ S (n) = f (n) DTIME (f (n)) Họ các ngôn ngữ có độ phức tạp về thời gian T (n) = f (n) NTIME (f (n)) Họ các ngôn ngữ có độ phức tạp không đơn định

về thời gian T (n) = f (n) Tất cả các họ trên được gọi là các lớp của độ phức tạp. Từ các định nghĩa trên, ta

suy ra rằng : DSPACE (f (n)) ⊆ NSPACE (f (n)) DTIME (f (n)) ⊆ NTIME (f (n))

và, nếu f ≤ g, thì: DSPACE (f (n)) ⊆ DSPACE (g (n)) NSPACE (f (n)) ⊆ NSPACE (g(n)) DTIME (f (n)) ⊆ DTIME (g (n)) NTIME (f (n)) ⊆ NTIME (g(n)) Giả sử L là ngôn ngữ được cho trong ví dụ 6. 1 trước đây, ta có: L ∈ DTIME (n) ∩ DSPACE (log2 (n)),

nhưng ta cũng có : L ∈ DTIME (n2) ∩ NTIME ( n) ∩ DSPACE (n)

Page 102: LyThuyetTinhToan - Phan Huy Khanh

96 Lý thuyết tính toán

II.1. Hiện tượng nén Giả sử T là một máy Turing có độ phức tạp về bộ nhớ là S(n) = f(n), bằng cách sử

dụng một bảng chữ trong đó, mỗi ký tự biểu diễn k ký tự liên tiếp của bảng chữ của T, ta có thể xây dựng một máy Turing T’ nhận biết cùng ngôn ngữ và có cùng độ phức tạp về bộ nhớ là f(n)/k. Máy T’ này mã hóa trên bảng chữ mới thông tin ghi trên mỗi một băng làm việc (nhớ rằng không kể không gian nhớ dùng để ghi dữ liệu vào).

Rõ ràng, nhờ phương pháp này, bằng cách sử dụng một thừa số c không đổi, ta có thể giảm bớt độ phức tạp về bộ nhớ để nhận biết một ngôn ngữ đã cho.

Nếu T là một máy Turing off-line có k băng, ta có thể nhận biết cùng một ngôn ngữ bằng cách sử dụng một máy Turing off−line chỉ có một băng, sử dụng cùng một phương pháp để không sử dụng không gian nhớ nhiều hơn T. Đối với độ phức tạp về bộ nhớ, việc ta giảm bớt số lượng băng làm việc không có nghĩa, cho nên, từ nay, ta chỉ xét đến các máy Turing off−line có một băng, thậm chí, trong trường hợp S(n) = n, ta chỉ xét các máy Turing có một băng mà không thêm gì nữa.

Ta cũng có thể áp dụng phương pháp nén vừa trình bày trên đây đối với độ phức tạp về thời gian. Tuy nhiên phương pháp này không miễn đọc dữ liệu, mà cần một thời gian n + 1 để đọc dữ liệu có độ dài n. Như vậy, ta có thể giảm bớt nhờ một thừa số không đổi là c ngay khi T(n)/n có khuynh hướng tăng vô hạn.

Bây giờ ta xem xét hiệu quả của độ phức tạp về thời gian khi giảm bớt số lượng các băng làm việc.

Khi giảm bớt còn một băng, phân tích phương pháp đã trình bày ở chương 3 để chuyển từ k băng về một băng, ta chứng minh được : L ∈ DTIME (T (n)) ⇒ L được thừa nhận bởi một máy Turing một băng

với chi phí thời gian là T2(n). Khi cần thực hiện việc sao chéo, ta có thể chuyển từ một băng sang hai băng

nhằm làm giảm đáng kể số bước tính toán. Ta chứng minh được rằng việc rút gọn còn hai băng thay vì chỉ còn một băng làm tối ưu rõ rệt chi phí về thời gian : L ∈ DTIME (T (n)) ⇒ L được thừa nhận bởi một máy Turing có hai băng

với thời gian T (n).log2(T (n))

Tuy nhiên, để trả lời câu hỏi : Với chi phí thời gian nhiều hơn (tương ứng : nhiều bộ nhớ hơn) thì người ta có

nhận biết được thực sự nhiều ngôn ngữ hơn không ? ta có mệnh đề sau đây : Mệnh đề 6.1 :

Với mọi hàm đệ quy toàn phần f, tồn tại một ngôn ngữ đệ quy L không thuộc họ DTIME (f (n)) (một cách tương ứng : không thuộc họ DSPACE (f (n))). Chứng minh :

Sử dụng kỹ thuật đường chéo cho ngôn ngữ : L = { wi | Ti không thừa nhận câu wi sau f (|wi|) bước tính toán }

Thật vậy, L là một ngôn ngữ đệ quy không thuộc họ DTIME (f (n)).

Page 103: LyThuyetTinhToan - Phan Huy Khanh

Độ phức tạp tính toán 97

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)).

II.2. Các họ P, NP và P−bộ nhớ (P−space) Các lớp của độ phức tạp tính toán sau đây đủ quan trọng để có tên riêng :

P = U1i ≥

DTIME (ni),

NP = U1i ≥

NTIME (ni).

Như vậy :

P là lớp các ngôn ngữ được nhận biết bởi một máy Turing đơn định cần một lượng thời gian bậc đa thức,

NP là lớp các ngôn ngữ được nhận biết bởi một máy Turing không đơn định cần một lượng thời gian bậc đa thức.

Ta đưa vào các lớp P−bộ nhớ (P−space) và NP−bộ nhớ (NP−space) như sau :

P−bộ nhớ = U1i ≥

DSPACE (ni),

NP−bộ nhớ = U1i ≥

NSPACE (ni).

P−bộ nhớ là lớp các ngôn ngữ được nhận biết bởi một máy Turing đơn định cần một lượng bộ nhớ bậc đa thức,

NP−bộ nhớ là lớp các ngôn ngữ được nhận biết bởi một máy Turing không đơn định cần một lượng bộ nhớ bậc đa thức.

Rõ ràng ta có đẳng thức :

Page 104: LyThuyetTinhToan - Phan Huy Khanh

98 Lý thuyết tính toán

P−bộ nhớ = NP−bộ nhớ Và ta có các bao hàm sau đây :

DSPACE (log2 (n)) ⊆ P ⊆ NP ⊆ P−bộ nhớ = NP−bộ nhớ.

Trong thực tế, người ta ước lượng một bài toán là : − xử lý được (tractable), nếu bài toán đó thuộc lớp P

hay giải được (workable) − không xử lý được (untractable), nếu bài toán đó không thuộc lớp P.

hay không giải được (unworkable) Vì vậy, ít khi người ta giải quyết những bài toán cần một lượng thời gian và bộ

nhớ dạng đa thức có bậc lớn hơn 4 vì sẽ làm tăng độ phức tạp tính toán.

III. Rút gọn đa thức và các bài toán NP−đầy đủ

III.1. Khái niệm Rút gọn đa thức (polynomial reduction) là làm mịn (refinement) khái niệm rút gọn

số học đã định nghĩa ở chương 5. Ta vẽ lại sơ đồ rút gọn số học như sau :

Hình 6.1 Rút gọn bài toán A về bài toán B

Định nghĩa 6.1 Người ta nói bài toán A được rút gọn kiểu đa thức 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 hết một lượng thời gian đa thức (polynomial time). 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

Người ta nói rằng máy Turing này đã thực hiện kiểu đa thức (polynomially work) việc rút gọn bài toán A về bài toán B. Từ đó, ta có mệnh đề sau : Mệnh đề 6.2 :

Nếu bài toán A được rút gọn kiểu đa thức về bài toán B, thì nếu B là một bài toán thuộc lớp P (một cách tương ứng : thuộc lớp NP), thì A cũng là một bài toán thuộc lớp P (một cách tương ứng : thuộc NP).

Người ta cũng nói rằng các lớp P và NP là đóng đối với phép rút gọn đa thức.

LPA

S*\LPA

LPB

S*\LPB

Anh của f từ các biểu diễn dữ liệu của bài toán A

Biểu diễn dữ liệu của bài toán B

Biểu diễn dữ liệu của bài toán A

f

f

Page 105: LyThuyetTinhToan - Phan Huy Khanh

Độ phức tạp tính toán 99

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.

III.2. Các bài toán cổ điển Sau đây là sáu bài toán cổ điển trong Tin học.

1. Bài toán tô màu các đỉnh của một đồ thị Dữ liệu : Một đồ thị G = <S, V> và một số nguyên k. Câu hỏi : Ta có thể tô mỗi đỉnh của đồ thị một màu sao cho cứ hai đỉnh của đồ thị

được nối với nhau bởi một cung thì không được tô cùng màu được chọn trong số k màu ?

2. Bài toán lập kế hoạch làm việc Dữ liệu : Cho n việc và một số nguyên k, mỗi việc được đặc trưng bởi bộ ba các

số nguyên (ti, di, pi), với ti, di, và pi lần lượt biểu diễn thời gian thực hiện, thời gian kết thúc và hình phạt ứng với việc thứ i.

Page 106: LyThuyetTinhToan - Phan Huy Khanh

100 Lý thuyết tính toá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 :

Pp = p(j)

j 1, np (j) p(r)

r 1, j P t d

0

= =

⎧ ⎡ ⎤= >⎣ ⎦⎪⎨⎪=⎩

∑ ∑nãuú

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 ?

III.3. Ví dụ về rút gọn kiểu đa thức Bây giờ ta xét một ví dụ : hãy rút gọn kiểu đa thức bài toán ba-lô về bài toán sắp

đặt các việc có hình phạt. Giả sử I = (s1, s2, ..., sn; c) là một dữ liệu vào cho bài toán ba-lô.

- Nếu c n 1, js j∑

=< thì câu trả lời là không.

Khi đó, ta xét bài toán sắp đặt các việc có hình phạt được định nghĩa bởi ti = 2, di = pi = 1 và k = 0 với câu trả lời không.

- Nếu trái lại, c n 1, js j∑

=≥ thì câu trả lời là thoả mãn.

Ta xét bài toán sắp đặt các việc có hình phạt được định nghĩa bởi ti = pi = si và di = c với ∀i = 1 .. n, và k = c

n 1, js j∑

=−

Bây giờ ta kiếm tra trường hợp cá biệt I của bài toán ba-lô có một lời giải nếu và chỉ nếu bài toán sắp đặt các việc có hình phạt mà ta sẽ đưa về cũng có một lời giải :

Page 107: LyThuyetTinhToan - Phan Huy Khanh

Độ phức tạp tính toán 101

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.

Page 108: LyThuyetTinhToan - Phan Huy Khanh

102 Lý thuyết tính toán

Định ký Cook - 1971 (Stephen Cook) : Bài toán về tính thỏa mãn của các biểu thức boolean dưới dạng chuẩn hội là một

bài toán NP -đầy đủ. Ta không chứng minh định lý này.

Bổ đề 6. 1 Cả sáu bài toán trên đây đều là NP-đầy đủ. Ta có mệnh đề sau:

Mệnh đề 6. 4 P = NP nếu và chỉ nếu tồn tại ngôn ngữ L ∈ P sao cho L là NP-đầy đủ.

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 ?