Package teamwork :: Package widgets :: Module DynamicsEditor
[hide private]
[frames] | no frames]

Source Code for Module teamwork.widgets.DynamicsEditor

  1  import string 
  2  from Tkinter import * 
  3  import tkMessageBox 
  4  import Pmw 
  5  from teamwork.math.Keys import ActionKey 
  6  from teamwork.widgets.TreeEditor import TreeEditor 
  7  from teamwork.math.KeyedVector import * 
  8  from teamwork.math.KeyedMatrix import * 
  9  from teamwork.math.KeyedTree import KeyedPlane 
 10  from teamwork.math.probability import Distribution 
 11  from MatrixEditor import MatrixEditor 
 12   
13 -class DynamicsEditor(TreeEditor):
14 - def __init__(self,parent,**kw):
15 optiondefs = ( 16 # The GenericSociety object for context 17 ('society', {}, Pmw.INITOPT), 18 ) 19 self.defineoptions(kw, optiondefs) 20 TreeEditor.__init__(self,parent) 21 # Initialize state values 22 stateKeys = {} 23 roleKeys = {} 24 classKeys = {} 25 relationKeys = {} 26 actionKeys = {} 27 if self['society']: 28 featureDict = {} 29 for entity in self['society'].members(): 30 for feature in entity.getStateFeatures(): 31 featureDict[feature] = True 32 for option in entity.actions.getOptions(): 33 for action in option: 34 key = ActionKey({'type': action['type'],'object': None, 35 'entity': entity.name}) 36 actionKeys[key] = True 37 key = ActionKey({'type': action['type'],'object': None, 38 'entity': None}) 39 actionKeys[key] = True 40 # Reserved role names 41 roles = {'actor': True,'object': True,'self': True} 42 # Fill in the possible relationship fillers 43 for entity in self['society'].members(): 44 for relation in entity.relationships.keys(): 45 for role in roles: 46 key = RelationshipKey({'feature':relation, 47 'relatee':role}) 48 relationKeys[key.simpleText()] = key 49 # Add relationship references, too 50 for entity in self['society'].members(): 51 roles.update(entity.relationships) 52 # Fill in all the states on roles 53 for role in roles.keys(): 54 for feature in featureDict.keys(): 55 key = StateKey({'entity':role,'feature':feature}) 56 stateKeys[key.simpleText()] = key 57 key = IdentityKey({'entity':role,'relationship':'equals'}) 58 roleKeys[key.simpleText()] = key 59 # Fill in all of the possible class fillers 60 for role in roles.keys(): 61 for entity in self['society'].keys(): 62 key = ClassKey({'entity':role, 63 'value':entity}) 64 classKeys[key.simpleText()] = key 65 self.createcomponent('menus',(),None,MatrixEditor, 66 (self.pane('editorPane'),), 67 states=stateKeys, 68 roles=roleKeys, 69 classes=classKeys, 70 relations=relationKeys, 71 actions=actionKeys, 72 ).pack(side='top',fill='both')
73
74 - def displayLeaf(self,value):
75 if isinstance(value,KeyedMatrix): 76 vector = value.values()[0] 77 if isinstance(vector,DeltaRow): 78 name = vector.simpleText() 79 else: 80 name = '' 81 rowKey = value.keys()[0] 82 elements = [] 83 for colKey,value in vector.items(): 84 if colKey == rowKey: 85 value -= 1. 86 if abs(value) > 0.: 87 if isinstance(colKey,ConstantKey): 88 elements.append('%5.3f' % (value)) 89 else: 90 elements.append('%d%% of %s' % (value*100., 91 colKey.simpleText())) 92 name = 'increment by %s' % (string.join(elements,' and ')) 93 elif isinstance(value,str): 94 name = value 95 elif value is None or isinstance(value,bool): 96 name = str(value) 97 else: 98 tkMessageBox.showwarning('Warning','Unable to display leaf nodes of type %s' % (value.__class__.__name__)) 99 name = '' 100 return name
101
102 - def displayPlane(self,planes):
103 if isinstance(planes,list): 104 # PWL branches 105 planeStr = string.join(map(lambda p:p.simpleText(numbers=self['expert']),planes),' and ') 106 return 'if %s' % (planeStr) 107 elif len(planes) == 1: 108 # Distribution, but no real branch 109 return 'with 100% probability' 110 elif len(planes) == 2: 111 # Probabilistic branch 112 return 'with %d%% probability' % (planes['then']*100.) 113 else: 114 # Too much to handle 115 raise UserWarning,'Unable to display distributions with more than 2 branches'
116
117 - def apply(self):
118 """Callback for applying changes to underlying L{KeyedTree<teamwork.math.KeyedTree.KeyedTree>} object""" 119 tree = self.selectedTree() 120 if tree is None: 121 pass 122 elif tree.isLeaf(): 123 row = self.component('menus').getDynamics() 124 tree.makeLeaf(row) 125 name = self.displayLeaf(tree.getValue()) 126 else: 127 branch = self.component('menus').getBranch() 128 children = tree.children() 129 if isinstance(branch,KeyedPlane): 130 # PWL branch 131 tree.split = [branch] 132 else: 133 # Probabilistic branch 134 prob = branch['then'] 135 branch = Distribution({'then': prob, 'else': 1.-prob}) 136 branch._domain['then'] = children[0] 137 branch._domain['else'] = children[1] 138 tree.branch(branch) 139 name = self.displayPlane(tree.split) 140 if tree.parent: 141 if tree.parent[0].isProbabilistic(): 142 name = '%s %s' % (tree.parent[1],name) 143 elif tree.parent[1]: 144 name = 'then %s' % (name) 145 else: 146 name = 'else %s' % (name) 147 selectednode = self.selection() 148 #keep track of expansion 149 rnode = self.component('tree').find_full_id(selectednode.full_id()) 150 expand = (rnode and rnode.expandable() and rnode.expanded()) 151 selectednode['label'] = name 152 selectednode.refresh() 153 if expand: 154 self.component('tree').find_full_id(selectednode.full_id()).expand() 155 self.nodes[id(self.selection())] = tree
156
157 - def setLeaf(self,rowType):
158 self.component('menus').setDynamics(rowType)
159
160 - def setBranch(self,rowType):
161 self.component('menus').setBranch(rowType)
162
163 - def selectLeaf(self):
164 if not self['society']: 165 self.component('box_apply').configure(state='disabled') 166 self.component('box_add').configure(state='disabled') 167 self.component('box_delete').configure(state='disabled') 168 return 169 ## self.component('menus_type').configure(menubutton_state='normal') 170 self.component('menus_type').configure(selectioncommand=self.setLeaf) 171 self.component('menus').displayDynamics(self.selectedTree().getValue())
172
173 - def selectBranch(self):
174 if not self['society']: 175 self.component('box_apply').configure(state='disabled') 176 self.component('box_add').configure(state='disabled') 177 self.component('box_delete').configure(state='disabled') 178 return 179 ## self.component('menus_type').configure(menubutton_state='normal') 180 self.component('menus_type').configure(selectioncommand=self.setBranch) 181 tree = self.selectedTree() 182 if isinstance(tree.split,list): 183 if len(tree.split) > 1: 184 raise NotImplementedError,'Currently unable to display multiple hyperplanes' 185 else: 186 self.component('menus').displayBranch(tree.split[0]) 187 else: 188 # Probabilistic branch 189 self.component('menus').displayBranch(tree.split)
190
191 - def addBranch(self):
192 tree = self.selectedTree() 193 parent = self.selection() 194 if tree.isLeaf(): 195 # Adding branch to leaf node 196 trueTree = tree.__class__() 197 trueTree.makeLeaf(copy.deepcopy(tree.getValue())) 198 falseTree = tree.__class__() 199 falseTree.makeLeaf(copy.deepcopy(tree.getValue())) 200 else: 201 # Adding branch above branch; must handle children first 202 for child in parent['children'][:]: 203 child.delete() 204 del self.nodes[id(child)] 205 # parent.refresh() 206 trueTree = copy.deepcopy(tree) 207 falseTree = copy.deepcopy(tree) 208 row = TrueRow() 209 plane = KeyedPlane(row,-.1) 210 # The None flags are important to prevent pruning (because 211 # left and right are ==, so they'll get collapsed otherwise) 212 tree.branch(plane,trueTree=trueTree,falseTree=falseTree, 213 pruneF=False,pruneT=False) 214 # Draw the new branch 215 self.component('tree').inhibitDraw = True 216 name = self.displayPlane(tree.split) 217 if tree.parent: 218 if tree.parent[1]: 219 name = 'then %s' % (name) 220 else: 221 name = 'else %s' % (name) 222 # parent.var.set(name) 223 parent['label'] = name 224 parent['isLeaf'] = False 225 subnode = parent.addChild(self.component('tree'),isLeaf=True) 226 subnode['action'] = self.select 227 self.setTree(trueTree,subnode,'then ') 228 subnode = parent.addChild(self.component('tree'),isLeaf=True) 229 subnode['action'] = self.select 230 self.setTree(falseTree,subnode,'else ') 231 self.nodes[id(parent)] = tree 232 self.component('tree').inhibitDraw = False 233 # self.component('tree').display() 234 parent.refresh(self.component('tree')) 235 self.select() 236 self.component('tree').find_full_id(parent.full_id()).expand()
237
238 - def __deleteRecursiveFromDict__(self,node,somedict):
239 for child in node['children'][:]: 240 self.__deleteRecursiveFromDict__(child,somedict) 241 somedict[id(node)] = None
242
243 - def deleteNode(self):
244 childTree = self.selectedTree() 245 if childTree.parent: 246 parentTree,side = childTree.parent 247 else: 248 tkMessageBox.showerror('Delete Error', 249 'You cannot delete the entire tree!') 250 return 251 childNode = self.selection() 252 # parentNode = childNode.master 253 parentNode = childNode['parent'] 254 if isinstance(parentTree.split,list): 255 # Binary tree 256 #do some housecleaning of our convenience hash 257 # self.__deleteRecursiveFromDict__(parentNode,self.nodes) 258 del self.nodes[id(parentNode)] 259 del self.nodes[id(childNode)] 260 261 fTree,tTree = parentTree.getValue() 262 if parentTree.parent is None: 263 prefix = '' 264 elif parentTree.parent[1]: 265 prefix = 'then ' 266 else: 267 prefix = 'else ' 268 if side: 269 # We're deleting T side 270 if fTree.isLeaf(): 271 parentTree.makeLeaf(fTree.getValue()) 272 elif fTree.isProbabilistic(): 273 tkMessageBox.showerror('Not implemented','Unable to delete children from probabilistic branches.') 274 else: 275 plane = fTree.split 276 fTree,tTree = fTree.getValue() 277 parentTree.branch(plane,fTree,tTree) 278 # name = parentNode.child[1].var.get() 279 name = parentNode['children'][1]['label'] 280 parentNode['label'] = prefix+name[5:] 281 parentNode['children'][0].delete() 282 parentNode['isLeaf'] = True 283 # parentNode.var.set(prefix+name[5:]) 284 # parentNode.deleteChild(parentNode.child[0]) 285 else: 286 # We're deleting F side 287 if tTree.isLeaf(): 288 parentTree.makeLeaf(tTree.getValue()) 289 elif tTree.isProbabilistic(): 290 tkMessageBox.showerror('Not implemented','Unable to delete children from probabilistic branches.') 291 else: 292 plane = tTree.split 293 fTree,tTree = tTree.getValue() 294 parentTree.branch(plane,fTree,tTree) 295 # name = parentNode.child[0].var.get() 296 name = parentNode['children'][0]['label'] 297 parentNode['label'] = prefix+name[5:] 298 parentNode['children'][1].delete() 299 parentNode['isLeaf'] = True 300 301 # parentNode.var.set(prefix+name[5:]) 302 # parentNode.deleteChild(parentNode.child[1]) 303 # children = parentNode.child[0].child 304 children = parentNode['children'][0]['children'][:] 305 # parentNode.state = parentNode.child[0].state 306 parentNode['children'][0].delete(recursive=False) 307 # parentNode.deleteChild(parentNode.child[0]) 308 for child in children: 309 # parentNode.child.append(child) 310 parentNode['children'].append(child) 311 child['parent'] = parentNode 312 parentNode['isLeaf'] = False 313 # child.master = parentNode 314 self.nodes[id(parentNode)] = parentTree 315 parentNode.selected = True 316 parentNode.refresh() 317 else: 318 tkMessageBox.showerror('Not implemented','Unable to delete children from probabilistic branches.') 319 return 320 # self.component('tree').display() 321 if self.selectedTree().isLeaf(): 322 self.selectLeaf() 323 else: 324 self.selectBranch()
325