Thursday, February 5, 2009

Ch6, Ex16

We can divide M users in K groups of equal size and in UserStep, user I can ask for performance information from the 3 users belonging to his group only.

These are the changes:
%We add another variable K that
%denotes the number of groups. K should be chosen
%so that (M mod K) is 0 i.e. It should be able
%to divide M users in K groups of equal size
declare
N=10000 M=500000 T=200 K=100 %K is the number of groups

%Sets A and B to the extremes of the group in
%which I fall into
proc {GroupEdges I ?A ?B}
X1 = (K*I) div M
X2 = (K*I) mod M
in
if X2==0 then
A = (X1-1)*(M div K)+1
B = X1*(M div K)
else
A = X1*(M div K) + 1
B = (X1+1)*(M div K)
end
end

%Chose users from the same group only
proc {UserStep I}
U = Users.I
local A B in
{GroupEdges I A B}
% Ask three users(belonging to I's group only) for
% their performance information
L = {List.map [{UniformI A B} {UniformI A B}
{UniformI A B}]
fun{$ X}
(Users.X.currentSite) #
Sites.(Users.X.currentSite).performance
+ {Gauss}*{IntToFloat N}
end}
end
% Calculate the best site
MS#MP = {List.foldL L
fun {$ X1 X2} if X2.2>X1.2 then X2 else X1 end end
U.currentSite #
Sites.(U.currentSite).performance
+ {Abs {Gauss}*{IntToFloat N}}
}
in
if MS\=U.currentSite then
Sites.(U.currentSite).hits :=
Sites.(U.currentSite).hits - 1
U.currentSite := MS
Sites.MS.hits := Sites.MS.hits + 1
end
end

==================================================================
Complete Code to run word-of-mouth simulation:
%Download File.oz from book's suppliment site then
%create ozc file by running following command
%$ozc -c File.oz

%CHANGE THESE PATHS
declare FileOzrc SimResults
FileOzrc=
'/path/File.ozf'
SimResults=
'/path/wordofmouth.txt'
declare
[File]= {Module.link [FileOzrc]}

declare NewRand
local
A=333667
B=213453321
M=1000000000
in
proc {NewRand ?Rand ?Init ?Max}
X={NewCell 0}
in
proc {Init Seed} X:=Seed end
fun {Rand} X:=(A*@X+B) mod M in @X end
Max=M
end
end

declare Rand Init Max Uniform UniformI Gauss
{NewRand Rand Init Max}
local
FMax={IntToFloat Max}
in
fun {Uniform}
{IntToFloat {Rand}}/FMax
end
fun {UniformI A B}
A+{FloatToInt {Floor {Uniform}*{IntToFloat B-A+1}}}
end
end
local
TwoPi=4.0*{Float.acos 0.0}
GaussCell={NewCell nil} in
fun {Gauss}
Prev={Exchange GaussCell $ nil}
in
if Prev\=nil then Prev
else R Phi in
R={Sqrt ~2.0*{Log {Uniform}}}
Phi=TwoPi*{Uniform}
GaussCell:=R*{Cos Phi}
R*{Sin Phi}
end
end
end

declare
N=10000 M=500000 T=200
{Init 0}
{File.writeOpen SimResults}
proc {Out S}
{File.write {Value.toVirtualString S 10 10}#"\n"}
end


declare
Sites={MakeTuple sites N}
for I in 1..N do
Sites.I={Record.toDictionary
o(hits:0 performance:{IntToFloat
{UniformI 1 80000}})}
end

declare
Users={MakeTuple users M}
for I in 1..M do
S={UniformI 1 N}
in
Users.I={Record.toDictionary o(currentSite:S)}
Sites.S.hits := Sites.S.hits + 1
end

proc {UserStep I}
U = Users.I
% Ask three users for their performance information
L = {List.map [{UniformI 1 M} {UniformI 1 M} {UniformI 1 M}]
fun{$ X}
(Users.X.currentSite) #
Sites.(Users.X.currentSite).performance
+ {Gauss}*{IntToFloat N}
end}
% Calculate the best site
MS#MP = {List.foldL L
fun {$ X1 X2} if X2.2>X1.2 then X2 else X1 end end
U.currentSite #
Sites.(U.currentSite).performance
+ {Abs {Gauss}*{IntToFloat N}}
}
in
if MS\=U.currentSite then
Sites.(U.currentSite).hits :=
Sites.(U.currentSite).hits - 1
U.currentSite := MS
Sites.MS.hits := Sites.MS.hits + 1
end
end

for J in 1..N do
{Out {Record.adjoinAt {Dictionary.toRecord site Sites.J}
name J}}
end
{Out endOfRound(time:0 nonZeroSites:N)}
for I in 1..T do
X = {NewCell 0}
in
for U in 1..M do {UserStep U} end
for J in 1..N do
H=Sites.J.hits in
if H\=0 then
{Out {Record.adjoinAt
{Dictionary.toRecord site Sites.J} name J}}
X:=1+@X
end
end
{Out endOfRound(time:I nonZeroSites:@X)}
end
{Out finished}
{File.writeClose}

No comments:

Post a Comment