swarm-support
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Counting agents


From: Benedikt Stefansson
Subject: Re: Counting agents
Date: Wed, 11 Jun 1997 14:01:33 +0200

Todd wrote:

    "I am working with a model in which each agent has a 'type' which is
     defined by the values of three agent level variables.  At each
     interaction in the model an agent has the option to change his
'type' to
     that of another agent which s/he encounters.  I need to keep track
of
     the number of agents of each 'type' in the population at each time
step
     which I would like to output to a file. Does anyone know of an easy
way
     to do this?"

Hi Todd,

If you can find a way to enumerate the agent types you might start by
looking at
the class Counter that I hacked up the other day for a similar purpose.
In my case the number of types was only 11 so the ascii file output
is fairly clean and simple, e.g. each period a space delimited record
of the number of each type is output. 

Manor's EZBin class does somewhat the same thing, but I've had problems
with it when the types/classes/bins are not real numbers and
don't fall in the (0,1) interval.

Of course if you have a space of types that is large neither of these 
schemes may work. In my current project there are 3^9 types, and I 
haven't quite figured out how to output a clean count since only
a tiny fraction of the type space is represented in each period.

But for what it's worth here go some examples of a) how to count data b)
print it 
out to a file and c) show it on a Histogram widget:

This is the header file for Counter:

// Code by Benedikt Stefansson 1996,1997
#import <swarmobject.h>
#import <activity.h>
#import <collections.h>
#import <simtools.h>
#import <stdlib.h>
#import <stdio.h>
#import <malloc.h>
#import <math.h>

@class Counter;
@class CounterData;

@interface Counter: Swarm {
        id theCollection;
        id theDataObjects;
        int numBins;
        int * theBins;
        int normalize;
        MessageProbe * theProbe;
}       

// Attach the counter to a list of agents and define the 
// number of "bins" into which the return variable may fall
-setCollection: (id) c numBins: (int) n andSelector: (SEL) s;

// You may wish to "normalize" the count, i.e. represent the
// count for each bin as a percentage of the total
-setNormalize;

// When updated is called the counter probes the agent collection
-update;

// Method used by graph widgets that need to get the information
// in array format
-(int *)getCountArray;

// Method returning an object collection containing CountData 
// objects, one for each bin being counted
-getCountObjects;

// Method returning count for a specific bin 
-(int)getCount: (int) i;

// Method returning the count object for a specific bin
-getData: (int) i;

@end

@interface CounterData: Swarm {
        int data;
}

// Set the count back to zero
-clear;

// Increase the count for this bin by one
-addOne;

// Return the data
-(int)getCount;

// Used if we want counts to sum up to 100%
-normalizeWith: (int) sum;


@end



Before I list the .m file let me show how you can use this class.

1) To record the information in an ASCII file, you may opt to use the
DataFile class that I recently uploaded to the user-contribution
directory on the Swarm website. In ObserverSwarm or BatchSwarm create a
DataFile instance and then a probe for the Counter. This is an example:

consumerDataFile=[DataFile createBegin: [self getZone]];
[consumerDataFile addFullDataSet: "moneyUse.ful"
                    withFeedFrom: [[modelSwarm getMoneyCounter]
getCountObjects] 
                     andSelector: M(getCount)];

Note that the instance moneyCounter was previously created in
ModelSwarm, and here we pass the CountData objects to the DataFile,
which expects a collection of objects, not an array.

In ModelSwarm the Counter was created like this:

moneyCounter=[Counter create: [self getZone]];
[moneyCounter setCollection: consumerList 
                    numBins: (numGoods+1) 
                andSelector: M(getBarterGood)];
[moneyCounter setNormalize];

Of course you have to remember to schedule an update on the counter,
either every period or at periodic intervals.

2) To monitor the data in real-time we can represent the counter data on
a histogram widget. This is of course just a specific example but you
probably catch the drift. The
messy stuff is in the GraphElements and ActiveGrapher creation, which is
why Manor wrote
the EZGraph, EZBin classes. But for more control you need this:

  // Create graph widget to display how many consumers use 
  // each good 1,...,N for money and how many barter 
  moneyHisto = [Histo create: [self getZone]];
  [moneyHisto setWidth: 400 Height: 250];
  [moneyHisto setNumPoints: [modelSwarm getNumGoods]+1
            Labels: labels
            Colors: labelColors];
  [moneyHisto title: "Consumers using good for money"];
  [moneyHisto axisLabelsX: "good index" Y: "percentage using as money"];
  [moneyHisto pack];
 

  // Create a graph widget to display the statistics on 
  // use of goods for money over time
  moneyGraph = [BLTGraph create: [self getZone]];
  [moneyGraph title: "Use of good for money"];
  [moneyGraph axisLabelsX: "time" Y: "percentage"];
  [moneyGraph setWidth: 400 Height: 250];

   // now create a bunch of elements, one per good to graph.
   moneyElements= malloc(sizeof(*moneyElements) * ([modelSwarm
getNumGoods]+1));
   moneyGrapher=  malloc(sizeof(*moneyGrapher) * ([modelSwarm
getNumGoods]+1));

   for (i = 0; i < ([modelSwarm getNumGoods]+1); i++) {
        // Create an element that is associated with good i 
        moneyElements[i] = [moneyGraph createElement];
        [[moneyElements[i] setLabel: labels[i]] setColor:
labelColors[i]];
 
        // And create an object that gets the data for good i
        moneyGrapher[i] = [ActiveGraph createBegin: [self getZone]];
        [moneyGrapher[i] setElement: moneyElements[i]]; 
        [moneyGrapher[i] setDataFeed: [[modelSwarm getMoneyCounter]
getData: i]];
        [moneyGrapher[i] setProbedSelector: @selector(getCount)];
        moneyGrapher[i]=[moneyGrapher[i] createEnd];
   }
   [moneyGraph pack];


