Biology · Algorithms
📅 March 2026 ⏱ ≈ 12 min read 🎯 Intermediate

ACO: Ant Colony Optimisation — from stigmergy to the Travelling Salesman

Ants have no central commander — yet they still find short paths. The secret is pheromones: chemical trail-following that self-organises the colony. Discover how to turn this natural process into a powerful optimisation algorithm.

1. Stigmergy and collective intelligence

У 1959 році ентомолог П'єр-Поль Грасс ввів термін стигмергія — координація через середовище. Мурахи не передають команди напряму: кожна лишає феромоновий слід, і наступна мурашка реагує на накопичені сліди всієї колонії. Так виникає «розподілена пам'ять» без центрального сервера.

Класичний дослід: між харчуванням і гніздом ставлять перешкоду з двома обходами — коротким і довгим. Спочатку мурахи розходяться рівномірно. Але ті, хто зайшов коротким шляхом, повертаються швидше й кладуть більше феромону. Решта починає надавати перевагу короткому маршруту — позитивний зворотній зв'язок підсилює фаворита до тих пір, поки практично весь трафік іде по оптимальному шляху.

Key property of ACO: алгоритм не шукає глобальний оптимум безпосередньо — він накопичує досвід популяції агентів. Це дозволяє знаходити хороші розв'язки у комбінаторних просторах, де перебір неможливий.

2. Formalisation: graph and the Travelling Salesman problem

Найкласичніша задача для ACO — Задача Комівояжера (TSP): знайти найкоротший гамільтонів цикл у повному графі з n міст. Кількість можливих маршрутів — (n−1)!/2: для 20 міст це ~6×10¹⁶. Перебір неможливий.

Модель графа:

d[i][j] = √((xᵢ − xⱼ)² + (yᵢ − yⱼ)²)
η[i][j] = 1 / d[i][j] ← visibility (heuristic)
τ[i][j] = τ₀ ← initial pheromone (uniform)

Один цикл алгоритму складається з трьох фаз: побудова рішень мурахами → оцінка якості (довжина маршруту) → оновлення феромонів.

3. Pheromone trail: updating τ

Після того як усі m мурах побудували свої маршрути, феромони оновлюються двома кроками:

Step 1 — evaporation

τ[i][j] ← (1 − ρ) · τ[i][j]
ρ ∈ (0,1] — evaporation rate

Евапорація запобігає нескінченному накопиченню феромону та дозволяє алгоритму «забувати» старі погані рішення. Типово ρ = 0.1.

Step 2 — deposition

τ[i][j] ← τ[i][j] + Σₖ Δτₖ[i][j]

Δτₖ[i][j] = Q / Lₖ якщо мурашка k пройшла ребро (i,j)
Δτₖ[i][j] = 0 інакше
Q — constant (e.g. 100), Lₖ — route length of ant k

Мурашки, що знайшли короткий маршрут (малий Lₖ), відкладають більше феромону на свої ребра — ці ребра стають привабливішими для наступного покоління.

Elite ACO variant: ще раз додати Δτ для найкращого знайденого маршруту (з більшим коефіцієнтом e·Q/L*), незалежно від поточної ітерації.

4. Probabilistic edge selection

Коли мурашка знаходиться у місті i і обирає наступне місто j, вона використовує правило пропорційного вибору (Ant System, Dorigo 1992):

p[i][j] = (τ[i][j]ᵅ · η[i][j]ᵝ) / Σₗ∈allowed (τ[i][l]ᵅ · η[i][l]ᵝ)

α ≥ 0 — вага феромону
β ≥ 0 — вага видимості (heuristic weight)
allowed = set of cities not yet visited

Типові значення: α = 1, β = 5. При α = 0 — чиста жадібність за відстанню; при β = 0 — довільний пошук, керований лише феромоном.

Parameter Small Large Recommended
α (pheromone) less past influence greedy trail-following 1
β (distance) less greediness almost Nearest-Neighbor 2–5
ρ (evaporation) slow forgetting unstable, memoryless 0.05–0.2
m (ants) weak parallelism slow convergence n/2 … n

Щоб обрати місто за ймовірністним вектором, використовують метод рулетки: генерують U(0,1), зсуваються по накопиченій сумі до першого j, де сума ≥ U.

5. Evaporation and saturation

Без евапорації феромони накопичуються нескінченно: перший знайдений маршрут залучає всіх мурах, алгоритм застряє у локальному оптимумі. Евапорація з параметром ρ вирішує це:

Баланс між exploration (дослідженням) та exploitation (використанням): мале ρ → довга пам'ять, більша ρ → швидке адаптування, але нестабільність.

