Chương trình lý luận về mã nguồn riêng


15

Cảm hứng cho câu hỏi này là câu hỏi (mơ hồ) sau đây: Ngôn ngữ lập trình / nền tảng logic để có AI có thể lý giải về mã nguồn của chính nó và sửa đổi nó là gì?

Điều này hoàn toàn không nghiêm ngặt, vì vậy đây là nỗ lực của tôi để rút ra một câu hỏi cụ thể từ nó. Có hai điều tôi quan tâm:

(A) Một ngôn ngữ lập trình P có thể biểu diễn và thao tác các chương trình của chính nó như một Chương trình kiểu dữ liệu (ví dụ như AST). (Nếu muốn, một đối tượng thuộc loại Chương trình có thể được chuyển đổi thành Chuỗi, là văn bản của chương trình hợp lệ trong ngôn ngữ đó. Điều này ngược lại với những gì trình biên dịch thực hiện.)

(B) Một phương pháp để lý giải về những gì một chương trình trong ngôn ngữ P làm. Đây là hai cấp độ tôi đang nghĩ về nó:

  1. Một ngôn ngữ khác Q (với các khả năng chứng minh định lý) mô hình hóa những gì một chương trình P làm. Nó sẽ có thể diễn đạt và chứng minh các tuyên bố như "kết quả của việc chạy Chương trình p là foo."
  2. Một cách để suy luận về những gì một chương trình p: Chương trình thực hiện trong P ngôn ngữ riêng của mình. (Vì vậy, chúng tôi đang lấy P = Q ở trên.)

Ở mức độ nào đã có một cái gì đó như thế này được thực hiện, hoặc tiến triển theo hướng này là gì? Những trở ngại thực tế là gì? Theo ý định ban đầu của câu hỏi, cách tốt nhất để chính thức hóa vấn đề là gì?

*

Như các câu trả lời cho thấy (cảm ơn!), Cả (A) và (B1) có thể được thực hiện một cách riêng biệt, mặc dù có vẻ như việc thực hiện chúng cùng nhau là một câu hỏi nghiên cứu nhiều hơn.

Đây là một số suy nghĩ đầu tiên của tôi về câu hỏi (cảnh báo: khá mơ hồ). Xem thêm ý kiến ​​của tôi về câu trả lời của Martin Berger.

Tôi quan tâm đến ngôn ngữ lập trình mô hình hóa cùng một ngôn ngữ lập trình, thay vì ngôn ngữ đơn giản hơn (vì vậy P = Q ở trên). Đây sẽ là một "bằng chứng về khái niệm" của một chương trình có thể "lý do về mã nguồn của chính nó." Các ngôn ngữ lập trình được gõ một cách phụ thuộc có thể đảm bảo về kết quả đầu ra của các chức năng của nó, nhưng điều này không được tính là "lý do về mã nguồn của chính nó" bất kỳ hơn "Thế giới xin chào!" được tính là một quine trong một ngôn ngữ sẽ tự động in ra một chuỗi trần --- cần phải có một số loại trích dẫn / tự tham khảo. Tương tự ở đây là có một kiểu dữ liệu đại diện cho Chương trình.

Có vẻ như một dự án khá lớn - ngôn ngữ càng đơn giản, càng khó diễn đạt mọi thứ bên trong nó; ngôn ngữ càng phức tạp thì càng phải thực hiện nhiều công việc để mô hình hóa ngôn ngữ.

Theo tinh thần của Định lý đệ quy, một chương trình sau đó có thể "lấy" mã nguồn của chính nó và sửa đổi nó (nghĩa là xuất ra một phiên bản sửa đổi của chính nó). (B2) sau đó cho chúng tôi biết rằng chương trình sẽ có thể thể hiện sự đảm bảo về chương trình đã sửa đổi (điều này sẽ có thể lặp lại, nghĩa là, nó sẽ có thể diễn tả điều gì đó về tất cả các sửa đổi trong tương lai-?).


1
Tại sao bạn cần ngôn ngữ để hoạt động như một người hoạt động theo định lý để xác định rằng "kết quả của việc chạy Chương trình p là foo"? Ngôn ngữ chỉ đơn giản là có thể chạy p! Thật vậy, đó là những gì đang xảy ra.
Martin Berger


