/*
*
* MAML TUTORIAL (Model 4.2)
* For full description refer to
* http://www.syslab.ceu.hu/maml/tutorial/
*
* (c) 1998, CEU Systems Laboratory
*
*/
@model m4 {
//Parameters of the model
@var: int numOfOffers, maxOffer, changeInOffer, numOfParties, numOfCivilians,
membersQuotient, fidelityFactor, maxWeight;
@agent Party {
@var: [] int offer;
// declares an int array variable
@var: int members;
// Setting the initial offer
@sub: (void) init {
@create [model->numOfOffers:i] int offer {
// create and initialize an int array
offer[i] = model->maxOffer/2;
}
members = 0;
}
// Changing the offer
@sub: (void) newOffer {
int i;
for (i=0; i<model->numOfOffers; i++) {
offer[i] += [uniformIntRand getIntegerWithMin: -model->changeInOffer
withMax: model->changeInOffer]
+ members/model->membersQuotient;
if (offer[i] > model->maxOffer) offer[i]=model->maxOffer;
if (offer[i] < 0 ) offer[i] = 0;
}
}
}
// The array of parties
@var: [] Party parties;
@agent Civilian {
@var: int favouriteParty, fidelity;
@var: [] int weights;
@sub: (void) init {
// Setting the preference weights randomly
@create [model->numOfOffers:i] int weights {
weights[i] = [uniformIntRand getIntegerWithMin: 0
withMax: model->maxWeight];
}
fidelity = 0;
favouriteParty = [uniformIntRand getIntegerWithMin: 0
withMax: model->numOfParties-1];
model->parties[favouriteParty]->members++;
}
// Calculating the weighted sum of the offers
@sub: (int) weightedSumOf: ([] int) offers {
// a subprogram returning int
int i;
int sum = 0;
for (i=0; i<model->numOfOffers; i++) sum += weights[i]*offers[i];
return sum;
}
// Deciding which party to support
@sub: (void) rethink {
int insistence =
[self weightedSumOf: model->parties[favouriteParty]->offer] +
model->fidelityFactor*fidelity;
int bestParty, i;
int bestOffer = insistence;
for (i=0; i<model->numOfParties; i++)
if (i!=favouriteParty) {
int iOffer = [self weightedSumOf: model->parties[i]->offer];
if (iOffer>bestOffer) {
bestOffer = iOffer;
bestParty = i;
}
}
if (bestOffer > insistence) {
model->parties[favouriteParty]->members--;
favouriteParty = bestParty;
model->parties[favouriteParty]->members++;
fidelity = 0;
} else fidelity++;
}
}
// Array of people
@var: [] Civilian civilians;
@planDef oneTurn seq {
@forEach groupOfParty newOffer;
@forEach groupOfCivilian rethink;
}
@schedule cyclic(1) {
0: @plan oneTurn;
}
@init:
@create [numOfParties:i] Party parties { [parties[i] init]; }
@create [numOfCivilians:i] Civilian civilians { [civilians[i] init]; }
}
@observe m4 {
@uses <analysis.h>;
@extendAgent Civilian {
@var: int previousFavourite, favouriteChanged;
@sub: (int) getParty { return favouriteParty; }
@sub: (int) getChange { return favouriteChanged; }
@sub: (void) testForChange {
favouriteChanged = (favouriteParty != previousFavourite);
previousFavourite = favouriteParty;
}
}
@probe: var "maxOffer", var "changeInOffer",
var "numOfParties", var "numOfCivilians",
var "membersQuotient", var "fidelityFactor",
var "maxWeight", var "numOfOffers";
@var: id histogram;
@var: id graph;
@extendPlan oneTurn {
@forEach groupOfCivilian testForChange;
}
@schedule cyclic (1) {
0: @planDef {
@to histogram reset;
@to histogram update;
@to histogram output;
}
0: @to graph step;
}
@init:
numOfOffers = 3;
maxOffer = 2000; changeInOffer = 100;
numOfParties = 5; numOfCivilians = 300;
membersQuotient = 1000; fidelityFactor = 10;
maxWeight = 10;
@buildProbes;
[model probe];
[controlPanel setStateStopped];
@initModel;
{
int i;
for (i=0; i<numOfCivilians; i++)
civilians[i]->previousFavourite = -1;
}
@create EZBin histogram {
[histogram setTitle: "Number Of Party Members"];
[histogram setAxisLabelsX: "Parties" Y: "Number of members"];
[histogram setBinCount: numOfParties];
[histogram setLowerBound: 0];
[histogram setUpperBound: numOfParties];
[histogram setCollection: groupOfCivilian];
[histogram setProbedSelector: M(getParty)];
}
@create EZGraph graph {
[graph setTitle: "Number Of Preference Changes"];
[graph setAxisLabelsX: "Number of people" Y: "Time"];
}
[graph createTotalSequence: "Changes" withFeedFrom: groupOfCivilian andSelector: M(getChange)];
}