Netlogo вычисляет всех черепах того типа, которые касаются

#while-loop #netlogo

Вопрос:

В Netlogo у меня есть сетка, в которой все черепахи соприкасаются, и я хочу подсчитать количество зеленых черепах (MHC = 3 в коде ниже), которые образуют каждый кластер зеленых черепах (среди других цветов). Возможно, я все делаю неправильно, но это кажется очень, очень трудным.

Я пробовал циклы while, предназначенные для запуска с одной зеленой ячейки (не связанной с каким-либо предыдущим зеленым кластером) и присвоения номера ее собственной переменной block . Затем каждый зеленый сосед in-radius 1 получает один и тот же номер, и так далее, и так далее, пока каждая соприкасающаяся зеленая ячейка не получит один и тот же номер. Затем следующий кластер получит новый номер и начнет все сначала. Однако, если только это не просто вопрос плохого брекетинга, это действительно не работает. Вот функциональный код (который просто создает сетку черепах, меняющих цвет):

 turtles-own[MHC block]

globals[prWound]

to set-up
  clear-all
  reset-ticks
  ask patches [sprout 1 [set color magenta]]
  ask turtles [set MHC 2]
  set prWound 0.0001
end

to rules
  ask turtles with [MHC = 0][set color red]
  ask turtles with [MHC = 1][set color green]
  ask turtles with [MHC = 2][set color magenta]
  ask turtles with [MHC = 3][set color blue]
  ask turtles with [MHC = 4][set color orange]

