Skip to content

Latest commit

 

History

History
455 lines (336 loc) · 20.5 KB

README_ru.md

File metadata and controls

455 lines (336 loc) · 20.5 KB

Ant colony optimization (Муравьиный алгоритм)

English version

Содержание


Введение

Муравьиный алгоритм (ACO) позволяет решать вычислительные задачи способом нахождения хороших путей на графе.

Решаемая задача может быть как "Задачей коммивояжера", так и "О кратчайшем пути", или путем с некими ограничениями (Constrained Shortest Path First).
Первые две задачи решены в данной библиотеке.

Существует множество стратегий и вариаций классического ACO алгоритма.
Библиотека предоставляет реализацию Классического ACO и вариант с использованием Элитных муравьев.

Библиотека гибко расширяется и позволяет вам создать свои алгоритмы из мира ACO, и решать свои задачи.

Исходные данные поступают и в виде матрицы смежности и в виде списка нод (городов, узлов, вершин) с X и Y координатами.

Работа библиотеки протестирована на наборах данных TSPLIB95, для проверки эффективности и производительности.

Кол-во муравьев, все коэффициенты и параматры, настраиваются.

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


Демо

Решение задачи коммивояжера с помощью ACO: Решение задачи коммивояжера с помощью ACO из данной библиотеки

Второй пример: Решение задачи коммивояжера с помощью ACO на карте США


Установка

Установка через composer:

Выполните

composer require --prefer-dist mgrechanik/ant-colony-optimization

или добавьте

"mgrechanik/ant-colony-optimization" : "~1.0.0"

в require секцию вашего composer.json файла.


Использование

Базовое API

  1. Создание Менеджера с нужными зависимостями
Manager::__construct(DistanceInterface $distanceStrategy = null, AFinder $finder = null, 
                     MathematicsInterface $mathematics = null, Task $task = null);

      - По умолчанию Поисковик будет устанавливаться в Классический ACO, а решаемая Задача - в Задачу Коммивояжера

  1. Загрузка данных в виде матрицы смежности
$manager->setMatrix(array $matrix, int $nameStart = 0)

      - $nameStart - с какого номера именовать алиас имени ноды, для их внешнего имени-алиаса

  1. Загрузка данных в виде списка городов
$manager->setCities(City ...$cities)

      - Данный список городов будет преобразован в матрицу смежности, расстояния вычислены по указанной Менеджеру стратегии.       - Если у города задано свойство name - оно станет его алиасом имени

  1. Изменение матрицы смежности
$manager->updateMatrix(int $y, int $x, float|int $value, bool $double = true)

      - Например, можем сделать некий участок непроходимым - $manager->updateMatrix(1, 0, 1000000);

  1. Запуск вычислительного процесса
$distance = $manager->run(int $iterations = 400)

      - для небольших графов, число итераций можно уменьшить.
      - Вернет найденное расстояние или null если поиск не увенчался успехом

  1. Получение найденного пути
$path = $manager->getInnerPath()

      - Найденный путь из номеров нод.
      Все ноды внутри именуются числами от 0 до N-1, где N - кол-во нод.

  1. Получение найденного пути из алиасов
$path = $manager->getNamedPath()

      - Найденный путь из алиасов имен нод, если вы их задавили.

Примеры

Решаем Задачу Коммивояжера классическим ACO

use mgrechanik\aco\Manager;

$manager = new Manager();
$matrix = [
            [ 0, 8, 4, 11],
            [ 8, 0, 9, 5 ],
            [ 4, 9, 0, 8 ],
            [11, 5, 8, 0 ]
          ];
$manager->setMatrix($matrix);
$distance = $manager->run(20);
var_dump('Distance=' . $distance);
var_dump($manager->getInnerPath())

Получим:

Distance=25

Array
(
    [0] => 0
    [1] => 1
    [2] => 3
    [3] => 2
    [4] => 0
) 

Решаем задачу "О кратчайшем пути", классическим ACO

use mgrechanik\aco\Manager;
use mgrechanik\aco\SppTask;

$task = new SppTask(0, 3);
$manager = new Manager(task : $task);
$matrix = [
            [ 0 , 8, 4, 100],
            [ 8 , 0, 9, 5  ],
            [ 4 , 9, 0, 8  ],
            [100, 5, 8, 0  ]
          ];
$manager->setMatrix($matrix);   
$finder = $manager->getFinder();
// increase amount of ants to 6
$finder->setM(6);
$distance = $manager->run(50);
var_dump('Distance=' . $distance);
var_dump($manager->getInnerPath())

