2013-08-11

Canvas Ant Colony Optimization

Intro

Another post in the "canvas drawing series". You can look up the basics of drawing etc. in the previous posts:

  1. Canvas Crossroad
  2. Canvas Balloons
  3. Canvas Bus
  4. Canvas Trains
  5. Canvas, circular motions and networks
  6. Canvas Wipers
  7. DIY Canvas Fountain
  8. Canvas Random Spherical Effects

Canvas Ant Colony Optimization

The inspiration for this animation came from a youtube video. In short, the ants explore various paths and leave pheromone trails. Over time the most efficient trails have the greatest amount of pheromones and the ants tend to follow that paths.

Graph creation

I've spent most of the development time for this example on the graph creation part. I wanted to create an algorithm that would turn an imaginary table into graph. Every joint has to have at least one exit point and no connections should cross over. Also, the connections are formed just between the neighbouring imaginary columns. In the development process I've found two variations of connection knitting. To keep the post as short as possible, I'll just show the upper knitting:

 var minPossible = 0;

 for (i = 0; i < jointsBefore.length; i++) {

  selection = randomInInterval(minPossible, possibleNodes.length - 1);

  if (selection > minPossible) {
   minPossible = selection;
  }

  jointsBefore[i].connections[0] = possibleNodes[selection];
  newConnectedNodes[selection] = true;

  selection = randomInInterval(minPossible, possibleNodes.length - 1);

  if (selection > minPossible) {
   minPossible = selection;
  }

  if (jointsBefore[i].connections[0].id !== selection) {
   jointsBefore[i].connections[1] = possibleNodes[selection];
   newConnectedNodes[selection] = true;
  }
 }

Ant path selection

Upon every node selection we're checking if the ant is exploring (going to path with lesser pheromones level) or taking the more visited path. And that's all:

 var selectedNode;

 if (joint.connections.length > 1) {

  if (Math.random() > globals.explorationProbability) {
   selectedNode = joint.selections[0] >= joint.selections[1] ? 0 : 1;
  } else {
   this.exploring = true;
   selectedNode = joint.selections[0] <= joint.selections[1] ? 0 : 1;
  }
  
 } else {
  selectedNode = 0;
 }

 this.destination = joint.connections[selectedNode];
 joint.selections[selectedNode]++;
 this.orientToPoint(this.destination);

And here's my example on:
Codepen

No comments: