ลูป do-while เพียงพอสำหรับทัวริงครบถ้วนหรือไม่


22

ฉันรู้ว่าในภาษาการเขียนโปรแกรมที่จำเป็นห่วงในขณะที่ทำก็เพียงพอในการสร้างโฟลว์การควบคุมเพื่อสร้างภาษาทัวริงที่สมบูรณ์ (เท่าที่โฟลว์การควบคุมดำเนินไป . ส่วนสำคัญของคำถามของฉันคือ: วนรอบในขณะที่ทำมีอำนาจการคำนวณเช่นเดียวกับวนรอบขณะทำ? กล่าวอีกนัยหนึ่งคือภาษาทัวริงจะสมบูรณ์หากไม่สามารถข้ามคำแนะนำทั้งหมดได้

ฉันรู้ว่าความหมายบางอย่างของที่นี่อาจจะคลุมเครือเล็กน้อยดังนั้นขอให้ฉันวลีคำถามจริงด้วยตัวอย่างเฉพาะ:

Brainfuck (BF) เป็น Turing tarpit ที่มีการควบคุมการไหลเพียงลูปแบบ while-do ซึ่งแสดงว่า[...](มีสเป็คภาษาสมบูรณ์ที่ด้านล่างของคำถามในกรณีที่คุณไม่คุ้นเคยกับ Brainfuck) ลองกำหนด * ภาษา BF ใหม่ที่,.+-<>มีความหมายเช่นเดียวกับใน BF แต่แทนที่จะ[]เรามี{}ซึ่งหมายถึงการทำในขณะที่ห่วง นั่นคือความแตกต่างเพียงอย่างเดียวของ BF คือว่าทุกลูปจะถูกดำเนินการอย่างน้อยหนึ่งครั้งก่อนที่จะข้ามการทำซ้ำต่อไป

BF * ทัวริงเสร็จสมบูรณ์หรือไม่ ถ้าเป็นเช่นนั้นฉันจะสนใจว่าฉันจะแปล BF เป็น BF * ได้อย่างไร ถ้าไม่ใช่ฉันจะพิสูจน์ได้อย่างไร

ข้อสังเกตของฉัน:

  • ไม่ใช่ทุกโปรแกรม BF ที่สามารถแปลเป็น BF * ตัวอย่างเช่นเป็นไปไม่ได้ที่จะเขียนโปรแกรมใน BF * ซึ่งอาจจะหรืออาจไม่อ่านหรือพิมพ์ค่า - หากโปรแกรมอาจพิมพ์ค่าหนึ่งค่าหรือมากกว่านั้นมันจะพิมพ์อย่างน้อยหนึ่งค่าเสมอ อย่างไรก็ตามอาจมีชุดย่อยของทัวริงที่สมบูรณ์ซึ่งสามารถแปลเป็น BF * ได้
  • เราไม่สามารถแปล[f](ซึ่งfบางโปรแกรมโดยเฉพาะ Brainfuck ซึ่งประกอบด้วยเท่านั้น+-[]<>) เป็น(ในความพยายามที่จะยกเลิกผลกระทบของการวนซ้ำครั้งแรก) เนื่องจาก) การทำงานที่คำนวณไม่ได้ทุกอันมีค่าผกผันและ b) แม้ว่ามันจะทำไม่จำเป็นต้องมีลูปน้อยกว่าดังนั้นการใช้ขั้นตอนนี้ซ้ำ ๆ จะไม่รับประกันว่าจะยุติในครั้งแรกf-1{f}f-1f

นี่คือภาพรวมโดยย่อของภาษา Brainfuck Brainfuck ทำงานบนเทปที่ไม่มีที่สิ้นสุดซึ่งแต่ละเซลล์มีค่าไบต์เริ่มแรกเป็นศูนย์ มีโอเวอร์โฟลว์พันรอบดังนั้นการเพิ่ม 255 จะให้ 0 และในทางกลับกัน ภาษาประกอบด้วย 8 คำแนะนำ:

+   Increment the current cell.
-   Decrement the current cell.
>   Move tape head to the right.
<   Move tape head to the left.
,   Input a character from STDIN into the current cell.
.   Output the current cell as a character to STDOUT.
[   If the current cell is zero, jump past the matching ].
]   If the current cell is non-zero, jump back to just behind the matching [.

2
คำถามที่คล้ายกันมาก
Raphael

น่าสนใจ แต่คิดว่ามันไม่ได้ถูกสร้างอย่างรอบคอบ []ไม่ได้กำหนดวง "ในขณะที่" ใน BF อย่างแน่นอน เช่นเดียวกับในตารางของคุณวงเล็บปีกกาซ้ายและขวาประเมินเซลล์ปัจจุบันเป็นศูนย์ / ไม่เป็นศูนย์ ดังนั้นคำอธิบายที่แน่นอนของ{}ตรรกะการประเมินผลที่สอดคล้องกันคืออะไร? แนะนำเพิ่มเติมโต้ตอบ / การอภิปรายในวิทยาการคอมพิวเตอร์สำหรับการพูดคุย นอกจากนี้ "การสังเกต" ของคุณก็เหมือน "สมมุติฐาน" หรือ "ข้อเสนอ" โดยไม่มีข้อพิสูจน์
vzn

@vzn นั่นเป็นจุดที่ดี ฉันคิดว่าคำนิยามที่ชัดเจนของการ{}จะทำให้{ไม่มีอะไรทำเลยและเช่นเดียวกับ} ]ฉันจะไม่มีเวลามากในสองสามวันถัดไป แต่ฉันจะเข้าร่วมแชทเมื่อฉันหาเวลา
Martin Ender

