在python代码中如何避免这么多索引

2024-10-02 04:20:27 发布

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

我是python新手,我觉得我在python编程中使用了完全错误的策略。举个例子:

我有这样一个清单:

selected_parents = 
[array([[4, 6, 3, 1, 0, 7, 5, 2]]), array([[0, 2, 7, 3, 5, 4, 1, 6]])]

现在我想对列表中的元素应用交叉(请参见p.S.了解我所说的交叉是什么意思以及它是如何实现的,但我的问题是,我应该如何避免在python编程时使用这么多索引):

crossed_p1 = np.zeros((len(selected_parents[0][0]))).astype(int)
crossed_p2 = np.zeros((len(selected_parents[0][0]))).astype(int)

co_point = rd.sample(range(len(selected_parents[0][0])),1)

if co_point[0] >= len(selected_parents[0][0])/2:
        crossed_p1[0:co_point[0]] = selected_parents[0][0][0:co_point[0]]

        indeces = []
        for i in range(co_point[0],len(selected_parents[0][0])):
            a = np.where(selected_parents[1][0] == selected_parents[0][0][i])
            indeces.append(a)
            indeces = sorted(indeces)

        for i in range(len(indeces)):
            crossed_p1[i + co_point[0]] = selected_parents[1][0][indeces[i][0][0]]

        crossed_p2[0:co_point[0]] = selected_parents[1][0][0:co_point[0]]

        indeces = []
        for i in range(co_point[0],len(selected_parents[0][0])):
            a = np.where(selected_parents[0][0] == selected_parents[1][0][i])
            indeces.append(a)
            indeces = sorted(indeces)

        for i in range(len(indeces)):
            crossed_p2[i + co_point[0]] = selected_parents[0][0][indeces[i][0][0]]

    else:
        crossed_p1[co_point[0]:] = selected_parents[0][0][co_point[0]:]

        indeces = []
        for i in range(co_point[0]):
            a = np.where(selected_parents[1][0] == selected_parents[0][0][i])
            indeces.append(a)
            indeces = sorted(indeces)

        for i in range(len(indeces)):
            crossed_p1[i] = selected_parents[1][0][indeces[i][0][0]]

        crossed_p2[co_point[0]:] = selected_parents[1][0][co_point[0]:]

        indeces = []
        for i in range(co_point[0]):
            a = np.where(selected_parents[0][0] == selected_parents[1][0][i])
            indeces.append(a)
            indeces = sorted(indeces)

        for i in range(len(indeces)):
            crossed_p2[i] = selected_parents[0][0][indeces[i][0][0]]

代码就像一个魅力,但我讨厌我写它的方式!就像我一直在问自己一样,我真的要写selected_parents[0][0][indeces[i][0][0]]这样的东西吗?!有没有更好的方法来做我正在做的事?!你知道吗

p.S.这是遗传算法的一个例子,我将selected_parents中的两个数组作为第一代父代。现在我想应用交叉,这意味着:随机选择一个切割点(即代码中的co_point),它是1和父长度(这里是8)之间的随机整数;第一个子代(即crossed_p1)从第一个父代继承一个较长的子串,并按出现的数字顺序替换较短子串的数字在第二个家长。对第二个后代(即crossed_p2)重复类似的过程。例如,基于当前的selected_parents列表,对于co_point = 5,第一子代(即crossed_p1)从第一个父代继承46310的子串,并且752的剩余子串被275替换,这是第二个父代中出现的数字顺序。因此,第一个后代(即crossed_p1)是46310275,第二个后代(即crossed_p2)将是02735461。你知道吗


Tags: inforlennprangewherepointselected
3条回答

这是你代码的矢量化版本。矢量化的一个令人愉快的副作用是它通常会去掉大多数索引。你知道吗

这段代码假设父向量是0, 1, 2, ...的乱序。如果不是这样,还需要做更多的工作:

def invperm(p):
    out = np.empty_like(p)
    idx = np.ogrid[tuple(map(slice, p.shape))]
    idx[-1] = p
    out[idx] = np.arange(p.shape[-1])
    return out

def f_pp(selected_parents):
    sp = np.reshape(selected_parents, (2, -1))
    _, N = sp.shape
    co = np.random.randint(0, N)
    out = sp.copy()
    slc = np.s_[:co] if 2*co < N else np.s_[co:]
    out[::-1, slc] = out[
        np.c_[:2], np.sort(invperm(sp)[np.c_[:2], sp[::-1, slc]], axis=1)]
    return out

大多数索引都指向selected_parents列表的元素,这些元素是二维数组:

selected_parents[0][0][0:co_point[0]]

数组可以用一组[]索引:

selected_parents[0][0, 0:co_point[0]]

注意,可以方便地“命名”列表中的2个元素(解包):

p1, p2 = selected_parents
p1[0, 0:co_point[0]]

一般来说,在数组上使用shape比使用len更好。替换

len(selected_parents[0][0])

p1.shape[1]

p1.shape是(1,8)

看起来p1, p2有相同的形状。在那种情况下

np.stack(selected_parents)

应该生成一个(2,1,8)数组,该数组可以重新调整为(2,8)。或者

np.concatenate(selected_parents, axis=0)

产生(2,8)数组。你知道吗

如果你的氏族是1D列表,这似乎是最简单的交叉方式:

>>> selected_parents = [[4, 6, 3, 1, 0, 7, 5, 2], [0, 2, 7, 3, 5, 4, 1, 6]]

让我们创建两个parant,并选择交叉点:

>>> p1, p2 = selected_parents
>>> cx = random.randint(len(p1))
>>> p1
[4, 6, 3, 1, 0, 7, 5, 2]
>>> p2
[0, 2, 7, 3, 5, 4, 1, 6]
>>> cx
4

第一个孩子和第二个孩子是两个单子的结合体

>>> ch1=p1[:cx]+p2[cx:]
>>> ch1
[4, 6, 3, 1, 5, 4, 1, 6]
>>> ch2=p2[:cx]+p1[cx:]
>>> ch2
[0, 2, 7, 3, 0, 7, 5, 2]
>>> 

如果你需要numpy,这不是问题。同样的想法如下:

>>> selected_parents = [array([[4, 6, 3, 1, 0, 7, 5, 2]]), array([[0, 2, 7, 3, 5, 4, 1, 6]])]
>>> p1, p2 = selected_parents
>>> p1
array([[4, 6, 3, 1, 0, 7, 5, 2]])
>>> p2
array([[0, 2, 7, 3, 5, 4, 1, 6]])
>>> cx = random.randint(p1.shape[1])
>>> cx
5
>>> ch1=append(p1[0][:cx],p2[0][cx:])
>>> ch1
array([4, 6, 3, 1, 0, 4, 1, 6])
>>> ch2=append(p2[0][:cx],p1[0][cx:])
>>> ch2
array([0, 2, 7, 3, 5, 7, 5, 2])

相关问题 更多 >

    热门问题