ABM(Agent-based modeling)是一种用来模拟具有自主意识的智能体(独立个体或共同群体,例如组织、团队)的行动和相互作用的计算模型,通过图像展示和评估智能体在系统整体中的作用。
一个ABM模型是一个计算机模拟系统,包括以下的要素 :
ABM模型的优点之一就是易于编译,并相对简单。使用基于对象的编译语言(OOP),将代码分类成不同的对象,每个对象具有不同的功能,且每个对象是基于一个模板“类”。因此从每个类可以创建多个对象,并改变其内在状态使其具有不同的功能。这种编程语言尤其适合ABM模型,在ABM模型中,我们使用Agent class
来表示类,并创建不同属性的Agents
。
一个典型的ABM模型有以下部分组成:
一个agent class
(类)表示agent的状态和属性(名字,年龄,位置,等等),以及一部分可运行的代码来指定agent的运动规则。这部分代码被定义为agent
的方法,被写在定义agent
的类中。例如,大多数具有位置变量的agent
通常会有move的方法或函数。在模型运行时会移动agent的位置。
下面是一个agent框架的简单示例:
import random
#定义agent 类
class Sheep():# 使用 __init__函数来初始化模型
'''
羊随机移动,吃草 (环境),和其他羊互动
'''
#self 作为对象的初始参数
def __init__ (self, x, y, environment,agents, neighbourhood):
self.x = x #x,y坐标
self.y = y
self.environment = environment #环境变量
self.store = 0
self.agents = agents #agents 列表
self.neighbourhood = neighbourhood
#使用randint函数创建一系列0到300的随机整数
if x == None:
self.x = random.randint(0,300)
else:
self.x = x
if y == None:
self.y = random.randint(0,300)
else:
self.y = y
#使agent根据一个随机地数字移动
def move(self):
if random.random() < 0.5:
self.x = (self.x + 1) % 300
else:
self.x = (self.x - 1) % 300
if random.random() < 0.5:
self.y = (self.y + 1) % 300
else:
self.y = (self.y - 1) % 300
def eat(self): #和环境互动(羊吃草)
if self.environment[self.y][self.x] > 10:
self.environment[self.y][self.x] -= 10
self.store += 10
#和相邻agent交换信息
def share_with_neighbours(self,neighbourhood):
for agent in self.agents:
dist = self.distance_between(agent) #调用 distance_between
if dist <= self.neighbourhood: #当距离小于等于neighborhood
sum = self.store + agent.store
ave = sum /2
self.store = ave #将值保存在self.store
agent.store = ave
print("sharing " + str(dist) + " " + str(ave))#to test sharing
#计算当前agent和相邻agent的距离
def distance_between(self, agent):
return (((self.x - agent.x)**2) + ((self.y - agent.y)**2))**0.5
一个Model class
模型类调用agent的函数来使他们行动。通常我们会使agent
们移动一定的次数,然后停止运行并观察模型的状态。或者可以定义一个模型停止运行的条件,使模型运行直到某一条件达到满足。
有上面两个文件足以组成一个简单的agent based model
,agent
将会依据自身定义的行动规则来行动,但目前它们不会进行互动。为了使agent互动,通常情况下会在ABM模型中设置某种环境,可以是简单的数组,或是计算机网络等。每个agent
也会包含一部分能够与其互动的agent
列表(neighbors
),可以是全体agent
,也可以是一部分临近位置的agent
列表。
下面是简单模型示例:
import matplotlib
matplotlib.use('TkAgg')
import random
import operator
import numpy as np
import matplotlib.pyplot
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import agentframework
import requests
import bs4
import matplotlib.animation as animation
import tkinter
#变量初始化
num_of_agents = 10 #初始化agent的数量
num_of_wolves = 3
num_of_iterations = 50 #i初始化迭代次数
agents = [] #创建空列表
neighbourhood = 20# #初始化neighbourhood个数
#读取环境数据(可以是栅格数据)
f = open("in.txt")
environment=[] #设置空列表写入环境数据
for row in f:
parsed_row = str.split(row,",") #按照","分隔数据
rowlist = [] #设置新行
for value in parsed_row:
rowlist.append(float(value)) #将字符串转化为浮点型数据
environment.append(rowlist) #将rowlist加入环境
f.close()
#初始化agent数据
r = requests.get('网络数据来源,可以是矢量点要素,面要素等')
#使用request获取网络数据
content = r.text
soup = bs4.BeautifulSoup(content, 'html.parser')#使用 bs4
td_ys = soup.find_all(attrs={"class" : "y"})
td_xs = soup.find_all(attrs={"class" : "x"})
r.close
# 创建 fig和ax变量来进行动画展示
fig = matplotlib.pyplot.figure(figsize=(7, 7))
ax = fig.add_axes([0, 0, 1, 1])
carry_on=True
# 添加sheep类的对象
for i in range(num_of_agents):#遍历所有agent
y = int(td_ys[i].text) #将x,y坐标值赋给agent
x = int(td_xs[i].text)
agents.append(agentframework.Sheep(x, y, environment,agents, neighbourhood))
#定义update函数来进行可视化
def update(frame_number):
fig.clear()
global carry_on
for i in range(num_of_agents):
agents[i].eat()
agents[i].move()
agents[i].share_with_neighbours(neighbourhood)
#画出agent的散点图和环境
for i in range(num_of_agents):
matplotlib.pyplot.xlim(0, 300)
matplotlib.pyplot.ylim(0, 300)
matplotlib.pyplot.imshow(environment)
matplotlib.pyplot.scatter(agents[i].y,agents[i].x,color="white")
#print(agents[i].x,agents[i].y)
#定义模型的停止
def gen_function(b = [0]):
a = 0
global carry_on
while (a < num_of_iterations) & (carry_on) :
yield a
a = a + 1
def run():# 定义运行模型的函数
animation = matplotlib.animation.FuncAnimation(fig, update, frames=gen_function, repeat=False)
canvas.draw()
root = tkinter.Tk()
root.wm_title("Model")
canvas = matplotlib.backends.backend_tkagg.FigureCanvasTkAgg(fig, master=root)
canvas._tkcanvas.pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=True)
menu_bar = tkinter.Menu(root)
root.config(menu=menu_bar)
model_menu = tkinter.Menu(menu_bar)
menu_bar.add_cascade(label="Model", menu=model_menu)
model_menu.add_command(label="Run model", command=run)
tkinter.mainloop()