小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

[計(jì)算模擬]森林火災(zāi)模擬.2:ABM編程基礎(chǔ):用agentpy實(shí)現(xiàn)經(jīng)典元胞自動(dòng)機(jī)的生命游戲

 godxiasad 2024-12-18 發(fā)布于北京

很長,反著你也不看,點(diǎn)個(gè)贊意思下就行

——前文再續(xù),書接上一回

ABM編程基礎(chǔ):元胞自動(dòng)機(jī)

在介紹森林火災(zāi)模擬的代碼之前,我們先簡單介紹一下ABM編程的基礎(chǔ)。
ABM是Agent-Based Modeling的縮寫,是一種基于多智能體的建模方法,它將現(xiàn)實(shí)世界中的實(shí)體(如人、動(dòng)物、物體等)抽象為計(jì)算機(jī)程序中的對(duì)象(Agent),并通過模擬這些對(duì)象之間的相互作用來研究復(fù)雜系統(tǒng)的行為。
在ABM中,每個(gè)對(duì)象都有自己的屬性和行為,這些屬性和行為可以通過編程來模擬。通過模擬多個(gè)對(duì)象之間的相互作用,我們可以研究復(fù)雜系統(tǒng)的行為,例如生態(tài)系統(tǒng)、社會(huì)系統(tǒng)、金融系統(tǒng)等。
另外,ABM實(shí)際上是元胞的一種衍生形式,元胞自動(dòng)機(jī)作為非線性模擬的奠基理論,在整個(gè)模擬計(jì)算領(lǐng)域中都起到了一個(gè)object的作用,ABM也是在元胞自動(dòng)機(jī)的基礎(chǔ)上進(jìn)行了擴(kuò)展和延生。
本著磨刀不誤砍柴工的原則,我們先了解一下元胞自動(dòng)機(jī)的基礎(chǔ),這些基礎(chǔ)也可以用在ABM中。

元胞自動(dòng)機(jī)

元胞自動(dòng)機(jī) (CA)是一種離散的、基于網(wǎng)格的計(jì)算模型,它由一組規(guī)則定義,這些規(guī)則決定了每個(gè)單元的狀態(tài)如何在時(shí)間上演變。CA的主要特點(diǎn)是其簡單性和可擴(kuò)展性,它可以用于研究許多不同類型的系統(tǒng),例如生物、化學(xué)、物理、社會(huì)等。
元胞自動(dòng)機(jī)最早是由約翰·馮·諾依曼在1940年提出的,它的主要思想是將一個(gè)復(fù)雜的系統(tǒng)分解成一組簡單的規(guī)則,這些規(guī)則可以通過計(jì)算機(jī)程序來模擬。

最知名的元胞自動(dòng)機(jī)是康威的生命游戲(Game of Life),它由英國數(shù)學(xué)家約翰·何頓·康威在1970年提出。康威的生命游戲是一個(gè)零玩家游戲,它的規(guī)則非常簡單,只需要考慮三個(gè)因素:
當(dāng)前細(xì)胞的狀態(tài)、周圍細(xì)胞的狀態(tài)和周圍細(xì)胞的數(shù)量。
根據(jù)這三個(gè)因素,康威的生命游戲可以得出當(dāng)前細(xì)胞的下一個(gè)狀態(tài)。

元胞自動(dòng)機(jī)的生命游戲非常簡單,但是卻可以模擬出非常復(fù)雜的行為,例如細(xì)胞的分裂、融合、消亡等。你的結(jié)果也會(huì)和你的初始條件有關(guān),系統(tǒng)會(huì)根據(jù)規(guī)則,自動(dòng)演化成各種形態(tài)。

元胞自動(dòng)機(jī)建模的要是有如下四個(gè):

空間網(wǎng)格

元胞在空間中分布的空間格點(diǎn)的承載介質(zhì),一般是個(gè)二維的網(wǎng)格,因?yàn)榫W(wǎng)格更容易實(shí)現(xiàn),也更容易計(jì)算后面的鄰域。

鄰域

