Функция Аккермана: различия между версиями

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
[отпатрулированная версия][непроверенная версия]
Содержимое удалено Содержимое добавлено
У меня не получается нормально добавить программу вычисления функции на Pascal'е (текст разбивается на части).
Нет описания правки
Строка 1: Строка 1:
'''Функция Аккермана''' — простой пример [[Вычислимая функция|вычислимой функции]], которая не является [[Примитивно рекурсивная функция|примитивно рекурсивной]]. Она принимает два неотрицательных [[Целое число|целых числа]] в качестве параметров и возвращает [[натуральное число]], обозначается <math>A(m,\;n)</math>. Эта функция растёт очень быстро, например, число <math>A(4,\;4)</math> настолько велико, что количество цифр в порядке этого числа многократно превосходит количество атомов в наблюдаемой части Вселенной.
'''Функция Аккермана''' — простой пример [[Вычислимая функция|вычислимой функции]], которая не является [[Примитивно рекурсивная функция|примитивно рекурсивной]]. Она принимает два неотрицательных [[Целое число|целых числа]] в качестве параметров и возвращает [[натуральное число]], обозначается <math>A(m,\;n)</math>. Эта функция растёт очень быстро, например, число <math>A(4,\;4)</math> настолько велико, что количество цифр в порядке этого числа многократно превосходит количество атомов в наблюдаемой части Вселенной.

==История==
В конце 20-х годов XX века математики-ученики [[Гильберт, Давид|Давида Гильберта]] [[Судан, Габриэль|Габриэль Судан]] и [[Аккерман, Вильгельм|Вильгельм Аккерман]] изучали основы вычислений. Судан и Аккерман известны<ref>{{cite journal | author=Cristian Calude, Solomon Marcus and Ionel Tevy | journal = Historia Math. | title=The first example of a recursive function which is not primitive recursive | month=November | year=1979 | pages=380–84 | volume=6 | issue=4 | doi=10.1016/0315-0860(79)90024-7}}</ref> за открытие всюду определенной [[вычислимая функция|вычислимой]] (иногда называемой просто "рекурсивной"), не являющейся [[Примитивно рекурсивная функция|примитивно рекурсивной]]. Судан открыл менее известную [[функция Судана|функцию Судана]], после чего, независимо от него, в 1928 Аккерман опубликовал его функцию <math>\varphi\,\!</math>. Функция трех аргументов Аккермана <math>\varphi(m, n, p)\,\!</math> определялась так, что для ''p'' = 0, 1, 2, она проводила операцию сложения, умножения или возведения в степень:
:<math>\varphi(m, n, 0) = m+n,\,\!</math>
:<math>\varphi(m, n, 1) = m\cdot n,\,\!</math>
:<math>\varphi(m, n, 2) = m^n,\,\!</math>
а для ''p'' > 2 она доопределяется с помощью [[Стрелочная нотация Кнута|стрелочной нотации Кнута]]:
:<math>\varphi(m, n, p) = m\uparrow^{p - 1}(n + 1)\,\!</math>.
(Помимо её исторической роли как первой всюду определенной не примитивно рекурсивной вычислимой функции, оригинальная функция Аккермана расширяла основные арифметические операции за возведение в степень, хотя и не так хорошо, как специально предназначенные для этого функции вроде последовательности [[гипероператор|гипероператоров]] [[Гудстейн, Рубен|Гудстейна]].)

