Revision: 2243
Author: jpalanca
Date: Tue Jul 31 06:58:54 2012
Log: (1) RPC module now has preconditions, postconditions, inputs and
outputs. outputs are stored in the agent's KB and inputs can be retrieved
from the agent's KB too.
(2) created kb module. agents can save variables in its KB using
kb.set(varname,value) and kb.get(varname).
(3) added new unittests for the kb component. assert raises executable not
found exceptions when needed.
(4) added new unittests for the tbcbp component. this is a Case-Based
Planner for the bdi agents.
(5) added the new BDI agents. At this moment they are tested only with the
SpadeKB knowledge base.
(6) solved some unittests whose behaviour have changed with the new bdi
agents (df tests, rpc tests, ...).
(7) added some helper classes: dblite, FlexQueue and odict.
http://code.google.com/p/spade2/source/detail?r=2243
Added:
/trunk/DEPENDENCIES.txt
/trunk/examples/bdi
/trunk/examples/bdi/clientBDI.py
/trunk/examples/bdi/server1BDI.py
/trunk/examples/bdi/server2BDI.py
/trunk/spade/FlexQueue.py
/trunk/spade/dblite.py
/trunk/spade/kb.py
/trunk/spade/odict.py
/trunk/spade/tbcbp.py
/trunk/test/factsTestCase.py
/trunk/test/tbcbpTestCase.py
Modified:
/trunk/ChangeLog
/trunk/spade/Agent.py
/trunk/spade/DF.py
/trunk/spade/RPC.py
/trunk/spade/bdi.py
/trunk/spade/logic.py
/trunk/test/basicTestCase.py
/trunk/test/bdiTestCase.py
/trunk/test/dfTestCase.py
/trunk/test/kbTestCase.py
/trunk/test/p2pTestCase.py
/trunk/test/pubsubTestCase.py
/trunk/test/rpcTestCase.py
/trunk/test.py
=======================================
--- /dev/null
+++ /trunk/DEPENDENCIES.txt Tue Jul 31 06:58:54 2012
@@ -0,0 +1,2 @@
+pexpect
+SPARQLWrapper
=======================================
--- /dev/null
+++ /trunk/examples/bdi/clientBDI.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,48 @@
+#####################################
+# BDI EXAMPLE #
+#####################################
+'''
+This file shows a simple client agent which
+activates a Goal to be pursued.
+The needed services are provided by the two
+agents contained in server1BDI.py and server2BDI.py
+This agent uses a BDI Behaviour
+You need to be running a SPADE platform host
+'''
+import os
+import sys
+import unittest
+sys.path.append('../..')
+sys.path.append('..')
+
+import spade
+from spade.bdi import Goal
+from spade.Agent import BDIAgent
+
+def MygoalCompletedCB(goal):
+ global goalCompleted
+ goalCompleted = True
+
+
+host = "127.0.0.1"
+
+a = BDIAgent("clientbdi@"+host,"secret")
+a.setDebugToScreen()
+a.start()
+
+goalCompleted=False
+
+a.saveFact("Value",0)
+
+a.setGoalCompletedCB(MygoalCompletedCB)
+
+a.addGoal(Goal("Var(Myoutput2,2,Int)"))
+
+import time
+counter = 0
+while not goalCompleted and counter<10:
+ time.sleep(1)
+ counter+=1
+
+a.stop()
+sys.exit()
=======================================
--- /dev/null
+++ /trunk/examples/bdi/server1BDI.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,45 @@
+#####################################
+# BDI EXAMPLE #
+#####################################
+'''
+This file presents a server agent for the bdi example
+It serves a service called "s1", which is registered in the DF
+You need to be running a SPADE platform host
+'''
+import os
+import sys
+import unittest
+sys.path.append('../..')
+sys.path.append('..')
+
+import spade
+from spade.Agent import Agent
+
+def s1_method(Value):
+ return {"Myoutput1":1}
+
+host = "127.0.0.1"
+
+a = Agent("server1bdi@"+host,"secret")
+a.setDebugToScreen()
+a.start()
+
+s1 = spade.DF.Service(name="s1", owner=a.getAID(),
inputs=["Value"],outputs=["Myoutput1"],P=["Var(Value,0,Int)"],Q=["Var(Myoutput1,1,Int)"])
+
+a.registerService(s1,s1_method)
+
+import time
+tmp=True
+while tmp:
+ try:
+ time.sleep(5)
+ except:
+ tmp=False
+
+s = spade.DF.Service()
+s.setOwner(a.getAID())
+a.deregisterService(s)
+
+a.stop()
+sys.exit()
+
=======================================
--- /dev/null
+++ /trunk/examples/bdi/server2BDI.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,45 @@
+#####################################
+# BDI EXAMPLE #
+#####################################
+'''
+This file presents a server agent for the bdi example
+It serves a service called "s2", which is registered in the DF
+You need to be running a SPADE platform host
+'''
+import os
+import sys
+import unittest
+sys.path.append('../..')
+sys.path.append('..')
+
+import spade
+from spade.Agent import Agent
+
+def s2_method(Myoutput1):
+ return {"Myoutput2":2}
+
+host = "127.0.0.1"
+
+a = Agent("server2bdi@"+host,"secret")
+a.setDebugToScreen()
+a.start()
+
+s2 = spade.DF.Service(name="s2", owner=a.getAID(),
inputs=["Myoutput1"],outputs=["Myoutput2"],P=["Var(Myoutput1,1,Int)"],Q=["Var(Myoutput2,2,Int)"])
+
+a.registerService(s2,s2_method)
+
+import time
+tmp=True
+while tmp:
+ try:
+ time.sleep(5)
+ except:
+ tmp=False
+
+s = spade.DF.Service()
+s.setOwner(a.getAID())
+a.deregisterService(s)
+
+a.stop()
+sys.exit()
+
=======================================
--- /dev/null
+++ /trunk/spade/FlexQueue.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,22 @@
+class FlexQueue(list):
+
+ def empty(self):
+ if len(self)==0: return True
+ return False
+
+ def qsize(self):
+ return len(self)
+
+ def get(self):
+ if not self.empty():
+ ret = self[0]
+ self.remove(ret)
+ return ret
+ return None
+
+ def put(self, item):
+ self.append(item)
+
+ def remove(self, item):
+ if item in self:
+ list.remove(self,item)
=======================================
--- /dev/null
+++ /trunk/spade/dblite.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,362 @@
+## {{{
http://code.activestate.com/recipes/496770/ (r4)
+"""PyDbLite.py
+
+In-memory database management, with selection by list comprehension
+or generator expression
+
+Fields are untyped : they can store anything that can be pickled.
+Selected records are returned as dictionaries. Each record is
+identified by a unique id and has a version number incremented
+at every record update, to detect concurrent access
+
+Syntax :
+ from PyDbLite import Base
+ db = Base('dummy')
+ # create new base with field names
+ db.create('name','age','size')
+ # existing base
+ db.open()
+ # insert new record
+ db.insert(name='homer',age=23,size=1.84)
+ # records are dictionaries with a unique integer key __id__
+ # selection by list comprehension
+ res = [ r for r in db if 30 > r['age'] >= 18 and r['size'] < 2 ]
+ # or generator expression
+ for r in (r for r in db if r['name'] in ('homer','marge') ):
+ # simple selection (equality test)
+ res = db(age=30)
+ # delete a record or a list of records
+ db.delete(one_record)
+ db.delete(list_of_records)
+ # delete a record by its id
+ del db[rec_id]
+ # direct access by id
+ record = db[rec_id] # the record such that record['__id__'] == rec_id
+ # create an index on a field
+ db.create_index('age')
+ # access by index
+ records = db._age[23] # returns the list of records with age == 23
+ # update
+ db.update(record,age=24)
+ # add and drop fields
+ db.add_field('new_field')
+ db.drop_field('name')
+ # save changes on disk
+ db.commit()
+"""
+
+import os
+import cPickle
+import bisect
+
+# compatibility with Python 2.3
+try:
+ set([])
+except NameError:
+ from sets import Set as set
+
+class Index:
+ """Class used for indexing a base on a field
+ The instance of Index is an attribute the Base instance"""
+
+ def __init__(self,db,field):
+ self.db = db # database object (instance of Base)
+ self.field = field # field name
+
+ def __iter__(self):
+ return iter(self.db.indices[self.field])
+
+ def keys(self):
+ return self.db.indices[self.field].keys()
+
+ def __getitem__(self,key):
+ """Lookup by key : return the list of records where
+ field value is equal to this key, or an empty list"""
+ ids = self.db.indices[self.field].get(key,[])
+ return [ self.db.records[_id] for _id in ids ]
+
+class Base:
+
+ def __init__(self,basename):
+
self.name = basename
+
+ def create(self,*fields,**kw):
+ """Create a new base with specified field names
+ A keyword argument mode can be specified ; it is used if a file
+ with the base name already exists
+ - if mode = 'open' : open the existing base, ignore the fields
+ - if mode = 'override' : erase the existing base and create a
+ new one with the specified fields"""
+ self.mode = mode = kw.get("mode",None)
+ if os.path.exists(
self.name):
+ if not os.path.isfile(
self.name):
+ raise IOError,"%s exists and is not a file" %
self.name
+ elif mode is None:
+ raise IOError,"Base %s already exists" %
self.name
+ elif mode == "open":
+ return self.open()
+ elif mode == "override":
+ os.remove(
self.name)
+ self.fields = list(fields)
+ self.records = {}
+ self.next_id = 0
+ self.indices = {}
+ self.commit()
+ return self
+
+ def create_index(self,*fields):
+ """Create an index on the specified field names
+
+ An index on a field is a mapping between the values taken by the
field
+ and the sorted list of the ids of the records whose field is equal
to
+ this value
+
+ For each indexed field, an attribute of self is created, an
instance
+ of the class Index (see above). Its name it the field name, with
the
+ prefix _ to avoid name conflicts
+ """
+ reset = False
+ for f in fields:
+ if not f in self.fields:
+ raise NameError,"%s is not a field name" %f
+ # initialize the indices
+ if self.mode == "open" and f in self.indices:
+ continue
+ reset = True
+ self.indices[f] = {}
+ for _id,record in self.records.iteritems():
+ # use bisect to quickly insert the id in the list
+ bisect.insort(self.indices[f].setdefault(record[f],[]),
+ _id)
+ # create a new attribute of self, used to find the records
+ # by this index
+ setattr(self,'_'+f,Index(self,f))
+ if reset:
+ self.commit()
+
+ def open(self):
+ """Open an existing database and load its content into memory"""
+ _in = open(
self.name) # don't specify binary mode !
+ self.fields = cPickle.load(_in)
+ self.next_id = cPickle.load(_in)
+ self.records = cPickle.load(_in)
+ self.indices = cPickle.load(_in)
+ for f in self.indices.keys():
+ setattr(self,'_'+f,Index(self,f))
+ _in.close()
+ self.mode = "open"
+ return self
+
+ def commit(self):
+ """Write the database to a file"""
+ out = open(
self.name,'wb')
+ cPickle.dump(self.fields,out)
+ cPickle.dump(self.next_id,out)
+ cPickle.dump(self.records,out)
+ cPickle.dump(self.indices,out)
+ out.close()
+
+ def insert(self,*args,**kw):
+ """Insert a record in the database
+ Parameters can be positional or keyword arguments. If positional
+ they must be in the same order as in the create() method
+ If some of the fields are missing the value is set to None
+ Returns the record identifier
+ """
+ if args:
+ kw = dict([(f,arg) for f,arg in zip(self.fields,args)])
+ # initialize all fields to None
+ record = dict([(f,None) for f in self.fields])
+ # set keys and values
+ for (k,v) in kw.iteritems():
+ record[k]=v
+ # add the key __id__ : record identifier
+ record['__id__'] = self.next_id
+ # add the key __version__ : version number
+ record['__version__'] = 0
+ # create an entry in the dictionary self.records, indexed by __id__
+ self.records[self.next_id] = record
+ # update index
+ for ix in self.indices.keys():
+ bisect.insort(self.indices[ix].setdefault(record[ix],[]),
+ self.next_id)
+ # increment the next __id__ to attribute
+ self.next_id += 1
+ return record['__id__']
+
+ def delete(self,removed):
+ """Remove a single record, or the records in an iterable
+ Before starting deletion, test if all records are in the base
+ and don't have twice the same __id__
+ Return the number of deleted items
+ """
+ if isinstance(removed,dict):
+ # remove a single record
+ removed = [removed]
+ else:
+ # convert iterable into a list (to be able to sort it)
+ removed = [ r for r in removed ]
+ if not removed:
+ return 0
+ _ids = [ r['__id__'] for r in removed ]
+ _ids.sort()
+ keys = set(self.records.keys())
+ # check if the records are in the base
+ if not set(_ids).issubset(keys):
+ missing = list(set(_ids).difference(keys))
+ raise IndexError,'Delete aborted. Records with these ids' \
+ ' not found in the base : %s' %str(missing)
+ # raise exception if duplicate ids
+ for i in range(len(_ids)-1):
+ if _ids[i] == _ids[i+1]:
+ raise IndexError,"Delete aborted. Duplicate
id : %s" %_ids[i]
+ deleted = len(removed)
+ while removed:
+ r = removed.pop()
+ _id = r['__id__']
+ # remove id from indices
+ for indx in self.indices.keys():
+ pos = bisect.bisect(self.indices[indx][r[indx]],_id)-1
+ del self.indices[indx][r[indx]][pos]
+ if not self.indices[indx][r[indx]]:
+ del self.indices[indx][r[indx]]
+ # remove record from self.records
+ del self.records[_id]
+ return deleted
+
+ def update(self,record,**kw):
+ """Update the record with new keys and values and update indices"""
+ # update indices
+ _id = record["__id__"]
+ for indx in self.indices.keys():
+ if indx in kw.keys():
+ if record[indx] == kw[indx]:
+ continue
+ # remove id for the old value
+ old_pos =
bisect.bisect(self.indices[indx][record[indx]],_id)-1
+ del self.indices[indx][record[indx]][old_pos]
+ if not self.indices[indx][record[indx]]:
+ del self.indices[indx][record[indx]]
+ # insert new value
+
bisect.insort(self.indices[indx].setdefault(kw[indx],[]),_id)
+ # update record values
+ record.update(kw)
+ # increment version number
+ record["__version__"] += 1
+
+ def add_field(self,field,default=None):
+ if field in self.fields + ["__id__","__version__"]:
+ raise ValueError,"Field %s already defined" %field
+ for r in self:
+ r[field] = default
+ self.fields.append(field)
+ self.commit()
+
+ def drop_field(self,field):
+ if field in ["__id__","__version__"]:
+ raise ValueError,"Can't delete field %s" %field
+ self.fields.remove(field)
+ for r in self:
+ del r[field]
+ if field in self.indices:
+ del self.indices[field]
+ self.commit()
+
+ def __call__(self,**kw):
+ """Selection by field values
+ db(key=value) returns the list of records where r[key] = value"""
+ for key in kw:
+ if not key in self.fields:
+ raise ValueError,"Field %s not in the database" %key
+ def sel_func(r):
+ for key in kw:
+ if not r[key] == kw[key]:
+ return False
+ return True
+ return [ r for r in self if sel_func(r) ]
+
+ def __getitem__(self,record_id):
+ """Direct access by record id"""
+ return self.records[record_id]
+
+ def __len__(self):
+ return len(self.records)
+
+ def __delitem__(self,record_id):
+ """Delete by record id"""
+ self.delete(self[record_id])
+
+ def __iter__(self):
+ """Iteration on the records"""
+ return self.records.itervalues()
+
+if __name__ == '__main__':
+ # test on a 1000 record base
+ import random
+ import datetime
+ names = ['pierre','claire','simon','camille','jean',
+ 'florence','marie-anne']
+ db = Base('PyDbLite_test')
+ db.create('name','age','size','birth',mode="override")
+ for i in range(1000):
+ db.insert(name=unicode(random.choice(names)),
+ age=random.randint(7,47),size=random.uniform(1.10,1.95),
+ birth=datetime.date(1990,10,10))
+ db.create_index('age')
+ db.commit()
+
+ print 'Record #20 :',db[20]
+ print '\nRecords with age=30 :'
+ for rec in db._age[30]:
+ print '%-10s | %2s
| %s' %(rec['name'],rec['age'],round(rec['size'],2))
+
+ print "\nSame with __call__"
+ for rec in db(age=30):
+ print '%-10s | %2s
| %s' %(rec['name'],rec['age'],round(rec['size'],2))
+ print db._age[30] == db(age=30)
+
+ db.insert(name=unicode(random.choice(names))) # missing fields
+ print '\nNumber of records with 30 <= age < 33 :',
+ print sum([1 for r in db if 33 > r['age'] >= 30])
+
+ print db.delete([])
+
+ d = db.delete([r for r in db if 32> r['age'] >= 30 and
r['name']==u'pierre'])
+ print "\nDeleting %s records with name == 'pierre' and 30 <= age <
32" %d
+ print '\nAfter deleting records '
+ for rec in db._age[30]:
+ print '%-10s | %2s
| %s' %(rec['name'],rec['age'],round(rec['size'],2))
+ print '\n',sum([1 for r in db]),'records in the database'
+ print '\nMake pierre uppercase for age > 27'
+ for record in ([r for r in db if r['name']=='pierre' and r['age']
>27]) :
+ db.update(record,name=u"Pierre")
+ print len([r for r in db if r['name']==u'Pierre']),'Pierre'
+ print len([r for r in db if r['name']==u'pierre']),'pierre'
+ print len([r for r in db if r['name'] in
[u'pierre',u'Pierre']]),'p/Pierre'
+ print 'is unicode :',isinstance(db[20]['name'],unicode)
+ db.commit()
+ db.open()
+ print '\nSame operation after commit + open'
+ print len([r for r in db if r['name']==u'Pierre']),'Pierre'
+ print len([r for r in db if r['name']==u'pierre']),'pierre'
+ print len([r for r in db if r['name'] in
[u'pierre',u'Pierre']]),'p/Pierre'
+ print 'is unicode :',isinstance(db[20]['name'],unicode)
+
+ print "\nDeleting record #20"
+ del db[20]
+ if not 20 in db:
+ print "record 20 removed"
+
+ print db[21]
+ db.drop_field('name')
+ print db[21]
+ db.add_field('adate',datetime.date.today())
+ print db[21]
+
+ k = db._age.keys()[0]
+ print "key",k
+ print k in db._age
+ db.delete(db._age[k])
+ print db._age[k]
+ print k in db._age
+## end of
http://code.activestate.com/recipes/496770/ }}}
=======================================
--- /dev/null
+++ /trunk/spade/kb.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,225 @@
+from logic import FolKB, fol_bc_ask, expr, is_definite_clause, variables
+
+import random
+import string
+import types
+
+class KBNameNotString(Exception): pass
+class KBValueNotKnown(Exception): pass
+
+class KBConfigurationFailed(Exception):
+ def __init__(self, msg=""):
+ self.msg = msg
+ def __str__(self):
+ return repr(self.msg)
+
+class SpadeKB(FolKB):
+ def tell(self, sentence):
+ if issubclass(sentence.__class__,str):
+ sentence = expr(sentence)
+ if is_definite_clause(sentence):
+ self.clauses.append(sentence)
+ else:
+ raise Exception("Not a definite clause: %s" % sentence)
+
+ def retract(self, sentence):
+ if issubclass(sentence.__class__,str):
+ sentence = expr(sentence)
+ self.clauses.remove(sentence)
+
+ def ask(self, q):
+ e = expr(q)
+ vars = variables(e)
+ ans = fol_bc_ask(self, [e])
+ res = []
+ for a in ans:
+ res.append(dict([(x, v) for (x, v) in a.items() if x in vars]))
+ res.sort(key=str)
+
+ if res==[]: return False
+ for r in res:
+ if r!={}:
+ return res
+ return True #res is a list of empty dicts
+
+ def _encode(self, key,value):
+ key = key.capitalize()
+ if issubclass(value.__class__, str):
+ self.tell("Var("+key+","+value.capitalize()+",Str)")
+
+ elif issubclass(value.__class__,int):
+ self.tell("Var("+key+","+str(value)+",Int)")
+
+ elif issubclass(value.__class__,float):
+ self.tell("Var("+key+","+str(value) + ",Float)")
+
+ elif issubclass(value.__class__,list):
+ listID
= ''.join(random.choice(string.ascii_uppercase+string.ascii_lowercase) for
x in range(8))
+ listID = listID.capitalize()
#listID.replace(listID[0],listID[0].lower(),1)
+ for elem in value:
+ self._encode(listID, elem)
+ self.tell("Var("+ key + ","+ listID +",List)")
+
+ elif issubclass(value.__class__,dict):
+ dictID
= ''.join(random.choice(string.ascii_uppercase+string.ascii_lowercase) for
x in range(8))
+ dictID = dictID.capitalize()
#listID.replace(listID[0],listID[0].lower(),1)
+ for k,v in value.items():
+ elemID
= ''.join(random.choice(string.ascii_uppercase+string.ascii_lowercase) for
x in range(8))
+ elemID = elemID.capitalize()
#elemID.replace(elemID[0],elemID[0].lower(),1)
+ self._encode(elemID+"Key",k)
+ self._encode(elemID+"Value",v)
+ self.tell("Pair("+dictID+","+elemID+")")
+ self.tell("Var("+key+","+dictID+",Dict)")
+
+ else:
+ raise KBValueNotKnown
+
+ def _decode(self, key):
+ gen = self._gen_decode(key)
+ try:
+ return gen.next()
+ except StopIteration:
+ return None
+
+ def _gen_decode(self, key):
+ key = key.capitalize()
+ results = self.ask("Var("+key+", value, type)")
+ if type(results)==types.BooleanType:
+ yield None
+ for res in results:
+ value = str(res[expr("value")])
+ typ = str(res[expr("type")])
+
+ if typ == "Int": yield int(value)
+ elif typ == "Str": yield str(value).lower()
+ elif typ == "Float": yield float(value)
+ elif typ == "List":
+ l = []
+ listID = str(value)
+ gen = self._gen_decode(listID)
+ hasElements=True
+ while hasElements:
+ try:
+ l.append(gen.next())
+ except:
+ hasElements=False
+ yield l
+ elif typ == "Dict":
+ dictID = str(value)
+ d = {}
+ for i in self.ask("Pair("+dictID+", elemid)"):
+ elemID = str(i[expr("elemid")])
+ newkey = self._gen_decode(elemID+"Key").next()
+ newvalue = self._gen_decode(elemID+"Value").next()
+ d[newkey] = newvalue
+ yield d
+
+
+
+
+class KB:
+
+ def __init__(self):
+ self.kb = SpadeKB()
+ self.type = "Spade"
+
+ def configure(self, typ, sentence=None, path=None):
+ """
+ Supported Knowledge Bases are:
["ECLiPSe", "Flora2", "SPARQL", "SWI", "XSB", "Spade"]
+ """
+ try:
+ if typ not in
["ECLiPSe", "Flora2", "SPARQL", "SWI", "XSB", "Spade"]:
+ raise KBConfigurationFailed(typ + " is not a valid KB.")
+ if typ=="Spade":
+ self.kb = SpadeKB()
+ return
+ elif typ=="SPARQL": import SPARQLKB
+ elif typ=="XSB": import XSBKB
+ elif typ=="Flora2": import Flora2KB
+ elif typ=="SWI": import SWIKB
+ elif typ=="ECLiPSe":import ECLiPSeKB
+ else: raise KBConfigurationFailed("Could not
import "+str(typ)+" KB.")
+
+ except KBConfigurationFailed as e:
+ #self.myAgent.DEBUG(str(e)+" Using Fol KB.", 'warn')
+ typ = "Spade"
+
+ self.type = typ
+ typ+="KB"
+
+ if typ=="SpadeKB":
+ self.kb = SpadeKB()
+ elif path!=None:
+ self.kb = eval(typ+"."+typ+"("+str(sentence)+", '"+path+"')")
+ else:
+ self.kb = eval(typ+"."+typ+"("+str(sentence)+")")
+
+ def tell(self, sentence):
+ return self.kb.tell(sentence)
+
+ def retract(self, sentence):
+ return self.kb.retract(sentence)
+
+ def ask(self, sentence):
+ return self.kb.ask(sentence)
+
+ def set(self, key, value):
+ if not issubclass(key.__class__, str):
+ raise KBNameNotString
+
+ self.kb._encode(key,value)
+
+ def get(self, key):
+ return self.kb._decode(key)
+
+
+if __name__ == "__main__":
+
+ kb0 = KB()
+
+ kb0.set("varname1",1234)
+ a = kb0.get("varname1")
+ print a, a.__class__
+
+ kb0.set("varname2","myString")
+ a = kb0.get("varname2")
+ print a, a.__class__
+
+ kb0.set("varname3",1.34)
+ a = kb0.get("varname3")
+ print a, a.__class__
+
+
+ kb0.set("varname4",[5,6,7,8])
+ a = kb0.get("varname4")
+ print a, a.__class__
+
+ kb0.set("varname5",[5,6.23,"7",[8,9]])
+ a = kb0.get("varname5")
+ print a, a.__class__
+
+ kb0.set("varname6",{'a':123,'b':456,789:"c"})
+ a = kb0.get("varname6")
+ print a, a.__class__
+
+ kb0.set("varname7",{'a':[123.25],'b':[4,5,6],789:{'a':1,'b':2}})
+ a = kb0.get("varname7")
+ print a, a.__class__
+
+ try:
+ kb0.set(123,"newvalue")
+ except KBNameNotString:
+ print "Test KBNameNotString passed."
+
+
+ class A: pass
+ try:
+ kb0.set("i8", A())
+ except KBValueNotKnown:
+ print "Test KBValueNotKnown passed."
+
+
+ a = kb0.get("varname9")
+ print a, a.__class__
+
+ #print kb0.kb.clauses
=======================================
--- /dev/null
+++ /trunk/spade/odict.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,328 @@
+# -*- coding: utf-8 -*-
+"""
+ odict
+ ~~~~~
+
+ This module is an example implementation of an ordered dict for the
+ collections module. It's not written for performance (it actually
+ performs pretty bad) but to show how the API works.
+
+
+ Questions and Answers
+ =====================
+
+ Why would anyone need ordered dicts?
+
+ Dicts in python are unordered which means that the order of items
when
+ iterating over dicts is undefined. As a matter of fact it is most
of
+ the time useless and differs from implementation to implementation.
+
+ Many developers stumble upon that problem sooner or later when
+ comparing the output of doctests which often does not match the
order
+ the developer thought it would.
+
+ Also XML systems such as Genshi have their problems with unordered
+ dicts as the input and output ordering of tag attributes is often
+ mixed up because the ordering is lost when converting the data into
+ a dict. Switching to lists is often not possible because the
+ complexity of a lookup is too high.
+
+ Another very common case is metaprogramming. The default namespace
+ of a class in python is a dict. With Python 3 it becomes possible
+ to replace it with a different object which could be an ordered
dict.
+ Django is already doing something similar with a hack that assigns
+ numbers to some descriptors initialized in the class body of a
+ specific subclass to restore the ordering after class creation.
+
+ When porting code from programming languages such as PHP and Ruby
+ where the item-order in a dict is guaranteed it's also a great help
+ to have an equivalent data structure in Python to ease the
transition.
+
+ Where are new keys added?
+
+ At the end. This behavior is consistent with Ruby 1.9 Hashmaps
+ and PHP Arrays. It also matches what common ordered dict
+ implementations do currently.
+
+ What happens if an existing key is reassigned?
+
+ The key is *not* moved. This is consitent with existing
+ implementations and can be changed by a subclass very easily::
+
+ class movingodict(odict):
+ def __setitem__(self, key, value):
+ self.pop(key, None)
+ odict.__setitem__(self, key, value)
+
+ Moving keys to the end of a ordered dict on reassignment is not
+ very useful for most applications.
+
+ Does it mean the dict keys are sorted by a sort expression?
+
+ That's not the case. The odict only guarantees that there is an
order
+ and that newly inserted keys are inserted at the end of the dict.
If
+ you want to sort it you can do so, but newly added keys are again
added
+ at the end of the dict.
+
+ I initializes the odict with a dict literal but the keys are not
+ ordered like they should!
+
+ Dict literals in Python generate dict objects and as such the
order of
+ their items is not guaranteed. Before they are passed to the odict
+ constructor they are already unordered.
+
+ What happens if keys appear multiple times in the list passed to the
+ constructor?
+
+ The same as for the dict. The latter item overrides the former.
This
+ has the side-effect that the position of the first key is used
because
+ the key is actually overwritten:
+
+ >>> odict([('a', 1), ('b', 2), ('a', 3)])
+ odict.odict([('a', 3), ('b', 2)])
+
+ This behavor is consistent with existing implementation in Python
+ and the PHP array and the hashmap in Ruby 1.9.
+
+ This odict doesn't scale!
+
+ Yes it doesn't. The delitem operation is O(n). This is file is a
+ mockup of a real odict that could be implemented for collections
+ based on an linked list.
+
+ Why is there no .insert()?
+
+ There are few situations where you really want to insert a key at
+ an specified index. To now make the API too complex the proposed
+ solution for this situation is creating a list of items,
manipulating
+ that and converting it back into an odict:
+
+ >>> d = odict([('a', 42), ('b', 23), ('c', 19)])
+ >>> l = d.items()
+ >>> l.insert(1, ('x', 0))
+ >>> odict(l)
+ odict.odict([('a', 42), ('x', 0), ('b', 23), ('c', 19)])
+
+ :copyright: (c) 2008 by Armin Ronacher and PEP 273 authors.
+ :license: modified BSD license.
+"""
+from itertools import izip, imap
+from copy import deepcopy
+
+missing = object()
+
+
+class odict(dict):
+ """
+ Ordered dict example implementation.
+
+ This is the proposed interface for a an ordered dict as proposed on the
+ Python mailinglist (proposal_).
+
+ It's a dict subclass and provides some list functions. The
implementation
+ of this class is inspired by the implementation of Babel but
incorporates
+ some ideas from the `ordereddict`_ and Django's ordered dict.
+
+ The constructor and `update()` both accept iterables of tuples as well
as
+ mappings:
+
+ >>> d = odict([('a', 'b'), ('c', 'd')])
+ >>> d.update({'foo': 'bar'})
+ >>> d
+ odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
+
+ Keep in mind that when updating from dict-literals the order is not
+ preserved as these dicts are unsorted!
+
+ You can copy an odict like a dict by using the constructor, `copy.copy`
+ or the `copy` method and make deep copies with `copy.deepcopy`:
+
+ >>> from copy import copy, deepcopy
+ >>> copy(d)
+ odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
+ >>> d.copy()
+ odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
+ >>> odict(d)
+ odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
+ >>> d['spam'] = []
+ >>> d2 = deepcopy(d)
+ >>> d2['spam'].append('eggs')
+ >>> d
+ odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])])
+ >>> d2
+ odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam',
['eggs'])])
+
+ All iteration methods as well as `keys`, `values` and `items` return
+ the values ordered by the the time the key-value pair is inserted:
+
+ >>> d.keys()
+ ['a', 'c', 'foo', 'spam']
+ >>> d.values()
+ ['b', 'd', 'bar', []]
+ >>> d.items()
+ [('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])]
+ >>> list(d.iterkeys())
+ ['a', 'c', 'foo', 'spam']
+ >>> list(d.itervalues())
+ ['b', 'd', 'bar', []]
+ >>> list(d.iteritems())
+ [('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])]
+
+ Index based lookup is supported too by `byindex` which returns the
+ key/value pair for an index:
+
+ >>> d.byindex(2)
+ ('foo', 'bar')
+
+ You can reverse the odict as well:
+
+ >>> d.reverse()
+ >>> d
+ odict.odict([('spam', []), ('foo', 'bar'), ('c', 'd'), ('a', 'b')])
+
+ And sort it like a list:
+
+ >>> d.sort(key=lambda x: x[0].lower())
+ >>> d
+ odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])])
+
+ .. _proposal:
http://thread.gmane.org/gmane.comp.python.devel/95316
+ .. _ordereddict:
http://www.xs4all.nl/~anthon/Python/ordereddict/
+ """
+
+ def __init__(self, *args, **kwargs):
+ dict.__init__(self)
+ self._keys = []
+ self.update(*args, **kwargs)
+
+ def __delitem__(self, key):
+ dict.__delitem__(self, key)
+ self._keys.remove(key)
+
+ def __setitem__(self, key, item):
+ if key not in self:
+ self._keys.append(key)
+ dict.__setitem__(self, key, item)
+
+ def __deepcopy__(self, memo=None):
+ if memo is None:
+ memo = {}
+ d = memo.get(id(self), missing)
+ if d is not missing:
+ return d
+ memo[id(self)] = d = self.__class__()
+ dict.__init__(d, deepcopy(self.items(), memo))
+ d._keys = self._keys[:]
+ return d
+
+ def __getstate__(self):
+ return {'items': dict(self), 'keys': self._keys}
+
+ def __setstate__(self, d):
+ self._keys = d['keys']
+ dict.update(d['items'])
+
+ def __reversed__(self):
+ return reversed(self._keys)
+
+ def __eq__(self, other):
+ if isinstance(other, odict):
+ if not dict.__eq__(self, other):
+ return False
+ return self.items() == other.items()
+ return dict.__eq__(self, other)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __cmp__(self, other):
+ if isinstance(other, odict):
+ return cmp(self.items(), other.items())
+ elif isinstance(other, dict):
+ return dict.__cmp__(self, other)
+ return NotImplemented
+
+ @classmethod
+ def fromkeys(cls, iterable, default=None):
+ return cls((key, default) for key in iterable)
+
+ def clear(self):
+ del self._keys[:]
+ dict.clear(self)
+
+ def copy(self):
+ return self.__class__(self)
+
+ def items(self):
+ return zip(self._keys, self.values())
+
+ def iteritems(self):
+ return izip(self._keys, self.itervalues())
+
+ def keys(self):
+ return self._keys[:]
+
+ def iterkeys(self):
+ return iter(self._keys)
+
+ def pop(self, key, default=missing):
+ if default is missing:
+ return dict.pop(self, key)
+ elif key not in self:
+ return default
+ self._keys.remove(key)
+ return dict.pop(self, key, default)
+
+ def popitem(self, key):
+ self._keys.remove(key)
+ return dict.popitem(key)
+
+ def setdefault(self, key, default=None):
+ if key not in self:
+ self._keys.append(key)
+ dict.setdefault(self, key, default)
+
+ def update(self, *args, **kwargs):
+ sources = []
+ if len(args) == 1:
+ if hasattr(args[0], 'iteritems'):
+ sources.append(args[0].iteritems())
+ else:
+ sources.append(iter(args[0]))
+ elif args:
+ raise TypeError('expected at most one positional argument')
+ if kwargs:
+ sources.append(kwargs.iteritems())
+ for iterable in sources:
+ for key, val in iterable:
+ self[key] = val
+
+ def values(self):
+ return map(self.get, self._keys)
+
+ def itervalues(self):
+ return imap(self.get, self._keys)
+
+ def index(self, item):
+ return self._keys.index(item)
+
+ def byindex(self, item):
+ key = self._keys[item]
+ return (key, dict.__getitem__(self, key))
+
+ def reverse(self):
+ self._keys.reverse()
+
+ def sort(self, *args, **kwargs):
+ self._keys.sort(*args, **kwargs)
+
+ def __repr__(self):
+ return 'odict.odict(%r)' % self.items()
+
+ __copy__ = copy
+ __iter__ = iterkeys
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
=======================================
--- /dev/null
+++ /trunk/spade/tbcbp.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,508 @@
+import Queue
+import time
+import random
+from odict import odict
+from copy import copy, deepcopy
+from uuid import uuid4
+from math import sqrt, pow, ceil, log, floor
+import math
+import types
+
+import dblite
+
+class TimeOut(Exception): pass
+class TooMuchPlans(Exception): pass
+
+class CaseDB:
+ def __init__(self):
+ self.db = dblite.Base("caseDB")
+ self.db.create("P","Q","inputs","outputs","case", mode="override")
+ self.db.open()
+
+ def add(self, case):
+ P = sorted(case.getP())
+ Q = sorted(case.getQ())
+ I = sorted(case.getInputs())
+ O = sorted(case.getOutputs())
+
+ self.db.insert(P=P,Q=Q,inputs=I,outputs=O,case=case)
+
+ def get(self, P=None,Q=None,inputs=None,outputs=None):
+ res = []
+ query = "self.db("
+ if P!=None: query+="P="+str(sorted(P))+","
+ if Q!=None: query+="Q="+str(sorted(Q))+","
+ if inputs!=None: query+="inputs="+str(sorted(inputs))+","
+ if outputs!=None: query+="outputs="+str(sorted(outputs))
+ query+=")"
+ for record in eval(query):
+ res.append(record["case"])
+
+ return res
+
+class Case(dict):
+
+ def __init__(self,P=[], Q=[], inputs=[], outputs=[], services=[],
QoS=1, ID=None):
+ dict.__init__(self)
+ self.P = P
+ self.Q = Q
+ self.inputs = inputs
+ self.outputs = outputs
+ self.QoS = QoS
+ self.services = services
+ self.time = 0
+ if ID == None: self.ID = str(uuid4())
+ else: self.ID = ID
+
+ self.rewards = 0
+ self.punishments= 0
+ self.executions = 0
+ self.trust = 0
+
+ def getID(self): return self.ID
+ def getP(self): return self.P
+ def getQ(self): return self.Q
+ def getInputs(self): return self.inputs
+ def getOutputs(self): return self.outputs
+ def getQoS(self): return self.QoS
+ def getTime(self): return self.time
+
+ def reward(self):
+ self.rewards+=1
+ self.executions+=1
+ self.trust = min(1.0,float(self.rewards)/float(self.executions))
+ self.QoS = self.trust
+
+ def punish(self):
+ if self.rewards>0: self.rewards-=1
+ self.punishments+=1
+ self.executions+=1
+ self.trust = max(0.0,float(self.rewards)/float(self.executions))
+ self.QoS = self.trust
+
+ def __add__(self,y):
+ #if str(self.Q)!=str(y.getP()):
+ for sentence in self.outputs:
+ if sentence not in y.inputs:
+ raise TypeError
+ return
Case(P=self.P,Q=y.getQ(),inputs=self.getInputs(),outputs=y.getOutputs(),
services=self.services+y.services,QoS=self.QoS*y.QoS, ID=str(uuid4()))
+
+ def __iadd__(self,y):
+ self = self+y
+ return self
+
+ def __eq__(self,y):
+ if not issubclass(y.__class__,Case): return False
+ if self.services!= y.services: return False
+ #if self.P!=y.getP():
+ if sorted(self.P) != sorted(y.P):
+ return False
+ #if self.Q!=y.getQ():
+ if sorted(self.Q) != sorted(y.Q):
+ return False
+ if sorted(self.inputs) != sorted(y.inputs):
+ return False
+ if sorted(self.outputs) != sorted(y.outputs):
+ return False
+ return True
+
+ def __ne__(self,y):
+ return not self==y
+
+ def __str__(self):
+ return "{ID: "+self.ID+" P: "+str(self.P)+ " Q: "+str(self.Q)+"
I: "+str(self.inputs)+" O: "+str(self.outputs)+"
SERVICES:"+str(self.services)+" QoS: "+str(self.QoS)+"}"
+
+ def __repr__(self):
+ return self.__str__()
+
+ def __len__(self):
+ return len(self.services)
+
+class Plan(dict):
+
+ def __init__(self,cases):
+ '''
+ Creates a new plan composed of a list of cases
+ Usage:
+ cases: a list of cases with at least 1 case
+ '''
+ dict.__init__(self)
+
+ if type(cases)!= types.ListType:
+ raise TypeError
+ if len(cases)<=0:
+ raise Exception("cases must have at least one case")
+
+ self.P=(cases[0]).getP()
+ self.Q=(cases[-1:][0]).getQ()
+ self.inputs=(cases[0]).getInputs()
+ self.outputs=(cases[-1:][0]).getOutputs()
+ self.cases=cases
+
+ self.active_case = 0
+ self.active_service = -1
+
+ def getP(self): return self.P
+ def getQ(self): return self.Q
+ def getInputs(self): return self.inputs
+ def getOutputs(self): return self.outputs
+
+ '''def match(self,P=[],Q=[]):
+ if (P!=[] and sorted(P)==sorted(self.P)) and (Q!=[] and
sorted(Q)==sorted(self.Q)): return True
+ elif (P==None and Q==self.Q): return True
+ elif (Q==None and P==self.P): return True
+ else: return False
+ '''
+
+ def getActiveCase(self): return self.active_case
+
+ def getNextService(self):
+ if len(self.cases)<=0: return None
+
+ self.active_service+=1
+ if self.active_service <
len(self.cases[self.active_case].services):
+ return
self.cases[self.active_case].services[self.active_service]
+ else:
+ self.active_service=0
+ self.active_case+=1
+ if self.active_case >= len(self.cases):
+ self.active_case=0
+ self.active_service=-1
+ return None
+ return
deepcopy(self.cases[self.active_case].services[self.active_service])
+
+ def getCases(self):
+ '''returns all the cases of the plan'''
+ return self.cases
+
+ def getCase(self):
+ '''
+ compose a new composite case by joining all the cases of the plan
+ returns a Case
+ '''
+ if len(self.cases)==0: return None
+ case = self.cases[0]
+ for c in self.cases[1:]: case += c
+ return case
+
+ def getServices(self):
+ '''
+ returns all the services of the cases that compose the plan
+ returns a list of DF.Service
+ '''
+ services=[]
+ for c in self.cases:
+ for s in c.services: services.append(s)
+ return services
+
+ def insertCase(self,case):
+ '''
+ inserts a new case at the beginning of the plan
+ the outputs of the new case MUST match with the inputs of the plan
+ returns the Plan with the new case added
+ '''
+ if sorted(case.getOutputs())!=sorted(self.inputs): raise Exception
+ self.cases.insert(0,case)
+ self.P = case.getP()
+ self.inputs = case.getInputs()
+ return self
+
+ def getCasebyID(self,ID):
+ for c in self.cases:
+ if c.getID()==ID: return c
+ return None
+
+ def getTime(self):
+ t=0
+ for case in self.cases:t+=case.getTime()
+ return t
+
+ def getQoS(self):
+ q=1
+ for case in self.cases:
+ q = q * case.getQoS()
+ return q
+
+ def __len__(self):
+ return len(self.cases)
+
+ def __str__(self):
+ return "{P: "+str(self.P)+ " Q: "+ str(self.Q) + "
I: "+str(self.inputs)+" O: "+ str(self.outputs) + "
CASES: "+str(self.cases)+"}"
+ def __repr__(self):
+ return self.__str__()
+
+
+class TBCBP:
+
+ def __init__(self, rl = {'maxth':0.95, 'limit':10000}):
+ self.db = CaseDB() #dict()
+ self.services = dict()
+
+ #RL values
+ self.threshold = 0.0
+ self.max_threshold = rl['maxth']
+ self.limit_steps = rl['limit']
+ self.steps = 1
+ self.RLlimit = log(self.limit_steps)
+
+ def getCaseTime(self,case):
+ t = 0
+ for name in case.services:
+ t += self.services[name]["time"]
+ return t
+
+ def registerService(self, service, time=1, QoS=1):
+ '''
+ registers a DF.Service
+ time and QoS parameters are optional
+ '''
+ name = service.getName()
+ P = service.getP()
+ Q = service.getQ()
+ I = service.getInputs()
+ O = service.getOutputs()
+
self.services[name]={'name':name,'s':service,"P":P,"Q":Q,"inputs":I, "outputs":O, "time":time,"QoS":QoS}
+
+ case = Case(P=P,Q=Q,inputs=I,outputs=O, services=[name],QoS=QoS)
+ case.time = time #self.getCaseTime(case)
+ self.addCase(case)
+
+ return case
+ #print "TBCBP::Service Registered: "+str(case)
+
+ def delService(self, name):
+ #TODO
+ pass
+ def getService(self, name):
+ '''returns a DF.Service'''
+ if self.services.has_key(name):
+ #print color_red + str(self.services[name]['s']) + color_none
+ #s =
self.services[name]["s"](P=self.services[name]["P"],Q=self.services[name]["Q"],inputs=self.services[name]["inputs"],outputs=self.services[name]["outputs"],name=name)
+ #return s
+ return self.services[name]['s']
+ return None
+
+ def getServiceInfo(self,name):
+ '''
+ returns info of a service
+ Usage:
+ name - string with the name of the service
+ returns a dict with the info of the service
+ '''
+ if self.services.has_key(name):
+ return self.services[name]
+
+ def addCase(self, case):
+ '''
+ inserts a new case in the case-base
+ services of the case MUST be registered in the TBCBP
+ '''
+ for s in case.services:
+ if s not in self.services.keys():
+ return False
+ case.time = self.getCaseTime(case)
+
+ self.db.add(case)
+
+ return True
+
+ def addPlan(self,plan):
+ case = plan.getCase()
+ self.addCase(case)
+
+
+ def getCases(self, P=None, Q=None, inputs=None, outputs=None):
+ '''
+ returns a list of cases where the P,Q,inputs and outputs match.
+ it only compares parameters if they are not None
+ '''
+ return self.db.get(P,Q,inputs,outputs)
+
+ def getCase(self,case):
+ '''
+ returns the case of the case-base whose parameters (P,Q,inputs and
outputs) match with the 'case' parameters
+ '''
+ try:
+ res =
self.db.get(P=case.getP(),Q=case.getQ(),inputs=case.getInputs(),outputs=case.getOutputs())
+ except:
+ return None
+ for r in res:
+ if r.services == case.services:
+ return r
+ return None
+
+ def getCaseOfService(self, name):
+ '''
+ returns the case that represents the service 'name' in the
case-base
+ Usage:
+ name - string with the name of the service
+ '''
+ service = self.getService(name)
+ if service==None: return None
+ case =
self.getCase(Case(P=service.getP(),Q=service.getQ(),inputs=service.getInputs(),outputs=service.getOutputs(),services=[name]))
+ return case
+
+ def planMatchesInKB(self, case, kb):
+ '''
+ returns True if all the Preconditions and Inputs of the case are
true in the knowledge-base
+ otherwise returns False
+ Usage:
+ case - the case that we want to compare. instance of Case
+ kb - the knowledge base of the agent. instance of kb.KB
+ '''
+ Preconditions_matched=True
+ Inputs_matched=True
+ for p in case.getP():
+ if kb.ask(p) == False:
+ Preconditions_matched=False
+ break #preconditions do not match
+ for i in case.getInputs():
+ if kb.get(i)==None:
+ Inputs_matched=False
+ break #inputs do not match
+ if Preconditions_matched and Inputs_matched:
+ return True
+ else:
+ return False
+
+ def composePlan(self, Goal, kb, tout=20, use_rl=True):
+
+ #print "TBCBP::DB:: "+str(self.db)
+ #print "TBCBP::SERVICES:: "+str(self.services)
+
#print "TBCBP::composePlan::GOAL::"+str(Goal)+"::KB::"+str(kb.kb.clauses)+"::TOUT::"+str(tout)
+
+ MAXPLANS=1000
+
+ results = []
+ plans = Queue.Queue()
+
+ t1 = time.time()
+
+ try:
+ try:
+ #print "TBCBP::composePlan::getCases
for "+str(Goal.expression)+" -> "+str(self.getCases(Q=[Goal.expression]))
+ for case in self.getCases(Q=[Goal.expression]): #.values():
+ if tout!=-1 and (time.time()-t1)>tout: raise TimeOut
+ #for case in cases:
+ new_plan = Plan(cases=[case])
+ #if Preconditions match and have all inputs, the plan is
finished
+ if self.planMatchesInKB(case,kb):
+ results.append(new_plan)
+ else: plans.put(new_plan)
+
+ if tout!=-1 and (time.time()-t1)>tout: raise TimeOut
+ if len(results)>MAXPLANS: raise TooMuchPlans
+
+ while plans.qsize() > 0:
+ if len(results)>MAXPLANS: raise TooMuchPlans
+ p = plans.get()
+ for case in self.getCases(outputs=p.getInputs()):
#.values():
+ #for case in cases:
+ new_plan = deepcopy(p)
+ new_plan.insertCase(case)
+ if self.planMatchesInKB(new_plan,kb):
+ #if new_plan not in results:
+ results.append(new_plan)
+ else:
+ plans.put(new_plan)
+ if tout!=-1 and (time.time()-t1)>tout: raise TimeOut
+
+ except TimeOut:
+ pass
+ #print "TIMEOUT!"
+ except TooMuchPlans:
+ pass
+ #print "TOOMUCHPLANS!"
+
+ finally:
+ pass
+
+ if results ==[]:
+ #print "NO PLANS FOUND!"
+ return None
+ sumT=0
+ sumQ=0
+ for plan in results:
+ sumT+=plan.getTime()
+ sumQ+=plan.getQoS()
+
+ #print "selecting best plan"
+ plans = []
+ exploit= odict()
+ last=0
+ normalize=10000
+
+ best_plan = results[0]
+ if sumT==0: T=0.0
+ else: T = (1.0/float(best_plan.getTime())/float(sumT))
+ if sumQ==0: Q=0.0
+ else: Q = (float(best_plan.getQoS())/float(sumQ))
+ f = T+Q
+ plans.append(best_plan)
+ if int(f*normalize) > 0:
+ exploit[int(f*normalize)] = best_plan
+ last=int(f*normalize)
+
+
+ for plan in results[1:]:
+ if sumT==0: T=0.0
+ else: T = (1.0/float(plan.getTime())/float(sumT))
+ if sumQ==0: Q=0.0
+ else: Q = (float(plan.getQoS())/float(sumQ))
+ if T+Q > f:
+ best_plan = plan
+ f = T+Q
+ plans.append(plan)
+ if int(last+(f*normalize))>0:
+ exploit[int(last+(f*normalize))] = plan
+ last = last+int(f*normalize)
+
+ #mini reinforcement learning
+ if use_rl:
+ explore = random.random()
+ if explore > self.threshold:
+ #explore!
+ best_plan = random.choice(plans)
+ else:
+ #exploit!
+ if last==0:
+ best_plan= random.choice(plans)
+ else:
+ i = random.randint(1,last)
+ for k in exploit.keys():
+ if i<=k:
+ best_plan=exploit[k]
+ break
+
+
+ #adjust threshold
+ self.steps+=1
+ if self.steps > self.limit_steps: self.threshold =
self.max_threshold
+ else: self.threshold = (self.max_threshold * log(self.steps)) /
self.RLlimit
+
+ self.addPlan(best_plan)
+ return best_plan
+
+
+
+ def retain(self, case, QoS=None):
+ if QoS!=None: case.QoS=QoS
+
+ c = self.getCase(case)
+ if c:
+ c.QoS=case.QoS
+
+
+ def reward(self,c):
+ case = self.getCase(c)
+ if case!=None:
+ case.reward()
+ return case
+ return False
+
+ def punish(self,c):
+ case = self.getCase(c)
+ if case!=None:
+ case.punish()
+ return case
+ return False
=======================================
--- /dev/null
+++ /trunk/test/factsTestCase.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,65 @@
+import types
+import unittest
+
+from spade.kb import KB, KBNameNotString, KBValueNotKnown
+
+class factsTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self.kb = KB()
+
+ def tearDown(self):
+ pass
+
+ def testInteger(self):
+ self.kb.set("varname1",1234)
+ var = self.kb.get("varname1")
+ assert var == 1234
+ assert type(var) == types.IntType
+
+ def testString(self):
+ self.kb.set("varname2","TestString")
+ var = self.kb.get("varname2")
+ assert var == "teststring"
+ assert type(var) == types.StringType
+
+ def testFloat(self):
+ self.kb.set("varname3",1234.5678)
+ var = self.kb.get("varname3")
+ assert var == 1234.5678
+ assert type(var) == types.FloatType
+
+ def testList(self):
+ self.kb.set("varname4",[1,2,3,4])
+ var = self.kb.get("varname4")
+ assert var == [1,2,3,4]
+ assert type(var) == types.ListType
+
+ def testListWithMultipleTypes(self):
+ self.kb.set("varname5",[1,2,3.4,"5",[6,7]])
+ var = self.kb.get("varname5")
+ assert var == [1,2,3.4,"5",[6,7]]
+ assert type(var) == types.ListType
+
+ def testDict(self):
+ self.kb.set("varname6",{'a':123,'b':456,789:"c"})
+ var = self.kb.get("varname6")
+ assert var == {'a':123,'b':456,789:"c"}
+ assert type(var) == types.DictType
+
+ def testDictWithComplexTypes(self):
+
self.kb.set("varname7",{'a':[123.25],'b':[4,5,6],789:{'a':1,'b':2}})
+ var = self.kb.get("varname7")
+ assert var == {'a':[123.25],'b':[4,5,6],789:{'a':1,'b':2}}
+ assert type(var) == types.DictType
+
+ def testKeyNotString(self):
+ self.assertRaises(KBNameNotString, self.kb.set, 123,"newvalue")
+
+ def testValueNotKnown(self):
+ class A:pass
+ self.assertRaises(KBValueNotKnown, self.kb.set, "varname8", A())
+
+if __name__ == "__main__":
+ unittest.main()
=======================================
--- /dev/null
+++ /trunk/test/tbcbpTestCase.py Tue Jul 31 06:58:54 2012
@@ -0,0 +1,428 @@
+import unittest
+
+from spade.tbcbp import *
+from spade.DF import Service
+from spade.kb import KB
+from spade.bdi import Goal
+
+class tbcbpCasesTestCase(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def testBasicCase(self):
+ case = Case(P=["P1","P2"],Q=["Q1"],
inputs=["invar1","invar2"],outputs=["outvar1"], services=["s1","s2","s3"])
+
+ assert case.getP() == ["P1","P2"]
+ assert case.getQ() == ["Q1"]
+ assert case.getInputs() == ["invar1","invar2"]
+ assert case.getOutputs() == ["outvar1"]
+ assert case.services == ["s1","s2","s3"]
+ assert case.getTime() == 0
+ assert case.getQoS() == 1
+
+ def testAddCase(self):
+ case1 = Case(P=["P1","P2"],Q=["Q1","Q2"],
inputs=["invar1","invar2"],outputs=["outvar1"], services=["s1","s2","s3"])
+ case2 = Case(P=["P3","P4"],Q=["Q3"],
inputs=["outvar1"],outputs=["outvar1"], services=["s4","s5","s6"])
+
+ case3 = case1+case2
+
+ assert case3.getP() == ["P1","P2"]
+ assert case3.getQ() == ["Q3"]
+ assert case3.getInputs() == ["invar1","invar2"]
+ assert case3.getOutputs() == ["outvar1"]
+
+ assert case3.services == ["s1","s2","s3","s4","s5","s6"]
+
+ def testIAddCase(self):
+ case1 = Case(P=["P1","P2"],Q=["Q1","Q2"],
inputs=["invar1","invar2"],outputs=["outvar1"], services=["s1","s2","s3"])
+ case2 = Case(P=["P3","P4"],Q=["Q3"],
inputs=["outvar1"],outputs=["outvar1"], services=["s4","s5","s6"])
+
+ case1 += case2
+
+ assert case1.getP() == ["P1","P2"]
+ assert case1.getQ() == ["Q3"]
+ assert case1.getInputs() == ["invar1","invar2"]
+ assert case1.getOutputs() == ["outvar1"]
+
+ assert case1.services == ["s1","s2","s3","s4","s5","s6"]
+
+ def testEqualCase(self):
+ case1 = Case(P=["P1","P2"],Q=["Q1","Q2"],
inputs=["invar1","invar2"],outputs=["outvar1"], services=["s1","s2","s3"])
+ case2 = Case(P=["P2","P1"],Q=["Q2","Q1"],
inputs=["invar2","invar1"],outputs=["outvar1"], services=["s1","s2","s3"])
+ case3 = Case(P=["P1","P2"],Q=["Q1","Q2"],
inputs=["invar1","invar2"],outputs=["outvar1"], services=["s2","s1","s3"])
+ case4 = Case(P=["P2","P1"],Q=["Q2","Q1"],
inputs=["invar3","invar1"],outputs=["outvar1"], services=["s1","s2","s3"])
+ case5 = Case(P=["P4","P1"],Q=["Q2","Q1"],
inputs=["invar2","invar1"],outputs=["outvar1"], services=["s1","s2","s3"])
+
+ assert case1==case2
+ assert case1!=case3
+ assert case1!=case4
+ assert case1!=case5
+ assert
case1!={"P":["P1","P2"],"Q":["Q1","Q2"],"inputs":["invar1","invar2"],"outputs":["outvar1"],"services":["s1","s2","s3"]}
+
+ def testRewardCase(self):
+ case = Case(P=[],Q=[], inputs=[],outputs=[],
services=["s1","s2","s3"])
+
+ case.reward()
+ assert case.trust == 1
+ case.reward()
+ assert case.trust == 1
+ case.punish()
+ assert case.trust == float(1)/float(3)
+ case.punish()
+ assert case.trust == 0.0
+ case.reward()
+ assert case.trust == float(1)/float(5)
+ for i in range(1000): case.reward()
+ assert case.trust <= 1.0
+
+
+class tbcbpPlansTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.case1 = Case(P=["P1","P2"],Q=["Q1","Q2"],
inputs=["invar1","invar2"],outputs=["outvar1"], services=["s1","s2","s3"])
+ self.case2 = Case(P=["P3","P4"],Q=["Q3"],
inputs=["outvar1"],outputs=["outvar2"], services=["s4","s5","s6"])
+ self.case3 = Case(P=["P1","P2"],Q=["Q1","Q2"],
inputs=["invar1","invar2"],outputs=["outvar1"], services=["s2","s1","s3"])
+
+ def testBasicPlan(self):
+
+ plan = Plan(cases=[self.case1,self.case2])
+
+ assert plan.getP() == ["P1","P2"]
+ assert plan.getQ() == ["Q3"]
+ assert plan.getInputs() == ["invar1","invar2"]
+ assert plan.getOutputs() == ["outvar2"]
+
+ assert plan.getCases() == [self.case1,self.case2]
+
+ def testBadPlanConstructor(self):
+ #can't create a plan with an empty list of cases
+ self.assertRaises(Exception, Plan, [])
+
+ def testGetCase(self):
+ plan = Plan(cases=[self.case1,self.case2])
+ assert plan.getCase() == self.case1+self.case2
+
+ plan = Plan(cases=[self.case1])
+ del plan.cases[0]
+ assert plan.getCase() == None
+
+ def testGetServices(self):
+ plan = Plan(cases=[self.case1,self.case2])
+ assert plan.getServices() == ["s1","s2","s3","s4","s5","s6"]
+
+ assert plan.getServices() != ["s3","s6","s4","s2","s5","s1"]
+
+ def testInsertCase(self):
+
+ plan = Plan(cases=[self.case2])
+
+ assert plan.getP() == ["P3","P4"]
+ assert plan.getQ() == ["Q3"]
+ assert plan.getInputs() == ["outvar1"]
+ assert plan.getOutputs() == ["outvar2"]
+ assert plan.getCases() == [self.case2]
+
+ plan.insertCase(self.case1)
+
+ assert plan.getP() == ["P1","P2"]
+ assert plan.getQ() == ["Q3"]
+ assert plan.getInputs() == ["invar1","invar2"]
+ assert plan.getOutputs() == ["outvar2"]
+ assert plan.getCases() == [self.case1,self.case2]
+
+ def testInsertCaseException(self):
+
+ plan = Plan(cases=[self.case1])
+
+ self.assertRaises(Exception, plan.insertCase, self.case3)
+
+ def testGetPlanTime(self):
+ case1 = Case(P=["P1","P2"],Q=["Q1","Q2"],
inputs=["invar1","invar2"],outputs=["outvar1"], services=["s1","s2","s3"])
+ case2 = Case(P=["P3","P4"],Q=["Q3"],
inputs=["outvar1"],outputs=["outvar2"], services=["s4","s5","s6"])
+
+ case1.time = 11
+ case2.time = 4
+ plan = Plan(cases=[case1,case2])
+
+ assert plan.getTime() == 15
+
+ def testGetNextService(self):
+
+ plan = Plan([self.case1,self.case2])
+
+ assert plan.getNextService() == "s1"
+ assert plan.getNextService() == "s2"
+ assert plan.getNextService() == "s3"
+ assert plan.getNextService() == "s4"
+ assert plan.getNextService() == "s5"
+ assert plan.getNextService() == "s6"
+ assert plan.getNextService() == None
+ assert plan.getNextService() == "s1"
+ assert plan.getNextService() == "s2"
+
+ def testLenPlan(self):
+ plan = Plan([self.case1,self.case2])
+
+ assert len(plan)==2
+
+class tbcbpTBCBPTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.s1 = Service(name="s1", P=["p1","p2"],Q=["q1","q2"],
inputs=["i1"], outputs=["o1"])
+ self.s1_1 = Service(name="s1_1", P=["p1","p2"],Q=["q1","q2"],
inputs=["i1"], outputs=["o1"])
+ self.s2 = Service(name="s2", P=["p3","p4"],Q=["q3","q4"],
inputs=["o1"], outputs=["o2"])
+
+
+ def testRegisterService(self):
+ tbcbp = TBCBP()
+ tbcbp.registerService(self.s1)
+
+ s = tbcbp.getService("s1")
+
+ assert s == self.s1
+
+ def testGetServiceInfo(self):
+
+ tbcbp = TBCBP()
+ tbcbp.registerService(self.s1, time=13)
+
+ s = tbcbp.getServiceInfo("s1")
+
+ assert s["s"] == self.s1
+ assert s["P"] == ["p1","p2"]
+ assert s["Q"] == ["q1","q2"]
+ assert s["inputs"] == ["i1"]
+ assert s["outputs"] == ["o1"]
+ assert s["time"] == 13
+ assert s["QoS"] == 1
+
+ case = Case(P=["p1","p2"], Q=["q1","q2"], inputs=["i1"],
outputs=["o1"], services=["s1"])
+
+ assert tbcbp.getCases(P=["p1","p2"], Q=["q1","q2"], inputs=["i1"],
outputs=["o1"])[0] == case
+
+
+ def testAddCase(self):
+ tbcbp = TBCBP()
+ tbcbp.registerService(self.s1)
+ tbcbp.registerService(self.s2)
+ tbcbp.registerService(self.s1_1)
+
+ case1 = Case(P=["p1","p2"],Q=["q1","q2"],
inputs=["i1"],outputs=["o2"], services=["s1","s2"])
+ case2 = Case(P=["p3","p4"],Q=["q1","q2"],
inputs=["i1"],outputs=["o1"], services=["s2","s1"])
+ case1_1 = Case(P=["p1","p2"],Q=["q1","q2"],
inputs=["i1"],outputs=["o2"], services=["s1_1","s2"])
+
+ #adding a case
+ assert tbcbp.addCase(case1) != False
+
+ #adding a case with unregistered services
+ assert tbcbp.addCase(Case(services=["s1","s3"])) == False
+
+ #check added cases
+ assert tbcbp.getCase(case1) == case1
+ assert tbcbp.getCase(case1) != case2
+ assert tbcbp.getCase(Case(services=["s2"])) == None
+
+ #adding similar cases
+ assert tbcbp.addCase(case1_1) != False
+ assert tbcbp.getCase(case1_1) != case1
+ assert tbcbp.getCase(case1_1) == case1_1
+
+ def testGetCaseOfService(self):
+ tbcbp = TBCBP()
+ tbcbp.registerService(self.s1)
+ tbcbp.registerService(self.s1_1)
+
+ case1 = Case(P=["p1","p2"],Q=["q1","q2"],
inputs=["i1"],outputs=["o1"], services=["s1"])
+ case1_1 = Case(P=["p1","p2"],Q=["q1","q2"],
inputs=["i1"],outputs=["o1"], services=["s1_1"])
+
+ assert tbcbp.getCaseOfService("s1") == case1
+ assert tbcbp.getCaseOfService("s1") != case1_1
+ assert tbcbp.getCaseOfService("s1_1") == case1_1
+ assert tbcbp.getCaseOfService("s1_1") != case1
+
+ def testPlanMatchesInKB(self):
+ tbcbp = TBCBP()
+ case1 = Case(P=["P(P1)","P(P2)"],Q=["Q(Q1)","Q(Q2)"],
inputs=["i1"],outputs=["o1"], services=["s1"])
+ kb0 = KB()
+ kb0.tell("P(P1)")
+ kb0.tell("P(P2)")
+ kb0.set("i1", 1024)
+
+ assert tbcbp.planMatchesInKB(case1, kb0) == True
+
+ case2 = Case(P=["P(P3)","P(P2)"],Q=["q1","q2"],
inputs=["i1"],outputs=["o1"], services=["s1"])
+ assert tbcbp.planMatchesInKB(case2, kb0) == False
+
+ case3 = Case(P=["P(P1)","P(P2)"],Q=["q1","q2"],
inputs=["i2"],outputs=["o1"], services=["s1"])
+ assert tbcbp.planMatchesInKB(case3, kb0) == False
+
+
+ def testAddPlan(self):
+ case1 = Case(P=["P1","P2"],Q=["Q1","Q2"],
inputs=["invar1","invar2"],outputs=["outvar1"], services=["s1","s2","s3"])
+ case2 = Case(P=["P3","P4"],Q=["Q3"],
inputs=["outvar1"],outputs=["outvar2"], services=["s4","s5","s6"])
+ plan = Plan(cases=[case1,case2])
+ tbcbp = TBCBP()
+
+ tbcbp.addPlan(plan)
+
+ tbcbp.getCase(case1+case2) == case1+case2
+
+ def testComposePlan1Case(self):
+ tbcbp = TBCBP()
+ s1 = Service(P=["P(P1)","P(P2)"],Q=["Q(Q1)"],
inputs=["i1"],outputs=["o1"], name="s1")
+ tbcbp.registerService(s1)
+
+ kb0 = KB()
+ kb0.tell("P(P1)")
+ kb0.tell("P(P2)")
+ kb0.set("i1", 1024)
+
+ g = Goal("Q(Q1)")
+
+ plan = tbcbp.composePlan(Goal=g, kb=kb0)
+
+ assert plan!=None
+ assert plan.getQ()==["Q(Q1)"]
+ assert plan.getP()==["P(P1)", "P(P2)"]
+ assert len(plan)==1
+
+ def testComposePlan2Cases(self):
+ tbcbp = TBCBP()
+ s1 = Service(P=["P(P1)","P(P2)"],Q=["Q(Q1)","Q(Q2)"],
inputs=["i1"],outputs=["o1"], name="s1")
+ s2 = Service(P=["P(P3)","P(P4)"],Q=["Q(Q3)"],
inputs=["o1"],outputs=["o2"], name="s2")
+ tbcbp.registerService(s1)
+ tbcbp.registerService(s2)
+
+ kb0 = KB()
+ kb0.tell("P(P1)")
+ kb0.tell("P(P2)")
+ kb0.set("i1", 1024)
+
+ g = Goal("Q(Q3)")
+
+ plan = tbcbp.composePlan(Goal=g, kb=kb0)
+
+ assert plan!=None
+ assert plan.getQ()==["Q(Q3)"]
+ assert plan.getP()==["P(P1)", "P(P2)"]
+ assert len(plan)==2
+
+ def testComposePlan1CaseNoP(self):
+ tbcbp = TBCBP()
+ s1 = Service(P=["P(P1)","P(P2)"],Q=["Q(Q1)"],
inputs=["i1"],outputs=["o1"], name="s1")
+ tbcbp.registerService(s1)
+
+ kb0 = KB()
+ kb0.tell("P(P1)")
+ #Missing kb0.tell("P(P2)")
+ kb0.set("i1", 1024)
+
+ g = Goal("Q(Q1)")
+
+ plan = tbcbp.composePlan(Goal=g, kb=kb0)
+
+ assert plan==None
+
+ def testComposePlan1CaseNoInputs(self):
+ tbcbp = TBCBP()
+ s1 = Service(P=["P(P1)","P(P2)"],Q=["Q(Q1)"],
inputs=["i1"],outputs=["o1"], name="s1")
+ tbcbp.registerService(s1)
+
+ kb0 = KB()
+ kb0.tell("P(P1)")
+ kb0.tell("P(P2)")
+ #Missing kb0.set("i1", 1024)
+
+ g = Goal("Q(Q1)")
+
+ plan = tbcbp.composePlan(Goal=g, kb=kb0)
+
+ assert plan==None
+
+ def testComposePlanNoCases(self):
+ tbcbp = TBCBP()
+ kb0 = KB()
+
+ g = Goal("Q(Q1)")
+
+ plan = tbcbp.composePlan(Goal=g, kb=kb0)
+
+ assert plan==None
+
+ def testComposePlanBestTime(self):
+ tbcbp = TBCBP()
+ s1 = Service(P=["P(P1)","P(P2)"],Q=["Q(Q1)","Q(Q2)"],
inputs=["i1"],outputs=["o1"], name="s1")
+ s2 = Service(P=["P(P3)","P(P4)"],Q=["Q(Q3)"],
inputs=["o1"],outputs=["o2"], name="s2")
+ s3 = Service(P=["P(P3)","P(P4)"],Q=["Q(Q3)"],
inputs=["o1"],outputs=["o2"], name="s3")
+
+ tbcbp.registerService(s1, time=10, QoS=1)
+ tbcbp.registerService(s2, time=200, QoS=1)
+ tbcbp.registerService(s3, time=20, QoS=1)
+
+ kb0 = KB()
+ kb0.tell("P(P1)")
+ kb0.tell("P(P2)")
+ kb0.set("i1", 1024)
+
+ g = Goal("Q(Q3)")
+
+ plan = tbcbp.composePlan(Goal=g, kb=kb0, use_rl=False)
+
+ for s in plan.getServices():
+ assert s in ["s1","s3"]
+ assert s != "s2"
+
+ def testComposePlanBestQoS(self):
+ tbcbp = TBCBP()
+ s1 = Service(P=["P(P1)","P(P2)"],Q=["Q(Q1)","Q(Q2)"],
inputs=["i1"],outputs=["o1"], name="s1")
+ s2 = Service(P=["P(P3)","P(P4)"],Q=["Q(Q3)"],
inputs=["o1"],outputs=["o2"], name="s2")
+ s3 = Service(P=["P(P3)","P(P4)"],Q=["Q(Q3)"],
inputs=["o1"],outputs=["o2"], name="s3")
+
+ tbcbp.registerService(s1, time=1, QoS=1)
+ tbcbp.registerService(s2, time=1, QoS=1)
+ tbcbp.registerService(s3, time=1, QoS=100)
+
+ kb0 = KB()
+ kb0.tell("P(P1)")
+ kb0.tell("P(P2)")
+ kb0.set("i1", 1024)
+
+ g = Goal("Q(Q3)")
+
+ plan = tbcbp.composePlan(Goal=g, kb=kb0, use_rl=False)
+
+ for s in plan.getServices():
+ assert s in ["s1","s3"]
+ assert s != "s2"
+
+
+ def testRewardAndPunishCase(self):
+ tbcbp = TBCBP()
+ tbcbp.registerService(self.s1, QoS=2)
+
+ case1 = Case(P=["p1","p2"],Q=["q1","q2"],
inputs=["i1"],outputs=["o2"], services=["s1"])
+ tbcbp.addCase(case1)
+ assert tbcbp.getCase(case1),getQoS() == 2
+
+ tbcbp.getCase(case1).reward()
+ assert tbcbp.getCase(case1).getQoS() == 1.0
+
+ tbcbp.getCase(case1).reward()
+ assert tbcbp.getCase(case1).getQoS() == 1.0
+
+ tbcbp.getCase(case1).punish()
+ assert tbcbp.getCase(case1).getQoS() >= 0.333333333333
+
+ tbcbp.getCase(case1).punish()
+ assert tbcbp.getCase(case1).getQoS() == 0.0
+
+ tbcbp.getCase(case1).reward()
+ assert tbcbp.getCase(case1).getQoS() == 0.2
+
+
+if __name__ == "__main__":
+ unittest.main()
=======================================
--- /trunk/ChangeLog Tue Jul 10 16:56:02 2012
+++ /trunk/ChangeLog Tue Jul 31 06:58:54 2012
@@ -1,4270 +0,0 @@
-2012-06-01 18:05 jpalanca
-
- * trunk/examples/unittests/coverage-unittests.py: added unittests
- for coverage analysis
-
-2012-06-01 16:52 jpalanca
-
- * trunk/examples/unittests/unittests.py: added
- unittest-xml-reporting
-
-2011-11-28 14:37 jpalanca
-
- * ChangeLog, doc/manual/book.xml, doc/manual/ch03-basic-agents.xml,
- doc/manual/ch06-bdi.xml, doc/manual/html/spade.bdi.html,
- doc/manual/images/note.png, doc/manual/images/tip.png,
- doc/manual/images/warning.png, svn2cl, svn2cl.xsl,
- trunk/spade/Agent.py: -Solved some issues in documentation
-
-2011-11-16 16:33 jpalanca
-
- * trunk/spade/Agent.py, trunk/spade/Behaviour.py: -Added
- retro-compatibility support for FIPA messages. Use the method
- attribute "xmppfipa" in the send function. -Added the regex patch
- to the message templates. Thanks to J. fernando Sanchez
-
-2011-11-11 16:02 jpalanca
-
- * trunk/spade/Agent.py, trunk/spade/diagram.py,
- trunk/templates/messages.pyra: -Changed sequencediagrams to
- Javascript API. Old API was not working. Still need to improve it.
- Websequencediagrams.com does not support large diagrams.
-
-2010-07-30 13:42 jpalanca
-
- * trunk/examples/unittests/aidTestCase.py,
- trunk/examples/unittests/dadTestCase.py,
- trunk/examples/unittests/dfTestCase.py,
- trunk/examples/unittests/pubsubTestCase.py,
- trunk/examples/unittests/rpcTestCase.py, trunk/spade/AID.py,
- trunk/spade/Agent.py, trunk/spade/DF.py, trunk/spade/RPC.py,
- trunk/spade/pubsub.py, trunk/xmppd/modules/pubsub.py: - Modified
- RPC API. Now service P and Q are matched with inputs and outputs
- stored (optionally) in the agent KB - DF.Service class now has a
- asContentObject method, so it can be converted easy to a XML
- string - DF now publishes service registrations and
- unregistrations using pubsub events - Fixed some XML and CO
- generations - Fixed pubsub module. Now PlatformAgents (with
- namespace NS_COMPONENT_ACCEPT) can use pubsub. Fixes issue 60.
-
-2010-07-20 15:35 jpalanca
-
- * trunk/examples/unittests/pubsubTestCase.py, trunk/spade/Agent.py,
- trunk/spade/Behaviour.py: - Added EventBehaviour to the pubsub
- subscriptions. Now an agent can register a callback
- (EventBehaviour) when an event is received! - Added and improved
- more pubsub unittests.
-
-2010-07-16 17:41 jpalanca
-
- * trunk/examples/pubsub, trunk/examples/pubsub/juliet.py,
- trunk/examples/pubsub/romeo.py,
- trunk/examples/unittests/pubsubTestCase.py,
- trunk/examples/unittests/unittests.py, trunk/spade.sh,
- trunk/spade/Agent.py, trunk/spade/pubsub.py,
- trunk/spade/socialnetwork.py, trunk/xmpp/protocol.py,
- trunk/xmppd/modules/__init__.py, trunk/xmppd/modules/db_fake.py,
- trunk/xmppd/modules/pubsub.py: - Added Personal Event Publication
- and Subscription Protocol! This amazing new feature (developed by
- cooldwind and sangarb1) allows agents to create events and
- subscribe to friend events, when their contact publish events.
- This was done following the Jabber XEP #60. This is an inital
- version, in future work more features will be added to the pubsub
- protocol. - Pubsub unittest were added. There is still some work
- to check their reliability. - Also some pubsub examples in
- directory examples/pubsub - Old spade.sh was deleted.
-
-2010-07-16 10:06 jpalanca
-
- * trunk/runspade.py, trunk/tlslite/TLSRecordLayer.py,
- trunk/tlslite/mathtls.py, trunk/tlslite/messages.py,
- trunk/tlslite/utils/cryptomath.py, trunk/xmpp/auth.py,
- trunk/xmppd/modules/dialback.py, trunk/xmppd/modules/jep0078.py,
- trunk/xmppd/modules/stream.py, trunk/xmppd/xmppd.py: - xmppd and
- tlslite now use hashlib instead of md5 and sha. Fixes issue 52 -
- runspade checks for netbsd OS
-
-2010-07-14 13:10 jpalanca
-
- * trunk/ChangeLog, trunk/examples/unittests/dfTestCase.py,
- trunk/spade/ACLMessage.py, trunk/spade/AMS.py,
- trunk/spade/Agent.py, trunk/spade/Behaviour.py, trunk/spade/DF.py,
- trunk/spade/Platform.py, trunk/spade/fipa.py, trunk/spade/wui.py,
- trunk/svn2cl, trunk/templates/404.pyra, trunk/templates/501.pyra,
- trunk/templates/503.pyra, trunk/templates/agents.pyra,
- trunk/templates/message.pyra, trunk/templates/sentmsg.pyra,
- trunk/xmpp/protocol.py: - Added send message WUI page - Fixed
- not-acceptable protocol type - Added reply_with and in_reply_to to
- ams and df templates to allow agents sending messages to
- themselves - Fixed ACL template match algorithm - Fixed acc loop
- hole when sending a message to the acc agent - DF main behaviour
- is not the default behaviour. using templates - WUI: notifyAMS now
- uses the standard fipa modifyAgent procedure - Error templates use
- new CSS style
-
-2010-07-11 23:13 jpalanca
-
- * trunk/examples/unittests/aidTestCase.py,
- trunk/examples/unittests/dadTestCase.py,
- trunk/examples/unittests/dfTestCase.py,
- trunk/examples/unittests/unittests.py, trunk/setup.py,
- trunk/spade/AID.py, trunk/spade/Agent.py, trunk/spade/DF.py,
- trunk/spade/SL0Parser.py, trunk/spade/fipa.py: - Fixed more bugs
- on DF and AID - Added AID unittests - Added DAD unittests - Fixed
- some bugs in setup.py
-
-2010-07-08 12:33 gusarba
-
- * trunk/runspade.py, trunk/spade/ACLMessage.py, trunk/spade/fipa.py,
- trunk/templates/header.pyra, trunk/templates/messages.pyra: -
- Fixed a potential bug in fipa.SearchAgentBehaviour when displaying
- a "not agree" or "not inform" debug message with a faulty AAD -
- WUI: More beautifying of the ACL messages in the 'Messages' tab
-
-2010-07-07 00:55 gusarba
-
- * trunk/spade/ACLMessage.py, trunk/spade/Agent.py,
- trunk/templates/messages.pyra: WUI: Started work on beautifying
- message inspector with ACLMessage.asHTML() method
-
-2010-07-06 09:38 cooldwind
-
- * trunk/spade/socialnetwork.py: Save agent and jid in SocialItem as
- attributes.
-
-2010-07-06 09:38 cooldwind
-
- * trunk/spade/socialnetwork.py: Fix bug in socialinetwork.py. Bad
- attribute name, self.presence -> self._presence.
-
-2010-07-05 20:51 jpalanca
-
- * trunk/spade/AID.py, trunk/spade/AMS.py, trunk/spade/Agent.py,
- trunk/spade/DF.py, trunk/templates/search.pyra: - Fixed agent
- search in WUI - Fixed AID match bug - Services inspection in
- search page - Added set/get Type to DF.Service
-
-2010-07-05 18:55 jpalanca
-
- * trunk/spade/AID.py, trunk/spade/AMS.py, trunk/spade/Agent.py,
- trunk/spade/DF.py, trunk/spade/Platform.py, trunk/spade/wui.py,
- trunk/templates/404.pyra, trunk/templates/501.pyra,
- trunk/templates/503.pyra, trunk/templates/admin.pyra,
- trunk/templates/agents.pyra, trunk/templates/clients.kid,
- trunk/templates/favicon.old.ico, trunk/templates/footer.pyra,
- trunk/templates/header.pyra, trunk/templates/header_platform.pyra,
- trunk/templates/img, trunk/templates/log.pyra,
- trunk/templates/login.kid, trunk/templates/login.pyra,
- trunk/templates/magwood.css, trunk/templates/master.html,
- trunk/templates/message-old.kid, trunk/templates/message.kid,
- trunk/templates/messages.pyra, trunk/templates/orgs.kid,
- trunk/templates/plugins.kid, trunk/templates/prefs.kid,
- trunk/templates/search.pyra, trunk/templates/services.kid,
- trunk/templates/services.pyra, trunk/templates/swimaster.kid,
- trunk/templates/webadmin-old.kid, trunk/templates/webadmin.pyra,
- trunk/templates/webadmin_indigo.pyra, trunk/templates/welcome.kid:
- - WUI: Fixed a bug in CSS. Now menu items are highlighted
- correctly. - WUI: Header and footer are now macros. - WUI: Deleted
- old web templates and images. - WUI: Added an agent (from and to)
- filter to the message inspector. - WUI: Widgetified some elements
- to a sidebar. - WUI: Started Search Box. Seems we have broken the
- agent empty search :(
-
-2010-07-04 14:59 gusarba
-
- * trunk/spade/DF.py, trunk/templates/admin.pyra,
- trunk/templates/agents.pyra, trunk/templates/footer.pyra,
- trunk/templates/header.pyra, trunk/templates/header_platform.pyra,
- trunk/templates/images/spade_logo_noalpha.png,
- trunk/templates/images/templatemo_background_section_top_bg.png,
- trunk/templates/images/templatemo_middle_section_box_bg.png,
- trunk/templates/log.pyra, trunk/templates/magwood.css,
- trunk/templates/messages.pyra, trunk/templates/services.pyra,
- trunk/templates/table.css, trunk/templates/table_blue.css,
- trunk/templates/webadmin_indigo.pyra: - Corrected SPADE url to
-
spade2.googlecode.com in some spots. - WUI: Changed the default
- CSS to a custom one based on our blog style (magwood.css). -
- Changed all the pyra templates to match the new CSS style. -
- Modified the Service asHTML() method to match new CSS style.
-
-2010-07-02 15:25 jpalanca
-
- * trunk/examples/unittests/dfTestCase.py,
- trunk/examples/unittests/rpcTestCase.py, trunk/spade/DF.py,
- trunk/spade/Platform.py, trunk/spade/RPC.py,
- trunk/templates/colorbox.css, trunk/templates/images,
- trunk/templates/images/border.png,
- trunk/templates/images/controls.png,
- trunk/templates/images/internet_explorer,
- trunk/templates/images/internet_explorer/borderBottomCenter.png,
- trunk/templates/images/internet_explorer/borderBottomLeft.png,
- trunk/templates/images/internet_explorer/borderBottomRight.png,
- trunk/templates/images/internet_explorer/borderMiddleLeft.png,
- trunk/templates/images/internet_explorer/borderMiddleRight.png,
- trunk/templates/images/internet_explorer/borderTopCenter.png,
- trunk/templates/images/internet_explorer/borderTopLeft.png,
- trunk/templates/images/internet_explorer/borderTopRight.png,
- trunk/templates/images/loading.gif,
- trunk/templates/images/loading_background.png,
- trunk/templates/images/overlay.png,
- trunk/templates/jquery.colorbox-min.js,
- trunk/templates/jquery.colorbox.js, trunk/templates/messages.pyra,
- trunk/templates/services.pyra: - Solved data inconsistency in
- DF.Service class. Now unittests are passed. Fixes issue 54. - New
- style for message inspector. Now using the colorbox javascript
- library. - Now modifying a service overwrites common parameters
- (ontologies, protocols and languages). - Service class has now
- function asHTML, which returns the service informations as html
- for the service wui controller.
-
-2010-06-29 23:39 jpalanca
-
- * trunk/examples/unittests/rpcTestCase.py, trunk/spade/AMS.py,
- trunk/spade/Agent.py, trunk/spade/RPC.py: More little problems
- solved in Message Inspector: 1)timestamp was not a good key for
- storing messages. 2) all messages have a From attr. No unknown
- message
-
-2010-06-29 20:27 cooldwind
-
- * trunk/spade/wui.py: Add timeout for WUI's httpd. Otherwise, agents
- can't stop. Fixes Issue #53. Signed-off-by: Santiago M. Mola
- <
cold...@coldwind.org>
-
-2010-06-29 19:24 jpalanca
-
- * trunk/examples/unittests/rpcTestCase.py, trunk/spade/AMS.py,
- trunk/spade/Agent.py, trunk/spade/MTP.py, trunk/spade/RPC.py,
- trunk/spade/peer2peer.py, trunk/spade/socialnetwork.py: Improved
- diagram logging for Message Inspector
-
-2010-06-28 21:39 jpalanca
-
- * trunk/spade/Agent.py, trunk/templates/messages.pyra,
- trunk/templates/quirksmode.css: Improved Message Inspector style
-
-2010-06-28 16:33 jpalanca
-
- * trunk/spade/ACLMessage.py, trunk/spade/Agent.py,
- trunk/spade/Platform.py, trunk/spade/content.py,
- trunk/spade/diagram.py, trunk/spade/wui.py,
- trunk/templates/404.pyra, trunk/templates/501.pyra,
- trunk/templates/503.pyra, trunk/templates/admin.pyra,
- trunk/templates/agents.pyra, trunk/templates/footer.pyra,
- trunk/templates/header.pyra, trunk/templates/header_platform.pyra,
- trunk/templates/log.pyra, trunk/templates/messages.pyra,
- trunk/templates/services.pyra, trunk/templates/webadmin.pyra,
- trunk/templates/webadmin_indigo.pyra: - Added new gorgeous Message
- Inspector with javascript and web services. Still needs a better
- CSS, but it is great. Fixes issue 46. - ACLMessages return now its
- XML representation by default. To get the ACL representation use
- the method asString() - Header and footer automatically included
- in templates - Removed some old references to gti-ia namespace.
- Spade namespace is now
spade2.googlecode.com
-
-2010-06-27 21:08 jpalanca
-
- * trunk/examples/unittests/rpcTestCase.py,
- trunk/examples/unittests/unittests.py, trunk/spade/Agent.py,
- trunk/spade/RPC.py: Added RPC unittests. Closes issue 50
-
-2010-06-26 13:49 jpalanca
-
- * trunk/examples/rpc.py, trunk/examples/unittests/dfTestCase.py,
- trunk/spade/Agent.py, trunk/spade/DF.py, trunk/spade/RPC.py,
- trunk/spade/pygooglechart.py, trunk/templates/admin.pyra: -Added
- new amazing feature: QR Codes at UI! Every agent shows a qrcode
- that shows its AID -Some corrections in RPC service invocation
-
-2010-06-25 17:40 jpalanca
-
- * trunk/examples/rpc.py: added an rpc example. unittests remain to
- be implemented
-
-2010-06-25 17:39 jpalanca
-
- * trunk/spade/Agent.py, trunk/spade/DF.py, trunk/spade/RPC.py,
- trunk/xmppd/modules/router.py: corrected some errors in RPC
- service invocation
-
-2010-06-24 23:31 jpalanca
-
- * trunk/spade/Agent.py, trunk/spade/RPC.py, trunk/spade/__init__.py,
- trunk/spade/bdi.py: Added Remote Service call using jabber-rpc.
- Need to write testcases
-
-2010-06-24 17:53 jpalanca
-
- * trunk/examples/unittests/dfTestCase.py, trunk/spade/Agent.py,
- trunk/spade/DF.py, trunk/spade/fipa.py: -Added a new Service()
- class that makes more easier the way of working with Services and
- with the DF -The old way of working with DfAgentDescriptors is
- still available, but the service-related methods now support
- *also* the new Service class. -All dfTestCases have been rewriting
- and now there are DAD and not DAD TestCases -Some new DF TestCases
- have been added -In future work a invokeService will be added to
- the Agent class
-
-2010-06-22 15:25 jpalanca
-
- * doc/manual/book.xml, doc/manual/ch06-bdi.xml,
- doc/manual/html/ch05s03.html, doc/manual/html/index.html,
- doc/manual/html/spade.advanced.eventbehaviour.html,
- doc/manual/html/spade.advanced.fsm.html,
- doc/manual/html/spade.advanced.html,
- doc/manual/html/spade.basic.html,
- doc/manual/html/spade.basic.im.html,
- doc/manual/html/spade.basic.mas.html,
- doc/manual/html/spade.basic.spadelibrary.html,
- doc/manual/html/spade.basic.spadeplatform.html,
- doc/manual/html/spade.basic.whatsnext.html,
- doc/manual/html/spade.basicagents.agentmodel.communication.html,
- doc/manual/html/spade.basicagents.agentmodel.html,
- doc/manual/html/spade.basicagents.behav.html,
- doc/manual/html/spade.basicagents.first.html,
- doc/manual/html/spade.basicagents.html,
- doc/manual/html/spade.basicagents.library.html,
- doc/manual/html/spade.basicagents.whatsnext.html,
- doc/manual/html/spade.bdi.future.html,
- doc/manual/html/spade.bdi.goals.html,
- doc/manual/html/spade.bdi.intro.html,
- doc/manual/html/spade.bdi.kb.html,
- doc/manual/html/spade.bdi.plans.html,
- doc/manual/html/spade.bdi.running.html,
- doc/manual/html/spade.foreword.html,
- doc/manual/html/spade.fundamental.html,
- doc/manual/html/spade.fundamental.platform.html,
- doc/manual/html/spade.platform.ams.html,
- doc/manual/html/spade.platform.df.html,
- doc/manual/html/spade.platform.html,
- doc/manual/html/spade.quickstart.html,
- doc/manual/html/spade.quickstart.installation.html,
- doc/manual/html/spade.quickstart.requirements.html,
- trunk/spade/DF.py: Corrected BDI documentation. Added a generic
- Service class to the DF
-
-2010-06-22 14:20 juagargi
-
- * trunk/spade/DF.py, trunk/spade/Platform.py,
- trunk/templates/agents.pyra, trunk/templates/services.pyra: WUI:
- Services tab works again. Fixes Issue 47
-
-2010-06-22 13:37 juagargi
-
- * trunk/templates/404.pyra, trunk/templates/501.pyra,
- trunk/templates/503.pyra, trunk/templates/admin.pyra,
- trunk/templates/agents.pyra, trunk/templates/log.pyra,
- trunk/templates/message.pyra, trunk/templates/services.pyra,
- trunk/templates/webadmin_indigo.pyra: WUI: Organizations tab
- removed. Fixes Issue 48
-
-2010-06-21 13:56 jpalanca
-
- * trunk/examples/unittests/eventbehavTestCase.py: Event Behaviour
- unittest added
-
-2010-06-21 13:15 juagargi
-
- * trunk/examples/event.py: Developed an EventBehaviour example
-
-2010-06-20 21:07 jpalanca
-
- * trunk/xmpp/transports.py: Commented the dns import error. Tried to
- import dnspython and did not work, so we choose to hide the error.
-
-2010-06-20 14:45 jpalanca
-
- * trunk/examples/unittests/amsTestCase.py, trunk/spade/AMS.py: Now
- Modifying an agent entry in the AMS does not require to provide an
- AID. AMS checks errors and completes the missing information.
- Fixes issue 34
-
-2010-06-20 11:01 gusarba
-
- * trunk/spade/Agent.py, trunk/spade/wui.py,
- trunk/templates/admin.pyra, trunk/templates/agents.pyra,
- trunk/templates/webadmin_indigo.pyra: WUI: The platform serves
- correctly its own documentation via a new 'API' tab. Fix #43
-
-2010-06-19 21:28 jpalanca
-
- * trunk/spade/AMS.py, trunk/spade/Agent.py, trunk/spade/DF.py,
- trunk/spade/SpadeConfigParser.py, trunk/spade/spade_backend.py,
- trunk/xmppd/modules/router.py:
-
-2010-06-19 01:39 jpalanca
-
- * trunk/runspade.py, trunk/spade/wui.py: improving the WUI debug
-
-2010-06-18 17:31 gusarba
-
- * trunk/spade/Agent.py, trunk/templates/admin.pyra: Pyra templates:
- Cleared up 'Admin' tab removing the agent log from the debug table
- and adding other minor enhancements
-
-2010-06-18 15:57 juagargi
-
- * trunk/xmppd/xmppd.py: Solved issues with xmppd server in windows.
- Now fake select and poll work in any OS
-
-2010-06-17 13:07 gusarba
-
- * trunk/templates/admin.pyra, trunk/templates/webadmin_indigo.pyra:
- Pyra templates: experimental attribute navigation in 'Admin' tab
-
-2010-06-17 13:07 gusarba
-
- * trunk/spade/Agent.py, trunk/spade/Platform.py: Pyra templates:
- experimental attribute navigation in 'Admin' tab
-
-2010-06-16 14:34 jpalanca
-
- * trunk/spade/Agent.py: Now agents notices when cannot connect to a
- SPADE platform. Fixes issue 45
-
-2010-06-16 13:51 jpalanca
-
- * trunk/runspade.py: Now runspade script shows an error message when
- there is no config file. fixes #27
-
-2010-06-15 14:07 gusarba
-
- * trunk/templates/agents.pyra: Fixed a bug in the WUI 'Agents' tab:
- the AWUI links now point to the 'Admin' tab instead of to a
- non-existent index page
-
-2010-06-11 08:33 jpalanca
-
- * trunk/runspade.py: updated copyright and version number (from RC3
- to RC4)
-
-2010-06-10 20:34 gusarba
-
- * trunk/templates/favicon.ico: Pyra templates: favicon changed
-
-2010-06-10 20:33 gusarba
-
- * trunk/templates/favicon.ico, trunk/templates/favicon.old.ico,
- trunk/templates/quirksmode.css: Pyra templates: Minor changes and
- favicon changed
-
-2010-06-10 20:15 gusarba
-
- * trunk/templates/404.pyra, trunk/templates/501.pyra,
- trunk/templates/503.pyra, trunk/templates/admin.pyra,
- trunk/templates/agents.pyra, trunk/templates/log.pyra,
- trunk/templates/quirksmode.css,
- trunk/templates/webadmin_indigo.pyra: Pyra templates: Removed some
- old corporate logos. Replaced logo with the new one. Some color
- changes
-
-2010-06-09 19:15 jpalanca
-
- * doc/manual/ch01-quickstart-guide.xml,
- doc/manual/ch02-fundamental-concepts.xml,
- doc/manual/ch03-basic-agents.xml, trunk/runspade.py: removing old
- corporative references
-
-2010-05-26 14:27 root
-
- * trunk/doc/api.tar.gz, trunk/doc/html,
- trunk/doc/html/api-objects.txt, trunk/doc/html/class-tree.html,
- trunk/doc/html/crarr.png, trunk/doc/html/epydoc.css,
- trunk/doc/html/epydoc.js, trunk/doc/html/frames.html,
- trunk/doc/html/help.html, trunk/doc/html/identifier-index-A.html,
- trunk/doc/html/identifier-index-B.html,
- trunk/doc/html/identifier-index-C.html,
- trunk/doc/html/identifier-index-D.html,
- trunk/doc/html/identifier-index-E.html,
- trunk/doc/html/identifier-index-F.html,
- trunk/doc/html/identifier-index-G.html,
- trunk/doc/html/identifier-index-H.html,
- trunk/doc/html/identifier-index-I.html,
- trunk/doc/html/identifier-index-J.html,
- trunk/doc/html/identifier-index-K.html,
- trunk/doc/html/identifier-index-L.html,
- trunk/doc/html/identifier-index-M.html,
- trunk/doc/html/identifier-index-N.html,
- trunk/doc/html/identifier-index-O.html,
- trunk/doc/html/identifier-index-P.html,
- trunk/doc/html/identifier-index-Q.html,
- trunk/doc/html/identifier-index-R.html,
- trunk/doc/html/identifier-index-S.html,
- trunk/doc/html/identifier-index-T.html,
- trunk/doc/html/identifier-index-U.html,
- trunk/doc/html/identifier-index-V.html,
- trunk/doc/html/identifier-index-W.html,
- trunk/doc/html/identifier-index-X.html,
- trunk/doc/html/identifier-index-Y.html,
- trunk/doc/html/identifier-index-Z.html,
- trunk/doc/html/identifier-index-_.html,
- trunk/doc/html/identifier-index.html, trunk/doc/html/index.html,
- trunk/doc/html/mimetools.Message-class.html,
- trunk/doc/html/module-tree.html, trunk/doc/html/redirect.html,
- trunk/doc/html/spade-module.html, trunk/doc/html/spade-pysrc.html,
- trunk/doc/html/spade.ACLMessage-module.html,
- trunk/doc/html/spade.ACLMessage-pysrc.html,
- trunk/doc/html/spade.ACLMessage.ACLMessage-class.html,
- trunk/doc/html/spade.ACLParser-module.html,
- trunk/doc/html/spade.ACLParser-pysrc.html,
- trunk/doc/html/spade.ACLParser.ACLParser-class.html,
- trunk/doc/html/spade.ACLParser.ACLxmlParser-class.html,
- trunk/doc/html/spade.AID-module.html,
- trunk/doc/html/spade.AID-pysrc.html,
- trunk/doc/html/spade.AID.aid-class.html,
- trunk/doc/html/spade.AMS-module.html,
- trunk/doc/html/spade.AMS-pysrc.html,
- trunk/doc/html/spade.AMS.AMS-class.html,
- trunk/doc/html/spade.AMS.AMS.DefaultBehaviour-class.html,
-
trunk/doc/html/spade.AMS.AMS.DefaultBehaviour.SubscribeBehaviour-class.html,
- trunk/doc/html/spade.AMS.AMS.ModifyBehaviour-class.html,
- trunk/doc/html/spade.AMS.AMS.PlatformBehaviour-class.html,
- trunk/doc/html/spade.AMS.AMS.RegisterBehaviour-class.html,
- trunk/doc/html/spade.AMS.AMS.SearchBehaviour-class.html,
- trunk/doc/html/spade.AMS.AmsAgentDescription-class.html,
- trunk/doc/html/spade.Agent-module.html,
- trunk/doc/html/spade.Agent-pysrc.html,
- trunk/doc/html/spade.Agent.AbstractAgent-class.html,
- trunk/doc/html/spade.Agent.Agent-class.html,
- trunk/doc/html/spade.Agent.PlatformAgent-class.html,
- trunk/doc/html/spade.Agent.jabberProcess-class.html,
- trunk/doc/html/spade.BasicFipaDateTime-module.html,
- trunk/doc/html/spade.BasicFipaDateTime-pysrc.html,
- trunk/doc/html/spade.BasicFipaDateTime.BasicFipaDateTime-class.html,
- trunk/doc/html/spade.Behaviour-module.html,
- trunk/doc/html/spade.Behaviour-pysrc.html,
- trunk/doc/html/spade.Behaviour.ACLTemplate-class.html,
- trunk/doc/html/spade.Behaviour.ANDTemplate-class.html,
- trunk/doc/html/spade.Behaviour.Behaviour-class.html,
- trunk/doc/html/spade.Behaviour.BehaviourTemplate-class.html,
- trunk/doc/html/spade.Behaviour.EventBehaviour-class.html,
- trunk/doc/html/spade.Behaviour.FSMBehaviour-class.html,
- trunk/doc/html/spade.Behaviour.MessageTemplate-class.html,
- trunk/doc/html/spade.Behaviour.NOTTemplate-class.html,
- trunk/doc/html/spade.Behaviour.ORTemplate-class.html,
- trunk/doc/html/spade.Behaviour.OneShotBehaviour-class.html,
- trunk/doc/html/spade.Behaviour.PeriodicBehaviour-class.html,
- trunk/doc/html/spade.Behaviour.TimeOutBehaviour-class.html,
- trunk/doc/html/spade.Behaviour.XORTemplate-class.html,
- trunk/doc/html/spade.DF-module.html,
- trunk/doc/html/spade.DF-pysrc.html,
- trunk/doc/html/spade.DF.DF-class.html,
- trunk/doc/html/spade.DF.DF.DefaultBehaviour-class.html,
- trunk/doc/html/spade.DF.DF.ModifyBehaviour-class.html,
- trunk/doc/html/spade.DF.DF.RegisterBehaviour-class.html,
- trunk/doc/html/spade.DF.DF.SearchBehaviour-class.html,
- trunk/doc/html/spade.DF.DfAgentDescription-class.html,
- trunk/doc/html/spade.DF.ServiceDescription-class.html,
- trunk/doc/html/spade.Envelope-module.html,
- trunk/doc/html/spade.Envelope-pysrc.html,
- trunk/doc/html/spade.Envelope.Envelope-class.html,
- trunk/doc/html/spade.FIPAMessage-module.html,
- trunk/doc/html/spade.FIPAMessage-pysrc.html,
- trunk/doc/html/spade.FIPAMessage.FipaMessage-class.html,
- trunk/doc/html/spade.MTP-module.html,
- trunk/doc/html/spade.MTP-pysrc.html,
- trunk/doc/html/spade.MTP.MTP-class.html,
- trunk/doc/html/spade.MessageReceiver-module.html,
- trunk/doc/html/spade.MessageReceiver-pysrc.html,
- trunk/doc/html/spade.MessageReceiver.MessageReceiver-class.html,
- trunk/doc/html/spade.Organization-module.html,
- trunk/doc/html/spade.Organization-pysrc.html,
- trunk/doc/html/spade.Organization.BanedUser-class.html,
- trunk/doc/html/spade.Organization.CreationError-class.html,
- trunk/doc/html/spade.Organization.DestroyError-class.html,
- trunk/doc/html/spade.Organization.JoinError-class.html,
- trunk/doc/html/spade.Organization.LastOwner-class.html,
- trunk/doc/html/spade.Organization.LockedOrganization-class.html,
- trunk/doc/html/spade.Organization.MaximumUsers-class.html,
- trunk/doc/html/spade.Organization.MemberOfFederation-class.html,
- trunk/doc/html/spade.Organization.MembersOnly-class.html,
- trunk/doc/html/spade.Organization.NickNameConflict-class.html,
- trunk/doc/html/spade.Organization.NotOwner-class.html,
- trunk/doc/html/spade.Organization.NotSupervisor-class.html,
- trunk/doc/html/spade.Organization.NotValidGoal-class.html,
- trunk/doc/html/spade.Organization.NotValidName-class.html,
- trunk/doc/html/spade.Organization.NotValidType-class.html,
- trunk/doc/html/spade.Organization.NotValidUnit-class.html,
- trunk/doc/html/spade.Organization.Organization-class.html,
-
trunk/doc/html/spade.Organization.Organization.CreateRoomBehaviour-class.html,
-
trunk/doc/html/spade.Organization.Organization.CreateTeamBehaviour-class.html,
-
trunk/doc/html/spade.Organization.Organization.DestroyBehaviour-class.html,
-
trunk/doc/html/spade.Organization.Organization.GetRegistrationFormBehaviour-class.html,
-
trunk/doc/html/spade.Organization.Organization.GetUnitInfoBehaviour-class.html,
-
trunk/doc/html/spade.Organization.Organization.GetUnitListBehaviour-class.html,
-
trunk/doc/html/spade.Organization.Organization.IsMemberBehaviour-class.html,
-
trunk/doc/html/spade.Organization.Organization.MyJoinRoomBehaviour-class.html,
-
trunk/doc/html/spade.Organization.Organization.SendRegistrationFormBehaviour-class.html,
-
trunk/doc/html/spade.Organization.Organization.TestRoomNameBehaviour-class.html,
- trunk/doc/html/spade.Organization.PaswordNeeded-class.html,
- trunk/doc/html/spade.Organization.Unavailable-class.html,
- trunk/doc/html/spade.Organization.UnavailableFunction-class.html,
- trunk/doc/html/spade.Organization_new-module.html,
- trunk/doc/html/spade.Organization_new-pysrc.html,
- trunk/doc/html/spade.Organization_new.BanedUser-class.html,
- trunk/doc/html/spade.Organization_new.CreationError-class.html,
- trunk/doc/html/spade.Organization_new.DestroyError-class.html,
- trunk/doc/html/spade.Organization_new.JoinError-class.html,
- trunk/doc/html/spade.Organization_new.LastOwner-class.html,
- trunk/doc/html/spade.Organization_new.LockedOrganization-class.html,
- trunk/doc/html/spade.Organization_new.MaximumUsers-class.html,
- trunk/doc/html/spade.Organization_new.MemberOfFederation-class.html,
- trunk/doc/html/spade.Organization_new.MembersOnly-class.html,
- trunk/doc/html/spade.Organization_new.NickNameConflict-class.html,
- trunk/doc/html/spade.Organization_new.NotCreatePermision-class.html,
- trunk/doc/html/spade.Organization_new.NotSupervisor-class.html,
- trunk/doc/html/spade.Organization_new.NotValidGoal-class.html,
- trunk/doc/html/spade.Organization_new.NotValidName-class.html,
- trunk/doc/html/spade.Organization_new.NotValidType-class.html,
- trunk/doc/html/spade.Organization_new.NotValidUnit-class.html,
- trunk/doc/html/spade.Organization_new.Organization_new-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.CreateRoomBehaviour-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.CreateTeamBehaviour-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.DestroyBehaviour-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.GetRegistrationFormBehaviour-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.GetUnitInfoBehaviour-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.GetUnitListBehaviour-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.IsMemberBehaviour-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.MyJoinRoomBehaviour-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.SendRegistrationFormBehaviour-class.html,
-
trunk/doc/html/spade.Organization_new.Organization_new.TestRoomNameBehaviour-class.html,
- trunk/doc/html/spade.Organization_new.PaswordNeeded-class.html,
- trunk/doc/html/spade.Organization_new.Unavailable-class.html,
- trunk/doc/html/spade.Organization_new.UnavailableFunction-class.html,
- trunk/doc/html/spade.Platform-module.html,
- trunk/doc/html/spade.Platform-pysrc.html,
- trunk/doc/html/spade.Platform.PlatformRestart-class.html,
- trunk/doc/html/spade.Platform.SpadePlatform-class.html,
- trunk/doc/html/spade.Platform.SpadePlatform.GetMembersBehav-class.html,
- trunk/doc/html/spade.Platform.SpadePlatform.RouteBehaviour-class.html,
- trunk/doc/html/spade.RDF0Parser-module.html,
- trunk/doc/html/spade.RDF0Parser-pysrc.html,
- trunk/doc/html/spade.RDF0Parser.Newdict-class.html,
- trunk/doc/html/spade.RDF0Parser.RDF0Parser-class.html,
- trunk/doc/html/spade.ReceivedObject-module.html,
- trunk/doc/html/spade.ReceivedObject-pysrc.html,
- trunk/doc/html/spade.ReceivedObject.ReceivedObject-class.html,
- trunk/doc/html/spade.SIMBA-module.html,
- trunk/doc/html/spade.SIMBA-pysrc.html,
- trunk/doc/html/spade.SIMBA.SIMBA-class.html,
- trunk/doc/html/spade.SIMBA.SIMBA.InboxBehaviour-class.html,
-
trunk/doc/html/spade.SIMBA.SIMBA.InboxBehaviour.SimbaRequestHandler-class.html,
- trunk/doc/html/spade.SIMBA.SIMBA.OutboxBehaviour-class.html,
- trunk/doc/html/spade.SL0Parser-module.html,
- trunk/doc/html/spade.SL0Parser-pysrc.html,
- trunk/doc/html/spade.SL0Parser.SL0Parser-class.html,
- trunk/doc/html/spade.SpadeConfigParser-module.html,
- trunk/doc/html/spade.SpadeConfigParser-pysrc.html,
- trunk/doc/html/spade.SpadeConfigParser.ConfigParser-class.html,
- trunk/doc/html/spade.SpadeConfigParser.ParseObject-class.html,
- trunk/doc/html/spade.SpadeConfigParser.spadeXML-class.html,
- trunk/doc/html/spade.SpadeConfigParser.spadeXMLHandler-class.html,
- trunk/doc/html/spade.Unit-module.html,
- trunk/doc/html/spade.Unit-pysrc.html,
- trunk/doc/html/spade.Unit.BanedUser-class.html,
- trunk/doc/html/spade.Unit.CreationError-class.html,
- trunk/doc/html/spade.Unit.DestroyError-class.html,
- trunk/doc/html/spade.Unit.JoinError-class.html,
- trunk/doc/html/spade.Unit.LastOwner-class.html,
- trunk/doc/html/spade.Unit.LockedUnit-class.html,
- trunk/doc/html/spade.Unit.MaximumUsers-class.html,
- trunk/doc/html/spade.Unit.MembersOnly-class.html,
- trunk/doc/html/spade.Unit.NickNameConflict-class.html,
- trunk/doc/html/spade.Unit.NotAdmin-class.html,
- trunk/doc/html/spade.Unit.NotSupervisor-class.html,
- trunk/doc/html/spade.Unit.NotValidGoal-class.html,
- trunk/doc/html/spade.Unit.NotValidGoalChange-class.html,
- trunk/doc/html/spade.Unit.NotValidName-class.html,
- trunk/doc/html/spade.Unit.NotValidType-class.html,
- trunk/doc/html/spade.Unit.NotValidUnit-class.html,
- trunk/doc/html/spade.Unit.PaswordNeeded-class.html,
- trunk/doc/html/spade.Unit.Unavailable-class.html,
- trunk/doc/html/spade.Unit.Unit-class.html,
- trunk/doc/html/spade.Unit.Unit.AddAdminBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.AddBanAgentBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.AddModeratorBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.AddOwnerBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.CreateRoomBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.DestroyBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetAdminListBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetBanAgentListBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetGoalBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetInfoBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetMaxAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetMemberListBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetMinAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetModeratorListBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetNumberOfAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GetOwnerListBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.GiveVoiceBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.KickAgentBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.MyJoinRoomBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.PresenceBehaviour-class.html,
-
trunk/doc/html/spade.Unit.Unit.PresenceBehaviour.MinAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.RemoveAdminBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.RemoveBanAgentBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.RemoveModeratorBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.RemoveOwnerBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.RevokeVoiceBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.SendMessageBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.SendPrivateMessageBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.SetGoalBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.SetMaxAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.SetMinAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit.Unit.TestRoomNameBehaviour-class.html,
- trunk/doc/html/spade.Unit_new-module.html,
- trunk/doc/html/spade.Unit_new-pysrc.html,
- trunk/doc/html/spade.Unit_new.BanedUser-class.html,
- trunk/doc/html/spade.Unit_new.CreationError-class.html,
- trunk/doc/html/spade.Unit_new.DestroyError-class.html,
- trunk/doc/html/spade.Unit_new.JoinError-class.html,
- trunk/doc/html/spade.Unit_new.LastOwner-class.html,
- trunk/doc/html/spade.Unit_new.LockedUnit-class.html,
- trunk/doc/html/spade.Unit_new.MaximumUsers-class.html,
- trunk/doc/html/spade.Unit_new.MembersOnly-class.html,
- trunk/doc/html/spade.Unit_new.NickNameConflict-class.html,
- trunk/doc/html/spade.Unit_new.NotCreatePermision-class.html,
- trunk/doc/html/spade.Unit_new.NotSupervisor-class.html,
- trunk/doc/html/spade.Unit_new.NotValidGoal-class.html,
- trunk/doc/html/spade.Unit_new.NotValidGoalChange-class.html,
- trunk/doc/html/spade.Unit_new.NotValidName-class.html,
- trunk/doc/html/spade.Unit_new.NotValidType-class.html,
- trunk/doc/html/spade.Unit_new.NotValidUnit-class.html,
- trunk/doc/html/spade.Unit_new.PaswordNeeded-class.html,
- trunk/doc/html/spade.Unit_new.Unavailable-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.AddAdminBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.AddBanAgentBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.AddModeratorBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.CreateRoomBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.DestroyBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.GetAdminListBehaviour-class.html,
-
trunk/doc/html/spade.Unit_new.Unit_new.GetBanAgentListBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.GetGoalBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.GetInfoBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.GetMaxAgentsBehaviour-class.html,
-
trunk/doc/html/spade.Unit_new.Unit_new.GetMemberListBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.GetMinAgentsBehaviour-class.html,
-
trunk/doc/html/spade.Unit_new.Unit_new.GetModeratorListBehaviour-class.html,
-
trunk/doc/html/spade.Unit_new.Unit_new.GetNumberOfAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.GetOwnerListBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.GiveVoiceBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.KickAgentBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.MyJoinRoomBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.PresenceBehaviour-class.html,
-
trunk/doc/html/spade.Unit_new.Unit_new.PresenceBehaviour.MinAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.RemoveAdminBehaviour-class.html,
-
trunk/doc/html/spade.Unit_new.Unit_new.RemoveBanAgentBehaviour-class.html,
-
trunk/doc/html/spade.Unit_new.Unit_new.RemoveModeratorBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.RevokeVoiceBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.SendMessageBehaviour-class.html,
-
trunk/doc/html/spade.Unit_new.Unit_new.SendPrivateMessageBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.SetGoalBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.SetMaxAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.SetMinAgentsBehaviour-class.html,
- trunk/doc/html/spade.Unit_new.Unit_new.TestRoomNameBehaviour-class.html,
- trunk/doc/html/spade.XMLCodec-module.html,
- trunk/doc/html/spade.XMLCodec-pysrc.html,
- trunk/doc/html/spade.XMLCodec.XMLCodec-class.html,
- trunk/doc/html/spade.bdi-module.html,
- trunk/doc/html/spade.bdi-pysrc.html,
- trunk/doc/html/spade.bdi.BDIAgent-class.html,
- trunk/doc/html/spade.bdi.Goal-class.html,
- trunk/doc/html/spade.bdi.Plan-class.html,
- trunk/doc/html/spade.bdi.PostConditionFailed-class.html,
- trunk/doc/html/spade.bdi.PreConditionFailed-class.html,
- trunk/doc/html/spade.bdi.Service-class.html,
- trunk/doc/html/spade.colors-module.html,
- trunk/doc/html/spade.colors-pysrc.html,
- trunk/doc/html/spade.content-module.html,
- trunk/doc/html/spade.content-pysrc.html,
- trunk/doc/html/spade.content.ContentObject-class.html,
- trunk/doc/html/spade.fipa-module.html,
- trunk/doc/html/spade.fipa-pysrc.html,
- trunk/doc/html/spade.fipa.ModifyAgentBehaviour-class.html,
- trunk/doc/html/spade.fipa.SearchAgentBehaviour-class.html,
- trunk/doc/html/spade.fipa.deregisterServiceBehaviour-class.html,
- trunk/doc/html/spade.fipa.getPlatformInfoBehaviour-class.html,
- trunk/doc/html/spade.fipa.modifyServiceBehaviour-class.html,
- trunk/doc/html/spade.fipa.registerServiceBehaviour-class.html,
- trunk/doc/html/spade.fipa.searchServiceBehaviour-class.html,
- trunk/doc/html/spade.logic-module.html,
- trunk/doc/html/spade.logic-pysrc.html,
- trunk/doc/html/spade.logic.Expr-class.html,
- trunk/doc/html/spade.logic.FolKB-class.html,
- trunk/doc/html/spade.logic.KB-class.html,
- trunk/doc/html/spade.logic.PropHornKB-class.html,
- trunk/doc/html/spade.logic.PropKB-class.html,
- trunk/doc/html/spade.logic.logicTest-class.html,
- trunk/doc/html/spade.msgtypes-module.html,
- trunk/doc/html/spade.msgtypes-pysrc.html,
- trunk/doc/html/spade.peer2peer-module.html,
- trunk/doc/html/spade.peer2peer-pysrc.html,
- trunk/doc/html/spade.peer2peer.DiscoBehaviour-class.html,
- trunk/doc/html/spade.peer2peer.P2PBehaviour-class.html,
-
trunk/doc/html/spade.peer2peer.P2PBehaviour.P2PRequestHandler-class.html,
- trunk/doc/html/spade.peer2peer.RequestDiscoInfoBehav-class.html,
- trunk/doc/html/spade.peer2peer.SendStreamInitiationBehav-class.html,
- trunk/doc/html/spade.peer2peer.StreamInitiationBehaviour-class.html,
- trunk/doc/html/spade.pyparsing-module.html,
- trunk/doc/html/spade.pyparsing-pysrc.html,
- trunk/doc/html/spade.pyparsing.And-class.html,
- trunk/doc/html/spade.pyparsing.CaselessLiteral-class.html,
- trunk/doc/html/spade.pyparsing.CharsNotIn-class.html,
- trunk/doc/html/spade.pyparsing.Combine-class.html,
- trunk/doc/html/spade.pyparsing.Dict-class.html,
- trunk/doc/html/spade.pyparsing.Each-class.html,
- trunk/doc/html/spade.pyparsing.Empty-class.html,
- trunk/doc/html/spade.pyparsing.FollowedBy-class.html,
- trunk/doc/html/spade.pyparsing.Forward-class.html,
- trunk/doc/html/spade.pyparsing.GoToColumn-class.html,
- trunk/doc/html/spade.pyparsing.Group-class.html,
- trunk/doc/html/spade.pyparsing.Keyword-class.html,
- trunk/doc/html/spade.pyparsing.LineEnd-class.html,
- trunk/doc/html/spade.pyparsing.LineStart-class.html,
- trunk/doc/html/spade.pyparsing.Literal-class.html,
- trunk/doc/html/spade.pyparsing.MatchFirst-class.html,
- trunk/doc/html/spade.pyparsing.NoMatch-class.html,
- trunk/doc/html/spade.pyparsing.NotAny-class.html,
- trunk/doc/html/spade.pyparsing.OneOrMore-class.html,
- trunk/doc/html/spade.pyparsing.Optional-class.html,
- trunk/doc/html/spade.pyparsing.Or-class.html,
- trunk/doc/html/spade.pyparsing.ParseBaseException-class.html,
- trunk/doc/html/spade.pyparsing.ParseElementEnhance-class.html,
- trunk/doc/html/spade.pyparsing.ParseException-class.html,
- trunk/doc/html/spade.pyparsing.ParseExpression-class.html,
- trunk/doc/html/spade.pyparsing.ParseFatalException-class.html,
- trunk/doc/html/spade.pyparsing.ParseResults-class.html,
- trunk/doc/html/spade.pyparsing.ParserElement-class.html,
- trunk/doc/html/spade.pyparsing.PositionToken-class.html,
- trunk/doc/html/spade.pyparsing.RecursiveGrammarException-class.html,
- trunk/doc/html/spade.pyparsing.SkipTo-class.html,
- trunk/doc/html/spade.pyparsing.StringEnd-class.html,
- trunk/doc/html/spade.pyparsing.StringStart-class.html,
- trunk/doc/html/spade.pyparsing.Suppress-class.html,
- trunk/doc/html/spade.pyparsing.Token-class.html,
- trunk/doc/html/spade.pyparsing.TokenConverter-class.html,
- trunk/doc/html/spade.pyparsing.Upcase-class.html,
- trunk/doc/html/spade.pyparsing.White-class.html,
- trunk/doc/html/spade.pyparsing.Word-class.html,
- trunk/doc/html/spade.pyparsing.ZeroOrMore-class.html,
- trunk/doc/html/spade.pyparsing._ForwardNoRecurse-class.html,
- trunk/doc/html/spade.pyratemp-module.html,
- trunk/doc/html/spade.pyratemp-pysrc.html,
- trunk/doc/html/spade.pyratemp.FileLoader-class.html,
- trunk/doc/html/spade.pyratemp.Parser-class.html,
- trunk/doc/html/spade.pyratemp.PseudoSandbox-class.html,
- trunk/doc/html/spade.pyratemp.Renderer-class.html,
- trunk/doc/html/spade.pyratemp.StringLoader-class.html,
- trunk/doc/html/spade.pyratemp.Template-class.html,
- trunk/doc/html/spade.pyratemp.TemplateBase-class.html,
- trunk/doc/html/spade.pyratemp.TemplateEval-class.html,
- trunk/doc/html/spade.pyratemp.TemplateException-class.html,
- trunk/doc/html/spade.pyratemp.TemplateIncludeError-class.html,
- trunk/doc/html/spade.pyratemp.TemplateParseError-class.html,
- trunk/doc/html/spade.pyratemp.TemplateRenderError-class.html,
- trunk/doc/html/spade.pyratemp.TemplateSyntaxError-class.html,
- trunk/doc/html/spade.pyratemp._dontescape-class.html,
- trunk/doc/html/spade.socialnetwork-module.html,
- trunk/doc/html/spade.socialnetwork-pysrc.html,
- trunk/doc/html/spade.socialnetwork.PresenceBehaviour-class.html,
- trunk/doc/html/spade.socialnetwork.RosterBehaviour-class.html,
- trunk/doc/html/spade.socialnetwork.SocialItem-class.html,
- trunk/doc/html/spade.spade_backend-module.html,
- trunk/doc/html/spade.spade_backend-pysrc.html,
- trunk/doc/html/spade.spade_backend.SpadeBackend-class.html,
- trunk/doc/html/spade.wui-module.html,
- trunk/doc/html/spade.wui-pysrc.html,
- trunk/doc/html/spade.wui.WUI-class.html,
- trunk/doc/html/spade.wui.WUIHandler-class.html,
- trunk/doc/html/spade.xmpp-module.html,
- trunk/doc/html/spade.xmpp-pysrc.html,
- trunk/doc/html/spade.xmpp.auth-module.html,
- trunk/doc/html/spade.xmpp.auth-pysrc.html,
- trunk/doc/html/spade.xmpp.auth.Bind-class.html,
- trunk/doc/html/spade.xmpp.auth.ComponentBind-class.html,
- trunk/doc/html/spade.xmpp.auth.NonSASL-class.html,
- trunk/doc/html/spade.xmpp.auth.SASL-class.html,
- trunk/doc/html/spade.xmpp.browser-module.html,
- trunk/doc/html/spade.xmpp.browser-pysrc.html,
- trunk/doc/html/spade.xmpp.browser.Browser-class.html,
- trunk/doc/html/spade.xmpp.client-module.html,
- trunk/doc/html/spade.xmpp.client-pysrc.html,
- trunk/doc/html/spade.xmpp.client.Client-class.html,
- trunk/doc/html/spade.xmpp.client.CommonClient-class.html,
- trunk/doc/html/spade.xmpp.client.Component-class.html,
- trunk/doc/html/spade.xmpp.client.PlugIn-class.html,
- trunk/doc/html/spade.xmpp.commands-module.html,
- trunk/doc/html/spade.xmpp.commands-pysrc.html,
- trunk/doc/html/spade.xmpp.commands.Command_Handler_Prototype-class.html,
- trunk/doc/html/spade.xmpp.commands.Commands-class.html,
- trunk/doc/html/spade.xmpp.commands.TestCommand-class.html,
- trunk/doc/html/spade.xmpp.debug-module.html,
- trunk/doc/html/spade.xmpp.debug-pysrc.html,
- trunk/doc/html/spade.xmpp.debug.Debug-class.html,
- trunk/doc/html/spade.xmpp.debug.NoDebug-class.html,
- trunk/doc/html/spade.xmpp.dispatcher-module.html,
- trunk/doc/html/spade.xmpp.dispatcher-pysrc.html,
- trunk/doc/html/spade.xmpp.dispatcher.Dispatcher-class.html,
- trunk/doc/html/spade.xmpp.features-module.html,
- trunk/doc/html/spade.xmpp.features-pysrc.html,
- trunk/doc/html/spade.xmpp.filetransfer-module.html,
- trunk/doc/html/spade.xmpp.filetransfer-pysrc.html,
- trunk/doc/html/spade.xmpp.filetransfer.IBB-class.html,
- trunk/doc/html/spade.xmpp.protocol-module.html,
- trunk/doc/html/spade.xmpp.protocol-pysrc.html,
- trunk/doc/html/spade.xmpp.protocol.BadFormat-class.html,
- trunk/doc/html/spade.xmpp.protocol.BadNamespacePrefix-class.html,
- trunk/doc/html/spade.xmpp.protocol.Conflict-class.html,
- trunk/doc/html/spade.xmpp.protocol.ConnectionTimeout-class.html,
- trunk/doc/html/spade.xmpp.protocol.DataField-class.html,
- trunk/doc/html/spade.xmpp.protocol.DataForm-class.html,
- trunk/doc/html/spade.xmpp.protocol.Error-class.html,
- trunk/doc/html/spade.xmpp.protocol.ErrorNode-class.html,
- trunk/doc/html/spade.xmpp.protocol.HostGone-class.html,
- trunk/doc/html/spade.xmpp.protocol.HostUnknown-class.html,
- trunk/doc/html/spade.xmpp.protocol.ImproperAddressing-class.html,
- trunk/doc/html/spade.xmpp.protocol.InternalServerError-class.html,
- trunk/doc/html/spade.xmpp.protocol.InvalidFrom-class.html,
- trunk/doc/html/spade.xmpp.protocol.InvalidID-class.html,
- trunk/doc/html/spade.xmpp.protocol.InvalidNamespace-class.html,
- trunk/doc/html/spade.xmpp.protocol.InvalidXML-class.html,
- trunk/doc/html/spade.xmpp.protocol.Iq-class.html,
- trunk/doc/html/spade.xmpp.protocol.JID-class.html,
- trunk/doc/html/spade.xmpp.protocol.Message-class.html,
- trunk/doc/html/spade.xmpp.protocol.NodeProcessed-class.html,
- trunk/doc/html/spade.xmpp.protocol.NotAuthorized-class.html,
- trunk/doc/html/spade.xmpp.protocol.PolicyViolation-class.html,
- trunk/doc/html/spade.xmpp.protocol.Presence-class.html,
- trunk/doc/html/spade.xmpp.protocol.Protocol-class.html,
- trunk/doc/html/spade.xmpp.protocol.RemoteConnectionFailed-class.html,
- trunk/doc/html/spade.xmpp.protocol.ResourceConstraint-class.html,
- trunk/doc/html/spade.xmpp.protocol.RestrictedXML-class.html,
- trunk/doc/html/spade.xmpp.protocol.SeeOtherHost-class.html,
- trunk/doc/html/spade.xmpp.protocol.StreamError-class.html,
- trunk/doc/html/spade.xmpp.protocol.SystemShutdown-class.html,
- trunk/doc/html/spade.xmpp.protocol.UndefinedCondition-class.html,
- trunk/doc/html/spade.xmpp.protocol.UnsupportedEncoding-class.html,
- trunk/doc/html/spade.xmpp.protocol.UnsupportedStanzaType-class.html,
- trunk/doc/html/spade.xmpp.protocol.UnsupportedVersion-class.html,
- trunk/doc/html/spade.xmpp.protocol.XMLNotWellFormed-class.html,
- trunk/doc/html/spade.xmpp.roster-module.html,
- trunk/doc/html/spade.xmpp.roster-pysrc.html,
- trunk/doc/html/spade.xmpp.roster.Roster-class.html,
- trunk/doc/html/spade.xmpp.session-module.html,
- trunk/doc/html/spade.xmpp.session-pysrc.html,
- trunk/doc/html/spade.xmpp.session.Session-class.html,
- trunk/doc/html/spade.xmpp.simplexml-module.html,
- trunk/doc/html/spade.xmpp.simplexml-pysrc.html,
- trunk/doc/html/spade.xmpp.simplexml.NT-class.html,
- trunk/doc/html/spade.xmpp.simplexml.Node-class.html,
- trunk/doc/html/spade.xmpp.simplexml.NodeBuilder-class.html,
- trunk/doc/html/spade.xmpp.simplexml.T-class.html,
- trunk/doc/html/spade.xmpp.transports-module.html,
- trunk/doc/html/spade.xmpp.transports-pysrc.html,
- trunk/doc/html/spade.xmpp.transports.HTTPPROXYsocket-class.html,
- trunk/doc/html/spade.xmpp.transports.TCPsocket-class.html,
- trunk/doc/html/spade.xmpp.transports.TLS-class.html,
- trunk/doc/html/spade.xmpp.transports.error-class.html,
- trunk/doc/html/spade.xmppd-module.html,
- trunk/doc/html/spade.xmppd-pysrc.html,
- trunk/doc/html/spade.xmppd.locales-module.html,
- trunk/doc/html/spade.xmppd.locales-pysrc.html,
- trunk/doc/html/spade.xmppd.modules-module.html,
- trunk/doc/html/spade.xmppd.modules-pysrc.html,
- trunk/doc/html/spade.xmppd.modules.config-module.html,
- trunk/doc/html/spade.xmppd.modules.config-pysrc.html,
- trunk/doc/html/spade.xmppd.modules.config.Config-class.html,
- trunk/doc/html/spade.xmppd.modules.config.xmppdXML-class.html,
- trunk/doc/html/spade.xmppd.modules.config.xmppdXMLHandler-class.html,
- trunk/doc/html/spade.xmppd.modules.db_fake-module.html,
- trunk/doc/html/spade.xmppd.modules.db_fake-pysrc.html,
- trunk/doc/html/spade.xmppd.modules.db_fake.AUTH-class.html,
- trunk/doc/html/spade.xmppd.modules.db_fake.DB-class.html,
- trunk/doc/html/spade.xmppd.modules.dialback-module.html,
- trunk/doc/html/spade.xmppd.modules.dialback-pysrc.html,
- trunk/doc/html/spade.xmppd.modules.dialback.Dialback-class.html,
- trunk/doc/html/spade.xmppd.modules.jep0077-module.html,
- trunk/doc/html/spade.xmppd.modules.jep0077-pysrc.html,
- trunk/doc/html/spade.xmppd.modules.jep0077.IBR-class.html,
- trunk/doc/html/spade.xmppd.modules.jep0078-module.html,
- trunk/doc/html/spade.xmppd.modules.jep0078-pysrc.html,
- trunk/doc/html/spade.xmppd.modules.jep0078.NSA-class.html,
- trunk/doc/html/spade.xmppd.modules.message-module.html,
- trunk/doc/html/spade.xmppd.modules.message-pysrc.html,
- trunk/doc/html/spade.xmppd.modules.message.MessageCatcher-class.html,
- trunk/doc/html/spade.xmppd.modules.muc-module.html,
- trunk/doc/html/spade.xmppd.modules.muc-pysrc.html,
- trunk/doc/html/spade.xmppd.modules.muc.BadPassword-class.html,
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/spade/Agent.py Tue Jul 10 16:56:02 2012
+++ /trunk/spade/Agent.py Tue Jul 31 06:58:54 2012
@@ -28,6 +28,9 @@
import socialnetwork
import RPC
import pubsub
+import bdi
+from logic import *
+from kb import *
import mutex
import types
@@ -39,6 +42,7 @@
import colors
import cPickle as pickle
import uuid
+import json
import DF
@@ -72,16 +76,17 @@
def require_login(func):
- self = func.__class__
- def wrap(self, *args, **kwargs):
+ '''decorator for requiring login in wui controllers'''
+ self = func.__class__
+ def wrap(self, *args, **kwargs):
if (not hasattr(self.session,"user_authenticated") or
getattr(self.session,"user_authenticated")==False) and
self.wui.passwd!=None:
name = self.getName().split(".")[0].upper()
if name=="ACC": name="SPADE"
return "login.pyra",
{"name":name,'message':"Authentication is
required.", "forward_url":self.session.url}
return func(self,*args,**kwargs)
- wrap.__doc__=func.__doc__
- wrap.__name__=func.__name__
- return wrap
+ wrap.__doc__=func.__doc__
+ wrap.__name__=func.__name__
+ return wrap
class AbstractAgent(MessageReceiver.MessageReceiver):
@@ -138,9 +143,14 @@
self._socialnetwork = {}
self._subscribeHandler = lambda frm,typ,stat,show: False
self._unsubscribeHandler = lambda frm,typ,stat,show: False
-
+
+ #PubSub
self._pubsub = pubsub.PubSub(self)
self._events = {}
+
+ #Knowledge base
+ self.kb = KB() # knowledge base
+
self._waitingForRoster = False # Indicates that a request for the
roster is in progress
@@ -173,45 +183,43 @@
self.RPC = {}
self.addBehaviour(RPC.RPCServerBehaviour(),
Behaviour.MessageTemplate(Iq(typ='set',queryNS=NS_RPC)))
- #BDI Support
- self.KB = {} #Knowledge Base
def setAdminPasswd(self, passwd):
self.wui.passwd = str(passwd)
def WUIController_login(self, password=None, forward_url="index"):
- if hasattr(self.session, "user_authenticated") and
getattr(self.session,"user_authenticated")==True:
- raise HTTP_REDIRECTION, 'index'
+ if hasattr(self.session, "user_authenticated") and
getattr(self.session,"user_authenticated")==True:
+ raise HTTP_REDIRECTION, 'index'
name = self.getName().split(".")[0].upper()
if name=="ACC": name="SPADE"
- if password==None:
- return "login.pyra", {"name":name, "message":"Authentication is
required.","forward_url":forward_url}
- if password!=self.wui.passwd:
- return "login.pyra", {"name":name, "message":"Password is incorrect.
Try again.","forward_url":forward_url}
-
- else:
- setattr(self.session,"user_authenticated",True)
- raise HTTP_REDIRECTION, forward_url
+ if password==None:
+ return "login.pyra", {"name":name, "message":"Authentication
is required.","forward_url":forward_url}
+ if password!=self.wui.passwd:
+ return "login.pyra", {"name":name, "message":"Password is
incorrect. Try again.","forward_url":forward_url}
+
+ else:
+ setattr(self.session,"user_authenticated",True)
+ raise HTTP_REDIRECTION, forward_url
def WUIController_logout(self):
- if hasattr(self.session, "user_authenticated"):
- delattr(self.session,"user_authenticated")
- raise HTTP_REDIRECTION, "index"
+ if hasattr(self.session, "user_authenticated"):
+ delattr(self.session,"user_authenticated")
+ raise HTTP_REDIRECTION, "index"
@require_login
def WUIController_admin(self):
import types
behavs = {}
attrs = {}
- sorted_attrs = []
+ sorted_attrs = []
for k in self._behaviourList.keys():
behavs[id(k)]=k
for attribute in self.__dict__:
if eval( "type(self."+attribute+") not in [types.MethodType,
types.BuiltinFunctionType, types.BuiltinMethodType, types.FunctionType]" ):
if attribute not in ["_agent_log"]:
- attrs[attribute] = eval( "str(self."+attribute+")" )
+ attrs[attribute] = eval( "str(self."+attribute+")" )
sorted_attrs = attrs.keys()
sorted_attrs.sort()
import pygooglechart
@@ -258,8 +266,8 @@
strm = strm.replace(""",'"')"""
x = xml.dom.minidom.parseString(strm)
strm = x.toprettyxml()
- # Quick'n dirty hack to display jabber messages on the WUI
- # Will fix with a proper display
+ # Quick'n dirty hack to display jabber messages on the WUI
+ # Will fix with a proper display
strm = strm.replace(">", ">")
strm = strm.replace("<", "<")
strm = strm.replace('"', """)
@@ -1120,7 +1128,7 @@
Stops the agent execution and blocks until the agent dies
"""
- self.wui.stop()
+ self.wui.stop()
self._kill()
if timeout > 0:
@@ -1143,6 +1151,14 @@
must be overridden
"""
pass
+
+ def _initBdiBehav(self):
+ """
+ starts the BDI behaviour ONLY
+ if self is a subclass of bdi.BDIAgent
+ """
+ if issubclass(self.__class__, BDIAgent):
+ self._startBdiBehav()
def takeDown(self):
"""
@@ -1187,7 +1203,7 @@
for b in bL:
t = bL[b]
if (t != None):
- if (t.match(msg) == True):
+ if (t.match(msg) == True):
if ((b == types.ClassType or type(b) ==
types.TypeType) and issubclass(b, Behaviour.EventBehaviour)):
ib = b()
if ib.onetime:
@@ -1450,16 +1466,16 @@
def searchService(self, DAD):
- """
- search a service in the DF
- the service template is a DfAgentDescriptor
-
- """
- if isinstance(DAD,DF.Service):
+ """
+ search a service in the DF
+ the service template is a DfAgentDescriptor
+
+ """
+ if isinstance(DAD,DF.Service):
DAD=DAD.getDAD()
returnDAD=False
else: returnDAD=True
-
+
msg = ACLMessage.ACLMessage()
template = Behaviour.ACLTemplate()
template.setConversationId(msg.getConversationId())
@@ -1498,7 +1514,7 @@
return r
-
+
def modifyService(self, DAD, methodCall=None):
"""
modifies a service in the DF
@@ -1533,10 +1549,14 @@
self.runBehaviourOnce(b,t)
return b.result
+ ####################
+ #RPC invokation
+ ####################
def invokeService(self, service, inputs=None):
"""
invokes a service using jabber-rpc (XML-RPC)
the service template is a DF.Service
+ if inputs is None, they are extracted from the agent's KB
"""
if not isinstance(service,DF.Service):
@@ -1545,8 +1565,17 @@
num = str(uuid.uuid4()).replace("-","")
- if inputs==None: inputs = self.KB
-
+ if inputs==None: #inputs = self.KB
+ inputs={}
+ for i in service.getInputs():
+ r = self.kb.get(str(i))
+ if r==None:
+ self.DEBUG("Can not invoke Service, input not found: "
+ str(i),'error')
+ return False
+ self.DEBUG("Adding input: "+str(i)+" = "+str(r))
+ inputs[i] = r
+
+ self.DEBUG("Invoking service " + str(service.getName()) + " with
inputs = "+ str(inputs))
b = RPC.RPCClientBehaviour(service,inputs,num)
t = Behaviour.MessageTemplate(Iq(typ="result",attrs={'id':num}))
@@ -1588,52 +1617,92 @@
return self._pubsub.createNode(name, server=None, type='leaf',
parent=None, access=None)
def deleteEvent(self, name, server=None):
return self._pubsub.deleteNode(name, server=None)
+
+
+ ########################
+ #Knowledge Base services
+ ########################
+
+ def addBelieve(self, sentence, type="insert"):
+ if isinstance(sentence,types.StringType):
+ try:
+ if issubclass(Flora2KB.Flora2KB,self.kb.__class__):
+ self.kb.tell(sentence,type)
+ except:
+ self.kb.tell(sentence)
+ else:
+ self.kb.tell(sentence)
+ self._needDeliberate = True
+ ###self.newBelieveCB(sentence) #TODO
+
+ def removeBelieve(self, sentence, type="delete"):
+ if isinstance(sentence,types.StringType):
+ try:
+ if issubclass(Flora2KB.Flora2KB,self.kb.__class__):
+ self.kb.retract(sentence,type)
+ except:
+ self.kb.retract(sentence)
+ else:
+ self.kb.retract(sentence)
+ self._needDeliberate = True
+
+ def askBelieve(self, sentence):
+ return self.kb.ask(sentence)
+
+ def configureKB(self, typ, sentence=None, path=None):
+ self.kb.configure(typ,sentence,path)
+
+ def saveFact(self, name, sentence):
+ self.kb.set(name, sentence)
+
+ def getFact(self, name):
+ return self.kb.get(name)
##################################
# Changed to be a 'daemonic' python Thread
class jabberProcess(threading.Thread):
- def __init__(self, socket, owner):
- self.jabber = socket
- #self._alive = True
- self._forceKill = threading.Event()
- self._forceKill.clear()
- threading.Thread.__init__(self)
- self.setDaemon(False)
- self._owner = owner
-
- def _kill(self):
- try:
- self._forceKill.set()
- except:
- #Agent is already dead
- pass
-
- def forceKill(self):
- return self._forceKill.isSet()
-
- def run(self):
- """
- periodic jabber update
- """
- while not self.forceKill():
- try:
- err = self.jabber.Process(0.4)
- except Exception, e:
- _exception = sys.exc_info()
- if _exception[0]:
-
self._owner.DEBUG( '\n'+''.join(traceback.format_exception(_exception[0],
_exception[1], _exception[2])).rstrip(),"err")
- self._owner.DEBUG("Exception in jabber process: "+ str(e),"err")
- self._owner.DEBUG("Jabber connection
failed: "+self._owner.getAID().getName()+" (dying)","err")
- self._kill()
- self._owner.stop()
- err = None
-
- if err == None or err == 0: # None or zero the integer, socket
closed
- self._owner.DEBUG("Agent
disconnected: "+self._owner.getAID().getName()+" (dying)","err")
- self._kill()
- self._owner.stop()
+ def __init__(self, socket, owner):
+ self.jabber = socket
+ #self._alive = True
+ self._forceKill = threading.Event()
+ self._forceKill.clear()
+ threading.Thread.__init__(self)
+ self.setDaemon(False)
+ self._owner = owner
+
+ def _kill(self):
+ try:
+ self._forceKill.set()
+ except:
+ #Agent is already dead
+ pass
+
+ def forceKill(self):
+ return self._forceKill.isSet()
+
+ def run(self):
+ """
+ periodic jabber update
+ """
+ while not self.forceKill():
+ try:
+ err = self.jabber.Process(0.4)
+ except Exception, e:
+ _exception = sys.exc_info()
+ if _exception[0]:
+
self._owner.DEBUG( '\n'+''.join(traceback.format_exception(_exception[0],
_exception[1], _exception[2])).rstrip(),"err")
+ self._owner.DEBUG("Exception in jabber process: "+
str(e),"err")
+ self._owner.DEBUG("Jabber connection
failed: "+self._owner.getAID().getName()+" (dying)","err")
+ self._kill()
+ self._owner.stop()
+ err = None
+
+ if err == None or err == 0: # None or zero the integer,
socket closed
+ self._owner.DEBUG("Agent
disconnected: "+self._owner.getAID().getName()+" (dying)","err")
+ self._kill()
+ self._owner.stop()
@@ -1735,6 +1804,9 @@
# Add Roster Behaviour
self.addBehaviour(socialnetwork.RosterBehaviour(),
Behaviour.MessageTemplate(Iq(queryNS=NS_ROSTER)))
+ # Add BDI Behaviour #only for BDI agents
+ self._initBdiBehav()
+
self.DEBUG("Agent %s registered"%(agentjid),"ok")
if not self.__register_in_AMS():
@@ -1950,3 +2022,34 @@
return False
return True
+
+class BDIAgent(Agent):
+ def _startBdiBehav(self):
+ self.bdiBehav = bdi.BDIBehaviour(period=1)
+ self.addBehaviour(self.bdiBehav,None)
+ self.DEBUG("BDI behaviour added.",'info')
+
+ def setPeriod(self, period):
+ self.bdiBehav.setPeriod(period)
+
+ def getPeriod(self):
+ return self.bdiBehav.getPeriod()
+
+ def addPlan(self, inputs=[], outputs=[],P=[],Q=[],services=[]):
+ return self.bdiBehav.addPlan(inputs,outputs,P,Q,services)
+
+ def addGoal(self, goal):
+ self.bdiBehav.addGoal(goal)
+
+ def setPlanSelectedCB(self, func):
+ '''func MUST have as input parameter a plan'''
+ self.bdiBehav.planSelectedCB = func
+
+ def setGoalCompletedCB(self, func):
+ '''func MUST have as input parameter a goal'''
+ self.bdiBehav.goalCompletedCB = func
+
+ def setServiceCompletedCB(self, func):
+ '''func MUST have as input parameter a DF.Service'''
+ self.bdiBehav.serviceCompletedCB = func
+
=======================================
--- /trunk/spade/DF.py Tue Jul 10 16:56:02 2012
+++ /trunk/spade/DF.py Tue Jul 31 06:58:54 2012
@@ -1284,6 +1284,9 @@
self.dad = DfAgentDescription()
sd = ServiceDescription()
+ self.inputs = inputs
+ self.outputs = outputs
+
if co and co.has_key("service"):
if
co.service.name: name =
co.service.name
if co.service.owner: owner = AID.aid(co=co.service.owner)
@@ -1452,7 +1455,11 @@
return y.dad.match(self.dad)
def __eq__(self,y):
+ if y==None: return False
return y.match(self)
+
+ def __ne__(self,y):
+ return not self==y
def __str__(self):
return str(self.dad)
=======================================
--- /trunk/spade/RPC.py Fri Jul 30 06:42:53 2010
+++ /trunk/spade/RPC.py Tue Jul 31 06:58:54 2012
@@ -18,7 +18,7 @@
params, name = xmlrpclib.loads("<?xml version='1.0'?>%s" %
str(mc))
name=name.lower()
self.myAgent.DEBUG("Params processed: name="+name+"
params="+str(params) + " in " + str(self.myAgent.RPC.keys()),"info","rpc")
-
+
if not self.myAgent.RPC.has_key(name):
self.myAgent.DEBUG("RPC: 404 method not
found",'error',"rpc")
xmlrpc_res = xmlrpclib.dumps(
xmlrpclib.Fault(404, "method not found"))
@@ -33,12 +33,13 @@
self.myAgent.DEBUG("service and method: "+ str(service)
+ " --> " + str(methodCall),"info","rpc")
- self.myAgent.DEBUG("Comparing service.getP(): "+
str(service.getP()) + " with params--> " + str(params),"info","rpc")
+ self.myAgent.DEBUG("Comparing service.getInputs(): "+
str(service.getInputs()) + " with params--> " + str(params),"info","rpc")
ps = params[0].keys()
- for p in service.getP():
+ for p in eval(str(service.getInputs())): #service.getP():
+ self.myAgent.DEBUG("Comparing input "+str(p)+ "
with "+str(ps))
if str(p) not in ps:
- self.myAgent.DEBUG("RPC: 500 missing
precondition: "+str(p)+ " is not in "+str(params),'error',"rpc")
- xmlrpc_res = xmlrpclib.dumps(
xmlrpclib.Fault(500, "missing precondition"))
+ self.myAgent.DEBUG("RPC: 500 missing
input: "+str(p)+ " is not in "+str(params),'error',"rpc")
+ xmlrpc_res = xmlrpclib.dumps(
xmlrpclib.Fault(500, "missing input"))
reply = self.msg.buildReply("error")
reply.setQueryPayload([xmpp.simplexml.XML2Node(xmlrpc_res)])
reply.setType("result")
@@ -66,12 +67,12 @@
self.myAgent.send(reply)
return
- #Check postconditions
+ #Check outputs
try:
fail=False
outputs={}
if type(result) == types.DictType:
- for q in service.getQ():
+ for q in eval(str(service.getOutputs())):
#service.getQ():
if q not in result.keys():
fail=True
break
@@ -83,8 +84,8 @@
except:
fail=True
if fail:
- self.myAgent.DEBUG("RPC: 500 missing
postcondition: "+str(service.getQ()),'error',"rpc")
- xmlrpc_res = xmlrpclib.dumps(
xmlrpclib.Fault(500, "missing postcondition"))
+ self.myAgent.DEBUG("RPC: 500 missing
output: "+str(service.getQ()),'error',"rpc")
+ xmlrpc_res = xmlrpclib.dumps(
xmlrpclib.Fault(500, "missing output"))
reply = self.msg.buildReply("error")
reply.setQueryPayload([xmpp.simplexml.XML2Node(xmlrpc_res)])
reply.setType("result")
@@ -106,6 +107,13 @@
class RPCClientBehaviour(Behaviour.OneShotBehaviour):
def __init__(self, service, inputs, num):
+ '''
+ This behaviour makes the Remote Procedure Call to the server
+ Usage:
+ service - DF.Service to be called
+ inputs - dictionary of inputs where key=input name, value=input
value
+ num - a numeric id
+ '''
Behaviour.OneShotBehaviour.__init__(self)
self.service = service
self.inputs = inputs
@@ -115,17 +123,16 @@
self.result=None
#send IQ methodCall
- params = {}
+ params = self.inputs
ps = None
ps = self.service.getP()
#self.service.getDAD().getServices()[0].getProperty("P")
for p in ps: #check all Preconditions are True
- if not p in self.inputs.keys():
- #if "askBelieve" in dir(self.myAgent):
- # if not self.myAgent.askBelieve(p):
+ #if not p in self.inputs.keys():
+ if not self.myAgent.askBelieve(p):
self.myAgent.DEBUG("Precondition "+ str(p) + " is not
satisfied. Can't call method "+self.service.getName(),'error',"rpc")
self.result=False
return
- else: params[p] = self.inputs[p]
+ #else: params[p] = self.inputs[p]
#params = tuple(ps)
self.myAgent.DEBUG("Params processed: "+str(params),"info","rpc")
@@ -158,10 +165,11 @@
self.DEBUG("Returned params "+str(params),'ok',"rpc")
self.result = params[0]
#if agent is a BDIAgent add result params as
postconditions
- #if "addBelieve" in dir(self.myAgent):
- for k,q in self.result.items(): #[0]:
- #self.myAgent.addBelieve(q)
- self.myAgent.KB[k]=q
+ for k,v in self.result.items(): #[0]:
+ self.myAgent.kb.set(k,v)
+ for q in self.service.getQ():
+ if not self.myAgent.askBelieve(q):
+ raise Exception("PostCondition "+str(q)+ " not
satisfied.")
return self.result
except Exception,e:
self.myAgent.DEBUG("Error executing RPC
service: "+str(e),"error","rpc")
=======================================
--- /trunk/spade/bdi.py Wed Jul 11 04:18:54 2012
+++ /trunk/spade/bdi.py Tue Jul 31 06:58:54 2012
@@ -1,18 +1,17 @@
from logic import *
from copy import copy
import types
-
-import Agent
+import random
+
import Behaviour
+import tbcbp
+import DF
+from FlexQueue import FlexQueue
+from Queue import Queue
class PreConditionFailed (Exception): pass
class PostConditionFailed(Exception): pass
class ServiceFailed(Exception): pass
-class KBConfigurationFailed(Exception):
- def __init__(self, msg):
- self.msg = msg
- def __str__(self):
- return repr(self.msg)
class Goal:
@@ -25,6 +24,7 @@
self.priority = 0
self.selected = False
self.unreachable = False
+ self.done = False
def testConflict(self, goal):
# No conflict test at the moment
@@ -33,190 +33,85 @@
def __str__(self):
if self.unreachable:
return "UNREACHABLE("+str(self.expression)+")"
+ elif self.done:
+ return "DONE("+str(self.expression)+")"
else:
return str(self.expression)
def __repr__(self):
return self.__str__()
-class Service:
- def __init__(self, P=None, Q=None):
- self.P = P #precondition
- self.Q = Q #postcontidion
-
- self.myAgent = None
-
- def setP(self, P): self.P = P
-
- def setQ(self, Q): self.Q = Q
-
- def getP(self): return self.P
-
- def getQ(self): return self.Q
-
- def reward(self):
- self.trust -= 1
- if self.trust<0: self.trust=0
- #print "Service "+
self.name+" rewarded!"
-
- def punish(self):
- self.trust += 10
- if self.trust>1000: self.trust=1000
- #print "Service "+
self.name+" punished!"
-
- def run(self):
- raise NotImplementedError
-
- def addBelieve(self,sentence):
- if self.myAgent:
- self.myAgent.addBelieve(sentence)
- else:
- raise NotImplementedError
- def removeBelieve(self,sentence):
- if self.myAgent:
- self.myAgent.removeBelieve(sentence)
- else:
- raise NotImplementedError
- def askBelieve(self,sentence):
- if self.myAgent:
- return self.myAgent.askBelieve(sentence)
- else:
- raise NotImplementedError
-
- def __str__(self):
- return "[P:"+str(self.P)+" Q:"+str(self.Q)+"]"
-
-class Plan:
- def __init__(self, P=None, Q=None):
- self.P = P
- self.Q = Q
-
- self.myAgent = None
-
- self.services = []
- self.next = None
-
- def addOwner(self, owner):
- self.myAgent = owner
- for service in self.services:
- service.myAgent = owner
-
- def appendService(self, service):
- if len(self.services)>0:
- lastService = self.services[len(self.services)-1]
- out = copy(lastService.outputs.keys()).sort()
- ins = copy(service.inputs.keys()).sort()
-
- if out == ins:
- if self.myAgent:
- service.myAgent = self.myAgent
- self.services.append(service)
- else:
- if self.myAgent:
- service.myAgent = self.myAgent
- self.services.append(service)
-
- def nextService(self):
- if self.next==None:
- self.next = 0
- elif self.next == len(self.services)-1:
- return None
- else:
- outs = self.services[self.next].outputs
- self.next += 1
- self.services[self.next].inputs.update(outs)
-
- if self.myAgent.askBelieve(self.services[self.next].P) != False:
- return self.services[self.next]
- else:
- raise PreconditionFailed()
-
- def __str__(self):
- s = "Plan(P:"+str(self.P)+" Q:"+str(self.Q)+") => "
- for i in range(len(self.services)):
- s+= "S"+str(i)+":"+str(self.services[i])+", "
- return s
-
-class BDIAgent(Agent.Agent):
-
- def __init__(self,agentjid, password, port=5222, debug=[], p2p=False):
- Agent.Agent.__init__(self,agentjid, password, port=port,
debug=debug, p2p=p2p)
-
+
+class PlanList(dict):
+ #plans hash table. PID is the PlanID
+ def add(self, plan):
+ pid = random.randint(1,100000000)
+ while self.has_key(pid):
+ pid = random.randint(1,100000000)
+ self[pid]=plan
+ plan.pid = pid
+ return pid
+
+
+#class BDIAgent(Agent.Agent):
+class BDIBehaviour(Behaviour.PeriodicBehaviour):
+
+ #def __init__(self,agentjid, password, port=5222, debug=[], p2p=False):
+ # Agent.Agent.__init__(self,agentjid, password, port=port,
debug=debug, p2p=p2p)
+ def __init__(self, period):
+ Behaviour.PeriodicBehaviour.__init__(self, period)
self.goals = [] # active goals
- self.kb = FolKB() # knowledge base
- self.plans = [] # plan library
+ self.plans = PlanList() # plan library
self.intentions = [] # selected plans for execution
- self.services = [] # services offered by the agent
-
- self.defaultMailbox = []
-
+ #self.services = [] # services offered by the agent
+ self.TBCBP = tbcbp.TBCBP()
+ self.active_goals = FlexQueue()
+ self.prepared_goals = FlexQueue()
+ self.scheduler = Queue()
+
self._needDeliberate = True
def configureKB(self, typ, sentence=None, path=None):
- """
- Supported Knowledge Bases are:
["ECLiPSe", "Flora2", "SPARQL", "SWI", "XSB"]
- """
- try:
- if typ not in ["ECLiPSe", "Flora2", "SPARQL", "SWI", "XSB"]:
- raise KBConfigurationFailed(typ + " is not a valid KB.")
- if typ=="SPARQL": import SPARQLKB
- elif typ=="XSB": import XSBKB
- elif typ=="Flora2": import Flora2KB
- elif typ=="SWI": import SWIKB
- elif typ=="ECLiPSe":import ECLiPSeKB
- else: raise KBConfigurationFailed("Could not
import "+str(typ)+" KB.")
-
- typ+="KB"
- #module = eval("__import__("+typ+")")
-
- if path!=None:
- self.kb =
eval(typ+"."+typ+"("+str(sentence)+", '"+path+"')")
- else:
- self.kb = eval(typ+"."+typ+"("+str(sentence)+")")
- except KBConfigurationFailed as e:
- self.DEBUG(str(e)+" Using Fol KB.", 'warn')
- self.kb = FolKB()
-
-
+ self.myAgent.kb.configure(typ,sentence,path)
+
def addBelieve(self, sentence, type="insert"):
- if isinstance(sentence,types.StringType):
- try:
- if issubclass(Flora2KB.Flora2KB,self.kb.__class__):
- self.kb.tell(sentence,type)
- except:
- if issubclass(FolKB, self.kb.__class__):
- self.kb.tell(expr(sentence))
- else:
- self.kb.tell(sentence)
- else:
- self.kb.tell(sentence)
+ self.myAgent.addBelieve(sentence,type)
self._needDeliberate = True
- self.newBelieveCB(sentence)
-
+
def removeBelieve(self, sentence, type="delete"):
- if isinstance(sentence,types.StringType):
- try:
- if issubclass(Flora2KB.Flora2KB,self.kb.__class__):
- self.kb.retract(sentence,type)
- except:
- if issubclass(FolKB, self.kb.__class__):
- self.kb.retract(expr(sentence))
- else:
- self.kb.retract(sentence)
- else:
- self.kb.retract(sentence)
- self._needDeliberate = True
+ self.myAgent.removeBelieve(sentence,type)
def askBelieve(self, sentence):
- if isinstance(sentence,types.StringType) and issubclass(FolKB,
self.kb.__class__):
- return self.kb.ask(expr(sentence))
- else:
- return self.kb.ask(sentence)
-
- def addPlan(self, plan):
- plan.addOwner(self)
- self.plans.append(plan)
- self.DEBUG("Plan added: "+str(plan),"ok")
+ return self.myAgent.askBelieve(sentence)
+
+ def saveFact(self, name, sentence):
+ self.myAgent.kb.set(name, sentence)
+ self._needDeliberate = True
+
+ def getFact(self, name):
+ return self.myAgent.kb.get(name)
+
+ def addPlan(self, P,Q,inputs, outputs, services):
+ '''Adds a new plan to the Planner (TBCBP)
+ Usage: addPlan (P, Q, services)
+ P - precondition of the plan
+ Q - postcondition of the plan
+ services - list of services names (strings)
+
+ Return: None'''
+ cases=[]
+ for s in services:
+ c = self.TBCBP.getCaseOfService(str(s))
+ if c==None:
+ self.myAgent.DEBUG("Plan was not added. Service "+str(s)
+ " does not exist.","err",'bdi')
+ return False
+ cases.append(c)
+
+ plan = tbcbp.Plan(cases)
+ self.TBCBP.addPlan(plan)
+ self.myAgent.DEBUG("Plan added: "+str(plan),"ok",'bdi')
+ self._needDeliberate = True
+ return True
def addGoal(self, goal):
#First add the goal if no conflicts
@@ -227,139 +122,263 @@
conflict = True
break
if not conflict and self.askBelieve(goal.expression)==False:
- self.DEBUG("Goal added: "+str(goal),"ok")
+ self.myAgent.DEBUG("Goal added: "+str(goal),"ok", 'bdi')
self.goals.append(goal)
+ self._needDeliberate = True
+
+ def registerServiceInTBCBP(self, service, time=1):
+ '''Registers new service in the Planner (TBCBP)
+ Usage: registerService(service, time)
+ service - A DF.Service class
+ time - the estimated execution time of the service (optional)
+
+ Returns: None'''
+
+ self.TBCBP.registerService(service=service,time=time)
+ self._needDeliberate = True
+
+ def unregisterServiceInTBCBP(self, name=None, service=None):
+ if not name: name= service.getName()
+ self.TBCBP.delService(name)
+ self._needDeliberate = True
+
+ def getPlan(self, goal):
+ '''Finds a plan for a specified goal.
+ If there is not an existing plan, it composes a new one (when
possible)
+ Usage getPlan( goal )
+ goal - a Goal object to be achieved
+
+ Returns: TBCBP.Plan object or None is there is no available plan'''
+
+ self.myAgent.DEBUG("Composing a plan for
goal "+str(goal),'info','bdi')
+ plan = self.composePlan(goal)
+
+ if plan == None:
+ #goal is unreachable
+ self.myAgent.DEBUG("No plan found for
Goal "+str(goal), 'warn','bdi')
+ return None
+
+ plan['index'] = 0
+ plan['goal'] = goal
+ plan.agent_owner = self.myAgent
+ return plan
+
+ def composePlan(self, goal, tout=-1):
+ '''
+ calls the Temporal-Bounded Case Based Planner
+ '''
+ return self.TBCBP.composePlan(goal,self.myAgent.kb,tout=20)
def selectIntentions(self):
- for goal in self.goals: #deliberate over goals
- if not goal.selected: #if the goal is not already selected for
execution
- self.DEBUG("Found not selected goal")
- for plan in self.plans: #search for a plan
- self.DEBUG("Compare plan.Q " + str(plan.Q) + " with
goal " + str(goal.expression),"ok")
- if plan.Q == goal.expression: #plan must pursue for
the goal
- #self.DEBUG("askBelieve plan.P -> " +
str(self.askBelieve(plan.P)))
- if self.askBelieve(plan.P)!=False: #preconditions
of the plan must be acomplished
- self.intentions.append(plan) #instantiate
plan as intention
- self.intentionSelectedCB(plan)
- goal.selected = True #flag goal as selected
- break #stop searching plans for this goal
-
-
- def run(self):
- """
- periodic agent execution
- """
- #Init The agent
- self._setup()
- self.behavioursGo.acquire()
- self._running = True
- self.behavioursGo.notifyAll()
- self.behavioursGo.release()
-
- #Start the Behaviours
- #if (self._defaultbehaviour != None):
- # self._defaultbehaviour.start()
-
- #If this agent supports P2P, wait for P2PBEhaviour to properly
start
- if self.p2p:
- while not self.p2p_ready:
- time.sleep(0.1)
+ '''
+ Prepares new plan for active goals
+ Looks for all prepared goals and selects a new plan for it.
+ then the goal is archived in prepared_goals
+ and the plan is stored in self.plans
+ '''
+
+ #while not self.prepared_goals.empty(): #return
+ goal = self.prepared_goals.get()
+ self.myAgent.DEBUG("Got goal "+ str(goal),'info','bdi')
+
+ if goal!=None:
+ if self.askBelieve(goal.expression)==True:
+ goal.done=True
+ return None #continue
+ if goal in self.active_goals: return None #continue
+
+ self.myAgent.DEBUG("Activate Goal: " + str(goal), 'info','bdi')
+ plan = self.getPlan(goal)
+ if plan!=None:
+ #activate plan
+ self.myAgent.DEBUG("Got a plan for goal " +
str(goal), 'info','bdi')
+ goal.selected = True
+ self.active_goals.put(goal)
+ plan.agent = self
+ #init plan
+ pid = self.plans.add(plan)
+ #activate first service
+ self.insertNextService(plan,pid)
+ self.planSelectedCB(plan)
+ else:
+ goal.unreachable = True
+ self.myAgent.DEBUG("Goal is
Unreachable: "+str(goal), 'warn','bdi')
+ return None
+
+ def insertNextService(self,plan,pid):
+ '''Selects the next service of a plan to be executed
+ Usage: insertNextService( plan, pid)
+ plan - the running plan (TBCBP.Plan)
+ pid - the plan identifier'''
+
+ service_name = plan.getNextService()
+ self.myAgent.DEBUG("next service is " +
str(service_name),'info','bdi')
+ if service_name == None:
+ self.EndPlan(pid, plan)
+ return
+ service = self.TBCBP.getService(service_name)
+ if service:
+ service.pid = pid
+ service.agent_owner = self
+
+ self.scheduler.put(service)
+
+ else: #plan has finished
+ self.EndPlan(pid, plan)
+
+ def EndPlan(self,pid,plan):
+ '''Finishes the execution of a plan.
+ If the plan run well, its case is rewarded. Otherwise, it is
punished.
+ Finally goal is setted as done and not active.
+ Usage: EndPlan ( pid, plan)
+ pid - Plan identifier
+ plan - TBCBP.Plan object
+ '''
+ del self.plans[pid]
+ #check its postcondition
+ if len(plan.getQ()) > 0 and self.askBelieve(plan.getQ()[0])==False:
+ #logging.error(color_red+"PLAN FAILED "+str(plan)+color_none)
+ self.TBCBP.punish(plan.getCase())
+ for goal in self.goals: #deselect the goal that raised the plan
+ if goal.expression == plan.getQ():
+ goal.selected = False
+ goal.done = False
+ self.active_goals.remove(goal)
+ else:
+ self.TBCBP.reward(plan.getCase())
+ self.myAgent.DEBUG("Rewarding Plan",'ok','bdi')
+ for goal in self.goals: #delete the goal that raised the
intention
+ if goal.expression in plan.getQ():
+ if goal.persistent: #if goal is persistent, deselect it
+ self.prepared_goals.put(goal)
+ self.active_goals.remove(goal)
+ goal.done = True
+ goal.selected = False
+ self.myAgent.DEBUG("Goal "+str(goal.expression)+" was
completed!",'ok','bdi')
+ self.myAgent.DEBUG("Calling goal completed CB: "+
str(self.goalCompletedCB),'info','bdi')
+ self.goalCompletedCB(goal)
+
+ def EndService(self,service,plan):
+ '''Finishes the execution of a service.
+ If the service failed, it is punished and the plan is finished.
+ Otherwise, the next service of the plan is selected.
+ Usage: EndService ( service, plan)
+ service - the current running DF.Service
+ plan - the TBCBP.Plan where the service belongs
+ '''
+
+ agent = self
+ pid = plan.pid
+ #service has been executed
+ if len(service.getQ()) > 0 and
self.askBelieve(service.getQ()[0])==False:
+ #service failed
+ self.myAgent.DEBUG("Service execution
failed: "+str(service.getQ()))
+ self.punishService(service)
+ #cancel plan and reactivate goal
+ self.EndPlan(pid,plan)
+ return
+
+ #5.2.1 select next service
+ self.insertNextService(plan, pid)
+
+ self.serviceCompletedCB(service)
+
+ def deliberate(self):
+ self.myAgent.DEBUG("deliberate about current
goals: "+str(self.goals),'info','bdi')
+ for goal in self.goals:
+ if (goal.unreachable == False) and (goal.done==False): # or
((goal.done==True) and (goal.persistent==True))):
+ if self.askBelieve(goal.expression)==False:
+ self.myAgent.DEBUG("Deliberate about " +
str(goal),'info','bdi')
+ if goal not in self.active_goals:
+ self.prepared_goals.put(goal)
+ else:
+ self.myAgent.DEBUG("Goal " + str(goal) + "is already
in the KB: " + str(self.askBelieve(goal.expression)),'warn','bdi')
+ goal.done = True
+
+
+ def discover(self):
+ #TODO: use PubSub features
+ s = DF.Service()
+ results = self.myAgent.searchService(s)
+ if results!=None:
+ self.myAgent.DEBUG("Discovered "+str(len(results))+ "
services.", 'info','bdi')
+ for service in results:
+ if self.TBCBP.getService(service.getName()) == None:
+ self.registerServiceInTBCBP(service)
+
+ def punishService(self, service):
+ P = service.getP()
+ Q = service.getQ()
+ I = service.getInputs()
+ O = service.getOutputs()
+
self.TBCBP.punish(Case(P=P,Q=Q,inputs=I,outputs=O,services=[service.getName()]))
+ return
+
+
+ ####Init The agent
+ ###self._setup()
+ ###self.behavioursGo.acquire()
+ ###self._running = True
+ ###self.behavioursGo.notifyAll()
+ ###self.behavioursGo.release()
#############
# Main Loop #
#############
- while not self.forceKill():
- try:
- #get and process all messages
- self.getMessages()
-
- #deliberate about current goals
- #self.DEBUG("deliberate about current goals")
- if self._needDeliberate:
- for goal in copy(self.goals):
- if self.askBelieve(goal.expression)!=False:
- if goal.persistent:
- goal.selected = False
- else:
- self.goals.remove(goal)
- self.goalCompletedCB(goal)
- #for intention in copy(self.intentions):
- # if self.bk.ask(intention.Q):
- # self.intentions.remove(intention)
- self._needDeliberate = False
-
- #select intentions
- #self.DEBUG("select intentions")
- self.selectIntentions()
-
- #run intentions
- #self.DEBUG("run intentions")
- for intention in copy(self.intentions):
- service = intention.nextService()
-
- if service == None: #intention has finished
- self.DEBUG("Intention finished: "+
str(intention),"ok")
- self.intentions.remove(intention) #delete intention
- if self.askBelieve(intention.Q)==False: #check its
postcondition
- raise PostConditionFailed()
- else:
- for goal in copy(self.goals): #delete the goal
that raised the intention
- if goal == intention.Q:
- if goal.persistent: #if goal is
persistent, deselect it
- goal.selected = False
- else:
- self.goals.remove(goal)
- else:
- service.run()
- if self.askBelieve(service.Q)==False:
- raise PostConditionFailed()
- else: self.serviceCompletedCB(service)
- if self._needDeliberate: break
-
- except Exception, e:
- self.DEBUG("Agent " + self.getName() + " Exception in
run: " + str(e), "err")
- self._kill()
-
- self._shutdown()
-
- def getMessages(self):
- #Check for queued messages
- proc = False
- msg = self._receive(block=True, timeout=0.01)
- if msg != None:
- bL = copy(self._behaviourList)
- for b in bL:
- t = bL[b]
- if (t != None):
- if (t.match(msg) == True):
- if ((b == types.ClassType or type(b) ==
types.TypeType) and issubclass(b, Behaviour.EventBehaviour)):
- b = b()
- b.setAgent(self)
- b.postMessage(msg)
- b.start()
- else:
- b.postMessage(msg)
- proc = True
-
- if (proc == False):
- self.defaultMailbox.append(msg)
- # #If no template matches, post the message to the Default
behaviour
- # if (self._defaultbehaviour != None):
- # self._defaultbehaviour.postMessage(msg)
-
- def intentionSelectedCB(self, intention=None):
- #callback executed when a new intention is selected for execution
+ ###while not self.forceKill():
+ ### try:
+ ### #get and process all messages
+ ### self.getMessages()
+
+ def _onTick(self):
+ """
+ periodic behaviour execution
+ """
+ #discover new services
+ self.myAgent.DEBUG("Discover new services...", 'info','bdi')
+ self.discover()
+
+ #deliberate about current goals
+ #if self._needDeliberate:
+ self.myAgent.DEBUG("Deliberating...", 'info','bdi')
+ self.deliberate()
+ #self._needDeliberate = False
+
+ #select intentions
+ self.DEBUG("select intentions", 'info','bdi')
+ self.selectIntentions()
+
+ self.myAgent.DEBUG("Init scheduler", 'info','bdi')
+ #run a service each iteration
+ if not self.scheduler.empty():
+ service = self.scheduler.get()
+ self.myAgent.DEBUG("Got service for execution: " +
str(service),'info','bdi')
+
+ #if service!=None:
+ pid = service.pid
+ plan = self.plans[pid]
+ try:
+ result = self.myAgent.invokeService(service)
+ except:
+ self.myAgent.DEBUG("Service failed!", 'warn','bdi')
+
+ self.EndService(service, plan)
+ else:
+ self.myAgent.DEBUG("NOP", 'info', 'bdi')
+
+ self.myAgent.DEBUG("Restarting BDI cycle", 'info','bdi')
+
+
+ def planSelectedCB(self, plan):
+ #callback executed when a new plan is selected for execution
#must be overloaded
pass
- def goalCompletedCB(self, goal=None):
+ def goalCompletedCB(self, goal):
#callback executed when a goal is completed succesfully
#must be overloaded
pass
- def serviceCompletedCB(self, service=None):
+ def serviceCompletedCB(self, service):
#callback executed when a service is completed succesfully
#must be overloaded
pass
- def newBelieveCB(self, believe=None):
- #callback executed when a believe is added to the knowledge base
- #must be overloaded
- pass
+
=======================================
--- /trunk/spade/logic.py Tue Jul 10 16:56:02 2012
+++ /trunk/spade/logic.py Tue Jul 31 06:58:54 2012
@@ -85,6 +85,8 @@
def ask(self, query):
"""Ask returns a substitution that makes the query true, or
it returns False. It is implemented in terms of ask_generator."""
+ if issubclass(query.__class__,str):
+ query = expr(query)
try:
return self.ask_generator(query).next()
except StopIteration:
=======================================
--- /trunk/test/basicTestCase.py Tue Jul 10 16:56:52 2012
+++ /trunk/test/basicTestCase.py Tue Jul 31 06:58:54 2012
@@ -3,24 +3,22 @@
import time
import unittest
-sys.path.append('../..')
-
import spade
host = "127.0.0.1"
class MyAgent(spade.Agent.Agent):
- def _setup(self):
- self.pi = None
- self.msg = None
+ def _setup(self):
+ self.pi = None
+ self.msg = None
class GetPIBehav(spade.Behaviour.OneShotBehaviour):
- def _process(self):
- self.myAgent.pi = self.myAgent.getPlatformInfo()
-
+ def _process(self):
+ self.myAgent.pi = self.myAgent.getPlatformInfo()
+
class SendMsgBehav(spade.Behaviour.OneShotBehaviour):
def _process(self):
@@ -54,10 +52,10 @@
msg = None
msg = self._receive(block=True,timeout=10)
if msg != None:
- content = msg.getContent()
- msg = msg.createReply()
- msg.setContent(content)
- self.myAgent.send(msg)
+ content = msg.getContent()
+ msg = msg.createReply()
+ msg.setContent(content)
+ self.myAgent.send(msg)
@@ -68,14 +66,14 @@
self.Aaid = spade.AID.aid("a@"+host,["xmpp://a@"+host])
self.Baid = spade.AID.aid("b@"+host,["xmpp://b@"+host])
- self.a = MyAgent("a@"+host, "secret")
- self.a.start()
- self.b = MyAgent("b@"+host, "secret")
- self.b.start()
-
- #self.rdf
= """<rdf:ap-description><rdf:ap-services><rdf:ap-service><rdf:type>fipa.agent-management.ams</rdf:type><rdf:addresses>acc.127.0.0.1</rdf:addresses><rdf:name>xmpp://ams.127.0.0.1</rdf:name></rdf:ap-service></rdf:ap-services><rdf:name>xmpp://acc.127.0.0.1</rdf:name></rdf:ap-description>"""
- self.rdf = """<rdf:RDF
xmlns:fipa="
http://www.fipa.org/schemas/fipa-rdf0#"
xmlns:rdf="
http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:ap-description><rdf:ap-services
list="true"><rdf:ap-services><rdf:ap-service><rdf:type>fipa.agent-management.ams</rdf:type><rdf:addresses
list="true"><rdf:addresses>acc.127.0.0.1</rdf:addresses></rdf:addresses><rdf:name>xmpp://ams.127.0.0.1</rdf:name></rdf:ap-service></rdf:ap-services></rdf:ap-services><rdf:name>xmpp://acc.127.0.0.1</rdf:name></rdf:ap-description></rdf:RDF>"""
- #self.pi = spade.content.RDFXML2CO(self.rdf)
+ self.a = MyAgent("a@"+host, "secret")
+ self.a.start()
+ self.b = MyAgent("b@"+host, "secret")
+ self.b.start()
+
+ #self.rdf
= """<rdf:ap-description><rdf:ap-services><rdf:ap-service><rdf:type>fipa.agent-management.ams</rdf:type><rdf:addresses>acc.127.0.0.1</rdf:addresses><rdf:name>xmpp://ams.127.0.0.1</rdf:name></rdf:ap-service></rdf:ap-services><rdf:name>xmpp://acc.127.0.0.1</rdf:name></rdf:ap-description>"""
+ self.rdf = """<rdf:RDF
xmlns:fipa="
http://www.fipa.org/schemas/fipa-rdf0#"
xmlns:rdf="
http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:ap-description><rdf:ap-services
list="true"><rdf:ap-services><rdf:ap-service><rdf:type>fipa.agent-management.ams</rdf:type><rdf:addresses
list="true"><rdf:addresses>acc.127.0.0.1</rdf:addresses></rdf:addresses><rdf:name>xmpp://ams.127.0.0.1</rdf:name></rdf:ap-service></rdf:ap-services></rdf:ap-services><rdf:name>xmpp://acc.127.0.0.1</rdf:name></rdf:ap-description></rdf:RDF>"""
+ #self.pi = spade.content.RDFXML2CO(self.rdf)
def tearDown(self):
self.a.stop()
@@ -83,7 +81,10 @@
def testGetPlatformInfo(self):
self.a.addBehaviour(GetPIBehav(), None)
- while self.a.pi == None: time.sleep(2)
+ counter = 0
+ while self.a.pi == None and counter<10:
+ time.sleep(1)
+ counter += 1
#print self.a.pi
from coTestCase import isEqualElement,isEqualXML
#self.assertEqual( str(self.a.pi), self.rdf) # 'Incorrect
Platform Info'
=======================================
--- /trunk/test/bdiTestCase.py Tue Jul 10 16:56:52 2012
+++ /trunk/test/bdiTestCase.py Tue Jul 31 06:58:54 2012
@@ -1,104 +1,196 @@
import os
import sys
import unittest
-sys.path.append('../..')
import spade
from spade.bdi import *
+from spade.Agent import BDIAgent
+from spade.tbcbp import Plan
host = "127.0.0.1"
-class Serv1(Service):
- def run(self):
- self.addBelieve(expr("Value(1)"))
-class Serv2(Service):
- def run(self):
- self.addBelieve(expr("Value(2)"))
-
-class MServ(Service):
- def __init__(self, P=None, Q=None, inputs={},outputs={}, belief=""):
- Service.__init__(self,P, Q, inputs,outputs)
- self.belief = str(belief)
- def run(self):
- self.addBelieve(expr("Value("+self.belief+")"))
-
+def s1_method(Value):
+ return {"Myoutput1":1}
+
+def s2_method(Myoutput1):
+ return {"Myoutput2":2}
+
+def s3_method(Value3):
+ return {"Myoutput3":4}
+
+def s4_method(Myoutput3):
+ return {"Myoutput4":5}
+
+class PlanTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self.a = BDIAgent("bdi@"+host,"secret")
+ self.a.start()
+
+ def tearDown(self):
+ self.a.stop()
+ del self.a
+
+ def testAddBelieve(self):
+ self.a.addBelieve(expr("Value(TestValue)"))
+
+ assert self.a.askBelieve("Value(TestValue)") == True
+
+ def testAddGoal(self):
+ g = Goal("Value(2)")
+ self.a.addGoal(g)
+
+ self.assertEqual(len(self.a.bdiBehav.goals),1)
+ self.assertEqual(self.a.bdiBehav.goals[0].expression,"Value(2)")
+
+
class BDITestCase(unittest.TestCase):
-
- def setUp(self):
-
- self.a = BDIAgent("bdi@"+host,"secret")
-
- def tearDown(self):
- #self.a.stop()
- pass
-
- def testAddBelief(self):
- self.a.addBelieve(expr("Value(0)"))
-
- self.assertEqual(self.a.askBelieve(expr("Value(0)")), {})
-
- def testAddGoal(self):
- g = Goal(expr("Value(2)"))
- self.a.addGoal(g)
-
- self.assertEqual(len(self.a.goals),1)
- self.assertEqual(self.a.goals[0].expression,expr("Value(2)"),{})
-
- def testAddService(self):
- p = Plan(P=expr("Value(0)"),Q=expr("Value(2)"))
- s1 = Serv1(P=expr("Value(0)"),Q=expr("Value(1)"))
- s2 = Serv2(P=expr("Value(1)"),Q=expr("Value(2)"))
-
- p.appendService(s1)
- self.assertEqual(len(p.services),1)
-
- p.appendService(s2)
- self.assertEqual(len(p.services),2)
-
- def testAddPlan(self):
- p = Plan(P=expr("Value(0)"),Q=expr("Value(2)"))
- self.a.addPlan(p)
-
- self.assertEqual(len(self.a.plans),1)
- self.assertEqual(self.a.plans[0].P,expr("Value(0)"))
- self.assertEqual(self.a.plans[0].Q,expr("Value(2)"))
-
- def testSimpleGoalCompleted(self):
- self.a.addBelieve(expr("Value(0)"))
- self.a.addGoal(Goal(expr("Value(1)")))
- p = Plan(P=expr("Value(0)"),Q=expr("Value(1)"))
- s1 = Serv1(P=expr("Value(0)"),Q=expr("Value(1)"))
- p.appendService(s1)
- self.a.addPlan(p)
-
- self.assertNotEqual(self.a.askBelieve(expr("Value(1)")),{})
- self.assertEqual(self.a.askBelieve(expr("Value(0)")), {})
-
- self.a.start()
-
- import time
- time.sleep(2)
-
- self.assertEqual(self.a.askBelieve(expr("Value(1)")), {})
-
- def testMultiGoalCompleted(self):
- self.a.addBelieve(expr("Value(0)"))
- self.a.addGoal(Goal(expr("Value(10)")))
- p = Plan(P=expr("Value(0)"),Q=expr("Value(10)"))
- for i in range(0,10):
- s =
MServ(P=expr("Value("+str(i)+")"),Q=expr("Value("+str(i+1)+")"),belief=i+1)
- p.appendService(s)
- self.a.addPlan(p)
-
- self.assertNotEqual(self.a.askBelieve(expr("Value(10)")),{})
- self.assertEqual(self.a.askBelieve(expr("Value(0)")), {})
-
- self.a.start()
-
- import time
- time.sleep(4)
-
- self.assertEqual(self.a.askBelieve(expr("Value(10)")), {})
+
+ def setUp(self):
+
+ self.a = BDIAgent("bdi@"+host,"secret")
+ #self.a.setDebugToScreen()
+ self.a.start()
+
+ self.s1 = spade.DF.Service(name="s1", owner=self.a.getAID(),
inputs=["Value"],outputs=["Myoutput1"],P=["Var(Value,0,Int)"],Q=["Var(Myoutput1,1,Int)"])
+ self.s2 = spade.DF.Service(name="s2", owner=self.a.getAID(),
inputs=["Myoutput1"],outputs=["Myoutput2"],P=["Var(Myoutput1,1,Int)"],Q=["Var(Myoutput2,2,Int)"])
+ self.s3 = spade.DF.Service(name="s3", owner=self.a.getAID(),
inputs=["Value3"],outputs=["Myoutput3"],P=["Var(Value3,3,Int)"],Q=["Var(Myoutput3,4,Int)"])
+ self.s4 = spade.DF.Service(name="s4", owner=self.a.getAID(),
inputs=["Myoutput3"],outputs=["Myoutput4"],P=["Var(Myoutput3,4,Int)"],Q=["Var(Myoutput4,5,Int)"])
+
+ self.a.registerService(self.s1,s1_method)
+ self.a.registerService(self.s2,s2_method)
+ self.a.registerService(self.s3,s3_method)
+ self.a.registerService(self.s4,s4_method)
+
+ def tearDown(self):
+ s = spade.DF.Service()
+ s.setOwner(self.a.getAID())
+ self.a.deregisterService(s)
+ self.a.stop()
+ del self.a
+
+ def testAddPlan(self):
+
+ self.a.bdiBehav.discover()
+ result =
self.a.addPlan(inputs=["Value"],outputs=["Myoutput2"],P=["Var(Value,0,Int)"],Q=["Var(Myoutput2,2,Int)"],
services=["s1","s2"])
+
+ assert result == True
+
+ def goalCompletedCB(self,goal):
+ self.goalCompleted = True
+
+ def testSimpleGoalCompleted(self):
+
+ self.goalCompleted=False
+
+ self.a.saveFact("Value",0)
+
+ self.a.setGoalCompletedCB(self.goalCompletedCB)
+
+ self.a.addGoal(Goal("Var(Myoutput1,1,Int)"))
+
+ import time
+ counter = 0
+ while not self.goalCompleted and counter<10:
+ time.sleep(1)
+ counter+=1
+
+ assert self.goalCompleted == True
+ assert self.a.askBelieve("Var(Myoutput1,1,Int)") == True
+ assert self.a.getFact("Myoutput1") == 1
+
+ def testGoalCompleted_withPlan(self):
+
+ self.goalCompleted=False
+
+ self.a.saveFact("Value",0)
+
+ self.a.setGoalCompletedCB(self.goalCompletedCB)
+
+ self.a.addGoal(Goal("Var(Myoutput2,2,Int)"))
+
+ import time
+ counter = 0
+ while not self.goalCompleted and counter<10:
+ time.sleep(1)
+ counter+=1
+
+ assert self.goalCompleted == True
+ assert self.a.askBelieve("Var(Myoutput2,2,Int)") == True
+ assert self.a.getFact("Myoutput2") == 2
+
+
+ def serviceCompletedCB(self,service):
+ s = service.getName()
+ if s=="s1": self.s1Completed=True
+ if s=="s2": self.s2Completed=True
+ if s=="s3": self.s3Completed=True
+ if s=="s4": self.s4Completed=True
+
+ def testMultiGoalCompleted(self):
+ self.s1Completed=False
+ self.s3Completed=False
+
+ self.a.saveFact("Value",0)
+ self.a.saveFact("Value3",3)
+
+ self.a.setServiceCompletedCB(self.serviceCompletedCB)
+
+ self.a.addGoal(Goal("Var(Myoutput3,4,Int)"))
+ self.a.addGoal(Goal("Var(Myoutput1,1,Int)"))
+
+ import time
+ counter = 0
+ while counter<10 and (self.s1Completed == False or
self.s3Completed == False):
+ time.sleep(1)
+ counter+=1
+
+ assert self.s1Completed == True
+ assert self.s3Completed == True
+ assert self.a.askBelieve("Var(Myoutput1,1,Int)") == True
+ assert self.a.getFact("Myoutput1") == 1
+ assert self.a.askBelieve("Var(Myoutput3,4,Int)") == True
+ assert self.a.getFact("Myoutput3") == 4
+
+ def testMultiGoalCompleted_withMultiServices(self):
+ self.s2Completed=False
+ self.s4Completed=False
+
+ self.a.saveFact("Value",0)
+ self.a.saveFact("Value3",3)
+
+ self.a.setServiceCompletedCB(self.serviceCompletedCB)
+
+ self.a.addGoal(Goal("Var(Myoutput2,2,Int)"))
+ self.a.addGoal(Goal("Var(Myoutput4,5,Int)"))
+
+ import time
+ counter = 0
+ while counter<10 and (self.s2Completed == False or
self.s4Completed == False):
+ time.sleep(1)
+ counter+=1
+
+ assert self.s2Completed == True
+ assert self.s4Completed == True
+ assert self.a.askBelieve("Var(Myoutput2,2,Int)") == True
+ assert self.a.getFact("Myoutput2") == 2
+ assert self.a.askBelieve("Var(Myoutput4,5,Int)") == True
+ assert self.a.getFact("Myoutput4") == 5
if __name__ == "__main__":
unittest.main()
+ sys.exit()
+ suite = unittest.TestSuite()
+ suite.addTest(BDITestCase('testMultiGoalCompleted'))
+ result = unittest.TestResult()
+
+ suite.run(result)
+ print str(result)
+ for f in result.errors:
+ print f[0]
+ print f[1]
+
+ for f in result.failures:
+ print f[0]
+ print f[1]
=======================================
--- /trunk/test/dfTestCase.py Tue Jul 10 16:56:52 2012
+++ /trunk/test/dfTestCase.py Tue Jul 31 06:58:54 2012
@@ -3,8 +3,6 @@
import time
import unittest
-sys.path.append('../..')
-
import spade
host = "127.0.0.1"
@@ -843,8 +841,8 @@
if __name__ == "__main__":
- #unittest.main()
- #sys.exit()
+ unittest.main()
+ sys.exit()
suite = unittest.TestSuite()
suite.addTest(DFTestCase('testRegisterService'))
=======================================
--- /trunk/test/kbTestCase.py Wed Jul 11 04:18:54 2012
+++ /trunk/test/kbTestCase.py Tue Jul 31 06:58:54 2012
@@ -5,6 +5,7 @@
import spade
from spade.bdi import *
+from spade.Agent import BDIAgent
from spade.pyxf import ECLiPSeExecutableNotFound,
Flora2ExecutableNotFound, SWIExecutableNotFound, XSBExecutableNotFound
host = "127.0.0.1"
@@ -32,141 +33,174 @@
}'''
class KBTestCase(unittest.TestCase):
-
- def setUp(self):
-
- self.a = BDIAgent("kb@"+host,"secret")
-
- def tearDown(self):
- #self.a.stop()
- pass
-
- def testSPARQLopenlink(self):
-
- try:
- from spade import SPARQLKB
- except:
- self.fail("Could not import SPARQLKB. Try installing
SPARQLWrapper (sudo easy_install SPARQLWrapper)")
-
- self.a.configureKB("SPARQL", sentence=None,
path='
http://lod.openlinksw.com/sparql')
- for result in self.a.askBelieve(sparql1):
- assert result["p"] in ["0.5", "0.55", "0.75", "0.85"]
- assert result["c"] == "GBP"
-
- def testSPARQLdbpedia(self):
- try:
- from spade import SPARQLKB
- except:
- self.fail("Could not import SPARQLKB. Try installing
SPARQLWrapper (sudo easy_install SPARQLWrapper)")
-
- self.a.configureKB("SPARQL", sentence=None,
path='
http://dbpedia.org/sparql')
- for result in self.a.askBelieve(sparql2):
- assert result["name"] in ["Croatia","Republic of
Croatia","Republika Hrvatska"]
-
- def testEclipse(self):
- try:
- from spade import ECLiPSeKB
- except:
- self.fail("Could not import ECLiPSeKB")
-
- try:
- self.a.configureKB("ECLiPSe", None, "eclipse")
- except ECLiPSeExecutableNotFound:
- self.fail('ECLiPSe Prolog executable not found on the specified
path.')
-
- if not issubclass(self.a.kb.__class__,ECLiPSeKB.ECLiPSeKB):
- self.fail("ECLiPSe was not properly configured.")
-
- self.a.addBelieve( 'a(b,c)' )
- self.a.addBelieve( 'a(c,d)' )
- self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Y) )' )
- self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Z), p(_Z,_Y) )' )
-
- for result in self.a.askBelieve( 'p(X,Y)' ):
- assert result in
[{'Y': 'c', 'X': 'b'},{'Y': 'd', 'X': 'c'},{'Y': 'd', 'X': 'b'}]
-
- def testFlora2(self):
- try:
- from spade import Flora2KB
- except:
- self.fail("Could not import Flora2KB")
- try:
- self.a.configureKB("Flora2", None, "runflora")
- except Flora2ExecutableNotFound:
- self.fail('Flora-2 executable not found on the specified path. Try
installing flora2')
-
- if not issubclass(self.a.kb.__class__,Flora2KB.Flora2KB):
- self.fail("Flora2 was not properly configured.")
-
- self.a.addBelieve( 'a[ b->c ]' )
- self.a.addBelieve( '( ?x[ c->?y ] :- ?x[ b->?y ] )', 'insertrule' )
-
- for result in self.a.askBelieve( '?x[ ?y->?z ]' ):
- assert result in
[{'y': 'b', 'x': 'a', 'z': 'c'},{'y': 'c', 'x': 'a', 'z': 'c'}]
-
- self.a.removeBelieve( 'a[ b->c ]' )
- result = self.a.askBelieve( '?x[ ?y->?z ]' )
- assert len(result)==0
-
- def testSWI(self):
- try:
- from spade import SWIKB
- except:
- self.fail("Could not import SWIKB")
-
- try:
- self.a.configureKB("SWI", None, "swipl")
- except SWIExecutableNotFound:
- self.fail('SWI-Prolog executable not found on the specified path.
Try installing swi-prolog.')
-
- if not issubclass(self.a.kb.__class__,SWIKB.SWIKB):
- self.fail("SWI was not properly configured.")
-
- self.a.addBelieve( 'a(b,c)' )
- self.a.addBelieve( 'a(c,d)' )
- self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Y) )' )
- self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Z), p(_Z,_Y) )' )
-
- for result in self.a.askBelieve( 'p(X,Y)' ):
- assert result in [{'Y': 'c', 'X': 'b'}, {'Y': 'd', 'X': 'c'},
{'Y': 'd', 'X': 'b'}]
-
- self.a.removeBelieve( 'a(b,c)' )
- for result in self.a.askBelieve( 'p(X,Y)' ):
- assert result in [{'Y': 'd', 'X': 'c'}]
-
- self.a.removeBelieve( 'a(c,d)' )
- self.assertFalse(self.a.askBelieve( 'p(X,Y)' ))
-
-
- def testXSB(self):
- try:
- from spade import XSBKB
- except:
- self.fail("Could not import XSBKB")
-
- try:
- self.a.configureKB("XSB", None, "xsb")
- except XSBExecutableNotFound:
- self.fail('XSB executable not found on the specified path. Try
installing xsb')
-
- if not issubclass(self.a.kb.__class__,XSBKB.XSBKB):
- self.fail("XSB was not properly configured.")
-
- self.a.addBelieve( 'a(b,c)' )
- self.a.addBelieve( 'a(c,d)' )
- self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Y) )' )
- self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Z), p(_Z,_Y) )' )
-
- for result in self.a.askBelieve( 'p(X,Y)' ):
- assert result in [{'Y': 'c', 'X': 'b'}, {'Y': 'd', 'X': 'c'},
{'Y': 'd', 'X': 'b'}]
-
- self.a.removeBelieve( 'a(b,c)' )
- for result in self.a.askBelieve( 'p(X,Y)' ):
- self.assertEqual(result,{'Y': 'd', 'X': 'c'})
-
- self.a.removeBelieve( 'a(c,d)' )
- result = self.a.askBelieve( 'p(X,Y)' )
- assert result == False
+
+ def setUp(self):
+
+ self.a = BDIAgent("kb@"+host,"secret")
+
+ def tearDown(self):
+ self.a.stop()
+
+ def testSPARQLopenlink(self):
+
+ try:
+ from spade import SPARQLKB
+ except:
+ self.fail("Could not import SPARQLKB. Try installing
SPARQLWrapper (sudo easy_install SPARQLWrapper)")
+
+ self.a.configureKB("SPARQL", sentence=None,
path='
http://lod.openlinksw.com/sparql')
+ for result in self.a.askBelieve(sparql1):
+ assert result["p"] in ["0.5", "0.55", "0.75", "0.85"]
+ assert result["c"] == "GBP"
+
+ def testSPARQLdbpedia(self):
+ try:
+ from spade import SPARQLKB
+ except:
+ self.fail("Could not import SPARQLKB. Try installing
SPARQLWrapper (sudo easy_install SPARQLWrapper)")
+
+ self.a.configureKB("SPARQL", sentence=None,
path='
http://dbpedia.org/sparql')
+ for result in self.a.askBelieve(sparql2):
+ assert result["name"] in ["Croatia","Republic of
Croatia","Republika Hrvatska"]
+
+ def testEclipse(self):
+ try:
+ from spade import ECLiPSeKB
+ except:
+ self.fail("Could not import ECLiPSeKB")
+
+ try:
+ self.a.configureKB("ECLiPSe", None, "eclipse")
+ except ECLiPSeExecutableNotFound:
+ self.fail('ECLiPSe Prolog executable not found on the
specified path.')
+
+ if not issubclass(self.a.kb.kb.__class__,ECLiPSeKB.ECLiPSeKB):
+ self.fail("ECLiPSe was not properly configured.")
+
+ self.a.addBelieve( 'a(b,c)' )
+ self.a.addBelieve( 'a(c,d)' )
+ self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Y) )' )
+ self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Z), p(_Z,_Y) )' )
+
+ for result in self.a.askBelieve( 'p(X,Y)' ):
+ assert result in
[{'Y': 'c', 'X': 'b'},{'Y': 'd', 'X': 'c'},{'Y': 'd', 'X': 'b'}]
+
+ def testEclipseNotFound(self):
+ try:
+ from spade import ECLiPSeKB
+ except:
+ self.fail("Could not import ECLiPSeKB")
+
+ self.assertRaises(ECLiPSeExecutableNotFound,
self.a.configureKB, "ECLiPSe", None, "dummyeclipse" )
+
+
+ def testFlora2(self):
+ try:
+ from spade import Flora2KB
+ except:
+ self.fail("Could not import Flora2KB")
+ try:
+ self.a.configureKB("Flora2", None, "runflora")
+ except Flora2ExecutableNotFound:
+ self.fail('Flora-2 executable not found on the specified path.
Try installing flora2')
+
+ if not issubclass(self.a.kb.kb.__class__,Flora2KB.Flora2KB):
+ self.fail("Flora2 was not properly configured.")
+
+ self.a.addBelieve( 'a[ b->c ]' )
+ self.a.addBelieve( '( ?x[ c->?y ] :- ?x[ b->?y ] )', 'insertrule' )
+
+ for result in self.a.askBelieve( '?x[ ?y->?z ]' ):
+ assert result in
[{'y': 'b', 'x': 'a', 'z': 'c'},{'y': 'c', 'x': 'a', 'z': 'c'}]
+
+ self.a.removeBelieve( 'a[ b->c ]' )
+ result = self.a.askBelieve( '?x[ ?y->?z ]' )
+ assert len(result)==0
+
+
+ def testFlora2NotFound(self):
+ try:
+ from spade import Flora2KB
+ except:
+ self.fail("Could not import Flora2KB")
+
+ self.assertRaises(Flora2ExecutableNotFound,
self.a.configureKB, "Flora2", None, "dummyrunflora" )
+
+ def testSWI(self):
+ try:
+ from spade import SWIKB
+ except:
+ self.fail("Could not import SWIKB")
+
+ try:
+ self.a.configureKB("SWI", None, "swipl")
+ except SWIExecutableNotFound:
+ self.fail('SWI-Prolog executable not found on the specified
path. Try installing swi-prolog.')
+
+ if not issubclass(self.a.kb.kb.__class__,SWIKB.SWIKB):
+ self.fail("SWI was not properly configured.")
+
+ self.a.addBelieve( 'a(b,c)' )
+ self.a.addBelieve( 'a(c,d)' )
+ self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Y) )' )
+ self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Z), p(_Z,_Y) )' )
+
+ for result in self.a.askBelieve( 'p(X,Y)' ):
+ assert result in [{'Y': 'c', 'X': 'b'}, {'Y': 'd', 'X': 'c'},
{'Y': 'd', 'X': 'b'}]
+
+ self.a.removeBelieve( 'a(b,c)' )
+ for result in self.a.askBelieve( 'p(X,Y)' ):
+ assert result in [{'Y': 'd', 'X': 'c'}]
+
+ self.a.removeBelieve( 'a(c,d)' )
+ self.assertFalse(self.a.askBelieve( 'p(X,Y)' ))
+
+
+ def testSWINotFound(self):
+ try:
+ from spade import SWIKB
+ except:
+ self.fail("Could not import SWIKB")
+
+ self.assertRaises(SWIExecutableNotFound,
self.a.configureKB, "SWI", None, "dummyswipl" )
+
+ def testXSB(self):
+ try:
+ from spade import XSBKB
+ except:
+ self.fail("Could not import XSBKB")
+
+ try:
+ self.a.configureKB("XSB", None, "xsb")
+ except XSBExecutableNotFound:
+ self.fail('XSB executable not found on the specified path. Try
installing xsb')
+
+ if not issubclass(self.a.kb.kb.__class__,XSBKB.XSBKB):
+ self.fail("XSB was not properly configured.")
+
+ self.a.addBelieve( 'a(b,c)' )
+ self.a.addBelieve( 'a(c,d)' )
+ self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Y) )' )
+ self.a.addBelieve( '( p(_X,_Y) :- a(_X,_Z), p(_Z,_Y) )' )
+
+ for result in self.a.askBelieve( 'p(X,Y)' ):
+ assert result in [{'Y': 'c', 'X': 'b'}, {'Y': 'd', 'X': 'c'},
{'Y': 'd', 'X': 'b'}]
+
+ self.a.removeBelieve( 'a(b,c)' )
+ for result in self.a.askBelieve( 'p(X,Y)' ):
+ self.assertEqual(result,{'Y': 'd', 'X': 'c'})
+
+ self.a.removeBelieve( 'a(c,d)' )
+ result = self.a.askBelieve( 'p(X,Y)' )
+ assert result == False
+
+ def testXSBNotFound(self):
+ try:
+ from spade import XSBKB
+ except:
+ self.fail("Could not import XSBKB")
+
+ self.assertRaises(XSBExecutableNotFound,
self.a.configureKB, "XSB", None, "dummyxsb" )
if __name__ == "__main__":
=======================================
--- /trunk/test/p2pTestCase.py Tue Jul 10 16:56:52 2012
+++ /trunk/test/p2pTestCase.py Tue Jul 31 06:58:54 2012
@@ -3,19 +3,17 @@
import time
import unittest
-sys.path.append('../..')
-
import spade
host = "127.0.0.1"
class MyAgent(spade.Agent.Agent):
- def _setup(self):
- self.msg = None
+ def _setup(self):
+ self.msg = None
-
+
class p2pSendMsgBehav(spade.Behaviour.OneShotBehaviour):
def __init__(self,method):
@@ -65,10 +63,10 @@
msg = None
msg = self._receive(block=True,timeout=10)
if msg != None:
- content = msg.getContent()
- msg = msg.createReply()
- msg.setContent(content)
- self.myAgent.send(msg, method=self.method)
+ content = msg.getContent()
+ msg = msg.createReply()
+ msg.setContent(content)
+ self.myAgent.send(msg, method=self.method)
class p2pSendMultiMsgBehav(spade.Behaviour.OneShotBehaviour):
@@ -119,12 +117,12 @@
self.Aaid = spade.AID.aid("a@"+host,["xmpp://a@"+host])
self.Baid = spade.AID.aid("b@"+host,["xmpp://b@"+host])
- self.a = MyAgent("a@"+host, "secret",p2p=True)
- #self.a._debug = True
- self.a.start()
- self.b = MyAgent("b@"+host, "secret",p2p=True)
- #self.b._debug=True
- self.b.start()
+ self.a = MyAgent("a@"+host, "secret",p2p=True)
+ #self.a._debug = True
+ self.a.start()
+ self.b = MyAgent("b@"+host, "secret",p2p=True)
+ #self.b._debug=True
+ self.b.start()
def tearDown(self):
self.a.stop()
@@ -173,7 +171,7 @@
t = spade.Behaviour.MessageTemplate(template)
self.a.addBehaviour(p2pSendAndRecvMsgBehav("p2p"),t)
counter = 0
- while self.a.msg == None and counter < 20:
+ while self.a.msg == None and counter < 10:
time.sleep(1)
counter += 1
self.assertNotEqual(self.a.msg,None)
@@ -232,6 +230,7 @@
self.assertEqual(self.b.errorTag,[])
self.assertEqual(self.a.routeTag,[])
+
if __name__ == "__main__":
unittest.main()
=======================================
--- /trunk/test/pubsubTestCase.py Tue Jul 10 16:56:52 2012
+++ /trunk/test/pubsubTestCase.py Tue Jul 31 06:58:54 2012
@@ -23,14 +23,14 @@
self.Aaid = spade.AID.aid("a@"+host,["xmpp://a@"+host])
self.Baid = spade.AID.aid("b@"+host,["xmpp://b@"+host])
- self.a = spade.Agent.Agent("a@"+host, "secret")
- self.a.wui.start()
- self.a.start()
- self.b = spade.Agent.Agent("b@"+host, "secret")
- self.b.wui.start()
- self.b.start()
-
- self.a.setSocialItem('b@'+host)
+ self.a = spade.Agent.Agent("a@"+host, "secret")
+ self.a.wui.start()
+ self.a.start()
+ self.b = spade.Agent.Agent("b@"+host, "secret")
+ self.b.wui.start()
+ self.b.start()
+
+ self.a.setSocialItem('b@'+host)
self.a._socialnetwork['b@'+host].subscribe()
self.b.setSocialItem('a@'+host)
self.b._socialnetwork['a@'+host].subscribe()
@@ -39,7 +39,7 @@
self.b.deleteEvent("ExistsNode")
self.a.deleteEvent("NENode")
self.b.deleteEvent("NENode")
-
+
def tearDown(self):
self.a.deleteEvent("ExistsNode")
self.b.deleteEvent("ExistsNode")
@@ -76,7 +76,6 @@
self.a.deleteEvent("ExistsNode")
def testPublishEvent(self):
-
result = self.a.createEvent("ExistsNode")
self.assertEqual(result, ('ok', ['ExistsNode']))
@@ -139,7 +138,6 @@
#TODO: Check that the last published item is sent after
subscription.
def testNotEventBehaviour(self):
-
class Behav(spade.Behaviour.Behaviour): pass
self.a.deleteEvent("ExistsNode")
self.b.deleteEvent("ExistsNode")
@@ -150,8 +148,8 @@
if __name__ == "__main__":
- #unittest.main()
- #sys.exit()
+ unittest.main()
+ sys.exit()
suite = unittest.TestSuite()
suite.addTest(PubSubTestCase('testCreateEvent'))
=======================================
--- /trunk/test/rpcTestCase.py Tue Jul 10 16:56:52 2012
+++ /trunk/test/rpcTestCase.py Tue Jul 31 06:58:54 2012
@@ -4,16 +4,14 @@
import types
import unittest
-sys.path.append('../..')
-
import spade
-
+from spade.kb import *
host = "127.0.0.1"
class MyAgent(spade.Agent.Agent):
- def _setup(self):
- self.result = None
+ def _setup(self):
+ self.result = None
def sumVec(vec):
r = 0
@@ -21,8 +19,8 @@
r+=int(i)
return {"sum":r}
-def CreateService(name, owner, P=None,Q=None):
- return spade.DF.Service(name, owner, P=P,Q=Q)
+def CreateService(name, owner, inputs=[],outputs=[]):
+ return spade.DF.Service(name, owner, inputs=inputs,outputs=outputs)
def Invoke(agent, service,inputs=None):
@@ -49,15 +47,15 @@
self.Aaid = spade.AID.aid("a@"+host,["xmpp://a@"+host])
self.Baid = spade.AID.aid("b@"+host,["xmpp://b@"+host])
- self.a = MyAgent("a@"+host, "secret")
- self.a.start()
- self.b = MyAgent("b@"+host, "secret")
- #self.b.setDebugToScreen()
- #self.a.setDebugToScreen()
- self.b.start()
- self.a.wui.start()
- self.b.wui.start()
-
+ self.a = MyAgent("a@"+host, "secret")
+ self.a.start()
+ self.b = MyAgent("b@"+host, "secret")
+ #self.b.setDebugToScreen()
+ #self.a.setDebugToScreen()
+ self.b.start()
+ #self.a.wui.start()
+ #self.b.wui.start()
+
def tearDown(self):
DeRegisterService(self.b)
self.a.stop()
@@ -66,7 +64,7 @@
def testInvokeService(self):
DeRegisterService(self.b)
- s = CreateService("VecSum",self.b.getAID(),P=["vec"],Q=["sum"])
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
RegisterService(self.b, s, sumVec)
Invoke(self.a, s,inputs={"vec":[10,20]})
@@ -79,11 +77,31 @@
self.assertEqual(self.b.result,True)
services = SearchService(self.a,s)
self.assertEqual(len(services),0)
+
+
+ def testInvokeService_withPostCondition(self):
+ DeRegisterService(self.b)
+
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
+ s.addQ("Var(sum,x,Int)")
+ RegisterService(self.b, s, sumVec)
+
+ Invoke(self.a, s,inputs={"vec":[10,20]})
+ self.assertNotEqual(self.a.result,None)
+ self.assertNotEqual(self.a.result,False)
+ self.assertEqual(type(self.a.result),types.DictType)
+ self.assertEqual(self.a.result,{"sum":30})
+
+ DeRegisterService(self.b)
+ self.assertEqual(self.b.result,True)
+ services = SearchService(self.a,s)
+ self.assertEqual(len(services),0)
+
def testInvokeOwnService(self):
DeRegisterService(self.b)
- s = CreateService("VecSum",self.b.getAID(),P=["vec"],Q=["sum"])
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
RegisterService(self.b, s, sumVec)
Invoke(self.b, s, inputs={"vec":[10,20]})
@@ -98,10 +116,10 @@
def testSearchAndInvoke(self):
DeRegisterService(self.b)
- s = CreateService("VecSum",self.b.getAID(),P=["vec"],Q=["sum"])
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
RegisterService(self.b, s, sumVec)
- s2 = CreateService("VecSum",self.b.getAID(),P=["vec"])
+ s2 = CreateService("VecSum",self.b.getAID(),inputs=["vec"])
services = SearchService(self.a,s2)
self.assertNotEqual(services,None)
self.assertEqual(len(services),1)
@@ -118,19 +136,21 @@
def testInvokeBadParams(self):
DeRegisterService(self.b)
- s = CreateService("VecSum",self.b.getAID(),P=["vec"],Q=["sum"])
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
RegisterService(self.b, s, sumVec)
s2 = CreateService("VecSum",self.b.getAID())
Invoke(self.a, s2, inputs={"vec":["param1","param2"]})
- self.assertEqual(self.a.result,False)
+ #self.assertEqual(self.a.result,False)
+ if self.a.result!=False:
+ self.fail(str(self.a.result))
DeRegisterService(self.b)
def testInvokeNotExistingService(self):
DeRegisterService(self.b)
- s = CreateService("VecSum",self.b.getAID(),P=["vec"])
+ s = CreateService("VecSum",self.b.getAID(),inputs=["vec"])
Invoke(self.a, s)
self.assertNotEqual(self.a.result,None)
@@ -139,7 +159,7 @@
def testInvokeTwice(self):
DeRegisterService(self.b)
- s = CreateService("VecSum",self.b.getAID(),P=["vec"],Q=["sum"])
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
RegisterService(self.b, s, sumVec)
Invoke(self.a, s, inputs={"vec":[10,20]})
@@ -160,44 +180,94 @@
def testInvokeService_withKB(self):
DeRegisterService(self.b)
- s = CreateService("VecSum",self.b.getAID(),P=["vec"],Q=["sum"])
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
RegisterService(self.b, s, sumVec)
- self.a.KB["vec"] = [10,20]
+ self.a.kb.set("vec",[10,20])
Invoke(self.a, s)
self.assertNotEqual(self.a.result,None)
self.assertNotEqual(self.a.result,False)
- self.assertEqual(self.a.KB["sum"],30)
+ self.assertEqual(self.a.kb.get("sum"),30)
DeRegisterService(self.b)
self.assertEqual(self.b.result,True)
services = SearchService(self.a,s)
self.assertEqual(len(services),0)
- del self.a.KB["sum"]
- del self.a.KB["vec"]
+ #del self.a.KB["sum"]
+ #del self.a.KB["vec"]
+ self.a.kb.configure(typ="Spade")
def testInvokeServiceMissingParams_withKB(self):
DeRegisterService(self.b)
- s = CreateService("VecSum",self.b.getAID(),P=["vec"],Q=["sum"])
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
RegisterService(self.b, s, sumVec)
Invoke(self.a, s)
self.assertEqual(self.a.result,False)
- if self.a.KB.has_key("sum"): self.fail()
+ if self.a.kb.get("sum")!=None: self.fail()
DeRegisterService(self.b)
self.assertEqual(self.b.result,True)
services = SearchService(self.a,s)
self.assertEqual(len(services),0)
+ def testInvokeService_withKB_withPreCondition(self):
+ DeRegisterService(self.b)
+
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
+ s.addP("Var(vec,x,List)")
+ RegisterService(self.b, s, sumVec)
+
+ self.a.kb.set("vec",[10,20])
+
+ Invoke(self.a, s)
+
+ self.assertNotEqual(self.a.result,None)
+ self.assertNotEqual(self.a.result,False)
+ self.assertEqual(self.a.kb.get("sum"),30)
+
+ DeRegisterService(self.b)
+
+ self.assertEqual(self.b.result,True)
+ services = SearchService(self.a,s)
+
+ self.assertEqual(len(services),0)
+
+ #del self.a.KB["sum"]
+ #del self.a.KB["vec"]
+ self.a.kb.configure(typ="Spade")
+
+ def testInvokeService_withKB_withFailedPreCondition(self):
+ DeRegisterService(self.b)
+
+ s =
CreateService("VecSum",self.b.getAID(),inputs=["vec"],outputs=["sum"])
+ s.addP("Var(MyVec,x,List)")
+ RegisterService(self.b, s, sumVec)
+
+ self.a.kb.set("vec",[10,20])
+
+ Invoke(self.a, s)
+ self.assertNotEqual(self.a.result,None)
+ self.assertEqual(self.a.result,False)
+
+ DeRegisterService(self.b)
+ self.assertEqual(self.b.result,True)
+ services = SearchService(self.a,s)
+ self.assertEqual(len(services),0)
+
+ #del self.a.KB["sum"]
+ #del self.a.KB["vec"]
+ self.a.kb.configure(typ="Spade")
+
+
if __name__ == "__main__":
unittest.main()
sys.exit()
suite = unittest.TestSuite()
- suite.addTest(RPCTestCase('testInvokeService_withKB'))
+ suite.addTest(RPCTestCase('testInvokeService_withKB_withPreCondition'))
result = unittest.TestResult()
suite.run(result)
=======================================
--- /trunk/test.py Wed Jul 11 05:26:53 2012
+++ /trunk/test.py Tue Jul 31 06:58:54 2012
@@ -1,19 +1,23 @@
-from test.basicTestCase import *
+from test.aidTestCase import *
from test.amsTestCase import *
-from test.dfTestCase import *
+from test.basicTestCase import *
+from test.bdiTestCase import *
from test.coTestCase import *
-from test.p2pTestCase import *
-from test.rpcTestCase import *
-from test.aidTestCase import *
from test.dadTestCase import *
+from test.dfTestCase import *
from test.eventbehavTestCase import *
+from test.factsTestCase import *
+from test.kbTestCase import *
+from test.p2pTestCase import *
from test.pubsubTestCase import *
-from test.kbTestCase import *
-from test.xfTestCase import *
+from test.rpcTestCase import *
+from test.tbcbpTestCase import *
+from test.xfTestCase import *
from spade import spade_backend
from xmppd.xmppd import Server
import thread
+import sys
import os
d="test"+os.sep
@@ -40,4 +44,4 @@
platform.shutdown()
s.shutdown("Jabber server terminated...")
-
+sys.exit(0)