Repast
Javacswarm 脚本编译模型,用 Javaswarm 脚本运行模型。
作为一个开源项目,在遵循 GNU 协议的基础上,所有人都可以分享 Swarm 的资料,
这也意味着所有人都可以自由地奉献自己的智慧。因此,对 Swarm 感兴趣的研究人员可以
结合自己的研究需要和建模经验,提出相关的设想,参与到 Swarm 的研究中去,本节后面
的资源链接中列出了相关网址。
Repast(Recurslve Porous Agent Simulation Toolkit)是芝加哥大学社会科学计算研究中
心研制的多主体建模工具,她提供了一系列用以生成、运行、显示和收集数据的类库,并能
对运行中的模型进行“快照”,记录某一时刻模型的当前状态,还可以生成模型运行过程中
状态动态演化的视频资料。Repast 从 Swarm 中借鉴了不少的设计结
构和方法,所以常常称 Repast 为类 Swarm 的架构。
一、设计思想及目标
由于 Swarm 对建模者来说还是有些过于复杂,Repast 项目希望提供一系列简化 Swarm
模型开发的 Java 类库。然而,随着 JavaSwarm①版本的推出,这种仅仅希望作为 Swarm 的
Java 扩展的想法很快就被摒弃了。设计者们开始尝试使用 Java 语言设计一个完全独立的模
型平台,而不再是从 Swarm 中做一些现成的提取有外围的包装。
RePast 项目拟订了三个设计目标:使用方便、容易学习和容易扩展。设计者通过让模
拟软件的底层结构具备抽象性、可扩展性以及“良好”的表现来实现这些目标。
1.抽象性
RePast 的设计借鉴了很多别的主体建模软件,汲取了各个软件中最优秀的设计思想。
类库设计时充分应用了面向对象和设计模式的思想,因此 RePast 的整个类库的结构非常明
晰优美。类库提供了普通常用的底层抽象库(如安排时序、显示、数据收集等类库),类库
还提供了一些用以建立表层元素的常用类。这些类可直接使用,也可以根据需要继承和扩展。
与 Swarm 一样,Repast 还设计了一些关键的抽象数据结构,其中一些结构直接模仿了
Swarm,如时序表等。
2.可扩展性
关键数据结构的抽象设计让 Repast 具备了可扩展的能力。
为了充分从 Swarm 的抽象结构中获得方便,Repast 继承了 Swarm 时间测试的设计方法,
这对于提高其扩展性十分有利。此外,Repast 还引人了设计模式中的一些经典抽象结构,使
得其扩展性得到进一步的提高。如用设计模式中的综合模式实现时序的安排机制(时序表对
象和各种行为类),由于这种综合模式允许终端用户在建模编程时,能够对单独行为和复合
行为进行统一编码处理,因此模型中的时序安排机制便变得很清晰直观,且易于扩展。
3.“良好” 的表现能力
表现能力是指应用该平台建立应用研究模型时,该平台能否有效地适用于实际应用领
域;如能否有效地用平台的开发接口把问题表述成计算机模型,模型能否在可承受的效率开
销下运行,等等。“良好”的表现能力是指:在不影响别的优越特性前提下,可接受的表现
能力。当表现能力的最优化不是设计的主要目标时,设计者的注意力应集中在如何减少对象
的生成开销,以达到一种能够接受的运行速度。RePast 可以算得上比较好地完成了这一目标,
甚至有所超越,相比其他模拟软件平台,Repast 提供了更好的表现能力。此外,随着 Java
虚拟机性能的提高,Repast 模型的速度也会得到改善。
虽然建模时仍然必须学习一门程序设计语言:Java 或 Python,但 Repast 仍然是一款相
当方便易用的软件。用 Java 作为实现语言避免了内存泄漏的问题,且 Java 的跨平台特性使
得在不同的平台上的安装和使用也很简便。从 Repast 3.0 版开始,模型的设计语言有了更
多的选择;Repast 3.0 提供了 Java 版、Python 版和 DotNet 版三个版本让最终用户选择安
装,除 Java 和 Python 外,还可以应用 Dot-Net 框架下的各种程序设计语言编制模型。
_、Repast 的体系结构
RePast 建模相当于设计一个状态机,状态机的核心状态是模型中所有成员的集体状态
属性集合。成员则分为底层结构和表层结构。底层结构是各种各样用于运行模型、显示和收
集数据等架构的机制;表层结构是设计者创立的模型。底层结构的状态就是模型的种种显示
状态、数据收集对象的状态等等;表层结构的状态指模型的描述状态,比如所有主体变量的
当前值,模拟环境空间的当前状态值,或他们运行的空间以及别的可能有的各种表层对象(例
如聚合“协同”的对象统计值等)。在这种状态机模式下,所有对状态机的改变都通过同一
对象界面接口来实现,这个对象界面接口是 SirnModellmnl 类。这种设计为建模者减轻了学
习负担,也简化了在工具包的功能不足时的扩展编程。
通过继承 SimModellmpl 来建模,在用户模型与 SimModellmpl 中间一般还会有一个
Template 结构。各部分间的路径和层次关系参见图 4—12 与图 4—13。图 4—12 的目录结构
图显示了 Repast 自带文件、Template 及用户利用 Repast 建立的模型在计算机中存放的路径
关系。图 4—13 层次关系图显示了一个典型的继承自 SimMod(,IImpl 的模型和 Template
结构间的层次关系。
三、类库简介
Repast 共有近 130 个类,封装在 6 个库中,下面是 6 个类库的简要介绍。
1.分析库 Analysis
分析库中的类是用来聚集、记录数据以及建立数据表。通过使用 DataRecorder 类,建
模者能将收集到的数据分类整理,并将这些数据以表格格式写人文件。
2.引擎库 Engine
引擎类负责建立、操纵和运行模型。SimModel 接口(Interface)是 Repast 中所有模型
的超类(继承树状图表示中的根类)。作为 SimModel 一个子类,SimModellmp 类可以作为
绝大多数用 Repast 创立的模型的基类。控制类(Base Controller,Controller,Batch-Controller)
负责通过图形用户界面处理用户交互,或通过批处理参数文件自动处理交互。时序表及相关
行为类主要用来改变模型中的状态。
3.博弈库 Games
博弈库中包含了一些建立对策论模型(比如囚徒困境等)所用的基本类。
4.因形用户界面库 GUI
GUI 类负责实现模型的图形可视化,包括对图形界面显示的快照功能以及制作模型运
行的活动录像(影像资料,quicktime 格式)。各种。Dsplay 类与 Space 空间库中的类协同工
作,把空间位置关系的抽象和空间关系的显示分离开来,可以针对不同的空间特征设计不同
的可视化显示方案。通过一个显示界面(Displaysurface),。Painter 类处理这些空间库在屏
幕上的显示,而显示界面本身就能够完成对所显示对象的探测。对可视化的模拟对象点击鼠
标左键,就会弹出一单独舷窗口,其中显示点中主体的当前状态。
5.空间库 Space
空间类是表述各种空间的基础容量类(在通常的计算机术语中,容量类是指以包含其
他类作为自己的元素的类,比如数组、集合、链表等)。空间类包括二维表空间(有边界)、
圆环面空间(上下无边界)等。这些空间类允许在 x,y 坐标轴的基础上对对象进行括人和
检索。空间库中还包含了一些节点类和链接类,以方便建立基于网络的模型。空间类和在
GUI 库中的显示类协同操作,以实现空间和对象的可视化。
在 RePast 中,空间(sPaces)的存在有两种目的:(1)作为空间型主体的基类,比如
附带的示例模型 Sugarscape and Lif;,中的 SugarSPace 或 InfiniteLifeSPace;(2)作为主体
的容器,定义 iE 体间的空间位置关系。
RePast 提供以下空间类:
Diffuse2D 二维散射的离散近似。空间本身是一个上下左右都闭合的圆环形的(toriodal)
网格,格子都有两层。
Obect2DGrid 离散的二维网格,单元格中有对象。
Object2DTorus 离散的二维圆环面,单元格中有对象。
Multl2DGrid 二维网格,单元格中可以包括一个以上的对象。每个单元格中的对象的顺
序不确定。
OrdMMulti2DGrid 二维网格,单元格中可以包括一个以上的对象。每个单元格中的对
象的顺序都是先进先出。
Multi2DTOrus 二维圆环面,单元格中可以包括一个以上.的对象。每个单元格中的对
象的顺序不确定。
OrderedMulti2DTorus 二维圆环面,单元格中可以包括一个以上的对象。每个单元格中
对象的顺序都是先进先出。
Diffuse2DHexagoual 二维散射的离散近似。空间本身是一个 to-riodal(甜甜圈形的)
六边形网格,格子都有两层。
Object2DHexaeonalGrid 离散的二维六边形网格,单元格中有对象。
ONeconHexgonalTorus 离散的二维六边形圆环面,单元格中有对象。
Multi2DHexalGrid 二维六边形网格。单元格中可以包括一个以上的对象,每个单元格
中对象的顺序不确定。
OrderedMulti2DRexagonalGrid 二维六边形网格。单元格中可以包括一个以上的对象,
每个单元格中对象的顺序都是先进先出。
MultiZDHexasonaITorus 二维六边形圆环面。单元格中可以包括一个以上的对象,每个
单元格中对象的顺序不确定。
OrderedMultiZDHexagonalTorus 二维六边形圆环面。单元格中可以包括一个以上的对
象,每个单元格中对象的顺序都是先进先出。
RasterSPace 表现地理数据的二维网格。每个单元格可以包含一个对象,在这个空间中
移动可以用距离、坐标系或者离散的单元格位置。
更多空间类信息可参见 Repast 的 API 文档。另外值得注意的是,网络空间与空间是完
全不同的,将在 4.3.6 节网络模型中介绍网络空间。此外,前面提到的六边形指的是单元
格的形状,所以在六边形的网格或者回环面中,每个单元格都是六边形的,因此有六个邻居。
这些空间类都有通过坐标系对 item 进行插人和删除的方法,还有能返回相邻单元格的
item 列表的方法,以及找出相邻单元格中最大或最小 item 的方法等。至于什么是最大、最
小,可以由用户自己定义。
用空间类存放主体的坐标方便了增删主体和排序主体的操作,也方便针对一个主体的
邻居空间进行查询。通常在一个特定空间中,所有的主体都由该空间的实例变量负责主体位
置的部署。如在 build-Modlel 方法中,可能有下述代码:
Object2DGrid space =new Object2DGrid(spaceWidth,spaceHeight);
for(int i=0;i
单元格是否被占用,可重空间中一个单元格可放置多个主体。
无论选择哪种空间类型,主体在空间中都有一个引用,并能获得自己的 X,y 坐标,能
把自己从先前占用的单元格中移出,加人到一个新的单元格中去。如:
SpaceputObjectAt(x,y,null);
x=newX;
y=newY;
SpaceputObjectAt(x,y,this);
上述代码通过把单元格的占有者设为空(null)来移除一个主体。这段代码是针对这个
主体发生的,所以用 this 来引用这个*主体,把它放到新的单元格中去。newX 和 newy 在
代码的外部就被设定好了,所以这里不再核查新的单元格是否已被占用。
6.Util 类库
Util 类库中只有一个类:SimUtiltities。该类提供了一些产生无序表单、显示信息对话框
等静态方法。
除了 Repast 自己提供的类,Repast 还充分利用了第三方提供的扩展类库,尤其是 Colt
库。Colt 库通过 Mersenne Twister DZ 具为 Repast 提供随机数据,而 Mersenne Twister
被认为是目前所知道最好的假随机数生成器之一。Colt 库中还包含其他各种能在 ReFast 中
使用的随机数生成器和随机分布。
四、建模基本过程
Repast 模型有两种运行方式:批处理方式运行和非批处理方式(也可称图形交互方式)
运行。批处理运行需要一个特殊格式的参数文件,在这个文件中要详细给出模型各个参数的
起始值、终止值和增量值,以及运行的次数等;有了参数文件后,模型就可无须用户干预连
续重复运行。
一个非批处理的运行则需要通过图形用户界面来交互地启动和终止模型,用户可以通
过图形界面来设定初始参数值,可以在运行过程中图形化地监控主体和模型的各种状态。
下面介绍编写模型的一般步骤,需要特别注意以下问题:如何能用参数文件来设定初
始参数?如何让用户能够图形化地设定起始参数?如何允许在运行时对模型进行图形化监
控?为了让模型支持这些交互需要在设计中要做哪些准备?等等。
数据结构上,RePast 模型一般至少有两个由用户编写的类:主体类和模型类。主体类
描述主体的行为(例如,在博弈中合作或者对立),模型类负责控制模型的创建和运行。主
体类大多需要专门构造,尽管 RePast 已经通过 GameAgent 接口以及 Game 抽象类为合作类
型的主体提供了最基本的支持。如果希望主体能够被图形化显示,主体类必须实现某一类型
的 Drawable 接口,后面在介绍到 Repast 内部机制 GUI 时还会具体介绍 Drawable 接口类的
使用。如果用户希望主体是可探测的,即主体状态的可视化和可运行时干预设置,则主体的
属性必须用附属方法模式(Accessor)编写,即以 get 和 set 打头的固定格式的方法,用于属
性的存取。
从过程的观点看,利用 RePast 建立一个基于主体的模型通常包括两步。第一步是设置
模型,为模型的运行做准备;第二步是实际运行模型的动作规定。在 RePast 中,模型的运
行按时间步(timesteps)或标记(tick)来推进。(注:在本节中交替使用时间步和标记两种
术语指谓这一概念)。每一个标记上,各个主体发生一些行为或状态的变化,主体们在这个
标记上的行为建立在之前行为的结果上。以“囚徒困境”(iterated prisoner’s dilemma,简
称 PD)模型为例,创建步骤中包括创建两个参与者,并且为他们每一个提供初始策略(例
如:TIT_FOR TAT)。在每一个标记上,每个参与者进行一次合作与否的决策,他们当前的
决策取决于各自的策略,也可以综合考虑前一次决策的结果。对于模型设计者来说,设计一
个 Repast 模型所必须做的全部工作就是,在前面提到的两个步骤中设置模型阶段需要准备
哪些工作?在一个标记上各种主体会发生什么行为或状态变化?Repast 自带的 SimPfeMoel
类提供分步实现模型的框架,接下来我们将首先介绍如何通过扩展该类建立自己的模型,接
着再介绍如何在一个实用的模型中设置参数(Parameter)使其可设置、可在运行时探测。
1.继承 SimPleModel、创建立模型类
尽管不一定必须应用 SimModel 接口,但应用这个接口可将底层和表层的建立过程分到
不同的方法组中,使得模型的结构与设计过程清晰明了。
void buildModel()
用 SimModel 和 Template 类建模的典型的模型结构包括以下三个方法:
(l)private
buildModel 负责创建代表模型的底层结构部分。主体对象、环境对象,还有一些可选的
数据收集对象常在此创建。如,在糖域模型中,SugarModel 在 buildModel()里构建了
SugarAgents 和 Sug-arSpace
(2)private void buildDisplay()
bllildDi8PIPy 建立了那些用于处理向用户显示模拟的表层结构部分,所以那些只以批处
理方式运行的模型很可能不需要实现这个方法。SugarModel 通过它建立了显示主体和图的
类。实际创建 Dis-playsurface 对象则通常放在一个预定义的 setup()方法中,稍后再
说明这个方法。
(3)private voidbuildschedule()
buildschedule 建立负责改变模型状态的时间表——何时运用什么方法调用什么对象的
时间表。
SimpleModel 作为模型类的基类,可根据需要继承扩展(特定化)。具体实现如下:
Import uchicago.sre.sim.engine.SimpleModel;
Public class MyModle extends SimpleModel{…
}
第一行导人了 SimpleMOdel,第二行继承了 SimpleModel。下面按建模过程的两步法建
立完整的模型类:
第一步:设 t 模型
SimPleModel 提供了两个方法作为实现这一步方便填充的框架:setuP()和 buildModel
()。他们可以按如下方式使用(以 IPD 为例):
Import uchicago.src.sin.engine.SimpleModel;;
Public class MyModle extends SimpleModel{
Public static final int TIT_FOR_TA=0;
Public static final int ALWAYS_DEFECT=1;
Private p1Strategy=TIT_FOR_TAT;
Private p2Strategy= ALWAYS_DEFECT;
…
Public voide setup () {
Super.setup();
P1Strategy=TIT_FOR_TAT;
Private p2Strategy= ALWAYS_DEFECT;
}
Public voide buildModel () {
Player1 p1=new Player(p1Strategy,p2) ;
Player2 p1=new Player(p2Strategy,p1) ;
agentList.dss(p1) ;
agentList.dss(p2) ;
}
}
在 setuP()中,首先调用 super.setup()使 SimpleModel 实现自身的创建,然
后设定了行为者的策略。这里假设行为者的策略可以通过用户的干预,或者可能在先前的模
型运行过程中从缺省值改变。setup()让模型的变量值重新回到缺省值。setup()在模型
启动时或单击控制条中“setup”键时被调用。当 setup()启动一个模型时,调用 buildModel
()来创建模型所需的对象,所以应在这里创建主体对象,并将其加人对象的列表 agentList
中。agentList 是由 SimPleModel 为此提供的一个 ArrayList。在 Setup 时所有的参数都恢复
到缺省值,所以在这里不能构造基于参数值的对象。在上面的例子中,两个参与者中一个根
据其初始策略决策,另一个根据对手的策略决策。
模型的执行顺序是:setup()调用在先,buildModel()调用在后。如上所述 setup()
在模型一被启动就被调用,当点击“set-up”键时也会被调用。buildMOdel()在模型运行
时(即“ run”或“step”键按下时)被调用,这就为用户通过图形界面接口改变变量提供
了机会。