수색…


간단한 메모

Memoization은 동일한 결과를 여러 번 계산하지 않도록 함수 결과를 캐싱하는 것으로 구성됩니다. 이것은 값 비싼 계산을 수행하는 함수로 작업 할 때 유용합니다.

간단한 계승 함수를 예제로 사용할 수 있습니다.

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

    innerLoop index 1

동일한 매개 변수로이 함수를 여러 번 호출하면 동일한 계산이 계속 반복됩니다.

Memoization은 계승 결과를 캐시하고 동일한 매개 변수가 다시 전달 된 경우이를 반환하는 데 도움이됩니다.

다음은 간단한 메모 구현입니다.

// 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

memoization 함수는 단순히 함수를 매개 변수로 사용하고 동일한 서명을 가진 함수를 반환합니다. f:('a -> 'b) -> ('a -> 'b) 와 같은 방법으로 서명을 볼 수 있습니다. 이렇게하면 계승 방법을 사용하는 것과 같은 방법으로 메모를 사용할 수 있습니다.

printfn 호출은 함수를 여러 번 호출 할 때 어떤 일이 일어나는지 보여주는 것입니다. 안전하게 제거 할 수 있습니다.

메모를 사용하는 것은 쉽습니다.

// 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

재귀 함수에서의 메모 작성

정수의 계승을 계산하는 이전 예제를 사용하여 재귀 내에 계산 된 계승의 모든 값을 해시 테이블에 넣습니다.이 값은 테이블에 나타나지 않습니다.

memoization 에 대한 기사에서와 같이, 함수 매개 변수 fact 와 정수 매개 변수를 받아들이는 함수 f 를 선언합니다. 이 함수 ffact(n-1) 에서 n 의 계승을 계산하기위한 지침을 포함합니다.

이것은 fact 자체가 아니라 memorec 의해 반환 된 함수에 의한 재귀를 처리 할 수 ​​있으며 fact(n-1) 값이 이미 계산되어 해시 테이블에있는 경우 계산을 중지 할 수 있습니다.

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

결과:

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
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow