/* * * MAML TUTORIAL (Model 4.2) -- The model's main file * For full description refer to * http://www.syslab.ceu.hu/maml/tutorial/ * * 'Segregation' a model by Thomas Schelling * * This simulation is based on a model published by T. Schelling, and consists * of agents living in a 2d grid. The agents are of two colors (blue and red) * and stay at a given location only if the ratio of the number of their * neighbors the same color and the number of neighbors is more than a * specified limit. What is interesting is that if this limit is fairly low * (appr. 0.5), this fairly tolerant behaviour leads to surprisingly high * rate of segregation at the global level. * It was implemented in MAML v0.03 as part of its tutorial. * * (c) 1998, CEU Systems Laboratory * */ @model Segregation { @uses ; // We need this Swarm package // to store the grid // Model parameters @var: int citySize, numOfResidents, ratio, minAgeLimit, maxAgeLimit; @var: float minLimit, maxLimit; // The grid holding the agents @var: id city; // Parameter: whether to consider empty locations as friendly @var: boolean emptyIsOK; //////////////////////////////////////////////////////////////////////// // Taking the file describing the agents' behaviour $import "resident.maml.stub"; //////////////////////////////////////////////////////////////////////// // Subroutine to create a new agent // (It was put in a separate routine as it is fairly complex.) @sub: (void) createNewResident: (Resident) r { // Variables to temporalily store the parameters of the newborn agent int color, x, y, age; float limit; // Random 'coloring' according to the given global ratio color = [uniformIntRand getIntegerWithMin: 0 withMax: 100]; if (color= maxLimit) // This branch is needed because limit = minLimit; // RNG does like if min=max else limit = (float)[uniformDblRand getDoubleWithMin: (double) minLimit withMax: (double) maxLimit ]; // Setting the maxAge parameter randomly in the given range if (minAgeLimit >= maxAgeLimit) // This branch is needed because age = minAgeLimit; // RNG does like if min=max else age = [uniformIntRand getIntegerWithMin: minAgeLimit withMax: maxAgeLimit]; [r setColor: color maxAge: age AndLimit: limit]; // Choosing an unoccupied spot randomly // Note that it results in an infinite loop if // there is no more unoccupied location. It should // be used carefully do { x = [uniformIntRand getIntegerWithMin: 0 withMax: (citySize-1)]; y = [uniformIntRand getIntegerWithMin: 0 withMax: (citySize-1)]; } while ([city getObjectAtX: x Y: y] != nil); [r setX: x Y: y]; } //////////////////////////////////////////////////////////////////////// // The model's schedule @schedule cyclic (1) { 0: @forEach groupOfResident step; // The step method is to be called // at each timestep of the model // for each resident (agent). } //////////////////////////////////////////////////////////////////////// // The initialization of the model @init: // Create the grid @create Discrete2d city { [city setSizeX: citySize Y: citySize]; } // Create the given number of residents (agents) { int i; Resident *dummy; // There can be no more residents than locations on the grid. // See the note at the end of 'createNewResident'. if (numOfResidents > citySize*citySize) numOfResidents = citySize*citySize; for (i=0; i