Чи можливо вирішити проблему зупинки, якщо у вас обмежений або передбачуваний вклад?


18

Проблема зупинки не може бути вирішена в загальному випадку. Можна створити визначені правила, які обмежують дозволені введення даних, і чи можна вирішити проблему зупинки для цього особливого випадку?

Наприклад, мабуть, мовою, яка, наприклад, не дозволяє циклів, було б дуже легко сказати, зупиняється чи ні програма.

Проблема, яку я зараз намагаюся вирішити, полягає в тому, що я намагаюся зробити перевірку скриптів, яка перевіряє чинність програми. Чи можна вирішити проблему зупинки, якщо я точно знаю, чого очікувати від авторів сценаріїв, тобто дуже передбачувані матеріали. Якщо це неможливо вирішити точно, які хороші методи наближення можуть вирішити це?

Відповіді:


10

Інтуїтивна відповідь полягає в тому, що якщо у вас немає безмежних циклів і у вас немає рекурсії і у вас немає goto, ваші програми припиняються. Це не зовсім вірно, є й інші способи прокрадання неприпинення, але це досить добре для більшості практичних випадків. Звичайно, навпаки невірно, є мови з цими конструкціями, які не дозволяють не закінчувати програми, але вони використовують інші види обмежень, такі як системи складних типів.

Рекурсія

Поширене обмеження в мовах сценаріїв полягає в динамічному запобіганні рекурсії: якщо A дзвінки B викликає C дзвінки ... дзвінки A, то перекладач (або перевіряючий у вашому випадку) відмовляється або сигналізує про помилку, навіть якщо рекурсія може фактично закінчитися. Два конкретні приклади:

  • Препроцесор C залишає макрос недоторканим, коли він розширює цей макрос. Найбільш поширене використання - це визначення обгортки навколо функції:

    #define f(x) (printf("calling f(%d)\n", (x)), f(x))
    f(3);
    

    Це розширюється до

    (printf("calling f(%d)\n", (3)), f(3))
    

    Також обробляється взаємна рекурсія. Наслідком цього є те, що препроцесор C завжди припиняється, хоча можна створити макроси з високою складністю виконання.

    #define f0(x) x(x)x(x)
    #define f1(x) f0(f0(x))
    #define f2(x) f1(f1(x))
    #define f3(x) f2(f2(x))
    f3(x)
    
  • Оболонки Unix розширюють псевдоніми рекурсивно, але лише до тих пір, поки вони не зустрінуться з псевдонімом, який вже розгортається. Знову ж таки, головна мета - визначити псевдонім для аналогічно названої команди.

    alias ls='ls --color'
    alias ll='ls -l'
    

Очевидне узагальнення полягає в тому, щоб дозволити глибину рекурсії до , з можливо можливо налаштувати.нн

Існують більш загальні методи доказування припинення рекурсивних викликів, таких як пошук деякого додатного цілого числа, яке завжди зменшується від одного рекурсивного виклику до іншого, але їх виявити значно складніше. Їх часто важко перевірити, не кажучи вже про висновки.

Петлі

Цикли закінчуються, якщо ви можете зв'язати кількість ітерацій. Найпоширенішим критерієм є те, що якщо у вас є forцикл (без хитрощів, тобто такий, який дійсно рахується від до ), він виконує обмежену кількість ітерацій. Отже, якщо тіло петлі припиняється, петля сама припиняється.мн

Зокрема, за допомогою циклів (плюс розумні конструкції мови, такі як умовні умови), ви можете записати всі примітивні рекурсивні функції , і навпаки. Ви можете розпізнати примітивні рекурсивні функції синтаксично (якщо вони написані безперешкодно), тому що вони не використовують цикл, ані гото, ані рекурсію чи інший трюк. Примітивні рекурсивні функції гарантовано припиняються, і більшість практичних завдань не виходять за рамки примітивної рекурсії.


4

Див. Термінатор та AProVe . Вони, як правило, покладаються на евристику, і я не впевнений, чи чітко вони описують клас програм, над якими вони працюють. Тим не менш, вони розглядаються як найсучасніші, тому вони повинні стати хорошими відправними точками для вас.


4

Так, це можливо. Одним із поширених способів вирішення таких завдань є розгляд додаткового (монотонного) незмінного параметра залежно від коду як частини введення. Складність проблеми, що має цей параметр, може бути значно зменшена.

Ми не можемо обчислити параметр, але якщо ви знаєте, що вхідні екземпляри, з якими ви маєте справу, мають невеликі значення параметрів, ви можете виправити його до невеликої кількості та скористатися алгоритмом.

Цей та подібні хитрощі використовуються у формальних методах для вирішення невідповідності зупинки та подібних проблем. Але якщо те, що ви хочете вирішити, є складним, складність ваших алгоритмів навряд чи буде кращою, ніж запуск алгоритму на цих екземплярах.

Що стосується іншого питання, якщо ви обмежите введення достатньо, то проблема зупинки може бути легкою. Наприклад, якщо ви знаєте, що вхідні дані є алгоритмами багаточленного часу, вирішення проблеми зупинки для них є тривіальною (оскільки кожен алгоритм багаточленного часу зупиняється).

Проблеми, що виникають у формальних методах, як правило, не можна вирішити, можливо, ви захочете перевірити літературу про те, як вони реалізують ці проблеми на практиці.


4

Не формально жорстка відповідь, але ось це:

Проблема у визначенні того, чи вона зупиняється чи циклічно назавжди. Замикання на кінцевих колекціях один за одним або між інтервалом чисел нормально. EDIT: Очевидно, це спрацює лише в тому випадку, якщо ітераційне збирання або інтервал забороняються змінювати (наприклад, за незмінності) під час його повторення (або, принаймні, заборонено рости).

Рекурсія, ймовірно, не нормальна, якщо тільки ви не встановите штучне правило, щоб зробити її обмеженою, наприклад, дозволити максимальну глибину стеку або змусити зменшення негативного параметра в кожній ітерації.

Довільні готи, як правило, погані. Назад-готи, дуже ймовірно, призводять до циклів, які можуть бути нескінченними.

Заяви про китів і хитрощів є проблемою, оскільки вони залежать від умови, яка не гарантується змінюватись або не під час виконання. Можливий (але, мабуть, дуже незадовільний) спосіб обмеження - це надання максимальної кількості можливих ітерацій.


2

Вам потрібно надати визначення мови вашого сценарію, і що ви розумієте під "очікуванням" від сценаріїв.

О(нω)

Аналогічний результат є для класу поліноміальної програми Аарона Р. Бредлі, Зохара Манна та Генні Б. Сіпми. Але AFAIK (я можу помилятися тут) час виконання є подвійним експоненціальним (по суті, час, необхідний для обчислення бази Грюбнера).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.