
Многие сложные системы удается исследовать только моделированием. Для систем, состоящих из большого количества независимых объектов, такие как поведение толпы, развитие многоклеточных организмов или военные операции, наиболее адекватным оказывается агентное моделирование. Есть много предназначенных для этого систем, например российская проприетарная AnyLogic.
Я же хочу рассказать об языке NetLogo, хорошо зарекомендовавшим себя в образовании, но годный и для взрослых задач.
Синтаксис
Синтаксис Logo минималистичен — разделенная пробелами последовательность имен и констант с редкой группировкой с помощью [] или (). [] служат для создания списков и группировки команд в блок в большинстве конструкций, () — обычные скобки для подвыражений. Имена ссылаются на встроенные или определенные программистом сущности — функции, переменные
Команды (процедуры) объявляются
to имя [список имен аргументов] тело end
Функции в NetLogo называются «репортеры» и объявляются немного по другому:
to-reporter имя [список имен аргументов] тело report возвращаемая величина end
Про каждую процедуру или функцию компилятор знает «арность» («валентность») и не требует лишний раз использовать группировку. Правда с функциями высших порядков может ошибаться — тогда ему нужна подсказка в виде круглых скобок.
Пусть у нас определены функции:
to-report inc [x] report x + 1 end to-report add [x y] report x + y end
Тогда можно написать
и получить заслуженную девятку.add add inc 1 inc 2 inc 3
Правильно работает так же
который возвращает список [2 3 4]. А для add уже придется написать скобкиmap inc [1 2 3]
(map add [1 2 3] [4 5 6])
Агенты
Агенты бывают трех видов — черепашки (turtle — как же без них), связи (link) и пятна (patch — они же места в пространстве). Для черепашек и связей можно задать определяемую пользователем породу (breed). Агенты одного типа объединены в набор соответствующий (agentset) — turtles, links и pathes. Представители одной породы так же объединены в набор. Новая порода создается командой
где ninja — название породы, а ninjas — название набора, объединяющего всех агентов этой породы.breed [ninjas ninja]
Есть так же особый агент — наблюдатель.
Черепашки создаются командой create-turtles (с аргументом — количество создаваемых черепах), и далее находятся по индексу функцией turtle. Агент — «first class value», при желании его можно сохранить в переменной, но требуется это редко.
Агент или набор агентов могут быть контекстом для команды. Выполнение команд в контексте агентов — основной механизм работы с ними.
Этот код попросит всех черепашек сделать шаг вперед.ask turtles [fd 1]
А этот покрасит поле с координатами (17,13) в нежно розовый цвет.ask patch 17 13 [set pcolor pink]
Породу можно установить динамически
ask turtle 1 [set bread ninjas] ask ninja 1 [set pcolor black]
Переменные
В исходном Logo была реализована динамическая область видимости, что создает неудобства и противоречит современным тенденциями в области языков программирования. Разработчики NetLogo поступили сурово — запретили создание одноименных переменных, область видимости которых могут пересечься. Разработчикам библиотек это удобства не прибавляет, но в обучении школьников скорее полезно. Да и социологам и военспецам в разработке моделей позволит делать меньше ошибок :-).
Область видимости статическая, что упрощает использование функций высших порядков.
Переменные могут быть глобальные, собственные для типа агентов или породы, формальными аргументами и локальные в блоке кода. Одно и то же имя переменной не может ссылаться на разные классы переменных, но локальные переменные в разных блоках, в том числе и в одной функции, могут называться одинаково. Имя локальной переменной не может совпадать с именем аргумента функции, где она определена или с именем глобальной или агентной переменной.
Глобальные переменные описываются
собственныеglobal [имя1 имя2 ...]
Локальные переменные создаются командойturtles-own [имя3 имя4 ...] ninjas-own [имя5 имя6 ...]
let имя7 начальное_значение
Функции высших порядков
Некоторые стандартные функции, такие как map, в качестве одного из аргументов получают другую функцию. Им можно просто указать имя передаваемой функции или написать замыкание. Замыкание представляет из себя код, заключенные в []. То, что это замыкание, а не список, компилятор угадывает по контексту. В качестве формальных параметров используются переменные '?', '?1', '?2' и тд.
Использование своих функций высших порядков сложнее. Присвоить переменной или передать другой функции функцию-значение можно с помощью специальной функции task, а вызвать функцию из переменной — с помощью runresult (или run для команд).
to test1 [f] show (runresult f 1) show (map f [2 3 4]) end test1 (task [? + 2])
Лично я такой подход с разделением функций и переменных, ссылающихся на функции, считаю не удачным, но он реализован, например, в Common Lisp, и имеет своих сторонников.
Интерфейс и графика

В программе присутствуют три вкладки (таба): «интерфейс», документация, и редактор кода. В табе «интерфейс» присутствуют поле графических объектов (в том числе и изображение мира), поле текстового вывода и REPL. В REPL можно переключать режимы, задающие в каком контексте выполняются водимые команды — «наблюдатель», «черепахи», «пятна» и «связи». REPL ограниченный — описывать переменные, породы, процедуры и функции в нем нельзя (они создаются вне контекста), придется переходить в редактор кода.
В зоне, где нарисовано поле с миром, можно «мышкой» (нажав правую кнопку на свободном месте) создавать другие графические объекты и элементы интерфейса. При создании им надо задать имена, по которым к ним можно обращаться из программы. Способа порождать графические объекты программно я не нашел. В файле эти объекты сохраняются в текстовом виде после кода, но в малопригодной для ручного редактирования форме.
Например, если мы создадим «график» с именем «plot1», то команда
нарисует график распределения черепах по красному, зеленому и синему цветам (предполагая, что другие не встречаются).set-current-plot "Class Histogram" histogram map [position ? [red green blue]] ([color] of turtles)
Библиотека моделей
К NetLogo прилагается обширная библиотека моделей, от учебных и развлекательных, до исследовательских. Некоторые модели умеют общаться со специализированным железом, таким как GoGo board.
Доступ к модели к модели осуществляется через меню File. Как правило, в интерфейсе моделей есть кнопки Setup и Go и для запуска их надо нажать в этом порядке. Setup инициализирует модель, после чего ее настройки можно изменить через интерфейс.
