Netlogo 让海龟在一个区域内随机行走
Netlogo let turtles random walk within an area
假设我有一片海滩和一片海洋,分别用灰色和青色色块表示。我有一些海龟(鱼),我将它们的起始位置随机限制在海洋中的某个地方。现在,每一次滴答,鱼都会按照正态分布(均值=0,标准差=1)的步长进行随机游动。从逻辑上讲,鱼在移动时应该留在海洋中而不是移动到海滩上。我尝试了与我用来将鱼的起始位置限制在海洋中相同的 while []
,但这似乎在这里不起作用,即鱼根本不动。有什么想法吗?
编辑:除了水中有 2 条鱼外,我在陆地上还有另外 2 只乌龟(例如牛和羊),它们与鱼类似,cannot/shouldn在它们进入水中时不会进入水中移动(事实上,我总共有 3 个 'habitats' 海龟不应该离开它们开始的栖息地)。当我将 LeirsW 的解决方案用于鱼和 cows/sheep 时,我的 Netlogo 冻结,我不得不强制退出。对此有什么想法吗?
编辑 2:x0 和 y0 没有错误,需要保留在代码中。
更新了以下代码:
breed [ fishes fish ]
fishes-own
[
x0 y0 xcur ycur
]
to setup
clear-all
reset-ticks
ask patches [set pcolor gray]
ask patches with [ pycor < (max-pycor / 2) ] [ set pcolor cyan ]
create-fishes 4
[
setxy random-xcor random-ycor
set x0 xcor
set y0 ycor
ifelse who <= ( 3 * 0.5 )
[ set shape "fish" set size 2 ]
[ set shape "fish" set size 3 ]
set color white
while [ pcolor != cyan ] [ setxy random-xcor random-ycor ]
]
create-fishes 4
[
setxy random-xcor random-ycor
set x0 xcor
set y0 ycor
ifelse who <= ( 4 - 1 + 4 * 0.5 )
[ set shape "sheep" set size 2 set color yellow ]
[ set shape "cow" set size 2 set color yellow]
;set color white
while [ pcolor != gray ] [ setxy random-xcor random-ycor ] ]
end
to go
fish-move
tick
end
to fish-move
ask fishes with [pcolor = cyan]
[
ifelse (random-float 1) < 0.95
[
let destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
while [ [pcolor] of destination != cyan ]
[
set destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
]
move-to destination
set xcur xcor
set ycur ycor
]
[
let destination patch random-xcor random-ycor
while [ [pcolor] of destination != cyan ]
[
set destination patch random-xcor random-ycor
]
move-to destination
set xcur xcor
set ycur ycor
]
]
ask fishes with [pcolor = gray]
[
ifelse (random-float 1) < 0.95
[
let destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
while [ [pcolor] of destination != gray ]
[
set destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
]
move-to destination
set xcur xcor
set ycur ycor
]
[
let destination patch random-xcor random-ycor
while [ [pcolor] of destination != gray ]
[
set destination patch random-xcor random-ycor
]
move-to destination
set xcur xcor
set ycur ycor
]
]
end
你的代码的问题是你要求你的鱼只在 non-cyan 方块上移动。因为它们都是从青色瓷砖开始的,所以它们都不会移动。
解决此问题的第一种方法是简单地让他们移动一次,然后只要他们在灰色上就再次移动
to fish-move
ask fishes
[
setxy (x0 + random-normal 0 1 ) (y0 + random-normal 0 1 )
while [ pcolor != cyan ]
[
setxy (x0 + random-normal 0 1 ) (y0 + random-normal 0 1 )
]
]
end
现在这带来了它自己的一系列问题,因为这意味着靠近灰色的鱼可能会移动到它上面并移动很长的距离,最后再次以青色结束。这就是为什么我更愿意将问题分为三个部分:选择目的地、评估目的地、移动到目的地。
为此,您可以使用 let
创建一个创造性地命名为“目的地”的局部变量:
let destination patch (xcor + random-normal 0 1 ) (ycor + random-normal 0 1 )
然后我们继续评估目的地是否是一个可行的补丁,如果有必要,选择一个新的目的地:
while [ [pcolor] of destination != cyan ] [ set destination <...> ]
然后最后,在找到令人满意的目的地之后,移动到它:
move-to destination
现在我也注意到你给每条鱼一个 x0
和 y0
并且你从不更新它们。这些鱼是不是要不断地在同一块地方盘旋?我假设不是,所以我删除了它们,让鱼根据它们当前的位置确定它们的目的地(xcor
和 ycor
)
breed [ fishes fish ]
to setup
clear-all
reset-ticks
ask patches [set pcolor gray]
ask patches with [ pycor < (max-pycor / 2) ] [ set pcolor cyan ]
create-fishes 4
[
setxy random-xcor random-ycor
set shape "fish" set size 2.5 set color white
while [ pcolor != cyan ] [ setxy random-xcor random-ycor ]
]
end
to go
fish-move
tick
end
to fish-move
ask fishes
[let destination patch (xcor + random-normal 0 1 ) (ycor + random-normal 0 1 )
while [ [pcolor] of destination != cyan ]
[
set destination patch (xcor + random-normal 0 1 ) (ycor + random-normal 0 1 )
]
move-to destination
]
end
最后一点,您也可以使用
let destination patch-at (random-normal 0 1) (random-normal 0 1)
这是一种略短的写法。
注意:由于问题已经更改,我觉得需要一个新的答案而不是编辑之前的答案,它本身仍然正确。但是,由于我最近才加入 Whosebug,如果需要,我会按照别人的判断将其附加到我之前的 post。
在您的新版本中,x0
和 y0
造成了您的问题。在将海龟洗牌以找到一个好的初始位置之前,您可以定义它们。这意味着一条鱼可以将其 x0
和 y0
设置为陆地。由于您的代码让他们在那个点附近寻找目的地,拒绝所有灰色目的地,您将陷入无休止的搜索。将 x0
和 y0
移动到 create-fishes
块的末尾解决了这个问题。
create-fishes 4
[
setxy random-xcor random-ycor
ifelse who <= ( 3 * 0.5 ) ; Set proportion of fishes in lagoon determined by slider
[ set shape "fish" set size 2 ]
[ set shape "fish" set size 3 ]
set color white
while [ pcolor != cyan ] [ setxy random-xcor random-ycor ]
set x0 xcor
set y0 ycor
]
现在进一步提出一般性建议
我添加了一个名为 habitat 的 fishes-own 变量。此变量在创建鱼时设置为一种颜色,并确定它们可以移动到哪种颜色的斑块。通过将其设为绑定到海龟的变量,您不需要为每种新类型的海龟设置新的移动代码。
我添加了 Matteo 的建议,即让他们 move-to one-of patches with [pcolor = [habitat] of myself]
.
更有效地选择他们的初始补丁
我将所有初始移动组合在一个单独的代码块中,只是为了不必为您要添加的每种不同类型的海龟重写它。
xcur
和ycur
有什么具体的目标吗?您已经可以在所有海龟上访问 xcor
和 ycor
,因此我看不到对它们的任何特定需求。
鱼种有什么具体的目标吗?否则,您可以只使用通用代理集 turtles
,并定义 turtles-own
而不是 fishes-own
。即使您有多个品种,定义为 turtles-own
的任何变量也可用于您的品种,因此您不必为每个品种分别定义它们。
breed [ fishes fish ]
fishes-own
[
x0 y0 xcur ycur habitat
]
to setup
clear-all
reset-ticks
ask patches [set pcolor gray]
ask patches with [ pycor < (max-pycor / 2) ] [ set pcolor cyan ]
create-fishes 4 ;create the water animals
[
ifelse who <= ( 3 * 0.5 )
[ set shape "fish" set size 2 ]
[ set shape "fish" set size 3 ]
set color white
set habitat cyan
]
create-fishes 4 ;create the land animals
[
ifelse who <= ( 4 - 1 + 4 * 0.5 )
[ set shape "sheep" set size 2 ]
[ set shape "cow" set size 2 ]
set color yellow
set habitat gray
]
ask fishes [ ;move all animals to their prefered habitat
move-to one-of patches with [pcolor = [habitat] of myself]
set x0 xcor
set y0 ycor
]
end
to go
fish-move
tick
end
to fish-move
ask fishes
[
ifelse (random-float 1) < 0.95
[
let destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
while [ [pcolor] of destination != habitat ]
[
set destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
]
move-to destination
set xcur xcor
set ycur ycor
]
[
let destination patch random-xcor random-ycor
while [ [pcolor] of destination != habitat ]
[
set destination patch random-xcor random-ycor
]
move-to destination
set xcur xcor
set ycur ycor
]
]
end
在NetLogo中,补丁是用整数坐标来标识的。也就是说,patch 0.4 0.4
与 patch 0 0
相同。 NetLogo 在定位补丁时将给定的坐标四舍五入到最接近的整数。因此,如果您的代码涉及向补丁的每个坐标添加 0 到 1 之间的随机值,则新计算的坐标很可能指的是同一个旧补丁。这也许可以解释为什么给定新计算的目的地的海龟似乎仍留在原来的地方。
解决您的问题的另一种方法是让海龟向前移动一段距离。这是一个例子,我告诉海龟检查它的前进方向,并在必要时改变路线:
ask turtles with [pcolor = cyan] [
let dist random-normal 0 1
while ([pcolor] of patch-at-heading-and-distance heading dist) != cyan [
set heading random-float 360
]
fd dist
]
在上面的代码中,变量dist
定义为移动的距离(负值表示向后移动),heading
是海龟的属性,表示它们的方向, fd
是 NetLogo 函数,告诉海龟朝它们前进的方向前进。
附带说明一下,random-normal
和 random-float
是两个不同的函数。具体来说,请注意 random-normal 0 1
从均值为 0 且标准差为 1 的正态分布中抽取随机数,而 random-float 1
给出介于 0 和 1 之间的随机数。
假设我有一片海滩和一片海洋,分别用灰色和青色色块表示。我有一些海龟(鱼),我将它们的起始位置随机限制在海洋中的某个地方。现在,每一次滴答,鱼都会按照正态分布(均值=0,标准差=1)的步长进行随机游动。从逻辑上讲,鱼在移动时应该留在海洋中而不是移动到海滩上。我尝试了与我用来将鱼的起始位置限制在海洋中相同的 while []
,但这似乎在这里不起作用,即鱼根本不动。有什么想法吗?
编辑:除了水中有 2 条鱼外,我在陆地上还有另外 2 只乌龟(例如牛和羊),它们与鱼类似,cannot/shouldn在它们进入水中时不会进入水中移动(事实上,我总共有 3 个 'habitats' 海龟不应该离开它们开始的栖息地)。当我将 LeirsW 的解决方案用于鱼和 cows/sheep 时,我的 Netlogo 冻结,我不得不强制退出。对此有什么想法吗?
编辑 2:x0 和 y0 没有错误,需要保留在代码中。
更新了以下代码:
breed [ fishes fish ]
fishes-own
[
x0 y0 xcur ycur
]
to setup
clear-all
reset-ticks
ask patches [set pcolor gray]
ask patches with [ pycor < (max-pycor / 2) ] [ set pcolor cyan ]
create-fishes 4
[
setxy random-xcor random-ycor
set x0 xcor
set y0 ycor
ifelse who <= ( 3 * 0.5 )
[ set shape "fish" set size 2 ]
[ set shape "fish" set size 3 ]
set color white
while [ pcolor != cyan ] [ setxy random-xcor random-ycor ]
]
create-fishes 4
[
setxy random-xcor random-ycor
set x0 xcor
set y0 ycor
ifelse who <= ( 4 - 1 + 4 * 0.5 )
[ set shape "sheep" set size 2 set color yellow ]
[ set shape "cow" set size 2 set color yellow]
;set color white
while [ pcolor != gray ] [ setxy random-xcor random-ycor ] ]
end
to go
fish-move
tick
end
to fish-move
ask fishes with [pcolor = cyan]
[
ifelse (random-float 1) < 0.95
[
let destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
while [ [pcolor] of destination != cyan ]
[
set destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
]
move-to destination
set xcur xcor
set ycur ycor
]
[
let destination patch random-xcor random-ycor
while [ [pcolor] of destination != cyan ]
[
set destination patch random-xcor random-ycor
]
move-to destination
set xcur xcor
set ycur ycor
]
]
ask fishes with [pcolor = gray]
[
ifelse (random-float 1) < 0.95
[
let destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
while [ [pcolor] of destination != gray ]
[
set destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
]
move-to destination
set xcur xcor
set ycur ycor
]
[
let destination patch random-xcor random-ycor
while [ [pcolor] of destination != gray ]
[
set destination patch random-xcor random-ycor
]
move-to destination
set xcur xcor
set ycur ycor
]
]
end
你的代码的问题是你要求你的鱼只在 non-cyan 方块上移动。因为它们都是从青色瓷砖开始的,所以它们都不会移动。
解决此问题的第一种方法是简单地让他们移动一次,然后只要他们在灰色上就再次移动
to fish-move
ask fishes
[
setxy (x0 + random-normal 0 1 ) (y0 + random-normal 0 1 )
while [ pcolor != cyan ]
[
setxy (x0 + random-normal 0 1 ) (y0 + random-normal 0 1 )
]
]
end
现在这带来了它自己的一系列问题,因为这意味着靠近灰色的鱼可能会移动到它上面并移动很长的距离,最后再次以青色结束。这就是为什么我更愿意将问题分为三个部分:选择目的地、评估目的地、移动到目的地。
为此,您可以使用 let
创建一个创造性地命名为“目的地”的局部变量:
let destination patch (xcor + random-normal 0 1 ) (ycor + random-normal 0 1 )
然后我们继续评估目的地是否是一个可行的补丁,如果有必要,选择一个新的目的地:
while [ [pcolor] of destination != cyan ] [ set destination <...> ]
然后最后,在找到令人满意的目的地之后,移动到它:
move-to destination
现在我也注意到你给每条鱼一个 x0
和 y0
并且你从不更新它们。这些鱼是不是要不断地在同一块地方盘旋?我假设不是,所以我删除了它们,让鱼根据它们当前的位置确定它们的目的地(xcor
和 ycor
)
breed [ fishes fish ]
to setup
clear-all
reset-ticks
ask patches [set pcolor gray]
ask patches with [ pycor < (max-pycor / 2) ] [ set pcolor cyan ]
create-fishes 4
[
setxy random-xcor random-ycor
set shape "fish" set size 2.5 set color white
while [ pcolor != cyan ] [ setxy random-xcor random-ycor ]
]
end
to go
fish-move
tick
end
to fish-move
ask fishes
[let destination patch (xcor + random-normal 0 1 ) (ycor + random-normal 0 1 )
while [ [pcolor] of destination != cyan ]
[
set destination patch (xcor + random-normal 0 1 ) (ycor + random-normal 0 1 )
]
move-to destination
]
end
最后一点,您也可以使用
let destination patch-at (random-normal 0 1) (random-normal 0 1)
这是一种略短的写法。
注意:由于问题已经更改,我觉得需要一个新的答案而不是编辑之前的答案,它本身仍然正确。但是,由于我最近才加入 Whosebug,如果需要,我会按照别人的判断将其附加到我之前的 post。
在您的新版本中,x0
和 y0
造成了您的问题。在将海龟洗牌以找到一个好的初始位置之前,您可以定义它们。这意味着一条鱼可以将其 x0
和 y0
设置为陆地。由于您的代码让他们在那个点附近寻找目的地,拒绝所有灰色目的地,您将陷入无休止的搜索。将 x0
和 y0
移动到 create-fishes
块的末尾解决了这个问题。
create-fishes 4
[
setxy random-xcor random-ycor
ifelse who <= ( 3 * 0.5 ) ; Set proportion of fishes in lagoon determined by slider
[ set shape "fish" set size 2 ]
[ set shape "fish" set size 3 ]
set color white
while [ pcolor != cyan ] [ setxy random-xcor random-ycor ]
set x0 xcor
set y0 ycor
]
现在进一步提出一般性建议
我添加了一个名为 habitat 的 fishes-own 变量。此变量在创建鱼时设置为一种颜色,并确定它们可以移动到哪种颜色的斑块。通过将其设为绑定到海龟的变量,您不需要为每种新类型的海龟设置新的移动代码。
我添加了 Matteo 的建议,即让他们
更有效地选择他们的初始补丁move-to one-of patches with [pcolor = [habitat] of myself]
.我将所有初始移动组合在一个单独的代码块中,只是为了不必为您要添加的每种不同类型的海龟重写它。
xcur
和ycur
有什么具体的目标吗?您已经可以在所有海龟上访问xcor
和ycor
,因此我看不到对它们的任何特定需求。鱼种有什么具体的目标吗?否则,您可以只使用通用代理集
turtles
,并定义turtles-own
而不是fishes-own
。即使您有多个品种,定义为turtles-own
的任何变量也可用于您的品种,因此您不必为每个品种分别定义它们。breed [ fishes fish ] fishes-own [ x0 y0 xcur ycur habitat ] to setup clear-all reset-ticks ask patches [set pcolor gray] ask patches with [ pycor < (max-pycor / 2) ] [ set pcolor cyan ] create-fishes 4 ;create the water animals [ ifelse who <= ( 3 * 0.5 ) [ set shape "fish" set size 2 ] [ set shape "fish" set size 3 ] set color white set habitat cyan ] create-fishes 4 ;create the land animals [ ifelse who <= ( 4 - 1 + 4 * 0.5 ) [ set shape "sheep" set size 2 ] [ set shape "cow" set size 2 ] set color yellow set habitat gray ] ask fishes [ ;move all animals to their prefered habitat move-to one-of patches with [pcolor = [habitat] of myself] set x0 xcor set y0 ycor ] end to go fish-move tick end to fish-move ask fishes [ ifelse (random-float 1) < 0.95 [ let destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1) while [ [pcolor] of destination != habitat ] [ set destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1) ] move-to destination set xcur xcor set ycur ycor ] [ let destination patch random-xcor random-ycor while [ [pcolor] of destination != habitat ] [ set destination patch random-xcor random-ycor ] move-to destination set xcur xcor set ycur ycor ] ] end
在NetLogo中,补丁是用整数坐标来标识的。也就是说,patch 0.4 0.4
与 patch 0 0
相同。 NetLogo 在定位补丁时将给定的坐标四舍五入到最接近的整数。因此,如果您的代码涉及向补丁的每个坐标添加 0 到 1 之间的随机值,则新计算的坐标很可能指的是同一个旧补丁。这也许可以解释为什么给定新计算的目的地的海龟似乎仍留在原来的地方。
解决您的问题的另一种方法是让海龟向前移动一段距离。这是一个例子,我告诉海龟检查它的前进方向,并在必要时改变路线:
ask turtles with [pcolor = cyan] [
let dist random-normal 0 1
while ([pcolor] of patch-at-heading-and-distance heading dist) != cyan [
set heading random-float 360
]
fd dist
]
在上面的代码中,变量dist
定义为移动的距离(负值表示向后移动),heading
是海龟的属性,表示它们的方向, fd
是 NetLogo 函数,告诉海龟朝它们前进的方向前进。
附带说明一下,random-normal
和 random-float
是两个不同的函数。具体来说,请注意 random-normal 0 1
从均值为 0 且标准差为 1 的正态分布中抽取随机数,而 random-float 1
给出介于 0 和 1 之间的随机数。