SimpleModel1/notes-changes1.txt ------------------------------- Suppose we want to count and graph the number of times agents move. (Recall, they may not move if they try to move into an occupied cell.) To do this, make the following changes: 0. First, make a new copy of this program in a new directory, so the original is still readily available. So cd cp -r SimpleModel1 SimpleModel1-A cd SimpleModel1-A 1. Add an instance variable in the Agent class to count the number of times an agent moves. A. In Agent.h - add an instance variable int numberOfMoves; Note it can go anywhere in the list of IVs - add a getNumberOfMoves accessor declaration (we don't really need a set). just copy/modify the getNumberOfMeetings method. B. In Agent.m - Add the definition of the getNumberOfMoves accessor (Again just copy and modify getNumberOfMeetings) - In the Agent-step method, lets test the return value from makeRandomMove, which is 0 if agent moved, -1 if not Thus replace the line [self makeRandomMove]; with something like if ( [self makeRandomMove] == 0 ) // agent moved! ++numberOfMoves; // so increment count I would now save the Agent.h/.m files and make to see that it compiles correctly. If it doesn't fix the errors. If it does, run it and then probe some agent, change its color to red (135) or something, and see if the agents IV increments iff it moves. Question: sometimes you'll see an isolated agent won't move. Why is that? 2. Next we want to get the average numberOfMoves over all agents at each time step. We'll want to put this on a graph, but first lets just write it to the report file. A. First lets define an instance variable in ModelSwarm.h to hold the average value: double avgNumberOfMoves; and also declare a getAvgNumberOfMoves method. (This time copy/modify the getAvgWealthPerTime method.) Then define that new getAvgNumberOfMoves method in the ModelSwarm.m file. Again, just copy and modify the getAvgWealthPerTime, just changing the references to WealthPerTime to NumberOfMoves as appropriate. I would "make" the program here, just to make sure there are no errors. B. Now modify the fprintf in ModelSwarm-stepReport to print a new column with this new value in it. This can be done by - In the "..." add a %6.3f before the \n (newline) to write out a decimal value with 3 digits to right of dot. - Add the avgNumberOfMoves after the other variables in the fprintf's list of variables to print. - Also send "self" (ie the ModelSwarm itself) the new getNumberOfMoves method, just like it sends the getAvgWealthPerTime to self. Now "make" the program, and when no errors, run it for a few steps, and then look at the report file by emacs report & or just cat report Note one thing we didn't change was the headers for the report file. This is set up by a fprintf in the ModelSwarm-buildObjects method. You could take a few seconds to fix that, too. 3. Now we want to put a new graph up, and plot this new value. Again, we are going to just copy the parts of the program that set up the graph we have, and just change the names of the variables to hold addresses of the graph objects, and of course its title, the places where it gets data, etc. The graphs have several parts, all set up in ObserverSwarm.h/.m, as we have for the existing graph and one of its lines: - the graph widget itself: id aGraph; - the object for the line: id awpmGraphElem; - the data transfer object: id awpmGrapher; So....lets try to do this stepwise: A. In ObserverSwarm.h, copy/modify the names of the instance variables listed just above. Name them, say, bGraph and bnmGraphElem and bnmGrapher B. In ObserverSwarm.m, in buildObjects, find the lines where we construct the existing graph and its elements. First copy the part for creating the graph, and in it change the name to bGraph and change the title a little. I would copy it after all the lines for the aGraph and its elements, ie put it just before the comment: // ok, put the world on the screen Do a "make" at this point, just to be sure all is ok. (Be sure to save files before makes!) C. Next, copy the set of lines for the awpmGraphElem and awpmGrapher, again put them after the bGraph lines, and change the names from awpm* to anm* , and make sure it refers to aGraph , and change line labels. *** Be sure to change awpm throughout these lines, not just on left! Finally, change the M(getAvgWealthPerMeeting) to getAvgNumberOfMoves. Again, do a make to be sure it at least is syntactically ok. When it makes with no errors, you can run it. You'll see the second graph, with appropriate title and labels (if you did all the changes), but no line will be plotted when you run the model. We need to do one more step. D. Now we need to modify the ObserverSwarm schedule, so that each time step it tells the bGrapher to draw a point to the graph. So, in the ObserverSwarm-buildActions method, copy the line for one of the lines in the first graph: [displayActions createActionTo: awpmGrapher message: M(step)]; and just change the awpm to bnm !! Now "make" again, and when you have no errors, run the model ./sm1 and run the model, and you should see the values plotted! E. Now you could do some testing to see if the numbers make sense. For example, presumably if you have fewer agents per world size, there should be more moves. 4. Once you get it working, you will want to save this version as it is, so that if you then make changes, and you want to get back to this working version, you can easily do so. Type make save That will create a "tar.gz" file that has all the important files stored in a "tape archive" file (tar), compressed (gz), in a subdirectory named "Saves/". You can see the file ll Saves If you do another save later, it will create another with a new date/time stamp.