python函数正在更改全局变量b

2024-09-28 05:16:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用python实现一个遗传算法。 我最初有六个人。我测量它们的适合度和进入下一代的概率,然后挑选三对交配,交配概率为0.7。为了进行交叉,我把配对和交配概率传递给一个函数。你知道吗

new_population = cross_over(pairsg, mating_prob)

其中,pairsg是为交配挑选的成对,而matching prob是一个二进制列表(如果1交叉,如果0不交叉)。问题是,交叉函数改变了原始总体,尽管其中从未使用总体变量

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

这是完整的代码:

from random import *
import numpy as np

#fitness function
def fit(x):
    return 15*x -x**2

#covert binary list to decimal number
def to_dec(x):
    return int("".join(str(e) for e in x), 2)

#picks pairs from the original population
def gen_pairs(populationl, prob):
    pairsl = []
    test = [0, 1, 2, 3, 4, 5]
    for i in range(3):
        pair = []
        for j in range(2):
            temp = np.random.choice(test, p=prob)
            pair.append(populationl[temp])
        pairsl.append(pair)

    return pairsl

#mating function
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


population = [[1,0,1,0], [0,1,1,0], [1,0,0,1], [1,1,1,0],[1,1,0,0],[1,0,0,0]]
fittness = [fit(to_dec(y)) for y in population]

s = sum(fittness)
prob = [e/s for e in fittness]
pairsg = gen_pairs(population.copy(), prob)

mating_prob = []
for i in pairsg:
    mating_prob.append(np.random.choice([0,1], p=[0.3,0.7]))

new_population = cross_over(pairsg, mating_prob)

Tags: innewforindexreturndefnprandom
2条回答

问题是你在

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())

任何时候向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

相关问题 更多 >

    热门问题