May Turing
September 22, 2017 | Author: thantrog | Category: N/A
Short Description
Download May Turing...
Description
MỤC LỤC CHƯƠNG 1. MÁY TURING VÀ THUẬT TOÁN................................................1 1. Mô tả và định nghĩa về máy Turing..............................................................1 1.1. Mô tả phi hình thức về máy turing .....................................................................1 1.2. Định nghĩa hình thức của máy Turing (máy Turing đơn băng – Single tape Turing machine) ........................................................................................................3 1.4. Ví dụ về máy Turing...........................................................................................4 1.5. Sơ đồ chuyển vị cho máy Turing .......................................................................5
2. Giới thiệu về máy Turing phổ dụng .............................................................6 3. Máy turing với biểu diễn thuật toán...........................................................10 3.1. Khái niệm thuật toán .......................................................................................10 3.2. Biểu diễn thuật toán một cách hình thức bằng máy Turing..............................11
CHƯƠNG 2. TÍNH KHẢ QUYẾT CỦA THUẬT TOÁN............................16 1. Tổng quan về tính khả quyết của thuật toán..............................................16 2. Luận đề Church-Turing..............................................................................17 3. Các chương trình như các bộ nhận dạng ngôn ngữ...................................18 3.1. Các chương trình và máy Turing.....................................................................20 3.2. Các hàm tính toán..............................................................................................20
4. Máy Turing và vấn đề khả quyết................................................................22 4.1. Các tập đệ quy kể được và khả quyết................................................................22 4.1.1. Một số định nghĩa...........................................................................................22 4.1.2. So sánh RE và tính khả quyết.........................................................................22 4.1.3. Tính kể được...................................................................................................23 4.2. Các ngôn ngữ đệ quy liệt kê .............................................................................24 4.2.1. Ngôn ngữ đệ quy............................................................................................24 4.2.2. Ngôn ngữ đệ quy liệt kê ................................................................................24 4.3. Các bài toán khả quyết .....................................................................................24
5. Một số vấn đề máy Turing không giải được...............................................26 5.1. Bài toán in (printing problem) và bài toán dừng(halting problem)...................26 5.2. Hàm dừng..........................................................................................................26 5.3. Entscheidungsproblem......................................................................................26
TÀI LIỆU THAM KHẢO...............................................................................28 ...........................................................................................................................28
Máy Turing và tính khả quyết của thuật toán 1
CHƯƠNG 1. MÁY TURING VÀ THUẬT TOÁN 1. Mô tả và định nghĩa về máy Turing 1.1. Mô tả phi hình thức về máy turing Khái niệm của máy Turing dựa trên ý tưởng của một người đã thực hiện một thủ tục rất rõ ràng bằng cách thay đổi những nội dụng của một băng giấy vô hạn, mà nó được phân thành các ô vuông có thể chứa một trong các tập hữu hạn các ký hiệu. Người này cần nhớ một trong các tập trạng thái hữu hạn và một thủ tục được trình bày trong nhiều bước cơ bản dưới dạng “Nếu trạng thái của bạn là 42 và ký hiệu mà bạn thấy là ‘0’ thì thay thế nó bằng ‘1’, di chuyển một ký hiệu sang phải, và thừa nhận rằng trạng thái 17 như một trạng thái mới của bạn”.
Trong một số mô hình, đầu đọc (head) di chuyển dọc theo băng tĩnh (Stationary tape). Chỉ thị để được thực hiện (q1) được chỉ ra bên trong đầu đọc. Trong mô hình này, băng trống là tất cả các ô bằng 0. Các ô vuông được tô đậm, gồm ô đã được quét qua bởi đầu đọc, và các ô vuông được đánh dấu 1, 1, B và biểu tượng đầu đọc, tạo thành trạng thái của hệ thống. Một cách rõ ràng hơn, có thể hình dung một máy Turing sẽ bao gồm các thành phần sau: •
Một băng (TAPE), hay còn gọi là một bộ nhớ vô hạn, dưới dạng một băng gồm nhiều ô, có thể kéo dài vô hạn về phía phải. Mỗi ô trên băng có thể chứa một ký hiệu thuộc một bộ chữ, gọi là bộ chữ trên băng (mà một phần trong đó là bộ chữ vào, dùng cho xâu vào); •
Một đầu đọc (HEAD) di chuyển ở trên băng, ở mỗi thời điểm nhìn vào một ô trên băng; • Một tập hữu hạn các trạng thái, trong đó có phân biệt một trạng thái đầu và một tập hợp các trạng thái đã được thừa nhận; •
Một hàm dịch chuyển chứa một tập hữu hạn chỉ thị cho phép cứ với mỗi trạng thái của máy và một ký hiệu đọc được trong ô đối diện với đầu đọc, máy sẽ thực hiện các bước như sau: o
Chuyển trạng thái
o In một ký hiệu trên băng tại ô đang duyệt (nghĩa là thay ký hiệu đọc được trên băng bằng ký hiệu nào đó)
Máy Turing và tính khả quyết của thuật toán 2
Dịch chuyển đầu đọc - viết (sang trái (L), sang phải (R) hoặc đứng yên(∅)) o
a1
a1
…
…
a1
B
B Băng
Đầu đọc
q
Trạng thái
Hình 1. Các bộ phận của máy Turing • Các thao tác có thể của một máy Turing (thường gọi là các thao tác nguyên tử - Atomic operations) • Đọc (xác định) ký hiệu hiện tại mà đầu đọc đang trỏ tới • Viết một ký hiệu lên ô vuông hiện tại mà đầu đọc đang trỏ tới (sau khi xóa lần đầu tiên ký hiệu vừa được ghi ở đó) • Di chuyển băng sang trái một ô • Di chuyển băng sang phải một ô • Thay đổi trạng thái • Ngắt
Máy Turing và tính khả quyết của thuật toán 3
•
Quá trình thực hiện của máy Turing có thể được mô tả như sau: •
Lúc khởi đầu, xâu vào được đặt trên băng (tận cùng bên trái). Mọi ô khác trên băng đều chứa một ký hiệu đặc biệt, B (blank), được gọi là ký hiệu trống. Đầu đọc trỏ vào ô thứ nhất trên băng và máy ở trạng thái đầu. • Cứ mỗi bước trong quá trình thực hiện (xem hình 2), máy sẽ thực hiện: o
Đọc ký hiệu đối diện đầu đọc,
o
Thay ký hiệu đó bằng ký hiệu tính được từ hàm dịch chuyển,
o Dời đầu đọc một ô sang trái hay sang phải theo hướng chỉ định bởi hàm dịch chuyển, o chuyển.
Đổi trạng thái hiện tại thành trạng thái tiếp theo, cho bởi hàm dịch • Xâu vào là được thừa nhận khi quá trình thực hiện đối với xâu đó đạt đến một trạng thái thừa nhận.
0
1
0
1
1
B
B
1
1
B
B
q
0
1
1
q
Hình 2. Một bước dịch chuyển
1.2. Định nghĩa hình thức của máy Turing (máy Turing đơn băng – Single tape Turing machine) Sự mô tả máy Turing một cách trực quan như ở phần 1 đã giúp chúng ta bước đầu dễ dàng hình dung ra sự hoạt động của nó. Tuy nhiên, một sự mô tả phi hình thức như thế là chưa đủ chặt chẽ để có thể tiến hành sự suy diễn toán học, nhằm đi sâu nghiên cứu về máy Turing được. Bởi vậy, ta cần có một định nghĩa hình thức về máy Turing. Theo Hopcroft và Ullman (1979) đã định nghĩa một cách hình thức một máy Turing như là một bộ 7- M = < Q, Γ , b,
∑ , δ , q , F> trong đó: 0
Máy Turing và tính khả quyết của thuật toán 4 •
Q là một tập hữu hạn các trạng thái,
•
Γlà bộ chữ trên băng (bộ chữ dùng trên băng),
b ∈ Γlà ký hiệu trống (ký hiệu duy nhất cho phép xuất hiện một cách vô hạn trên băng ở bất kỳ bước nào trong quá trình tính toán), • •
∑ ⊆ Γlà bộ chữ vào (bộ chữ dùng cho xâu vào),
δ : Q x Γ → Q x Γ x {L, R} là một hàm bộ phận, hay còn gọi là hàm dịch chuyển (là hàm định nghĩa các việc dịch chuyển trạng thái của máy Turing hoặc máy trạng thái), trong đó L và R được hiểu là trái (Left) và phải (Right)). •
•
q0 ∈ Q là trạng thái đầu (trạng thái khởi tạo),
F ⊆ Q là tập các trạng thái thừa nhận – accepting state (hoặc trạng thái cuối). •
1.4. Ví dụ về máy Turing Dưới đây là ví dụ về máy Turing ứng đụng trong việc chấp nhận các tập. Ví dụ 1. Thiết kế máy Turing chấp nhận ngôn ngữ L = { 0n1n | n ≥ 1} Khởi đầu, máy Turing chứa 0n1n bên trái nhất trên băng sau đó là vô hạn khoảng trống Blank. Máy Turing lặp lại quá trình sau: M thay 0 bên trái nhất bằng X rồi chuyển sang phải tới 1 trái nhất, máy Turing thay 1 này bằng Y rồi dịch chuyển về bên trái cho tới khi gặp X phải nhất nó chuyển sang phải một ô (tới 0 trái nhất) rồi tiếp tục lặp một chu trình mới. Nếu trong khi dịch chuyển sang phải để tìm 1 mà máy Turing gặp Blank thì máy Turing dừng và không chấp nhận input. Tương tự, khi máy Turing đã thay hết 0 bằng X và kiểm tra còn 1 trên băng thì máy Turing cũng dừng và không chấp nhận input. Máy Turing chấp nhận input nếu như cũng không còn ký hiệu 1 nào nữa trên băng. Đặt máy Turing M = < Q, Γ , b,
∑ , δ , q , F> với các thành phần : 0
Q = {q0, q1, q2, q3, q4}; ∑= {0, 1}; Γ = {0, 1, X, Y, B} và F = {q4}. Ta có thể hình dung mỗi trạng thái là một câu lệnh hoặc một nhóm các câu lệnh trong chương trình. Trạng thái q0 là trạng thái khởi đầu và nó làm cho ký hiệu 0 bên trái nhất thay bằng X. Trạng thái q1 được dùng để tiến sang phải bỏ qua các số 0 và Y để tìm 1 bên trái nhất. Nếu M tìm thấy 1 nó thay 1 bằng Y rồi đi vào trạng thái q2. Trạng thái q2 đưa M tiến sang trái cho tới X đầu tiên và đi vào trạng thái q0, dịch chuyển sang phải để tới 0 bên trái nhất và tiếp tục một chu trình mới. Khi M tiến sang phải trong trạng thái q1, nếu B hoặc X được tìm thấy trước 1 thì input bị loại bỏ (không chấp nhận) vì có chứa nhiều ký hiệu 0 hơn 1 hoặc input không có dạng 0*1* .
Máy Turing và tính khả quyết của thuật toán 5
Trạng thái q0 còn có vai trò khác. Nếu trạng thái q2 tìm thấy X bên phải nhất và ngay sau đó là Y thì các số 0 đã được xét hết, do đó ở trạng thái bắt đầu một chu trình mới q0 không tìm thấy ký hiệu 0 nào để thay thành X mà chỉ gặp Y thì máy Turing đi vào trạng thái q3 duyệt qua các Y để kiểm tra có hay không có ký hiệu 1 còn lại. Nếu theo ngay sau các Y là B, nghĩa là trên băng nhập không còn ký hiệu 1 nào nữa thì máy Turing sẽ đi vào q4 (trạng thái kết thúc) để chấp nhận input. Ngược lại input bị loại bỏ. Ta có hàm chuyển δ được cho trong bảng sau :
Hình 4. Một máy Turing kiểm nhận {0n1n | n>=1} Các phép chuyển hình thái của máy Turing M trên input 0011 : q00011 ⊢ Xq1011 ⊢ X0q111 ⊢ X q20Y1 ⊢ q2X0Y1 ⊢ X q00Y1 ⊢ XXq1Y1 ⊢ XXY q11 ⊢ XX q2YY ⊢ X q2XYY ⊢ XX q0YY ⊢ XXYq3Y ⊢ XXYYq3 ⊢ XXYYq4
1.5. Sơ đồ chuyển vị cho máy Turing Chúng ta có thể biểu diễn các chuyển vị của một máy Turing một cách hình ảnh. Một sơ đồ chuyển vị (transition diagram) bao gồm một tập các nút tương ứng với các trạng thái của máy Turing. Một cung từ trạng thái q đến trạng thái p với nhãn là một hoặc nhiều mục có dạng X/YD, trong đó X và Y là các ký hiệu băng, D là một hướng (L hoặc R). Điều này có nghĩa là mỗi khi δ (q, Xi) = (p, Y, D), chúng ta thấy nhãn X/YD trên cung từ q đến p. Tuy nhiên, trong sơ đồ của chúng ta, hướng D được biểu diễn bằng các mũi tên chỉ sang trái ( ← ) hoặc chỉ sang phải ( → ). Giống như các loại sơ đồ chuyển vị khác, chúng ta biểu diễn khởi trạng bằng từ “start” và một mũi tên đi vào trạng thái đó. Kiểm trạng được chi ra bằng vòng kép. Vì thế thông tin duy nhất của máy Turing không đọc trực tiếp được từ sơ đồ là ký hiệu được dùng cho ô trống. Chúng ta sẽ xem như đó là B trừ khi được nói rõ. Ví dụ 1: Hình 5 trình bày sơ đồ chuyển vị cho máy Turing ở ví dụ 1 vừa trình bày ở trên, với hàm chuyển vị được cho trong hình 4.
Máy Turing và tính khả quyết của thuật toán 6
Hình 5. Sơ đồ chuyển vị cho một máy Turing kiểm nhận các chuỗi có dạng 0n1n
2. Giới thiệu về máy Turing phổ dụng Máy Turing phổ dụng là một máy Turing có thể bắt chước sự hoạt động của bất kỳ máy Turing nào. Máy Turing phổ dụng U có thể được hiểu như sau: Với một cách mã hóa thích hợp, ánh xạ chuyển trạng thái của máy Turing bất kỳ M và từ ω trên bảng chữ vào. Với từ đã mã hóa này máy Turing phổ dụng U dừng khi và chỉ khi máy Turing M dừng với từ ω .
Hình 6. Máy Turing phổ dụng Chúng ta có thể xem máy Turing phổ dụng như là mô hình toán học của máy tính điện tử ngày hôm nay. Các máy này thực hiện công việc bằng cách mã hóa chương trình theo ngôn ngữ bên trong được gọi là ngôn ngữ máy. Tập các kí hiệu có thể ghi lên băng là hữu hạn nên ta có thể ký hiệu chúng như sau: S0 = B, S1, S2, ..., Sm và có thể mã hóa bằng bộ các chữ số 1. Chẳng hạn: B – 1, S1 – 11, S2 – 111, ..., Sm – 1m+1. Tương tự như vậy, tập các trạng thái là hữu hạn và ta cũng có thể mã hóa chúng như sau: q0 – 1, q1 – 11, q2 – 111, ..., qn – 1n+1.
Máy Turing và tính khả quyết của thuật toán 7
Cuối cùng hai ký hiệu L và R cũng có thể được mã hóa L – 1 và R – 11. Bây giờ, để mã hóa ánh xạ chuyển trạng thái của máy Turing, ta sử dụng bảng biểu diễn ánh xạ này. Trong bảng các cột được ký hiệu bởi các ký hiệu có thể ghi lên băng vào, các dòng được ký hiệu bởi các trạng thái. Tiếp theo, liệt kê các phần tử của bảng theo dòng cùng với các chỉ số dòng và cột tương ứng của chúng: Các phần tử của dòng 1, tiếp đến các phần tử của dòng 2, ... Chẳng hạn, trên một dòng xuất hiện bộ có nghĩa là δ (qi, Sj) = . Giữa các dãy mã của các bộ 5 có chèn hai ký hiệu 0 và giữa mã các ký hiệu trong bộ 5 được chèn bởi một ký hiệu 0. Máy Turing M được mã hóa như vậy có ký hiệu là [M]. Ở đây, chúng ta thừa nhận mà không chứng minh rằng: Với một máy Turing M bất kỳ tồn tại một máy Turing tương đương chỉ có một trạng thái kết thúc. Vì vậy, chúng ta có quyền giải thiết q0 là trạng thái đầu và q1 là trạng thái kết thúc duy nhất của máy Turing M. Ví dụ 2. Cho máy Turing M với ánh xạ chuyển trạng thái được cho bởi bảng sau:
q0
B
S1
q1
q2
Các phần tử của mảng được sắp xếp thành dãy dưới đây : Dãy này sẽ được mã hóa dưới dạng dãy số 0, 1. [M] = 01010110110010110110110100110110110101 1100111011011010111 Nếu trên băng vào có ω = S1S1BS1, thì mã tương ứng của nó sẽ là: [ ω ] = 1101101011 Với [M] và [ ω ] đã cho ta có thể dịch ra M và từ ω như sau: M = < {q0, q1, q2}, {S1}, B, {S1, B}, q0, {q1}> Trong đó: δ (q0, B) = , δ (q0, S1) =
δ (q0, S1) = δ (q0, S1) =
Máy Turing và tính khả quyết của thuật toán 8
và ω =S1S1BS1 Bây giờ giả sử máy Turing M có n trạng thái trong và bảng chữ ghi lên băng có m ký hiệu, thêm vào đó các ký hiệu, các trạng thái, và ánh xạ chuyển trạng thái của M được mã hóa như đã nói ở trên. Mô hình hóa hoạt động của máy Turing M bằng một máy Turing phổ dụng U có thể mô tả khái quát như sau: Trước hết [M] và [ ω ] cần phải được ghi lên băng của máy Turing phổ dụng U theo quy cách sau đây: Ký hiệu X được ghi lên băng, chia băng thành 2 nửa vô hạn. Nửa băng bên phải được dành ra 3 đoạn kề nhau kể từ vị trí ký hiệu ngay sau X: Đoạn đầu tiên được gọi là Buffer gồm n + m + 2 vị trí ký hiệu và tất cả đều được nhận ký hiệu 0; đoạn tiếp theo được gọi là vùng mã hóa của M, bắt đầu bởi ký hiệu Y, tiếp sau Y là [M] và được kết thúc bởi 3 chữ số 0 ; đoạn sau cùng được gọi là đoạn mã hóa của ω , bắt đầu bởi ký hiêu Z và tiếp theo là [ ω ]. Hình ảnh của băng lúc đầu như sau:
B X
0
. . .
Buffer
Y
. . .
0
0
0
Z
Mã hóa M
. . .
B B
Mã hóa
Hình 7. Hình ảnh của Băng lúc đầu Buffer phục vụ cho việc ghi nhận nhận cấu hình của M trong từng bước. Chúng ta có thể sao chép vào vùng này trạng thái bên trong và mã hóa của ký hiệu đang đọc. Ký hiệu Y thường đứng trước bộ 5 xác định trạng thái hiện hành của M, ký hiệu hiện hành hành trên băng, hướng chuyển động của đầu đọc trên băng. Z đánh dấu ký hiệu đang đọc trên băng của M. Quá trình tính toán trong U mô phỏng hoạt động của máy Turing M với xâu vào ω được chia ra các pha thích hợp với việc dịch chuyển các cấu hình của M. Một giai đoạn (pha) hoạt động của máy Turing phổ dụng U có thể được tóm tắt như sau: Đầu tiên sao chép vào buffer một khối các ký hiệu 1 nằm ngay sau Y (gọi là khối Y), sau đó ghi vào cuối khối vừa được chép một ký hiệu X, tiếp theo xóa ký hiệu Y, chạy sang phải tìm ký hiệu Z và sao chép khối ký hiệu 1 ngay sau Z (gọi là khối Z) vào buffer ngay sau ký hiệu X rồi ghi lại ký hiệu Y trước [M]. Như vậy, sau giải đoạn này, trong Buffer chứa mã của trạng thái và ký hiệu hiện hành của máy Turing M. Bước tiếp theo, máy Turing phổ dụng U so sánh 2 khối ký hiệu 1 liên tiếp nhau sau Y với nội dung buffer. Nếu trùng nhau thì tìm được bộ 5 cần tìm. Nếu ngược lại, thì tìm đến mã hóa của bộ 5 tiếp theo sau Y và lại tiếp tục so sánh. Trong trường hợp giữa các bộ 5 mô tả M không tìm thấy bộ nào thích hợp thì U dừng. Ngược lại, nếu tìm được bộ 5 cần tìm thì xóa nội dung buffer rồi chuyển Y đến trước phần tử thứ 3 trong bộ 5 đó. Đổi nội
Máy Turing và tính khả quyết của thuật toán 9
dung của khối sau Z bởi nội dung của khối sau Y và chuyển Y đến trước phần tử thứ tư của bộ 5. Sau khi đã đọc xong phần tử thứ tư mà nó xác định hướng chuyển động của đầu đọc/ghi của M và U chuyển ký hiệu Y đến sau phần tử trước phẩn tử thứ 5. Tùy thuộc vào nội dung của khối thứ 4 (một ký hiệu 1 hay hai ký hiệu 1) mà U sẽ chuyển Z qua phải hay qua trái một khối. Nếu Z lúc đầu nằm ở tận cùng bên trái của băng ghi và M cần dịch chuyển sang phải thì U đẩy mã của từ sang phải và ghi mã hóa của ký hiệu trắng vào sau Z. Nếu Z nằm tận cùng bên phải và cần chuyển sang phải thì khi đó U ghi mã của ký hiệu trắng vào cuối từ. Khi hoàn thành các công việc trên khối ký hiệu 1 đứng sau Y ký hiệu trạng thái hiện hành của M, còn khối sau Z xác định ký hiệu M cần đọc tiếp theo. Như vậy, giai đoạn tiếp theo của việc mô phỏng bước tiếp theo của M có thể bắt đầu. Các giai đoạn hoạt động của máy Turing phổ dụng U mô hình hóa hoạt động từng bước của máy Turing M như đã chỉ ra ở trên. Ngoài ra, U còn thực hiện công việc sau đây: Đầu tiên U thay tất cả các ký hiệu 0 trên 3 đoạn của băng vào bằng các khoảng trắng, cuối công việc, khi M dừng máy U còn kiểm tra liệu trạng thái cuối của M có phải là trạng thái kết thúc hay không. Các pha của một máy Turing phổ dụng U được chia thành 9 phần như sau: •
Phần 1. Thay các ký hiệu 0 bởi ký hiệu B và đầu đọc/ghi chuyển đến trước Y. •
Phần 2. Sao chép mã của trạng thái hiện hành vào buffer.
•
Phần 3. Sao chép mã của ký hiệu cần đọc trên băng của M vào buffer.
•
Phần 4. Đặt X và Y vào trước buffer và trước vị trí của [M].
•
Phần 5. Tìm bộ 5 có mã của trạng thái và ký hiệu trên băng trùng với buffer. •
Phần 6. Xóa buffer
•
Phần 7. Thay mã ký hiệu đã đọc bằng mã ký hiệu mới của M.
•
Phần 8. Đẩy Z sang phải hay sang trái một khối mà mã ký hiệu của khối đó sẽ được đọc trong pha tiếp theo. Nếu cần thì ghi mã một khoảng trắng vào phải hoặc trái từ trên băng M. •
Phần 9. Máy Turing phổ dụng U dừng ở trạng thái kết thúc khi và chỉ khi M dừng ở trạng thái kết thúc. Đồng thời trong vùng mã hóa của từ trên băng sẽ chứa mã của từ đáng ra còn lại trên băng của M, còn mã của trạng thái cuối của M có thể thấy trên buffer. Chúng ta ký hiệu là [M] và [ ω ] được ghi trên băng của U và gọi T(U) là ngôn ngữ được chấp nhận bởi máy Turing phổ dụng U. Chúng ta có thể nhận thấy rằng thuộc T(U) khi và chỉ khi ω được chấp nhận bởi M, có nghĩa là: T(U) = { : ω
∈ T(M)}
Máy Turing và tính khả quyết của thuật toán 10
3. Máy turing với biểu diễn thuật toán 3.1. Khái niệm thuật toán Trong vòng 200 năm qua, vẫn chưa một một định nghĩa về thuật toán được chấp nhận một cách rộng rãi. Tuy nhiên, phần lớn các nhà nghiên cứu trong các lĩnh vực toán học, tính toán, và các chuyên ngành liên quan đều thống nhất rằng thuật toán là một quá trình (một tập hữu hạn các lệnh hay phương cách được định nghĩa rõ ràng) để hoàn thành một số tác vụ nào đó, với một trạng thái ban đầu cho trước, khi các lệnh này được áp dụng triệt để thì sẽ kết thúc tại một trạng thái kết thúc được đã được định nghĩa. Nói cách khác, thuật toán là một bộ các qui tắc hay qui trình cụ thể nhằm giải quyết một vấn đề trong một số bước hữu hạn, hoặc nhằm cung cấp một kết quả từ một tập hợp của các dữ kiện đưa vào. Việc nghiên cứu thuật toán là một trong những lĩnh vực nền tảng của khoa học máy tính. Thông qua việc xây dựng một chương trình máy tính nhằm giải quyết một bài toán cụ thể, người lập trình đã biểu diễn bằng ngôn ngữ máy tính một thuật toán giải bài toán, qua đó điều chỉnh thuật toán thành một chương trình máy tính. Nhiều thuật toán rất hữu dụng trong nhiều ứng dụng máy tính đa dạng. Những thuật toán cơ sở này được nghiên cứu rộng rãi và được xem là một thành phần thiết yếu của khoa học máy tính, bao gồm các thuật toán sắp xếp, tìm kiếm, xử lý chuỗi, đồ thị, thực hiện các phép tính toán toán học phổ biến, … Ví dụ 3. Thuật toán để giải phương trình bậc nhất P(x): ax + b = c, (a, b, c là các số thực), trong tập hợp các số thực có thể là một bộ các bước sau đây: 1. Nếu a = 0 o b = c thì P(x) có nghiệm bất kì o b ≠ c thì P(c) vô nghiệm 2. Nếu a ≠ 0 o P(x) có duy nhất một nghiệm x = (c - b)/a Knuth (1968, 1973) đã đưa ra một danh sách 5 thuộc tính được thừa nhận rộng rãi như là các yêu cầu của một thuật toán: o Tính hữu hạn: “Một thuật toán luôn phải dừng sau một số hữu hạn bước … một số hữu hạn có thể chấp nhận được”. Các thuật toán cần được tạo thành từ một tập hữu hạn các thao tác và phải hoàn thành việc thực hiện trong một thời gian hữu hạn. o Tính tường minh: “Từng bước của thuật toán phải được định nghĩa chính xác, các hành động được thực hiện phải chặt chẽ và được xác định không nhập nhằng cho từng trường hợp”. Cụ thể là bất kỳ những bước điều kiện nào cũng phải được xử lý một cách có hệ thống theo từng trường hợp với tiêu chí là từng trường hợp phải rõ ràng (và có thể tính được). Ngoài ra, vì một thuật toán là một tập các thao tác/lệnh, chúng ta phải biết trật tự đúng để thực hiện các thao tác. Nếu trật tự không rõ ràng, chúng ta có thể thực hiện các thao tác sai hay không chắc chắn thao tác nào sẽ được thực hiện tiếp theo.
Máy Turing và tính khả quyết của thuật toán 11
o Đầu vào: “… định lượng cần được gán lúc ban đầu trước khi thuật toán bắt đầu. Những đầu vào này được lấy ra từ một tập các đối tượng xác định” o Đầu ra: “… định lượng có một quan hệ xác định với đầu ra”. Và các thuật toán phải đưa ra các kết quả cụ thể, qua đó có thể xác định các kết quả đó là đúng hay sai. o Tính hiệu quả: “… tất cả các thao tác cần thực hiện trong thuật toán phải được đảm bảo về nguyên tắc có thể được thực hiện một cách chính xác và trong một khoảng thời gian hữu hạn”. Những thao tác toán học như tìm căn bậc hai của một số âm sẽ là thao tác không hiệu quả, do đó không thể được sử dụng trong các thuật toán Thuật toán có thể được biểu diễn bằng nhiều cách, bao gồm ngôn ngữ tự nhiên, giả mã, ngôn ngữ lưu đồ (sơ đồ khối), ngôn ngữ lập trình. Tuy nhiên, một khi dùng ngôn ngữ lập trình thì chỉ những lệnh được phép trong ngôn ngữ đó mới có thể dùng được và điều này thường làm cho sự mô tả các thuật toán trở nên rối rắm và khó hiểu. Hơn nữa, vì nhiều ngôn ngữ lập trình đều được dùng rộng rãi, nên chọn một ngôn ngữ đặc biệt nào đó là điều người ta không muốn. Vì vậy ở đây các thuật toán ngoài việc được trình bày bằng ngôn ngữ tự nhiên cùng với những ký hiệu toán học quen thuộc còn dùng một dạng giả mã để mô tả thuật toán. Giả mã tạo ra bước trung gian giữa sự mô tả một thuật toán bằng ngôn ngữ thông thường và sự thực hiện thuật toán đó trong ngôn ngữ lập trình. Các bước của thuật toán được chỉ rõ bằng cách dùng các lệnh giống như trong các ngôn ngữ lập trình.
3.2. Biểu diễn thuật toán một cách hình thức bằng máy Turing Máy Turing là một thành phần rất quan trọng trong nền khoa học của thế kỷ XX, một phần vì máy Turing đóng vai trò trung tâm trong lý thuyết về tính toán và khả năng tính toán. Đặc biệt, máy Turing không chỉ được quan tâm như là một bộ chấp nhận ngôn ngữ mà còn cung cấp một định nghĩa nghiêm ngặt về thuộc tính hay phương pháp. Có thể nói các thuật toán rất cần thiết cho máy tính xử lý thông tin, vì một chương trình máy tính cần là một thuật toán chỉ ra cho máy tính các bước cụ thể nào cần thực hiện (theo trật tự nào) nhằm thực hiện một tác vụ cụ thể với mục đích chính của một máy tính là biến đổi input thành output. Thông thường, khi một thuật toán được kết hợp với thông tin xử lý, dữ liệu được đọc từ một nguồn hay thiết bị đầu vào, được viết trên một thiết bị đầu ra, và/hoặc được lưu trữ cho các xử lý tiếp sau. Dữ liệu được lưu trữ được xem là một phần của trạng thái bên trong của thực thể thực hiện thuật toán. Trên thực tế, trạng thái được lưu trong một cấu trúc dữ liệu, nhưng một thuật toán chỉ yêu cầu dữ liệu bên trong cho các tập thao tác xác định gọi là các kiểu dữ liệu trừu tượng. Trong đó, một kiểu dữ liệu trừu tượng được định nghĩa là đặc tả của một tập dữ liệu và tập thao tác có thể thực hiện trên dữ liệu. Kiểu dữ liệu này trừu tượng trên khía cạnh độc lập với các thực thi cụ thể khác nhau. Trong khi đó, một máy Turing có thể được biểu diễn như một hệ thống thực hiện chức năng tự động có khả năng ở một số hữu hạn các trạng thái bên trong và được hỗ trợ bởi một bộ nhớ bên ngoài vô hạn, gọi là băng (nhập/xuất). Trong đó,
Máy Turing và tính khả quyết của thuật toán 12
băng đóng vai trò là phương tiện lưu trữ có mục đích tổng quát của máy Turing: máy được thiết lập ở trạng thái chuyển động với các đầu vào là nội dung cụ thể thời điểm khởi đầu băng chứa, đầu ra là nội dung cụ thể thời điểm kết thúc băng chứa, và băng sẽ là bộ nhớ hoạt động tạm thời để lưu các kết quả của các bước trung gian trong quá trình tính toán. Chương trình (bảng trạng thái) chỉ đạo quá trình tính cụ thể mà máy sẽ thực hiện cũng được lưu trữ trên băng. Một chương trình nhỏ, cố định được tích hợp sẵn trong đầu đọc sẽ hỗ trợ đầu đọc đọc và thực hiện các chỉ dẫn của chương trình bất kỳ đang ở trên băng. Trong bối cảnh đó, khái niệm máy Turing có thể được sử dụng để đảm bảo mô hình hóa ý tưởng tổng quát của một thuật toán được chính xác với một bảng chữ cái đã cho như sau: • Input của một sự tính toán là tất cả các kí hiệu không trắng trên băng tại thời điểm khởi đầu. • Tại thời điểm kết thúc của sự tính toán, output sẽ là bất kì cái gì có trên băng.
• Vậy có thể xem một máy Turing M như là một sự hiện thực của một hàm f được định nghĩa bởi = f(w) trong đó q0w M qf với qf là một trạng thái kết thúc nào đó. • Lúc đó, một hàm f với miền xác định D được gọi là khả tính toánTuring hay đơn giản là khả tính toán nếu tồn tại một máy Turing nào đó M = < Q, Γ , b,
∑ , δ , q , F> 0
sao cho q0w
M
qf f(w), qf ∈F,
∀w ∈ D. Ví dụ 4. Xét bài toán cộng hai số nguyên viết ở dạng nhị phân f(x, y) = x + y . Thủ tục thực hiện phép cộng có thể dựa trên phương pháp thông thường là cộng cặp chữ số nhị phân với nhau (có nhớ) để tính tổng của hai số nguyên. Để cộng a và b, trước hết cộng hai bit ở phải cùng của chúng, tức là: a0 + b0 = c0.2 + s0. Ở đây s0 là bit phải cùng trong khai triển nhị phân của a+b, c 0 là số nhớ, nó có thể bằng 0 hoặc 1. Sau đó ta cộng hai bit tiếp theo và số nhớ a1 + b1 + c0 = c1.2 + s1. Ở đây s1 là bit tiếp theo (tính từ bên phải) trong khai triển nhị phân của a+b và c1 là số nhớ. Tiếp tục quá trình này bằng cách cộng các bit tương ứng trong hai khai triển nhị phân và số nhớ để xác định bit tiếp sau tính từ bên phải trong khai triển nhị phân của tổng a+b. Ở giai đoạn cuối cùng, cộng an-1, bn-1 và cn-2 để nhận
Máy Turing và tính khả quyết của thuật toán 13
được cn-1.2+sn-1. Bit đứng đầu của tổng là sn=cn-1. Kết quả, thủ tục này tạo ra được khai triển nhị phân của tổng, cụ thể là a+b = (sn sn-1 sn-2 ... s1 s0)2. Triển khai thuật toán này với máy Turing, chúng ta phải quyết định các số x và y vào lúc ban đầu được đặt như thế nào trên băng và tổng của chúng xuất hiện như thế nào lúc kết thúc sự tính toán. • Chúng ta giả thiết rằng w(x) và w(y) được phân cách bằng một kí hiệu , với đầu đọc ở trên kí tự phải cùng của w(y).
• Chúng ta vì vậy muốn thiết kế một máy Turing để thực hiện sự tính toán (trong đó qf là một trạng thái kết thúc) q0w(x) w(y)
M
qf w(x + y) ,
Q = {q0, q1, q2, q3,…., q9, qf}, F = {qf}
Với bảng trạng thái được cho bởi đồ thị trạng thái như sau:
• Sau khi tính toán, w(x + y) sẽ ở trên băng và được theo sau bởi một kí tự , và đầu đọc sẽ được đặt trên kí tự phải cùng của kết quả.
Như trên, chúng ta đã thấy máy Turing có thể thực hiện được các phép toán cơ bản và quan trọng những cái mà có trong tất cả các máy tính. Vì trong các máy tính số, các phép toán cơ bản như vậy là các thành phần cơ bản cho các lệnh phức tạp hơn, sau đây là một ví dụ trình bày khả năng máy Turing kết hợp các phép toán này lại với nhau. Giả sử chúng ta thiết kế máy Turing tính toán hàm sau:
Máy Turing và tính khả quyết của thuật toán 14
Ta xây dựng mô hình tính toán như sau:
Vấn đề xây dựng được hàm tính toán được yêu cầu của chúng ta bây giờ sẽ được chuyển thành xây dựng các bộ so sánh, bộ cộng và bộ xóa. Điều này cũng có nghĩa rằng bài toán phức tạp của chúng ta đã được chuyển thành kết hợp các phép toán cơ bản. Với khá nhiều bằng chứng mạnh mẽ tuy chưa đủ là một chứng minh chặt chẽ, nhưng chúng ta chấp nhận miêu tả chính xác của ý tưởng tổng quát về thuật toán trong một bộ chữ cái được thực hiện bởi máy Turing là hoàn toàn đầy đủ. Có nghĩa rằng, đối với mọi thuật toán trong bảng chữ cái cụ thể, có thể xây dựng một thuật toán Turing cho cùng các kết quả với cùng dữ liệu ban đầu như thuật toán . Sự chấp nhận này được gọi là luận đề Turing trong lý thuyết thuật toán, như một định nghĩa của một “sự tính toán cơ học”. Cụ thể, • Bất kỳ cái gì có thể được thực hiện trên bất kỳ máy tính số đang tồn tại nào đều có thể được thực hiện bởi một máy Turing. • Không ai có thể đưa ra một bài toán, có thể giải quyết được bằng những gì mà một cách trực quan chúng ta xem là một thuật toán, mà đối với nó không tồn tại máy Turing nào giải quyết được. • Các mô hình thay thế khác có thể được đưa ra cho sự tính toán cơ học nhưng không có cái nào trong số chúng là mạnh hơn mô hình máy Turing. Bằng việc chấp nhận luận đề Turing, chúng ta sẵn sàng để định nghĩa chính xác khái niệm thuật toán, một khái niệm cơ bản trong khoa học máy tính. Một thuật toán cho một hàm f: D → R là một máy Turing M sao cho cho một chuỗi nhập w∈D trên băng nhập, cuối cùng M dừng với kết quả f(w) ∈R trên băng. Một cách cụ thể là: q0w
M
qf f(w), qf ∈F, ∀w ∈ D.
Luận đề Turing ngay lập tức được chấp nhận rộng rãi. Thông qua việc thực hiện các phép tính dựa trên một kế hoạch được chọn trước, các nhà khoa học đã tiến hành theo một cách tương đương với máy Turing: xem xét một số vị trí trong bài viết của mình và ở trong một “trạng thái trí tuệ”nhất định, họ tiến hành sửa đổi
Máy Turing và tính khả quyết của thuật toán 15
trong bài viết của mình và được thúc đẩy bởi một “trạng thái trí tuệ” mới, sẽ chuyển sang suy ngẫm về các phần viết sau. Tóm lại, một thuật toán có thể được xem là một chuỗi các thao tác có thể được thực hiện bởi một hệ thống Turing-đầy đủ (Turing complete) (còn được gọi là Turing-tương đương (Turing equivalent) hay phổ dụng ((computationally) universal). Trong đó, một máy trừu tượng hay ngôn ngữ lập trình được gọi là Turing-đầy đủ nếu có khả năng tính toán tương đương một mô hình được đơn giản hóa của máy tính có khả năng lập trình, đó chính là máy Turing phổ dụng. “Lý luận không hình thức của Turing trong luận đề của ông đã giải thích cho một luận đề mạnh hơn: Mọi thuật toán có thể được mô phỏng bởi một máy Turing” Gurevich (2000) Còn theo Savage [1987], “Một thuật toán là một quá trình tính được định nghĩa bởi một máy Turing”
Máy Turing và tính khả quyết của thuật toán 16
CHƯƠNG 2. TÍNH KHẢ QUYẾT CỦA THUẬT TOÁN 1. Tổng quan về tính khả quyết của thuật toán Trong phần này, chúng ta sẽ tìm hiểu về một trong nền tảng khoa học cơ bản nhất của khoa học máy tính, đó là tính khả quyết của bài toán. Đó là “Những vấn đề nào có thể và không thể thực hiện được bởi thuật toán hay máy tính?” Trong lý thuyết tính toán, một bài toán quyết định là một câu hỏi trong một số hệ thống hình thức với các câu trả lời có/không. Ví dụ, bài toán “cho 2 số x và y, x có chia hết y không?”. Câu trả lời sẽ là “có” hay “không”, phụ thuộc vào giá trị của x và y. Bên cạnh đó, các bài toán quyết định còn liên hệ mật thiết với các bài toán hàm (function problem) có thể có các câu trả lời phức tạp hơn so với có/không. Một bài toán hàm có thể là “cho 2 số x, y, tìm x có thể chia hết bởi y?”. Các bài toán quyết định còn có thể quan hệ với các bài toán tối ưu, được xét đến với việc tìm lời giải tối ưu cho một vấn đề cụ thể. Trong một hướng tiếp cận mới trong vấn đề về tính khả quyết của bài toán, những nhà khoa học quan tâm đến một họ các bài toán và tìm một thuật toán để quyết định từng họ bài toán đó. Theo đó, vì các thuật toán là lời giải cho các bài toán nên các phương pháp được sử dụng để giải các bài toán quyết định được gọi là thủ tục quyết định hay thuật toán. Từ đó, một bài toán tổng quát khả quyết nếu lời giải của nó sẽ dừng trong một khoảng thời gian hữu hạn, còn không bài toán bất khả quyết. Chúng ta cần chú ý rằng vấn đề về tính khả quyết chỉ là một phần của lý thuyết tính toán không quan tâm đến lượng thời gian mà một lời giải cần mà chỉ cần khoảng thời gian đó là hữu hạn. Ví dụ, một thuật toán cho bài toán quyết định sẽ giải thích làm cách nào để xác định x có chia hết cho y không, với x và y cho trước. Một bài toán quyết định có thể được giải bởi một số thuật toán được gọi là khả quyết. Năm 1936, Church đã hình thức hóa một họ các bài toán mà ông có thể chứng minh rằng không thể quyết định được bởi bất kỳ thuật toán nào. Để phát biểu này có nghĩa, khái niệm toán học mới của một thuật toán phải được đưa ra. Và Church đã sử dụng các công cụ từ logic, khái niệm các hàm đệ quy, để hình thức hóa khái niệm về khả năng giải được về mặt thuật toán. Trong cùng một năm khi Church công bố công trình của mình, Turing cũng đã đưa ra khái niệm về máy Turing. Và ngày nay, chúng ta gọi những bài toán có khả năng tính được về mặt thuật toán (algorithmic solvability) nếu chúng có thể được tính bởi máy Turing. Tuy nhiên, các nhà khoa học đã thống nhất rằng lớp các hàm có thể tính được bằng thuật toán trùng với lớp các hàm có thể tính được bằng máy Turing. Nhiều mô hình tính toán khác đã được đề xuất (một số mô hình tương đối khác với máy Turing) nhưng chúng ta vẫn chưa tìm được một mô hình máy có thể giải quyết được nhiều vấn đề tính toán hơn máy Turing. Trong phần sau đây, chúng ta sẽ khảo sát về luận đề Church-Turing, một luận đề nền tảng trong lý thuyết về tính khả quyết của bài toán
Máy Turing và tính khả quyết của thuật toán 17
2. Luận đề Church-Turing Luận đề Church-Turing đề cập đến khái niệm của một thuật toán hiệu quả trong logic và toán học. Một thuật toán, hay thủ tục, M, cho việc thu được các kết quả mong muốn được gọi là “hiệu quả” trong trường hợp: • M được thiết lập với hình thức một số hữu hạn các lệnh chính xác (từng lệnh được biểu diễn dưới dạng một số hữu hạn các ký hiệu) • Nếu được thực hiện không lỗi, M sẽ đưa ra các kết quả mong muốn trong một số hữu hạn bước. Khái niệm về một thuật toán hiệu quả là một khái niệm không hình thức, và các nỗ lực để xác định tính hiệu quả cho yêu cầu quan trọng mà thuật toán đòi hỏi vẫn được được phát triển. Một trong những thành tựu hàng đầu của Turing – và là bước phát triển lớn đầu tiên trong quá trình phát triển của lý thuyết tính toán – là đề xuất một biểu thức được định nghĩa một cách nghiêm ngặt, qua đó phát biểu không chính quy “bằng một thuật toán hiệu quả” có thể được thay “bằng một máy Turing”. Tầm quan trọng của đề xuất Turing là ở chỗ: nếu đề xuất là chính xác, thì việc nói về sự tồn tại và không tồn tại các thuật toán hiệu quả có thể được thay thế, cả trong toán học và logic, bằng cách nói về sự tồn tại hay không tồn tại của các chương trình máy Turing. Ví dụ, một người có thể thiết lập rằng không có thuật toán hiệu quả để thực hiện một vấn đề nào đó bằng cách chứng minh rằng không có máy Turing nào có thể thực hiện được cùng vấn đề đó. Khái niệm hình thức được đề xuất bởi Turing là khái niệm về tính khả quyết của máy Turing. Ông cho rằng mỗi khi có một thuật toán hiệu quả có thể thu được các giá trị của một hàm toán học, hàm đó cũng có thể được tính bởi máy Turing. Chúng ta cần chú ý rằng phần đảo của luận đề - bất kỳ thuật toán giải quyết vấn đề nào có thể thực hiện bởi máy Turing đều hiệu quả - là đúng. Đó là do chương trình máy Turing tự mình là một đặc tả của thuật toán hiệu quả, nên một người có thể, về mặt lý thuyết, làm việc với bất kỳ một chương trình máy Turing nào, theo các lệnh đã được định nghĩa trước và thực hiện các thao tác được yêu cầu. Trước đó, Church cũng đã độc lập đề xuất một cách khác để thay thế cách nói về các thuật toán hiệu quả với ngôn ngữ chính xác một cách chính quy, sử dụng khái niệm khả năng định nghĩa-lambda (lambda-definability) thay vì “khả năng tính được của máy Turing”. Trong đó, một hàm các số nguyên dương được gọi là có khả năng định nghĩa-lambda nếu giá trị của hàm có thể được tính bằng một quá trình các phép thế được lặp lại. Và ông đã sử dụng biểu diễn (phi hình thức) “có thể tính được hiệu quả” để chỉ ra rằng có một thuật toán hiệu quả để tính các giá trị của hàm qua đề xuất: “Xác định khái niệm của một hàm có thể tính được hiệu quả các số nguyên dương bằng cách xác định khái niệm đó bằng khái niệm của hàm đệ quy của các số nguyên dương (hay với khái niệm hàm có khả năng định nghĩa-lambda các số nguyên dương”. Trong thực tế, Church đã đề xuất “Một hàm các số nguyên dương có khả năng tính được hiệu quả chỉ khi là hàm đệ quy”
Máy Turing và tính khả quyết của thuật toán 18
Sự đảo lại, rằng mọi hàm đệ quy của các số nguyên dương là có khả năng tính được hiệu quả, thường được xem là định lý đảo của luận đề Church. Sau khi tìm hiểu đề xuất của Church, Turing nhanh chóng chứng minh được rằng cấu trúc của khái niệm khả năng định nghĩa-lambda của Church và cấu trúc khái niệm về khả năng tính được của ông là tương đương. Do đó, trong đề xuất của Church, các từ “hàm đệ quy của các số nguyên dương” có thể được thay thế bởi các từ “hàm các số nguyên dương có thể tính được bởi máy Turing”. Và với quan điểm của các kết quả được tìm hiểu trên đây, nếu chỉ giới hạn trong các hàm các số nguyên dương, thì luận đề của Church và của Turing đề xuất, tuy có vẻ rất khác nhau, nhưng lại trở thành tương đương nhau, theo nghĩa là mỗi hướng đề đưa ra chung một tập các hàm toán học. Luận đề Church-Turing là sự khẳng định rằng tập này bao gồm mọi hàm có giá trị có thể thu được bằng một thuật toán thỏa mãn các điều kiện trên đây cho tính hiệu quả. Tuy nhiên, cả Turing và Church đề nhận ra rằng cách triển khai của Turing là “có sức thuyết phục hơn” [turing] và “có ưu điểm trong việc đưa ra khả năng nhận dạng với tính hiệu quả… hiển nhiên ngay lập tức” [Church]. Tóm lại, luận đề Church-Turing, mà nay đã trở thành chuẩn, được đề xuất bởi Kleene như sau: “Các luận đề của Turing và Church là tương đương nhau. Chúng ta có thể xem các luận đề này vừa là luận đề Church, hay liên hệ với một trong các phiên bản … của nó có quan hệ với máy Turing như Luận đề Church-Turing”.
3. Các chương trình như các bộ nhận dạng ngôn ngữ Như trên tiểu luận đã trình bày, ưu điểm nổi bật của máy Turing là tính đơn giản, và cần chú ý rằng chỉ một sự thay đổi đơn giản máy automat hữu hạn (thêm bộ nhớ đọc/viết) đã mang lại cho chúng ta khả năng tính toán phổ dụng. Tuy nhiên, việc máy Turing thuộc loại “bậc thấp” đã dẫn đến các hạn chế trong một số tình huống như sau: Xây dựng một máy Turing chỉ để thực hiện một công việc đơn giản như kiểm tra một số nguyên có phải là một số nguyên tố hay không cũng đã là một công việc rắc rối và mất thời gian. Chính vì lý do đó, trong tiểu luận này, chúng ta sẽ tiến hành theo một cách tương đối phi truyền thống. Chúng ta sẽ sử dụng chính các chương trình để nghiên cứu khả năng tính toán thuần túy như một khái niệm, định lý … trong phần dưới đây sẽ đảm bảo cho chúng ta rằng việc chúng ta có sử dụng các máy Turing hay các chương trình như cách hình thức hóa “chính thức” không phải là vấn đề quan trọng. Đầu tiên, chúng ta cần xác định một chương trình chấp nhận một ngôn ngữ có ý nghĩa như thế nào. Để cụ thể, chúng ta xét lại một số quy ước về chương trình (mà ở đây là chương trình C): • Một file văn bản được mô hình hóa như một chuỗi các ký tự (được kết thúc bằng một dấu hiệu đánh dấu). Trong thuật ngữ ngôn ngữ hình thức chuẩn, một file văn bản đơn giản là một từ trên bảng ký tự ASCII. • Một chương trình p có thể lấy đầu vào từ file đầu vào chuẩn, và có thể xuất các kết quả đầu ra vào một file đầu ra chuẩn
Máy Turing và tính khả quyết của thuật toán 19
• Khi một chương tình dừng, nó sẽ trả về một điều kiện thoát cho hệ điều hành bằng cách gọi hàm exit(status). Trạng thái 0 được sử dụng để thông báo sự thực hiện thành công mà ở đây chúng ta ký hiệu là exit(0). Chúng ta cũng ký hiệu một trạng thái thoát khác của 1 là exit(1) minh họa các điều kiện khác được sử dụng để báo hiệu sự không thành công. • Và chương trình tự bản thân cũng chỉ là một file văn bản Vì vậy, cho p là chương trình, x là file văn bản, và giả sử rằng p được thực hiện với x là đầu vào. Hãy tạm bỏ qua đầu ra và chỉ chú trọng vào cách kết thúc của p. Có 3 khả năng sau đây: • p dừng với exit(0), hay • p dừng với điều kiện dừng khác, hay • p không thể dừng lại, có nghĩa là quá trình tính toán sẽ được thực hiện mãi mãi (chú ý rằng trong mô hình tính toán của chúng ta, chúng ta không cho phép hệ điều hành có thể dừng chương trình vì tràn stack hay các ràng buộc khác) Theo cách này, chúng ta có thể xét một chương trình p để định nghĩa một tập các từ trên bảng chữ cái ASCII: những từ này sẽ làm cho chương trình thực hiện lệnh exit(0). Nghĩa là, bất kỳ chương trình nào cũng định nghĩa (đoán nhận) một ngôn ngữ trên ASCII. Qua đây, chúng ta có thể thấy được mối liên quan khăng khít và tự nhiên giữa lý thuyết tính toán và lý thuyết ngôn ngữ. Tóm lại: Định nghĩa 1. Cho bảng ký tự ASCII được ký hiệu bằng Σ A. Giả sử p là chương trình, và x là từ trên Σ A. Xét kết quả của việc thực hiện chương trình p khi đầu vào chuẩn là một file với nội dung x. Nếu p dừng với exit(0) (tức thành công), chúng ta sẽ phát biểu P chấp nhận x. Tập ngôn ngữ được chấp nhận bởi p là tập tất cả các từ được chấp nhận bởi p và được ký hiệu là L(p): L(p) Với
{x∈
| p dừng với điều kiện thoát exit(0) trên đầu vào x}
là tập tất cả các từ có thể được thành lập từ Σ A.
Ví dụ 5. Cho p là chương trình có giả mã như sau: //Chấp nhận anbncn Đọc đầu vào vào một mảng; oksofar = true; duyệt mảng, đếm số a, lưu kết quả đếm vào n1; duyệt mảng, đếm số b, lưu kết quả đếm vào n2; nếu thấy một a, exit(1); duyệt mảng, đếm số c, lưu kết quả đếm vào n3; nếu thấy a hay b, exit(1); nếu không eof, exit(1); nếu n1 == n2 == n3 exit(0) còn không thì exit(1)
Máy Turing và tính khả quyết của thuật toán 20
Lúc này L(p) là {anbncn | n ≥ 0} Thực tế, có thể rút ra được nhiều điều từ việc chương trình p chấp nhận ngôn ngữ {a b c | n ≥ 0}. Vì p luôn dừng, chúng ta có thể xét exit(0) như “đúng vậy, từ đầu vào có vẻ như là anbncn với một số n”, và chúng ta có thể xét exit(1) như “không, từ đầu vào không có vẻ là anbncn với bất kỳ n nào”. Có nghĩa là, chúng ta có thể xét một cách tự nhiên rằng p như một thủ tục quyết định để kiểm tra các phần tử của ngôn ngữ {anbncn | n ≥ 0}. n n n
Định nghĩa 2. Cho p là một chương trình. Ta nói p là một bộ quyết định nếu với mọi đầu vào x, hoặc p sẽ dừng với exit(0), hoặc p sẽ dừng với exit(1). Đôi khi một bộ quyết định còn được gọi là một chương trình toàn thể (total program) Điểm cần chú ý ở đây là p sẽ không bao giờ thực hiện mãi mãi trên bất kỳ một đầu vào nào, cũng như không dừng với trạng thái thoát nào ngoài exit(0) hay exit(1). Chúng ta có thể thấy p là một bộ quyết định. Sự phân biệt trên đây là rất quan trọng [], và là nguyên tắc trung tâm mà lý thuyết về tính khả quyết sử dụng làm nền tảng. Chúng ta sẽ xét điểm này chi tiết trong những phần sau.
3.1. Các chương trình và máy Turing Với nền tảng lý thuyết ở phần trên (khả năng biểu diễn thuật toán một cách hình thức của máy Turing + khả năng nhận dạng ngôn ngữ của máy Turing), chúng ta có thể suy ra những kết quả cơ bản sau: Định lý 1. Cho một chương trình p, có một máy Turing M mô phỏng p cho mọi từ x với nghĩa sau: • Nếu p dừng với exit(0) trên đầu vào x thì M chấp nhận x và dừng, • Nếu p dừng với một số điều kiện thoát khác trên đầu vào x thì M dừng trên x mà không chấp nhận x, và • Nếu p không dừng trên đầu vào x thì M không thể dừng trên đầu vào x. Hơn nữa, cho một máy Turing M, có một chương trình p mô phỏng M theo cùng một cách như trên. Chú ý rằng, những quan sát trên đây mang lại cho chúng ta những khái niệm đáng chú ý về quá trình tính toán bằng các chương trình. Đó chính là khái niệm mạnh (robust) không phân biêt theo những ngôn ngữ lập trình khác nhau. Và một lần nữa chúng ta có thể thấy rằng khái niệm máy Turing, dù đơn giản hơn rất nhiều so với các ngôn ngữ lập trình hiện đại, vẫn sẵn sàng thực hiện tất cả các thao tác phức tạp có thể có trong quá trình tính toán.
3.2. Các hàm tính toán Trên đây chúng ta đã xét các chương trình đơn giản như là các bộ chấp nhận từ, nghĩa là định nghĩa ngôn ngữ. Dĩ nhiên, các chương trình thường cũng cho ra các đầu ra cũng như các đầu vào, và do đó các chương trình tính các hàm.
Máy Turing và tính khả quyết của thuật toán 21
Trong phần trên, chúng ta đã xét một định nghĩa hình thức của một thuật toán tổng quát với máy Turing. Phần này, chúng ta sẽ xét một số định nghĩa thuật ngữ về các hàm trên khía cạnh nhận dạng ngôn ngữ. Định nghĩa 3. Một hàm một phần từ Σ * vào Σ * là một hàm f từ D và Σ *, trong đó D là tập con của Σ *. Chú ý rằng, nếu f là hàm một phần trên các từ vựng, hoàn toàn có thể xảy ra trường hợp miền D của f là tất cả Σ *, lúc này ta gọi f là hàm toàn phần từ Σ * vào Σ *. Định nghĩa 4. Cho p là chương trình, và w là từ. Xét kết quả của chương trình thực thi p khi đầu vào chuẩn là một file với nội dung là w. Nếu p dừng với exit(0), và nội dung của file đầu ra chuẩn là từ x, chúng ta sẽ nói rằng quá trình tính toán của p trên w sẽ trả về x. Hàm một phần được tính bởi p là hàm một phần từ các từ vựng vào các từ vựng được miêu tả ở phần trên. Và chúng ta cũng cần chú ý rằng miền của hàm được tính bởi p chính xác là L(p). Dĩ nhiên, chúng ta cũng có những mối quan hệ chung giữa các máy Turing và các chương trình trong bối cảnh các hàm chúng ta cho nhận dạng ngôn ngữ như sau: Định lý 2. Cho một chương trình p, có một máy Turing M sao cho M tính cùng một hàm một phần trên các từ vựng mà p đã thực hiện. Cho máy Turing M có một chương trình p sao cho p tính cùng một hàm một phần trên các từ vựng mà M đã thực hiện. Lúc này, • Một hàm một phần f từ Σ * vào Σ * được gọi là hàm một phần T-tính được nếu tồn tại một máy Turing sao cho: o Với một xâu đầu vào w thuộc miền xác định của f, thì máy Turing sẽ dừng ở một hình trạng mà f(w) đang ở trên băng, o Với xâu đầu vào w không thuộc miền xác định của f, thì máy Turing sẽ chạy không dừng hoặc sẽ dừng và thông báo, nhờ một giá trị quy ước trên băng rằng hàm là không xác định • Một hàm toàn phần f từ Σ * vào Σ * được gọi là hàm T-tính được nếu tồn tại một máy Turing sao cho với mọi đầu vào w, máy sẽ dừng ở một hình trạng mà f(w) đang ở trên băng. Trong tiểu luận này, chúng ta xét một bài toán quyết định là mọi câu hỏi có/không bất kỳ trên một tập các đầu vào vô hạn. Do đó, chúng ta có thể định nghĩa bài toán quyết định dưới hình thức tập các đầu vào mà bài toán sẽ trả về kết quả có. Với nghĩa này, một bài toán quyết định tương đương với bài toán quyết định một chuỗi đã cho có thuộc về tập các chuỗi hay không, với tập các chuỗi này được gọi là một ngôn ngữ hình thức, trong đó một chuỗi đầu vào thuộc tập này sẽ trả về CÓ. Hay phát biểu một cách hình thức hơn, một thuật toán khả quyết sẽ dừng với một câu trả lời CÓ hay KHÔNG trên mỗi chuỗi đầu vào đối với một ngôn ngữ L đã cho. Đối với một vấn đề cụ thể, nếu một thuật toán có thể quyết định chính xác một
Máy Turing và tính khả quyết của thuật toán 22
chuỗi có thuộc một ngôn ngữ không thì bài toán sẽ khả quyết. Do đó, tính khả quyết của nhiều ngôn ngữ có thể được xác định theo thuật toán. Và cũng theo đó, việc chỉ ra rằng một ngôn ngữ là khả quyết cũng sẽ tương đương với việc chỉ ra rằng một bài toán là khả quyết. Trong đó, một bài toán khả quyết là T-quyết định được nếu tồn tại một máy Turing quyết định ngôn ngữ liên kết với bài toán đó (có nghĩa ngôn ngữ liên kết với nó là đệ quy). Còn một bài toán khả quyết là T-nửa quyết định được nếu tồn tại một máy Turing thừa nhận ngôn ngữ liên kết với bài toán đó (có nghĩa ngôn ngữ liên kết với nó là đệ quy kể được). Trong những phần sau, chúng ta sẽ xét các khái niệm đệ quy và đệ quy kể được một cách cụ thể hơn.
4. Máy Turing và vấn đề khả quyết 4.1. Các tập đệ quy kể được và khả quyết 4.1.1. Một số định nghĩa Định nghĩa 5. Cho p là một chương trình. Người ta nói rằng p là một bộ quyết định (decider) nếu với mỗi đầu vào x, hoặc p ngắt với EXIT_SUCCESS hoặc p ngắt với EXIT_FAILURE. Điểm mấu chốt ở đây là p sẽ không bao giờ chạy mãi trên bất kỳ đầu vào nào, cũng không ngắt với một trạng thái kết thúc nào ngoài EXIT_SUCCESS hoặc EXIT_FAILURE. Định nghĩa 6. Cho A là một tập con của
∑
*
.
•
A là nửa khả quyết (semi-decidability), hoặc là đệ quy kể được (RE) nếu nó là ngôn ngữ L(p) cho một chương trình p nào đó.
•
A là khả quyết nếu nó là ngôn ngữ L(p) cho một bộ quyết định p nào đó.
Định đề 1. Cho A là một tập con của
∑
*
. Thì :
•
A là RE nếu và chỉ nếu có một máy Turing M sao cho A = L(M)
•
A là khả quyết nếu và chỉ nếu có một máy Turing M mà nó ngắt trên mỗi đầu vào sao cho A = L(M).
4.1.2. So sánh RE và tính khả quyết Điểm khác nhau giữa RE và khả quyết là gì? Một điều chắc chắn rằng, nếu một tập A là khả quyết thì A là RE. Điều này được suy ra trực tiếp từ các định nghĩa: Nếu A là khả quyết thì nó là L(p) cho một bộ quyết định p nào đó, và do đó nó cũng là L(p) cho một chương trình p nào đó, suy ra nó là RE. Vậy, điều ngược lại sẽ như thế nào? Đó là, nếu A là RE, thì liệu rằng A có khả quyết không? Trong một số tài liệu đã chỉ ra rằng điều ngược lại này là không đúng vì có các tập RE nhưng chúng lại không khả quyết. Tóm lại: Nếu chúng ta nói rằng “A là RE” thì điều này có nghĩa là “A là nửa khả quyết, nó cũng có thể hoặc không thể là khả quyết”.
Máy Turing và tính khả quyết của thuật toán 23
4.1.3. Tính kể được Thuật ngữ “đệ quy kể được” được nêu ra trong các định nghĩa ở trên dường như là một nghịch lý, bởi có thể thấy rằng hầu như không có cái gì liên quan đến “đếm được” cả. Chúng ta cùng nhau xem định nghĩa dưới đây: Định nghĩa 7. Một chương trình E kể được một tập A nếu, khi được xử lý với một file đầu vào rỗng, nó tạo ra một chuỗi các từ bao gồm các thành phần của A. Nó không được yêu cầu rằng một bộ kể được (enumerator) tạo ra các từ của A trong bất kỳ thứ tự cụ thể nào. Nó cũng không được yêu cầu rằng một bộ kể được tạo ra các từ chỉ một lần. Nghĩa là một bộ kể được E cho một tập A sẽ tạo ra cùng một x từ A sau nhiều lần thực hiện. Nó chỉ được yêu cầu rằng mỗi thành phần của A xuất hiện ít nhất một lần trong đầu ra của E. Nói cách khác, bạn có thể chỉ ra rằng nếu A là RE thì có một bộ kể được nào đó cho A mà nó có thể in mỗi thành phần của A đúng một lần. Chú ý rằng một bộ kể được sẽ không bao giờ ngắt. Nếu nó ngắt nghĩa là nó sẽ đếm một tập hữu hạn. Ngay cả khi nó không ngắt nó cũng có thể chỉ đếm một tập hữu hạn. Tuy nhiên, nó cũng hoàn toàn có thể đếm một tập vô hạn, bởi vì một bộ kể được không được yêu cầu ngắt. Định lý chính của phần này đó là: Một tập là đệ quy kể được nếu và chỉ nếu nó có thể kể được bởi một chương trình nào đó. Đến đây, có thể thấy rằng cái tên “đệ quy kể được” không còn ẩn đi như lúc trước nữa. Chiều “nếu” của chứng minh có thể được kiểm chứng một cách dễ dàng. Chiều còn lại thì có vẻ hơi phức tạp. Giả sử A là RE, một chương trình p với L(p) = A. Ở đây, chúng ta phải đi tìm một chương trình E để tạo ra một danh sách của thành phần của A. Ý tưởng dưới đây hoàn toàn có thể thực hiện được: bằng việc đếm tất cả các từ x0, x1, x2, … xem mỗi xi lần lượt là đầu vào của p. Bất kể khi nào p chấp nhận xi, thì thêm xi vào đầu ra của E. Một rắc rối xảy ra với ý tưởng này đó là nếu chúng ta không cẩn thận, chúng ta sẽ rơi vào một vòng lặp vô hạn để cố gắng quyết định phải chăng p chấp nhận một xi cụ thể nào đó và chưa bao giờ có cơ hội để xem xét xi+1, xi+2, … Một thủ thuật ở đây là chạy một cách có hiệu quả tất cả các kiểm tra trên tất cả các giá trị x i một cách đồng thời. Đoạn mã được cho bên dưới (trong chứng minh của nửa thứ hai của mệnh đề nếu và chỉ nếu) đưa ra một kỹ thuật thực sự. Định lý 3. Một tập A ⊆
∑
*
là RE nếu và chỉ nếu có một chương trình máy tính
mà nó đếm được A. Chứng minh. Giả sử có một chương trình E. Ở đây, ta có một chương trình p sao cho L(p) = E. Trên đầu vào x; Bắt đầu chương trình E và xem đầu ra; Nếu và khi x xuất hiện trên đầu ra của E, thì exit(0).
Máy Turing và tính khả quyết của thuật toán 24
Ngược lại, giả sử rằng A là RE. Ở đây, ta có một chương trình E mà nó kể được A. int k = 0; while true do For each xi with 0 ≤ i ≤ k Chạy p trên xi trong k bước; Bất kể khi nào xi được chấp nhận bởi p thì print(xi); k = k+1;
Chú ý rằng, với việc kể được của chương trình E mà chúng ta đã xây dựng trong phần 2, mỗi x trong A hoàn toàn được in bởi E nhiều lần một cách vô hạn.
4.2. Các ngôn ngữ đệ quy liệt kê 4.2.1. Ngôn ngữ đệ quy Ngôn ngữ đệ quy là tập tất cả các ngôn ngữ mà chúng được quyết định bởi một máy Turing nào đó. LREC = {L : Tồn tại một máy Turing M, sao cho M quyết định L} 4.2.2. Ngôn ngữ đệ quy liệt kê Ngôn ngữ đệ quy liệt kê là tập tất cả các ngôn ngữ mà chúng được quyết định một nửa (semi-decided) bởi một máy Turing nào đó LR.E = {L : Tồn tại một máy Turing, sao cho M quyết định một nửa L }
4.3. Các bài toán khả quyết Có một quan hệ gần gũi giữa các câu hỏi về mối quan hệ giữa các ngôn ngữ và loại câu hỏi “yes/no” mà chúng ta thường muốn giải quyết trong thế giới thực, chẳng hạn như kiểm tra tính nguyên thủy (primality) của các số nguyên, kiểm tra các đồ thị có là đồ thị phẳng hay không, hay kiểm tra tính đúng đắn của các chương trình. Mối quan hệ này chỉ đơn giản như sau: mỗi khi chúng ta đặt một ký tự
∑
lên những gì mà chúng ta sẽ biểu diễn các trường hợp của một bài toán, các trường hợp mà nó cho ra câu trả lời ứng với câu hỏi của chúng ta là “đúng” thì nó sẽ định nghĩa một ngôn ngữ trên
∑ , đó là tập con của ∑
*
. Với cách này, có thể hiểu
rằng bài toán của chúng ta là khả quyết hoặc RE. Sự liên hệ này rất đáng để chú ý: Chúng ta xác định một vấn đề đã cho với một ngôn ngữ chứa tất cả các đầu vào lấy từ một câu trả lời “đúng” cho vấn đề đó. Chẳng hạn, như đã định nghĩa ở trên, ngôn ngữ sau đây: {w ∈ [0, 1] * | w mã hóa một số nguyên tố} có thể được xác định với bài toán: Đầu vào: Một số nguyên n ở dạng nhị phân Câu hỏi: n có phải là số nguyên tố hay không?
Máy Turing và tính khả quyết của thuật toán 25
Như vậy, chúng ta nói rằng một bài toán là RE hoặc khả quyết khi ngôn ngữ kết hợp là RE hoặc khả quyết, nghĩa là khi ngôn ngữ kết hợp có một chương trình nhận ra nó hoặc thậm chí là quyết định nó. Ví dụ 7. Bài toán dưới đây là khả quyết Đầu vào: Một số nguyên n ở dạng nhị phân Câu hỏi: Có phải n là số nguyên tố không? Những gì mà chúng tôi muốn nói ở đây, đó là: các số nguyên được mã hóa dưới dạng các từ trên tập {0, 1} sử dụng cơ số 2. Tập các từ để mã hóa một số nguyên tố là một ngôn ngữ. Và chúng ta khai báo rằng ngôn ngữ này là ngôn ngữ khả quyết. Để định nghĩa khai báo này, chúng ta sẽ trình bày một chương trình mà nó như là một bộ quyết định hoặc ngắt với exit(0) trên đầu vào w nếu và chỉ nếu w mã hóa một số nguyên tố. Rõ ràng rằng chương trình có thể làm được điều này, chẳng hạn một tìm kiếm hoàn thiện của tất cả các ước số có thể có. Ví dụ 8. Bài toán dưới đây là nửa khả quyết. Đầu vào: Một chương trình viết bằng Java P Câu hỏi: Với đầu vào là 17, p có dừng một cách thông thường hay không? Xem các chương trình như là các từ trên S. Tập S của các từ mà chúng mã hóa các chương trình hợp lệ để chương trình dừng một cách thông thường với đầu vào là 17 là một ngôn ngữ. Để nói rằng tập này là RE hoặc bài toán này là nửa khả quyết, thì cần chỉ ra rằng: Có thể viết một chương mà nó dừng với điều kiện ngắt thành công trên đầu vào w nếu và chỉ nếu w mã hóa được một chương trình như thế. Cách mà chúng ta nhìn thấy ở đây là có thể viết một chương trình TermTst mà nó căn cứ vào đầu vào p, biên dịch p thành mã máy trừu tượng Java _ JAM (Java Abstract Machine codee) (nếu p không phải là một chương trình hợp lệ thì loại bỏ p) và sau đó mô phỏng mã JAM này trên đầu vào 17. Nếu và khi việc mô phòng dừng, thì chương trình TermTst sẽ quan sát sự kiện này và ngắt với exit(0). Nếu việc mô phỏng ngắt không bình thường (chẳng hạn bị ngắt bằng lỗi division by 0), thì chương trình TermTst của chúng ta ngắt với exit(1). Thảo luận trên chỉ ra rằng tập S là một tập nửa khả quyết hoặc RE. Tuy nhiên, ở ví dụ trên có một điểm rất nguy hiểm, đó là bạn sẽ rất dễ nhầm lẫn TermTst với các chương trình Java đang được kiểm tra. Đừng nhầm lẫn! TermTst là một chương trình để kiểm tra chương trình; nó có thể xử lý bất kỳ chương trình java nào mà bạn chuyển cho nó. Hãy chắc rằng bạn chỉ chứng minh S là nửa khả quyết, chứ không phải là khả quyết, bởi vì chương trình TermTst không được đảm bảo là có thể ngắt trên tất cả các đầu vào. Tóm lại là chúng ta biết chắc chắn một điều rằng TermTst sẽ bị lỗi khi ngắt trên một số đầu vào nào đó, bởi vì đơn giản rằng một số chương trình Java sẽ lặp vô hạn khi lấy 17 như một đầu vào, và TermTst, là một chương trình khá đơn giản, chỉ chuyển dịch sang phải. Với quan điểm này, hy vọng rằng sẽ có thể viết ra một chương trình SuperTermTst thông minh hơn mà nó sẽ có thể xoay xở để phân tích các chương trình Java một cách thông minh, và có thể dự đoán được phải chăng
Máy Turing và tính khả quyết của thuật toán 26
chương trình p sẽ dừng một cách bình thường mà không phải mô phỏng p một cách mù quáng. Nếu chúng ta có thể xây dựng một chương trình SuperTermTst như thế, chúng ta có thể chứng minh S là khả quyết. Tuy nhiên, chúng ta không thể thực hiện được điều này, như chúng ta sẽ thấy …nhiều ứng dụng phải chờ cho đến khi chúng ta tiến hành xong một nghiên cứu nào đó nữa dựa trên các kiến thức cơ sở.
5. Một số vấn đề máy Turing không giải được 5.1. Bài toán in (printing problem) và bài toán dừng(halting problem) Turing đã miêu tả một số các bài toán toán học không thể giải được bởi máy Turing, trong đó có bài toán in. Một số chương trình in “0” ở một số bước trong quá trình tính toán của mình; còn tất cả các chương trình còn lại thì không bao giờ in “0”. Bài toán in là bài toán quyết định, với một chương trình bất kỳ đã cho, là chương trình đó thuộc loại nào trong hai loại trên đây. Turing đã chỉ ra rằng bài toán này là không thể giải được bởi máy Turing phổ dụng. Bài toán dừng là một ví dụ khác của các bài toán không thể giải được bằng máy Turing phổ dụng. Đây là bài toán xác định, với một máy Turing bất kỳ đã cho, máy cuối cùng có dừng hay không khi bắt đầu trên một băng trống. Trong một số trường hợp, chúng ta không thể xác định rõ ràng từ một bảng của máy rằng máy có dừng hay không. Trong trường hợp một máy vẫn hoạt động và chưa dừng lại, không có cách thức hiệu quả nào để quyết định máy Turing sẽ dừng hay không.
5.2. Hàm dừng Một hàm là một ánh xạ từ “các đối số” (đầu vào) vào “các giá trị” (đầu ra). Ví dụ, phép + là một hàm ánh xác các cặp số vào những số duy nhất. Một hàm được gọi là có thể tính được bởi máy Turing nếu một số máy Turing sẽ dùng các đối số của hàm (hay các cặp đối số…) và, sau khi thực hiện một số hữu hạn các thao tác cơ bản, đưa ra giá trị tương ứng – và, hơn nữa sẽ thực hiện đối số bất kỳ của hàm đã được trình bày. Ví dụ, phép cộng trên các số nguyên là có thể tính được bởi máy Turing, vì máy Turing có thể được thiết lập sao cho mỗi khi 2 số nguyên được đưa vào băng (nhị phân), máy sẽ đưa ra kết quả phép cộng của hai số đó. Hàm dừng được miêu tả như sau: Giả sử các máy Turing được sắp xếp theo một trật tự nào đó, sao cho chúng ta có thể nói đến máy Turing đầu tiên trong danh sách, máy thứ hai, … Các đối số của hàm dừng đơn giản là 1, 2, 3, … Giá trị của hàm dừng cho đối số n bất kỳ là 1 nếu máy Turing thứ n trong trật tự sắp xếp cuối cùng sẽ dừng khi bắt đầu trên một băng trống, và là 0 nếu máy thứ n chạy mãi mãi (ví dụ như một máy Turing được lập trính để đưa ra liên tiếp các con trong biểu diễn thập phân của π). Định lý về máy Turing phổ dụng không thể giải bài toán dừng thường được biểu diễn dưới dạng hàm dừng.
5.3. Entscheidungsproblem Entscheidungsproblem, hay bài toán quyết định, là động lực chính của Turing trong công trình “Về các số tính được”. Vào đầu thế kỷ 20, nhà toán học D. Hilbert đã tự hỏi liệu có thể tìm ra một thuật toán xác định được tính đúng sai cho mọi mệnh đề toán học hay không và ông cùng W.Ackermann đã đưa ra định nghĩa về Entscheidungsproblem như sau:
Máy Turing và tính khả quyết của thuật toán 27
“Entscheidungsproblem được giải quyết khi chúng ta biết một thủ tục qua đó có thể quyết định trong một số hữu hạn các thao tác một biểu thức logic đã cho có đúng hay có thể được thỏa mãn không. Lời giải của Entscheidungsproblem đóng vai trò quan trọng nền tảng cho lý thuyết của tất cả mọi lĩnh vực, và cho các định lý có khả năng phát triển logic từ các tiên đề hữu hạn” []. Trong đó, Hilbert và các cộng sự đã đề xuất các nhà toán học nên biểu diễn toán theo một dạng hệ thống hình thức hoàn chỉnh, nhất quán, khả quyết – một hệ thống biểu diễn “toàn bộ nội dung ý tưởng của toán học theo một cách thống nhất” []. Một hệ thống nhất quán có nghĩa là không chứa mâu thuẫn, một hệ thống đầy đủ trong đó mọi phát biểu toán học đúng đều có thể được chứng minh. “Khả quyết” hàm ý rằng có một phương pháp hiệu quả để có thể cho biết, với từng phát biểu toán học, phát biểu đó có thể được chứng minh trong hệ thống hay không, và qua đó chỉ ra phát biểu đó là đúng hay sai. Tuy nhiên, năm 1931, nhà toán học người Uc Kurt Gödel đã chứng minh rằng ý tưởng của Hilbert là không thể thỏa mãn. Đây được xem như Định lý về tính không đầy đủ đầu tiên của Gödel, trong đó có thể thấy được có những câu hỏi toán học được hình thức hóa hoàn hảo nhưng lại không đầy đủ và bất khả quyết. Gödel đã chỉ ra rằng dù các nhà toán học có xây dựng hệ thống hình thức theo tư tưởng của Hilbert hoàn thiện đến mức nào đi nữa thì kết quả, dù có nhất quán, cũng không thể đầy đủ. Gödel sau này đã tổng quát hóa kết quả này, chỉ ra rằng “với nền tảng là các công trình của Turing, bây giờ ta có thể đưa ra một định nghĩa chính xác và không thể bàn cãi về khái niệm tổng quát của một hệ thống hình thức”, với hệ quả rằng sự không đầy đủ “có thể được chứng minh một cách nghiêm ngặt cho mọi hệ thống hình thức thống nhất có chứa một lý thuyết số hữu hạn nhất định”[]. Tuy nhiên, định lý của Gödel đã không đề cập đến tính khả quyết. Khía cạnh này được Turing và Church [] đề cập đến, một cách độc lập, rằng không có hệ thống hình thức nhất quán của số học nào là khả quyết. Họ trình bày điều này bằng cách chứng minh rằng ngay cả hệ thống logic thuần nhất được giả sử trước bởi một hệ thống hình thức số học bất kỳ và được gọi là phép tính vị từ bậc nhất (first-order predicate calculus) là khả quyết. Ông chỉ ra một cách hình thức rằng không có máy Turing nào có thể xác định, trong một số hữu hạn bước, một công thức đã cho bất kỳ của phép tính vị từ có phải là định lý (theorem) của phép tính không. Hướng tiếp cận của Turing trong việc chứng minh các phép tính vị từ bậc nhất là bất khả quyết liên quan đến bài toán in. Ông đã chỉ ra rằng nếu một máy Turing có thể, với bất kỳ phát biểu nào, xác định phát biểu đó là có thể chứng minh được bằng phép tính vị từ bậc nhất, thì một máy Turing có thể, với mọi máy Turing đã cho, xác định nó có in “0” hay không. Vì, như Turing đã thiết lập, không có máy Turing nào có thể giải bài toán in, do đó không có máy Turing nào có thể giải bài toán Entscheidungsproblem . Và bước cuối cùng là áp dụng luận đề Turing: nếu không tồn tại máy Turing có thể thực hiện tác vụ được hỏi, thì sẽ không có thuật toán hiệu quả nào để thực hiện tác vụ đó. Do đó, theo luận đề Turing, sẽ không thể tìm được thuật toán nào thỏa yêu cầu.
Máy Turing và tính khả quyết của thuật toán 28
TÀI LIỆU THAM KHẢO 1. Dan Dougherty. Notes on Decidability. Worcester Polytechnic Institute, 2007. 2. Jack Copeland. Computation. www.blackwellpublishing.com/pci/downloads/SampleChapter.pdf 3. Jack Copeland. The Church-Turing Thesis. Stanford Encyclopedia of Philosophy, 2002. 4. Lê Mạnh Thạnh. Nhập môn Ngôn ngữ hình thức và Ôtômat hữu hạn. NXB Giáo dục, Đà Nẵng, 1998. 5. Nguyễn Gia Định. Giáo trình Lý thuyết Ngôn ngữ hình thức và Ôtômat. Huế, 2004. 6. Nguyễn Văn Ba. Lý thuyết Ngôn ngữ và Tính toán. NXB Đại học Quốc gia Hà Nội, Hà Nội, 2006. 7. Peter Gács and László Lovász. Algorithmic decidability. Lecture Notes, Yale University, 1999. 8. Wikipedia, http://en.wikipedia.org/wiki/Wiki
View more...
Comments