3
Lưu ý rằng về nguyên tắc tất cả các ngôn ngữ có thể tự thực hiện một trình thông dịch có thể làm những việc bạn đang yêu cầu. Theo một cách toán học hơn, định lý đệ quy cho bất kỳ mô hình tính toán nào đủ mạnh. Một số ngôn ngữ lập trình chỉ làm cho nó dễ dàng hơn bằng cách tích hợp nó. Tương tự cho lý luận: bạn có thể thực hiện bất kỳ hệ thống lý luận nào bên trong các ngôn ngữ này. Tất nhiên người ta không thể mong đợi lý do tất cả mọi thứ, ví dụ như vấn đề tạm dừng cho các chương trình.
Kaveh

2
Tôi nghĩ rằng câu hỏi không rõ ràng lắm. Bạn nên xem qua các ngôn ngữ lập trình như Python, Java và những ngôn ngữ được Martin đề cập trong câu trả lời của anh ấy và làm rõ câu hỏi để rõ ràng rằng chúng đáp ứng những gì bạn đang tìm kiếm hoặc nếu không thì tại sao không.
Kaveh

1
@HoldenLee Theo "P = Q", thuật ngữ được thiết lập là "lập trình meta đồng nhất", trái ngược với "lập trình meta không đồng nhất" trong đó P Q.
Martin Berger

Câu trả lời:


14

Tôi nghĩ rằng bạn đang hỏi về hai điều khác nhau.

  • Khả năng của một ngôn ngữ lập trình đại diện cho tất cả các chương trình của nó dưới dạng dữ liệu.
  • Lý do về các chương trình như dữ liệu.

Đối với mục đích phân tích, thật hữu ích để tách chúng ra. Tôi sẽ tập trung vào trước đây.

Khả năng của một ngôn ngữ lập trình đại diện, thao tác (và chạy) các chương trình của nó khi dữ liệu tuân theo các thuật ngữ như lập trình meta hoặc đồng âm .

Theo một cách (vụng về), tất cả các ngôn ngữ lập trình nổi tiếng đều có thể lập trình meta, cụ thể là bằng cách sử dụng kiểu dữ liệu chuỗi cùng với khả năng gọi các chương trình bên ngoài (trình biên dịch, trình liên kết, v.v.) trên chuỗi (ví dụ bằng cách ghi chúng vào tệp hệ thống đầu tiên). Tuy nhiên, đó có lẽ không phải là ý bạn. Bạn có thể có cú pháp tốt đẹp trong tâm trí. Các chuỗi không phải là cú pháp đẹp để biểu diễn chương trình vì hầu hết tất cả các chuỗi không đại diện cho các chương trình, tức là kiểu dữ liệu chuỗi chứa rất nhiều 'rác' khi được xem như là một cơ chế biểu diễn chương trình. Để làm cho vấn đề tồi tệ hơn, đại số của các hoạt động chuỗi về cơ bản không có mối liên hệ nào với đại số của việc xây dựng chương trình.

Những gì bạn có thể có trong tâm trí là một cái gì đó đẹp hơn nhiều. Ví dụ: nếu là một chương trình, sau đó P P , nhưng như dữ liệu, trong tầm tay cho thao tác và phân tích. Điều này thường được gọi là trích dẫn . Trong thực tế, trích dẫn là không linh hoạt, vì vậy chúng tôi sử dụng trích dẫn thay thế, đó là một khái quát của trích dẫn trong đó trích dẫn có thể có 'lỗ hổng' trong đó các chương trình có thể được chạy để cung cấp dữ liệu để 'lấp đầy' các lỗ hổng. Ví dụ i fPPP là một quasi-quote đại diện cho một điều kiện nơi thay vì một điều kiện chúng ta có một lỗ [ ] . Nếu chương trình M đánh giá lại số liệux > 0 thì bán quotei f

if[]then7else8+9
[]Mx>0 đánh giá lại số liệui f
if[M]then7else8+9
ifx>0then7else8+9.

(Lưu ý rằng là một chương trình bình thường (không phải là chương trình dưới dạng dữ liệu) trả về chương trình được trích dẫn, tức là chương trình dưới dạng dữ liệu.) Để làm việc này, bạn cần loại dữ liệu để biểu diễn các chương trình. Thông thường, kiểu dữ liệu đó được gọi là AST (cây cú pháp trừu tượng) và bạn có thể xem (gần như) các trích dẫn dưới dạng cơ chế viết tắt cho AST.M

