Birkaç yüz azaltma adımı Y fac ⌜3⌝ normal formunu elde etmek için çok mu fazla?


9

Son zamanlarda λ-hesabının temelini öğrettiğim için, Common Lisp'de basit bir λ-calculus değerlendiricisi uyguladım. Y fac 3Normal düzen azaltımında normal biçimini sorduğumda, biraz fazla görünen 619 adım atıyor.

Tabii ki, kağıt üzerinde benzer indirimler her yaptığımda, türlenmemiş λ hesabını hiç kullanmadım, ancak üzerinde çalışan sayılar ve işlevler ekledim. Bu durumda, fac şöyle tanımlanır:

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

Bu durumda, dikkate =, *ve -işlevleri tımar olarak, sadece almak için yaklaşık 50 adımlar atması Y fac 3normal forma 6.

Ancak değerlendiricimde aşağıdakileri kullandım:

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 adımda Y fac ⌜3⌝normal formuna ⌜6⌝, yani normal formuna geçiyorum λf.λx.f (f (f (f (f (f x))))).

Birçok adımın hızlı bir şekilde gözden kaybolmasından, sanırım bu preduzun bir azaltmayı gerektiriyor, ama yine de benim uygulamada büyük bir kötü hata olup olmadığını merak ediyorum ...

DÜZENLEME: Başlangıçta bin adım hakkında sordum, bazıları gerçekten normal düzenin yanlış uygulanmasına neden oldu, bu yüzden ilk adım sayısının 2 / 3'üne düştüm. Aşağıda yorumlandığı gibi, mevcut uygulama ile, Kilise'den Peano aritmetiğine geçmek aslında adım sayısını arttırıyor…

Yanıtlar:


11

Kullanmak isterseniz kilise kodlaması gerçekten kötüdür pred. Peano tarzında daha verimli kodlama kullanmanızı öneririm:

// aritmetik

: 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. değil (! fp)) tt

// sayılar

: 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
...

Bu, eski kütüphanelerimden birinden alınan bir kod ve μ!f. …sadece optimize edilmiş bir yapıydı Y (λf. …). (Ve tt, ff, notmantıksal ifadenin bulunmaktadır.)

facYine de daha iyi sonuçlar alacağınızdan emin değilim .


Bahşiş için teşekkürler, bu alternatif kodlamayla çalışmak benim uygulamamda birkaç hata bulmama yardımcı oldu. Aslında, adımların sayısına yardımcı olmaz, çünkü sabitledikten sonra normal 3 şeklini bulmak! Kilise rakamlarıyla 619 adım ve Peano rakamlarıyla 687 adım atıyor…
Hiçbir yerde adam

Evet, ben de öyle düşünmüştüm, çünkü Ykısa indirimler elde etmek için bazı özel indirgeme kurallarını kullanmak çok önemlidir (özellikle Peano rakamları için).
Stéphane Gimenez

Sadece merak ediyorum, ya 4 !, 5 !, 6! ?
Stéphane Gimenez

1
Garip bir şekilde, 3! 'Ten sonra, Peano kodlaması Kilise kodlamasından daha verimli hale gelir. Sırasıyla 1 !, 2 !, 3 !, 4 normal formunu almak için! ve 5! Peano / Church ile 10/10, 40/33, 157/134, 685/667, 3541/3956 ve 21629/27311 adımlarını atıyor. 6 için adım sayısına yaklaşma! önceki verilerden enterpolasyon yaparak okuyucu için bir alıştırma olarak bırakılır.
Hiçbir yerde

1
Yukarıda belirtilenlerin tam olarak Scott rakamları "Peano + λ = Scott" olduğu görülüyor. Denemeye değer başka bir şey ikili varyantlarıdır (hem Church hem de <strike> Peano </strike> Scott için).
Stéphane Gimenez

2

Bir CPU'nun 3'ün faktöriyelini hesaplamak için kaç şey yaptığını düşünürsem, örneğin Python'da, birkaç yüz indirimi hiç de önemli değildir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.