Python - numpy 数组 - 阿贝尔沙堆

Python - numpy arrays - Abelian sandpile

我正在尝试使用简单的 numpy 数组来构建阿贝尔沙堆模型。
当 'pile' 为 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 )。

使用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