Một số ngôn ngữ lập trình cung cấp báo giá gần đúng và tính năng khác cho lập trình meta. Chính Lisp với chức năng macroing đã tiên phong cho khả năng này để coi các chương trình là dữ liệu. Có lẽ thật không may, sức mạnh của các macro dựa trên Lisp từ lâu đã được thấy phần lớn dựa trên cú pháp tối giản của Lisp; chỉ đến MetaML (1), một ngôn ngữ hiện đại, giàu cú pháp mới được chứng minh là có khả năng lập trình meta. Kể từ đó, MetaOCaml (2) (hậu duệ của MetaML, quan trọng cho sự đột phá của nó trong nhiệm vụ vẫn đang tiếp diễn để giải quyết vấn đề về cách nhập chương trình dưới dạng dữ liệu), Template Haskell (3) và Converge (4) (ngôn ngữ đầu tiên nhận được tất cả các tính năng lập trình meta chính ngay theo ý kiến ​​của tôi) đã chỉ ra rằng một loạt các ngôn ngữ lập trình hiện đại có thể chứa lập trình meta. Điều quan trọng là nhận ra rằng chúng ta có thểbất kỳ ngôn ngữ lập trình và biến nó thành ngôn ngữ lập trình meta L m pL cùng với khả năng biểu diễn (và đánh giá) các chương trình của chính nó dưới dạng dữ liệu.LLmpL

eval()PPPPeval(P)PP

Đối với chiều thứ hai, lý luận về các chương trình được đưa ra dưới dạng dữ liệu. Ngay khi bạn có thể chuyển đổi chương trình thành dữ liệu, chúng là dữ liệu 'bình thường' và có thể được coi là dữ liệu. Bạn có thể sử dụng tất cả các cách thức của công nghệ prover, ví dụ như các loại phụ thuộc hoặc hợp đồng hoặc các trình xử lý định lý tương tác hoặc các công cụ tự động, như Joshua đã chỉ ra. Tuy nhiên, bạn sẽ phải trình bày ngữ nghĩa của ngôn ngữ của bạn trong quá trình suy luận. Nếu ngôn ngữ đó, như bạn yêu cầu, có khả năng lập trình meta, mọi thứ có thể trở nên hơi rắc rối và không có nhiều công việc được thực hiện theo hướng này, với (5) là logic chương trình duy nhất cho mục đích này. Ngoài ra còn có Curry-Howard dựa trên lý luận về lập trình meta (6, 7, 8). Lưu ý rằng các phương pháp dựa trên logic này, và cách tiếp cận dựa trên loại (2) thực sự có thể thể hiện các thuộc tính giữ cho tất cả các giai đoạn lập trình meta trong tương lai. Ngoài (2) không có giấy tờ nào được thực hiện.

Tóm lại: những gì bạn yêu cầu đã được triển khai, nhưng nó khá tinh tế và vẫn còn những câu hỏi mở, đặc biệt là liên quan đến các loại và lý luận hợp lý.


  1. W. Taha. Lập trình nhiều giai đoạn: Lý thuyết và ứng dụng của nó .

  2. W. Taha và MF Nielsen. Phân loại môi trường .

  3. T. Sheard và S. Peyton Jones. Mẫu lập trình meta cho Haskell .

  4. L. Tratt. Lập trình meta thời gian biên dịch bằng ngôn ngữ OO được gõ động .

  5. M. Berger, L. Tratt, Logic chương trình cho lập trình meta đồng nhất .

  6. R. Davies, F. Pfenning, Một phân tích phương thức tính toán theo giai đoạn .

  7. R. Davies, Phương pháp tiếp cận logic tạm thời để phân tích thời gian ràng buộc .

  8. T. Tsukada, A. Igarashi. Một nền tảng logic cho phân loại môi trường .


