Участник:Shersh/Теорема о рекурсии — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м
(Пример использования)
 
(не показано 5 промежуточных версий 3 участников)
Строка 1: Строка 1:
 +
По [[Теорема о рекурсии | теореме о рекурсии]], программа может знать свой исходный код. Значит, в неё можно написать функцию <tex> \mathrm{getSrc()} </tex>, которая вернёт строку {{---}} исходный код программы. Далее будем считать, что такая функция определена в каждой программе.
 
== Неразрешимость универсального языка ==
 
== Неразрешимость универсального языка ==
 
{{Утверждение
 
{{Утверждение
Строка 7: Строка 8:
 
<code>
 
<code>
 
   p(x):
 
   p(x):
     '''if''' u(p, x) // можем так написать, потому что по теореме о рекурсии программа может знать свой код
+
     '''if''' u(getSrc(), x)
 
       '''while''' ''true''
 
       '''while''' ''true''
 
     '''else'''
 
     '''else'''
Строка 24: Строка 25:
 
<tex> L_A </tex> {{---}} множество программ, удовлетворяющих св-ву <tex> A </tex>.
 
<tex> L_A </tex> {{---}} множество программ, удовлетворяющих св-ву <tex> A </tex>.
  
Допустим, что пустой язык <tex> \varnothing </tex> принадлежит семейству <tex> A </tex>. Если это не так, то мы можем перейти к рассмотрению дополнения семейства: к <tex> \overline{A} </tex>. К тому же, так как свойство <tex> A </tex> нетривиальное, то его дополнение содержит какой-то перечислимый язык. Пусть <tex> q </tex> {{---}} полуразрешитель какого-то фиксированного непустого языка из <tex> \overline{A} </tex>, то есть <tex> q \notin L_A </tex>. Тогда напишем такую программу:
+
Теперь допустим, что язык <tex> L_A </tex> разрешим. Тогда напишем такую программу:
  
 
<code>
 
<code>
 +
  propA(code):
 +
    // программа, разрешающее свойство языка <tex> A </tex>
 +
  f(x):
 +
    // такая программа <tex> f </tex>, что <tex>f \in A </tex>; существует потому что <tex> A </tex> {{---}} нетривиальное свойство
 +
  g(x):
 +
    // такая программа <tex> g </tex>, что <tex>g \notin A </tex>; существует потому что <tex> A </tex> {{---}} нетривиальное свойство
 
   p(x):
 
   p(x):
     '''if''' p <tex> \in ~ L_A </tex> // можем так написать, потому что по предположению <tex> L_A </tex> {{---}} разрешимый
+
     '''if''' propA(getSrc())
      '''return''' q(x)
+
        '''return''' g(x)
 
     '''else'''
 
     '''else'''
      '''while''' ''true''
+
        '''return''' f(x)
 
</code>
 
</code>
  
Если <tex> p </tex> не удовлетворяет свойству <tex> A </tex>, тогда будет выполняться всегда вторая ветка, и <tex> p \equiv \varnothing </tex>. Но пустой язык принадлежит <tex> A </tex>. Получили противоречие.
+
Если <tex> p </tex> не удовлетворяет свойству <tex> A </tex>, тогда будет выполняться всегда вторая ветка, и <tex> L(p) = L(f) </tex>. Но язык программы <tex> f </tex> принадлежит <tex> A </tex>. Получили противоречие.
  
Если <tex> p </tex> удовлетворяет свойству <tex> A </tex>, то <tex> L(p) = L(q) </tex>, а <tex> q \notin A </tex>. Опять получили противоречие.
+
Если <tex> p </tex> удовлетворяет свойству <tex> A </tex>, то <tex> L(p) = L(g) </tex>, а <tex> g \notin A </tex>. Опять получили противоречие.
 
== Колмогоровская сложность ==
 
== Колмогоровская сложность ==
 
{{Определение
 
{{Определение
Строка 78: Строка 85:
 
<code>
 
<code>
 
   p():
 
   p():
     '''for''' i = 1..BB(<tex>|p|</tex>) + 1
+
     '''for''' i = 1..BB(<tex>|\mathrm{getSrc()}|</tex>) + 1
 
       do smth
 
       do smth
 
</code>
 
</code>
Строка 94: Строка 101:
 
Можно переформулировать теорему следующим образом: невозможно доказать, что <tex> p(x) = \perp </tex>.
 
Можно переформулировать теорему следующим образом: невозможно доказать, что <tex> p(x) = \perp </tex>.
  
Тогда напишем такую программу:
+
Таким образом напишем такую программу:
 
<code>
 
<code>
 
   p(x):
 
   p(x):
Строка 102: Строка 109:
 
</code>
 
</code>
 
}}
 
}}
 +
 
== Теорема о неподвижной точке ==
 
== Теорема о неподвижной точке ==
Зафиксируем главную нумерацию <tex> W </tex>. Обозначим за <tex> W_n </tex> множество слов, допускаемых программой с номером <tex> n </tex>.
+
Зафиксируем [[Главные нумерации | главную нумерацию]] <tex> W </tex>. Обозначим за <tex> W_n </tex> множество слов, допускаемых программой с номером <tex> n </tex>.
 
{{Утверждение
 
{{Утверждение
 
|id=идентификатор (необязательно), пример: proposalF.  
 
|id=идентификатор (необязательно), пример: proposalF.  
Строка 111: Строка 119:
 
<code>
 
<code>
 
   p(q):
 
   p(q):
     '''if''' p == q // сравниваем как строки; так можно сделать, потому что программа знает свой код по теореме о рекурсии
+
     '''if''' p.getSrc() == q.getSrc()
       print number(p)
+
       '''return''' 1
 
     '''else'''
 
     '''else'''
 
       '''while''' ''true''
 
       '''while''' ''true''

Текущая версия на 23:56, 2 января 2017

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

Неразрешимость универсального языка

Утверждение:
[math]\triangleright[/math]

Допустим, что он разрешим. Тогда напишем такую программу:

 p(x):
   if u(getSrc(), x)
     while true
   else
     return 1

Если [math] u(p, x) = 1 [/math], тогда программа [math] p [/math] на входе [math] x [/math] должна вернуть [math] 1 [/math], но по условию [math] if [/math] она зависает, а следовательно, не принадлежит универсальному языку.

Если же [math] u(p, x) \neq 1 [/math], то мы пойдём во вторую ветку условного оператора и вернём [math] 1 [/math], значит, пара [math] \langle p, x \rangle [/math] принадлежит универсальному языку, но [math] u(p, x) \neq 1 [/math], значит, пара не принадлежит. Опять получили противоречие.
[math]\triangleleft[/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]. Опять получили противоречие.

Колмогоровская сложность

Определение:
Колмогоровской сложностью строки [math] x [/math] называется функция [math] K(x) [/math], которая равна минимальной длине программы [math] p : p(\varepsilon) = x [/math].

Сложность считается в каком-то фиксированном языке программирования. Так, например, у языков C++ и Python будет разная колмогоровская сложность одной программы.

Пример

Колмогоровская сложность программы, выводящей [math] n [/math] нулей [math] K(0^n) \leqslant n + c [/math]. Просто программа, в которой записано [math] n [/math] нулей. Но можно записать и более короткую программу для больших [math] n [/math] со сложностью [math] K(0^n) \leqslant \log{n} + c [/math], например вот такую:

 [math]p_n[/math]():
   for i = 1..n
     print(0)

Теорема (Невычислимость Колмогоровской сложности):
Колмогоровская сложность — невычислимая функция.
Доказательство:
[math]\triangleright[/math]

[math] \forall x \gt x_0: K(x) \gt f(x)[/math], если только [math]f \leqslant const [/math] или [math] f [/math] — невычислима.

Допустим, что [math] K [/math] вычислима, тогда напишем такую программу:

 p([math]\varepsilon[/math]):
   foreach x [math]\in ~ \Sigma^* [/math] // перебираем слова по возрастанию длины
     if [math] K(x) \gt  |p|[/math] // теорема о рекурсии используется здесь
       print(x)
       exit     

Начиная с [math] x_0 [/math], [math] f(x) \gt |p| [/math].
[math]\triangleleft[/math]

Busy beaver

Утверждение:
Функция Busy beaver невычислима.
[math]\triangleright[/math]

Предположим, что это не так. Тогда напишем такую программу

 p():
   for i = 1..BB([math]|\mathrm{getSrc()}|[/math]) + 1
     do smth

Такая программа всегда совершает больше шагов, чем функция [math] BB [/math] от этой программы. А это невозможно, так [math] BB(|p|) [/math] равна максимальному числу шагов как раз этой программы. Получили противоречие.
[math]\triangleleft[/math]

Аналог I теоремы Гёделя о неполноте

Теорема:
В любой "достаточно богатой системе" существует истинное недоказуемое утверждение.
Доказательство:
[math]\triangleright[/math]

Поясним, что это значит. Так как любой язык программирования эквивалентен машине Тьюринга, то всё связанное с ним кодируется в логике первого порядка с аксиомами Пеано (для этого достаточно, чтобы программа умела прибавлять к числу единицу и вызывать подпрограммы), поэтому можно в терминах программ получать утверждения, эквивалентные тем, что строил Гёдель.

Можно переформулировать теорему следующим образом: невозможно доказать, что [math] p(x) = \perp [/math].

Таким образом напишем такую программу:

 p(x):
   foreach q [math] \in ~ \Sigma^* [/math]
     if q proves "p(x) зависает"
       exit    
[math]\triangleleft[/math]

Теорема о неподвижной точке

Зафиксируем главную нумерацию [math] W [/math]. Обозначим за [math] W_n [/math] множество слов, допускаемых программой с номером [math] n [/math].

Утверждение:
[math] \exists n : W_n = \{n\} [/math]
[math]\triangleright[/math]

Напишем такую программу:

 p(q):
   if p.getSrc() == q.getSrc()
     return 1
   else
     while true

Программа [math] p [/math] знает свой код, что то же самое, что и знает свой номер. Как видно из её кода, она допускает только одно число — свой номер.
[math]\triangleleft[/math]

Ссылки