CHƯƠNG I NHỮNG BÀI TOÁN KHÔNG THỂ GIẢI ĐƯỢC Khi đề cập đến máy Turing, ta thường quan tâm đến các lớp ngôn ngữ đơn giản và những cách đơn giản được sử dụng trong giải quyết các vấn đề nh
Trang 1I H C À N NG
ĐẠI HỌC ĐÀ NẴNG ỌC ĐÀ NẴNG Đ ẴNG
TR ƯỜNG ĐẠI HỌC BÁCH KHOA NG ĐẠI HỌC ĐÀ NẴNG I H C BÁCH KHOA ỌC ĐÀ NẴNG KHOA CÔNG NGH THÔNG TIN Ệ THÔNG TIN
tài
Đề tài :
NH NG V N ỮNG VẤN ĐỀ MÀ MÁY TÍNH KHÔNG ẤN ĐỀ MÀ MÁY TÍNH KHÔNG ĐỀ MÀ MÁY TÍNH KHÔNG MÀ MÁY TÍNH KHÔNG
TH GI I QUY T Ể GIẢI QUYẾT ĐƯỢC ẢI QUYẾT ĐƯỢC ẾT ĐƯỢC ĐƯỢC C
GVHD : PGS TS Phan Huy Khánh HVTH : VÕ MINH TI N ẾN
H NG C TÚ Ồ NGỌC TÚ ỌC TÚ
TR N VI T ẦN VIẾT ẾN
L P ỚP : Khoa h c máy tính k24 ọc máy tính k24
Trang 2LỜI MỞ ĐẦU
Liệu có thể chế tạo ra một loại máy tính nào đó có hiểu được con người và thông minh như người hay không? Với thế hệ máy tính ngày nay có thể hiểu được như
bộ não của người không? Tìm hiểu chính bản thân mình – đó là niềm khát khao của loài người trong suốt quá trình phát triển Những thành tựu khoa học vang dội gần đây như nhân bản vô tính, giải mã bộ gen người,… phần nào tạo nên ấn tượng con người sắp đạt đến chỗ hiểu được chính mình Như vậy, con người đang đứng trước một câu hỏi lớn: liệu có thể chế tạo ra các máy tính thông minh được không? tức là sẽ
có hay không các máy tính biết tư duy như con người?
Công trình của A Turing (1912-1954), nhà toán học người Anh, cũng nằm trong hướng nghiên cứu vấn đề hình thức hoá toán học (theo tinh thần bài toán mà Hilbert đặt ra năm 1928 tại Hội nghị Toán học thế giới) Turing chứng minh rằng, mọi quá trình tính toán tổng quát có thể thực hiện được bởi một “máy” Máy này gồm
có một cuộn băng độ dài vô hạn với các ô vuông, một thiết bị có hữu hạn trạng thái dùng để đọc các kí hiệu trên cuộn băng Dựa trên kí hiệu ở cuộn băng và trạng thái của thiết bị tại thời điểm hiện tại, máy sẽ thay kí hiệu đang có trên cuộn băng bởi một
kí hiệu khác, đồng thời đổi trạng thái của thiết bị Thiết bị đọc kí hiệu có thể dịch chuyển về bên phải và bên trái.
Trong phạm vi của báo cáo môn học này chúng em xin phép được trình bày một phần rất nhỏ trong việc cấu tạo ra các máy Turing và tổ hợp chúng lại để thực hiện những mục đích cụ thể Chức năng chính của các máy Turing trong phần này thể hiện trên việc đoán nhận và chấp nhận một ngôn ngữ Trên cơ sở những định nghĩa về ngôn ngữ đệ quy và liệt kê đệ quy để tìm hiểu các tính chất của ngôn ngữ hình thức và tính bất biến của các tính chất đó Đề tài gồm có những nội dung chính:
Chương 1 Những bài toán không thể giải được
Chương 2 Bài tập
Trang 3Qua những phần trên cung cấp cho chúng ta những thông tin về phương diện nhận dạng ngôn ngữ của các máy Turing, khả năng thiết kế các máy Turing chấp nhận ngôn ngữ tổ hợp Tuy việc diễn đạt nội dung chính xác, rõ ràng nhưng vẫn còn hạn chế là phạm vi còn nhỏ hẹp Chúng em mong muốn có những điều kiện tốt hơn để nâng cao chất lượng đề tài.
Trên những cơ sở lý thuyết được học và các tài liệu tham khảo, với sự hợp tác làm việc chuyên cần của các thành viên trong nhóm, chúng em xin được báo cáo công việc đã thực hiện được Kính mong được sự góp ý chân thành của quý thầy và các anh chị học viên trong lớp Chúng em xin chân thành cảm ơn sự chỉ bảo tận tình của PGS.TS Phan Huy Khánh giúp chúng em hoàn thành báo cáo này.
Nhóm thực hiện báo cáo:
Võ Minh Tiến Trần Viết
Hồ Ngọc Tú
Trang 4Chương I và Chương II được thực hiện trên nền tảng lý thuyết của cuốn sách
"Introduction to languages and theory of computation" của John C Martin và
tham khảo theo lý thuyết của tài liệu "Lý thuyết tính toán" của PGS TS Phan Huy
Khánh Học viên Võ Minh Tiến, Hồ Ngọc Tú chịu trách nhiệm phần dịch Anh-Việt.
Phần ví dụ minh họa và các chứng minh liên quan do cả 3 học viên Trần Viết, Hồ Ngọc Tú và Võ Minh Tiến phối hợp thực hiện Phần bài tập do học viên Hồ Ngọc Tú thực hiện, học viên Trần Viết chịu trách nhiệm kiểm tra, chỉnh sửa lỗi và thiết kế bản
in Nhóm thực hiện xin chân thành cảm ơn các tác giả đã cho phép nhóm tham khảo tài liệu
Trang 5MỤC LỤC
LỜI MỞ ĐẦU 1
NHỮNG BÀI TOÁN KHÔNG THỂ GIẢI ĐƯỢC 5
I CÁC VẤN ĐỀ KHÔNG THỂ GIẢI ĐƯỢC TRÊN MÁY TÍNH 5
II CÁC CHƯƠNG TRÌNH IN “Hello, World” 6
III GIẢ THIẾT VỀ CHƯƠNG TRÌNH KIỂM TRA “HELLO, WORLD” 8
CHƯƠNG II: BÀI TẬP 13
Trang 6CHƯƠNG I NHỮNG BÀI TOÁN KHÔNG THỂ GIẢI ĐƯỢC
Khi đề cập đến máy Turing, ta thường quan tâm đến các lớp ngôn ngữ đơn giản
và những cách đơn giản được sử dụng trong giải quyết các vấn đề như: phân tích giao thức, tìm kiếm văn bản hoặc các chương trình phân tích văn phạm… Trong phần trình
bày này, nhóm em sẽ trình bày vấn đề “những ngôn ngữ nào sẽ không thể giải bằng
thiết bị tính toán”, vấn đề này tương đương với câu hỏi “máy tính có thể làm được
những gì?”, việc nhận dạng văn bản trong 1 ngôn ngữ là cách diễn đạt vấn đề này một cách tốt nhất
Ta bắt đầu với một vấn đề sau, bằng cách sử dụng ngôn ngữ lập trình C, để chỉ
ra rằng có một số vấn đề máy tính không thể giải được – đó là những vấn đề được gọi
là “không thể quyết định” hoặc "không thể giải được"
I CÁC VẤN ĐỀ KHÔNG THỂ GIẢI ĐƯỢC TRÊN MÁY TÍNH
Mục đích của phần này là cung cấp 1 ví dụ được viết dựa trên ngôn ngữ C để chứng minh có những vấn đề mà máy tính không thể giải quyết Đó là đoạn chương trình C in ra dòng “Hello, World”, ở đây ta không quan tâm đến thời gian giải quyết vấn đề mà ta quan tâm đến chương trình đã làm những gì
Trang 7II CÁC CHƯƠNG TRÌNH IN “Hello, World”
Chúng ta đến với ví dụ sau, đây là ví dụ mà chúng dễ dàng nhận ra rằng kết quả của nó
là in ra xâu hello, world Nó là một ví dụ chung để giới thiệu ngôn ngữ bằng cách xuất
ra chữ hello, world
main() { printf(“hello, world\n”);
} Tuy nhiên, có nhiều chương trình khác cũng cho ra kết quả là hello, world hay không thì không được rõ rang lắm Như ở ví dụ dưới đây chương trình có thể in ra hello, world Nó nhận đầu vào là một số n, và tìm kiếm các số nguyên thỏa mãn biểu thức
xn+yn=zn Nếu nó tìm được 1 bộ ba số nguyên x, y, z thỏa mãn thì nó sẽ in ra hello, world còn nếu không tìm được thì nó cứ tiếp tục chạy mãi và sẽ không bao giờ in ra hello, world
Để hiểu được chương trình này làm như thế nào thì việc đầu tiên chúng ta hiểu là exp, exp là hàm bổ trợ tính lũy thừa Chương trình chính cần tìm kiếm thông qua bộ ba (x,
y, z) theo một trật tự xác định và các số phải là số nguyên dương
Để tổ chức tìm kiếm một các hợp lý, ta sử dụng biến thứ tư là total, giá trị bắt đầu của total là 3 và trong vòng lặp while nó sẽ được tăng một đơn vị mỗi lần Bên trong vòng lặp chúng ta phân chia total cho 3 biến x, y, z Đầu tiên cho x chạy từ 1 cho đến total –
2, y sẽ chạy từ total – 1 – x còn lại z sẽ chạy từ total – x – y Nếu trong vòng lặp bộ ba (x, y, z) được kiểm tra thỏa điều kiện xn+yn=zn thì sẽ in ra màn hình hello world, còn nếu không thì sẽ không hiển thị gì
int exp(int i, n)
/* computes i to the power n *
{
int ans, j;
ans = 1;
for(j=1; j<=n; j++)
Trang 8ans *=i;
return(ans);
}
main()
{
int n, total, x, y, z;
scanf(“%d”, &n);
total = 3;
while(1){
for(x=1; x<=total -2; x++)
for(y=1; y<total –x-1; y++) {
z= total – x – y;
if (exp(x,n) + exp(y,n)==exp(z,n)) printf(“hello, world\n”);
} total++;
}
}
Nếu giá trị của n là 2 thì nó sẽ tìm thấy bộ các số như sau total = 12, x = 3, y = 4, and
z = 5, thỏa mãn điều kiện 32 + 42 = 5 2 Vậy với đầu vào là 2 thì chương trình sẽ in ra
hello, world
- Tuy nhiên với n > 2 thì đoạn chương trình sẽ không tìm thấy 3 số nguyên dương thỏa điều kiện trên nên sẽ không bao giờ in ra “Hello, World”
III GIẢ THIẾT VỀ CHƯƠNG TRÌNH KIỂM TRA “HELLO, WORLD”
Bằng chứng về việc không thể thực hiện các kiểm tra hello-world, là một bằng chứng của sự mâu thuẫn Đó là, giả sử chúng ta có một chương trình, gọi là H, nó sử
Trang 9dụng một chương trình P và một đầu vào I, và với P và I nó thực hiện in ra kết quả: “hello, world”
Hình 8.3 là một đại diện của những gì H thực hiện Đặc biệt, chương trình H chỉ
in kết quả gồm 3 kí tự “Yes” hoặc in 2 kí tự là “No”
Nếu vấn đề có một thuật toán giống như H, mà luôn luôn thể hiện một cách chính xác xem một thể hiện của vấn đề đã trả lời "có" hoặc "không”, sau đó vấn đề được gọi là không giải quyết được
Hình 8.3 Giả thuyết H là một chương trình kiểm tra chương trình in “hello, world”
Để chứng minh sự mâu thuẫn, chúng ta sẽ thay đổi một số H, sau đó xây dựng một chương trình liên quan được gọi là H2 mà chúng tôi cho thấy không tồn tại.Kể
từ khi thay đổi để H chuyển đổi đơn giản có thể được thực hiện vào bất kỳ chương trình C nào, khẳng định đã có sự tồn tại của H, do đó, giả định chúng ta đặt ra
đã mâu thuẫn
Để đơn giản hóa cuộc thảo luận, chúng ta sẽ làm một chương trình giả định bằng ngôn ngữ C Chương trình này sẽ làm cho công việc của dễ dàng hơn, không khó khăn hơn, vì vậy nếu chúng ta có thể hiển thị một "hello-thế giới thử nghiệm" cho các chương trình hạn chế không tồn tại, thì chắc chắn không có thử nghiệm như vậy có thể làm việccho một lớp học rộng lớn hơn của chương trình Giả định của chúng tôi là:
1 Đầu ra tất cả là dựa trên ký tự, ví dụ như, chúng tôi không sử dụng một gói phần mềm đồ họa hay cơ sở nào khác để làm cho sản lượng đó không phải
là trong các hình thức của các nhân vật
I
Hello -world Tester H
H1
yes
hello, world P
Trang 102 Tất cả các đầu ra dựa trên ký tự được thực hiện bằng cách sử dụng printf, chứ không phải là char ( ) hoặc một chức năng đầu ra dựa trên ký tự
Bây giờ chúng ta giả định rằng chương trình H đã tồn tại.Sửa đổi đầu tiên của chúng ta
là làm sao để không có đầu ra, đó là đáp ứng mà H làm cho khi đầu vào P chương trình của nó không in “hello, world” như kết quả đầu tiên đã đáp ứng với đầu vào I
Ngay sau khi H in "n", chúng ta biết nó cuối cùng sẽ in tiếp "o." Chúng ta có thể sửa
đổi bất kỳ kết quả in ra trong H, có thể in "n" thay vì in “hello, world” Kết quả là tạo
ra được 1 chương trình mới, mà chúng ta gọi là H1, hoạt động như H, ngoại trừ việc
nó sẽ chấp nhận in “hello, world” thay vì in “no” như H Đề xuất cho H1 được minh họa ở hình 8.4
Hình 8.4 H1 giống như H, nhưng nó in ra “hello, world” thay vì in “no”
Chuyển đổi tiếp theo của chúng ta trên chương trình là phức tạp hơn, nó là vấn
đề cơ bản trong cái nhìn sâu sắc cho phép Alan Turing chứng minh kết quả của mình
về máy Turing Kể từ khi chúng ta thực sự quan tâm đến chương trình mà phải mất các chương trình khác như là đầu vào và một số vấn đề khác, chúng ta sẽ hạn chế H1 để nó:
a, Chỉ có P mà không có cả P và I
b, Hỏi những gì P sẽ làm gì nếu đầu vào của nó là mã riêng của nó, tức
là H1 sẽ làm gì với đầu vào P là chương trình và P như là đầu vào của tôi cũng?
Các thay đổi chúng ta phải thực hiện trên H1 để sản xuất các chương trình H2 ở hình 8.5 được minh họa như sau:
H1
I
yes
hello, world P
Trang 111 H2 đầu tiên đọc P đầu vào toàn bộ và lưu trữ nó trong một mảng A.
2 Sau đó H2 mô phỏng H1, nhưng bất cứ khi nào H1 được đọc đầu
vào từ P hoặc I, H2 đọc từ các bản sao lưu trong A Để theo dõi bao
nhiêu P và H1 đã đọc H2 có thể duy trì hai con trỏ đánh dấu vị trí trong A
Hình 8.5 H2 giống như H1, nhưng nó chỉ sử dụng P thay vì cả P và I
Chúng tôi đã sẵn sàng để chứng minh H-2 không thể tồn tại H1 không tồn tại,và tương tự như vậy, H không tồn tại.Các đối số là để hình dung những gì
H2 không là chính nó như đầu vào Tình trạng này được đề xuất trong hình 8.6 Nhớ lại rằng H2, cho bất kỳ P chương trình như là đầu vào, làm cho đầu
ra có nếu P in “hello,world” khi đưa ra chính nó như là đầu vào Ngoài ra,
H2 in “hello, world” nếu P, cho chính nó như là đầu vào, không in “hello, world” như kết quả đầu tiên của nó
Hình 8.6 H2 hoạt động thế nào khi xem chính nó là đầu vào
Nó xuất hiện trong hình 8,6 với đầu ra là “hello, world”, vì nó là một hay khác.Nhưng nếu H2 xem chính nó như là đầu vào, in “hello, world” đầu
tiên, sau đó đầu ra của nó là thông báo “yes” Chúng ta có thể tranh luận rằng nó làm cho đầu ra khác
H2
yes
hello, world P
H2
yes
hello, world H2
Trang 12Tình trạng này là nghịch lý, và chúng tôi kết luận rằng H2 không thể tồn
tại Kết quả là, chúng tôi đã mâu thuẫn với giả định rằng H tồn tại.Vậy chúng ta
đã chứng minh rằng không có chương trình H có thể nhận chương
trình P được với đầu vào I để in” hello, world” như kết quả đầu tiên
IV Việc giảm một vấn đề đến những vấn đề khác
Bây giờ, chúng ta có một vấn đề đó là liệu có làm chương trình với dữ liệu vào
in ra hello, world như là điều đầu tiên nó in hay không? Điều này chúng ta biết là máy tính không thể giải quyết được gọi là không thể quyết định được
Có thể chúng ta chứng minh vấn đề mới không giải quyết bởi một kỹ thuật giống như những cái mà chúng ta làm cho vấn đề hello, world : giả sử có một chương trình có thể giải quyết được nó và được phát triển lên thành một chương trình nghịch
lý là có thể làm 2 thứ trái ngược nhau, giống như chương trình H2 Tuy nhiên, chúng
ta có một vấn đề mà chúng ta biết vấn đề đó là không thể quyết định được, chúng ta không cần chứng minh tồn tại của một trạng thái nghịch lý Nếu chúng ta có thể giải quyết được vấn đề mới, sau đó chúng ta có thể sử dụng sự giải thích đó để giải quyết vấn đề mà chúng ta biết là không giải được Chiến lược được đề nghị ở hình bên dưới được dọi là sự giairm của P1 đến P2
Hình 8.7
Để làm bằng chứng cho vấn đề P2 là không giải quyết được chúng ta cần giả sử một cấu trúc, được biểu diễn bởi hình vuông trong hình 8.7, cái mà có thể chuyển từ trạng thái hiện hành của P1 đến trạng thái hiện hành của P2 đều có chung một kết quả Điều đó có nghĩa là vài chuỗi trong ngôn ngữ P1 được chuyển sang vài chuỗi trong
Trang 13ngôn ngữ P2 và những chuỗi không thuộc ngôn ngữ P1 khi chuyển qua cũng sẽ không thuộc ngôn ngữ P2 Và chúng ta có cấu trúc của P1 chúng ta có thể giải quyết P1 theo cách sau:
1 Chúng ta đưa dữ liệu vào của P1 là một xấu w có thể thuộc hay không thuộc ngôn ngữ P1 Áp dụng cấu trúc của thuật toán để cho kết quả xâu x
2 Kiểm tra xâu x ở trong P2 Nếu w nằm trong P1 thì x nằm trong P2 và ngược lại
Trang 14CHƯƠNG II: BÀI TẬP
* Bài 8.1.4 Cho chương trình và một dữ liệu đầu vào hỏi có thể cho ra vài kết quả khác nhau hay không?
* Bài giải:
Một chương trình được gọi là không giải quyết được hay không quyết định được đều
có thể cho ra kết quả khác nhau nhưng với những dữ liệu đầu vào khác nhau Còn riêng bài toán này thì cùng một chương trình cùng một dữ liệu đầu vào nếu cho ra kết quả khác nhau thì chỉ có khi chúng ta sử dụng hàm random Ví dụ như chương trình sau có đầu vào là n là số nguyên dương Chương trình sẽ in ra một số nguyên bất kỳ là tích của n với random(100)
void main()
{
int n, s;
printf(“nhap so nguyen duong n”);
scanf(“%d”, &n);
s= n* random(100);
printf(s);
}
Chương trình sẽ in ra s, dù có thể cùng một dữ liệu đầu vào nhưng kết quả của s có thể
là khác nhau
Nếu không sử dụng hàm random thì sẽ không có chương trình nào thảo mãn yêu cầu bài toán trên
Trang 15Tài liệu tham khảo
[1] John C Martin, Introduction to languages and the theory of coputation, The
McGraw-Hill Companies, Inc, 1997
[2] Phan Huy Khánh, Giáo trình lý thuyết ngôn ngữ hình thức và Ôtômat, Đà
Nẵng, 1998
[3] TS Phan Huy Khánh, Lý thuyết tính toán, Đà Nẵng, 1999.