NetLogo - 家庭范围模型可以工作但很慢 - 可以加速吗?

时间:2014-04-17 21:53:29

标签: netlogo

我一直在研究NetLogo模型,模拟家园范围(我使用区域和家庭范围可互换的术语)动物的领土动物。在模型中,女性选择具有最高猎物值的补丁并将这些补丁添加到其区域。这很好用,看起来很快。男性受到女性的限制,因此将尝试让他们的家庭范围重叠多个女性家庭范围。在模型中,男性将占据单个女性家庭范围的90%(即,将相同的补丁添加到他的领地),然后移动到下一个最接近的女性家庭范围(其中没有其他男性在场)开始占领。这个过程似乎工作正常,但运行速度非常慢,以至于我担心自己无法进行多次模拟。有关如何加快这一过程的任何想法?我做了一些愚蠢的事情,比如在我不必要的时候要求所有补丁做某事吗?模型代码变得越来越长,所以我只添加了与男性家庭范围增长相关的部分。如果问题似乎在其他地方,我可以向某人提供更多代码。任何帮助将非常感激!

to update-male-home-range
  ask males ; the following procedure allows males to encompass 90% of a female's home range
  [
    let this-male self
    foreach [owner-fem] of females-in-my-territory ; the number of females in male territory is set when the males are dropped onto the landscape at tick 5. This number is updated at the end of this whole process.
    [
      let ? [owner-fem] of females-in-my-territory ; this ensures that the male will occupy each female territory sequentially instead of jumping back and forth
      while [((count patches with [(owner-fem = ?) and (owner-male = this-male)]) / (count [territory] of ?)) < 0.9] ; the male keeps adding cells to his home range from the home range of the female until he has encompassed 90% of them
      [ 
        let avail-fem-patches no-patches
        let target nobody
        let new-patches no-patches
        ask territory
          [
            ; Add unoccupied neighbor patches as potential targets:
            set avail-fem-patches (patch-set avail-fem-patches neighbors4 with [(owner-fem = ?) and (owner-male = nobody)])
          ]
        ; Set of all potential targets:
        set new-patches (patch-set new-patches avail-fem-patches) 

        ; Only chooses unoccupied neighbors 
        if any? new-patches
          [
            ask new-patches
              [
                if any? avail-fem-patches 
                [set target one-of avail-fem-patches]
              ]
            move-to target ; I let the animal move so you can see which patch he chose
          ]

        if target != nobody
          [
            ; Add target patch to territory of the current animal:
            set territory (patch-set territory target) ; this is the territory of the calling animal - we are still in its context
            ask target [ set owner-male myself ] ; Tell target patch that is has new owner-male:
          ]

        ask territory
        [
          set pcolor ([color] of myself) - 2
          if owner-male != myself [ user-message "Something wrong" ]
        ]

        set XY [list pxcor pycor] of territory
        set X map [(item 0 ?)] XY ;getting X coordinates for home range mapping later
        set Y map [(item 1 ?)] XY ;getting Y coordinates for home range mapping later

        let fem-patch-in-male-hr count patches with [(owner-fem = ?) and (owner-male = this-male)] ; this is for reporting purposes only. 
        ; This shows the number of patches belonging to the female home range that has also been claimed by the male
        let size-of-fem-hr (count [territory] of ?) ; this is for reporting purposes only
        ; This reports the total size of the female home range that the male has begun overlapping
        let fem-patch-hr-size-ratio fem-patch-in-male-hr / size-of-fem-hr ; this if for reporting purposes only
        ; This is  ratio of the number of patches claimed by the male that belongs to the home range of the female. 
        ; This ratio is the same as that in the "while" procedure above and shows whether the male has encompassed 90% or not.
      ]
      ;set total-females count females-in-my-territory
    ]

  ] ; ask males

  ask males ; After all males have encompassed their respective female home ranges, this procedure tells the males to find the closest female home range that is unoccupied and move to it to begin overlapping her home range
  [
    let other-females females with [not member? self ([females-in-my-territory] of myself)] ; females not in my territory
    let females-with-males females with [count males-in-my-territory != 0] ; female home ranges occupied by a male including myself
    let females-with-no-males females with [count males-in-my-territory = 0] ; female home ranges with no male
    let other-males-females females-with-males with [not member? myself ([males-in-my-territory] of self)] ; female home ranges occupied by a male not including myself 
    if count females-with-no-males > 0 ; if a female home range does not have a male occupying it
    [
      let target-patches no-patches
      set target-patches (patch-set target-patches ([territory] of females-with-no-males in-radius 10)) ; create patch-set that is all territories of females with no males occupying their home ranges
      let target-fem-patch no-patches
      ask territory 
      [
        set target-fem-patch min-one-of target-patches [distance myself] ; select the patch from female home ranges with no males that is closest to my home range.  This doesn't seem like it is working quite right.


      if target-fem-patch != nobody
      [
        move-to target-fem-patch ; move the male to this patch in the female home range previously unoccupied
        set territory (patch-set territory target-fem-patch) ; update the male's territory
        ;let old-owner-male [owner-male] of target-fem-patch
        ask target-fem-patch [ set owner-male myself ] ; update the owner
        ask territory ; update the color of the patch according to the owner of the territory
        [
          set pcolor ([color] of myself) - 2
          if owner-male != myself [ user-message "Something wrong" ]
        ]
        set females-in-my-territory females with [member? self ([owner-fem] of [territory] of myself)] ; update the number of female home ranges that the male occupies
        ask females 
        [
          set males-in-my-territory males with [member? self ([owner-male] of [territory] of myself)] ; update the number of males that occupy each female's home range
        ]
      ]
    ]

    ask territory ; update the patch color again because some males may not have been able to add any patches from the prior procedure
      [
        set pcolor ([color] of myself) - 2
        if owner-male != myself [ user-message "Something wrong" ]
      ]

    set XY [list pxcor pycor] of territory ; update the XY coordinates for the male territories for the home range calculation later
    set X map [(item 0 ?)] XY
    set Y map [(item 1 ?)] XY
  ]

end ; update-male-home-range

2 个答案:

答案 0 :(得分:3)

这绝对是一大堆代码。我尽量不让我的程序超过大约10或15行(并且这只是一个上限,许多好的程序只是1或3或5行)。否则,复杂性就太多了,而且几乎不可能有效地理解或排除任何问题。

此外,如果您将其分解为较小的程序,那么您可以使用分析器扩展程序来衡量哪些程序一直在进行。

重新&#34;要求所有补丁在我不必做的时候做某事,是的,是的。您正在执行count patches with ...,它会循环遍历所有修补程序,并且您正在while循环内执行此循环,该循环位于foreach循环内,位于ask循环内{1}}循环......!

我不太了解您的代码,无法提出修复建议。

答案 1 :(得分:2)

首先可以轻松优化:

    if any? new-patches
      [
        ask new-patches
          [
            if any? avail-fem-patches 
            [set target one-of avail-fem-patches]
          ]
        move-to target ; I let the animal move so you can see which patch he chose
      ]

您已将所有new-patches设为target。但是,他们只是覆盖相同的target变量。实际上,您甚至不需要new-patches来执行此操作。因此,您可以用以下代码替换上面的代码:

if any? avail-fem-patches [
  set target one-of avail-fem-patches
  move-to target
]

接下来,这个:

    ask territory
    [
      set pcolor ([color] of myself) - 2
      if owner-male != myself [ user-message "Something wrong" ]
    ]

一遍又一遍地将整个territory设置为相同的颜色(循环的每次迭代),但是你只需要设置目标补丁的颜色,对吧?所以这可以成为:

ask target [ set pcolor ([color] of myself) - 2 ]

你继续mapterritory的{​​{1}}(在这样的紧密循环中这是昂贵的),但你实际上从未使用过结果:{{ 1}},ycorX。最低限度,你应该只在最后,在所有循环之外做到这一点。但你可以完全删除它。

快速注意事项:Y实际上只设置为XY,因为它在while循环的每次迭代开始时设置为new-patches,然后设置为{avail-fem-patches 1}}。这是一个错误吗?

最后,现在您正在查看每个区域补丁的每个单个邻居,以向no-patches添加单个补丁。相反,你可以在循环的每次迭代中尽可能多地修补补丁。类似的东西(用(patch-set avail-fem-patches new-patches)替换territory):

target

然后您将所有targets添加到该地区。这在行为上会有所不同。现在,你可以将小径切入女性的领地。在这里,男性的领土将尽可能广泛地扩大。不确定这是不是坏事。