这两天看关于”涌现“现象的内容,无意中发现了 NetLogo 这个软件,可以用它方便的为各种涌现(Emergence)现象建模,甚至还可以为进化博弈(Evolutionary Game)模型进行建模分析,因此迅速花了几小时学习了下,并把学习笔记整理如下。
另外,Logo 语言是笔者在 1984 年学习的第一门计算机语言,所以当 40 年后,再一次用到“小图龟(Turtle)”时,顿感亲切!
NetLogo
(官网:https://ccl.northwestern.edu/netlogo )是一个多主体可编程的建模环境(Multi Agent-based Programmable Modeling Environment),它基于 Logo 绘图语言,用于模拟自然和社会现象。它由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 来理解仿真建模。
这一部分让你了解什么是计算机建模以及如何使用它,也让你对 NetLogo 软件有所了解。
你是否参加过聚会,注意过人们是怎样聚集成小组的吗?你也可能注意到人们并非一直呆在一个小组里,而是走来走去。当人们走来走去的时候,小组就发生变化。如果你长期观察这种变化,你应该注意到使用模型思维来研究这个聚会现象。
NetLogo 的“Party”模型从性别这个特殊角度考察这个问题:为什么有些小组多数是男性,或多数是女性?相同的思路可以扩展到拥有相同性格、观点、话题的人们往往更容易聚在一起。
启动 NetLogo
打开文件夹 “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).
我们来试一个生物模型:狼吃羊,这是一个掠食 - 食饵种群模型
。
从文件菜单打开模型库
从 Biology 部分选择”Wolf Sheep Predation” 按下”Open”
当你第一次打开模型时,你会看到视图是空的(全黑)。要让模型开始,你需要先设置它。
按下”setup”按钮
按下”go”按钮开始仿真
按下”go”按钮停止运行
按钮按下后模型就会通过执行一个动作做出响应。按钮分为“一次性”(once)和“永久性”(forever) 两种。可以通过按钮上的一个符号区分二者。
一次性按钮执行动作一次然后停止。当动作完成后,按钮弹起。
永久性按钮不断的执行一个动作。当你想让动作停止时,再次按下按钮。它会完成当前动作,然后弹起。
大多数模型,包括狼吃羊模型,有一个一次性按钮称为“setup”和一个永久性按钮称为“go”。许多模型还有一个一次性按钮称作“go once”或“step once”,它们很像 go 按钮,但区别在于它们只执行一步(时间步长)。使用这样的一次性按钮能让你更仔细的查 看模型的运行过程。
当模型因某种原因卡住时,可以使用 Tools 下的 Halt 强行停止模型运行。
滑块左移使模型速度变慢,右移使模型速度变快,变快可能会引起跳帧。
另外,所谓的加速,其实是视图更新更频繁。实际没有变慢,可以从时钟(tick)显示确认这一点。
模型的配置给了你尝试不同场景或假设的机会。修改配置运行模型,观察这些改变所引起的反应,使你能更深入的了解所模拟的现象。
我们看看如果改变下面的设置的话,羊群怎么变化。
打开”grass?” 开关
按下”setup” 和 “go” ,运行与上次差不多相同的时间
开关有与它相连的信息。这些信息采用开 / 关格式。开关发出特别的指令,这些指令对模型并非必要,但为模型增加了附加的维度。打开”grass?“影响模型结果。
通过设置和打开草的增长率,我们能够对三个因素建模:羊、狼和草。
滑动条是一个可调的数值范围。例如”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
主要有两个显示数据的方式:绘图和监视器。
这些线显示了随着时间推进,模型中发生了什么。要想知道每条线代表什么,在图形窗口的右上角单击”Pens”,打开画笔图例。一个关键字说明了每条线是什么。在本例中就是种群数量。 当图快被充满时,水平轴增加,以前的数据被压缩只占一部分空间,更多的空间用来绘制将来的图形。
如果你想保存图上数据以备查看或在另一个程序里进行分析,使用 File 菜单的”Export Plot”。这些数据就被保存,数据格式可以被电子表格,如 Excel,或数据库程序识别。
监视器”time-ticks”告诉我们仿真时间。其他的监视器告诉我们狼、羊、草的数量。(记 住,草的数量除以 4,为了别使图形太高)
当模型运行时监视器中的数值不断更新,而图形能显示模型整个运行过程中的数据。
模型库包括五部分:Sample Models
, Perspective Demos
, Curricular Models
, Code Examples
, HubNet Computer Activities
.
Sample Models 部分是分科目组织的,目前有 210 多个模型。我们一直在增加模型,因此过段时间后能看到新加的模型。
有些文件夹下包含”(unverified)“子文件夹。这些模型是完整、可用的,但模型的内容、精度、代码质量等仍在评审之中。
这些模型在 Sample Models 中也有。但是略作修改,用来演示 NetLogo 的透视功能。
这些模型是西北大学 CCL 开发的在学校使用的课程。有些模型在 Sample Models 中也有,有些没有。看看信息标签页,了解更多的信息。
这是 NetLogo 特别功能的一些简单演示。当你以后扩展现存模型或新建模型时很有用。例如,你想在模型中增加直方图,可以看看”Histogram Example”,看看怎么做。
这一部分包括教室中使用的参与式仿真。要了解 HubNet 的更多信息,参见 HubNet Guide.
在这一部分,焦点从观察模型转换到改变模型。
在这个模型里,你会注意到一系列蓝车
里有一辆红车
,车流同向移动。这些车时不时的会挤成一堆,无法移动。这是关于幽灵式阻塞的模型,即有时交通流会出现阻塞,但却找不到任何明显的原因。通过改变模型的参数:加速与刹车,会发现堵塞是由驾驶习惯导致的。
这个模型的配置太简单,黑色背景、白色街道、一些蓝车和一辆红车。现在需要对模型做点改变:改变车的形状和颜色、加上房子或路灯、新建信号灯、或者再创建一条车道。这些建议有些是装饰性的,只是改善模型的观感,另外一些是行为性的。在本教程里我们主要关注较简单的、装饰性的改变。
命令中心位于界面最下方,在这里可以向模型发出指令。
例如:输入下面所示的文本
ask patches [set pcolor yellow]ask turtles [set color brown]
可以看到背景色和图龟颜色都变了。
NetLogo
是由海龟 (turtles)、瓦片 (patches) 和观察者 (observers) 组成的二维世界。瓦片构成背景,海龟在背景上移动,观察者(observer)是观察着所有事情的一个生命体。
为得到一个没有名字的颜色,你需要使用一个数值,或者在颜色名上加上或减去一个数。
例如,输入set color red
与输入set color 15
效果完全一样。要得到一个更浅或更深的颜色,只需使用一个比该颜色更小或更大的一个数。如
set pcolor red - 2
(“-” 两侧的空格很重要 )
set pcolor red + 2
,通过在 red 上加上一个数, 得到更浅的颜色。
修改属性:
方法一:在Agent Monitors
最下方直接输入set color green
方法二:直接在Turtle Monitor
中改属性
修改 patch 的属性方式同修改图龟属性。
NetLogo 中可以执行命令的主体类型有:
瓦片(patch)
海龟(turtle)
链(link)
观察者(observer) 瓦片是静止的,组成网格。海龟在网格上移动,链(link)接两个海龟。观察者俯视在进行的所有事情, 做那些海龟、瓦片和链自己不能做的事情。
所有这四种主体都能执行 NetLogo 命令。前三种主体还能运行程序(procedures)。
一个程序包括一系列 NetLogo 命令,你将它们定义为一个单一的新命令,让海龟移动、进食、繁殖和死亡。还将学习如何制作监视器、滑动 条和绘图。我们要建立一个简单的生态系统模型,与教学#1 的狼吃羊模型部分相似。
新建一个模型。
切换到代码 code 窗口,输入setup
按钮的代码:
to setup clear-all create-turtles 100 ask turtles [ setxy random-xcor random-ycor ] end
同上,在桌面上创建 go 按钮,注意:需要选择forever
,持续执行。
在代码窗口添加代码:
to go move-turtles endto 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
添加个一个绘图的方法:
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
方法。
在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
【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。