有没有一种简单的方法来为 netlogo 中的一系列刻度线编码?
Is there a simple way to code for a sequence of multiples of ticks in netlogo?
我如何让模型每 x 刻度减少一个变量,而不是简单地编写一个长列表?似乎应该有一种方法可以使用ticks,例如每 20n ticks 减少变量,其中 n = 1, 2, 3,...,但我想不出它是如何工作的,所以我只是创建了一个列表。
例如,在下面的代码中,我将变量 octopamine-level 每 20 个 ticks 减少 1 个单位,超过 first-leader-tick。
if (ticks - first-leader-tick = 20) or (ticks - first-leader-tick = 40) or (ticks - first-leader-tick = 60) or (ticks - first-leader-tick = 80) or (ticks - first-leader-tick = 100) or (ticks - first-leader-tick = 120) or (ticks - first-leader-tick = 140) or (ticks - first-leader-tick = 160) or (ticks - first-leader-tick = 180)
[set octopamine-level octopamine-level - 1]
但是,我计划使用一个更大的变量,这将需要一个长得离谱的列表,因此更简洁的方法会非常有帮助。
谢谢!
简单方法#1
您可以在下次需要更新值时使用提醒:
globals [
next-update
octopamine-level
]
to setup
clear-all
reset-ticks
set octopamine-level 10
type "initial level of octopamine: " print octopamine-level
set next-update "none" ; This is needed because, otherwise, the first iteration (i.e. where
; 'ticks = 0') would always satisfy the 'if (ticks = next-update)'
; condition. Doing 'set next-update - 1' would work too, depending on
; which approach you find more relevant and/or elegant.
end
to go
; With this first block of commands I'm just randomly choosing the
; initial tick for starting the reduction.
if (octopamine-level = 10) AND (random 100 < 1) [
set octopamine-level octopamine-level - 1
set next-update ticks + 20
type "ticks = " type ticks type ", octopamine = " type octopamine-level print ", reduction started"
]
if (ticks = next-update) [
set octopamine-level octopamine-level - 1
set next-update ticks + 20
type "ticks = " type ticks type ", octopamine = " print octopamine-level
]
if (octopamine-level = 0) [stop]
tick
end
简单方法#2
如果您还想更容易地访问关于下一次更新需要多长时间/自上次更新以来已经过了多长时间的信息,您可以创建一个计数器:
globals [
counter
counter-on? ; See comment to in 'to setup'.
octopamine-level
]
to setup
clear-all
reset-ticks
set octopamine-level 10
type "initial level of octopamine: " print octopamine-level
set counter "none"
set counter-on? FALSE ; This, together with the condition in which it is used, is needed
; because we cannot simply 'set counter "none"', as that will give
; a runtime error when executing 'set counter counter - 1' (and using
; 'if (is-number? counter) [set counter counter - 1]' doesn't look
; very nice to me).
; Note that you could get rid of all the 'counter-on?' thing and just
; do 'set counter -1' upon setup. This would work, but would also
; execute 'set counter counter - 1' at every tick, bringing 'counter'
; to always more negative numbers before the reduction actually starts -
; which I personally don't really like.
end
to go
; With this first block of commands I'm just randomly choosing the
; initial tick for starting the reduction.
if (octopamine-level = 10) AND (random 100 < 1) [
set counter-on? TRUE
set counter 20
set octopamine-level octopamine-level - 1
type "ticks = " type ticks type ", octopamine = " type octopamine-level print ", reduction started"
]
if (counter = 0) [
set octopamine-level octopamine-level - 1
set counter 20
type "ticks = " type ticks type ", octopamine = " print octopamine-level
]
if (octopamine-level = 0) [stop]
if (counter-on?) [
set counter counter - 1
]
tick
end
这种方法的另一个积极方面是,如果需要,它可以很容易地随时暂停和恢复计数器,只需使用 set counter-on? FALSE
和 set counter-on? TRUE
.
不太简单的方法
要采用一种看起来更类似于您的思路的方法(但比之前的选项更复杂),这种需求也可以通过使用 remainders 来解决,在 NetLogo 中你确实可以使用 remainder
(check here).
您可以使用以下例程每 20 个刻度执行一次命令。
if (remainder ticks 20 = remainder first-leader-tick 20) [
set octopamine-level octopamine-level - 1
]
总的来说,执行我之前针对其他方法讨论的调整类型,它看起来像:
globals [
first-leader-tick
reduction-on?
octopamine-level
]
to setup
clear-all
reset-ticks
set octopamine-level 10
type "initial level of octopamine: " print octopamine-level
set reduction-on? FALSE
end
to go
; With this first block of commands I'm just randomly choosing the
; initial tick for starting the reduction.
if (octopamine-level = 10) AND (random 100 < 1) [
set reduction-on? TRUE
set first-leader-tick ticks
set octopamine-level octopamine-level - 1
type "ticks = " type ticks type ", octopamine = " type octopamine-level print ", reduction started"
]
if (reduction-on?) AND (ticks > first-leader-tick) AND (remainder ticks 20 = remainder first-leader-tick 20) [
set octopamine-level octopamine-level - 1
type "ticks = " type ticks type ", octopamine = " print octopamine-level
]
if (octopamine-level = 0) [stop]
tick
end
需要(reduction-on?)
条件,否则tick 0总是会通过测试(事实上remainder 20 20 = remainder 0 20
)。
需要(ticks > first-leader-tick)
条件,因为(remainder ticks 20 = remainder first-leader-tick 20)
在缩减开始时(即ticks = first-leader-tick
时)也为真,这将导致执行两次set octopamine-level octopamine-level - 1
在减少开始时打勾(一次在第一个 if 块中,一次在第二个 if 块中)。
或者,如果您愿意,可以通过 :
摆脱 (ticks > first-leader-tick)
条件
- 从第一个 if 块中删除
set octopamine-level octopamine-level - 1
行;
- 将第二个 if 块(计算余数的那个)放在第一个 if 块(开始减少的那个)之前。
非常简单,您可以使用 MOD 运算符来完成此操作。
MOD 除法,然后 returns 余数。
这有一个很大的副作用,即总是返回一个介于 0 和比除数小 1 之间的数字。
更简单:ticks MOD 20 总是给出 0 到 19 之间的数字。100 mod 20 是 0。119 mod 20 是 19。120 mod 20又归零了。看?整洁,对吧?
所以你可以做
If (ticks - first-leader-tick) mod 20 = 0
[
;;每 20 个滴答做一次你做的事情。
]
请注意,这也会使其在第一次执行此操作。所以相应地调整你的逻辑。
我如何让模型每 x 刻度减少一个变量,而不是简单地编写一个长列表?似乎应该有一种方法可以使用ticks,例如每 20n ticks 减少变量,其中 n = 1, 2, 3,...,但我想不出它是如何工作的,所以我只是创建了一个列表。
例如,在下面的代码中,我将变量 octopamine-level 每 20 个 ticks 减少 1 个单位,超过 first-leader-tick。
if (ticks - first-leader-tick = 20) or (ticks - first-leader-tick = 40) or (ticks - first-leader-tick = 60) or (ticks - first-leader-tick = 80) or (ticks - first-leader-tick = 100) or (ticks - first-leader-tick = 120) or (ticks - first-leader-tick = 140) or (ticks - first-leader-tick = 160) or (ticks - first-leader-tick = 180)
[set octopamine-level octopamine-level - 1]
但是,我计划使用一个更大的变量,这将需要一个长得离谱的列表,因此更简洁的方法会非常有帮助。
谢谢!
简单方法#1
您可以在下次需要更新值时使用提醒:
globals [
next-update
octopamine-level
]
to setup
clear-all
reset-ticks
set octopamine-level 10
type "initial level of octopamine: " print octopamine-level
set next-update "none" ; This is needed because, otherwise, the first iteration (i.e. where
; 'ticks = 0') would always satisfy the 'if (ticks = next-update)'
; condition. Doing 'set next-update - 1' would work too, depending on
; which approach you find more relevant and/or elegant.
end
to go
; With this first block of commands I'm just randomly choosing the
; initial tick for starting the reduction.
if (octopamine-level = 10) AND (random 100 < 1) [
set octopamine-level octopamine-level - 1
set next-update ticks + 20
type "ticks = " type ticks type ", octopamine = " type octopamine-level print ", reduction started"
]
if (ticks = next-update) [
set octopamine-level octopamine-level - 1
set next-update ticks + 20
type "ticks = " type ticks type ", octopamine = " print octopamine-level
]
if (octopamine-level = 0) [stop]
tick
end
简单方法#2
如果您还想更容易地访问关于下一次更新需要多长时间/自上次更新以来已经过了多长时间的信息,您可以创建一个计数器:
globals [
counter
counter-on? ; See comment to in 'to setup'.
octopamine-level
]
to setup
clear-all
reset-ticks
set octopamine-level 10
type "initial level of octopamine: " print octopamine-level
set counter "none"
set counter-on? FALSE ; This, together with the condition in which it is used, is needed
; because we cannot simply 'set counter "none"', as that will give
; a runtime error when executing 'set counter counter - 1' (and using
; 'if (is-number? counter) [set counter counter - 1]' doesn't look
; very nice to me).
; Note that you could get rid of all the 'counter-on?' thing and just
; do 'set counter -1' upon setup. This would work, but would also
; execute 'set counter counter - 1' at every tick, bringing 'counter'
; to always more negative numbers before the reduction actually starts -
; which I personally don't really like.
end
to go
; With this first block of commands I'm just randomly choosing the
; initial tick for starting the reduction.
if (octopamine-level = 10) AND (random 100 < 1) [
set counter-on? TRUE
set counter 20
set octopamine-level octopamine-level - 1
type "ticks = " type ticks type ", octopamine = " type octopamine-level print ", reduction started"
]
if (counter = 0) [
set octopamine-level octopamine-level - 1
set counter 20
type "ticks = " type ticks type ", octopamine = " print octopamine-level
]
if (octopamine-level = 0) [stop]
if (counter-on?) [
set counter counter - 1
]
tick
end
这种方法的另一个积极方面是,如果需要,它可以很容易地随时暂停和恢复计数器,只需使用 set counter-on? FALSE
和 set counter-on? TRUE
.
不太简单的方法
要采用一种看起来更类似于您的思路的方法(但比之前的选项更复杂),这种需求也可以通过使用 remainders 来解决,在 NetLogo 中你确实可以使用 remainder
(check here).
您可以使用以下例程每 20 个刻度执行一次命令。
if (remainder ticks 20 = remainder first-leader-tick 20) [
set octopamine-level octopamine-level - 1
]
总的来说,执行我之前针对其他方法讨论的调整类型,它看起来像:
globals [
first-leader-tick
reduction-on?
octopamine-level
]
to setup
clear-all
reset-ticks
set octopamine-level 10
type "initial level of octopamine: " print octopamine-level
set reduction-on? FALSE
end
to go
; With this first block of commands I'm just randomly choosing the
; initial tick for starting the reduction.
if (octopamine-level = 10) AND (random 100 < 1) [
set reduction-on? TRUE
set first-leader-tick ticks
set octopamine-level octopamine-level - 1
type "ticks = " type ticks type ", octopamine = " type octopamine-level print ", reduction started"
]
if (reduction-on?) AND (ticks > first-leader-tick) AND (remainder ticks 20 = remainder first-leader-tick 20) [
set octopamine-level octopamine-level - 1
type "ticks = " type ticks type ", octopamine = " print octopamine-level
]
if (octopamine-level = 0) [stop]
tick
end
需要(reduction-on?)
条件,否则tick 0总是会通过测试(事实上remainder 20 20 = remainder 0 20
)。
需要(ticks > first-leader-tick)
条件,因为(remainder ticks 20 = remainder first-leader-tick 20)
在缩减开始时(即ticks = first-leader-tick
时)也为真,这将导致执行两次set octopamine-level octopamine-level - 1
在减少开始时打勾(一次在第一个 if 块中,一次在第二个 if 块中)。
或者,如果您愿意,可以通过 :
摆脱(ticks > first-leader-tick)
条件
- 从第一个 if 块中删除
set octopamine-level octopamine-level - 1
行; - 将第二个 if 块(计算余数的那个)放在第一个 if 块(开始减少的那个)之前。
非常简单,您可以使用 MOD 运算符来完成此操作。
MOD 除法,然后 returns 余数。
这有一个很大的副作用,即总是返回一个介于 0 和比除数小 1 之间的数字。
更简单:ticks MOD 20 总是给出 0 到 19 之间的数字。100 mod 20 是 0。119 mod 20 是 19。120 mod 20又归零了。看?整洁,对吧?
所以你可以做
If (ticks - first-leader-tick) mod 20 = 0 [ ;;每 20 个滴答做一次你做的事情。 ]
请注意,这也会使其在第一次执行此操作。所以相应地调整你的逻辑。