Common mistake: занадто мала кількість мурах (m < 5) при великому ρ. Феромонні сліди зникають швидше, ніж встигають оновитися, — алгоритм деградує до випадкового пошуку.

6. Min-Max ACO

Класичний Ant System має тенденцію до стагнації: через кілька сотень ітерацій усі мурахи йдуть одним маршрутом, дослідження зупиняється. MAX-MIN Ant System (Stützle & Hoos, 2000) вирішує проблему явними обмеженнями:

τ_min ≤ τ[i][j] ≤ τ_max

τ_max ≈ 1 / (ρ · L*) ← where L* is the best known length
τ_min ≈ τ_max / (2 · n) ← empirical formula

Додаткове правило: лише найкраща мурашка (за ітерацію чи глобально) відкладає феромон. Це зменшує шум від поганих рішень.

Min-Max advantage

7. JavaScript implementation

Реалізація ACO для TSP: n міст, m мурах, iterations ітерацій. Масиви tau (феромони) та eta (видимість) зберігаються як плоскі Float64Array.

function acoTSP(cities, { m = 20, alpha = 1, beta = 5,
                              rho = 0.1, Q = 100, iterations = 200 } = {}) {
  const n = cities.length;
  const idx = (i, j) => i * n + j;

  // Distances and visibility
  const dist = new Float64Array(n * n);
  const eta  = new Float64Array(n * n);
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      if (i === j) continue;
      const dx = cities[i].x - cities[j].x;
      const dy = cities[i].y - cities[j].y;
      dist[idx(i,j)] = Math.sqrt(dx*dx + dy*dy);
      eta[idx(i,j)]  = 1 / dist[idx(i,j)];
    }
  }

  // Pheromone initialisation
  const tau0 = 1 / n;
  const tau  = new Float64Array(n * n).fill(tau0);

  let bestTour = null, bestLen = Infinity;

  for (let iter = 0; iter < iterations; iter++) {
    const allTours = [];

    // Each ant builds a route
    for (let k = 0; k < m; k++) {
      const visited = new Uint8Array(n);
      const tour = [Math.floor(Math.random() * n)];
      visited[tour[0]] = 1;

      while (tour.length < n) {
        const cur = tour[tour.length - 1];
        const probs = [];
        let   sum   = 0;

        for (let j = 0; j < n; j++) {
          if (visited[j]) { probs.push(0); continue; }
          const v = Math.pow(tau[idx(cur,j)], alpha)
                  * Math.pow(eta[idx(cur,j)], beta);
          probs.push(v); sum += v;
        }

        // Roulette wheel
        let r = Math.random() * sum, acc = 0, next = -1;
        for (let j = 0; j < n; j++) {
          if (visited[j]) continue;
          acc += probs[j];
          if (acc >= r) { next = j; break; }
        }
        if (next === -1) next = probs.findIndex((v,j)=>!visited[j]);
        tour.push(next); visited[next] = 1;
      }

      // Route length
      let len = 0;
      for (let i = 0; i < n; i++)
        len += dist[idx(tour[i], tour[(i+1) % n])];
      allTours.push({ tour, len });
      if (len < bestLen) { bestLen = len; bestTour = [...tour]; }
    }

    // Evaporation
    for (let i = 0; i < tau.length; i++) tau[i] *= (1 - rho);

    // Pheromone deposition
    for (const { tour, len } of allTours) {
      const deposit = Q / len;
      for (let i = 0; i < n; i++) {
        const a = tour[i], b = tour[(i+1) % n];
        tau[idx(a,b)] += deposit;
        tau[idx(b,a)] += deposit; // symmetric graph
      }
    }
  }

  return { tour: bestTour, length: bestLen };
}

Для 50 міст на 200 ітерацій з m = 25 мурахами функція знаходить маршрут протягом <100 мс. При збільшенні n > 200 доцільно обмежити список кандидатів (nearest neighbor list) розміром 20–30.

8. ACO applications

Task Description Result
TSP Optimal city tour ≤5% from optimum for 200+ cities
VRP Vehicle Routing: freight delivery Practical application in logistics
Job Shop Job scheduling on processor clusters Competitive with genetic algorithms
Routing Network packet routing AntNet — adaptive router
Graph coloring Graph colouring with minimum colours Competitive on sparse graphs

АКО особливо корисний там, де динамічне середовище: якщо граф змінюється (ребра з'являються або зникають), мурашиний алгоритм може адаптуватися в реальному часі — феромони «пам'ятають» актуальний стан.

9. Extensions and variants

▶ Live Demo

🐜 Ant simulation

Watch an ant colony self-organise its pheromone trails in real time.

Open simulation →

🔗 Related Simulations

🗺️Pathfinding 📍TSP 🧬Genetic Algo 🐦Boids