Получим:

Distance=12

Array
(
    [0] => 0
    [1] => 2
    [2] => 3
)
// for comparison, the direct path [0, 3] is closed by big distance and distance of path [0, 1, 3] is 13

Загрузка данных в виде списка городов

use mgrechanik\aco\Manager;
use mgrechanik\aco\City;

$cities = [new City(10,10), new City(50,50), new City(10,50), new City(60,10)];
$manager = new Manager();
$manager->setCities(...$cities);

Загрузка данных в виде матрицы смежности

use mgrechanik\aco\Manager;

$matrix = [
            [ 0, 8, 4, 11],
            [ 8, 0, 9, 5 ],
            [ 4, 9, 0, 8 ] ,
            [11, 5, 8, 0 ]
          ];
$manager = new Manager();
$manager->setMatrix($matrix);

Используем поисковик c элитными муравьями

$finder = new \mgrechanik\aco\elitist\Finder();
$manager = new Manager(finder : $finder);
//...

Смотрим историю работы, состоит из лучших путей, которые мы находили

use mgrechanik\aco\Manager;

$matrix = [
            [ 0, 8, 4, 11],
            [ 8, 0, 9, 5 ],
            [ 4, 9, 0, 8 ] ,
            [11, 5, 8, 0 ]
          ];
$manager = new Manager();
$finder = $manager->getFinder();
$manager->setMatrix($matrix);
$manager->run();
var_dump($finder->getHistory());

Грузим список городов из картинки

При использовании данной библиотеки мы можем загрузить список городов из картинки, и результат поиска отобразить на результирующей картинке. Визуально будут картинки как на Demo.

Подробнее по подготовке картинки изучайте в описании к той библиотеке, но вкратце - на белом холсте отметьте кружочками диаметром 10 px, вершины графа, и используйте в коде ниже эту картинку.

use mgrechanik\aco\Manager;
use mgrechanik\aco\City;

try {
    $imageSearcher = new \mgrechanik\imagepointssearcher\Searcher(
        './images/your_image.jpg',
    );
    $found = $imageSearcher->run();    
    if ($found > 1) {
        $points = $imageSearcher->getPoints();
        $cities = [];
        foreach ($points as $point) {
            $cities[] = new City($point['x'], $point['y']);
        }    
        $manager = new Manager();
        $manager->setCities(...$cities);
        if ($res = $manager->run()) {
            $innerPath = $manager->getInnerPath();
            $imageResult = new \mgrechanik\imagepointssearcher\ImageResult($imageSearcher);
            $imageResult->drawLabels();
            $imageResult->drawMargins();
            $imageResult->drawPath($innerPath);
            $imageResult->save('./images/result.jpg');
        }
    }
  
} catch (Exception $e) {
    //
}

Настройка

Настройка Поисковика

Основной настраиваемый обьект - Это поисковик.
Получаем его:

$manager = new Manager();
$finder = $manager->getFinder();
// Настраиваем
//$finder->set...
// ...
//$manager->run();

Доступные настройки:

  • Установим величину расстояния, при которой участок между двумя узлами считается непроходимым
    ->setClosedPathValue(int $value)

  • Установим число муравьев
    ->setM(int $m)

  • Установим число муравьев как процент от числа нод. Используется по умолчанию (=40%)
    ->setMPercent(int $mPercent)

  • Устанавливаем коэффициенты для формулы

->setAlpha(float $alpha);
->setBeta(float $beta);
->setP(float $p);
->setC(float $c);
->setQ(int $q);
  • Установить стратегию выполнения математических задач
    ->setMathematics(MathematicsInterface $mathematics)

  • Установить текущую выполняемую задачу. TSP, SPP или др.
    ->setTask(Task $task)

  • Установим число элитных муравьев (для поисковика с элитными муравьями)
    ->setSigma(int $sigma)

  • Установим число элитных муравьев как процент от числа регулярных муравьев. Используется по умолчанию (=50%) (для поисковика с элитными муравьями)
    ->setSigmaPercent(int $sPercent)


Производительность

Прежде всего отключите XDebug или аналоги, т.к. они могут на порядок влиять на скорость работы

Данный ACO алгоритм находит хорошие пути на графе. И даже лучшие.

Для примера возьмем задачу berlin52.tsp из библиотеки TSPLIB95, где 52 узла у графа.
Решаем задачу кодом ниже:

