AntPheromones1/extracts.txt --------------------------- This is a list of additions to AntPheromones1 (beyound the basic randomly move agents in RandmoMoveInGrid and Min2D_Pars) to show how to use the Diffuse2D class from RePast to represent a chemical distributed (and diffusing) over the 2D space. In summary we have: AntPheromones1.java -- conceptual model (Note its a torus now!) a) instance variables -- new parameters and the address of the Diffuse2D object b) buildModel() - create the Diffuse2D object, inject pheromone into it - restructure how bugs (agents) are created and placed in the world c) step() - diffuse the pher, tell bugs to move, inject pher. and update pSpace GUIModel.java a) instance variables for gui related objects and colors b) setup() -- create a color map c) buildDisplay() - set update mapping from pher-space to colors on screen d) step() -- no change!! the linkages created in buildDisplay() take care of it all! Bug.java (the agents) a) class variables for the Diffuse2D space and bugsWorld b) step() -- tries to move uphill, otherwise randomly; uses... c) Point findRandOpenNeighborCell() ======================================================================= AntPheromones1.java ------------------- Instance variables: public Diffuse2D pSpace; // a 2d space from RePast public double diffusionK, evapRate; // for the Diffuse2D public int pSourceX, pSourceY; // exogenous source of pheromone public double exogRate; // exog source rate, frac of maxPher Class variable: (why?? no reason!!) public static int maxPher; // max value, so we can map to colors Make the obvious changes to these: addModelSpecificParameters () getInitParam () setup() and add getters/setters for the parameters/instance variables. ------------------------------------------------------- buildModel() { pSourceX = sizeX/2; pSourceY = sizeY/2; // create the 2D diffusion space for pheromones, tell bugs about it pSpace = new Diffuse2D( diffusionK, evapRate, sizeX, sizeY ); Bug.setPSpace( pSpace ); for ( int i = 0; i < numBugs; i++ ) { Bug aBug = new Bug(); bugList.add( aBug ); ---> Point location = placeObjectRandomlyInWorld ( (Object) aBug ); aBug.setX( (int) location.getX() ); aBug.setY( (int) location.getY() ); } // lets start the world with some pheromone... double exogPheromone = 2.0 * maxPher * exogRate; double initPher = Math.min( exogPheromone, (double) maxPher ); pSpace.putValueAt( pSourceX, pSourceY, initPher ); pSpace.update(); // move from write copy to read copy ------------------------------------------------------- public Point placeObjectRandomlyInWorld ( Object obj ) { int randomX, randomY; do { randomX = getUniformIntFromTo( 0, world.getSizeX () - 1 ); randomY = getUniformIntFromTo( 0, world.getSizeY () - 1 ); } while ( world.getObjectAt( randomX, randomY ) != null ); world.putObjectAt( randomX, randomY, obj ); Point pt = new Point ( randomX, randomY ); return pt; } ------------------------------------------------------- public void step () { // diffuse() diffuses from the read matrix (T) and into write (T') // *and* it then does an update(), i.e., writes T' into new read T+1 pSpace.diffuse(); // now the bugs get a chance to move around for ( int i = 0; i < bugList.size(); i++ ) { Bug aBug = bugList.get (i); aBug.step (); } // add the exogenous supply. be sure not to go over maxPher // otherwise the color doesn't work right. // *** Note: This assumes the bugs have not altered the PSpace // without updating the pspace read copy!! // (this is adding to the amount it reads from the Read matrix) double v = (maxPher * exogRate) + pSpace.getValueAt( pSourceX, pSourceY ); v = Math.min( v, maxPher ); pSpace.putValueAt( pSourceX, pSourceY, v ); // now update the pSpace -- move values from the write to read copy pSpace.update(); stepReport(); } ============================================================================ GUIModel.java ------------- Instance variables: private Object2DDisplay worldDisplay; // 2D Object lattice -> display (Repast) private Value2DDisplay pSpaceDisplay; // 2D Value lattice -> display (Repast) private DisplaySurface dsurf; // display surface (RePast) Class variables: (??) public static ColorMap pherColorMap; public static final int colorMapSize = 64; public static final double colorMapMax = colorMapSize - 1.0; ------------------------------------------------------- setup() // create the ColorMap for displaying the amount of pheromone // as a degree of red-ness in the cells. pherColorMap = new ColorMap (); for (int i = 0; i < colorMapSize; i++) { // we specify the position i, and a fraction of each of RGB shade pherColorMap.mapColor ( i, i / colorMapMax, 0, 0 ); } ------------------------------------------------------- buildDisplay() // create the link between the pSpace and the dsurf. // we have to tell it how to scale values to fit the colorMap. // We want the largest possible state (pheromone) value // to map into the colorMapMax-th entry in the colorMap array. // The Value2DDisplay does this mapping with the parameters m,c: // int color index = (state / m) + c // so we want m = truncate( maxValue / maxColorIndex ) pSpaceDisplay = new Value2DDisplay( pSpace, pherColorMap ); int m = (int) (maxPher / colorMapMax); pSpaceDisplay.setDisplayMapping( m, 0 ); // add the pSpace first, so the bugs write over it. dsurf.addDisplayable( pSpaceDisplay, "Pheromone"); dsurf.addDisplayableProbeable( worldDisplay, "Bugs"); ----------------------------------------------------------- step() -- no change!! public void step() { super.step(); // the model does whatever it does dsurf.updateDisplay(); // display updates pheromone and bug display! } ============================================================================ ============================================================================ ============================================================================ Bug.java -------- Class variables: public static Object2DTorus bugsWorld; // where the bugs live public static Diffuse2D pSpace; // where the pheromone is stored -------------------------------------------------------------- step () { int moved = 0; // not moved this step // pick a random neighbor cell, and if it is open, // check the pheromone there, and if its more there, move there. Point pt = findRandomOpenNeighborCell (); if ( pt != null ) { // we got one! int newX = (int) pt.getX(); int newY = (int) pt.getY(); if ( pSpace.getValueAt( x, y ) < pSpace.getValueAt( newX, newY ) ) { moved = moveTo( newX, newY ); } } // if didn't move to better cell, then try to find any open neighbor. if ( moved == 0 ) { pt = findRandomOpenNeighborCell (); if ( pt != null ) { moved = moveTo( (int) pt.getX(), (int) pt.getY() ); } } } -------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////// // findRandomOpenNeighborCell // pick random open Moore neighbor cell and return its // coordinates in a Point, // Return null if no open cell found. public Point findRandomOpenNeighborCell () { ArrayList openPts = new ArrayList(); // list of open points int minx = x - 1; // we could change the "neighborhood radius" here int maxx = x + 1; int miny = y - 1; int maxy = y + 1; for ( int tx = minx; tx <= maxx; ++tx ) { for ( int ty = miny; ty <= maxy; ++ty ) { if ( bugsWorld.getObjectAt( tx, ty ) == null ) // its open openPts.add( new Point( tx, ty ) ); // add to list } } // now pick a random open point, if any to pick from int numOpenPts = openPts.size(); Point openP = null; // the one we return if ( numOpenPts == 1 ) // only one to pick! openP = openPts.get( 0 ); else if ( numOpenPts > 1 ) // pick one at random openP = openPts.get( model.getUniformIntFromTo( 0, numOpenPts-1 ) ); return openP; } --------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////// // moveTo newX, newY // check to see if the new location is open, and if so move to it: // - tell world it moved // - change bug's own x,y values // - return 1 to indicate move was succesful // if that location not open, return 0 // // NOTE: assumes we are on a torus (eg Object2DTorus object) public int moveTo( int newX, int newY ) { if ( bugsWorld.getObjectAt( newX, newY ) != null ) return 0; // oops, something is there! bugsWorld.putObjectAt( x, y, null ); // leaving that cell empty now bugsWorld.putObjectAt( newX, newY, this ); // move into new location x = SimUtilities.norm( newX, bugsWorld.getSizeX() ); // normalize for torus y = SimUtilities.norm( newY, bugsWorld.getSizeY() ); // normalize for torus return 1; } ============================================================================