program SIML
! Program (in fortran90) to simulate a large message list.
! Copyright Constantine S. Chassapis -- 25 Aug, 2000.
! contact me at cschassapis@acm.org
! Description: See the MEMO and related emails:
.
! Output to a classic console. No windows,
! just calculations. Iterative dynamic loop. First all
! list-members act, then the robot requests SUM-UPs and
! does some acoounting, and finally collectors (if there
! are any) are asked by the robot (the program) to form
! collections. Then the loop is repeated.
! Each user has six attribures:
! user(i,atrrib.j), i=1..N, j=1..6:
! attr.1 == attrib.activity: -1,0,+1: denied, notActive, active
! attr.2 == attrib.points: integer unlimited
! attr.3 == attrib.hasPosted: 1, 0, (yes,no)
! attr.4 == attrib.isThreaded: -1, 0, +1: notResponded, no, yes
! attr.5 == attrib.isCollector: 1, 0, (yes,no) !for minimizing point-comparisons
! attr.6 == attrib.worker: five-valued:
! tourist,lazy,average,hardworker,exceptional
!
! The pointing system currently programmed is:
! A. Per member:
! pentr: +100 at entry.
! pmess: +0 per message posted.
! psump: +1 per SUM UP done.
! psnot: -10 per SUM UP not done but required.
! pimpr: -1 per improper message.
! pthrd: +1 per message that starts a thread
! plink: +1 per message that is linked back in a collector's collection.
! pcoll: +1 for a collection given to the collector
! B. If member points greater than +300 then COLLECTOR.
! C. If member points less than -100 then provisional denial of
! message posting capability.
! This program if run outputs after 10000 steps:
! time thrds msgs oksum nosum links colex denied colectr active avepoi
! 10000 440 1800 170 45 2445 250 550 3800 10650 862
! and after 100000 steps:
! time thrds msgs oksum nosum links colex denied colectr active avepoi
!100000 424 1571 184 68 1447 172 563 4165 10272 8475
! Note that the above values are not average values except for the averaged points.
! According to the characteristics of the list (number of users, distribution
! of eagerness to work, various activity percentages) different pointing
! systems will produce stability. The user must experiment.
! DEFINE
implicit none
! number of active members of the list
integer numus
parameter (numus=15000)
! the users:
integer users(numus,6)
! user attributes:
integer activ, points, hasPost, isThrd, isColl, workr
parameter (activ=1, points=2, hasPost=3, isThrd=4, isColl=5, workr=6)
! pointing system:
integer pentr, pmess, psump, psnot, pimpr, pthrd, plink, pcoll
parameter (pentr=100, pmess=0, psump=1, psnot=-10, pimpr=-1, pthrd=1, plink=1, pcoll=1)
! various aux variables:
real unif, ran, response, avepoi, ran2
integer iu, iu2, iattr, iseed, it, tolink, ilink, itime,iseed0
integer tcount, mcount, dcount, ccount, acount, lcount, icollx
integer oksum, nosum
logical found
! INITIALIZE
iseed=-1
iseed0=-1
unif=ran2(iseed)
unif=ran(iseed0)
do 100, iu = 1, numus
users(iu,activ)=+1 !activity
users(iu,points)=pentr !points: unlimited
users(iu,hasPost)=0 !hasPosted
users(iu,isThrd)=0 !isThreaded
users(iu,isColl)=0 !isCollector: binary
unif=ran2(iseed)
! the users are distributed as follows:
! (tourist,lazy,average,hardworker,exceptional)=(5%,30%,40%,20%,5%)
if (unif.le.0.4)then
users(iu,workr)=+3 !worker: average. Fills 40%.
else if (unif.le.0.7.and.unif.gt.0.4) then
users(iu,workr)=+2 !worker: lazy. Fills 30%.
else if (unif.le.0.9.and.unif.gt.0.7) then
users(iu,workr)=+4 !worker: hard. Fills 20%.
else if (unif.le.0.95.and.unif.gt.0.9) then
users(iu,workr)=+1 !worker: tourist. Fills 5%.
else if (unif.le.1.0.and.unif.gt.0.95) then
users(iu,workr)=+5 !worker: exceptional. Fills 5%.
else
stop '1 should never arrive here'
endif
100 continue
! Total simulation steps (time).
itime=100000
! RUN
print*,' time thrds msgs oksum nosum links colex denied colectr active avepoi'
do 300, it = 1, itime
tcount = 0
mcount = 0
dcount = 0
ccount = 0
acount = 0
avepoi = 0.
lcount = 0
icollx = 0
oksum = 0
nosum = 0
! users actions
! the particular percentages (3%,13%,84%) were sellected so
! to have a given activity of messages and threads per step.
! We also allow for a 10% of improper messages per step.
do 410, iu=1,numus
if (users(iu,activ).eq.1)then
unif=ran2(iseed)
if (unif.le.0.03) then ! fills 3%
if (users(iu,hasPost).eq.1) then
users(iu,isThrd) = +1
users(iu,points) = users(iu,points) + pthrd
tcount = tcount + 1
endif
else if (unif.le.0.16.and.unif.gt.0.03)then ! fills 13%
unif=ran(iseed0)
if (unif.le.0.9) then ! fills 90%
unif=ran2(iseed)
if (unif.le.response(users(iu,workr),users(iu,points))) then
users(iu,points) = users(iu,points) + pmess
users(iu,hasPost) = +1
mcount = mcount + 1
endif
else if (unif.le.1.0.and.unif.gt.0.9) then ! fills 10%
unif=ran2(iseed)
if (unif.le.response(users(iu,workr),users(iu,points))) then
users(iu,points) = users(iu,points) + pimpr
users(iu,hasPost) = +1
mcount = mcount + 1
endif
else
stop '3: should never arrive here'
endif
else if (unif.le.1.0000.and.unif.gt.0.16)then ! fills 84%
! do nothing
else
stop '2: should never arrive here'
endif
endif
410 continue
! robot actions
! the particular percentages (2%,98%) were sellected so
! to have a given activity of SUM-UPs per step.
do 430, iu=1, numus
if (users(iu,activ).ne.0)then
unif=ran(iseed0)
if (unif.le.0.02) then ! fills 2%
if(users(iu,isThrd).eq.0)then
unif=ran2(iseed)
if (unif.le.response(users(iu,workr),users(iu,points))) then
do 433, iu2 = 1, numus
found=(users(iu2,isThrd).eq.-1)
if(found)goto 434
433 continue
434 continue
if(found)then
users(iu,points) = users(iu,points) + psump
users(iu2,isThrd) = 0
oksum = oksum + 1
endif
endif
elseif(users(iu,isThrd).eq.+1)then
unif=ran2(iseed)
if (unif.le.response(users(iu,workr),users(iu,points))) then
users(iu,points) = users(iu,points) + psump
users(iu,isThrd) = 0
oksum = oksum + 1
mcount = mcount + 1
else
users(iu,isThrd) = -1
users(iu,points) = users(iu,points) + psnot
nosum = nosum + 1
endif
endif
else ! fills 98%
! do nothing
endif
endif
! just accounting
if (users(iu,points) .lt. -100 ) then
users(iu, activ) = -1
users(iu, isColl) = 0
dcount = dcount + 1
elseif (users(iu,points).ge.-100.and.users(iu,points).lt.+300) then
users(iu, activ) = +1
users(iu, isColl) = 0
acount = acount + 1
elseif(users(iu,points) .ge. +300 ) then
users(iu, isColl)=+1
ccount = ccount + 1
endif
avepoi = avepoi + users(iu,points)
430 continue
! collectors actions
! the particular percentages (8%,92%) were sellected so
! to have a given activity of collections per step.
do 450, iu=1,numus
if (users(iu,activ).eq.1.and.users(iu,isColl).eq.1)then
unif=ran(iseed0)
if (unif.le.0.08) then ! fills 8%
unif=ran2(iseed)
if (unif.le.response(users(iu,workr),users(iu,points))) then
users(iu,points) = users(iu,points) + pcoll
mcount = mcount + 1
unif = ran2(iseed)
tolink = max(nint(mcount*unif/100.),1)
ilink = 0
do 457, iu2 = 1, numus
if(users(iu2,hasPost).eq.1)then
ilink = ilink + 1
if (ilink.gt.tolink)goto 458
users(iu2,points) = users(iu2,points) + plink
endif
457 continue
458 continue
lcount = lcount + ilink
icollx = icollx + 1
endif
else ! fills 92%
!do nothing
endif
endif
450 continue
write(*,'(10(1x,i6),1x,f8.1)')it,tcount, mcount, oksum, nosum, lcount, icollx, dcount, ccount, acount, (avepoi/numus)
if(mod(it,15).eq.0) print*,' time thrds msgs oksum nosum links colex denied colectr active avepoi'
300 continue
end program SIML
!---------*---------*---------*---------*---------*---------*---------*-
real FUNCTION RAN(ISEED)
! Numerical Recipes (1st ed.) routine RAN.
PARAMETER(IA=7141,IC=54773,IM=259200)
ISEED=MOD(ISEED*IA+IC,IM)
RAN=FLOAT(ISEED)/FLOAT(IM)
RETURN
END
!---------*---------*---------*---------*---------*---------*---------*-
real function response(user, points)
! routine that defines the responsiveness of the list-members. Note
! that responsiveness declines as the user gets more points. Note
! also that there are asymptotes at 0% and at 100%.
integer user, points
integer tourist,lazy,average,hardw,exception
parameter (tourist=1,lazy=2,average=3,hardWorker=4,exceptional=5)
real x0,xscal
if(user.eq.tourist)then
x0=-400.
xscal=100.
elseif(user.eq.lazy)then
x0=-200.
xscal=300.
elseif(user.eq.average)then
x0=0.
xscal=300.
elseif(user.eq.hardWorker)then
x0=500.
xscal=300.
elseif(user.eq.exceptional)then
x0=1000.
xscal=300.
else
stop '9 should never arrive here'
endif
! sigmoid response. Gives 1 if points tend to a large negative
! number and gives 0 if points tend to large positive number.
response = 1.-tanh((real(points)-x0)/xscal)/2.
end
!---------*---------*---------*---------*---------*---------*---------*-
real function ran2(idum)
! version 1.0.2 of 21/6/97.
! Numerical Recipes (1st ed.) routine RAN2.
! Only 714 025 differend randoms between 0 and 1 are possible as output.
! Set or Reset the sequence by giving a negative to idum, otherwise do
! not change it.
implicit none
integer j, m, ia, ic, iff, idum, iy
real rm
parameter(m=714025, ia=1366, ic=150889, rm=1./m)
integer ir(97)
data iff /0/
if(idum.lt.0.or.iff.eq.0)then
iff=1
idum=mod(ic-idum,m)
do 11, j=1,97
idum=mod(ia*idum+ic,m)
ir(j)=idum
11 continue
idum=mod(ia*idum+ic,m)
iy=idum
endif
j = 1+(97*iy)/m
if(j.gt.97.or.j.lt.1)then
stop'ran2 stop. check!'
endif
iy=ir(j)
ran2=iy*rm
idum=mod(ia*idum+ic,m)
ir(j)=idum
end
If you have something to say about anything in this page, please, communicate! Contact me at cschassapis@acm.org or write your thoughts into amorphous.art guestbook. But, if you download and save this page to your machine, or print this page, then, please send me an e-mail saying that you did that. Thanks.
Last updated: Aug 25, 2000