我为每只海龟创建了一个变量
utilities
(分配给补丁(学校)的实用程序),其中包含从 school-utility
(记者)派生的 30 个值,每个值对应一个补丁(学校)。每只海龟在该变量上都有 30 个值。然后我为每只海龟创建了累积总和。
to utility
set utilities [ school-utility ] of patches with [ schoolachievement_2 > 0 ]
set cumul sum utilities
let temp utilities
set school-utility_1 map [ i -> i / cumul ] temp
set school-utility_1 sort school-utility_1
let cum-sum []
let sum-so-far 0
let index 0
foreach school-utility_1 [
let next-sum sum-so-far + item index school-utility_1
set cum-sum lput next-sum cum-sum
set sum-so-far next-sum
set index index + 1
]
set cum-utility_1 cum-sum
我试图让海龟选择补丁(学校),以最小化
random-number 0 + random-float 1
和cum-utility_1
之间的差异。问题是 cum-utility_1
是一个海龟变量。
我已经尝试过了
set targets patches with <....>
let min-patch min-one-of targets [abs (random-number - [ cum-utility_1] of myself)]
但我收到消息
- expected input to be a number but got the list...
。
我也尝试过
set targets patches with <....>
let min-patch min-one-of targets [abs (random-number - cum-utility_1)]
得到
this code can't be run by a patch, only a turtle...
我怀疑问题是 Netlogo 不知道如何将 cum-utility_1
的不同值映射到每个补丁(学校)。
对于每只需要将实用程序链接到补丁的海龟来说,这是一种方法。它使用列表的列表,其中每个子列表的第一个元素是补丁(学校),第二个元素是与该补丁相关的一些值。列表的列表有点棘手,但一旦你习惯了它们,就不那么糟糕了。请注意,我的
school-utility
报告器只是说明性的,但它确实包含来自补丁和乌龟的变量,正如我收集到的那样。另请注意, random-number 0 + random-float 1
不是有效的语法,因此我将其解释为 random-number
是您要从中减去每个 cum-utility
的随机数。最后,如果不将其嵌入到更大的模型中,我无法测试此代码,因此可能存在我尚未发现的语法错误。
;school-utility should return a list of lists, of the form [[patch value] [patch value] ...]
;For instance:
to-report school-utility
report list self (school-achievement_2 * [some-variable] of myself)
end
;Then,
to utility
set utilities [ school-utility ] of patches with [ schoolachievement_2 > 0 ]
set cumul sum map [i -> last i] utilities
set school-utility_1 map [ i -> list (first i) (last i / cumul) ] utilities
set school-utility_1 sort-by [[i j] -> last i < last j] school-utility_1
;Now we have the patches sorted by their utilities, with the first item in each
;sublist being the patch and the second (last) being the utility.
let cum-sum []
let sum-so-far 0
foreach school-utility_1 [i ->
let next-sum sum-so-far + last i
;for a simple list without patch links
set cum-sum lput next-sum cum-sum
;for a list with patch links, which is what you will want below
set cum-sum lput list first i cum-sum
set sum-so-far next-sum
]
set cum-utility_1 cum-sum
;I think that last cum-utility_1 = 1.0?
let random-number random-float 1
let possible-targets map [i -> list first i abs (random-number - last i)]
;Now we want to find the sublist in possible targets with the minimum value for its
;second (last) element. target will be the first item in the first
;sublist of the sorted possible-targets.
set target first first sort-by [[i j] -> last i < last j] possible-targets
end
我认为使用链接可能不像@LeirsW 和我最初想象的那么糟糕。我可能会玩一下。
这是使用链接解决问题的另一种方法。每个学生在搜索过程中都会创建指向潜在学校的链接,然后将其删除,而不是永久链接。这会产生一些开销,但在任何给定时间的链接数量仍然很小。而且,由于学生和每个潜在学校之间存在单一链接,因此该链接可以保存特定于每个学生/学校对的那些变量。然而,有一个问题。 NetLogo 不允许海龟和斑块之间存在链接,因此我们不得不将学校设为一种海龟,然后将其放置在斑块上。这实际上是一种更好的方法,因为补丁是一个位置,而学校是一个将位置作为一个实体,但只是其属性之一。既然学校是海龟的一个品种,那么让学生拥有自己的品种也是有意义的。
同样,如果没有完整的模型,我无法测试其准确性或速度。
breed [schools school]
breed [students student]
links-own [school-utility_1 cum-utility_1 target-value]
students-own [some-variable target]
schools-own [school-achievement_2]
to-report school-utility
; Since these are directed links created by
; students, they run from student (end1) to school (end2).
report ([school-achievement_2] of end2 * [some-variable] of end1)
end
to utility ; this is run by turtles (students)
; create links to possible targets (schools) and have each link
; determine the utility of that school.
let possible-targets schools with [school-achievement_2 > 0]
create-links-to possible-targets [
set school-utility_1 school-utility
]
; sum the utilties of all the possible schools
let cumul sum [school-utility_1] of my-out-links
; calculate the school utilities relative to the total
ask my-out-links [set school-utility_1 school-utility_1 / cumul]
; now sort the links by school-utility_1.
; this gives us a list of links to the schools.
let sorted-links sort-on [school-utility_1] my-out-links
; and build the cum-utility_1 values
let sum-so-far 0
foreach sorted-links [i ->
let next-sum sum-so-far + [school-utility_1] of i
ask i [set cum-utility_1 next-sum]
set sum-so-far next-sum
]
; now find the target.
; We want to find the link, and thus the school, with the minimum calculated value.
let random-number random-float 1
ask my-out-links [
set target-value abs (random-number - cum-utility_1)
]
set target [end2] of min-one-of my-out-links [target-value]
; finally, clean up
ask my-out-links [ die ]
end
@Charles,@LeirsW,非常感谢您的建议。使用您建议的列表方法代码列表,我现在拥有以下内容。代码没有给出错误,海龟确实按照预期移动到补丁,但我仍在尝试了解代码是否满足我的需要。 谢谢你,尼克
to-report school-utility
report ( (schoolachievement_2) * [ some-variable ] of myself )
end
to utility
let patches-with-utilities patches with [schoolachievement_2 > 0]
let cumul 0
let utilities []
foreach (list patches-with-utilities) [p ->
ask p [
let util school-utility
set cumul cumul + util
set utilities lput (list p util) utilities
]
]
set school-utility_1 map [i -> list (first i) (last i / cumul)] utilities
let cum-sum []
let sum-so-far 0
foreach school-utility_1 [i ->
let next-sum sum-so-far + last i
; for a list with patch links, which is what you will want below
set cum-sum lput cum-sum (list first i)
set sum-so-far next-sum
]
set cum-utility_1 cum-sum
;last cum-utility_1 = 1.0
to test
let random-number random-float 1.00001
let possible-targets map [i -> list (first i) abs (random-number - last i)] school-utility_1
;Now we want to find the sublist in possible targets with the minimum value for its
;second (last) element.
let target nobody
let lowest 100
foreach possible-targets [i ->
if last i < lowest [
set lowest last i
set target first i
]
]
if target != nobody [
move-to one-of target
set enrolled? TRUE
]