swarm-modeling
[Top][All Lists]
Advanced

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

ASM-2.1.1 (Artificial Stock Market) announcement


From: Paul Johnson
Subject: ASM-2.1.1 (Artificial Stock Market) announcement
Date: Fri, 02 Jun 2000 13:20:33 -0500

Thanks to some help from Blake LeBaron, I have completed enough work to
announce a new version the ASM code.  You can find it at
http://ArtStkMkt.sourceforge.net.  You can either take a snapshot or
CVS.  Just for your information, when I make a snapshot, I create a
patch from the previous edition, so the ASMpatch1 applies against the
ASM code as released in April, and ASMpatch2 assumes you applied
ASMpatch1. 

I'm going to lay off this for a little while because it has been
all-absorbing, difficult work. My next agenda item is to upgrade the
data input/output mechanisms. You will note I've used the
lispAppArchiver for the new BFParams class, and now I will go through
the other classes and use it with them too.

Most of the changes deal with a
clarification/restructuring/modernization of the BFagent (BitForecasting
Agent) class. Here are the comments I put in the new version of
BFagent.m


 comments June 2, 2000

I began with the code as released by the ASM research team through
Brandon Weber in April, 2000.  Here is a summary of the vital changes
that affect the BFagent class.

0. New classes used in this version:
    A. BFCast.[hm]
    B. BFParams.[hm]
    C. BitVector.[hm]

1. I am fully aware of confusion about the meaning of bit in this
model. Bit does usually mean something that is 0 or 1, but in this
model it means something else.  In the agent, a bit is what is often
called a "trit", something that is valued 00, 01, 10, or 11. Trit
means smallest thing that can hold three values.  In these agents, a
trit has these meanings:

  binary value    integer equivalent   meaning 
  00                 0                  # or "don't care"
  01                 1                  NO
  10                 2                  YES
  11                 3                  not in use, a place holder value 

GET READY for the big surprise. In World.m, the coding is reversed, so
01 means yes and 10 means no.  This accelerates the comparision of the
agent's bit vector against the state of the world.  Look for the & in
the-updateActiveList: medthod and you'll see why.  I've written an
alternative, more transparent algorithm.  I don't think it takes much
more time, but perhaps your computer will tell differently.

2. The bit math got frustrating enough that I have segregated it in a
class I call "BitVector".  It is really a vector of "trits" but so
much of the rest of this code uses the term bit that I didn't have the
enthusiasm to change it.  When a "BitVector" instance is created, it
has to be told how many bits, er trits, of information it is supposed
to hold.  Whenever the agent needs to keep track of a bunch of bits,
er trits, it can create a BitVector object to do it, and the interface
allows values to be put in and retrieved in a relatively obvious way.

Furthermore, when agents create the "forecast objects" using the
BFCast class, then those forecast objects will contain within them
BitVector objects that keep track of that forcast object's bits.

3. The BFCast class now has taken the place of the struct BF_cast that
was in BFagent.h.  Any bit manipulation that needs to be done can be
done by talking to an instance of that class. The bit manipulation is
hidden from this BFagent class, so at some time in the future we could
re-implement BFCast and as long as it had the right interface, the
BFagent would not care.  The BFCast class talks to the forecast object
that is inside it and tells it to set bits (er, trits) to certain
values with messages like "setConditionsbit: 5 To: 2" and BFCast can
handle the rest by passing on the news to the BitVector object.

4. The BFParams class now has taken the place of the struct BF_Params
that was in BFagent.  This change allows some significant upgrades in
functionality.  First, the BFParams class uses the Swarm
lispAppArchiver.  See the initial values in asm.scm.  Because the
BFParams object contains some variables that are derived from the
values in the archiver, it is necessary to send an "init" message
after creating a BFParams object. Second, it is now possible to
customize the agents by creating a customized BFParams object for each
agent.  In the original ASM-2.0 code, there is a "global" variable
params and all agents use that one set of parameters.  So far, I not
done much to investigate the advantages of allowing agents to use
different numbers of bits (er, trits), but I intend to.  Until I do
that, the instance variable "privateParams" simply points to the same
single BFParams object that is created by ASMModelSwarm, and
parameters retrieved from either are thus the same.  

