python函数正在改变一个全局变量

时间:2018-05-30 17:33:03

标签: python genetic-algorithm

我正在尝试在python中实现遗传算法。 我的初始人口为六个人。我测量它们在下一代的适应度和概率,并选择三对交配概率为0.7。为了进行交叉,我将对和交配概率传递给函数。

lock (_yourLockObj)
{
    games.Add(new Game() { Name = msg });
}

其中 pairsg 是为交配挑选的对,交配概率是二进制列表(如果1执行交叉,则如果0不执行)。 问题是cross_over功能会改变原始人口,尽管人口变量从未在其中使用

new_population = cross_over(pairsg, mating_prob)

这是完整的代码:

def cross_over(prs, mp):
    new = []
    for pr in prs:
        if mp[prs.index(pr)] == 1:
            index = np.random.choice([1,2,3], p=[1/3, 1/3, 1/3])
            pr[0][:index], pr[1][:index] = pr[1][:index], pr[0][:index]

    for pr in prs:
        new.append(pr[0])
        new.append(pr[1])

    return new

2 个答案:

答案 0 :(得分:3)

问题是你在

中制作了copy
gen_pairs(population.copy(), prob)

但是您复制外部列表,但不复制子列表数据(它是副本)。所以

pr[0][:index], pr[1][:index] = pr[1][:index], pr[0][:index]

更改原始数据(因为pair.append(populationl[temp])也不会复制但使用相同的子列表引用)

你必须按照子列表的引用来解决这个问题。

一旦你理解了这个问题,就有很多方法可以避免这个问题。在某些时候制作子列表的副本。

你可以这样做:

gen_pairs([x.copy() for x in population], prob)

创建"深拷贝" (或copy.deepcopy(population))

或替换

pair.append(populationl[temp])

通过

pair.append(populationl[temp].copy())

答案 1 :(得分:1)

每次将参数传递给python函数时,基本上只是传递对该对象的引用,而对函数内部对象所做的一切也会反映在外部。即使对象外面有不同的名称,也会发生这种情况。 pairsgprs仍然引用相同的列表。这类似于在a = []b = a之后,ab都指向完全相同的对象。

在将可变参数(例如列表)传递给函数时要小心。对于不可变参数,参数传递的作用相同,但是您不会遇到此问题,因为无法更改不可变参数。

所以解决方法是不修改prs。这应该有效:

def cross_over(prs, mp):
    new = []
    for pr in prs:
        if mp[prs.index(pr)] == 1:
            index = np.random.choice([1,2,3], p=[1/3, 1/3, 1/3])
            new.append(pr[1][:index])
            new.append(pr[0][:index])
        else:
            new.append(pr[0])
            new.append(pr[1])

    return new