Package spade :: Module bdi
[hide private]
[frames] | no frames]

Source Code for Module spade.bdi

  1  from logic import * 
  2  from copy import copy 
  3  import types 
  4  import random 
  5   
  6  import Behaviour 
  7  import tbcbp 
  8  import DF 
  9  from FlexQueue import FlexQueue 
 10  from Queue import Queue 
 11   
12 -class PreConditionFailed (Exception): pass
13 -class PostConditionFailed(Exception): pass
14 -class ServiceFailed(Exception): pass
15
16 -class Goal:
17 18 types = ["achieve","mantain","cease","query","perform"] 19
20 - def __init__(self, expression, typ="achieve"):
21 self.type = typ 22 self.expression = expression 23 self.persistent = False 24 self.priority = 0 25 self.selected = False 26 self.unreachable = False 27 self.done = False
28
29 - def testConflict(self, goal):
30 # No conflict test at the moment 31 return False
32
33 - def __str__(self):
34 if self.unreachable: 35 return "UNREACHABLE("+str(self.expression)+")" 36 elif self.done: 37 return "DONE("+str(self.expression)+")" 38 else: 39 return str(self.expression)
40
41 - def __repr__(self):
42 return self.__str__()
43 44
45 -class PlanList(dict):
46 #plans hash table. PID is the PlanID
47 - def add(self, plan):
48 pid = random.randint(1,100000000) 49 while self.has_key(pid): 50 pid = random.randint(1,100000000) 51 self[pid]=plan 52 plan.pid = pid 53 return pid
54 55 56 #class BDIAgent(Agent.Agent):
57 -class BDIBehaviour(Behaviour.PeriodicBehaviour):
58 59 #def __init__(self,agentjid, password, port=5222, debug=[], p2p=False): 60 # Agent.Agent.__init__(self,agentjid, password, port=port, debug=debug, p2p=p2p)
61 - def __init__(self, period):
62 Behaviour.PeriodicBehaviour.__init__(self, period) 63 self.goals = [] # active goals 64 self.plans = PlanList() # plan library 65 self.intentions = [] # selected plans for execution 66 #self.services = [] # services offered by the agent 67 self.TBCBP = tbcbp.TBCBP() 68 self.active_goals = FlexQueue() 69 self.prepared_goals = FlexQueue() 70 self.scheduler = Queue() 71 72 self._needDeliberate = True
73
74 - def configureKB(self, typ, sentence=None, path=None):
75 self.myAgent.kb.configure(typ,sentence,path)
76
77 - def addBelieve(self, sentence, type="insert"):
78 self.myAgent.addBelieve(sentence,type) 79 self._needDeliberate = True
80
81 - def removeBelieve(self, sentence, type="delete"):
82 self.myAgent.removeBelieve(sentence,type)
83
84 - def askBelieve(self, sentence):
85 return self.myAgent.askBelieve(sentence)
86
87 - def saveFact(self, name, sentence):
88 self.myAgent.kb.set(name, sentence) 89 self._needDeliberate = True
90
91 - def getFact(self, name):
92 return self.myAgent.kb.get(name)
93
94 - def addPlan(self, P,Q,inputs, outputs, services):
95 '''Adds a new plan to the Planner (TBCBP) 96 Usage: addPlan (P, Q, services) 97 P - precondition of the plan 98 Q - postcondition of the plan 99 services - list of services names (strings) 100 101 Return: None''' 102 cases=[] 103 for s in services: 104 c = self.TBCBP.getCaseOfService(str(s)) 105 if c==None: 106 self.myAgent.DEBUG("Plan was not added. Service "+str(s) + " does not exist.","err",'bdi') 107 return False 108 cases.append(c) 109 110 plan = tbcbp.Plan(cases) 111 self.TBCBP.addPlan(plan) 112 self.myAgent.DEBUG("Plan added: "+str(plan),"ok",'bdi') 113 self._needDeliberate = True 114 return True
115
116 - def addGoal(self, goal):
117 #First add the goal if no conflicts 118 if goal not in self.goals: 119 conflict = False 120 for g in self.goals: 121 if g.testConflict(goal): 122 conflict = True 123 break 124 if not conflict and self.askBelieve(goal.expression)==False: 125 self.myAgent.DEBUG("Goal added: "+str(goal),"ok", 'bdi') 126 self.goals.append(goal) 127 self._needDeliberate = True
128
129 - def registerServiceInTBCBP(self, service, time=1):
130 '''Registers new service in the Planner (TBCBP) 131 Usage: registerService(service, time) 132 service - A DF.Service class 133 time - the estimated execution time of the service (optional) 134 135 Returns: None''' 136 137 self.TBCBP.registerService(service=service,time=time) 138 self._needDeliberate = True
139
140 - def unregisterServiceInTBCBP(self, name=None, service=None):
141 if not name: name= service.getName() 142 self.TBCBP.delService(name) 143 self._needDeliberate = True
144
145 - def getPlan(self, goal):
146 '''Finds a plan for a specified goal. 147 If there is not an existing plan, it composes a new one (when possible) 148 Usage getPlan( goal ) 149 goal - a Goal object to be achieved 150 151 Returns: TBCBP.Plan object or None is there is no available plan''' 152 153 self.myAgent.DEBUG("Composing a plan for goal "+str(goal),'info','bdi') 154 plan = self.composePlan(goal) 155 156 if plan == None: 157 #goal is unreachable 158 self.myAgent.DEBUG("No plan found for Goal "+str(goal), 'warn','bdi') 159 return None 160 161 plan['index'] = 0 162 plan['goal'] = goal 163 plan.agent_owner = self.myAgent 164 return plan
165
166 - def composePlan(self, goal, tout=-1):
167 ''' 168 calls the Temporal-Bounded Case Based Planner 169 ''' 170 return self.TBCBP.composePlan(goal,self.myAgent.kb,tout=20)
171
172 - def selectIntentions(self):
173 ''' 174 Prepares new plan for active goals 175 Looks for all prepared goals and selects a new plan for it. 176 then the goal is archived in prepared_goals 177 and the plan is stored in self.plans 178 ''' 179 180 #while not self.prepared_goals.empty(): #return 181 goal = self.prepared_goals.get() 182 self.myAgent.DEBUG("Got goal "+ str(goal),'info','bdi') 183 184 if goal!=None: 185 if self.askBelieve(goal.expression)==True: 186 goal.done=True 187 return None #continue 188 if goal in self.active_goals: return None #continue 189 190 self.myAgent.DEBUG("Activate Goal: " + str(goal), 'info','bdi') 191 plan = self.getPlan(goal) 192 if plan!=None: 193 #activate plan 194 self.myAgent.DEBUG("Got a plan for goal " + str(goal), 'info','bdi') 195 goal.selected = True 196 self.active_goals.put(goal) 197 plan.agent = self 198 #init plan 199 pid = self.plans.add(plan) 200 #activate first service 201 self.insertNextService(plan,pid) 202 self.planSelectedCB(plan) 203 else: 204 goal.unreachable = True 205 self.myAgent.DEBUG("Goal is Unreachable: "+str(goal), 'warn','bdi') 206 return None
207
208 - def insertNextService(self,plan,pid):
209 '''Selects the next service of a plan to be executed 210 Usage: insertNextService( plan, pid) 211 plan - the running plan (TBCBP.Plan) 212 pid - the plan identifier''' 213 214 service_name = plan.getNextService() 215 self.myAgent.DEBUG("next service is " + str(service_name),'info','bdi') 216 if service_name == None: 217 self.EndPlan(pid, plan) 218 return 219 service = self.TBCBP.getService(service_name) 220 if service: 221 service.pid = pid 222 service.agent_owner = self 223 224 self.scheduler.put(service) 225 226 else: #plan has finished 227 self.EndPlan(pid, plan)
228
229 - def EndPlan(self,pid,plan):
230 '''Finishes the execution of a plan. 231 If the plan run well, its case is rewarded. Otherwise, it is punished. 232 Finally goal is setted as done and not active. 233 Usage: EndPlan ( pid, plan) 234 pid - Plan identifier 235 plan - TBCBP.Plan object 236 ''' 237 del self.plans[pid] 238 #check its postcondition 239 if len(plan.getQ()) > 0 and self.askBelieve(plan.getQ()[0])==False: 240 #logging.error(color_red+"PLAN FAILED "+str(plan)+color_none) 241 self.TBCBP.punish(plan.getCase()) 242 for goal in self.goals: #deselect the goal that raised the plan 243 if goal.expression == plan.getQ(): 244 goal.selected = False 245 goal.done = False 246 self.active_goals.remove(goal) 247 else: 248 self.TBCBP.reward(plan.getCase()) 249 self.myAgent.DEBUG("Rewarding Plan",'ok','bdi') 250 for goal in self.goals: #delete the goal that raised the intention 251 if goal.expression in plan.getQ(): 252 if goal.persistent: #if goal is persistent, deselect it 253 self.prepared_goals.put(goal) 254 self.active_goals.remove(goal) 255 goal.done = True 256 goal.selected = False 257 self.myAgent.DEBUG("Goal "+str(goal.expression)+" was completed!",'ok','bdi') 258 self.myAgent.DEBUG("Calling goal completed CB: "+ str(self.goalCompletedCB),'info','bdi') 259 self.goalCompletedCB(goal)
260
261 - def EndService(self,service,plan):
262 '''Finishes the execution of a service. 263 If the service failed, it is punished and the plan is finished. 264 Otherwise, the next service of the plan is selected. 265 Usage: EndService ( service, plan) 266 service - the current running DF.Service 267 plan - the TBCBP.Plan where the service belongs 268 ''' 269 270 agent = self 271 pid = plan.pid 272 #service has been executed 273 if len(service.getQ()) > 0 and self.askBelieve(service.getQ()[0])==False: 274 #service failed 275 self.myAgent.DEBUG("Service execution failed: "+str(service.getQ())) 276 self.punishService(service) 277 #cancel plan and reactivate goal 278 self.EndPlan(pid,plan) 279 return 280 281 #5.2.1 select next service 282 self.insertNextService(plan, pid) 283 284 self.serviceCompletedCB(service)
285
286 - def deliberate(self):
287 self.myAgent.DEBUG("deliberate about current goals: "+str(self.goals),'info','bdi') 288 for goal in self.goals: 289 if (goal.unreachable == False) and (goal.done==False): # or ((goal.done==True) and (goal.persistent==True))): 290 if self.askBelieve(goal.expression)==False: 291 self.myAgent.DEBUG("Deliberate about " + str(goal),'info','bdi') 292 if goal not in self.active_goals: 293 self.prepared_goals.put(goal) 294 else: 295 self.myAgent.DEBUG("Goal " + str(goal) + "is already in the KB: " + str(self.askBelieve(goal.expression)),'warn','bdi') 296 goal.done = True
297 298
299 - def discover(self):
300 #TODO: use PubSub features 301 s = DF.Service() 302 results = self.myAgent.searchService(s) 303 if results!=None: 304 self.myAgent.DEBUG("Discovered "+str(len(results))+ " services.", 'info','bdi') 305 for service in results: 306 if self.TBCBP.getService(service.getName()) == None: 307 self.registerServiceInTBCBP(service)
308
309 - def punishService(self, service):
310 P = service.getP() 311 Q = service.getQ() 312 I = service.getInputs() 313 O = service.getOutputs() 314 self.TBCBP.punish(Case(P=P,Q=Q,inputs=I,outputs=O,services=[service.getName()])) 315 return
316 317 318 ####Init The agent 319 ###self._setup() 320 ###self.behavioursGo.acquire() 321 ###self._running = True 322 ###self.behavioursGo.notifyAll() 323 ###self.behavioursGo.release() 324 325 ############# 326 # Main Loop # 327 ############# 328 ###while not self.forceKill(): 329 ### try: 330 ### #get and process all messages 331 ### self.getMessages() 332
333 - def _onTick(self):
334 """ 335 periodic behaviour execution 336 """ 337 #discover new services 338 self.myAgent.DEBUG("Discover new services...", 'info','bdi') 339 self.discover() 340 341 #deliberate about current goals 342 #if self._needDeliberate: 343 self.myAgent.DEBUG("Deliberating...", 'info','bdi') 344 self.deliberate() 345 #self._needDeliberate = False 346 347 #select intentions 348 self.DEBUG("select intentions", 'info','bdi') 349 self.selectIntentions() 350 351 self.myAgent.DEBUG("Init scheduler", 'info','bdi') 352 #run a service each iteration 353 if not self.scheduler.empty(): 354 service = self.scheduler.get() 355 self.myAgent.DEBUG("Got service for execution: " + str(service),'info','bdi') 356 357 #if service!=None: 358 pid = service.pid 359 plan = self.plans[pid] 360 try: 361 result = self.myAgent.invokeService(service) 362 except: 363 self.myAgent.DEBUG("Service failed!", 'warn','bdi') 364 365 self.EndService(service, plan) 366 else: 367 self.myAgent.DEBUG("NOP", 'info', 'bdi') 368 369 self.myAgent.DEBUG("Restarting BDI cycle", 'info','bdi')
370 371
372 - def planSelectedCB(self, plan):
373 #callback executed when a new plan is selected for execution 374 #must be overloaded 375 pass
376 - def goalCompletedCB(self, goal):
377 #callback executed when a goal is completed succesfully 378 #must be overloaded 379 pass
380 - def serviceCompletedCB(self, service):
381 #callback executed when a service is completed succesfully 382 #must be overloaded 383 pass
384