Package teamwork :: Package agent :: Module lightweight
[hide private]
[frames] | no frames]

Source Code for Module teamwork.agent.lightweight

  1  """A minimal agent implementation that uses only the PWL representations of an agent's beliefs, policy, etc. 
  2  """ 
  3  from Agent import Agent 
  4  from teamwork.dynamics.pwlDynamics import PWLDynamics,IdentityDynamics 
  5  from teamwork.action.PsychActions import Action 
  6  from teamwork.action.DecisionSpace import parseSpace 
  7  from teamwork.math.Keys import StateKey,LinkKey,keyConstant 
  8  from teamwork.math.probability import Distribution 
  9  from teamwork.math.KeyedVector import KeyedVector 
 10  from teamwork.math.KeyedMatrix import IdentityMatrix 
 11  from teamwork.policy.policyTable import PolicyTable 
 12  from teamwork.reward.MinMaxGoal import MinMaxGoal 
 13  import copy 
 14   
15 -class PWLAgent(Agent):
16 """Lightweight version of a PsychSim agent with only the barest essentials for generating behaviors 17 @ivar dynamics: a dictionary of dictionaries of L{PWLDynamics} objects. The top-level key is the state feature the dynamics affect. The keys at the level below are L{Action} types. 18 @type dynamics: strS{->}(strS{->}L{PWLDynamics}) 19 @ivar parent: the parent of this agent, included for compatibility with L{RecursiveAgent<teamwork.agent.RecursiveAgent.RecursiveAgent>} instances. Always C{None}. 20 @ivar policy: this agent's policy of behavior 21 @type policy: L{PolicyTable} 22 @ivar goals: this agent's goal weights 23 @type goals: L{KeyedVector} 24 @ivar liking: the liking this agent has for others 25 @type liking: L{KeyedVector} 26 @ivar trust: the trust this agent has in others 27 @type trust: L{KeyedVector} 28 @cvar _supportFeature: the label for the liking relationship 29 @cvar _trustFeature: the label for the trust relationship 30 @type _supportFeature,_trustFeature: str 31 @ivar relationships: an empty dictionary of inter-agent relationships from this agent 32 @ivar compiled: if C{True}, the value function is compiled (default is C{False} 33 @type compiled: bool 34 """ 35 _supportFeature = 'likes' 36 _trustFeature = 'trusts' 37
38 - def __init__(self,agent=None):
39 """Constructor that creates a lightweight version of a given PsychSim agent 40 @param agent: the L{RecursiveAgent<teamwork.agent.RecursiveAgent.RecursiveAgent>} to be distilled (if omitted, an empty agent is created) 41 """ 42 self.dynamics = {} 43 self.parent = None 44 self.policy = None 45 self.horizon = 0 46 self.state = Distribution({KeyedVector({keyConstant:1.}):1.}) 47 self.goals = Distribution({KeyedVector():1.}) 48 self.relationships = {} 49 self.links = KeyedVector() 50 self.linkDynamics = {self._supportFeature:{}, 51 self._trustFeature:{}} 52 self.linkTypes = [self._supportFeature,self._trustFeature] 53 self.classes = [] 54 self.world = None 55 self.society = None 56 self.compiled = False 57 self.beliefs = self.state 58 self.estimators = {} 59 if agent is None: 60 name='Piecewise Linear Agent' 61 elif isinstance(agent,str): 62 name = agent 63 else: 64 name = agent.name 65 Agent.__init__(self,name) 66 if isinstance(agent,Agent): 67 self.actions = agent.actions 68 if len(agent.entities) > 0: 69 self.beliefs = copy.deepcopy(agent.entities.getState()) 70 # Copy over the policy 71 self.horizon = agent.horizon 72 self.policy = PolicyTable(self,self.actions,agent.policy.horizon) 73 self.policy.attributes = agent.policy.attributes[:] 74 self.policy.rules = copy.deepcopy(agent.policy.rules) 75 # Copy over raw state dynamics 76 for feature,dynTable in agent.dynamics.items(): 77 self.dynamics[feature] = {} 78 for action,dynamics in dynTable.items(): 79 if isinstance(action,str): 80 self.dynamics[feature][action] = dynamics 81 # Copy over goal weights 82 self.goals = agent.getGoalVector()['state'] 83 # Copy over liking, trust, etc. 84 self.linkTypes = agent.getLinkTypes()[:] 85 for linkType in agent.getLinkTypes(): 86 for name in agent.getLinkees(linkType): 87 key = agent.getLinkKey(linkType,name) 88 self.links[key] = agent.getLink(linkType,name) 89 # Copy over raw relationship dynamics 90 for feature,dynTable in agent.linkDynamics.items(): 91 self.linkDynamics[feature] = {} 92 for action,dynamics in dynTable.items(): 93 if isinstance(action,str): 94 self.linkDynamics[feature][action] = dynamics 95 # Copy over class membership 96 self.classes = agent.classes[:] 97 # Copy over relationships 98 for relation,relatees in agent.relationships.items(): 99 self.relationships[relation] = relatees[:]
100
101 - def setHierarchy(self,classes):
102 """We don't need no stinking defaults""" 103 pass
104
105 - def ancestry(self):
106 """ 107 @return: a string representation of this entity's position in the recursive belief tree. 108 - If C{self.parent == None}, then returns C{self.name} 109 - Otherwise, returns C{self.parent.ancestry()+'->'+self.name} 110 @rtype: C{str} 111 """ 112 name = self.name 113 parent = self.parent 114 while parent: 115 name = parent.name + '->' + name 116 parent = parent.parent 117 return name
118
119 - def instanceof(self,className):
120 """ 121 @return: True iff this entity is a member of the specified class 122 @param className: name of class to test against 123 @type className: C{str} 124 @rtype: C{boolean} 125 """ 126 return className in self.classes
127
128 - def getStateFeatures(self):
129 """ 130 @return: names of the valid state features 131 @rtype: C{str[]} 132 """ 133 keyList = [] 134 for key in self.state.domainKeys(): 135 if isinstance(key,StateKey) and key['entity'] == self.name: 136 keyList.append(key['feature']) 137 return keyList
138
139 - def getState(self,feature):
140 """Returns the current L{Distribution} over the specified feature 141 @type feature: string 142 @rtype: L{Distribution}""" 143 key = StateKey({'entity':self.name,'feature':feature}) 144 return self.state.getMarginal(key)
145
146 - def setState(self,feature,value):
147 """Sets this entity's state value for the specified feature 148 @type feature: string 149 @type value: either a float or a L{Distribution}. If the value is a float, it is first converted into a point distribution.""" 150 key = StateKey({'entity':self.name,'feature':feature}) 151 frozen = self.state.unfreeze() 152 self.state.join(key,value) 153 if frozen: 154 self.state.freeze()
155
156 - def getEntities(self):
157 entities = {} 158 for key in self.beliefs.domain()[0].keys(): 159 if isinstance(key,StateKey): 160 entities[key['entity']] = True 161 return entities.keys()
162
163 - def getEntity(self,name):
164 return self.world[name]
165
166 - def getEntityBeliefs(self):
167 return map(self.getEntity,self.getEntities())
168
169 - def getBeliefKeys(self):
170 """ 171 @return: the state features across all beliefs that this agent has 172 @rtype: L{StateKey}[] 173 """ 174 return self.beliefs.expectation().keys()
175
176 - def getLinkTypes(self):
177 """ 178 @return: all of the available dynamics relationship types that 179 his entity has 180 @rtype: str[] 181 """ 182 return self.linkTypes
183
184 - def getLinkees(self,relationship):
185 """ 186 @param relationship: the dynamic relationship (e.g., 'likes', 187 'trusts') to evaluate 188 @type relationship: str 189 @return: the others to which this entity has explicit 190 relationships of the specified type 191 @rtype: str[] 192 """ 193 result = [] 194 for key in self.links.keys(): 195 if key['subject'] == self.name and key['verb'] == relationship: 196 result.append(key['object']) 197 return result
198
199 - def getLinkKey(self,relation,entity):
200 """ 201 @return: the vector index for this entity's relation to the given 202 entity 203 @rtype: L{LinkKey} 204 """ 205 return LinkKey({'subject':self.name, 206 'verb':relation, 207 'object':entity})
208 224 237 238 # SE^0_i
239 - def initialStateEstimator(self):
240 """Generates the initial belief state for the specified agent""" 241 return Distribution({KeyedVector():1.})
242
243 - def getBelief(self,entity,feature):
244 """ 245 @param entity: the name of the relevant entity 246 @type entity: str 247 @param feature: the state feature of interest 248 @type feature: str 249 @return: the agent's current belief about the given entity's value for the given state feature 250 @rtype: L{Distribution} 251 """ 252 key = StateKey({'entity':entity,'feature':feature}) 253 return self.beliefs.getMarginal(key)
254
255 - def setBelief(self,entity,feature,value):
256 """Sets this entity's belief value for the specified entity's state feature value 257 @param entity: the name of the relevant entity 258 @type entity: str 259 @param feature: the state feature of interest 260 @type feature: string 261 @type value: either a float or a L{Distribution}. If the value is a float, it is first converted into a point distribution.""" 262 key = StateKey({'entity':entity,'feature':feature}) 263 self.beliefs.unfreeze() 264 self.beliefs.join(key,value) 265 self.beliefs.freeze()
266
267 - def getGoals(self):
268 return []
269
270 - def getGoalVector(self):
271 return {'state': self.goals}
272
273 - def applyPolicy(self,state=None,actions=[],history=None,debug=None, 274 explain=False,entities={},cache={}):
275 """Generates a decision chosen according to the agent's current policy 276 @param state: the current state vector 277 @type state: L{Distribution}(L{KeyedVector}) 278 @param actions: the possible actions the agent can consider (defaults to all available actions) 279 @type actions: L{Action}[] 280 @param history: a dictionary of actions that have already been performed (and which should not be performed again if they are labeled as not repeatable) 281 @type history: L{Action}[]:bool 282 @param explain: flag indicating whether an explanation should be generated 283 @type explain: bool 284 @param entities: a dictionary of entities to be used as a value tree cache 285 @param cache: values computed so far 286 @return: a list of actions and an explanation, the latter provided by L{execute<PolicyTable.execute>} 287 @rtype: C{(L{Action}[],Element)} 288 """ 289 if state is None: 290 state = {None:self.beliefs} 291 return self.policy.execute(state=state,choices=actions,history=history, 292 debug=debug,explain=explain, 293 entities=entities,cache=cache)
294
295 - def actionValue(self,actions,horizon=1,state=None,debug=False):
296 """Compute the expected value of performing the given action 297 @param actions: the actions whose effect we want to evaluate 298 @type actions: L{Action}[] 299 @param horizon: the length of the forward projection 300 @type horizon: int 301 @param state: the world state to evaluate the actions in (defaults to current world state) 302 @type state: L{Distribution} 303 @warning: Computation assumes that dynamics for I{instantiated} actions are already stored. Missing dynamics are taken to imply no effect. 304 """ 305 if state is None: 306 state = {None:self.beliefs} 307 eState = state[None].expectation() 308 goals = self.goals.expectation() 309 projection = {} 310 total = 0. 311 for key in filter(lambda k: goals[k] > Distribution.epsilon, 312 goals.keys()): 313 if key['entity'] == self.name: 314 entity = self 315 elif self.world: 316 entity = self.world[key['entity']] 317 else: 318 raise UserWarning,'Entity %s has no world' % (self.name) 319 dynamics,delta = self.world.getEffect(actions[0],key,eState, 320 not self.compiled) 321 if dynamics: 322 if delta is None: 323 tree = dynamics.getTree() 324 delta = dynamics.apply(state[None]).expectation() 325 total += goals[key]*(delta[key]*eState) 326 for subKey in delta[key].keys(): 327 try: 328 projection[subKey] += goals[key]*delta[key][subKey] 329 except KeyError: 330 projection[subKey] = goals[key]*delta[key][subKey] 331 return total,{'value':total,'projection':projection}
332
333 - def stateEstimator(self,beliefs=None,actions=[],observation=None):
334 """Updates the agent's beliefs in response to the given agents 335 @param beliefs: the agent's current beliefs (typically C{self.beliefs}) 336 @type beliefs: L{Distribution}(L{KeyedVector}) 337 @param actions: the observed actions 338 @type actions: L{Action}[] 339 @param obersvation: if in a partially observable domain, this is the observation received (default is C{None}) 340 @type observation: str 341 @return: the new beliefs (updates the agent's beliefs as a side effect) 342 @rtype: L{Distribution}(L{KeyedVector}) 343 """ 344 if beliefs is None: 345 doForReal = True 346 beliefs = self.beliefs 347 else: 348 doForReal = False 349 if observation: 350 if isinstance(beliefs,list): 351 # Observation history 352 beliefs = beliefs + [observation] 353 else: 354 # Belief state 355 SE = self.estimators[observation] 356 rule = SE.index(beliefs) 357 numerator = SE.values[rule][str(actions)] 358 beliefs = numerator*beliefs 359 beliefs *= 1./sum(beliefs.getArray()) 360 else: 361 dynamics = self.dynamics[str(actions)] 362 beliefs = dynamics[beliefs]*beliefs 363 if doForReal: 364 self.beliefs = beliefs 365 return beliefs
366 367
368 - def setEstimator(self,trans,obs):
369 """Compute state estimator 370 """ 371 self.estimators.clear() 372 others = [] 373 for agent in self.world.members(): 374 if agent.name != self.name and len(agent.actions.getOptions()) > 0: 375 others.append(agent) 376 if len(others) > 1: 377 raise NotImplementedError,'Unable to handle more than 2 agents' 378 n = len(self.policy.tables) - 1 379 if n <= 0: 380 # I'm not really an agent 381 policy = others[0].policy.getTable(0) 382 else: 383 # I think of other as using (n-1)-level policy 384 policy = others[0].policy.getTable(n-1) 385 for omega in obs.values()[0].keys(): 386 # Compute T table 387 T = policy.getTable() 388 for rule in range(len(T)): 389 yrAction = T.rules[rule] 390 T.values[rule].clear() 391 for myAction in self.actions.getOptions(): 392 actions = {self.name:myAction,others[0].name:yrAction} 393 actionKey = ' '.join(map(str,actions.values())) 394 value = copy.copy(trans[actionKey]) 395 T.values[rule][str(myAction)] = value 396 # Compute O table 397 O = policy.getTable() 398 for rule in range(len(O)): 399 yrAction = O.rules[rule] 400 O.values[rule].clear() 401 for myAction in self.actions.getOptions(): 402 actions = {self.name:myAction,others[0].name:yrAction} 403 actionKey = ' '.join(map(str,actions.values())) 404 value = copy.copy(obs[actionKey][omega]) 405 O.values[rule][str(myAction)] = value 406 # SE = O*T 407 def merge(o,t): 408 result = copy.copy(t) 409 for key in result.rowKeys(): 410 result[key] = result[key]*o[key] 411 return result
412 self.estimators[omega] = O.__mul__(T,merge) 413 return self.estimators
414 415
416 - def getDynamics(self,act,feature,cache=False,debug=False):
417 """ 418 @return: this entity's dynamics model for the given action 419 @param act: the action whose effect we are interested in 420 @type act: L{Action} 421 @param feature: the feature whose effect we want to get the dynamics for 422 @type feature: C{str} 423 @param cache: if C{True}, then save the instantiated dynamics for future recall (default is C{False}) 424 @type cache: bool 425 @rtype: L{PWLDynamics} 426 @param debug: if C{True}, prints out some debugging statements (default is C{False} 427 @type debug: bool 428 """ 429 if debug: 430 print 'Computing effect of %s on %s\'s %s' % \ 431 (str(act),self.name,feature) 432 try: 433 dynFun = self.dynamics[feature][act] 434 if debug: 435 print '\tAlready computed' 436 except KeyError: 437 try: 438 dynFun = self.dynamics[feature][act['type']] 439 if debug: 440 print '\tFound generic dynamics' 441 except KeyError: 442 # It's OK for an action to have no dynamics 443 # (e.g., the "wait" action) 444 if debug: 445 print '\tNo generic dynamics' 446 return None 447 if isinstance(dynFun,str): 448 # Linked to uninstantiated dynamics in generic society 449 if debug: 450 print '\tLink to generic dynamics' 451 dynFun = self.society[dynFun].dynamics[feature][act['type']] 452 if dynFun: 453 if debug: 454 print '\tInstantiating...' 455 dynFun = dynFun.instantiate(self,act) 456 tree = dynFun.getTree() 457 if tree.isLeaf(): 458 matrix = tree.getValue() 459 if isinstance(matrix,IdentityMatrix): 460 # Don't bother storing identities as trees 461 dynFun = None 462 else: 463 # Check whether it's an untagged identity 464 key = StateKey({'entity':self.name,'feature':feature}) 465 vector = matrix[key] 466 if abs(sum(vector.getArray())-1.) < Distribution.epsilon and \ 467 abs(vector[key]-1.) < Distribution.epsilon: 468 dynFun = None 469 if dynFun is None: 470 if debug: 471 print '\tNull effect' 472 return None 473 if cache: 474 if dynFun and self.world: 475 # Check for identical dynamics somewhere else 476 for other in self.world.members(): 477 for key,table in other.dynamics.items(): 478 for action,dynamics in table.items(): 479 if isinstance(action,Action) and \ 480 isinstance(dynamics,PWLDynamics) and \ 481 dynamics.getTree() == dynFun.getTree(): 482 if debug: 483 print '\tLink to effect of %s on %s\'s %s' % (str(action),other.name,key) 484 dynFun = {'entity':other.name, 485 'feature':key, 486 'action':action} 487 break 488 if isinstance(dynFun,dict): 489 break 490 if isinstance(dynFun,dict): 491 break 492 try: 493 self.dynamics[feature][act] = dynFun 494 except KeyError: 495 self.dynamics[feature] = {act: dynFun} 496 if debug: 497 print '\tCached' 498 assert isinstance(act,Action) 499 assert self.dynamics[feature].has_key(act) 500 if isinstance(dynFun,dict): 501 # Linked to instantiated dynamics somewhere else 502 return self.world[dynFun['entity']].dynamics[dynFun['feature']][dynFun['action']] 503 else: 504 # Actual dynamics objects 505 return dynFun
506
507 - def __xml__(self,dynamics=False):
508 """ 509 @param dynamcis: if C{True}, instantiated dynamics are stored as well (default is C{False} 510 @type dynamics: bool 511 """ 512 doc = Agent.__xml__(self) 513 # Dynamics 514 node = doc.createElement('dynamics') 515 doc.documentElement.appendChild(node) 516 for feature,subDict in self.dynamics.items(): 517 featureNode = doc.createElement('feature') 518 node.appendChild(featureNode) 519 featureNode.setAttribute('label',feature) 520 for actType,dynamic in subDict.items(): 521 if isinstance(actType,str): 522 # This test prevents the saving of compiled dynamics 523 actNode = doc.createElement('action') 524 actNode.setAttribute('compiled','0') 525 featureNode.appendChild(actNode) 526 actNode.setAttribute('type',actType) 527 if isinstance(dynamic,str): 528 actNode.setAttribute('link',dynamic) 529 else: 530 actNode.appendChild(dynamic.__xml__().documentElement) 531 else: 532 # Store compiled dynamics 533 actNode = actType.__xml__().documentElement 534 actNode.setAttribute('compiled','1') 535 featureNode.appendChild(actNode) 536 if dynamic is None: 537 raise UserWarning 538 elif isinstance(dynamic,dict): 539 link = doc.createElement('link') 540 link.setAttribute('entity',dynamic['entity']) 541 link.setAttribute('feature',dynamic['feature']) 542 link.appendChild(dynamic['action'].__xml__().documentElement) 543 actNode.appendChild(link) 544 else: 545 actNode.appendChild(dynamic.__xml__().documentElement) 546 # Relationships 547 node = doc.createElement('relationships') 548 doc.documentElement.appendChild(node) 549 for label,agents in self.relationships.items(): 550 relationshipNode = doc.createElement('relationship') 551 node.appendChild(relationshipNode) 552 relationshipNode.setAttribute('label',label) 553 for name in agents: 554 subNode = doc.createElement('relatee') 555 subNode.appendChild(doc.createTextNode(name)) 556 relationshipNode.appendChild(subNode) 557 # Add beliefs 558 if not self.beliefs is self.state: 559 node = doc.createElement('beliefs') 560 doc.documentElement.appendChild(node) 561 node.appendChild(self.beliefs.__xml__().documentElement) 562 # Add policy 563 node = doc.createElement('policy') 564 doc.documentElement.appendChild(node) 565 node.appendChild(self.policy.__xml__().documentElement) 566 # Actions 567 node = doc.createElement('actions') 568 doc.documentElement.appendChild(node) 569 node.appendChild(self.actions.__xml__().documentElement) 570 # Goals 571 node = doc.createElement('goals') 572 doc.documentElement.appendChild(node) 573 node.appendChild(self.goals.__xml__().documentElement) 574 # Classes 575 for cls in self.classes: 576 node = doc.createElement('class') 577 node.setAttribute('name',cls) 578 doc.documentElement.appendChild(node) 579 # Dynamic relationships 580 node = doc.createElement('links') 581 node.appendChild(self.links.__xml__().documentElement) 582 doc.documentElement.appendChild(node) 583 # Write available link types 584 for linkType in self.getLinkTypes(): 585 node = doc.createElement('linktype') 586 node.setAttribute('name',linkType) 587 doc.documentElement.appendChild(node) 588 # Write link dynamics 589 for linkType,table in self.linkDynamics.items(): 590 for action,dynamics in table.items(): 591 if isinstance(action,str): 592 node = doc.createElement('linkdynamics') 593 node.setAttribute('feature',linkType) 594 node.setAttribute('action',action) 595 node.appendChild(dynamics.__xml__().documentElement) 596 doc.documentElement.appendChild(node) 597 return doc
598
599 - def parse(self,element):
600 Agent.parse(self,element) 601 child = element.firstChild 602 while child: 603 if child.nodeType == child.ELEMENT_NODE: 604 if child.tagName == 'dynamics': 605 node = child.firstChild 606 while node: 607 if node.nodeType == node.ELEMENT_NODE: 608 assert(node.tagName=='feature') 609 feature = str(node.getAttribute('label')) 610 self.dynamics[feature] = {} 611 subNode = node.firstChild 612 while subNode: 613 if subNode.nodeType == subNode.ELEMENT_NODE: 614 assert(subNode.tagName=='action') 615 flag = subNode.getAttribute('compiled') 616 if flag == '': 617 flag = False 618 else: 619 flag = int(flag) 620 if flag: 621 # Instantiated dynamics 622 self.compiled = True 623 link = subNode.firstChild 624 while link: 625 if link.nodeType == link.ELEMENT_NODE and (link.tagName == 'link' or link.tagName == 'dynamic'): 626 break 627 link = link.nextSibling 628 else: 629 raise UserWarning,subNode.toxml() 630 if link.tagName == 'link': 631 # Link to other dynamics 632 dyn = {'entity':str(link.getAttribute('entity')), 633 'feature':str(link.getAttribute('feature')), 634 'action':Action()} 635 action = link.firstChild 636 while action: 637 if action.nodeType == action.ELEMENT_NODE: 638 break 639 action = action.nextSibling 640 assert action.tagName == 'action' 641 dyn['action'] = dyn['action'].parse(action) 642 else: 643 # Dynamics stored here 644 dyn = PWLDynamics() 645 dyn.parse(link) 646 # Store dynamics under action 647 action = Action() 648 action.parse(subNode) 649 self.dynamics[feature][action] = dyn 650 else: 651 # Uninstantiated dynamics 652 actionType = str(subNode.getAttribute('type')) 653 assert(actionType not in self.dynamics[feature].keys()) 654 dyn = str(subNode.getAttribute('link')) 655 if not dyn: 656 dyn = PWLDynamics() 657 subchild = subNode.firstChild 658 while subchild and subchild.nodeType != child.ELEMENT_NODE: 659 subchild = subchild.nextSibling 660 dyn.parse(subchild) 661 self.dynamics[feature][actionType] = dyn 662 subNode = subNode.nextSibling 663 node = node.nextSibling 664 elif child.tagName == 'actions': 665 subNode = child.firstChild 666 while subNode and subNode.nodeType != subNode.ELEMENT_NODE: 667 subNode = subNode.nextSibling 668 if subNode: 669 self.actions = parseSpace(subNode) 670 for action in self.actions.getOptions(): 671 for subAct in action: 672 subAct['actor'] = self.name 673 elif child.tagName == 'beliefs': 674 subNodes = child.getElementsByTagName('distribution') 675 if len(subNodes) == 1: 676 self.beliefs.parse(subNodes[0],KeyedVector) 677 elif len(subNodes) > 1: 678 raise UserWarning,'Multiple distributions in beliefs' 679 else: 680 raise UserWarning,'Missing distribution in beliefs' 681 elif child.tagName == 'policy': 682 subNode = child.firstChild 683 while subNode and subNode.nodeType != subNode.ELEMENT_NODE: 684 subNode = subNode.nextSibling 685 if subNode: 686 self.policy = PolicyTable(self,self.actions) 687 self.policy.parse(subNode) 688 elif child.tagName == 'goals': 689 self.goals.parse(child.firstChild,KeyedVector) 690 elif child.tagName == 'class': 691 self.classes.append(str(child.getAttribute('name'))) 692 elif child.tagName == 'relationships': 693 node = child.firstChild 694 while node: 695 if node.nodeType == node.ELEMENT_NODE: 696 label = str(node.getAttribute('label')) 697 self.relationships[label] = [] 698 subNode = node.firstChild 699 while subNode: 700 if subNode.nodeType == subNode.ELEMENT_NODE: 701 assert(subNode.tagName == 'relatee') 702 name = subNode.firstChild.data 703 name = str(name).strip() 704 self.relationships[label].append(name) 705 subNode = subNode.nextSibling 706 node = node.nextSibling 707 elif child.tagName == 'links': 708 node = child.firstChild 709 while node: 710 if node.nodeType == node.ELEMENT_NODE: 711 self.links = self.links.parse(node) 712 break 713 node = node.nextSibling 714 elif child.tagName == 'linktype': 715 linkType = str(child.getAttribute('name')) 716 if not self.linkDynamics.has_key(linkType): 717 assert not linkType in self.linkTypes 718 self.linkTypes.append(linkType) 719 self.linkDynamics[linkType] = {} 720 elif child.tagName == 'linkdynamics': 721 linkType = str(child.getAttribute('feature')) 722 action = str(child.getAttribute('action')) 723 dyn = PWLDynamics() 724 subChild = child.firstChild 725 while subChild: 726 if subChild.nodeType == child.ELEMENT_NODE: 727 dyn.parse(subChild) 728 break 729 subChild = subChild.nextSibling 730 try: 731 self.linkDynamics[linkType][action] = dyn 732 except KeyError: 733 self.linkDynamics[linkType] = {action: dyn} 734 elif child.tagName in ['trust','liking']: 735 # Obsolete, but harmless 736 pass 737 else: 738 print 'Unhandled tag %s for lightweight agent %s' % \ 739 (child.tagName,self.name) 740 child = child.nextSibling
741