/
pwid.py
173 lines (149 loc) · 7.78 KB
/
pwid.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
"""------------------------------------------------------------------------------------------
Bayesian Affect Control Theory
Person with Dementia subclass of Agent class
Based on the Assistant subclass
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
----------------------------------------------------------------------------------------------"""
#also change to bayesact in bayesactassistant.py
from bayesact import *
class PwD(Agent):
def __init__(self,*args,**kwargs):
super(PwD, self).__init__(self,*args,**kwargs)
#x for the Assistant is a triple:
#the first is the turn (required)
#the second value
#is the planstep (0 to N-1) and the third
# is the binary awareness of the client 0/1
#dictionary defining the dynamics of the state
self.nextPsDict = kwargs.get("nextpsd",{0:([1.0],[1]),1:([1.0],[1])})
self.num_plansteps=len(self.nextPsDict)
#initial awarness distribution
self.px = [0.3,0.7]
#dynamics of behaviours as a function of integer deflections from 0-9
#defb[d] gives the probability that a person will move to the next planstep
#if they are aware, they were given a prompt and the deflection has value d
self.defb = [1.0,0.99,0.95,0.5,0.3,0.2,0.1,0.05,0.02,0.01]
#these are the numbers for a person losing awareness spontaneously, without a prompt
#defbnp[d] gives the probability that a person will move to the next planstep
#if they are aware and the deflection has value d
self.defbnp = [0.8,0.6,0.5,0.3,0.2,0.1,0.05,0.005,0.002,0.001]
self.currPlanStep=0
self.currAwareness=list(NP.random.multinomial(1,self.px)).index(1)
self.lastPrompt = None
def print_params(self):
Agent.print_params(self)
print "num plansteps: ",self.num_plansteps
print "current (initial) awareness: ",self.currAwareness
print "ps dynamics: ",self.nextPsDict
def print_state(self):
print "current awareness: ",self.currAwareness
print "current planstep: ",self.currPlanStep
print "current lastPrompt: ",self.lastPrompt
def is_done(self):
return self.currPlanStep == self.num_plansteps-1
#get the next planstep to take according to a plan-graph
#def getNextPlanStep(self):
# return min(self.num_plansteps,self.currPlanStep+1) #in general, could be next step according to some plan-graph
def getNextPlanStep(self):
newps = self.nextPsDict[self.currPlanStep][1][list(NP.random.multinomial(1,self.nextPsDict[self.currPlanStep][0])).index(1)]
return newps
#The only difference between an Assistant and an Agent
#is dynamics of x and reward
def initialise_x(self,initx):
if not initx:
initpx=self.px
initturn=State.turnnames.index("client") #hard-coded client start??
print "initpx: ",initpx, "initturn: ",initturn
else:
initpx=initx[1]
initturn=State.turnnames.index(initx[0])
#draw a sample from initx over awareness
initx=list(NP.random.multinomial(1,initpx)).index(1)
#start at zeroth planstep always
initps=0
return [initturn,initps,initx]
#called from get_next_action (bayesact.py)
def get_default_action(self,state):
if state.get_turn()=="agent":
(aab,paab)=self.get_default_predicted_action(state)
else:
(aab,paab)=self.get_null_action()
#in any case, get the propositional action (always happens)
paab = self.get_prop_action(state)
return (aab,paab)
#implement a default policy where we look at the client's current awareness
#and move to the next planstep if is above a threshold
#if prompted, the threshold will lower
#called from get_default_action (above)
#in the real implemented system, this will be getting a measurement of the current planstep from the computer vision system
#in fact, we get a measure of the client's behaviour, but we can convert this to planstep (e.g. if the behaviour is to do nothing,
#the planstep stays the same)
def get_prop_action(self,state,rollout=False,samplenum=0):
awareness = self.currAwareness
new_awareness=awareness
print "getting propositonal action for pwid:",awareness,self.lastPrompt,self.currPlanStep,self.getNextPlanStep()
if awareness == 1:
#the client is aware
if self.lastPrompt == 0:
#without a prompt, the client will do the right thing and stay aware if deflection is low
if NP.random.random() < self.defbnp[min(9,int(round(self.deflection_avg)))]: #> 0.5:
self.currPlanStep = self.getNextPlanStep()
#otherwise, loses awareness and stays at same planstep
else:
new_awareness = 0
else:
#in a high deflection situation, a prompt will likely confuse the client
if NP.random.random() > self.defb[min(9,int(round(self.deflection_avg)))]: #0.4:
new_awareness = 0
#will also confuse the client if it is not one that is appropriate
elif not self.lastPrompt in self.nextPsDict[self.currPlanStep][1]:
new_awareness = 0
#otherwise, a prompt is unlikely to mess things up
elif NP.random.random() > 0.3:
self.currPlanStep = self.getNextPlanStep()
#but if it does, the client may lose awareness, and this is deflection dependent
elif NP.random.random() > self.defb[min(9,int(round(self.deflection_avg)))]: #0.8:
new_awareness = 0
else:
#the client is not aware
if self.lastPrompt == 0:
#without a prompt
#very likely that client will do nothing,
#but might randomly gain awareness and move on
if NP.random.random() > 0.95:
self.currPlanStep = self.getNextPlanStep()
new_awareness = 1
else:
#with a low-deflection prompt, user will likely move on
# and gain awareness
nn=NP.random.random()
if self.lastPrompt in self.nextPsDict[self.currPlanStep][1] and nn < self.defb[min(9,int(round(self.deflection_avg)))]: #0.1:
print "moving on anyways at deflection ",str(self.deflection_avg)," because of random number ",nn
self.currPlanStep = self.lastPrompt
new_awareness = 1
else:
#high deflection prompt will be unlikely to have an effect
if NP.random.random() > 0.99:
new_awareness = 1
self.currAwareness = new_awareness
#this will need to be changed in the real system - we don't actually get a measure of the current planstep,
#but rather a measure of the change in planstep, but maybe we can simply convert ...
return self.currPlanStep
#this is the only way the pwid finds out what the action of the agent was: its in xobs[1]
def evalSampleXvar(self,sample,xobs):
self.lastPrompt=xobs[1]
return 1.0
#not used
def reward(self,sample,action=None):
xreward=0.0
if self.currPlanStep==self.num_plansteps-1:
xreward=1.0
return xreward