Recherche…


Mémo simple

La mémorisation consiste à mettre en cache les résultats des fonctions pour éviter de calculer le même résultat plusieurs fois. Ceci est utile lorsque vous travaillez avec des fonctions qui effectuent des calculs coûteux.

Nous pouvons utiliser une fonction factorielle simple comme exemple:

let factorial index =
    let rec innerLoop i acc =
        match i with
        | 0 | 1 -> acc
        | _ -> innerLoop (i - 1) (acc * i)

    innerLoop index 1

L'appel de cette fonction plusieurs fois avec le même paramètre entraîne le même calcul encore et encore.

La mémorisation nous aidera à mettre en cache le résultat factoriel et à le renvoyer si le même paramètre est transmis à nouveau.

Voici une implémentation simple de mémo:

// memoization takes a function as a parameter
// This function will be called every time a value is not in the cache
let memoization f =
    // The dictionary is used to store values for every parameter that has been seen
    let cache = Dictionary<_,_>()
    fun c ->
        let exist, value = cache.TryGetValue (c)
        match exist with
        | true -> 
            // Return the cached result directly, no method call
            printfn "%O -> In cache" c
            value
        | _ -> 
            // Function call is required first followed by caching the result for next call with the same parameters
            printfn "%O -> Not in cache, calling function..." c
            let value = f c
            cache.Add (c, value)
            value

La fonction de memoization prend simplement une fonction comme paramètre et renvoie une fonction avec la même signature. Vous pouvez le voir dans la signature de la méthode f:('a -> 'b) -> ('a -> 'b) . De cette façon, vous pouvez utiliser la mémorisation de la même manière que si vous appeliez la méthode factorielle.

Les appels à printfn doivent montrer ce qui se passe lorsque nous appelons la fonction plusieurs fois; ils peuvent être enlevés en toute sécurité.

Utiliser la mémorisation est facile:

// Pass the function we want to cache as a parameter via partial application
let factorialMem = memoization factorial

// Then call the memoized function
printfn "%i" (factorialMem 10)
printfn "%i" (factorialMem 10)
printfn "%i" (factorialMem 10)
printfn "%i" (factorialMem 4)
printfn "%i" (factorialMem 4)

// Prints
// 10 -> Not in cache, calling function...
// 3628800
// 10 -> In cache
// 3628800
// 10 -> In cache
// 3628800
// 4 -> Not in cache, calling function...
// 24
// 4 -> In cache
// 24

Mémo dans une fonction récursive

En utilisant l'exemple précédent de calcul de la factorielle d'un entier, mettez dans la table de hachage toutes les valeurs de factorielles calculées à l'intérieur de la récursivité, qui n'apparaissent pas dans la table.

Comme dans l'article sur la mémorisation , nous déclarons une fonction f qui accepte un paramètre de fonction fact et un paramètre entier. Cette fonction f comprend des instructions pour calculer la factorielle de n fact(n-1) .

Cela permet de gérer la récursivité par la fonction retournée par memorec et non par la fact elle-même et éventuellement arrêter le calcul si le fact(n-1) valeur a été déjà calculé et est situé dans la table de hachage.

let memorec f =
   let cache = Dictionary<_,_>()
   let rec frec n = 
       let value = ref 0
       let exist = cache.TryGetValue(n, value)
       match exist with
       | true -> 
           printfn "%O -> In cache" n
       | false ->
           printfn "%O -> Not in cache, calling function..." n
           value := f frec n
           cache.Add(n, !value)
       !value
   in frec

let f = fun fact n -> if n<2 then 1 else n*fact(n-1)

[<EntryPoint>]
let main argv = 
    let g = memorec(f)
    printfn "%A" (g 10)
    printfn "%A" "---------------------"
    printfn "%A" (g 5)
    Console.ReadLine()
    0

Résultat:

10 -> Not in cache, calling function...
9 -> Not in cache, calling function...
8 -> Not in cache, calling function...
7 -> Not in cache, calling function...
6 -> Not in cache, calling function...
5 -> Not in cache, calling function...
4 -> Not in cache, calling function...
3 -> Not in cache, calling function...
2 -> Not in cache, calling function...
1 -> Not in cache, calling function...
3628800
"---------------------"
5 -> In cache
120


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow