Создание условных ссылок между двумя породами

#netlogo #agent-based-modeling

#netlogo #моделирование на основе агентов

Вопрос:

Я пишу модель рынка жилья NetLogo и его политические последствия. В модели есть две породы: домохозяйства и дома. Ранний шаг в моей разработке, с которым я сталкиваюсь с трудностями, — это сопоставление домохозяйств с домами с помощью одного из двух типов ссылок, собственных или арендуемых, определяемых вложенными условными операторами. Это привело к двум трудностям, которые я пока не смог преодолеть.

  1. В рамках команды setup-market command я пытаюсь определить набор возможных домов для покупки для каждого домохозяйства, которые, если они соответствуют набору условий, домохозяйство затем покупает (и создает link ). Если он не может позволить себе купить, он попытается арендовать. Если он не может позволить себе арендовать домашнее хозяйство die .

Мой код постоянно приводит к следующей ошибке:

IFELSE expected input to be a TRUE/FALSE but got the turtle (house XXX) instead.

  1. Существует еще одна проблема, с которой я сталкиваюсь позже в коде (в двух строках, закомментированных с помощью «;»), где я пытаюсь установить переменные owner-occupied и renter на 1 основе наличия соответствующей ссылки (они должны оставаться равными 0, и домохозяйство должно умереть, если оно останется несвязанным).

Полный код приведен ниже. Строка с «;; Это строка, вызывающая у меня проблемы», обозначает, где, по-видимому, возникает ошибка.

