Перебор патчей с общими свойствами в Netlogo

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

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

globals [
  AT-data
  ABC
  area
  ]

patches-own [
  ID
  AT1
  AT2
  seed
  sum_AT1
]

to setup
  ;; here I just create patches with different values that also appear in the list
  ca
  set ABC [ "A" "B" "C" "D" "E" "F" "G" "H" "I" ]
  ask patches [ set seed random 10 set ID one-of ABC
    ifelse (seed = 4)
    [ set pcolor orange] [set pcolor white]
  ]
end

to load
  reset-timer
  ; first, we load the database file
  ; We check to make sure the file exists first
  ifelse ( file-exists? "AT_data.txt" )
  [
    ; We are saving the data into a list, so it only needs to be loaded once.
    set AT-data []
    file-open "AT_data.txt"
    while [ not file-at-end? ]
    [
      ; file-read gives variables stored in a double list
      ; Each iteration we append the next three-tuple to the current list: ID AT1 AT2
      set AT-data sentence AT-data (list (list file-read file-read file-read))
    ]
    user-message "File loading complete!"
    file-close
   
    assign-data
    stop
    ]
  [ user-message "There is no AT_data.txt file in current directory!" ]

  file-close-all

  print timer
end


to assign-data
  reset-timer
  ask patches with [seed = 4] [
    let i 1
    while [i < length AT-data] [
      let current-inner-list item i AT-data
      ifelse (ID = item 0 current-inner-list)
        [ set AT1 item 1 current-inner-list set AT2 item 2 current-inner-list
          stop]
        [ set i i + 1 ]
      ]
      ]
  print timer
end


to simulation
  reset-timer
  ask patches [
    let i 1
    while [i < length AT-data] [
      let current-inner-list item i AT-data
      ifelse (ID = item 0 current-inner-list)
     
     ;; I tried with and without this following line
      ;[ask patches with [ID = item 0 current-inner-list] [
      [ set area  area + AT1
        print area
        print ID
        stop
        ]
      ;]
      
    ;; this one is an alternative
       ;[ print sum [AT1] of patches with [ID = item 0 current-inner-list]
       ;print ID
       ;]
      [ set i i + 1 ]
      ]
  ]

  print timer
end

AT_data.txt это

   "A"      65      81
   "B"      21      71
   "C"      54      18
   "D"      23      41
   "E"      85      27
   "F"      35      88
   "G"      29       4
   "H"      78       2
   "I"      99      60

Спасибо за ваше время !

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
31
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Мое первое замечание: у вас есть патчи, которые снова просят патчи в simulation.

Ваше второе решение было проще для работы. Главное здесь было вырвать его из контекста патча и позволить наблюдателю запустить его. Для вывода на печать я предлагаю использовать такой формат, как print (word current-ID ": " current-sum). Это намного чище, когда вы хотите быстро проверить это после запуска модели.

to simulation-2
  reset-timer
  
  let i 0
  while [i < length AT-data] [
    let current-inner-list item i AT-data
    let current-ID item 0 current-inner-list
    let current-sum sum [AT1] of patches with [ID = current-ID]
    print (word current-ID ": " current-sum)
    
    set i i + 1 
  ]
  
  print timer
end

Для вашего первого решения ваша проблема заключалась в том, что у вас была только одна переменная области, которую вы увеличили. В следующем примере я превратил область в список той же длины, что и AT-данные, содержащий списки. Каждый внутренний список состоит из идентификатора и счетчика, установленного на 0 [["A" 0] ["B" 0] ... ["I" 0]]. Для этого я использую процедуру map. map берет каждый отдельный элемент списка, выполняет с ним определенную операцию и возвращает их все как новый список. В общем, это очень полезная процедура для изучения, когда вы будете работать со списками.

Затем я перебираю все исправления, как вы, и увеличиваю счетчик моего списка областей для правильного идентификатора. У меня есть две разные версии этого увеличения. Первый имеет множество локальных переменных, чтобы наглядно показать, как он работает. Вы выкапываете правильный подсписок, затем выкапываете правильную переменную, увеличиваете эту переменную, заменяете ее в подсписке и заменяете подсписок в основном списке. Второй делает то же самое, но в одной строке кода.

to simulation-1
  reset-timer
  
  set area map [inner-list -> list item 0 inner-list 0] AT-data ;creates a new list of lists of the form [["A" 0] ["B" 0] ... ].
  
  ask patches [
    let i 0
    while [i < length AT-data] [
      let current-inner-list item i AT-data
      ifelse (ID = item 0 current-inner-list)
      [ let inner-area-list item i area    ;grab the correct innerlist
        let increased-count item 1 inner-area-list + AT1    ;increment the second part of this inner list
        set inner-area-list replace-item 1 inner-area-list increased-count    ;put the incremented count back into the inner list
        set area replace-item i area inner-area-list    ;put the inner list back into the complete list
        
        ;; all these can be combined into a single line of code but that is more prone to errors
        ;set area replace-item i area (replace-item 1 item i area (item 1 item i area + AT1))
        
        stop
      ]
      [ set i i + 1 ]
    ]
  ]
  print area
  
  print timer
end

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

Когда вы говорите, что у меня есть патчи, запрашивающие патчи снова, вы имеете в виду эту строку кода: [ask patches with [ID = item 0 current-inner-list] [ первого решения? Я действительно понял это, и поэтому я попробовал и без него... Большое спасибо LeirsW за решение с командой sum и подсказку об использовании команды word!

Sarahdata 13.05.2022 09:40

На самом деле я рассматриваю второй вариант, потому что мне нужно работать с несколькими свойствами патчей, принадлежащих одному и тому же идентификатору (суммируя одно свойство, выполняя некоторые математические операции с другим свойством с данными, поступающими из файла, а затем суммируя их). Поэтому я считаю, что лучше всего хранить эти результаты в списках. Однако я проверил команду map, но не смог создать новый список с более чем одним новым элементом, например ["A" 0 0] [ "B" 0 0 ] ... Если мне нравится set area map [inner-list -> list item 0 inner-list 0 inner-list 0] AT-data, возникает ошибка

Sarahdata 13.05.2022 10:38

или если я попробую, как set area1 map [inner-list -> list item 0 inner-list 0 ] AT-data set area2 map [inner-list -> list item 0 item 1 inner-list 0 ] area1 , это не сработает. Спасибо за понимание, я все еще в процессе обучения.

Sarahdata 13.05.2022 10:39

@Sarahdata Рад помочь вам. Ошибка, вероятно, возникает из-за того, что list по умолчанию ожидает ровно 2 входа. Вы можете изменить количество входных данных, используя скобки. В отличие от многих других языков программирования, сам list также должен быть включен в эти скобки. set area1 map [inner-list -> (list item 0 inner-list 0 0) ] AT-data генерирует формат [["A" 0 0] [ "B" 0 0 ] ... ].

LeirsW 13.05.2022 13:18

Спасибо ! Я пробовал команду, которую вы написали, но без скобок... Я не понял из словаря (список значение1 значение2 (список значение1...)) что по умолчанию было 2 значения и может быть больше с скобкой. Теперь я буду понимать словарь совсем по-другому/эффективнее!! :D

Sarahdata 13.05.2022 13:49

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