为什么海龟总数与 UI 与代理设置中定义的数量不同?

问题描述 投票:0回答:1

我要求 Netlogo 创建代表旧车、中年车和新车的海龟作为代理,每个都有一定的固定百分比(分别为 65%、30% 和 5%)。我在用户界面中有一个滑块,用于设置汽车总数,代码会计算这些比例。所发生的情况是,并不是每次我在设置中都得到准确数量的代理。例如,对于在 UI 中设置的 10 个代理,我总共设置了 9 辆车,其中 6 辆是旧车,3 辆是中年车,0 辆是新车。我想我希望代码对这些数字进行四舍五入,以使设置的代理总数与 UI 中显示的代理总数相匹配。 我的代码如下:

to create-ICE-engine-cars
  let ICE-old (cars-ICE-engine * 0.65)
  let ICE-middle (cars-ICE-engine * 0.3)
  let ICE-new (cars-ICE-engine * 0.05)
  
  ask n-of ICE-old patches with [p-road-data > 9] 
  [sprout 1]

  ask n-of ICE-middle patches with [p-road-data > 9]
  [sprout 1]
  
  ask n-of ICE-new patches with [p-road-data > 9]
  [sprout 1]
end

我认为对于给定类别而言,向上或向下舍入并不重要。我只需要拥有与 UI 中定义的设置代理数量相同的设置代理。谢谢你。

user-interface rounding netlogo agent
1个回答
0
投票

当您尝试将浮点数用于“sprout”等过程时,Netlogo 会将浮点数舍入到下一个整数。因此,您必须编写一些代码来确保您仍然添加一些额外的汽车。一种方法是首先创建您想要的汽车数量,然后再更改它们。

您可以采取的另一种方法是计算每个类别有多少辆汽车,然后根据随机加权选择分配最后一辆汽车

to test
  let cars-ICE-engine 10
  
  let ICE-old (cars-ICE-engine * 0.65)
  let ICE-middle (cars-ICE-engine * 0.3)
  let ICE-new (cars-ICE-engine * 0.05)
  
  let int-old floor ICE-old
  let int-middle floor ICE-middle
  let int-new floor ICE-new 
  
  
  let remainder-old ICE-old - int-old
  let remainder-middle ICE-middle - int-middle
  let remainder-new ICE-new - int-new 
  


  let number random-float 1
  (ifelse 
    number <= remainder-old [set int-old int-old + 1]
    number <= remainder-old + remainder-middle [set int-middle int-middle + 1]
    number <= remainder-old + remainder-middle + remainder-new [set int-new int-new + 1]
  )
  
  print int-old
  print int-middle
  print int-new
end

这种方法不能很好地扩展,因为如果您有更多类别怎么办?如果分配的方式恰好是您缺少超过 1 辆车怎么办? 以下代码通过使用列表和循环可以更好地扩展,但根据您编写程序的目的,它可能有点过头了。

to go-2
  let cars-ICE-engine 111034

  ;Initiate multiple categories
  let ICE-old (cars-ICE-engine * 0.35)
  let ICE-middle (cars-ICE-engine * 0.3)
  let ICE-new (cars-ICE-engine * 0.05)
  let ICE-1 (cars-ICE-engine * 0.07)
  let ICE-2 (cars-ICE-engine * 0.10)
  let ICE-3 (cars-ICE-engine * 0.13)
  
  let ICE-list (list ICE-old ICE-middle ICE-new ICE-1 ICE-2 ICE-3) ;join all the categories into one lit
  let int-list map floor ICE-list ;Round all the numbers downfor the actual number of cars each category will get
  let remainder-list (map [[a b] -> a - b] ICE-list int-list) ;Calculate the remainder for each number that you rounded down
   
  
  let to-distribute round sum remainder-list ;Calculate how many cars still need to be distributed
  
  repeat to-distribute [
    let number random-float to-distribute
    let flag False
    let cum-rem-list map [i -> sum sublist remainder-list 0 (i + 1)] range length remainder-list ;I create a new list where each value is the sum of itself and all prior values i nthe remainder-list This list is useful for selecting a category using a random weighted method
    
    foreach range length cum-rem-list [ i ->
      if not flag [
        if number <= item i cum-rem-list [
          set int-list replace-item i int-list (item i int-list + 1)  ;I increase the value of the selected category by 1
          set to-distribute to-distribute - item i remainder-list ;Subtract the selected value from t-distribute so that the newto-distribute is still the sum of everything in the remainder-list
          set remainder-list replace-item i remainder-list 0 ;I remove the selected value from the remainder-list so that it can't be selected again
          set flag True
        ]
      ]
    ]
  ]
  
  print int-list
  print sum int-list
  
end
© www.soinside.com 2019 - 2024. All rights reserved.