首页 > 解决方案 > Netlogo:嵌套的 if/ifelse 语句

问题描述

使用 Netlogo 构建我的第一个 ABM,并且遇到了涉及 ifelse 语句以及如何使用它们的问题。我正在模拟代理对被淹没的属性的响应。概念如下:

如果代理被淹没,他们将考虑采取保护措施(如果他们还没有)。如果代理采取了保护措施并被淹没,则计算该措施的成功。

我的代码如下:

    to process-property
  let $random-flood-number random-float 1
  ask properties [
    set flood-damage-list-consequent replace-item 1 flood-damage-list-consequent (item 1 flood-damage-list-initial * (1 - PLP-reduction))
    set flood-damage-list-consequent replace-item 2 flood-damage-list-consequent (item 2 flood-damage-list-initial * (1 - PLP-reduction))'
    ifelse $random-flood-number < probability-flooding
    [
      set flooded? TRUE
      set number-of-times-flooded (number-of-times-flooded + 1)
      if plp-adopted? != TRUE [
        calculate-adoption-intention
      ]
    ]
    [
      set flooded? FALSE
    ]
  ]

  ask properties with [plp-adopted? = TRUE] [
    plp-reliability-analysis
  ]

end

    to plp-reliability-analysis
  if plp-abandoned? = TRUE [stop]
  if flooded? = TRUE [
  if number-of-times-flooded > 1 [
    let plp-reliability-factor 0.77 ;;This variable represents the probability of success that Manual PLP will offer full reduction in damage. Taken from JBA (2012;2014).
    ifelse random-float 1 < plp-reliability-factor
      [
        set plp-deployed-successful? TRUE
        set PLP-reduction 0.25
        set successful-flood-damage-reduction (sum flood-damage-list-initial * PLP-reduction)
      ]
      [
        set plp-deployed-successful? FALSE
        set PLP-reduction 0.9
        set unsuccessful-flood-damage-reduction (sum flood-damage-list-initial * PLP-reduction)
        calculate-abandonment-intention
      ]
    ]
  ]
end

我编写了以下代码作为错误检查,我不断得到:

if flooded? = FALSE and plp-deployed-successful? = TRUE [error["Properties should only deploy PLP when they are flooded"]]

我认为问题在于“plp-reliability-analysis”过程中的 ifelse 语句。我是 Netlogo 的新手,对何时使用“if”或“ifelse”语句感到困惑。如果有人可以解释并查看上面的代码,我将不胜感激。

谢谢,大卫

标签: if-statementnetlogoagent-based-modeling

解决方案


if和的区别在于ifelse

  • if当您只想在某些条件下运行某些代码时使用
  • ifelse当您想在某些条件下运行一段代码时使用,如果条件不满足,则使用另一段代码。

看看你的代码的这个缩短版本。请注意,我将左括号移到了行首,以对齐代码块的开头和结尾。对于非常短的代码块,我还将结束括号放在同一行,但括号与您的相同。

to process-property
  let $random-flood-number random-float 1
  ask properties
  [ ifelse $random-flood-number < probability-flooding
    [ set flooded? TRUE ]
    [ set flooded? FALSE ]
  ]
  ask properties with [plp-adopted? = TRUE]
  [ plp-reliability-analysis
  ]
end

to plp-reliability-analysis
  if flooded? = TRUE
  [ if number-of-times-flooded > 1
    [ let plp-reliability-factor 0.77
      ifelse random-float 1 < plp-reliability-factor
      [ set plp-deployed-successful? TRUE ]
      [ set plp-deployed-successful? FALSE ]
    ]
  ]
end

您绘制一个随机数并将其分配给变量 $random-flood-number。然后您要求每个房地产经纪人将该数字与 的值进行比较probability-flooding。但是,您永远不会绘制新的随机数。因此,如果一个属性为真,那么所有属性都为真。鉴于这是一个洪水模型,这可能是故意的,因为所有房屋都同样受到洪水的影响。

想象一下,绘制的数字很低,它们都被淹没了。所有带有 plp 的都采用了?然后发送到 plp-reliability-analysis 程序。对于他们所有人来说,变量被淹没了?为真,因此运行代码块。

第一行是if number-of-times-flooded > 1. 第一次发生洪水时,洪水的次数从 0 更改为 1。这将使测试失败(您的意思是使用 >= 而不是 > 吗?)并且其余代码将不会运行. 它只会跳转到结束括号。

[ let plp-reliability-factor 0.77
  ifelse random-float 1 < plp-reliability-factor
  [ set plp-deployed-successful? TRUE ]
  [ set plp-deployed-successful? FALSE ]
]

但是对于第二个和以后的代码,它将运行并且 77% 的属性将 plp 记录为成功,而其他设置为不成功。

那么,你如何最终得到一些具有假洪水组合的属性?和真正的 plp 部署成功?

现在及时向前跳跃,发生 2 次(或更多)洪水。一场洪水刚刚发生,那么77% 的房产有plp-adopted?有真正的 plp 部署成功吗?这一次,没有洪水,所有的财产都被淹了?设置为假。那些用plp收养的?被发送到 plp-reliability-analysis 程序。然而,被淹?现在为假,因此代码块不会运行并且它们保留其 plp-deployed-successful 的值?从之前的贯穿。


推荐阅读