„Memoisation“ – Versionsunterschied

[gesichtete Version][gesichtete Version]
Inhalt gelöscht Inhalt hinzugefügt
K englische Schreibweise ergänzt
 
(31 dazwischenliegende Versionen von 29 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
'''Memoisation''' ist eine Technik, um [[Computerprogramm]]e zu beschleunigen, indem Rückgabewerte von Funktionen zwischengespeichert anstatt neu berechnet werden. Memoisation ähnelt [[Dynamische Programmierung|Dynamischer Programmierung]], bewahrt jedoch im Gegensatz zu dieser die grundlegende Vorgehensweise des zu beschleunigenden Verfahrens.
'''Memoisation''' (engl.: '''Memoization''') oder '''Memoisierung''' ist eine Technik, um [[Computerprogramm]]e zu beschleunigen, indem Rückgabewerte von Funktionen zwischengespeichert anstatt neu berechnet werden. Memoisation ähnelt [[Dynamische Programmierung|Dynamischer Programmierung]], bewahrt jedoch im Gegensatz zu dieser die grundlegende Vorgehensweise des zu beschleunigenden Verfahrens.


Funktionen können nur „memoisiert“ werden, wenn sie referenziell transparent sind, d. h. sie geben bei gleichen Eingaben immer dieselben Ausgaben zurück. Operationen, die nicht referenziell transparent sind, aber wo Abweichungen in der Ausgabe relativ selten zu erwarten sind, können mit anderen Methoden (wie [[Cache]]) zwischengespeichert werden. Generell haben "memoisierte" Ausgaben kein Ablaufdatum und müssen nicht neu berechnet werden, wie das bei Caches im Allgemeinen der Fall ist. In [[Imperative Programmierung|imperativen Programmiersprachen]] wird Memoisation üblicherweise in Form eines [[Assoziatives Array|assoziativen Arrays]] implementiert.
Funktionen können nur memoisiert werden, wenn sie [[Referenzielle Transparenz|referenziell transparent]] sind, d. h., sie geben bei gleichen Eingaben immer dieselben Ausgaben zurück. Operationen, die nicht referenziell transparent sind, aber bei denen Abweichungen in der Ausgabe relativ selten zu erwarten sind, können mit anderen Methoden (wie [[Cache]]) zwischengespeichert werden. Generell haben memoisierte Ausgaben kein Ablaufdatum und müssen nicht neu berechnet werden, wie das bei Caches im Allgemeinen der Fall ist. In [[Imperative Programmierung|imperativen Programmiersprachen]] wird Memoisation üblicherweise in Form eines [[Assoziatives Array|assoziativen Arrays]] implementiert.


In einer [[Funktionale Programmierung|funktionalen Programmiersprache]] ist es möglich eine [[Funktion höherer Ordnung]] <code>memoize</code> für jede referenziell transparente Funktion zu konstruieren. In Sprachen ohne die Möglichkeit einer Funktion höherer Ordnung muss die Memoisation separat in jede Funktion implementiert werden, die davon Gebrauch macht.
In einer [[Funktionale Programmierung|funktionalen Programmiersprache]] ist es möglich, eine [[Funktion höherer Ordnung]] <code>memoize</code> für jede referenziell transparente Funktion zu konstruieren. In Sprachen ohne die Möglichkeit einer Funktion höherer Ordnung muss die Memoisation separat in jede Funktion implementiert werden, die davon Gebrauch macht.


==Etymologie==
==Etymologie==
Das englische Wort ''memoization'' entstand 1968 durch [[Donald Michie]] aus seinem Artikel ''Memo functions and machine learning'' in der Zeitschrift [[Nature]].
"Memoisation" ist aus dem [[Latein|lateinischen]] Wort ''[[Memorandum]]'' abgeleitet, was so viel wie "''das zu Erinnernde''" bedeutet. Im allgemeinen Sprachgebrauch wird Memorandum auch ''Memo'' genannt und man kann Memoisation als "eine Funktion in eine Memo umwandeln" verstehen.


Memoisation ist aus dem [[Latein|lateinischen]] Wort ''[[Memorandum]]'' abgeleitet, was so viel wie „das zu Erinnernde“ bedeutet. Im allgemeinen Sprachgebrauch wird Memorandum auch Memo genannt und man kann Memoisation als eine Funktion in eine Memo umwandeln verstehen.
Das Wort ''Memoisation'' wird oft mit dem englischen Wort ''Memorization'' verwechselt, welches eine ähnliche Bedeutung aufweist.


Das Wort Memoisation wird oft mit dem englischen Wort ''Memorization'' verwechselt, welches eine ähnliche Bedeutung aufweist.
==Beispiel==

== Beispiel ==
Ein einfaches Programm, das die [[Fibonacci-Zahlen]] berechnet, ist
Ein einfaches Programm, das die [[Fibonacci-Zahlen]] berechnet, ist
function fib(n)
if (n <= 2)
return 1
return fib(n-1) + fib(n-2)
(Dieses Beispiel soll keine effiziente Implementierung darstellen. Es dient ausschließlich der Illustration der Memoisation.)


Weil <code>fib</code> mit denselben Parametern mehrmals aufgerufen wird, ist die Laufzeit der Funktion größer als [[O-Notation|O]](1.6<sup>n</sup>). Falls man die Werte von <code>fib</code> bei der ersten Berechnung memoisiert und die Speicherreservierung und -initialisierung in [[O-Notation|O]](n) vorgenommen werden kann, sinkt die Laufzeit auf [[O-Notation|O]](n).
fib(n) {
if n is 1 or 2, return 1;
return fib(n-1) + fib(n-2);
}


Speicher für Memo-Array memo reservieren und alle Werte darin auf 0 setzen.
(Dieses Beispiel soll keine effiziente Implementierung darstellen. Es dient ausschließlich der Illustration der Memoisation.)
Initialisiere memo[1] und memo[2] auf 1.
function fib(n)
if (memo[n] 0) return memo[n]
memo[n] = fib(n-1) + fib(n-2)
return memo[n]


Anstelle eines Arrays soll nun ein assoziatives Array zur Verwendung stehen. Bietet die Programmiersprache die Möglichkeit zur Formulierung von [[Closure (Funktion)|Closures]], so lässt sich eine Funktion memoize schreiben, die das Prinzip der Memoisation von <code>fib</code> abstrahiert.
Weil fib() mit denselben Parametern mehrmals aufgerufen wird, ist die Laufzeit der Funktion größer als [[O-Notation|O]](1.6<sup>n</sup>). Falls man die Werte von fib(n) bei der ersten Berechnung "memoisiert" und die Speicherreservierung und -initialisierung in [[O-Notation|O]](n) vorgenommen werden kann, sinkt die Laufzeit auf [[O-Notation|O]](n).
function memoize(f)
var memo = { }
return function(n)
if (n not in memo) memo[n] = f(n)
return memo[n]
fib = memoize(fib)


Zusätzlich zur Memoisation tritt bei diesem Beispiel gleichzeitig Rekursion auf. Hierbei ist zu beachten, dass <code>fib</code> auch innerhalb ihrer eigenen Definition eine Variable sein muss, deren Inhalt mit der memoisierten Version überschrieben wurde. Wenn das nicht möglich ist, kann man die Memoisation alternativ in den [[Fixpunkt-Kombinator]] einbauen. Dieser ist zunächst gegeben durch:
Speicher für Memo-Array memo reservieren und alle Werte darin auf 0 setzen;
Initialisiere memo[1] und memo[2] auf 1;


function fix(F)
fib(n) {
return function f(n)
if memo[n] is not zero, return memo[n];
memo[n] = fib(n-1) + fib(n-2);
return F(f,n)
return memo[n];
}


Der modifizierte Algorithmus beinhaltet nun das zuvor beschriebene Verfahren:
== Geschichte ==

Das englische Wort „memoization“ entstand 1968 durch [[Donald Michie]] aus seinem Artikel „Memo functions and machine learning“ in der Zeitschrift ''[[Nature (Zeitschrift)|Nature]]''.
function fix(F)
var memo = { }
return function f(n)
if (n not in memo) memo[n] = F(f,n)
return memo[n]
fib = fix(function(f,n))
return 1 if n <= 2 else f(n-1) + f(n-2))


== Literatur ==
== Literatur ==
Zeile 48: Zeile 70:


== Weblinks ==
== Weblinks ==
*[http://www.cliki.net/memoize Memoize] - Memoize ist eine kleine Bibliothek für Memoisation in Common Lisp. Es wurde von Tim Bradshaw geschrieben.
*[http://www.cliki.net/memoize Memoize] Memoize ist eine kleine Bibliothek für Memoisation in Common Lisp. Es wurde von Tim Bradshaw geschrieben.
*[http://search.cpan.org/dist/Memoize/Memoize.pm Memoize.pm] - ein [[Perl (Programmiersprache)|Perl]]-Modul welches memoisierte Unterroutinen enthält.
*[http://search.cpan.org/dist/Memoize/Memoize.pm Memoize.pm] ein [[Perl (Programmiersprache)|Perl]]-Modul, welches memoisierte Unterroutinen enthält.
*[http://www.onjava.com/pub/a/onjava/2003/08/20/memoization.html Java Memoisation] - ein Beispiel in Java welches eine dynamische Proxyklasse benutzt.
*[http://www.onjava.com/pub/a/onjava/2003/08/20/memoization.html Java Memoisation] ein Beispiel in Java, welches eine dynamische Proxyklasse benutzt.
*[http://raa.ruby-lang.org/project/memoize/ memoize] - ein [[Ruby (Programmiersprache)| Ruby]] Modul mit Memoise-Methoden.
*[http://raa.ruby-lang.org/project/memoize/ memoize] ein [[Ruby (Programmiersprache)| Ruby]]-Modul mit Memoise-Methoden.
*[http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52201 Python Memoisation] - ein Beispiel der Memoisation in Python.
*[http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52201 Python Memoisation] ein Beispiel der Memoisation in Python.
* [http://martin.jambon.free.fr/pa_memo.ml.html OCaml Memoisation] implementiert als eine [[Camlp4]] Syntaxerweiterung.
* [http://blogs.msdn.com/sriram/archive/2006/01/15/lisp_is_sin.aspx ein C# 2.0 Beispiel] der Memoisation


[[Kategorie:Optimierung]]
[[Kategorie:Optimierung]]

[[en:Memoization]]
[[fr:Mémoization]]
[[it:Memoizzazione]]
[[ja:メモ化]]
[[ko:메모이제이션]]
[[sv:Memoisation]]

Aktuelle Version vom 15. Juli 2023, 20:13 Uhr

Memoisation (engl.: Memoization) oder Memoisierung ist eine Technik, um Computerprogramme zu beschleunigen, indem Rückgabewerte von Funktionen zwischengespeichert anstatt neu berechnet werden. Memoisation ähnelt Dynamischer Programmierung, bewahrt jedoch im Gegensatz zu dieser die grundlegende Vorgehensweise des zu beschleunigenden Verfahrens.

Funktionen können nur memoisiert werden, wenn sie referenziell transparent sind, d. h., sie geben bei gleichen Eingaben immer dieselben Ausgaben zurück. Operationen, die nicht referenziell transparent sind, aber bei denen Abweichungen in der Ausgabe relativ selten zu erwarten sind, können mit anderen Methoden (wie Cache) zwischengespeichert werden. Generell haben memoisierte Ausgaben kein Ablaufdatum und müssen nicht neu berechnet werden, wie das bei Caches im Allgemeinen der Fall ist. In imperativen Programmiersprachen wird Memoisation üblicherweise in Form eines assoziativen Arrays implementiert.

In einer funktionalen Programmiersprache ist es möglich, eine Funktion höherer Ordnung memoize für jede referenziell transparente Funktion zu konstruieren. In Sprachen ohne die Möglichkeit einer Funktion höherer Ordnung muss die Memoisation separat in jede Funktion implementiert werden, die davon Gebrauch macht.

Etymologie

Das englische Wort memoization entstand 1968 durch Donald Michie aus seinem Artikel Memo functions and machine learning in der Zeitschrift Nature.

Memoisation ist aus dem lateinischen Wort Memorandum abgeleitet, was so viel wie „das zu Erinnernde“ bedeutet. Im allgemeinen Sprachgebrauch wird Memorandum auch Memo genannt und man kann Memoisation als eine Funktion in eine Memo umwandeln verstehen.

Das Wort Memoisation wird oft mit dem englischen Wort Memorization verwechselt, welches eine ähnliche Bedeutung aufweist.

Beispiel

Ein einfaches Programm, das die Fibonacci-Zahlen berechnet, ist

function fib(n)
    if (n <= 2)
        return 1
    return fib(n-1) + fib(n-2)

(Dieses Beispiel soll keine effiziente Implementierung darstellen. Es dient ausschließlich der Illustration der Memoisation.)

Weil fib mit denselben Parametern mehrmals aufgerufen wird, ist die Laufzeit der Funktion größer als O(1.6n). Falls man die Werte von fib bei der ersten Berechnung memoisiert und die Speicherreservierung und -initialisierung in O(n) vorgenommen werden kann, sinkt die Laufzeit auf O(n).

Speicher für Memo-Array memo reservieren und alle Werte darin auf 0 setzen.
Initialisiere memo[1] und memo[2] auf 1.

function fib(n)
    if (memo[n] ≠ 0) return memo[n]
    memo[n] = fib(n-1) + fib(n-2)
    return memo[n]

Anstelle eines Arrays soll nun ein assoziatives Array zur Verwendung stehen. Bietet die Programmiersprache die Möglichkeit zur Formulierung von Closures, so lässt sich eine Funktion memoize schreiben, die das Prinzip der Memoisation von fib abstrahiert.

function memoize(f)
    var memo = { }
    return function(n)
        if (n not in memo) memo[n] = f(n)
        return memo[n]

fib = memoize(fib)

Zusätzlich zur Memoisation tritt bei diesem Beispiel gleichzeitig Rekursion auf. Hierbei ist zu beachten, dass fib auch innerhalb ihrer eigenen Definition eine Variable sein muss, deren Inhalt mit der memoisierten Version überschrieben wurde. Wenn das nicht möglich ist, kann man die Memoisation alternativ in den Fixpunkt-Kombinator einbauen. Dieser ist zunächst gegeben durch:

function fix(F)
    return function f(n)
        return F(f,n)

Der modifizierte Algorithmus beinhaltet nun das zuvor beschriebene Verfahren:

function fix(F)
    var memo = { }
    return function f(n)
        if (n not in memo) memo[n] = F(f,n)
        return memo[n]

fib = fix(function(f,n))
    return 1 if n <= 2 else f(n-1) + f(n-2))

Literatur

  • Memoize – Memoize ist eine kleine Bibliothek für Memoisation in Common Lisp. Es wurde von Tim Bradshaw geschrieben.
  • Memoize.pm – ein Perl-Modul, welches memoisierte Unterroutinen enthält.
  • Java Memoisation – ein Beispiel in Java, welches eine dynamische Proxyklasse benutzt.
  • memoize – ein Ruby-Modul mit Memoise-Methoden.
  • Python Memoisation – ein Beispiel der Memoisation in Python.