《Netlogo多主体建模入门》笔记 9

9 - 通过人工鸟群Boid模型学习List的使用

该系列笔记基于集智乐园的《Netlogo多主体建模入门》课程,感谢张江老师与各位志愿者的辛勤付出。

  • 集智乐园 《Netlogo多主体建模入门》 https://campus.swarma.org/play/play?id=429

 

 

 

三条简单的规则

  • 靠近规则

当鸟偏离鸟群的时候,能自动靠拢鸟群。

  • 对齐规则

鸟的飞行方向取决于 周围鸟的飞行方向。具体来说是:周围鸟的飞行方向 的平均矢量。

  • 分离规则

当鸟距离另一只鸟过近的时候,会自动远离。

《Netlogo多主体建模入门》笔记 9_第1张图片

 

实现思路:

  1. 将鸟群飞行的模型转化成一个多质点相互作用(受力)的力学模型
  2. 构建 三个分力,靠近的拉力F1 、对齐的拉力F2、 分离的斥力 F3
  3. 通过将三个力(F1 、F2、 F3) 合成 为一个力 F,并结合 简单的欧拉法来 更新 运动的方向 v 和位置 p,这样就能模拟鸟群的运动。

《Netlogo多主体建模入门》笔记 9_第2张图片

 

 

 

首先,我们需要划定 规则的生效范围:

  • 在蓝色区域内,是 靠近、对齐规则起作用的范围
  • 在红色区域内,是 分离规则起作用的范围

 

《Netlogo多主体建模入门》笔记 9_第3张图片

 

 

构造分力所需要的一些参数:

  • 邻居的平均位置矢量(矢量指向的点,又叫重心)

公式:

Pi 指的是 鸟 的邻居节点 的向量,在这个示例中,邻居节点有5个。

邻居的平均位置矢量 指的就是 将这5个向量相加,然后除以邻居节点数 5 ,从而得到的矢量(图中红线)。【为了避免看起来乱,只画了两条蓝线】

《Netlogo多主体建模入门》笔记 9_第4张图片

  • 邻居节点的平均速度矢量

公式:

将邻居节点的速度相加,然后除以邻居节点数 5,即可得到。

因为速度是矢量,有方向和标量。所以能通过邻居节点的飞行方向来决定这只鸟的飞行方向。

《Netlogo多主体建模入门》笔记 9_第5张图片

  • 碰撞者的平均位置矢量(矢量指向的点,又叫重心)

计算方法同

 

 

 

开始构造分力

 

  • 靠近的拉力F1

通过受力分析,能得出F1的公式:

但是我们到后面合成合力的时候,会给F1 多乘上一个系数,后面的两个分力也是如此。

《Netlogo多主体建模入门》笔记 9_第6张图片

  • 对齐的拉力F2

F2这力等于 邻居节点的平均速度矢量 。

《Netlogo多主体建模入门》笔记 9_第7张图片

 

  • 分离的斥力 F3

因为是斥力,所以要 远离碰撞节点的重心(浅紫色的点),方向为矢量( P- C平均) 的方向。

因为考虑到这个碰撞节点的重心可能会和本节点重合,导致矢量( P- C平均) 的模变为0,所以会加上一个很小的系数 ε 。

分母 | P- C平均 | 平方的原因:

第一次除以 | P- C平均 | ,是因为 | P- C平均 | 是 矢量( P- C平均)的模,除以它就能实现向量归一化。

第二次除以 | P- C平均 | ,是为了实现: 当这只鸟离碰撞重心越近,斥力越大。

《Netlogo多主体建模入门》笔记 9_第8张图片

 

最终将分力以加权的形式合成 合力F ,我们可以在模型中调整 w1、w2、w3 这三个参数。

 

 

如何让鸟运动起来?

 

  • 通过合力F,更新鸟的飞行速度 V 的方向和大小。

《Netlogo多主体建模入门》笔记 9_第9张图片

  • 通过鸟当前的速度 V,更新位置P。

《Netlogo多主体建模入门》笔记 9_第10张图片

 

在正式开始写代码之前,我们需要知道一些语法知识:

 

list的使用

创建:

  • 如果列表中的元素都是一些数值常数

set lst [0 0 1]

直接用方括号

  • 如果列表中的元素含有变量

set lst ( list (sqrt 4) val1 val2 )

调用 list 对象的构造函数

 

访问:

  • first lst

取出list对象 lst 的第一个元素

  • last lst

取出list对象 lst 的最后一个元素

  • item 3 lst

取列表中的第4个元素

 

 

MAP的用法-矢量的数乘

用法一 单个形参:

  • map [? -> ? * 2] [1 3 4]

[? -> ? * 2] 有点像java里的lambda表达式,是一个匿名函数,?代表了形参。

你可以将 " -> " 这个符号当作 “变成”。 [? -> ? * 2] 的意思就是把 变量x 变成 2x 的一个匿名函数。