Bạn nói đúng - ngôn ngữ lập trình P có thể khác với ngôn ngữ Q thể hiện các định lý / bằng chứng về các chương trình trong ngôn ngữ đó (ví dụ có thể có trong Coq). Loại định lý mà tôi đang nghĩ sẽ diễn ra như sau: Giả sử chúng ta có một chương trình được thiết kế cẩn thận A_1. Thm: Với mỗi n lần giữ sau: Chương trình A_n sẽ xuất ra (m_n, A_ {n + 1}), trong đó m_n là một số nguyên, A_ {n + 1} là một chương trình khác (ví dụ: có được bằng cách sửa đổi A_n theo một cách nào đó) và với tất cả n, chúng ta có m_n> 0.
Holden Lee

(Phiên bản khoa học viễn tưởng của điều này là chúng tôi có một "bằng chứng" rằng một chương trình tự sửa đổi, sẽ không bao giờ nhấn nút phóng tên lửa hạt nhân, hoặc chương trình sẽ luôn tối ưu hóa một số lượng nhất định.)
Holden Lee

Đây là lý do tại sao tôi muốn phân biệt giữa chạy chương trình và suy luận về những gì chương trình sẽ xuất ra - chúng tôi muốn biết các thuộc tính của những gì nó sẽ làm trước khi chạy, mà không chạy nó. Lưu ý rằng nếu chúng ta muốn A_n có thể "sửa đổi mã nguồn của nó" để tạo A_ {n + 1}, thì P nhất thiết sẽ có khả năng lập trình siêu dữ liệu (đặt chúng ta vào vị trí của (5)).
Holden Lee

Dường như với tôi rằng nó sẽ rất thú vị với P = Q. Về mặt giả thuyết, A là một chương trình AI và cách mà nó sẽ tự sửa đổi bằng cách suy luận về mã của chính nó - ví dụ, viết ra các định lý về các bit của mã, chứng minh chúng và chỉ sau đó sửa đổi mã của nó. Sau đó, có vẻ như P sẽ cần phải có khả năng của Q.
Holden Lee

@HoldenLee Có thể viết các chương trình như A_n. Nếu bạn sử dụng chuỗi làm đại diện cho các chương trình, điều này có thể được thực hiện một cách tầm thường trong bất kỳ ngôn ngữ nào, nếu bạn muốn trích dẫn gần giống hoặc tương tự, điều này có thể xảy ra trong ví dụ: Converge. Tôi không hiểu vai trò của m_n trong việc xây dựng.
Martin Berger

6

Không, không có hệ thống hiện tại nào thực hiện cả bốn bước trong hệ thống của bạn. Nếu bạn muốn thiết kế một hệ thống, một trong những yêu cầu đầu tiên là ngôn ngữ đồng âm. Tối thiểu bạn sẽ muốn ngôn ngữ lập trình cốt lõi của bạn mà bạn có càng nhỏ càng tốt để khi bạn vào hệ thống và bắt đầu làm cho nó diễn giải chính nó, nó sẽ hoạt động. Vì vậy, do đó bạn muốn có một trình thông dịch siêu vòng tròn được tiên phong trong lisp. Các ngôn ngữ khác cũng đã làm điều đó nhưng có một số lượng lớn các nghiên cứu hiện có về lisp.

Bước đầu tiên nếu bạn muốn làm điều này là có một ngôn ngữ đồng âm như Lisp hoặc một số khung mà bạn có thể suy luận về một chương trình đang chạy. Lisp được sử dụng cho mục đích này vì lý do duy nhất là bạn có thể định nghĩa trình thông dịch siêu vòng tròn trong ngôn ngữ hoặc bạn chỉ có thể coi mã của mình là dữ liệu. Coi mã là dữ liệu là điều quan trọng nhất Có cùng thảo luận về ý nghĩa của homoiconic trên c2 wiki.

Ví dụ trong Lisp, kiểu dữ liệu "Chương trình" của bạn là các chương trình lisp hợp lệ. Bạn chuyển các chương trình lisp cho một thông dịch viên và nó sẽ tính toán một cái gì đó. Nó bị từ chối bởi thông dịch viên nếu bạn không lập trình một "Chương trình" hợp lệ.

Do đó, một ngôn ngữ đồng âm làm ba yêu cầu của bạn. Bạn thậm chí có thể xác định ý tưởng của một chương trình chính thức.

Bạn có thể mô hình lisp bên trong lisp? Có, điều này thường được thực hiện chủ yếu như một bài tập ở cuối cuốn sách lập trình lisp để kiểm tra khả năng của bạn. SICP

