在Julia中重复运行一个函数N次(组合)

6
我正在尝试制作一个函数,可以将函数f(x)自我组合N次,类似于以下内容:
function CompositionN(f,N)
             for i in 1:N
                f(x) = f(f(x))
             end
return f(x)

我需要函数CompositionN返回另一个函数,而不是一个值。

3个回答

4
你可以利用 函数,它允许你组合多个函数:
julia> composition(f, n) = ∘(ntuple(_ -> f, n)...)
composition (generic function with 1 method)

julia> composition(sin, 3)(3.14)
0.001592651569876818

julia> sin(sin(sin(3.14)))
0.001592651569876818

2
这对于小 n 的情况非常有效,在我的电脑上可以处理小于 10 的数。但是对于大的 n,这种方法似乎更好:compose(f, n) = reduce(∘, ntuple(_ -> f, n)) - DNF
@giordano 我该如何组合多个函数,这些函数的输入和输出都是2个变量?例如 f= (x,y)->(x+y,x*y); ∘(f,f,f)(1,1) 返回错误而不是 (5,6) - Leo
@Leo:如果你的函数组合不是匿名的,而是命名为 f(x, y) = (x+y, x*y),那么它就能够正常工作。 - Jake Ireland
@JakeIreland,没有语法可以使它也适用于无名称的函数吗? - Leo

4
< p>使用ntuple和展开操作符的解决方案在一定数量的组合(比如10)内表现非常好,但是当组合数过多时,性能急剧下降。< /p> < p>另一种解决方案是使用reduce,在大量组合(n)时速度较快,但对于小数量级则相对较慢:< /p>
compose_(f, n) = reduce(∘, ntuple(_ -> f, n))

我认为以下的解决方案对于大型和小型的 n 都是最佳的:
function compose(f, n)
    function (x)  # <- this is syntax for an anonymous function
        val = f(x)
        for _ in 2:n
            val = f(val)
        end
        return val
    end
end

顺便说一句:在这种方法中,组合函数的构建速度更快。生成的函数的运行时间似乎是相同的。


谢谢!这样让我更清楚地了解了构成! - Evelyn Alvarez

1

Here's a recursive approach:

julia> compose(f, n) = n <= 1 ? f : f ∘ compose(f, n-1)
compose (generic function with 1 method)

julia> compose(x -> 2x, 3)(1)
8

如果我们愿意进行一些类型的盗版,我们可以使用幂运算符^对函数进行操作以表示n阶自我组合:
julia> Base.:^(f::Union{Type,Function}, n::Integer) = n <= 1 ? f : f ∘ f^(n-1)

julia> f(x) = 2x
f (generic function with 1 method)

julia> (f^3)(1)
8

1
也许可以测试 n<=1 来避免在负数 n 的情况下发生堆栈溢出? - DNF
@DNF 很好的观点。我已经编辑了答案以包含它。 - Cameron Bieganek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接