This example illustrates the use of SWSL-Rules for Web service discovery. The particular features of the language that this example relies on include frame-based representation, reification, and nonmonotonic Lloyd-Topor extensions. In addition, logical updates à la Transaction logic [Bonner98] are used in the discovery queries. Transaction Logic was mentioned in Section 3.15 as a possible extension for SWSL-Rules.
To make the example manageable, services are described only by their names and conditional effects. To discover a service, users must represent their goals using the goal ontology described below. These goals are described in terms of user requests, which represent formulas that the user wants to be true in the after-state of the service (i.e., the state that would result after the execution of the service).
User goals and services may be expressed in different ontologies and so
mediators are needed to translate between those ontologies.
This type of mediators is known as wgMediators [Bruijn05]. In this example, we
assume that each service advertises the mediators that can be used to talk
to this service though the attribute mediators
.
Geographical ontology.
To begin, we assume the following simple geographic taxonomy, which is
shared by user goals and services. It defines
several regions and subregions, such
as America
, USA
, Europe
,
Tyrol
. Each region is viewed as a class of cities. For
instance, Innsbruck
is a city in Tyrol
and 'Stony Brook'
is a town in the New York State
(NYState
).
USA::America. Germany::Europe. Austria::Europe. France::Europe. Tyrol::Austria. NewYorkState::USA. StonyBrook:NewYorkState. NewYork:NewYorkState. Innsbruck:Tyrol. Lienz:Tyrol. Vienna:Austria. Bonn:Germany. Frankfurt:Germany. Paris:France. Nancy:France. Europe:Region. America:Region. ?Reg:Region :- ?Reg1:Region and ?Reg::?Reg1. ?Loc:Location :- ?Reg:Region and ?Loc:?Reg.
To make it easier to specify what is a region and what is not, we use a rule (the penultimate statement above) to say that a subclasses of a region are also regions and, therefore, such subclasses do not need to be explicitly declared as regions. The last rule simply says that any object that is a member of a geographical region is a location.
Goal ontology. Services write their descriptions to conform to specific ontologies. Likewise, clients describe their goals in terms of goal ontologies. Here we will not describe these ontologies, but rather the forms of the inputs and outputs that the services expect to produce and the structure of the user goals. Furthermore, since users and service designers are unlikely to be skilled knowledge engineers, we assume that the inputs, the outputs, and the goals are fairly simple and that most of the intelligence lies in the mediators.
We assume that there is one ontology for goals and two for services. Consequently, there are two mediators: one translating between the goal ontology and the first service ontology, and the other between the goal ontology and the second service ontology.
The goal ontology looks as follows:
Goal[requestId *=> Request, request *=> TravelSearchQuery, result *=> Service ].
The classes Request
and Service
will be specified
explicitly by placing specific object Ids in them. The class
TravelSearchQuery
consists of the following search queries:
searchTrip(?From,?To):TravelSearchQuery :- ?From:(Region or Location) and ?To:(Region or Location). searchCitipass(?Loc):TravelSearchQuery :- ?Loc:(Region or Location).
The meaning of the query searchTrip(?X,?Y)
depends on whether the
parameters are regions or just locations. For location-parameters, the query
is assumed to fetch the services that serve those locations. For
region-parameters, the query is assumed to find services that
service every location in the region that is known to the knowledge
base. For instance, searchTrip(Paris, Germany)
is a request for
travel services that can sell a ticket from Paris to any city in
Germany. Similarly, searchCitipass(NewYork)
is interpreted as
a search for travel services that can sell city passes for New York and
the request searchCitipass(USA)
is looking for services that
can sell city passes for every location in USA.
The result
attribute is provided by the ontology as a place
where the discovery mechanism is supposed to put the results.
Domain-specific service ontologies. A service ontology is intended to represent the inputs and outputs of the service as well as the effects of the service. Since the inputs are not generally provided in the user goal (since the user is not expected to know anything about such inputs), the job of translating goal queries into the inputs to the services lies with the mediator.
Service ontology #1 is defined as follows:
// Service input search(?requestId,?fromLocation,?toLocation):ProcessInput :- ?requestId:Request and ?fromLocation:Location and ?toLocation:Location. search(?requestId,?city):ProcessInput :- ?requestId:Request and ?city:Location. // Service output ItineraryInfo::ServiceOutput. PassInfo::ServiceOutput. ItineraryInfo[from*=>Location, to*=>Location]. PassInfo[city*=>Location]. itinerary(?reqNumber):ItineraryInfo :- ?reqNumber:Request. pass(?reqNumber):PassInfo :- ?reqNumber:Request.
Note that services expect locations as part of their input and they know nothing about regions. In contrast, as we have seen, user goals can have region-wide requests. It is one of the responsibilities of the mediators to bridge this mismatch.
Service ontology #2 is similar to ontology #1 except that it understands only requests for citipasses and the formats for the input and the output are slightly different.
// Service input discover(?requestId,?city):ProcessInput :- ?requestId:Request and ?city:Location. // Service output ServiceOutput[location*=>Location]. ?reqNumber:ServiceOutput :- ?reqNumber:Request.
Shared core ontology for services.
In addition, we need a core ontology that is shared by everyone in order to
provide a common ground for the service infrastructure. In this example, the
core ontology is represented by a single class
Service
, which is declared as follows:
prefix xsd = "http://www.w3.org/2001/XMLSchema". Service[ name *=> xsd#string, process *=> Process[effect(ProcessInput) *=> Formula], mediators *=> Mediator ].
Note that the definition of the class Service
belongs to the
core ontology and therefore it is shared by everybody.
The method effect
represents the conditional effect of the
service. It takes an input to the service as a parameter and returns a set of
rules that specify the effects of the service for that
input. Formula
is a predefined class.
The attribute mediators
indicates the mediators that the
service advertises for anywho would want to talk to that service.
Note that the class ProcessInput
belongs to the core ontology,
but it's extension (the set of objects that are members of that class) is
defined by domain-specific ontologies.
We now present instances of concrete services.
// This service uses ontology #1, and mediator med1 bridges it to the goal ontology serv1:Service[ name -> "Schwartz Travel, Inc.", // Input must be a request for ticket from somewhere in Germany to somewhere // in Austria OR a request for a city pass for a city in Tyrol // Depending on the input, output is either an itinerary object with Id // itinerary(requestId) or a citipass object with Id // pass(requestId). process -> _#[effect(?Input) -> ${ (itinerary(?Req)[from->?From,to->?To] :- Input = search(?Req, ?From:Germany, ?To:Austria)) and (pass(?Req)[city->?City] :- ?Input=search(?Req,?City:Tyrol)) }], mediators -> med1 ]. // Another ontology #1 service serv2:Service[ name -> "Mueller Travel, Inc.", process -> _#[effect(?Input)-> ${ itinerary(?Req)[from->?From, to->?To] :- ?Input = search(?Req,?From:(France or Germany),?To:Austria) }], mediators -> med1 ]. // An ontology #2 service serv3:Service[ name -> "France Citeseeing, Inc.", process -> _#[effect(?Input)-> ${ ?Req[location->?City] :- ?Input=discover(?Req,?City:France) }], mediators -> med2 ]. // Another ontology #2 service serv4:Service[ name -> "Province Travel", process -> _#[effect(?Input)-> ${ ?Req[location->?City] :- ?Input = discover(?Req,?City:France) and ?City != Paris }], mediators -> med2 ].
Next we show examples of user goals. Note that the value of the
attribute result
is initially the empty set. When the goal is
posed to the discovery engine, this value will be changed to contain the
result of the discovery.
goal1:Goal[ requestId -> _#:Request, request -> searchTrip(Bonn,Innsbruck), result -> {} ]. // search for services that serve all cities in France and Austria goal2:Goal[ requestId -> _#:Request, request -> searchTrip(France,Austria), result -> {} ]. goal3:Goal[ requestId -> _#:Request, request -> searchCitipass(Frankfurt), result -> {} ]. goal4:Goal[ requestId -> _#:Request, request -> searchCitipass(Innsbruck), result -> {} ]. // services that can sell citipasses for every city in France goal5:Goal[ requestId -> _#:Request, request -> searchCitipass(France), result -> {} ].
Each of the two mediators, med1
and med2
, consists
of several main clauses. The first clause in each mediator takes a user goal
and translates it into input (to services)
that is appropriate for the corresponding
domain-specific service ontology.
The remaining clauses define the mediator's method getResult
.
This method is supposed to be invoked in the after-state of the service
execution. It takes as parameters the user goal and the service (in whose
after-state the method is invoked). Depending on the form of the goal's
request, getResult
poses a query that is appropriate
for that request and the service ontology of the service. For instance, if
the request is searchCitipass(?City:Location)
, i.e.,
finding services that can sell citipasses for a specific location, then the
query appropriate for services that use ontology #1
is pass(?)[city->?City]
and
the query for ontology #2 is ?[location->?City]
.
Finally, if the query yields results, the mediator constructs output that can
be used to return results to the user and this output is compliant with
our goal ontology.
Each form of the input has two cases: one assumes that the parameters are
locations (e.g., searchCitipass(?City:Location)
) and the other
that they are regions (e.g., searchCitipass(?City:Region)
).
Therefore, for each form of the input our mediators have two clauses.
Since ontology #2 understands only one input, med2
uses only two
clauses to define getResult
. The mediator for ontology
#1, med1
, needs four clauses to cover both forms of the input.
Finally, we remark that the clauses that deal with region-based requests have to construct more sophisticated queries to be asked in the after-state of the services. In our example, we use nonmonotonic Lloyd-Topor extensions to simplify such queries.
// mediator for ontology #1 med1:Mediator. med1[constructInput(?Goal)->?Input] :- ?Goal[requestId->?ReqId, request->?Query] and if ?Query = searchTrip(?From,?To) then ?Input = search(?ReqId,?From1,?To1) else if ?Query = searchCitipass(?City) then ?Input = search(?ReqId,?City1). med1[getResult(?Goal,?Serv) -> ${?Goal[result->?Serv]}] :- ?Goal[request->searchCitipass(?City:Location)] and pass(?)[city->?City]. med1[getResult(?Goal,?Serv) -> ${?Goal[result->?Serv]}] :- ?Goal[request->searchCitipass(?Region:Region)] and forall ?City (?City:?Region ==> pass(?)[city->?City]). med1[getResult(?Goal,?Serv) -> ${?Goal[result->?Serv]}] :- ?Goal[request->searchTrip(?From:Location,?To:Location)] and itinerary(?)[from->?From, to->?To]. med1[getResult(?Goal,?Serv) -> and ?Result = ${?Goal[result->?Serv]}] :- ?Goal[request->searchTrip(?From:Region,?To:Region)] and forall ?From,?To (?City1:?FromReg and ?City2:?ToReg ==> itinerary(?)[from->?City1, to->?City2]). // mediator for ontology #2 med2:Mediator. med2[constructInput(?Goal)->?Input] :- ?Goal[requestId->?ReqId, request->?Query] and if ?Query = searchCitipass(?City) then ?Input = discover(?ReqId,?City1). med2[getResult(?Goal,?Serv) -> ${?Goal[result->?Serv]}] :- ?Goal[request->searchCitipass(?City:Location)] and ?[location->?City]. med2[getResult(?Goal,?Serv) -> ${?Goal[result->?Serv]}] :- ?Goal[request->searchCitipass(?Region:Region)] and forall ?City (?City:?Region ==> ?[location->?City]).
The final piece of the puzzle is the actual engine that performs service discovery. It relies on the features, borrowed from Transaction Logic [Bonner98], which are currently not in SWSL-Language, but are considered for future extensions. These features include modifications to the current state of the knowledge base and hypothetical execution of such modifications.
findService(?Goal) :- ?Serv[mediators -> ?Mediator] and ?Mediator[constructInput(?Goal) -> ?Input] and ?Serv.process[effect(?Input) -> ?Effects] and hypothetically( insert{?Effects} and ?Mediator[getResult(?Goal,?Serv) -> ?Result] ) and insert{?Result}.
The findService
transaction performs the
following tasks:
It then hypothetically does the following:
If the above hypothetical execution fails for a particular
service, no result is returned and the subsequent insert
operation is not executed.
If the hypothetical execution succeeds, it means that the
service s matches the goal.
After the hypothetical execution, the state of the knowledge base
returns to what was before the execution of the service, but the
variable ?Result
is now bound to a result, which is a
formula of the form
goal[result->s]
This is then inserted into the knowledge base. In this way, the set of
answers to the goal is built as the value of the result
attribute of the goal object.
For instance, if
?- findService(goal1).
is executed then the following will become true:
goal1[result -> {serv1,serv2}]
Similarly, executing
?- findService(goal2).
yields goal2[result -> serv2]
. The third
goal, goal3
, matches none of the services listed above, so only
goal3[result->{}]
can be derived.
Executing
?- findService(goal4).
yields goal4[result -> serv1]
.
A more interesting goal is goal5
, because it requests
citipasses for an entire region (France). Given the information available in
our knowledge base, only serv3
should match. Note
that serv4
does not match because it does not serve Paris,
while the goal specifies only those services that can sell citipasses for
every location in France.