1 import copy
2 from types import *
3
4 from PsychAgents import *
5 from teamwork.math.matrices import epsilon
6
8 """A utility class that supports sequential turns by a group of agents. The order is determined by the ordering methods on the component agent classes.
9 @warning: sequentiality is required, so don't try having multiple agents act at the same time.
10 """
12 """Creates a new order vector. Orders the agents according to the comparison method on the member agents
13 @param entities: the ordered list of entities to use (if omitted, defaults to the sorted list of active members)
14 @type entities: L{teamwork.agent.Agent.Agent}[]
15 @return: the turn state vector suitable for the initial state of the simulation
16 @rtype: L{KeyedVector}
17 """
18 self._turnDynamics.clear()
19 if entities is None:
20 entities = self.activeMembers()
21 entities.sort()
22 order = KeyedVector()
23 self.positions = {}
24 for index in range(len(entities)):
25 agent = entities[index]
26 value = 1./pow(2,index) * self.threshold + epsilon
27 self.positions[agent.name] = value
28 order[StateKey({'entity':agent.name,
29 'feature':self.turnFeature})] = value
30 order[keyConstant] = 1.
31 order.freeze()
32 return order
33
35 """Computes the change in turn due to the specified actions
36 @param actions: the actions being performed, indexed by actor name
37 @type actions: C{dict:strS{->}L{teamwork.action.PsychActions.Action}[]}
38 @return: a decision tree representing the changes to the standing turn order vector based on the specified actions
39 @rtype: L{KeyedTree}
40 """
41 assert(len(actions) == 1)
42
43 unchangedMatrix = KeyedMatrix()
44 for key in self.order.keys():
45 row = KeyedVector()
46 row[key] = 1.
47 unchangedMatrix[key] = row
48 row = KeyedVector()
49 row[keyConstant] = 1.
50 unchangedMatrix[keyConstant] = row
51
52 if len(self) == 0:
53 tree = KeyedTree()
54 tree.makeLeaf(unchangedMatrix)
55 return tree
56 actor = actions.keys()[0]
57
58 resetWeights = KeyedVector()
59 for key in self.order.keys():
60 if isinstance(key,StateKey) and not actions.has_key(key['entity']):
61 resetWeights[key] = 1.
62 resetPlane = KeyedPlane(resetWeights,0.0001)
63
64 updateMatrix = KeyedMatrix()
65 for key in self.order.keys():
66 row = KeyedVector()
67 if isinstance(key,StateKey):
68 if actions.has_key(key['entity']):
69
70 value = pow(2,len(self.activeMembers())-1)
71 row[keyConstant] = 1./value*self.threshold + epsilon
72 else:
73
74 row[key] = 2.
75 else:
76
77 row[key] = 1.
78 updateMatrix[key] = row
79
80 alreadyActed = ThresholdRow(keys=[{'entity':actor,
81 'feature':self.turnFeature}])
82 updateTree = KeyedTree()
83 updateTree.branch(KeyedPlane(alreadyActed,0.),
84 unchangedMatrix,updateMatrix)
85
86 resetMatrix = KeyedMatrix()
87 for key in self.order.keys():
88 row = KeyedVector()
89 if isinstance(key,StateKey):
90 row[keyConstant] = self.positions[key['entity']]
91 else:
92 row[keyConstant] = 1.
93 resetMatrix[key] = row
94
95 tree = KeyedTree()
96 tree.branch(resetPlane,resetMatrix,updateTree)
97 return tree
98