【问题标题】:Cellular Automata using python class使用 python 类的元胞自动机
【发布时间】:2020-07-25 22:22:52
【问题描述】:

我创建了一个启动和更新 CA 数据的类,并创建了一个函数“Simulate”,它根据火在树上蔓延并留下空白空间的规则更新单元格。基于给定的概率,空白空间被替换为树。

有一个问题,我的函数似乎将规则应用于当前时间数据持有者,而不是之前的时间数据持有者。我已将prevstate = self.state 设置为上一次迭代的临时数据持有者,但运行小型测试我发现它给出的结果与我根本没有包含这一行一样。我做错了什么?

import numpy as np
import random
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap, colorConverter
from matplotlib.animation import FuncAnimation

#dimentions:
x = 10
y = 10

lighting = 0  #set to 0 for testing
grow = 0.3


#parameter values
empty = 0
tree = 1
fire = 2

random.seed(1)

#CA Rule definition
def update(mat, i, j, lighting, grow, prob):
    if mat[i, j] == empty:
        if prob < grow:
            return tree
        else:
            return empty
    elif mat[i, j] == tree:
        if max(mat[i-1, j], mat[i+1, j], mat[i, j-1], mat[i, j+1]) == fire:
            return fire
        elif prob < lighting:
            return fire
        else:
            return tree
    else:
        return empty


########## Data Holder
class Simulation:
    def __init__(self):
        self.frame = 0
        #self.state = np.random.randint(2, size=(x, y)) commented out for testing
        self.state = np.ones((x, y))
        self.state[5, 5] = 2  #initial fire started at this location for testing

    def updateS(self):
        prevstate = self.state    #line of code i think should be passing previous iteration through rule

        for i in range(1, y-1):
            for j in range(1, x-1):
                prob = random.random()
                self.state[i, j] = update(prevstate, i, j, lighting, grow, prob)

    def step(self):
        self.updateS()
        self.frame += 1


simulation = Simulation()
figure = plt.figure()

ca_plot = plt.imshow(simulation.state, cmap='seismic', interpolation='bilinear', vmin=empty, vmax=fire)
plt.colorbar(ca_plot)
transparent = colorConverter.to_rgba('black', alpha=0)
#wall_colormap = LinearSegmentedColormap.from_list('my_colormap', [transparent, 'green'], 2)


def animation_func(i):
    simulation.step()
    ca_plot.set_data(simulation.state)
    return ca_plot

animation = FuncAnimation(figure, animation_func, interval=1000)
mng = plt.get_current_fig_manager()
mng.window.showMaximized()
plt.show()

欢迎任何关于实现 CA 的更好方法的 cmets!

【问题讨论】:

    标签: python python-3.x class cellular-automata


    【解决方案1】:

    Python 赋值是指针...所以当你更新 self.state 时,prevstate 也会更新。

    我希望你设置为:

    prevstate = copy.copy(self.state)
    

    这应该可以解决您的问题。

    Copy docs

    【讨论】:

    • 非常感谢!澄清一下,我的问题是prevstate 指向self.state,它正在更新并且在迭代过程中始终与self.state 相同?
    • 没问题。想起来更像。有一个数组。该行:prevstate = self.state 将两个变量设置为指向同一个数组。但仍然是一个数组。 Copy.copy() 将 2 个数组分配给 2 个变量。
    【解决方案2】:

    正如 jabberwocky 正确指出的那样,您的问题是 prevstate = self.state 行使 prevstate 成为对与 self.state 相同的 numpy 数组的新引用,因此修改其中一个的内容也会修改另一个。

    与在每次迭代时复制数组不同,一个稍微更有效的解决方案是预先分配两个数组并交换它们,如下所示:

    class Simulation:
        def __init__(self):
            self.frame = 0
            self.state = np.ones((x, y))
            self.state[5, 5] = 2
            self.prevstate = np.ones((x, y))  # <-- add this line
    
        def updateS(self):
            self.state, self.prevstate = self.prevstate, self.state  # <-- swap the buffers
    
            for i in range(1, y-1):
                for j in range(1, x-1):
                    prob = random.random()
                    self.state[i, j] = update(self.prevstate, i, j, lighting, grow, prob)
    

    我说“稍微”是因为您真正节省的只是一个 numpy 数组副本和垃圾收集器的一些工作。然而,如果你足够优化你的内部状态更新循环——也许例如使用numba 实现 CA 规则——额外的数组副本的相对成本将开始显着。无论如何,使用这种“双缓冲”方法并没有真正的缺点,所以这是一个很好的习惯。

    【讨论】:

    • 谢谢,关于 numba 的精彩提示。您的编辑运行速度更快!您能否解释一下交换缓冲区的行的语法背后的逻辑?我不明白 1. 如何使用逗号,或者设置self.prevstate = self.prevstate 如何更新任一数组?
    • 这是一个使用tuple unpackingcommon idiom to swap variables in Python。逗号的优先级高于赋值运算符,因此解析为(state, prevstate) = (prevstate, state)。 (请注意,it doesn't work for numpy array slices。)
    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    相关资源
    最近更新 更多