管理内存:在遍历树的 Lua 函数中。

我有两种算法,可以返回树中的随机节点,其中一个节点可以有0-N个子节点(当前节点为node,节点的第一个子节点为node [1]等)。第一种算法是均匀选择,它从树中均匀选择一个随机节点。它存储要返回的节点,随着它在树中向下移动,该节点用当前节点替换,并且替换的概率为1/(到目前为止看到的节点数)。下面是Lua代码。

function uniformSelect(node)
    local chosen = node

    function choose(node, counter)
        counter = counter + 1
        local probability = 1/counter
        if math.random() < probability then
            chosen = node
        end

        for i = 1, node.arity do
            choose(node[i], counter)
        end
    end

    choose(node, 0)
    return chosen
end

第二种算法在树中向下移动,查看它当前所在的节点,并给定概率P返回它。如果不返回此节点,则移动到节点的子项的概率为P1,P2 ... PN,它们相加为1。下面是Lua代码。

function select(node, prob)
    local r = math.random()
    if r < prob or node.arity == 0 then
        return node
    end

    local p = {}
    if node.arity == 1 then
        table.insert(p, 1)
    else
        local total = count(node) -- total number of nodes below this one
        for i = 1, node.arity do
            -- insert probability of moving to child i into p
            table.insert(p, (count(node[i])+1)/total)
        end

    end
    -- move to a child node chosen by roulette wheel selection
    return select(node[roulette(p)], prob)
end

这些算法在遗传编程框架中使用。当我使用第一种算法,均匀选择时,它在速度和内存方面首先运行良好。然而,第二个算法不能与经过多代演化的大型人口一起使用,它使用的内存会爆炸。我下面绘制了这个内存增长图,蓝线“prob”是第二个算法,select

![内存使用](https://i.stack.imgur.com/gDJLb.png)

对我来说,select看起来像尾递归。我也尝试了显式调用垃圾收集器,看看它是否有所帮助,它稍微减缓了增长速度,但增长仍然很大。

有人可以告诉我这种差异是什么原因吗?

点赞
用户1516403
用户1516403

我绘制了被生产的树的平均深度并找到了答案。select函数的交叉操作会增加种群中树的平均深度,导致程序变慢并且占用更多的内存。

enter image description here

2013-03-22 23:27:14