numpy向量化并行更新 [英] numpy vectorize a parallel update
问题描述
我想用以下简单规则实现一维元胞自动机:
I want to implement a one-dimensional cellular automaton with the following simple rules:
- 如果单元格为 1 ,而相邻单元格为 0 ,则向右移动
- 如果单元格为 1 而邻居单元格为 1 ,请不要移动
- 所有单元格都根据其状态同时更新.
- 我们有封闭边界条件.这意味着最后一个单元格的邻居是第一个单元格.
- If cell is 1 and neighbor cell is 0, move (to the right)
- if cell is 1 and neighbor cell is 1, don't move
- All cells update at the same time according to their state.
- We have closed boundary conditions. That means the neighbor of the last cell is the first cell.
例如:
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
-算法.
That works fine, but the solution do not exploit all the possibilities of np.arrays
and reduces to a simple list
-algorithm.
我以为我可以在cells
和neighbors
之间找到一个整齐的逻辑,但是显然我现在必须去睡觉.
I thought I could find a neat logic between cells
and neighbors
, but apparently I have to go sleep now.
有些想法?
推荐答案
要获取不循环的单元格值,您需要同时在 侧都知道它的邻居.您需要左边的,因为如果您是0
,则新值取决于您的左邻居.
To get the value for a cell without looping, you need to know its neighbors on both sides. You need the left because if you're a 0
your new value depends on your left neighbor's, while if you're a 1
your new value depends on your right neighbor.
您可以详尽地编写所有3单元组合,对吗?换句话说:
You can exhaustively write all the 3-cell combinations, right? In other words:
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
您可以轻松地将该表转换为布尔函数.我们可以简化它,但是让我们愚蠢的开始于:-x & y & z | x & -y & -z | x & -y & z | x & y & z
.
You can turn that table into a boolean function pretty easily. We could simplify it, but let's just be stupid to start with: -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 | # ...)
现在,您当然想简化布尔方程,*,但这应该可以帮助您入门.
Now of course you'll want to simplify the boolean equation,* but this should get you started.
*或者也许退后一步,重新思考规则.如果您是0
,则总是从您的左邻居复制新值;如果您是1
,则总是从您的正确邻居那里复制它.您可以使用布尔运算符的组合来编写该代码,但是使用带掩码的赋值可能更简单:result[cells] = left[cells]; result[notcells] = right[notcells]
.
* Or maybe step back and rethink the rules. If you're a 0
, your new value is always copied from your left neighbor; if you're a 1
, it's always copied from your right neighbor. You can write that with a combination of boolean operators, but it might be even simpler with masked assignment: result[cells] = left[cells]; result[notcells] = right[notcells]
.
这篇关于numpy向量化并行更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!