项目作者: aptem336

项目描述 :
Implementation of the ACO (Ants Colony Optimization) for the traveling salesman problem. JOGL used
高级语言: Java
项目地址: git://github.com/aptem336/ACO.git
创建时间: 2017-12-07T10:14:27Z
项目社区:https://github.com/aptem336/ACO

开源协议:

下载


AI Course Assignment

Ants

Assignment repository for AI course at Inha University

Problem choice: metaheuristic algorithm “Ant colony optimization”

Demo

Demo

Technologies used

  • Java
  • OpenGL

How to run

Clone repository:

  1. $ git clone git://github.com/xtenzQ/Uni-AI.git

To run the application, you need:

After NetBeans installation, you should install JOGL plugin:

  • Go menubar Tools
    • Menu Plugin
      • Tab Downloaded
        • Button Add Plugins...
          • Choose all plugins in the folder except GLSL editor.

TODO

  • Algorithm
  • Settings menu

Problem

In the ant colony optimization algorithms, an artificial ant is a simple computational agent that searches for good solutions to a given optimization problem. To apply an ant colony algorithm, the optimization problem needs to be converted into the problem of finding the shortest path on a weighted graph. In the first step of each iteration, each ant stochastically constructs a solution, i.e. the order in which the edges in the graph should be followed. In the second step, the paths found by the different ants are compared. The last step consists of updating the pheromone levels on each edge. —Wikipedia

Pseudocode:

  1. procedure ACO_MetaHeuristic
  2. while(not_termination)
  3. generateSolutions()
  4. daemonActions()
  5. pheromoneUpdate()
  6. end while
  7. end procedure

Each ant needs to construct a solution to move through the graph. To select the next edge in its tour, an ant will consider the length of each edge available from its current position, as well as the corresponding pheromone level.

Probability equation

  • - pheromone level on i,j edge;
  • - parameter which controls influence on
  • - attractiveness of i,j edge ( where d is distance);
  • - parameter which controls influence on

The process of updating pheromones is slightly different from the one which is commonly used. I decided to update pheromone level on all the roads by multiplying the current level with evaporation coefficient and the update of pheronome on the egdes depends on its length. The longer the way, the less pheromone is added to the graph edge.

Solution

Algorithm

  1. Initialize transition matrix by calculating the length of the edges of the graph (hypotenuse) (update() function, Data.java file):
  1. private static void update() {
  2. isData = true;
  3. transitionsMatrix = new double[cities.size()][cities.size()];
  4. colorMatrix = new int[cities.size()][cities.size()];
  5. for (int i = 0; i < cities.size(); i++) {
  6. for (int j = i + 1; j < cities.size(); j++) {
  7. double[] first = cities.get(i);
  8. double[] second = cities.get(j);
  9. // fill edge matrix with its length
  10. transitionsMatrix[i][j] = transitionsMatrix[j][i] = (Math.hypot(second[0] - first[0], second[1] - first[1]));
  11. colorMatrix[i][j] = Data.defaultColor;
  12. }
  13. //
  14. transitionsMatrix[i][i] = 0;
  15. colorMatrix[i][i] = Data.defaultColor;
  16. }
  17. Algorithm.newMatrix(transitionsMatrix);
  18. }

In newMatrix() method transitionMatrix is assigned to waysLength which represents the road length between cities.

  1. Initiate ants traveling (iterate() function, Algorithm.java file)
  1. ants.forEach((ant) -> {
  2. ant.newTravel();
  3. });

by assigning ants to random cities

  1. /**
  2. * Send ant to new city
  3. */
  4. public final void newTravel() {
  5. chainLength = 0;
  6. for (int i = 0; i < numOfCities; i++) {
  7. visited[i] = false;
  8. }
  9. // init ant in a random city
  10. currentCity = citiesChain[0] = random.nextInt(numOfCities);
  11. visited[currentCity] = true;
  12. }
  1. Select next city for ant to travel to (iterate() function, Algorithm.java file)
  1. for (currentTransition = 1; currentTransition <= numOfCities; currentTransition++) {
  2. ants.forEach((ant) -> {
  3. ant.selectCity();
  4. });
  5. }

