Netlogo: эффективная итерация с использованием foreach

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

Минимальный пример кода модели будет выглядеть так:

globals [ N-x1 N-x2, N-x5 sum-A-x1 sum-A-x2 sum-A-x5 x-list ]

turtles-own [ condition1? A x ]

set x-list ( list 1 2 5 )

Учитывая, что в реальной модели x-list принимает 88 дискретных значений, я подумал, что использование цикла foreach будет подходящим способом справиться с этим. Обратите внимание, что количество черепах в реальной модели составляет около 75 тысяч, поэтому эффективность имеет значение.

Следуя комбинации предыдущих ответов (здесь и здесь), я придумал следующее решение:

  foreach x-list
  [ x ->
    
    ; Count turtles by x
    let temp1 (word "set N-x" x " count turtles with [ condition1? = true and x = " x "]" )
    run temp1
    
    ; Calculate sum of A by x
    let temp2 (word "set sum-A-x" x " sum [ A ] of turtles with [ condition1? = true and x = " x "]" ) 
   
   ; Capture errors due to empty list in calculating the sum
    carefully [ run temp2 ] 
    [ let temp3 (word "set sum-A-x" x " 0" )
      run temp3
    ]
  ]

Хотя это и работает, каждый прогон модели существенно замедлялся. Простое (но все же грубое) решение, которое, как я думал, поможет ускорить код, — это сначала определить набор агентов черепахи, на котором будут выполняться последующие команды (подсчет и суммирование). Поскольку я не смог найти способ использовать let внутри цикла foreach для этого, я решил вручную определить все вручную (для каждого из 88 значений x):

; Define needed agentsets
let turtles-x1 with [ condition1? = true and x = 1 ]
let turtles-x2 with [ condition1? = true and x = 2 ]
let turtles-x5 with [ condition1? = true and x = 5 ]

; Count turtles meeting condition1
set N-x1 count turtles-x1
set N-x2 count turtles-x2
set N-x5 count turtles-x5

; Sum A over turtles meeting condition1
if N-x1 > 0 [ set sum-A-x1 sum [ A ] of turtles-x1 ]
if N-x2 > 0 [ set sum-A-x2 sum [ A ] of turtles-x2 ]
if N-x5 > 0 [ set sum-A-x5 sum [ A ] of turtles-x5 ]

Казалось, это немного улучшило производительность. Может ли кто-нибудь придумать более эффективный (то есть более разумный) способ сделать то же самое? Например. используя map, о котором я не могу понять, или расширение table?

Обновлено: хотя ответы по-прежнему приветствуются, я нашел способ решить проблему, используя расширение table и map. Оставлю здесь, на случай, если кто-нибудь наткнется на подобный случай.

Я рад, что вы нашли решение, которое вам подходит! Оставить ответ на свой вопрос в SO можно, и это приветствуется. Вам также следует пометить его как принятый, чтобы любой, кто его найдет, знал, что это решило проблему.

Jasper 23.05.2024 16:26

Спасибо @Jasper, готово! (И приносим извинения за незнание правил/норм сообщества.. :-))

G. Papad. 24.05.2024 18:16
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Следуя ответам, найденным здесь и здесь, гораздо более эффективное решение:

globals [ x-keys x-N turtle-list turtle-A ]

; Store table of relevant turtles and their x's (to preserve order)
let temp-table table:group-agents turtles with [ condition1? = true ] [ x ] 

; Relevant turtles' Xs (in the order inserted)
set x-keys table:keys temp-table
  
; Counts of relevant turtles per x (in the order inserted)
set x-N map count table:values temp-table
  
; Relevant turtles in the order inserted (in an agentset list)
set turtle-list table:values temp-table

; Calculate sum of A per x
set turtle-A map [ y -> precision ( sum [ A ] of y ) 3 ] turtle-list

Это решает многие проблемы, такие как предварительное определение каждой переменной, выполнение нескольких if для проверки, заполнен ли x (т. е. N > 0) для запуска суммы, и сохранение ненужной информации (например, установка суммы случаев вручную с N = 0, до нуля). Это значительно повысило скорость и вдвое уменьшило размер генерируемого вывода (в эксперименте BehaviorSpace).

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