/users/rlr/RePast/Demo-3/RandomMoveInGrid/Readme.txt ---------------------------------------------------- A simple Repast program that is a "model" of Agents that move randomly in a 2D Grid world. In short: - A 2D grid world, bounded, is created. - Agents are created and placed at random in the world The agents are also kept on an agentList. - Each "time step": - each agent is sent a message step(), which causes it to try to move to a randomly selected open neighbor cell. - some simple info is written to the "report" file (the time step and the average X location of all Agents) This program builds on the Repast SimModelImpl class, which provides the GUI control and paramater parameters, as well as the basic "architecture" of - Model - common "conceptual" parts of the model - GUIModel - extends Model to add GUI controls, etc. - BatchModel - extends Model to allow run in non-gui mode. This differs from the Repast distributed demos in that this also is built on the ModelParameters.java class, so parameters can be set on the run command, and it is ready to use with Drone, to run experiments in batch mode. Its easy to add new parameters that are run-time settable and automatically recorded in the report file. The class structure and what they do: Drawable (interface) // | draw() BatchModel GUIModel // | getX(),getY() \ run without / Object2DDisplay (uses Drawable) \ \ GUI / DisplaySurface (implements) \ / ColorMap | \ / | \ / | Model ====================> Conceputual model | | build model ArrayList agentList | step() Grid2DObject world | tell agents to act Schedule schedule | stepReport() | calc, write measures | ModelParameters | process run-time settable paramters | start/use a good RNG | methods for report file open/write | | SimModelImpl (Repast) | - Control Panel | - Parameter Panel | (...) The rest of this file explains: - How to get a copy and run the program - The core conceptual components and where they are. - How the GUIModel works - How the BatchModel works ------------------------------------------------------------------------ All the source files are in the subdirectories src/RandomMoveInGrid The compiled classes are put in classes/ The package name is RandomMoveInGrid . To get a copy of this program, first create the "project" directory for it: mkdir RandomMoveInGrid cd RandomMoveInGrid mkdir -p src/RandomMoveInGrid bin classes Saves Then export RMIG=/users/rlr/RePast/Demos-3/RandomMoveInGrid cp $RMIG/Readme.txt . <<== Don't forget the dot (.) on this! cp $RMIG/src/RandomMoveInGrid/*.java src/RandomMoveInGrid cp $RMIG/bin/*.sh bin pwd Then you have to edit this three files in the bin/ directory: compile.sh guirun.sh batchrun.sh Near the top of each, change this line: PROJECTDIR=/users/rlr/RePast/Demos-3/RandomMoveInGrid so that it has the value of the path to *your* copy, e.g., from the output from the pwd command above, eg, PROJECTDIR=/users/yourLogin/RePast/RandomMoveInGrid/ Then you can compile it as follows: bin/compile.sh You will get something like this: Note: Some input files use unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. Its just telling you there are warnings from the compilation, but you can ignore these for now. Then to run it in GUI mode: bin/guirun.sh bin/guirun.sh X=41 Y=41 numAgents=50 and in batch mode: bin/batchrun.sh T=100 X=41 Y=41 numAgents=50 S=333 Note you can include parameters as desired to set the initial values for the model. (S sets the RNG seed). You can see the "help" for the model (such as it is) with bin/batchrun.sh -h After a run you can see what the report file looks like by editing or otherwise reading the file report.00 e.g., less report.00 to use the less command to see it. (Enter man less to see how to use the less command!) Note you can do a run and then a re-run with the same seed and parameters as follows: bin/batchrun.sh T=100 X=41 Y=41 numAgents=50 That produces a report.00 file, and a report.xml.00 file which has the same data, in xml format. We can use that xml file to set parameters on the next run, but then we also tell it to use a new report file name: bin/batchrun.sh iPFN=report.xml.00 rFN=report-rerun We can see the report files: ll report* and compare them diff report.00 report-rerun.00 diff report.xml.00 report-rerun.xml.00 They should only differ in the intial and report file names. Debugging messages: ------------------- There is one parameter, rDebug (aka D), provided by ModelParameters that can be used to control the display of debugging messages. Thus you will see in this program lines like this one in Model step() if ( rDebug > 0 ) System.out.printf( "==> Model step %.0f:\n", getTickCount() ); If the rDebug parameter (an int) is set to anything above 0, this message will be printed each time the Model step() method is entered. This kind of debugging message can be very useful when you are trying to figure out what series of events occur when the model is run one or more steps. One thing to think about when adding debugging messages is what information should you be printing. E.g., in the Agent step() method you might print out various values to help you understand why the Agent is doing what it is doing. One reason i find using this debugging approach (vs using tools like those provided by IDE's like Eclipse, etc) is that just the act of thinking about what you will put in the debugging messages encourages/forces you to think through the method operations, and thus you often find problems ("bugs") just by writing the debugging messages! Advice on edit/compile: ----------------------- The layout of files in a "project" directory like this is RandomMoveInGrid/ bin/ -- compile.sh, guirun.sh, batchrun.sh classes/ -- compiled (.class) files src/RandomMoveInGrid -- source (.java) files In general its best to use the project dir as your working dir, and edit and run the program from there. Thus a good way to edit the source files is like this emacs src/RandomMoveInGrid/Model.java & After you make and save changes, you can then use bin/compile.sh bin/guirun.sh to compile and run the program, to test your changes in that same terminal window, *leaving the emacs session running* in the background. Using ant to compile/run programs -- YOU CAN SKIP THIS! --------------------------------- You can also use the tool "ant" to compile and run programs. ant uses a file "build.xml" which contains all the information needed to compile and run the program (its name, the classpath's for repast and other libraries, etc). If you want to use ant, the easiest way to get a copy of a program like RandomMoveInGrid (which has a build.xml already) is to use this script: /appl/repast/Demos-3/bin/copyProject.pl \ -S/users/rlr/RePast/Demos-3 -XRandomMoveInGrid \ -R/users/YourLogin/YourPath -PRandomMoveInGrid Where you replace YourLogin with your login, and YourPath with the path to the place where you want this "project directory" to be placed. (Note the \ are just to tell linux the command continues on the next line. If you do it on one line, leave the \ off!) Also note that you will have to edit the bin/compile.sh and bin/guirun.sh files, as noted above, change the PROJECTDIR . (The bin/batchrun.sh is changed by the copyProject.pl command.) ----------------------------------------------------------------- See the drawing and notes in the file architecture.txt for a sketch of all the key objects in the program, as well as how they are related to each other and to the things on the screen. Note that both GUIModel and BatchModel extend Model, so that whichever way you run it, you get the same "conceptual" model, and those superclasses just add what they need for control of the model. ------------------------------------------------------------------ The "conceptual" model parts The core parts of the "conceptual" model are in these files: Model.java -- top level of conceptual model - keeps track of all model components, e.g. agentList, the (2d) world and schedule. - extends: - ModelParameters (UM): to get the builtin parameters/report - SimModelImpl (Repast): to get the schedule, panels, etc. Agent.java -- the only agents in this simple model The "intersting" parts of the program for the conceptual-model are: Model-buildModel() - the model components are created (agentList, 2D world, etc) - agents are placed into the world - tell the Agent class about the model and the 2D world objects Model-step() - defines what happens each click of the RePast clock - here just tells each agent to execute its own step() method, and then calls stepReport() to write stats. Agent-step() - top level action executed by each agent agent step. - generates a random dx,dy for its movement, - then asks the model to move it if possible. Contraints: 1 agent per cell, and bounded edges. Model- Point moveObjectInWorld ( Drawable obj, int dX, int dY ) This is used by an Agent instance to ask the model to (try to) move the agent instance to the location that is dx,dy from where the agent is now. See the Agent-step() method for its use. This method: - checks the world to see if the requested move is legal (recall: bounded world, and 1 object/cell) - if that move is "legal", changes the world to reflect the move Returns: Java Point object with new x,y location if moved null if couldn't move. NOTE: its up to the agent to update its cache of its own x,y location! Model-stepReport() This writes to the report file. Thus you change this method to write other stats. ------------------------------------------------------------------------------ Some of the simple ways you might change this program: - Add new parameters -- see howTo-AddParameter.txt - Add new types of agents -- see howTo-AddNewClass.txt Then create these, add to the world, etc. - Change what the Agent's do when sent the step() method - Collect and write more stats to the report file Slightly more complicated changes: - Add a graphing object to the GUI for some stats - randomize agent activation each step--several different ways. - Add new "layers" for storing mutliple types of information for each spatial location. - change the nature of the space--to a torus, hexagonal, etc. - add birth and death of agents - drawing objects faster to the 2D screen - open and write to additional "report" files - add new RNG distributions - add custom actions to the gui - draw agents in different shapes, color, hollow/not, etc. - using RePast's agent-network features - Use DES scheduling ( See Demos-3/SIR_DS1 ) These will be covered in related future versions of this program and in other demos/programs. ---------------------------------------------------------------------------- How the GUIModel works. The GUIModel extends the Model class in order to add all the objects needed to support whatever GUI components one wants. At a minimum this means using the Repast supplied control and parameter panels. Often it means creating and updating 2D displays, plots of data, histograms, and so on. Typically the only changes made to GUIModel are: - add instance variables to store addresses of GUI objects, e.g. these: DisplaySurface dsurf; Object2DDisplay worldDisplay; are used to display the 2D grid and Agents. - add colormap's to allow mapping from values to colors - setup() method: for any objects added for GUI components, "tear them down" to prepare for initialization of the model by begin(). - buildDisplay() create an objects needed to display 2D world, plots, historgrams, etc. - buildSchedule() One might schedule events here to update various GUI display objects. Or as in the simple RandomMoveInGrid program, all that is done in the single step() method, so there is no need to change buildSchedule() . - step() this just tells the super class (Model) to do what it does each time step, then this tells various display objects to update their displays. For more complex Model schedules, the way the GUI schedule interacts with the Model events might be more complex than in this simple discrete time program. For example, in DES (like mousetraps) we might want to update some displays not after each event, but only after some fixed "time" (e.g., every second). ---------------------------------------------------------------------------- How the BatchModel works. The BatchModel class is a very simple extension of the Model class. Basically it relies on the Model class for everything, except BatchModel also schedules sending the message processEndOfRun() to itself at the tick count specified by the stopT parameter, which causes the sim to clean things up and stop the program. Usually the only thing that needs to be changed in BatchModel is the schedule, when a model does something more complicated. Probably a better way to up BatchModel would be to have BatchModel's buildSchedule() ask the Model superclass to build its schedule, and then BatchModel just adds the processEndofRun() at the specified stopT. Note that in some models the stopT is really a kind of "safety stop" in that the Model can schedule an method that checks for some condition (e.g., all agents are dead, a certain number of events have happened, etc) and stop the sim if that condition is met. ----------------------------------------------------------------------------