识别和替换 python 中 nxn 数组中的元素以制作元胞自动机

identifying and replacing elements in an nxn array in python to make a cellular automaton

我一直在努力开始这项关于元胞自动机的大学作业。前提很简单,给出如下形式的数组,其中 1 代表黑色方块(或活细胞),0 代表白色方块(或死细胞)。

world1 = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0]
 [0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0]
 [0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0]
 [0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0]
 [0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0]
 [0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0]
 [0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

在每个时间步长 ("tick"),所有单元格同时发生以下转换:

任何少于两个活邻居的活细胞都会死亡,好像是由人口不足引起的。

任何有两个或三个活邻居的活细胞都会存活到下一代。

任何拥有三个以上活邻居的活细胞都会死亡,就像人口过剩一样。

任何死细胞只要有三个活的邻居就会变成活细胞,就像通过繁殖一样 . 这里的neighbors指的是每个元素周围的8个方块

现在,作为一名物理专业的学生,​​我可以看到数学相当简单,但我真的不知道如何构建代码以及如何构建代码以便稍后可以将其转换为动画。我还可以看到边缘的元素应该有一些例外。 Bellow 是我到目前为止的尝试......它运行但 returns 什么都没有。 我相信你可以告诉我在编程方面相当新!

import numpy as np
world1 = np.loadtxt('data/Pulsar.txt',dtype=np.int8) #loading data
def tick(world):
    north = world[i,i-1] #defining neighboughs as se, ne , n etc ..
    south = world[i,i+1]
    west = world[i+1,i]
    east = world[i-1,i]
    se = world[i+1,i+1]
    sw = world[i+1,i-1]
    ne = world[i-1,i+1]
    nw = world[i-1,i-1]
    neibours = (north, south, west, east, se, sw, ne, nw) #list of neighbough values
    np.where(world.all==0 and sum(neibours)==3, 1, world ) #replacing elements in array 
    np.where(world.all==1 and sum(neibours)<=2, 0, world )
    np.where(world.all==1 and sum(neibours)==2 or 3, 1, world )
    np.where(world.all==1 and sum(neibours)>=4, 0, world )


print(tick(world1))

我认为主要问题是您在 tick 函数中混淆了对单个单元格和整个矩阵的处理。

它开始似乎处理单个单元格(引用 i,我假设它是 'current' 单元格的索引,虽然没有真正在任何地方定义......),但你似乎尝试使用一些 numpy 魔法将其作为矢量化操作应用于所有单元格。这可能是可能的,但为了简单起见,我将从更明确的开始。

您可能还应该考虑其他几件事:

  • 您需要为矩阵的每个 单元格执行一些计算 - 应该有一个循环迭代矩阵的所有单元格...
  • 一个单元格的状态 post tick,应该不会影响相邻单元格的计算 pre tick - 对于每个你想要创建矩阵的新副本并用新状态填充它的 tick ,而不是就地写入更改并允许矩阵处于 'polluted' 中间刻度状态。

所以,非常粗略地(伪python):

def tick(matrix):
  new_state = np.array(X,Y) 
  for i in range(X):
    for j in range(Y):
      # this is where most of your `tick` function comes in,
      # adjusted to compute new state for a single given cell
      new_state[i][j] = compute_cell_state(i,j,matrix) 
  return new_state

for t in range(ticks):
  matrix = tick(matrix)
  print(matrix)

我认为我越来越接近了,但是我认为我使用的某些数据类型存在问题,因此目前出现错误“缩放器变量的索引无效”

def tick(matrix):
    new_state = np.array((17,17))
    for i in range(17):
        for j in range(17):
            north = matrix[i][j-1]
            south = matrix[i][j+1]
            west = matrix[i+1][j]
            east = matrix[i-1][j]
            se = matrix[i+1][j+1]
            sw = matrix[i+1][j-1]
            ne = matrix[i-1][j+1]
            nw = matrix[i-1][j-1]
            neibours = (north, south, west, east, se, sw, ne, nw)
            if matrix[i][j] == 0 and sum(neibours)==3:
                new_state [i][j] == 1
            if matrix[i][j] == 1 and sum(neibours)<=2:
                new_state [i][j] == 1
            if matrix[i][j] == 1 and sum(neibours)>=4:
                new_state [i][j] == 0
            if matrix[i][j] == 1 and sum(neibours)==2 or 3:
                new_state [i][j] == 1


            return new_state
world1 = np.loadtxt('data/Pulsar.txt',dtype=np.int8)        
print(tick(world1))