===== Ant pheromones behavior ===== for information about this please have a look at [[The Swarm]] ==== Simulation of pheromone behavior ==== For our Mini-Project in class we tried to create an simulation of ants finding their way from the ant hill to the food and back. === Teaser === {{group1_group1project1teaser1.png|}} === Links === * [[http://iridia.ulb.ac.be/~mdorigo/ACO/RealAnts.html| Ants finding shortest path ]] * [[http://ai-depot.com/CollectiveIntelligence/Ant-Colony.html|Ants Colony and Multi-Agents]] * [[http://uk.arxiv.org/pdf/nlin.AO/0502057.pdf|Social Cognitive Maps, Swarm Perception and Distributed Search on Dynamic Landscapes]] * [[http://www.forgefx.com/casestudies/prenticehall/ph/ants/ants.htm|3D Simulation of Ants using pheromones]] * [[http://www.microsoft.com/germany/msdn/coding4fun/antme/default.mspx|AntMe!]] === Implementation === This is code written with the help of the [[http://processing.org|Processing]] Framework. Images and the font file are not included. (The latter can be created with processing.) //**Version as of 2007-Nov-01. Licensed under the [[http://sam.zoy.org/wtfpl/|WTFPL]]**// // ANTphetamine // A simulation of ants finding shortest paths by using pheromones // (C) 2007 Felix Faulmann, Daniel Rentzsch & Thomas Efer // Part of the lecture "Nature Inspired Computing" /////////////////////////////////// SETTINGS & GLOBAL VARS ////////////////////////////////////////////////////// // SETTINGS: /////////////////// int maxAntNum = 1000; // Maximum Ant number int antNum = 0; // count variable Ant[] ants; // Array where ant-Objects are stored int dimx = 800; // Window width int dimy = 600; // Window heigth int homex = 180; // Home location X int homey = 200; // Home location Y int homerad = 20; // Home radius int foodx = 630; // Food location X int foody = 330; // Food location Y int foodrad = 25; // Food radius float[][] searchmap; // Map where the "Searching for food"-pheromone is stored float[][] foundmap; // Map where the "Searching for home"-pheromone is stored PImage bgimg; // Background image PImage himg; // PImage fimg; boolean drawProgress=true; // Switch display of ants and pheromone trails int sweepc=0; // Counter that controls the removal of pheromones from the map int sweepsteps = 10; // Reduce the pheromone density each [n] simulation steps float redfact = .996; // Factor of pheromone reduction per simulaton step float redval = .04; // Additional absolute value of pheromone reduction per simulaton step int foodScore; // statistical counter int homeScore; // statistical counter float pinc=10; // pheromone drop ammount per ant int birthrate = 5; // influences the number of ants born in one simulation step (see coded formula below) float divAng = PI*6/21; // Angle difference (left & right) to check pheromone density (2 steps ahead) float gainAng = PI*6/17; // Angle to turn into best direction each step int dcprob = 85; // Probability (in %) that the direction is changed in a particular simulation step float randdiff = PI/18; // Random direction change bias maximum (into each direction) float threshold = 120; // Pheromone ammount maximum where direction changes (dizziness threshold) /////////////////////////////////// INITIAL SETUP //////////////////////////////////////////////////////// void setup () { size(dimx,dimy,P3D); // Set window size ants = new Ant[maxAntNum]; // Initialize ant array searchmap = new float[dimx+1][dimy+1]; // Initialize maps foundmap = new float[dimx+1][dimy+1]; // textFont(loadFont("LucidaSans-Italic-16.vlw")); // Load bitmap font bgimg = loadImage("bg.jpg"); // Load background image himg = loadImage("home.png"); // Load home image fimg = loadImage("burger.png"); // Load food image // create initially scattered ants for (int i= 0; i < maxAntNum/20; i++) ants[antNum++]=new Ant(true); } /////////////////////////////////// DRAW CYCLE (Also main simulation step) ///////////////////////////////////////////////// void draw() { // Buffering on loadPixels(); // Draw the Background background(bgimg); // Pheromone drawing and reduction sweepc=sweepc++%sweepsteps; for(int i=0; i0 || f>0) { if (drawProgress) pixels[i*width + j] = color(red(bgimg.pixels[i*width + j])+s*2,+green(bgimg.pixels[i*width + j]),blue(bgimg.pixels[i*width + j])+f*2); } // in sweep-simulation-steps, reduce the pheromone ammount if (sweepc == 0) { searchmap[j][i]*=redfact; foundmap[j][i]*=redfact; searchmap[j][i]-=redval; foundmap[j][i]-=redval; if (s<0) searchmap[j][i]=0; if (f<0) foundmap[j][i]=0; } } } // Draw home and food images where they belong image(himg, homex-homerad,homey-homerad); image(fimg, foodx-foodrad,foody-foodrad); // Move and draw the ants (call each ant's move method and (if needed) their paint method) for (int i = 0; i < antNum; i++) {ants[i].move(); if (drawProgress) ants[i].paint();}; // output statistics fill(0,0,0,180); text("Ant count: "+antNum+" | Food sightings: "+foodScore+" | Safe returns: "+homeScore, 15, 30); fill(255,255,255); text("Ant count: "+antNum+" | Food sightings: "+foodScore+" | Safe returns: "+homeScore, 14, 29); // Buffering off (bake image to screen) updatePixels(); // New ants to be born? if (antNum < maxAntNum) for(int i = 0; i< (maxAntNum-antNum) * birthrate / maxAntNum +1; i++) ants[antNum++]=new Ant(); } /////////////////////////////////// EVENT HANDLERS /////////////////////////////////////////////////////////// // On any key pressed switch display mode (full / counters only) void keyPressed() { drawProgress=!drawProgress; } // On mouse dragging paint fat pheromone trail (debug) void mouseDragged() { addFoundPher((int)mouseX,(int)mouseY,100); addSearchPher((int)mouseX,(int)mouseY,100); addFoundPher((int)mouseX+1,(int)mouseY+2,10.0); addSearchPher((int)mouseX-1,(int)mouseY-2,10.0); addFoundPher((int)mouseX-2,(int)mouseY+1,10.0); addSearchPher((int)mouseX+2,(int)mouseY-1,10.0); } /////////////////////////////////// HELPER FUNCTIONS /////////////////////////////////////////////////////////// void addSearchPher(int x, int y, float pher) { searchmap[(int)x][(int)y]+=pher; searchmap[(int)x][(int)y+1]+=pher/2; searchmap[(int)x][(int)y-1]+=pher/2; searchmap[(int)x+1][(int)y]+=pher/2; searchmap[(int)x-1][(int)y]+=pher/2; } void addFoundPher(int x, int y, float pher) { foundmap[(int)x][(int)y]+=pher; foundmap[(int)x][(int)y+1]+=pher/2; foundmap[(int)x][(int)y-1]+=pher/2; foundmap[(int)x+1][(int)y]+=pher/2; foundmap[(int)x-1][(int)y]+=pher/2; } /////////////////////////////////// ANT CLASS ///////////////////////////////////////////////////////////// // Represents a single Ant class Ant { // fields float x; float y; float dir; boolean foodsearch = true; // Constructor for birth placement near home Ant(){ x=homex+random(-homerad,homerad)*.7; y=homey+random(-homerad,homerad)*.7; dir=random(0,2*PI); } // Constructor for randomly scattered birth (debug) Ant(boolean randomizer){ x=random(4,dimx-4); y=random(4,dimy-4); dir=random(0,2*PI); } // void move() { // helper variables float xold = x; float yold = y; x=x+sin(dir); y=y+cos(dir); // Hit the border of the Universe? Try turning around somewhat randomly. if ((x < 2) || (y < 2) || (x >= dimx-1) || (y >= dimy-1)) {dir=(dir+3*PI)%(2*PI)+random(-PI/2,PI/2); x = xold; y = yold;}; // Move this time? if(random(0,100) straightVal && leftVal > rightVal) DIFF+=gainAng; if (rightVal > straightVal && rightVal > leftVal) DIFF-=gainAng; // Take into consideration that ants freak out (or just walk on stupidly) when there's too much pheromone in their way. if (straightVal > threshold) DIFF=0; //DIFF+=random(-2*PI,2*PI); // // Have some additional random divergence (useless? maybe!) DIFF += random(-randdiff/5,randdiff/5); // And finally set the new direction value dir=(dir+DIFF+2*PI)%(2*PI); } // Destiny reached? Turn around and do the oppsite thing! Increase the fitting counter by the way... if (foodsearch && sqrt((foodx-x)*(foodx-x)+(foody-y)*(foody-y)) < foodrad) {dir=(dir+3*PI)%(2*PI); foodsearch=false; foodScore++;} if (!foodsearch && sqrt((homex-x)*(homex-x)+(homey-y)*(homey-y)) < homerad) {dir=(dir+3*PI)%(2*PI); foodsearch=true; homeScore++;} // And don't forget to "deposit" pheromones if (foodsearch) addSearchPher((int)x,(int)y,pinc); else addFoundPher((int)x,(int)y,pinc); } // Draw each individual ant void paint() { stroke(0,0,0); //point(x,y); ellipse(x-1,y-1,2,2); stroke(255,255,255); point(x+sin(dir),y+cos(dir)); } }