首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Julia 1.0中使用memoization或memoization

如何在Julia 1.0中使用memoization或memoization
EN

Stack Overflow用户
提问于 2018-08-28 12:45:59
回答 3查看 1.9K关注 0票数 8

我一直在尝试在Julia中为Fibonacci函数做记忆。这就是我想出来的。

原始的未修改代码(用于控制目的)

代码语言:javascript
复制
function fib(x)
    if x < 3
        return 1
    else
        return fib(x-2) + fib(x-1)
    end
end

这是我第一次尝试

代码语言:javascript
复制
memory=Dict()

function memfib(x)
    global memory
    if haskey(memory,x)
        return memory[x]
    else
        if x < 3
            return memory[x] = 1
        else
            return memory[x] = memfib(x-2) + memfib(x-1)
        end
    end
end

我的第二次尝试

代码语言:javascript
复制
memory=Dict()

function membetafib(x)
    global memory
    return haskey(memory,x) ? memory[x] : x < 3 ? memory[x]=1 : memory[x] = membetafib(x-2) + membetafib(x-1)
end

我的第三次尝试

代码语言:javascript
复制
memory=Dict()

function memgammafib!(memory,x)
    return haskey(memory,x) ? memory[x] : x < 3 ? memory[x]=1 : memory[x] = memgammafib!(memory,x-2) + memgammafib!(memory,x-1)
end

有没有其他我不知道的方法呢?

EN

回答 3

Stack Overflow用户

发布于 2018-08-29 00:36:18

正如评论中指出的,Memoize.jl包肯定是最简单的选择。这要求您在定义时标记该方法。

然而,到目前为止最强大的方法是使用Cassette.jl,它允许您向预先存在的函数添加memoization,例如

代码语言:javascript
复制
fib(x) = x < 3 ? 1 : fib(x-2) + fib(x-1)

using Cassette
Cassette.@context MemoizeCtx
function Cassette.overdub(ctx::MemoizeCtx, ::typeof(fib), x)
       get(ctx.metadata, x) do
           result = recurse(ctx, fib, x)
           ctx.metadata[x] = result
           return result
       end
   end

对正在发生的事情进行一点描述:

  • MemoizeCtx是我们正在运行的磁带“defining
  • overdub”,而不是原始的函数定义。我们使用它来检查元数据中是否存在参数dictionary.
  • recurse(...)告诉磁带调用函数,但忽略顶级overload.

现在我们可以使用memoization来运行函数:

代码语言:javascript
复制
Cassette.overdub(MemoizeCtx(metadata=Dict{Int,Int}()), fib, 80)

现在更酷的是,我们可以获取一个调用fib的现有函数,并在该函数中记住对fib的调用:

代码语言:javascript
复制
function foo()
    println("calling fib")
    @show fib(80)
    println("done.")
end
Cassette.overdub(MemoizeCtx(metadata=Dict{Int,Int}()), foo)

(Cassette对编译器来说仍然很难,所以第一次运行可能需要一段时间,但之后会很快)。

票数 18
EN

Stack Overflow用户

发布于 2018-08-30 02:29:43

最简单的方法是使用get!

代码语言:javascript
复制
const fibmem = Dict{Int,Int}()
function fib(n)
    get!(fibmem, n) do
        n < 3 ? 1 : fib(n-1) + fib(n-2)
    end
end

注意fibmem外部的const说明符。这避免了对global的需要,并将使代码更快,因为它允许编译器在fib中使用类型推断。

票数 11
EN

Stack Overflow用户

发布于 2020-06-22 03:30:51

由于函数的参数是整数,您可以使用简单的数组,这将比Dict更快(请确保在缓存中为大参数使用BigInts,以避免溢出):

代码语言:javascript
复制
function fib(n, cache=sizehint!(BigInt[0,1],n))
    n < length(cache) && return cache[n+1]
    f = fib(n-1,cache) + fib(n-2,cache)
    push!(cache,f)
    return f
end
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52050262

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档