这两天看关于”涌现“现象的内容,无意中发现了NetLogo这个软件,可以用它方便的为各种涌现(Emergence)现象建模,甚至还可以为进化博弈(Evolutionary Game)模型进行建模分析,因此迅速花了几小时学习了下,并把学习笔记整理如下。
另外,Logo语言是笔者在1984年学习的第一门计算机语言,所以当40年后,再一次用到“小图龟(Turtle)”时,顿感亲切!
NetLogo
(官网:https://ccl.northwestern.edu/netlogo )是一个多主体可编程的建模环境(Multi Agent-based Programmable Modeling Environment),用于模拟自然和社会现象。它由Uri Wilensky
于1999年发起,并由西北大学Center for Connected Learning and Computer-Based Modeling (CCL)
中心持续开发,目前最新版是6.3.0,支持Windows,MacOS和Linux桌面系统。
NetLogo
非常适合对随时间演化的复杂系统进行建模。可以模拟成百上千个独立运行的”主体”(agent),这使得我们能够探究个体行为与涌现
出的宏观模式之间的微观与宏观联系。
本文参考张发翻译的《NetLogo 4.0.2 用户手册》,整理了一份简易教程,以便更好地使用NetLogo来理解仿真建模。
第一部分:体验
模型实例:聚会(Party)
这一部分让你了解什么是计算机建模以及如何使用它,也让你对 NetLogo 软件有所了解。
场景描述
你是否参加过聚会,注意过人们是怎样聚集成小组的吗?你也可能注意到人们并非一直呆在一个小组里,而是走来走去。当人们走来走去的时候,小组就发生变化。如果你长期观察这种变化,你应该注意到使用模型思维来研究这个聚会现象。
NetLogo 的“Party”模型从性别这个特殊角度考察这个问题:为什么有些小组多数是男性,或多数是女性?相同的思路可以扩展到拥有相同性格、观点、话题的人们往往更容易聚在一起。
初始化模型
- 启动 NetLogo
- 在 File 菜单中选择 “Models Library”(模型库)
- 打开文件夹 “Social Science”下的”Party”模型
- 点击”Setup” 按钮
在视图中你可以看到粉线和蓝线,还有数字。
这些线表示聚会上男女混合的小组。男性用蓝色表示,女性用粉色。数字是每个小组的人数。假如你邀请了 150 人参加聚会,假设人们分成了 10 组,我们使用计算机仿真,来看看人们是怎样扎堆的。
启动模型
- 按下 “go” 按钮 (再次按下 “go” 会停止模型运行)
- 观察人们的移动直到模型停止
- 看图形输出了解发生了什么?每组有多少人?
开始时你可能认为将 150 人分成 10 组的结果是每组大约 10 人。从模型运行得知,人们并没有均等的分成 10 组,相反,有些组人数特别少,而有些组人数却特别多。更有意思的是,随着时间发展,所有小组男女都转变为均由同性组成。
如何解释这个现象?
对这个问题有很多可能的解释。本模型的设计者认为聚会上的小组不是完全按随机方式形成的。小组如何形成取决于个体的行为。模型设计者关注一个特殊变量“tolerance”(容忍度):
这里将容忍度定义为个体感到舒服的异性的比例。如果小组中异性比例超过容忍度,他们就觉得不舒服,因此离开这一组去寻找别的小组。
例如,如果容忍度水平设为 25%,那么一个男性只有在女性比例少于25%的小组里才会感到舒服。同样女性只有在男性少于 25%的小组里才会感到舒服。当个体变得不舒服时会选择离开,转移到别的小组,这可能又让这个组中的某些人不舒服。这种链式反应不断进行,直到聚会上的所有人都感到舒服。
重启模型
在这个模型中,容忍度可以用滑动条改变,重新运行模型,再看看结果会如何。
- 如果 “go” 按钮已按下 (黑色),说明模型还在运行。再次按下该按钮停止运行。
- 通过拖动滑块调整 “tolerance” 值
- 按下”setup”按钮重设模型
- 按下”go”按钮再次启动模型
挑战
-
作为聚会的主人,你希望看到各组里都是男女混合。调整容忍度滑动条,让每组都尽量能够男女混合。 为保证 10 个小组都是男女混合,容忍度水平要设成多少? 如何达到尽量让不同人混在一起的容忍度,也许是会议或社群组织者要考虑的重要问题。
-
你能想到可能影响每组中男女比例的其他因素吗? 当你检验假设的时候,你会从数据中发现模型所产生的
涌现
(Emergence)。 -
容忍度水平与混合组的比例有什么关系?
涌现
用NetLogo
对聚会这样的情景建模使你可以对系统进行快速、灵活的试验,而在现实情况下这是很困难的。建模也给了你少受偏见的影响去观察各种情景的机会,因为你可以检查系统内部的动态。你会发现随着你建模越来越多,对许多现象的原有的想法会被改变。例如 Party模型一个令人惊讶的结果是:即使容忍度水平相对较高,不同性别的人仍然会分开。
这是关于涌现
现象的一个经典例子,这里小组模式是许多个体交互的结果。涌现
思想可以应用在几乎任何领域,NetLogo
是研究涌现
现象的重要工具,NetLogo 模型库里有许多模型,演示了各种不同类型的涌现
现象,如:蚂蚁寻食,鸟类迁徙等著名涌现现象
。
要更详细了解关于涌现
的讨论以及NetLogo
如何帮助学习者进行探索,参见《Modeling
Nature’s Emergent Patterns with Multi-agent Languages》 (Wilensky, 2001).
模型实例:狼吃羊( Wolf Sheep Predation)
我们来试一个生物模型:狼吃羊,这是一个掠食-食饵种群模型
。
- 从文件菜单打开模型库
- 从 Biology 部分选择”Wolf Sheep Predation” 按下”Open”
当你第一次打开模型时,你会看到视图是空的(全黑)。要让模型开始,你需要先设置它。
- 按下”setup”按钮
- 按下”go”按钮开始仿真
- 按下”go”按钮停止运行
控制模型:按钮
按钮按下后模型就会通过执行一个动作做出响应。按钮分为“一次性”(once)和“永久性”(forever)两种。可以通过按钮上的一个符号区分二者。
- 永久性按钮的右下角有两个箭头:
- 一次性按钮没有箭头:
一次性按钮执行动作一次然后停止。当动作完成后,按钮弹起。
永久性按钮不断的执行一个动作。当你想让动作停止时,再次按下按钮。它会完成当前动作,然后弹起。
大多数模型,包括狼吃羊模型,有一个一次性按钮称为“setup”和一个永久性按钮称为“go”。许多模型还有一个一次性按钮称作“go once”或“step once”,它们很像go按钮,但区别在于它们只执行一步(时间步长)。使用这样的一次性按钮能让你更仔细的查 看模型的运行过程。
当模型因某种原因卡住时,可以使用Tools下的Halt强行停止模型运行。
控制速度:速度滑动条
速度滑动条控制模型运行速度,即海龟(Turtle)的移动速度、瓦片(Patches)颜色改变的速度,等等
滑块左移使模型速度变慢,右移使模型速度变快,变快可能会引起跳帧。
另外,所谓的加速,其实是视图更新更频繁。实际没有变慢,可以从时钟(tick)显示确认这一点。
调整设置:滑动条和开关
模型的配置给了你尝试不同场景或假设的机会。修改配置运行模型,观察这些改变所引起的反应,使你能更深入的了解所模拟的现象。
下面是狼吃羊模型中的开关和滑动条:
调整1:开关
我们看看如果改变下面的设置的话,羊群怎么变化。
- 打开”grass?” 开关
- 按下”setup” 和 “go” ,运行与上次差不多相同的时间
开关有与它相连的信息。这些信息采用开/关格式。开关发出特别的指令,这些指令对模型并非必要,但为模型增加了附加的维度。打开”grass?”影响模型结果。
通过设置和打开草的增长率,我们能够对三个因素建模:羊、狼和草。
调整2:滑动条。
滑动条是一个可调的数值范围。例如”initial-number-sheep”滑动条最小值为0,最大值为250。模型运行时可以有 0 只羊,也可以有 250只羊,或者中间的任何一个数值。
实验:
- 关掉”grass?” 开关
- 设置”initial-number-sheep” 滑动条为 100.
- 设置”initial-number-wolves” 滑动条为 20.
- 按下 “setup” 和 “go”.
- 模型运行约 100 时间步
实验:
- 设置 “initial-number-sheep” 为 80 ,”initial-number-wolves” 为 50.
- 设置”sheep-reproduce” 为 10.0%.
- 按下”setup” 和 “go”.
- 模型运行约 100 时间步
绘图和监视器
建模的目的之一是对那些难以在实验室中进行研究的问题收集数据。NetLogo
主要有两个显示数据的方式:绘图和监视器。
绘图(Plots)
狼吃羊中的图有三条线:羊、狼和草/4(草除以 4 的原因是为了别使图形太高)。
这些线显示了随着时间推进,模型中发生了什么。要想知道每条线代表什么,在图形窗口的右上角单击”Pens”,打开画笔图例。一个关键字说明了每条线是什么。在本例中就是种群数量。 当图快被充满时,水平轴增加,以前的数据被压缩只占一部分空间,更多的空间用来绘制将来的图形。
如果你想保存图上数据以备查看或在另一个程序里进行分析,使用 File 菜单的”Export Plot”。这些数据就被保存,数据格式可以被电子表格,如 Excel,或数据库程序识别。
监视器(Monitors)
监视器是模型显示信息的另一种方法。下面是狼吃羊模型中的监视器:
监视器”time-ticks”告诉我们仿真时间。其他的监视器告诉我们狼、羊、草的数量。(记 住,草的数量除以 4,为了别使图形太高)
当模型运行时监视器中的数值不断更新,而图形能显示模型整个运行过程中的数据。
模型库
模型库包括五部分:Sample Models
, Perspective Demos
, Curricular Models
, Code Examples
, HubNet Computer Activities
.
模型样例(Sample Models)
Sample Models 部分是分科目组织的,目前有 210 多个模型。我们一直在增加模型,因此过段时间后能看到新加的模型。
有些文件夹下包含”(unverified)”子文件夹。这些模型是完整、可用的,但模型的内容、精度、代码质量等仍在评审之中。
透视演示(Perspective Demos)
这些模型在 Sample Models 中也有。但是略作修改,用来演示 NetLogo 的透视功能。
课程模型(Curricular Models)
这些模型是西北大学 CCL 开发的在学校使用的课程。有些模型在 Sample Models 中也有,有些没有。看看信息标签页,了解更多的信息。
代码例子(Code Examples )
这是 NetLogo 特别功能的一些简单演示。当你以后扩展现存模型或新建模型时很有用。例如,你想在模型中增加直方图,可以看看”Histogram Example”,看看怎么做。
HubNet 计算机活动(HubNet Computer Activities)
这一部分包括教室中使用的参与式仿真。要了解HubNet的更多信息,参见 HubNet Guide.
第二部分:常用命令Commands
在这一部分,焦点从观察模型转换到改变模型。
模型实例: 基本交通模型(Traffic Basic)
- 在”Social Science”部分,找到并打开 Traffic Basic 模型
在这个模型里,你会注意到一系列蓝车
里有一辆红车
,车流同向移动。这些车时不时的会挤成一堆,无法移动。这是关于幽灵式阻塞的模型,即有时交通流会出现阻塞,但却找不到任何明显的原因。通过改变模型的参数:加速与刹车,会发现堵塞是由驾驶习惯导致的。
这个模型的配置太简单,黑色背景、白色街道、一些蓝车和一辆红车。现在需要对模型做点改变:改变车的形状和颜色、加上房子或路灯、新建信号灯、或者再创建一条车道。这些建议有些是装饰性的,只是改善模型的观感,另外一些是行为性的。在本教程里我们主要关注较简单的、装饰性的改变。
命令中心(The Command Center)
命令中心位于界面最下方,在这里可以向模型发出指令。
例如:输入下面所示的文本
ask patches [set pcolor yellow]
ask turtles [set color brown]
可以看到背景色和图龟颜色都变了。
NetLogo
是由海龟(turtles)、瓦片(patches)和观察者(observers)组成的二维世界。瓦片构成背景,海龟在背景上移动,观察者(observer)是观察着所有事情的一个生命体。
颜色名称
NetLogo的颜色表:
为得到一个没有名字的颜色,你需要使用一个数值,或者在颜色名上加上或减去一个数。
例如,输入set color red
与输入set color 15
效果完全一样。要得到一个更浅或更深的颜色,只需使用一个比该颜色更小或更大的一个数。如
set pcolor red - 2
(“-“ 两侧的空格很重要)set pcolor red + 2
,通过在 red 上加上一个数, 得到更浅的颜色。
主体监视器(Agent Monitors)和主体命令器(Agent Commanders)
修改单个图龟属性
鼠标右键
获取图龟ID,即who
,如本例中为who=17
修改属性:
-
方法一:在
Agent Monitors
最下方直接输入set color green
-
方法二:直接在
Turtle Monitor
中改属性
- 方法三:在命令菜单中改
修改单个patch属性
鼠标右键
注意:patch与turtle的ID不一样,patch的ID为位置信息,比如上图中表示该patch的pxcor=9,pycor=0
,即9 0
修改patch的属性方式同修改图龟属性。
第三部分:程序(Procedures)
NetLogo 中可以执行命令的主体类型有:
- 瓦片(patch)
- 海龟(turtle)
- 链(link)
- 观察者(observer) 瓦片是静止的,组成网格。海龟在网格上移动,链(link)接两个海龟。观察者俯视在进行的所有事情, 做那些海龟、瓦片和链自己不能做的事情。
所有这四种主体都能执行 NetLogo 命令。前三种主体还能运行程序(procedures)。
一个程序包括一系列 NetLogo 命令,你将它们定义为一个单一的新命令,让海龟移动、进食、繁殖和死亡。还将学习如何制作监视器、滑动 条和绘图。我们要建立一个简单的生态系统模型,与教学#1 的狼吃羊模型部分相似。
制作 setup 按钮
-
新建一个模型。
-
在工具框中选择
Button
,然后放到适当位置,命名为setup
。 -
切换到代码code窗口,输入
setup
按钮的代码:to setup clear-all create-turtles 100 ask turtles [ setxy random-xcor random-ycor ] end
制作 go 按钮
- 同上,在桌面上创建go按钮,注意:需要选择
forever
,持续执行。 - 在代码窗口添加代码: ``` to go move-turtles end
to move-turtles ask turtles [ right random 360 ;向右随机旋转一个角度 forward 1 ] end
### 为海龟添加属性
turtles-own [energy]
添加一个叫`energy`的属性。
另外,在添加一个`eat-grass`的方法,并在`go`方法中调用`eat-grass`:
to eat-grass ask turtles [ if pcolor = green [ set pcolor brown set energy energy + 10 ] ] end
在`move-turtles`方法中,增加走一步需要消耗能量的代码:
to move-turtles ask turtles [ right random 360 ;随机旋转角度 forward 1 set energy energy - 1 ] end
### 添加监视器
* 添加海龟数量的监视器,在`reporter`中输入:`count turtles`
* 添加绿地数量的监视器,在`reporter`中输入:`count patches with [pcolor = green]`
### 添加开关
* 添加“开关”组件,注意变量名需要加问号?,然后重写`eat-grass`方法
to eat-grass ask turtles [ if pcolor = green [ set pcolor black set energy energy + 10 ] ifelse show-energy? [ set label energy ] [ set label “” ] ] end
### 添加养小海龟的方法
to reproduce ask turtles [ if energy > 50 [ ;如果能量值>50,则生小海龟 set energy energy - 50 ;生完小海龟,能量值减50 hatch 1 [ set energy 50 ] ;hatch为孵化一个新的turtle(属性同母体),后面[]中写初始化设置 ] ] end
### 添加海龟死亡的方法
to check-death ask turtles [ if energy <= 0 [ die ] ;die为默认方法,销毁一个turtle ] end
### 添加草场生长的方法
to regrow-grass ask patches [ if random 100 < 3 [ set pcolor green ] ;3%概率会生长出草地 ] end
### 将上述方法添加到`go`方法中,供每一步都调用
to go move-turtles eat-grass reproduce check-death regrow-grass end
运行上述代码,现在能看到模型的一些有趣行为:一些海龟死掉,一些新海龟出现(孵出),一些草恢
复。
![](https://live.staticflickr.com/65535/53160591475_a5fb659f19_o.png)
### 跟踪数据变化,并绘图
创建一个`plot`
![](https://live.staticflickr.com/65535/53160182411_b89b1de8f8_o.png)
添加个一个绘图的方法:
to do-plots set-current-plot “Totals” set-current-plot-pen “turtles” plot count turtles set-current-plot-pen “grasses” plot count patches with [pcolor = green] end
然后分别在`setup`和`go`方法中调用`do-plots`方法。
### 控制时间与步数 tick
在`setup`方法中添加:`reset-ticks`;
修改`go`方法:
to go if ticks >= 500 [ stop ] … tick ;步进一次 end
### 添加草场生长速度的参数输入框
添加一个`输入框`,并命名为`regrow-grass-speed`,数量范围为0-100。
然后将`regrow-grass`方法改为如下:
to regrow-grass ask patches [ if random 100 < regrow-grass-speed [ set pcolor green ] ] end
### 添加初始化海龟数量的滑块
添加一个`滑块`,命名为`initial-turtles`,然后将`set-turtles`方法改为:
to set-turtles create-turtles initial-turtles ask turtles [ setxy random-xcor random-ycor ] end ```
完成上述操作后的界面如下: