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]]
我正在尝试使用简单的 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]]