2.1. There’s a possibility for an ant to travel to a random city (selectCity() function, Algorithm.java file)

  1. // Possibility of a transition to a random city
  2. int randCity = random.nextInt(numOfCities);
  3. //
  4. if (random.nextDouble() < randomFactor) {
  5. //
  6. if (!visited[randCity]) {
  7. visit(randCity);
  8. return;
  9. }
  10. }

2.2. Otherwise ant is going to city based on probabilities (selectCity() function, Algorithm.java file)

  1. // Calculate transition probabilities
  2. double[] transitionProbabilities = calcProbabilities();
  3. // Transition to city
  4. double rand = random.nextDouble();
  5. double total = 0;
  6. for (int i = 0; i < numOfCities; i++) {
  7. total += transitionProbabilities[i];
  8. if (total >= rand) {
  9. visit(i);
  10. return;
  11. }
  12. }

calcProbabilities() function:

  1. /**
  2. * Calculate probability of ant travel
  3. *
  4. * @return
  5. */
  6. private double[] calcProbabilities() {
  7. double[] transitionProbabilities = new double[numOfCities];
  8. // if it's last city
  9. if (currentTransition == numOfCities) {
  10. for (int i = 0; i < numOfCities; i++) {
  11. // we stop
  12. transitionProbabilities[i] = 0;
  13. }
  14. // get back to start city
  15. transitionProbabilities[citiesChain[0]] = 1;
  16. return transitionProbabilities;
  17. }
  18. // calculate according to formula
  19. double sumProbalities = 0.0;
  20. for (int i = 0; i < numOfCities; i++) {
  21. if (visited[i]) {
  22. transitionProbabilities[i] = 0;
  23. } else {
  24. //
  25. transitionProbabilities[i] = Math.pow(getWaysPheromone()[currentCity][i], alpha) * Math.pow(1.0 / waysLength[currentCity][i], beta);
  26. }
  27. sumProbalities += transitionProbabilities[i];
  28. }
  29. for (int i = 0; i < numOfCities; i++) {
  30. transitionProbabilities[i] /= sumProbalities;
  31. }
  32. return transitionProbabilities;
  33. }
  1. Update pheromones on edges (iterate() function, Algorithm.java file)
  1. updatePheromone();

3.1. Evaporate pheromone from every edge by multiplying evaporation coefficient with existing pheromone level on the edge (updatePheromone() function, Algorithm.java file)

  1. // evaporate pheromone
  2. for (int i = 0; i < numOfCities; i++) {
  3. for (int j = 0; j < numOfCities; j++) {
  4. getWaysPheromone()[i][j] *= evaporation;
  5. }
  6. }

3.2. Add pheromone to every edge ant went through. The longer the way, the less pheromone is added to the graph edge (updatePheromone() function, Algorithm.java file)

  1. ants.forEach((ant) -> {
  2. // pheromoneReserve - pheromone amount for each ant
  3. // the longer the path the less we add
  4. double pheromoneInc = pheromoneReserve / ant.getChainLength();
  5. for (int i = 0; i < numOfCities; i++) {
  6. // we add popularity to every edge ant went through
  7. getWaysPopularity()[ant.citiesChain[i]][ant.citiesChain[(i + 1) % numOfCities]]++;
  8. // we add pheromone to every edge ant went through
  9. getWaysPheromone()[ant.citiesChain[i]][ant.citiesChain[(i + 1) % numOfCities]] += pheromoneInc;
  10. }
  11. });
  1. Update best solution (Algorithm.java file)
  1. private static void updateBest() {
  2. //
  3. if (bestChain == null) {
  4. bestChainLength = ants.get(0).getChainLength();
  5. bestChain = ants.get(0).getCitiesChain();
  6. }
  7. // we search for the shortest way and the chain of the city it produced
  8. ants.forEach((ant) -> {
  9. if (ant.getChainLength() < bestChainLength) {
  10. bestChainLength = ant.getChainLength();
  11. bestChain = ant.getCitiesChain().clone();
  12. }
  13. });
  14. }