/* Copyright 2009 by Sean Luke and George Mason University Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package sim.app.antsforage; import sim.engine.*; import sim.field.grid.*; import sim.util.*; public /*strictfp*/ class AntsForage extends SimState { private static final long serialVersionUID = 1; public static final int GRID_HEIGHT = 100; public static final int GRID_WIDTH = 100; public static final int HOME_XMIN = 75; public static final int HOME_XMAX = 75; public static final int HOME_YMIN = 75; public static final int HOME_YMAX = 75; public static final int FOOD_XMIN = 25; public static final int FOOD_XMAX = 25; public static final int FOOD_YMIN = 25; public static final int FOOD_YMAX = 25; public static final int NO_OBSTACLES = 0; public static final int ONE_OBSTACLE = 1; public static final int TWO_OBSTACLES = 2; public static final int ONE_LONG_OBSTACLE = 3; public static final int OBSTACLES = TWO_OBSTACLES; public static final int ALGORITHM_VALUE_ITERATION = 1; public static final int ALGORITHM_TEMPORAL_DIFERENCE = 2; public static final int ALGORITHM = ALGORITHM_VALUE_ITERATION; public static final double IMPOSSIBLY_BAD_PHEROMONE = -1; public static final double LIKELY_MAX_PHEROMONE = 3; public static final int HOME = 1; public static final int FOOD = 2; public int numAnts = 1000; public double evaporationConstant = 0.999; public double reward = 1.0; public double updateCutDown = 0.9; public double diagonalCutDown = computeDiagonalCutDown(); public double computeDiagonalCutDown() { return Math.pow(updateCutDown, Math.sqrt(2)); } public double momentumProbability = 0.8; public double randomActionProbability = 0.1; // some properties public int getNumAnts() { return numAnts; } public void setNumAnts(int val) {if (val > 0) numAnts = val; } public double getEvaporationConstant() { return evaporationConstant; } public void setEvaporationConstant(double val) {if (val >= 0 && val <= 1.0) evaporationConstant = val; } public double getReward() { return reward; } public void setReward(double val) {if (val >= 0) reward = val; } public double getCutDown() { return updateCutDown; } public void setCutDown(double val) {if (val >= 0 && val <= 1.0) updateCutDown = val; diagonalCutDown = computeDiagonalCutDown(); } public Object domCutDown() { return new Interval(0.0, 1.0); } public double getMomentumProbability() { return momentumProbability; } public void setMomentumProbability(double val) {if (val >= 0 && val <= 1.0) momentumProbability = val; } public Object domMomentumProbability() { return new Interval(0.0, 1.0); } public double getRandomActionProbability() { return randomActionProbability; } public void setRandomActionProbability(double val) {if (val >= 0 && val <= 1.0) randomActionProbability = val; } public Object domRandomActionProbability() { return new Interval(0.0, 1.0); } public IntGrid2D sites = new IntGrid2D(GRID_WIDTH, GRID_HEIGHT,0); public DoubleGrid2D toFoodGrid = new DoubleGrid2D(GRID_WIDTH, GRID_HEIGHT,0); public DoubleGrid2D toHomeGrid = new DoubleGrid2D(GRID_WIDTH, GRID_HEIGHT,0); public SparseGrid2D buggrid = new SparseGrid2D(GRID_WIDTH, GRID_HEIGHT); public IntGrid2D obstacles = new IntGrid2D(GRID_WIDTH, GRID_HEIGHT,0); public AntsForage(long seed) { super(seed); } public void start() { super.start(); // clear out the schedule // make new grids sites = new IntGrid2D(GRID_WIDTH, GRID_HEIGHT,0); toFoodGrid = new DoubleGrid2D(GRID_WIDTH, GRID_HEIGHT,0); toHomeGrid = new DoubleGrid2D(GRID_WIDTH, GRID_HEIGHT,0); //valgrid2 = new DoubleGrid2D(GRID_WIDTH, GRID_HEIGHT, 0); buggrid = new SparseGrid2D(GRID_WIDTH, GRID_HEIGHT); obstacles = new IntGrid2D(GRID_WIDTH, GRID_HEIGHT, 0); switch( OBSTACLES ) { case NO_OBSTACLES: break; case ONE_OBSTACLE: for( int x = 0 ; x < GRID_WIDTH ; x++ ) for( int y = 0 ; y < GRID_HEIGHT ; y++ ) { obstacles.field[x][y] = 0; if( ((x-55)*0.707+(y-35)*0.707)*((x-55)*0.707+(y-35)*0.707)/36+ ((x-55)*0.707-(y-35)*0.707)*((x-55)*0.707-(y-35)*0.707)/1024 <= 1 ) obstacles.field[x][y] = 1; } break; case TWO_OBSTACLES: for( int x = 0 ; x < GRID_WIDTH ; x++ ) for( int y = 0 ; y < GRID_HEIGHT ; y++ ) { obstacles.field[x][y] = 0; if( ((x-45)*0.707+(y-25)*0.707)*((x-45)*0.707+(y-25)*0.707)/36+ ((x-45)*0.707-(y-25)*0.707)*((x-45)*0.707-(y-25)*0.707)/1024 <= 1 ) obstacles.field[x][y] = 1; if( ((x-35)*0.707+(y-70)*0.707)*((x-35)*0.707+(y-70)*0.707)/36+ ((x-35)*0.707-(y-70)*0.707)*((x-35)*0.707-(y-70)*0.707)/1024 <= 1 ) obstacles.field[x][y] = 1; } break; case ONE_LONG_OBSTACLE: for( int x = 0 ; x < GRID_WIDTH ; x++ ) for( int y = 0 ; y < GRID_HEIGHT ; y++ ) { obstacles.field[x][y] = 0; if( (x-60)*(x-60)/1600+ (y-50)*(y-50)/25 <= 1 ) obstacles.field[x][y] = 1; } break; } // initialize the grid with the home and food sites for( int x = HOME_XMIN ; x <= HOME_XMAX ; x++ ) for( int y = HOME_YMIN ; y <= HOME_YMAX ; y++ ) sites.field[x][y] = HOME; for( int x = FOOD_XMIN ; x <= FOOD_XMAX ; x++ ) for( int y = FOOD_YMIN ; y <= FOOD_YMAX ; y++ ) sites.field[x][y] = FOOD; for(int x=0; x < numAnts; x++) { Ant ant = new Ant(reward); buggrid.setObjectLocation(ant,(HOME_XMAX+HOME_XMIN)/2,(HOME_YMAX+HOME_YMIN)/2); schedule.scheduleRepeating(Schedule.EPOCH + x, 0, ant, 1); } // Schedule evaporation to happen after the ants move and update schedule.scheduleRepeating(Schedule.EPOCH,1, new Steppable() { public void step(SimState state) { toFoodGrid.multiply(evaporationConstant); toHomeGrid.multiply(evaporationConstant); } }, 1); } public static void main(String[] args) { doLoop(AntsForage.class, args); System.exit(0); } }