ask turtles [if random 100 < 1 [set MHC (random 5)] ;vary MHC betwen 0-4,
    set block 0
    if random-float 1 < prWound [ask turtles in-radius 4 [die] die] 
    if any? patches in-radius 1 with [not any? turtles-here] and random 100 < 50 [if random 100 < 2.5 
[set MHC (random 5)] hatch 1 [move-to one-of patches in-radius 1 with [not any? turtles-here]
  ]
  tick
end

to go
  rules
end
 

Вот та часть, где я пытаюсь добавить block значения, которые я не могу получить на работе (добавлено непосредственно перед галочкой):

   ask turtles with [MHC = 1][
    if block = 0 [set block (max([block] of turtles)   1) ]
    while [any? [turtles with [MHC = 1 and block = 0] in-radius 1] of turtles with [block = [block] of myself]]
[if any? [turtles with [MHC = 1 and block = 0] in-radius 1] of turtles with [block = [block] of myself]
[set block ([block] of myself)]]
  ]
 

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

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

1. Обратите внимание, что в вашем примере есть проблема со скобками после следующего блока команд hatch 1 .

2. Кроме того, для будущих вопросов, пожалуйста, укажите, какое неожиданное поведение вы видите (т. Е. Вместо просто «это не работает») — это поможет вам получить помощь.

3. Правильно, сойдет. Я добавил сообщение об ошибке ниже для любых будущих читателей: ЕСТЬ? ожидаемый ввод должен быть набором агентов, но вместо этого получил список [(набор агентов, 0 черепах)].

Ответ №1:

Обновление: более простой подход

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

 to count-blocks
  set block-now 0
  
  ask turtles [set block 0]
  
  while [any? turtles with [condition]] [
   set block-now block-now   1
   
   ask one-of turtles with [condition] [
     join-and-search 
    ]
  ]
end


to join-and-search
  set block block-now
  
  if any? (turtles-on neighbors) with [condition] [
   ask (turtles-on neighbors) with [condition] [
      join-and-search
    ]
  ]
end


to-report condition
  ifelse (color = green and block = 0)
   [report TRUE]
   [report FALSE]
end
 

Обратите внимание, что, хотя while в этом случае используется только один раз, to join-and-search на самом деле создает цикл путем вызова самого себя, при этом рекурсивный вызов выполняется только if any? (turtles on neighbor) with [condition] один раз; что делает candidate? переход (т. Е. Стать кандидатом, набирать кандидатов, перестать быть кандидатом) здесь не требуется.

Я думаю, что в этом случае следует просто предупредить: я не знаю, является ли лучшей практикой позволить процедуре вызывать саму себя. С одной стороны, это звучит как нечто, заслуживающее внимания; с другой стороны, мне кажется, что это join-and-search не может быть более проблематичным, чем любая другая петля, построенная со странным условием.

Первоначальный ответ

Пытаясь решить эту проблему, я сам обнаружил кое-что , о чем я не задумывался in-radius , и, безусловно, в этом заключается часть проблемы.

Прежде чем раскрыть это, однако, позвольте мне сказать, что я не уверен, что это in-radius -все, что было не так с вашей попыткой: к тому времени, когда я узнал об этом, я уже использовал свой подход к проблеме.

В целом, однако, один совет: держите свой код как можно более аккуратным и читаемым (включая отступы) — становится намного проще определить, в чем заключается проблема.

Тем не менее, основные элементы моего подхода:

  • Два while цикла: первый проверяет, есть ли во всей симуляции подходящие черепахи, которые инициируют новую block ; второй (вложенный в первый) проверяет, остались ли какие-либо черепахи, которые должны быть выделены для текущей block оценки.
  • candidate? turtles-own Переменная, которая составляет условие для второго while цикла. При выделении в блок каждая черепаха также выполняет поиск своих соседей. Если есть какие-либо черепахи, которые следует добавить в текущий блок, то они попадают candidate? = TRUE , и внутренний цикл начинается снова.
  • Кроме того, я разделил относительно небольшое количество команд на множество процедур с соответствующими именами. Это делает код более читабельным, но также и более масштабируемым: когда вы собираетесь расширить переменные модели, наборы агентов, условия и т.д., Будет проще добавить строку кодов в выделенные разделы и проверить, работает ли конкретный раздел самостоятельно.
  • to-report condition и глобальная переменная block-now существует в основном для удобства чтения.
  • На данный момент этот код пересчитывает блоки каждый go раз (и количество блоков может меняться между одной итерацией go и другой). Несомненно, можно будет адаптировать подход к случаю, когда вы хотите сохранить номера блоков на разных go итерациях.
 globals [
  prWound
  block-now
]

turtles-own [
 MHC
 block
 candidate?
]


to setup
  clear-all
  reset-ticks
  ask patches [sprout 1 [set color magenta]]
  ask turtles [set MHC 2]
  set prWound 0.0001
end


to go
  rules
  count-blocks
  tick
end


to rules
  ask turtles with [MHC = 0][set color red]
  ask turtles with [MHC = 1][set color green]
  ask turtles with [MHC = 2][set color magenta]
  ask turtles with [MHC = 3][set color blue]
  ask turtles with [MHC = 4][set color orange]

ask turtles [
    if random 100 < 1 [set MHC (random 5)] 
    set block 0
    if random-float 1 < prWound [ask turtles in-radius 4 [die] die]
    if any? patches in-radius 1 with [not any? turtles-here] and random 100 < 50 [
     if random 100 < 2.5 [
       set MHC random 5
      ]
      hatch 1 [move-to one-of patches in-radius 1 with [not any? turtles-here]]
    ]
  ]
end


to count-blocks
  set block-now 0
  
  ask turtles [
   set block 0
  ]
  
  while [any? turtles with [condition]] [start-count-round]
  
end


to start-count-round
  
  set block-now (block-now   1)
  
  ask turtles [
   set candidate? FALSE
  ]
  
  ask one-of turtles with [condition] [set candidate? TRUE]
  
  while [any? turtles with [candidate?]] [
    ask turtles with [candidate?] [
     join
     search
     conclude 
    ]
  ]
end


to join
  set block block-now
end


to search
  let target (turtles-on neighbors) with [condition and not candidate?]
  ask target [set candidate? TRUE]
end


to conclude
  set candidate? FALSE
end


to-report condition
  ifelse (color = green and block = 0)
   [report TRUE]
   [report FALSE]
end
 

До

Нажмите, чтобы увидеть изображение

После

Нажмите, чтобы увидеть изображение

О чем in-radius ?

Хотя может показаться интуитивно понятным, что черепаха, которая ищет turtles in-radius 1 , найдет черепах, стоящих на любом из ближайших соседних участков, это не так: входное число для in-radius фактически является расстоянием, т. Е. не количеством участков, которые необходимо пересечь.

С точки зрения расстояния черепахи, стоящие на соседних по горизонтали или вертикали участках, будут находиться на расстоянии 1. Вместо этого черепахи, стоящие на соседних по диагонали участках, будут находиться на расстоянии 1,4:

 observer> clear-all
observer> ask patch 0 0 [sprout 1]
observer> ask patch 0 1 [sprout 1]
observer> ask patch 1 1 [sprout 1]
observer> ask turtle 0 [show distance turtle 1]
(turtle 0): 1
observer> ask turtle 0 [show distance turtle 2]
(turtle 0): 1.4142135623730951
 

Это причина, по которой даже мой подход не работал, пока я let target turtles in-radius 1 with [condition and not candidate?] не заменил let target (turtles-on neighbors) with [condition and not candidate?] его .

Обратите внимание, что вы используете in-radius дважды в первом фрагменте кода, которым вы поделились. В то время как в одном случае это справедливо patches in-radius 1 , и вы можете заменить neighbors этим , в другом случае это так turtles in-radius 4 . Вы, возможно, захотите рассмотреть влияние этого расстояния в последнем случае.

Заключительная записка по коду

Просто чтобы убедиться: вы уверены, что порядок вещей to rules -это то, чего вы хотите? Для того, как обстоят дела сейчас, черепахи меняют свою MHC ценность, но меняют цвет только в следующем раунде go (но к тому времени они снова изменятся MHC ).

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

1. Это также хороший момент в изменении цвета, я изменю и это, хотя мой основной вывод-электронные таблицы данных