<Apology mode> Note further, I did not write "get" methods for every
variable in the BFParams class. It just seemed onerous to do so.
There are 2 ways to get values out of BFParams.  First, use the ->.  I
declared the IVARS in BFParams to be public, so they can be retrieved
with the symbol -> as if the parameter object were a pointer to a
struct, as in: privateParams->condwords.  I hate doing that, and have
the long term plan of replacing all of these usages with get messages.
Second, for the short term, I put in the getDouble() and getInt()
functions which can be used to do get values. These will work even for
private variables, so if you get concerned about declaring all those
public IVARS in BFParams, you can get values in this way:
getInt(privateParams,"condwords").  I used that a number of times in
this file, but not everywhere, because I got tired of typing.
</Apology mode>

5. More object orientation.  The "homemade" linked lists, built with
pointers and other C concepts, are replaced by Swarm collections.
Iteration now uses Swarm index objects.  Many usages of C alloc and
calloc are eliminated.  This should approach a high level of
readability.

Example: code that used to look like this for looping through a list:
   struct BF_fcast *fptr, *topfptr;
   topfptr = fcast + p->numfcasts;
   for (fptr = fcast; fptr < topfptr; fptr++) 
      {
        if (fptr->conditions[0] & real0) continue;
        *nextptr = fptr;
        nextptr = &fptr->next;
      }

Now it looks like this:
   id <Index> index=[ fcastList begin: [self getZone]];
    for ( aForecast=[index next]; [index getLoc]==Member;
aForecast=[index next] )
    {
      if ( [aForecast getConditionsWord: 0] & real0 )   continue ;
      //if that's true, this does not get done:
      [activeList addLast: aForecast];
    }
    [index drop];

Example 2: What was like this:
  for (fptr = fcast; fptr < topfptr; fptr++) 
    {
      agntcond = fptr->conditions;
      for (i = 0; i < condbits; i++)
        count[(int)((agntcond[WORD(i)]>>SHIFT[i])&3)][i]++;
    }
Is now like this:
 index=[ fcastList begin: [self getZone] ];  
 for( aForecast=[index next]; [index getLoc]==Member; aForecast=[index
next] )
   {
     agntcond = [aForecast getConditions];
      for (i = 0; i < condbits; i++)
        {
            count[ (int)[aForecast getConditionsbit: i]][i]++;
        }
   }
 [index drop];
 
Note the usage of Swarm lists, indexes, and methods like
"getConditionsbit" and "getConditionsWord", instead of bitmath.

Usage of pointers to arrays is now minimized as well.  There used to
be a class method called +prepareForTrading that would retrieve a copy
of all the world's information and pick out what was needed for an
agent of this class.  Then the result of that calculation would get
stored in world.  While this had the advantage of doing the
calculation once for all agents of the class, it has the disadvantage
of restricting us to having identical bit vectors in all agent
forecasts.  I've dropped this approach, instead creating a variable
myworld in the agent's -prepareForTrading method, and each agent can
look to the world and get the information it wants.


6. Think locally, act locally.  Global pointers and lists and anything
else have been replaced wherever possible by automatic variables
(inside methods) or instance variables.  I created several new methods
that take bits from bit methods/functions and do them in isolation
(see -updateActiveList or -collectWorldData.

7. Genetic Algorithm now is written in Obj-C methods that pass whatever 
arguments are needed, rather than using C functions that access a lot 
of global variables. Agent's don't share workspace for the GA, either, 
each has its own memory.  

8. Formulas to calcuate strength, specfactor, and variance in the 
forecast objects were different in the original BFagent.m than in 
the bfagent.m.  Since the bfagent.m file matched the documentation 
released with ASM-2.0, I have changed to use the bfagent.m formulas 
in this file.  Some cleanup can still be made.  */


-- 
Paul E. Johnson                       email: address@hidden
Dept. of Political Science            http://lark.cc.ukans.edu/~pauljohn
University of Kansas                  Office: (785) 864-9086
Lawrence, Kansas 66045                FAX: (785) 864-5700


                  ==================================
   Swarm-Modelling is for discussion of Simulation and Modelling techniques
   esp. using 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]