Оптимизация колоний муравьев
1. Вступление
The aim of this series соответствуетexplain the idea of genetic algorithms and show the most known implementations.
В этом руководстве мы будем использоватьdescribe the concept of the ant colony optimization (ACO), а затем пример кода.
2. Как работает ACO
ACO - это генетический алгоритм, вдохновленный естественным поведением муравья. Чтобы полностью понять алгоритм ACO, нам необходимо ознакомиться с его основными понятиями:
-
муравьи используют феромоны, чтобы найти кратчайший путь между домом и источником пищи
-
феромоны быстро испаряются
-
муравьи предпочитают использовать более короткие пути с более плотным феромоном
Давайте покажем простой пример использования ACO вTraveling Salesman Problem. В следующем случае нам нужно найти кратчайший путь между всеми узлами графа:
Следуя естественному поведению, муравьи начнут исследовать новые пути во время исследования. Более сильный синий цвет указывает пути, которые используются чаще, чем другие, тогда как зеленый цвет указывает текущий кратчайший путь, который найден:
Приятный инструмент с графическим интерфейсом для тестирования ACO можно найтиhere.
3. Реализация Java
3.1. Параметры ACO
Обсудим основные параметры алгоритма ACO, объявленного в классеAntColonyOptimization:
private double c = 1.0;
private double alpha = 1;
private double beta = 5;
private double evaporation = 0.5;
private double Q = 500;
private double antFactor = 0.8;
private double randomFactor = 0.01;
Параметрc указывает исходное количество следов в начале моделирования. Кроме того,alpha контролирует важность феромона, аbeta контролирует приоритет расстояния. In general, the beta parameter should be greater than alpha for the best results.
Затем переменнаяevaporation показывает процент испарения феромона на каждой итерации, тогда какQ предоставляет информацию об общем количестве феромона, оставшегося на следе каждымAnt, аantFactor сообщает нам, сколько муравьев мы будем использовать в каждом городе.
Наконец, нам нужно иметь немного случайности в наших симуляциях, и это покрываетсяrandomFactor.
3.2. Создать муравьев
КаждыйAnt сможет посетить определенный город, запомнить все посещенные города и отслеживать длину маршрута:
public void visitCity(int currentIndex, int city) {
trail[currentIndex + 1] = city;
visited[city] = true;
}
public boolean visited(int i) {
return visited[i];
}
public double trailLength(double graph[][]) {
double length = graph[trail[trailSize - 1]][trail[0]];
for (int i = 0; i < trailSize - 1; i++) {
length += graph[trail[i]][trail[i + 1]];
}
return length;
}
3.3. Настроить муравьев
В самом начале нам нужноinitialize our ACO code implementation, предоставив матрицы следов и муравьев:
graph = generateRandomMatrix(noOfCities);
numberOfCities = graph.length;
numberOfAnts = (int) (numberOfCities * antFactor);
trails = new double[numberOfCities][numberOfCities];
probabilities = new double[numberOfCities];
ants = new Ant[numberOfAnts];
IntStream.range(0, numberOfAnts).forEach(i -> ants.add(new Ant(numberOfCities)));
Затем нам нужноsetup the ants matrix, чтобы начать со случайного города:
public void setupAnts() {
IntStream.range(0, numberOfAnts)
.forEach(i -> {
ants.forEach(ant -> {
ant.clear();
ant.visitCity(-1, random.nextInt(numberOfCities));
});
});
currentIndex = 0;
}
Для каждой итерации цикла мы будем выполнять следующие операции:
IntStream.range(0, maxIterations).forEach(i -> {
moveAnts();
updateTrails();
updateBest();
});
3.4. Переместить муравьев
Начнем с методаmoveAnts(). Нам нужноchoose the next city for all ants, помнить, что каждый муравей пытается идти по следам других муравьев:
public void moveAnts() {
IntStream.range(currentIndex, numberOfCities - 1).forEach(i -> {
ants.forEach(ant -> {
ant.visitCity(currentIndex, selectNextCity(ant));
});
currentIndex++;
});
}
The most important part is to properly select next city to visit. Мы должны выбрать следующий город, основываясь на логике вероятности. Во-первых, мы можем проверить, должен лиAnt посетить случайный город:
int t = random.nextInt(numberOfCities - currentIndex);
if (random.nextDouble() < randomFactor) {
OptionalInt cityIndex = IntStream.range(0, numberOfCities)
.filter(i -> i == t && !ant.visited(i))
.findFirst();
if (cityIndex.isPresent()) {
return cityIndex.getAsInt();
}
}
Если мы не выбрали какой-либо случайный город, нам нужно рассчитать вероятность выбора следующего города, помня, что муравьи предпочитают идти более сильными и короткими тропами. Мы можем сделать это, сохранив вероятность перехода к каждому городу в массиве:
public void calculateProbabilities(Ant ant) {
int i = ant.trail[currentIndex];
double pheromone = 0.0;
for (int l = 0; l < numberOfCities; l++) {
if (!ant.visited(l)){
pheromone
+= Math.pow(trails[i][l], alpha) * Math.pow(1.0 / graph[i][l], beta);
}
}
for (int j = 0; j < numberOfCities; j++) {
if (ant.visited(j)) {
probabilities[j] = 0.0;
} else {
double numerator
= Math.pow(trails[i][j], alpha) * Math.pow(1.0 / graph[i][j], beta);
probabilities[j] = numerator / pheromone;
}
}
}
После того, как мы вычислим вероятности, мы можем решить, в какой город идти, используя:
double r = random.nextDouble();
double total = 0;
for (int i = 0; i < numberOfCities; i++) {
total += probabilities[i];
if (total >= r) {
return i;
}
}
3.5. Обновить маршруты
На этом шаге мы должны обновить следы и левый феромон:
public void updateTrails() {
for (int i = 0; i < numberOfCities; i++) {
for (int j = 0; j < numberOfCities; j++) {
trails[i][j] *= evaporation;
}
}
for (Ant a : ants) {
double contribution = Q / a.trailLength(graph);
for (int i = 0; i < numberOfCities - 1; i++) {
trails[a.trail[i]][a.trail[i + 1]] += contribution;
}
trails[a.trail[numberOfCities - 1]][a.trail[0]] += contribution;
}
}
3.6. Обновите лучшее решение
Это последний шаг каждой итерации. Нам нужно обновить лучшее решение, чтобы сохранить ссылку на него:
private void updateBest() {
if (bestTourOrder == null) {
bestTourOrder = ants[0].trail;
bestTourLength = ants[0].trailLength(graph);
}
for (Ant a : ants) {
if (a.trailLength(graph) < bestTourLength) {
bestTourLength = a.trailLength(graph);
bestTourOrder = a.trail.clone();
}
}
}
После всех итераций окончательный результат укажет лучший путь, найденный ACO. Please note that by increasing the number of cities, the probability of finding the shortest path decreases.с
4. Заключение
Это руководствоintroduces the Ant Colony Optimization algorithm. Вы можете узнать о генетических алгоритмахwithout any previous knowledge этой области, имея лишь базовые навыки компьютерного программирования.
Полный исходный код для фрагментов кода в этом руководстве доступенin the GitHub project.
Для всех статей в серии, включая другие примеры генетических алгоритмов, проверьте следующие ссылки:
-
Оптимизация колоний муравьев (это)