python - numpy vectorize a parallel update -
i want implement one-dimensional cellular automaton following simple rules:
- if cell 1 , neighbor cell 0, move (to right)
- if cell 1 , neighbor cell 1, don't move
- all cells update @ same time according state.
- we have closed boundary conditions. means neighbor of last cell first cell.
for example:
0 1 1 0 1
after update:
1 1 0 1 0
my solution is
def update(cells): neighbors = np.roll(cells,-1) dim = len(cells) tmp_cells = np.zeros(dim) i,j in enumerate(cells): if j , not neighbors[i]: tmp_cells[i], tmp_cells[(i+1)%dim] = 0, 1 elif j: tmp_cells[i] = 1 return tmp_cells
that works fine, solution not exploit possibilities of np.arrays
, reduces simple list
-algorithm.
i thought find neat logic between cells
, neighbors
, apparently have go sleep now.
some ideas?
to value cell without looping, need know neighbors on both sides. need left because if you're 0
new value depends on left neighbor's, while if you're 1
new value depends on right neighbor.
you can exhaustively write 3-cell combinations, right? in other words:
000 -> 0 001 -> 0 010 -> 0 # move right 011 -> 1 # stay put 100 -> 1 # left neighbor has moved 101 -> 1 # left neighbor has moved 110 -> 0 # move right 111 -> 1 # stay put
you can turn table boolean function pretty easily. simplify it, let's stupid start with: -x & y & z | x & -y & -z | x & -y & z | x & y & z
.
and that's it:
left = np.roll(cells, -1) right = np.roll(cells, 1) return (np.logical_not(left) & cells & right | # ...)
now of course you'll want simplify boolean equation,* should started.
* or maybe step , rethink rules. if you're 0
, new value copied left neighbor; if you're 1
, it's copied right neighbor. can write combination of boolean operators, might simpler masked assignment: result[cells] = left[cells]; result[notcells] = right[notcells]
.
Comments
Post a Comment