ОБНОВЛЕНИЕ: Код был обновлен с помощью решения JenB. Результирующая ошибка now: CREATE-LINK-WITH expected input to be a turtle but got NOBODY instead. которая возникает в строке: create-link-with one-of potentialHomes [ set color red

 undirected-link-breed [own-links own-link]
undirected-link-breed [rent-links rent-link]
breed [city-centers city-center]
breed [households household]
households-own 
[ 
  age 
  money 
  income 
  monthly-income 
  consumption 
  monthly-consumption 
  hh-size race 
  preference 
  net-income
  net-monthly-income
  myHouse
]
breed [houses house]
houses-own 
[ 
  cost 
  down-payment 
  mortgage-payment 
  rent 
  rent-premium 
  rooms 
  onMarket
  owner-occupied
  rental
  onMarket?
]
patches-own [ 
  seed?  ;;district seed
  district  ;;district number
  full? ;;is the district at capacity?
  quadrant 
]

to setup
  clear-all
  reset-ticks
  setup-patches
  set-default-shape households "person"
  create-households num-households [ setxy random-xcor random-ycor ]
  set-default-shape houses "house"
  create-houses num-houses [ setxy random-xcor random-ycor ]
  setup-households
  setup-houses
  setup-market
  generate-cities
end

to generate-cities
  let center-x random-xcor / 1.5 ;;keep cities away from edges
  let center-y random-ycor / 1.5
end

to setup-patches
  ask patches with [pxcor > 0 and pycor > 0] [set quadrant 1 set pcolor 19 ]
  ask patches with [pxcor > 0 and pycor < 0] [set quadrant 2 set pcolor 49 ]
  ask patches with [pxcor < 0 and pycor < 0] [set quadrant 3 set pcolor 139 ]
  ask patches with [pxcor < 0 and pycor > 0] [set quadrant 4 set pcolor 89 ]
end

to setup-households
  ask households
    [ set age random-poisson 38
      set money random-exponential 30600
      set income random-exponential 64324
      set monthly-income income / 12
      set consumption .5 * income
      set monthly-consumption consumption / 12 
      set hh-size random 6   1
      set net-income income - consumption
      set net-monthly-income monthly-income - monthly-consumption
    ]
end

to setup-houses
  ask houses
    [ set cost random-normal 300000 50000
      set down-payment cost * down-payment-rate
      set mortgage-payment (cost - down-payment) / 360 
      set rooms random-exponential 3
      set onMarket 1
      set rent mortgage-payment   mortgage-payment * .25
      set owner-occupied 0
      set rental 0
    ]
end

to setup-market
  ask houses
    [ set onMarket? TRUE ]
  ask households 
    [ ifelse any? houses with [ [money] of myself > down-payment and [net-monthly-income] of myself > mortgage-payment ]
      [ let potentialHomes houses with [[money] of myself > cost and onMarket? ] 
        create-link-with one-of potentialHomes [ 
          set color red
        ]
      ] 
      [ 
        ifelse any? houses with [ [net-monthly-income] of myself > rent]
[ let potentialRentals houses with [ [net-monthly-income] of myself > rent and onMarket? ] 
  create-link-with one-of potentialRentals [ set color blue ]
]
[ die ]
      ]
  ]
  ask houses 
    [ if any? link-neighbors [set onMarket FALSE ] 
      ;if any? link-neighbors and color red [ set owner-occupied 1 ]
      ;if any? link-neighbors and color blue [ set rental 1 ]
  ]
end

to go
  move-households
  tick
end

to move-households
  ask households [
    move-to myHouse
  ]
end
  

Ответ №1:

Вам не нужно «подозревать», в чем проблема, NetLogo указывает на проблемную строку. Запуск вашего кода, проблема на самом деле ifelse one-of houses with [ [net-monthly-income] of myself > rent] . Глядя на эту строку, вы вытаскиваете случайно выбранный дом из пула с арендной платой меньше, чем доход. Но у вас нет условия для ifelse тестирования.

В предыдущих конструкциях у вас было != nobody в конце, но вы забыли, что в этой строке. Это исправит ошибку, но ваш код был бы гораздо менее подвержен ошибкам, если бы вы использовали any? вместо этого. Вы, кажется, используете one-of .... != nobody для проверки, есть ли какие-либо черепахи, которые удовлетворяют условию. Вот any? для чего.

Поэтому вместо:

 ifelse one-of houses with [ [net-monthly-income] of myself > rent] != nobody
[ let potentialRentals houses with [[money] of myself > rent and onMarket = 1 ] 
  create-link-with one-of potentialRentals [ set color blue ]
]
[ die ]
  

вы можете иметь:

 ifelse any? houses with [ [net-monthly-income] of myself > rent]
[ let potentialRentals houses with [[money] of myself > rent and onMarket = 1 ] 
  create-link-with one-of potentialRentals [ set color blue ]
]
[ die ]
  

Я должен добавить, что здесь есть потенциальная логическая проблема. Скажем, есть дома с арендной платой ниже, чем доход, код переходит к первым (истинным) действиям. Но нет никакой гарантии, что есть какие-либо дома, которые удовлетворяют новым условиям, которые отличаются.

Кроме того, в NetLogo есть концепция true и false , поэтому вам не нужно использовать 1 и 0. По соглашению (но не обязательно) имена логических переменных заканчиваются вопросительным знаком. Таким образом, вы могли бы иметь set onMarket? true вместо set onMarket 1 . Зачем вам это делать? Это делает логические операторы более чистыми и удобными для чтения (что уменьшает количество ошибок). Ваша строка:

 let potentialRentals houses with [[money] of myself > rent and onMarket = 1 ]
  

будет выглядеть так:

 let potentialRentals houses with [[money] of myself > rent and onMarket? ]
  

И вы можете делать такие вещи, как if not onMarket? вместо if onMarket? = false или if onMarket = 0

Комментарии:

1. Спасибо за ответ. Я не был хорошо знаком с any? командой, поэтому ваши отзывы невероятно полезны. Я также привыкаю к синтаксису NetLogo (обычно я кодирую на R), поэтому ? полезно иметь в виду использование в качестве логического оператора.

2. Я не совсем уверен в логической проблеме, которую вы определили, и надеюсь, что вы сможете немного прояснить. Чего я пытаюсь достичь, так это логики: (1) домашнее хозяйство ищет дом, для которого оно может позволить себе первоначальный взнос из сбережений ( money>down-payment ) и net-monthly-income>mortgage-payment ; если ни один дом не удовлетворяет (1), то (2) домашнее хозяйство ищет аренду, где оно может позволить себе ежемесячную арендную плату; если ни один дом не удовлетворяет (2), затем (3) домашнее хозяйство умирает. Я понял, что неправильно net-monthly-income определил переменную по крайней мере в одном месте в OP; Я опубликую исправление. Еще раз спасибо за руководство.

3. Еще один комментарий: скорректированный код теперь выдает ошибку: CREATE-LINK-WITH expected input to be a turtle but got NOBODY instead. Это происходит в строке: create-link-with one-of potentialHomes [ set color red . Возможно, это связано с вашей выявленной логической проблемой? (Хотя я все еще не совсем уверен в проблеме.)

4. @Abe пожалуйста, не обновляйте свой пост последующими вопросами после предоставления ответа — это не так, как работает SO; если ответ разрешил первоначально сообщенную проблему, пожалуйста, примите его и откройте новый вопрос с новой проблемой (ссылка здесь, если необходимо).