Я не на 100% впевнений, що це неможливо зробити за допомогою двох комплектів дужок. Однак, якщо комірки стрічки BF дозволяють без обмежених значень, достатньо трьох наборів дужок. (Для простоти я також припускаю, що ми можемо перемістити головку стрічки ліворуч від її початкової точки, хоча, оскільки ця конструкція використовує лише кінцеву область стрічки, ми могли б зняти це обмеження, додавши достатньо багато >
команд на початку програма.) Конструкція нижче вимагає припущення Артінавміти складати довільно великі програми; однак, навіть якщо думка Артіна помилкова, все одно можна буде показати Повноту Тюрінга побічно, переклавши інтерпретатора мови Тюрінга на BF, використовуючи конструкцію внизу, та запустивши довільні програми, подавши їх як вхід до цього перекладача.
Мова Тюрінга, яку ми складаємо в безмежну BF, - це модель водоспаду , яка є однією з найпростіших відомих обчислювальних моделей. Для людей, які цього ще не знають, він складається з декількох лічильників (і початкових значень для них) та функції від пар лічильників до цілих чисел; Виконання програми складається з багаторазового віднімання 1 з кожного лічильника, тоді якщо будь-який лічильник дорівнює 0, додавання до кожного лічильника (програма записується таким чином, що це ніколи не відбувається з кількома лічильниками одночасно). За моїм посиланням є доказ повноти Тьюрінга для цієї мови. Не втрачаючи загальності, ми будемо вважати, що всі лічильники мають однакове значення самозавантаження (тобтоfxf(x,y)yf(x,x) однаковий для всіх ); це безпечне припущення, оскільки для будь-якого конкретного додавання однакової константи до кожного не змінить поведінку програми.xxf(x,y)
Нехай - кількість лічильників; не втрачаючи загальності (припускаючи гіпотезу Артіна), припустимо, що має примітивний корінь 2. Нехай буде , де - найменша потужність на 2, більша за . Без втрати загальності буде менше ( обмежено поліноміально, зростає експоненціально, тому будь-який достатньо великий буде працювати).ppqp(1+s+s2)sp2q2p2q2pp
Розташування стрічки полягає в наступному: пронумеруємо кожен лічильник цілим числом (і без втрати загальності вважаємо, що існує один лічильник зупинки і пронумеруємо його ). Значення більшості лічильників зберігається на комірці стрічки , за винятком лічильника 0, який зберігається на клітинці стрічки . Для кожної комірки з непарними номерами стрічки від клітинки -1 до та включає0≤i<p22i2q2p+1+2p+1, ця клітинка стрічки завжди містить 1, крім випадків, коли вона знаходиться ліворуч від лічильника; у цьому випадку вона завжди містить 0. Яєчкові клітинки стрічки, які не використовуються як лічильники, мають невідповідні значення (які можуть бути, а можуть і не бути 0 ); і комірки стрічкового номера з непарними номерами поза вказаним діапазоном також мають неактуальні значення. Зауважте, що для встановлення стрічки у відповідний початковий стан потрібно ініціалізувати лише кінцево багато елементів стрічки до постійних значень, це означає, що ми можемо це зробити з послідовністю <>+-
інструкцій (насправді >+
вони потрібні лише ), тому дужки не мають. В кінці цієї ініціалізації переміщуємо покажчик стрічки на комірку -1.
Загальна форма нашої програми буде виглядати приблизно так:
ініціалізація коригування[>>>[
>
×(2p−1) [
<
×(2p) ]>-]
<<<]
Ініціалізація ставить стрічку в очікувану форму, а вказівник на клітинку -1. Це не клітинка зліва від лічильника (0 не є потужністю 2), тому вона має значення 1, і ми вводимо цикл. Інваріант циклу для цієї зовнішньої петлі полягає в тому, що вказівник стрічки (на початку та в кінці кожної ітерації циклу) три комірки зліва від лічильника; видно, що цикл вийде таким чином, лише якщо у нас три комірки зліва від лічильника 2 (у кожного лічильника є 1 три комірки ліворуч, а щоб мати 0, це означатиме, що позиції стрічки двох лічильників були 2 комірки один від одного; єдині дві потужності 2, які відрізняються на 2, є і , і бінарне представлення змінюється від рядків s до рядків2122q01s або навпаки, щонайменше чотири рази, і, отже, не можна бути віддаленим від потужності 2).
Друга петля багаторазово петлюється над лічильниками, зменшуючи їх. Інваріант циклу полягає в тому, що вказівник стрічки завжди вказує на лічильник; таким чином цикл вийде, коли деякий лічильник стане 0. Декремент справедливий -
; шлях, який ми переходимо від одного лічильника до іншого, є складнішим. Основна ідея полягає в тому, що переміщення пробілів праворуч від розмістить нас на осередку з непарною нумерацією , що знаходиться праворуч від будь-якого лічильника ( - останній лічильник, - позитивний, оскільки - позитивний); за модулем це значення відповідає (за малою теоремою Ферма) . Найпотужніша петля кілька разів переміщується вліво2p−12x2p+2x−12p2x−1x2p2x+12p пробіли, які також не змінюють індексу модуля комірки стрічки , і, зрештою, повинні знайти комірку конгруентною до модуля який має значення (яке буде клітинка зліва від деякого лічильника); через нашу первісну кореневу вимогу існує саме одна така клітинка ( є конгруентною до модуля , а відповідає для будь-якої інше , де - дискретний логарифм до основи 2 по модулю ). Додатково видно, що положення вказівника стрічки модуль2p2x+12p2q−1−12p2log2,p(r)+1−12r−1rlog2,pp2pзбільшується на рази кожен раз, округлюючи середню петлю. Таким чином, покажчик стрічки повинен переходити між усіма лічильниками (у порядку їх значень по модулю ). Таким чином, з кожними ітераціями ми зменшуємо кожен лічильник (як потрібно). Якщо цикл проривається частково через ітерацію, ми відновимо зменшення, коли повторно введемо цикл (оскільки решта зовнішньої петлі не змінює мережу в положення вказівника стрічки).2p2pp
Коли лічильник набиває 0, середній цикл розривається, переводячи нас до коду "коригування". Це в основному просто кодування ; для кожної пари він додає до елемента стрічки, який знаходиться на тій же відстані ліворуч / праворуч від поточного вказівника стрічки, що і розташування стрічки лічильника ліворуч / праворуч від лічильника 's розташування стрічки (а потім видаляє вказівник стрічки туди, де вона почалася). Щоразу, коли , ця відстань виявляється унікальною:f(x,y)f(x,y)yxx≠y
- Різниця між двома потужностями 2 - це двійкове число, що складається з рядка 1 або більше с, за яким слідує рядок 0 або більше с (зі значеннями місця початку початку числа і початку рядка , залежно від більших і менших відповідно і ); тому всі ці відмінності є чіткими. * Що стосується різниці потужності 2 і , вона повинна містити щонайменше два переходи між рядками с і с (100xyq10q містить щонайменше чотири таких переходи, віднімання може видалити лише 2), таким чином відрізняється від усіх відмінностей двох степенів двох, і ці відмінності, очевидно, також відрізняються один від одного.
Для ми, очевидно, знаходимо, що відстань, яку перемістили, дорівнює 0. Але оскільки всі рівні, ми можемо просто використовувати це як коригування для поточної комірки. І видно, що код коригування таким чином реалізує ефект "коли лічильник б'є 0" для кожного лічильника; всі комірки, які насправді представляють лічильники, будуть скориговані на правильну кількість, а всі інші коригування впливатимуть на безлічинні парні комірки (різниця між двома парними числами є парними), які не впливають на поведінку програми.x=yf(x,y)
Таким чином, тепер ми маємо робочу компіляцію будь-якої програми в моделі Водоспад до BF (включаючи поведінку зупинки, але не включаючи введення-виведення, яке не потрібно для повноти Тьюрінга), використовуючи лише три пари дужок, і, отже, три пари дужок достатньо для Тюрінга-повноти.