ดังนั้นอนิจจานี้ค่อนข้างบอบบางที่จะถามและดูเหมือนจะมีสองคำถามที่แตกต่างกันโดยสิ้นเชิงที่นี่ (1) ให้ภาษาทัวริงที่สมบูรณ์ด้วยลูปแบบ while-do (และ "สิ่งอื่น ๆ ") สามารถแปลงเป็นภาษาที่สมบูรณ์ของทัวริงได้ด้วยการวนลูป do-while แทน แต่แล้วเราต้องรู้เพิ่มเติมเกี่ยวกับ "สิ่งอื่น ๆ " ในรายละเอียดเพื่อตอบ (2) ได้รับ BF และ BF * ใหม่ที่มีการกำหนด{}และรับไป[]เป็น BF * ทัวริงเสร็จสมบูรณ์ ด้วยความเข้าใจว่า BF []เป็นสิ่งก่อสร้างเพียงบางสิ่งบางอย่างที่ค่อนข้างเหมือน / คล้ายคลึงกับห่วงในขณะที่ทำในทัวริง
vzn

1
@vzn ส่วน (1) เป็นเพียงส่วน TL; DR ของคำถามของฉัน ฉันรู้อยู่เต็มอกว่านี่อาจเป็นไปไม่ได้ที่จะตอบว่า "บางภาษา" นี่คือเหตุผลที่ฉันได้ถามคำถามจริงในแง่ของภาษาของเล่นง่าย ๆ (BF) เพื่อ จำกัด ให้แคบลงกับพฤติกรรมของลูป (เพราะฉันคิดว่าถ้า BF * สามารถแสดงเป็น TC ที่จะทำให้ง่ายขึ้น เพื่อแสดงสำหรับภาษาอื่นซึ่งมีลูปทำในขณะนั้นเท่านั้น) ฉันไม่แน่ใจว่าคุณคิดอย่างไรว่าลูป BF แตกต่างจากลูปของภาษาอื่นในขณะที่ทำ
Martin Ender

คำตอบ:


10

ฉันไม่รู้ Brainfuck ดังนั้นคุณต้องแปลบางอย่างจากรหัสเทียมของฉัน แต่สมมติว่า Brainfuck ทำงานอย่างสมเหตุสมผล (ฮ่า!) ทุกอย่างด้านล่างควรใช้

do-while เทียบเท่ากับ while-do do X while Yเทียบเท่ากับX; while Y do Xและสมมติว่าคุณมีเงื่อนไข, เทียบเท่ากับwhile Y do Xif Y then (do X while Y)

ชีวิตนั้นยากขึ้นนิดหน่อยถ้าคุณไม่มีเงื่อนไข หากคุณมีในขณะที่ทำคุณสามารถจำลองif Y then Xโดยใช้สิ่งนี้:

B := true
while (Y and B) do
    X
    B := false
endwhile

แต่ถ้าคุณเพียงทำในขณะที่? ฉันอ้างว่าการจำลองต่อไปนี้if Y then Xสมมติว่าการXยกเลิกกำหนดค่าปัจจุบันของตัวแปร (สิ่งนี้ไม่ได้รับประกัน: โปรแกรมif y=0 then loopforeverจะยุติลงy != 0แม้ว่าXลูปสำหรับตัวแปรใด ๆ ก็ตาม) Let V1, ... , Vnเป็นตัวแปรแก้ไขโดยXและให้X'ได้รับการXแก้ไขเพื่อที่จะใช้Vi'แทนViสำหรับแต่ละตัวแปรเหล่านั้น swap(A,B)หมายถึงรหัสที่เห็นได้ชัดว่า swaps ตัวแปรและAB

V1' := V1; ...; Vn' := Vn
V1'' := V1; ...; Vn'' := Vn
C := 0
do
    X'
    swap (V1',V1''); ...; swap (Vn',Vn'')
    C := C+1
while Y and C<2
V1 := V1'; ...; Vn := Vn'