В статье ''On the Infinite'' Гильберт высказал гипотезу, что функция Аккермана не является примитивно рекурсивной, и Аккерман (личный секретарь и бывший студент Гильберта) доказал эту гипотезу в статье ''On Hilbert’s Construction of the Real Numbers''. [[Роза Петер]] и [[Рафаэль Робинсон]] позже представили двухаргументную версию функции Аккермана, которую теперь многие авторы предпочитают оригинальной.<ref>{{cite journal | author=Raphael M. Robinson | title=Recursion and Double Recursion | journal=[[Bulletin of the American Mathematical Society]] | year=1948 | volume=54 | pages=987-993 | url=http://projecteuclid.org/DPubS?verb=Display&version=1.0&service=UI&handle=euclid.bams/1183512393&page=record | doi=10.1090/S0002-9904-1948-09121-2 | issue=10}}</ref>


== Определение ==
== Определение ==
Функция [[Аккерман, Вильгельм|Аккермана]] определяется [[Рекурсия|рекурсивно]] для неотрицательных целых чисел <math>m</math> и <math>n</math> следующим образом:
Функция Аккермана определяется [[Рекурсия|рекурсивно]] для неотрицательных целых чисел <math>m</math> и <math>n</math> следующим образом:
: <math>A(m,\;n)=\begin{cases}n+1,&m=0;\\A(m-1,\;1),&m>0,\;n=0;\\A(m-1,\;A(m,\;n-1)),&m>0,\;n>0.\end{cases}</math>
: <math>A(m,\;n)=\begin{cases}n+1,&m=0;\\A(m-1,\;1),&m>0,\;n=0;\\A(m-1,\;A(m,\;n-1)),&m>0,\;n>0.\end{cases}</math>
Может показаться неочевидным, что рекурсия всегда заканчивается. Это следует из того, что при рекурсивном вызове или уменьшается значение <math>m</math>, или значение <math>m</math> сохраняется, но уменьшается значение <math>n</math>. Это означает, что каждый раз пара <math>(m,\;n)</math> уменьшается с точки зрения [[Лексикографический порядок|лексикографического порядка]], значит, значение <math>m</math> в итоге достигнет нуля: для одного значения <math>m</math> существует конечное число возможных значений <math>n</math> (так как первый вызов с данным <math>m</math> был произведён с каким-то определённым значением <math>n</math>, а в дальнейшем, если значение <math>m</math> сохраняется, значение <math>n</math> может только уменьшаться), а количество возможных значений <math>m</math>, в свою очередь, тоже конечно. Однако, при уменьшении <math>m</math> значение, на которое увеличивается <math>n</math>, неограничено и обычно очень велико.
Может показаться неочевидным, что рекурсия всегда заканчивается. Это следует из того, что при рекурсивном вызове или уменьшается значение <math>m</math>, или значение <math>m</math> сохраняется, но уменьшается значение <math>n</math>. Это означает, что каждый раз пара <math>(m,\;n)</math> уменьшается с точки зрения [[Лексикографический порядок|лексикографического порядка]], значит, значение <math>m</math> в итоге достигнет нуля: для одного значения <math>m</math> существует конечное число возможных значений <math>n</math> (так как первый вызов с данным <math>m</math> был произведён с каким-то определённым значением <math>n</math>, а в дальнейшем, если значение <math>m</math> сохраняется, значение <math>n</math> может только уменьшаться), а количество возможных значений <math>m</math>, в свою очередь, тоже конечно. Однако, при уменьшении <math>m</math> значение, на которое увеличивается <math>n</math>, неограничено и обычно очень велико.
Строка 85: Строка 96:


== Обратная функция ==
== Обратная функция ==
Так как функция <math>f(n)=A(n,\;n)</math> растёт очень быстро, обратная функция <math>f^{-1}(n)=\min\{k\geqslant 1:A(k,\;k)\geqslant n\}</math>, обозначаемая α, растёт очень медленно. Эта функция встречается при исследовании [[Теория сложности вычислений|сложности]] некоторых [[алгоритм]]ов, например, [[система непересекающихся множеств|системы непересекающихся множеств]] или алгоритма Чазелла для построения [[минимальное остовное дерево|минимального остовного дерева]]<ref>[http://rain.ifmo.ru/cat/view.php/theory/graph-spanning-trees/mst-2006 Дискретная математика: алгоритмы. Минимальные остовные деревья]</ref>. При [[Анализ алгоритмов|анализе]] [[Асимптотическая оценка|асимптотики]] можно считать, что для всех практически встречающихся чисел значение этой функции меньше пяти, так как A(4,&nbsp;4) одного порядка с <math>2^{2^{10^{19729}}}</math>.

==Использование в [[Бенчмарк (компьютер)|бенчмарках]]==
Функция Аккермана в силу своего определения имеет очень глубокий уровень рекурсии, что можно использовать для проверки способности [[компилятор]]а оптимизировать рекурсию. Первым функцию Аккермана для этого использовал Ингви Сандблад <ref>{{cite journal | author=Y. Sundblad | title=The Ackermann function, A theoretical, computational and formula manipulative study | journal=BIT | year=1971 | volume=11 | pages=107–119 | url=http://www.springerlink.com/content/t0701h82385w7718/ | doi=10.1007/BF01935330}}</ref>.

Брайан Вичман (соавтор бенчмарка [[Whetstone]]) учел эту статью при написании серии статей о тестировании оптимизации вызовов <ref>{{cite web | title=Ackermann's Function: A Study In The Efficiency Of Calling Procedures | year=1975 | url=http://history.dcs.ed.ac.uk/archive/docs/Imp_Benchmarks/ack.pdf}}</ref><ref>{{cite web | title=How to Call Procedures, or Second Thoughts on Ackermann's Function | year=1977 | url=http://history.dcs.ed.ac.uk/archive/docs/Imp_Benchmarks/ackpe.pdf}}</ref><ref>{{cite web | title=Latest results from the procedure calling test, Ackermann's function | year=1982 | url=http://history.dcs.ed.ac.uk/archive/docs/Imp_Benchmarks/acklt.pdf}}</ref>.

Например, компилятор, который анализируя вычисление ''A''(3,&nbsp;30) способен сохранять промежуточные значения вроде ''A''(3,&nbsp;''n'') и ''A''(2,&nbsp;''n''), может ускорить вычисление ''A''(3,&nbsp;30) в сотни и тысячи раз. Также вычисление ''A''(2,&nbsp;''n'') напрямую вместо рекурсивного раскрытия в ''A''(1,&nbsp;''A''(1,&nbsp;''A''(1,...''A''(1,&nbsp;0)...))) прилично ускорит вычисление. Вычисление ''A''(1,&nbsp;''n'') занимает линейное время ''n''. Вычисленние ''A''(2,&nbsp;''n'') требует квадратичное время, т.к. оно раскрывается в [[O большое|O]](''n'') вложенных вызовов ''A''(1,&nbsp;''i'') для различных ''i''. Вычисление ''A''(3,&nbsp;''n'') требует времени пропорционально 4<sup>''n''+1</sup>.

''A''(4,&nbsp;2) невозможно посчитать с помощью простого рекурсивного применения за разумное время. Вместо этого для оптимизации рекурсивных вызовов используются сокращенные формулы вроде ''A''(3,&nbsp;''n'') = 8×2<sup>''n''</sup>−3.

Один из практичных способов вычисления значений функции Аккермана - [[Мемоизация]] промежуточных результатов. Компилятор может применить эту технику к функции автоматически, используя memo functions <ref name="Michie1968">Michie, Donald, "Memo Functions and Machine Learning," ''Nature'', No. 218, pp. 19–22, 1968.</ref><ref>[http://www.gtoal.com/plsql/ackerman-memo.pls.html Example: Explicit memo function version of Ackermann's function] implemented in PL/SQL</ref> Дональда Мичи.



== Примечания ==
Так как функция <math>f(n)=A(n,\;n)</math> растёт очень быстро, обратная функция <math>f^{-1}(n)=\min\{k\geqslant 1:A(k,\;k)\geqslant n\}</math> растёт очень медленно. Эта функция встречается при исследовании [[Теория сложности вычислений|сложности]] некоторых [[алгоритм]]ов. Так как для всех практически встречающихся чисел значение этой функции меньше пяти, при [[Анализ алгоритмов|анализе]] [[Асимптотическая оценка|асимптотики]] алгоритмов можно принять её за константу.
<references/>


== Ссылки ==
== Ссылки ==

Версия от 15:24, 13 августа 2011

Функция Аккермана — простой пример вычислимой функции, которая не является примитивно рекурсивной. Она принимает два неотрицательных целых числа в качестве параметров и возвращает натуральное число, обозначается . Эта функция растёт очень быстро, например, число настолько велико, что количество цифр в порядке этого числа многократно превосходит количество атомов в наблюдаемой части Вселенной.

История

В конце 20-х годов XX века математики-ученики Давида Гильберта Габриэль Судан и Вильгельм Аккерман изучали основы вычислений. Судан и Аккерман известны[1] за открытие всюду определенной вычислимой (иногда называемой просто "рекурсивной"), не являющейся примитивно рекурсивной. Судан открыл менее известную функцию Судана, после чего, независимо от него, в 1928 Аккерман опубликовал его функцию . Функция трех аргументов Аккермана определялась так, что для p = 0, 1, 2, она проводила операцию сложения, умножения или возведения в степень:

а для p > 2 она доопределяется с помощью стрелочной нотации Кнута:

.

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

В статье On the Infinite Гильберт высказал гипотезу, что функция Аккермана не является примитивно рекурсивной, и Аккерман (личный секретарь и бывший студент Гильберта) доказал эту гипотезу в статье On Hilbert’s Construction of the Real Numbers. Роза Петер и Рафаэль Робинсон позже представили двухаргументную версию функции Аккермана, которую теперь многие авторы предпочитают оригинальной.[2]

Определение

Функция Аккермана определяется рекурсивно для неотрицательных целых чисел и следующим образом:

Может показаться неочевидным, что рекурсия всегда заканчивается. Это следует из того, что при рекурсивном вызове или уменьшается значение , или значение сохраняется, но уменьшается значение . Это означает, что каждый раз пара уменьшается с точки зрения лексикографического порядка, значит, значение в итоге достигнет нуля: для одного значения существует конечное число возможных значений (так как первый вызов с данным был произведён с каким-то определённым значением , а в дальнейшем, если значение сохраняется, значение может только уменьшаться), а количество возможных значений , в свою очередь, тоже конечно. Однако, при уменьшении значение, на которое увеличивается , неограничено и обычно очень велико.

Таблица значений

Подробнее о hyper см Гипероператор
\
(всего блоков )

Обратная функция

Так как функция растёт очень быстро, обратная функция , обозначаемая α, растёт очень медленно. Эта функция встречается при исследовании сложности некоторых алгоритмов, например, системы непересекающихся множеств или алгоритма Чазелла для построения минимального остовного дерева[3]. При анализе асимптотики можно считать, что для всех практически встречающихся чисел значение этой функции меньше пяти, так как A(4, 4) одного порядка с .

Использование в бенчмарках

Функция Аккермана в силу своего определения имеет очень глубокий уровень рекурсии, что можно использовать для проверки способности компилятора оптимизировать рекурсию. Первым функцию Аккермана для этого использовал Ингви Сандблад [4].

Брайан Вичман (соавтор бенчмарка Whetstone) учел эту статью при написании серии статей о тестировании оптимизации вызовов [5][6][7].

Например, компилятор, который анализируя вычисление A(3, 30) способен сохранять промежуточные значения вроде A(3, n) и A(2, n), может ускорить вычисление A(3, 30) в сотни и тысячи раз. Также вычисление A(2, n) напрямую вместо рекурсивного раскрытия в A(1, A(1, A(1,...A(1, 0)...))) прилично ускорит вычисление. Вычисление A(1, n) занимает линейное время n. Вычисленние A(2, n) требует квадратичное время, т.к. оно раскрывается в O(n) вложенных вызовов A(1, i) для различных i. Вычисление A(3, n) требует времени пропорционально 4n+1.

A(4, 2) невозможно посчитать с помощью простого рекурсивного применения за разумное время. Вместо этого для оптимизации рекурсивных вызовов используются сокращенные формулы вроде A(3, n) = 8×2n−3.

Один из практичных способов вычисления значений функции Аккермана - Мемоизация промежуточных результатов. Компилятор может применить эту технику к функции автоматически, используя memo functions [8][9] Дональда Мичи.


Примечания

  1. Cristian Calude, Solomon Marcus and Ionel Tevy (1979). "The first example of a recursive function which is not primitive recursive". Historia Math. 6 (4): 380—84. doi:10.1016/0315-0860(79)90024-7. {{cite journal}}: Неизвестный параметр |month= игнорируется (справка)
  2. Raphael M. Robinson (1948). "Recursion and Double Recursion". Bulletin of the American Mathematical Society. 54 (10): 987–993. doi:10.1090/S0002-9904-1948-09121-2.
  3. Дискретная математика: алгоритмы. Минимальные остовные деревья
  4. Y. Sundblad (1971). "The Ackermann function, A theoretical, computational and formula manipulative study". BIT. 11: 107—119. doi:10.1007/BF01935330.
  5. Ackermann's Function: A Study In The Efficiency Of Calling Procedures (1975).
  6. How to Call Procedures, or Second Thoughts on Ackermann's Function (1977).
  7. Latest results from the procedure calling test, Ackermann's function (1982).
  8. Michie, Donald, "Memo Functions and Machine Learning," Nature, No. 218, pp. 19–22, 1968.
  9. Example: Explicit memo function version of Ackermann's function implemented in PL/SQL

Ссылки


Шаблон:Link FA Шаблон:Link FA