Tại thời điểm hiện tại, vấn đề bốn là một câu hỏi nghiên cứu và dưới đây là những gì tôi đã tìm thấy để cố gắng trả lời câu hỏi này.

Tôi muốn nói có nhiều loại chương trình cố gắng làm điều này. Dưới đây là tất cả các chương trình mà tôi biết.

  • JSLint là một ví dụ về các máy phân tích tĩnh lấy mã máy hoặc một số ngôn ngữ khác và tìm kiếm các lỗi rõ ràng. Sau đó, nó yêu cầu một lập trình viên để sửa điều đó.

  • Coq là một môi trường cho phép bạn chỉ định bằng chứng bằng ngôn ngữ lập trình. Nó cũng có chiến thuật nơi nó gợi ý các cách để bạn giải quyết vấn đề. Tuy nhiên, điều này mong đợi một con người để làm việc. Coq sử dụng các loại phụ thuộc để làm việc và do đó rất lý thuyết loại. Nó rất phổ biến trong số các nhà khoa học máy tính và những người làm việc về Lý thuyết loại Homotopy.

  • ACL2 mặt khác là một người hoạt động định lý tự động. Hệ thống này sẽ chứng minh các tuyên bố dựa trên một cái gì đó mà bạn lập trình.

  • ACL2 và Coq có một plugin phần mềm giao diện hệ thống của họ với hệ thống máy học . Những gì được sử dụng để đào tạo các hệ thống này là các chương trình bằng văn bản trước đây. Theo hiểu biết của tôi, các hệ thống này thêm một tính năng khác, nơi bạn không chỉ có chiến thuật của mình mà còn đề xuất các định lý hỗ trợ phát triển bằng chứng.

Dưới đây là nhiều hơn một nền tảng của những gì câu hỏi của bạn có nghĩa.

  • gcc là một ví dụ về trình biên dịch Optimizng có thể tự lấy làm đầu vào và sau đó xuất ra một phiên bản tối ưu hóa của chính nó. Ý tưởng về một trình biên dịch dịch các chương trình từ biểu diễn này sang biểu diễn khác và cải thiện tốc độ do một số cờ tối ưu hóa được hiểu rất rõ. Khi bạn khởi động trình biên dịch và nó tạo mã máy hợp lệ thì bạn có thể thêm tối ưu hóa và biên dịch lại trình biên dịch và nó tạo ra một phiên bản hiệu quả hơn của chính nó.

1
Không cần phải làm cho ngôn ngữ tối thiểu nhất có thể. Bạn có thể thêm các tính năng lập trình meta có liên quan vào bất kỳ ngôn ngữ nào. Công việc MetaML của Taha đã cho thấy điều này. Thật vậy, việc bổ sung các khả năng lập trình meta là cơ học.
Martin Berger

1
Tôi cũng không đồng ý rằng "không có hệ thống hiện tại nào thực hiện cả bốn bước". Câu hỏi 4 chỉ nói về các chương trình đang chạy dưới dạng mã. Điều đó hoàn toàn có thể, thực sự ngay cả eval của Javascript cũng làm điều đó.
Martin Berger

@MartinBerger điều tôi muốn nói là bạn tạo kernel cốt lõi tối thiểu nhất có thể. Ngoài ra nếu bạn thậm chí bắt đầu muốn hy vọng rằng hệ thống của bạn sẽ làm # 4, bạn sẽ muốn một hệ thống mà bạn có thể đào tạo không chỉ con người mà cả máy tính để sử dụng, vì vậy nó sẽ có lợi cho bạn để có một hệ thống tối thiểu và họ có các thư viện được mã hóa hệ thống đó giống như một mẫu lập trình meta
Joshua Herman

Nó phụ thuộc vào những gì (4) chúng ta đang nói về. Câu hỏi ban đầu chứa hai chi tiết. Đầu tiên là tầm thường, bạn chỉ cần chạy chương trình. Cái thứ hai có thể được xử lý bằng logic tôi đã trích dẫn là (5) trong câu trả lời của tôi về hệ thống gõ (2). Sau này được thực hiện trong MetaOCaml. Nhưng có một phạm vi để nghiên cứu thêm: không (2) hay (5) không thể đối phó với các hình thức lập trình meta tùy ý và các thuộc tính được bảo đảm bởi (2) hơi yếu (xét cho cùng, đó là một hệ thống gõ với suy luận kiểu) .
Martin Berger

