Skip to main content
 首页 » 编程设计

python之numpy 向量化并行更新

2025年05月04日15zhwl

我想用以下简单规则实现一维元胞自动机:

  1. 如果单元格为1且相邻单元格为0,则(向右)移动
  2. 如果单元格为1且相邻单元格为1,则不要移动
  3. 所有细胞根据它们的状态同时更新。
  4. 我们有封闭边界条件。这意味着最后一个单元格的邻居是第一个单元格。

例如:

0 1 1 0 1

更新后:

1 1 0 1 0

我的解决方案是

def update(cells): 
    neighbors = np.roll(cells,-1) 
    dim = len(cells) 
    tmp_cells = np.zeros(dim) 
    for i,j in  enumerate(cells): 
        if j and not neighbors[i]: 
            tmp_cells[i], tmp_cells[(i+1)%dim] = 0, 1 
        elif j: 
            tmp_cells[i] = 1 
    return tmp_cells 

这很好,但解决方案并没有利用 np.arrays 的所有可能性,而是简化为一个简单的 list 算法。

我以为我可以在 cells 和 neighbors 之间找到一个简洁的逻辑,但显然我现在必须去 sleep 了。

一些想法?

请您参考如下方法:

要在不循环的情况下获取单元格的值,您需要知道它在两边 的邻居。您需要左边,因为如果您是 0,您的新值取决于您左边邻居的值,而如果您是 1,您的新值取决于您右边邻居的值。

你可以穷尽所有的 3 格组合,对吧?换句话说:

000 -> 0 
001 -> 0 
010 -> 0 # move to the right 
011 -> 1 # stay put 
100 -> 1 # left neighbor has moved 
101 -> 1 # left neighbor has moved 
110 -> 0 # move to the right 
111 -> 1 # stay put 

您可以很容易地将那个表变成一个 bool 函数。我们可以简化它,但让我们开始时是愚蠢的:-x & y & z | x & -y & -z | x & -y & z | x & y & z.

就是这样:

left = np.roll(cells, -1) 
right = np.roll(cells, 1) 
return (np.logical_not(left) & cells & right | # ...) 

现在您当然想要简化 bool 方程,*但这应该让您入门。

* 或者退后一步,重新考虑规则。如果你是 0,你的新值总是从你左边的邻居那里复制;如果你是 1,它总是从你右边的邻居那里复制的。您可以使用 bool 运算符的组合来编写它,但使用掩码赋值可能会更简单:result[cells] = left[cells];结果[notcells] = right[notcells].