$cities = TspLibLoader::loadCitiesFromEuc2dFile(__DIR__ . '/images/data/berlin52.tsp');
$finder = new \mgrechanik\aco\elitist\Finder();
$finder->setSigmaPercent(150);
$finder->setMPercent(30);
$finder->setAlpha(0.7);
$manager = new Manager(finder : $finder);
$manager->setCities(...$cities);
$distance = $manager->run(300);
var_dump('Distance=' . $distance);
var_dump($finder->getHistory());

Получили вывод:

Distance=7542

   Array ... 
    [85] => Array
        (
            [distance] => 7542
            [inner_path] => 0_21_30_17_2_16_20_41_6_1_29_22_19_49_28_15_45_43_33_34_35_38_39_36_37_47_23_4_14_5_3_24_11_27_26_25_46_12_13_51_10_50_32_42_9_8_7_40_18_44_31_48_0
            [iteration] => 85
            [time_spent] => 1.94 sec
        )  
    )

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

Здесь мы использовали поисковик на основе алгоритма с использования элитных муравьев. Он на практике дает лучшие результаты, чем классический.

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


TSPLIB95

Библиотека TSPLIB95, содержит множество Задач коммивояжера - исходные данные и решения - лучшие рузультаты, которые были когда либо найдены для этих задач (пути и расстояния).

Библиотека ценна тем, что на ее данных можно протестировать эффективность наших алгоритмов, коэффициентов и параметров.

Библиотека предоставляет множество разных форматов исходных данных. Мы из коробки поддерживаем два из них.

Подключение данных в виде списка X и Y координат. Расстояние Эвклидовое.

Пример файла с этим форматом - berlin52.tsp . Загружаем из него список нод (городов) и передаем менеджеру:

use mgrechanik\aco\TspLibLoader;
use mgrechanik\aco\Manager;

$fileName = __DIR__ . '/berlin52.tsp';
$cities = TspLibLoader::loadCitiesFromEuc2dFile($fileName);
$manager = new Manager();
$manager->setCities(...$cities);

Подключение данных в виде матрицы смежности

Пример файла с этим форматом - bays29.tsp .

Загружаем из него матрицу смежности и передаем менеджеру:

use mgrechanik\aco\TspLibLoader;
use mgrechanik\aco\Manager;

$fileName = __DIR__ . '/bays29.tsp';
$matrix = TspLibLoader::loadMatrixFromExplicitMatrixFile($fileName);
$manager = new Manager();
// tsplib95 library names nodes starting with "1"
$manager->setMatrix($matrix, 1);

Терминология

ACO - Муравьиный алгоритм (Ant colony optimization algorithm)

Nodes - Ноды, или узлы, или вершины графа. Или города. Муравьи путешествуют между ними

Adjacency Matrix - Матрица смежности, задает расстояния между узлами графа. Это базовая структура, с которой начинает работать алгоритм.

Если граф представлен как Города с координатами, то эта информация сначала переводится в матрицу смежности

Classic Finder - Поисковик, реализующий Классическую разновидность ACO алгоритма

Elitist Finder - Поисковик, реализующий алгоритм ACO с использованием элитных муравьев

Ant - муравей, рабочий юнит, который двигается по графу и ищет пути

Task - Задача, решаемая на графе. Например это может быть "Задача коммивояжера". Или задача "О кратчайшем пути". Или другая.

TSP - Задача коммивояжера. С данной библиотекой мы можем решать обе разновидности tsp - симметричную и асимметричную

Manager - Менеджер, задача которого, сформировать Матрицу смежности, и передать Поисковику выполнение выбранной Задачи.

Iteration - Итерация, во время которой, все муравьи находят по одному пути и оставляют феромоны. Количество итераций задаем сами

Pheromon - Феромон, то вещество, которое муравьи оставляют на найденных путях

m - Количество муравьев

mPercent - Количество муравьев в процентах относительно кол-ва узлов графа

sigma - Количество элитных муравьев, если используем соответствующий алгоритм

sigmaPercent - Количество элитных муравьев в процентах относительно кол-ва регулярных муравьев

alpha - коэффициент влияния обьема феромонов на выбор пути

beta - коэффициент влияния привлекательности пути

p - коэффициент испарения феромонов после каждой итерации

c - стартовое кол-во феромонов на всех путях

Q - Константа, участвующая в вычислении, сколько феромонов муравей оставляет на найденном пути