1
Đối với "bạn tạo kernel lõi tối thiểu nhất có thể": điều đó không bắt buộc. Bạn có thể thêm lập trình meta đầy đủ vào bất kỳ ngôn ngữ nào.
Martin Berger

5

Như câu trả lời của @ user217281728 có đề cập đến một loại máy liên quan nhiều hơn đến suy luận và AI, được gọi là Máy Godel

Một máy Gôdel là một chương trình máy tính tự cải tiến được phát minh bởi Jürgen Schmidhuber để giải quyết các vấn đề một cách tối ưu. Nó sử dụng một giao thức tự cải tiến đệ quy trong đó nó viết lại mã của chính nó khi nó có thể chứng minh mã mới cung cấp một chiến lược tối ưu hơn. Chiếc máy được phát minh bởi Jürgen Schmidhuber, nhưng được đặt theo tên của Kurt Gödel, người đã truyền cảm hứng cho các lý thuyết toán học.

Ấn phẩm được tham khảo của Jürgen Schmidhuber về "Máy Goedel: Người giải quyết vấn đề phổ biến tự tham khảo Thực hiện tự cải thiện tối ưu", (2006) arXiv: cs / 0309048v5

Cách thức hoạt động của máy để thực hiện siêu học tập có hai giai đoạn:

  1. Học từ dữ liệu (cấp 1, học)
  2. Sử dụng dữ liệu đã học để sửa đổi / tối ưu hóa mã nguồn / thuật toán của nó (cấp 2, học để học)

Vì máy tự sửa đổi nguồn của chính nó, nó là tự tham chiếu, tức là có thuộc tính tự sửa đổi (xem thêm ở đây ).

Theo nghĩa này, nó có thể tự sửa đổi thuật toán học tập theo nghĩa nghiêm ngặt (chứng minh sự tự sửa đổi tối ưu). Có những vấn đề với tự tham chiếu và không có khả năng mà trong trường hợp này có dạng:

.. một cỗ máy Godel với tài nguyên tính toán không giới hạn phải bỏ qua những cải tiến bản thân mà hiệu quả của nó không thể chứng minh

Các ngôn ngữ khác (và các máy thông dịch liên kết của chúng) có thuộc tính tự sửa đổi là ví dụ LISP .

Trong mã LISP và dữ liệu có thể thay đổi được hoặc mã nguồn AST có sẵn dưới dạng dữ liệu, trong chương trình LISP và có thể được sửa đổi dưới dạng dữ liệu. Mặt khác, dữ liệu có thể được xem là AST, đối với một số mã nguồn.

cập nhật

Cũng có những máy khác , như máy tự lập trình (trong số những máy khác) kết hợp tự tham khảo , tự tái tạotự lập trình .

Một khía cạnh thú vị ở trên là tự tham khảo không có vấn đề gì cả, thay vào đó nó là một yếu tố cần thiết trong tự động tự tái tạo / tự lập trình .

Để biết thêm chi tiết (và nhiều ấn phẩm hơn) tham khảo JP Moulin, CR Biology 329 (2006)

trừu tượng

Hệ thống sống có khả năng có những phản ứng phù hợp với môi trường không thể đoán trước. Kiểu tự tổ chức này dường như hoạt động như một cỗ máy tự lập trình, tức là một cơ hội có thể tự sửa đổi. Cho đến nay, các mô hình tự tổ chức của các sinh vật được đề xuất là các giải pháp chức năng của các hệ thống vi sai hoặc các chức năng chuyển tiếp của automata. Các chức năng này là cố định và do đó các mô hình này không thể sửa đổi tổ chức của chúng. Mặt khác, khoa học máy tính đề xuất rất nhiều mô hình có các đặc tính của hệ sinh vật thích nghi, nhưng tất cả các mô hình này phụ thuộc vào sự so sánh giữa mục tiêu và kết quả và sự lựa chọn khéo léo của các lập trình viên, trong khi không có ý định của lập trình viên cũng không phải sự lựa chọn trong các hệ thống sống.mspMsp


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.