Создание социальной сети связанных агентов NetLogo разных пород

Я пытаюсь собрать что-то вроде "социальной сети" в NetLogo. Группа людей разных возрастных групп, которые связаны ссылками.

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

Ниже приведен соответствующий код с рассматриваемой функцией "create-network". Мне нужно попросить каждого агента (всего их будет около 800) подключиться к определенному количеству каждого типа другого агента (при условии, что этот другой агент не заполнен). Например, если черепаха принадлежит к породе, то у нее будет всего 10 звеньев, 5 из которых предназначены для других малышей, 2 - для детей, 2 - для взрослых и от 1 до 45 лет. Если первый узел - это малыш, и он соединяется со взрослым, мне нужно будет уменьшить количество малышей, к которым взрослый узел будет пытаться подключиться, когда я к нему тоже доберусь, если это имеет смысл.

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

Каждый раз, когда я что-то пробую, это приводит к ошибкам, и у меня нет идей и желания жить. Большое спасибо заранее за ваше время. Даже если у вас есть мысли по поводу лучшего алгоритма, но не кода, это было бы очень кстати

breed [toddlers toddler]
breed [children child]
breed [adults adult]
breed [over45s over45]

globals
[
  num-nodes
]

toddlers-own
[
  tod-total-connections
  tod-tods
  tod-children
  tod-adults
  tod-over45s
]

children-own
[
  child-total-connections
  child-tods
  child-children
  child-adults
  child-over45s
]

adults-own
[
  adult-total-connections
  adult-tods
  adult-children
  adult-adults
  adult-over45s
]

over45s-own
[
  over45-total-connections
  over45-tods
  over45-children
  over45-adults
  over45-over45s
]


to generate
  clear-all
  create-toddlers num-toddlers
  create-children num-children
  create-adults num-adults
  create-over45s num-over45
  create-network
  setup
  reset-ticks
end

to setup 
  ask turtles
    [reset-node]
  ask links
    [set color gray + 1.5]
  ask adults
    [set shape "circle"
      set size 4]
  ask toddlers
    [set shape "face happy"
      set size 4]
  ask over45s
    [set shape "triangle"
      set size 4]


  ;;INITIALISE BREEDS

  ;;Initialise Toddlers
  ask toddlers [set total-connections 10]
  ask toddlers [set tod-tods 5]
  ask toddlers [set tod-children 2]
  ask toddlers [set tod-adults 2]
  ask toddlers [set tod-over45s 1]

  ;;Initialise Children
  ask children [set total-connections 17]
  ask children [set child-tods 3]
  ask children [set child-children 8]
  ask children [set child-adults 5]
  ask children [set child-over45s 1]

  ;;Initialise Adults
  ask adults [set total-connections 13]
  ask adults [set adult-tods 1]
  ask adults [set adult-children 3]
  ask adults [set adult-adults 6]
  ask adults [set adult-over45s 3]

  ;;Initialise Over45s
  ask over45s [set total-connections 12]
  ask over45s [set over45-tods 1]
  ask over45s [set over45-children 1]
  ask over45s [set over45-adults 5]
  ask over45s [set over45-over45s 5]



  ;; Layout turtles:
  layout-circle (sort turtles) max-pxcor - 8
  ask turtles
  [
    facexy 0 0
    if who mod 2 = 0 [fd 4]
  ]
  display
end


;; THIS IS THE PROBLEM FUNCTION
to create-network
  let q 0
  let n 0
   while [q < count turtles]
  [
    let m 1
    while [m < count turtles]
        [
           make-link-between turtle n
                  turtle ((n + m) mod count turtles)
           set m m + 1 
;;results in a fully connected network which I don't want
         ]  
     set n n + 1
     set q q + 1
  ]

end


;; connects the two nodes
to make-link-between [node1 node2]
  ask node1 [
    create-link-with node2
      [ set color gray + 1.5]
  ]
end

Мне также интересно, было бы возможно иметь функцию, чтобы "приостановить" связи между агентами. Например, чтобы отключить несколько или все ссылки между детьми. Я знаю, что ссылки имеют атрибут tie-mode, но я не уверен, что это может сделать это. Из того, что я прочитал, похоже, больше связано с объединением движущихся агентов? Могу ли я использовать untie как способ отключения ссылки, но чтобы она все еще присутствовала?

Изменить: Скрыть ссылку может быть более подходящим. Как скрыть правильные ссылки это следующая вещь

1 ответ

Решение

Во-первых, давайте уберем это с пути:

Я не могу понять, как спросить нынешнюю черепаху, что это за порода

Черепахи имеют переменную породу.

Но я думаю, что в целом вы еще не смирились с NetLogo. Ваш код очень обязателен, используя циклы while и индексы. Вы должны избегать решения черепах их who цифры (хотя ваш собственный код макета может быть редким исключением из этого). NETLogo - это списки, наборы агентов и (когда это возможно) функциональные преобразования.

Во всяком случае, вот что я считаю лучшим подходом к вашей проблеме. Самое хитрое это как reverse-num-connexions вычисляется, но попытка выяснить, как это работает, должна стать отличным упражнением для обучения работе со списками.

Кроме того, обратите внимание, что возможно, что черепаха не заканчивается желаемым количеством соединений, потому что все ее цели превышены. Это будет зависеть от вашей численности населения.

breed [ toddlers toddler ]
breed [ children child ]
breed [ adults adult ]
breed [ over45s over45 ]

to setup
  clear-all
  create-toddlers 200
  create-children 200
  create-adults 200
  create-over45s 200
  create-network
  reset-ticks
end

to create-network

  let connexions (list
    (list toddlers toddlers 5)
    (list toddlers children 2)
    (list toddlers adults 2)
    (list toddlers over45s 1)
    (list children toddlers 3)
    (list children children 8)
    (list children adults 5)
    (list children over45s 1)
    (list adults toddlers 1)
    (list adults children 3)
    (list adults adults 6)
    (list adults over45s 3)
    (list over45s toddlers 1)
    (list over45s children 1)
    (list over45s adults 5)
    (list over45s over45s 5)
  )

  foreach connexions [
    let source-breed item 0 ?
    let target-breed item 1 ?
    let num-connexions item 2 ?
    let reverse-num-connexions item 2 first filter [
      item 0 ? = target-breed and item 1 ? = source-breed
    ] connexions
    ask source-breed [
      repeat num-connexions [
        let possible-targets other target-breed with [
          (not member? myself link-neighbors) and
          (count link-neighbors with [ breed = source-breed ] < reverse-num-connexions)
        ]
        let target one-of possible-targets
        if target != nobody [ create-link-with target ]
      ]
    ]
  ]

end

reverse-num-connexionsобъяснение (редактировать)

Допустим, мы проходим наш список номеров соединений, и мы получаем [toddlers adults 2], Это говорит о том, что каждый малыш должен иметь связь с 2 взрослыми. Но если мы посмотрим дальше по списку, то увидим, что взрослые должны быть подключены не более чем к 1 малышу: [adults toddlers 1], Это число (1) это то, что мы пытаемся извлечь для хранения как reverse-num-connexions,

Первое, что нужно сделать, это найти правильный список. Это будет та, где "исходная" и "целевая" породы обратны текущей. Выражение filter [ item 0 ? = target-breed and item 1 ? = source-breed ] connexions вернет список только с этим подсписком: [[adults toddlers 1]], Чтобы извлечь его, мы используем first, что дает нам только подсписок: [adults toddlers 1], Теперь мы хотим, чтобы последний элемент этого подсписка, который item 2, Это даст нам 1 что мы были после.

Другие вопросы по тегам