In reinen funktionalen Sprachen gibt es einen Algorithmus, um die inverse Funktion?
In reinen funktionalen Sprachen wie Haskell gibt es einen Algorithmus, um die inverse einer Funktion (edit), wenn es bijektive? Und gibt es eine bestimmte Art und Weise zu Programmieren, Ihre Funktion, so dass es ist?
- Mathematisch ist es nicht falsch zu sagen, dass, im Falle von
f x = 1
der Kehrwert von 1 ist ein Satz von Integer-zahlen und der inversen, alles andere ist eine leere Menge. Unabhängig davon, was einige Antworten sagen, die Funktion nicht bijektive ist nicht das größte problem. - Die richtige Antwort ist JA, aber es ist nicht effizient. Sei f : A -> B und A endlich, dann, da b€B, "nur" müssen, um prüfen alle f(A) finde alle a€A, f(a)=b. In einem Quanten-computer, vielleicht hätte O(size(a)) Komplexität. Natürlich, Sie suchen einen praktischen Algorithmus. Es ist nicht (ist mit O(2^Größe(a)) ), aber es besteht...
- QuickCheck macht es genau (schauen Sie für eine False-in f : A -> Bool).
- Ich bin nicht einverstanden; das ist meist nicht das, was gemeint ist mit inverse. So ziemlich jedes mal stoße ich auf den Begriff, die inverse von
f
ist eine Funktiong
so dassf . g = id
undg . f = id
. Ihr Kandidat gar nicht typecheck in diesem Fall. - du hast Recht. Was ich gesagt habe, nennt man eine inverse Bild, nicht eine inverse-Funktion. Mein Punkt war, dass die Antworten darauf hin, dass
f x = 1
hat keine inverse nehmen einen sehr engen Ansatz und ignorieren die ganze Komplexität des Problems. - eine inverse" ist genau das gleiche wie zu sagen, das inverse Bild ist ein singleton.
- Es ist ein verbreiteter Irrtum, dass Quantencomputer bestimmte Vorgänge ausführen können exponentiell viele Kopien der Daten parallel. Denken Sie daran, die Messung ist destruktiv, und die Messung eines verschränkten Wert erzeugt nur einen klassischen Wert. Holevo-Ungleichung sagt, dass die n qubits codieren kann höchstens n bits. Und würde es als sehr überraschend, wenn Quanten-Computer könnte effizient lösen alle NP-Probleme (mehr formal, denken wir, dass NP ⊄ BQP). [cont...]
- Für den speziellen Fall, die Sie erwähnen—Suche durch eine ungeordnete Liste von Elementen, die Sie verwenden möchten, Grover ' s Algorithmus, der sucht einen Länge-n-Liste in O(√*n*) Zeit auf einem Quanten-computer. Und tatsächlich, Wikipedia sagt, dass "es vielleicht genauer zu beschreiben [Grover' s Algorithmus] als 'Umkehrung eine Funktion ist,'" so dass Sie gehen. Das gibt eine quadratische Beschleunigung: anstelle von O(2^|A|) Zeit zum umkehren einer Funktion, Sie am Ende mit O(2^(|A|/2)) Zeit, und die können nicht besser.
- Danke @AntalS-Z, ich sagte: "vielleicht hätte", weil "Die Beziehung zwischen BQP und NP ist nicht bekannt"
Du musst angemeldet sein, um einen Kommentar abzugeben.
In einigen Fällen, ja! Es gibt ein schönes Papier genannt Bidirectionalization Kostenlos!, die beschreibt einige Fälle-wenn Sie Ihre Funktion ausreichend polymorph sein-wo es möglich ist, ganz automatisch zur Ableitung einer inversen Funktion. (Es wird auch erläutert, was das problem macht hart, wenn die Funktionen nicht polymorph.)
Was man in dem Fall Ihre Funktion ist invertierbar, ist die inverse (mit einer fadenscheinigen input); in anderen Fällen, erhalten Sie eine Funktion, die versucht, "merge", eine alte input-Wert und eine neue Ausgabe Wert.
put
Funktionen in beliebiger Datensatz-Strukturen ableitenData
: haskell.org/pipermail/haskell-cafe/2008-April/042193.html mit einem ähnlichen Konzept, das später vorgestellt (konsequenter, mehr im Allgemeinen, mehr prinzipientreue, etc.) in "for free".Nein, es ist nicht möglich im Allgemeinen.
Beweis: betrachten bijektive Funktionen vom Typ
mit
Angenommen, wir haben einen Wechselrichter
inv :: F -> F
so dassinv f . f ≡ id
. Sagen wir, wir haben es getestet für die Funktionf = id
, mit der Bestätigung, dassSeit diesem ersten
B0
in die Ausgabe gekommen sein muss, nachdem eine begrenzte Zeit, wir haben eine Obere Grenzen
sowohl die Tiefe, bis zu derinv
hatte tatsächlich ausgewertet unser test-Eingang um dieses Resultat zu bekommen, sowie die Anzahl der Zeiten, die Sie haben können, genanntf
. Definieren Sie nun eine Familie von FunktionenKlar, für alle
0<j≤n
,g j
ist eine bijection, in der Tat selbst-invers. Wir sollten also in der Lage sein, um zu bestätigen,aber dieses erfüllen,
inv (g j)
müsste entwederg j (B1 : repeat B0)
bis zu einer Tiefe vonn+j > n
head $ g j l
für mindestensn
verschiedenen Listen passendenreplicate (n+j) B0 ++ B1 : ls
Bis zu diesem Punkt, mindestens eine der
g j
ist nicht vonf
, und dainv f
noch nicht getan haben, entweder von diesen Auswertungeninv
konnte unmöglich gesagt haben, es auseinander – kurz, zu tun, einige Laufzeit-Messungen auf seine eigene, und das ist nur möglich in derIO Monad
.⬜
Können Sie es nachschlagen auf wikipedia, es heißt Reversible Computing.
Im Allgemeinen, die Sie nicht tun können, obwohl, und keiner von den funktionalen Sprachen, die diese option haben. Zum Beispiel:
Diese Funktion nicht haben eine inverse.
f
hat eine inverse, es ist nur so, dass die inverse ist eine nicht-deterministische Funktion?g :: Int -> a
was ist das Gegenteil vonf
, auch wenn Sie können, beschreiben Sie die inverse vonf
mathematisch.f x = 2 * x
werdenf' x = [x / 2]
, und dann die inverse vonf _ = 1
istf' 1 = [minBound ..]; f' _ = []
. Das heißt, es gibt viele inversen für 1, und keiner für einen anderen Wert.Nicht in den meisten funktionalen Sprachen, aber in der Logik der Programmierung bzw. der relationalen Programmierung, die meisten Funktionen, die Sie definieren, sind in Wirklichkeit nicht um Funktionen, sondern "Beziehungen", und diese kann in beiden Richtungen verwendet werden. Siehe zum Beispiel prolog oder kanren.
Aufgaben wie diese sind fast immer unentscheidbaren. Sie können eine Lösung für einige spezifische Funktionen, aber nicht im Allgemeinen.
Hier, Sie können nicht einmal erkennen, welche Funktionen haben eine inverse. Zitieren Barendregt, H. P. The Lambda-Kalkül: Syntax und Semantik. North Holland, Amsterdam (1984):
Nehmen wir Ein, um die Menge der lambda-Bedingungen darstellen invertierbaren Funktionen und B den rest. Beide sind nicht-leer und geschlossen unter beta-Gleichheit. Es ist also nicht möglich, zu entscheiden, ob eine Funktion invertierbar ist oder nicht.
(Dies gilt für der nicht typisierte lambda-Kalkül. TBH ich weiß nicht, ob das argument direkt an eine typisierte lambda-Kalkül, wenn wir wissen, den Typ einer Funktion, die wir wollen umkehren. Aber ich bin mir ziemlich sicher, es wird ähnlich sein.)
Wenn Sie aufzählen können, die in der Domäne der Funktion und vergleichen können, - Elemente der Reihe für die Gleichstellung, Sie kann - in einer eher einfachen Art und Weise. Durch aufzählen ich, dass man eine Liste aller verfügbaren Elemente. Ich bleibe bei Haskell, da ich nicht weiß, Ocaml (oder sogar, wie zu profitieren ist es richtig 😉
Was Sie tun möchten, ist laufen durch die Elemente der Domäne und sehen, ob Sie gleich dem element des Bereichs, den Sie versuchen zu invertieren, und nehmen Sie die erste, der funktioniert:
Da Sie erklärt habe, dass
f
ist eine bijection, gibt es zwangsläufig ein und nur ein solches element. Der trick, natürlich, ist, um sicherzustellen, dass Ihre Aufzählung der domain tatsächlich erreicht alle Elemente in einer endlichen Zeit. Wenn Sie versuchen, zu invertieren bijection vonInteger
zuInteger
mit[0,1 ..] ++ [-1,-2 ..]
wird nicht funktionieren, da wirst du aber nie bekommen, um die negativen zahlen. Konkretinv ([0,1 ..] ++ [-1,-2 ..]) (+1) (-3)
niemals ergeben Sie einen Wert.Jedoch
0 : concatMap (\x -> [x,-x]) [1..]
arbeiten, wie das läuft durch die ganzen zahlen in der folgenden Reihenfolge[0,1,-1,2,-2,3,-3, and so on]
. In der Tatinv (0 : concatMap (\x -> [x,-x]) [1..]) (+1) (-3)
umgehend zurück-4
!Den Kontrolle.Monade.Omega Paket kann Ihnen helfen, führen Sie durch Listen von Tupeln usw. in einem guten Weg; ich bin sicher, es gibt mehr Pakete wie, aber ich kenne Sie nicht.
Natürlich, dieser Ansatz ist eher low-Stirn-und brute-force, nicht zu erwähnen, hässlich und ineffizient! Also werde ich Ende mit ein paar Bemerkungen zu dem letzten Teil deiner Frage, wie 'schreiben' bijections. Das Typsystem von Haskell ist nicht up, um zu beweisen, dass eine Funktion eine bijection - wollen Sie wirklich so etwas wie Agda - aber es ist bereit, Ihnen zu Vertrauen.
(Achtung: ungetestet-code folgt)
So können Sie definieren einen Datentyp
Bijection
s zwischen Artena
undb
:zusammen mit so vielen Konstanten (wo man sagen kann 'ich wissen Sie sind bijections!') wie Sie möchten, wie:
und ein paar smart-combinators, wie:
Ich denke, Sie könnten dann tun
invert (mapBi add1Bi) [1,5,6]
und bekommen[0,4,5]
. Wenn Sie wählen Sie Ihre combinators in eine intelligente Art und Weise, ich denke, die Anzahl der Zeiten, die Sie haben zu schreiben, eineBi
ständige von hand könnte ziemlich begrenzt.Nach allem, wenn Sie wissen eine Funktion ist eine bijection, du wirst hoffentlich ein Beweis-Skizze, die Tatsache in den Kopf, die die Curry-Howard Isomorphie sollte in der Lage sein wiederum in ein Programm 🙂
Ich habe seit kurzem den Umgang mit Problemen wie diesem, und Nein, ich würde sagen, dass (a) es ist nicht schwierig, in vielen Fällen aber (b) es ist nicht effizient überhaupt.
Grundsätzlich angenommen, Sie haben
f :: a -> b
, und dassf
ist in der Tat ein bjiection. Sie können berechnen die inversef' :: b -> a
in eine wirklich blöde Art und Weise:Wenn
f
ist eine bijection undenumerate
wirklich produziert alle Werte dera
, dann werden Sie schließlich traf einena
so dassf a == b
.Typen, die haben ein
Bounded
und einEnum
Instanz kann trivial ausRecursivelyEnumerable
. PaarEnumerable
Typen können auchEnumerable
:Gleiche gilt für die Bruchstellen der
Enumerable
Typen:Dass wir das können, tun dies sowohl für
(,)
undEither
bedeutet wahrscheinlich, dass wir tun können, ist es für jeden algebraischen Datentyp.Nicht jede Funktion hat eine inverse. Wenn Sie beschränken die Diskussion um one-to-one-Funktionen, die Fähigkeit zum umkehren einer beliebigen Funktion ermöglicht das knacken jedes Kryptosystem. Wir müssen hoffen, dass dies nicht möglich ist, auch in der Theorie!
String encrypt(String key, String text)
ohne die Taste, die Sie noch nicht in der Lage sein, etwas zu tun. EDIT: Plus das, was delnan sagte.Nein, nicht alle Funktionen haben sogar inversen. Was würde beispielsweise die inverse dieser Funktion werden?
In einigen Fällen ist es möglich, die inverse zu finden, der eine bijektive Funktion durch Umwandlung in eine symbolische Darstellung. Basierend auf dieses Beispiel, ich schrieb das Haskell-Programm zu finden inversen einige einfache Polynomfunktionen:
Dieses Beispiel funktioniert nur mit arithmetischen Ausdrücken, aber es könnte wohl verallgemeinert werden, um die Arbeit mit Listen als auch.