Чи достатньо циклу "до часу" для цілісності Тьюрінга?


22

Я знаю, що в імперативних мовах програмування цикл time-do є достатнім як конструкція потоку управління, щоб зробити мову Turing-повною (що стосується потоку управління - звичайно, нам також потрібна необмежена пам'ять і певні оператори ...) . Суть мого питання полягає в тому: чи цикл do-while має таку ж обчислювальну потужність, що і цикл while-do? Іншими словами, чи може бути мовою Тюрінг повною, якщо неможливо повністю пропустити інструкції.

Я розумію, що частина семантики тут може бути дещо неоднозначною, тому дозвольте сформулювати власне питання на конкретному прикладі:

Brainfuck (BF) - це Тарріт Тюрінга, де єдиним керуючим потоком є ​​цикл "time-do", позначений як [...](у нижній частині питання є повна специфікація мови, якщо ви не знайомі з Brainfuck). Давайте визначимо нову мову BF *, де ,.+-<>мають ту саму семантику, що й у BF, але замість цього []ми маємо, {}що позначає цикл do-while. Тобто, єдиною відмінністю BF є те, що кожен цикл виконується принаймні один раз, перш ніж можна пропустити подальші ітерації.

Чи завершено BF * Turing? Якщо це так, мені було б цікаво, як я міг би перевести BF на BF *. Якщо це не так, як я можу це довести?

Деякі мої спостереження:

  • Не кожну програму BF можна перекласти на BF *. Наприклад, неможливо написати програму в BF *, яка може чи не може прочитати або надрукувати значення - якщо програма потенційно надрукує одне або більше значень, вона завжди буде надрукувати принаймні одне. Однак, можливо, існує повна підмножина BF, яку можна перекласти на BF *.
  • Ми не можемо просто перекласти [f](де fє якась довільна програма Brainfuck, що складається лише з +-[]<>) у (у спробі скасувати ефект першої ітерації), тому що: а) не кожна обчислювана функція має обчислювальну зворотну форму ; не обов'язково матиме менше циклів, ніж застосування цього кроку рекурсивно не гарантується в першу чергу.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 [.


Цікаво, але думаю, що він не повністю ретельно побудований. []не точно визначає цикл "while do" в BF. як у вашій таблиці лівий і правий дужки оцінюють поточну комірку нуль / нуль. так що точний опис відповідної {}логіки оцінки брекетів? запропонуйте подальший діалог / обговорення в чаті з інформатики . також ваші "спостереження" більше схожі на "постулати" або "пропозиції" без доказів.
vzn

@vzn Це хороші моменти. Я подумав, що очевидним визначенням {}буде змусити {взагалі нічого не робити і }таким же, як ]. У наступних кількох днів у мене не буде багато часу, але я приєднаюся до вас у чаті, коли знайду якийсь час.
Мартін Ендер

так на жаль, це, мабуть, дещо тонко запитувати, і тут, здається, є два абсолютно різні питання. (1) з огляду на будь-яку повну мову Тьюрінга з циклом time-do (та "інші речі"), чи можна її перетворити на повну мову Тьюрінга із лише циклом "do-while". але тоді потрібно детальніше знати про "інші речі", щоб відповісти. (2) Даний BF та новий BF * із заданим визначенням {}та відніманням [], BF * Turing завершений. з розумінням того, що BF []- це конструкт лише щось на зразок / аналогічне циклу while-do в Turing повних мовах.
vzn

1
@vzn частина (1) була лише TL; DR частина мого запитання. Я цілком усвідомлюю, що це, мабуть, неможливо відповісти за "якусь мову". Ось чому я сформулював власне питання з точки зору дуже простої іграшкової мови (BF), щоб дійсно звузити його до поведінки циклів (тому що я зрозумів, якщо BF * може бути показаний як TC, що спростить його) показати його для інших мов, у яких є лише цикли виконання часу). Я не впевнений, чим ви вважаєте, що цикли BF відрізняються від циклів, які виконують інші мови.
Мартін Ендер

Відповіді:


10

Я не знаю Brainfuck, тому вам доведеться зробити переклад з мого псевдокоду. Але, припускаючи, що Brainfuck поводиться розважливо (га!), Все, що нижче, має застосовуватися.

do-while еквівалентний while-do. do X while Yеквівалентно X; while Y do Xі, якщо у вас є умовні умови, while Y do Xрівнозначно if 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певне значення змінних). Нехай V1, ..., Vnзмінні змінені, Xі нехай X'будуть Xзмінені так, щоб вони використовувались Vi'замість Viкожної з цих змінних. swap(A,B)позначає очевидний код, який підміняє змінні Aта B.

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може не припинятися для поточного значення змінних? (Дякую Мартіну Ендеру за вказівку на таку можливість.) У такому випадку нам потрібно моделювати Xінструкцію за інструкцією, використовуючи подібні ідеї до наведених вище. Кожна інструкція безумовно закінчується, тому ми можемо використовувати ifмоделювання вище, щоб зробити розшифровку інструкцій, відповідно до рядків "Якщо опкод є foo, зробіть це; якщо це бар, зробіть це; ...". Отже, зараз ми використовуємо цикл, щоб перебирати вказівки X, використовуючи вказівник інструкцій тощо, щоб ми знали, яку інструкцію виконувати далі. В кінці кожної ітерації циклу перевірте Yі перевірте, чи Xще зупинилося. Якщо Yпомилково, техніка заміни дозволяє скасувати наслідкиXПерша інструкція.


1
Це чітка ідея, але я думаю, що тут є одне питання: розгляньте випадок, коли Yпомилковий, але Xне закінчується на поточному наборі змінних значень. if Y then Xприпиняється, але ваш переклад не робить, оскільки його завжди потрібно виконати X'хоча б один раз.
Мартін Ендер

1
@ MartinBüttner Urgh. Ти правий. Тому нам потрібно використовувати цикл для імітації Xінструкцій за інструкцією та перевірки Yпісля кожної інструкції. Кожна інструкція гарантовано припиняється, тому все спрацює. Але боляче записати.
Девід Річербі,

1
Я не зовсім впевнений, чи можна так деконструювати X, якщо він починається з певного циклу / умовно. Мені доведеться подумати над цим ще трохи.
Мартін Ендер

Також "Отже, зараз ми використовуємо цикл для повторення через вказівки X, використовуючи вказівник інструкцій тощо, щоб ми знали, яку команду виконувати далі". Я відчуваю, що це саме по собі може зажадати якогось умовного.
Мартін Ендер

1
Я все ще не зовсім впевнений, як ви визначаєте "кожну інструкцію", якщо X'вона нелінійна. Не хотіли б ви включити ще трохи деталей для простої, але нетривіальної іграшки X? Наприклад do (while A do B) while C? (зовнішнє do whileпоходить від зовнішнього, while doщо ми зараз перекладаємо)
Мартін Ендер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.