Ein Beispiel, bei dem der kleinste normale Lambda-Term nicht der schnellste ist

12

Die von -terms sei wie folgt definiert:λsizeλ

  • size(x)=1 ,
  • size(λx.t)=size(t)+1 ,
  • size(ts)=size(t)+size(s)+1 .

Die Komplexität eines λ -terms t sei definiert als die Anzahl der parallelen Beta-Reduktionen von tx auf seine normale Form (unter Verwendung eines optimalen Bewerters im Sinne von Levy).

Ich suche ein Beispiel für zwei normale λ Terme für dieselbe Funktion, bei denen der größere Term eine geringere Komplexität aufweist.

...

Aus Gründen der Übersichtlichkeit bearbeiten

Da es nicht offensichtlich ist, was ich frage, werde ich versuchen, ein solides Beispiel zu geben. Es gibt oft die Überzeugung, dass die "naive" / "einfachste" Definition einer Funktion langsam und nicht optimal ist. Eine bessere Leistung erhöht die Komplexität des Begriffs, da Sie zusätzliche Datenstrukturen, Formeln usw. benötigen. Ein gutes Beispiel ist fibonacci, das "naiv" definiert werden kann als:

-- The fixed fibonacci definition
fib_rec fib n =
    if (is_zero x) 
        then 1 
        else fib (n - 1) + f (n - 2)

-- Using church numbers instead of the λ-combinator to get a normal form
fib n = n fib_rec 0 n 

Dies wird oft als die "einfachste" Definition von fib angesehen und ist sehr langsam (exponentiell). Wenn wir die Abhängigkeiten von fib(die üblichen Definitionen für das Hinzufügen von Kirchennummern, pred, is_zero) erweitern und normalisieren, erhalten wir diesen Begriff:

fib = (λa.(a(λbc.(c(λdef.f)(λde.d)(λde.(de))
      (λde.(b(λfg.(c(λhi.(i(hf)))(λh.g)(λh.h)))
      d(b(λfg.(c(λhi.(i(h(λjk.(k(jf))))))(λhi.g)
      (λh.h)(λh.h)))de)))))(λbc.c)a))

Verbesserungen wie Memoization-Tabellen würden diesen Begriff vergrößern. Dennoch gibt es einen anderen Begriff, der viel kleiner ist ...

fib = (λa.(a(λb.(b(λcde.(e(λfg.(cf(dfg)))c))))
      (λb.(b(λcd.(cd))(λcd.d)))(λbc.b)))

und ist seltsamerweise auch dem naiven, der hereinläuft, asymptotisch überlegen O(N). Von allen Definitionen, die mir bekannt sind, ist dies sowohl die schnellste als auch die einfachste . Der gleiche Effekt tritt beim Sortieren auf. "Naive" Definitionen wie Blasensortierung und Einfügungssortierung werden häufig zu großen Begriffen (mehr als 20 Zeilen lang) erweitert, aber es gibt eine kleine Definition:

-- sorts a church list (represented as the fold) of church numbers
sort = λabc.a(λdefg.f(d(λhij.j(λkl.k(λmn.mhi)l)(h(λkl.l)i))
       (λhi.i(λjk.bd(jhk))(bd(h(λjk.j(λlm.m)k)c))))e)(λde.e)
       (λde.d(λfg.g)e)c

Was auch asymptotisch schneller ist als jede andere Definition, die ich kenne. Diese Beobachtung lässt mich glauben, dass im Gegensatz zu allgemeiner Überzeugung der einfachste Begriff mit der geringsten Kolmogorov-Komplexität normalerweise der schnellere ist. Meine Frage ist im Grunde, ob es Beweise für das Gegenteil gibt, obwohl es mir schwer fallen würde, sie zu formalisieren.

MaiaVictor
quelle
3
Nein hat sqrt (n) Komplexität. n!=n.n1....2.1
T ....
2
Ich bin mir ziemlich sicher, dass Sie die Testteilung durch einen kürzeren Begriff als den AKS-Algorithmus codieren können. λ
Emil Jeřábek 3.0
2
Ich stimme @ EmilJeřábek zu und sehe tatsächlich nicht, wie ein Beispiel nicht durch Betrachten von Sortieralgorithmen erhalten wird, wie Sie es bereits getan haben: Ist die Implementierung der Blasensortierung term nicht kürzer als die Implementierung -term sagen wir, Haufen sortieren? Oder, ich weiß nicht, eine Brute-Force-Suche, super kurz zu implementieren, aber exponentiell, im Vergleich zu einem cleveren Polytime-Algorithmus, der mehr Codezeilen erfordert ...? Ich muss etwas vermissen, ich fürchte, ich verstehe die Frage nicht wirklich. λλ
Damiano Mazza
1
Ich habe mich nicht bemüht, es tatsächlich aufzuschreiben, aber als heuristisches Prinzip werden die relativen Längen zweier Algorithmen normalerweise nicht sehr stark von der Wahl der Programmiersprache beeinflusst, und ich sehe absolut keinen Grund, warum -calculus eine Ausnahme sein sollte . Beachten Sie insbesondere, dass Normalisierung hier ein roter Hering ist: Die natürlichste Art, Algorithmen in -calculus auszudrücken, liefert von Anfang an normale Begriffe, und IIRC aus meiner Erfahrung mit Unlambda kann jeden Begriff in einen Begriff umwandeln normaler Term ähnlicher Länge, der bei Anwendung das gleiche Ergebnis liefert. λλ
Emil Jeřábek 3.0
2
Und ja, wie Damiano erwähnt, war AKS nur ein Beispiel. Dasselbe sollte in mehr oder weniger jeder Situation gelten, in der wir einen trivialen ineffizienten Algorithmus und eine effiziente, aber viel ausgefeiltere Lösung desselben Problems haben.
Emil Jeřábek 3.0

Antworten:

10

Blums Beschleunigungssatz wird normalerweise in der Sprache teilweise rekursiver Funktionen angegeben, aber bis zu geringfügigen Unterschieden in der Notation funktioniert er in der Sprache von -calculus genauso.λ

Es heißt, dass wir bei jedem vernünftigen Komplexitätsmaß (zum Beispiel der optimalen Anzahl von Reduktionen wie in der Frage) und einer rekursiven Funktion (zum Beispiel ) ein rekursives Prädikat so dass:Mf(x,y)2yP(x)

Für jeden Algorithmus (dh -term in normaler Form hier) berechnet , gibt es einen anderen Algorithmus für , der eine Geschwindigkeit über : λgPhPfg

f(x,M(h,x))M(g,x) for all large enough inputs x,

wobei die Komplexität der Berechnung von am Eingang gemäß Maß .M(g,x)gxM

Folglich:

  • P hat in dem gegebenen Maß keinen asymptotisch optimalen Algorithmus

  • Insbesondere ist der kürzeste Algorithmus für nicht asymptotisch optimalP

  • Für jeden Algorithmus für gibt es einen asymptotisch schnelleren Algorithmus, dessen Normalform länger ist (da es bis zur Umbenennung von Variablen nur endlich viele normale Terme einer bestimmten Länge gibt).P

Emil Jeřábek 3.0
quelle