forked from alihussainxyz/bayesact
/
bayesactsim.py
496 lines (381 loc) · 22.2 KB
/
bayesactsim.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
"""------------------------------------------------------------------------------------------
Bayesian Affect Control Theory
Simulator Test Code
Author: Jesse Hoey jhoey@cs.uwaterloo.ca http://www.cs.uwaterloo.ca/~jhoey
September 2013
Use for research purposes only.
Please do not re-distribute without written permission from the author
Any commerical uses strictly forbidden.
Code is provided without any guarantees.
Research sponsored by the Natural Sciences and Engineering Council of Canada (NSERC).
use python2.6
see README for details
----------------------------------------------------------------------------------------------"""
from bayesact import *
import getopt
import cProfile
import sys
import threading
sys.path.append("./gui/")
from cEnum import eTurn
class cBayesactSim(object):
def __init__(self, argv):
#NP.set_printoptions(precision=5)
#NP.set_printoptions(suppress=True)
NP.set_printoptions(linewidth=10000)
#get some key parameters from the command line
self.num_samples=1000
#agent knowledge of client id:
#0 : nothing
#1 : one of a selection of num_confusers+1 randoms
#2 : exactly
#3 : same as 0 but also agent does not know its own id
self.agent_knowledge=0
#client knowledge of agent id:
self.client_knowledge=0
self.agent_id_label=""
self.client_id_label=""
self.agent_gender="male"
self.client_gender="male"
#used only for label extraction if the user enters a label they want to use for simulations
self.identities_filename="fidentities.dat"
self.behaviours_filenmae="fbehaviours.dat" #not used
#uniform draws - if true will draw client IDs uniformly over -4.3,4.3.
#If false, drawn from Normal distribution of the client ids in the database
self.uniform_draws=False
self.gamma_value=1.0
#if>0, add a small amount of roughening noise to the client identities
self.roughening_noise=-1.0
#environment noise: this will corrupt the transmission of the actions with zero-mean Gaussian noise with this variance
self.env_noise=0.0
self.max_horizon=50
self.num_trials=20
self.num_experiments=10
self.get_full_id_rate=20
self.learn_init_turn="agent"
self.simul_init_turn="client"
self.verbose=False
self.helpstring="Bayesact simulator (2 agents) usage:\n bayesactsim.py\n\t -t <number of trials (default 20)>\n\t -x <number of experiments per trial (default 10)>\n\t -n <number of samples (default 1000)>\n\t -c <client knowledge (0,1,2) (default 2)>\n\t -a <agent knowledge (0,1,2) (Default 0)>\n\t -u (if specified - do uniform draws)\n\t -d <max horizon - default 50>\n\t -r <roughening noise: default n^(-1/3) - to use no roughening ('full' method), specify 0>\n\t -e <environment noise (default 0.0)>\n\t -g <gamma_value (default 1.0)>\n\t -i <agent id label: default randomly chosen>\n\t -j <client id label: default randomly chosen>\n\t -k <agent gender (default: male) - only works if agent_id is specified with -i>\n\t -l (client gender (default: male) only works if client_id is specified with -j>"
try:
opts, args = getopt.getopt(argv[1:],"huvon:t:x:a:c:d:r:e:g:i:j:k:l:",["help","n=","t=","x=","c=","a=","u=","d=","r=","e=","g=","i=","j=","k=","l="])
except getopt.GetoptError:
print self.helpstring
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print self.helpstring
sys.exit()
elif opt == '-v':
self.verbose = True
elif opt in ("-n", "--numsamples"):
self.num_samples = int(arg)
elif opt in ("-t", "--numtrials"):
self.num_trials = int(arg)
elif opt in ("-x", "--numexperiments"):
self.num_experiments = int(arg)
elif opt in ("-c", "--clientknowledge"):
self.client_knowledge = int(arg)
elif opt in ("-a", "--agentknowledge"):
self.agent_knowledge = int(arg)
elif opt in ("-d", "--horizon"):
self.max_horizon = int(arg)
elif opt in ("-u", "--uniformdraws"):
self.uniform_draws=True
elif opt in ("-r", "--roughen"):
self.roughening_noise=float(arg)
elif opt in ("-e", "--enoise"):
self.env_noise=float(arg)
elif opt in ("-g", "--gamma"):
self.gamma_value=float(arg)
elif opt in ("-i", "--agentid"):
self.agent_id_label=arg
elif opt in ("-j", "--clientid"):
self.client_id_label=arg
elif opt in ("-k", "--agentgender"):
self.agent_gender=arg
elif opt in ("-l", "--clientgender"):
self.client_gender=arg
if self.roughening_noise<0.0:
#default
self.roughening_noise=self.num_samples**(-1.0/3.0)
#-----------------------------------------------------------------------------------------------------------------------------
#simulation start
#-----------------------------------------------------------------------------------------------------------------------------
self.num_agent_confusers=3
self.num_client_confusers=3
#to roughen, not use proposal - for any unknown identity
self.learn_agent_rough=0.0
self.learn_client_rough=0.0
if (self.agent_knowledge==0 or self.agent_knowledge==3) and self.roughening_noise>0:
self.learn_client_rough=self.roughening_noise
if self.agent_knowledge==3:
self.learn_agent_rough=self.roughening_noise
self.simul_agent_rough=0.0
self.simul_client_rough=0.0
if (self.client_knowledge==0 or self.client_knowledge==3) and self.roughening_noise>0:
self.simul_client_rough=self.roughening_noise
if self.client_knowledge==3:
self.simul_agent_rough=self.roughening_noise
self.simul_verbose=self.verbose
self.learn_verbose=self.verbose
self.meanlearndefl =[]
self.meansimuldefl = []
self.meanlearnddvo = []
self.meansimulddvo = []
#the mean and covariance of IDs for male agents as taken from the databases
#should do this automatically in python based on actual genders of client/agent....
self.mean_ids=NP.array([0.40760,0.40548,0.45564])
self.cov_ids=NP.array([[2.10735,1.01121, 0.48442],[1.01121,1.22836,0.55593],[0.48442,0.55593,0.77040]])
# Does this do anything?
self.randseeds=[373044980,27171222,156288614]
#to make it consistent across different trials
#NP.random.seed(1)
self.plotter = None
self.threadEvent = None
self.waiting = True
self.terminateFlag = False
def startBayesactSim(self):
self.waiting = False
print "num trials: ",self.num_trials
print "num experiments: ",self.num_experiments
print "num samples: ",self.num_samples
print "client knowledge: ",self.client_knowledge
print "agent knowledge: ",self.agent_knowledge
print "uniform draws: ",self.uniform_draws
print "max horizon: ",self.max_horizon
print "roughening noise: ",self.roughening_noise
print "environment noise: ",self.env_noise
print "gamma value: ",self.gamma_value
print "client id label: ",self.client_id_label
print "agent id label: ",self.agent_id_label
print "agent gender: ",self.agent_gender
print "client gender: ",self.client_gender
for trial in range(self.num_trials):
#this was moved from below the client_id agent_id generation
#on March 22nd at 11:52am
#for repeatability
rseed = NP.random.randint(0,382948932)
#rseed=randseeds[trial]
#rseed = 373044980 #lady and shoplifter
#rseed = 156288614 #hero and insider
#rseed=60890393
#rseed=120534679
print "random seeed is : ",rseed
NP.random.seed(rseed)
#the actual (true) ids drawn from the distribution over ids
if self.client_id_label=="":
client_id = NP.asarray([NP.random.multivariate_normal(self.mean_ids,self.cov_ids)]).transpose()
else:
client_id = NP.asarray([getIdentity(self.identities_filename,self.client_id_label,self.client_gender)]).transpose()
if self.agent_id_label=="":
agent_id = NP.asarray([NP.random.multivariate_normal(self.mean_ids,self.cov_ids)]).transpose()
else:
agent_id = NP.asarray([getIdentity(self.identities_filename,self.agent_id_label,self.agent_gender)]).transpose()
print "agent id: ",agent_id
print "client id: ",client_id
#these are uniformly distributed which will generate waaay too many extreme ids
#client_id = NP.dot(NP.random.random([3,1]),8.6)-4.3
#agent_id = NP.dot(NP.random.random([3,1]),8.6)-4.3
#simulation agent knows client and agent ids (it is the client)
(learn_tau_init,learn_prop_init,learn_beta_client_init,learn_beta_agent_init)=init_id(self.agent_knowledge,agent_id,client_id,self.mean_ids,self.num_agent_confusers)
(simul_tau_init,simul_prop_init,simul_beta_client_init,simul_beta_agent_init)=init_id(self.client_knowledge,client_id,agent_id,self.mean_ids,self.num_client_confusers)
learn_initx=self.learn_init_turn
simul_initx=self.simul_init_turn
#this version has the agents more flexible about their identities....
#simul_agent=TutoringAgent(N=num_samples,alpha_value=1.0,initx=learn_initx,goalx=learn_goalx,gamma_value=1.0,beta_value_agent=0.05,beta_value_client=0.05,beta_value_client_init=simul_beta_init)
#learn_agent=TutoringAgent(N=num_samples,alpha_value=1.0,initx=simul_initx,goalx=simul_goalx,gamma_value=1.0,beta_value_agent=0.05,beta_value_client=0.05,beta_value_client_init=learn_beta_init)
simul_agent=Agent(N=self.num_samples,alpha_value=0.1,gamma_value=self.gamma_value,beta_value_agent=0.005,beta_value_client=0.005,beta_value_client_init=simul_beta_client_init,beta_value_agent_init=simul_beta_agent_init,agent_rough=self.simul_agent_rough,client_rough=self.simul_client_rough,identities_file=self.identities_filename,init_turn=self.learn_init_turn)
learn_agent=Agent(N=self.num_samples,alpha_value=0.1,gamma_value=self.gamma_value,beta_value_agent=0.005,beta_value_client=0.005,beta_value_client_init=learn_beta_client_init,beta_value_agent_init=learn_beta_agent_init,agent_rough=self.learn_agent_rough,client_rough=self.learn_client_rough,identities_file=self.identities_filename,init_turn=self.simul_init_turn)
print 100*"$"
print "trial number: ",trial
print 100*"$"
print 10*"-","simulation agent parameters: "
simul_agent.print_params()
print "simulator init tau: ",simul_tau_init
print "simulator prop init: ",simul_prop_init
print "simulator beta client init: ",simul_beta_client_init
print "simulator beta agent init: ",simul_beta_agent_init
print 10*"-","learning agent parameters: "
learn_agent.print_params()
print "learner init tau: ",learn_tau_init
print "learner prop init: ",learn_prop_init
print "learner beta client init: ",learn_beta_client_init
print "learner beta agent init: ",learn_beta_agent_init
learn_ddvo=[]
learn_defl=[]
simul_ddvo=[]
simul_defl=[]
for exper in range(self.num_experiments):
print 100*"$"
print "experiment number: ",exper
print 100*"$"
learn_avgs=learn_agent.initialise_array(learn_tau_init,learn_prop_init,learn_initx)
simul_avgs=simul_agent.initialise_array(simul_tau_init,simul_prop_init,simul_initx)
#To plot initial data
if (None != self.plotter):
#to send the initial sentiments to the plotter
learn_agent.sendSamplesToPlotter(learn_agent.samples,self.plotter,eTurn.learner)
simul_agent.sendSamplesToPlotter(simul_agent.samples,self.plotter,eTurn.simulator)
self.plotter.plot()
if (None != self.threadEvent):
# For some reason, while a thread is waiting, the program will say it is leaking memory sometimes
self.waiting = True
self.threadEvent.wait()
self.waiting = False
if (self.terminateFlag):
self.plotter.clearPlots()
self.waiting = True
return
print "simulator average: "
simul_avgs.print_val()
print "learner average f: "
learn_avgs.print_val()
learn_turn="agent"
simul_turn="client"
for iter in range(self.max_horizon):
print "learner turn: ",learn_turn
print "simulator turn: ",simul_turn
observ=[]
print 10*"-d","iter ",iter,80*"-"
#In fact, both agents should update on every turn now, so
#we should be able to always call get_next_action for both agents here?
#like this:
(learn_aab,learn_paab)=learn_agent.get_next_action(learn_avgs)
print "agent action/client observ: ",learn_aab
simul_observ=learn_aab
(simul_aab,simul_paab)=simul_agent.get_next_action(simul_avgs)
print "client action/agent observ: ",simul_aab
learn_observ=simul_aab
#add environmental noise here if it is being used
if self.env_noise>0.0:
learn_observ=map(lambda fv: NP.random.normal(fv,self.env_noise), learn_observ)
simul_observ=map(lambda fv: NP.random.normal(fv,self.env_noise), simul_observ)
print "learn observ: ",learn_observ
print "simul observ: ",simul_observ
learn_xobserv=[State.turnnames.index(invert_turn(learn_turn))]
simul_xobserv=[State.turnnames.index(invert_turn(simul_turn))]
#learn_avgs=cProfile.run('learn_agent.propagate_forward(learn_turn,learn_aab,learn_observ,verb=learn_verbose)')
learn_avgs=learn_agent.propagate_forward(learn_aab,learn_observ,learn_xobserv,verb=self.learn_verbose,plotter=self.plotter,agent=eTurn.learner)
simul_avgs=simul_agent.propagate_forward(simul_aab,simul_observ,simul_xobserv,verb=self.simul_verbose,plotter=self.plotter,agent=eTurn.simulator)
print "learner f is: "
learn_avgs.print_val()
print "simulator f is: "
simul_avgs.print_val()
#I think these should be based on fundamentals, not transients
(aid,cid)=learn_agent.get_avg_ids(learn_avgs.f)
print "learner agent id:",aid
print "learner client id:",cid
(aid,cid)=simul_agent.get_avg_ids(simul_avgs.f)
print "simul agent id:",aid
print "simul client id:",cid
if self.get_full_id_rate>0 and (iter+1)%self.get_full_id_rate==0:
(cnt_ags,cnt_cls)=learn_agent.get_all_ids()
print "top ten ids for agent (learner perspective):"
print cnt_ags[0:10]
print "top ten ids for client (learner perspective):"
print cnt_cls[0:10]
(cnt_ags,cnt_cls)=simul_agent.get_all_ids()
print "top ten ids for agent (simulator perspective):"
print cnt_ags[0:10]
print "top ten ids for client (simulator perspective):"
print cnt_cls[0:10]
print "current deflection of averages: ",learn_agent.deflection_avg
learn_d=learn_agent.compute_deflection()
print "current deflection (learner perspective): ",learn_d
simul_d=simul_agent.compute_deflection()
print "current deflection (simulator perspective): ",simul_d
if learn_turn=="client":
learn_turn="agent"
simul_turn="client"
else:
learn_turn="client"
simul_turn="agent"
#To plot data
if (None != self.plotter):
self.plotter.plot()
if (None != self.threadEvent):
self.waiting = True
self.threadEvent.wait()
self.waiting = False
if (self.terminateFlag):
self.plotter.clearPlots()
self.waiting = True
return
print 10*"+","EXPERIMENT ",exper," RESULTS",10*"+"
print "final deflection (learner): ",learn_d
learn_defl.append(learn_d)
print "final learned client id: "
print learn_avgs.f[6:9]
print "actual client id: "
print client_id.transpose()
dvo= client_id.transpose()-learn_avgs.f[6:9]
#changed from sqrt(dot(...)) here on April 4th, 2013
learn_ddvo.append(NP.dot(dvo,dvo.transpose()))
print "sum of squared differences between agent learned and client true id:"
print learn_ddvo[-1]
print "final deflection (simulator): ",simul_d
simul_defl.append(simul_d)
print "final learned agent id: "
print simul_avgs.f[6:9]
print "actual agent id: "
print agent_id.transpose()
dvo = agent_id.transpose()-simul_avgs.f[6:9]
#changed from sqrt(dot(...)) here on April 4th, 2013
simul_ddvo.append(NP.dot(dvo,dvo.transpose()))
print "sum of squared differences between simul learned and agent true id:"
print simul_ddvo[-1]
print 30*"+"
self.meanlearndefl.append(NP.mean(learn_defl))
self.meansimuldefl.append(NP.mean(simul_defl))
self.meanlearnddvo.append(NP.mean(learn_ddvo))
self.meansimulddvo.append(NP.mean(simul_ddvo))
stdlearndefl = NP.std(learn_defl)
stdsimuldefl = NP.std(simul_defl)
stdlearnddvo = NP.std(learn_ddvo)
stdsimulddvo = NP.std(simul_ddvo)
print 10*"*","TRIAL ",trial," RESULTS",10*"*"
print "mean deflection (learner): ",self.meanlearndefl[-1]," +/- ",stdlearndefl
print "mean deflection (simulator): ",self.meansimuldefl[-1]," +/- ",stdsimuldefl
print "mean difference in id sentiments (learner): ",self.meanlearnddvo[-1]," +/- ",stdlearnddvo
print "mean differnece in id sentiments (simulator): ",self.meansimulddvo[-1]," +/- ",stdsimulddvo
print 30*"*"
stdlearndefl = NP.std(self.meanlearndefl)
stdsimuldefl = NP.std(self.meansimuldefl)
stdlearnddvo = NP.std(self.meanlearnddvo)
stdsimulddvo = NP.std(self.meansimulddvo)
print 10*"*","OVERALL RESULTS",10*"*"
print "mean deflection (learner): ",NP.mean(self.meanlearndefl)," +/- ",stdlearndefl
print "mean deflection (simulator): ",NP.mean(self.meansimuldefl)," +/- ",stdsimuldefl
print "mean difference in id sentiments (learner): ",NP.mean(self.meanlearnddvo)," +/- ",stdlearnddvo
print "mean differnece in id sentiments (simulator): ",NP.mean(self.meansimulddvo)," +/- ",stdsimulddvo
print 30*"*"
if (None != self.plotter and None != self.plotter.m_PlotFrame):
self.plotter.m_PlotFrame.Close()
def main(argv):
# This is required as plotting with wx does not allow wx.App.MainLoop to be started as a thread
# I'm going to use the -o and -v option it can be changed anytime
plot = False
oBayesactSim = cBayesactSim(argv)
# A hack, should probably be fixed later
helpstring="Bayesact simulator (2 agents) usage:\n bayesactsim.py\n\t -t <number of trials (default 20)>\n\t -x <number of experiments per trial (default 10)>\n\t -n <number of samples (default 1000)>\n\t -c <client knowledge (0,1,2) (default 2)>\n\t -a <agent knowledge (0,1,2) (Default 0)>\n\t -u (if specified - do uniform draws)\n\t -d <max horizon - default 50>\n\t -r <roughening noise: default n^(-1/3) - to use no roughening ('full' method), specify 0>\n\t -e <environment noise (default 0.0)>\n\t -g <gamma_value (default 1.0)>\n\t -i <agent id label: default randomly chosen>\n\t -j <client id label: default randomly chosen>\n\t -k <agent gender (default: male) - only works if agent_id is specified with -i>\n\t -l (client gender (default: male) only works if client_id is specified with -j>"
try:
opts, args = getopt.getopt(argv[1:],"huvon:t:x:a:c:d:r:e:g:i:j:k:l:",["help","n=","t=","x=","c=","a=","u=","d=","r=","e=","g=","i=","j=","k=","l="])
except getopt.GetoptError:
print helpstring
sys.exit(2)
for opt, arg in opts:
if "-o" == opt:
plot = True
if (False == plot):
oBayesactSim.startBayesactSim()
else:
from cPlotBayesactThread import cPlotBayesactThread
plotter = cPlotBayesactThread()
plotPanel = plotter.initFrame()
plotter.initPlotBayesactSim(plotPanel)
oBayesactSim.plotter = plotter
bayesactSimThread = threading.Thread(target=oBayesactSim.startBayesactSim)
plotter.setThread(bayesactSimThread)
plotter.startApp()
if __name__ == "__main__":
main(sys.argv)