我撰寫了一個小代碼來使用滲透進行相變模擬。這個視頻解釋了整個原理:https ://www.youtube.com/watch?v= a-767WnbaCQ(順便說一句,我看過的最好的數學視頻之一)。為了理解代碼,恐怕您必須先觀看視頻的前 5 分鐘。
下面是對代碼的快速解釋: 陣列main(我猜它的名字很可怕)被初始化為一個空的二維陣列。陣列的每個索引代表一個節點。該函式為您輸入group的每個節點(索引)找到一個“組”(一種顏色,一個階段) 。main為此,它會檢查到另一個節點的鏈接是否處于活動狀態,如果該節點不屬于組,則將其添加到組中并對該節點重復該操作。main代碼中的組由陣列中的唯一編號表示。鏈接由兩個陣串列示:connections_horizontal和connections_vertical。
該代碼在 p>0.5 時作業正常,但在 p<0.5 時開始做一些不穩定的事情。很容易看出代碼必須經過的遞回量是巨大的。如果只有一個階段(一種顏色),則遞回深度的大小為 ^2。在我強制代碼更改最大遞回深度之前,我遇到了堆疊溢位錯誤并且代碼崩潰了(在低 p 處)。現在,代碼只因 p 值較低而停止(沒有任何錯誤訊息)。我的猜測是,不知何故,python 只是在某個遞回深度處停止(在低 p 時,你有更大的階段,所以遞回深度更大)。有誰知道為什么?如果代碼令人困惑,我提前道歉(我盡力評論它)。提前感謝任何有勇氣閱讀/觀看視頻的人。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import sys
np.random.seed(0)
size=200
x=size**2
sys.setrecursionlimit(x)
main=np.zeros((size,size)) #where everything happens, every index in main is a point on the plane
connections_horizontal=np.random.rand(size-1,size) #horizontal connections between every points in main
connections_vertical=np.random.rand(size,size-1) #vertical connections between every points in main
p=0.5 #parameter of percolation
def group(array,index,grp_nbr,p): #index of point for which we want to find the group, the group number (to distinguish the groups), parameter p (percolation)
array[index]=grp_nbr
# 1: find if the neighbouring connection is active
# 2. if the connection is active, put the neighbouring point in the same group
# 3. for every new point, repeat the procedure until either no connections, or every neighbour is in the same group
if index[0]<size-1: #checking connections to the right
if connections_horizontal[index]>p: #if connection is active
if array[index[0] 1,index[1]]!=grp_nbr: #and neighbour is not in the same group
array[index[0] 1,index[1]]=grp_nbr #adding the point to the group
group(array,(index[0] 1,index[1]),grp_nbr,p) #repeat procedure for new point (recursion)
if index[1]<size-1: #checking the connections up
if connections_vertical[index]>p:
if array[index[0],index[1] 1]!=grp_nbr:
array[index[0],index[1] 1]=grp_nbr
group(array,(index[0],index[1] 1),grp_nbr,p)
if index[0]>0: #checking the connections to the left
if connections_horizontal[index[0]-1,index[1]]>p:
if array[index[0]-1,index[1]]!=grp_nbr:
array[index[0]-1,index[1]]=grp_nbr
group(array,(index[0]-1,index[1]),grp_nbr,p)
if index[1]>0: #checking the connections down
if connections_vertical[index[0],index[1]-1]>p:
if array[index[0],index[1]-1]!=grp_nbr:
array[index[0],index[1]-1]=grp_nbr
group(array,(index[0],index[1]-1),grp_nbr,p)
for i in range(size): #finding a group for every point on the plane
for j in range(size):
if main[i,j]==0:
group(main,(i,j),np.random.rand(1),p)
plt.imshow(main,cmap='rainbow',interpolation='none')
plt.savefig('test.png')
plt.show()
uj5u.com熱心網友回復:
該問題似乎與您的演算法或p特定值無關(盡管這也可以進行一些改進,但這不是問題的原因)。相反,它與您一起玩遞回限制,這會影響imshow.
嘗試運行這個:
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.setrecursionlimit(7 ** 2)
main = np.array([[0.5666014542065752, 0.5666014542065752, 0.2653894909394454, 0.2653894909394454, 0.2653894909394454, 0.5232480534666997, 0.09394051075844168], [0.5666014542065752, 0.5666014542065752, 0.2653894909394454, 0.2653894909394454, 0.5232480534666997, 0.5232480534666997, 0.5759464955561793], [0.5666014542065752, 0.5666014542065752, 0.2653894909394454, 0.2653894909394454, 0.5232480534666997, 0.5232480534666997, 0.5759464955561793], [0.2653894909394454, 0.9292961975762141, 0.2653894909394454, 0.2653894909394454, 0.5232480534666997, 0.5232480534666997, 0.5759464955561793], [0.2653894909394454, 0.2653894909394454, 0.2653894909394454, 0.2653894909394454, 0.5232480534666997, 0.5232480534666997, 0.5759464955561793], [0.2653894909394454, 0.2653894909394454, 0.2653894909394454, 0.2653894909394454, 0.31856895245132366, 0.5232480534666997, 0.6674103799636817], [0.2653894909394454, 0.2653894909394454, 0.2653894909394454, 0.2653894909394454, 0.31856895245132366, 0.13179786240439217, 0.13179786240439217]])
plt.imshow(main,cmap='rainbow',interpolation='none')
plt.savefig('test.png')
plt.show()
如果我使用以下命令運行您的腳本,則會生成該 7x7 陣列:
size = 7
p = 0.5
您會注意到,即使您沒有涉及任何代碼,它也會導致遞回錯誤。問題是內部引起的imshow。甚至plt.imshow(main)會觸發問題。
嘗試提高遞回限制,問題就消失了:
sys.setrecursionlimit(52)
對于本例來說,這是一個恰好足夠的值 - 但它大于size ** 2,計算結果為 49size = 7.
如果imshow沒有引起麻煩(您在示例中共享的值可能就是這種情況),則 的值p本質上不是問題。例如,試試這個:
size=50
x=size**3
p=0.2
完全沒問題 - 但是將大小增加到 60 并且它失敗了(無論如何在我的機器上)。問題是您的演算法效率非常低,并且p可能會超過低遞回深度,或者只是導致系統耗盡其他資源。遞回深度受到限制是有原因的:遞回是資源密集型的,提高數量并不會神奇地為您帶來更多資源。
您可以遞回撰寫的任何內容也可以迭代撰寫 - 如果您覺得您擁有的演算法接近您的需要,您應該嘗試實作非遞回解決方案。但是可能有更有效的解決方案可以遞回地作業。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/515665.html
