julian做python的收益率(和收益率)

时间:2017-10-23 16:20:42

标签: julia

朱利安的做法是什么?as python do产生收益(和收益率)?

编辑:我将尝试在python中添加小例子。

想想4x4棋盘。找到每一个N动作长路棋王可以做到的。不要浪费记忆 - >制作每条路径的发电机。

如果我们用数字签署每个位置:

0  1  2  3
4  5  6  7
8  9  10 11
12 13 14 16

点0有3个邻居(1,4,5)。我们可以为每个点找到每个邻居的表格:

NEIG = [[1, 4, 5], [0, 2, 4, 5, 6], [1, 3, 5, 6, 7], [2, 6, 7], [0, 1, 5, 8, 9], [0, 1, 2, 4, 6, 8, 9, 10], [1, 2, 3, 5, 7, 9, 10, 11], [2, 3, 6, 10, 11], [4, 5, 9, 12, 13], [4, 5, 6, 8, 10, 12, 13, 14], [5, 6, 7, 9, 11, 13, 14, 15], [6, 7, 10, 14, 15], [8, 9, 13], [8, 9, 10, 12, 14], [9, 10, 11, 13, 15], [10, 11, 14]]

递归函数(生成器)从点列表或从(...的生成器)点的生成器放大给定路径:

def enlarge(path):
    if isinstance(path, list):
        for i in NEIG[path[-1]]:
            if i not in path:
                yield path[:] + [i]
    else:
        for i in path:
            yield from enlarge(i)

函数(生成器)给出具有给定长度的每个路径

def paths(length):
    steps = ([i] for i in range(16))  # first steps on every point on board
    for _ in range(length-1):
        nsteps = enlarge(steps)
        steps = nsteps
    yield from steps

我们可以看到有905776个长度为10的路径:

sum(1 for i in paths(10))
Out[89]: 905776

在ipython中我们可以计时:

%timeit sum(1 for i in paths(10))
1.21 s ± 15.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

我的朱莉娅实施丑陋而且复杂得多。而且似乎更慢。

3 个答案:

答案 0 :(得分:3)

查看ResumableFunctions.jl

来自README的

using ResumableFunctions

@resumable function fibonnaci(n::Int) :: Int
  a = 0
  b = 1
  for i in 1:n-1
    @yield a
    a, b = b, a+b
  end
  a
end

for fib in fibonnaci(10)
  println(fib)
end

答案 1 :(得分:1)

您可以使用频道:

function fibo(n)
    Channel() do ch
        a, b = 0, 1
        for _ in 1:n
            a, b = b, a + b
            put!(ch, a)
        end
    end
end

像这样使用它:

for val in fibo(10)
    print(val, " ")
end

输出:

1 1 2 3 5 8 13 21 34 55

要获得 yield from 行为,您可以只使用 for 循环。例如,要获得斐波那契数列 r 次:

function repeat_fibo(r, n)
    Channel() do ch
        for _ in 1:r
            for val in fibo(n)
                put!(ch, val)
            end
        end
    end
end

有关详细信息,请参阅 docs

请注意,ResumableFunctions.jl 库的一些基准测试表明,他们的解决方案比使用 Channels 快得多(参见 @gggg's answer)。也许频道性能会在未来的 Julia 版本中得到改善。

为了获得更好的频道性能,您应该设置频道的元素类型和频道的大小:例如,使用 Channel{Int64}(100) 而不是 Channel()

这是使用 Channels 解决国际象棋问题的 Julia 实现:

NEIG = [[1, 4, 5], [0, 2, 4, 5, 6], [1, 3, 5, 6, 7], [2, 6, 7], [0, 1, 5, 8, 9],
        [0, 1, 2, 4, 6, 8, 9, 10], [1, 2, 3, 5, 7, 9, 10, 11], [2, 3, 6, 10, 11],
        [4, 5, 9, 12, 13], [4, 5, 6, 8, 10, 12, 13, 14],
        [5, 6, 7, 9, 11, 13, 14, 15], [6, 7, 10, 14, 15], [8, 9, 13],
        [8, 9, 10, 12, 14], [9, 10, 11, 13, 15], [10, 11, 14]]

function paths(start, length)
    Channel{Vector{Int64}}(100) do ch
        if length == 1
            put!(ch, [start])
        else
            for path in paths(start, length - 1)
                for next_step in NEIG[path[end] + 1]
                    next_step in path || put!(ch, [path; next_step])
                end
            end
        end
    end
end

function paths(length)
    Channel{Vector{Int64}}(100) do ch
        for start in 0:15
            for path in paths(start, length)
                put!(ch, path)
            end
        end
    end
end

您可以像在 Python 中一样计算所有长度为 10 的路径:

sum(1 for _ in paths(10))

你也可以计时:

@time sum(1 for _ in paths(10))

在我的机器上,这大约需要 4 秒。可能有进一步优化的方法,但这确实表明渠道性能仍有一些改进空间。

答案 2 :(得分:0)

您可以使用 Julia Iterators

struct Fibonacci
    last::Int64
end

function Base.iterate(fibo::Fibonacci)
    return 1, (1, 1, 2) # the first output, and the next iteration state
end

function Base.iterate(fibo::Fibonacci, state)
    i, a, b = state
    if i ≤ fibo.last
        return a, (i + 1, b, a + b) # the output, and the next iteration state
    end
end

然后你可以像这样使用它:

for i in Fibonacci(10)
    print(i, " ")
end

输出:

1 1 2 3 5 8 13 21 34 55 89

这可以带来出色的性能,但通常有点冗长,而且决定使用哪种迭代状态以及如何找到给定该状态的下一个元素也很棘手。在您的国际象棋示例中,我会避​​免使用这种方法,但在其他情况下,它会派上用场。

相关问题