第一行:国际惯例咕咕咕。
第二行:人工势场这个概念好神奇(虽然我觉得就是强行捏了一个高大上的词
第三行:希望全天下的软件都能把要用的东西集成成库,然后只需要无脑点点就可以了(我本人:又懒又馋还不爱劳动(武林外传十娘皱眉苦瓜脸.jpg
第四行:所有代码注释:不知道netlogo该怎么写注释就按python来了【upd:我知道了用“;;”来注释但是懒得改了】
第五行:netlogo的语法就是所有的东西都得空格隔开,3*9也得写成3 * 9
第六行:我要开始自行编辑了
一、安装+初步认识
这本书真好使,简单明了容易上手:《Netlogo多主体建模入门》
话不多说官网走起:netlogo下载链接
(实验室15kb的网速支持我摸鱼)(老师你看这可不怪我是网不行)(我超会找借口der)
1.1 生命游戏
具体规则:略(好多不想打上,反正就是小方格中的黑白色块在周8个邻居的相互作用下变黑变白的过程)
步骤:新建项目:文件->模型库->life(左图);setup-random:初始化(中图);go-forever:最终结果(右图)
结果:最终会形成小方格中黑白色块的死亡or存活图
1.2 鸟群模型
具体规则:略(模拟鸟群靠近or远离其他鸟,且保持飞行方向的过程)
步骤:新建项目:文件->模型库->bioligy(左图);setup+go(右图)
结果:最终可以看到鸟群成群一起往某个方向飞并且鸟群没有发生碰撞
1.3 财富分布模型
具体规则:略(更麻烦了,分谷物和人的分布,人:采集谷物+消耗谷物+代谢不同+可能饿死+新出生,谷物:生长)
步骤:文件->模型库->ScocialSicence.Economics.Sugarscape(左图);set-go(右图)
结果:class plot+class histogram:展示穷人、中产、富人的数量对比(可以看出二八定律);Lorenz curve(洛伦兹曲线):反映财富分配不均衡现象(红线越弯曲不均衡程度越高);Gini-Index(基尼系数):国际通用衡量财富不均衡的指标,数值越大越不均衡(一般0.3/0.4左右)
二、正式上手
此部分中都有各自的规则(但是由于我懒,我就不写了
2.1 小球宇宙
本模型:随机出现,单步移动
学习:对语法集合等有个初步认识
添加按钮并对按钮命名,右键黑色世界后编辑可对模拟世界的属性进行修改,在代码模块中编写代码对按钮进行设置
#对setup按钮进行设置
to setup
clear-all #每次运行清空屏幕
set-default-shape turtles "circle" #设置形状为圆形
create-turtles 50[
setxy random-xcor random-ycor #50个小球且setxy随机横纵坐标
]
end
#对go按钮进行设置
to go
ask turtles[ #ask相当于循环,对turtles这个集合进行下面操作的循环
forward 1 #每点一次小球前进一个位置
]
end
效果图(左:setup,右:go):
2.2 生命游戏
本模型:被邻居影响而改变
学习要求:对集合+patch有进一步的概念,掌握set命名变量、条件语句、with筛选集合,会调整model和patch的大小
模拟世界本质由许多patch组成(可以理解为n*n的像素矩阵),所以可以对ptach进行属性设定,利用patch的颜色设置来模拟生命游戏
16*16的世界+13的patch
50*50的世界+4的patch
patches-own [living] #设置变量名为living的patch(本质为一个集合
to setup
clear-all
ask patches[ #对这个集合内的变量进行循环
if random-float 1 < 0.3[ #此命令产生一个小于1的0-1之间的数,并用if判断产生的数是否小于0.3
set pcolor white #设置变量pcolor为白色
]
set living 0 #设置变量living为0
]
end
to go
ask patches[
set living count neighbors with [pcolor = black]
#对每个patch设置living变量为计算周围8个patch中为黑色的数量
#count为自带计数函数
#neighbors为保留字(构成集合
#with也为保留字(后跟限定条件来筛选集合
]
ask patches[
ifelse (pcolor = black)[ #ifelse条件语句,注意格式为ifelse[条件1][条件2]
if living > 3 or living < 2[
set pcolor white
]
][
if (living = 3)[
set pcolor black
]
]
]
end
2.3 朗顿的蚂蚁
本模型:主体和环境不停地相互影响并发生改变
学习要求:学习random函数,掌握时间计数方式(设置更新按时间步更新)
(左图的中心其实是有一个patch的(像素太小了可能看不出来(但是不调大小就看不出蚂蚁修路来(bushi(很神奇的是1w时间步左右开始修路后面就不修了成一个花点点了
to setup
clear-all
reset-ticks #ticks用来计时
create-turtles 1[ #生成了一个turtle
set heading random 3 * 90 #设置的是turtle的朝向,随机生成四个方向
#这句的本质是heading((random 3)*90)即随机生成一个小于3的非负整数后再乘90,即只会生成0,90,180,270四种
]
end
to go
ask turtles[
ifelse (pcolor = white)[
right 90 #向右转90°,其实相当于是head = head+90
set pcolor black
forward 1
][
left 90 #向左转90°,同理,head-90
set pcolor white
forward 1
]
]
tick
end
2.5 羊草生态系统
本模型:两种不同的主体相互影响作用,草被吃也生长,羊吃草也繁衍也死亡
学习要求:自定义函数的使用、智能主体的监控、如何绘图
左图:setup后绿色为草,红色为羊 右图:一段时间后被吃的草和繁衍的羊
左图:右键patch后可以观察其具体 右图:能看到的具体属性
左图:添加绘图按钮后并进行绘图 右图:运行一段时间后(可以看出这是一个典型的捕食者-被捕食者模型,绿色代表草,一开始很多,黑色代表羊一开始很少,短期内羊大量繁殖,草急剧减少,过了一段时间会达到一个相对平衡的状态)
turtles-own [energy] #同样设置了一个变量
to setup
clear-all
reset-ticks
ask patches[
if random-float 1 < 0.2[
set pcolor green
]
]
create-turtles 1[
set energy 100 #设置该变量的初始值为100
]
end
#草增加函数
to add_food
ask n-of 10 patches[
#n-of函数的作用是从patches集合中随机挑选10个patch形成一个新的集合
set pcolor green
]
end
#羊移动函数
to turtle_move
if pcolor = green[
set energy energy + 10 #羊移动会吃草,增加自身能量,但是草会没有
set pcolor black
]
if random-float 1 < 0.2[
set heading random 360 #设定概率让羊随机转换方向移动
]
set energy energy - 1 #每次移动都会消耗自身能量
fd 1 #forward缩写,即移动
end
#羊繁衍
to turtle_breed
if energy > 500[
set energy energy - 500 #大于500就生小羊,自身能量减少
hatch 1[
fd 1
set energy 100 #新羊的能量100,前移1格
]
]
end
#羊死亡
to turtle_die
if energy <= 0[
die
]
end
to go
add_food #草不停增加
ask turtles[ #羊不停移动+吃草+繁衍+死亡
turtle_move
turtle_breed
turtle_die
]
tick
end
三、进阶开始
3.1 人工经济模型
本模型:财富分配的表示(交易过程中的财富聚集)
学习要求:了解set和let的区别(let 和 set都可以对变量进行赋值,不同的是let可以赋值未定义的变量,set只能赋值前面定义过的变量);注意变量的作用域;对绘图进行设置(可进行画笔的设置来画直方图or条形图等);用滑块来控制变量数;使用工具-行为空间-新建实验做重复实验;在观察中心设置命令进行实验
#设置变量(利用滑块设置的全局变量)
turtles-own[
money #每个主体有的钱数
save_rate #储蓄率
]
to setup
clear-all
reset-ticks
create-turtles num_agents[
set money (total_money / num_agents) #钱=总/人数
setxy random-xcor random-ycor
set save_rate random-float 1 #随机的储蓄率
]
end
to transaction [trader] #[]中是传入的变量
let deltam 0 #货币转移量,初值为0
let money1 ([money] of trader) #存储传入变量的值
let epsilon (random-float 1) #0~1的随机数
set deltam (epsilon - 1) * money + epsilon * money1 #设置交易量
if money + deltam >= 0 and money1 - deltam >= 0[ #不允许借贷,交易货币总量不低于0才会交易
set money money + deltam
ask trader[
set money money1 - deltam
]
]
end
to go
ask turtles[
let agsets other turtles-here #对每个变量进行赋值,turtle-here返回的是潜在交易对象
#当前patch上除了自身外的所有turtle,是一个集合
if count agsets >= 1[
transaction (one-of agsets) #大于等于1就发生交易,one-of从集合中随机选择元素
]
forward 1
]
tick
end
#新的交易中引入了储蓄率有的人并不会全部进行交易
to transaction_new [trader]
let deltam 0
let money0 ((1 - save_rate) * money)
let money1 ((1 - ([save_rate] of trader)) * ([money] of trader))
let epsilon (random-float 1)
set deltam (epsilon - 1) * money0 + epsilon * money1
if money + deltam >= 0 and ([money] of trader) - deltam >= 0[
set money money + deltam
ask trader[
set money money - deltam
]
]
end
to new_go
ask turtles[
let agsets other turtles-here
if count agsets >= 1[
transaction_new (one-of agsets)
]
forward 1
]
tick
end
to to-update-plot
let lst [money] of turtles #是一个集合,每个turtle的财富值
set-histogram-num-bars 100 #统计小区间的个数为100
if not empty? lst[
set-plot-x-range 0 max lst #设置x轴的范围
histogram lst #绘制直方图
]
end
to save-file
file-open "agents.txt" #打开一个txt文件(会自行生成
let wealths ""
ask turtles[
set wealths (word wealths money "\r\n") #word 数值 数值,对wealth进行赋值
]
file-print wealths #写入文件
file-close
end
to update-lorenz-plot
clear-plot
#绘制表示财富分布绝对均衡的曲线
set-current-plot-pen "equal" #激活画笔
plot 0 #设置纵坐标,横坐标等水平间隔
plot 1
#极端不平衡的曲线
set-current-plot-pen "dominant"
plot-pen-down #开始绘图
plotxy 0 0 #设置xy点
plotxy 1 0
plotxy 1 1
plot-pen-up #停止绘图
#洛伦兹曲线(根据洛伦兹的规则来的)
set-current-plot-pen "lorenz"
set-plot-pen-interval 1 / num_agents #设置间隔量
plot 0
let sorted-wealths sort [money] of turtles #
let total-wealth sum sorted-wealths
let wealth-sum-so-far 0
let index 0
let gini 0
repeat num_agents[
set wealth-sum-so-far(wealth-sum-so-far + item index sorted-wealths)
plot(wealth-sum-so-far / total-wealth)
set index (index + 1)
set gini gini + ((index / num_agents) - (wealth-sum-so-far / total-wealth)) / num_agents
]
set-current-plot "gini" #基尼系数
plot gini * 2
end
to-report compute-gini
let sorted-wealths sort [money] of turtles
let total-wealth sum sorted-wealths
let wealth-sum-so-far 0
let index 0
let gini 0
repeat num_agents[
set wealth-sum-so-far (wealth-sum-so-far + item index sorted-wealths)
plot (wealth-sum-so-far / total-wealth)
set index (index + 1)
set gini gini + ((index / num_agents) - (wealth-sum-so-far / total-wealth)) / num_agents
]
set-current-plot "gini"
report gini * 2
end
3.2 人工鸟群
本模型:鸟的跟随or远离(鸟的视野半径+靠近规则+对齐规则+分离规则)
学习要求:掌握矢量的加减法、数乘;list的使用;map来对整个列表进行作用
(注意:因为书中没有给出变量的设置,所以不同的数值会影响不同的靠近对齐等,可自行进行修改调整)
turtles-own[
velocity flockingmates colisionmates
] #设置了速度矢量+靠近范围的所有邻居+分离范围的所有邻居(是集合
to setup
clear-all
crt num_boids[
setxy random-xcor random-ycor
set velocity [0 0] #是一个速度矢量,用二元列表实现
set size 3
]
end
to go
ask turtles[ #first和last用来取列表的最初和最后元素
get-neighbors #获取每只鸟的邻居,包括靠近范围内的邻居和分离范围内的邻居
flocking #根据Boids的3条规则,计算所有的力并更新速度
facexy xcor + (first velocity) ycor + (last velocity) #设定鸟的朝向为其速度矢量
setxy xcor + (first velocity) ycor + (last velocity) #设定下一时刻的位置
]
end
to get-neighbors #设置了分离半径和视野半径
set flockingmates (other turtles in-radius viewdistance) #获得veditance距离内的所有其他岛
set colisionmates (other turtles in-radius collisiondistance) #获得cosoindisie距离内的
end
to flocking
let corr [0 0] #所有邻居的平均位置
let v[0 0] #所有邻居的平均速度
let cn count flockingmates #邻居的数量,count为自带函数
ask flockingmates[ #map可以运算列表中的所有元素
set corr (map + corr (list xcor ycor)) #对列表中的所有元素进行+xcor ycor
set v (map + v velocity) #全加velocity
]
if cn > 0[ #?表示形式化的参数,?1 ?2表示第一二个参数,?表示所有参数(可以理解为:f(x,y)等)
set corr (map[ ?1 -> ?1 / cn ] corr) #corr中的所有元素都除以cn
set v (map[ ?1 -> ?1 / cn ] v) #v中的每个元素都除以cn
]
let dis(map - corr (list xcor ycor)) #dis= Corr -XCOr, ycOr,从“我”的位
set cn count colisionmates
let cdis [0 0]
if cn > 0[
let ccorr [0 0]
ask colisionmates[
set ccorr (map + ccorr (list xcor ycor))
]
set ccorr (map[ ?1 -> ?1 / cn] ccorr)
set cdis (map - (list xcor ycor) ccorr)
set cdis (map [?1 -> ?1 / ((norm cdis)*(norm cdis) + 0.001) ] cdis)
]
let w1 weight_cohesion
let w2 weight_alignment
let w3 weight_collision
let f1 (map [ ?1 -> ?1 * w1 ] dis)
let f2 (map[ ?1 -> ?1 * w2] v)
let f3 (map[ ?1 -> ?1 * W3 ] cdis)
let force (map [[?1 ?2 ?3] -> ?1 + ?2 + ?3] f1 f2 f3)
set velocity (map + velocity force)
if (norm velocity) > 5[
set velocity normalize velocity
set velocity map [?1 -> ?1 * 5] velocity
]
end
to-report normalize [xy] #进行归一化处理
let realdis norm xy
let out [0 0]
if realdis > 0[
set out (map [ ?1 -> ?1 / realdis ] xy)
]
report out
end
to-report norm [arr] #计算矢量的模,传入的是列表arr
let xx first arr
let yy last arr
report sqrt (xx * xx + yy * yy)
end