用python编译ABM(Agent-based modeling)模型简介

邢弘业
2023-12-01

用python编译ABM(Agent-based modeling)模型简介

ABM(Agent-based modeling)是一种用来模拟具有自主意识的智能体(独立个体或共同群体,例如组织、团队)的行动和相互作用的计算模型,通过图像展示和评估智能体在系统整体中的作用。
一个ABM模型是一个计算机模拟系统,包括以下的要素 :

  • 一定数量的智能体agents (属于自定义模型的一部分)
  • 一定数量的智能体之间的关系
  • 一个模拟智能体的行为和互动的框架

ABM模型的优点之一就是易于编译,并相对简单。使用基于对象的编译语言(OOP),将代码分类成不同的对象,每个对象具有不同的功能,且每个对象是基于一个模板“类”。因此从每个类可以创建多个对象,并改变其内在状态使其具有不同的功能。这种编程语言尤其适合ABM模型,在ABM模型中,我们使用Agent class来表示类,并创建不同属性的Agents
一个典型的ABM模型有以下部分组成:

Agentframework

一个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

一个Model class模型类调用agent的函数来使他们行动。通常我们会使agent们移动一定的次数,然后停止运行并观察模型的状态。或者可以定义一个模型停止运行的条件,使模型运行直到某一条件达到满足。

有上面两个文件足以组成一个简单的agent based modelagent将会依据自身定义的行动规则来行动,但目前它们不会进行互动。为了使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()

 类似资料: