Соціальне моделювання · Архітектура
📅 Липень 2026 ⏱ ≈ 11 хв читання 🎯 Середній рівень

Agent-Based Modelling: архітектура та дизайн

Кожна симуляція евакуації натовпу, ринкової бульбашки чи сегрегації на цьому сайті побудована з одного й того ж скелету: популяція незалежних агентів, цикл perceive-decide-act і планувальник, що зв'язує все разом. Ця стаття розбирає цей скелет, щоб ви могли спроєктувати власну агент-орієнтовану модель (ABM) з нуля.

Коротко: Агент-орієнтована модель складається з трьох частин, які повторюються в будь-якій симуляції: стан кожного агента, цикл perceive-decide-act, що робить оновлення незалежними від порядку обробки, і просторовий індекс (сітка чи quadtree), який тримає пошук сусідів швидким навіть при тисячах агентів. Стаття показує, як ці частини поєднуються — разом зі скелетом на JavaScript з випадковим плануванням — щоб з простих локальних правил виникали такі патерни, як сегрегація чи затори при евакуації.

Що таке агент-орієнтоване моделювання?

Агент-орієнтована модель замінює одне глобальне рівняння популяцією автономних агентів, кожен з яких дотримується простих локальних правил і реагує лише на своє найближче оточення. Замість того, щоб розв'язувати "яка середня поведінка системи", ви симулюєте кожного індивіда й дозволяєте сукупному патерну виникнути знизу вгору. Це протилежний підхід до моделі диференціальних рівнянь на кшталт SIR чи Лотки-Вольтерри, які описують популяції як неперервні величини.

ABM — природний інструмент, коли важлива гетерогенність, локальна взаємодія чи дискретні рішення: пішоходи обирають вихід, домогосподарства обирають район, трейдери вирішують купувати чи продавати. Симуляції евакуації натовпу, сегрегації Шеллінга та Дилеми в'язня на цьому сайті — всі це ABM, побудовані на архітектурі, описаній нижче.

Стан агента та поведінка

Кожному агенту потрібен компактний стан — мінімум даних, необхідних для прийняття рішення про наступну дію — і функція поведінки, що перетворює стан плюс локальні спостереження на новий стан. Мінімальний стан важливий для продуктивності: з 10 000+ агентів, що оновлюються щокадру, кожне зайве поле — це 10 000 зайвих байтів, що проходять через кеш процесора щоразу.

Категорія полівПрикладиМутується щотік?
Кінематикапозиція, швидкість, напрямоктак
Внутрішній станціль, настрій, багатство, думкатак
Ідентичність/типвид, стратегія, групарідко
Похідні (кешовані)список сусідів, локальна щільністьтак, перераховується

Часта помилка — переплітати логіку поведінки з кодом рендерингу. Тримайте агентів як прості дані (Structure-of-Arrays або легкий клас) і трактуйте малювання як окремий прохід, що лише читає стан — це робить модель тривіально переносимою між Canvas 2D, WebGL і headless-запусками пакетів для перебору параметрів.

Цикл perceive-decide-act

Майже кожна агент-орієнтована модель, незалежно від домену, розбиває своє оновлення за тік на три фази:

1. PERCEIVE (сприйняти) — зібрати локальну інформацію (сусіди, клітини оточення, ціни)
2. DECIDE (вирішити) — застосувати правило поведінки й отримати намічену дію
3. ACT (діяти) — застосувати дію й оновити стан (рух, обмін, зміна стратегії)

Розділення decide і act — не стилістичний вибір, а те, що робить симуляцію незалежною від порядку обробки. Якщо агент A діє одразу після рішення, агент B (наступний у тій самій ітерації) сприйматиме нову позицію A замість тієї, яку A мав на початку тіку. Це непомітно змінює динаміку і робить результати залежними від порядку ітерації, що рідко буває бажаним.

Правило: спочатку обчисліть усі рішення в буфер, потім застосуйте всі дії другим проходом. Цей патерн "подвійної буферизації" коштує одного зайвого масиву на поле, але гарантує детерміновані, незалежні від порядку оновлення — критично важливо для відтворюваних експериментів та для паралелізації фази decide через web workers.

Просторове індексування: сітки, quadtree, spatial hashing

Фаза perceive зазвичай потребує "хто поруч зі мною", і наївне сканування всіх пар O(N²) стає вузьким місцем уже за кілька тисяч агентів. Три структури покривають майже всі випадки використання ABM:

СтруктураНайкраща дляВартість запиту
Рівномірна сіткаприблизно рівномірна щільність, фіксований радіус взаємодіїO(1) сер.
Просторова хеш-мапанеобмежений світ, розріджені агентиO(1) сер.
Quadtree / k-d treeдуже нерівномірна щільність (міста, кластери)O(log N)

Для евакуації натовпу чи ринкової симуляції Больцмана-Парето рівномірна сітка з розміром клітини приблизно рівним радіусу взаємодії майже завжди є правильним першим вибором: перебудуйте її кожен тік за O(N), тоді кожен запит сусідів сканує лише блок 3×3 (9 клітин) навколо агента замість усієї популяції.

class SpatialGrid {
  constructor(cellSize) {
    this.cellSize = cellSize;
    this.cells = new Map();  // ключ: "cx,cy" -> масив індексів агентів
  }
  key(x, y) {
    const cx = Math.floor(x / this.cellSize);
    const cy = Math.floor(y / this.cellSize);
    return cx + ',' + cy;
  }
  rebuild(agents) {
    this.cells.clear();
    for (let i = 0; i < agents.length; i++) {
      const k = this.key(agents[i].x, agents[i].y);
      if (!this.cells.has(k)) this.cells.set(k, []);
      this.cells.get(k).push(i);
    }
  }
  neighbours(x, y, agents) {
    const cx = Math.floor(x / this.cellSize);
    const cy = Math.floor(y / this.cellSize);
    const out = [];
    for (let dx = -1; dx <= 1; dx++)
      for (let dy = -1; dy <= 1; dy++) {
        const bucket = this.cells.get((cx+dx) + ',' + (cy+dy));
        if (bucket) out.push(...bucket);
      }
    return out;
  }
}

Порядок планування: синхронний vs асинхронний

Окрім розділення decide/act, потрібно обрати хто оновлюється й коли:

Часта помилка: перемішувати порядок агентів лише один раз при ініціалізації замість кожного тіку. Це непомітно повертає упередженість порядку — агент 37 у перемішаному масиві все одно завжди оновлюється одразу після агента 12, тік за тіком.

Звідки береться емерджентність

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

  1. Локальна взаємодія: агенти реагують лише на найближчих агентів/клітини, ніколи на глобальне середнє.
  2. Нелінійність або пороги: маленька зміна локальної змінної (ще один несхожий сусід, ще один панічний пішохід) може повністю змінити рішення агента.
  3. Зворотний зв'язок: дія агента змінює локальне оточення, яке сусіди сприймають наступного тіку, що змінює їхні дії, які знову змінюють оточення.

Саме тому модель сегрегації Томаса Шеллінга така вражаюча: жоден агент у моделі не має сильної переваги до повної сегрегації — достатньо порогу "лише 30% схожих сусідів" — але емерджентний патерн на рівні цілого міста наближається до повного розділення. Урок узагальнюється: щоб зрозуміти складний соціальний патерн, шукайте просте локальне правило і петлю зворотного зв'язку, що його підсилює, а не одну "причину" на рівні системи.

Мінімальний скелет ABM на JavaScript

Зібравши все з попередніх розділів, ось форма, якої дотримується кожна ABM на цьому сайті — просторовий індекс, розділення decide/act і рандомізоване планування:

class Simulation {
  constructor(n, worldSize) {
    this.agents = Array.from({ length: n }, () => ({
      x: Math.random() * worldSize,
      y: Math.random() * worldSize,
      vx: 0, vy: 0,
      state: 'idle',
    }));
    this.grid = new SpatialGrid(10);
  }

  step(dt) {
    this.grid.rebuild(this.agents);
    const order = this.agents.map((_, i) => i);
    shuffle(order); // випадкове асинхронне планування

    // 1) DECIDE — обчислити наміри, не мутуючи стан
    const intents = new Array(this.agents.length);
    for (const i of order) {
      const a = this.agents[i];
      const nearby = this.grid.neighbours(a.x, a.y, this.agents);
      intents[i] = decide(a, nearby, this.agents);
    }
    // 2) ACT — застосувати всі наміри
    for (const i of order) {
      act(this.agents[i], intents[i], dt);
    }
  }
}

Усе інше — Social Force Model для евакуації, оновлення стратегій за матрицею виграшів для Дилеми в'язня чи поріг схожості Шеллінга — підключається до decide() і act(). Каркас навколо (сітка, планування, подвійна буферизація) лишається тим самим у радикально різних доменах.

👥 Запустити ABM евакуації натовпу

Social Force Model, просторова сітка, сотні агентів шукають вихід у реальному часі

Відкрити симуляцію →