1 from Tkinter import *
2 import tkMessageBox
3 import Pmw
4 from teamwork.widgets.cookbook import MultiListbox
5 from teamwork.widgets.images import getImage
6 from teamwork.widgets.attribute import AttributeDialog
7 from teamwork.widgets.PsychGUI.TurnDialog import TurnDialog
8 from teamwork.math.KeyedVector import KeyedVector
9 from teamwork.agent.lightweight import PWLAgent
10 import random
11 random.seed()
12 import string
13
15
17 optiondefs = (
18 ('balloon',None,Pmw.INITOPT),
19 ('command',None,None),
20 ('generic',False,None),
21 ('society',{},None),
22 ('expert', False,self.setExpert),
23 ('actions',None,None),
24 )
25 self.defineoptions(kw, optiondefs)
26 self.entity = entity
27 self.selected = None
28 self.lists = {}
29 Pmw.ScrolledFrame.__init__(self,parent)
30 if self.entity.policy:
31 g = Pmw.Group(self.interior(),tag_text='Edit Rule Conditions')
32
33 button = Button(g.interior(),text='Auto-generate Conditions',
34 width=32)
35 button.grid(row=0,column=0,padx=5,pady=5,sticky='ew')
36 button.configure(command=self.generateLHS)
37 if isinstance(self.entity,PWLAgent):
38 button.configure(state='disabled')
39 if self['balloon']:
40 msg = 'Automatically generate the possible situations for '\
41 'this agent to consider.'
42 self['balloon'].bind(button,msg)
43
44 button = Button(g.interior(),text='Add Condition...',width=32)
45 button.grid(row=1,column=0,padx=5,pady=5,sticky='ew')
46 button.configure(command=self.newAttribute)
47 if self['balloon']:
48 msg = 'Add an additional condition to the left-hand side '\
49 'of the rules.'
50 self['balloon'].bind(button,msg)
51
52 button = self.createcomponent('delete',(),None,Button,
53 (g.interior(),),
54 text='Delete Condition',width=32,
55 state='disabled')
56 button.grid(row=2,column=0,padx=5,pady=5,sticky='ew')
57 button.configure(command=self.delAttribute)
58 if self['balloon']:
59 msg = 'Removes the selected condition from the left-hand '\
60 'side of the rules.'
61 self['balloon'].bind(button,msg)
62 g.grid(row=0,column=0,sticky='nsew')
63 g = Pmw.Group(self.interior(),tag_text='Edit Rule Actions')
64
65 self.horizon = self.createcomponent('Horizon',
66 (),None,Pmw.Counter,
67 (g.interior(),),
68 labelpos='w',
69 label_text='Horizon:',)
70 button = self.horizon.component('entryfield')
71 button.configure(modifiedcommand=self.getHorizon,
72 validate={'validator':'integer','min':1},
73 )
74 button.setentry(self.entity.policy.horizon)
75 self.horizon.grid(row=0,column=0,padx=5,pady=5,sticky='ew')
76 if self['balloon']:
77 msg = 'The number of turns into the future this agent '\
78 'considers when choosing an action.'
79 self['balloon'].bind(self.horizon,msg)
80
81 button = Button(g.interior(),text='Optimize Actions',width=32)
82 button.grid(row=1,column=0,padx=5,pady=5,sticky='ew')
83 button.configure(command=self.policyIteration)
84 if self['balloon']:
85 msg = 'Generate a human-readable specification of this '\
86 'agent\'s behavior, over all possible situations.'
87 self['balloon'].bind(button,msg)
88
89 button = Button(g.interior(),text='Randomize Actions',width=32)
90 button.grid(row=2,column=0,padx=5,pady=5,sticky='ew')
91 button.configure(command=self.seed)
92 if self['balloon']:
93 msg = 'Seed the rules with a random initial set of actions.'
94 self['balloon'].bind(button,msg)
95
96 button = Button(g.interior(),text='View Current Action',width=32)
97 button.grid(row=3,column=0,padx=5,pady=5,sticky='ew')
98 button.configure(command=self.open)
99 if self['balloon']:
100 msg = 'Opens a dialog box for viewing or editing the action ranking that will be applied in the current state.'
101 self['balloon'].bind(button,msg)
102 g.grid(row=0,column=1,sticky='nsew')
103
104 widget = self.createcomponent('Policy',(),None,MultiListbox,
105 (self.interior(),
106 [('Action',32)]),
107 rowselectcommand=self.clickRow,
108 colselectcommand=self.clickCol,
109 doublecommand=self.double,
110 )
111 widget.grid(row=1,column=0,columnspan=2,sticky='snew')
112 self.interior().columnconfigure(0,weight=1)
113 self.interior().columnconfigure(1,weight=1)
114 self.interior().rowconfigure(1,weight=1)
115 self.createcomponent('new attribute',(),None,AttributeDialog,
116 (self.interior(),self.entity),
117 title='New Policy Attribute',
118 command=self.addAttribute,
119 buttons=('OK','Cancel'),
120 ).withdraw()
121 self.createcomponent('order',(),None,TurnDialog,
122 (self.interior(),),
123 serial=True,editor_editable=True,
124 title='Policy of %s' % (self.entity.ancestry()),
125 command=self.setOrder).withdraw()
126 self.initialiseoptions()
127 if len(self.entity.policy.attributes) > 0:
128 self.displayPolicy()
129
132
134 if self['actions']:
135 options = self['actions'].getActions()
136 else:
137 options = self.entity.actions.getOptions()
138 if len(options) == 0:
139 tkMessageBox.showerror('Agent Action Error','The agent has no allowable actions! Please go to the Action pane and select at least one possible choice.')
140 return options
141
153
155 if len(self.entity.policy.attributes) == 0:
156 tkMessageBox.showerror('Empty Policy','Please add some conditions (either manually or automatically) first!')
157 elif self['command']:
158 self['command'](self.entity)
159
198
204
206 """Activates dialog for adding a new attribute
207 """
208 self.component('new attribute').activate()
209
232
234 """Removes the selected attribute from the LHS
235 """
236 assert self.selected is not None
237 policy = self.entity.policy
238 for index in range(len(policy.attributes)):
239 obj,values = policy.attributes[index]
240 if obj.simpleText() == self.selected:
241 break
242 else:
243 raise UserWarning,'Trying to delete unknown attribute: %s' % \
244 (self.selected)
245 del policy.attributes[index]
246 self.component('Policy').delList(self.selected)
247 self.component('delete').configure(state='disabled')
248 self.selected = None
249 self.displayPolicy()
250 self.propAttributes()
251
253 widget = self.component('Policy')
254 msg = attr.simpleText()
255 widget.addList(msg,16)
256 self.lists[msg] = index
257 if self['balloon']:
258 self['balloon'].bind(widget.component('label %s' % (msg)),msg)
259
261 """Sets all of the agents in this entity's beliefs to use the current LHS attributes
262 """
263 entities = self.entity.entities.activeMembers()
264 root = self.entity
265 while root.parent:
266 root = root.parent
267 while len(entities) > 0:
268 entity = entities.pop()
269 entities += entity.entities.activeMembers()
270 entity.policy.attributes = []
271 for obj,values in self.entity.policy.attributes:
272 entity.policy.attributes.append((obj,values[:]))
273 entity.policy.rules = []
274 entity.policy.initialize()
275 label = '%s Policy' % (entity.ancestry())
276 try:
277 widget = root.attributes['window'].component(label)
278 except KeyError:
279 widget = None
280 if widget:
281 widget.displayPolicy()
282
284 self.component('delete').configure(state='disabled')
285 self.selected = None
286
288 self.component('delete').configure(state='normal')
289 self.selected = col
290
291 - def double(self,row,event=None):
292 root = self.entity
293 while root.parent:
294 root = root.parent
295 window = root.attributes['window']
296 if self.entity.parent:
297 options = window.component('%s Actions' % (self.entity.ancestry())).getActions()[:]
298 else:
299 options = window.component('Actions').getActions()[:]
300 rules = self.entity.policy.rules
301 if rules[row] is None:
302 rhs = options
303 else:
304 rhs = rules[row][:]
305 try:
306 try:
307 values = self.entity.policy.values[row]
308 except KeyError:
309 values = {}
310 for index in range(len(rhs)):
311 option = rhs[index]
312 try:
313 value = values[self.entity.name][str(option)]
314 except KeyError:
315 value = None
316 rhs[index] = str(option)
317 if not value is None:
318 rhs[index] += ' (%5.3f)' % (str(value))
319 try:
320 options[options.index(option)] = rhs[index]
321 except ValueError:
322 print self.entity.ancestry(),option
323 raise ValueError
324 except IndexError:
325 pass
326 dialog = self.component('order')
327 dialog.configure(elements=options,order=rhs)
328 dialog.activate()
329
338
340 dialog = self.component('order')
341 if button == 'OK':
342 for row in self.component('Policy').curselection():
343 order = dialog.cget('order')
344 if isinstance(order[0],str):
345
346 for index in range(len(order)):
347 for option in self.entity.actions.getOptions():
348 if str(option) == order[index]:
349 break
350 else:
351 raise NameError,'Unknown action: %s' % (order[index])
352 order[index] = option
353 if int(row) < len(self.entity.policy.values):
354 order = map(lambda l:l[:l.rfind('(')-1],order)
355 rhs = self.entity.policy.rules[int(row)]
356 for option in rhs:
357 rhs[order.index(str(option))] = option
358 else:
359 self.entity.policy.rules[int(row)] = order[:]
360 self.displayPolicy()
361 self.component('Policy').selection_set(row)
362 dialog.deactivate()
363
380
381 - def unpost(self,event):
382 event.widget.unpost()
383