在元胞自動(dòng)機(jī)中,每個(gè)元胞都有一定數(shù)量的鄰居,這些鄰居可以是同一行、同一列、同一斜線上的相鄰元胞,也可以是不同行、不同列、不同斜線上的相鄰元胞。鄰居的數(shù)量取決于元胞的形狀和拓?fù)浣Y(jié)構(gòu)。這些元胞的鄰居可以用來計(jì)算元胞的狀態(tài),也可以用來更新元胞的狀態(tài)。

狀態(tài)集合

在元胞自動(dòng)機(jī)中,每個(gè)元胞都有一個(gè)狀態(tài),這個(gè)狀態(tài)可以是一個(gè)數(shù)字、一個(gè)字母、一個(gè)顏色等等。狀態(tài)集合是元胞的狀態(tài)的集合,它可以是一個(gè)有限的集合,也可以是一個(gè)無限的集合。狀態(tài)集合的大小取決于元胞的形狀和拓?fù)浣Y(jié)構(gòu)。

例如在生命游戲里面,狀態(tài)集合就是0和1,0代表死亡,1代表存活。
在森林火災(zāi)的模型里面,狀態(tài)集合也是0和1,0代表樹木,1代表被燃燒。

演化規(guī)則

最后一個(gè)是演化規(guī)則,這個(gè)是最重要的,也是整個(gè)模型的核心。在元胞自動(dòng)機(jī)中,演化規(guī)則是用來描述元胞狀態(tài)如何從一個(gè)狀態(tài)轉(zhuǎn)換到另一個(gè)狀態(tài)的。演化規(guī)則可以是一個(gè)簡單的規(guī)則,也可以是一個(gè)復(fù)雜的規(guī)則。
例如在生命游戲里面,演化規(guī)則就是:元胞旁邊的8個(gè)元胞中,如果有3個(gè)元胞是存活的,那么這個(gè)元胞就會(huì)變成存活的(元胞繁殖)。如果有2個(gè)元胞是存活的,那么這個(gè)元胞就會(huì)保持原來的狀態(tài)。如果少于2個(gè)元胞是存活的,或者多于3個(gè)元胞是存活的,那么這個(gè)元胞就會(huì)變成死亡的(過少或者過多都會(huì)死亡)
下面我來寫一個(gè)簡單的例子,來演示一下生命游戲:
先看效果:是用一個(gè)50 * 50的網(wǎng)格空間,隨機(jī)取10%的元胞是存活的,然后演化100次。
初始化狀態(tài):

存活的細(xì)胞是250,然后按照生命游戲的規(guī)則,進(jìn)行演化,第一次演化,細(xì)胞就死了一多半……

然后有一些位置的元胞,會(huì)進(jìn)入一個(gè)穩(wěn)態(tài),如下:

大家看我圈出來的幾個(gè)結(jié)構(gòu),這幾個(gè)結(jié)構(gòu)是穩(wěn)定的,只要不發(fā)生外部元胞的入侵,本身就不會(huì)再發(fā)生變化。
然后我們來看看后續(xù)的演變,發(fā)現(xiàn)外部的元胞入侵之后,就會(huì)發(fā)生變化,直接把之前的穩(wěn)定結(jié)構(gòu)給破壞了……
經(jīng)過100步的演變之后,最終變成了這個(gè)樣子:

整個(gè)過程還是比較有意思的,大家可以自己去試試。

全部演算過程如下:

注意,因?yàn)槲疫@里的初始化條件是隨機(jī)的,所以你運(yùn)行的結(jié)果在細(xì)節(jié)上可能和我的不一樣,但是整體的趨勢是一致的。

生命游戲的代碼實(shí)現(xiàn)

