Свойства перечислимых языков. Теорема Успенского-Райса

Материал из Викиконспекты
Версия от 00:08, 26 декабря 2016; ExileHell (обсуждение | вклад) (Альтернативное доказательство с использованием теоремы о рекурсии)
Перейти к: навигация, поиск

Свойства языков

Рассмотрим множество всех перечислимых языков [math] \mathrm {RE} [/math].

Определение:
Свойством языков (англ. property of languages) называется множество [math] A \subset \mathrm {RE} [/math].


Определение:
Свойство называется тривиальным (англ. trivial), если [math] A = \varnothing [/math] или [math] A = \mathrm {RE} [/math].


Определение:
Язык свойства (англ. language of property) [math] A [/math] — множество программ, языки которых обладают этим свойством: [math]L(A) \overset{\underset{\mathrm{def}}{}}{=} \lbrace p \mid L(p) \in A \rbrace [/math].


Отметим, что принадлежность программы [math]p[/math] языку свойства [math]A[/math] можно выразить двумя эквивалентными утверждениями:

[math]L(p) \in A[/math]
[math]p \in L(A)[/math]

Далее в конспекте будет употребляться [math]p \in L(A)[/math].


Определение:
Свойство [math] A [/math] называется разрешимым (англ. recursive), если [math]L(A) [/math] является разрешимым.

Примеры

Примеры свойств:

  1. Язык должен содержать слово hello.
  2. Язык должен содержать хотя бы одно простое число.

Псевдокод для разрешителя [math]L(A)[/math], где [math]A = \mathrm {RE}: [/math]

[math]p_A(p_X)[/math]  // [math]p_X[/math] — полуразрешитель некоторого языка
  return true

Псевдокод для программы в общем случае, то есть для проверки того, что язык удовлетворяет свойству :

[math]p_A(p_X)[/math] 
  return [math]p_X \in L(A)[/math]

Псевдокод полуразрешителя для языка свойства из первого примера:

[math]p_A(p_X)[/math]  // [math]X[/math] — перечислимый язык в общем случае, поэтому [math]p_A[/math] — полуразрешитель (по теореме Райса-Шапиро)
  return [math]p_X[/math]('hello')

Теорема Успенского-Райса

Теорема:
Язык никакого нетривиального свойства [math]A[/math] не является разрешимым.

Доказательство

Пусть [math]p_\infty[/math] — всегда зацикливающийся алгоритм.

Рассмотрим случай, когда [math]p_\infty \in L(A)[/math].

Приведём доказательство от противного. Предположим, что [math]A[/math] разрешимо.

Рассмотрим язык [math]S[/math], такой что [math] S \in \overline{A}[/math] (такой язык существует, так как [math]A[/math] — нетривиально). Тогда [math]p_S \in L(\overline{A})[/math].

Рассмотрим также произвольное перечислимое неразрешимое множество [math]X[/math]. Пусть [math]p_X(n)[/math] — полуразрешитель [math]X[/math].

Зафиксируем произвольное [math]n \in \mathbb{N}[/math] и построим следующую функцию [math]V_n(x) = \begin{cases} p_S(x), n \in X \\ p_\infty(x), n \notin X \\ \end{cases} [/math]

function [math]V_n[/math](x):
  if [math]p_X[/math](n) == 1
    return [math]p_S[/math](x)
  while true

Получили, что если [math]n \in X[/math], то [math]V_n \in L(\overline A)[/math], а если [math]n \notin X[/math], то [math]V_n \in L(A)[/math]. Таким образом, [math]n \in X \iff V_n \in L(\overline A)[/math].

Так как [math]\overline A[/math] — разрешимо, то можно проверить для любого [math]V_n[/math], лежит ли оно в [math]L(\overline{A})[/math]. Но это тоже самое, что и проверка [math]n \in X[/math]. Тогда можно для каждого [math]n[/math] проверить, лежит ли оно в [math]X[/math], а следовательно и построить разрешитель для [math]X[/math]. Так как [math]X[/math] — неразрешимо, получили противоречие.

Теперь рассмотрим случай, когда [math]p_\infty \in L(\overline{A})[/math].

Так как [math]\overline{A}[/math] — нетривиально (как дополнение к нетривиальному множеству), то по первой части доказательства оно неразрешимо. Следовательно, [math]A[/math] также неразрешимо.

Альтернативное доказательство с использованием теоремы о рекурсии

По теореме о рекурсии, программа может знать свой исходный код. Значит, в неё можно написать функцию [math] \mathrm{getSrc()} [/math], которая вернёт строку — исходный код программы.

[math] A [/math] — разрешимое семейство языков.

[math] L_A [/math] — множество программ, удовлетворяющих св-ву [math] A [/math].

Теперь допустим, что язык [math] L_A [/math] разрешим. Тогда напишем такую программу:

 propA(code):
   // программа, разрешающее свойство языка [math] A [/math]
 f(x):
   // такая программа [math] f [/math], что [math]f \in A [/math]; существует потому что [math] A [/math] — нетривиальное свойство
 g(x):
   // такая программа [math] g [/math], что [math]g \notin A [/math]; существует потому что [math] A [/math] — нетривиальное свойство 
 p(x):
   if propA(getSrc())
       return g(x)
   else
       return f(x)

Если [math] p [/math] не удовлетворяет свойству [math] A [/math], тогда будет выполняться всегда вторая ветка, и [math] L(p) = L(f) [/math]. Но язык программы [math] f [/math] принадлежит [math] A [/math]. Получили противоречие.

Если [math] p [/math] удовлетворяет свойству [math] A [/math], то [math] L(p) = L(g) [/math], а [math] g \notin A [/math]. Опять получили противоречие.

См. также

Источники информации

  • Wikipedia — Rice's theorem
  • Rice, H. G. — Classes of Recursively Enumerable Sets and Their Decision Problems." — Trans. Amer. Math. Soc. 74, 358-366, 1953.
  • Хопкрофт Д., Мотванн Р., Ульманн Д. —Введение в теорию автоматов, языков и вычислений — стр. 397.