The labels and labelColor arrays were defined previously in the
ObserverSwarm .m
file. In my case I put these two lines after the #import directives but
before the @implementation directive:

char *labelColors[] = {
  "red", "orange", "yellow", "green", "blue", "purple", "grey50",
"black",
 
"MediumOrchid","Pink","SeaGreen","LightBlue","SandyBrown","DarkTurquoise","Purple",
  "LightSalmon","MediumOrchid","CadetBlue","IndianRed"};

char *labels[] = {"barter","good1 ","good2 ","good3 ","good4 ","good5
","good6 ",
                  "good7 ","good8 ","good9 
","good10","good11","good12","good13",
                  
"good14","good15","good16","good17","good18","good19","good20"};


If you require a larger number of colors or labels you may want to write
a loop
that creates this with sprintf functions etc.

Finally here comes the actual Counter class. You'll probably have to
make numerous changes to these classes, but I hope they help you along.

Best regards,

-Benedikt


The Counter.m file:


// Code by Benedikt Stefansson 1996,1997
#import "Counter.h"


@implementation Counter

-setCollection: (id) c numBins: (int) n andSelector: (SEL) s {

        int i;

        theCollection=c;
        numBins=n;

        theBins=malloc(numBins*sizeof(int));
        if(!theBins) {
                                              
                exit(1);
        }

        theDataObjects=[Array create: [self getZone] setCount: numBins];

        for(i=0;i<numBins;i++) {
                theBins[i]=0;
                [theDataObjects atOffset: i 
                                     put: [[CounterData create: [self
getZone]] clear]];
        }

        theProbe=[MessageProbe createBegin: [self getZone]];
        [theProbe setProbedSelector: s];
        theProbe=[theProbe createEnd];
        
        return self;
}

-setNormalize {
        normalize=1;
        return self;
}       

-update {

        id index;
        id theMember;
        int i;
        int data;
        int theSum=0;

        for(i=0;i<numBins;i++) 
                theBins[i]=0;

        [theDataObjects forEach:M(clear)];

        index=[theCollection begin: [self getZone]];
        while((theMember=[index next])) {
             data=(int)[theProbe doubleDynamicCallOn: theMember];
             if((data>=0) && (data<numBins)) {
                theBins[data]+=1; 
                [[theDataObjects atOffset: data] addOne];
            } else {
                printf(stderr,"Counter: Warning! Object returned data out of
range\n");
            }
        }
        [index drop];

        if(normalize==1) {
                // Normalize to % as integer number 0,...,100
                for(i=0;i<numBins;i++)
                        theSum+=theBins[i];
                if((theSum==0))
                        theSum=1;
                for(i=0;i<numBins;i++) {
                        
theBins[i]=(int)floor(((double)theBins[i]/(double)theSum)*100.0);
                        [[theDataObjects atOffset: i] normalizeWith: theSum];
                }
        }
        return self;
}


-(int*) getCountArray {
        return theBins;
}

-getCountObjects {
        return theDataObjects;
}

-(int) getCount: (int) i {
        return theBins[i];
}

-getData: (int) i {
        return [theDataObjects atOffset: i];
}

@end

@implementation CounterData

-clear {
        data=0;

        return self;
}

-addOne {
        data++;
        return self;
}

-normalizeWith: (int) sum {

        data=(int)floor(((double)data/(double)sum)*100.0);
        return self;
}


-(int)getCount {
        return data;
}


@end


--------------------
Benedikt Stefansson               address@hidden

Center for Computable Economics   Tel. (310) 825-1777
Department of Economics, UCLA     Fax. (310) 825-9528
Los Angeles, CA 90095-1477        http://cce.sscnet.ucla.edu

Laboratorio di Economia           Tel. (0461) 882246
Dip. di Economia, U. di Trento    Fax. (0461) 882222
38100, Trento, Italy              http://www-ceel.gelso.unitn.it

                  ==================================
   Swarm-Support is for discussion of the technical details of the day
   to day usage of Swarm.  For list administration needs (esp.
   [un]subscribing), please send a message to <address@hidden>
   with "help" in the body of the message.
                  ==================================


reply via email to

[Prev in Thread] Current Thread [Next in Thread]