【问题标题】:Python - numpy arrays - Abelian sandpilePython - numpy 数组 - 阿贝尔沙堆
【发布时间】:2021-05-18 18:52:41
【问题描述】:

我正在尝试使用简单的 numpy 数组来制作阿贝尔沙堆模型。
当“堆”为 4 >= 时,它会在其邻居中崩溃。
我了解“重力”的工作原理,但我想不出一种方法。
这是制作我的数组的代码:

import numpy as np
spile = np.zeros((5, 5), dtype=np.uint32)
spile[2, 2] = 16

这给了我以下信息:

array([[ 0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0],
       [ 0,  0, 16,  0,  0],
       [ 0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0]], dtype=uint32)

现在,我需要执行这些计算步骤的“重力”代码:

array([[ 0,  0,  0,  0,  0],
       [ 0,  0,  4,  0,  0],
       [ 0,  4,  0,  4,  0],
       [ 0,  0,  4,  0,  0],
       [ 0,  0,  0,  0,  0]], dtype=uint32)


array([[ 0,  0,  1,  0,  0],
       [ 0,  2,  1,  2,  0],
       [ 1,  1,  0,  1,  1],
       [ 0,  2,  1,  2,  0],
       [ 0,  0,  1,  0,  0]], dtype=uint32)

最后一个数组是我想要得到的最终结果。
我不是想让你们为我编写代码,我只是需要一些想法,因为我从来没有做过这样的事情(但如果你是那种人,请随时提供代码:p)。

【问题讨论】:

    标签: python numpy cellular-automata


    【解决方案1】:

    使用np.divmod 确定细胞在哪里翻滚以及翻滚的程度。然后使用数组切片将跌落的数量转移并重新添加到沙堆中。

    import numpy as np      
    spile = np.zeros((5, 5), dtype=np.uint32)
    spile[2, 2] = 16         
    
    def do_add( spile, tumbled ):
        """ Updates spile in place """
        spile[ :-1, :] += tumbled[ 1:, :] # Shift N and add                 
        spile[ 1:, :] += tumbled[ :-1, :] # Shift S   
        spile[ :, :-1] += tumbled[ :, 1:] # Shift W
        spile[ :, 1:] += tumbled[ :, :-1] # Shift E
    
    def tumble( spile ):
        while ( spile > 3 ).any():
            tumbled, spile = np.divmod( spile, 4 )
            do_add( spile, tumbled )
            # print( spile, '\n' )  # Uncomment to print steps
        return spile
    
    print( tumble( spile ) ) 
    # or tumble( spile ); print( spile )
    
    # [[0 0 1 0 0]
    # [0 2 1 2 0]
    # [1 1 0 1 1]
    # [0 2 1 2 0]
    # [0 0 1 0 0]]
    

    未注释的打印语句打印这些结果

    [[0 0 0 0 0]
     [0 0 4 0 0]
     [0 4 0 4 0]
     [0 0 4 0 0]
     [0 0 0 0 0]] 
    
    [[0 0 1 0 0]
     [0 2 0 2 0]
     [1 0 4 0 1]
     [0 2 0 2 0]
     [0 0 1 0 0]] 
    
    [[0 0 1 0 0]
     [0 2 1 2 0]
     [1 1 0 1 1]
     [0 2 1 2 0]
     [0 0 1 0 0]] 
    

    http://rosettacode.org/wiki/Abelian_sandpile_model

    【讨论】:

    • 非常感谢!从中学到了很多东西,如果只打印最后一个结果,你会怎么做?
    • 将 print 语句放在 while 循环之外。我把它放进去看看发生了什么。我已经改变了答案。删除您不需要的任何打印语句。您可以将 while 循环放在一个函数中,以使用任何 spile 运行并返回结果。
    • 不错!是否有可能只有通过调用 spile var 才能完成工作?就像 do_the_work(sile) 然后我只需要打印(sile) 就可以得到最后一个?
    • 将 while 循环转换为函数。你看过罗塞塔代码吗?答案中的链接。
    • 不知道这个网站,非常感谢您的工作!
    猜你喜欢
    • 1970-01-01
    • 2013-08-07
    • 2014-11-15
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    相关资源
    最近更新 更多