Package teamwork :: Package multiagent :: Module GenericSociety
[hide private]
[frames] | no frames]

Source Code for Module teamwork.multiagent.GenericSociety

  1  """Collection of inter-related L{teamwork.agent.Generic.GenericModel} instances 
  2  @author: David V. Pynadath <pynadath@isi.edu> 
  3  """ 
  4  from xml.dom.minidom import * 
  5   
  6  from teamwork.agent.Generic import GenericModel 
  7  from teamwork.agent.Entities import * 
  8  from teamwork.multiagent.Multiagent import * 
  9   
10 -class GenericSociety(MultiagentSystem):
11 """A taxonomy of generic agent models 12 13 In essence, a generic society is simply a dictionary of L{GenericModel} 14 objects. You can manipulate the society through the following operations: 15 16 0. Creating a new society: 17 - C{society = L{GenericSociety}()} 18 19 1. Insert/overwrite a generic model: 20 - C{society.L{addMember}(model)} 21 22 2. Get a generic model by name 23 - C{model = society[name]} 24 25 3. Get a list of model objects: 26 - C{society.L{members}()} 27 28 4. Get a list of names of leaf nodes 29 - C{society.L{leaves}()} 30 31 5. Get a list of leaf node model objects 32 - C{society.L{leafModels}()} 33 34 6. Delete a generic model 35 - C{del society[model.name]} 36 37 7. Get a list of model names: 38 - C{society.keys()} 39 40 8. Get a list of (name,model) tuples 41 - C{society.items()} 42 43 9. Create an instantiated agent model of a particular class 44 - C{entity = society.L{instantiate}(className,instanceName)} 45 46 @ivar network: a dictionary representation of the descendent relationships in this society 47 @ivar root: a list of all of the root models in this society 48 """
49 - def __init__(self,agents=[]):
50 """Initializes a collection to contain the given list of agents""" 51 MultiagentSystem.__init__(self,agents) 52 self._keys = self.keys() 53 self._keys.sort() 54 self.turns = {} 55 self.network = {} 56 self.root = []
57
58 - def addMember(self,agent):
59 """Adds the agent to this collection 60 @param agent: the agent to add 61 @type agent: L{teamwork.agent.Agent} 62 @warning: will clobber any pre-existing agent with the same name 63 """ 64 MultiagentSystem.addMember(self,agent) 65 agent.setHierarchy(self) 66 try: 67 # We could test whether it's parallel, but what the heck 68 self._keys[0].append(agent.name) 69 except: 70 # I guess we were wrong 71 self._keys.insert(0,agent.name) 72 self.network[agent.name] = [] 73 if len(agent.getParents()) == 0: 74 self.root.append(agent.name) 75 self.root.sort() 76 for name in agent.getParents(): 77 try: 78 self.network[name].append(agent.name) 79 self.network[name].sort() 80 except KeyError: 81 pass 82 for name in self.network.keys(): 83 if agent.name in self[name].getParents(): 84 self.network[agent.name].append(name) 85 self.network[agent.name].sort()
86
87 - def renameEntity(self,old,new):
88 """ 89 @param old: the current name of the member 90 @param new: the new name of the member 91 @type old,new: str 92 """ 93 try: 94 # Maybe it's serial? 95 turn = self._keys.index(old) 96 agent = self[old] 97 index = self._keys.index(old) 98 self._keys.insert(index,new) 99 except ValueError: 100 # Nope 101 for names in self._keys: 102 try: 103 names.remove(old) 104 names.append(new) 105 break 106 except ValueError: 107 pass 108 self[new] = agent 109 for agent in self.members(): 110 agent.renameEntity(old,new) 111 # Update network 112 self.network[new] = self.network[old] 113 for names in self.network.values(): 114 if old in names: 115 names.append(new) 116 if old in self.root: 117 self.root.append(new) 118 del self[old]
119
120 - def merge(self,society):
121 """Merges the contents of a new society into this one 122 """ 123 warnings = [] 124 leftover = [] 125 for name,entity in society.items(): 126 if self.has_key(name): 127 warnings += self[name].merge(entity) 128 else: 129 self.addMember(entity) 130 for name,entity in society.items(): 131 if len(entity.getParents()) == 0: 132 self.root.append(entity.name) 133 self.root.sort() 134 for parent in entity.getParents(): 135 if not name in self.network[parent]: 136 self.network[parent].append(name) 137 self.network[parent].sort() 138 return warnings
139
140 - def descendents(self,name):
141 """ 142 @return: the names of the given entity and all of its descendents in the hierarchy 143 @rtype: str[] 144 """ 145 result = {} 146 remaining = [name] 147 while len(remaining) > 0: 148 current = remaining.pop(0) 149 result[current] = True 150 remaining += self.network[current] 151 return result.keys()
152
153 - def __delitem__(self,name):
154 MultiagentSystem.__delitem__(self,name) 155 for agent in self.members(): 156 try: 157 agent.parentModels.remove(name) 158 except ValueError: 159 # Not a parent 160 pass 161 try: 162 # Assume serial 163 self._keys.remove(name) 164 except ValueError: 165 # Oh well 166 for names in self._keys: 167 try: 168 names.remove(name) 169 break 170 except ValueError: 171 pass 172 del self.network[name] 173 try: 174 self.root.remove(name) 175 except ValueError: 176 pass 177 for names in self.network.values(): 178 try: 179 names.remove(name) 180 except ValueError: 181 pass
182
183 - def __xml__(self):
184 doc = MultiagentSystem.__xml__(self) 185 node = doc.createElement('order') 186 if self._keys and isinstance(self._keys[0],list): 187 node.setAttribute('serial','0') 188 else: 189 node.setAttribute('serial','1') 190 for index in range(len(self._keys)): 191 if isinstance(self._keys[index],str): 192 names = [self._keys[index]] 193 else: 194 names = self._keys[index] 195 for name in names: 196 child = doc.createElement('turn') 197 child.setAttribute('name',name) 198 child.setAttribute('position',str(index)) 199 node.appendChild(child) 200 doc.documentElement.appendChild(node) 201 return doc
202
203 - def parse(self,element):
204 """Extracts society elements from the provided XML Document""" 205 MultiagentSystem.parse(self,element,GenericModel) 206 for agent in self.members(): 207 agent.setHierarchy(self) 208 # Extract turn order 209 indices = {} 210 child = element.firstChild 211 serial = True 212 while child: 213 if child.nodeType == child.ELEMENT_NODE: 214 if child.tagName == 'order': 215 serial = str(child.getAttribute('serial')) != '0' 216 children = child.getElementsByTagName('turn') 217 for node in children: 218 name = str(node.getAttribute('name')) 219 index = int(node.getAttribute('position')) 220 indices[name] = index 221 child = child.nextSibling 222 # Unpack turn order results 223 if serial: 224 self._keys = map(lambda i: None,range(len(self))) 225 for name,position in indices.items(): 226 self._keys[position] = name 227 self._keys = filter(lambda k: not k is None,self._keys) 228 else: 229 self._keys = map(lambda i: [],range(len(self))) 230 for name,position in indices.items(): 231 self._keys[position].append(name) 232 self._keys = filter(lambda l: len(l),self._keys) 233 # Check for obsolete links 234 for agent in self.members(): 235 for relation in agent.getLinkTypes(): 236 for name in agent.getLinkees(relation): 237 if not self.has_key(name): 238 agent.removeLink(relation,name)
239
240 - def importDict(self,hierarchy,modelClass=None):
241 """Updates society from dictionary-style hierarchy 242 @param hierarchy: the specification of the generic society 243 @type hierarchy: C{dict} 244 @param modelClass: the class for the individual generic agent models (default is L{GenericModel} 245 @type modelClass: C{class} 246 """ 247 if not modelClass: 248 modelClass = GenericModel 249 # Read the separate models in 250 for name,generic in hierarchy.items(): 251 if not name: 252 # Ignore "None" entry? 253 continue 254 model = modelClass(name) 255 self.addMember(model) 256 model.importDict(generic) 257 # Tie up some connections among models 258 for name,generic in self.items(): 259 self.__copyGeneric(generic)
260
261 - def __copyGeneric(self,generic):
262 """Copies top-level generic values onto nested belief models""" 263 for other in generic.getEntities(): 264 entity = generic.getEntity(other) 265 if self.has_key(other): 266 # Belief about another class in this society 267 toExplore = [other] 268 while len(toExplore) > 0: 269 cls = toExplore.pop() 270 if len(self[cls].models) > 0: 271 entity.models = self[cls].models 272 break 273 toExplore += self[cls].getParents() 274 entity.dynamics = self[other].dynamics 275 # Anything else to copy? 276 # Descend recursively 277 self.__copyGeneric(entity)
278
279 - def leaves(self):
280 """Returns a list of generic model names that are leaf nodes""" 281 leaves = self.keys() 282 for name,model in self.items(): 283 for parent in model.getParents(): 284 try: 285 leaves.remove(parent) 286 except ValueError: 287 pass 288 return leaves
289
290 - def leafModels(self):
291 """Returns a list of generic model objects that are leaf nodes""" 292 return map(lambda name,s=self:s[name], self.leaves())
293
294 - def instantiate(self,className,instanceName,objClass=None):
295 """Returns a new instantiated agent model 296 @param className: name of the relevant generic model 297 @type className: C{str} 298 @param instanceName: name for the new instance 299 @type instanceName: C{str} 300 objClass: class to create agent object from (defaults to L{PsychEntity}) 301 """ 302 if not objClass: 303 objClass = PsychEntity 304 if not self.has_key(className): 305 raise UserWarning,'Unknown class: %s' % (className) 306 entity = objClass(instanceName) 307 entity.applyDefaults(className,self) 308 entity.society = self 309 return entity
310 311 if __name__ == '__main__': 312 import sys 313 import bz2 314 from xml.dom.minidom import parseString 315 316 f = bz2.BZ2File(sys.argv[1],'r') 317 data = f.read() 318 f.close() 319 320 try: 321 key = sys.argv[2].lower() 322 except IndexError: 323 key = '' 324 325 doc = parseString(data) 326 newClasses = GenericSociety() 327 newClasses.parse(doc.documentElement) 328 329 names = newClasses.keys() 330 names.sort(lambda x,y:cmp(x.lower(),y.lower())) 331 332 for name in names: 333 entity = newClasses[name] 334 if key[:5] == 'state': 335 for feature in entity.getStateFeatures(): 336 print '%s,%s,%5.3f' % (name,feature,entity.getState(feature)) 337 elif key[:6] == 'action': 338 for action in entity.actions.getOptions(): 339 if action[0]['object']: 340 print '%s,%s,%s' % (name,action[0]['type'], 341 action[0]['object']) 342 else: 343 print '%s,%s,' % (name,action[0]['type']) 344 elif key[:8] == 'relation': 345 for relation in entity.getLinkTypes(): 346 for other in entity.getLinkees(relation): 347 print '%s,%s,%s,%5.3f' % (name,relation,other, 348 entity.getLink(relation,other)) 349 elif key[:6] == 'leaves': 350 if name in newClasses.leaves(): 351 print name 352 elif key[:6] == 'static': 353 for relation,fillers in entity.relationships.items(): 354 for other in fillers: 355 print '%s,%s,%s' % (name,relation,other) 356 elif key[:5] == 'neigh': 357 if 'Neighborhood' in entity.getParents(): 358 print name 359 else: 360 print name 361