這里采用的是Python來進(jìn)行實(shí)現(xiàn)的,用的是一個(gè)很強(qiáng)大的ABM包,叫做agentpy。
這包不僅提供了abm的全套建模腳手架,而且還有可視化能力,老好用了,目的就是做出一個(gè)netlogo的平替。
安裝的時(shí)候,直接用pip安裝就可以了:
pip install agentpy
唯一問題是這個(gè)包自2021之后一個(gè)版本更新之后,就挺了兩年多了,雖然現(xiàn)在基礎(chǔ)功能足夠用了,但是沒有更新的東西的總是讓人覺得有點(diǎn)懸。
不過我們也就是用他的engine,所以更新不更新就不重要了。
import agentpy as ap

import matplotlib.pyplot as plt
import seaborn as sns
import IPython
# 解決繪圖中的中文亂碼問題
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 定義模型
class LifeGameModel(ap.Model):
def setup(self):
# 初始化參數(shù)
self.p = {
'size': 50,
'density': 0.1,
'steps': 100,
}

# 初始化細(xì)胞數(shù)量
cell_init_size = int(self.p['size'] * self.p['size'])
# 創(chuàng)建agent
cells = self.agents = ap.AgentDList(self, cell_init_size)

# 創(chuàng)建空間網(wǎng)格
self.space = ap.Grid(self, [self.p['size']] * 2, track_empty=True)
self.space.add_agents(cells, random=True, empty=True)

# 初始化細(xì)胞狀態(tài)
self.agents.condition = 0

# 隨機(jī)選擇一些細(xì)胞作為初始活細(xì)胞,選取數(shù)量為預(yù)設(shè)的密度
initial_live_cells = self.random.sample(self.agents, int(cell_init_size * self.p['density']))
for cell in initial_live_cells:
cell.condition = 1

def step(self):
# 計(jì)算規(guī)則:獲取所有細(xì)胞,然后計(jì)算每個(gè)細(xì)胞的鄰居的信息
#元胞旁邊的8個(gè)元胞中,
# 如果有3個(gè)元胞是存活的,那么這個(gè)元胞就會(huì)變成存活的。
# 如果有2個(gè)元胞是存活的,那么這個(gè)元胞就會(huì)保持原來的狀態(tài)。
# 如果少于2個(gè)元胞是存活的,那么這個(gè)元胞就會(huì)變成死亡的。
# 如果多于3個(gè)元胞是存活的,那么這個(gè)元胞就會(huì)變成死亡的
live_cells = self.agents.select(self.agents.condition > -1)
for live_c in live_cells:
live_neighbors = self.space.neighbors(live_c)
# 計(jì)算每個(gè)元胞的鄰居的信息,需要知道活著的鄰居的數(shù)量
live_neighbors_count = 0
for ne in live_neighbors.to_list():
if ne.condition ==1:
live_neighbors_count += 1

if live_neighbors_count < 2 or live_neighbors_count > 3:
live_c.condition = 0
elif live_neighbors_count == 3:
live_c.condition = 1
else:
live_c.condition = live_c.condition

if self.t >= self.p['steps']:
self.stop()

def end(self):
# 在模擬結(jié)束時(shí),打印最終的細(xì)胞狀態(tài)
print("Simulation ended. Final cell states:")
for cell in self.agents:
print(cell.condition, end=' ')
print()

# 可視化過程,agentpy內(nèi)置了seaborn的擴(kuò)展,可以自動(dòng)生成動(dòng)態(tài)可視化效果
def animation_plot(model, ax):
attr_grid = model.space.attr_grid('condition')
color_dict = {0:'#F3F3F3', 1:'#d62c2c'}
ap.gridplot(attr_grid, ax=ax, color_dict=color_dict, convert=True)
ax.set_title(f"生命游戲模擬\n"
f"模擬步數(shù): {model.t}, 存活的細(xì)胞數(shù)量: "
f"{len(model.agents.select(model.agents.condition == 1))}")

fig, ax = plt.subplots()
model = LifeGameModel()
animation = ap.animate(model, fig, ax, animation_plot)
IPython.display.HTML(animation.to_jshtml(fps=15))

我這里是用jupyter來進(jìn)行演示的,所以沒有main函數(shù),如下所示:




今日福利

有同學(xué)推薦我在后面加福利,作為我的logo……

真正的男生減速帶:

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多