1 """Class for applying the defaults in a L{GenericModel<Generic.GenericModel>} instance to an instantiated L{Stereotyper<stereotypes.Stereotyper>}
2 @author: David V. Pynadath <pynadath@isi.edu>
3 """
4 import copy
5
6 import string
7 import time
8 from types import *
9
10 from teamwork.math.Interval import *
11 from teamwork.agent.stereotypes import *
12 from teamwork.policy.policyTable import PolicyTable
13 from teamwork.agent.Generic import *
14
15 classHierarchy = None
16
18 """Generic entity class with general-purpose methods for
19 instantiating an entity, using class-specific defaults"""
20
21 copyCount = 0.0
22
23 factors = []
24
30
32 """Sets the hierarchy of L{GenericModel} instances that this agent uses for its default values
33 @type classes: L{GenericSociety<teamwork.multiagent.GenericSociety.GenericSociety>}
34 """
35 self.hierarchy = classes
36
38 """Applies the generic model in the society of the given class name"""
39 self.type = className
40 self.setHierarchy(hierarchy)
41
42 self.classes = []
43 toExpand = [self.type]
44 while len(toExpand) > 0:
45 for className in toExpand[:]:
46 toExpand.remove(className)
47 self.classes.append(className)
48 try:
49 toExpand += self.hierarchy[className].getParents()
50 except KeyError:
51 pass
52
53 self.model = None
54 try:
55 self.models = copyModels(self.getDefault('models'))
56 except KeyError:
57 self.models = {}
58
59 self.initActions(self.getDefault('actions'))
60
61 self.initState()
62
63
64
65 self.omega.update(self.getDefault('omega'))
66 self.observations = copy.deepcopy(self.getDefault('observations'))
67 try:
68
69 self.attributes['imageName'] = self.getDefault('imageName')
70 except KeyError:
71
72 pass
73
75 """Finds the most specific class defaults for the specified
76 feature; raises KeyError exception if no default exists"""
77 if self.hierarchy is None:
78
79 raise KeyError,'%s has no feature %s' % (self.name,feature)
80 result = None
81 last = None
82 for cls in self.classes:
83
84 try:
85 result = self.hierarchy[cls].__dict__[feature]
86 except KeyError:
87
88 try:
89 result = self.hierarchy[cls].attributes[feature]
90 except KeyError:
91
92 continue
93 if feature in ['models','dynamics']:
94
95 if len(result) > 0:
96 break
97 elif feature == 'imageName':
98 if result is not None:
99 break
100 elif feature == 'actions':
101 if result.branchType:
102
103 break
104 elif last is None:
105 last = result
106 else:
107
108 last = copy.deepcopy(last)
109 for option in result.extras:
110 last.directAdd(option)
111 result = last
112 elif feature == 'depth':
113
114 if last is None:
115 last = result
116 else:
117 last = min(last,result)
118 result = last
119 else:
120
121 break
122 if result is None:
123 if feature == 'actions':
124 pass
125 else:
126 raise KeyError,'%s has no feature %s' % (self.name,feature)
127 return result
128
130 """Instantiates all of the state defaults relevant to this entity"""
131 for cls in self.classes:
132 try:
133 featureList = self.hierarchy[cls].getStateFeatures()
134 except KeyError:
135 featureList = []
136 for feature in featureList:
137 if not feature in self.getStateFeatures():
138 value = self.hierarchy[cls].getState(feature)
139 self.setState(feature,value)
140 self.setModel(None)
141
143 """Initializes the actions to follow the form of the given L{DecisionSpace<teamwork.action.DecisionSpace.DecisionSpace>}"""
144 self.actions = decisions.__class__()
145 self.actions.illegal.update(decisions.illegal)
146 self._initActions(self.actions,decisions)
147
148 for option in decisions.extras:
149 if not self.actions.illegal.has_key(str(option)):
150 for action in option:
151 if action['object'] is not None:
152 break
153 else:
154 self.actions.directAdd(copy.deepcopy(option))
155
157 while isinstance(decisions,DecisionSpace):
158 mySpace.key = decisions.key
159 for value in decisions.values:
160 if value['type'] == 'literal':
161 mySpace.append(value['value'])
162 elif value['type'] == 'decision':
163 newDecisions = value['value'].__class__()
164 self._initActions(newDecisions,value['value'])
165 mySpace.append(newDecisions)
166 if isinstance(decisions.base,DecisionSpace):
167 mySpace.base = decisions.base.__class__()
168 mySpace = mySpace.base
169 else:
170 mySpace.base = copy.deepcopy(decisions.base)
171 decisions = decisions.base
172
174 """Instantiates the relationships of this entity regarding the
175 provided list of entities"""
176
177 try:
178 relations = self.getDefault('relationships')
179 except KeyError:
180 relations = {}
181 for relation,targetList in relations.items():
182 if not self.relationships.has_key(relation):
183
184
185 self.relationships[relation] = []
186 for entity in entityList:
187
188
189 for target in targetList:
190 if entity.name != self.name and \
191 target in entity.classes:
192 self.relationships[relation].append(entity.name)
193 if relation == '_commandee':
194 for name in self.relationships[relation]:
195 for entity in entityList:
196 if entity.name == name:
197 break
198 else:
199 raise NameError,'Missing commandee: %s' % (name)
200 if len(self.relationships[relation]) == 0:
201 del self.relationships[relation]
202
217
262
264 """Sets the beliefs that this entity has about the given entity,
265 following the various defaults"""
266
267 relations = []
268 for relation in self.relationships.keys():
269 if entity.name in self.relationships[relation]:
270 relations.append(relation)
271
272 myClassList = self.classes[:]
273 myClassList.reverse()
274 yourClassList = entity.classes[:]
275 yourClassList.reverse()
276 for default in myClassList:
277 beliefs = {}
278
279 for cls in yourClassList:
280
281 try:
282 beliefs = self.hierarchy[default].getEntity(cls)
283 except KeyError:
284
285
286 continue
287
288 entity.applyBeliefs(beliefs)
289
290 for relation in relations:
291 try:
292 beliefs = self.hierarchy[default].getEntity(relation)
293 except KeyError:
294 continue
295
296 entity.applyBeliefs(beliefs)
297 if entity.name == self.name:
298 try:
299 beliefs = self.hierarchy[default].getEntity('self')
300
301 entity.applyBeliefs(beliefs)
302 except KeyError:
303 pass
304 return entity
305
311
313 """Sets world dynamics of this entity in response to all of the possible actions in the given multiagent system
314 @param entities: the agents whose actions are relevant
315 @type entities: strS{->}Agent
316 """
317 for cls in self.classes:
318 for feature,actDict in self.hierarchy[cls].dynamics.items():
319 if not self.dynamics.has_key(feature):
320 self.dynamics[feature] = {}
321 types = filter(lambda a:not self.dynamics[feature].has_key(a),
322 actDict.keys())
323 for actType in types:
324 dynamics = actDict[actType]
325 if actType is None:
326
327
328 self.dynamics[feature][actType] = cls
329 else:
330 found = False
331 for agent in entities.values():
332 for option in agent.actions.getOptions():
333 for action in option:
334 if action['type'] == actType:
335
336
337 self.dynamics[feature][actType] = cls
338 found = True
339 break
340 if found:
341 break
342 if found:
343 break
344
346 """Sets the goal weights of this entity based on class
347 defaults. The resulting goals depend on the group of entities
348 passed in as the optional argument."""
349 goals = []
350
351
352 keys = []
353 for cls in self.classes:
354 for goal in self.hierarchy[cls].getGoals():
355 goalList = self.instantiateGoal(goal,entities)
356 for subGoal in goalList:
357 key = str(subGoal)
358 try:
359 index = keys.index(key)
360 goals[index].weight += subGoal.weight
361 except ValueError:
362 keys.append(key)
363 goals.append(subGoal)
364 if len(goals) > 0:
365
366 self.setGoals(goals)
367
369 """Instantiates generic observation function with given entity list"""
370 for entry in self.observations:
371
372 print entry
373 print len(entities)
374
376 """Specializes the given goal to the given scenario context
377
378 Returns a list of goals created by instantiating the given
379 goal template (i.e., it refers to classes or relationships)
380 with respect to the provided list of entities and current
381 relationships"""
382 entityList = self.instantiateList(goal.entity,[[]],entities)
383 goals = []
384 for refList in entityList:
385 newGoal = goal.__class__(refList,goal.direction,
386 goal.type,goal.key)
387 newGoal.weight = goal.weight
388 goals.append(newGoal)
389 return goals
390
392 """
393 @param nameList: list of names to be instantiated
394 @type nameList: C{str[]}
395 @param refList: partial results of name lists instantiation so far
396 @type refList: C{str[][]}
397 @param entities: the entities from which to draw instances from
398 @type entities: C{L{Agent}[]}
399 @return: a list of entity lists appropriate for recursive beliefs with all name references replaced by the appropriate entities"""
400 try:
401 name = nameList[0]
402 except IndexError:
403 return refList
404 newNames = self.instantiateName(name,entities)
405 newList = []
406 for ref in refList:
407 for name in newNames:
408 newList.append(ref[:]+[name])
409 return self.instantiateList(nameList[1:],newList,entities)
410
412 """Returns a list of instance names that match the given abstract entity reference (either 'self', relationship, or class name).
413 @param name: the reference(s) to be instantiated
414 @type name: C{str} or C{str[]}
415 @param entities: the entities to search for the given reference. If no entities are provided, defaults to the list of entities that this entity has beliefs about
416 @type entities: L{Agent}[]
417 @rtype: C{str[]}
418 """
419 if len(entities) == 0:
420 entities = self.entities.values()
421 if isinstance(name,list):
422 return map(lambda n,s=self,e=entities:s.instantiateName(n,e))
423 if name == 'self':
424 return [self.name]
425 elif self.relationships.has_key(name):
426 matches = []
427 for entity in entities:
428 if entity.name in self.relationships[name]:
429 matches.append(entity.name)
430 return matches
431 else:
432 matches = []
433 for entity in entities:
434 if entity.instanceof(name):
435 matches.append(entity.name)
436 return matches
437
439 """Adds any actions that I can perform with respect to the given entities
440 @type entities: L{Agent}[]
441 """
442 default = self.getDefault('actions')
443 self._addActions(entities,default,self.actions)
444 for option in default.extras:
445 if self.actions.illegal.has_key(str(option)):
446 continue
447 newOptions = [[]]
448 for action in option:
449 if not action['object'] is None:
450 names = self.instantiateName(action['object'],entities)
451 if self.name in names:
452 try:
453 selfEligible = action['self']
454 except KeyError:
455
456 selfEligible = False
457 if not selfEligible:
458 names.remove(self.name)
459 for new in newOptions[:]:
460 newOptions.remove(new)
461 for name in names:
462 newAction = copy.deepcopy(action)
463 newAction['object'] = name
464 newOption = copy.deepcopy(new)
465 newOption.append(newAction)
466 newOptions.append(newOption)
467 else:
468
469 for new in newOptions:
470 new.append(copy.deepcopy(action))
471 if len(newOptions) == 0:
472 break
473 else:
474 for newOption in newOptions:
475 self.actions.directAdd(newOption)
476
477 - def _addActions(self,entities,baseActions,realActions):
478 while isinstance(baseActions,DecisionSpace):
479 for value in baseActions.values:
480 if value['type'] == 'generic':
481 for entity in entities:
482 if value['value'] in entity.classes:
483 if entity.name != realActions:
484 realActions.append(entity.name)
485 elif value['type'] == 'relationship':
486 for entity in entities:
487 if value['value'] in self.relationships.keys() and \
488 entity.name in \
489 self.relationships[value['value']]:
490 if entity.name != realActions:
491 realActions.append(entity.name)
492 elif value['type'] == 'decision':
493 space = value['value'].__class__()
494 self._initActions(space,value['value'])
495 self._addActions(entities,value['value'],space)
496 realActions.append(space)
497 baseActions = baseActions.base
498 realActions = realActions.base
499
501 """
502 @return: True iff this entity is a member of the specified class
503 @param className: name of class to test against
504 @type className: C{str}
505 @rtype: C{boolean}
506 """
507 return className in self.classes
508
521
523 doc = Stereotyper.__xml__(self)
524 for cls in self.classes:
525 node = doc.createElement('class')
526 node.setAttribute('name',cls)
527 doc.documentElement.appendChild(node)
528 return doc
529
530 - def parse(self,element):
531 """Extracts this agent's recursive belief structure from the given XML Element
532 @type element: Element
533 """
534 Stereotyper.parse(self,element)
535 child = element.firstChild
536 while child:
537 if child.nodeType == child.ELEMENT_NODE and \
538 child.tagName == 'class':
539 self.classes.append(str(child.getAttribute('name')))
540 child = child.nextSibling
541
543 """Packages up the tree branch containing L{GenericEntity} into a neat
544 little dictionary, indexed by class name, with the values being
545 lists of classes that represent the branch up to the root (we
546 don't include L{GenericEntity}, which is the root)"""
547 for entry in linkList:
548 if type(entry) is TupleType:
549 child = entry[0].__name__
550 parent = entry[1][0].__name__
551 if not result.has_key(child):
552 result[child] = []
553 if parent != 'GenericEntity':
554 if not result.has_key(parent):
555 result[parent] = []
556 result[child].append(parent)
557 result[child] = result[child] + result[parent]
558 else:
559 packageHierarchy(entry,result)
560 return result
561
563 newModels = {}
564 for key in models.keys():
565 newModels[key] = copyModel(models[key])
566 return newModels
567
575
576 if __name__ == '__main__':
577
578 Beliefs.__TK__ = None
579 gov = createEntity('Government','CortinaGov')
580 clf = createEntity('TerroristCadres','CLFCadres')
581
582 print clf.instanceof('Psyops')
583 entities = [gov,clf]
584
585
586
587
588 entities = PsychAgents(entities)
589
590
591