这次挑了一个比较复杂的模型进行分析
涉及到了turtle的排列,新的主体link,loop循环,函数递归,图像等等
研究过程中也遇到了一些问题
这个模型主要是用来研究连通巨片的
每个时间步加一条边,每次加边重新探索整个图,来找连通巨片
找到连通巨片上色
之后给边上色,然后对边和点排列一波
之前我发现我的模型颜色一直在闪烁,最后发现是,我的视图更新方式是连续更新,应该设置成按时间步更新
这个闪烁问题差点把我弄自闭
这个模型是在模型库里就能找到的,在下面搜索 giant component即可
整体的界面如下
;;1.全局变量
globals[
current-component-size ;;当前探索连通片大小
giantComponent-size ;;当前最大的连通巨片大小
giantComponent-startNode ;;连通巨片的一个起点,后面上色方便找到连通巨片
]
;;2.节点附带属性
patches-own[
explored? ;;是否被探索过
]
;;3.初始化按钮 setup 代码
to setup
clear-all ;;清空一切
initial-node ;;调用初始化节点方法
reset-ticks ;;重设时钟
end
;;4.初始化节点方法 initial-node 代码
to initial-node
set-default-shape turtles "circle" ;;设置节点默认形状是圆
create-turtles nodeNum [ ;;创建nodeNum个节点,每个节点大小为3,颜色是黄色
set size 3
set color yellow
]
set giantComponent-startNode one-of turtles ;;随机选一个节点成为连通巨片
ask giantComponent-startNode[ ;;把其颜色变成红色
set color red
]
layout-circle turtles max-pxcor - 1 ;;把所有节点排列成一个圆圈,半径为 max-pxcor-1
end
;;5.循环迭代按钮 go 代码
to go
if( ((count links) * 2) >= (count turtles) * (count turtles - 1) )[ ;;退出条件
display
user-message "网络已经形成全连接网络,不能再加边了。"
stop
]
add-edge ;;执行函数,加一条边
explore-components ;;执行函数,探索所有的连通片,找到连通巨片
ask turtles[
set explored? false ;;方便之后涂色的探索
]
ask giantComponent-startNode[
color-giantComponent ;;给连通巨片上色
]
ask links[
set color [color] of end1 ;;设置边的颜色为 连边一端节点的颜色
]
layout ;;调用layout函数,对边和节点进行排列
tick ;;时间步+1
end
;;6.加边函数 add-edge
to add-edge
let node1 one-of turtles with [count link-neighbors < nodeNum - 1]
let node2 one-of turtles with [count link-neighbors < nodeNum - 1]
ask node1[
ifelse link-neighbor? node2 or node1 = node2[
add-edge
]
[
create-link-with node2
]
]
end
;;7.explore-components函数 代码
to explore-components
ask turtles[
set color yellow
set explored? false
]
loop[
let start one-of turtles with [not explored?] ;;每次选一个没有被探索过的节点
if start = nobody[ ;;全都探索过了退出
stop
]
set current-component-size 0
ask start[ ;;从这个节点开始,把这个连通片探索一遍
explore-current-component
]
if current-component-size > giantComponent-size[ ;;如果当前连通片最大,更新最大连通片
set giantComponent-size current-component-size
set giantComponent-startNode start
]
]
end
;;8.explore-current-component函数 代码
to explore-current-component
if explored? [
stop
]
set explored? true
set current-component-size current-component-size + 1
ask link-neighbors[
explore-current-component
]
end
;;9.color-giantComponnet函数 代码
to color-giantComponent
if explored?[
stop
]
set color red
set explored? true
ask link-neighbors[
color-giantComponent
]
end
;;10.layout函数
to layout
if not layout?[
stop ;;如果layout开关是关闭的,停止
]
repeat 10[ ;;重复10次
do-layout ;;执行排列函数
display ;;刷新界面
]
end
;;上方layout函数用到了 layout?这个开关,在主界面添加
;;layout函数调用了 do-layout函数
;;11.do-layout函数
to do-layout
;;这个弹簧排列是为了让整个模型运行起来更美观,传入节点集合和边结合
;;节点满足只要有一个邻居节点,就能加入节点集,边集合就是全体边
;;后面的三个系数是弹簧常数,弹簧长度,回归常数 就这样设置就行
layout-spring (turtles with [any? link-neighbors]) links 0.4 6 1
end
图代码
自己调试的时候,一定要注意,要保存文件
我昨天就因为时间步的问题,导致程序卡死,代码还没有保存
今天起来重新敲了一遍
基本的内容代码里都注释过了
为什么模型看上去不那么呆板? 用的layout-spring(弹簧样式),把连边当成弹簧
通过设置一系列系数,让动画看上去十分流畅
基本碰到循环,首先在开头考虑退出条件
调试的时候可以右击画面,点开全局变量,实时查看全局变量的情况
每次做模型先考虑模型的大小,左右上下是否连起来