Print

Print


Allow me to jump in on this conversation very late, and without having read very well.  :-)

It sounds like your original concern was that the agents seem to be behaving strangely in the first step, and then work fine from then on.  But the conversation seems to have morphed into a discussion of proper use of random number generators.  I won't be able to look into your code regarding the original concern for a few days probably.  But let me weigh in on the random number generation discussion.

The rule of thumb with random number generators is as follows: unless you know exactly what you are doing, you should:

1. Seed a single random number generator

2. Only use that random number generator throughout your run

3. If you have multiple threads active, and ONLY if this is the case (because it is somewhat slow), then code in each thread should lock on SOMETHING before accesing the random number generator.  In MASON, that something is by convention the random number generator itself, that is,         synchronized (state.random) { return state.random.nextInt(n); }  etc.

And that's it.  Your agents are welcome to have pointers to the SimState RNG, but they should NOT have their own independent RNGs.  This is not because it's not possible to write perfectly cromulent code with agents having their own independent RNGs.  It's because with a high probability you will not write it correctly, and because there's absolutely no reason to do this in the first place.

Problem 1: seeding.  You have to seed each generator separately.  How are you going to do this?  You can't do it based on wall-clock time: they'll likely be synchronized.  You could seed them based on increasing steps beyond wall-clock time and that will PROBABLY work okay, but it's a major potential source of hard-to-debug errors.  For example, I'm guessing that you probably didn't pulse each of the Mersenne Twister RNGs about 1500 times to get rid of initial bad randomness in your seeding.  No one thinks of stuff like this.  You could also (as Joey said) seed them based on a random number generation from a master RNG.  This is called "forking" an RNG. Note that Mersenne Twister is NOT DESIGNED FOR FORKING.  It's not going to have statistically guarantees.  

Problem 2: memory.  Each of your agents now is holding onto an object that contains about 3K of RAM for no good reason.  If you have 1000 agents, that's 3 megs just for unneccessary RNGs.

This stuff has to be done delicately and in ways you probably didn't think of.  For example, the GUI has its own separate RNG to assign random colors etc. for GUI purposes so as not to pollute the underlying model RNG.

So here's what you should do.  Each of your agents should be given a pointer to the SimState (state), or to state.random, and just call SimState's RNG directly if they're all in the same thread.  And that's it.  You'll save memory, it'll be just as fast, and you'll dramatically reduce the chances that you've introduced RNG bugs.

Sean