#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. Это также хороший момент в изменении цвета, я изменю и это, хотя мой основной вывод-электронные таблицы данных