แนวคิดมีดังต่อไปนี้ ก่อนอื่นสมมติว่าYเป็นเท็จ เราจำลองการทำXหนึ่งครั้งและเก็บผลลัพธ์ไว้ในV1'', ... , Vn''; V1', ... , Vn'เก็บค่าดั้งเดิมของV1, ... , Vn. จากนั้นเรามอบหมายV1 := V1'; ...; Vn := Vn'ซึ่งไม่ทำอะไรเลย ดังนั้นหากYเป็นเท็จเราไม่ได้ทำอะไรเลย ตอนนี้สมมติว่าYเป็นจริง ตอนนี้เราจะจำลองX สองครั้งโดยเก็บผลลัพธ์ไว้ในทั้งตัวแปร "ทำสีรองพื้น" และ "ทำสีรองพื้น" ดังนั้นตอนนี้การกำหนดที่ส่วนท้ายของลูปจะมีผลกระทบที่Xคำนวณได้หนึ่งครั้ง โปรดทราบว่าYขึ้นอยู่กับตัวแปร "unprimed" เท่านั้นดังนั้นค่าของมันจะไม่ได้รับผลกระทบจากการวนซ้ำซ้ำ ๆ

ตกลงดังนั้นจะเกิดอะไรขึ้นหากXไม่สามารถยกเลิกค่าปัจจุบันของตัวแปรได้ (ขอบคุณ Martin Ender ที่ชี้ให้เห็นถึงความเป็นไปได้นี้) ในกรณีนี้เราจำเป็นต้องจำลองการXเรียนการสอนตามคำแนะนำโดยใช้แนวคิดที่คล้ายกับที่กล่าวมาข้างต้น การเรียนการสอนแต่ละรายการยุติลงอย่างแน่นอนเพื่อให้เราสามารถใช้การifจำลองด้านบนเพื่อทำการถอดรหัสการสอนตามบรรทัดของ "ถ้า opcode เป็น foo ทำสิ่งนี้ถ้าเป็นแท่งให้ทำเช่นนั้น; ... " ดังนั้นตอนนี้เราใช้การวนซ้ำเพื่อทำซ้ำตามคำแนะนำของการXใช้ตัวชี้คำสั่งและอื่น ๆ เพื่อให้เรารู้ว่าคำสั่งที่จะดำเนินการต่อไป ในตอนท้ายของการวนซ้ำแต่ละรอบให้ตรวจสอบYและตรวจสอบว่าXมีการหยุดหรือยัง หากYเป็นเท็จเทคนิคการแลกเปลี่ยนช่วยให้เราสามารถยกเลิกผลกระทบของXคำสั่งแรกของ.


1
นี่เป็นความคิดที่เรียบร้อย แต่ฉันคิดว่ามีปัญหาหนึ่งที่นี่: พิจารณากรณีที่Yเป็นเท็จ แต่Xไม่ยุติในชุดค่าตัวแปรปัจจุบัน if Y then Xสิ้นสุดลง แต่การแปลของคุณไม่ได้เพราะจะต้องดำเนินการX'อย่างน้อยหนึ่งครั้ง
Martin Ender

1
@ MartinBüttner Urgh คุณถูก. ดังนั้นเราต้องใช้การวนซ้ำเพื่อจำลองการXสอนตามคำสั่งและตรวจสอบYแต่ละคำสั่ง แต่ละคำสั่งรับประกันว่าจะยุติดังนั้นทุกอย่างจะทำงานได้ แต่มันเป็นความเจ็บปวดที่จะเขียนลงไป
David Richerby

1
ฉันไม่แน่ใจว่ามันเป็นไปได้หรือไม่ที่จะแยกแยะXอย่างนั้นถ้ามันเริ่มต้นด้วยขณะที่ลูป / เงื่อนไขเอง ฉันจะต้องคิดถึงเรื่องนี้ให้มากขึ้น
Martin Ender

นอกจากนี้ "ดังนั้นตอนนี้เราใช้การวนซ้ำเพื่อทำตามคำแนะนำของ X โดยใช้ตัวชี้คำสั่งและอื่น ๆ เพื่อให้เรารู้ว่าคำสั่งใดที่จะดำเนินการต่อไป" ฉันรู้สึกแบบนี้ในตัวเองอาจต้องมีเงื่อนไขบางอย่าง
Martin Ender

1
ฉันยังไม่แน่ใจทั้งหมดว่าคุณกำหนด "แต่ละคำสั่ง" อย่างไรถ้าX'ไม่ใช่เชิงเส้น คุณจะใจรวมถึงรายละเอียดเพิ่มเติมสำหรับของเล่นที่เรียบง่าย แต่ไม่สำคัญXหรือไม่? เช่นdo (while A do B) while C? (ด้านนอกdo whileมาจากด้านนอกwhile doที่เรากำลังแปล)
Martin Ender
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.