1 """Dynamics objects for the PWL implementation
2 @var constantDynamics: a reusable instance of dynamics for the constant value in the state vector
3 @type constantDynamics: L{PWLDynamics}
4 """
5 from teamwork.math.Keys import *
6 from teamwork.math.matrices import *
7 from teamwork.math.KeyedVector import *
8 from teamwork.math.KeyedMatrix import *
9 from teamwork.math.ProbabilityTree import *
10 import arbitraryDynamics
11
12 import time
13 from types import *
14 from xml.dom.minidom import *
15
17 """Class of objects that represent the dynamics of a specific
18 state/belief feature in the simulation
19 @ivar effects: table of roles affected, containing keys 'actor','object','other'. If the value is C{True}, then the dynamics object affects that role
20 @type effects: strS{->}bool
21 """
22
26
28 """Helper function that extracts the context used in instantiating dynamics
29 @rtype: dict
30 """
31 table = dict(action)
32 table['self'] = entity
33 for relationship,entities in entity.relationships.items():
34 if len(entities) == 1:
35 table[relationship] = entities[0]
36 return table
37
39 """Returns a new L{PWLDynamics} instance that has been specialized to apply to only the specified entity in response to the specified instantiated action. This produces a more compact decision tree where branches irrelevant to the given entity and action have been pruned away.
40 @type action: dict
41 @rtype: L{PWLDynamics}
42 """
43 table = self.extractTable(entity,action)
44 args = copy.copy(self.args)
45 args['tree'] = self.getTree().instantiate(table)
46 args['tree'].prune()
47 return self.__class__(args)
48
51 """Performs both L{instantiate} and L{apply} in a single call, but does a minimal instantiation, by ignoring branches that are irrelevant in the given state
52 @param entity: the entity performing the update
53 @type entity: L{Agent<teamwork.agent.Agent.Agent>}
54 @param action: the action being applied
55 @type action: L{Action<teamwork.action.PsychActions.Action>}
56 @param state: the current state of the world
57 @type state: L{Distribution}(L{KeyedVector})
58 @rtype: L{Distribution}(L{KeyedMatrix})
59 """
60 if not table:
61 table = self.extractTable(entity,action)
62 if tree is None:
63 tree = self.getTree()
64 if tree.isLeaf():
65 return tree.getValue().instantiate(table)
66 else:
67 falseTree,trueTree = tree.getValue()
68 value = True
69 for plane in tree.split:
70 result = plane.instantiate(table)
71 if isinstance(result,plane.__class__):
72 value = result.test(state)
73 elif result < 0:
74 value = False
75 if not value:
76 break
77 if value:
78 return self.instantiateAndApply(state,table=table,
79 tree=trueTree)
80 else:
81 return self.instantiateAndApply(state,table=table,
82 tree=falseTree)
83
85 """
86 @return: the decision tree for this dynamics object
87 @rtype: L{ProbabilityTree}"""
88 return self.args['tree']
89
90 - def apply(self,state,debug=0):
97
99 """Merges the new dynamics into this one by calling L{KeyedMatrix.merge} on the leaves of the decision trees
100 @type other: L{PWLDynamics}
101 """
102 myTree = self.getTree()
103 yrTree = other.getTree()
104 newTree = myTree.merge(yrTree,KeyedMatrix.merge)
105 return self.__class__({'tree':newTree})
106
108 """
109 @param old: the current name of the entity
110 @param new: the new name of the entity
111 @type old,new: str
112 """
113 if tree is None:
114 tree = self.getTree()
115 if not tree.isLeaf():
116 for index in range(len(tree.split)):
117
118 plane = tree.split[index]
119 newKeys = []
120 for key in plane.weights.specialKeys:
121 newKey = {}
122 newKey.update(key)
123 if isinstance(key,StateKey) and key['entity'] == old:
124 newKey['entity'] = new
125 elif isinstance(key,ClassKey) and key['value'] == old:
126 newKey['value'] = new
127 newKeys.append(newKey)
128 newPlane = plane.weights.__class__(keys=newKeys)
129 tree.split[index] = KeyedPlane(newPlane,plane.threshold)
130
131 for child in tree.children():
132 self.renameEntity(old,new,child)
133
139
145
147 doc = Document()
148 root = doc.createElement('dynamic')
149 doc.appendChild(root)
150 tree = self.getTree()
151 root.appendChild(tree.__xml__().documentElement)
152 return doc
153
154 - def parse(self,element):
164
167
176
187
189 """
190 @return: a dynamics object with an identity matrix over the constant value
191 @rtype: L{KeyedMatrix}
192 """
193 row = KeyedVector({keyConstant:1.})
194 matrix = KeyedMatrix()
195 matrix[keyConstant] = row
196 return matrix
197
198 constantDynamics = ConstantDynamics()
199
200 if __name__ == '__main__':
201 dynamics = PWLDynamics()
202 doc = parse('dynamics.xml')
203 dynamics.parse(doc.documentElement)
204
205 blah
206 from teamwork.math.KeyedTree import *
207
208
209 keys = {'myPower':keyMyValue,
210 'constant': keyConstant}
211
212 keys['actorPower'] = `{'entity':'actor',
213 'feature':'militarypower',
214 'total':1}`
215
216 keys['objectPower'] = `{'entity':'object',
217 'feature':'militarypower',
218 'total':1}`
219
220 keys['amActor'] = `{'entity':'actor',
221 'relationship':'identity'}`
222
223 keys['amObject'] = `{'entity':'object',
224 'relationship':'identity'}`
225
226
227 weights = {keys['myPower']:1.}
228 unchangedTree = createNodeTree(KeyedVector(weights))
229
230
231 weights = {keys['actorPower']: -1.,
232 keys['objectPower']: 1.}
233 plane = KeyedPlane(KeyedVector(weights),0.)
234
235
236 weights = {keys['myPower']: 1.,
237 keys['actorPower']: -.1,
238 keys['objectPower']: .1,
239 keys['constant']: -.05}
240 objWeaker = createNodeTree(KeyedVector(weights))
241
242
243 weights= {keys['myPower']: 1.,
244 keys['constant']: -.01}
245 objStronger = createNodeTree(KeyedVector(weights))
246
247
248 objectTree = createBranchTree(plane,objWeaker,objStronger)
249
250
251 weights = {keys['amObject']: 1.}
252 notActorTree = createBranchTree(KeyedPlane(KeyedVector(weights),0.5),
253 unchangedTree,objectTree)
254
255
256 weights = {keys['myPower']: 1.,
257 keys['actorPower']: .1,
258 keys['objectPower']: -.1,
259 keys['constant']: .02}
260 actorMuchWeakerTree = createNodeTree(KeyedVector(weights))
261
262
263 weights = {keys['myPower']: 1.,
264 keys['constant']: -.01}
265 actorWeakerTree = createNodeTree(KeyedVector(weights))
266
267
268 weights = {keys['actorPower']: -1.,
269 keys['objectPower']: 1.}
270 actorTree = createBranchTree(KeyedPlane(KeyedVector(weights),0.2),
271 actorWeakerTree,actorMuchWeakerTree)
272
273
274 weights = {keys['amActor']: 1.}
275 tree = createBranchTree(KeyedPlane(KeyedVector(weights),0.5),
276 notActorTree,actorTree)
277
278 dynamics = PWLDynamics({'tree':tree})
279
280 from teamwork.utils.PsychUtils import load
281 from teamwork.action.PsychActions import PsychAction
282
283 print 'Loading...'
284 entities = load('/home/pynadath/python/teamwork/examples/MRE/mre.scn')
285 print 'done.'
286 feature = 'firepower'
287 followers = entities['Followers']
288 aides = entities['Aides']
289 print aides.getState(feature)
290 action = followers.actionClass({'actor':followers,
291 'type':'demonstrate',
292 'object':aides})
293 entities.performAct([action])
294 print aides.getState(feature)
295