Чи декілька сотень кроків зменшення занадто багато, щоб отримати нормальну форму Y fac ⌜3⌝?


9

Оскільки я останнім часом викладаю основи λ-числення, я запровадив просту оцінку λ-числення в Common Lisp. Коли я запитую нормальну форму зменшення Y fac 3нормального порядку, вона займає 619 кроків, що здавалося небагато.

Звичайно, щоразу, коли я робив подібні скорочення на папері, я ніколи не використовував нетипізовані λ-обчислення, але додавав числа та функції, що діють на них. У цьому випадку fac визначається як такий:

fac = λfac.λn.if (= n 0) 1 (* n (fac (- n 1)))

У цьому випадку, враховуючи =, *і -як функцію каррінгу, для досягнення Y fac 3нормальної форми потрібно лише приблизно 50 кроків 6.

Але в своєму оцінювачі я використав наступне:

true = λx.λy.x
false = λx.λy.y
⌜0⌝ = λf.λx.x
succ = λn.λf.λx.f n f x
⌜n+1⌝ = succ ⌜n⌝
zero? = λn.n (λx.false) true
mult = λm.λn.λf.m (n f)
pred = λn.λf.λx.n (λg.λh.h (g f)) (λu.x) (λu.u)
fac = λfac.λn.(zero? n) ⌜1⌝ (* n (fac (pred n)))
Y = λf.(λf.λx.f (x x)) f ((λf.λx.f (x x)) f)

За 619 кроків я переходжу Y fac ⌜3⌝до нормальної форми ⌜6⌝, а саме λf.λx.f (f (f (f (f (f x))))).

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

EDIT: Спочатку я просив близько тисячі кроків, деякі з яких справді були спричинені неправильним виконанням звичайного замовлення, тому я знизився до 2/3 початкової кількості кроків. Як коментується нижче, при моїй теперішній реалізації перехід від церкви до арифметики Пеано фактично збільшує кількість кроків ...

Відповіді:


11

Церковне кодування дійсно погано, якщо ви хочете використовувати pred. Я б порадив вам скористатись більш ефективним кодуванням у стилі Peano:

// Арифметика

: p_zero = λs.λz.z
: p_one = λs.λz.s p_zero
: p_succ = λn.λs.λz.sn
: p_null = λn.n (λx. ff) tt
: p_pred = λn.n (λp.p) p_zero
: p_plus = μ! f.λn.λm.n (λp. p_succ (! fpm)) m
: p_subs = μ! f.λn.λm.n (λp. p_pred (! fpm)) m
: p_eq = μ! f.λm.λn. m (λp. n (λq.! fpq) ff) (n (λx.ff) tt)
: p_mult = μ! f.λm.λn. m (λp. p_plus n (! fpn)) p_zero
: p_exp = μ! f.λm.λn. m (λp. p_mult n (! fpn)) p_one
: p_even = μ! f.λm. m (λp. не (! fp)) tt

// числа

: p_0 = λs.λz.z
: p_1 = λs.λz.s p_0
: p_2 = λs.λz.s p_1
: p_3 = λs.λz.s p_2
...

Це якийсь код, узятий з однієї зі моїх старих бібліотек, і μ!f. …був просто оптимізованою конструкцією Y (λf. …). (І tt, ff, notє булеві.)

Я не дуже впевнений, що ви отримаєте кращі результати fac.


Дякую за пораду, робота з цим альтернативним кодуванням допомогла мені знайти кілька помилок у моїй реалізації. Насправді, це не допомагає для кількості кроків, тому що після виправлення знаходження нормальної форми 3! робить 619 кроків з церковними цифрами і 687 з цифрами Пеано…
Ніде людина

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

Просто цікаво, що про 4 !, 5 !, 6! ?
Стефан Гіменез

1
Як не дивно, після 3! Кодування Peano стає більш ефективним, ніж кодування Церкви. Для отримання нормальної форми відповідно 1 !, 2 !, 3 !, 4! і 5! для Пеано / Церкви потрібно 10-10, 40/33, 157/134, 685/667, 3541/3956 та 21629/27311 кроків. Приблизна кількість кроків за 6! Інтерполяція від попередніх даних залишається як вправа для читача.
Ніде людина

1
Здається, що вищезгадані саме шотландські цифри "Peano + λ = Scott". Щось ще, що варто спробувати, - це їх бінарні варіанти (як для Церкви, так і для "Пестро </strike> Скотта").
Стефан Гіменез

2

Якщо я подумаю про те, скільки речей робить CPU для обчислення факторіалу 3, скажімо, в Python, то кілька сотень скорочень зовсім не є великою справою.

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