map [? -> ? * 2] [1 3 4] 的意思就是 把 这个匿名函数 作用于右边列表[1 3 4] 里的元素。

《Netlogo多主体建模入门》笔记 9_第11张图片

 

《Netlogo多主体建模入门》笔记 9_第12张图片

 

 

 

用法二 多个形参:

map [[?1 ?2 ?3] -> ?1 + ?2 + ?3] [1 2 3] [2 3 4] [0 1 2]

[3 6 9]

注意:在命令中心,要用 show(命令) 的形式才能打印结果。

“ ?1” 、“?2”、“?3” 这三个参数就是代表了形参,可以理解为中间变量。你的输入是多少,它就是多少,而且可以不断更新,直到运算完毕。看图就能懂了。

 

 

《Netlogo多主体建模入门》笔记 9_第13张图片

 

 

了解了这些之后,我们可以开始建立模型了:

 

添加按钮和滑块

 

从上往下每个滑块的意思:

  • 鸟群中鸟的数量 --------- num_birds
  • 视野半径大小 ------ view_range
  • 碰撞距离(小于这个距离的时候,触发分离规则) ------- coll_range

 

 

《Netlogo多主体建模入门》笔记 9_第14张图片

 

  • 三个分力的 权值大小

w_coh,F1 聚集拉力 的系数

w_ali , F2 对齐拉力 的系数

w_col , F3 分离斥力 的系数

《Netlogo多主体建模入门》笔记 9_第15张图片

 

然后开始敲代码啦!

 

以下代码是看课程视频照着敲的,就是有些变量的名字改了。我这里写的代码就不写注释了,大家跟着视频看一遍就懂啦。

ps:千万要记得每一个变量名是代表了什么,而且起名要能明显看出对应其意义。

还有就是,建议各位抽点时间把代码敲一遍,加深理解。

 

  • In-radius

示例: other turtles in-radius 5 ------- 限定条件,表示半径5以内的其他 turtles 。

 

turtles-own [
 v
 nei_mates
 col_mates
]

to setup
  clear-all
  crt num_birds [
    setxy random-xcor random-ycor
    set v [0 0]
    set size 5
  ]
end


to go
  ask turtles [
    get_neis
    flocking
    facexy xcor + (first v)  ycor + (last v)
    setxy xcor + (first v)  ycor + (last v)
  ]
end

to get_neis
  set nei_mates (other turtles in-radius view_range)
  set col_mates (other turtles in-radius coll_range)

end

to flocking
  let corr [0 0]
  let vel [0 0]
  let nei_n count nei_mates

  ask nei_mates[
   set corr (map + corr (list xcor ycor))
    set vel (map + vel v)
  ]

  if nei_n > 0 [
    set corr (map [ ?1 -> ?1 / nei_n ] corr)
    set vel (map [ ?1 -> ?1 / nei_n ] vel )
  ]
  let dis (map - corr (list xcor ycor))

  let col_n count col_mates
  let cdis [0 0]
  if col_n > 0 [
    let  ccorr [0 0]
    ask col_mates [
      set ccorr (map + ccorr (list xcor ycor))
    ]

    set ccorr (map [ ?1 -> ?1 / col_n ] ccorr)
    set cdis (map - (list xcor ycor ) ccorr)
    set cdis (map [ ? -> ?  / (((norm cdis) * (norm cdis)) + 0.01  )] vel )
  ]

  let w1 w_coh
  let w2 w_ali
  let w3 w_col
  let f1 (map [ ? -> ? * w1 ] dis)
  let f2 (map [ ? -> ? * w2 ] vel)
  let f3 (map [ ? -> ? * w3 ] cdis)

  let force (map [ [?1 ?2 ?3] -> ?1 + ?2 + ?3 ] f1 f2 f3 )

  set v (map + v force)

  if (norm v) > 5 [
   set v normalize v
    set v map [ ? -> ? * 5 ] v
  ]
end

to-report normalize [xy]
  let realdis norm xy
  let out [0 0]
  if realdis > 0[
    set out  (map [ ? -> ? / realdis ] xy)
  ]
  report out
end

to-report norm [arr]
  let xx first arr
  let yy last arr
  report sqrt (xx * xx + yy * yy )
end

 

 

代码完成后,就可以跑模型啦!

 

 

  • 当我们试图调高 聚集系数的时候:

鸟群的飞行开始倾向为一条线的形状。

 

  • 当我们试图调高 对齐系数的时候:

鸟群的飞行方向的变得更加相同。

 

  • 当我们试图调高 防碰撞系数 的时候:

鸟群的结构趋于松散化。

 

除此之外,还可以用netlogo自带的 flocking 模型,改模型也是能模拟鸟群飞行的模型之一。

《Netlogo多主体建模入门》笔记 9_第16张图片

 

flocking 模型运行界面:

 

你可能感兴趣的:(Netlogo多主体建模入门,数据仿真,Netlogo)